Add tests for Array.prototype methods when length property exceeds safe integer limit (#1028)

This commit is contained in:
André Bargull 2017-05-10 18:20:06 +02:00 committed by Leo Balter
parent ed714d702a
commit 947bf6d3e2
19 changed files with 922 additions and 7 deletions

View File

@ -0,0 +1,35 @@
// Copyright (C) 2017 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.pop
description: >
Length values exceeding 2^53-1 are clamped to 2^53-1.
info: |
1. ...
2. Let len be ? ToLength(? Get(O, "length")).
...
4. Else len > 0,
a. Let newLen be len-1.
...
e. Perform ? Set(O, "length", newLen, true).
...
---*/
var arrayLike = {};
arrayLike.length = 2**53 - 1;
Array.prototype.pop.call(arrayLike);
assert.sameValue(arrayLike.length, 2**53 - 2, "Length is 2**53 - 1");
arrayLike.length = 2**53;
Array.prototype.pop.call(arrayLike);
assert.sameValue(arrayLike.length, 2**53 - 2, "Length is 2**53");
arrayLike.length = 2**53 + 2;
Array.prototype.pop.call(arrayLike);
assert.sameValue(arrayLike.length, 2**53 - 2, "Length is 2**53 + 2");
arrayLike.length = Infinity;
Array.prototype.pop.call(arrayLike);
assert.sameValue(arrayLike.length, 2**53 - 2, "Length is Infinity");

View File

@ -0,0 +1,43 @@
// Copyright (C) 2017 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.pop
description: >
A value is removed from an array-like object whose length property is near the integer limit.
info: |
...
2. Let len be ? ToLength(? Get(O, "length")).
...
4. Else len > 0,
a. Let newLen be len-1.
b. Let index be ! ToString(newLen).
c. Let element be ? Get(O, index).
d. Perform ? DeletePropertyOrThrow(O, index).
e. Perform ? Set(O, "length", newLen, true).
f. Return element.
---*/
var arrayLike = {
"9007199254740989": "9007199254740989",
"9007199254740990": "9007199254740990",
"9007199254740991": "9007199254740991",
length: 2**53 - 1
};
var value = Array.prototype.pop.call(arrayLike);
assert.sameValue(value, "9007199254740990",
"arrayLike['9007199254740990'] is returned from pop()");
assert.sameValue(arrayLike.length, 2**53 - 2,
"New arrayLike.length is 2**53 - 2");
assert.sameValue(arrayLike["9007199254740989"], "9007199254740989",
"arrayLike['9007199254740989'] is unchanged");
assert.sameValue("9007199254740990" in arrayLike, false,
"arrayLike['9007199254740990'] is removed");
assert.sameValue(arrayLike["9007199254740991"], "9007199254740991",
"arrayLike['9007199254740991'] is unchanged");

View File

@ -0,0 +1,35 @@
// Copyright (C) 2017 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.push
description: >
Length values exceeding 2^53-1 are clamped to 2^53-1.
info: |
1. ...
2. Let len be ? ToLength(? Get(O, "length")).
3. Let items be a List whose elements are, in left to right order, the arguments
that were passed to this function invocation.
4. Let argCount be the number of elements in items.
...
7. Perform ? Set(O, "length", len, true).
...
---*/
var arrayLike = {};
arrayLike.length = 2**53 - 1;
Array.prototype.push.call(arrayLike);
assert.sameValue(arrayLike.length, 2**53 - 1, "Length is 2**53 - 1");
arrayLike.length = 2**53;
Array.prototype.push.call(arrayLike);
assert.sameValue(arrayLike.length, 2**53 - 1, "Length is 2**53");
arrayLike.length = 2**53 + 2;
Array.prototype.push.call(arrayLike);
assert.sameValue(arrayLike.length, 2**53 - 1, "Length is 2**53 + 2");
arrayLike.length = Infinity;
Array.prototype.push.call(arrayLike);
assert.sameValue(arrayLike.length, 2**53 - 1, "Length is Infinity");

View File

@ -0,0 +1,39 @@
// Copyright (C) 2017 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.push
description: >
A value is inserted in an array-like object whose length property is near the integer limit.
info: |
...
2. Let len be ? ToLength(? Get(O, "length")).
3. Let items be a List whose elements are, in left to right order, the
arguments that were passed to this function invocation.
...
5. Repeat, while items is not empty
...
7. Perform ? Set(O, "length", len, true).
...
---*/
var arrayLike = {
"9007199254740989": "9007199254740989",
/* "9007199254740990": empty */
"9007199254740991": "9007199254740991",
length: 2**53 - 2
};
Array.prototype.push.call(arrayLike, "new-value");
assert.sameValue(arrayLike.length, 2**53 - 1,
"New arrayLike.length is 2**53 - 1");
assert.sameValue(arrayLike["9007199254740989"], "9007199254740989",
"arrayLike['9007199254740989'] is unchanged");
assert.sameValue(arrayLike["9007199254740990"], "new-value",
"arrayLike['9007199254740990'] has new value");
assert.sameValue(arrayLike["9007199254740991"], "9007199254740991",
"arrayLike['9007199254740991'] is unchanged");

View File

@ -0,0 +1,38 @@
// Copyright (C) 2017 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.push
description: >
A TypeError is thrown if the new length exceeds 2^53-1.
info: |
1. ...
2. Let len be ? ToLength(? Get(O, "length")).
3. Let items be a List whose elements are, in left to right order, the arguments
that were passed to this function invocation.
4. Let argCount be the number of elements in items.
5. If len + argCount > 2^53-1, throw a TypeError exception.
...
---*/
var arrayLike = {};
arrayLike.length = 2**53 - 1;
assert.throws(TypeError, function() {
Array.prototype.push.call(arrayLike, null);
}, "Length is 2**53 - 1");
arrayLike.length = 2**53;
assert.throws(TypeError, function() {
Array.prototype.push.call(arrayLike, null);
}, "Length is 2**53");
arrayLike.length = 2**53 + 2;
assert.throws(TypeError, function() {
Array.prototype.push.call(arrayLike, null);
}, "Length is 2**53 + 2");
arrayLike.length = Infinity;
assert.throws(TypeError, function() {
Array.prototype.push.call(arrayLike, null);
}, "Length is Infinity");

View File

@ -0,0 +1,32 @@
// Copyright (C) 2017 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.reverse
description: >
Ensure reverse() implementation correctly handles length exceeding 2^53-1 with plain objects.
info: |
...
2. Let len be ? ToLength(? Get(O, "length")).
...
---*/
function StopReverse() { }
// Object with large "length" property and no indexed properties in the uint32 range.
var arrayLike = {
get "9007199254740990"() {
throw new StopReverse();
},
get "9007199254740991"() {
$ERROR("Get 9007199254740991");
},
get "9007199254740992"() {
$ERROR("Get 9007199254740992");
},
length: 2**53 + 2,
};
assert.throws(StopReverse, function() {
Array.prototype.reverse.call(arrayLike);
});

View File

@ -0,0 +1,119 @@
// Copyright (C) 2017 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.reverse
description: >
Ensure correct MOP operations are called when length exceeds 2^53-1.
includes: [compareArray.js, proxyTrapsHelper.js]
---*/
function StopReverse() { }
var arrayLike = {
0: "zero",
/* 1: hole, */
2: "two",
/* 3: hole, */
get 4() {
throw new StopReverse();
},
9007199254740987: "2**53-5",
/* 9007199254740988: hole, */
/* 9007199254740989: hole, */
9007199254740990: "2**53-2",
length: 2**53 + 2,
};
var traps = [];
var proxy = new Proxy(arrayLike, allowProxyTraps({
getOwnPropertyDescriptor(t, pk) {
traps.push(`GetOwnPropertyDescriptor:${String(pk)}`);
return Reflect.getOwnPropertyDescriptor(t, pk);
},
defineProperty(t, pk, desc) {
traps.push(`DefineProperty:${String(pk)}`);
return Reflect.defineProperty(t, pk, desc);
},
has(t, pk) {
traps.push(`Has:${String(pk)}`);
return Reflect.has(t, pk);
},
get(t, pk, r) {
traps.push(`Get:${String(pk)}`);
return Reflect.get(t, pk, r);
},
set(t, pk, v, r) {
traps.push(`Set:${String(pk)}`);
return Reflect.set(t, pk, v, r);
},
deleteProperty(t, pk) {
traps.push(`Delete:${String(pk)}`);
return Reflect.deleteProperty(t, pk);
},
}))
// Uses a separate exception than Test262Error, so that errors from allowProxyTraps
// are properly propagated.
assert.throws(StopReverse, function() {
Array.prototype.reverse.call(proxy);
});
assert.compareArray(traps, [
// Initial get length operation.
"Get:length",
// Lower and upper index are both present.
"Has:0",
"Get:0",
"Has:9007199254740990",
"Get:9007199254740990",
"Set:0",
"GetOwnPropertyDescriptor:0",
"DefineProperty:0",
"Set:9007199254740990",
"GetOwnPropertyDescriptor:9007199254740990",
"DefineProperty:9007199254740990",
// Lower and upper index are both absent.
"Has:1",
"Has:9007199254740989",
// Lower index is present, upper index is absent.
"Has:2",
"Get:2",
"Has:9007199254740988",
"Delete:2",
"Set:9007199254740988",
"GetOwnPropertyDescriptor:9007199254740988",
"DefineProperty:9007199254740988",
// Lower index is absent, upper index is present.
"Has:3",
"Has:9007199254740987",
"Get:9007199254740987",
"Set:3",
"GetOwnPropertyDescriptor:3",
"DefineProperty:3",
"Delete:9007199254740987",
// Stop exception.
"Has:4",
"Get:4",
]);
assert.sameValue(arrayLike.length, 2**53 + 2, "Length property is not modified");
assert.sameValue(arrayLike[0], "2**53-2", "Property at index 0");
assert.sameValue(1 in arrayLike, false, "Property at index 1");
assert.sameValue(2 in arrayLike, false, "Property at index 2");
assert.sameValue(arrayLike[3], "2**53-5", "Property at index 3");
assert.sameValue(9007199254740987 in arrayLike, false, "Property at index 2**53-5");
assert.sameValue(arrayLike[9007199254740988], "two", "Property at index 2**53-4");
assert.sameValue(9007199254740989 in arrayLike, false, "Property at index 2**53-3");
assert.sameValue(arrayLike[9007199254740990], "zero", "Property at index 2**53-2");

View File

@ -4,8 +4,7 @@
es6id: 22.1.3.23
esid: sec-array.prototype.slice
description: >
An undefined value for the @@species constructor triggers the creation of
an Array exotic object
Ensure a RangeError is thrown when a proxied array returns an invalid array length.
info: |
[...]
8. Let A be ? ArraySpeciesCreate(O, count).
@ -13,18 +12,17 @@ info: |
9.4.2.3 ArraySpeciesCreate
[...]
3. Let isArray be ? IsArray(originalArray).
[...]
5. Let C be ? Get(originalArray, "constructor").
[...]
7. If Type(C) is Object, then
a. Let C be ? Get(C, @@species).
b. If C is null, let C be undefined.
8. If C is undefined, return ? ArrayCreate(length).
10. Return ? Construct(C, « length »).
9.4.2.2 ArrayCreate
[...]
3. If length>232-1, throw a RangeError exception.
3. If length>2^32-1, throw a RangeError exception.
features: [Proxy]
---*/

View File

@ -0,0 +1,56 @@
// Copyright (C) 2017 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.slice
description: >
Length property is clamped to 2^53-1, test with indices near 2^53-1 and negative indices
and a proxy to an array.
info: |
...
2. Let len be ? ToLength(? Get(O, "length")).
3. Let relativeStart be ? ToInteger(start).
4. If relativeStart < 0, let k be max((len + relativeStart), 0);
else let k be min(relativeStart, len).
5. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToInteger(end).
6. If relativeEnd < 0, let final be max((len + relativeEnd), 0);
else let final be min(relativeEnd, len).
...
includes: [compareArray.js]
---*/
var array = [];
array["9007199254740988"] = "9007199254740988";
array["9007199254740989"] = "9007199254740989";
array["9007199254740990"] = "9007199254740990";
array["9007199254740991"] = "9007199254740991";
// Create a proxy to an array object, so IsArray returns true, but we can still
// return a length value exceeding the integer limit.
var proxy = new Proxy(array, {
get(t, pk, r) {
if (pk === "length")
return 2**53 + 2;
return Reflect.get(t, pk, r);
}
});
var result = Array.prototype.slice.call(proxy, 9007199254740989);
assert.compareArray(result, [ "9007199254740989", "9007199254740990" ],
"slice(9007199254740989)");
var result = Array.prototype.slice.call(proxy, 9007199254740989, 9007199254740990);
assert.compareArray(result, [ "9007199254740989" ],
"slice(9007199254740989, 9007199254740990)");
var result = Array.prototype.slice.call(proxy, 9007199254740989, 9007199254740996);
assert.compareArray(result, [ "9007199254740989", "9007199254740990" ],
"slice(9007199254740989, 9007199254740996)");
var result = Array.prototype.slice.call(proxy, -2);
assert.compareArray(result, [ "9007199254740989", "9007199254740990" ],
"slice(-2)");
var result = Array.prototype.slice.call(proxy, -2, -1);
assert.compareArray(result, [ "9007199254740989" ],
"slice(-2, -1)");

View File

@ -0,0 +1,47 @@
// Copyright (C) 2017 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.slice
description: >
Length property is clamped to 2^53-1, test with indices near 2^53-1 and negative indices.
info: |
...
2. Let len be ? ToLength(? Get(O, "length")).
3. Let relativeStart be ? ToInteger(start).
4. If relativeStart < 0, let k be max((len + relativeStart), 0);
else let k be min(relativeStart, len).
5. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToInteger(end).
6. If relativeEnd < 0, let final be max((len + relativeEnd), 0);
else let final be min(relativeEnd, len).
...
includes: [compareArray.js]
---*/
var arrayLike = {
"9007199254740988": "9007199254740988",
"9007199254740989": "9007199254740989",
"9007199254740990": "9007199254740990",
"9007199254740991": "9007199254740991",
length: 2**53 + 2,
};
var result = Array.prototype.slice.call(arrayLike, 9007199254740989);
assert.compareArray(result, [ "9007199254740989", "9007199254740990" ],
"slice(9007199254740989)");
var result = Array.prototype.slice.call(arrayLike, 9007199254740989, 9007199254740990);
assert.compareArray(result, [ "9007199254740989" ],
"slice(9007199254740989, 9007199254740990)");
var result = Array.prototype.slice.call(arrayLike, 9007199254740989, 9007199254740996);
assert.compareArray(result, [ "9007199254740989", "9007199254740990" ],
"slice(9007199254740989, 9007199254740996)");
var result = Array.prototype.slice.call(arrayLike, -2);
assert.compareArray(result, [ "9007199254740989", "9007199254740990" ],
"slice(-2)");
var result = Array.prototype.slice.call(arrayLike, -2, -1);
assert.compareArray(result, [ "9007199254740989" ],
"slice(-2, -1)");

View File

@ -0,0 +1,36 @@
// Copyright (C) 2017 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.splice
description: >
Length values exceeding 2^53-1 are clamped to 2^53-1.
info: |
1. ...
2. Let len be ? ToLength(? Get(O, "length")).
...
5. If the number of actual arguments is 0, then
a. Let insertCount be 0.
b. Let actualDeleteCount be 0.
...
19. Perform ? Set(O, "length", len - actualDeleteCount + itemCount, true).
...
---*/
var arrayLike = {};
arrayLike.length = 2**53 - 1;
Array.prototype.splice.call(arrayLike);
assert.sameValue(arrayLike.length, 2**53 - 1, "Length is 2**53 - 1");
arrayLike.length = 2**53;
Array.prototype.splice.call(arrayLike);
assert.sameValue(arrayLike.length, 2**53 - 1, "Length is 2**53");
arrayLike.length = 2**53 + 2;
Array.prototype.splice.call(arrayLike);
assert.sameValue(arrayLike.length, 2**53 - 1, "Length is 2**53 + 2");
arrayLike.length = Infinity;
Array.prototype.splice.call(arrayLike);
assert.sameValue(arrayLike.length, 2**53 - 1, "Length is Infinity");

View File

@ -0,0 +1,88 @@
// Copyright (C) 2017 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.splice
description: >
Create species constructor with length exceeding integer limit and ensure MOP
operations are called in correct order.
info: |
...
9. Let A be ? ArraySpeciesCreate(O, actualDeleteCount).
10. Let k be 0.
11. Repeat, while k < actualDeleteCount
a. Let from be ! ToString(actualStart+k).
b. Let fromPresent be ? HasProperty(O, from).
c. If fromPresent is true, then
i. Let fromValue be ? Get(O, from).
ii. Perform ? CreateDataPropertyOrThrow(A, ! ToString(k), fromValue).
d. Increment k by 1.
12. Perform ? Set(A, "length", actualDeleteCount, true).
...
includes: [compareArray.js, proxyTrapsHelper.js]
---*/
function StopSplice() {}
var traps = [];
var targetLength;
var array = ["no-hole", /* hole */, "stop"];
array.constructor = {
[Symbol.species]: function(n) {
targetLength = n;
return target;
}
};
var source = new Proxy(array, allowProxyTraps({
get(t, pk, r) {
traps.push(`source.[[Get]]:${String(pk)}`);
// length property exceeding 2^53-1.
if (pk === "length")
return 2**53 + 2;
return Reflect.get(t, pk, r);
},
has(t, pk, r) {
traps.push(`source.[[Has]]:${String(pk)}`);
return Reflect.get(t, pk, r);
},
}));
var target = new Proxy([], allowProxyTraps({
defineProperty(t, pk, desc) {
traps.push(`target.[[DefineProperty]]:${String(pk)}`);
if (pk === "0" || pk === "1")
return Reflect.defineProperty(t, pk, desc);
throw new StopSplice();
}
}));
assert.throws(StopSplice, function() {
// deleteCount argument exceeding 2^53-1.
Array.prototype.splice.call(source, 0, 2**53 + 4);
});
assert.sameValue(targetLength, 2**53 - 1,
"length and deleteCount were correctly clamped to 2^53-1");
assert.compareArray(traps, [
"source.[[Get]]:length",
"source.[[Get]]:constructor",
"source.[[Has]]:0",
"source.[[Get]]:0",
"target.[[DefineProperty]]:0",
"source.[[Has]]:1",
"source.[[Has]]:2",
"source.[[Get]]:2",
"target.[[DefineProperty]]:2",
]);

View File

@ -0,0 +1,54 @@
// Copyright (C) 2017 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.splice
description: >
Length and deleteCount are both clamped to 2^53-1 when they exceed the integer limit.
info: |
...
2. Let len be ? ToLength(? Get(O, "length")).
...
7. Else,
a. Let insertCount be the number of actual arguments minus 2.
b. Let dc be ? ToInteger(deleteCount).
c. Let actualDeleteCount be min(max(dc, 0), len - actualStart).
...
11. Repeat, while k < actualDeleteCount
a. Let from be ! ToString(actualStart+k).
b. Let fromPresent be ? HasProperty(O, from).
c. If fromPresent is true, then
i. Let fromValue be ? Get(O, from).
ii. Perform ? CreateDataPropertyOrThrow(A, ! ToString(k), fromValue).
d. Increment k by 1.
...
includes: [compareArray.js]
---*/
var arrayLike = {
"9007199254740988": "9007199254740988",
"9007199254740989": "9007199254740989",
"9007199254740990": "9007199254740990",
"9007199254740991": "9007199254740991",
length: 2**53 + 2,
};
var result = Array.prototype.splice.call(arrayLike, 9007199254740989, 2**53 + 4);
assert.compareArray(result, [ "9007199254740989", "9007199254740990" ],
"arrayLike['9007199254740989'] and arrayLike['9007199254740990'] are removed");
assert.sameValue(arrayLike.length, 2**53 - 3,
"New length is 2**53 - 3");
assert.sameValue(arrayLike["9007199254740988"], "9007199254740988",
"arrayLike['9007199254740988'] is unchanged");
assert.sameValue("9007199254740989" in arrayLike, false,
"arrayLike['9007199254740989'] is removed");
assert.sameValue("9007199254740990" in arrayLike, false,
"arrayLike['9007199254740990'] is removed");
assert.sameValue(arrayLike["9007199254740991"], "9007199254740991",
"arrayLike['9007199254740991'] is unchanged");

View File

@ -0,0 +1,64 @@
// Copyright (C) 2017 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.splice
description: >
An element is removed from an array-like object whose length exceeds the integer limit.
info: |
...
15. If itemCount < actualDeleteCount, then
a. Let k be actualStart.
b. Repeat, while k < (len - actualDeleteCount)
i. Let from be ! ToString(k+actualDeleteCount).
ii. Let to be ! ToString(k+itemCount).
iii. Let fromPresent be ? HasProperty(O, from).
iv. If fromPresent is true, then
1. Let fromValue be ? Get(O, from).
2. Perform ? Set(O, to, fromValue, true).
v. Else fromPresent is false,
1. Perform ? DeletePropertyOrThrow(O, to).
vi. Increase k by 1.
c. Let k be len.
d. Repeat, while k > (len - actualDeleteCount + itemCount)
i. Perform ? DeletePropertyOrThrow(O, ! ToString(k-1)).
ii. Decrease k by 1.
...
includes: [compareArray.js]
---*/
var arrayLike = {
"9007199254740986": "9007199254740986",
"9007199254740987": "9007199254740987",
"9007199254740988": "9007199254740988",
/* "9007199254740989": hole */
"9007199254740990": "9007199254740990",
"9007199254740991": "9007199254740991",
length: 2**53 + 2,
};
var result = Array.prototype.splice.call(arrayLike, 9007199254740987, 1);
assert.compareArray(result, [ "9007199254740987" ],
"arrayLike['9007199254740987'] is removed");
assert.sameValue(arrayLike.length, 2**53 - 2,
"New length is 2**53 - 2");
assert.sameValue(arrayLike["9007199254740986"], "9007199254740986",
"arrayLike['9007199254740986'] is unchanged");
assert.sameValue(arrayLike["9007199254740987"], "9007199254740988",
"arrayLike['9007199254740988'] is moved to arrayLike['9007199254740987']");
assert.sameValue("9007199254740988" in arrayLike, false,
"arrayLike['9007199254740990'] is removed");
assert.sameValue(arrayLike["9007199254740989"], "9007199254740990",
"arrayLike['9007199254740990'] is moved to arrayLike['9007199254740989']");
assert.sameValue("9007199254740990" in arrayLike, false,
"arrayLike['9007199254740990'] is removed");
assert.sameValue(arrayLike["9007199254740991"], "9007199254740991",
"arrayLike['9007199254740991'] is unchanged");

View File

@ -0,0 +1,62 @@
// Copyright (C) 2017 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.splice
description: >
A value is inserted in an array-like object whose length property is near the integer limit.
info: |
...
16. Else if itemCount > actualDeleteCount, then
a. Let k be (len - actualDeleteCount).
b. Repeat, while k > actualStart
i. Let from be ! ToString(k + actualDeleteCount - 1).
ii. Let to be ! ToString(k + itemCount - 1).
iii. Let fromPresent be ? HasProperty(O, from).
iv. If fromPresent is true, then
1. Let fromValue be ? Get(O, from).
2. Perform ? Set(O, to, fromValue, true).
v. Else fromPresent is false,
1. Perform ? DeletePropertyOrThrow(O, to).
vi. Decrease k by 1.
...
includes: [compareArray.js]
---*/
var arrayLike = {
"9007199254740985": "9007199254740985",
"9007199254740986": "9007199254740986",
"9007199254740987": "9007199254740987",
/* "9007199254740988": hole */
"9007199254740989": "9007199254740989",
/* "9007199254740990": empty */
"9007199254740991": "9007199254740991",
length: 2**53 - 2,
};
var result = Array.prototype.splice.call(arrayLike, 9007199254740986, 0, "new-value");
assert.compareArray(result, [], "No elements are removed");
assert.sameValue(arrayLike.length, 2**53 - 1, "New length is 2**53 - 1");
assert.sameValue(arrayLike["9007199254740985"], "9007199254740985",
"arrayLike['9007199254740985'] is unchanged");
assert.sameValue(arrayLike["9007199254740986"], "new-value",
"arrayLike['9007199254740986'] contains the inserted value");
assert.sameValue(arrayLike["9007199254740987"], "9007199254740986",
"arrayLike['9007199254740986'] is moved to arrayLike['9007199254740987']");
assert.sameValue(arrayLike["9007199254740988"], "9007199254740987",
"arrayLike['9007199254740987'] is moved to arrayLike['9007199254740988']");
assert.sameValue("9007199254740989" in arrayLike, false,
"arrayLike['9007199254740989'] is removed");
assert.sameValue(arrayLike["9007199254740990"], "9007199254740989",
"arrayLike['9007199254740989'] is moved to arrayLike['9007199254740990']");
assert.sameValue(arrayLike["9007199254740991"], "9007199254740991",
"arrayLike['9007199254740991'] is unchanged");

View File

@ -0,0 +1,40 @@
// Copyright (C) 2017 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.splice
description: >
A TypeError is thrown if the new length exceeds 2^53-1.
info: |
1. ...
2. Let len be ? ToLength(? Get(O, "length")).
...
7. Else,
a. Let insertCount be the number of actual arguments minus 2.
b. Let dc be ? ToInteger(deleteCount).
c. Let actualDeleteCount be min(max(dc, 0), len - actualStart).
8. If len+insertCount-actualDeleteCount > 2^53-1, throw a TypeError exception.
...
---*/
var arrayLike = {};
arrayLike.length = 2**53 - 1;
assert.throws(TypeError, function() {
Array.prototype.splice.call(arrayLike, 0, 0, null);
}, "Length is 2**53 - 1");
arrayLike.length = 2**53;
assert.throws(TypeError, function() {
Array.prototype.splice.call(arrayLike, 0, 0, null);
}, "Length is 2**53");
arrayLike.length = 2**53 + 2;
assert.throws(TypeError, function() {
Array.prototype.splice.call(arrayLike, 0, 0, null);
}, "Length is 2**53 + 2");
arrayLike.length = Infinity;
assert.throws(TypeError, function() {
Array.prototype.splice.call(arrayLike, 0, 0, null);
}, "Length is Infinity");

View File

@ -0,0 +1,32 @@
// Copyright (C) 2017 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.unshift
description: >
Length values exceeding 2^53-1 are clamped to 2^53-1.
info: |
1. ...
2. Let len be ? ToLength(? Get(O, "length")).
3. Let argCount be the number of actual arguments.
4. If argCount > 0, then ...
5. Perform ? Set(O, "length", len+argCount, true).
---*/
var arrayLike = {};
arrayLike.length = 2**53 - 1;
Array.prototype.unshift.call(arrayLike);
assert.sameValue(arrayLike.length, 2**53 - 1, "Length is 2**53 - 1");
arrayLike.length = 2**53;
Array.prototype.unshift.call(arrayLike);
assert.sameValue(arrayLike.length, 2**53 - 1, "Length is 2**53");
arrayLike.length = 2**53 + 2;
Array.prototype.unshift.call(arrayLike);
assert.sameValue(arrayLike.length, 2**53 - 1, "Length is 2**53 + 2");
arrayLike.length = Infinity;
Array.prototype.unshift.call(arrayLike);
assert.sameValue(arrayLike.length, 2**53 - 1, "Length is Infinity");

View File

@ -0,0 +1,60 @@
// Copyright (C) 2017 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.unshift
description: >
Test properties are correctly accessed when length property is near 2^53-1.
info: |
2. Let len be ? ToLength(? Get(O, "length")).
3. Let argCount be the number of actual arguments.
4. If argCount > 0, then
...
b. Let k be len.
c. Repeat, while k > 0,
i. Let from be ! ToString(k-1).
ii. Let to be ! ToString(k+argCount-1).
iii. Let fromPresent be ? HasProperty(O, from).
iv. If fromPresent is true, then
1. Let fromValue be ? Get(O, from).
2. Perform ? Set(O, to, fromValue, true).
v. Else fromPresent is false,
1. Perform ? DeletePropertyOrThrow(O, to).
vi. Decrease k by 1.
---*/
function StopUnshift() {}
var arrayLike = {
get "9007199254740986"() {
throw new StopUnshift();
},
"9007199254740987": "9007199254740987",
/* "9007199254740988": hole */
"9007199254740989": "9007199254740989",
/* "9007199254740990": empty */
"9007199254740991": "9007199254740991",
length: 2**53 - 2
};
assert.throws(StopUnshift, function() {
Array.prototype.unshift.call(arrayLike, null);
});
assert.sameValue(arrayLike.length, 2**53 - 2,
"arrayLike.length is unchanged");
assert.sameValue(arrayLike["9007199254740987"], "9007199254740987",
"arrayLike['9007199254740987'] is unchanged");
assert.sameValue(arrayLike["9007199254740988"], "9007199254740987",
"arrayLike['9007199254740988'] is replaced with arrayLike['9007199254740987']");
assert.sameValue("9007199254740989" in arrayLike, false,
"arrayLike['9007199254740989'] is removed");
assert.sameValue(arrayLike["9007199254740990"], "9007199254740989",
"arrayLike['9007199254740990'] is replaced with arrayLike['9007199254740989']");
assert.sameValue(arrayLike["9007199254740991"], "9007199254740991",
"arrayLike['9007199254740991'] is unchanged");

View File

@ -0,0 +1,37 @@
// Copyright (C) 2017 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.unshift
description: >
A TypeError is thrown if the new length exceeds 2^53-1.
info: |
1. ...
2. Let len be ? ToLength(? Get(O, "length")).
3. Let argCount be the number of actual arguments.
4. If argCount > 0, then
a. If len+argCount > 2^53-1, throw a TypeError exception.
b. ...
---*/
var arrayLike = {};
arrayLike.length = 2**53 - 1;
assert.throws(TypeError, function() {
Array.prototype.unshift.call(arrayLike, null);
}, "Length is 2**53 - 1");
arrayLike.length = 2**53;
assert.throws(TypeError, function() {
Array.prototype.unshift.call(arrayLike, null);
}, "Length is 2**53");
arrayLike.length = 2**53 + 2;
assert.throws(TypeError, function() {
Array.prototype.unshift.call(arrayLike, null);
}, "Length is 2**53 + 2");
arrayLike.length = Infinity;
assert.throws(TypeError, function() {
Array.prototype.unshift.call(arrayLike, null);
}, "Length is Infinity");