diff --git a/features.txt b/features.txt index 47f3388511..30feb0436e 100644 --- a/features.txt +++ b/features.txt @@ -284,6 +284,11 @@ regexp-duplicate-named-groups # https://github.com/tc39/proposal-symbols-as-weakmap-keys symbols-as-weakmap-keys +# Array.prototype.toReversed, Array.prototype.toSorted, Array.prototype.toSpliced, +# Array.prototype.with and the equivalent TypedArray methods. +# https://github.com/tc39/proposal-change-array-by-copy/ +change-array-by-copy + ## Standard language features # # Language features that have been included in a published version of the diff --git a/test/built-ins/Array/prototype/Symbol.unscopables/change-array-by-copy.js b/test/built-ins/Array/prototype/Symbol.unscopables/change-array-by-copy.js new file mode 100644 index 0000000000..4e734f8ee6 --- /dev/null +++ b/test/built-ins/Array/prototype/Symbol.unscopables/change-array-by-copy.js @@ -0,0 +1,29 @@ +// Copyright (C) 2021 Igalia. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-array.prototype-@@unscopables +description: > + Initial value of `Symbol.unscopables` property +info: | + 22.1.3.32 Array.prototype [ @@unscopables ] + + ... + 12. Perform ! CreateDataPropertyOrThrow(unscopableList, "toReversed", true). + 13. Perform ! CreateDataPropertyOrThrow(unscopableList, "toSorted", true). + 14. Perform ! CreateDataPropertyOrThrow(unscopableList, "toSpliced", true). + ... +includes: [propertyHelper.js] +features: [Symbol.unscopables, change-array-by-copy] +---*/ + +var unscopables = Array.prototype[Symbol.unscopables]; + +for (const unscopable of ["toReversed", "toSorted", "toSpliced"]) { + verifyProperty(unscopables, unscopable, { + value: true, + writable: true, + configurable: true + }) +}; + +assert.sameValue(Object.hasOwnProperty.call(unscopables, "with"), false, "does not have `with`"); diff --git a/test/built-ins/Array/prototype/toReversed/frozen-this-value.js b/test/built-ins/Array/prototype/toReversed/frozen-this-value.js new file mode 100644 index 0000000000..2c0cf118a8 --- /dev/null +++ b/test/built-ins/Array/prototype/toReversed/frozen-this-value.js @@ -0,0 +1,18 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toReversed +description: > + Array.prototype.toReversed works on frozen objects +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var arr = Object.freeze([0, 1, 2]); +var result = arr.toReversed(); +assert.compareArray(result, [2, 1, 0]); + +var arrayLike = Object.freeze({ length: 3, 0: 0, 1: 1, 2: 2 }); +result = Array.prototype.toReversed.call(arrayLike); +assert.compareArray(result, [2, 1, 0]); diff --git a/test/built-ins/Array/prototype/toReversed/get-descending-order.js b/test/built-ins/Array/prototype/toReversed/get-descending-order.js new file mode 100644 index 0000000000..c9d324d55a --- /dev/null +++ b/test/built-ins/Array/prototype/toReversed/get-descending-order.js @@ -0,0 +1,49 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toReversed +description: > + Array.prototype.toReversed gets the array elements from the last one to the first one. +info: | + Array.prototype.toReversed ( ) + + ... + 2. Let len be ? LengthOfArrayLike(O). + ... + 5. Repeat, while k < len + a. Let from be ! ToString(𝔽(len - k - 1)). + ... + c. Let fromValue be ? Get(O, from). + ... +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var order = []; +var arrayLike = { + length: 3, + get 0() { + order.push(0); + }, + get 1() { + order.push(1); + }, + get 2() { + order.push(2); + }, +}; + +Array.prototype.toReversed.call(arrayLike); + +assert.compareArray(order, [2, 1, 0]); + +order = []; +var arr = [0, 1, 2]; +Object.defineProperty(arr, 0, { get: function() { order.push(0); } }); +Object.defineProperty(arr, 1, { get: function() { order.push(1); } }); +Object.defineProperty(arr, 2, { get: function() { order.push(2); } }); + +Array.prototype.toReversed.call(arr); + +assert.compareArray(order, [2, 1, 0]); diff --git a/test/built-ins/Array/prototype/toReversed/holes-not-preserved.js b/test/built-ins/Array/prototype/toReversed/holes-not-preserved.js new file mode 100644 index 0000000000..90510f186a --- /dev/null +++ b/test/built-ins/Array/prototype/toReversed/holes-not-preserved.js @@ -0,0 +1,29 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toReversed +description: > + Array.prototype.toReversed does not preserve holes in the array +info: | + Array.prototype.toReversed ( ) + + ... + 2. Let len be ? LengthOfArrayLike(O). + ... + 5. Repeat, while k < len + a. Let from be ! ToString(𝔽(len - k - 1)). + ... + c. Let fromValue be ? Get(O, from). + d. Perform ? CreateDataPropertyOrThrow(A, Pk, fromValue). + ... +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var arr = [0, /* hole */, 2, /* hole */, 4]; +Array.prototype[3] = 3; + +var reversed = arr.toReversed(); +assert.compareArray(reversed, [4, 3, 2, undefined, 0]); +assert(reversed.hasOwnProperty(3)); diff --git a/test/built-ins/Array/prototype/toReversed/ignores-species.js b/test/built-ins/Array/prototype/toReversed/ignores-species.js new file mode 100644 index 0000000000..6c29739478 --- /dev/null +++ b/test/built-ins/Array/prototype/toReversed/ignores-species.js @@ -0,0 +1,31 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toReversed +description: > + Array.prototype.toReversed ignores @@species +info: | + Array.prototype.toReversed ( ) + + ... + 3. Let A be ? ArrayCreate(𝔽(len)). + ... +features: [change-array-by-copy] +---*/ + +var a = []; +a.constructor = {}; +a.constructor[Symbol.species] = function () {} + +assert.sameValue(Object.getPrototypeOf(a.toReversed()), Array.prototype); + +var b = []; + +Object.defineProperty(b, "constructor", { + get() { + throw new Test262Error("Should not get .constructor"); + } +}); + +b.toReversed(); diff --git a/test/built-ins/Array/prototype/toReversed/immutable.js b/test/built-ins/Array/prototype/toReversed/immutable.js new file mode 100644 index 0000000000..b3c5883dbd --- /dev/null +++ b/test/built-ins/Array/prototype/toReversed/immutable.js @@ -0,0 +1,16 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toReversed +description: > + Array.prototype.toReversed does not mutate its this value +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var arr = [0, 1, 2]; +arr.toReversed(); + +assert.compareArray(arr, [0, 1, 2]); +assert.notSameValue(arr.toReversed(), arr); diff --git a/test/built-ins/Array/prototype/toReversed/length-casted-to-zero.js b/test/built-ins/Array/prototype/toReversed/length-casted-to-zero.js new file mode 100644 index 0000000000..4576827611 --- /dev/null +++ b/test/built-ins/Array/prototype/toReversed/length-casted-to-zero.js @@ -0,0 +1,20 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toReversed +description: > + Array.prototype.toReversed creates an empty array if the this value .length is not a positive integer. +info: | + Array.prototype.toReversed ( ) + + ... + 2. Let len be ? LengthOfArrayLike(O). + ... +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +assert.compareArray(Array.prototype.toReversed.call({ length: -2 }), []); +assert.compareArray(Array.prototype.toReversed.call({ length: "dog" }), []); +assert.compareArray(Array.prototype.toReversed.call({ length: NaN }), []); diff --git a/test/built-ins/Array/prototype/toReversed/length-decreased-while-iterating.js b/test/built-ins/Array/prototype/toReversed/length-decreased-while-iterating.js new file mode 100644 index 0000000000..90a40d601a --- /dev/null +++ b/test/built-ins/Array/prototype/toReversed/length-decreased-while-iterating.js @@ -0,0 +1,32 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toReversed +description: > + Array.prototype.toReversed caches the length getting the array elements. +info: | + Array.prototype.toReversed ( ) + + ... + 2. Let len be ? LengthOfArrayLike(O). + ... + 5. Repeat, while k < len + ... + c. Let fromValue be ? Get(O, from). + ... +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var arr = [0, 1, 2, 3, 4]; +Array.prototype[1] = 5; + +Object.defineProperty(arr, "3", { + get() { + arr.length = 1; + return 3; + } +}); + +assert.compareArray(arr.toReversed(), [4, 3, undefined, 5, 0]); diff --git a/test/built-ins/Array/prototype/toReversed/length-exceeding-array-length-limit.js b/test/built-ins/Array/prototype/toReversed/length-exceeding-array-length-limit.js new file mode 100644 index 0000000000..e3a212a078 --- /dev/null +++ b/test/built-ins/Array/prototype/toReversed/length-exceeding-array-length-limit.js @@ -0,0 +1,38 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toReversed +description: > + Array.prototype.toReversed limits the length to 2 ** 32 - 1 +info: | + Array.prototype.toReversed ( ) + + ... + 2. Let len be ? LengthOfArrayLike(O). + 3. Let A be ? ArrayCreate(𝔽(len)). + ... + + ArrayCreate ( length [, proto ] ) + + 1. If length > 2 ** 32 - 1, throw a RangeError exception. +features: [change-array-by-copy] +---*/ + +// Object with large "length" property +var arrayLike = { + get "0"() { + throw new Test262Error("Get 0"); + }, + get "4294967295" () { // 2 ** 32 - 1 + throw new Test262Error("Get 2147483648"); + }, + get "4294967296" () { // 2 ** 32 + throw new Test262Error("Get 2147483648"); + }, + length: 2 ** 32 +}; + +assert.throws(RangeError, function() { + Array.prototype.toReversed.call(arrayLike); +}); diff --git a/test/built-ins/Array/prototype/toReversed/length-increased-while-iterating.js b/test/built-ins/Array/prototype/toReversed/length-increased-while-iterating.js new file mode 100644 index 0000000000..8f7b099097 --- /dev/null +++ b/test/built-ins/Array/prototype/toReversed/length-increased-while-iterating.js @@ -0,0 +1,30 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toReversed +description: > + Array.prototype.toReversed caches the length getting the array elements. +info: | + Array.prototype.toReversed ( ) + + ... + 2. Let len be ? LengthOfArrayLike(O). + ... + 5. Repeat, while k < len + ... + c. Let fromValue be ? Get(O, from). + ... +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var arr = [0, 1, 2]; +Object.defineProperty(arr, "0", { + get() { + arr.push(4); + return 0; + } +}); + +assert.compareArray(arr.toReversed(), [2, 1, 0]); diff --git a/test/built-ins/Array/prototype/toReversed/length-tolength.js b/test/built-ins/Array/prototype/toReversed/length-tolength.js new file mode 100644 index 0000000000..6d175a899d --- /dev/null +++ b/test/built-ins/Array/prototype/toReversed/length-tolength.js @@ -0,0 +1,29 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toReversed +description: > + Array.prototype.toReversed converts the this value length to a number. +info: | + Array.prototype.toReversed ( ) + + ... + 2. Let len be ? LengthOfArrayLike(O). + ... +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +assert.compareArray(Array.prototype.toReversed.call({ length: "2", 0: 1, 1: 2, 2: 3 }), [2, 1]); + +var arrayLike = { + length: { + valueOf: () => 2 + }, + 0: 1, + 1: 2, + 2: 3, +}; + +assert.compareArray(Array.prototype.toReversed.call(arrayLike), [2, 1]); diff --git a/test/built-ins/Array/prototype/toReversed/metadata/length.js b/test/built-ins/Array/prototype/toReversed/metadata/length.js new file mode 100644 index 0000000000..bb28f08522 --- /dev/null +++ b/test/built-ins/Array/prototype/toReversed/metadata/length.js @@ -0,0 +1,30 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toReversed +description: > + The "length" property of Array.prototype.toReversed +info: | + 17 ECMAScript Standard Built-in Objects + + Every built-in function object, including constructors, has a length property + whose value is an integer. Unless otherwise specified, this value is equal to + the largest number of named arguments shown in the subclause headings for the + function description. Optional parameters (which are indicated with brackets: + [ ]) or rest parameters (which are shown using the form «...name») are not + included in the default argument count. + + Unless otherwise specified, the length property of a built-in function object + has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [change-array-by-copy] +---*/ + +verifyProperty(Array.prototype.toReversed, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); diff --git a/test/built-ins/Array/prototype/toReversed/metadata/name.js b/test/built-ins/Array/prototype/toReversed/metadata/name.js new file mode 100644 index 0000000000..5ea28d2c32 --- /dev/null +++ b/test/built-ins/Array/prototype/toReversed/metadata/name.js @@ -0,0 +1,28 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toReversed +description: > + Array.prototype.toReversed.name is "toReversed". +info: | + Array.prototype.toReversed ( ) + + 17 ECMAScript Standard Built-in Objects: + Every built-in Function object, including constructors, that is not + identified as an anonymous function has a name property whose value + is a String. + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [change-array-by-copy] +---*/ + +verifyProperty(Array.prototype.toReversed, "name", { + value: "toReversed", + writable: false, + enumerable: false, + configurable: true, +}); diff --git a/test/built-ins/Array/prototype/toReversed/metadata/property-descriptor.js b/test/built-ins/Array/prototype/toReversed/metadata/property-descriptor.js new file mode 100644 index 0000000000..e0ff507c13 --- /dev/null +++ b/test/built-ins/Array/prototype/toReversed/metadata/property-descriptor.js @@ -0,0 +1,25 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toReversed +description: > + "toReversed" property of Array.prototype +info: | + 17 ECMAScript Standard Built-in Objects + + Every other data property described in clauses 18 through 26 and in Annex B.2 + has the attributes { [[Writable]]: true, [[Enumerable]]: false, + [[Configurable]]: true } unless otherwise specified. +includes: [propertyHelper.js] +features: [change-array-by-copy] +---*/ + +assert.sameValue(typeof Array.prototype.toReversed, "function", "typeof"); + +verifyProperty(Array.prototype, "toReversed", { + value: Array.prototype.toReversed, + writable: true, + enumerable: false, + configurable: true, +}); diff --git a/test/built-ins/Array/prototype/toReversed/not-a-constructor.js b/test/built-ins/Array/prototype/toReversed/not-a-constructor.js new file mode 100644 index 0000000000..6cfabfe6ff --- /dev/null +++ b/test/built-ins/Array/prototype/toReversed/not-a-constructor.js @@ -0,0 +1,33 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + Array.prototype.toReversed does not implement [[Construct]], is not new-able +info: | + ECMAScript Function Objects + + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified in + the description of a particular function. + + sec-evaluatenew + + ... + 7. If IsConstructor(constructor) is false, throw a TypeError exception. + ... +includes: [isConstructor.js] +features: [change-array-by-copy, Reflect.construct] +---*/ + +assert.sameValue( + isConstructor(Array.prototype.toReversed), + false, + 'isConstructor(Array.prototype.toReversed) must return false' +); + +assert.throws(TypeError, () => { + new Array.prototype.toReversed(); +}, '`new Array.prototype.toReversed()` throws TypeError'); + diff --git a/test/built-ins/Array/prototype/toReversed/this-value-boolean.js b/test/built-ins/Array/prototype/toReversed/this-value-boolean.js new file mode 100644 index 0000000000..a9534ccea8 --- /dev/null +++ b/test/built-ins/Array/prototype/toReversed/this-value-boolean.js @@ -0,0 +1,29 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toReversed +description: > + Array.prototype.toReversed converts booleans to objects +info: | + Array.prototype.toReversed ( ) + + 1. Let O be ? ToObject(this value). + 2. Let len be ? LengthOfArrayLike(O). + ... +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +assert.compareArray(Array.prototype.toReversed.call(true), []); +assert.compareArray(Array.prototype.toReversed.call(false), []); + +/* Add length and indexed properties to `Boolean.prototype` */ +Boolean.prototype.length = 3; +assert.compareArray(Array.prototype.toReversed.call(true), [undefined, undefined, undefined]); +assert.compareArray(Array.prototype.toReversed.call(false), [undefined, undefined, undefined]); +delete Boolean.prototype.length; +Boolean.prototype[0] = "monkeys"; +Boolean.prototype[2] = "bogus"; +assert.compareArray(Array.prototype.toReversed.call(true), []); +assert.compareArray(Array.prototype.toReversed.call(false), []); diff --git a/test/built-ins/Array/prototype/toReversed/this-value-nullish.js b/test/built-ins/Array/prototype/toReversed/this-value-nullish.js new file mode 100644 index 0000000000..b81e99f592 --- /dev/null +++ b/test/built-ins/Array/prototype/toReversed/this-value-nullish.js @@ -0,0 +1,22 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toReversed +description: > + Array.prototype.toReversed throws if the receiver is null or undefined +info: | + Array.prototype.toReversed ( ) + + 1. Let O be ? ToObject(this value). + ... +features: [change-array-by-copy] +---*/ + +assert.throws(TypeError, () => { + Array.prototype.toReversed.call(null); +}, '`Array.prototype.toReversed.call(null)` throws TypeError'); + +assert.throws(TypeError, () => { + Array.prototype.toReversed.call(undefined); +}, '`Array.prototype.toReversed.call(undefined)` throws TypeError'); diff --git a/test/built-ins/Array/prototype/toReversed/zero-or-one-element.js b/test/built-ins/Array/prototype/toReversed/zero-or-one-element.js new file mode 100644 index 0000000000..110fa41b65 --- /dev/null +++ b/test/built-ins/Array/prototype/toReversed/zero-or-one-element.js @@ -0,0 +1,20 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toReversed +description: > + Array.prototype.toReversed returns a new array even if it has zero or one elements +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var zero = []; +var zeroReversed = zero.toReversed(); +assert.notSameValue(zero, zeroReversed); +assert.compareArray(zero, zeroReversed); + +var one = [1]; +var oneReversed = one.toReversed(); +assert.notSameValue(one, oneReversed); +assert.compareArray(one, oneReversed); diff --git a/test/built-ins/Array/prototype/toSorted/comparefn-called-after-get-elements.js b/test/built-ins/Array/prototype/toSorted/comparefn-called-after-get-elements.js new file mode 100644 index 0000000000..f9d675003e --- /dev/null +++ b/test/built-ins/Array/prototype/toSorted/comparefn-called-after-get-elements.js @@ -0,0 +1,43 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSorted +description: > + Array.prototype.toSorted reads all the array elements before calling compareFn +info: | + SortIndexedProperties ( obj, len, SortCompare, skipHoles ) + + ... + 3. Repeat, while k < len, + a. Let Pk be ! ToString(𝔽(k)). + ... + i. Let kValue be ? Get(O, Pk). + ... + 4. Sort items using an implementation-defined sequence of + calls to SortCompare. If any such call returns an abrupt + completion, stop before performing any further calls to + SortCompare or steps in this algorithm and return that + Completion Record. + ... +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var getCalls = []; + +var arrayLike = { + length: 3, + get 0() { getCalls.push(0); return 2; }, + get 1() { getCalls.push(1); return 1; }, + get 2() { getCalls.push(2); return 3; }, + +} + +assert.throws(Test262Error, function() { + Array.prototype.toSorted.call(arrayLike, () => { + throw new Test262Error(); + }); +}); + +assert.compareArray(getCalls, [0, 1, 2]); diff --git a/test/built-ins/Array/prototype/toSorted/comparefn-not-a-function.js b/test/built-ins/Array/prototype/toSorted/comparefn-not-a-function.js new file mode 100644 index 0000000000..427130c1b2 --- /dev/null +++ b/test/built-ins/Array/prototype/toSorted/comparefn-not-a-function.js @@ -0,0 +1,33 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSorted +description: > + Array.prototype.toSorted verifies that the comparator is callable before reading the length. +info: | + Array.prototype.toSorted ( compareFn ) + + 1. If comparefn is not undefined and IsCallable(comparefn) is false, throw a TypeError exception. + 2. ... + 3. Let len be ? LengthOfArrayLike(O). +features: [change-array-by-copy] +---*/ + +var getLengthThrow = { + get length() { + throw new Test262Error("IsCallable(comparefn) should be observed before this.length"); + } +}; + +var invalidComparators = [null, true, false, "", /a/g, 42, 42n, [], {}, Symbol()]; + +for (var i = 0; i < invalidComparators.length; i++) { + assert.throws(TypeError, function() { + [1].toSorted(invalidComparators[i]); + }, String(invalidComparators[i]) + " on an array"); + + assert.throws(TypeError, function() { + Array.prototype.toSorted.call(getLengthThrow, invalidComparators[i]); + }, String(invalidComparators[i]) + " on an object whose 'length' throws"); +} diff --git a/test/built-ins/Array/prototype/toSorted/comparefn-stop-after-error.js b/test/built-ins/Array/prototype/toSorted/comparefn-stop-after-error.js new file mode 100644 index 0000000000..4b1838d1e8 --- /dev/null +++ b/test/built-ins/Array/prototype/toSorted/comparefn-stop-after-error.js @@ -0,0 +1,42 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSorted +description: > + Array.prototype.toSorted doesn't call compareFn if there is an error +info: | + Array.prototype.toSorted ( compareFn ) + + ... + 7. Sort items using an implementation-defined sequence of + calls to SortCompare. If any such call returns an abrupt + completion, stop before performing any further calls to + SortCompare or steps in this algorithm and return that completion. + ... +features: [change-array-by-copy] +---*/ + +var arrayLike = { + length: 1, + get 0() { throw new Test262Error(); }, +}; + +var called = false; +assert.throws(Test262Error, function() { + Array.prototype.toSorted.call(arrayLike, () => { + called = true; + }); +}); +assert.sameValue(called, false); + +called = 0; +assert.throws(Test262Error, function() { + [1, 2, 3].toSorted(() => { + ++called; + if (called === 1) { + throw new Test262Error(); + } + }); +}); +assert.sameValue(called, 1); diff --git a/test/built-ins/Array/prototype/toSorted/frozen-this-value.js b/test/built-ins/Array/prototype/toSorted/frozen-this-value.js new file mode 100644 index 0000000000..4d7cad0307 --- /dev/null +++ b/test/built-ins/Array/prototype/toSorted/frozen-this-value.js @@ -0,0 +1,18 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSorted +description: > + Array.prototype.toSorted works on frozen objects +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var arr = Object.freeze([2, 0, 1]); +var result = arr.toSorted(); +assert.compareArray(result, [0, 1, 2]); + +var arrayLike = Object.freeze({ length: 3, 0: 2, 1: 0, 2: 1 }); +result = Array.prototype.toSorted.call(arrayLike); +assert.compareArray(result, [0, 1, 2]); diff --git a/test/built-ins/Array/prototype/toSorted/holes-not-preserved.js b/test/built-ins/Array/prototype/toSorted/holes-not-preserved.js new file mode 100644 index 0000000000..f630632df9 --- /dev/null +++ b/test/built-ins/Array/prototype/toSorted/holes-not-preserved.js @@ -0,0 +1,25 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSorted +description: > + Array.prototype.toSorted does not preserve holes in the array +info: | + Array.prototype.toSorted ( compareFn ) + + ... + 8. Repeat, while j < len, + a. Perform ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(j)), sortedList[j]). + b. Set j to j + 1. + ... +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var arr = [3, /* hole */, 4, /* hole */, 1]; +Array.prototype[3] = 2; + +var sorted = arr.toSorted(); +assert.compareArray(sorted, [1, 2, 3, 4, undefined]); +assert(sorted.hasOwnProperty(4)); diff --git a/test/built-ins/Array/prototype/toSorted/ignores-species.js b/test/built-ins/Array/prototype/toSorted/ignores-species.js new file mode 100644 index 0000000000..42246a7e35 --- /dev/null +++ b/test/built-ins/Array/prototype/toSorted/ignores-species.js @@ -0,0 +1,30 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSorted +description: > + Array.prototype.toSorted ignores @@species +info: | + Array.prototype.toSorted ( compareFn ) + + ... + 8. Let A be ? ArrayCreate(𝔽(len)). + ... +features: [change-array-by-copy] +---*/ + +var a = []; +a.constructor = {}; +a.constructor[Symbol.species] = function () {} + +assert.sameValue(Object.getPrototypeOf(a.toSorted()), Array.prototype); + +var b = []; +Object.defineProperty(b, "constructor", { + get() { + throw new Test262Error("Should not get .constructor"); + } +}); + +b.toSorted(); diff --git a/test/built-ins/Array/prototype/toSorted/immutable.js b/test/built-ins/Array/prototype/toSorted/immutable.js new file mode 100644 index 0000000000..57bdb9f020 --- /dev/null +++ b/test/built-ins/Array/prototype/toSorted/immutable.js @@ -0,0 +1,16 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSorted +description: > + Array.prototype.toSorted does not mutate its this value +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var arr = [2, 0, 1]; +arr.toSorted(); + +assert.compareArray(arr, [2, 0, 1]); +assert.notSameValue(arr.toSorted(), arr); diff --git a/test/built-ins/Array/prototype/toSorted/length-casted-to-zero.js b/test/built-ins/Array/prototype/toSorted/length-casted-to-zero.js new file mode 100644 index 0000000000..197c6e3fd7 --- /dev/null +++ b/test/built-ins/Array/prototype/toSorted/length-casted-to-zero.js @@ -0,0 +1,20 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSorted +description: > + Array.prototype.toSorted creates an empty array if the this value .length is not a positive integer. +info: | + Array.prototype.toSorted ( compareFn ) + + ... + 3. Let len be ? LengthOfArrayLike(O). + ... +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +assert.compareArray(Array.prototype.toSorted.call({ length: -2 }), []); +assert.compareArray(Array.prototype.toSorted.call({ length: "dog" }), []); +assert.compareArray(Array.prototype.toSorted.call({ length: NaN }), []); diff --git a/test/built-ins/Array/prototype/toSorted/length-decreased-while-iterating.js b/test/built-ins/Array/prototype/toSorted/length-decreased-while-iterating.js new file mode 100644 index 0000000000..b8d441c3c0 --- /dev/null +++ b/test/built-ins/Array/prototype/toSorted/length-decreased-while-iterating.js @@ -0,0 +1,31 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSorted +description: > + Array.prototype.toSorted caches the length getting the array elements. +info: | + Array.prototype.toSorted ( compareFn ) + + ... + 3. Let len be ? LengthOfArrayLike(O). + ... + 6. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, false). + ... + +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var arr = [5, 1, 4, 6, 3]; +Array.prototype[3] = 2; + +Object.defineProperty(arr, "2", { + get() { + arr.length = 1; + return 4; + } +}); + +assert.compareArray(arr.toSorted(), [1, 2, 4, 5, undefined]); diff --git a/test/built-ins/Array/prototype/toSorted/length-exceeding-array-length-limit.js b/test/built-ins/Array/prototype/toSorted/length-exceeding-array-length-limit.js new file mode 100644 index 0000000000..72ae5353a5 --- /dev/null +++ b/test/built-ins/Array/prototype/toSorted/length-exceeding-array-length-limit.js @@ -0,0 +1,39 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSorted +description: > + Array.prototype.toSorted limits the length to 2 ** 32 - 1 +info: | + Array.prototype.toSorted ( compareFn ) + + ... + 3. Let len be ? LengthOfArrayLike(O). + ... + 8. Let A be ? ArrayCreate(𝔽(len)). + ... + + ArrayCreate ( length [, proto ] ) + + 1. If length > 2 ** 32 - 1, throw a RangeError exception. +features: [change-array-by-copy] +---*/ + +// Object with large "length" property +var arrayLike = { + get "0"() { + throw new Test262Error("Get 0"); + }, + get "4294967295" () { // 2 ** 32 - 1 + throw new Test262Error("Get 2147483648"); + }, + get "4294967296" () { // 2 ** 32 + throw new Test262Error("Get 2147483648"); + }, + length: 2 ** 32 +}; + +assert.throws(RangeError, function() { + Array.prototype.toSorted.call(arrayLike); +}); diff --git a/test/built-ins/Array/prototype/toSorted/length-increased-while-iterating.js b/test/built-ins/Array/prototype/toSorted/length-increased-while-iterating.js new file mode 100644 index 0000000000..c5614665b5 --- /dev/null +++ b/test/built-ins/Array/prototype/toSorted/length-increased-while-iterating.js @@ -0,0 +1,29 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSorted +description: > + Array.prototype.toSorted caches the length getting the array elements. +info: | + Array.prototype.toSorted ( compareFn ) + + ... + 3. Let len be ? LengthOfArrayLike(O). + ... + 6. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, false). + ... + +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var arr = [5, 0, 3]; +Object.defineProperty(arr, "0", { + get() { + arr.push(1); + return 5; + } +}); + +assert.compareArray(arr.toSorted(), [0, 3, 5]); diff --git a/test/built-ins/Array/prototype/toSorted/length-tolength.js b/test/built-ins/Array/prototype/toSorted/length-tolength.js new file mode 100644 index 0000000000..d84ea0e881 --- /dev/null +++ b/test/built-ins/Array/prototype/toSorted/length-tolength.js @@ -0,0 +1,29 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSorted +description: > + Array.prototype.toSorted converts the this value length to a number. +info: | + Array.prototype.toSorted ( compareFn ) + + ... + 3. Let len be ? LengthOfArrayLike(O). + ... +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +assert.compareArray(Array.prototype.toSorted.call({ length: "2", 0: 4, 1: 0, 2: 1 }), [0, 4]); + +var arrayLike = { + length: { + valueOf: () => 2 + }, + 0: 4, + 1: 0, + 2: 1, +}; + +assert.compareArray(Array.prototype.toSorted.call(arrayLike), [0, 4]); diff --git a/test/built-ins/Array/prototype/toSorted/metadata/length.js b/test/built-ins/Array/prototype/toSorted/metadata/length.js new file mode 100644 index 0000000000..b1c447b0ea --- /dev/null +++ b/test/built-ins/Array/prototype/toSorted/metadata/length.js @@ -0,0 +1,30 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSorted +description: > + The "length" property of Array.prototype.toSorted +info: | + 17 ECMAScript Standard Built-in Objects + + Every built-in function object, including constructors, has a length property + whose value is an integer. Unless otherwise specified, this value is equal to + the largest number of named arguments shown in the subclause headings for the + function description. Optional parameters (which are indicated with brackets: + [ ]) or rest parameters (which are shown using the form «...name») are not + included in the default argument count. + + Unless otherwise specified, the length property of a built-in function object + has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [change-array-by-copy] +---*/ + +verifyProperty(Array.prototype.toSorted, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); diff --git a/test/built-ins/Array/prototype/toSorted/metadata/name.js b/test/built-ins/Array/prototype/toSorted/metadata/name.js new file mode 100644 index 0000000000..cffc50eabf --- /dev/null +++ b/test/built-ins/Array/prototype/toSorted/metadata/name.js @@ -0,0 +1,28 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSorted +description: > + Array.prototype.toSorted.name is "toSorted". +info: | + Array.prototype.toSorted ( compareFn ) + + 17 ECMAScript Standard Built-in Objects: + Every built-in Function object, including constructors, that is not + identified as an anonymous function has a name property whose value + is a String. + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [change-array-by-copy] +---*/ + +verifyProperty(Array.prototype.toSorted, "name", { + value: "toSorted", + writable: false, + enumerable: false, + configurable: true, +}); diff --git a/test/built-ins/Array/prototype/toSorted/metadata/property-descriptor.js b/test/built-ins/Array/prototype/toSorted/metadata/property-descriptor.js new file mode 100644 index 0000000000..b7550bc62f --- /dev/null +++ b/test/built-ins/Array/prototype/toSorted/metadata/property-descriptor.js @@ -0,0 +1,25 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSorted +description: > + "toSorted" property of Array.prototype +info: | + 17 ECMAScript Standard Built-in Objects + + Every other data property described in clauses 18 through 26 and in Annex B.2 + has the attributes { [[Writable]]: true, [[Enumerable]]: false, + [[Configurable]]: true } unless otherwise specified. +includes: [propertyHelper.js] +features: [change-array-by-copy] +---*/ + +assert.sameValue(typeof Array.prototype.toSorted, "function", "typeof"); + +verifyProperty(Array.prototype, "toSorted", { + value: Array.prototype.toSorted, + writable: true, + enumerable: false, + configurable: true, +}); diff --git a/test/built-ins/Array/prototype/toSorted/not-a-constructor.js b/test/built-ins/Array/prototype/toSorted/not-a-constructor.js new file mode 100644 index 0000000000..8865d18166 --- /dev/null +++ b/test/built-ins/Array/prototype/toSorted/not-a-constructor.js @@ -0,0 +1,33 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + Array.prototype.toSorted does not implement [[Construct]], is not new-able +info: | + ECMAScript Function Objects + + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified in + the description of a particular function. + + sec-evaluatenew + + ... + 7. If IsConstructor(constructor) is false, throw a TypeError exception. + ... +includes: [isConstructor.js] +features: [change-array-by-copy, Reflect.construct] +---*/ + +assert.sameValue( + isConstructor(Array.prototype.toSorted), + false, + 'isConstructor(Array.prototype.toSorted) must return false' +); + +assert.throws(TypeError, () => { + new Array.prototype.toSorted(); +}, '`new Array.prototype.toSorted()` throws TypeError'); + diff --git a/test/built-ins/Array/prototype/toSorted/this-value-boolean.js b/test/built-ins/Array/prototype/toSorted/this-value-boolean.js new file mode 100644 index 0000000000..27b05c44f4 --- /dev/null +++ b/test/built-ins/Array/prototype/toSorted/this-value-boolean.js @@ -0,0 +1,30 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSorted +description: > + Array.prototype.toSorted converts booleans to objects +info: | + Array.prototype.toSorted ( compareFn ) + + 1. Let O be ? ToObject(this value). + 2. Let len be ? LengthOfArrayLike(O). + ... +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +assert.compareArray(Array.prototype.toSorted.call(true), []); +assert.compareArray(Array.prototype.toSorted.call(false), []); + + +/* Add length and indexed properties to `Boolean.prototype` */ +Boolean.prototype.length = 3; +assert.compareArray(Array.prototype.toSorted.call(true), [undefined, undefined, undefined]); +assert.compareArray(Array.prototype.toSorted.call(false), [undefined, undefined, undefined]); +delete Boolean.prototype.length; +Boolean.prototype[0] = "monkeys"; +Boolean.prototype[2] = "bogus"; +assert.compareArray(Array.prototype.toSorted.call(true), []); +assert.compareArray(Array.prototype.toSorted.call(false), []); diff --git a/test/built-ins/Array/prototype/toSorted/this-value-nullish.js b/test/built-ins/Array/prototype/toSorted/this-value-nullish.js new file mode 100644 index 0000000000..6be9d4cb4f --- /dev/null +++ b/test/built-ins/Array/prototype/toSorted/this-value-nullish.js @@ -0,0 +1,22 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSorted +description: > + Array.prototype.toSorted throws if the receiver is null or undefined +info: | + Array.prototype.toSorted ( compareFn ) + + 1. Let O be ? ToObject(this value). + ... +features: [change-array-by-copy] +---*/ + +assert.throws(TypeError, () => { + Array.prototype.toSorted.call(null); +}, '`Array.prototype.toSorted.call(null)` throws TypeError'); + +assert.throws(TypeError, () => { + Array.prototype.toSorted.call(undefined); +}, '`Array.prototype.toSorted.call(undefined)` throws TypeError'); diff --git a/test/built-ins/Array/prototype/toSorted/zero-or-one-element.js b/test/built-ins/Array/prototype/toSorted/zero-or-one-element.js new file mode 100644 index 0000000000..a692e118bd --- /dev/null +++ b/test/built-ins/Array/prototype/toSorted/zero-or-one-element.js @@ -0,0 +1,20 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSorted +description: > + Array.prototype.toSorted returns a new array even if it has zero or one elements +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var zero = []; +var zeroReversed = zero.toSorted(); +assert.notSameValue(zero, zeroReversed); +assert.compareArray(zero, zeroReversed); + +var one = [1]; +var oneReversed = one.toSorted(); +assert.notSameValue(one, oneReversed); +assert.compareArray(one, oneReversed); diff --git a/test/built-ins/Array/prototype/toSpliced/deleteCount-clamped-between-zero-and-remaining-count.js b/test/built-ins/Array/prototype/toSpliced/deleteCount-clamped-between-zero-and-remaining-count.js new file mode 100644 index 0000000000..21e2e8ddf3 --- /dev/null +++ b/test/built-ins/Array/prototype/toSpliced/deleteCount-clamped-between-zero-and-remaining-count.js @@ -0,0 +1,37 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSpliced +description: deleteCount is clamped between zero and len - actualStart +info: | + 22.1.3.25 Array.prototype.toSpliced (start, deleteCount , ...items ) + + ... + 10. Else, + a. Let dc be ? ToIntegerOrInfinity(deleteCount). + b. Let actualDeleteCount be the result of clamping dc between 0 and len - actualStart. + ... +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +assert.compareArray( + [0, 1, 2, 3, 4, 5].toSpliced(2, -1), + [0, 1, 2, 3, 4, 5] +); + +assert.compareArray( + [0, 1, 2, 3, 4, 5].toSpliced(-4, -1), + [0, 1, 2, 3, 4, 5] +); + +assert.compareArray( + [0, 1, 2, 3, 4, 5].toSpliced(2, 6), + [0, 1] +); + +assert.compareArray( + [0, 1, 2, 3, 4, 5].toSpliced(-4, 6), + [0, 1] +); diff --git a/test/built-ins/Array/prototype/toSpliced/deleteCount-missing.js b/test/built-ins/Array/prototype/toSpliced/deleteCount-missing.js new file mode 100644 index 0000000000..ffc1589ad6 --- /dev/null +++ b/test/built-ins/Array/prototype/toSpliced/deleteCount-missing.js @@ -0,0 +1,20 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSpliced +description: Array.prototype.toSpliced deletes the elements after start when called with one argument +info: | + 22.1.3.25 Array.prototype.toSpliced (start, deleteCount , ...items ) + + ... + 9. Else if deleteCount is not present, then + a. Let actualDeleteCount be len - actualStart. + ... +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var result = ["first", "second", "third"].toSpliced(1); + +assert.compareArray(result, ["first"]); diff --git a/test/built-ins/Array/prototype/toSpliced/deleteCount-undefined.js b/test/built-ins/Array/prototype/toSpliced/deleteCount-undefined.js new file mode 100644 index 0000000000..b777389248 --- /dev/null +++ b/test/built-ins/Array/prototype/toSpliced/deleteCount-undefined.js @@ -0,0 +1,29 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSpliced +description: Array.prototype.toSpliced(number, undefined) returns a copy of the original array +info: | + 22.1.3.25 Array.prototype.toSpliced (start, deleteCount , ...items ) + + ... + 3. Let relativeStart be ? ToIntegerOrInfinity(start). + ... + 6. Else, let actualStart be min(relativeStart, len). + ... + 8. If start is not present, then + a. Let actualDeleteCount be 0. + 9. Else if deleteCount is not present, then + a. Let actualDeleteCount be len - actualStart. + 10. Else, + a. Let dc be ? ToIntegerOrInfinity(deleteCount). + b. Let actualDeleteCount be the result of clamping dc between 0 and len - actualStart. + ... +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var result = ["first", "second", "third"].toSpliced(1, undefined); + +assert.compareArray(result, ["first", "second", "third"]); diff --git a/test/built-ins/Array/prototype/toSpliced/discarded-element-not-read.js b/test/built-ins/Array/prototype/toSpliced/discarded-element-not-read.js new file mode 100644 index 0000000000..2b31e96cd1 --- /dev/null +++ b/test/built-ins/Array/prototype/toSpliced/discarded-element-not-read.js @@ -0,0 +1,52 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSpliced +description: Array.prototype.toSpliced does not Get the discarded elements in the original array +info: | + 22.1.3.25 Array.prototype.toSpliced (start, deleteCount , ...items ) + + ... + 3. Let relativeStart be ? ToIntegerOrInfinity(start). + ... + 6. Else, let actualStart be min(relativeStart, len). + ... + 8. If start is not present, then + a. Let actualDeleteCount be 0. + 9. Else if deleteCount is not present, then + a. Let actualDeleteCount be len - actualStart. + 10. Else, + a. Let dc be ? ToIntegerOrInfinity(deleteCount). + b. Let actualDeleteCount be the result of clamping dc between 0 and len - actualStart. + 11. Let newLen be len + insertCount - actualDeleteCount. + ... + 15. Let r be actualStart + actualDeleteCount. + ... + 18. Repeat, while i < newLen, + a. Let Pi be ! ToString(𝔽(i)). + b. Let from be ! ToString(𝔽(r)). + c. Let fromValue be ? Get(O, from). + d. Perform ! CreateDataPropertyOrThrow(A, Pi, fromValue). + e. Set i to i + 1. + f. Set r to r + 1. + +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var arrayLike = { + 0: "a", + 1: "b", + get 2() { throw new Test262Error(); }, + 3: "c", + length: 4, +}; + +/* + * In this example, just before step 18, i == 2 and r == 3. + * So A[2] is set to arrayLike[3] and arrayLike[2] is never read + * (since i and r both increase monotonically). + */ +var result = Array.prototype.toSpliced.call(arrayLike, 2, 1); +assert.compareArray(result, ["a", "b", "c"]); diff --git a/test/built-ins/Array/prototype/toSpliced/elements-read-in-order.js b/test/built-ins/Array/prototype/toSpliced/elements-read-in-order.js new file mode 100644 index 0000000000..9f2d96291d --- /dev/null +++ b/test/built-ins/Array/prototype/toSpliced/elements-read-in-order.js @@ -0,0 +1,59 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSpliced +description: Array.prototype.toSpliced reads the items of the original array in order +info: | + 22.1.3.25 Array.prototype.toSpliced (start, deleteCount , ...items ) + + ... + 14. Let i be 0. + 15. Let r be actualStart + actualDeleteCount. + 16. Repeat, while i < actualStart, + a. Let Pi be ! ToString(𝔽(i)). + b. Let iValue be ? Get(O, Pi). + c. Perform ! CreateDataPropertyOrThrow(A, Pi, iValue). + d. Set i to i + 1. + 17. For each element E of items, do + a. Let Pi be ! ToString(𝔽(i)). + b. Perform ! CreateDataPropertyOrThrow(A, Pi, E). + c. Set i to i + 1. + 18. Repeat, while i < newLen, + a. Let Pi be ! ToString(𝔽(i)). + b. Let from be ! ToString(𝔽(r)). + c. Let fromValue be ? Get(O, from). + d. Perform ! CreateDataPropertyOrThrow(A, Pi, fromValue). + e. Set i to i + 1. + f. Set r to r + 1. + ... + +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var order = []; + +var arrayLike = { + get 0() { order.push(0); return "a" }, + get 1() { order.push(1); return "b" }, + 2: "none", + get 3() { order.push(3); return "c" }, + length: 4, +}; + +var result = Array.prototype.toSpliced.call(arrayLike, 2, 1); +assert.compareArray(result, ["a", "b", "c"]); + +assert.compareArray(order, [0, 1, 3]); + +order = []; +var arr = [0, 1, "none", 3]; +Object.defineProperty(arr, 0, { get: function() { order.push(0); return "a" } }); +Object.defineProperty(arr, 1, { get: function() { order.push(1); return "b" } }); +Object.defineProperty(arr, 3, { get: function() { order.push(3); return "c" } }); + +result = Array.prototype.toSpliced.call(arr, 2, 1); +assert.compareArray(result, ["a", "b", "c"]); + +assert.compareArray(order, [0, 1, 3]); diff --git a/test/built-ins/Array/prototype/toSpliced/frozen-this-value.js b/test/built-ins/Array/prototype/toSpliced/frozen-this-value.js new file mode 100644 index 0000000000..54e421cc77 --- /dev/null +++ b/test/built-ins/Array/prototype/toSpliced/frozen-this-value.js @@ -0,0 +1,18 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSpliced +description: > + Array.prototype.toSpliced works on frozen objects +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var arr = Object.freeze([2, 0, 1]); +var result = arr.toSpliced(); +assert.compareArray(result, [2, 0, 1]); + +var arrayLike = Object.freeze({ length: 3, 0: 0, 1: 1, 2: 2 }); + +assert.compareArray(Array.prototype.toSpliced.call(arrayLike, 1, 1, 4, 5), [0, 4, 5, 2]); diff --git a/test/built-ins/Array/prototype/toSpliced/holes-not-preserved.js b/test/built-ins/Array/prototype/toSpliced/holes-not-preserved.js new file mode 100644 index 0000000000..8299c96e24 --- /dev/null +++ b/test/built-ins/Array/prototype/toSpliced/holes-not-preserved.js @@ -0,0 +1,41 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSpliced +description: > + Array.prototype.toSpliced does not preserve holes in the array +info: | + Array.prototype.toSpliced ( start, deleteCount, ...items ) + + ... + 13. Let k be 0. + 14. Repeat, while k < actualStart, + a. Let Pk be ! ToString(𝔽(k)). + b. Let kValue be ? Get(O, Pk). + c. Perform ? CreateDataPropertyOrThrow(A, Pk, kValue). + d. Set k to k + 1. + ... + 16. Repeat, while k < newLen, + a. Let Pk be ! ToString(𝔽(k)). + b. Let from be ! ToString(𝔽(k + actualDeleteCount - insertCount)). + c. Let fromValue be ? Get(O, from). + d. Perform ? CreateDataPropertyOrThrow(A, Pk, fromValue). + e. Set k to k + 1. + ... +includes: [compareArray.js] +features: [change-array-by-copy] +---*/ + +var arr = [0, /* hole */, 2, /* hole */, 4]; +Array.prototype[3] = 3; + +var spliced = arr.toSpliced(0, 0); +assert.compareArray(spliced, [0, undefined, 2, 3, 4]); +assert(spliced.hasOwnProperty(1)); +assert(spliced.hasOwnProperty(3)); + +spliced = arr.toSpliced(0, 0, -1); +assert.compareArray(spliced, [-1, 0, undefined, 2, 3, 4]); +assert(spliced.hasOwnProperty(1)); +assert(spliced.hasOwnProperty(3)); diff --git a/test/built-ins/Array/prototype/toSpliced/ignores-species.js b/test/built-ins/Array/prototype/toSpliced/ignores-species.js new file mode 100644 index 0000000000..b667a01c98 --- /dev/null +++ b/test/built-ins/Array/prototype/toSpliced/ignores-species.js @@ -0,0 +1,30 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSpliced +description: > + Array.prototype.toSpliced ignores @@species +info: | + Array.prototype.toSpliced ( start, deleteCount, ...items ) + + ... + 12. Let A be ? ArrayCreate(𝔽(newLen)). + ... +features: [change-array-by-copy] +---*/ + +var a = []; +a.constructor = {}; +a.constructor[Symbol.species] = function () {} + +assert.sameValue(Object.getPrototypeOf(a.toSpliced(0, 0)), Array.prototype); + +var b = []; +Object.defineProperty(b, "constructor", { + get() { + throw new Test262Error("Should not get .constructor"); + } +}); + +b.toSpliced(0, 0); diff --git a/test/built-ins/Array/prototype/toSpliced/immutable.js b/test/built-ins/Array/prototype/toSpliced/immutable.js new file mode 100644 index 0000000000..e43654b0d5 --- /dev/null +++ b/test/built-ins/Array/prototype/toSpliced/immutable.js @@ -0,0 +1,17 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSpliced +description: > + Array.prototype.toSpliced does not mutate its this value +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var arr = [2, 0, 1]; +arr.toSpliced(0, 0, -1); + +assert.compareArray(arr, [2, 0, 1]); +assert.notSameValue(arr.toSpliced(0, 0, -1), arr); +assert.notSameValue(arr.toSpliced(0, 1, -1), arr); diff --git a/test/built-ins/Array/prototype/toSpliced/length-casted-to-zero.js b/test/built-ins/Array/prototype/toSpliced/length-casted-to-zero.js new file mode 100644 index 0000000000..8bb470d556 --- /dev/null +++ b/test/built-ins/Array/prototype/toSpliced/length-casted-to-zero.js @@ -0,0 +1,21 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSpliced +description: > + Array.prototype.toSpliced treats its `this` value's `length` property as zero if the + property's value is not a positive integer. +info: | + Array.prototype.toSpliced ( start, deleteCount, ...items ) + + ... + 2. Let len be ? LengthOfArrayLike(O). + ... +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +assert.compareArray(Array.prototype.toSpliced.call({ length: -2 }, 0, 0, 2, 3), [2, 3]); +assert.compareArray(Array.prototype.toSpliced.call({ length: "dog" }, 0, 0, 2, 3), [2, 3]); +assert.compareArray(Array.prototype.toSpliced.call({ length: NaN }, 0, 0, 2, 3), [2, 3]); diff --git a/test/built-ins/Array/prototype/toSpliced/length-clamped-to-2pow53minus1.js b/test/built-ins/Array/prototype/toSpliced/length-clamped-to-2pow53minus1.js new file mode 100644 index 0000000000..5938e729be --- /dev/null +++ b/test/built-ins/Array/prototype/toSpliced/length-clamped-to-2pow53minus1.js @@ -0,0 +1,34 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSpliced +description: > + Length is clamped to 2^53-1 when they exceed the integer limit. +info: | + ... + 2. Let len be ? LengthOfArrayLike(O). + ... + + ToLength ( argument ) + + 1. Let len be ? ToIntegerOrInfinity(argument). + 2. If len ≤ 0, return +0𝔽. + 3. Return 𝔽(min(len, 2^53 - 1)) +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var arrayLike = { + "9007199254740989": 2 ** 53 - 3, + "9007199254740990": 2 ** 53 - 2, + "9007199254740991": 2 ** 53 - 1, + "9007199254740992": 2 ** 53, + "9007199254740994": 2 ** 53 + 2, // NOTE: 2 ** 53 + 1 is 2 ** 53 + length: 2 ** 53 + 20, +}; + +var result = Array.prototype.toSpliced.call(arrayLike, 0, 2 ** 53 - 3); + +assert.sameValue(result.length, 2); +assert.compareArray(result, [2 ** 53 - 3, 2 ** 53 - 2]); diff --git a/test/built-ins/Array/prototype/toSpliced/length-decreased-while-iterating.js b/test/built-ins/Array/prototype/toSpliced/length-decreased-while-iterating.js new file mode 100644 index 0000000000..35b2c1740f --- /dev/null +++ b/test/built-ins/Array/prototype/toSpliced/length-decreased-while-iterating.js @@ -0,0 +1,44 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSpliced +description: > + Array.prototype.toSpliced caches the length getting the array elements. +info: | + Array.prototype.toSpliced ( start, deleteCount, ...items ) + + ... + 2. Let len be ? LengthOfArrayLike(O). + ... + 11. Let newLen be len + insertCount - actualDeleteCount. + ... + 13. Let k be 0. + 14. Repeat, while k < actualStart, + a. Let Pk be ! ToString(𝔽(k)). + b. Let kValue be ? Get(O, Pk). + c. Perform ? CreateDataPropertyOrThrow(A, Pk, kValue). + d. Set k to k + 1. + ... + 16. Repeat, while k < newLen, + a. Let Pk be ! ToString(𝔽(k)). + b. Let from be ! ToString(𝔽(k + actualDeleteCount - insertCount)). + c. Let fromValue be ? Get(O, from). + d. Perform ? CreateDataPropertyOrThrow(A, Pk, fromValue). + e. Set k to k + 1. + ... +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var arr = [0, 1, 2, 3, 4, 5]; +Array.prototype[3] = 6; + +Object.defineProperty(arr, "2", { + get() { + arr.length = 1; + return 2; + } +}); + +assert.compareArray(arr.toSpliced(0, 0), [0, 1, 2, 6, undefined, undefined]); diff --git a/test/built-ins/Array/prototype/toSpliced/length-exceeding-array-length-limit.js b/test/built-ins/Array/prototype/toSpliced/length-exceeding-array-length-limit.js new file mode 100644 index 0000000000..ddd2a4dce2 --- /dev/null +++ b/test/built-ins/Array/prototype/toSpliced/length-exceeding-array-length-limit.js @@ -0,0 +1,76 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSpliced +description: > + Array.prototype.toSpliced limits the length to 2 ** 32 - 1 +info: | + Array.prototype.toSpliced ( start, deleteCount, ...items ) + + ... + 3. Let len be ? LengthOfArrayLike(O). + ... + 11. Let newLen be len + insertCount - actualDeleteCount. + 12. If _newLen_ > 2 ** 53< - 1, throw a *TypeError* exception. + 13. Let A be ? ArrayCreate(𝔽(newLen)). + ... + + ArrayCreate ( length [, proto ] ) + + 1. If length > 2 ** 32 - 1, throw a RangeError exception. +features: [change-array-by-copy] +---*/ + +// Object with large "length" property +var arrayLike = { + get "0"() { + throw new Test262Error("Get 0"); + }, + get "4294967295" () { // 2 ** 32 - 1 + throw new Test262Error("Get 4294967295"); + }, + get "4294967296" () { // 2 ** 32 + throw new Test262Error("Get 4294967296"); + }, + length: 2 ** 32 +}; + +assert.throws(RangeError, function() { + Array.prototype.toSpliced.call(arrayLike, 0, 0); +}); + +arrayLike.length = 2 ** 32 - 1; +assert.throws(RangeError, function() { + Array.prototype.toSpliced.call(arrayLike, 0, 0, 1); +}); + +arrayLike.length = 2 ** 32; +assert.throws(RangeError, function() { + Array.prototype.toSpliced.call(arrayLike, 0, 0, 1); +}); + +arrayLike.length = 2 ** 32 + 1; +assert.throws(RangeError, function() { + Array.prototype.toSpliced.call(arrayLike, 0, 0, 1); +}); + +arrayLike.length = 2 ** 52 - 2; +assert.throws(RangeError, function() { + Array.prototype.toSpliced.call(arrayLike, 0, 0, 1); +}); + +arrayLike.length = 2 ** 53 - 1; +assert.throws(TypeError, function() { + Array.prototype.toSpliced.call(arrayLike, 0, 0, 1); +}); + +arrayLike.length = 2 ** 53; +assert.throws(TypeError, function() { + Array.prototype.toSpliced.call(arrayLike, 0, 0, 1); +}); + +arrayLike.length = 2 ** 53 + 1; +assert.throws(TypeError, function() { + Array.prototype.toSpliced.call(arrayLike, 0, 0, 1); +}); diff --git a/test/built-ins/Array/prototype/toSpliced/length-increased-while-iterating.js b/test/built-ins/Array/prototype/toSpliced/length-increased-while-iterating.js new file mode 100644 index 0000000000..836be9e6ba --- /dev/null +++ b/test/built-ins/Array/prototype/toSpliced/length-increased-while-iterating.js @@ -0,0 +1,37 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSpliced +description: > + Array.prototype.toSpliced caches the length getting the array elements. +info: | + Array.prototype.toSpliced ( start, deleteCount, ...items ) + + ... + 3. Let len be ? LengthOfArrayLike(O). + ... + 5. Let k be 0. + 6. Repeat, while k < len, + a. Let Pk be ! ToString(𝔽(k)). + b. Let kValue be ? Get(O, Pk). + ... +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var arr = [0, 1, 2]; +Object.defineProperty(arr, "0", { + get() { + arr.push(10); + return 0; + } +}); +Object.defineProperty(arr, "2", { + get() { + arr.push(11); + return 2; + } +}); + +assert.compareArray(arr.toSpliced(1, 0, 0.5), [0, 0.5, 1, 2]); diff --git a/test/built-ins/Array/prototype/toSpliced/length-tolength.js b/test/built-ins/Array/prototype/toSpliced/length-tolength.js new file mode 100644 index 0000000000..b8652a445d --- /dev/null +++ b/test/built-ins/Array/prototype/toSpliced/length-tolength.js @@ -0,0 +1,29 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSpliced +description: > + Array.prototype.toSpliced converts the this value length to a number. +info: | + Array.prototype.toSpliced ( start, deleteCount, ...items ) + + ... + 2. Let len be ? LengthOfArrayLike(O). + ... +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +assert.compareArray(Array.prototype.toSpliced.call({ length: "2", 0: 0, 1: 1, 2: 2 }, 0, 0), [0, 1]); + +var arrayLike = { + length: { + valueOf: () => 2 + }, + 0: 0, + 1: 1, + 2: 2, +}; + +assert.compareArray(Array.prototype.toSpliced.call(arrayLike, 0, 0), [0, 1]); diff --git a/test/built-ins/Array/prototype/toSpliced/metadata/length.js b/test/built-ins/Array/prototype/toSpliced/metadata/length.js new file mode 100644 index 0000000000..fe4c1621b8 --- /dev/null +++ b/test/built-ins/Array/prototype/toSpliced/metadata/length.js @@ -0,0 +1,30 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSpliced +description: > + The "length" property of Array.prototype.toSpliced +info: | + 17 ECMAScript Standard Built-in Objects + + Every built-in function object, including constructors, has a length property + whose value is an integer. Unless otherwise specified, this value is equal to + the largest number of named arguments shown in the subclause headings for the + function description. Optional parameters (which are indicated with brackets: + [ ]) or rest parameters (which are shown using the form «...name») are not + included in the default argument count. + + Unless otherwise specified, the length property of a built-in function object + has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [change-array-by-copy] +---*/ + +verifyProperty(Array.prototype.toSpliced, "length", { + value: 2, + writable: false, + enumerable: false, + configurable: true, +}); diff --git a/test/built-ins/Array/prototype/toSpliced/metadata/name.js b/test/built-ins/Array/prototype/toSpliced/metadata/name.js new file mode 100644 index 0000000000..9bcf1c3b1e --- /dev/null +++ b/test/built-ins/Array/prototype/toSpliced/metadata/name.js @@ -0,0 +1,28 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSpliced +description: > + Array.prototype.toSpliced.name is "toSpliced". +info: | + Array.prototype.toSpliced ( start, deleteCount, ...items ) + + 17 ECMAScript Standard Built-in Objects: + Every built-in Function object, including constructors, that is not + identified as an anonymous function has a name property whose value + is a String. + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [change-array-by-copy] +---*/ + +verifyProperty(Array.prototype.toSpliced, "name", { + value: "toSpliced", + writable: false, + enumerable: false, + configurable: true, +}); diff --git a/test/built-ins/Array/prototype/toSpliced/metadata/property-descriptor.js b/test/built-ins/Array/prototype/toSpliced/metadata/property-descriptor.js new file mode 100644 index 0000000000..b5eb9316c5 --- /dev/null +++ b/test/built-ins/Array/prototype/toSpliced/metadata/property-descriptor.js @@ -0,0 +1,25 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSpliced +description: > + "toSpliced" property of Array.prototype +info: | + 17 ECMAScript Standard Built-in Objects + + Every other data property described in clauses 18 through 26 and in Annex B.2 + has the attributes { [[Writable]]: true, [[Enumerable]]: false, + [[Configurable]]: true } unless otherwise specified. +includes: [propertyHelper.js] +features: [change-array-by-copy] +---*/ + +assert.sameValue(typeof Array.prototype.toSpliced, "function", "typeof"); + +verifyProperty(Array.prototype, "toSpliced", { + value: Array.prototype.toSpliced, + writable: true, + enumerable: false, + configurable: true, +}); diff --git a/test/built-ins/Array/prototype/toSpliced/mutate-while-iterating.js b/test/built-ins/Array/prototype/toSpliced/mutate-while-iterating.js new file mode 100644 index 0000000000..7513ff2e50 --- /dev/null +++ b/test/built-ins/Array/prototype/toSpliced/mutate-while-iterating.js @@ -0,0 +1,46 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSpliced +description: > + Array.prototype.toSpliced gets array elements one at a time. +info: | + Array.prototype.toSpliced ( start, deleteCount, ...items ) + + ... + 16. Repeat, while i < actualStart, + a. Let Pi be ! ToString(𝔽(i)). + b. Let iValue be ? Get(O, Pi). + c. Perform ! CreateDataPropertyOrThrow(A, Pi, iValue). + d. Set i to i + 1. + ... + 18. Repeat, while i < newLen, + a. Let Pi be ! ToString(𝔽(i)). + b. Let from be ! ToString(𝔽(r)). + c. Let fromValue be ? Get(O, from). + d. Perform ! CreateDataPropertyOrThrow(A, Pi, fromValue). + e. Set i to i + 1. + f. Set r to r + 1. + ... + +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var arr = [0, 1, 2, 3]; +Object.defineProperty(arr, "0", { + get() { + arr[1] = 42; + return 0; + } +}); +Object.defineProperty(arr, "2", { + get() { + arr[0] = 17; + arr[3] = 37; + return 2; + } +}); + +assert.compareArray(arr.toSpliced(1, 0, 0.5), [0, 0.5, 42, 2, 37]); diff --git a/test/built-ins/Array/prototype/toSpliced/not-a-constructor.js b/test/built-ins/Array/prototype/toSpliced/not-a-constructor.js new file mode 100644 index 0000000000..b702fa27e3 --- /dev/null +++ b/test/built-ins/Array/prototype/toSpliced/not-a-constructor.js @@ -0,0 +1,32 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + Array.prototype.toSpliced does not implement [[Construct]], is not new-able +info: | + ECMAScript Function Objects + + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified in + the description of a particular function. + + sec-evaluatenew + + ... + 7. If IsConstructor(constructor) is false, throw a TypeError exception. + ... +includes: [isConstructor.js] +features: [change-array-by-copy, Reflect.construct] +---*/ + +assert.sameValue( + isConstructor(Array.prototype.toSpliced), + false, + 'isConstructor(Array.prototype.toSpliced) must return false' +); + +assert.throws(TypeError, () => { + new Array.prototype.toSpliced(); +}, '`new Array.prototype.toSpliced()` throws TypeError'); diff --git a/test/built-ins/Array/prototype/toSpliced/start-and-deleteCount-missing.js b/test/built-ins/Array/prototype/toSpliced/start-and-deleteCount-missing.js new file mode 100644 index 0000000000..bfc5825dca --- /dev/null +++ b/test/built-ins/Array/prototype/toSpliced/start-and-deleteCount-missing.js @@ -0,0 +1,27 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSpliced +description: Array.prototype.toSpliced returns a copy of the array if called with zero arguments +info: | + 22.1.3.25 Array.prototype.toSpliced (start, deleteCount , ...items ) + + ... + 3. Let relativeStart be ? ToIntegerOrInfinity(start). + ... + 6. Else, let actualStart be min(relativeStart, len). + ... + 8. If start is not present, then + a. Let actualDeleteCount be 0. + ... +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +let arr = ["first", "second", "third"]; +let result = arr.toSpliced(); + +assert.compareArray(result, arr); +assert.notSameValue(result, arr); + diff --git a/test/built-ins/Array/prototype/toSpliced/start-and-deleteCount-undefineds.js b/test/built-ins/Array/prototype/toSpliced/start-and-deleteCount-undefineds.js new file mode 100644 index 0000000000..0f755fadb3 --- /dev/null +++ b/test/built-ins/Array/prototype/toSpliced/start-and-deleteCount-undefineds.js @@ -0,0 +1,29 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSpliced +description: Array.prototype.toSpliced(undefined, undefined) returns a copy of the original array +info: | + 22.1.3.25 Array.prototype.toSpliced (start, deleteCount , ...items ) + + ... + 3. Let relativeStart be ? ToIntegerOrInfinity(start). + ... + 6. Else, let actualStart be min(relativeStart, len). + ... + 8. If start is not present, then + a. Let actualDeleteCount be 0. + 8. Else if deleteCount is not present, then + a. Let actualDeleteCount be len - actualStart. + ... +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +let arr = ["first", "second", "third"]; +let result = arr.toSpliced(undefined, undefined); + +assert.compareArray(result, arr); +assert.notSameValue(result, arr); + diff --git a/test/built-ins/Array/prototype/toSpliced/start-bigger-than-length.js b/test/built-ins/Array/prototype/toSpliced/start-bigger-than-length.js new file mode 100644 index 0000000000..77917ef510 --- /dev/null +++ b/test/built-ins/Array/prototype/toSpliced/start-bigger-than-length.js @@ -0,0 +1,23 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSpliced +description: > + Array.prototype.toSpliced clamps the start argument to the this value length. +info: | + Array.prototype.toSpliced ( start, deleteCount, ...items ) + + ... + 2. Let len be ? LengthOfArrayLike(O). + 3. Let relativeStart be ? ToIntegerOrInfinity(start). + 4. If relativeStart is -∞, let actualStart be 0. + 5. Else if relativeStart < 0, let actualStart be max(len + relativeStart, 0). + 6. Else, let actualStart be min(relativeStart, len). + ... +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var result = [0, 1, 2, 3, 4].toSpliced(10, 1, 5, 6); +assert.compareArray(result, [0, 1, 2, 3, 4, 5, 6]); diff --git a/test/built-ins/Array/prototype/toSpliced/start-neg-infinity-is-zero.js b/test/built-ins/Array/prototype/toSpliced/start-neg-infinity-is-zero.js new file mode 100644 index 0000000000..fd3240624f --- /dev/null +++ b/test/built-ins/Array/prototype/toSpliced/start-neg-infinity-is-zero.js @@ -0,0 +1,22 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSpliced +description: > + Array.prototype.toSpliced treats negative Infinity as zero for start. +info: | + Array.prototype.toSpliced ( start, deleteCount, ...items ) + + ... + 2. Let len be ? LengthOfArrayLike(O). + 3. Let relativeStart be ? ToIntegerOrInfinity(start). + 4. If relativeStart is -∞, let actualStart be 0. + 5. Else if relativeStart < 0, let actualStart be max(len + relativeStart, 0). + ... +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var result = [0, 1, 2, 3, 4].toSpliced(-Infinity, 2); +assert.compareArray(result, [2, 3, 4]); diff --git a/test/built-ins/Array/prototype/toSpliced/start-neg-less-than-minus-length-is-zero.js b/test/built-ins/Array/prototype/toSpliced/start-neg-less-than-minus-length-is-zero.js new file mode 100644 index 0000000000..554090eb36 --- /dev/null +++ b/test/built-ins/Array/prototype/toSpliced/start-neg-less-than-minus-length-is-zero.js @@ -0,0 +1,22 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSpliced +description: > + Array.prototype.toSpliced treats a value smaller than -length as zero for start. +info: | + Array.prototype.toSpliced ( start, deleteCount, ...items ) + + ... + 2. Let len be ? LengthOfArrayLike(O). + 3. Let relativeStart be ? ToIntegerOrInfinity(start). + 4. If relativeStart is -∞, let actualStart be 0. + 5. Else if relativeStart < 0, let actualStart be max(len + relativeStart, 0). + ... +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var result = [0, 1, 2, 3, 4].toSpliced(-20, 2); +assert.compareArray(result, [2, 3, 4]); diff --git a/test/built-ins/Array/prototype/toSpliced/start-neg-subtracted-from-length.js b/test/built-ins/Array/prototype/toSpliced/start-neg-subtracted-from-length.js new file mode 100644 index 0000000000..8b631fd470 --- /dev/null +++ b/test/built-ins/Array/prototype/toSpliced/start-neg-subtracted-from-length.js @@ -0,0 +1,22 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSpliced +description: > + Array.prototype.toSpliced treats a negative start as relative to the end. +info: | + Array.prototype.toSpliced ( start, deleteCount, ...items ) + + ... + 2. Let len be ? LengthOfArrayLike(O). + 3. Let relativeStart be ? ToIntegerOrInfinity(start). + 4. If relativeStart is -∞, let actualStart be 0. + 5. Else if relativeStart < 0, let actualStart be max(len + relativeStart, 0). + ... +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var result = [0, 1, 2, 3, 4].toSpliced(-3, 2); +assert.compareArray(result, [0, 1, 4]); diff --git a/test/built-ins/Array/prototype/toSpliced/start-undefined-and-deleteCount-missing.js b/test/built-ins/Array/prototype/toSpliced/start-undefined-and-deleteCount-missing.js new file mode 100644 index 0000000000..e447845493 --- /dev/null +++ b/test/built-ins/Array/prototype/toSpliced/start-undefined-and-deleteCount-missing.js @@ -0,0 +1,26 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSpliced +description: Array.prototype.toSpliced(undefined) returns an empty array +info: | + 22.1.3.25 Array.prototype.toSpliced (start, deleteCount , ...items ) + + ... + 3. Let relativeStart be ? ToIntegerOrInfinity(start). + ... + 6. Else, let actualStart be min(relativeStart, len). + ... + 8. If start is not present, then + a. Let actualDeleteCount be 0. + 8. Else if deleteCount is not present, then + a. Let actualDeleteCount be len - actualStart. + ... +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var result = ["first", "second", "third"].toSpliced(undefined); + +assert.compareArray(result, []); diff --git a/test/built-ins/Array/prototype/toSpliced/this-value-boolean.js b/test/built-ins/Array/prototype/toSpliced/this-value-boolean.js new file mode 100644 index 0000000000..fd00b3098d --- /dev/null +++ b/test/built-ins/Array/prototype/toSpliced/this-value-boolean.js @@ -0,0 +1,29 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSpliced +description: > + Array.prototype.toSpliced converts booleans to objects +info: | + Array.prototype.toSpliced ( start, deleteCount, ...items ) + + 1. Let O be ? ToObject(this value). + 2. Let len be ? LengthOfArrayLike(O). + ... +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +assert.compareArray(Array.prototype.toSpliced.call(true, 0, 0), []); +assert.compareArray(Array.prototype.toSpliced.call(false, 0, 0), []); + +/* Add length and indexed properties to `Boolean.prototype` */ +Boolean.prototype.length = 3; +assert.compareArray(Array.prototype.toSpliced.call(true, 0, 0), [undefined, undefined, undefined]); +assert.compareArray(Array.prototype.toSpliced.call(false, 0, 0), [undefined, undefined, undefined]); +delete Boolean.prototype.length; +Boolean.prototype[0] = "monkeys"; +Boolean.prototype[2] = "bogus"; +assert.compareArray(Array.prototype.toSpliced.call(true, 0, 0), []); +assert.compareArray(Array.prototype.toSpliced.call(false, 0, 0), []); diff --git a/test/built-ins/Array/prototype/toSpliced/this-value-nullish.js b/test/built-ins/Array/prototype/toSpliced/this-value-nullish.js new file mode 100644 index 0000000000..fa32e40948 --- /dev/null +++ b/test/built-ins/Array/prototype/toSpliced/this-value-nullish.js @@ -0,0 +1,22 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSpliced +description: > + Array.prototype.toSpliced throws if the receiver is null or undefined +info: | + Array.prototype.toSpliced ( start, deleteCount, ...items ) + + 1. Let O be ? ToObject(this value). + ... +features: [change-array-by-copy] +---*/ + +assert.throws(TypeError, () => { + Array.prototype.toSpliced.call(null, 0, 0); +}, '`Array.prototype.toSpliced.call(null)` throws TypeError'); + +assert.throws(TypeError, () => { + Array.prototype.toSpliced.call(undefined, 0, 0); +}, '`Array.prototype.toSpliced.call(undefined)` throws TypeError'); diff --git a/test/built-ins/Array/prototype/toSpliced/unmodified.js b/test/built-ins/Array/prototype/toSpliced/unmodified.js new file mode 100644 index 0000000000..bce38b68e9 --- /dev/null +++ b/test/built-ins/Array/prototype/toSpliced/unmodified.js @@ -0,0 +1,15 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.toSpliced +description: > + Array.prototype.toSpliced returns a new array even if it the result is equal to the original array +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var arr = [1, 2, 3]; +var spliced = arr.toSpliced(1, 0); +assert.notSameValue(arr, spliced); +assert.compareArray(arr, spliced); diff --git a/test/built-ins/Array/prototype/with/frozen-this-value.js b/test/built-ins/Array/prototype/with/frozen-this-value.js new file mode 100644 index 0000000000..3578de7fba --- /dev/null +++ b/test/built-ins/Array/prototype/with/frozen-this-value.js @@ -0,0 +1,18 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.with +description: > + Array.prototype.with works on frozen objects +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var arr = Object.freeze([0, 1, 2]); +var result = arr.with(1, 3); +assert.compareArray(result, [0, 3, 2]); + +var arrayLike = Object.freeze({ length: 3, 0: 0, 1: 1, 2: 2 }); +var result2 = Array.prototype.with.call(arrayLike, 1, 3); +assert.compareArray(result2, [0, 3, 2]); diff --git a/test/built-ins/Array/prototype/with/holes-not-preserved.js b/test/built-ins/Array/prototype/with/holes-not-preserved.js new file mode 100644 index 0000000000..3d3a260cae --- /dev/null +++ b/test/built-ins/Array/prototype/with/holes-not-preserved.js @@ -0,0 +1,30 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.with +description: > + Array.prototype.with does not preserve holes in the array +info: | + Array.prototype.with ( ) + + ... + 2. Let len be ? LengthOfArrayLike(O). + ... + 5. Repeat, while k < len + a. Let Pk be ! ToString(𝔽(k)). + b. If k is actualIndex, let fromValue be value. + c. Else, let fromValue be ? Get(O, Pk). + d. Perform ? CreateDataPropertyOrThrow(A, Pk, fromValue). + e. Set k to k + 1. +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var arr = [0, /* hole */, 2, /* hole */, 4]; +Array.prototype[3] = 3; + +var result = arr.with(2, 6); +assert.compareArray(result, [0, undefined, 6, 3, 4]); +assert(result.hasOwnProperty(1)); +assert(result.hasOwnProperty(3)); diff --git a/test/built-ins/Array/prototype/with/ignores-species.js b/test/built-ins/Array/prototype/with/ignores-species.js new file mode 100644 index 0000000000..b69290c030 --- /dev/null +++ b/test/built-ins/Array/prototype/with/ignores-species.js @@ -0,0 +1,30 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.with +description: > + Array.prototype.with ignores @@species +info: | + Array.prototype.with ( ) + + ... + 8. Let A be ? ArrayCreate(𝔽(len)). + ... +features: [change-array-by-copy] +---*/ + +var a = [1, 2, 3]; +a.constructor = {}; +a.constructor[Symbol.species] = function () {} + +assert.sameValue(Object.getPrototypeOf(a.with(0, 0)), Array.prototype); + +var b = [1, 2, 3]; +Object.defineProperty(b, "constructor", { + get() { + throw new Test262Error("Should not get .constructor"); + } +}); + +b.with(0, 0); diff --git a/test/built-ins/Array/prototype/with/immutable.js b/test/built-ins/Array/prototype/with/immutable.js new file mode 100644 index 0000000000..b1dae8e3c1 --- /dev/null +++ b/test/built-ins/Array/prototype/with/immutable.js @@ -0,0 +1,17 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.with +description: > + Array.prototype.with does not mutate its this value +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var arr = [0, 1, 2]; +arr.with(1, 3); + +assert.compareArray(arr, [0, 1, 2]); +assert.notSameValue(arr.with(1, 3), arr); +assert.notSameValue(arr.with(1, 1), arr); diff --git a/test/built-ins/Array/prototype/with/index-bigger-or-eq-than-length.js b/test/built-ins/Array/prototype/with/index-bigger-or-eq-than-length.js new file mode 100644 index 0000000000..932f0861b6 --- /dev/null +++ b/test/built-ins/Array/prototype/with/index-bigger-or-eq-than-length.js @@ -0,0 +1,35 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.with +description: > + Array.prototype.with throws if the index is bigger than or equal to the array length. +info: | + Array.prototype.with ( index, value ) + + ... + 2. Let len be ? LengthOfArrayLike(O). + 3. Let relativeIndex be ? ToIntegerOrInfinity(index). + 4. If index >= 0, let actualIndex be relativeIndex. + 5. Else, let actualIndex be len + relativeIndex. + 6. If actualIndex >= len or actualIndex < 0, throw a *RangeError* exception. + ... +features: [change-array-by-copy] +---*/ + +assert.throws(RangeError, function() { + [0, 1, 2].with(3, 7); +}); + +assert.throws(RangeError, function() { + [0, 1, 2].with(10, 7); +}); + +assert.throws(RangeError, function() { + [0, 1, 2].with(2 ** 53 + 2, 7); +}); + +assert.throws(RangeError, function() { + [0, 1, 2].with(Infinity, 7); +}); diff --git a/test/built-ins/Array/prototype/with/index-casted-to-number.js b/test/built-ins/Array/prototype/with/index-casted-to-number.js new file mode 100644 index 0000000000..b09da4bf17 --- /dev/null +++ b/test/built-ins/Array/prototype/with/index-casted-to-number.js @@ -0,0 +1,27 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.with +description: > + Array.prototype.with casts the index to an integer. +info: | + Array.prototype.with ( index, value ) + + ... + 2. Let len be ? LengthOfArrayLike(O). + 3. Let relativeIndex be ? ToIntegerOrInfinity(index). + 4. If index >= 0, let actualIndex be relativeIndex. + 5. Else, let actualIndex be len + relativeIndex. + ... +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var arr = [0, 4, 16]; + +assert.compareArray(arr.with(1.2, 7), [0, 7, 16]); +assert.compareArray(arr.with("1", 3), [0, 3, 16]); +assert.compareArray(arr.with("-1", 5), [0, 4, 5]); +assert.compareArray(arr.with(NaN, 2), [2, 4, 16]); +assert.compareArray(arr.with("dog", "cat"), ["cat", 4, 16]); diff --git a/test/built-ins/Array/prototype/with/index-negative.js b/test/built-ins/Array/prototype/with/index-negative.js new file mode 100644 index 0000000000..f4db686c17 --- /dev/null +++ b/test/built-ins/Array/prototype/with/index-negative.js @@ -0,0 +1,27 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.with +description: > + Array.prototype.with adds length to index if it's negative. +info: | + Array.prototype.with ( index, value ) + + ... + 2. Let len be ? LengthOfArrayLike(O). + 3. Let relativeIndex be ? ToIntegerOrInfinity(index). + 4. If index >= 0, let actualIndex be relativeIndex. + 5. Else, let actualIndex be len + relativeIndex. + ... +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var arr = [0, 1, 2]; + +assert.compareArray(arr.with(-1, 4), [0, 1, 4]); +assert.compareArray(arr.with(-3, 4), [4, 1, 2]); + +// -0 is not < 0 +assert.compareArray(arr.with(-0, 4), [4, 1, 2]); diff --git a/test/built-ins/Array/prototype/with/index-smaller-than-minus-length.js b/test/built-ins/Array/prototype/with/index-smaller-than-minus-length.js new file mode 100644 index 0000000000..644718f66b --- /dev/null +++ b/test/built-ins/Array/prototype/with/index-smaller-than-minus-length.js @@ -0,0 +1,37 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.with +description: > + Array.prototype.with throws if the (negative) index is smaller than -length. +info: | + Array.prototype.with ( index, value ) + + ... + 2. Let len be ? LengthOfArrayLike(O). + 3. Let relativeIndex be ? ToIntegerOrInfinity(index). + 4. If index >= 0, let actualIndex be relativeIndex. + 5. Else, let actualIndex be len + relativeIndex. + 6. If actualIndex >= len or actualIndex < 0, throw a *RangeError* exception. + ... +features: [change-array-by-copy] +---*/ + +[0, 1, 2].with(-3, 7); + +assert.throws(RangeError, function() { + [0, 1, 2].with(-4, 7); +}); + +assert.throws(RangeError, function() { + [0, 1, 2].with(-10, 7); +}); + +assert.throws(RangeError, function() { + [0, 1, 2].with(-(2 ** 53) - 2, 7); +}); + +assert.throws(RangeError, function() { + [0, 1, 2].with(-Infinity, 7); +}); diff --git a/test/built-ins/Array/prototype/with/length-decreased-while-iterating.js b/test/built-ins/Array/prototype/with/length-decreased-while-iterating.js new file mode 100644 index 0000000000..a63fe0b97a --- /dev/null +++ b/test/built-ins/Array/prototype/with/length-decreased-while-iterating.js @@ -0,0 +1,40 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.with +description: > + Array.prototype.with caches the length getting the array elements. +info: | + Array.prototype.with ( index, value ) + + ... + 2. Let len be ? LengthOfArrayLike(O). + ... + 5. Repeat, while k < len + a. Let Pk be ! ToString(𝔽(k)). + b. If k is actualIndex, let fromValue be value. + c. Else, let fromValue be ? Get(O, Pk). + d. Perform ? CreateDataPropertyOrThrow(A, Pk, fromValue). + e. Set k to k + 1. +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +Array.prototype[4] = 5; + +var arr = Object.defineProperty([0, 1, 2, 3, 4], "1", { + get() { + arr.length = 1; + return 1; + } +}); +assert.compareArray(arr.with(2, 7), [0, 1, 7, undefined, 5]); + +arr = Object.defineProperty([0, 1, 2, 3, 4], "1", { + get() { + arr.length = 1; + return 1; + } +}); +assert.compareArray(arr.with(0, 7), [7, 1, undefined, undefined, 5]); diff --git a/test/built-ins/Array/prototype/with/length-exceeding-array-length-limit.js b/test/built-ins/Array/prototype/with/length-exceeding-array-length-limit.js new file mode 100644 index 0000000000..f6f2d7de49 --- /dev/null +++ b/test/built-ins/Array/prototype/with/length-exceeding-array-length-limit.js @@ -0,0 +1,39 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.with +description: > + Array.prototype.with limits the length to 2 ** 32 - 1 +info: | + Array.prototype.with ( index, value ) + + ... + 2. Let len be ? LengthOfArrayLike(O). + ... + 7. Let A be ? ArrayCreate(𝔽(len)). + ... + + ArrayCreate ( length [, proto ] ) + + 1. If length > 2 ** 32 - 1, throw a RangeError exception. +features: [change-array-by-copy] +---*/ + +// Object with large "length" property +var arrayLike = { + get "0"() { + throw new Test262Error("Get 0"); + }, + get "4294967295" () { // 2 ** 32 - 1 + throw new Test262Error("Get 4294967295"); + }, + get "4294967296" () { // 2 ** 32 + throw new Test262Error("Get 4294967296"); + }, + length: 2 ** 32 +}; + +assert.throws(RangeError, function() { + Array.prototype.with.call(arrayLike, 0, 0); +}); diff --git a/test/built-ins/Array/prototype/with/length-increased-while-iterating.js b/test/built-ins/Array/prototype/with/length-increased-while-iterating.js new file mode 100644 index 0000000000..be56837490 --- /dev/null +++ b/test/built-ins/Array/prototype/with/length-increased-while-iterating.js @@ -0,0 +1,32 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.with +description: > + Array.prototype.with caches the length getting the array elements. +info: | + Array.prototype.with ( index, value ) + + ... + 2. Let len be ? LengthOfArrayLike(O). + ... + 5. Repeat, while k < len + a. Let Pk be ! ToString(𝔽(k)). + b. If k is actualIndex, let fromValue be value. + c. Else, let fromValue be ? Get(O, Pk). + d. Perform ? CreateDataPropertyOrThrow(A, Pk, fromValue). + e. Set k to k + 1. +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var arr = [0, 1, 2]; +Object.defineProperty(arr, "0", { + get() { + arr.push(4); + return 0; + } +}); + +assert.compareArray(arr.with(1, 4), [0, 4, 2]); diff --git a/test/built-ins/Array/prototype/with/length-tolength.js b/test/built-ins/Array/prototype/with/length-tolength.js new file mode 100644 index 0000000000..e50ce8a010 --- /dev/null +++ b/test/built-ins/Array/prototype/with/length-tolength.js @@ -0,0 +1,30 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.with +description: > + Array.prototype.with converts the this value length to a number. +info: | + Array.prototype.with ( index, value ) + + ... + 2. Let len be ? LengthOfArrayLike(O). + ... +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var arrayLike = { length: "2", 0: 1, 1: 2, 2: 3 }; +assert.compareArray(Array.prototype.with.call(arrayLike, 0, 4), [4, 2]); + +var arrayLike = { + length: { + valueOf: () => 2 + }, + 0: 1, + 1: 2, + 2: 3, +}; + +assert.compareArray(Array.prototype.with.call(arrayLike, 0, 4), [4, 2]); diff --git a/test/built-ins/Array/prototype/with/metadata/length.js b/test/built-ins/Array/prototype/with/metadata/length.js new file mode 100644 index 0000000000..07afcbfbae --- /dev/null +++ b/test/built-ins/Array/prototype/with/metadata/length.js @@ -0,0 +1,30 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.with +description: > + The "length" property of Array.prototype.with +info: | + 17 ECMAScript Standard Built-in Objects + + Every built-in function object, including constructors, has a length property + whose value is an integer. Unless otherwise specified, this value is equal to + the largest number of named arguments shown in the subclause headings for the + function description. Optional parameters (which are indicated with brackets: + [ ]) or rest parameters (which are shown using the form «...name») are not + included in the default argument count. + + Unless otherwise specified, the length property of a built-in function object + has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [change-array-by-copy] +---*/ + +verifyProperty(Array.prototype.with, "length", { + value: 2, + writable: false, + enumerable: false, + configurable: true, +}); diff --git a/test/built-ins/Array/prototype/with/metadata/name.js b/test/built-ins/Array/prototype/with/metadata/name.js new file mode 100644 index 0000000000..d5d849e966 --- /dev/null +++ b/test/built-ins/Array/prototype/with/metadata/name.js @@ -0,0 +1,28 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.with +description: > + Array.prototype.with.name is "with". +info: | + Array.prototype.with ( index, value ) + + 17 ECMAScript Standard Built-in Objects: + Every built-in Function object, including constructors, that is not + identified as an anonymous function has a name property whose value + is a String. + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [change-array-by-copy] +---*/ + +verifyProperty(Array.prototype.with, "name", { + value: "with", + writable: false, + enumerable: false, + configurable: true, +}); diff --git a/test/built-ins/Array/prototype/with/metadata/property-descriptor.js b/test/built-ins/Array/prototype/with/metadata/property-descriptor.js new file mode 100644 index 0000000000..13128b08d3 --- /dev/null +++ b/test/built-ins/Array/prototype/with/metadata/property-descriptor.js @@ -0,0 +1,25 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.with +description: > + "with" property of Array.prototype +info: | + 17 ECMAScript Standard Built-in Objects + + Every other data property described in clauses 18 through 26 and in Annex B.2 + has the attributes { [[Writable]]: true, [[Enumerable]]: false, + [[Configurable]]: true } unless otherwise specified. +includes: [propertyHelper.js] +features: [change-array-by-copy] +---*/ + +assert.sameValue(typeof Array.prototype.with, "function", "typeof"); + +verifyProperty(Array.prototype, "with", { + value: Array.prototype.with, + writable: true, + enumerable: false, + configurable: true, +}); diff --git a/test/built-ins/Array/prototype/with/no-get-replaced-index.js b/test/built-ins/Array/prototype/with/no-get-replaced-index.js new file mode 100644 index 0000000000..e31be0c106 --- /dev/null +++ b/test/built-ins/Array/prototype/with/no-get-replaced-index.js @@ -0,0 +1,30 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.with +description: > + Array.prototype.with does not [[Get]] the value in the replaced position +info: | + Array.prototype.with ( ) + + ... + 5. Repeat, while k < len + a. Let Pk be ! ToString(𝔽(k)). + b. If k is actualIndex, let fromValue be value. + c. Else, let fromValue be ? Get(O, Pk). + d. Perform ? CreateDataPropertyOrThrow(A, Pk, fromValue). + e. Set k to k + 1. +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +var arr = [0, 1, 2, 3]; +Object.defineProperty(arr, "2", { + get() { + throw new Test262Error("Should not get '2'"); + } +}); + +var result = arr.with(2, 6); +assert.compareArray(result, [0, 1, 6, 3]); diff --git a/test/built-ins/Array/prototype/with/not-a-constructor.js b/test/built-ins/Array/prototype/with/not-a-constructor.js new file mode 100644 index 0000000000..5c8d8ab652 --- /dev/null +++ b/test/built-ins/Array/prototype/with/not-a-constructor.js @@ -0,0 +1,33 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + Array.prototype.with does not implement [[Construct]], is not new-able +info: | + ECMAScript Function Objects + + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified in + the description of a particular function. + + sec-evaluatenew + + ... + 7. If IsConstructor(constructor) is false, throw a TypeError exception. + ... +includes: [isConstructor.js] +features: [change-array-by-copy, Reflect.construct] +---*/ + +assert.sameValue( + isConstructor(Array.prototype.with), + false, + 'isConstructor(Array.prototype.with) must return false' +); + +assert.throws(TypeError, () => { + new Array.prototype.with(); +}, '`new Array.prototype.with()` throws TypeError'); + diff --git a/test/built-ins/Array/prototype/with/this-value-boolean.js b/test/built-ins/Array/prototype/with/this-value-boolean.js new file mode 100644 index 0000000000..e46901f24a --- /dev/null +++ b/test/built-ins/Array/prototype/with/this-value-boolean.js @@ -0,0 +1,39 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.with +description: > + Array.prototype.with casts primitive receivers to objects +info: | + Array.prototype.with ( index, value ) + + 1. Let O be ? ToObject(this value). + 2. Let len be ? LengthOfArrayLike(O). + ... +features: [change-array-by-copy] +includes: [compareArray.js] +---*/ + +Boolean.prototype.length = 2; +Boolean.prototype[0] = 0; +Boolean.prototype[1] = 1; + +assert.compareArray(Array.prototype.with.call(true, 0, 2), [2, 1]); +assert.compareArray(Array.prototype.with.call(false, 0, 2), [2, 1]); + +/* Add length and indexed properties to `Boolean.prototype` */ +Boolean.prototype.length = 3; +delete Boolean.prototype[0]; +delete Boolean.prototype[1]; +assert.compareArray(Array.prototype.with.call(true, 0, 2), [2, undefined, undefined]); +assert.compareArray(Array.prototype.with.call(false, 0, 2), [2, undefined, undefined]); +delete Boolean.prototype.length; +Boolean.prototype[0] = "monkeys"; +Boolean.prototype[2] = "bogus"; +assert.throws(RangeError, + () => compareArray(Array.prototype.with.call(true, 0, 2)), + "Array.prototype.with on object with undefined length"); +assert.throws(RangeError, + () => compareArray(Array.prototype.with.call(false, 0, 2)), + "Array.prototype.with on object with undefined length"); diff --git a/test/built-ins/Array/prototype/with/this-value-nullish.js b/test/built-ins/Array/prototype/with/this-value-nullish.js new file mode 100644 index 0000000000..d71deb31e6 --- /dev/null +++ b/test/built-ins/Array/prototype/with/this-value-nullish.js @@ -0,0 +1,22 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-array.prototype.with +description: > + Array.prototype.with throws if the receiver is null or undefined +info: | + Array.prototype.with ( index, value ) + + 1. Let O be ? ToObject(this value). + ... +features: [change-array-by-copy] +---*/ + +assert.throws(TypeError, () => { + Array.prototype.with.call(null, 0, 0); +}, '`Array.prototype.with.call(null, 0, 0)` throws TypeError'); + +assert.throws(TypeError, () => { + Array.prototype.with.call(undefined, 0, 0); +}, '`Array.prototype.with.call(undefined, 0, 0)` throws TypeError'); diff --git a/test/built-ins/TypedArray/prototype/toReversed/ignores-species.js b/test/built-ins/TypedArray/prototype/toReversed/ignores-species.js new file mode 100644 index 0000000000..eccce6b92b --- /dev/null +++ b/test/built-ins/TypedArray/prototype/toReversed/ignores-species.js @@ -0,0 +1,41 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-%typedarray%.prototype.toReversed +description: > + %TypedArray%.prototype.toReversed ignores @@species +info: | + %TypedArray%.prototype.toReversed ( ) + + ... + 4. Let A be ? TypedArrayCreateSameType(O, « 𝔽(length) »). + ... + + TypedArrayCreateSameType ( exemplar, argumentList ) + ... + 2. Let constructor be the intrinsic object listed in column one of Table 63 for exemplar.[[TypedArrayName]]. + ... +includes: [testTypedArray.js] +features: [TypedArray, change-array-by-copy] +---*/ + +testWithTypedArrayConstructors(TA => { + var ta = new TA(); + ta.constructor = TA === Uint8Array ? Int32Array : Uint8Array; + assert.sameValue(Object.getPrototypeOf(ta.toReversed()), TA.prototype); + + ta = new TA(); + ta.constructor = { + [Symbol.species]: TA === Uint8Array ? Int32Array : Uint8Array, + }; + assert.sameValue(Object.getPrototypeOf(ta.toReversed()), TA.prototype); + + ta = new TA(); + Object.defineProperty(ta, "constructor", { + get() { + throw new Test262Error("Should not get .constructor"); + } + }); + ta.toReversed(); +}); diff --git a/test/built-ins/TypedArray/prototype/toReversed/immutable.js b/test/built-ins/TypedArray/prototype/toReversed/immutable.js new file mode 100644 index 0000000000..283b99516b --- /dev/null +++ b/test/built-ins/TypedArray/prototype/toReversed/immutable.js @@ -0,0 +1,18 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-%typedarray%.prototype.toReversed +description: > + %TypedArray%.prototype.toReversed does not mutate its this value +includes: [testTypedArray.js, compareArray.js] +features: [TypedArray, change-array-by-copy] +---*/ + +testWithTypedArrayConstructors(TA => { + var ta = new TA([0, 1, 2]); + ta.toReversed(); + + assert.compareArray(ta, [0, 1, 2]); + assert.notSameValue(ta.toReversed(), ta); +}); diff --git a/test/built-ins/TypedArray/prototype/toReversed/length-property-ignored.js b/test/built-ins/TypedArray/prototype/toReversed/length-property-ignored.js new file mode 100644 index 0000000000..c3a5ed7d85 --- /dev/null +++ b/test/built-ins/TypedArray/prototype/toReversed/length-property-ignored.js @@ -0,0 +1,50 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-%typedarray%.prototype.toReversed +description: > + %TypedArray%.prototype.toReversed does not read a "length" property +info: | + %TypedArray%.prototype.toReversed ( ) + + ... + 3. Let length be O.[[ArrayLength]]. + ... +includes: [testTypedArray.js, compareArray.js] +features: [TypedArray, change-array-by-copy] +---*/ + +testWithTypedArrayConstructors(TA => { + var ta = new TA([0, 1, 2]); + Object.defineProperty(ta, "length", { value: 2 }) + var res = ta.toReversed(); + assert.compareArray(res, [2, 1, 0]); + assert.sameValue(res.length, 3); + + ta = new TA([0, 1, 2]); + Object.defineProperty(ta, "length", { value: 5 }); + res = ta.toReversed(); + assert.compareArray(res, [2, 1, 0]); + assert.sameValue(res.length, 3); +}); + +function setLength(length) { + Object.defineProperty(TypedArray.prototype, "length", { + get: () => length, + }); +} + +testWithTypedArrayConstructors(TA => { + var ta = new TA([0, 1, 2]); + + setLength(2); + var res = ta.toReversed(); + setLength(3); + assert.compareArray(res, [2, 1, 0]); + + setLength(5); + res = ta.toReversed(); + setLength(3); + assert.compareArray(res, [2, 1, 0]); +}); diff --git a/test/built-ins/TypedArray/prototype/toReversed/metadata/length.js b/test/built-ins/TypedArray/prototype/toReversed/metadata/length.js new file mode 100644 index 0000000000..a09002e8f0 --- /dev/null +++ b/test/built-ins/TypedArray/prototype/toReversed/metadata/length.js @@ -0,0 +1,30 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-%typedarray%.prototype.toReversed +description: > + The "length" property of %TypedArray%.prototype.toReversed +info: | + 17 ECMAScript Standard Built-in Objects + + Every built-in function object, including constructors, has a length property + whose value is an integer. Unless otherwise specified, this value is equal to + the largest number of named arguments shown in the subclause headings for the + function description. Optional parameters (which are indicated with brackets: + [ ]) or rest parameters (which are shown using the form «...name») are not + included in the default argument count. + + Unless otherwise specified, the length property of a built-in function object + has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js, testTypedArray.js] +features: [TypedArray, change-array-by-copy] +---*/ + +verifyProperty(TypedArray.prototype.toReversed, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); diff --git a/test/built-ins/TypedArray/prototype/toReversed/metadata/name.js b/test/built-ins/TypedArray/prototype/toReversed/metadata/name.js new file mode 100644 index 0000000000..57b51abeaa --- /dev/null +++ b/test/built-ins/TypedArray/prototype/toReversed/metadata/name.js @@ -0,0 +1,28 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-%typedarray%.prototype.toReversed +description: > + %TypedArray%.prototype.toReversed.name is "toReversed". +info: | + %TypedArray%.prototype.toReversed ( ) + + 17 ECMAScript Standard Built-in Objects: + Every built-in Function object, including constructors, that is not + identified as an anonymous function has a name property whose value + is a String. + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js, testTypedArray.js] +features: [TypedArray, change-array-by-copy] +---*/ + +verifyProperty(TypedArray.prototype.toReversed, "name", { + value: "toReversed", + writable: false, + enumerable: false, + configurable: true, +}); diff --git a/test/built-ins/TypedArray/prototype/toReversed/metadata/property-descriptor.js b/test/built-ins/TypedArray/prototype/toReversed/metadata/property-descriptor.js new file mode 100644 index 0000000000..84811c0edc --- /dev/null +++ b/test/built-ins/TypedArray/prototype/toReversed/metadata/property-descriptor.js @@ -0,0 +1,25 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-%typedarray%.prototype.toReversed +description: > + "toReversed" property of %TypedArray%.prototype +info: | + 17 ECMAScript Standard Built-in Objects + + Every other data property described in clauses 18 through 26 and in Annex B.2 + has the attributes { [[Writable]]: true, [[Enumerable]]: false, + [[Configurable]]: true } unless otherwise specified. +includes: [propertyHelper.js, testTypedArray.js] +features: [TypedArray, change-array-by-copy] +---*/ + +assert.sameValue(typeof TypedArray.prototype.toReversed, "function", "typeof"); + +verifyProperty(TypedArray.prototype, "toReversed", { + value: TypedArray.prototype.toReversed, + writable: true, + enumerable: false, + configurable: true, +}); diff --git a/test/built-ins/TypedArray/prototype/toReversed/not-a-constructor.js b/test/built-ins/TypedArray/prototype/toReversed/not-a-constructor.js new file mode 100644 index 0000000000..630eba76ed --- /dev/null +++ b/test/built-ins/TypedArray/prototype/toReversed/not-a-constructor.js @@ -0,0 +1,33 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + %TypedArray%.prototype.toReversed does not implement [[Construct]], is not new-able +info: | + ECMAScript Function Objects + + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified in + the description of a particular function. + + sec-evaluatenew + + ... + 7. If IsConstructor(constructor) is false, throw a TypeError exception. + ... +includes: [isConstructor.js, testTypedArray.js] +features: [TypedArray, change-array-by-copy, Reflect.construct] +---*/ + +assert.sameValue( + isConstructor(TypedArray.prototype.toReversed), + false, + 'isConstructor(TypedArray.prototype.toReversed) must return false' +); + +assert.throws(TypeError, () => { + new TypedArray.prototype.toReversed(); +}, '`new TypedArray.prototype.toReversed()` throws TypeError'); + diff --git a/test/built-ins/TypedArray/prototype/toReversed/this-value-invalid.js b/test/built-ins/TypedArray/prototype/toReversed/this-value-invalid.js new file mode 100644 index 0000000000..648630a947 --- /dev/null +++ b/test/built-ins/TypedArray/prototype/toReversed/this-value-invalid.js @@ -0,0 +1,44 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-%typedarray%.prototype.toReversed +description: > + %TypedArray%.prototype.toReversed throws if the receiver is not a valid TypedArray +info: | + %TypedArray%.prototype.toReversed ( ) + + 1. Let O be the this value. + 2. Perform ? ValidateTypedArray(O). + ... +includes: [testTypedArray.js] +features: [TypedArray, change-array-by-copy] +---*/ + +var invalidValues = { + 'null': null, + 'undefined': undefined, + 'true': true, + '"abc"': "abc", + '12': 12, + 'Symbol()': Symbol(), + '[1, 2, 3]': [1, 2, 3], + '{ 0: 1, 1: 2, 2: 3, length: 3 }': { 0: 1, 1: 2, 2: 3, length: 3 }, + 'Uint8Array.prototype': Uint8Array.prototype, + '1n': 1n, +}; + +Object.entries(invalidValues).forEach(value => { + assert.throws(TypeError, () => { + TypedArray.prototype.toReversed.call(value[1]); + }, `${value[0]} is not a valid TypedArray`); +}); + +testWithTypedArrayConstructors(function(TA) { + let buffer = new ArrayBuffer(8); + let sample = new TA(buffer, 0, 1); + $DETACHBUFFER(sample.buffer); + assert.throws(TypeError, () => { + sample.toReversed(); + }, `array has a detached buffer`); +}); diff --git a/test/built-ins/TypedArray/prototype/toSorted/comparefn-not-a-function.js b/test/built-ins/TypedArray/prototype/toSorted/comparefn-not-a-function.js new file mode 100644 index 0000000000..c86e546588 --- /dev/null +++ b/test/built-ins/TypedArray/prototype/toSorted/comparefn-not-a-function.js @@ -0,0 +1,27 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-%typedarray%.prototype.toSorted +description: > + %TypedArray%.prototype.toSorted verifies that the comparator is callable before reading the length. +info: | + %TypedArray%.prototype.toSorted ( comparefn ) + + 1. If comparefn is not undefined and IsCallable(comparefn) is false, throw a TypeError exception. + 2. ... + 3. Let len be ? LengthOfArrayLike(O). +includes: [testTypedArray.js] +features: [TypedArray, change-array-by-copy] +---*/ + +var invalidComparators = [null, true, false, "", /a/g, 42, 42n, [], {}, Symbol()]; + +testWithTypedArrayConstructors(TA => { + const ta = new TA([1]); + for (var i = 0; i < invalidComparators.length; i++) { + assert.throws(TypeError, function() { + ta.toSorted(invalidComparators[i]); + }, String(invalidComparators[i])); + } +}); diff --git a/test/built-ins/TypedArray/prototype/toSorted/comparefn-stop-after-error.js b/test/built-ins/TypedArray/prototype/toSorted/comparefn-stop-after-error.js new file mode 100644 index 0000000000..3fe2004c15 --- /dev/null +++ b/test/built-ins/TypedArray/prototype/toSorted/comparefn-stop-after-error.js @@ -0,0 +1,33 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-%typedarray%.prototype.toSorted +description: > + %TypedArray%.prototype.toSorted doesn't call copmareFn if there is an error +info: | + %TypedArray%.prototype.toSorted ( compareFn ) + + ... + 9. Sort items using an implementation-defined sequence of + calls to SortCompare. If any such call returns an abrupt + completion, stop before performing any further calls to + SortCompare or steps in this algorithm and return that completion. + ... +includes: [testTypedArray.js] +features: [TypedArray, change-array-by-copy] +---*/ + +testWithTypedArrayConstructors(TA => { + var calls = 0; + var ta = new TA([3, 1, 2]); + try { + ta.toSorted(() => { + ++calls; + if (calls === 1) { + throw new Test262Error(); + } + }); + } catch (e) {} + assert.sameValue(calls <= 1, true, "compareFn is not called after an error"); +}); diff --git a/test/built-ins/TypedArray/prototype/toSorted/ignores-species.js b/test/built-ins/TypedArray/prototype/toSorted/ignores-species.js new file mode 100644 index 0000000000..05d6af46a6 --- /dev/null +++ b/test/built-ins/TypedArray/prototype/toSorted/ignores-species.js @@ -0,0 +1,41 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-%typedarray%.prototype.toSorted +description: > + %TypedArray%.prototype.toSorted ignores @@species +info: | + %TypedArray%.prototype.toSorted ( comparefn ) + + ... + 6. Let A be ? TypedArrayCreateSameType(O, « 𝔽(len) »). + ... + + TypedArrayCreateSameType ( exemplar, argumentList ) + ... + 2. Let constructor be the intrinsic object listed in column one of Table 63 for exemplar.[[TypedArrayName]]. + ... +includes: [testTypedArray.js] +features: [TypedArray, change-array-by-copy] +---*/ + +testWithTypedArrayConstructors(TA => { + var ta = new TA(); + ta.constructor = TA === Uint8Array ? Int32Array : Uint8Array; + assert.sameValue(Object.getPrototypeOf(ta.toSorted()), TA.prototype); + + ta = new TA(); + ta.constructor = { + [Symbol.species]: TA === Uint8Array ? Int32Array : Uint8Array, + }; + assert.sameValue(Object.getPrototypeOf(ta.toSorted()), TA.prototype); + + ta = new TA(); + Object.defineProperty(ta, "constructor", { + get() { + throw new Test262Error("Should not get .constructor"); + } + }); + ta.toSorted(); +}); diff --git a/test/built-ins/TypedArray/prototype/toSorted/immutable.js b/test/built-ins/TypedArray/prototype/toSorted/immutable.js new file mode 100644 index 0000000000..a528f81ef5 --- /dev/null +++ b/test/built-ins/TypedArray/prototype/toSorted/immutable.js @@ -0,0 +1,18 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-%typedarray%.prototype.toSorted +description: > + %TypedArray%.prototype.toSorted does not mutate its this value +includes: [testTypedArray.js, compareArray.js] +features: [TypedArray, change-array-by-copy] +---*/ + +testWithTypedArrayConstructors(TA => { + var ta = new TA([3, 1, 2]); + ta.toSorted(); + + assert.compareArray(ta, [3, 1, 2]); + assert.notSameValue(ta.toSorted(), ta); +}); diff --git a/test/built-ins/TypedArray/prototype/toSorted/length-property-ignored.js b/test/built-ins/TypedArray/prototype/toSorted/length-property-ignored.js new file mode 100644 index 0000000000..c150b8d6bb --- /dev/null +++ b/test/built-ins/TypedArray/prototype/toSorted/length-property-ignored.js @@ -0,0 +1,51 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-%typedarray%.prototype.toSorted +description: > + %TypedArray%.prototype.toSorted does not read a "length" property +info: | + %TypedArray%.prototype.toSorted ( comparefn ) + + ... + 4. Let len be O.[[ArrayLength]]. + ... +includes: [testTypedArray.js, compareArray.js] +features: [TypedArray, change-array-by-copy] +---*/ + +testWithTypedArrayConstructors(TA => { + var ta = new TA([3, 1, 2]); + Object.defineProperty(ta, "length", { value: 2 }) + var res = ta.toSorted() + assert.compareArray(res, [1, 2, 3]); + assert.sameValue(res.length, 3); + + ta = new TA([3, 1, 2]); + Object.defineProperty(ta, "length", { value: 5 }); + res = ta.toSorted(); + assert.compareArray(res, [1, 2, 3]); + assert.sameValue(res.length, 3); +}); + +function setLength(length) { + Object.defineProperty(TypedArray.prototype, "length", { + get: () => length, + }); +} + +testWithTypedArrayConstructors(TA => { + var ta = new TA([3, 1, 2]); + + setLength(2); + var res = ta.toSorted(); + setLength(3); + assert.compareArray(res, [1, 2, 3]); + + setLength(5); + res = ta.toSorted(); + setLength(3); + + assert.compareArray(res, [1, 2, 3]); +}); diff --git a/test/built-ins/TypedArray/prototype/toSorted/metadata/length.js b/test/built-ins/TypedArray/prototype/toSorted/metadata/length.js new file mode 100644 index 0000000000..5d38f28627 --- /dev/null +++ b/test/built-ins/TypedArray/prototype/toSorted/metadata/length.js @@ -0,0 +1,30 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-%typedarray%.prototype.toSorted +description: > + The "length" property of %TypedArray%.prototype.toSorted +info: | + 17 ECMAScript Standard Built-in Objects + + Every built-in function object, including constructors, has a length property + whose value is an integer. Unless otherwise specified, this value is equal to + the largest number of named arguments shown in the subclause headings for the + function description. Optional parameters (which are indicated with brackets: + [ ]) or rest parameters (which are shown using the form «...name») are not + included in the default argument count. + + Unless otherwise specified, the length property of a built-in function object + has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js, testTypedArray.js] +features: [TypedArray, change-array-by-copy] +---*/ + +verifyProperty(TypedArray.prototype.toSorted, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); diff --git a/test/built-ins/TypedArray/prototype/toSorted/metadata/name.js b/test/built-ins/TypedArray/prototype/toSorted/metadata/name.js new file mode 100644 index 0000000000..59bcecfa81 --- /dev/null +++ b/test/built-ins/TypedArray/prototype/toSorted/metadata/name.js @@ -0,0 +1,28 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-%typedarray%.prototype.toSorted +description: > + %TypedArray%.prototype.toSorted.name is "toSorted". +info: | + %TypedArray%.prototype.toSorted ( comparefn ) + + 17 ECMAScript Standard Built-in Objects: + Every built-in Function object, including constructors, that is not + identified as an anonymous function has a name property whose value + is a String. + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js, testTypedArray.js] +features: [TypedArray, change-array-by-copy] +---*/ + +verifyProperty(TypedArray.prototype.toSorted, "name", { + value: "toSorted", + writable: false, + enumerable: false, + configurable: true, +}); diff --git a/test/built-ins/TypedArray/prototype/toSorted/metadata/property-descriptor.js b/test/built-ins/TypedArray/prototype/toSorted/metadata/property-descriptor.js new file mode 100644 index 0000000000..a5c4ead9e6 --- /dev/null +++ b/test/built-ins/TypedArray/prototype/toSorted/metadata/property-descriptor.js @@ -0,0 +1,25 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-%typedarray%.prototype.toSorted +description: > + "toSorted" property of %TypedArray%.prototype +info: | + 17 ECMAScript Standard Built-in Objects + + Every other data property described in clauses 18 through 26 and in Annex B.2 + has the attributes { [[Writable]]: true, [[Enumerable]]: false, + [[Configurable]]: true } unless otherwise specified. +includes: [propertyHelper.js, testTypedArray.js] +features: [TypedArray, change-array-by-copy] +---*/ + +assert.sameValue(typeof TypedArray.prototype.toSorted, "function", "typeof"); + +verifyProperty(TypedArray.prototype, "toSorted", { + value: TypedArray.prototype.toSorted, + writable: true, + enumerable: false, + configurable: true, +}); diff --git a/test/built-ins/TypedArray/prototype/toSorted/not-a-constructor.js b/test/built-ins/TypedArray/prototype/toSorted/not-a-constructor.js new file mode 100644 index 0000000000..6d47d98c71 --- /dev/null +++ b/test/built-ins/TypedArray/prototype/toSorted/not-a-constructor.js @@ -0,0 +1,33 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + %TypedArray%.prototype.toSorted does not implement [[Construct]], is not new-able +info: | + ECMAScript Function Objects + + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified in + the description of a particular function. + + sec-evaluatenew + + ... + 7. If IsConstructor(constructor) is false, throw a TypeError exception. + ... +includes: [isConstructor.js, testTypedArray.js] +features: [TypedArray, change-array-by-copy, Reflect.construct] +---*/ + +assert.sameValue( + isConstructor(TypedArray.prototype.toSorted), + false, + 'isConstructor(TypedArray.prototype.toSorted) must return false' +); + +assert.throws(TypeError, () => { + new TypedArray.prototype.toSorted(); +}, '`new TypedArray.prototype.toSorted()` throws TypeError'); + diff --git a/test/built-ins/TypedArray/prototype/toSorted/this-value-invalid.js b/test/built-ins/TypedArray/prototype/toSorted/this-value-invalid.js new file mode 100644 index 0000000000..961c1ff609 --- /dev/null +++ b/test/built-ins/TypedArray/prototype/toSorted/this-value-invalid.js @@ -0,0 +1,44 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-%typedarray%.prototype.toSorted +description: > + %TypedArray%.prototype.toSorted throws if the receiver is not a valid TypedArray +info: | + %TypedArray%.prototype.toSorted ( comparefn ) + + 2. Let O be the this value. + 3. Perform ? ValidateTypedArray(O). + ... +includes: [testTypedArray.js] +features: [TypedArray, change-array-by-copy] +---*/ + +var invalidValues = { + 'null': null, + 'undefined': undefined, + 'true': true, + '"abc"': "abc", + '12': 12, + 'Symbol()': Symbol(), + '[1, 2, 3]': [1, 2, 3], + '{ 0: 1, 1: 2, 2: 3, length: 3 }': { 0: 1, 1: 2, 2: 3, length: 3 }, + 'Uint8Array.prototype': Uint8Array.prototype, + '1n': 1n, +}; + +Object.entries(invalidValues).forEach(value => { + assert.throws(TypeError, () => { + TypedArray.prototype.toSorted.call(value[1]); + }, `${value[0]} is not a valid TypedArray`); +}); + +testWithTypedArrayConstructors(function(TA) { + let buffer = new ArrayBuffer(8); + let sample = new TA(buffer, 0, 1); + $DETACHBUFFER(sample.buffer); + assert.throws(TypeError, () => { + sample.toSorted(); + }, `array has a detached buffer`); +}); diff --git a/test/built-ins/TypedArray/prototype/with/BigInt/early-type-coercion-bigint.js b/test/built-ins/TypedArray/prototype/with/BigInt/early-type-coercion-bigint.js new file mode 100644 index 0000000000..c1a9141ba7 --- /dev/null +++ b/test/built-ins/TypedArray/prototype/with/BigInt/early-type-coercion-bigint.js @@ -0,0 +1,31 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-%typedarray%.prototype.with +description: > + %TypedArray%.prototype.with invokes ToNumber before copying +info: | + %TypedArray%.prototype.with ( index, value ) + + ... + 7. If _O_.[[ContentType]] is ~BigInt~, set _value_ to ? ToBigInt(_value_). + 8. Else, set _value_ to ? ToNumber(_value_). + ... +features: [BigInt, TypedArray, change-array-by-copy] +includes: [testBigIntTypedArray.js, compareArray.js] +---*/ + +testWithBigIntTypedArrayConstructors(function(TA) { + var arr = new TA([0n, 1n, 2n]); + + var value = { + valueOf() { + arr[0] = 3n; + return 4n; + } + }; + + assert.compareArray(arr.with(1, value), [3n, 4n, 2n]); + assert.compareArray(arr, [3n, 1n, 2n]); +}); diff --git a/test/built-ins/TypedArray/prototype/with/early-type-coercion.js b/test/built-ins/TypedArray/prototype/with/early-type-coercion.js new file mode 100644 index 0000000000..2be53157a2 --- /dev/null +++ b/test/built-ins/TypedArray/prototype/with/early-type-coercion.js @@ -0,0 +1,31 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-%typedarray%.prototype.with +description: > + %TypedArray%.prototype.with invokes ToNumber before copying +info: | + %TypedArray%.prototype.with ( index, value ) + + ... + 7. If _O_.[[ContentType]] is ~BigInt~, set _value_ to ? ToBigInt(_value_). + 8. Else, set _value_ to ? ToNumber(_value_). + ... +features: [TypedArray, change-array-by-copy] +includes: [testTypedArray.js, compareArray.js] +---*/ + +testWithTypedArrayConstructors(TA => { + var arr = new TA([0, 1, 2]); + + var value = { + valueOf() { + arr[0] = 3; + return 4; + } + }; + + assert.compareArray(arr.with(1, value), [3, 4, 2]); + assert.compareArray(arr, [3, 1, 2]); +}); diff --git a/test/built-ins/TypedArray/prototype/with/ignores-species.js b/test/built-ins/TypedArray/prototype/with/ignores-species.js new file mode 100644 index 0000000000..7ba4803585 --- /dev/null +++ b/test/built-ins/TypedArray/prototype/with/ignores-species.js @@ -0,0 +1,41 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-%typedarray%.prototype.with +description: > + %TypedArray%.prototype.with ignores @@species +info: | + %TypedArray%.prototype.with ( index, value ) + + ... + 10. Let A be ? TypedArrayCreateSameType(O, « 𝔽(len) »). + ... + + TypedArrayCreateSameType ( exemplar, argumentList ) + ... + 2. Let constructor be the intrinsic object listed in column one of Table 63 for exemplar.[[TypedArrayName]]. + ... +includes: [testTypedArray.js] +features: [TypedArray, change-array-by-copy] +---*/ + +testWithTypedArrayConstructors(TA => { + var ta = new TA([1, 2, 3]); + ta.constructor = TA === Uint8Array ? Int32Array : Uint8Array; + assert.sameValue(Object.getPrototypeOf(ta.with(0, 2)), TA.prototype); + + ta = new TA([1, 2, 3]); + ta.constructor = { + [Symbol.species]: TA === Uint8Array ? Int32Array : Uint8Array, + }; + assert.sameValue(Object.getPrototypeOf(ta.with(0, 2)), TA.prototype); + + ta = new TA([1, 2, 3]); + Object.defineProperty(ta, "constructor", { + get() { + throw new Test262Error("Should not get .constructor"); + } + }); + ta.with(0, 2); +}); diff --git a/test/built-ins/TypedArray/prototype/with/immutable.js b/test/built-ins/TypedArray/prototype/with/immutable.js new file mode 100644 index 0000000000..265bf1f71e --- /dev/null +++ b/test/built-ins/TypedArray/prototype/with/immutable.js @@ -0,0 +1,19 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-%typedarray%.prototype.with +description: > + %TypedArray%.prototype.with does not mutate its this value +includes: [testTypedArray.js, compareArray.js] +features: [TypedArray, change-array-by-copy] +---*/ + +testWithTypedArrayConstructors(TA => { + var ta = new TA([3, 1, 2]); + ta.with(0, 2); + + assert.compareArray(ta, [3, 1, 2]); + assert.notSameValue(ta.with(0, 2), ta); + assert.notSameValue(ta.with(0, 3), ta); +}); diff --git a/test/built-ins/TypedArray/prototype/with/index-bigger-or-eq-than-length.js b/test/built-ins/TypedArray/prototype/with/index-bigger-or-eq-than-length.js new file mode 100644 index 0000000000..979676e62e --- /dev/null +++ b/test/built-ins/TypedArray/prototype/with/index-bigger-or-eq-than-length.js @@ -0,0 +1,40 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-typed%array%.prototype.with +description: > + %TypedArray%.prototype.with throws if the index is bigger than or equal to the array length. +info: | + %TypedArray%.prototype.with ( index, value ) + + ... + 3. Let len be O.[[ArrayLength]]. + 3. Let relativeIndex be ? ToIntegerOrInfinity(index). + 4. If index >= 0, let actualIndex be relativeIndex. + 5. Else, let actualIndex be len + relativeIndex. + 6. If ! IsValidIntegerIndex(O, actualIndex) is false, throw a *RangeError* exception. + ... +includes: [testTypedArray.js] +features: [TypedArray, change-array-by-copy] +---*/ + +testWithTypedArrayConstructors(TA => { + var arr = new TA([0, 1, 2]); + + assert.throws(RangeError, function() { + arr.with(3, 7); + }); + + assert.throws(RangeError, function() { + arr.with(10, 7); + }); + + assert.throws(RangeError, function() { + arr.with(2 ** 53 + 2, 7); + }); + + assert.throws(RangeError, function() { + arr.with(Infinity, 7); + }); +}); diff --git a/test/built-ins/TypedArray/prototype/with/index-casted-to-number.js b/test/built-ins/TypedArray/prototype/with/index-casted-to-number.js new file mode 100644 index 0000000000..22ffe7878d --- /dev/null +++ b/test/built-ins/TypedArray/prototype/with/index-casted-to-number.js @@ -0,0 +1,29 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-%typedarray%.prototype.with +description: > + %TypedArray%.prototype.with casts the index to an integer. +info: | + %TypedArray%.prototype.with ( index, value ) + + ... + 2. Let len be ? LengthOfArrayLike(O). + 3. Let relativeIndex be ? ToIntegerOrInfinity(index). + 4. If index >= 0, let actualIndex be relativeIndex. + 5. Else, let actualIndex be len + relativeIndex. + ... +features: [TypedArray, change-array-by-copy] +includes: [testTypedArray.js, compareArray.js] +---*/ + +testWithTypedArrayConstructors(TA => { + var arr = new TA([0, 4, 16]); + + assert.compareArray(arr.with(1.2, 7), [0, 7, 16]); + assert.compareArray(arr.with("1", 3), [0, 3, 16]); + assert.compareArray(arr.with("-1", 5), [0, 4, 5]); + assert.compareArray(arr.with(NaN, 2), [2, 4, 16]); + assert.compareArray(arr.with("dog", 33), [33, 4, 16]); +}); diff --git a/test/built-ins/TypedArray/prototype/with/index-negative.js b/test/built-ins/TypedArray/prototype/with/index-negative.js new file mode 100644 index 0000000000..3e49f8f5e1 --- /dev/null +++ b/test/built-ins/TypedArray/prototype/with/index-negative.js @@ -0,0 +1,28 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-%typedarray%.prototype.with +description: > + %TypedArray%.prototype.with adds length to index if it's negative. +info: | + %TypedArray%.prototype.with ( index, value ) + + ... + 2. Let len be ? LengthOfArrayLike(O). + 3. Let relativeIndex be ? ToIntegerOrInfinity(index). + 4. If index >= 0, let actualIndex be relativeIndex. + 5. Else, let actualIndex be len + relativeIndex. + ... +features: [TypedArray, change-array-by-copy] +includes: [testTypedArray.js, compareArray.js] +---*/ + +testWithTypedArrayConstructors(TA => { + var arr = new TA([0, 1, 2]); + + assert.compareArray(arr.with(-1, 4), [0, 1, 4]); + assert.compareArray(arr.with(-3, 4), [4, 1, 2]); + // -0 is not negative. + assert.compareArray(arr.with(-0, 4), [4, 1, 2]); +}); diff --git a/test/built-ins/TypedArray/prototype/with/index-smaller-than-minus-length.js b/test/built-ins/TypedArray/prototype/with/index-smaller-than-minus-length.js new file mode 100644 index 0000000000..42a5941cdb --- /dev/null +++ b/test/built-ins/TypedArray/prototype/with/index-smaller-than-minus-length.js @@ -0,0 +1,40 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-%typedarray%.prototype.with +description: > + %TypedArray%.prototype.with throws if the (negative) index is smaller than -length. +info: | + %TypedArray%.prototype.with ( index, value ) + + ... + 2. Let len be ? LengthOfArrayLike(O). + 3. Let relativeIndex be ? ToIntegerOrInfinity(index). + 4. If index >= 0, let actualIndex be relativeIndex. + 5. Else, let actualIndex be len + relativeIndex. + 6. If actualIndex >= len or actualIndex < 0, throw a *RangeError* exception. + ... +features: [TypedArray, change-array-by-copy] +includes: [testTypedArray.js] +---*/ + +testWithTypedArrayConstructors(TA => { + var arr = new TA([0, 1, 2]); + + assert.throws(RangeError, function() { + arr.with(-4, 7); + }); + + assert.throws(RangeError, function() { + arr.with(-10, 7); + }); + + assert.throws(RangeError, function() { + arr.with(-(2 ** 53) - 2, 7); + }); + + assert.throws(RangeError, function() { + arr.with(-Infinity, 7); + }); +}); diff --git a/test/built-ins/TypedArray/prototype/with/length-property-ignored.js b/test/built-ins/TypedArray/prototype/with/length-property-ignored.js new file mode 100644 index 0000000000..b8276ce51d --- /dev/null +++ b/test/built-ins/TypedArray/prototype/with/length-property-ignored.js @@ -0,0 +1,50 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-%typedarray%.prototype.with +description: > + %TypedArray%.prototype.with reads the TypedArray length ignoring the .length property +info: | + %TypedArray%.prototype.with ( index, value ) + + ... + 3. Let len be O.[[ArrayLength]]. + ... +includes: [testTypedArray.js, compareArray.js] +features: [TypedArray, change-array-by-copy] +---*/ + +testWithTypedArrayConstructors(TA => { + var ta = new TA([3, 1, 2]); + Object.defineProperty(ta, "length", { value: 2 }) + var res = ta.with(0, 0); + assert.compareArray(res, [0, 1, 2]); + assert.sameValue(res.length, 3); + + ta = new TA([3, 1, 2]); + Object.defineProperty(ta, "length", { value: 5 }); + res = ta.with(0, 0); + assert.compareArray(res, [0, 1, 2]); + assert.sameValue(res.length, 3); +}); + +function setLength(length) { + Object.defineProperty(TypedArray.prototype, "length", { + get: () => length, + }); +} + +testWithTypedArrayConstructors(TA => { + var ta = new TA([3, 1, 2]); + + setLength(2); + var res = ta.with(0, 0); + setLength(3); + assert.compareArray(res, [0, 1, 2]); + + setLength(5); + res = ta.with(0, 0); + setLength(3); + assert.compareArray(res, [0, 1, 2]); +}); diff --git a/test/built-ins/TypedArray/prototype/with/metadata/length.js b/test/built-ins/TypedArray/prototype/with/metadata/length.js new file mode 100644 index 0000000000..954e380e8f --- /dev/null +++ b/test/built-ins/TypedArray/prototype/with/metadata/length.js @@ -0,0 +1,30 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-%typedarray%.prototype.with +description: > + The "length" property of %TypedArray%.prototype.with +info: | + 17 ECMAScript Standard Built-in Objects + + Every built-in function object, including constructors, has a length property + whose value is an integer. Unless otherwise specified, this value is equal to + the largest number of named arguments shown in the subclause headings for the + function description. Optional parameters (which are indicated with brackets: + [ ]) or rest parameters (which are shown using the form «...name») are not + included in the default argument count. + + Unless otherwise specified, the length property of a built-in function object + has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [testTypedArray.js, propertyHelper.js] +features: [TypedArray, change-array-by-copy] +---*/ + +verifyProperty(TypedArray.prototype.with, "length", { + value: 2, + writable: false, + enumerable: false, + configurable: true, +}); diff --git a/test/built-ins/TypedArray/prototype/with/metadata/name.js b/test/built-ins/TypedArray/prototype/with/metadata/name.js new file mode 100644 index 0000000000..3866597269 --- /dev/null +++ b/test/built-ins/TypedArray/prototype/with/metadata/name.js @@ -0,0 +1,28 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-%typedarray%.prototype.with +description: > + %TypedArray%.prototype.with.name is "with". +info: | + %TypedArray%.prototype.with ( index, value ) + + 17 ECMAScript Standard Built-in Objects: + Every built-in Function object, including constructors, that is not + identified as an anonymous function has a name property whose value + is a String. + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +includes: [testTypedArray.js, propertyHelper.js] +features: [TypedArray, change-array-by-copy] +---*/ + +verifyProperty(TypedArray.prototype.with, "name", { + value: "with", + writable: false, + enumerable: false, + configurable: true, +}); diff --git a/test/built-ins/TypedArray/prototype/with/metadata/property-descriptor.js b/test/built-ins/TypedArray/prototype/with/metadata/property-descriptor.js new file mode 100644 index 0000000000..8d5ae32a75 --- /dev/null +++ b/test/built-ins/TypedArray/prototype/with/metadata/property-descriptor.js @@ -0,0 +1,25 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-%typedarray%.prototype.with +description: > + "with" property of %TypedArray%.prototype +info: | + 17 ECMAScript Standard Built-in Objects + + Every other data property described in clauses 18 through 26 and in Annex B.2 + has the attributes { [[Writable]]: true, [[Enumerable]]: false, + [[Configurable]]: true } unless otherwise specified. +includes: [testTypedArray.js, propertyHelper.js] +features: [TypedArray, change-array-by-copy] +---*/ + +assert.sameValue(typeof TypedArray.prototype.with, "function", "typeof"); + +verifyProperty(TypedArray.prototype, "with", { + value: TypedArray.prototype.with, + writable: true, + enumerable: false, + configurable: true, +}); diff --git a/test/built-ins/TypedArray/prototype/with/not-a-constructor.js b/test/built-ins/TypedArray/prototype/with/not-a-constructor.js new file mode 100644 index 0000000000..46fb946367 --- /dev/null +++ b/test/built-ins/TypedArray/prototype/with/not-a-constructor.js @@ -0,0 +1,33 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + %TypedArray%.prototype.with does not implement [[Construct]], is not new-able +info: | + ECMAScript Function Objects + + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified in + the description of a particular function. + + sec-evaluatenew + + ... + 7. If IsConstructor(constructor) is false, throw a TypeError exception. + ... +includes: [isConstructor.js, testTypedArray.js] +features: [TypedArray, change-array-by-copy, Reflect.construct] +---*/ + +assert.sameValue( + isConstructor(TypedArray.prototype.with), + false, + 'isConstructor(TypedArray.prototype.with) must return false' +); + +assert.throws(TypeError, () => { + new TypedArray.prototype.with(0, 1); +}, '`new %TypedArray%.prototype.with()` throws TypeError'); + diff --git a/test/built-ins/TypedArray/prototype/with/this-value-invalid.js b/test/built-ins/TypedArray/prototype/with/this-value-invalid.js new file mode 100644 index 0000000000..aa6d9345b9 --- /dev/null +++ b/test/built-ins/TypedArray/prototype/with/this-value-invalid.js @@ -0,0 +1,35 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-%typedarray%.prototype.with +description: > + %TypedArray%.prototype.with throws if the receiver is null or undefined +info: | + %TypedArray%.prototype.with ( index, value ) + + 1. Let O be the this value. + 2. Perform ? ValidateTypedArray(O). + ... +includes: [testTypedArray.js] +features: [TypedArray, change-array-by-copy] +---*/ + +var invalidValues = { + 'null': null, + 'undefined': undefined, + 'true': true, + '"abc"': "abc", + '12': 12, + 'Symbol()': Symbol(), + '[1, 2, 3]': [1, 2, 3], + '{ 0: 1, 1: 2, 2: 3, length: 3 }': { 0: 1, 1: 2, 2: 3, length: 3 }, + 'Uint8Array.prototype': Uint8Array.prototype, +}; + +Object.keys(invalidValues).forEach(desc => { + var value = invalidValues[desc]; + assert.throws(TypeError, () => { + TypedArray.prototype.with.call(value, 0, 0); + }, `${desc} is not a valid TypedArray`); +});