mirror of https://github.com/svaarala/duktape.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
102 lines
2.9 KiB
102 lines
2.9 KiB
/*
|
|
* If array length is 0xffffffff, Array.prototype.push() appends all the
|
|
* requested items and then sets the final 'length'.
|
|
*
|
|
* For Ecmascript arrays (objects with array special behavior), the item
|
|
* writes will succeed, and the modified [[DefineOwnProperty]] algorithm
|
|
* in Section 15.4.5.1 triggers an automatic 'length' update for items
|
|
* whose index is in the range [0,0xfffffffe]. Outside this range the
|
|
* item gets written successfully but 'length' won't get updated. The
|
|
* final explicit 'length' write causes a RangeError if the final length
|
|
* would be above 0xffffffff. In error cases -all items- get written and
|
|
* length may be updated (up to 0xffffffff).
|
|
*
|
|
* When the argument is not an Ecmascript array, the length is updated to
|
|
* 0x100000000.
|
|
*/
|
|
|
|
/*===
|
|
array
|
|
RangeError
|
|
4294967295 foo
|
|
RangeError
|
|
4294967295 foo bar quux baz
|
|
4294967295 foo bar
|
|
non-array
|
|
4294967296 foo
|
|
4294967297 foo bar quux baz
|
|
4294967295 foo bar
|
|
===*/
|
|
|
|
function testArray() {
|
|
var a;
|
|
|
|
// 0xffffffff is maximum 'normal' length for an Array, e.g. assigning
|
|
// to offset 0xffffffff gets no special behavior to avoid bumping length
|
|
// to 0x100000000. However, Array.prototype.push() has no such limitation.
|
|
// Check for -noncompliant- but real world compatible behavior to refuse a
|
|
// push which would causes a non-32-bit length.
|
|
|
|
a = [];
|
|
a.length = 0xffffffff;
|
|
try {
|
|
a.push('foo');
|
|
} catch (e) {
|
|
print(e.name);
|
|
}
|
|
print(a.length, a[0xffffffff]);
|
|
|
|
// Same happens for lower 'length' values when there are enough push()
|
|
// arguments. Note that when the push() algorithm writes elements using
|
|
// numeric indices, array exotic behavior gets triggered for indices
|
|
// in the range [0,0xfffffffe] so that 'length' gets updated here to
|
|
// 0xffffffff. Items above this range -will- get written to the array
|
|
// but won't trigger a RangeError. Only the final explicit 'length'
|
|
// write causes a RangeError; all items get written!
|
|
|
|
a = [];
|
|
a.length = 0xfffffffd;
|
|
try {
|
|
a.push('foo', 'bar', 'quux', 'baz');
|
|
} catch (e) {
|
|
print(e.name);
|
|
}
|
|
print(a.length, a[0xfffffffd], a[0xfffffffe], a[0xffffffff], a[0x100000000]);
|
|
|
|
// Boundary cases should work.
|
|
|
|
a = [];
|
|
a.length = 0xfffffffd;
|
|
a.push('foo', 'bar');
|
|
print(a.length, a[0xfffffffd], a[0xfffffffe]);
|
|
}
|
|
|
|
function testNonArray() {
|
|
var a;
|
|
|
|
a = { length: 0xffffffff };
|
|
Array.prototype.push.call(a, 'foo');
|
|
print(a.length, a[0xffffffff]);
|
|
|
|
a = { length: 0xfffffffd };
|
|
Array.prototype.push.call(a, 'foo', 'bar', 'quux', 'baz');
|
|
print(a.length, a[0xfffffffd], a[0xfffffffe], a[0xffffffff], a[0x100000000]);
|
|
|
|
a = { length: 0xfffffffd };
|
|
Array.prototype.push.call(a, 'foo', 'bar');
|
|
print(a.length, a[0xfffffffd], a[0xfffffffe]);
|
|
}
|
|
|
|
print('array');
|
|
try {
|
|
testArray();
|
|
} catch (e) {
|
|
print(e);
|
|
}
|
|
|
|
print('non-array');
|
|
try {
|
|
testNonArray();
|
|
} catch (e) {
|
|
print(e);
|
|
}
|
|
|