Socket
Socket
Sign inDemoInstall

rfdc

Package Overview
Dependencies
0
Maintainers
2
Versions
12
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.1.4 to 1.2.0

.github/workflows/ci.yml

20

index.js
'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) {

@@ -20,2 +28,4 @@ opts = opts || {}

a2[k] = new Date(cur)
} else if (ArrayBuffer.isView(cur)) {
a2[k] = copyBuffer(cur)
} else {

@@ -40,2 +50,4 @@ a2[k] = fn(cur)

o2[k] = new Date(cur)
} else if (ArrayBuffer.isView(cur)) {
o2[k] = copyBuffer(cur)
} else {

@@ -59,2 +71,4 @@ o2[k] = clone(cur)

o2[k] = new Date(cur)
} else if (ArrayBuffer.isView(cur)) {
o2[k] = copyBuffer(cur)
} else {

@@ -84,2 +98,4 @@ o2[k] = cloneProto(cur)

a2[k] = new Date(cur)
} else if (ArrayBuffer.isView(cur)) {
a2[k] = copyBuffer(cur)
} else {

@@ -111,2 +127,4 @@ var index = refs.indexOf(cur)

o2[k] = new Date(cur)
} else if (ArrayBuffer.isView(cur)) {
o2[k] = copyBuffer(cur)
} else {

@@ -139,2 +157,4 @@ var i = refs.indexOf(cur)

o2[k] = new Date(cur)
} else if (ArrayBuffer.isView(cur)) {
o2[k] = copyBuffer(cur)
} else {

@@ -141,0 +161,0 @@ var i = refs.indexOf(cur)

12

package.json
{
"name": "rfdc",
"version": "1.1.4",
"version": "1.2.0",
"description": "Really Fast Deep Clone",
"main": "index.js",
"exports": {
".": "./index.js",
"./default": "./default.js"
},
"scripts": {
"test": "tap -R min test && npm run lint",
"test": "tap -R min test && npm run lint && tsd",
"bench": "node benchmark",

@@ -43,2 +47,3 @@ "lint": "standard --fix",

"devDependencies": {
"clone-deep": "^4.0.1",
"codecov": "^3.4.0",

@@ -50,3 +55,4 @@ "deep-copy": "^1.4.2",

"standard": "^11.0.1",
"tap": "^12.0.1"
"tap": "^12.0.1",
"tsd": "^0.7.4"
},

@@ -53,0 +59,0 @@ "directories": {

@@ -26,3 +26,3 @@ # rfdc

It's marginally faster to allow enumerable properties on the prototype
It's marginally faster to allow enumerable properties on the prototype
to be copied into the cloned object (not onto it's prototype, directly onto the object).

@@ -43,3 +43,3 @@

additional 25% overhead. Even if an object doesn't have any circular references,
the tracking overhead is the cost. By default if an object with a circular
the tracking overhead is the cost. By default if an object with a circular
reference is passed to `rfdc`, it will throw (similar to how `JSON.stringify` \

@@ -53,5 +53,14 @@ would throw).

### `default` import
It is also possible to directly import the clone function with all options set
to their default:
```js
const clone = require("rfdc/default")
clone({a: 1, b: {c: 2}}) // => {a: 1, b: {c: 2}}
```
### Types
`rdfc` clones all JSON types:
`rfdc` clones all JSON types:

@@ -68,2 +77,4 @@ * `Object`

* `undefined` (copied)
* `Buffer` (copied)
* `TypedArray` (copied)
* `Function` (referenced)

@@ -80,13 +91,10 @@ * `AsyncFunction` (referenced)

```js
const rdfc = require('rdfc')()
const rfdc = require('rfdc')()
const err = Error()
err.code = 1
JSON.parse(JSON.stringify(e)) // {code: 1}
rdfc(e) // {code: 1}
rfdc(e) // {code: 1}
JSON.parse(JSON.stringify(new Uint8Array([1, 2, 3]))) // {'0': 1, '1': 2, '2': 3 }
rdfc(new Uint8Array([1, 2, 3])) // {'0': 1, '1': 2, '2': 3 }
JSON.parse(JSON.stringify({rx: /foo/})) // {rx: {}}
rdfc({rx: /foo/}) // {rx: {}}
rfdc({rx: /foo/}) // {rx: {}}
```

@@ -101,9 +109,10 @@

```
benchDeepCopy*100: 549.618ms
benchLodashCloneDeep*100: 1461.134ms
benchFastCopy*100: 878.146ms
benchRfdc*100: 323.899ms
benchRfdcProto*100: 314.136ms
benchRfdcCircles*100: 384.561ms
benchRfdcCirclesProto*100: 381.775ms
benchDeepCopy*100: 457.568ms
benchLodashCloneDeep*100: 1230.773ms
benchCloneDeep*100: 655.208ms
benchFastCopy*100: 747.017ms
benchRfdc*100: 281.018ms
benchRfdcProto*100: 277.265ms
benchRfdcCircles*100: 328.148ms
benchRfdcCirclesProto*100: 323.004ms
```

@@ -110,0 +119,0 @@

@@ -5,7 +5,10 @@ 'use strict'

const rfdc = require('..')
const cloneDefault = require('../default')
const clone = rfdc()
const cloneProto = rfdc({proto: true})
const cloneCircles = rfdc({circles: true})
const cloneCirclesProto = rfdc({circles: true, proto: true})
const cloneProto = rfdc({ proto: true })
const cloneCircles = rfdc({ circles: true })
const cloneCirclesProto = rfdc({ circles: true, proto: true })
const rnd = (max) => Math.round(Math.random() * max)
types(clone, 'default')

@@ -16,10 +19,17 @@ types(cloneProto, 'proto option')

test('default – does not copy proto properties', async ({is}) => {
is(clone(Object.create({a: 1})).a, undefined, 'value not copied')
test('default – does not copy proto properties', async ({ is }) => {
is(clone(Object.create({ a: 1 })).a, undefined, 'value not copied')
})
test('proto option – copies enumerable proto properties', async ({is}) => {
is(cloneProto(Object.create({a: 1})).a, 1, 'value copied')
test('default – shorthand import', async ({ same }) => {
same(
clone(Object.create({ a: 1 })),
cloneDefault(Object.create({ a: 1 })),
'import equals clone with default options'
)
})
test('circles option - circular object', async ({same, is, isNot}) => {
const o = {nest: {a: 1, b: 2}}
test('proto option – copies enumerable proto properties', async ({ is }) => {
is(cloneProto(Object.create({ a: 1 })).a, 1, 'value copied')
})
test('circles option - circular object', async ({ same, is, isNot }) => {
const o = { nest: { a: 1, b: 2 } }
o.circular = o

@@ -33,4 +43,4 @@ same(cloneCircles(o), o, 'same values')

})
test('circles option – deep circular object', async ({same, is, isNot}) => {
const o = {nest: {a: 1, b: 2}}
test('circles option – deep circular object', async ({ same, is, isNot }) => {
const o = { nest: { a: 1, b: 2 } }
o.nest.circular = o

@@ -42,12 +52,24 @@ same(cloneCircles(o), o, 'same values')

is(c.nest.circular, c, 'circular references point to copied parent')
isNot(c.nest.circular, o, 'circular references do not point to original parent')
isNot(
c.nest.circular,
o,
'circular references do not point to original parent'
)
})
test('circles option alone – does not copy proto properties', async ({is}) => {
is(cloneCircles(Object.create({a: 1})).a, undefined, 'value not copied')
test('circles option alone – does not copy proto properties', async ({
is
}) => {
is(cloneCircles(Object.create({ a: 1 })).a, undefined, 'value not copied')
})
test('circles and proto option – copies enumerable proto properties', async ({is}) => {
is(cloneCirclesProto(Object.create({a: 1})).a, 1, 'value copied')
test('circles and proto option – copies enumerable proto properties', async ({
is
}) => {
is(cloneCirclesProto(Object.create({ a: 1 })).a, 1, 'value copied')
})
test('circles and proto option - circular object', async ({same, is, isNot}) => {
const o = {nest: {a: 1, b: 2}}
test('circles and proto option - circular object', async ({
same,
is,
isNot
}) => {
const o = { nest: { a: 1, b: 2 } }
o.circular = o

@@ -61,4 +83,8 @@ same(cloneCirclesProto(o), o, 'same values')

})
test('circles and proto option – deep circular object', async ({same, is, isNot}) => {
const o = {nest: {a: 1, b: 2}}
test('circles and proto option – deep circular object', async ({
same,
is,
isNot
}) => {
const o = { nest: { a: 1, b: 2 } }
o.nest.circular = o

@@ -70,5 +96,13 @@ same(cloneCirclesProto(o), o, 'same values')

is(c.nest.circular, c, 'circular references point to copied parent')
isNot(c.nest.circular, o, 'circular references do not point to original parent')
isNot(
c.nest.circular,
o,
'circular references do not point to original parent'
)
})
test('circles and proto option – deep circular array', async ({same, is, isNot}) => {
test('circles and proto option – deep circular array', async ({
same,
is,
isNot
}) => {
const o = { nest: [1, 2] }

@@ -85,24 +119,24 @@ o.nest.push(o)

function types (clone, label) {
test(label + ' – number', async ({is}) => {
test(label + ' – number', async ({ is }) => {
is(clone(42), 42, 'same value')
})
test(label + ' – string', async ({is}) => {
test(label + ' – string', async ({ is }) => {
is(clone('str'), 'str', 'same value')
})
test(label + ' – boolean', async ({is}) => {
test(label + ' – boolean', async ({ is }) => {
is(clone(true), true, 'same value')
})
test(label + ' – function', async ({is}) => {
test(label + ' – function', async ({ is }) => {
const fn = () => {}
is(clone(fn), fn, 'same function')
})
test(label + ' – async function', async ({is}) => {
test(label + ' – async function', async ({ is }) => {
const fn = async () => {}
is(clone(fn), fn, 'same function')
})
test(label + ' – generator function', async ({is}) => {
test(label + ' – generator function', async ({ is }) => {
const fn = function * () {}
is(clone(fn), fn, 'same function')
})
test(label + ' – date', async ({is, isNot}) => {
test(label + ' – date', async ({ is, isNot }) => {
const date = new Date()

@@ -112,11 +146,11 @@ is(+clone(date), +date, 'same value')

})
test(label + ' – null', async ({is}) => {
test(label + ' – null', async ({ is }) => {
is(clone(null), null, 'same value')
})
test(label + ' – shallow object', async ({same, isNot}) => {
const o = {a: 1, b: 2}
test(label + ' – shallow object', async ({ same, isNot }) => {
const o = { a: 1, b: 2 }
same(clone(o), o, 'same values')
isNot(clone(o), o, 'different object')
})
test(label + ' – shallow array', async ({same, isNot}) => {
test(label + ' – shallow array', async ({ same, isNot }) => {
const o = [1, 2]

@@ -126,4 +160,4 @@ same(clone(o), o, 'same values')

})
test(label + ' – deep object', async ({same, isNot}) => {
const o = {nest: {a: 1, b: 2}}
test(label + ' – deep object', async ({ same, isNot }) => {
const o = { nest: { a: 1, b: 2 } }
same(clone(o), o, 'same values')

@@ -133,4 +167,4 @@ isNot(clone(o), o, 'different objects')

})
test(label + ' – deep array', async ({same, isNot}) => {
const o = [ {a: 1, b: 2}, [3] ]
test(label + ' – deep array', async ({ same, isNot }) => {
const o = [{ a: 1, b: 2 }, [3]]
same(clone(o), o, 'same values')

@@ -141,39 +175,39 @@ isNot(clone(o), o, 'different arrays')

})
test(label + ' – nested number', async ({is}) => {
is(clone({a: 1}).a, 1, 'same value')
test(label + ' – nested number', async ({ is }) => {
is(clone({ a: 1 }).a, 1, 'same value')
})
test(label + ' – nested string', async ({is}) => {
is(clone({s: 'str'}).s, 'str', 'same value')
test(label + ' – nested string', async ({ is }) => {
is(clone({ s: 'str' }).s, 'str', 'same value')
})
test(label + ' – nested boolean', async ({is}) => {
is(clone({b: true}).b, true, 'same value')
test(label + ' – nested boolean', async ({ is }) => {
is(clone({ b: true }).b, true, 'same value')
})
test(label + ' – nested function', async ({is}) => {
test(label + ' – nested function', async ({ is }) => {
const fn = () => {}
is(clone({fn}).fn, fn, 'same function')
is(clone({ fn }).fn, fn, 'same function')
})
test(label + ' – nested async function', async ({is}) => {
test(label + ' – nested async function', async ({ is }) => {
const fn = async () => {}
is(clone({fn}).fn, fn, 'same function')
is(clone({ fn }).fn, fn, 'same function')
})
test(label + ' – nested generator function', async ({is}) => {
test(label + ' – nested generator function', async ({ is }) => {
const fn = function * () {}
is(clone({fn}).fn, fn, 'same function')
is(clone({ fn }).fn, fn, 'same function')
})
test(label + ' – nested date', async ({is, isNot}) => {
test(label + ' – nested date', async ({ is, isNot }) => {
const date = new Date()
is(+clone({d: date}).d, +date, 'same value')
isNot(clone({d: date}).d, date, 'different object')
is(+clone({ d: date }).d, +date, 'same value')
isNot(clone({ d: date }).d, date, 'different object')
})
test(label + ' – nested date in array', async ({is, isNot}) => {
test(label + ' – nested date in array', async ({ is, isNot }) => {
const date = new Date()
is(+clone({d: [date]}).d[0], +date, 'same value')
isNot(clone({d: [date]}).d[0], date, 'different object')
is(+cloneCircles({d: [date]}).d[0], +date, 'same value')
isNot(cloneCircles({d: [date]}).d, date, 'different object')
is(+clone({ d: [date] }).d[0], +date, 'same value')
isNot(clone({ d: [date] }).d[0], date, 'different object')
is(+cloneCircles({ d: [date] }).d[0], +date, 'same value')
isNot(cloneCircles({ d: [date] }).d, date, 'different object')
})
test(label + ' – nested null', async ({is}) => {
is(clone({n: null}).n, null, 'same value')
test(label + ' – nested null', async ({ is }) => {
is(clone({ n: null }).n, null, 'same value')
})
test(label + ' – arguments', async ({isNot, same}) => {
test(label + ' – arguments', async ({ isNot, same }) => {
function fn (...args) {

@@ -185,2 +219,62 @@ same(clone(arguments), args, 'same values')

})
test(`${label} copies buffers from object correctly`, async ({ ok, is, isNot }) => {
const input = Date.now().toString(36)
const inputBuffer = Buffer.from(input)
const clonedBuffer = clone({ a: inputBuffer }).a
ok(Buffer.isBuffer(clonedBuffer), 'cloned value is buffer')
isNot(clonedBuffer, inputBuffer, 'cloned buffer is not same as input buffer')
is(clonedBuffer.toString(), input, 'cloned buffer content is correct')
})
test(`${label} copies buffers from arrays correctly`, async ({ ok, is, isNot }) => {
const input = Date.now().toString(36)
const inputBuffer = Buffer.from(input)
const [clonedBuffer] = clone([inputBuffer])
ok(Buffer.isBuffer(clonedBuffer), 'cloned value is buffer')
isNot(clonedBuffer, inputBuffer, 'cloned buffer is not same as input buffer')
is(clonedBuffer.toString(), input, 'cloned buffer content is correct')
})
test(`${label} copies TypedArrays from object correctly`, async ({ ok, is, isNot }) => {
const [input1, input2] = [rnd(10), rnd(10)]
var buffer = new ArrayBuffer(8)
const int32View = new Int32Array(buffer)
int32View[0] = input1
int32View[1] = input2
const cloned = clone({ a: int32View }).a
ok(cloned instanceof Int32Array, 'cloned value is instance of class')
isNot(cloned, int32View, 'cloned value is not same as input value')
is(cloned[0], input1, 'cloned value content is correct')
is(cloned[1], input2, 'cloned value content is correct')
})
test(`${label} copies TypedArrays from array correctly`, async ({ ok, is, isNot }) => {
const [input1, input2] = [rnd(10), rnd(10)]
var buffer = new ArrayBuffer(16)
const int32View = new Int32Array(buffer)
int32View[0] = input1
int32View[1] = input2
const [cloned] = clone([int32View])
ok(cloned instanceof Int32Array, 'cloned value is instance of class')
isNot(cloned, int32View, 'cloned value is not same as input value')
is(cloned[0], input1, 'cloned value content is correct')
is(cloned[1], input2, 'cloned value content is correct')
})
test(`${label} copies complex TypedArrays`, async ({ ok, deepEqual, is, isNot }) => {
const [input1, input2, input3] = [rnd(10), rnd(10), rnd(10)]
var buffer = new ArrayBuffer(4)
const view1 = new Int8Array(buffer, 0, 2)
const view2 = new Int8Array(buffer, 2, 2)
const view3 = new Int8Array(buffer)
view1[0] = input1
view2[0] = input2
view3[3] = input3
const cloned = clone({ view1, view2, view3 })
ok(cloned.view1 instanceof Int8Array, 'cloned value is instance of class')
ok(cloned.view2 instanceof Int8Array, 'cloned value is instance of class')
ok(cloned.view3 instanceof Int8Array, 'cloned value is instance of class')
isNot(cloned.view1, view1, 'cloned value is not same as input value')
isNot(cloned.view2, view2, 'cloned value is not same as input value')
isNot(cloned.view3, view3, 'cloned value is not same as input value')
deepEqual(Array.from(cloned.view1), [input1, 0], 'cloned value content is correct')
deepEqual(Array.from(cloned.view2), [input2, input3], 'cloned value content is correct')
deepEqual(Array.from(cloned.view3), [input1, 0, input2, input3], 'cloned value content is correct')
})
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc