mirror of https://github.com/tc39/test262.git
Add tests for Array.prototype methods when length property exceeds safe integer limit (#1028)
This commit is contained in:
parent
ed714d702a
commit
947bf6d3e2
|
@ -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");
|
|
@ -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");
|
|
@ -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");
|
|
@ -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");
|
|
@ -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");
|
32
test/built-ins/Array/prototype/reverse/length-exceeding-integer-limit-with-object.js
vendored
Normal file
32
test/built-ins/Array/prototype/reverse/length-exceeding-integer-limit-with-object.js
vendored
Normal 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);
|
||||
});
|
119
test/built-ins/Array/prototype/reverse/length-exceeding-integer-limit-with-proxy.js
vendored
Normal file
119
test/built-ins/Array/prototype/reverse/length-exceeding-integer-limit-with-proxy.js
vendored
Normal 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");
|
|
@ -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]
|
||||
---*/
|
||||
|
56
test/built-ins/Array/prototype/slice/length-exceeding-integer-limit-proxied-array.js
vendored
Normal file
56
test/built-ins/Array/prototype/slice/length-exceeding-integer-limit-proxied-array.js
vendored
Normal 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)");
|
|
@ -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)");
|
|
@ -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");
|
88
test/built-ins/Array/prototype/splice/create-species-length-exceeding-integer-limit.js
vendored
Normal file
88
test/built-ins/Array/prototype/splice/create-species-length-exceeding-integer-limit.js
vendored
Normal 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",
|
||||
]);
|
54
test/built-ins/Array/prototype/splice/length-and-deleteCount-exceeding-integer-limit.js
vendored
Normal file
54
test/built-ins/Array/prototype/splice/length-and-deleteCount-exceeding-integer-limit.js
vendored
Normal 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");
|
64
test/built-ins/Array/prototype/splice/length-exceeding-integer-limit-shrink-array.js
vendored
Normal file
64
test/built-ins/Array/prototype/splice/length-exceeding-integer-limit-shrink-array.js
vendored
Normal 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");
|
62
test/built-ins/Array/prototype/splice/length-near-integer-limit-grow-array.js
vendored
Normal file
62
test/built-ins/Array/prototype/splice/length-near-integer-limit-grow-array.js
vendored
Normal 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");
|
|
@ -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");
|
|
@ -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");
|
|
@ -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");
|
|
@ -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");
|
Loading…
Reference in New Issue