Skip to content

Commit 7e2ceeb

Browse files
committed
Allow array API's accept string & negative args. Fixes #2062.
Brings the API more in line with native splice, etc.
1 parent cb32751 commit 7e2ceeb

2 files changed

Lines changed: 286 additions & 6 deletions

File tree

‎src/standard/notify-path.html‎

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,9 @@
380380
var args = Array.prototype.slice.call(arguments, 1);
381381
var len = array.length;
382382
var ret = array.push.apply(array, args);
383-
this._notifySplice(array, path, len, args.length, []);
383+
if (args.length) {
384+
this._notifySplice(array, path, len, args.length, []);
385+
}
384386
return ret;
385387
},
386388

@@ -399,10 +401,12 @@
399401
*/
400402
pop: function(path) {
401403
var array = this.get(path);
404+
var hadLength = Boolean(array.length);
402405
var args = Array.prototype.slice.call(arguments, 1);
403-
var rem = array.slice(-1);
404406
var ret = array.pop.apply(array, args);
405-
this._notifySplice(array, path, array.length, 0, rem);
407+
if (hadLength) {
408+
this._notifySplice(array, path, array.length, 0, [ret]);
409+
}
406410
return ret;
407411
},
408412

@@ -425,9 +429,21 @@
425429
*/
426430
splice: function(path, start, deleteCount) {
427431
var array = this.get(path);
432+
// Normalize fancy native splice handling of crazy start values
433+
if (start < 0) {
434+
start = array.length - Math.floor(Math.abs(start));
435+
} else {
436+
start = Math.floor(start);
437+
}
438+
if (!start || !isFinite(start)) {
439+
start = 0;
440+
}
428441
var args = Array.prototype.slice.call(arguments, 1);
429442
var ret = array.splice.apply(array, args);
430-
this._notifySplice(array, path, start, args.length - 2, ret);
443+
var addedCount = Math.max(args.length - 2, 0);
444+
if (addedCount || ret.length) {
445+
this._notifySplice(array, path, start, addedCount, ret);
446+
}
431447
return ret;
432448
},
433449

@@ -446,9 +462,12 @@
446462
*/
447463
shift: function(path) {
448464
var array = this.get(path);
465+
var hadLength = Boolean(array.length);
449466
var args = Array.prototype.slice.call(arguments, 1);
450467
var ret = array.shift.apply(array, args);
451-
this._notifySplice(array, path, 0, 0, [ret]);
468+
if (hadLength) {
469+
this._notifySplice(array, path, 0, 0, [ret]);
470+
}
452471
return ret;
453472
},
454473

@@ -470,7 +489,9 @@
470489
var array = this.get(path);
471490
var args = Array.prototype.slice.call(arguments, 1);
472491
var ret = array.unshift.apply(array, args);
473-
this._notifySplice(array, path, 0, args.length, []);
492+
if (args.length) {
493+
this._notifySplice(array, path, 0, args.length, []);
494+
}
474495
return ret;
475496
}
476497

‎test/unit/notify-path.html‎

Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -901,6 +901,265 @@
901901
assert.equal(el.get('array.prop'), 'foo');
902902
});
903903

904+
var nop = function() {};
905+
906+
test('push array', function() {
907+
el.arrayChanged = nop;
908+
el.array = ['orig1', 'orig2', 'orig3'];
909+
Polymer.Collection.get(el.array);
910+
var key = el.array.length;
911+
el.arrayChanged = function(change) {
912+
assert.strictEqual(change.indexSplices.length, 1);
913+
assert.strictEqual(change.indexSplices[0].index, 3);
914+
assert.strictEqual(change.indexSplices[0].addedCount, 2);
915+
assert.strictEqual(change.indexSplices[0].removed.length, 0);
916+
assert.strictEqual(change.keySplices.length, 1);
917+
assert.strictEqual(change.keySplices[0].index, 3);
918+
assert.strictEqual(change.keySplices[0].added.length, 2);
919+
assert.strictEqual(change.keySplices[0].added[0], key);
920+
assert.strictEqual(change.keySplices[0].added[1], key+1);
921+
assert.strictEqual(change.keySplices[0].removed.length, 0);
922+
};
923+
var ret = el.push('array', 'new1', 'new2');
924+
assert.strictEqual(ret, 5);
925+
assert.strictEqual(el.array.length, 5);
926+
assert.strictEqual(el.array[0], 'orig1');
927+
assert.strictEqual(el.array[1], 'orig2');
928+
assert.strictEqual(el.array[2], 'orig3');
929+
assert.strictEqual(el.array[3], 'new1');
930+
assert.strictEqual(el.array[4], 'new2');
931+
});
932+
933+
test('pop array', function() {
934+
el.arrayChanged = nop;
935+
el.array = ['orig1', 'orig2', 'orig3'];
936+
Polymer.Collection.get(el.array);
937+
var key = el.array.length-1;
938+
el.arrayChanged = function(change) {
939+
assert.strictEqual(change.indexSplices.length, 1);
940+
assert.strictEqual(change.indexSplices[0].index, 2);
941+
assert.strictEqual(change.indexSplices[0].addedCount, 0);
942+
assert.strictEqual(change.indexSplices[0].removed.length, 1);
943+
assert.strictEqual(change.indexSplices[0].removed[0], 'orig3');
944+
assert.strictEqual(change.keySplices.length, 1);
945+
assert.strictEqual(change.keySplices[0].index, 2);
946+
assert.strictEqual(change.keySplices[0].added.length, 0);
947+
assert.strictEqual(change.keySplices[0].removed.length, 1);
948+
assert.strictEqual(change.keySplices[0].removed[0], key);
949+
};
950+
var ret = el.pop('array');
951+
assert.strictEqual(ret, 'orig3');
952+
assert.strictEqual(el.array.length, 2);
953+
assert.strictEqual(el.array[0], 'orig1');
954+
assert.strictEqual(el.array[1], 'orig2');
955+
});
956+
957+
test('unshift array', function() {
958+
el.arrayChanged = nop;
959+
el.array = ['orig1', 'orig2', 'orig3'];
960+
Polymer.Collection.get(el.array);
961+
var key = el.array.length;
962+
el.arrayChanged = function(change) {
963+
assert.strictEqual(change.indexSplices.length, 1);
964+
assert.strictEqual(change.indexSplices[0].index, 0);
965+
assert.strictEqual(change.indexSplices[0].addedCount, 2);
966+
assert.strictEqual(change.indexSplices[0].removed.length, 0);
967+
assert.strictEqual(change.keySplices.length, 1);
968+
assert.strictEqual(change.keySplices[0].index, 0);
969+
assert.strictEqual(change.keySplices[0].added.length, 2);
970+
assert.strictEqual(change.keySplices[0].added[0], key);
971+
assert.strictEqual(change.keySplices[0].added[1], key+1);
972+
assert.strictEqual(change.keySplices[0].removed.length, 0);
973+
};
974+
var ret = el.unshift('array', 'new1', 'new2');
975+
assert.strictEqual(ret, 5);
976+
assert.strictEqual(el.array.length, 5);
977+
assert.strictEqual(el.array[0], 'new1');
978+
assert.strictEqual(el.array[1], 'new2');
979+
assert.strictEqual(el.array[2], 'orig1');
980+
assert.strictEqual(el.array[3], 'orig2');
981+
assert.strictEqual(el.array[4], 'orig3');
982+
});
983+
984+
test('shift array', function() {
985+
el.arrayChanged = nop;
986+
el.array = ['orig1', 'orig2', 'orig3'];
987+
Polymer.Collection.get(el.array);
988+
el.arrayChanged = function(change) {
989+
assert.strictEqual(change.indexSplices.length, 1);
990+
assert.strictEqual(change.indexSplices[0].index, 0);
991+
assert.strictEqual(change.indexSplices[0].addedCount, 0);
992+
assert.strictEqual(change.indexSplices[0].removed.length, 1);
993+
assert.strictEqual(change.indexSplices[0].removed[0], 'orig1');
994+
assert.strictEqual(change.keySplices[0].index, 0);
995+
assert.strictEqual(change.keySplices.length, 1);
996+
assert.strictEqual(change.keySplices[0].added.length, 0);
997+
assert.strictEqual(change.keySplices[0].removed.length, 1);
998+
assert.strictEqual(change.keySplices[0].removed[0], 0);
999+
};
1000+
var ret = el.shift('array');
1001+
assert.strictEqual(ret, 'orig1');
1002+
assert.strictEqual(el.array.length, 2);
1003+
assert.strictEqual(el.array[0], 'orig2');
1004+
assert.strictEqual(el.array[1], 'orig3');
1005+
});
1006+
1007+
test('splice array', function() {
1008+
el.arrayChanged = nop;
1009+
el.array = ['orig1', 'orig2', 'orig3'];
1010+
var key = el.array.length;
1011+
Polymer.Collection.get(el.array);
1012+
el.arrayChanged = function(change) {
1013+
assert.strictEqual(change.indexSplices.length, 1);
1014+
assert.strictEqual(change.indexSplices[0].index, 1);
1015+
assert.strictEqual(change.indexSplices[0].addedCount, 2);
1016+
assert.strictEqual(change.indexSplices[0].removed.length, 1);
1017+
assert.strictEqual(change.indexSplices[0].removed[0], 'orig2');
1018+
assert.strictEqual(change.keySplices.length, 1);
1019+
assert.strictEqual(change.keySplices[0].index, 1);
1020+
assert.strictEqual(change.keySplices[0].added.length, 2);
1021+
assert.strictEqual(change.keySplices[0].added[0], key);
1022+
assert.strictEqual(change.keySplices[0].added[1], key+1);
1023+
assert.strictEqual(change.keySplices[0].removed.length, 1);
1024+
assert.strictEqual(change.keySplices[0].removed[0], 1);
1025+
};
1026+
var ret = el.splice('array', 1, 1, 'new1', 'new2');
1027+
assert.deepEqual(ret, ['orig2']);
1028+
assert.strictEqual(el.array.length, 4);
1029+
assert.strictEqual(el.array[0], 'orig1');
1030+
assert.strictEqual(el.array[1], 'new1');
1031+
assert.strictEqual(el.array[2], 'new2');
1032+
assert.strictEqual(el.array[3], 'orig3');
1033+
});
1034+
1035+
test('corner: no-op push array', function() {
1036+
el.arrayChanged = nop;
1037+
el.array = ['orig1', 'orig2', 'orig3'];
1038+
Polymer.Collection.get(el.array);
1039+
el.arrayChanged = function(change) {
1040+
throw new Error("should not notify");
1041+
};
1042+
var ret = el.push('array');
1043+
assert.deepEqual(ret, 3);
1044+
assert.strictEqual(el.array.length, 3);
1045+
assert.strictEqual(el.array[0], 'orig1');
1046+
assert.strictEqual(el.array[1], 'orig2');
1047+
assert.strictEqual(el.array[2], 'orig3');
1048+
});
1049+
1050+
test('corner: no-op pop array', function() {
1051+
el.arrayChanged = nop;
1052+
el.array = [];
1053+
Polymer.Collection.get(el.array);
1054+
el.arrayChanged = function(change) {
1055+
throw new Error("should not notify");
1056+
};
1057+
var ret = el.pop('array');
1058+
assert.strictEqual(ret, undefined);
1059+
assert.strictEqual(el.array.length, 0);
1060+
});
1061+
1062+
test('corner: no-op unshift array', function() {
1063+
el.arrayChanged = nop;
1064+
el.array = ['orig1', 'orig2', 'orig3'];
1065+
Polymer.Collection.get(el.array);
1066+
var key = el.array.length;
1067+
el.arrayChanged = function(change) {
1068+
throw new Error("should not notify");
1069+
};
1070+
var ret = el.unshift('array');
1071+
assert.deepEqual(ret, 3);
1072+
assert.strictEqual(el.array.length, 3);
1073+
assert.strictEqual(el.array[0], 'orig1');
1074+
assert.strictEqual(el.array[1], 'orig2');
1075+
assert.strictEqual(el.array[2], 'orig3');
1076+
});
1077+
1078+
test('corner: no-op shift array', function() {
1079+
el.arrayChanged = nop;
1080+
el.array = [];
1081+
Polymer.Collection.get(el.array);
1082+
el.arrayChanged = function(change) {
1083+
throw new Error("should not notify");
1084+
};
1085+
var ret = el.shift('array');
1086+
assert.strictEqual(ret, undefined);
1087+
assert.strictEqual(ret, undefined);
1088+
assert.strictEqual(el.array.length, 0);
1089+
});
1090+
1091+
test('corner: no-op splice array', function() {
1092+
el.arrayChanged = nop;
1093+
el.array = ['orig1', 'orig2', 'orig3'];
1094+
var key = el.array.length;
1095+
Polymer.Collection.get(el.array);
1096+
el.arrayChanged = function(change) {
1097+
throw new Error("should not notify");
1098+
};
1099+
var ret = el.splice('array');
1100+
assert.deepEqual(ret, []);
1101+
assert.strictEqual(el.array.length, 3);
1102+
assert.strictEqual(el.array[0], 'orig1');
1103+
assert.strictEqual(el.array[1], 'orig2');
1104+
assert.strictEqual(el.array[2], 'orig3');
1105+
});
1106+
1107+
test('corner: splice array: string args', function() {
1108+
el.arrayChanged = nop;
1109+
el.array = ['orig1', 'orig2', 'orig3'];
1110+
var key = el.array.length;
1111+
Polymer.Collection.get(el.array);
1112+
el.arrayChanged = function(change) {
1113+
assert.strictEqual(change.indexSplices.length, 1);
1114+
assert.strictEqual(change.indexSplices[0].index, 1);
1115+
assert.strictEqual(change.indexSplices[0].addedCount, 2);
1116+
assert.strictEqual(change.indexSplices[0].removed.length, 1);
1117+
assert.strictEqual(change.indexSplices[0].removed[0], 'orig2');
1118+
assert.strictEqual(change.keySplices.length, 1);
1119+
assert.strictEqual(change.keySplices[0].index, 1);
1120+
assert.strictEqual(change.keySplices[0].added.length, 2);
1121+
assert.strictEqual(change.keySplices[0].added[0], key);
1122+
assert.strictEqual(change.keySplices[0].added[1], key+1);
1123+
assert.strictEqual(change.keySplices[0].removed.length, 1);
1124+
assert.strictEqual(change.keySplices[0].removed[0], 1);
1125+
};
1126+
var ret = el.splice('array', '1', '1', 'new1', 'new2');
1127+
assert.deepEqual(ret, ['orig2']);
1128+
assert.strictEqual(el.array.length, 4);
1129+
assert.strictEqual(el.array[0], 'orig1');
1130+
assert.strictEqual(el.array[1], 'new1');
1131+
assert.strictEqual(el.array[2], 'new2');
1132+
assert.strictEqual(el.array[3], 'orig3');
1133+
});
1134+
1135+
test('corner: splice array: negative start', function() {
1136+
el.arrayChanged = nop;
1137+
el.array = ['orig1', 'orig2', 'orig3'];
1138+
var key = el.array.length;
1139+
Polymer.Collection.get(el.array);
1140+
el.arrayChanged = function(change) {
1141+
assert.strictEqual(change.indexSplices.length, 1);
1142+
assert.strictEqual(change.indexSplices[0].index, 1);
1143+
assert.strictEqual(change.indexSplices[0].addedCount, 2);
1144+
assert.strictEqual(change.indexSplices[0].removed.length, 1);
1145+
assert.strictEqual(change.indexSplices[0].removed[0], 'orig2');
1146+
assert.strictEqual(change.keySplices.length, 1);
1147+
assert.strictEqual(change.keySplices[0].index, 1);
1148+
assert.strictEqual(change.keySplices[0].added.length, 2);
1149+
assert.strictEqual(change.keySplices[0].added[0], key);
1150+
assert.strictEqual(change.keySplices[0].added[1], key+1);
1151+
assert.strictEqual(change.keySplices[0].removed.length, 1);
1152+
assert.strictEqual(change.keySplices[0].removed[0], 1);
1153+
};
1154+
var ret = el.splice('array', '-2', '1', 'new1', 'new2');
1155+
assert.deepEqual(ret, ['orig2']);
1156+
assert.strictEqual(el.array.length, 4);
1157+
assert.strictEqual(el.array[0], 'orig1');
1158+
assert.strictEqual(el.array[1], 'new1');
1159+
assert.strictEqual(el.array[2], 'new2');
1160+
assert.strictEqual(el.array[3], 'orig3');
1161+
});
1162+
9041163
});
9051164

9061165
</script>

0 commit comments

Comments
 (0)