diff --git a/README.md b/README.md index aad32bf..96db3f6 100644 --- a/README.md +++ b/README.md @@ -302,11 +302,16 @@ var newList = cursor.select('one').shift('two'); Splices the selected list. This will of course fail if the selected node is not a list. The `splice` specifications works the same as for [`Array.prototype.splice`](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Array/splice). +There is one exception though: Per specification, splice deletes no values if the `deleteCount` argument is not parseable as a number. +The `splice` implementation of Baobab instead throws an error, if the given `deleteCount` argument could not be parsed. ```js // Splicing the list var newList = cursor.splice([1, 1]); +// Omitting the deleteCount argument makes splice delete no elements. +var newList = cursor.splice([1]); + // Inserting an item etc. var newList = cursor.splice([1, 0, 'newItem']); var newList = cursor.splice([1, 0, 'newItem1', 'newItem2']); diff --git a/src/helpers.js b/src/helpers.js index e0d8e9b..d1cddd3 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -570,6 +570,12 @@ export function solveUpdate(affectedPaths, comparedPaths) { * @return {array} - The spliced array. */ export function splice(array, startIndex, nb, ...elements) { + if (nb === undefined) + nb = array.length - startIndex; + else if (nb === null) + nb = 0; + else if (Number.isNaN(Number.parseInt(nb))) + throw new Error(`argument nb ${nb} can not be parsed into a number!`); nb = Math.max(0, nb); // Solving startIndex diff --git a/src/type.js b/src/type.js index 8e2fbf8..98b8978 100644 --- a/src/type.js +++ b/src/type.js @@ -112,11 +112,12 @@ type.primitive = function(target) { * @return {boolean} */ type.splicer = function(target) { - if (!type.array(target) || target.length < 2) + if (!type.array(target) || target.length < 1) + return false; + if(target.length > 1 && Number.isNaN(Number.parseInt(target[1]))) return false; - return anyOf(target[0], ['number', 'function', 'object']) && - type.number(target[1]); + return anyOf(target[0], ['number', 'function', 'object']); }; /** diff --git a/test/suites/helpers.js b/test/suites/helpers.js index a3312f2..3e08329 100644 --- a/test/suites/helpers.js +++ b/test/suites/helpers.js @@ -223,6 +223,30 @@ describe('Helpers', function() { [{name: 'John'}, {name: 'Paul'}] ); }); + + describe('Issue #472 - tree/cursor.splice does not conform with the specification as of ES6 (ECMAScript 2015)', function () { + it('should be possible to splice an array when omitting the nb (deleteCount) argument or passing null', function () { + const array = [0, 1, 2, 3, 4]; + + assert.deepEqual(splice(array, 2), [0, 1]); + + assert.deepEqual(splice(array, -2), [0, 1, 2]); + + assert.deepEqual(splice(array, 2, null), [0, 1, 2, 3, 4]); + }); + + it('should throw an error when supplying an argument for nb (deleteCount) which is not parseable as number', function () { + const array = [0, 1, 2, 3, 4]; + + assert.throws(function () { + splice(array, 2, "a"); + }, Error); + + assert.throws(function () { + splice(array, 2, {}); + }, Error); + }); + }); }); /**