123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- 'use strict'
- module.exports = rfdc
-
- function copyBuffer (cur) {
- if (cur instanceof Buffer) {
- return Buffer.from(cur)
- }
-
- return new cur.constructor(cur.buffer.slice(), cur.byteOffset, cur.length)
- }
-
- function rfdc (opts) {
- opts = opts || {}
- if (opts.circles) return rfdcCircles(opts)
-
- const constructorHandlers = new Map()
- constructorHandlers.set(Date, (o) => new Date(o))
- constructorHandlers.set(Map, (o, fn) => new Map(cloneArray(Array.from(o), fn)))
- constructorHandlers.set(Set, (o, fn) => new Set(cloneArray(Array.from(o), fn)))
- if (opts.constructorHandlers) {
- for (const handler of opts.constructorHandlers) {
- constructorHandlers.set(handler[0], handler[1])
- }
- }
-
- let handler = null
-
- return opts.proto ? cloneProto : clone
-
- function cloneArray (a, fn) {
- const keys = Object.keys(a)
- const a2 = new Array(keys.length)
- for (let i = 0; i < keys.length; i++) {
- const k = keys[i]
- const cur = a[k]
- if (typeof cur !== 'object' || cur === null) {
- a2[k] = cur
- } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {
- a2[k] = handler(cur, fn)
- } else if (ArrayBuffer.isView(cur)) {
- a2[k] = copyBuffer(cur)
- } else {
- a2[k] = fn(cur)
- }
- }
- return a2
- }
-
- function clone (o) {
- if (typeof o !== 'object' || o === null) return o
- if (Array.isArray(o)) return cloneArray(o, clone)
- if (o.constructor !== Object && (handler = constructorHandlers.get(o.constructor))) {
- return handler(o, clone)
- }
- const o2 = {}
- for (const k in o) {
- if (Object.hasOwnProperty.call(o, k) === false) continue
- const cur = o[k]
- if (typeof cur !== 'object' || cur === null) {
- o2[k] = cur
- } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {
- o2[k] = handler(cur, clone)
- } else if (ArrayBuffer.isView(cur)) {
- o2[k] = copyBuffer(cur)
- } else {
- o2[k] = clone(cur)
- }
- }
- return o2
- }
-
- function cloneProto (o) {
- if (typeof o !== 'object' || o === null) return o
- if (Array.isArray(o)) return cloneArray(o, cloneProto)
- if (o.constructor !== Object && (handler = constructorHandlers.get(o.constructor))) {
- return handler(o, cloneProto)
- }
- const o2 = {}
- for (const k in o) {
- const cur = o[k]
- if (typeof cur !== 'object' || cur === null) {
- o2[k] = cur
- } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {
- o2[k] = handler(cur, cloneProto)
- } else if (ArrayBuffer.isView(cur)) {
- o2[k] = copyBuffer(cur)
- } else {
- o2[k] = cloneProto(cur)
- }
- }
- return o2
- }
- }
-
- function rfdcCircles (opts) {
- const refs = []
- const refsNew = []
-
- const constructorHandlers = new Map()
- constructorHandlers.set(Date, (o) => new Date(o))
- constructorHandlers.set(Map, (o, fn) => new Map(cloneArray(Array.from(o), fn)))
- constructorHandlers.set(Set, (o, fn) => new Set(cloneArray(Array.from(o), fn)))
- if (opts.constructorHandlers) {
- for (const handler of opts.constructorHandlers) {
- constructorHandlers.set(handler[0], handler[1])
- }
- }
-
- let handler = null
- return opts.proto ? cloneProto : clone
-
- function cloneArray (a, fn) {
- const keys = Object.keys(a)
- const a2 = new Array(keys.length)
- for (let i = 0; i < keys.length; i++) {
- const k = keys[i]
- const cur = a[k]
- if (typeof cur !== 'object' || cur === null) {
- a2[k] = cur
- } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {
- a2[k] = handler(cur, fn)
- } else if (ArrayBuffer.isView(cur)) {
- a2[k] = copyBuffer(cur)
- } else {
- const index = refs.indexOf(cur)
- if (index !== -1) {
- a2[k] = refsNew[index]
- } else {
- a2[k] = fn(cur)
- }
- }
- }
- return a2
- }
-
- function clone (o) {
- if (typeof o !== 'object' || o === null) return o
- if (Array.isArray(o)) return cloneArray(o, clone)
- if (o.constructor !== Object && (handler = constructorHandlers.get(o.constructor))) {
- return handler(o, clone)
- }
- const o2 = {}
- refs.push(o)
- refsNew.push(o2)
- for (const k in o) {
- if (Object.hasOwnProperty.call(o, k) === false) continue
- const cur = o[k]
- if (typeof cur !== 'object' || cur === null) {
- o2[k] = cur
- } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {
- o2[k] = handler(cur, clone)
- } else if (ArrayBuffer.isView(cur)) {
- o2[k] = copyBuffer(cur)
- } else {
- const i = refs.indexOf(cur)
- if (i !== -1) {
- o2[k] = refsNew[i]
- } else {
- o2[k] = clone(cur)
- }
- }
- }
- refs.pop()
- refsNew.pop()
- return o2
- }
-
- function cloneProto (o) {
- if (typeof o !== 'object' || o === null) return o
- if (Array.isArray(o)) return cloneArray(o, cloneProto)
- if (o.constructor !== Object && (handler = constructorHandlers.get(o.constructor))) {
- return handler(o, cloneProto)
- }
- const o2 = {}
- refs.push(o)
- refsNew.push(o2)
- for (const k in o) {
- const cur = o[k]
- if (typeof cur !== 'object' || cur === null) {
- o2[k] = cur
- } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {
- o2[k] = handler(cur, cloneProto)
- } else if (ArrayBuffer.isView(cur)) {
- o2[k] = copyBuffer(cur)
- } else {
- const i = refs.indexOf(cur)
- if (i !== -1) {
- o2[k] = refsNew[i]
- } else {
- o2[k] = cloneProto(cur)
- }
- }
- }
- refs.pop()
- refsNew.pop()
- return o2
- }
- }
|