pax_global_header00006660000000000000000000000064141361276530014522gustar00rootroot0000000000000052 comment=41da7dc2a0edae815c79c4b8debddf0ab4dfc21b klona-2.0.5/000077500000000000000000000000001413612765300126325ustar00rootroot00000000000000klona-2.0.5/.editorconfig000066400000000000000000000003231413612765300153050ustar00rootroot00000000000000# http://editorconfig.org root = true [*] indent_size = 2 indent_style = tab end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true [*.{json,yml,md}] indent_style = space klona-2.0.5/.github/000077500000000000000000000000001413612765300141725ustar00rootroot00000000000000klona-2.0.5/.github/FUNDING.yml000066400000000000000000000000171413612765300160050ustar00rootroot00000000000000github: lukeed klona-2.0.5/.github/workflows/000077500000000000000000000000001413612765300162275ustar00rootroot00000000000000klona-2.0.5/.github/workflows/ci.yml000066400000000000000000000016551413612765300173540ustar00rootroot00000000000000name: CI on: push: paths: - '*.json' - '.github/**' - 'test/**' - 'src/**' branches: - '**' tags-ignore: - '**' pull_request: paths: - '*.json' - '.github/**' - 'test/**' - 'src/**' branches: - master jobs: test: name: Node.js v${{ matrix.nodejs }} runs-on: ubuntu-latest strategy: matrix: nodejs: [8, 10, 12] steps: - uses: actions/checkout@v2 - uses: actions/setup-node@v1 with: node-version: ${{ matrix.nodejs }} - name: Install run: | npm install npm install -g nyc - name: Test w/ Coverage run: nyc --include=src npm test - name: Report if: matrix.nodejs >= 12 run: | nyc report --reporter=text-lcov > coverage.lcov bash <(curl -s https://codecov.io/bash) env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} klona-2.0.5/.gitignore000066400000000000000000000001061413612765300146170ustar00rootroot00000000000000node_modules .DS_Store *-lock.* *.lock *.log /dist /json /lite /full klona-2.0.5/bench/000077500000000000000000000000001413612765300137115ustar00rootroot00000000000000klona-2.0.5/bench/fixtures/000077500000000000000000000000001413612765300155625ustar00rootroot00000000000000klona-2.0.5/bench/fixtures/default.js000066400000000000000000000010131413612765300175370ustar00rootroot00000000000000class Test { constructor(num = 123) { this.value = num; this.items = [1, 2, 3]; } get number() { return this.value; } } module.exports = { regexp: /foo[\\\/](?=\d)/, array: [ new Date(), new Date(100), 'invalid date', Date.now(), ], map: new Map([ [{ foo: 1 }, { a: 1 }], [{ bar: 2 }, { b: 2 }], ]), set: new Set([ { foo: 1 }, { bar: 2 }, [1, 2, 3] ]), custom: new Test(456), int8arr: new Int8Array([4, 5, 6]), dataview: new DataView(new ArrayBuffer(4)), buffer: Buffer.from('hello'), } klona-2.0.5/bench/fixtures/full.js000066400000000000000000000013651413612765300170670ustar00rootroot00000000000000const symbol1 = Symbol('foo'); const symbol2 = Symbol('bar'); const item = { regexp: /foo[\\\/](?=\d)/, array: [ new Date(), new Date(100), 'invalid date', Date.now(), ], map: new Map([ [{ foo: 1 }, { a: 1 }], [{ bar: 2 }, { b: 2 }], ]), set: new Set([ { foo: 1 }, { bar: 2 }, [1, 2, 3] ]), int8arr: new Int8Array([4, 5, 6]), buffer: Buffer.from('hello'), symbol1: symbol1, symbol2: symbol2, [symbol1]: 'hello', [symbol2]: [1, 2, 3, 4] } Object.defineProperty(item, 'hidden1', { enumerable: false, value: 'found me' }); Object.defineProperty(item, 'hidden2', { enumerable: false, value: [1, 2, 3] }); Object.defineProperty(item, 'secret', { enumerable: false, get() { return 'password'; } }); module.exports = item; klona-2.0.5/bench/fixtures/json.js000066400000000000000000000052601413612765300170740ustar00rootroot00000000000000module.exports = [ { "_id": "5e16d8c6d7eee2857c907fbe", "index": 0, "nickname": null, "isActive": false, "balance": 2077.55, "picture": "http://placehold.it/32x32", "age": 33, "details": { "email": "ericksonphillips@retrotex.com", "address": { "street": "554 Lyme Avenue", "city": "Harborton", "state": "Texas", "zipcode": 4945, "coords": { "latitude": 61.497735, "longitude": -38.711066 } } }, "interests": [ "amet", "voluptate", "sit", "duis", "fugiat", "consectetur", "amet" ], "friends": [ { "id": 0, "name": "Belinda Chandler", "friends_common": { "count": 2, "friends_of_friends": [ { "id": 0, "name": "George Ayala" }, { "id": 1, "name": "Nadia Nguyen" } ] } }, { "id": 1, "name": "Sheena Kidd", "friends_common": { "count": 2, "friends_of_friends": [ { "id": 0, "name": "Kimberly Martinez" }, { "id": 1, "name": "Meadows Fitzpatrick" } ] } }, { "id": 2, "name": "Winnie Mccarthy", "friends_common": { "count": 2, "friends_of_friends": [ { "id": 0, "name": "Robbie Dale" }, { "id": 1, "name": "Orr Houston" } ] } } ] }, { "_id": "5e16d8c6ed426d1c22bf306b", "index": 1, "nickname": null, "isActive": false, "balance": 2916.08, "picture": "http://placehold.it/32x32", "age": 20, "details": { "email": "orrhouston@retrotex.com", "address": { "street": "962 McDonald Avenue", "city": "Lithium", "state": "West Virginia", "zipcode": 4536, "coords": { "latitude": 83.372808, "longitude": 150.181923 } } }, "interests": [ "eu", "et", "dolore", "sunt", "elit", "nulla", "fugiat" ], "friends": [ { "id": 0, "name": "Hood Washington", "friends_common": { "count": 2, "friends_of_friends": [ { "id": 0, "name": "Hebert Delacruz" }, { "id": 1, "name": "Sharp Rose" } ] } }, { "id": 1, "name": "Karla Velasquez", "friends_common": { "count": 2, "friends_of_friends": [ { "id": 0, "name": "Carey Holman" }, { "id": 1, "name": "Baird Short" } ] } }, { "id": 2, "name": "Juliet Oneal", "friends_common": { "count": 2, "friends_of_friends": [ { "id": 0, "name": "Owens Richards" }, { "id": 1, "name": "Lily Olsen" } ] } } ] } ] klona-2.0.5/bench/fixtures/lite.js000066400000000000000000000055011413612765300170560ustar00rootroot00000000000000module.exports = [ { "_id": "5e16d8c6d7eee2857c907fbe", "index": 0, "nickname": null, "isActive": false, "balance": 2077.55, "password": undefined, "picture": "http://placehold.it/32x32", "age": 33, "joined": new Date(), "locales": /(EN|ES)/i, "details": { "email": "ericksonphillips@retrotex.com", "address": { "street": "554 Lyme Avenue", "city": "Harborton", "state": "Texas", "zipcode": 4945, "coords": { "latitude": 61.497735, "longitude": -38.711066 } } }, "interests": [ "amet", "voluptate", "sit", "duis", "fugiat", "consectetur", "amet" ], "friends": [ { "id": 0, "name": "Belinda Chandler", "friends_common": { "count": 2, "friends_of_friends": [ { "id": 0, "name": "George Ayala" }, { "id": 1, "name": "Nadia Nguyen" } ] } }, { "id": 1, "name": "Sheena Kidd", "friends_common": { "count": 2, "friends_of_friends": [ { "id": 0, "name": "Kimberly Martinez" }, { "id": 1, "name": "Meadows Fitzpatrick" } ] } }, { "id": 2, "name": "Winnie Mccarthy", "friends_common": { "count": 2, "friends_of_friends": [ { "id": 0, "name": "Robbie Dale" }, { "id": 1, "name": "Orr Houston" } ] } } ] }, { "_id": "5e16d8c6ed426d1c22bf306b", "index": 1, "nickname": null, "isActive": false, "balance": 2916.08, "password": undefined, "picture": "http://placehold.it/32x32", "age": 20, "joined": new Date(), "locales": /(EN)/i, "details": { "email": "orrhouston@retrotex.com", "address": { "street": "962 McDonald Avenue", "city": "Lithium", "state": "West Virginia", "zipcode": 4536, "coords": { "latitude": 83.372808, "longitude": 150.181923 } } }, "interests": [ "eu", "et", "dolore", "sunt", "elit", "nulla", "fugiat" ], "friends": [ { "id": 0, "name": "Hood Washington", "friends_common": { "count": 2, "friends_of_friends": [ { "id": 0, "name": "Hebert Delacruz" }, { "id": 1, "name": "Sharp Rose" } ] } }, { "id": 1, "name": "Karla Velasquez", "friends_common": { "count": 2, "friends_of_friends": [ { "id": 0, "name": "Carey Holman" }, { "id": 1, "name": "Baird Short" } ] } }, { "id": 2, "name": "Juliet Oneal", "friends_common": { "count": 2, "friends_of_friends": [ { "id": 0, "name": "Owens Richards" }, { "id": 1, "name": "Lily Olsen" } ] } } ] } ] klona-2.0.5/bench/index.js000066400000000000000000000055061413612765300153640ustar00rootroot00000000000000const { join } = require('path'); const { Suite } = require('benchmark'); console.log('Load times: '); console.time('lodash/clonedeep'); const lodash = require('lodash/clonedeep'); console.timeEnd('lodash/clonedeep'); console.time('rfdc'); const rfdc = require('rfdc'); console.timeEnd('rfdc'); console.time('clone'); const clone = require('clone'); console.timeEnd('clone'); console.time('clone-deep'); const clonedeep = require('clone-deep'); console.timeEnd('clone-deep'); console.time('deep-copy'); const deepcopy = require('deep-copy'); console.timeEnd('deep-copy'); console.time('klona/full'); const full = require('klona/full'); console.timeEnd('klona/full'); console.time('klona'); const klona = require('klona'); console.timeEnd('klona'); console.time('klona/lite'); const lite = require('klona/lite'); console.timeEnd('klona/lite'); console.time('klona/json'); const json = require('klona/json'); console.timeEnd('klona/json'); const naiive = x => JSON.parse(JSON.stringify(x)); const clone_full = x => clone(x, { includeNonEnumerable: true }); function runner(name, contenders) { const fixture = join(__dirname, 'fixtures', name + '.js'); const validator = join(__dirname, 'validate', name + '.js'); console.log('\nValidation :: %s', name); Object.keys(contenders).forEach(name => { const isValid = require(validator); const INPUT = require(fixture); try { isValid(INPUT, contenders[name](INPUT)); console.log(' ✔', name); } catch (err) { console.log(' ✘', name, `(FAILED @ "${err.message}")`); } finally { delete require.cache[fixture]; } }); const INPUT = require(fixture); console.log('\nBenchmark :: %s', name); const bench = new Suite().on('cycle', e => { console.log(' ' + e.target); }); Object.keys(contenders).forEach(name => { bench.add(name + ' '.repeat(22 - name.length), () => contenders[name](INPUT)) }); bench.run(); } // --- // ONLY KEEP PASSING // --- runner('json', { 'JSON.stringify': naiive, 'lodash': lodash, 'rfdc': rfdc(), 'clone': clone, 'clone/include': clone_full, 'clone-deep': clonedeep, 'deep-copy': deepcopy, 'klona/full': full.klona, 'klona': klona.klona, 'klona/lite': lite.klona, 'klona/json': json.klona, }); runner('lite', { 'lodash': lodash, 'clone': clone, 'clone/include': clone_full, 'clone-deep': clonedeep, 'klona/full': full.klona, 'klona': klona.klona, 'klona/lite': lite.klona, }); runner('default', { 'lodash': lodash, // FAIL @ Buffer, Map keys 'clone': clone, // FAIL @ DataView 'clone/include': clone_full, // FAIL @ DataView // FAIL @ "Set #2" & "Map #2" :: 'clone-deep': clonedeep, 'klona/full': full.klona, 'klona': klona.klona, }); runner('full', { 'lodash': lodash, // FAIL @ Buffer, Map keys, non-enumerable properties, 'clone/include': clone_full, // FAIL @ DataView, non-enumerable descriptors 'klona/full': full.klona, }); klona-2.0.5/bench/package.json000066400000000000000000000003661413612765300162040ustar00rootroot00000000000000{ "private": true, "devDependencies": { "benchmark": "2.1.4", "clone": "2.1.2", "clone-deep": "4.0.1", "deep-copy": "1.4.2", "deepcopy": "2.0.0", "klona": "file:../", "lodash": "4.17.19", "rfdc": "1.1.4" } } klona-2.0.5/bench/validate/000077500000000000000000000000001413612765300155025ustar00rootroot00000000000000klona-2.0.5/bench/validate/default.js000066400000000000000000000040161413612765300174650ustar00rootroot00000000000000const assert = require('assert'); module.exports = function (input, copy) { assert.deepStrictEqual(copy, input, 'initial copy'); // RegExp copy.regexp.lastIndex = 9; assert.notEqual(input.regexp.lastIndex, 9, 'regexp.lastindex'); // Array + Date input.array[0].setMinutes(1); assert.notEqual(copy.array[0].getMinutes(), 0, 'Array #1'); copy.array[3] = new Date(copy.array[3]); assert.notEqual(input.array[3] instanceof Date, true, 'Array #2'); // Set input.set.add(9); assert.equal(copy.set.has(9), false, 'Set #1'); [...copy.set][2].push(123); assert.deepEqual([...input.set][2], [1, 2, 3], 'Set #2'); assert.deepEqual([...copy.set][2], [1, 2, 3, 123], 'Set #3'); // Map input.map.set('hello', 'world'); assert.equal(copy.map.has('hello'), false, 'Map #1'); [...copy.map.keys()][0].bar = 123; assert.deepEqual([...input.map.keys()][0], { foo: 1 }, 'Map #2'); assert.deepEqual([...copy.map.keys()][0], { foo: 1, bar: 123 }, 'Map #3'); // Class input.custom.value = 789; assert.equal(copy.custom.number, 456, 'Class #1'); input.custom.items.push(789); assert.deepEqual(copy.custom.items, [1, 2, 3], 'Class #2'); copy.custom.items.pop(); assert.equal(input.custom.items.length, 4, 'Class #3'); // Int8Array copy.int8arr[1] = 42; assert.equal(input.int8arr[1], 5, 'Int8 #1'); input.int8arr[0] = 0; assert.equal(copy.int8arr[0], 4, 'Int8 #2'); // Buffer :: "hello" copy.buffer.write('foobar'); assert.equal(input.buffer.toString(), 'hello', 'Buffer #1'); copy.buffer[1] = 11; assert.notEqual(input.buffer[1], copy.buffer[1], 'Buffer #2'); const current = copy.buffer.toString(); input.buffer.write('hello'); assert.equal(copy.buffer.toString(), current, 'Buffer #3'); // DataView :: [0, 0, 0] input.dataview.setInt8(1, 1); assert.equal(input.dataview.getInt8(1), 1, 'Dataview #1'); assert.equal(copy.dataview.getInt8(1), 0, 'Dataview #2'); copy.dataview.setInt8(0, 3); assert.equal(input.dataview.getInt8(0), 0, 'Dataview #3'); assert.equal(copy.dataview.getInt8(0), 3, 'Dataview #4'); } klona-2.0.5/bench/validate/full.js000066400000000000000000000047321413612765300170100ustar00rootroot00000000000000const assert = require('assert'); module.exports = function (input, copy) { // assert.deepStrictEqual(copy, input, 'initial copy'); // RegExp copy.regexp.lastIndex = 9; assert.notEqual(input.regexp.lastIndex, 9, 'regexp.lastindex'); // Array + Date input.array[0].setMinutes(1); assert.notEqual(copy.array[0].getMinutes(), 0, 'Array #1'); copy.array[3] = new Date(copy.array[3]); assert.notEqual(input.array[3] instanceof Date, true, 'Array #2'); // Set input.set.add(9); assert.equal(copy.set.has(9), false, 'Set #1'); [...copy.set][2].push(123); assert.deepEqual([...input.set][2], [1, 2, 3], 'Set #2'); assert.deepEqual([...copy.set][2], [1, 2, 3, 123], 'Set #3'); // Map input.map.set('hello', 'world'); assert.equal(copy.map.has('hello'), false, 'Map #1'); [...copy.map.keys()][0].bar = 123; assert.deepEqual([...input.map.keys()][0], { foo: 1 }, 'Map #2'); assert.deepEqual([...copy.map.keys()][0], { foo: 1, bar: 123 }, 'Map #3'); // Int8Array copy.int8arr[1] = 42; assert.equal(input.int8arr[1], 5, 'Int8 #1'); input.int8arr[0] = 0; assert.equal(copy.int8arr[0], 4, 'Int8 #2'); // Buffer :: "hello" copy.buffer.write('foobar'); assert.equal(input.buffer.toString(), 'hello', 'Buffer #1'); copy.buffer[1] = 11; assert.notEqual(input.buffer[1], copy.buffer[1], 'Buffer #2'); const current = copy.buffer.toString(); input.buffer.write('hello'); assert.equal(copy.buffer.toString(), current, 'Buffer #3'); // Symbol assert.equal(input.symbol1, copy.symbol1, 'Symbol #1'); assert.equal(input.symbol2, copy.symbol2, 'Symbol #2'); // Symbol Properties assert.equal(input[input.symbol1], 'hello', 'SymProp #1'); assert.equal(copy[copy.symbol1], 'hello', 'SymProp #2'); input[input.symbol2].push(7, 8, 9); assert.equal(input[input.symbol2].length, 7, 'SymProp #3'); assert.equal(copy[copy.symbol2].length, 4, 'SymProp #4'); copy[copy.symbol2].push('hello'); assert.equal(input[input.symbol2].length, 7, 'SymProp #3'); assert.equal(copy[copy.symbol2].length, 5, 'SymProp #4'); // NON-Enumerable Properties assert.deepEqual( Object.getOwnPropertyDescriptor(input, 'hidden1'), Object.getOwnPropertyDescriptor(copy, 'hidden1'), 'Hidden #1' ); assert.deepEqual( Object.getOwnPropertyDescriptor(input, 'hidden2'), Object.getOwnPropertyDescriptor(copy, 'hidden2'), 'Hidden #2' ); assert.equal(input.secret, copy.secret, 'Hidden #3'); copy.hidden2.push('hello'); assert.equal(input.hidden2.includes('hello'), false, 'Hidden #4'); } klona-2.0.5/bench/validate/json.js000066400000000000000000000007751413612765300170220ustar00rootroot00000000000000const assert = require('uvu/assert'); module.exports = function (input, output) { assert.equal(output, input, 'initial copy'); output[0].age++; assert.is.not(input[0].age, 34, 'increment'); output[1].details.address.coords.longitude = 100; assert.is.not(input[1].details.address.coords.longitude, 100, 'nested assignment'); output[0].friends[1].friends_common.friends_of_friends.push('BOB'); assert.is(input[0].friends[1].friends_common.friends_of_friends.includes('BOB'), false, 'nested push'); } klona-2.0.5/bench/validate/lite.js000066400000000000000000000014031413612765300167730ustar00rootroot00000000000000const assert = require('uvu/assert'); module.exports = function (input, copy) { assert.equal(copy, input, 'initial copy'); copy[0].age++; assert.is.not(input[0].age, 34, 'increment'); copy[1].details.address.coords.longitude = 100; assert.is.not(input[1].details.address.coords.longitude, 100, 'nested assignment'); copy[0].friends[1].friends_common.friends_of_friends.push('BOB'); assert.is(input[0].friends[1].friends_common.friends_of_friends.includes('BOB'), false, 'nested push'); input[0].joined.setHours(9); assert.not.equal(input[0].joined, copy[0].joined); copy[0].joined.setMinutes(56); assert.not.equal(input[0].joined, copy[0].joined); copy[1].locales.lastIndex = 9; assert.is.not(input[1].locales.lastIndex, copy[1].locales.lastIndex); } klona-2.0.5/index.d.ts000066400000000000000000000000461413612765300145330ustar00rootroot00000000000000export function klona(input: T): T;klona-2.0.5/license000066400000000000000000000021201413612765300141720ustar00rootroot00000000000000MIT License Copyright (c) Luke Edwards (lukeed.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. klona-2.0.5/logo.png000066400000000000000000000504521413612765300143060ustar00rootroot00000000000000PNG  IHDRna pHYs  sRGBgAMA aPIDATxoU՝E HPʄ 1@Ct!FEy {`&U]t:OTS%`Wu t"BO3]\t+A5`p s?Yx8k~Us>{]5p"H 'p"H 'p"H 'p"H 'p"A2W6'O6ƍ3K.5v2EЍ;5Ơ34h~O>k #@蘍7td@x c˖-73f0֭33gt?|}'Mdn2@20FÆ }g֮]5Hl߾=ǎ3L*`kժUو1 e U4k֬eY`Aϟ9T:eJaCaBB4)Ϡ"yK4ݻYny;td@WcP&[f8Ϡ#y~N̦MNzh3P`cXQk֬)\FT..ʺ* tq<mPSYl&Ne <+W̝}bDaGajRTuVS7uUT2m۶јE0Q*uڼys 8 D]wUh0р,6S$RtQS b4iʋ]AA Ee(5)$l,&bG&uS/li m Z,v! bDOsQf쁣}AGeCyhd(gP` f^zN l ( OG \`:|pgWyA_,Y2pI=qڦ"Pzozcɶ=k0Ӡm>o޼dj3  'rQp&soٲ%lveG%KV*tPjիMOe/ݵ}E_@A+DEvAA;hcOMS?8?x0 ä'jbw^U}UJ p* @FGOG1'O4s2!#q|9FrLr4ft?(VEK2!QSۚ(04ؿ꫇[oN.~n /Am.I XӧO5̱daH&t7lʕ+!˨tכh{k #]_|y,q7R8䁎w%ş@f͚\?ӦM3.ʦ۷ol瘔d|%my%۽mQt`?fΧ͞=/?lLд8>lnJީGKO/&jE}F˓pǹ,C]v.X-O'~*^A@AbDP5BQJ|+$?F"B^*=qQ?aI uߙ'OBh؋8ib5ag:q|f8&R7ndA*;75(띷t-t q<_y[Kz 'x 0 7 :Z/Uny[4M^Fhxk"+W;S G(0ikGA< z48i[-!EǣXxMg )e( qѫdSYjOYKNdr1Qͳ>3fĉwȫJ`ڴKKMHQTq_|=rMS~wb,!rdڄ( MۺIPBbLePel)de>P; @4wLYӦM5W^y q<|5TE暲<رc A4 }e~AyX"4RM4Q~q<|9_3y#$|v&r?;Us^ q<|9?ÕDMMÙߟ?jң; JT۬BFbV!!kC4 AY(׉FnG}rçxUJ87m&jg?nTuꂄEbUP*C WJ<`3f8ӧ÷xU!̙S=*C4@b>Cpa*FCE@|4NЫ cwʔ MU>AuM57x@ew}fڵuP1 o]Lx 0Eݻ7dQ+W"cM*.k=䓦KTu<m9[άZq@a>8p!çj8mڥȑ7MMW!D#'£;Y\EVa>$,v6N9PIS/L0Ă8>u)ud/ u5޽y#`etIC ͛g &6}8u-;rヒՓy@\SjBy9I鄷zd~5uw>PoM%q$Qj~ӄ .]3{ǬkwPuRK/V)=D `tnڴ)ij@| EA@:u1UQg 5QTRNEE,(#=nذ!d9yZr"S9|#c^W.C?'B.Zʃ_(͚1R*xԭqiS._4U<~#J (ӠS4 ;N"/ "4IT;. .)36OE CD&t1yDD `0(SvȠHe<~DT\Yo /_dʔ MhѤZqD3 *wTfT{}ޘLWCt m;i>Tt>W4 Á8^4?Mv^J^vgQ)Ӭʍ͚5f0}ҶS>uާD.>/8~8geс:@Nv0W)t42i۩H)2:5Cl x8q|3Hї:@'sA;DcMZזgؾ}{l7PJZ+e: p+rfhiLO1ԥʾ2{C5P q踲ݰpm?c >S%jg?iG/G]r'4h,JKWݻwaI5oONyGc|[Å8Yӧ[eӫ .408W߼y2a~WՄ&Gt vP Å8Y&o|DAWÕnZ@MΨAgJWXabk>< @9w6m".1k%4:4@ӠBe&Рdɒ̟Q6*m7ZZn[}~,~-Es\/@h{rKI]+1gڙW^ES/Yց\v  bZVϻvZ2$z54 ;R֙Wˬ~ zw/!@?ExMU5$'LW U pe.}HMR&+OcEY~}\3 xk z.e,XPu{͓˳JhY>50;y_ ڟ@AI uAh,:4)F@TF/JIe g͚lJKVFYeP [:3$]zeسwŶp$'E_N1 PKVFGYKKY";uǎ3v.OYDzA%O.ܩkɓ޷o_޽{+{?kCX̐+RjlU0nKmG=t^oy}նW_g̘c l͎//{,2m!?qwٰ"E߼a+SI y]t@)+\=ٻFvڲ` ƀ#t\b ,M@_k ѝ([2@yҤILc $SϢ&D" ub}̞Wua!ږ9x\GJ,Uگ況h}׏8Y!񾓅,]xlmb) *'>K]}Z͕#r.xc^OcZ.iP [o~ J\ >y!]Am/=b`jCU[q|sz$ =D# ׇk) H> mj@0#ftƷ޻bj\l'>K]F$eжWO缼y'yKYY?_\߻TuWm}:EWGjYu *} v&䪲] t+P&[$aRdHK*9Žcc1y6˫uN۽~{~Ʒ{ d!OGx˶Nh6 CK`]IeY` ezKN*!nF՘>vKϛ_1ujڹ_v˺(FB^UVA7*@6W۳–ܻ@;2dV{9^Eu]>CI|vƏ:LJ:@hAF@wBlvR_\4|~̓> ,\Ys_MʞzieCx㟓={1##Ϙ<; r)#ZRv`.cYIs)ȴ/vE<[B2dlYwq^J.&Y}.Uqӆ:1z+1V"Ѵ Uq U 56j< y/e߿e3eʌ$妛V.s:K/d2}~.4)n$(Dti6H+ii#c-}aoĎmpHDQK"[9d^ybrcE&J5Iơ6k< oOSB]ICAGSO$Ɨtm245q}v 65)hr?sH T (KK h#yw@\K./`jZ]N76%Yק+4u=y`mUh4tǫm=逪`V :$;&$=:zœ8A#c… .H2s;ĩ ZW]=svt? 0n,m~wtJLb*OZJ*l)p.u tYd{9JIA fUĝNO.z8%t75\1%Ļi|7nq`~wcFg񓟼L6ЕSN=^`4_6G5wZd`<y쥂.N\k"s*k| quHV_|&,mJ"(hNҠ0?tHRnlܠcDSrՖ{g[]!GFݽ+)]McG?q?g=mwcFIPy)w?#ٯmR$[Y~YR~FlUh}WYM}M <,ÄLNf\[*=Oj>tYm˚Pw] ]T*םAoݕ<+Az=i?m7ꅠ >QBz(SQX2nsz @K;Met*3ҁ3ud9LʹtP ^G8/{gqĉgeT1VQɖ mRM]<\=Ԟ3s)S.L :~`E$-;z}$Tw*lg͜9 ڣ q^9Fą0-83o1`|%,:]BmUjĆehȯo#]iP#?qc!::vW#q|1XAY%I~yY >sxˢrH;MSS͉*Jedyi"'JkĜ93 q;+tv[SE_BMM(sϋ0KJ%ʼvɉ:qiwSc qeliZtsRgIMj<^3kWFƏ?[Mus{\V+WI%vMruR "KSn+%(`*7Q/mA%V>JzvI4}wYO]ۦ>A! 'ϋ8 :\4_r޽nv<'g-aU\j4;&6V25JW'؟lgҳ&kP}啗' ꡆϧvucPe6&S\|ƾ4MlYw5q\6 tAcdkݕ}iVS^CU%Fi.xxxH qHt"mb'j'ϝ4vMX5QSAJ){- ?'p{z u7^р\,6`,v%e o첑v IǕ<бs㼦.n{j Xuh bA E)ܵB*O߀wxBy!jPrBO=SWm4+ۦ{]Z/&g_9<Iw[)Tn&7u-aq*X|R/1ZI HM>ډ59/ȁ2IY={I*Wti48TFsf5VA'&VxKrͣʢAG'MdtDMyT¢R]^Z f j֭il롇1?UW-3eL81kY_,Vs<~> F/:ݷȊʃb>l| @]&." nBo3|)Ծu =ԪCوF-U <'쬥kmZBW#W-{+[9۬:Y4b˜nʖ6Bcɓ':/Dې]<rAJ o!OK} OGq|9OUǣV7cW;!e3Eo銚$ =ϚT>FVۢcǎ%ۿΟfq66P9Ӓ]>Wgi!%q1|WbM&M2mcjٶeRB#'I8g-Vӟ׷uk^_)@&>E8QY+uRd1R}[u1qAc>z9_EmM8>{O]Qgy}, }.bǟ8~i[qƩzA\YCwѣw$J~XVHs;MYstau (b @xsnٲp OBУ:>RK0u]~}) 1sz]}6uTv|J ǟ:u8eS\d| "hYUNϧ?=`9wj~?,?95W3Ȁ~uۺ/@H+CV G!NLʧ) |WV0D6|.>ot4 !F߼3>uu@x;.UƛnZe|YfϾ,k鎰ٙ-͒U6KPi3iYāB'dwHKs_Q^H: Twhd8sC@ w#oVqd@P[XJ!]g4jҗM%i`28X|ԋjOeT֚6W"P*$J c mL ۩sA绐Lj)S6Qx7N1UhIJ:88iQǠcist|Hcx\+Uٔ(sRN;U6 C!M(R|ڇ qUC<&a \᭷5"/8gE9?4@p\F',ywT'&2/hϸq㒇k*6S,*k\ Qύgk{U 5L2kjqaÆ ޒv Un q|<~@6Qt ֬YsfY+6S4(8SŮu`%ZH vDP&gل>W=t.lAzMzQc -x&q||NaI xjء'{cf|94#@Ot;CsJ,O|G@Wr@Kīɓ歷&xBt6y Z֭^v~#i BNYA6yA7&7JDGzB|`!+q||6Q1RS OLN'nR*\] _<{b F' ,58unk%O=,\8woe¤hAw+]x@' Ƀs5DQU7 %4d-4,ӧ @ ?Wq|W` 0Ve <~MPEuMc3ȺA?ҼW_=dνE*S6=|oSb>7W32Tlٲ\4tUVym b9UUI $8\1?zm` (>Ę_bEu}u/d~?Y\\pk;M]Tt@CZB zٚ7yāV`عsyw1n@2 _E߮XxMgA$|6-i+ê'O?v22L4Zpݐ.Zɺ&* VxB޽{SYsLAo@[I Pr$?Wlq/<ܳ?C_?IiꋉH 9XcZ+w`y:+k4mZ=/ꠒ7831$%N^ܹ%WU̙33ixn:SQ vIiE +yCsOQ"3 {="sǷ+8g:oAkݪ۷'b2ͬha}Gib0|c u%;iJ",_ߵ{6Ks5{W@H[nJ1]jR_Oڀeg^[nM֘/sW^*|iI:UҼA|+J,X Y޵Hw}A+v#,8?_'o>'u&Y5cp,~Ϭ`I;2c#&tZ}Q WRhFV7OT wZROp3OcV೨&.]N hBSFtfB~u?˛6m2Mp%2L4Au!J %ݷA7FL\][ y2*t dҴ(wxFGoAɪ[oS3u괁5:;0?={'d֬Y΄/J i)۹i.2-҄8~xUd7O$oJZ)&<13WHw\w-Fw=ƍXvVg :<=c{$cN}4{owB]SQgz\}0X_K8%\s}~Qǒ1󹜣;>b$LJB_S|%+@<V5 އwJν/4<'uTĉMz^`R.4Y^j؛@4f=n:H iJ0s(Bs@]Y񔈢A |w5MΗRC=_e>JF&|#&/LJon%sjQ|ڐ9U,^9T؟=2UW}!ϾΩ C?MT`hʺo4u4:﹚qՁcN{ u<{K+gMW d-\~Vtq`us/v_@[/9uAs!UM,\A*lS OPج^.Z4oiU鎫&LH\⚇BIwژGYQ>-X:>)"iޟkU.mg?⪭&=ڞemܸٜ" ^Ϊ(]w4, :KYUr4cxe, %jTm7 E$y`<4ktF㰒:|rz.)3PÖ;P48gXż-YuOqI\KwVFIIz6m:sU$ϳO;imvܷӶB#Y/跷K]㛋%<-Sd EAl4$w@:^la,rGe>x\$Eˬco )) U(p:x` Z_{ߥQ@LF ;ͤ;qv):>3;]!4YloGYd}:V]s5UE1M諦(y&O~uWG㫭׮دgā%q/q|*~eK{n z/*ۓ?o c^z`CmNRDR{A7S vqػoO{Kӂ1S@c@M5^}x *r;ږٿ E^oHu{/5곴]w~cߣSY۴*ɔNi Ug3fs"SUfyQ4_=z>cMvkg !i gOaUX8>8iӦ&IaʔLBxJmjOo3֝Ÿ% Ń$i4VH Zd0נ;[&6:͛\&wUp ԘN`o]gȾ7;F}bI'y:\I=5 ݆B7 ~vWmU7w>OMGAnSu!_{i/d/6)d㥗޿u}~OۈgM\y>)EJ49ޖ! ALc*U Q\q|pcc4U4B-V>ȡJ+Hb\ .Ta+Ol W~ؤRsC]4RIS tu9U!l7IzY-1{C V 0,Fʚ[Ye2ChbJ4`NñS^5R#ć~Tqיӧ׃8>,jxmXxciɩ̐i.9m@Tr`NB$ۧ i.5GiڿY㋳ pc:8ȑj+hՎhqC,1- :l*[c0Ds,rC@]&.S@Wy|5mJ RShYꔪž(Dϫl@OYOs/cS~3jloQOSR*:@P,Y;ddHf.] d22Z=\Ҹ6,Zd*CY{u0:DUNO]XdBЩ'u__:6*Q6Sr@S#eevOT,Y咴-@|mN,ЊBh{~tYxŴJҪ * :˚#U>67 sU5nݺ5ʪ 8Ym„Bq|7xP6 Nuj 2rԖ-[Li;htN*- dhѕ U!qibTBN%ĕҺ1uqE~wuW6]tӲe3S\hŊbD?+qPr MV7t`/'eT]*-éqȋW*Q*ǎ3WRh p/2y qpjAP}̙eBԹh,^}OZ2}DkLO=R.eJȫtj^K.u%RsJ-[f:9 FJ0m P.KǎM C/WRndDo8@.T8wJ%Tq'lA\YI@)<8iԶmۜ?$I;6o q|u5״[lR曯3&7lA|Ke|Y7t6lY  &m!wShWc-tNׯwvNͥ5+n8MʝY&y}.v{y`X>3P8u!i\?%E=i~zPnѢ+>0&)/ vQst=hYm.swZ~O=c֭[g]wrN_|q|5vE="?}|=㹗j":thQNMee|<ȳJl]g 橧U nEhq'x"8^7ر+{GzІ2;@ YVZdz3ίK̼y,Rwɼi,]4T S/6|2I CAKrj饗~.5͠m1{ߝU6w隡X![q|qKS1SQS@+CfQfUsm1MڦgڵCɢƿ&} qوj})qh\p]0@Ȣ;ΙR672sʮX"9ؚ쀣A+I@uJ$h.vtӥ-~7ǫ]@qΧ?ki!IX$([ӢLϥ~\qżۅ~`FG_9캬~B>un(StUԩ̞=Ϙ^;PjIW4H@>xŷg:wYx)q< WzhPҿݻ7L8|'?yXV#gرwߓ|- dyyޏ\II:Y޾kB_1?i}UǤIf5Piǫڢlĉ|8y@JNּoĉGz3ugدvVǏOjԠSuVebo?e,?1z##Ϥ-CfM%ٳSx]_ǫA /)h,Sxq{JDBY~Gm,8{e5݉ǣ_@N$ )ի&.MKtRj* ?񊣉5$6m24>`25klذ!y͝;w& i͛7Ph:': CHЅv۷\ѵ*gրvWnu[OZqaRe%K+Vǣ$"AEvNub͘1#fg~Uɓ'ӧǣU$:@#6@N$ D8@N$ D8@N$ D8@N$ Dr:uTy{Rl̜9ӴcXGF1ǎ}{t=?4%q.͛7:t(b a;0|ǍGb CEK.5uYdi2\s%:ڴ8u PѪUj9xV^LV;4u{p뭷v:W8@Hsɵe(;CAG uz;ÄB; ֭[g6lؐdҠ7G5f2>yBJ`8]6K}6m *"Oڠ+_TޤI??'OtpܱcGms0aYb9~ٷo)Cqʕ{K &ŧ>ٳgO81_^xAk)1J\oߞ<@͢)Oʀb)ڵkٲeKH{tQV!@8^%7oN ( rp"H 'p"H 'p"H 'p"H 'p:oqa67.IENDB`klona-2.0.5/package.json000066400000000000000000000027421413612765300151250ustar00rootroot00000000000000{ "name": "klona", "version": "2.0.5", "repository": "lukeed/klona", "description": "A tiny (240B to 501B) and fast utility to \"deep clone\" Objects, Arrays, Dates, RegExps, and more!", "module": "dist/index.mjs", "unpkg": "dist/index.min.js", "main": "dist/index.js", "types": "index.d.ts", "license": "MIT", "author": { "name": "Luke Edwards", "email": "luke.edwards05@gmail.com", "url": "https://lukeed.com" }, "files": [ "*.d.ts", "dist", "full", "json", "lite" ], "exports": { ".": { "import": "./dist/index.mjs", "require": "./dist/index.js" }, "./json": { "import": "./json/index.mjs", "require": "./json/index.js" }, "./lite": { "import": "./lite/index.mjs", "require": "./lite/index.js" }, "./full": { "import": "./full/index.mjs", "require": "./full/index.js" }, "./package.json": "./package.json" }, "modes": { "json": "src/json.js", "lite": "src/lite.js", "default": "src/index.js", "full": "src/full.js" }, "engines": { "node": ">= 8" }, "scripts": { "build": "bundt", "pretest": "npm run build", "postbuild": "echo \"lite full json\" | xargs -n1 cp -v index.d.ts", "test": "uvu -r esm test -i suites" }, "keywords": [ "clone", "copy", "deep", "extend", "recursive", "object" ], "devDependencies": { "bundt": "1.0.2", "esm": "3.2.25", "uvu": "0.5.2" } } klona-2.0.5/readme.md000066400000000000000000000157601413612765300144220ustar00rootroot00000000000000
klona
A tiny (240B to 501B) and fast utility to "deep clone" Objects, Arrays, Dates, RegExps, and more!
## Features * Super tiny and [performant](#benchmarks) * Deep clone / recursive copies * Safely handles complex data types
_Array, Date, Map, Object, RegExp, Set, TypedArray, and more_ Unlike a "shallow copy" (eg, `Object.assign`), a "deep clone" recursively traverses a source input and copies its _values_ — instead of _references_ to its values — into a new instance of that input. The result is a structurally equivalent clone that operates independently of the original source and controls its own values. > **Why "klona"?** It's "clone" in Swedish.
> **What's with the sheep?** [Dolly](https://en.wikipedia.org/wiki/Dolly_(sheep)). ## Install ``` $ npm install --save klona ``` ## Modes There are multiple "versions" of `klona` available, which allows you to bring only the functionality you need! #### `klona/json` > **Size (gzip):** 240 bytes
> **Availability:** [CommonJS](https://unpkg.com/klona/json/index.js), [ES Module](https://unpkg.com/klona/json/index.mjs), [UMD](https://unpkg.com/klona/json/index.min.js)
> **Ability:** JSON data types ```js import { klona } from 'klona/json'; ``` #### `klona/lite` > **Size (gzip):** 354 bytes
> **Availability:** [CommonJS](https://unpkg.com/klona/lite/index.js), [ES Module](https://unpkg.com/klona/lite/index.mjs), [UMD](https://unpkg.com/klona/lite/index.min.js)
> **Ability:** extends `klona/json` with support for custom class, Date, and RegExp ```js import { klona } from 'klona/lite'; ``` #### `klona` > **Size (gzip):** 451 bytes
> **Availability:** [CommonJS](https://unpkg.com/klona/dist/index.js), [ES Module](https://unpkg.com/klona/dist/index.mjs), [UMD](https://unpkg.com/klona/dist/index.min.js)
> **Ability:** extends `klona/lite` with support for Map, Set, DataView, ArrayBuffer, TypedArray ```js import { klona } from 'klona'; ``` #### `klona/full` > **Size (gzip):** 501 bytes
> **Availability:** [CommonJS](https://unpkg.com/klona/full/index.js), [ES Module](https://unpkg.com/klona/full/index.mjs), [UMD](https://unpkg.com/klona/full/index.min.js)
> **Ability:** extends `klona` with support for Symbol properties and and non-enumerable properties ```js import { klona } from 'klona/full'; ``` ## Usage ```js import { klona } from 'klona'; const input = { foo: 1, bar: { baz: 2, bat: { hello: 'world' } } }; const output = klona(input); // exact copy of original assert.deepStrictEqual(input, output); // applying deep updates... output.bar.bat.hola = 'mundo'; output.bar.baz = 99; // ...doesn't affect source! console.log( JSON.stringify(input, null, 2) ); // { // "foo": 1, // "bar": { // "baz": 2, // "bat": { // "hello": "world" // } // } // } ``` ## API ### klona(input) Returns: `typeof input` Returns a deep copy/clone of the input. ## Benchmarks > Running Node v12.18.3 The benchmarks can be found in the [`/bench`](/bench) directory. They are separated into multiple categories: * `JSON` – compares an array of objects comprised of JSON data types (`String`, `Number`, `null`, `Array`, `Object`) * `LITE` – like `JSON`, but adds `RegExp`, `Date` and `undefined` values * `DEFAULT` – object with `RegExp`, `Date`, `Array`, `Map`, `Set`, custom class, `Int8Array`, `DataView`, `Buffer` values * `FULL` – like `DEFAULT`, but adds `Symbol` and non-enumerable properties > **Important:** Only candidates that pass validation step(s) are listed.
However, `lodash` and `clone` are kept to highlight important differences. > **Note:** The `clone/include` candidate refers to its [`includeNonEnumerable` option](https://www.npmjs.com/package/clone#api) enabled. ``` Load times: lodash/clonedeep 29.257ms rfdc 0.511ms clone 0.576ms clone-deep 2.494ms deep-copy 0.451ms klona/full 0.408ms klona 0.265ms klona/lite 0.308ms klona/json 0.263ms Benchmark :: JSON JSON.stringify x 53,899 ops/sec ±0.76% (92 runs sampled) lodash x 46,800 ops/sec ±0.86% (90 runs sampled) rfdc x 221,456 ops/sec ±0.88% (92 runs sampled) clone x 39,537 ops/sec ±0.68% (92 runs sampled) clone/include x 25,488 ops/sec ±1.06% (88 runs sampled) clone-deep x 99,998 ops/sec ±0.91% (93 runs sampled) deep-copy x 141,270 ops/sec ±0.95% (92 runs sampled) klona/full x 55,016 ops/sec ±0.68% (94 runs sampled) klona x 281,215 ops/sec ±0.77% (93 runs sampled) klona/lite x 318,481 ops/sec ±0.72% (91 runs sampled) klona/json x 334,932 ops/sec ±0.66% (93 runs sampled) Benchmark :: LITE lodash x 36,992 ops/sec ±0.65% (91 runs sampled) clone x 35,974 ops/sec ±1.13% (88 runs sampled) clone/include x 22,609 ops/sec ±1.02% (91 runs sampled) clone-deep x 92,846 ops/sec ±0.66% (93 runs sampled) klona/full x 47,873 ops/sec ±0.83% (88 runs sampled) klona x 226,638 ops/sec ±1.16% (93 runs sampled) klona/lite x 257,900 ops/sec ±0.82% (93 runs sampled) Benchmark :: DEFAULT lodash x 55,914 ops/sec ±0.75% (93 runs sampled) ✘ Buffer ✘ Map keys clone x 92,127 ops/sec ±0.83% (94 runs sampled) ✘ DataView clone/include x 62,052 ops/sec ±0.88% (93 runs sampled) ✘ DataView klona/full x 90,308 ops/sec ±0.68% (89 runs sampled) klona x 230,257 ops/sec ±0.71% (91 runs sampled) Benchmark :: FULL lodash x 60,361 ops/sec ±0.65% (91 runs sampled) ✘ Buffer ✘ Map keys ✘ Missing non-enumerable Properties clone/include x 47,263 ops/sec ±0.85% (93 runs sampled) ✘ DataView ✘ Incorrect non-enumerable Properties klona/full x 82,346 ops/sec ±0.62% (93 runs sampled) ``` ## Related * [dlv](https://github.com/developit/dlv) – safely **read** from deep properties in 120 bytes * [dset](https://github.com/lukeed/dset) – safely **write** into deep properties in 160 bytes * [dequal](https://github.com/lukeed/dequal) – safely check for deep equality in 304 to 489 bytes ## License MIT © [Luke Edwards](https://lukeed.com) klona-2.0.5/src/000077500000000000000000000000001413612765300134215ustar00rootroot00000000000000klona-2.0.5/src/full.js000066400000000000000000000031261413612765300147230ustar00rootroot00000000000000function set(obj, key, val) { if (typeof val.value === 'object') val.value = klona(val.value); if (!val.enumerable || val.get || val.set || !val.configurable || !val.writable || key === '__proto__') { Object.defineProperty(obj, key, val); } else obj[key] = val.value; } export function klona(x) { if (typeof x !== 'object') return x; var i=0, k, list, tmp, str=Object.prototype.toString.call(x); if (str === '[object Object]') { tmp = Object.create(x.__proto__ || null); } else if (str === '[object Array]') { tmp = Array(x.length); } else if (str === '[object Set]') { tmp = new Set; x.forEach(function (val) { tmp.add(klona(val)); }); } else if (str === '[object Map]') { tmp = new Map; x.forEach(function (val, key) { tmp.set(klona(key), klona(val)); }); } else if (str === '[object Date]') { tmp = new Date(+x); } else if (str === '[object RegExp]') { tmp = new RegExp(x.source, x.flags); } else if (str === '[object DataView]') { tmp = new x.constructor( klona(x.buffer) ); } else if (str === '[object ArrayBuffer]') { tmp = x.slice(0); } else if (str.slice(-6) === 'Array]') { // ArrayBuffer.isView(x) // ~> `new` bcuz `Buffer.slice` => ref tmp = new x.constructor(x); } if (tmp) { for (list=Object.getOwnPropertySymbols(x); i < list.length; i++) { set(tmp, list[i], Object.getOwnPropertyDescriptor(x, list[i])); } for (i=0, list=Object.getOwnPropertyNames(x); i < list.length; i++) { if (Object.hasOwnProperty.call(tmp, k=list[i]) && tmp[k] === x[k]) continue; set(tmp, k, Object.getOwnPropertyDescriptor(x, k)); } } return tmp || x; } klona-2.0.5/src/index.js000077500000000000000000000027731413612765300151020ustar00rootroot00000000000000export function klona(x) { if (typeof x !== 'object') return x; var k, tmp, str=Object.prototype.toString.call(x); if (str === '[object Object]') { if (x.constructor !== Object && typeof x.constructor === 'function') { tmp = new x.constructor(); for (k in x) { if (x.hasOwnProperty(k) && tmp[k] !== x[k]) { tmp[k] = klona(x[k]); } } } else { tmp = {}; // null for (k in x) { if (k === '__proto__') { Object.defineProperty(tmp, k, { value: klona(x[k]), configurable: true, enumerable: true, writable: true, }); } else { tmp[k] = klona(x[k]); } } } return tmp; } if (str === '[object Array]') { k = x.length; for (tmp=Array(k); k--;) { tmp[k] = klona(x[k]); } return tmp; } if (str === '[object Set]') { tmp = new Set; x.forEach(function (val) { tmp.add(klona(val)); }); return tmp; } if (str === '[object Map]') { tmp = new Map; x.forEach(function (val, key) { tmp.set(klona(key), klona(val)); }); return tmp; } if (str === '[object Date]') { return new Date(+x); } if (str === '[object RegExp]') { tmp = new RegExp(x.source, x.flags); tmp.lastIndex = x.lastIndex; return tmp; } if (str === '[object DataView]') { return new x.constructor( klona(x.buffer) ); } if (str === '[object ArrayBuffer]') { return x.slice(0); } // ArrayBuffer.isView(x) // ~> `new` bcuz `Buffer.slice` => ref if (str.slice(-6) === 'Array]') { return new x.constructor(x); } return x; } klona-2.0.5/src/json.js000066400000000000000000000011351413612765300147300ustar00rootroot00000000000000export function klona(val) { var k, out, tmp; if (Array.isArray(val)) { out = Array(k=val.length); while (k--) out[k] = (tmp=val[k]) && typeof tmp === 'object' ? klona(tmp) : tmp; return out; } if (Object.prototype.toString.call(val) === '[object Object]') { out = {}; // null for (k in val) { if (k === '__proto__') { Object.defineProperty(out, k, { value: klona(val[k]), configurable: true, enumerable: true, writable: true, }); } else { out[k] = (tmp=val[k]) && typeof tmp === 'object' ? klona(tmp) : tmp; } } return out; } return val; } klona-2.0.5/src/lite.js000066400000000000000000000017211413612765300147150ustar00rootroot00000000000000export function klona(x) { if (typeof x !== 'object') return x; var k, tmp, str=Object.prototype.toString.call(x); if (str === '[object Object]') { if (x.constructor !== Object && typeof x.constructor === 'function') { tmp = new x.constructor(); for (k in x) { if (x.hasOwnProperty(k) && tmp[k] !== x[k]) { tmp[k] = klona(x[k]); } } } else { tmp = {}; // null for (k in x) { if (k === '__proto__') { Object.defineProperty(tmp, k, { value: klona(x[k]), configurable: true, enumerable: true, writable: true, }); } else { tmp[k] = klona(x[k]); } } } return tmp; } if (str === '[object Array]') { k = x.length; for (tmp=Array(k); k--;) { tmp[k] = klona(x[k]); } return tmp; } if (str === '[object Date]') { return new Date(+x); } if (str === '[object RegExp]') { tmp = new RegExp(x.source, x.flags); tmp.lastIndex = x.lastIndex; return tmp; } return x; } klona-2.0.5/test/000077500000000000000000000000001413612765300136115ustar00rootroot00000000000000klona-2.0.5/test/full.js000066400000000000000000000007541413612765300151170ustar00rootroot00000000000000import * as suites from './suites'; import { klona } from '../src/full'; suites.API(klona); suites.Strings(klona); suites.Booleans(klona); suites.Numbers(klona); suites.Nully(klona); suites.Dates(klona); suites.RegExps(klona); suites.Objects(klona); suites.Arrays(klona); suites.Functions(klona); suites.Pollutions(klona); suites.Classes(klona); suites.Maps(klona); suites.Sets(klona); suites.TypedArrays(klona); suites.Symbols(klona); suites.Descriptors(klona); suites.Dicts(klona); klona-2.0.5/test/index.js000066400000000000000000000006451413612765300152630ustar00rootroot00000000000000import * as suites from './suites'; import { klona } from '../src/index'; suites.API(klona); suites.Strings(klona); suites.Booleans(klona); suites.Numbers(klona); suites.Nully(klona); suites.Dates(klona); suites.RegExps(klona); suites.Objects(klona); suites.Arrays(klona); suites.Functions(klona); suites.Pollutions(klona); suites.Classes(klona); suites.Maps(klona); suites.Sets(klona); suites.TypedArrays(klona); klona-2.0.5/test/json.js000066400000000000000000000004021413612765300151140ustar00rootroot00000000000000import * as suites from './suites'; import { klona } from '../src/json'; suites.API(klona); suites.Strings(klona); suites.Booleans(klona); suites.Numbers(klona); suites.Nully(klona); suites.Objects(klona); suites.Arrays(klona); suites.Pollutions(klona); klona-2.0.5/test/lite.js000066400000000000000000000005371413612765300151110ustar00rootroot00000000000000import * as suites from './suites'; import { klona } from '../src/lite'; suites.API(klona); suites.Strings(klona); suites.Booleans(klona); suites.Numbers(klona); suites.Nully(klona); suites.Dates(klona); suites.RegExps(klona); suites.Objects(klona); suites.Arrays(klona); suites.Functions(klona); suites.Pollutions(klona); suites.Classes(klona); klona-2.0.5/test/suites/000077500000000000000000000000001413612765300151255ustar00rootroot00000000000000klona-2.0.5/test/suites/api.js000066400000000000000000000003451413612765300162360ustar00rootroot00000000000000import { suite } from 'uvu'; import * as assert from 'uvu/assert'; export default function (klona) { const API = suite('exports'); API('should export a function', () => { assert.type(klona, 'function'); }); API.run(); } klona-2.0.5/test/suites/array.js000066400000000000000000000012111413612765300165740ustar00rootroot00000000000000import { suite } from 'uvu'; import * as assert from 'assert'; export default function (klona) { const Arrays = suite('Arrays'); Arrays('flat', () => { const input = ['foo', 'bar', 'baz']; const output = klona(input); assert.deepEqual(input, output); output[1] = 'hello'; assert.notEqual(input[1], 'hello'); }); Arrays('nested', () => { const input = ['foo', [1, 2, ['hello', 'world'], 3], 'bar', 'baz']; const output = klona(input); assert.deepEqual(input, output); output[1][2][0] = 'howdy'; assert.equal(input[1][2][0], 'hello'); output[1] = 'hello'; assert.notEqual(input[1], 'hello'); }); Arrays.run(); } klona-2.0.5/test/suites/boolean.js000066400000000000000000000005041413612765300171010ustar00rootroot00000000000000import { suite } from 'uvu'; import * as assert from 'assert'; export default function (klona) { const Booleans = suite('Boolean'); Booleans('boolean', () => { const input = true; let output = klona(input); assert.deepEqual(input, output); output = false; assert.equal(input, true); }); Booleans.run(); } klona-2.0.5/test/suites/class.js000066400000000000000000000111621413612765300165710ustar00rootroot00000000000000import { suite } from 'uvu'; import * as assert from 'assert'; export default function (klona) { const Classes = suite('class'); Classes('class', () => { class Foobar {} const input = new Foobar(); const output = klona(input); assert.deepEqual(input, output); assert.equal(input.constructor, output.constructor); assert.equal(output.constructor.name, 'Foobar'); output.foobar = 123; // @ts-ignore assert.notEqual(input.foobar, 123); }); // @see https://github.com/lukeed/klona/issues/14 Classes('prototype', () => { function Test () {} Test.prototype.val = 42; const input = new Test(); const output = klona(input); assert.deepEqual(input, output); assert.deepEqual(output.constructor, Test); assert.deepEqual(output.__proto__, { val: 42 }); assert.deepEqual(output, {}); assert.equal(output.val, 42); }); Classes('prototype methods :: manual', () => { function Test() {} Test.prototype = { count: 0, increment() { this.count++; } }; const input = new Test(); const output = klona(input); assert.equal(input.count, 0); assert.equal(output.count, 0); assert.equal(typeof input.increment, 'function'); assert.equal(typeof output.increment, 'function'); output.increment(); assert.equal(input.count, 0); assert.equal(output.count, 1); input.increment(); assert.equal(input.count, 1); assert.equal(output.count, 1); }); Classes('prototype methods :: class', () => { class Test { constructor() { this.count = 0; } increment() { this.count++ } } const input = new Test(); const output = klona(input); assert.deepEqual(input, output); assert.deepEqual(output.__proto__, Test.prototype); assert.equal(input.count, 0); assert.equal(output.count, 0); assert.equal(typeof input.increment, 'function'); assert.equal(typeof output.increment, 'function'); output.increment(); assert.equal(input.count, 0); assert.equal(output.count, 1); input.increment(); assert.equal(input.count, 1); assert.equal(output.count, 1); }); Classes('constructor properties', () => { function Test (num) { this.value = num; } Test.prototype.val = 42; const input = new Test(123); const output = klona(input); assert.deepEqual(input, output); assert.deepEqual(output.constructor, Test); assert.deepEqual(output.__proto__, { val: 42 }); assert.equal(output.value, 123); assert.equal(output.val, 42); }); Classes('constructor properties :: class', () => { class Test { constructor(num) { this.value = num; } } Test.prototype.val = 42; const input = new Test(123); const output = klona(input); assert.deepEqual(input, output); assert.deepEqual(output.constructor, Test); assert.deepEqual(output.__proto__, { val: 42 }); assert.equal(output.value, 123); assert.equal(output.val, 42); }); Classes('constructor properties :: defaults', () => { class Test { constructor(num = 123) { this.value = num; } } const input = new Test(456); const output = klona(input); assert.deepEqual(input, output); assert.equal(output.value, 456); }); Classes('accessors', () => { class Test { get val() { return 42; } } const input = new Test(); const output = klona(input); assert.deepEqual(input, output); assert.deepEqual(output.constructor, Test); assert.deepEqual(output.__proto__, {}); assert.deepEqual( // @ts-ignore Object.getOwnPropertyDescriptor(input.__proto__, 'val'), Object.getOwnPropertyDescriptor(output.__proto__, 'val'), ); assert.equal(output.val, 42); }); Classes('inheritance', () => { class Animal { constructor() { this.cute = true; } get carbon() { return true; } } class Dog extends Animal { constructor(name) { super(); this.name = name; } bark() { console.log('woof'); } } const input = new Dog('spot'); const output = klona(input); assert.deepEqual(input, output); assert.deepEqual(input.name, output.name); assert.equal(output instanceof Animal, true); assert.deepEqual(output.constructor, Dog); assert.deepEqual(output.__proto__, {}); assert.equal(output.carbon, true); assert.deepStrictEqual( Object.getOwnPropertyDescriptors(input), Object.getOwnPropertyDescriptors(output), ); }); Classes('constructor properties :: Object.assign', () => { class Foobar { constructor(data) { Object.assign(this, data); } } const input = new Foobar({ test: 123 }); const output = klona(input); assert.deepEqual(input, output); assert.equal(input.constructor, output.constructor); assert.equal(output.constructor.name, 'Foobar'); }); Classes.run(); } klona-2.0.5/test/suites/date.js000066400000000000000000000006571413612765300164100ustar00rootroot00000000000000import { suite } from 'uvu'; import * as assert from 'assert'; export default function (klona) { const Dates = suite('Date'); Dates('date', () => { const input = new Date; const output = klona(input); const original = input.toString(); assert.deepEqual(input, output); output.setDate('foobar123'); assert.equal(output.toString(), 'Invalid Date'); assert.equal(input.toString(), original); }); Dates.run(); } klona-2.0.5/test/suites/descriptor.js000066400000000000000000000031401413612765300176370ustar00rootroot00000000000000import { suite } from 'uvu'; import * as assert from 'assert'; export default function (klona) { const Descriptors = suite('Descriptor'); Descriptors('hidden', () => { const input = { foo: 123 }; Object.defineProperty(input, 'bar', { enumerable: false, value: [1, 2, 3] }); const output = klona(input); assert.deepEqual(input, output); assert.deepEqual( Object.getOwnPropertyDescriptor(output, 'bar'), { enumerable: false, configurable: false, writable: false, value: [1, 2, 3] } ); output.bar.push('howdy'); assert.deepEqual(input.bar, [1, 2, 3]); }); Descriptors('hidden writable configurable', () => { const input = { foo: 123 }; Object.defineProperty(input, 'bar', { enumerable: false, configurable: true, writable: true, value: [1, 2, 3] }); const output = klona(input); assert.deepEqual(input, output); assert.deepEqual( Object.getOwnPropertyDescriptor(output, 'bar'), { enumerable: false, configurable: true, writable: true, value: [1, 2, 3] } ); output.bar.push('howdy'); assert.deepEqual(input.bar, [1, 2, 3]); }); Descriptors('hidden getter', () => { const input = { foo: 123 }; Object.defineProperty(input, 'bar', { enumerable: false, get() { return [1, 2, 3] } }); const output = klona(input); assert.deepEqual(input, output); const xyz = Object.getOwnPropertyDescriptor(output, 'bar'); assert.equal(typeof xyz.get, 'function'); output.bar.push('howdy'); assert.deepEqual(input.bar, [1, 2, 3]); assert.deepEqual(output.bar, [1, 2, 3]); }); Descriptors.run(); } klona-2.0.5/test/suites/dictionary.js000066400000000000000000000013511413612765300176300ustar00rootroot00000000000000import { suite } from 'uvu'; import * as assert from 'assert'; export default function (klona) { const Dictionarys = suite('Dictionary'); Dictionarys('dictionary :: empty', () => { const input = Object.create(null); let output = klona(input); assert.deepEqual(input, output); assert.equal(output.constructor, undefined); output.foo = 123; assert.equal(input.foo, undefined); }); Dictionarys('dictionary :: values', () => { const input = Object.create(null); input.hello = 'world'; input.list = [1, 2, 3]; let output = klona(input); assert.deepEqual(input, output); assert.equal(output.constructor, undefined); output.list.push('howdy'); assert.deepEqual(input.list, [1, 2, 3]); }); Dictionarys.run(); } klona-2.0.5/test/suites/function.js000066400000000000000000000007071413612765300173140ustar00rootroot00000000000000import { suite } from 'uvu'; import * as assert from 'assert'; export default function (klona) { const Functions = suite('Function'); Functions('function', () => { let input = () => {}; let output = klona(input); let original = input.toString(); assert.deepEqual(input, output); input = () => 123; assert.equal(output.toString(), original); output = () => 456; assert.equal(input.toString(), '() => 123'); }); Functions.run(); } klona-2.0.5/test/suites/index.js000066400000000000000000000015271413612765300165770ustar00rootroot00000000000000export { default as API } from './api'; export { default as Numbers } from './number'; export { default as Booleans } from './boolean'; export { default as Strings } from './string'; export { default as Nully } from './nullish'; export { default as Maps } from './map'; export { default as Sets } from './set'; export { default as TypedArrays } from './typedarray'; export { default as Descriptors } from './descriptor'; export { default as Symbols } from './symbol'; export { default as Dates } from './date'; export { default as RegExps } from './regexp'; export { default as Dicts } from './dictionary'; export { default as Objects } from './object'; export { default as Arrays } from './array'; export { default as Functions } from './function'; export { default as Pollutions } from './pollution'; export { default as Classes } from './class'; klona-2.0.5/test/suites/map.js000066400000000000000000000022251413612765300162410ustar00rootroot00000000000000import { suite } from 'uvu'; import * as assert from 'assert'; export default function (klona) { const Maps = suite('Map'); Maps('flat', () => { const input = new Map(); const output = klona(input); assert.deepEqual(input, output); output.set('hello', 'world'); assert.equal(input.get('hello'), undefined); input.set('foo', 'bar'); assert.equal(output.get('foo'), undefined); }); Maps('nested', () => { const input = new Map([ ['foo', { a: 1 }], ['bar', [1, 2, 3]], ]); const output = klona(input); const foo = output.get('foo'); foo.b = 2; foo.a++; assert.deepEqual(input.get('foo'), { a: 1 }); assert.deepEqual(output.get('foo'), { a: 2, b: 2 }); output.get('bar').push(4, 5, 6); assert.deepEqual(input.get('bar'), [1, 2, 3]); assert.deepEqual(output.get('bar'), [1, 2, 3, 4, 5, 6]); }); Maps('nested :: keys', () => { const input = new Map([ [{ foo:1 }, { a: 1 }] ]); const output = klona(input); assert.deepEqual(input, output); [...output.keys()][0].bar = 2; assert.deepEqual([...input.keys()][0], { foo:1 }); assert.deepEqual([...output.keys()][0], { foo:1, bar:2 }); }); Maps.run(); } klona-2.0.5/test/suites/nullish.js000066400000000000000000000017231413612765300171440ustar00rootroot00000000000000import { suite } from 'uvu'; import * as assert from 'assert'; export default function (klona) { const Nully = suite('nullish'); Nully('null', () => { let input = null; let output = klona(input); assert.deepEqual(input, output); output = 1; assert.equal(input, null); input = 123; assert.equal(output, 1); }); Nully('undefined', () => { let input = undefined; let output = klona(input); assert.deepEqual(input, output); output = 1; assert.equal(input, undefined); input = 123; assert.equal(output, 1); }); Nully('0', () => { let input = 0; let output = klona(input); assert.deepEqual(input, output); output = 1; assert.equal(input, 0); input = 123; assert.equal(output, 1); }); Nully('NaN', () => { let input = NaN; let output = klona(input); assert.equal(Number.isNaN(output), true); output = 1; assert.equal(Number.isNaN(input), true); input = 123; assert.equal(output, 1); }); Nully.run(); } klona-2.0.5/test/suites/number.js000066400000000000000000000005431413612765300167550ustar00rootroot00000000000000import { suite } from 'uvu'; import * as assert from 'assert'; export default function (klona) { const Numbers = suite('Number'); Numbers('number', () => { let input = 123; let output = klona(input); assert.deepEqual(input, output); output++; assert.equal(input, 123); input += 100; assert.equal(output, 124); }); Numbers.run(); } klona-2.0.5/test/suites/object.js000066400000000000000000000020741413612765300167340ustar00rootroot00000000000000import { suite } from 'uvu'; import * as assert from 'assert'; export default function (klona) { const Objects = suite('Object'); Objects('flat', () => { const input = { foo:1, bar:2, baz:3 }; const output = klona(input); assert.deepEqual(input, output); output.foo++; assert.equal(input.foo, 1); output.bar = 'hello'; assert.equal(input.bar, 2); }); Objects('nested', () => { const input = { foo: 1, bar: { a: 2, b: ['hello', 'world'], c: [{ hello: 1, world: 2 }] }, baz: 3 }; const output = klona(input); assert.equal( JSON.stringify(input), JSON.stringify(output) ); output.bar.a = 11; assert.equal(input.bar.a, 2); output.bar.b[1] = 'mundo'; assert.equal(input.bar.b[1], 'world'); output.bar.c[0].hello = 99; assert.equal(input.bar.c[0].hello, 1); }); Objects('Object.create', () => { const input = Object.create({ method() { return 'foo'; } }); const output = klona(input); assert.equal(input.method(), 'foo'); assert.equal(output.method(), 'foo'); }); Objects.run(); } klona-2.0.5/test/suites/pollution.js000066400000000000000000000036601413612765300175150ustar00rootroot00000000000000import { suite } from 'uvu'; import * as assert from 'assert'; export default function (klona) { const Pollution = suite('pollution'); // @see https://snyk.io/vuln/SNYK-JS-LODASH-450202 Pollution('constructor', () => { const payload = '{"constructor":{"prototype":{"a0":true}}}'; const input = JSON.parse(payload); const output = klona(input); assert.equal( JSON.stringify(output), payload ); assert.notEqual(({})['a0'], true, 'Safe POJO'); assert.notEqual(new Object()['a0'], true, 'Safe Object'); assert.notEqual(Object.create(null)['a0'], true, 'Safe dictionary'); assert.notEqual(Object.create(Object.prototype)['a0'], true, 'Safe prototype'); assert.notEqual(input['a0'], true, 'Safe input'); assert.notEqual(output['a0'], true, 'Safe output'); }); // @see https://snyk.io/vuln/SNYK-JS-LODASH-450202 Pollution('__proto__', () => { const payload = '{"__proto__":{"a0":true}}'; const input = JSON.parse(payload); const output = klona(input); assert.equal( JSON.stringify(output), payload ); assert.notEqual(({})['a0'], true, 'Safe POJO'); assert.notEqual(new Object()['a0'], true, 'Safe Object'); assert.notEqual(Object.create(null)['a0'], true, 'Safe dictionary'); assert.notEqual(Object.create(Object.prototype)['a0'], true, 'Safe prototype'); }); Pollution('prototype', () => { const payload = '{"prototype":{"hello":"world"}}'; const input = JSON.parse(payload); const output = klona(input); assert.equal( JSON.stringify(output), payload ); assert.notEqual(({})['hello'], 'world', 'Safe POJO'); assert.notEqual(new Object()['hello'], 'world', 'Safe Object'); assert.notEqual(Object.create(null)['hello'], 'world', 'Safe dictionary'); assert.notEqual(Object.create(Object.prototype)['hello'], 'world', 'Safe prototype'); assert.notEqual(input['hello'], 'world', 'Safe input'); assert.notEqual(output['hello'], 'world', 'Safe output'); }); Pollution.run(); } klona-2.0.5/test/suites/regexp.js000066400000000000000000000012361413612765300167570ustar00rootroot00000000000000import { suite } from 'uvu'; import * as assert from 'assert'; export default function (klona) { const RegExps = suite('RegExp'); RegExps('basic', () => { const input = /foo/gi; const output = klona(input); assert.deepEqual(input, output); output.exec('foofoofoo'); assert.equal(output.lastIndex, 3); assert.equal(input.lastIndex, 0); }); RegExps('state', () => { const input = /foo/gi; input.exec('foofoofoo'); const index = input.lastIndex; const output = klona(input); assert.deepEqual(input, output); assert.equal(index, 3); assert.equal(input.lastIndex, index); assert.equal(output.lastIndex, index); }); RegExps.run(); } klona-2.0.5/test/suites/set.js000066400000000000000000000012611413612765300162560ustar00rootroot00000000000000import { suite } from 'uvu'; import * as assert from 'assert'; export default function (klona) { const Sets = suite('Set'); Sets('flat', () => { const input = new Set('hello'); const output = klona(input); assert.deepEqual(input, output); output.add('world'); assert.equal(input.has('world'), false); input.add('foobar'); assert.equal(output.has('foobar'), false); }); Sets('nested', () => { const input = new Set([{ foo: 123 }]); const output = klona(input); assert.deepEqual(input, output); const [obj] = [...output.keys()]; obj.bar = 456; obj.foo++; const [item] = [...input.keys()]; assert.deepEqual(item, { foo: 123 }); }); Sets.run(); } klona-2.0.5/test/suites/string.js000066400000000000000000000005751413612765300170000ustar00rootroot00000000000000import { suite } from 'uvu'; import * as assert from 'assert'; export default function (klona) { const Strings = suite('String'); Strings('string', () => { let input = 'hello'; let output = klona(input); assert.equal(input, output); output += ' world'; assert.equal(input, 'hello'); input += '123'; assert.equal(output, 'hello world'); }); Strings.run(); } klona-2.0.5/test/suites/symbol.js000066400000000000000000000010651413612765300167720ustar00rootroot00000000000000import { suite } from 'uvu'; import * as assert from 'assert'; export default function (klona) { const Symbols = suite('Symbol'); Symbols('direct', () => { const input = Symbol('input'); const output = klona(input); assert.deepStrictEqual(input, output); }); // https://github.com/lukeed/klona/issues/16 Symbols('object :: enumerable key', () => { const key = Symbol('key'); const input = { foo: 123, [key]: 456 }; const output = klona(input); assert.equal(output[key], 456); assert.deepStrictEqual(input, output); }); Symbols.run(); } klona-2.0.5/test/suites/typedarray.js000066400000000000000000000054461413612765300176600ustar00rootroot00000000000000import { suite } from 'uvu'; // import * as assert from 'uvu/assert'; import * as assert from 'assert'; export default function(klona) { const test = suite('TypedArray'); test('Buffer', () => { const input = Buffer.from('asd'); const output = klona(input); assert.deepEqual(input, output); output.write('foobar'); assert.equal(input.toString(), 'asd'); output[1] = 11; assert.notEqual(input[1], output[1]); const current = output.toString(); input.write('hello'); assert.equal(output.toString(), current); }); test('Int16Array', () => { const input = new Int16Array([42]); const output = klona(input); assert.deepEqual(input, output); output[1] = 42; assert.equal(input[1], undefined); input[0] = 0; assert.equal(output[0], 42); }); test('Int32Array', () => { const buf = new ArrayBuffer(8); const input = new Int32Array(buf); const output = klona(input); assert.deepEqual(input, new Int32Array([0, 0])); assert.deepEqual(output, new Int32Array([0, 0])); assert.deepEqual(input, output); output[1] = 42; assert.equal(input[1], 0); input[0] = 22; assert.equal(output[0], 0); }); test('Int32Array', () => { const buf = new ArrayBuffer(8); const input = new Int32Array(buf); const output = klona(input); assert.deepEqual(input, new Int32Array([0, 0])); assert.deepEqual(output, new Int32Array([0, 0])); assert.deepEqual(input, output); output[1] = 42; assert.equal(input[1], 0); input[0] = 22; assert.equal(output[0], 0); }); test('ArrayBuffer :: empty', () => { const input = new ArrayBuffer(6); const output = klona(input); assert.deepEqual(input, output); const view1 = new DataView(input); const view2 = new DataView(output); view1.setInt8(0, 4); assert.equal(view1.getInt8(0), 4); assert.equal(view2.getInt8(0), 0); view2.setInt8(1, 8); assert.equal(view1.getInt8(1), 0); assert.equal(view2.getInt8(1), 8); }); test('ArrayBuffer :: values', () => { const input = new ArrayBuffer(3); const view1 = new DataView(input); view1.setInt8(0, 4); view1.setInt8(1, 5); view1.setInt8(2, 6); const output = klona(input); const view2 = new DataView(output); assert.deepEqual(input, output); assert.equal(view2.getInt8(0), 4); assert.equal(view2.getInt8(1), 5); assert.equal(view2.getInt8(2), 6); }); test('DataView', () => { const ints = new Int8Array([1, 2, 3]); const input = new DataView(ints.buffer); const output = klona(input); assert.deepEqual(input, output); assert.deepEqual(input.buffer, output.buffer); input.setInt8(1, 6); assert.equal(ints[1], 6); assert.equal(input.getInt8(1), 6); assert.equal(output.getInt8(1), 2); output.setInt8(0, 4); assert.equal(ints[0], 1); assert.equal(input.getInt8(0), 1); assert.equal(output.getInt8(0), 4); }); test.run(); }