Skip to content
Snippets Groups Projects
Commit 947bf6d3 authored by André Bargull's avatar André Bargull Committed by Leo Balter
Browse files

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

parent ed714d70
No related branches found
No related tags found
No related merge requests found
Showing
with 922 additions and 7 deletions
// 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");
// 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");
// 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");
// 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");
// 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");
// 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);
});
// 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");
...@@ -4,8 +4,7 @@ ...@@ -4,8 +4,7 @@
es6id: 22.1.3.23 es6id: 22.1.3.23
esid: sec-array.prototype.slice esid: sec-array.prototype.slice
description: > description: >
An undefined value for the @@species constructor triggers the creation of Ensure a RangeError is thrown when a proxied array returns an invalid array length.
an Array exotic object
info: | info: |
[...] [...]
8. Let A be ? ArraySpeciesCreate(O, count). 8. Let A be ? ArraySpeciesCreate(O, count).
...@@ -13,18 +12,17 @@ info: | ...@@ -13,18 +12,17 @@ info: |
9.4.2.3 ArraySpeciesCreate 9.4.2.3 ArraySpeciesCreate
[...]
3. Let isArray be ? IsArray(originalArray).
[...] [...]
5. Let C be ? Get(originalArray, "constructor"). 5. Let C be ? Get(originalArray, "constructor").
[...] [...]
7. If Type(C) is Object, then 10. Return ? Construct(C, « length »).
a. Let C be ? Get(C, @@species).
b. If C is null, let C be undefined.
8. If C is undefined, return ? ArrayCreate(length).
9.4.2.2 ArrayCreate 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] features: [Proxy]
---*/ ---*/
......
// 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)");
// 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)");
// 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");
// 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",
]);
// 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");
// 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");
// 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");
// 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");
// 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");
// 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");
// 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");
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment