diff --git a/lib/mixins/property-effects.html b/lib/mixins/property-effects.html index 3e7cb521c1..a238379414 100644 --- a/lib/mixins/property-effects.html +++ b/lib/mixins/property-effects.html @@ -1933,13 +1933,33 @@ // Normalize fancy native splice handling of crazy start values if (start < 0) { start = array.length - Math.floor(-start); - } else { + } else if (start) { start = Math.floor(start); } - if (!start) { - start = 0; + // array.splice does different things based on the number of arguments + // you pass in. Therefore, array.splice(0) and array.splice(0, undefined) + // do different things. In the former, the whole array is cleared. In the + // latter, no items are removed. + // This means that we need to detect whether 1. one of the arguments + // is actually passed in and then 2. determine how many arguments + // we should pass on to the native array.splice + // + let ret; + // Omit any additional arguments if they were not passed in + if (start !== undefined && !deleteCount && !items.length) { + ret = array.splice(start); + // Either start was undefined and the others were defined, but in this + // case we can safely pass on all arguments + // + // Note: this includes the case where none of the arguments were passed in, + // e.g. this.splice('array'). However, if both start and deleteCount + // are undefined, array.splice will not modify the array (as expected) + } else { + ret = array.splice(start, deleteCount, ...items); } - let ret = array.splice(start, deleteCount, ...items); + // At the end, check whether any items were passed in (e.g. insertions) + // or if the return array contains items (e.g. deletions). + // Only notify if items were added or deleted. if (items.length || ret.length) { notifySplice(this, array, info.path, start, items.length, ret); } diff --git a/test/unit/path-effects.html b/test/unit/path-effects.html index 4ba3b96384..8659c87890 100644 --- a/test/unit/path-effects.html +++ b/test/unit/path-effects.html @@ -498,6 +498,13 @@ assert.equal(el.$.boundChild.arrayLength, el.data.length); }); + test('splice correctly deletes length', function() { + el.data = [1,2,3]; + assert.equal(el.data.length, 3); + el.splice('data', 0); + assert.equal(el.data.length, 0); + }); + }); suite('path API', function() {