}
-function ObservedArrayPop(n) {
- n--;
- var value = this[n];
-
- EnqueueSpliceRecord(this, n, [value], 1, 0);
-
- try {
- BeginPerformSplice(this);
- delete this[n];
- this.length = n;
- } finally {
- EndPerformSplice(this);
- }
-
- return value;
-}
-
// Removes the last element from the array and returns it. See
// ECMA-262, section 15.4.4.6.
function ArrayPop() {
this.length = n;
return;
}
-
- if (%IsObserved(this))
- return ObservedArrayPop.call(this, n);
-
n--;
var value = this[n];
delete this[n];
try {
BeginPerformSplice(this);
+
for (var i = 0; i < m; i++) {
this[i+n] = %_Arguments(i);
}
}
-function ObservedArrayShift(len) {
- var first = this[0];
-
- EnqueueSpliceRecord(this, 0, [first], 1, 0);
-
- try {
- BeginPerformSplice(this);
- SimpleMove(this, 0, 1, len, 0);
- this.length = len - 1;
- } finally {
- EndPerformSplice(this);
- }
-
- return first;
-}
-
function ArrayShift() {
if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
throw MakeTypeError("called_on_null_or_undefined",
return;
}
- if (%IsObserved(this))
- return ObservedArrayShift.call(this, len);
-
var first = this[0];
- if (IS_ARRAY(this)) {
+ if (IS_ARRAY(this) && !%IsObserved(this)) {
SmartMove(this, 0, 1, len, 0);
} else {
SimpleMove(this, 0, 1, len, 0);
return first;
}
-function ObservedArrayUnshift() {
- var len = TO_UINT32(this.length);
- var num_arguments = %_ArgumentsLength();
-
- EnqueueSpliceRecord(this, 0, [], 0, num_arguments);
-
- try {
- BeginPerformSplice(this);
- SimpleMove(this, 0, 0, len, num_arguments);
- for (var i = 0; i < num_arguments; i++) {
- this[i] = %_Arguments(i);
- }
- this.length = len + num_arguments;
- } finally {
- EndPerformSplice(this);
- }
-
- return len + num_arguments;
-}
function ArrayUnshift(arg1) { // length == 1
if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
["Array.prototype.unshift"]);
}
- if (%IsObserved(this))
- return ObservedArrayUnshift.apply(this, arguments);
-
var len = TO_UINT32(this.length);
var num_arguments = %_ArgumentsLength();
- if (IS_ARRAY(this)) {
+ if (IS_ARRAY(this) && !%IsObserved(this)) {
SmartMove(this, 0, 0, len, num_arguments);
} else {
SimpleMove(this, 0, 0, len, num_arguments);
}
-function ComputeSpliceStartIndex(start_i, len) {
- if (start_i < 0) {
- start_i += len;
- return start_i < 0 ? 0 : start_i;
+function ArraySplice(start, delete_count) {
+ if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
+ throw MakeTypeError("called_on_null_or_undefined",
+ ["Array.prototype.splice"]);
}
- return start_i > len ? len : start_i;
-}
+ var num_arguments = %_ArgumentsLength();
+ var len = TO_UINT32(this.length);
+ var start_i = TO_INTEGER(start);
+
+ if (start_i < 0) {
+ start_i += len;
+ if (start_i < 0) start_i = 0;
+ } else {
+ if (start_i > len) start_i = len;
+ }
-function ComputeSpliceDeleteCount(delete_count, num_arguments, len, start_i) {
// SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is
// given as a request to delete all the elements from the start.
// And it differs from the case of undefined delete count.
// This does not follow ECMA-262, but we do the same for
// compatibility.
var del_count = 0;
- if (num_arguments == 1)
- return len - start_i;
-
- del_count = TO_INTEGER(delete_count);
- if (del_count < 0)
- return 0;
-
- if (del_count > len - start_i)
- return len - start_i;
-
- return del_count;
-}
-
+ if (num_arguments == 1) {
+ del_count = len - start_i;
+ } else {
+ del_count = TO_INTEGER(delete_count);
+ if (del_count < 0) del_count = 0;
+ if (del_count > len - start_i) del_count = len - start_i;
+ }
-function ObservedArraySplice(start, delete_count) {
- var num_arguments = %_ArgumentsLength();
- var len = TO_UINT32(this.length);
- var start_i = ComputeSpliceStartIndex(TO_INTEGER(start), len);
- var del_count = ComputeSpliceDeleteCount(delete_count, num_arguments, len,
- start_i);
var deleted_elements = [];
deleted_elements.length = del_count;
- var num_elements_to_add = num_arguments > 2 ? num_arguments - 2 : 0;
-
- try {
- BeginPerformSplice(this);
- SimpleSlice(this, start_i, del_count, len, deleted_elements);
- SimpleMove(this, start_i, del_count, len, num_elements_to_add);
-
- // Insert the arguments into the resulting array in
- // place of the deleted elements.
- var i = start_i;
- var arguments_index = 2;
- var arguments_length = %_ArgumentsLength();
- while (arguments_index < arguments_length) {
- this[i++] = %_Arguments(arguments_index++);
- }
- this.length = len - del_count + num_elements_to_add;
-
- } finally {
- EndPerformSplice(this);
- if (deleted_elements.length || num_elements_to_add) {
- EnqueueSpliceRecord(this,
- start_i,
- deleted_elements.slice(),
- deleted_elements.length,
- num_elements_to_add);
- }
- }
-
- // Return the deleted elements.
- return deleted_elements;
-}
-
-
-function ArraySplice(start, delete_count) {
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["Array.prototype.splice"]);
+ // Number of elements to add.
+ var num_additional_args = 0;
+ if (num_arguments > 2) {
+ num_additional_args = num_arguments - 2;
}
- if (%IsObserved(this))
- return ObservedArraySplice.apply(this, arguments);
-
- var num_arguments = %_ArgumentsLength();
- var len = TO_UINT32(this.length);
- var start_i = ComputeSpliceStartIndex(TO_INTEGER(start), len);
- var del_count = ComputeSpliceDeleteCount(delete_count, num_arguments, len,
- start_i);
- var deleted_elements = [];
- deleted_elements.length = del_count;
- var num_elements_to_add = num_arguments > 2 ? num_arguments - 2 : 0;
-
var use_simple_splice = true;
+
if (IS_ARRAY(this) &&
- num_elements_to_add !== del_count) {
+ !%IsObserved(this) &&
+ num_additional_args !== del_count) {
// If we are only deleting/moving a few things near the end of the
// array then the simple version is going to be faster, because it
// doesn't touch most of the array.
if (use_simple_splice) {
SimpleSlice(this, start_i, del_count, len, deleted_elements);
- SimpleMove(this, start_i, del_count, len, num_elements_to_add);
+ SimpleMove(this, start_i, del_count, len, num_additional_args);
} else {
SmartSlice(this, start_i, del_count, len, deleted_elements);
- SmartMove(this, start_i, del_count, len, num_elements_to_add);
+ SmartMove(this, start_i, del_count, len, num_additional_args);
}
// Insert the arguments into the resulting array in
while (arguments_index < arguments_length) {
this[i++] = %_Arguments(arguments_index++);
}
- this.length = len - del_count + num_elements_to_add;
+ this.length = len - del_count + num_additional_args;
// Return the deleted elements.
return deleted_elements;
]);
// Pop
-reset();
-var array = [1, 2];
+reset()
+var array = {0: 1, 1: 2, length: 2};
Object.observe(array, observer.callback);
-Array.observe(array, observer2.callback);
-array.pop();
-array.pop();
-array.pop();
+Array.prototype.pop.call(array);
+Array.prototype.pop.call(array);
Object.deliverChangeRecords(observer.callback);
observer.assertCallbackRecords([
{ object: array, name: '1', type: 'deleted', oldValue: 2 },
{ object: array, name: '0', type: 'deleted', oldValue: 1 },
{ object: array, name: 'length', type: 'updated', oldValue: 1 },
]);
-Object.deliverChangeRecords(observer2.callback);
-observer2.assertCallbackRecords([
- { object: array, type: 'splice', index: 1, removed: [2], addedCount: 0 },
- { object: array, type: 'splice', index: 0, removed: [1], addedCount: 0 }
-]);
// Shift
-reset();
-var array = [1, 2];
+reset()
+var array = {0: 1, 1: 2, length: 2};
Object.observe(array, observer.callback);
-Array.observe(array, observer2.callback);
-array.shift();
-array.shift();
-array.shift();
+Array.prototype.shift.call(array);
+Array.prototype.shift.call(array);
Object.deliverChangeRecords(observer.callback);
observer.assertCallbackRecords([
{ object: array, name: '0', type: 'updated', oldValue: 1 },
{ object: array, name: '0', type: 'deleted', oldValue: 2 },
{ object: array, name: 'length', type: 'updated', oldValue: 1 },
]);
-Object.deliverChangeRecords(observer2.callback);
-observer2.assertCallbackRecords([
- { object: array, type: 'splice', index: 0, removed: [1], addedCount: 0 },
- { object: array, type: 'splice', index: 0, removed: [2], addedCount: 0 }
-]);
// Unshift
-reset();
-var array = [1, 2];
+reset()
+var array = {0: 1, 1: 2, length: 2};
Object.observe(array, observer.callback);
-Array.observe(array, observer2.callback);
-array.unshift(3, 4);
-array.unshift(5);
+Array.prototype.unshift.call(array, 3, 4);
Object.deliverChangeRecords(observer.callback);
observer.assertCallbackRecords([
{ object: array, name: '3', type: 'new' },
- { object: array, name: 'length', type: 'updated', oldValue: 2 },
{ object: array, name: '2', type: 'new' },
{ object: array, name: '0', type: 'updated', oldValue: 1 },
{ object: array, name: '1', type: 'updated', oldValue: 2 },
- { object: array, name: '4', type: 'new' },
- { object: array, name: 'length', type: 'updated', oldValue: 4 },
- { object: array, name: '3', type: 'updated', oldValue: 2 },
- { object: array, name: '2', type: 'updated', oldValue: 1 },
- { object: array, name: '1', type: 'updated', oldValue: 4 },
- { object: array, name: '0', type: 'updated', oldValue: 3 },
-]);
-Object.deliverChangeRecords(observer2.callback);
-observer2.assertCallbackRecords([
- { object: array, type: 'splice', index: 0, removed: [], addedCount: 2 },
- { object: array, type: 'splice', index: 0, removed: [], addedCount: 1 }
+ { object: array, name: 'length', type: 'updated', oldValue: 2 },
]);
// Splice
-reset();
-var array = [1, 2, 3];
+reset()
+var array = {0: 1, 1: 2, 2: 3, length: 3};
Object.observe(array, observer.callback);
-Array.observe(array, observer2.callback);
-array.splice(1, 0, 4, 5); // 1 4 5 2 3
-array.splice(0, 2); // 5 2 3
-array.splice(1, 2, 6, 7); // 5 6 7
-array.splice(2, 0);
+Array.prototype.splice.call(array, 1, 1, 4, 5);
Object.deliverChangeRecords(observer.callback);
observer.assertCallbackRecords([
- { object: array, name: '4', type: 'new' },
- { object: array, name: 'length', type: 'updated', oldValue: 3 },
{ object: array, name: '3', type: 'new' },
{ object: array, name: '1', type: 'updated', oldValue: 2 },
{ object: array, name: '2', type: 'updated', oldValue: 3 },
-
- { object: array, name: '0', type: 'updated', oldValue: 1 },
- { object: array, name: '1', type: 'updated', oldValue: 4 },
- { object: array, name: '2', type: 'updated', oldValue: 5 },
- { object: array, name: '4', type: 'deleted', oldValue: 3 },
- { object: array, name: '3', type: 'deleted', oldValue: 2 },
- { object: array, name: 'length', type: 'updated', oldValue: 5 },
-
- { object: array, name: '1', type: 'updated', oldValue: 2 },
- { object: array, name: '2', type: 'updated', oldValue: 3 },
-]);
-Object.deliverChangeRecords(observer2.callback);
-observer2.assertCallbackRecords([
- { object: array, type: 'splice', index: 1, removed: [], addedCount: 2 },
- { object: array, type: 'splice', index: 0, removed: [1, 4], addedCount: 0 },
- { object: array, type: 'splice', index: 1, removed: [2, 3], addedCount: 2 },
+ { object: array, name: 'length', type: 'updated', oldValue: 3 },
]);
// Exercise StoreIC_ArrayLength