diff --git a/.eslintrc b/.eslintrc index d8824e9..30de5dd 100644 --- a/.eslintrc +++ b/.eslintrc @@ -11,7 +11,7 @@ "func-style": [2, "declaration"], "global-require": 1, "max-lines-per-function": 0, - "max-statements-per-line": 1, + "max-statements-per-line": [1, {"max": 2}], "multiline-comment-style": 0, "no-proto": 0, "no-sparse-arrays": 1, @@ -27,7 +27,17 @@ "rules": { "no-console": 0, "no-plusplus": 0, + "no-magic-numbers": 0, }, }, + { + "files": [ + "test/typed-array.js", + "test/mutability.js", + ], + "globals": { + "Uint8Array": false + }, + } ], } diff --git a/index.js b/index.js index 256a700..23d0766 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,8 @@ 'use strict'; +var whichTypedArray = require('which-typed-array'); +var taSlice = require('typedarray.prototype.slice'); + // TODO: use call-bind, is-date, is-regex, is-string, is-boolean-object, is-number-object function toS(obj) { return Object.prototype.toString.call(obj); } function isDate(obj) { return toS(obj) === '[object Date]'; } @@ -68,17 +71,22 @@ function copy(src) { dst = { message: src.message }; } else if (isBoolean(src) || isNumber(src) || isString(src)) { dst = Object(src); - } else if (Object.create && Object.getPrototypeOf) { - dst = Object.create(Object.getPrototypeOf(src)); - } else if (src.constructor === Object) { - dst = {}; } else { - var proto = (src.constructor && src.constructor.prototype) - || src.__proto__ - || {}; - var T = function T() {}; // eslint-disable-line func-style, func-name-matching - T.prototype = proto; - dst = new T(); + var ta = whichTypedArray(src); + if (ta) { + return taSlice(src); + } else if (Object.create && Object.getPrototypeOf) { + dst = Object.create(Object.getPrototypeOf(src)); + } else if (src.constructor === Object) { + dst = {}; + } else { + var proto = (src.constructor && src.constructor.prototype) + || src.__proto__ + || {}; + var T = function T() {}; // eslint-disable-line func-style, func-name-matching + T.prototype = proto; + dst = new T(); + } } forEach(ownEnumerableKeys(src), function (key) { @@ -287,6 +295,10 @@ Traverse.prototype.clone = function () { var parents = []; var nodes = []; + if (whichTypedArray(this.value)) { + return taSlice(this.value); + } + return (function clone(src) { for (var i = 0; i < parents.length; i++) { if (parents[i] === src) { diff --git a/package.json b/package.json index 4c2c290..c92b2da 100644 --- a/package.json +++ b/package.json @@ -91,6 +91,10 @@ ".github/workflows" ] }, + "dependencies": { + "typedarray.prototype.slice": "^1.0.1", + "which-typed-array": "^1.1.11" + }, "engines": { "node": ">= 0.4" } diff --git a/test/mutability.js b/test/mutability.js index dc5d6f4..c52fe4b 100644 --- a/test/mutability.js +++ b/test/mutability.js @@ -77,6 +77,19 @@ test('cloneT', function (t) { t.end(); }); +test('cloneTypedArray', { skip: typeof Uint8Array !== 'function' }, function (t) { + var obj = new Uint8Array([1]); + var res = traverse.clone(obj); + + t.same(obj, res); + t.ok(obj !== res); + obj.set([2], 0); + res.set([3], 0); + t.same(obj, new Uint8Array([2])); + t.same(res, new Uint8Array([3])); + t.end(); +}); + test('reduce', function (t) { var obj = { a: 1, b: 2, c: [3, 4] }; var res = traverse(obj).reduce(function (acc, x) { @@ -194,6 +207,7 @@ test('deleteRedux', function (t) { t.ok(!deepEqual(obj, { a: 1, c: [3, undefined, 5] })); + // eslint-disable-next-line no-sparse-arrays t.ok(deepEqual(obj, { a: 1, c: [3,, 5] })); t.ok(!deepEqual(obj, { a: 1, c: [3, null, 5] })); @@ -219,7 +233,8 @@ test('deleteMap', function (t) { t.ok(deepEqual(res, { a: 1, c: xs })); - t.ok(deepEqual(res, { a: 1, c: [3,,] })); // eslint-disable-line comma-spacing + // eslint-disable-next-line comma-spacing, no-sparse-arrays + t.ok(deepEqual(res, { a: 1, c: [3,,] })); t.ok(deepEqual(res, { a: 1, c: [3] })); @@ -244,6 +259,7 @@ test('deleteMapRedux', function (t) { t.ok(!deepEqual(res, { a: 1, c: [3, 5] })); + // eslint-disable-next-line no-sparse-arrays t.ok(deepEqual(res, { a: 1, c: [3,, 5] })); t.end(); diff --git a/test/typed-array.js b/test/typed-array.js new file mode 100644 index 0000000..b73992f --- /dev/null +++ b/test/typed-array.js @@ -0,0 +1,12 @@ +'use strict'; + +var test = require('tape'); +var traverse = require('../'); + +test('traverse an Uint8Array', { skip: typeof Uint8Array !== 'function' }, function (t) { + var obj = new Uint8Array(4); + var results = traverse(obj).map(function () {}); + t.same(results, obj); + t.end(); +}); +