Merge branch 'main' into chromium-export-99eec8f4a2

This commit is contained in:
Rezvan Mahdavi Hezaveh 2024-08-28 09:51:29 -07:00 committed by GitHub
commit 9f94490ff1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
473 changed files with 19054 additions and 3538 deletions

View File

@ -21,7 +21,7 @@ jobs:
- name: download esmeta
run: |
mkdir -p "${ESMETA_HOME}"
git clone --branch v0.4.1 --depth 1 https://github.com/es-meta/esmeta.git "${ESMETA_HOME}"
git clone --branch v0.4.2 --depth 1 https://github.com/es-meta/esmeta.git "${ESMETA_HOME}"
cd "${ESMETA_HOME}" && git submodule update --init --depth 1
- name: build esmeta
working-directory: ${{ env.ESMETA_HOME }}

View File

@ -209,8 +209,9 @@ This key is for boolean properties associated with the test.
- **raw** - execute the test without any modification (no harness files will be
included); necessary to test the behavior of directive prologue; implies
`noStrict`
- **async** - defer interpretation of test results until after the invocation
of the global `$DONE` function
- **async** - defer interpretation of test results until settlement of an
`asyncTest` callback promise or manual invocation of `$DONE`; refer to
[Writing Asynchronous Tests](#writing-asynchronous-tests) for details
- **generated** - informative flag used to denote test files that were
created procedurally using the project's test generation tool; refer to
[Procedurally-generated tests](#procedurally-generated-tests)
@ -346,7 +347,7 @@ Consumers that violate the spec by throwing exceptions for parsing errors at run
An asynchronous test is any test that include the `async` frontmatter flag.
For most asynchronous tests, the `asyncHelpers.js` harness file includes an `asyncTest` method that precludes needing to interact with the test runner via the `$DONE` function. `asyncTest` takes an async function and will ensure that `$DONE` is called properly if the async function returns or throws an exception. For example, a test written using `asyncTest` might look like:
Most asynchronous tests should include the `asyncHelpers.js` harness file and call its `asyncTest` function **exactly once**, with a callback returning a promise that indicates test failure via rejection and otherwise fulfills upon test conclusion (such as an async function).
```js
/*---

View File

@ -42,6 +42,7 @@ properties of the global scope prior to test execution.
the test runner. This is used as a communication mechanism for asynchronous
tests (via the `async` flag, described below).
- **`$262`** An ordinary object with the following properties:
- **`AbstractModuleSource`** - a reference to the `%AbstractModuleSource%` constructor which does not appear as a property of the global object.
- **`createRealm`** - a function which creates a new [ECMAScript
Realm](https://tc39.github.io/ecma262/#sec-code-realms),
defines this API on the new realm's global object, and returns the `$262`
@ -107,7 +108,6 @@ properties of the global scope prior to test execution.
- **`sleep`** - a function that takes a millisecond argument and
sleeps the execution for approximately that duration.
- **`monotonicNow`** - a function that returns a value that conforms to [`DOMHighResTimeStamp`][] and is produced in such a way that its semantics conform to **[Monotonic Clock][]**.
- **`AbstractModuleSource`** - a reference to the `%AbstractModuleSource%` constructor which does not appear as a property of the global object.
In addition, consumers may choose to override any of [the functions defined by test harness files](https://github.com/tc39/test262/blob/HEAD/CONTRIBUTING.md#test-environment) as they see fit. See [the documentation on handling errors and negative test cases](https://github.com/tc39/test262/blob/HEAD/CONTRIBUTING.md#handling-errors-and-negative-test-cases) for a useful example of this.

View File

@ -1,11 +1,11 @@
The << Software identified by reference to the Ecma Standard* ("Software)">> is protected by copyright and is being
Test262: ECMAScript Test Suite ("Software") is protected by copyright and is being
made available under the "BSD License", included below. This Software may be subject to third party rights (rights
from parties other than Ecma International), including patent rights, and no licenses under such third party rights
are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA
CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT http://www.ecma-international.org/memento/codeofconduct.htm FOR
CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://www.ecma-international.org/ipr FOR
INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS*.
Copyright (C) 2012-2013 Ecma International
Copyright (C) 2012 Ecma International
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
@ -25,4 +25,4 @@ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
* Ecma International Standards hereafter means Ecma International Standards as well as Ecma Technical Reports
* Ecma International Standards hereafter means Ecma International Standards as well as Ecma Technical Reports

View File

@ -31,20 +31,10 @@ legacy-regexp
# https://github.com/tc39/proposal-import-attributes/
import-attributes
# Import Assertions (Normative Optional, Deprecated)
# This feature should not be implemented, but if it is it must
# respect the specified behavior
# https://github.com/tc39/proposal-import-attributes/
import-assertions
# JSON modules
# https://github.com/tc39/proposal-json-modules
json-modules
# ArrayBuffer transfer
# https://github.com/tc39/proposal-arraybuffer-transfer
arraybuffer-transfer
# Temporal
# https://github.com/tc39/proposal-temporal
Temporal
@ -72,6 +62,10 @@ Array.fromAsync
# https://github.com/tc39/proposal-json-parse-with-source
json-parse-with-source
# RegExp.escape
# https://github.com/tc39/proposal-regex-escaping
RegExp.escape
# Regular expression modifiers
# https://github.com/tc39/proposal-regexp-modifiers
regexp-modifiers
@ -106,6 +100,10 @@ source-phase-imports-module-source
# https://github.com/tc39/proposal-arraybuffer-base64
uint8array-base64
# Atomics.pause
# https://github.com/tc39/proposal-atomics-microwait
Atomics.pause
## Standard language features
#
# Language features that have been included in a published version of the
@ -125,6 +123,7 @@ Array.prototype.includes
Array.prototype.values
Atomics.waitAsync
array-grouping
arraybuffer-transfer
arrow-function
async-iteration
async-functions

View File

@ -3,9 +3,17 @@
/*---
description: |
A collection of assertion and wrapper functions for testing asynchronous built-ins.
defines: [asyncTest]
defines: [asyncTest, assert.throwsAsync]
---*/
/**
* Defines the **sole** asynchronous test of a file.
* @see {@link ../docs/rfcs/async-helpers.md} for background.
*
* @param {Function} testFunc a callback whose returned promise indicates test results
* (fulfillment for success, rejection for failure)
* @returns {void}
*/
function asyncTest(testFunc) {
if (!Object.hasOwn(globalThis, "$DONE")) {
throw new Test262Error("asyncTest called without async flag");
@ -28,86 +36,70 @@ function asyncTest(testFunc) {
}
}
/**
* Asserts that a callback asynchronously throws an instance of a particular
* error (i.e., returns a promise whose rejection value is an object referencing
* the constructor).
*
* @param {Function} expectedErrorConstructor the expected constructor of the
* rejection value
* @param {Function} func the callback
* @param {string} [message] the prefix to use for failure messages
* @returns {Promise<void>} fulfills if the expected error is thrown,
* otherwise rejects
*/
assert.throwsAsync = function (expectedErrorConstructor, func, message) {
return new Promise(function (resolve) {
var innerThenable;
if (message === undefined) {
message = "";
} else {
message += " ";
}
if (typeof func === "function") {
try {
innerThenable = func();
if (
innerThenable === null ||
typeof innerThenable !== "object" ||
typeof innerThenable.then !== "function"
) {
message +=
"Expected to obtain an inner promise that would reject with a" +
expectedErrorConstructor.name +
" but result was not a thenable";
throw new Test262Error(message);
}
} catch (thrown) {
message +=
"Expected a " +
expectedErrorConstructor.name +
" to be thrown asynchronously but an exception was thrown synchronously while obtaining the inner promise";
throw new Test262Error(message);
var fail = function (detail) {
if (message === undefined) {
throw new Test262Error(detail);
}
} else {
message +=
"assert.throwsAsync called with an argument that is not a function";
throw new Test262Error(message);
throw new Test262Error(message + " " + detail);
};
if (typeof expectedErrorConstructor !== "function") {
fail("assert.throwsAsync called with an argument that is not an error constructor");
}
if (typeof func !== "function") {
fail("assert.throwsAsync called with an argument that is not a function");
}
var expectedName = expectedErrorConstructor.name;
var expectation = "Expected a " + expectedName + " to be thrown asynchronously";
var res;
try {
resolve(innerThenable.then(
function () {
message +=
"Expected a " +
expectedErrorConstructor.name +
" to be thrown asynchronously but no exception was thrown at all";
throw new Test262Error(message);
},
function (thrown) {
var expectedName, actualName;
if (typeof thrown !== "object" || thrown === null) {
message += "Thrown value was not an object!";
throw new Test262Error(message);
} else if (thrown.constructor !== expectedErrorConstructor) {
expectedName = expectedErrorConstructor.name;
actualName = thrown.constructor.name;
if (expectedName === actualName) {
message +=
"Expected a " +
expectedName +
" but got a different error constructor with the same name";
} else {
message +=
"Expected a " + expectedName + " but got a " + actualName;
}
throw new Test262Error(message);
}
}
));
res = func();
} catch (thrown) {
if (typeof thrown !== "object" || thrown === null) {
message +=
"Expected a " +
expectedErrorConstructor.name +
" to be thrown asynchronously but innerThenable synchronously threw a value that was not an object ";
} else {
message +=
"Expected a " +
expectedErrorConstructor.name +
" to be thrown asynchronously but a " +
thrown.constructor.name +
" was thrown synchronously";
}
throw new Test262Error(message);
fail(expectation + " but the function threw synchronously");
}
if (res === null || typeof res !== "object" || typeof res.then !== "function") {
fail(expectation + " but result was not a thenable");
}
var onResFulfilled, onResRejected;
var resSettlementP = new Promise(function (onFulfilled, onRejected) {
onResFulfilled = onFulfilled;
onResRejected = onRejected;
});
try {
res.then(onResFulfilled, onResRejected)
} catch (thrown) {
fail(expectation + " but .then threw synchronously");
}
resolve(resSettlementP.then(
function () {
fail(expectation + " but no exception was thrown at all");
},
function (thrown) {
var actualName;
if (thrown === null || typeof thrown !== "object") {
fail(expectation + " but thrown value was not an object");
} else if (thrown.constructor !== expectedErrorConstructor) {
actualName = thrown.constructor.name;
if (expectedName === actualName) {
fail(expectation +
" but got a different error constructor with the same name");
}
fail(expectation + " but got a " + actualName);
}
}
));
});
};

View File

@ -10,6 +10,18 @@ defines:
- GeneratorFunction
---*/
var AsyncFunction = Object.getPrototypeOf(async function () {}).constructor;
var AsyncGeneratorFunction = Object.getPrototypeOf(async function* () {}).constructor;
var GeneratorFunction = Object.getPrototypeOf(function* () {}).constructor;
var AsyncFunction;
var AsyncGeneratorFunction;
var GeneratorFunction;
try {
AsyncFunction = Object.getPrototypeOf(new Function('return async function dummy() {}')()).constructor;
} catch(e) {}
try {
AsyncGeneratorFunction = Object.getPrototypeOf(new Function('return async function* dummy() {}')()).constructor;
} catch(e) {}
try {
GeneratorFunction = Object.getPrototypeOf(new Function('return function* dummy() {}')()).constructor;
} catch(e) {}

View File

@ -23,8 +23,8 @@ const validateNativeFunctionSource = function(source) {
// `/\p{Space_Separator}/u`
const UnicodeSpaceSeparator = /[ \xA0\u1680\u2000-\u200A\u202F\u205F\u3000]/;
const isNewline = (c) => /[\u000A\u000D\u2028\u2029]/u.test(c);
const isWhitespace = (c) => /[\u0009\u000B\u000C\u0020\u00A0\uFEFF]/u.test(c) || UnicodeSpaceSeparator.test(c);
const isNewline = (c) => /[\u000A\u000D\u2028\u2029]/.test(c);
const isWhitespace = (c) => /[\u0009\u000B\u000C\u0020\u00A0\uFEFF]/.test(c) || UnicodeSpaceSeparator.test(c);
let pos = 0;

View File

@ -13,20 +13,20 @@ function buildString(args) {
const loneCodePoints = args.loneCodePoints;
const ranges = args.ranges;
const CHUNK_SIZE = 10000;
let result = Reflect.apply(String.fromCodePoint, null, loneCodePoints);
let result = String.fromCodePoint.apply(null, loneCodePoints);
for (let i = 0; i < ranges.length; i++) {
const range = ranges[i];
const start = range[0];
const end = range[1];
const codePoints = [];
let range = ranges[i];
let start = range[0];
let end = range[1];
let codePoints = [];
for (let length = 0, codePoint = start; codePoint <= end; codePoint++) {
codePoints[length++] = codePoint;
if (length === CHUNK_SIZE) {
result += Reflect.apply(String.fromCodePoint, null, codePoints);
result += String.fromCodePoint.apply(null, codePoints);
codePoints.length = length = 0;
}
}
result += Reflect.apply(String.fromCodePoint, null, codePoints);
result += String.fromCodePoint.apply(null, codePoints);
}
return result;
}
@ -41,8 +41,8 @@ function printCodePoint(codePoint) {
function printStringCodePoints(string) {
const buf = [];
for (const symbol of string) {
const formatted = printCodePoint(symbol.codePointAt(0));
for (let symbol of string) {
let formatted = printCodePoint(symbol.codePointAt(0));
buf.push(formatted);
}
return buf.join(' ');
@ -50,8 +50,8 @@ function printStringCodePoints(string) {
function testPropertyEscapes(regExp, string, expression) {
if (!regExp.test(string)) {
for (const symbol of string) {
const formatted = printCodePoint(symbol.codePointAt(0));
for (let symbol of string) {
let formatted = printCodePoint(symbol.codePointAt(0));
assert(
regExp.test(symbol),
`\`${ expression }\` should match ${ formatted } (\`${ symbol }\`)`
@ -70,7 +70,7 @@ function testPropertyOfStrings(args) {
const nonMatchStrings = args.nonMatchStrings;
const allStrings = matchStrings.join('');
if (!regExp.test(allStrings)) {
for (const string of matchStrings) {
for (let string of matchStrings) {
assert(
regExp.test(string),
`\`${ expression }\` should match ${ string } (${ printStringCodePoints(string) })`
@ -82,7 +82,7 @@ function testPropertyOfStrings(args) {
const allNonMatchStrings = nonMatchStrings.join('');
if (regExp.test(allNonMatchStrings)) {
for (const string of nonMatchStrings) {
for (let string of nonMatchStrings) {
assert(
!regExp.test(string),
`\`${ expression }\` should not match ${ string } (${ printStringCodePoints(string) })`

View File

@ -17,15 +17,16 @@ defines:
- TestIterationAndResize
features: [BigInt]
---*/
class MyUint8Array extends Uint8Array {
// Helper to create subclasses without bombing out when `class` isn't supported
function subClass(type) {
try {
return new Function('return class My' + type + ' extends ' + type + ' {}')();
} catch (e) {}
}
class MyFloat32Array extends Float32Array {
}
class MyBigInt64Array extends BigInt64Array {
}
const MyUint8Array = subClass('Uint8Array');
const MyFloat32Array = subClass('Float32Array');
const MyBigInt64Array = subClass('BigInt64Array');
const builtinCtors = [
Uint8Array,
@ -39,15 +40,18 @@ const builtinCtors = [
Uint8ClampedArray,
];
// BigInt and Float16Array are newer features adding them above unconditionally
// Big(U)int64Array and Float16Array are newer features adding them above unconditionally
// would cause implementations lacking it to fail every test which uses it.
if (typeof Float16Array !== 'undefined') {
builtinCtors.push(Float16Array);
}
if (typeof BigInt !== 'undefined') {
builtinCtors.push(BigUint64Array);
builtinCtors.push(BigInt64Array);
if (typeof BigUint64Array !== 'undefined') {
builtinCtors.push(BigUint64Array);
}
if (typeof BigInt64Array !== 'undefined') {
builtinCtors.push(BigInt64Array);
}
const floatCtors = [
@ -60,13 +64,9 @@ if (typeof Float16Array !== 'undefined') {
floatCtors.push(Float16Array);
}
const ctors = [
...builtinCtors,
MyUint8Array,
MyFloat32Array
];
const ctors = builtinCtors.concat(MyUint8Array, MyFloat32Array);
if (typeof BigInt !== 'undefined') {
if (typeof MyBigInt64Array !== 'undefined') {
ctors.push(MyBigInt64Array);
}
@ -125,7 +125,7 @@ function TestIterationAndResize(iterable, expected, rab, resizeAfter, newByteLen
let resized = false;
var arrayValues = false;
for (const value of iterable) {
for (let value of iterable) {
if (Array.isArray(value)) {
arrayValues = true;
values.push([

View File

@ -127,7 +127,7 @@ var TemporalHelpers = {
* Return the canonical era code.
*/
canonicalizeCalendarEra(calendarId, eraName) {
assert.sameValue(typeof calendarId, "string");
assert.sameValue(typeof calendarId, "string", "calendar must be string in canonicalizeCalendarEra");
if (calendarId === "iso8601") {
assert.sameValue(eraName, undefined);
@ -138,7 +138,7 @@ var TemporalHelpers = {
if (eraName === undefined) {
return undefined;
}
assert.sameValue(typeof eraName, "string");
assert.sameValue(typeof eraName, "string", "eraName must be string or undefined in canonicalizeCalendarEra");
for (let {era, aliases = []} of TemporalHelpers.CalendarEras[calendarId]) {
if (era === eraName || aliases.includes(eraName)) {

View File

@ -1,30 +0,0 @@
// Copyright (C) 2017 Ecma International. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: |
Used in website/scripts/sth.js
defines: [setTimeout]
---*/
//setTimeout is not available, hence this script was loaded
if (Promise === undefined && this.setTimeout === undefined) {
if(/\$DONE()/.test(code))
throw new Test262Error("Async test capability is not supported in your test environment");
}
if (Promise !== undefined && this.setTimeout === undefined) {
(function(that) {
that.setTimeout = function(callback, delay) {
var p = Promise.resolve();
var start = Date.now();
var end = start + delay;
function check(){
var timeLeft = end - Date.now();
if(timeLeft > 0)
p.then(check);
else
callback();
}
p.then(check);
}
})(this);
}

View File

@ -194,7 +194,7 @@ f();
Tests written like this will correctly pass if the import Promise is rejected, and will correctly fail if the import succeeds (due to the imported module object being passed to `$DONE`.)
However, at a first glance, it's not immediately clear that the test is correct in the case of the import succeeding; in fact in an earlier draft of this RFC I thought the test was incorrect.
Others, such as [`test/language/expressions/dynamic-import/import-assertions/2nd-param-non-object.js`](https://github.com/tc39/test262/blob/main/test/language/expressions/dynamic-import/import-assertions/2nd-param-non-object.js), use a pattern more like what is proposed in this RFC. However, this pattern doesn't format the messages as helpfully in all the edge cases that `assert.throws()` does, such as:
Others, such as [`test/language/expressions/dynamic-import/import-attributes/2nd-param-non-object.js`](https://github.com/tc39/test262/blob/main/test/language/expressions/dynamic-import/import-attributes/2nd-param-non-object.js), use a pattern more like what is proposed in this RFC. However, this pattern doesn't format the messages as helpfully in all the edge cases that `assert.throws()` does, such as:
- the Promise being rejected with a primitive value;
- the error constructor being a different object with the same name, such as a different iframe's TypeError;

View File

@ -1,14 +0,0 @@
// Copyright (C) 2018 Leo Balter. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
desc: ImportCall trailing comma following first parameter
template: syntax/valid
info: |
ImportCall :
import( AssignmentExpression[+In, ?Yield, ?Await] ,opt )
import( AssignmentExpression[+In, ?Yield, ?Await] , AssignmentExpression[+In, ?Yield, ?Await] ,opt )
features: [import-assertions]
---*/
//- import
import('./empty_FIXTURE.js',)

View File

@ -1,14 +0,0 @@
// Copyright (C) 2021 V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
desc: ImportCall trailing comma following second parameter
template: syntax/valid
info: |
ImportCall :
import( AssignmentExpression[+In, ?Yield, ?Await] ,opt )
import( AssignmentExpression[+In, ?Yield, ?Await] , AssignmentExpression[+In, ?Yield, ?Await] ,opt )
features: [import-assertions]
---*/
//- import
import('./empty_FIXTURE.js', {},)

View File

@ -9,6 +9,7 @@ info: |
The initial value of %AbstractModuleSource%.prototype is the %AbstractModuleSource% prototype object.
This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.
includes: [propertyHelper.js]
features: [source-phase-imports]
flags: [module]
---*/
@ -18,5 +19,5 @@ verifyProperty($262.AbstractModuleSource, 'prototype', {
value: $262.AbstractModuleSource.prototype,
writable: false,
enumerable: false,
configurable: false
configurable: true
});

View File

@ -23,8 +23,11 @@ includes: [propertyHelper.js]
assert.sameValue(typeof $262.AbstractModuleSource, 'function');
verifyProperty($262.AbstractModuleSource.prototype, Symbol.toStringTag, {
enumerable: false,
configurable: false,
writable: false,
configurable: true,
set: undefined,
value: undefined,
}, {
restore: true,
});
// Return undefined if this value does not have a [[ModuleSourceClassName]] internal slot.

View File

@ -33,8 +33,8 @@ var child = new Con();
Object.defineProperty(child, "toString", {
value: function() {
toStringAccessed = true;
return '1';
toStringAccessed = true;
return '1';
}
});

View File

@ -19,7 +19,7 @@ let resizeTo;
// resizeTo. To be called by a method of the view being collected.
// Note that rab, values, resizeAfter, and resizeTo may need to be reset
// before calling this.
function ResizeBufferMidIteration(n) {
function ResizeMidIteration(n) {
// Returns true by default.
return CollectValuesAndResize(n, values, rab, resizeAfter, resizeTo);
}
@ -35,7 +35,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 2;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
assert(Array.prototype.every.call(fixedLength, ResizeBufferMidIteration));
assert(Array.prototype.every.call(fixedLength, ResizeMidIteration));
assert.compareArray(values, [
0,
2,
@ -49,7 +49,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 1;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
assert(Array.prototype.every.call(fixedLengthWithOffset, ResizeBufferMidIteration));
assert(Array.prototype.every.call(fixedLengthWithOffset, ResizeMidIteration));
assert.compareArray(values, [
4,
6
@ -61,7 +61,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 2;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
assert(Array.prototype.every.call(lengthTracking, ResizeBufferMidIteration));
assert(Array.prototype.every.call(lengthTracking, ResizeMidIteration));
assert.compareArray(values, [
0,
2,
@ -75,7 +75,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 1;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
assert(Array.prototype.every.call(lengthTrackingWithOffset, ResizeBufferMidIteration));
assert(Array.prototype.every.call(lengthTrackingWithOffset, ResizeMidIteration));
assert.compareArray(values, [
4,
6

View File

@ -19,7 +19,7 @@ let resizeTo;
// resizeTo. To be called by a method of the view being collected.
// Note that rab, values, resizeAfter, and resizeTo may need to be reset
// before calling this.
function ResizeBufferMidIteration(n) {
function ResizeMidIteration(n) {
// Returns true by default.
return CollectValuesAndResize(n, values, rab, resizeAfter, resizeTo);
}
@ -35,7 +35,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 2;
resizeTo = 3 * ctor.BYTES_PER_ELEMENT;
assert(Array.prototype.every.call(fixedLength, ResizeBufferMidIteration));
assert(Array.prototype.every.call(fixedLength, ResizeMidIteration));
assert.compareArray(values, [
0,
2
@ -47,7 +47,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 1;
resizeTo = 3 * ctor.BYTES_PER_ELEMENT;
assert(Array.prototype.every.call(fixedLengthWithOffset, ResizeBufferMidIteration));
assert(Array.prototype.every.call(fixedLengthWithOffset, ResizeMidIteration));
assert.compareArray(values, [4]);
}
for (let ctor of ctors) {
@ -56,7 +56,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 2;
resizeTo = 3 * ctor.BYTES_PER_ELEMENT;
assert(Array.prototype.every.call(lengthTracking, ResizeBufferMidIteration));
assert(Array.prototype.every.call(lengthTracking, ResizeMidIteration));
assert.compareArray(values, [
0,
2,
@ -69,6 +69,6 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 1;
resizeTo = 3 * ctor.BYTES_PER_ELEMENT;
assert(Array.prototype.every.call(lengthTrackingWithOffset, ResizeBufferMidIteration));
assert(Array.prototype.every.call(lengthTrackingWithOffset, ResizeMidIteration));
assert.compareArray(values, [4]);
}

View File

@ -4,8 +4,8 @@
/*---
esid: sec-array.prototype.filter
description: >
Array.p.filter behaves correctly on receivers backed by resizable
buffers that grow mid-iteration
Array.p.filter behaves correctly on TypedArrays backed by resizable buffers
that grow mid-iteration.
includes: [compareArray.js, resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
@ -19,7 +19,7 @@ let resizeTo;
// resizeTo. To be called by a method of the view being collected.
// Note that rab, values, resizeAfter, and resizeTo may need to be reset
// before calling this.
function ResizeBufferMidIteration(n) {
function ResizeMidIteration(n) {
CollectValuesAndResize(n, values, rab, resizeAfter, resizeTo);
return false;
}
@ -36,7 +36,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 2;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
assert.compareArray(ToNumbers(Array.prototype.filter.call(fixedLength, ResizeBufferMidIteration)), []);
assert.compareArray(ToNumbers(Array.prototype.filter.call(fixedLength, ResizeMidIteration)), []);
assert.compareArray(values, [
0,
2,
@ -50,7 +50,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 1;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
assert.compareArray(ToNumbers(Array.prototype.filter.call(fixedLengthWithOffset, ResizeBufferMidIteration)), []);
assert.compareArray(ToNumbers(Array.prototype.filter.call(fixedLengthWithOffset, ResizeMidIteration)), []);
assert.compareArray(values, [
4,
6
@ -62,7 +62,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 2;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
assert.compareArray(ToNumbers(Array.prototype.filter.call(lengthTracking, ResizeBufferMidIteration)), []);
assert.compareArray(ToNumbers(Array.prototype.filter.call(lengthTracking, ResizeMidIteration)), []);
assert.compareArray(values, [
0,
2,
@ -76,10 +76,9 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 1;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
assert.compareArray(ToNumbers(Array.prototype.filter.call(lengthTrackingWithOffset, ResizeBufferMidIteration)), []);
assert.compareArray(ToNumbers(Array.prototype.filter.call(lengthTrackingWithOffset, ResizeMidIteration)), []);
assert.compareArray(values, [
4,
6
]);
}

View File

@ -0,0 +1,79 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-%array%.prototype.filter
description: >
Array.p.filter behaves correctly on TypedArrays backed by resizable buffers
that shrink mid-iteration.
includes: [compareArray.js, resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
let values;
let rab;
let resizeAfter;
let resizeTo;
// Collects the view of the resizable array buffer rab into values, with an
// iteration during which, after resizeAfter steps, rab is resized to length
// resizeTo. To be called by a method of the view being collected.
// Note that rab, values, resizeAfter, and resizeTo may need to be reset
// before calling this.
function ResizeMidIteration(n) {
CollectValuesAndResize(n, values, rab, resizeAfter, resizeTo);
return false;
}
// Orig. array: [0, 2, 4, 6]
// [0, 2, 4, 6] << fixedLength
// [4, 6] << fixedLengthWithOffset
// [0, 2, 4, 6, ...] << lengthTracking
// [4, 6, ...] << lengthTrackingWithOffset
for (let ctor of ctors) {
rab = CreateRabForTest(ctor);
const fixedLength = new ctor(rab, 0, 4);
values = [];
resizeAfter = 2;
resizeTo = 3 * ctor.BYTES_PER_ELEMENT;
assert.compareArray(ToNumbers(Array.prototype.filter.call(fixedLength, ResizeMidIteration)),[]);
assert.compareArray(values, [
0,
2
]);
}
for (let ctor of ctors) {
rab = CreateRabForTest(ctor);
const fixedLengthWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT, 2);
values = [];
resizeAfter = 1;
resizeTo = 3 * ctor.BYTES_PER_ELEMENT;
assert.compareArray(ToNumbers(Array.prototype.filter.call(fixedLengthWithOffset, ResizeMidIteration)),[]);
assert.compareArray(values, [
4
]);
}
for (let ctor of ctors) {
rab = CreateRabForTest(ctor);
const lengthTracking = new ctor(rab, 0);
values = [];
resizeAfter = 2;
resizeTo = 3 * ctor.BYTES_PER_ELEMENT;
assert.compareArray(ToNumbers(Array.prototype.filter.call(lengthTracking, ResizeMidIteration)),[]);
assert.compareArray(values, [
0,
2,
4
]);
}
for (let ctor of ctors) {
rab = CreateRabForTest(ctor);
const lengthTrackingWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT);
values = [];
resizeAfter = 1;
resizeTo = 3 * ctor.BYTES_PER_ELEMENT;
assert.compareArray(ToNumbers(Array.prototype.filter.call(lengthTrackingWithOffset, ResizeMidIteration)),[]);
assert.compareArray(values, [
4
]);
}

View File

@ -4,8 +4,7 @@
/*---
esid: sec-array.prototype.filter
description: >
Array.p.filter behaves correctly on receivers backed by resizable
buffers
Array.p.filter behaves correctly on TypedArrays backed by resizable buffers.
includes: [compareArray.js, resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/

View File

@ -19,7 +19,7 @@ let resizeTo;
// resizeTo. To be called by a method of the view being collected.
// Note that rab, values, resizeAfter, and resizeTo may need to be reset
// before calling this.
function ResizeBufferMidIteration(n) {
function ResizeMidIteration(n) {
CollectValuesAndResize(n, values, rab, resizeAfter, resizeTo);
return false;
}
@ -36,7 +36,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 2;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
assert.sameValue(Array.prototype.find.call(fixedLength, ResizeBufferMidIteration), undefined);
assert.sameValue(Array.prototype.find.call(fixedLength, ResizeMidIteration), undefined);
assert.compareArray(values, [
0,
2,
@ -50,7 +50,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 1;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
assert.sameValue(Array.prototype.find.call(fixedLengthWithOffset, ResizeBufferMidIteration), undefined);
assert.sameValue(Array.prototype.find.call(fixedLengthWithOffset, ResizeMidIteration), undefined);
assert.compareArray(values, [
4,
6
@ -62,7 +62,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 2;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
assert.sameValue(Array.prototype.find.call(lengthTracking, ResizeBufferMidIteration), undefined);
assert.sameValue(Array.prototype.find.call(lengthTracking, ResizeMidIteration), undefined);
assert.compareArray(values, [
0,
2,
@ -76,7 +76,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 1;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
assert.sameValue(Array.prototype.find.call(lengthTrackingWithOffset, ResizeBufferMidIteration), undefined);
assert.sameValue(Array.prototype.find.call(lengthTrackingWithOffset, ResizeMidIteration), undefined);
assert.compareArray(values, [
4,
6

View File

@ -19,7 +19,7 @@ let resizeTo;
// resizeTo. To be called by a method of the view being collected.
// Note that rab, values, resizeAfter, and resizeTo may need to be reset before
// calling this.
function ResizeBufferMidIteration(n) {
function ResizeMidIteration(n) {
CollectValuesAndResize(n, values, rab, resizeAfter, resizeTo);
return false;
}
@ -35,7 +35,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 2;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
assert.sameValue(Array.prototype.findIndex.call(fixedLength, ResizeBufferMidIteration), -1);
assert.sameValue(Array.prototype.findIndex.call(fixedLength, ResizeMidIteration), -1);
assert.compareArray(values, [
0,
2,
@ -49,7 +49,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 1;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
assert.sameValue(Array.prototype.findIndex.call(fixedLengthWithOffset, ResizeBufferMidIteration), -1);
assert.sameValue(Array.prototype.findIndex.call(fixedLengthWithOffset, ResizeMidIteration), -1);
assert.compareArray(values, [
4,
6
@ -61,7 +61,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 2;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
assert.sameValue(Array.prototype.findIndex.call(lengthTracking, ResizeBufferMidIteration), -1);
assert.sameValue(Array.prototype.findIndex.call(lengthTracking, ResizeMidIteration), -1);
assert.compareArray(values, [
0,
2,
@ -75,7 +75,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 1;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
assert.sameValue(Array.prototype.findIndex.call(lengthTrackingWithOffset, ResizeBufferMidIteration), -1);
assert.sameValue(Array.prototype.findIndex.call(lengthTrackingWithOffset, ResizeMidIteration), -1);
assert.compareArray(values, [
4,
6

View File

@ -19,7 +19,7 @@ let resizeTo;
// resizeTo. To be called by a method of the view being collected.
// Note that rab, values, resizeAfter, and resizeTo may need to be reset before
// calling this.
function ResizeBufferMidIteration(n) {
function ResizeMidIteration(n) {
CollectValuesAndResize(n, values, rab, resizeAfter, resizeTo);
return false;
}
@ -35,7 +35,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 2;
resizeTo = 3 * ctor.BYTES_PER_ELEMENT;
assert.sameValue(Array.prototype.findIndex.call(fixedLength, ResizeBufferMidIteration), -1);
assert.sameValue(Array.prototype.findIndex.call(fixedLength, ResizeMidIteration), -1);
assert.compareArray(values, [
0,
2,
@ -49,7 +49,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 1;
resizeTo = 3 * ctor.BYTES_PER_ELEMENT;
assert.sameValue(Array.prototype.findIndex.call(fixedLengthWithOffset, ResizeBufferMidIteration), -1);
assert.sameValue(Array.prototype.findIndex.call(fixedLengthWithOffset, ResizeMidIteration), -1);
assert.compareArray(values, [
4,
undefined
@ -61,7 +61,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 2;
resizeTo = 3 * ctor.BYTES_PER_ELEMENT;
assert.sameValue(Array.prototype.findIndex.call(lengthTracking, ResizeBufferMidIteration), -1);
assert.sameValue(Array.prototype.findIndex.call(lengthTracking, ResizeMidIteration), -1);
assert.compareArray(values, [
0,
2,
@ -75,7 +75,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 1;
resizeTo = 3 * ctor.BYTES_PER_ELEMENT;
assert.sameValue(Array.prototype.findIndex.call(lengthTrackingWithOffset, ResizeBufferMidIteration), -1);
assert.sameValue(Array.prototype.findIndex.call(lengthTrackingWithOffset, ResizeMidIteration), -1);
assert.compareArray(values, [
4,
undefined

View File

@ -19,7 +19,7 @@ let resizeTo;
// resizeTo. To be called by a method of the view being collected.
// Note that rab, values, resizeAfter, and resizeTo may need to be reset before
// calling this.
function ResizeBufferMidIteration(n) {
function ResizeMidIteration(n) {
CollectValuesAndResize(n, values, rab, resizeAfter, resizeTo);
return false;
}
@ -35,7 +35,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 2;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
assert.sameValue(Array.prototype.findLast.call(fixedLength, ResizeBufferMidIteration), undefined);
assert.sameValue(Array.prototype.findLast.call(fixedLength, ResizeMidIteration), undefined);
assert.compareArray(values, [
6,
4,
@ -49,7 +49,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 1;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
assert.sameValue(Array.prototype.findLast.call(fixedLengthWithOffset, ResizeBufferMidIteration), undefined);
assert.sameValue(Array.prototype.findLast.call(fixedLengthWithOffset, ResizeMidIteration), undefined);
assert.compareArray(values, [
6,
4
@ -61,7 +61,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 2;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
assert.sameValue(Array.prototype.findLast.call(lengthTracking, ResizeBufferMidIteration), undefined);
assert.sameValue(Array.prototype.findLast.call(lengthTracking, ResizeMidIteration), undefined);
assert.compareArray(values, [
6,
4,
@ -75,7 +75,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 1;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
assert.sameValue(Array.prototype.findLast.call(lengthTrackingWithOffset, ResizeBufferMidIteration), undefined);
assert.sameValue(Array.prototype.findLast.call(lengthTrackingWithOffset, ResizeMidIteration), undefined);
assert.compareArray(values, [
6,
4

View File

@ -19,7 +19,7 @@ let resizeTo;
// resizeTo. To be called by a method of the view being collected.
// Note that rab, values, resizeAfter, and resizeTo may need to be reset before
// calling this.
function ResizeBufferMidIteration(n) {
function ResizeMidIteration(n) {
CollectValuesAndResize(n, values, rab, resizeAfter, resizeTo);
return false;
}
@ -36,7 +36,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 2;
resizeTo = 3 * ctor.BYTES_PER_ELEMENT;
assert.sameValue(Array.prototype.findLast.call(fixedLength, ResizeBufferMidIteration), undefined);
assert.sameValue(Array.prototype.findLast.call(fixedLength, ResizeMidIteration), undefined);
assert.compareArray(values, [
6,
4,
@ -50,7 +50,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 1;
resizeTo = 3 * ctor.BYTES_PER_ELEMENT;
assert.sameValue(Array.prototype.findLast.call(fixedLengthWithOffset, ResizeBufferMidIteration), undefined);
assert.sameValue(Array.prototype.findLast.call(fixedLengthWithOffset, ResizeMidIteration), undefined);
assert.compareArray(values, [
6,
undefined
@ -62,7 +62,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 2;
resizeTo = 3 * ctor.BYTES_PER_ELEMENT;
assert.sameValue(Array.prototype.findLast.call(lengthTracking, ResizeBufferMidIteration), undefined);
assert.sameValue(Array.prototype.findLast.call(lengthTracking, ResizeMidIteration), undefined);
assert.compareArray(values, [
6,
4,
@ -76,7 +76,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 1;
resizeTo = 3 * ctor.BYTES_PER_ELEMENT;
assert.sameValue(Array.prototype.findLast.call(lengthTrackingWithOffset, ResizeBufferMidIteration), undefined);
assert.sameValue(Array.prototype.findLast.call(lengthTrackingWithOffset, ResizeMidIteration), undefined);
assert.compareArray(values, [
6,
4

View File

@ -19,7 +19,7 @@ let resizeTo;
// resizeTo. To be called by a method of the view being collected.
// Note that rab, values, resizeAfter, and resizeTo may need to be reset before
// calling this.
function ResizeBufferMidIteration(n) {
function ResizeMidIteration(n) {
CollectValuesAndResize(n, values, rab, resizeAfter, resizeTo);
return false;
}
@ -35,7 +35,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 2;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
assert.sameValue(Array.prototype.findLastIndex.call(fixedLength, ResizeBufferMidIteration), -1);
assert.sameValue(Array.prototype.findLastIndex.call(fixedLength, ResizeMidIteration), -1);
assert.compareArray(values, [
6,
4,
@ -49,7 +49,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 1;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
assert.sameValue(Array.prototype.findLastIndex.call(fixedLengthWithOffset, ResizeBufferMidIteration), -1);
assert.sameValue(Array.prototype.findLastIndex.call(fixedLengthWithOffset, ResizeMidIteration), -1);
assert.compareArray(values, [
6,
4
@ -61,7 +61,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 2;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
assert.sameValue(Array.prototype.findLastIndex.call(lengthTracking, ResizeBufferMidIteration), -1);
assert.sameValue(Array.prototype.findLastIndex.call(lengthTracking, ResizeMidIteration), -1);
assert.compareArray(values, [
6,
4,
@ -75,7 +75,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 1;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
assert.sameValue(Array.prototype.findLastIndex.call(lengthTrackingWithOffset, ResizeBufferMidIteration), -1);
assert.sameValue(Array.prototype.findLastIndex.call(lengthTrackingWithOffset, ResizeMidIteration), -1);
assert.compareArray(values, [
6,
4

View File

@ -19,7 +19,7 @@ let resizeTo;
// resizeTo. To be called by a method of the view being collected.
// Note that rab, values, resizeAfter, and resizeTo may need to be reset before
// calling this.
function ResizeBufferMidIteration(n) {
function ResizeMidIteration(n) {
CollectValuesAndResize(n, values, rab, resizeAfter, resizeTo);
return false;
}
@ -35,7 +35,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 2;
resizeTo = 3 * ctor.BYTES_PER_ELEMENT;
assert.sameValue(Array.prototype.findLastIndex.call(fixedLength, ResizeBufferMidIteration), -1);
assert.sameValue(Array.prototype.findLastIndex.call(fixedLength, ResizeMidIteration), -1);
assert.compareArray(values, [
6,
4,
@ -49,7 +49,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 1;
resizeTo = 3 * ctor.BYTES_PER_ELEMENT;
assert.sameValue(Array.prototype.findLastIndex.call(fixedLengthWithOffset, ResizeBufferMidIteration), -1);
assert.sameValue(Array.prototype.findLastIndex.call(fixedLengthWithOffset, ResizeMidIteration), -1);
assert.compareArray(values, [
6,
undefined
@ -61,7 +61,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 2;
resizeTo = 3 * ctor.BYTES_PER_ELEMENT;
assert.sameValue(Array.prototype.findLastIndex.call(lengthTracking, ResizeBufferMidIteration), -1);
assert.sameValue(Array.prototype.findLastIndex.call(lengthTracking, ResizeMidIteration), -1);
assert.compareArray(values, [
6,
4,
@ -75,7 +75,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 1;
resizeTo = 2 * ctor.BYTES_PER_ELEMENT;
assert.sameValue(Array.prototype.findLastIndex.call(lengthTracking, ResizeBufferMidIteration), -1);
assert.sameValue(Array.prototype.findLastIndex.call(lengthTracking, ResizeMidIteration), -1);
assert.compareArray(values, [
6,
undefined,
@ -89,7 +89,7 @@ for (let ctor of ctors) {
values = [];
resizeAfter = 1;
resizeTo = 3 * ctor.BYTES_PER_ELEMENT;
assert.sameValue(Array.prototype.findLastIndex.call(lengthTrackingWithOffset, ResizeBufferMidIteration), -1);
assert.sameValue(Array.prototype.findLastIndex.call(lengthTrackingWithOffset, ResizeMidIteration), -1);
assert.compareArray(values, [
6,
4

View File

@ -0,0 +1,92 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.includes
description: >
Array.p.includes behaves correctly on TypedArrays backed by resizable buffers
that are resized during argument coercion.
includes: [resizableArrayBufferUtils.js]
features: [resizable-arraybuffer, Array.prototype.includes]
---*/
function MayNeedBigInt(ta, n) {
if (typeof n == 'number' && (ta instanceof BigInt64Array || ta instanceof BigUint64Array)) {
return BigInt(n);
}
return n;
}
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const fixedLength = new ctor(rab, 0, 4);
let evil = {
valueOf: () => {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
return 0;
}
};
assert(!Array.prototype.includes.call(fixedLength, undefined));
// The TA is OOB so it includes only "undefined".
assert(Array.prototype.includes.call(fixedLength, undefined, evil));
}
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const fixedLength = new ctor(rab, 0, 4);
let evil = {
valueOf: () => {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
return 0;
}
};
let n0 = MayNeedBigInt(fixedLength, 0);
assert(Array.prototype.includes.call(fixedLength, n0));
// The TA is OOB so it includes only "undefined".
assert(!Array.prototype.includes.call(fixedLength, n0, evil));
}
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const lengthTracking = new ctor(rab);
let evil = {
valueOf: () => {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
return 0;
}
};
assert(!Array.prototype.includes.call(lengthTracking, undefined));
// "includes" iterates until the original length and sees "undefined"s.
assert(Array.prototype.includes.call(lengthTracking, undefined, evil));
}
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const lengthTracking = new ctor(rab);
for (let i = 0; i < 4; ++i) {
WriteToTypedArray(lengthTracking, i, 1);
}
let evil = {
valueOf: () => {
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
return 0;
}
};
let n0 = MayNeedBigInt(lengthTracking, 0);
assert(!Array.prototype.includes.call(lengthTracking, n0));
// The TA grew but we only look at the data until the original length.
assert(!Array.prototype.includes.call(lengthTracking, n0, evil));
}
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const lengthTracking = new ctor(rab);
WriteToTypedArray(lengthTracking, 0, 1);
let evil = {
valueOf: () => {
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
return -4;
}
};
let n1 = MayNeedBigInt(lengthTracking, 1);
assert(Array.prototype.includes.call(lengthTracking, n1, -4));
// The TA grew but the start index conversion is done based on the original
// length.
assert(Array.prototype.includes.call(lengthTracking, n1, evil));
}

View File

@ -0,0 +1,22 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-%array%.prototype.includes
description: >
Array.p.includes behaves correctly for special float values on float
TypedArrays backed by resizable buffers.
includes: [resizableArrayBufferUtils.js]
features: [resizable-arraybuffer, Array.prototype.includes]
---*/
for (let ctor of floatCtors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const lengthTracking = new ctor(rab);
lengthTracking[0] = -Infinity;
lengthTracking[1] = Infinity;
lengthTracking[2] = NaN;
assert(Array.prototype.includes.call(lengthTracking, -Infinity));
assert(Array.prototype.includes.call(lengthTracking, Infinity));
assert(Array.prototype.includes.call(lengthTracking, NaN));
}

View File

@ -0,0 +1,128 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.includes
description: >
Array.p.includes behaves correctly on TypedArrays backed by resizable buffers.
includes: [resizableArrayBufferUtils.js]
features: [resizable-arraybuffer, Array.prototype.includes]
---*/
function MayNeedBigInt(ta, n) {
if (typeof n == 'number' && (ta instanceof BigInt64Array || ta instanceof BigUint64Array)) {
return BigInt(n);
}
return n;
}
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const fixedLength = new ctor(rab, 0, 4);
const fixedLengthWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT, 2);
const lengthTracking = new ctor(rab, 0);
const lengthTrackingWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT);
// Write some data into the array.
const taWrite = new ctor(rab);
for (let i = 0; i < 4; ++i) {
WriteToTypedArray(taWrite, i, 2 * i);
}
// Orig. array: [0, 2, 4, 6]
// [0, 2, 4, 6] << fixedLength
// [4, 6] << fixedLengthWithOffset
// [0, 2, 4, 6, ...] << lengthTracking
// [4, 6, ...] << lengthTrackingWithOffset
// If fixedLength is a BigInt array, they all are BigInt Arrays.
let n2 = MayNeedBigInt(fixedLength, 2);
let n4 = MayNeedBigInt(fixedLength, 4);
assert(Array.prototype.includes.call(fixedLength, n2));
assert(!Array.prototype.includes.call(fixedLength, undefined));
assert(Array.prototype.includes.call(fixedLength, n2, 1));
assert(!Array.prototype.includes.call(fixedLength, n2, 2));
assert(Array.prototype.includes.call(fixedLength, n2, -3));
assert(!Array.prototype.includes.call(fixedLength, n2, -2));
assert(!Array.prototype.includes.call(fixedLengthWithOffset, n2));
assert(Array.prototype.includes.call(fixedLengthWithOffset, n4));
assert(!Array.prototype.includes.call(fixedLengthWithOffset, undefined));
assert(Array.prototype.includes.call(fixedLengthWithOffset, n4, 0));
assert(!Array.prototype.includes.call(fixedLengthWithOffset, n4, 1));
assert(Array.prototype.includes.call(fixedLengthWithOffset, n4, -2));
assert(!Array.prototype.includes.call(fixedLengthWithOffset, n4, -1));
assert(Array.prototype.includes.call(lengthTracking, n2));
assert(!Array.prototype.includes.call(lengthTracking, undefined));
assert(Array.prototype.includes.call(lengthTracking, n2, 1));
assert(!Array.prototype.includes.call(lengthTracking, n2, 2));
assert(Array.prototype.includes.call(lengthTracking, n2, -3));
assert(!Array.prototype.includes.call(lengthTracking, n2, -2));
assert(!Array.prototype.includes.call(lengthTrackingWithOffset, n2));
assert(Array.prototype.includes.call(lengthTrackingWithOffset, n4));
assert(!Array.prototype.includes.call(lengthTrackingWithOffset, undefined));
assert(Array.prototype.includes.call(lengthTrackingWithOffset, n4, 0));
assert(!Array.prototype.includes.call(lengthTrackingWithOffset, n4, 1));
assert(Array.prototype.includes.call(lengthTrackingWithOffset, n4, -2));
assert(!Array.prototype.includes.call(lengthTrackingWithOffset, n4, -1));
// Shrink so that fixed length TAs go out of bounds.
rab.resize(3 * ctor.BYTES_PER_ELEMENT);
// Orig. array: [0, 2, 4]
// [0, 2, 4, ...] << lengthTracking
// [4, ...] << lengthTrackingWithOffset
assert(!Array.prototype.includes.call(fixedLength, n2));
assert(!Array.prototype.includes.call(fixedLengthWithOffset, n2));
assert(Array.prototype.includes.call(lengthTracking, n2));
assert(!Array.prototype.includes.call(lengthTracking, undefined));
assert(!Array.prototype.includes.call(lengthTrackingWithOffset, n2));
assert(Array.prototype.includes.call(lengthTrackingWithOffset, n4));
assert(!Array.prototype.includes.call(lengthTrackingWithOffset, undefined));
// Shrink so that the TAs with offset go out of bounds.
rab.resize(1 * ctor.BYTES_PER_ELEMENT);
assert(!Array.prototype.includes.call(fixedLength, n2));
assert(!Array.prototype.includes.call(fixedLengthWithOffset, n2));
assert(!Array.prototype.includes.call(lengthTrackingWithOffset, n2));
// Shrink to zero.
rab.resize(0);
assert(!Array.prototype.includes.call(fixedLength, n2));
assert(!Array.prototype.includes.call(fixedLengthWithOffset, n2));
assert(!Array.prototype.includes.call(lengthTrackingWithOffset, n2));
assert(!Array.prototype.includes.call(lengthTracking, n2));
assert(!Array.prototype.includes.call(lengthTracking, undefined));
// Grow so that all TAs are back in-bounds.
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
for (let i = 0; i < 6; ++i) {
WriteToTypedArray(taWrite, i, 2 * i);
}
// Orig. array: [0, 2, 4, 6, 8, 10]
// [0, 2, 4, 6] << fixedLength
// [4, 6] << fixedLengthWithOffset
// [0, 2, 4, 6, 8, 10, ...] << lengthTracking
// [4, 6, 8, 10, ...] << lengthTrackingWithOffset
let n8 = MayNeedBigInt(fixedLength, 8);
assert(Array.prototype.includes.call(fixedLength, n2));
assert(!Array.prototype.includes.call(fixedLength, undefined));
assert(!Array.prototype.includes.call(fixedLength, n8));
assert(!Array.prototype.includes.call(fixedLengthWithOffset, n2));
assert(Array.prototype.includes.call(fixedLengthWithOffset, n4));
assert(!Array.prototype.includes.call(fixedLengthWithOffset, undefined));
assert(!Array.prototype.includes.call(fixedLengthWithOffset, n8));
assert(Array.prototype.includes.call(lengthTracking, n2));
assert(!Array.prototype.includes.call(lengthTracking, undefined));
assert(Array.prototype.includes.call(lengthTracking, n8));
assert(!Array.prototype.includes.call(lengthTrackingWithOffset, n2));
assert(Array.prototype.includes.call(lengthTrackingWithOffset, n4));
assert(!Array.prototype.includes.call(lengthTrackingWithOffset, undefined));
assert(Array.prototype.includes.call(lengthTrackingWithOffset, n8));
}

View File

@ -0,0 +1,55 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.indexof
description: >
Array.p.indexOf behaves correctly when the backing resizable buffer is grown
during argument coercion.
includes: [resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
function MayNeedBigInt(ta, n) {
if (typeof n == 'number' && (ta instanceof BigInt64Array || ta instanceof BigUint64Array)) {
return BigInt(n);
}
return n;
}
// Growing + length-tracking TA.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const lengthTracking = new ctor(rab);
for (let i = 0; i < 4; ++i) {
WriteToTypedArray(lengthTracking, i, 1);
}
let evil = {
valueOf: () => {
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
return 0;
}
};
let n0 = MayNeedBigInt(lengthTracking, 0);
assert.sameValue(Array.prototype.indexOf.call(lengthTracking, n0), -1);
// The TA grew but we only look at the data until the original length.
assert.sameValue(Array.prototype.indexOf.call(lengthTracking, n0, evil), -1);
}
// Growing + length-tracking TA, index conversion.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const lengthTracking = new ctor(rab);
WriteToTypedArray(lengthTracking, 0, 1);
let evil = {
valueOf: () => {
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
return -4;
}
};
let n1 = MayNeedBigInt(lengthTracking, 1);
assert.sameValue(Array.prototype.indexOf.call(lengthTracking, n1, -4), 0);
// The TA grew but the start index conversion is done based on the original
// length.
assert.sameValue(Array.prototype.indexOf.call(lengthTracking, n1, evil), 0);
}

View File

@ -0,0 +1,67 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.indexof
description: >
Array.p.indexOf behaves correctly when the backing resizable buffer is shrunk
during argument coercion.
includes: [resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
function MayNeedBigInt(ta, n) {
if (typeof n == 'number' && (ta instanceof BigInt64Array || ta instanceof BigUint64Array)) {
return BigInt(n);
}
return n;
}
// Shrinking + fixed-length TA.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const fixedLength = new ctor(rab, 0, 4);
let evil = {
valueOf: () => {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
return 0;
}
};
let n0 = MayNeedBigInt(fixedLength, 0);
assert.sameValue(Array.prototype.indexOf.call(fixedLength, n0), 0);
// The TA is OOB so indexOf returns -1.
assert.sameValue(Array.prototype.indexOf.call(fixedLength, n0, evil), -1);
}
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const fixedLength = new ctor(rab, 0, 4);
let evil = {
valueOf: () => {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
return 0;
}
};
let n0 = MayNeedBigInt(fixedLength, 0);
assert.sameValue(Array.prototype.indexOf.call(fixedLength, n0), 0);
// The TA is OOB so indexOf returns -1, also for undefined).
assert.sameValue(Array.prototype.indexOf.call(fixedLength, undefined, evil), -1);
}
// Shrinking + length-tracking TA.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const lengthTracking = new ctor(rab);
for (let i = 0; i < 4; ++i) {
WriteToTypedArray(lengthTracking, i, i);
}
let evil = {
valueOf: () => {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
return 0;
}
};
let n2 = MayNeedBigInt(lengthTracking, 2);
assert.sameValue(Array.prototype.indexOf.call(lengthTracking, n2), 2);
// 2 no longer found.
assert.sameValue(Array.prototype.indexOf.call(lengthTracking, n2, evil), -1);
}

View File

@ -0,0 +1,26 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-%array%.prototype.indexof
description: >
Array.p.indexOf behaves correctly for special float values on TypedArrays
backed by resizable buffers.
includes: [resizableArrayBufferUtils.js]
features: [resizable-arraybuffer, Array.prototype.includes]
---*/
for (let ctor of floatCtors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const lengthTracking = new ctor(rab);
lengthTracking[0] = -Infinity;
lengthTracking[1] = -Infinity;
lengthTracking[2] = Infinity;
lengthTracking[3] = Infinity;
lengthTracking[4] = NaN;
lengthTracking[5] = NaN;
assert.sameValue(Array.prototype.indexOf.call(lengthTracking, -Infinity), 0);
assert.sameValue(Array.prototype.indexOf.call(lengthTracking, Infinity), 2);
// NaN is never found.
assert.sameValue(Array.prototype.indexOf.call(lengthTracking, NaN), -1);
}

View File

@ -0,0 +1,126 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.indexof
description: >
Array.p.indexOf behaves correctly on TypedArrays backed by resizable buffers.
includes: [resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
function MayNeedBigInt(ta, n) {
if (typeof n == 'number' && (ta instanceof BigInt64Array || ta instanceof BigUint64Array)) {
return BigInt(n);
}
return n;
}
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const fixedLength = new ctor(rab, 0, 4);
const fixedLengthWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT, 2);
const lengthTracking = new ctor(rab, 0);
const lengthTrackingWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT);
// Write some data into the array.
const taWrite = new ctor(rab);
for (let i = 0; i < 4; ++i) {
WriteToTypedArray(taWrite, i, Math.floor(i / 2));
}
// Orig. array: [0, 0, 1, 1]
// [0, 0, 1, 1] << fixedLength
// [1, 1] << fixedLengthWithOffset
// [0, 0, 1, 1, ...] << lengthTracking
// [1, 1, ...] << lengthTrackingWithOffset
// If fixedLength is a BigInt array, they all are BigInt Arrays.
let n0 = MayNeedBigInt(fixedLength, 0);
let n1 = MayNeedBigInt(fixedLength, 1);
assert.sameValue(Array.prototype.indexOf.call(fixedLength, n0), 0);
assert.sameValue(Array.prototype.indexOf.call(fixedLength, n0, 1), 1);
assert.sameValue(Array.prototype.indexOf.call(fixedLength, n0, 2), -1);
assert.sameValue(Array.prototype.indexOf.call(fixedLength, n0, -2), -1);
assert.sameValue(Array.prototype.indexOf.call(fixedLength, n0, -3), 1);
assert.sameValue(Array.prototype.indexOf.call(fixedLength, n1, 1), 2);
assert.sameValue(Array.prototype.indexOf.call(fixedLength, n1, -3), 2);
assert.sameValue(Array.prototype.indexOf.call(fixedLength, n1, -2), 2);
assert.sameValue(Array.prototype.indexOf.call(fixedLength, undefined), -1);
assert.sameValue(Array.prototype.indexOf.call(fixedLengthWithOffset, n0), -1);
assert.sameValue(Array.prototype.indexOf.call(fixedLengthWithOffset, n1), 0);
assert.sameValue(Array.prototype.indexOf.call(fixedLengthWithOffset, n1, -2), 0);
assert.sameValue(Array.prototype.indexOf.call(fixedLengthWithOffset, n1, -1), 1);
assert.sameValue(Array.prototype.indexOf.call(fixedLengthWithOffset, undefined), -1);
assert.sameValue(Array.prototype.indexOf.call(lengthTracking, n0), 0);
assert.sameValue(Array.prototype.indexOf.call(lengthTracking, n0, 2), -1);
assert.sameValue(Array.prototype.indexOf.call(lengthTracking, n1, -3), 2);
assert.sameValue(Array.prototype.indexOf.call(lengthTracking, undefined), -1);
assert.sameValue(Array.prototype.indexOf.call(lengthTrackingWithOffset, n0), -1);
assert.sameValue(Array.prototype.indexOf.call(lengthTrackingWithOffset, n1), 0);
assert.sameValue(Array.prototype.indexOf.call(lengthTrackingWithOffset, n1, 1), 1);
assert.sameValue(Array.prototype.indexOf.call(lengthTrackingWithOffset, n1, -2), 0);
assert.sameValue(Array.prototype.indexOf.call(lengthTrackingWithOffset, undefined), -1);
// Shrink so that fixed length TAs go out of bounds.
rab.resize(3 * ctor.BYTES_PER_ELEMENT);
// Orig. array: [0, 0, 1]
// [0, 0, 1, ...] << lengthTracking
// [1, ...] << lengthTrackingWithOffset
assert.sameValue(Array.prototype.indexOf.call(fixedLength, n1), -1);
assert.sameValue(Array.prototype.indexOf.call(fixedLengthWithOffset, n1), -1);
assert.sameValue(Array.prototype.indexOf.call(lengthTracking, n1), 2);
assert.sameValue(Array.prototype.indexOf.call(lengthTracking, undefined), -1);
assert.sameValue(Array.prototype.indexOf.call(lengthTrackingWithOffset, n0), -1);
assert.sameValue(Array.prototype.indexOf.call(lengthTrackingWithOffset, n1), 0);
assert.sameValue(Array.prototype.indexOf.call(lengthTrackingWithOffset, undefined), -1);
// Shrink so that the TAs with offset go out of bounds.
rab.resize(1 * ctor.BYTES_PER_ELEMENT);
assert.sameValue(Array.prototype.indexOf.call(fixedLength, n0), -1);
assert.sameValue(Array.prototype.indexOf.call(fixedLengthWithOffset, n0), -1);
assert.sameValue(Array.prototype.indexOf.call(lengthTrackingWithOffset, n0), -1);
assert.sameValue(Array.prototype.indexOf.call(lengthTracking, n0), 0);
// Shrink to zero.
rab.resize(0);
assert.sameValue(Array.prototype.indexOf.call(fixedLength, n0), -1);
assert.sameValue(Array.prototype.indexOf.call(fixedLengthWithOffset, n0), -1);
assert.sameValue(Array.prototype.indexOf.call(lengthTrackingWithOffset, n0), -1);
assert.sameValue(Array.prototype.indexOf.call(lengthTracking, n0), -1);
assert.sameValue(Array.prototype.indexOf.call(lengthTracking, undefined), -1);
// Grow so that all TAs are back in-bounds.
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
for (let i = 0; i < 6; ++i) {
WriteToTypedArray(taWrite, i, Math.floor(i / 2));
}
// Orig. array: [0, 0, 1, 1, 2, 2]
// [0, 0, 1, 1] << fixedLength
// [1, 1] << fixedLengthWithOffset
// [0, 0, 1, 1, 2, 2, ...] << lengthTracking
// [1, 1, 2, 2, ...] << lengthTrackingWithOffset
let n2 = MayNeedBigInt(fixedLength, 2);
assert.sameValue(Array.prototype.indexOf.call(fixedLength, n1), 2);
assert.sameValue(Array.prototype.indexOf.call(fixedLength, n2), -1);
assert.sameValue(Array.prototype.indexOf.call(fixedLength, undefined), -1);
assert.sameValue(Array.prototype.indexOf.call(fixedLengthWithOffset, n0), -1);
assert.sameValue(Array.prototype.indexOf.call(fixedLengthWithOffset, n1), 0);
assert.sameValue(Array.prototype.indexOf.call(fixedLengthWithOffset, n2), -1);
assert.sameValue(Array.prototype.indexOf.call(fixedLengthWithOffset, undefined), -1);
assert.sameValue(Array.prototype.indexOf.call(lengthTracking, n1), 2);
assert.sameValue(Array.prototype.indexOf.call(lengthTracking, n2), 4);
assert.sameValue(Array.prototype.indexOf.call(lengthTracking, undefined), -1);
assert.sameValue(Array.prototype.indexOf.call(lengthTrackingWithOffset, n0), -1);
assert.sameValue(Array.prototype.indexOf.call(lengthTrackingWithOffset, n1), 0);
assert.sameValue(Array.prototype.indexOf.call(lengthTrackingWithOffset, n2), 2);
assert.sameValue(Array.prototype.indexOf.call(lengthTrackingWithOffset, undefined), -1);
}

View File

@ -0,0 +1,38 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.join
description: >
Array.p.join behaves correctly when the receiver is grown during
argument coercion
includes: [resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
// Growing + fixed-length TA.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const fixedLength = new ctor(rab, 0, 4);
let evil = {
toString: () => {
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
return '.';
}
};
assert.sameValue(Array.prototype.join.call(fixedLength, evil), '0.0.0.0');
}
// Growing + length-tracking TA.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const lengthTracking = new ctor(rab);
let evil = {
toString: () => {
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
return '.';
}
};
// We iterate 4 elements, since it was the starting length.
assert.sameValue(Array.prototype.join.call(lengthTracking, evil), '0.0.0.0');
}

View File

@ -0,0 +1,42 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.join
description: >
Array.p.join behaves correctly when the receiver is shrunk during
argument coercion
includes: [resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
// Shrinking + fixed-length TA.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const fixedLength = new ctor(rab, 0, 4);
let evil = {
toString: () => {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
return '.';
}
};
// We iterate 4 elements, since it was the starting length, but the TA is
// OOB right after parameter conversion, so all elements are converted to
// the empty string.
assert.sameValue(Array.prototype.join.call(fixedLength, evil), '...');
}
// Shrinking + length-tracking TA.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const lengthTracking = new ctor(rab);
let evil = {
toString: () => {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
return '.';
}
};
// We iterate 4 elements, since it was the starting length. Elements beyond
// the new length are converted to the empty string.
assert.sameValue(Array.prototype.join.call(lengthTracking, evil), '0.0..');
}

View File

@ -0,0 +1,82 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.join
description: >
Array.p.join behaves correctly when the receiver is backed by resizable
buffer
includes: [resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const fixedLength = new ctor(rab, 0, 4);
const fixedLengthWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT, 2);
const lengthTracking = new ctor(rab, 0);
const lengthTrackingWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT);
const taWrite = new ctor(rab);
// Write some data into the array.
for (let i = 0; i < 4; ++i) {
WriteToTypedArray(taWrite, i, 2 * i);
}
// Orig. array: [0, 2, 4, 6]
// [0, 2, 4, 6] << fixedLength
// [4, 6] << fixedLengthWithOffset
// [0, 2, 4, 6, ...] << lengthTracking
// [4, 6, ...] << lengthTrackingWithOffset
assert.sameValue(Array.prototype.join.call(fixedLength), '0,2,4,6');
assert.sameValue(Array.prototype.join.call(fixedLengthWithOffset), '4,6');
assert.sameValue(Array.prototype.join.call(lengthTracking), '0,2,4,6');
assert.sameValue(Array.prototype.join.call(lengthTrackingWithOffset), '4,6');
// Shrink so that fixed length TAs go out of bounds.
rab.resize(3 * ctor.BYTES_PER_ELEMENT);
// Orig. array: [0, 2, 4]
// [0, 2, 4, ...] << lengthTracking
// [4, ...] << lengthTrackingWithOffset
assert.sameValue(Array.prototype.join.call(fixedLength), '');
assert.sameValue(Array.prototype.join.call(fixedLengthWithOffset), '');
assert.sameValue(Array.prototype.join.call(lengthTracking), '0,2,4');
assert.sameValue(Array.prototype.join.call(lengthTrackingWithOffset), '4');
// Shrink so that the TAs with offset go out of bounds.
rab.resize(1 * ctor.BYTES_PER_ELEMENT);
assert.sameValue(Array.prototype.join.call(fixedLength), '');
assert.sameValue(Array.prototype.join.call(fixedLengthWithOffset), '');
assert.sameValue(Array.prototype.join.call(lengthTrackingWithOffset), '');
assert.sameValue(Array.prototype.join.call(lengthTracking), '0');
// Shrink to zero.
rab.resize(0);
assert.sameValue(Array.prototype.join.call(fixedLength), '');
assert.sameValue(Array.prototype.join.call(fixedLengthWithOffset), '');
assert.sameValue(Array.prototype.join.call(lengthTrackingWithOffset), '');
assert.sameValue(Array.prototype.join.call(lengthTracking), '');
// Grow so that all TAs are back in-bounds.
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
for (let i = 0; i < 6; ++i) {
WriteToTypedArray(taWrite, i, 2 * i);
}
// Orig. array: [0, 2, 4, 6, 8, 10]
// [0, 2, 4, 6] << fixedLength
// [4, 6] << fixedLengthWithOffset
// [0, 2, 4, 6, 8, 10, ...] << lengthTracking
// [4, 6, 8, 10, ...] << lengthTrackingWithOffset
assert.sameValue(Array.prototype.join.call(fixedLength), '0,2,4,6');
assert.sameValue(Array.prototype.join.call(fixedLengthWithOffset), '4,6');
assert.sameValue(Array.prototype.join.call(lengthTracking), '0,2,4,6,8,10');
assert.sameValue(Array.prototype.join.call(lengthTrackingWithOffset), '4,6,8,10');
}

View File

@ -0,0 +1,60 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.keys
description: >
Array.p.keys behaves correctly when receiver is backed by a resizable
buffer and is grown mid-iteration
features: [resizable-arraybuffer]
includes: [compareArray.js, resizableArrayBufferUtils.js]
---*/
// Orig. array: [0, 2, 4, 6]
// [0, 2, 4, 6] << fixedLength
// [4, 6] << fixedLengthWithOffset
// [0, 2, 4, 6, ...] << lengthTracking
// [4, 6, ...] << lengthTrackingWithOffset
for (let ctor of ctors) {
const rab = CreateRabForTest(ctor);
const fixedLength = new ctor(rab, 0, 4);
// The fixed length array is not affected by resizing.
TestIterationAndResize(Array.prototype.keys.call(fixedLength), [
0,
1,
2,
3
], rab, 2, 6 * ctor.BYTES_PER_ELEMENT);
}
for (let ctor of ctors) {
const rab = CreateRabForTest(ctor);
const fixedLengthWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT, 2);
// The fixed length array is not affected by resizing.
TestIterationAndResize(Array.prototype.keys.call(fixedLengthWithOffset), [
0,
1
], rab, 2, 6 * ctor.BYTES_PER_ELEMENT);
}
for (let ctor of ctors) {
const rab = CreateRabForTest(ctor);
const lengthTracking = new ctor(rab, 0);
TestIterationAndResize(Array.prototype.keys.call(lengthTracking), [
0,
1,
2,
3,
4,
5
], rab, 2, 6 * ctor.BYTES_PER_ELEMENT);
}
for (let ctor of ctors) {
const rab = CreateRabForTest(ctor);
const lengthTrackingWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT);
TestIterationAndResize(Array.prototype.keys.call(lengthTrackingWithOffset), [
0,
1,
2,
3
], rab, 2, 6 * ctor.BYTES_PER_ELEMENT);
}

View File

@ -0,0 +1,53 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.keys
description: >
Array.p.keys behaves correctly when receiver is backed by resizable
buffer that is shrunk mid-iteration
features: [resizable-arraybuffer]
includes: [compareArray.js, resizableArrayBufferUtils.js]
---*/
// Orig. array: [0, 2, 4, 6]
// [0, 2, 4, 6] << fixedLength
// [4, 6] << fixedLengthWithOffset
// [0, 2, 4, 6, ...] << lengthTracking
// [4, 6, ...] << lengthTrackingWithOffset
for (let ctor of ctors) {
const rab = CreateRabForTest(ctor);
const fixedLength = new ctor(rab, 0, 4);
// The fixed length array goes out of bounds when the RAB is resized.
assert.throws(TypeError, () => {
TestIterationAndResize(Array.prototype.keys.call(fixedLength), null, rab, 2, 3 * ctor.BYTES_PER_ELEMENT);
});
}
for (let ctor of ctors) {
const rab = CreateRabForTest(ctor);
const fixedLengthWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT, 2);
// The fixed length array goes out of bounds when the RAB is resized.
assert.throws(TypeError, () => {
TestIterationAndResize(Array.prototype.keys.call(fixedLengthWithOffset), null, rab, 2, 3 * ctor.BYTES_PER_ELEMENT);
});
}
for (let ctor of ctors) {
const rab = CreateRabForTest(ctor);
const lengthTracking = new ctor(rab, 0);
TestIterationAndResize(Array.prototype.keys.call(lengthTracking), [
0,
1,
2
], rab, 2, 3 * ctor.BYTES_PER_ELEMENT);
}
for (let ctor of ctors) {
const rab = CreateRabForTest(ctor);
const lengthTrackingWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT);
TestIterationAndResize(Array.prototype.keys.call(lengthTrackingWithOffset), [
0,
1
], rab, 2, 3 * ctor.BYTES_PER_ELEMENT);
}

View File

@ -0,0 +1,142 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.keys
description: >
Array.p.keys behaves correctly when receiver is backed by resizable
buffer
includes: [compareArray.js, resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const fixedLength = new ctor(rab, 0, 4);
const fixedLengthWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT, 2);
const lengthTracking = new ctor(rab, 0);
const lengthTrackingWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT);
// Write some data into the array.
const taWrite = new ctor(rab);
for (let i = 0; i < 4; ++i) {
WriteToTypedArray(taWrite, i, 2 * i);
}
assert.compareArray(Array.from(Array.prototype.keys.call(fixedLength)), [
0,
1,
2,
3
]);
assert.compareArray(Array.from(Array.prototype.keys.call(fixedLengthWithOffset)), [
0,
1
]);
assert.compareArray(Array.from(Array.prototype.keys.call(lengthTracking)), [
0,
1,
2,
3
]);
assert.compareArray(Array.from(Array.prototype.keys.call(lengthTrackingWithOffset)), [
0,
1
]);
// Shrink so that fixed length TAs go out of bounds.
rab.resize(3 * ctor.BYTES_PER_ELEMENT);
// Orig. array: [0, 2, 4]
// [0, 2, 4, ...] << lengthTracking
// [4, ...] << lengthTrackingWithOffset
// TypedArray.prototype.{entries, keys, values} throw right away when
// called. Array.prototype.{entries, keys, values} don't throw, but when
// we try to iterate the returned ArrayIterator, that throws.
Array.prototype.keys.call(fixedLength);
Array.prototype.keys.call(fixedLengthWithOffset);
assert.throws(TypeError, () => {
Array.from(Array.prototype.keys.call(fixedLength));
});
assert.throws(TypeError, () => {
Array.from(Array.prototype.keys.call(fixedLengthWithOffset));
});
assert.compareArray(Array.from(Array.prototype.keys.call(lengthTracking)), [
0,
1,
2
]);
assert.compareArray(Array.from(Array.prototype.keys.call(lengthTrackingWithOffset)), [0]);
// Shrink so that the TAs with offset go out of bounds.
rab.resize(1 * ctor.BYTES_PER_ELEMENT);
Array.prototype.keys.call(fixedLength);
Array.prototype.keys.call(fixedLengthWithOffset);
Array.prototype.keys.call(lengthTrackingWithOffset);
assert.throws(TypeError, () => {
Array.from(Array.prototype.keys.call(fixedLength));
});
assert.throws(TypeError, () => {
Array.from(Array.prototype.keys.call(fixedLengthWithOffset));
});
assert.throws(TypeError, () => {
Array.from(Array.prototype.keys.call(lengthTrackingWithOffset));
});
assert.compareArray(Array.from(Array.prototype.keys.call(lengthTracking)), [0]);
// Shrink to zero.
rab.resize(0);
Array.prototype.keys.call(fixedLength);
Array.prototype.keys.call(fixedLengthWithOffset);
Array.prototype.keys.call(lengthTrackingWithOffset);
assert.throws(TypeError, () => {
Array.from(Array.prototype.keys.call(fixedLength));
});
assert.throws(TypeError, () => {
Array.from(Array.prototype.keys.call(fixedLengthWithOffset));
});
assert.throws(TypeError, () => {
Array.from(Array.prototype.keys.call(lengthTrackingWithOffset));
});
assert.compareArray(Array.from(Array.prototype.keys.call(lengthTracking)), []);
// Grow so that all TAs are back in-bounds.
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
for (let i = 0; i < 6; ++i) {
WriteToTypedArray(taWrite, i, 2 * i);
}
// Orig. array: [0, 2, 4, 6, 8, 10]
// [0, 2, 4, 6] << fixedLength
// [4, 6] << fixedLengthWithOffset
// [0, 2, 4, 6, 8, 10, ...] << lengthTracking
// [4, 6, 8, 10, ...] << lengthTrackingWithOffset
assert.compareArray(Array.from(Array.prototype.keys.call(fixedLength)), [
0,
1,
2,
3
]);
assert.compareArray(Array.from(Array.prototype.keys.call(fixedLengthWithOffset)), [
0,
1
]);
assert.compareArray(Array.from(Array.prototype.keys.call(lengthTracking)), [
0,
1,
2,
3,
4,
5
]);
assert.compareArray(Array.from(Array.prototype.keys.call(lengthTrackingWithOffset)), [
0,
1,
2,
3
]);
}

View File

@ -0,0 +1,57 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.lastindexof
description: >
Array.p.lastIndexOf behaves correctly when the resizable buffer is grown by
argument coercion.
includes: [resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
function MayNeedBigInt(ta, n) {
if (typeof n == 'number' && (ta instanceof BigInt64Array || ta instanceof BigUint64Array)) {
return BigInt(n);
}
return n;
}
// Growing + length-tracking TA.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const lengthTracking = new ctor(rab);
for (let i = 0; i < 4; ++i) {
WriteToTypedArray(lengthTracking, i, 1);
}
let evil = {
valueOf: () => {
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
return -1;
}
};
let n0 = MayNeedBigInt(lengthTracking, 0);
assert.sameValue(Array.prototype.lastIndexOf.call(lengthTracking, n0), -1);
// Because lastIndexOf iterates from the given index downwards, it's not
// possible to test that "we only look at the data until the original
// length" without also testing that the index conversion happening with the
// original length.
assert.sameValue(Array.prototype.lastIndexOf.call(lengthTracking, n0, evil), -1);
}
// Growing + length-tracking TA, index conversion.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const lengthTracking = new ctor(rab);
let evil = {
valueOf: () => {
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
return -4;
}
};
let n0 = MayNeedBigInt(lengthTracking, 0);
assert.sameValue(Array.prototype.lastIndexOf.call(lengthTracking, n0, -4), 0);
// The TA grew but the start index conversion is done based on the original
// length.
assert.sameValue(Array.prototype.lastIndexOf.call(lengthTracking, n0, evil), 0);
}

View File

@ -0,0 +1,66 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.lastindexof
description: >
Array.p.lastIndexOf behaves correctly when the resizable buffer is shrunk by
argument coercion.
includes: [resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
function MayNeedBigInt(ta, n) {
if (typeof n == 'number' && (ta instanceof BigInt64Array || ta instanceof BigUint64Array)) {
return BigInt(n);
}
return n;
}
// Shrinking + fixed-length TA.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const fixedLength = new ctor(rab, 0, 4);
let evil = {
valueOf: () => {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
return 2;
}
};
let n = MayNeedBigInt(fixedLength, 0);
assert.sameValue(Array.prototype.lastIndexOf.call(fixedLength, n), 3);
// The TA is OOB so lastIndexOf returns -1.
assert.sameValue(Array.prototype.lastIndexOf.call(fixedLength, n, evil), -1);
}
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const fixedLength = new ctor(rab, 0, 4);
let evil = {
valueOf: () => {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
return 2;
}
};
assert.sameValue(Array.prototype.lastIndexOf.call(fixedLength, MayNeedBigInt(fixedLength, 0)), 3);
// The TA is OOB so lastIndexOf returns -1, also for undefined).
assert.sameValue(Array.prototype.lastIndexOf.call(fixedLength, undefined, evil), -1);
}
// Shrinking + length-tracking TA.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const lengthTracking = new ctor(rab);
for (let i = 0; i < 4; ++i) {
WriteToTypedArray(lengthTracking, i, i);
}
let evil = {
valueOf: () => {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
return 2;
}
};
let n = MayNeedBigInt(lengthTracking, 2);
assert.sameValue(Array.prototype.lastIndexOf.call(lengthTracking, n), 2);
// 2 no longer found.
assert.sameValue(Array.prototype.lastIndexOf.call(lengthTracking, n, evil), -1);
}

View File

@ -0,0 +1,132 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.lastindexof
description: >
Array.p.lastIndexOf behaves correctly on TypedArrays backed by resizable
buffers.
includes: [resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
function MayNeedBigInt(ta, n) {
if (typeof n == 'number' && (ta instanceof BigInt64Array || ta instanceof BigUint64Array)) {
return BigInt(n);
}
return n;
}
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const fixedLength = new ctor(rab, 0, 4);
const fixedLengthWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT, 2);
const lengthTracking = new ctor(rab, 0);
const lengthTrackingWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT);
// Write some data into the array.
const taWrite = new ctor(rab);
for (let i = 0; i < 4; ++i) {
WriteToTypedArray(taWrite, i, Math.floor(i / 2));
}
// Orig. array: [0, 0, 1, 1]
// [0, 0, 1, 1] << fixedLength
// [1, 1] << fixedLengthWithOffset
// [0, 0, 1, 1, ...] << lengthTracking
// [1, 1, ...] << lengthTrackingWithOffset
// If fixedLength is a BigInt array, they all are BigInt Arrays.
let n0 = MayNeedBigInt(fixedLength, 0);
let n1 = MayNeedBigInt(fixedLength, 1);
assert.sameValue(Array.prototype.lastIndexOf.call(fixedLength, n0), 1);
assert.sameValue(Array.prototype.lastIndexOf.call(fixedLength, n0, 1), 1);
assert.sameValue(Array.prototype.lastIndexOf.call(fixedLength, n0, 2), 1);
assert.sameValue(Array.prototype.lastIndexOf.call(fixedLength, n0, -2), 1);
assert.sameValue(Array.prototype.lastIndexOf.call(fixedLength, n0, -3), 1);
assert.sameValue(Array.prototype.lastIndexOf.call(fixedLength, n1, 1), -1);
assert.sameValue(Array.prototype.lastIndexOf.call(fixedLength, n1, -2), 2);
assert.sameValue(Array.prototype.lastIndexOf.call(fixedLength, n1, -3), -1);
assert.sameValue(Array.prototype.lastIndexOf.call(fixedLength, undefined), -1);
assert.sameValue(Array.prototype.lastIndexOf.call(fixedLengthWithOffset, n0), -1);
assert.sameValue(Array.prototype.lastIndexOf.call(fixedLengthWithOffset, n1), 1);
assert.sameValue(Array.prototype.lastIndexOf.call(fixedLengthWithOffset, n1, -2), 0);
assert.sameValue(Array.prototype.lastIndexOf.call(fixedLengthWithOffset, n1, -1), 1);
assert.sameValue(Array.prototype.lastIndexOf.call(fixedLengthWithOffset, undefined), -1);
assert.sameValue(Array.prototype.lastIndexOf.call(lengthTracking, n0), 1);
assert.sameValue(Array.prototype.lastIndexOf.call(lengthTracking, n0, 2), 1);
assert.sameValue(Array.prototype.lastIndexOf.call(lengthTracking, n0, -3), 1);
assert.sameValue(Array.prototype.lastIndexOf.call(lengthTracking, n1, 1), -1);
assert.sameValue(Array.prototype.lastIndexOf.call(lengthTracking, n1, 2), 2);
assert.sameValue(Array.prototype.lastIndexOf.call(lengthTracking, n1, -3), -1);
assert.sameValue(Array.prototype.lastIndexOf.call(lengthTracking, undefined), -1);
assert.sameValue(Array.prototype.lastIndexOf.call(lengthTrackingWithOffset, n0), -1);
assert.sameValue(Array.prototype.lastIndexOf.call(lengthTrackingWithOffset, n1), 1);
assert.sameValue(Array.prototype.lastIndexOf.call(lengthTrackingWithOffset, n1, 1), 1);
assert.sameValue(Array.prototype.lastIndexOf.call(lengthTrackingWithOffset, n1, -2), 0);
assert.sameValue(Array.prototype.lastIndexOf.call(lengthTrackingWithOffset, n1, -1), 1);
assert.sameValue(Array.prototype.lastIndexOf.call(lengthTrackingWithOffset, undefined), -1);
// Shrink so that fixed length TAs go out of bounds.
rab.resize(3 * ctor.BYTES_PER_ELEMENT);
// Orig. array: [0, 0, 1]
// [0, 0, 1, ...] << lengthTracking
// [1, ...] << lengthTrackingWithOffset
assert.sameValue(Array.prototype.lastIndexOf.call(fixedLength, n1), -1);
assert.sameValue(Array.prototype.lastIndexOf.call(fixedLengthWithOffset, n1), -1);
assert.sameValue(Array.prototype.lastIndexOf.call(lengthTracking, n0), 1);
assert.sameValue(Array.prototype.lastIndexOf.call(lengthTracking, undefined), -1);
assert.sameValue(Array.prototype.lastIndexOf.call(lengthTrackingWithOffset, n0), -1);
assert.sameValue(Array.prototype.lastIndexOf.call(lengthTrackingWithOffset, n1), 0);
assert.sameValue(Array.prototype.lastIndexOf.call(lengthTrackingWithOffset, undefined), -1);
// Shrink so that the TAs with offset go out of bounds.
rab.resize(1 * ctor.BYTES_PER_ELEMENT);
assert.sameValue(Array.prototype.lastIndexOf.call(fixedLength, n0), -1);
assert.sameValue(Array.prototype.lastIndexOf.call(fixedLengthWithOffset, n0), -1);
assert.sameValue(Array.prototype.lastIndexOf.call(lengthTrackingWithOffset, n0), -1);
assert.sameValue(Array.prototype.lastIndexOf.call(lengthTracking, n0), 0);
// Shrink to zero.
rab.resize(0);
assert.sameValue(Array.prototype.lastIndexOf.call(fixedLength, n0), -1);
assert.sameValue(Array.prototype.lastIndexOf.call(fixedLengthWithOffset, n0), -1);
assert.sameValue(Array.prototype.lastIndexOf.call(lengthTrackingWithOffset, n0), -1);
assert.sameValue(Array.prototype.lastIndexOf.call(lengthTracking, n0), -1);
assert.sameValue(Array.prototype.lastIndexOf.call(lengthTracking, undefined), -1);
// Grow so that all TAs are back in-bounds.
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
for (let i = 0; i < 6; ++i) {
WriteToTypedArray(taWrite, i, Math.floor(i / 2));
}
// Orig. array: [0, 0, 1, 1, 2, 2]
// [0, 0, 1, 1] << fixedLength
// [1, 1] << fixedLengthWithOffset
// [0, 0, 1, 1, 2, 2, ...] << lengthTracking
// [1, 1, 2, 2, ...] << lengthTrackingWithOffset
let n2 = MayNeedBigInt(fixedLength, 2);
assert.sameValue(Array.prototype.lastIndexOf.call(fixedLength, n1), 3);
assert.sameValue(Array.prototype.lastIndexOf.call(fixedLength, n2), -1);
assert.sameValue(Array.prototype.lastIndexOf.call(fixedLength, undefined), -1);
assert.sameValue(Array.prototype.lastIndexOf.call(fixedLengthWithOffset, n0), -1);
assert.sameValue(Array.prototype.lastIndexOf.call(fixedLengthWithOffset, n1), 1);
assert.sameValue(Array.prototype.lastIndexOf.call(fixedLengthWithOffset, n2), -1);
assert.sameValue(Array.prototype.lastIndexOf.call(fixedLengthWithOffset, undefined), -1);
assert.sameValue(Array.prototype.lastIndexOf.call(lengthTracking, n1), 3);
assert.sameValue(Array.prototype.lastIndexOf.call(lengthTracking, n2), 5);
assert.sameValue(Array.prototype.lastIndexOf.call(lengthTracking, undefined), -1);
assert.sameValue(Array.prototype.lastIndexOf.call(lengthTrackingWithOffset, n0), -1);
assert.sameValue(Array.prototype.lastIndexOf.call(lengthTrackingWithOffset, n1), 1);
assert.sameValue(Array.prototype.lastIndexOf.call(lengthTrackingWithOffset, n2), 3);
assert.sameValue(Array.prototype.lastIndexOf.call(lengthTrackingWithOffset, undefined), -1);
}

View File

@ -0,0 +1,82 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.map
description: >
Array.p.map behaves correctly when the resizable buffer is grown mid-iteration.
includes: [compareArray.js, resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
let values;
let rab;
let resizeAfter;
let resizeTo;
// Collects the view of the resizable array buffer rab into values, with an
// iteration during which, after resizeAfter steps, rab is resized to length
// resizeTo. To be called by a method of the view being collected.
// Note that rab, values, resizeAfter, and resizeTo may need to be reset
// before calling this.
function ResizeMidIteration(n) {
CollectValuesAndResize(n, values, rab, resizeAfter, resizeTo);
return n;
}
// Orig. array: [0, 2, 4, 6]
// [0, 2, 4, 6] << fixedLength
// [4, 6] << fixedLengthWithOffset
// [0, 2, 4, 6, ...] << lengthTracking
// [4, 6, ...] << lengthTrackingWithOffset
for (let ctor of ctors) {
values = [];
rab = CreateRabForTest(ctor);
const fixedLength = new ctor(rab, 0, 4);
resizeAfter = 2;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
Array.prototype.map.call(fixedLength, ResizeMidIteration);
assert.compareArray(values, [
0,
2,
4,
6
]);
}
for (let ctor of ctors) {
values = [];
rab = CreateRabForTest(ctor);
const fixedLengthWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT, 2);
resizeAfter = 1;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
Array.prototype.map.call(fixedLengthWithOffset, ResizeMidIteration);
assert.compareArray(values, [
4,
6
]);
}
for (let ctor of ctors) {
values = [];
rab = CreateRabForTest(ctor);
const lengthTracking = new ctor(rab, 0);
resizeAfter = 2;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
Array.prototype.map.call(lengthTracking, ResizeMidIteration);
assert.compareArray(values, [
0,
2,
4,
6
]);
}
for (let ctor of ctors) {
values = [];
rab = CreateRabForTest(ctor);
const lengthTrackingWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT);
resizeAfter = 1;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
Array.prototype.map.call(lengthTrackingWithOffset, ResizeMidIteration);
assert.compareArray(values, [
4,
6
]);
}

View File

@ -0,0 +1,79 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.map
description: >
Array.p.map behaves correctly when the resizable buffer is shrunk mid-iteration.
includes: [compareArray.js, resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
let values;
let rab;
let resizeAfter;
let resizeTo;
// Collects the view of the resizable array buffer rab into values, with an
// iteration during which, after resizeAfter steps, rab is resized to length
// resizeTo. To be called by a method of the view being collected.
// Note that rab, values, resizeAfter, and resizeTo may need to be reset
// before calling this. This version can deal with the undefined values
// resulting by shrinking rab.
function ShrinkMidIteration(n, ix, ta) {
CollectValuesAndResize(n, values, rab, resizeAfter, resizeTo);
// We still need to return a valid BigInt / non-BigInt, even if
// n is `undefined`.
if (ta instanceof BigInt64Array || ta instanceof BigUint64Array) {
return 0n;
}
return 0;
}
// Orig. array: [0, 2, 4, 6]
// [0, 2, 4, 6] << fixedLength
// [4, 6] << fixedLengthWithOffset
// [0, 2, 4, 6, ...] << lengthTracking
// [4, 6, ...] << lengthTrackingWithOffset
for (let ctor of ctors) {
values = [];
rab = CreateRabForTest(ctor);
const fixedLength = new ctor(rab, 0, 4);
resizeAfter = 2;
resizeTo = 3 * ctor.BYTES_PER_ELEMENT;
Array.prototype.map.call(fixedLength, ShrinkMidIteration);
assert.compareArray(values, [
0,
2
]);
}
for (let ctor of ctors) {
values = [];
rab = CreateRabForTest(ctor);
const fixedLengthWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT, 2);
resizeAfter = 1;
resizeTo = 3 * ctor.BYTES_PER_ELEMENT;
Array.prototype.map.call(fixedLengthWithOffset, ShrinkMidIteration);
assert.compareArray(values, [4]);
}
for (let ctor of ctors) {
values = [];
rab = CreateRabForTest(ctor);
const lengthTracking = new ctor(rab, 0);
resizeAfter = 2;
resizeTo = 3 * ctor.BYTES_PER_ELEMENT;
Array.prototype.map.call(lengthTracking, ShrinkMidIteration);
assert.compareArray(values, [
0,
2,
4
]);
}
for (let ctor of ctors) {
values = [];
rab = CreateRabForTest(ctor);
const lengthTrackingWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT);
resizeAfter = 1;
resizeTo = 3 * ctor.BYTES_PER_ELEMENT;
Array.prototype.map.call(lengthTrackingWithOffset, ShrinkMidIteration);
assert.compareArray(values, [4]);
}

View File

@ -0,0 +1,141 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.map
description: >
Array.p.map behaves as expected on TypedArrays backed by resizable buffers.
includes: [compareArray.js, resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const fixedLength = new ctor(rab, 0, 4);
const fixedLengthWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT, 2);
const lengthTracking = new ctor(rab, 0);
const lengthTrackingWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT);
// Write some data into the array.
const taWrite = new ctor(rab);
for (let i = 0; i < taWrite.length; ++i) {
WriteToTypedArray(taWrite, i, 2 * i);
}
// Orig. array: [0, 2, 4, 6]
// [0, 2, 4, 6] << fixedLength
// [4, 6] << fixedLengthWithOffset
// [0, 2, 4, 6, ...] << lengthTracking
// [4, 6, ...] << lengthTrackingWithOffset
function MapGatherCompare(array) {
const values = [];
function GatherValues(n, ix) {
assert.sameValue(ix, values.length);
values.push(n);
if (typeof n == 'bigint') {
return n + 1n;
}
return n + 1;
}
const newValues = Array.prototype.map.call(array, GatherValues);
for (let i = 0; i < values.length; ++i) {
if (typeof values[i] == 'bigint') {
assert.sameValue(values[i] + 1n, newValues[i]);
} else {
assert.sameValue(values[i] + 1, newValues[i]);
}
}
return ToNumbers(values);
}
assert.compareArray(MapGatherCompare(fixedLength), [
0,
2,
4,
6
]);
assert.compareArray(MapGatherCompare(fixedLengthWithOffset), [
4,
6
]);
assert.compareArray(MapGatherCompare(lengthTracking), [
0,
2,
4,
6
]);
assert.compareArray(MapGatherCompare(lengthTrackingWithOffset), [
4,
6
]);
// Shrink so that fixed length TAs go out of bounds.
rab.resize(3 * ctor.BYTES_PER_ELEMENT);
// Orig. array: [0, 2, 4]
// [0, 2, 4, ...] << lengthTracking
// [4, ...] << lengthTrackingWithOffset
assert.compareArray(MapGatherCompare(fixedLength), []);
assert.compareArray(MapGatherCompare(fixedLengthWithOffset), []);
assert.compareArray(MapGatherCompare(lengthTracking), [
0,
2,
4
]);
assert.compareArray(MapGatherCompare(lengthTrackingWithOffset), [4]);
// Shrink so that the TAs with offset go out of bounds.
rab.resize(1 * ctor.BYTES_PER_ELEMENT);
assert.compareArray(MapGatherCompare(fixedLength), []);
assert.compareArray(MapGatherCompare(fixedLengthWithOffset), []);
assert.compareArray(MapGatherCompare(lengthTrackingWithOffset), []);
assert.compareArray(MapGatherCompare(lengthTracking), [0]);
// Shrink to zero.
rab.resize(0);
assert.compareArray(MapGatherCompare(fixedLength), []);
assert.compareArray(MapGatherCompare(fixedLengthWithOffset), []);
assert.compareArray(MapGatherCompare(lengthTrackingWithOffset), []);
assert.compareArray(MapGatherCompare(lengthTracking), []);
// Grow so that all TAs are back in-bounds.
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
for (let i = 0; i < 6; ++i) {
WriteToTypedArray(taWrite, i, 2 * i);
}
// Orig. array: [0, 2, 4, 6, 8, 10]
// [0, 2, 4, 6] << fixedLength
// [4, 6] << fixedLengthWithOffset
// [0, 2, 4, 6, 8, 10, ...] << lengthTracking
// [4, 6, 8, 10, ...] << lengthTrackingWithOffset
assert.compareArray(MapGatherCompare(fixedLength), [
0,
2,
4,
6
]);
assert.compareArray(MapGatherCompare(fixedLengthWithOffset), [
4,
6
]);
assert.compareArray(MapGatherCompare(lengthTracking), [
0,
2,
4,
6,
8,
10
]);
assert.compareArray(MapGatherCompare(lengthTrackingWithOffset), [
4,
6,
8,
10
]);
}

View File

@ -0,0 +1,86 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.reduce
description: >
Array.p.reduce behaves correctly when the resizable buffer is grown
mid-iteration.
includes: [compareArray.js, resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
let values;
let rab;
let resizeAfter;
let resizeTo;
// Collects the view of the resizable array buffer rab into values, with an
// iteration during which, after resizeAfter steps, rab is resized to length
// resizeTo. To be called by a method of the view being collected.
// Note that rab, values, resizeAfter, and resizeTo may need to be reset
// before calling this.
function ResizeMidIteration(acc, n) {
// Returns true by default.
return CollectValuesAndResize(n, values, rab, resizeAfter, resizeTo);
}
// Orig. array: [0, 2, 4, 6]
// [0, 2, 4, 6] << fixedLength
// [4, 6] << fixedLengthWithOffset
// [0, 2, 4, 6, ...] << lengthTracking
// [4, 6, ...] << lengthTrackingWithOffset
// Test for reduce.
for (let ctor of ctors) {
values = [];
rab = CreateRabForTest(ctor);
const fixedLength = new ctor(rab, 0, 4);
resizeAfter = 2;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
Array.prototype.reduce.call(fixedLength, ResizeMidIteration, 'initial value');
assert.compareArray(values, [
0,
2,
4,
6
]);
}
for (let ctor of ctors) {
values = [];
rab = CreateRabForTest(ctor);
const fixedLengthWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT, 2);
resizeAfter = 1;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
Array.prototype.reduce.call(fixedLengthWithOffset, ResizeMidIteration, 'initial value');
assert.compareArray(values, [
4,
6
]);
}
for (let ctor of ctors) {
values = [];
rab = CreateRabForTest(ctor);
const lengthTracking = new ctor(rab, 0);
resizeAfter = 2;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
Array.prototype.reduce.call(lengthTracking, ResizeMidIteration, 'initial value');
assert.compareArray(values, [
0,
2,
4,
6
]);
}
for (let ctor of ctors) {
values = [];
rab = CreateRabForTest(ctor);
const lengthTrackingWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT);
resizeAfter = 1;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
Array.prototype.reduce.call(lengthTrackingWithOffset, ResizeMidIteration, 'initial value');
assert.compareArray(values, [
4,
6
]);
}

View File

@ -0,0 +1,79 @@
// Copyright 2024 Igalia S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-%array%.prototype.reduce
description: >
Array.p.reduce behaves correctly when the backing resizable buffer is shrunk
mid-iteration.
includes: [compareArray.js, resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
let values;
let rab;
let resizeAfter;
let resizeTo;
// Collects the view of the resizable array buffer rab into values, with an
// iteration during which, after resizeAfter steps, rab is resized to length
// resizeTo. To be called by a method of the view being collected.
// Note that rab, values, resizeAfter, and resizeTo may need to be reset
// before calling this.
function ResizeMidIteration(acc, n) {
// Returns true by default.
return CollectValuesAndResize(n, values, rab, resizeAfter, resizeTo);
}
// Orig. array: [0, 2, 4, 6]
// [0, 2, 4, 6] << fixedLength
// [4, 6] << fixedLengthWithOffset
// [0, 2, 4, 6, ...] << lengthTracking
// [4, 6, ...] << lengthTrackingWithOffset
for (let ctor of ctors) {
values = [];
rab = CreateRabForTest(ctor);
const fixedLength = new ctor(rab, 0, 4);
resizeAfter = 2;
resizeTo = 3 * ctor.BYTES_PER_ELEMENT;
Array.prototype.reduce.call(fixedLength, ResizeMidIteration, 'initial value');
assert.compareArray(values, [
0,
2
]);
}
for (let ctor of ctors) {
values = [];
rab = CreateRabForTest(ctor);
const fixedLengthWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT, 2);
resizeAfter = 1;
resizeTo = 3 * ctor.BYTES_PER_ELEMENT;
Array.prototype.reduce.call(fixedLengthWithOffset, ResizeMidIteration, 'initial value');
assert.compareArray(values, [
4
]);
}
for (let ctor of ctors) {
values = [];
rab = CreateRabForTest(ctor);
const lengthTracking = new ctor(rab, 0);
resizeAfter = 2;
resizeTo = 3 * ctor.BYTES_PER_ELEMENT;
Array.prototype.reduce.call(lengthTracking, ResizeMidIteration, 'initial value');
assert.compareArray(values, [
0,
2,
4
]);
}
for (let ctor of ctors) {
values = [];
rab = CreateRabForTest(ctor);
const lengthTrackingWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT);
resizeAfter = 1;
resizeTo = 3 * ctor.BYTES_PER_ELEMENT;
Array.prototype.reduce.call(lengthTrackingWithOffset, ResizeMidIteration, 'initial value');
assert.compareArray(values, [
4
]);
}

View File

@ -0,0 +1,126 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.reduce
description: >
Array.p.reduce behaves correctly on TypedArrays backed by resizable buffers.
includes: [compareArray.js, resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const fixedLength = new ctor(rab, 0, 4);
const fixedLengthWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT, 2);
const lengthTracking = new ctor(rab, 0);
const lengthTrackingWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT);
// Write some data into the array.
const taWrite = new ctor(rab);
for (let i = 0; i < 4; ++i) {
WriteToTypedArray(taWrite, i, 2 * i);
}
// Orig. array: [0, 2, 4, 6]
// [0, 2, 4, 6] << fixedLength
// [4, 6] << fixedLengthWithOffset
// [0, 2, 4, 6, ...] << lengthTracking
// [4, 6, ...] << lengthTrackingWithOffset
function ReduceCollecting(array) {
const reduceValues = [];
Array.prototype.reduce.call(array, (acc, n) => {
reduceValues.push(n);
}, 'initial value');
return ToNumbers(reduceValues);
}
assert.compareArray(ReduceCollecting(fixedLength), [
0,
2,
4,
6
]);
assert.compareArray(ReduceCollecting(fixedLengthWithOffset), [
4,
6
]);
assert.compareArray(ReduceCollecting(lengthTracking), [
0,
2,
4,
6
]);
assert.compareArray(ReduceCollecting(lengthTrackingWithOffset), [
4,
6
]);
// Shrink so that fixed length TAs go out of bounds.
rab.resize(3 * ctor.BYTES_PER_ELEMENT);
// Orig. array: [0, 2, 4]
// [0, 2, 4, ...] << lengthTracking
// [4, ...] << lengthTrackingWithOffset
assert.compareArray(ReduceCollecting(fixedLength), []);
assert.compareArray(ReduceCollecting(fixedLengthWithOffset), []);
assert.compareArray(ReduceCollecting(lengthTracking), [
0,
2,
4
]);
assert.compareArray(ReduceCollecting(lengthTrackingWithOffset), [4]);
// Shrink so that the TAs with offset go out of bounds.
rab.resize(1 * ctor.BYTES_PER_ELEMENT);
assert.compareArray(ReduceCollecting(fixedLength), []);
assert.compareArray(ReduceCollecting(fixedLengthWithOffset), []);
assert.compareArray(ReduceCollecting(lengthTracking), [0]);
// Shrink to zero.
rab.resize(0);
assert.compareArray(ReduceCollecting(fixedLength), []);
assert.compareArray(ReduceCollecting(fixedLengthWithOffset), []);
assert.compareArray(ReduceCollecting(lengthTrackingWithOffset), []);
assert.compareArray(ReduceCollecting(lengthTracking), []);
// Grow so that all TAs are back in-bounds.
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
for (let i = 0; i < 6; ++i) {
WriteToTypedArray(taWrite, i, 2 * i);
}
// Orig. array: [0, 2, 4, 6, 8, 10]
// [0, 2, 4, 6] << fixedLength
// [4, 6] << fixedLengthWithOffset
// [0, 2, 4, 6, 8, 10, ...] << lengthTracking
// [4, 6, 8, 10, ...] << lengthTrackingWithOffset
assert.compareArray(ReduceCollecting(fixedLength), [
0,
2,
4,
6
]);
assert.compareArray(ReduceCollecting(fixedLengthWithOffset), [
4,
6
]);
assert.compareArray(ReduceCollecting(lengthTracking), [
0,
2,
4,
6,
8,
10
]);
assert.compareArray(ReduceCollecting(lengthTrackingWithOffset), [
4,
6,
8,
10
]);
}

View File

@ -37,8 +37,8 @@ function callbackfn(prevVal, curVal, idx, obj) {
Object.defineProperty(child, "toString", {
value: function() {
toStringAccessed = true;
return '1';
toStringAccessed = true;
return '1';
}
});

View File

@ -0,0 +1,83 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.reduceright
description: >
Array.p.reduceRight behaves correctly on TypedArrays backed by resizable
buffers that are grown mid-iteration.
includes: [compareArray.js, resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
let values;
let rab;
let resizeAfter;
let resizeTo;
// Collects the view of the resizable array buffer rab into values, with an
// iteration during which, after resizeAfter steps, rab is resized to length
// resizeTo. To be called by a method of the view being collected.
// Note that rab, values, resizeAfter, and resizeTo may need to be reset before
// calling this.
function ResizeBufferMidIteration(acc, n) {
return CollectValuesAndResize(n, values, rab, resizeAfter, resizeTo);
}
// Orig. array: [0, 2, 4, 6]
// [0, 2, 4, 6] << fixedLength
// [4, 6] << fixedLengthWithOffset
// [0, 2, 4, 6, ...] << lengthTracking
// [4, 6, ...] << lengthTrackingWithOffset
for (let ctor of ctors) {
values = [];
rab = CreateRabForTest(ctor);
const fixedLength = new ctor(rab, 0, 4);
resizeAfter = 2;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
Array.prototype.reduceRight.call(fixedLength, ResizeBufferMidIteration, 'initial value');
assert.compareArray(values, [
6,
4,
2,
0
]);
}
for (let ctor of ctors) {
values = [];
rab = CreateRabForTest(ctor);
const fixedLengthWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT, 2);
resizeAfter = 1;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
Array.prototype.reduceRight.call(fixedLengthWithOffset, ResizeBufferMidIteration, 'initial value');
assert.compareArray(values, [
6,
4
]);
}
for (let ctor of ctors) {
values = [];
rab = CreateRabForTest(ctor);
const lengthTracking = new ctor(rab, 0);
resizeAfter = 2;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
Array.prototype.reduceRight.call(lengthTracking, ResizeBufferMidIteration, 'initial value');
assert.compareArray(values, [
6,
4,
2,
0
]);
}
for (let ctor of ctors) {
values = [];
rab = CreateRabForTest(ctor);
const lengthTrackingWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT);
resizeAfter = 1;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
Array.prototype.reduceRight.call(lengthTrackingWithOffset, ResizeBufferMidIteration, 'initial value');
assert.compareArray(values, [
6,
4
]);
}

View File

@ -0,0 +1,95 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-%array%.prototype.reduceright
description: >
Array.p.reduceRight behaves correctly when the backing resizable buffer is
shrunk mid-iteration.
includes: [compareArray.js, resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
let values;
let rab;
let resizeAfter;
let resizeTo;
// Collects the view of the resizable array buffer rab into values, with an
// iteration during which, after resizeAfter steps, rab is resized to length
// resizeTo. To be called by a method of the view being collected.
// Note that rab, values, resizeAfter, and resizeTo may need to be reset before
// calling this.
function ResizeMidIteration(acc, n) {
return CollectValuesAndResize(n, values, rab, resizeAfter, resizeTo);
}
// Orig. array: [0, 2, 4, 6]
// [0, 2, 4, 6] << fixedLength
// [4, 6] << fixedLengthWithOffset
// [0, 2, 4, 6, ...] << lengthTracking
// [4, 6, ...] << lengthTrackingWithOffset
for (let ctor of ctors) {
values = [];
rab = CreateRabForTest(ctor);
const fixedLength = new ctor(rab, 0, 4);
resizeAfter = 2;
resizeTo = 3 * ctor.BYTES_PER_ELEMENT;
Array.prototype.reduceRight.call(fixedLength, ResizeMidIteration, 'initial value');
assert.compareArray(values, [
6,
4
]);
}
for (let ctor of ctors) {
values = [];
rab = CreateRabForTest(ctor);
const fixedLengthWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT, 2);
resizeAfter = 1;
resizeTo = 3 * ctor.BYTES_PER_ELEMENT;
Array.prototype.reduceRight.call(fixedLengthWithOffset, ResizeMidIteration, 'initial value');
assert.compareArray(values, [
6
]);
}
for (let ctor of ctors) {
values = [];
rab = CreateRabForTest(ctor);
const lengthTracking = new ctor(rab, 0);
resizeAfter = 2;
resizeTo = 3 * ctor.BYTES_PER_ELEMENT;
// Unaffected by the shrinking, since we've already iterated past the point.
Array.prototype.reduceRight.call(lengthTracking, ResizeMidIteration, 'initial value');
assert.compareArray(values, [
6,
4,
2,
0
]);
}
for (let ctor of ctors) {
values = [];
rab = CreateRabForTest(ctor);
const lengthTracking = new ctor(rab, 0);
resizeAfter = 1;
resizeTo = 2 * ctor.BYTES_PER_ELEMENT;
Array.prototype.reduceRight.call(lengthTracking, ResizeMidIteration, 'initial value');
assert.compareArray(values, [
6,
2,
0
]);
}
for (let ctor of ctors) {
values = [];
rab = CreateRabForTest(ctor);
const lengthTrackingWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT);
resizeAfter = 1;
resizeTo = 3 * ctor.BYTES_PER_ELEMENT;
// Unaffected by the shrinking, since we've already iterated past the point.
Array.prototype.reduceRight.call(lengthTrackingWithOffset, ResizeMidIteration, 'initial value');
assert.compareArray(values, [
6,
4
]);
}

View File

@ -0,0 +1,129 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.reduceright
description: >
Array.p.reduceRight behaves correctly on TypedArrays backed by resizable
buffers.
includes: [compareArray.js, resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const fixedLength = new ctor(rab, 0, 4);
const fixedLengthWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT, 2);
const lengthTracking = new ctor(rab, 0);
const lengthTrackingWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT);
// Write some data into the array.
const taWrite = new ctor(rab);
for (let i = 0; i < 4; ++i) {
WriteToTypedArray(taWrite, i, 2 * i);
}
// Orig. array: [0, 2, 4, 6]
// [0, 2, 4, 6] << fixedLength
// [4, 6] << fixedLengthWithOffset
// [0, 2, 4, 6, ...] << lengthTracking
// [4, 6, ...] << lengthTrackingWithOffset
function ReduceRightCollecting(array) {
const reduceRightValues = [];
Array.prototype.reduceRight.call(array, (acc, n) => {
reduceRightValues.push(n);
}, 'initial value');
reduceRightValues.reverse();
return ToNumbers(reduceRightValues);
}
assert.compareArray(ReduceRightCollecting(fixedLength), [
0,
2,
4,
6
]);
assert.compareArray(ReduceRightCollecting(fixedLengthWithOffset), [
4,
6
]);
assert.compareArray(ReduceRightCollecting(lengthTracking), [
0,
2,
4,
6
]);
assert.compareArray(ReduceRightCollecting(lengthTrackingWithOffset), [
4,
6
]);
// Shrink so that fixed length TAs go out of bounds.
rab.resize(3 * ctor.BYTES_PER_ELEMENT);
// Orig. array: [0, 2, 4]
// [0, 2, 4, ...] << lengthTracking
// [4, ...] << lengthTrackingWithOffset
assert.compareArray(ReduceRightCollecting(fixedLength), []);
assert.compareArray(ReduceRightCollecting(fixedLengthWithOffset), []);
assert.compareArray(ReduceRightCollecting(lengthTracking), [
0,
2,
4
]);
assert.compareArray(ReduceRightCollecting(lengthTrackingWithOffset), [4]);
// Shrink so that the TAs with offset go out of bounds.
rab.resize(1 * ctor.BYTES_PER_ELEMENT);
assert.compareArray(ReduceRightCollecting(fixedLength), []);
assert.compareArray(ReduceRightCollecting(fixedLengthWithOffset), []);
assert.compareArray(ReduceRightCollecting(lengthTracking), [0]);
// Shrink to zero.
rab.resize(0);
assert.compareArray(ReduceRightCollecting(fixedLength), []);
assert.compareArray(ReduceRightCollecting(fixedLengthWithOffset), []);
assert.compareArray(ReduceRightCollecting(lengthTrackingWithOffset), []);
assert.compareArray(ReduceRightCollecting(lengthTracking), []);
// Grow so that all TAs are back in-bounds.
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
for (let i = 0; i < 6; ++i) {
WriteToTypedArray(taWrite, i, 2 * i);
}
// Orig. array: [0, 2, 4, 6, 8, 10]
// [0, 2, 4, 6] << fixedLength
// [4, 6] << fixedLengthWithOffset
// [0, 2, 4, 6, 8, 10, ...] << lengthTracking
// [4, 6, 8, 10, ...] << lengthTrackingWithOffset
assert.compareArray(ReduceRightCollecting(fixedLength), [
0,
2,
4,
6
]);
assert.compareArray(ReduceRightCollecting(fixedLengthWithOffset), [
4,
6
]);
assert.compareArray(ReduceRightCollecting(lengthTracking), [
0,
2,
4,
6,
8,
10
]);
assert.compareArray(ReduceRightCollecting(lengthTrackingWithOffset), [
4,
6,
8,
10
]);
}

View File

@ -0,0 +1,164 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.reverse
description: >
Array.p.reverse behaves correctly on TypedArrays backed by resizable buffers.
includes: [compareArray.js, resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const fixedLength = new ctor(rab, 0, 4);
const fixedLengthWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT, 2);
const lengthTracking = new ctor(rab, 0);
const lengthTrackingWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT);
const wholeArrayView = new ctor(rab);
function WriteData() {
// Write some data into the array.
for (let i = 0; i < wholeArrayView.length; ++i) {
WriteToTypedArray(wholeArrayView, i, 2 * i);
}
}
WriteData();
// Orig. array: [0, 2, 4, 6]
// [0, 2, 4, 6] << fixedLength
// [4, 6] << fixedLengthWithOffset
// [0, 2, 4, 6, ...] << lengthTracking
// [4, 6, ...] << lengthTrackingWithOffset
Array.prototype.reverse.call(fixedLength);
assert.compareArray(ToNumbers(wholeArrayView), [
6,
4,
2,
0
]);
Array.prototype.reverse.call(fixedLengthWithOffset);
assert.compareArray(ToNumbers(wholeArrayView), [
6,
4,
0,
2
]);
Array.prototype.reverse.call(lengthTracking);
assert.compareArray(ToNumbers(wholeArrayView), [
2,
0,
4,
6
]);
Array.prototype.reverse.call(lengthTrackingWithOffset);
assert.compareArray(ToNumbers(wholeArrayView), [
2,
0,
6,
4
]);
// Shrink so that fixed length TAs go out of bounds.
rab.resize(3 * ctor.BYTES_PER_ELEMENT);
WriteData();
// Orig. array: [0, 2, 4]
// [0, 2, 4, ...] << lengthTracking
// [4, ...] << lengthTrackingWithOffset
Array.prototype.reverse.call(fixedLength);
assert.compareArray(ToNumbers(wholeArrayView), [
0,
2,
4
]);
Array.prototype.reverse.call(fixedLengthWithOffset);
assert.compareArray(ToNumbers(wholeArrayView), [
0,
2,
4
]);
Array.prototype.reverse.call(lengthTracking);
assert.compareArray(ToNumbers(wholeArrayView), [
4,
2,
0
]);
Array.prototype.reverse.call(lengthTrackingWithOffset);
assert.compareArray(ToNumbers(wholeArrayView), [
4,
2,
0
]);
// Shrink so that the TAs with offset go out of bounds.
rab.resize(1 * ctor.BYTES_PER_ELEMENT);
WriteData();
Array.prototype.reverse.call(fixedLength);
assert.compareArray(ToNumbers(wholeArrayView), [0]);
Array.prototype.reverse.call(fixedLengthWithOffset);
assert.compareArray(ToNumbers(wholeArrayView), [0]);
Array.prototype.reverse.call(lengthTrackingWithOffset);
assert.compareArray(ToNumbers(wholeArrayView), [0]);
Array.prototype.reverse.call(lengthTracking);
assert.compareArray(ToNumbers(wholeArrayView), [0]);
// Shrink to zero.
rab.resize(0);
Array.prototype.reverse.call(fixedLength);
assert.compareArray(ToNumbers(wholeArrayView), []);
Array.prototype.reverse.call(fixedLengthWithOffset);
assert.compareArray(ToNumbers(wholeArrayView), []);
Array.prototype.reverse.call(lengthTrackingWithOffset);
assert.compareArray(ToNumbers(wholeArrayView), []);
Array.prototype.reverse.call(lengthTracking);
assert.compareArray(ToNumbers(wholeArrayView), []);
// Grow so that all TAs are back in-bounds.
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
WriteData();
// Orig. array: [0, 2, 4, 6, 8, 10]
// [0, 2, 4, 6] << fixedLength
// [4, 6] << fixedLengthWithOffset
// [0, 2, 4, 6, 8, 10, ...] << lengthTracking
// [4, 6, 8, 10, ...] << lengthTrackingWithOffset
Array.prototype.reverse.call(fixedLength);
assert.compareArray(ToNumbers(wholeArrayView), [
6,
4,
2,
0,
8,
10
]);
Array.prototype.reverse.call(fixedLengthWithOffset);
assert.compareArray(ToNumbers(wholeArrayView), [
6,
4,
0,
2,
8,
10
]);
Array.prototype.reverse.call(lengthTracking);
assert.compareArray(ToNumbers(wholeArrayView), [
10,
8,
2,
0,
4,
6
]);
Array.prototype.reverse.call(lengthTrackingWithOffset);
assert.compareArray(ToNumbers(wholeArrayView), [
10,
8,
6,
4,
0,
2
]);
}

View File

@ -0,0 +1,56 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.slice
description: >
Array.p.slice behaves correctly on TypedArrays backed by resizable buffers that
are grown by argument coercion.
includes: [compareArray.js, resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
// The start argument grows the resizable array buffer rab.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const lengthTracking = new ctor(rab);
for (let i = 0; i < 4; ++i) {
WriteToTypedArray(lengthTracking, i, i + 1);
}
const evil = {
valueOf: () => {
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
return 0;
}
};
assert.compareArray(ToNumbers(Array.prototype.slice.call(lengthTracking, evil)), [
1,
2,
3,
4
]);
assert.sameValue(rab.byteLength, 6 * ctor.BYTES_PER_ELEMENT);
}
// The end argument grows the resizable array buffer rab.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const lengthTracking = new ctor(rab);
for (let i = 0; i < 4; ++i) {
WriteToTypedArray(lengthTracking, i, i + 1);
}
const evil = {
valueOf: () => {
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
return 5;
}
};
assert.compareArray(ToNumbers(Array.prototype.slice.call(lengthTracking,4,evil)), [
]);
assert.compareArray(ToNumbers(Array.prototype.slice.call(lengthTracking,3,evil)), [
4,
0
]);
assert.sameValue(rab.byteLength, 6 * ctor.BYTES_PER_ELEMENT);
}

View File

@ -0,0 +1,95 @@
// Copyright 2023 Igalia S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.slice
description: >
Array.p.slice behaves correctly on TypedArrays backed by resizable buffers that
are shrunk by argument coercion.
includes: [compareArray.js, resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
// The start argument shrinks the resizable array buffer rab.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const fixedLength = new ctor(rab, 0, 4);
const evil = {
valueOf: () => {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
return 0;
}
};
assert.compareArray(ToNumbers(Array.prototype.slice.call(fixedLength, evil)), [
undefined,
undefined,
undefined,
undefined
]);
assert.compareArray(ToNumbers(Array.prototype.slice.call(fixedLength, evil)), [
]);
assert.sameValue(rab.byteLength, 2 * ctor.BYTES_PER_ELEMENT);
}
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const lengthTracking = new ctor(rab);
for (let i = 0; i < 4; ++i) {
WriteToTypedArray(lengthTracking, i, i + 1);
}
const evil = {
valueOf: () => {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
return 0;
}
};
assert.compareArray(ToNumbers(Array.prototype.slice.call(lengthTracking, evil)), [
1,
2,
undefined,
undefined
]);
assert.compareArray(ToNumbers(Array.prototype.slice.call(lengthTracking, evil)), [
1,
2
]);
assert.sameValue(rab.byteLength, 2 * ctor.BYTES_PER_ELEMENT);
}
// The end argument shrinks the resizable array buffer rab.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const fixedLength = new ctor(rab, 0, 4);
const evil = {
valueOf: () => {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
return 3;
}
};
assert.compareArray(ToNumbers(Array.prototype.slice.call(fixedLength, 2, evil)), [
undefined
]);
assert.compareArray(ToNumbers(Array.prototype.slice.call(fixedLength, 2, evil)), [
]);
assert.sameValue(rab.byteLength, 2 * ctor.BYTES_PER_ELEMENT);
}
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const lengthTracking = new ctor(rab);
for (let i = 0; i < 4; ++i) {
WriteToTypedArray(lengthTracking, i, i + 1);
}
const evil = {
valueOf: () => {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
return 3;
}
};
assert.compareArray(ToNumbers(Array.prototype.slice.call(lengthTracking, 1, evil)), [
2,
undefined
]);
assert.compareArray(ToNumbers(Array.prototype.slice.call(lengthTracking, 1, evil)), [
2
]);
assert.sameValue(rab.byteLength, 2 * ctor.BYTES_PER_ELEMENT);
}

View File

@ -0,0 +1,124 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.slice
description: >
Array.p.slice behaves correctly on TypedArrays backed by resizable buffers.
includes: [compareArray.js, resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const fixedLength = new ctor(rab, 0, 4);
const fixedLengthWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT, 2);
const lengthTracking = new ctor(rab, 0);
const lengthTrackingWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT);
// Write some data into the array.
const taWrite = new ctor(rab);
for (let i = 0; i < 4; ++i) {
WriteToTypedArray(taWrite, i, i);
}
const fixedLengthSlice = Array.prototype.slice.call(fixedLength);
assert.compareArray(ToNumbers(fixedLengthSlice), [
0,
1,
2,
3
]);
const fixedLengthWithOffsetSlice = Array.prototype.slice.call(fixedLengthWithOffset);
assert.compareArray(ToNumbers(fixedLengthWithOffsetSlice), [
2,
3
]);
const lengthTrackingSlice = Array.prototype.slice.call(lengthTracking);
assert.compareArray(ToNumbers(lengthTrackingSlice), [
0,
1,
2,
3
]);
const lengthTrackingWithOffsetSlice = Array.prototype.slice.call(lengthTrackingWithOffset);
assert.compareArray(ToNumbers(lengthTrackingWithOffsetSlice), [
2,
3
]);
// Shrink so that fixed length TAs go out of bounds.
rab.resize(3 * ctor.BYTES_PER_ELEMENT);
assert.compareArray(ToNumbers(Array.prototype.slice.call(fixedLength)), []);
assert.compareArray(ToNumbers(Array.prototype.slice.call(fixedLengthWithOffset)), []);
assert.compareArray(ToNumbers(Array.prototype.slice.call(lengthTracking)), [
0,
1,
2
]);
assert.compareArray(ToNumbers(Array.prototype.slice.call(lengthTrackingWithOffset)), [2]);
// Shrink so that the TAs with offset go out of bounds.
rab.resize(1 * ctor.BYTES_PER_ELEMENT);
assert.compareArray(ToNumbers(Array.prototype.slice.call(fixedLength)), []);
assert.compareArray(ToNumbers(Array.prototype.slice.call(fixedLengthWithOffset)), []);
assert.compareArray(ToNumbers(Array.prototype.slice.call(lengthTracking)), [0]);
assert.compareArray(ToNumbers(Array.prototype.slice.call(lengthTrackingWithOffset)), []);
// Shrink to zero.
rab.resize(0);
assert.compareArray(ToNumbers(Array.prototype.slice.call(fixedLength)), []);
assert.compareArray(ToNumbers(Array.prototype.slice.call(fixedLengthWithOffset)), []);
assert.compareArray(ToNumbers(Array.prototype.slice.call(lengthTracking)), []);
assert.compareArray(ToNumbers(Array.prototype.slice.call(lengthTrackingWithOffset)), []);
// Verify that the previously created slices aren't affected by the
// shrinking.
assert.compareArray(ToNumbers(fixedLengthSlice), [
0,
1,
2,
3
]);
assert.compareArray(ToNumbers(fixedLengthWithOffsetSlice), [
2,
3
]);
assert.compareArray(ToNumbers(lengthTrackingSlice), [
0,
1,
2,
3
]);
assert.compareArray(ToNumbers(lengthTrackingWithOffsetSlice), [
2,
3
]);
// Grow so that all TAs are back in-bounds. New memory is zeroed.
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
assert.compareArray(ToNumbers(Array.prototype.slice.call(fixedLength)), [
0,
0,
0,
0
]);
assert.compareArray(ToNumbers(Array.prototype.slice.call(fixedLengthWithOffset)), [
0,
0
]);
assert.compareArray(ToNumbers(Array.prototype.slice.call(lengthTracking)), [
0,
0,
0,
0,
0,
0
]);
assert.compareArray(ToNumbers(Array.prototype.slice.call(lengthTrackingWithOffset)), [
0,
0,
0,
0
]);
}

View File

@ -0,0 +1,84 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.some
description: >
Array.p.some behaves correctly on TypedArrays backed by resizable buffers that
are grown mid-iteration.
features: [resizable-arraybuffer]
includes: [compareArray.js, resizableArrayBufferUtils.js]
---*/
let values;
let rab;
let resizeAfter;
let resizeTo;
// Collects the view of the resizable array buffer rab into values, with an
// iteration during which, after resizeAfter steps, rab is resized to length
// resizeTo. To be called by a method of the view being collected.
// Note that rab, values, resizeAfter, and resizeTo may need to be reset
// before calling this.
function ResizeMidIteration(n) {
CollectValuesAndResize(n, values, rab, resizeAfter, resizeTo);
return false;
}
// Orig. array: [0, 2, 4, 6]
// [0, 2, 4, 6] << fixedLength
// [4, 6] << fixedLengthWithOffset
// [0, 2, 4, 6, ...] << lengthTracking
// [4, 6, ...] << lengthTrackingWithOffset
for (let ctor of ctors) {
rab = CreateRabForTest(ctor);
const fixedLength = new ctor(rab, 0, 4);
values = [];
resizeAfter = 2;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
assert(!Array.prototype.some.call(fixedLength, ResizeMidIteration));
assert.compareArray(values, [
0,
2,
4,
6
]);
}
for (let ctor of ctors) {
rab = CreateRabForTest(ctor);
const fixedLengthWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT, 2);
values = [];
resizeAfter = 1;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
assert(!Array.prototype.some.call(fixedLengthWithOffset, ResizeMidIteration));
assert.compareArray(values, [
4,
6
]);
}
for (let ctor of ctors) {
rab = CreateRabForTest(ctor);
const lengthTracking = new ctor(rab, 0);
values = [];
resizeAfter = 2;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
assert(!Array.prototype.some.call(lengthTracking, ResizeMidIteration));
assert.compareArray(values, [
0,
2,
4,
6
]);
}
for (let ctor of ctors) {
rab = CreateRabForTest(ctor);
const lengthTrackingWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT);
values = [];
rab = rab;
resizeAfter = 1;
resizeTo = 5 * ctor.BYTES_PER_ELEMENT;
assert(!Array.prototype.some.call(lengthTrackingWithOffset, ResizeMidIteration));
assert.compareArray(values, [
4,
6
]);
}

View File

@ -0,0 +1,74 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.some
description: >
Array.p.some behaves correctly on TypedArrays backed by resizable buffers that
are shrunk mid-iteration.
features: [resizable-arraybuffer]
includes: [compareArray.js, resizableArrayBufferUtils.js]
---*/
let values;
let rab;
let resizeAfter;
let resizeTo;
// Collects the view of the resizable array buffer rab into values, with an
// iteration during which, after resizeAfter steps, rab is resized to length
// resizeTo. To be called by a method of the view being collected.
// Note that rab, values, resizeAfter, and resizeTo may need to be reset
// before calling this.
function ResizeMidIteration(n) {
CollectValuesAndResize(n, values, rab, resizeAfter, resizeTo);
return false;
}
// Orig. array: [0, 2, 4, 6]
// [0, 2, 4, 6] << fixedLength
// [4, 6] << fixedLengthWithOffset
// [0, 2, 4, 6, ...] << lengthTracking
// [4, 6, ...] << lengthTrackingWithOffset
for (let ctor of ctors) {
rab = CreateRabForTest(ctor);
const fixedLength = new ctor(rab, 0, 4);
values = [];
resizeAfter = 2;
resizeTo = 3 * ctor.BYTES_PER_ELEMENT;
assert(!Array.prototype.some.call(fixedLength, ResizeMidIteration));
assert.compareArray(values, [
0,
2
]);
}
for (let ctor of ctors) {
rab = CreateRabForTest(ctor);
const fixedLengthWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT, 2);
values = [];
resizeAfter = 1;
resizeTo = 3 * ctor.BYTES_PER_ELEMENT;
assert(!Array.prototype.some.call(fixedLengthWithOffset, ResizeMidIteration));
assert.compareArray(values, [4]);
}
for (let ctor of ctors) {
rab = CreateRabForTest(ctor);
const lengthTracking = new ctor(rab, 0);
values = [];
resizeAfter = 2;
resizeTo = 3 * ctor.BYTES_PER_ELEMENT;
assert(!Array.prototype.some.call(lengthTracking, ResizeMidIteration));
assert.compareArray(values, [
0,
2,
4
]);
}
for (let ctor of ctors) {
rab = CreateRabForTest(ctor);
const lengthTrackingWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT);
values = [];
resizeAfter = 1;
resizeTo = 3 * ctor.BYTES_PER_ELEMENT;
assert(!Array.prototype.some.call(lengthTrackingWithOffset, ResizeMidIteration));
assert.compareArray(values, [4]);
}

View File

@ -0,0 +1,99 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.some
description: >
Array.p.some behaves correctly on TypedArrays backed by resizable buffers.
includes: [resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const fixedLength = new ctor(rab, 0, 4);
const fixedLengthWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT, 2);
const lengthTracking = new ctor(rab, 0);
const lengthTrackingWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT);
// Write some data into the array.
const taWrite = new ctor(rab);
for (let i = 0; i < 4; ++i) {
WriteToTypedArray(taWrite, i, 2 * i);
}
// Orig. array: [0, 2, 4, 6]
// [0, 2, 4, 6] << fixedLength
// [4, 6] << fixedLengthWithOffset
// [0, 2, 4, 6, ...] << lengthTracking
// [4, 6, ...] << lengthTrackingWithOffset
function div3(n) {
return Number(n) % 3 == 0;
}
function over10(n) {
return Number(n) > 10;
}
assert(Array.prototype.some.call(fixedLength, div3));
assert(!Array.prototype.some.call(fixedLength, over10));
assert(Array.prototype.some.call(fixedLengthWithOffset, div3));
assert(!Array.prototype.some.call(fixedLengthWithOffset, over10));
assert(Array.prototype.some.call(lengthTracking, div3));
assert(!Array.prototype.some.call(lengthTracking, over10));
assert(Array.prototype.some.call(lengthTrackingWithOffset, div3));
assert(!Array.prototype.some.call(lengthTrackingWithOffset, over10));
// Shrink so that fixed length TAs go out of bounds.
rab.resize(3 * ctor.BYTES_PER_ELEMENT);
// Orig. array: [0, 2, 4]
// [0, 2, 4, ...] << lengthTracking
// [4, ...] << lengthTrackingWithOffset
assert(!Array.prototype.some.call(fixedLength, div3));
assert(!Array.prototype.some.call(fixedLengthWithOffset, div3));
assert(Array.prototype.some.call(lengthTracking, div3));
assert(!Array.prototype.some.call(lengthTracking, over10));
assert(!Array.prototype.some.call(lengthTrackingWithOffset, div3));
assert(!Array.prototype.some.call(lengthTrackingWithOffset, over10));
// Shrink so that the TAs with offset go out of bounds.
rab.resize(1 * ctor.BYTES_PER_ELEMENT);
assert(!Array.prototype.some.call(fixedLength, div3));
assert(!Array.prototype.some.call(fixedLengthWithOffset, div3));
assert(!Array.prototype.some.call(lengthTrackingWithOffset, div3));
assert(Array.prototype.some.call(lengthTracking, div3));
assert(!Array.prototype.some.call(lengthTracking, over10));
// Shrink to zero.
rab.resize(0);
assert(!Array.prototype.some.call(fixedLength, div3));
assert(!Array.prototype.some.call(fixedLengthWithOffset, div3));
assert(!Array.prototype.some.call(lengthTrackingWithOffset, div3));
assert(!Array.prototype.some.call(lengthTracking, div3));
assert(!Array.prototype.some.call(lengthTracking, over10));
// Grow so that all TAs are back in-bounds.
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
for (let i = 0; i < 6; ++i) {
WriteToTypedArray(taWrite, i, 2 * i);
}
// Orig. array: [0, 2, 4, 6, 8, 10]
// [0, 2, 4, 6] << fixedLength
// [4, 6] << fixedLengthWithOffset
// [0, 2, 4, 6, 8, 10, ...] << lengthTracking
// [4, 6, 8, 10, ...] << lengthTrackingWithOffset
assert(Array.prototype.some.call(fixedLength, div3));
assert(!Array.prototype.some.call(fixedLength, over10));
assert(Array.prototype.some.call(fixedLengthWithOffset, div3));
assert(!Array.prototype.some.call(fixedLengthWithOffset, over10));
assert(Array.prototype.some.call(lengthTracking, div3));
assert(!Array.prototype.some.call(lengthTracking, over10));
assert(Array.prototype.some.call(lengthTrackingWithOffset, div3));
assert(!Array.prototype.some.call(lengthTrackingWithOffset, over10));
}

View File

@ -0,0 +1,69 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.sort
description: >
Array.p.sort behaves correctly on TypedArrays backed by resizable buffers which
are grown by the comparison callback.
includes: [compareArray.js, resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
function ResizeAndCompare(rab, resizeTo) {
return (a, b) => {
rab.resize(resizeTo);
if (a < b) {
return -1;
}
if (a > b) {
return 1;
}
return 0;
}
}
function WriteUnsortedData(taFull) {
for (let i = 0; i < taFull.length; ++i) {
WriteToTypedArray(taFull, i, 10 - i);
}
}
// Fixed length TA.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const resizeTo = 6 * ctor.BYTES_PER_ELEMENT;
const fixedLength = new ctor(rab, 0, 4);
const taFull = new ctor(rab, 0);
WriteUnsortedData(taFull);
Array.prototype.sort.call(fixedLength, ResizeAndCompare(rab, resizeTo));
// Growing doesn't affect the sorting.
assert.compareArray(ToNumbers(taFull), [
7,
8,
9,
10,
0,
0
]);
}
// Length-tracking TA.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const resizeTo = 6 * ctor.BYTES_PER_ELEMENT;
const lengthTracking = new ctor(rab, 0);
const taFull = new ctor(rab, 0);
WriteUnsortedData(taFull);
Array.prototype.sort.call(lengthTracking, ResizeAndCompare(rab, resizeTo));
// Growing doesn't affect the sorting. Only the elements that were part of
// the original TA are sorted.
assert.compareArray(ToNumbers(taFull), [
7,
8,
9,
10,
0,
0
]);
}

View File

@ -0,0 +1,191 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.sort
description: >
Array.p.sort behaves correctly on TypedArrays backed by resizable buffers and
is passed a user-provided comparison callback.
includes: [compareArray.js, resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const fixedLength = new ctor(rab, 0, 4);
const fixedLengthWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT, 2);
const lengthTracking = new ctor(rab, 0);
const lengthTrackingWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT);
const taFull = new ctor(rab, 0);
function WriteUnsortedData() {
// Write some data into the array.
for (let i = 0; i < taFull.length; ++i) {
WriteToTypedArray(taFull, i, 10 - i);
}
}
function OddBeforeEvenComparison(a, b) {
// Sort all odd numbers before even numbers.
a = Number(a);
b = Number(b);
if (a % 2 == 1 && b % 2 == 0) {
return -1;
}
if (a % 2 == 0 && b % 2 == 1) {
return 1;
}
if (a < b) {
return -1;
}
if (a > b) {
return 1;
}
return 0;
}
// Orig. array: [10, 9, 8, 7]
// [10, 9, 8, 7] << fixedLength
// [8, 7] << fixedLengthWithOffset
// [10, 9, 8, 7, ...] << lengthTracking
// [8, 7, ...] << lengthTrackingWithOffset
WriteUnsortedData();
Array.prototype.sort.call(fixedLength, OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [
7,
9,
8,
10
]);
WriteUnsortedData();
Array.prototype.sort.call(fixedLengthWithOffset, OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [
10,
9,
7,
8
]);
WriteUnsortedData();
Array.prototype.sort.call(lengthTracking, OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [
7,
9,
8,
10
]);
WriteUnsortedData();
Array.prototype.sort.call(lengthTrackingWithOffset, OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [
10,
9,
7,
8
]);
// Shrink so that fixed length TAs go out of bounds.
rab.resize(3 * ctor.BYTES_PER_ELEMENT);
// Orig. array: [10, 9, 8]
// [10, 9, 8, ...] << lengthTracking
// [8, ...] << lengthTrackingWithOffset
WriteUnsortedData();
Array.prototype.sort.call(fixedLength, OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [
10,
9,
8
]);
Array.prototype.sort.call(fixedLengthWithOffset, OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [
10,
9,
8
]);
WriteUnsortedData();
Array.prototype.sort.call(lengthTracking, OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [
9,
8,
10
]);
WriteUnsortedData();
Array.prototype.sort.call(lengthTrackingWithOffset, OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [
10,
9,
8
]);
// Shrink so that the TAs with offset go out of bounds.
rab.resize(1 * ctor.BYTES_PER_ELEMENT);
WriteUnsortedData();
Array.prototype.sort.call(fixedLength, OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [10]);
Array.prototype.sort.call(fixedLengthWithOffset, OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [10]);
Array.prototype.sort.call(lengthTrackingWithOffset, OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [10]);
WriteUnsortedData();
Array.prototype.sort.call(lengthTracking, OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [10]);
// Shrink to zero.
rab.resize(0);
Array.prototype.sort.call(fixedLength, OddBeforeEvenComparison);
Array.prototype.sort.call(fixedLengthWithOffset, OddBeforeEvenComparison);
Array.prototype.sort.call(lengthTrackingWithOffset, OddBeforeEvenComparison);
Array.prototype.sort.call(lengthTracking, OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), []);
// Grow so that all TAs are back in-bounds.
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
// Orig. array: [10, 9, 8, 7, 6, 5]
// [10, 9, 8, 7] << fixedLength
// [8, 7] << fixedLengthWithOffset
// [10, 9, 8, 7, 6, 5, ...] << lengthTracking
// [8, 7, 6, 5, ...] << lengthTrackingWithOffset
WriteUnsortedData();
Array.prototype.sort.call(fixedLength, OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [
7,
9,
8,
10,
6,
5
]);
WriteUnsortedData();
Array.prototype.sort.call(fixedLengthWithOffset, OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [
10,
9,
7,
8,
6,
5
]);
WriteUnsortedData();
Array.prototype.sort.call(lengthTracking, OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [
5,
7,
9,
6,
8,
10
]);
WriteUnsortedData();
Array.prototype.sort.call(lengthTrackingWithOffset, OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [
10,
9,
5,
7,
6,
8
]);
}

View File

@ -0,0 +1,71 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.sort
description: >
Array.p.sort behaves correctly on TypedArrays backed by resizable buffers and
is shrunk by the comparison callback.
includes: [compareArray.js, resizableArrayBufferUtils.js]
features: [resizable-arraybuffer, Array.prototype.includes]
---*/
function ResizeAndCompare(rab, resizeTo) {
return (a, b) => {
rab.resize(resizeTo);
if (a < b) {
return -1;
}
if (a > b) {
return 1;
}
return 0;
}
}
function WriteUnsortedData(taFull) {
for (let i = 0; i < taFull.length; ++i) {
WriteToTypedArray(taFull, i, 10 - i);
}
}
// Fixed length TA.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const resizeTo = 2 * ctor.BYTES_PER_ELEMENT;
const fixedLength = new ctor(rab, 0, 4);
const taFull = new ctor(rab, 0);
WriteUnsortedData(taFull);
Array.prototype.sort.call(fixedLength, ResizeAndCompare(rab, resizeTo));
// The data is unchanged.
assert.compareArray(ToNumbers(taFull), [
10,
9
]);
}
// Length-tracking TA.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const resizeTo = 2 * ctor.BYTES_PER_ELEMENT;
const lengthTracking = new ctor(rab, 0);
const taFull = new ctor(rab, 0);
WriteUnsortedData(taFull);
Array.prototype.sort.call(lengthTracking, ResizeAndCompare(rab, resizeTo));
// The sort result is implementation defined, but it contains 2 elements out
// of the 4 original ones.
const newData = ToNumbers(taFull);
assert.sameValue(newData.length, 2);
assert([
10,
9,
8,
7
].includes(newData[0]));
assert([
10,
9,
8,
7
].includes(newData[1]));
}

View File

@ -0,0 +1,173 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.sort
description: >
Array.p.sort behaves correctly on TypedArrays backed by resizable buffers.
includes: [compareArray.js, resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
// The default comparison function for Array.prototype.sort is the string sort.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const fixedLength = new ctor(rab, 0, 4);
const fixedLengthWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT, 2);
const lengthTracking = new ctor(rab, 0);
const lengthTrackingWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT);
const taFull = new ctor(rab, 0);
function WriteUnsortedData() {
// Write some data into the array.
for (let i = 0; i < taFull.length; ++i) {
WriteToTypedArray(taFull, i, 10 - 2 * i);
}
}
// Orig. array: [10, 8, 6, 4]
// [10, 8, 6, 4] << fixedLength
// [6, 4] << fixedLengthWithOffset
// [10, 8, 6, 4, ...] << lengthTracking
// [6, 4, ...] << lengthTrackingWithOffset
WriteUnsortedData();
Array.prototype.sort.call(fixedLength);
assert.compareArray(ToNumbers(taFull), [
10,
4,
6,
8
]);
WriteUnsortedData();
Array.prototype.sort.call(fixedLengthWithOffset);
assert.compareArray(ToNumbers(taFull), [
10,
8,
4,
6
]);
WriteUnsortedData();
Array.prototype.sort.call(lengthTracking);
assert.compareArray(ToNumbers(taFull), [
10,
4,
6,
8
]);
WriteUnsortedData();
Array.prototype.sort.call(lengthTrackingWithOffset);
assert.compareArray(ToNumbers(taFull), [
10,
8,
4,
6
]);
// Shrink so that fixed length TAs go out of bounds.
rab.resize(3 * ctor.BYTES_PER_ELEMENT);
// Orig. array: [10, 8, 6]
// [10, 8, 6, ...] << lengthTracking
// [6, ...] << lengthTrackingWithOffset
WriteUnsortedData();
Array.prototype.sort.call(fixedLength); // OOB -> NOOP
assert.compareArray(ToNumbers(taFull), [
10,
8,
6
]);
Array.prototype.sort.call(fixedLengthWithOffset); // OOB -> NOOP
assert.compareArray(ToNumbers(taFull), [
10,
8,
6
]);
Array.prototype.sort.call(lengthTracking);
assert.compareArray(ToNumbers(taFull), [
10,
6,
8
]);
WriteUnsortedData();
Array.prototype.sort.call(lengthTrackingWithOffset);
assert.compareArray(ToNumbers(taFull), [
10,
8,
6
]);
// Shrink so that the TAs with offset go out of bounds.
rab.resize(1 * ctor.BYTES_PER_ELEMENT);
WriteUnsortedData();
Array.prototype.sort.call(fixedLength); // OOB -> NOOP
assert.compareArray(ToNumbers(taFull), [10]);
Array.prototype.sort.call(fixedLengthWithOffset); // OOB -> NOOP
assert.compareArray(ToNumbers(taFull), [10]);
Array.prototype.sort.call(lengthTrackingWithOffset); // OOB -> NOOP
assert.compareArray(ToNumbers(taFull), [10]);
Array.prototype.sort.call(lengthTracking);
assert.compareArray(ToNumbers(taFull), [10]);
// Shrink to zero.
rab.resize(0);
Array.prototype.sort.call(fixedLength); // OOB -> NOOP
assert.compareArray(ToNumbers(taFull), []);
Array.prototype.sort.call(fixedLengthWithOffset); // OOB -> NOOP
assert.compareArray(ToNumbers(taFull), []);
Array.prototype.sort.call(lengthTrackingWithOffset); // OOB -> NOOP
assert.compareArray(ToNumbers(taFull), []);
Array.prototype.sort.call(lengthTracking);
assert.compareArray(ToNumbers(taFull), []);
// Grow so that all TAs are back in-bounds.
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
// Orig. array: [10, 8, 6, 4, 2, 0]
// [10, 8, 6, 4] << fixedLength
// [6, 4] << fixedLengthWithOffset
// [10, 8, 6, 4, 2, 0, ...] << lengthTracking
// [6, 4, 2, 0, ...] << lengthTrackingWithOffset
WriteUnsortedData();
Array.prototype.sort.call(fixedLength);
assert.compareArray(ToNumbers(taFull), [
10,
4,
6,
8,
2,
0
]);
WriteUnsortedData();
Array.prototype.sort.call(fixedLengthWithOffset);
assert.compareArray(ToNumbers(taFull), [
10,
8,
4,
6,
2,
0
]);
WriteUnsortedData();
Array.prototype.sort.call(lengthTracking);
assert.compareArray(ToNumbers(taFull), [
0,
10,
2,
4,
6,
8
]);
WriteUnsortedData();
Array.prototype.sort.call(lengthTrackingWithOffset);
assert.compareArray(ToNumbers(taFull), [
10,
8,
0,
2,
4,
6
]);
}

View File

@ -0,0 +1,88 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.tolocalestring
description: >
Array.p.toLocaleString behaves correctly on TypedArrays backed by resizable
buffers.
includes: [resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const fixedLength = new ctor(rab, 0, 4);
const fixedLengthWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT, 2);
const lengthTracking = new ctor(rab, 0);
const lengthTrackingWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT);
const taWrite = new ctor(rab);
// toLocaleString separator is implementation dependent.
function listToString(list) {
const comma = ['',''].toLocaleString();
return list.join(comma);
}
// Write some data into the array.
for (let i = 0; i < 4; ++i) {
WriteToTypedArray(taWrite, i, 2 * i);
}
// Orig. array: [0, 2, 4, 6]
// [0, 2, 4, 6] << fixedLength
// [4, 6] << fixedLengthWithOffset
// [0, 2, 4, 6, ...] << lengthTracking
// [4, 6, ...] << lengthTrackingWithOffset
assert.sameValue(Array.prototype.toLocaleString.call(fixedLength), listToString([0,2,4,6]));
assert.sameValue(Array.prototype.toLocaleString.call(fixedLengthWithOffset), listToString([4,6]));
assert.sameValue(Array.prototype.toLocaleString.call(lengthTracking), listToString([0,2,4,6]));
assert.sameValue(Array.prototype.toLocaleString.call(lengthTrackingWithOffset), listToString([4,6]));
// Shrink so that fixed length TAs go out of bounds.
rab.resize(3 * ctor.BYTES_PER_ELEMENT);
// Orig. array: [0, 2, 4]
// [0, 2, 4, ...] << lengthTracking
// [4, ...] << lengthTrackingWithOffset
assert.sameValue(Array.prototype.toLocaleString.call(fixedLength), listToString([]));
assert.sameValue(Array.prototype.toLocaleString.call(fixedLengthWithOffset), listToString([]));
assert.sameValue(Array.prototype.toLocaleString.call(lengthTracking), listToString([0,2,4]));
assert.sameValue(Array.prototype.toLocaleString.call(lengthTrackingWithOffset), listToString([4]));
// Shrink so that the TAs with offset go out of bounds.
rab.resize(1 * ctor.BYTES_PER_ELEMENT);
assert.sameValue(Array.prototype.toLocaleString.call(fixedLength), listToString([]));
assert.sameValue(Array.prototype.toLocaleString.call(fixedLengthWithOffset), listToString([]));
assert.sameValue(Array.prototype.toLocaleString.call(lengthTrackingWithOffset), listToString([]));
assert.sameValue(Array.prototype.toLocaleString.call(lengthTracking), listToString([0]));
// Shrink to zero.
rab.resize(0);
assert.sameValue(Array.prototype.toLocaleString.call(fixedLength), listToString([]));
assert.sameValue(Array.prototype.toLocaleString.call(fixedLengthWithOffset), listToString([]));
assert.sameValue(Array.prototype.toLocaleString.call(lengthTrackingWithOffset), listToString([]));
assert.sameValue(Array.prototype.toLocaleString.call(lengthTracking), listToString([]));
// Grow so that all TAs are back in-bounds.
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
for (let i = 0; i < 6; ++i) {
WriteToTypedArray(taWrite, i, 2 * i);
}
// Orig. array: [0, 2, 4, 6, 8, 10]
// [0, 2, 4, 6] << fixedLength
// [4, 6] << fixedLengthWithOffset
// [0, 2, 4, 6, 8, 10, ...] << lengthTracking
// [4, 6, 8, 10, ...] << lengthTrackingWithOffset
assert.sameValue(Array.prototype.toLocaleString.call(fixedLength), listToString([0,2,4,6]));
assert.sameValue(Array.prototype.toLocaleString.call(fixedLengthWithOffset), listToString([4,6]));
assert.sameValue(Array.prototype.toLocaleString.call(lengthTracking), listToString([0,2,4,6,8,10]));
assert.sameValue(Array.prototype.toLocaleString.call(lengthTrackingWithOffset), listToString([4,6,8,10]));
}

View File

@ -0,0 +1,81 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.tolocalestring
description: >
Array.p.toLocaleString behaves correctly when {Number,BigInt}.prototype.toLocaleString
is replaced with a user-provided function that grows the array.
includes: [resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
const oldNumberPrototypeToLocaleString = Number.prototype.toLocaleString;
const oldBigIntPrototypeToLocaleString = BigInt.prototype.toLocaleString;
// toLocaleString separator is implementation dependent.
function listToString(list) {
const comma = ['',''].toLocaleString();
const len = list.length;
let result = '';
if (len > 1) {
for (let i=0; i < len - 1 ; i++) {
result += list[i] + comma;
}
}
if (len > 0) {
result += list[len-1];
}
return result;
}
// Growing + fixed-length TA.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const fixedLength = new ctor(rab, 0, 4);
let resizeAfter = 2;
Number.prototype.toLocaleString = function () {
--resizeAfter;
if (resizeAfter == 0) {
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
}
return oldNumberPrototypeToLocaleString.call(this);
};
BigInt.prototype.toLocaleString = function () {
--resizeAfter;
if (resizeAfter == 0) {
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
}
return oldBigIntPrototypeToLocaleString.call(this);
};
// We iterate 4 elements since it was the starting length. Resizing doesn't
// affect the TA.
assert.sameValue(Array.prototype.toLocaleString.call(fixedLength), listToString([0,0,0,0]));
}
// Growing + length-tracking TA.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const lengthTracking = new ctor(rab);
let resizeAfter = 2;
Number.prototype.toLocaleString = function () {
--resizeAfter;
if (resizeAfter == 0) {
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
}
return oldNumberPrototypeToLocaleString.call(this);
};
BigInt.prototype.toLocaleString = function () {
--resizeAfter;
if (resizeAfter == 0) {
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
}
return oldBigIntPrototypeToLocaleString.call(this);
};
// We iterate 4 elements since it was the starting length.
assert.sameValue(Array.prototype.toLocaleString.call(lengthTracking), listToString([0,0,0,0]));
}
Number.prototype.toLocaleString = oldNumberPrototypeToLocaleString;
BigInt.prototype.toLocaleString = oldBigIntPrototypeToLocaleString;

View File

@ -0,0 +1,82 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.tolocalestring
description: >
Array.p.toLocaleString behaves correctly when {Number,BigInt}.prototype.toLocaleString
is replaced with a user-provided function that shrinks the array.
includes: [resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
const oldNumberPrototypeToLocaleString = Number.prototype.toLocaleString;
const oldBigIntPrototypeToLocaleString = BigInt.prototype.toLocaleString;
// toLocaleString separator is implementation dependent.
function listToString(list) {
const comma = ['',''].toLocaleString();
const len = list.length;
let result = '';
if (len > 1) {
for (let i=0; i < len - 1 ; i++) {
result += list[i] + comma;
}
}
if (len > 0) {
result += list[len-1];
}
return result;
}
// Shrinking + fixed-length TA.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const fixedLength = new ctor(rab, 0, 4);
let resizeAfter = 2;
Number.prototype.toLocaleString = function () {
--resizeAfter;
if (resizeAfter == 0) {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
}
return oldNumberPrototypeToLocaleString.call(this);
};
BigInt.prototype.toLocaleString = function () {
--resizeAfter;
if (resizeAfter == 0) {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
}
return oldBigIntPrototypeToLocaleString.call(this);
};
// We iterate 4 elements, since it was the starting length. The TA goes
// OOB after 2 elements.
assert.sameValue(Array.prototype.toLocaleString.call(fixedLength),listToString([0,0,'','']));
}
// Shrinking + length-tracking TA.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const lengthTracking = new ctor(rab);
let resizeAfter = 2;
Number.prototype.toLocaleString = function () {
--resizeAfter;
if (resizeAfter == 0) {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
}
return oldNumberPrototypeToLocaleString.call(this);
};
BigInt.prototype.toLocaleString = function () {
--resizeAfter;
if (resizeAfter == 0) {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
}
return oldBigIntPrototypeToLocaleString.call(this);
};
// We iterate 4 elements, since it was the starting length. Elements beyond
// the new length are converted to the empty string.
assert.sameValue(Array.prototype.toLocaleString.call(lengthTracking),listToString([0,0,'','']));
}
Number.prototype.toLocaleString = oldNumberPrototypeToLocaleString;
BigInt.prototype.toLocaleString = oldBigIntPrototypeToLocaleString;

View File

@ -0,0 +1,60 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.values
description: >
Array.p.values behaves correctly on TypedArrays backed by resizable buffers and
resized mid-iteration.
features: [resizable-arraybuffer]
includes: [compareArray.js, resizableArrayBufferUtils.js]
---*/
// Orig. array: [0, 2, 4, 6]
// [0, 2, 4, 6] << fixedLength
// [4, 6] << fixedLengthWithOffset
// [0, 2, 4, 6, ...] << lengthTracking
// [4, 6, ...] << lengthTrackingWithOffset
for (let ctor of ctors) {
const rab = CreateRabForTest(ctor);
const fixedLength = new ctor(rab, 0, 4);
// The fixed length array is not affected by resizing.
TestIterationAndResize(Array.prototype.values.call(fixedLength), [
0,
2,
4,
6
], rab, 2, 6 * ctor.BYTES_PER_ELEMENT);
}
for (let ctor of ctors) {
const rab = CreateRabForTest(ctor);
const fixedLengthWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT, 2);
// The fixed length array is not affected by resizing.
TestIterationAndResize(Array.prototype.values.call(fixedLengthWithOffset), [
4,
6
], rab, 2, 6 * ctor.BYTES_PER_ELEMENT);
}
for (let ctor of ctors) {
const rab = CreateRabForTest(ctor);
const lengthTracking = new ctor(rab, 0);
TestIterationAndResize(Array.prototype.values.call(lengthTracking), [
0,
2,
4,
6,
0,
0
], rab, 2, 6 * ctor.BYTES_PER_ELEMENT);
}
for (let ctor of ctors) {
const rab = CreateRabForTest(ctor);
const lengthTrackingWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT);
TestIterationAndResize(Array.prototype.values.call(lengthTrackingWithOffset), [
4,
6,
0,
0
], rab, 2, 6 * ctor.BYTES_PER_ELEMENT);
}

View File

@ -0,0 +1,52 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.values
description: >
Array.p.values behaves correctly on TypedArrays backed by resizable buffers
that are shrunk mid-iteration.
features: [resizable-arraybuffer]
includes: [compareArray.js, resizableArrayBufferUtils.js]
---*/
// Orig. array: [0, 2, 4, 6]
// [0, 2, 4, 6] << fixedLength
// [4, 6] << fixedLengthWithOffset
// [0, 2, 4, 6, ...] << lengthTracking
// [4, 6, ...] << lengthTrackingWithOffset
for (let ctor of ctors) {
const rab = CreateRabForTest(ctor);
const fixedLength = new ctor(rab, 0, 4);
// The fixed length array goes out of bounds when the RAB is resized.
assert.throws(TypeError, () => {
TestIterationAndResize(Array.prototype.values.call(fixedLength), null, rab, 2, 3 * ctor.BYTES_PER_ELEMENT);
});
}
for (let ctor of ctors) {
const rab = CreateRabForTest(ctor);
const fixedLengthWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT, 2);
assert.throws(TypeError, () => {
TestIterationAndResize(Array.prototype.values.call(fixedLengthWithOffset), null, rab, 2, 3 * ctor.BYTES_PER_ELEMENT);
});
}
for (let ctor of ctors) {
const rab = CreateRabForTest(ctor);
const lengthTracking = new ctor(rab, 0);
TestIterationAndResize(Array.prototype.values.call(lengthTracking), [
0,
2,
4
], rab, 2, 3 * ctor.BYTES_PER_ELEMENT);
}
for (let ctor of ctors) {
const rab = CreateRabForTest(ctor);
const lengthTrackingWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT);
// The fixed length array goes out of bounds when the RAB is resized.
TestIterationAndResize(Array.prototype.values.call(lengthTrackingWithOffset), [
4,
6
], rab, 2, 3 * ctor.BYTES_PER_ELEMENT);
}

View File

@ -0,0 +1,156 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.values
description: >
Array.p.values behaves correctly on TypedArrays backed by resizable buffers.
includes: [compareArray.js, resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
function IteratorToNumbers(iterator) {
const result = [];
for (let value of iterator) {
result.push(Number(value));
}
return result;
}
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const fixedLength = new ctor(rab, 0, 4);
const fixedLengthWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT, 2);
const lengthTracking = new ctor(rab, 0);
const lengthTrackingWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT);
// Write some data into the array.
const taWrite = new ctor(rab);
for (let i = 0; i < 4; ++i) {
WriteToTypedArray(taWrite, i, 2 * i);
}
// Orig. array: [0, 2, 4, 6]
// [0, 2, 4, 6] << fixedLength
// [4, 6] << fixedLengthWithOffset
// [0, 2, 4, 6, ...] << lengthTracking
// [4, 6, ...] << lengthTrackingWithOffset
assert.compareArray(IteratorToNumbers(Array.prototype.values.call(fixedLength)), [
0,
2,
4,
6
]);
assert.compareArray(IteratorToNumbers(Array.prototype.values.call(fixedLengthWithOffset)), [
4,
6
]);
assert.compareArray(IteratorToNumbers(Array.prototype.values.call(lengthTracking)), [
0,
2,
4,
6
]);
assert.compareArray(IteratorToNumbers(Array.prototype.values.call(lengthTrackingWithOffset)), [
4,
6
]);
// Shrink so that fixed length TAs go out of bounds.
rab.resize(3 * ctor.BYTES_PER_ELEMENT);
// Orig. array: [0, 2, 4]
// [0, 2, 4, ...] << lengthTracking
// [4, ...] << lengthTrackingWithOffset
// TypedArray.prototype.{entries, keys, values} throw right away when
// called. Array.prototype.{entries, keys, values} don't throw, but when
// we try to iterate the returned ArrayIterator, that throws.
Array.prototype.values.call(fixedLength);
Array.prototype.values.call(fixedLengthWithOffset);
assert.throws(TypeError, () => {
Array.from(Array.prototype.values.call(fixedLength));
});
assert.throws(TypeError, () => {
Array.from(Array.prototype.values.call(fixedLengthWithOffset));
});
assert.compareArray(IteratorToNumbers(Array.prototype.values.call(lengthTracking)), [
0,
2,
4
]);
assert.compareArray(IteratorToNumbers(Array.prototype.values.call(lengthTrackingWithOffset)), [4]);
// Shrink so that the TAs with offset go out of bounds.
rab.resize(1 * ctor.BYTES_PER_ELEMENT);
Array.prototype.values.call(fixedLength);
Array.prototype.values.call(fixedLengthWithOffset);
Array.prototype.values.call(lengthTrackingWithOffset);
assert.throws(TypeError, () => {
Array.from(Array.prototype.values.call(fixedLength));
});
assert.throws(TypeError, () => {
Array.from(Array.prototype.values.call(fixedLengthWithOffset));
});
assert.throws(TypeError, () => {
Array.from(Array.prototype.values.call(lengthTrackingWithOffset));
});
assert.compareArray(IteratorToNumbers(Array.prototype.values.call(lengthTracking)), [0]);
// Shrink to zero.
rab.resize(0);
Array.prototype.values.call(fixedLength);
Array.prototype.values.call(fixedLengthWithOffset);
Array.prototype.values.call(lengthTrackingWithOffset);
assert.throws(TypeError, () => {
Array.from(Array.prototype.values.call(fixedLength));
});
assert.throws(TypeError, () => {
Array.from(Array.prototype.values.call(fixedLengthWithOffset));
});
assert.throws(TypeError, () => {
Array.from(Array.prototype.values.call(lengthTrackingWithOffset));
});
assert.compareArray(IteratorToNumbers(Array.prototype.values.call(lengthTracking)), []);
// Grow so that all TAs are back in-bounds.
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
for (let i = 0; i < 6; ++i) {
WriteToTypedArray(taWrite, i, 2 * i);
}
// Orig. array: [0, 2, 4, 6, 8, 10]
// [0, 2, 4, 6] << fixedLength
// [4, 6] << fixedLengthWithOffset
// [0, 2, 4, 6, 8, 10, ...] << lengthTracking
// [4, 6, 8, 10, ...] << lengthTrackingWithOffset
assert.compareArray(IteratorToNumbers(Array.prototype.values.call(fixedLength)), [
0,
2,
4,
6
]);
assert.compareArray(IteratorToNumbers(Array.prototype.values.call(fixedLengthWithOffset)), [
4,
6
]);
assert.compareArray(IteratorToNumbers(Array.prototype.values.call(lengthTracking)), [
0,
2,
4,
6,
8,
10
]);
assert.compareArray(IteratorToNumbers(Array.prototype.values.call(lengthTrackingWithOffset)), [
4,
6,
8,
10
]);
}

View File

@ -0,0 +1,23 @@
// Copyright (C) 2023 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-ecmascript-standard-built-in-objects
description: >
The AsyncDisposableStack constructor implements [[Construct]]
info: |
IsConstructor ( argument )
The abstract operation IsConstructor takes argument argument (an ECMAScript language value).
It determines if argument is a function object with a [[Construct]] internal method.
It performs the following steps when called:
If Type(argument) is not Object, return false.
If argument has a [[Construct]] internal method, return true.
Return false.
includes: [isConstructor.js]
features: [explicit-resource-management, Reflect.construct]
---*/
assert.sameValue(isConstructor(AsyncDisposableStack), true, 'isConstructor(AsyncDisposableStack) must return true');
new AsyncDisposableStack();

View File

@ -0,0 +1,32 @@
// Copyright (C) 2023 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-asyncdisposablestack
description: AsyncDisposableStack.length property descriptor
info: |
AsyncDisposableStack ( )
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: [explicit-resource-management]
---*/
verifyProperty(AsyncDisposableStack, 'length', {
value: 0,
writable: false,
enumerable: false,
configurable: true
});

View File

@ -0,0 +1,31 @@
// Copyright (C) 2023 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-asyncdisposablestack
description: AsyncDisposableStack.name property descriptor
info: |
AsyncDisposableStack ( )
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, this value is the name that
is given to the function in this specification. For functions that
are specified as properties of objects, the name value is the
property name string used to access the function. [...]
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: [explicit-resource-management]
---*/
verifyProperty(AsyncDisposableStack, 'name', {
value: 'AsyncDisposableStack',
writable: false,
enumerable: false,
configurable: true
});

View File

@ -0,0 +1,22 @@
// Copyright (C) 2023 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-asyncdisposablestack-constructor
description: >
Property descriptor of AsyncDisposableStack
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: [explicit-resource-management]
---*/
verifyProperty(this, 'AsyncDisposableStack', {
enumerable: false,
writable: true,
configurable: true
});

View File

@ -0,0 +1,32 @@
// Copyright (C) 2023 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-asyncdisposablestack.prototype.adopt
description: AsyncDisposableStack.prototype.adopt.length property descriptor
info: |
AsyncDisposableStack.prototype.adopt ( value, onDisposeAsync )
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: [explicit-resource-management]
---*/
verifyProperty(AsyncDisposableStack.prototype.adopt, 'length', {
value: 2,
writable: false,
enumerable: false,
configurable: true
});

View File

@ -0,0 +1,31 @@
// Copyright (C) 2023 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-asyncdisposablestack.prototype.adopt
description: AsyncDisposableStack.prototype.adopt.name property descriptor
info: |
AsyncDisposableStack.prototype.adopt.name value and property descriptor
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, this value is the name that
is given to the function in this specification. For functions that
are specified as properties of objects, the name value is the
property name string used to access the function. [...]
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: [explicit-resource-management]
---*/
verifyProperty(AsyncDisposableStack.prototype.adopt, 'name', {
value: 'adopt',
writable: false,
enumerable: false,
configurable: true
});

View File

@ -0,0 +1,32 @@
// Copyright (C) 2023 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-asyncdisposablestack.prototype.adopt
description: >
AsyncDisposableStack.prototype.adopt 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: [Reflect.construct, explicit-resource-management, arrow-function]
---*/
assert.sameValue(
isConstructor(AsyncDisposableStack.prototype.adopt),
false,
'isConstructor(AsyncDisposableStack.prototype.adopt) must return false'
);
assert.throws(TypeError, () => {
let stack = new AsyncDisposableStack({}); new stack.adopt();
}, '`let stack = new AsyncDisposableStack({}); new stack.adopt()` throws TypeError');

View File

@ -0,0 +1,24 @@
// Copyright (C) 2023 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-asyncdisposablestack.prototype.adopt
description: >
Property descriptor of AsyncDisposableStack.prototype.adopt
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: [explicit-resource-management]
---*/
assert.sameValue(typeof AsyncDisposableStack.prototype.adopt, 'function');
verifyProperty(AsyncDisposableStack.prototype, 'adopt', {
enumerable: false,
writable: true,
configurable: true
});

View File

@ -0,0 +1,32 @@
// Copyright (C) 2023 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-asyncdisposablestack.prototype.defer
description: AsyncDisposableStack.prototype.defer.length property descriptor
info: |
AsyncDisposableStack.prototype.defer ( onDisposeAsync )
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: [explicit-resource-management]
---*/
verifyProperty(AsyncDisposableStack.prototype.defer, 'length', {
value: 1,
writable: false,
enumerable: false,
configurable: true
});

View File

@ -0,0 +1,31 @@
// Copyright (C) 2023 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-asyncdisposablestack.prototype.defer
description: AsyncDisposableStack.prototype.defer.name property descriptor
info: |
AsyncDisposableStack.prototype.defer.name value and property descriptor
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, this value is the name that
is given to the function in this specification. For functions that
are specified as properties of objects, the name value is the
property name string used to access the function. [...]
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: [explicit-resource-management]
---*/
verifyProperty(AsyncDisposableStack.prototype.defer, 'name', {
value: 'defer',
writable: false,
enumerable: false,
configurable: true
});

View File

@ -0,0 +1,32 @@
// Copyright (C) 2023 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-asyncdisposablestack.prototype.defer
description: >
AsyncDisposableStack.prototype.defer 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: [Reflect.construct, explicit-resource-management, arrow-function]
---*/
assert.sameValue(
isConstructor(AsyncDisposableStack.prototype.defer),
false,
'isConstructor(AsyncDisposableStack.prototype.defer) must return false'
);
assert.throws(TypeError, () => {
let stack = new AsyncDisposableStack({}); new stack.defer();
}, '`let stack = new AsyncDisposableStack({}); new stack.defer()` throws TypeError');

View File

@ -0,0 +1,24 @@
// Copyright (C) 2023 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-asyncdisposablestack.prototype.defer
description: >
Property descriptor of AsyncDisposableStack.prototype.defer
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: [explicit-resource-management]
---*/
assert.sameValue(typeof AsyncDisposableStack.prototype.defer, 'function');
verifyProperty(AsyncDisposableStack.prototype, 'defer', {
enumerable: false,
writable: true,
configurable: true
});

View File

@ -0,0 +1,32 @@
// Copyright (C) 2023 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-asyncdisposablestack.prototype.disposeAsync
description: AsyncDisposableStack.prototype.disposeAsync.length property descriptor
info: |
AsyncDisposableStack.prototype.disposeAsync ( )
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: [explicit-resource-management]
---*/
verifyProperty(AsyncDisposableStack.prototype.disposeAsync, 'length', {
value: 0,
writable: false,
enumerable: false,
configurable: true
});

View File

@ -0,0 +1,31 @@
// Copyright (C) 2023 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-asyncdisposablestack.prototype.disposeAsync
description: AsyncDisposableStack.prototype.disposeAsync.name property descriptor
info: |
AsyncDisposableStack.prototype.disposeAsync.name value and property descriptor
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, this value is the name that
is given to the function in this specification. For functions that
are specified as properties of objects, the name value is the
property name string used to access the function. [...]
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: [explicit-resource-management]
---*/
verifyProperty(AsyncDisposableStack.prototype.disposeAsync, 'name', {
value: 'disposeAsync',
writable: false,
enumerable: false,
configurable: true
});

View File

@ -0,0 +1,32 @@
// Copyright (C) 2023 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-asyncdisposablestack.prototype.disposeAsync
description: >
AsyncDisposableStack.prototype.disposeAsync 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: [Reflect.construct, explicit-resource-management, arrow-function]
---*/
assert.sameValue(
isConstructor(AsyncDisposableStack.prototype.disposeAsync),
false,
'isConstructor(AsyncDisposableStack.prototype.disposeAsync) must return false'
);
assert.throws(TypeError, () => {
let stack = new AsyncDisposableStack({}); new stack.disposeAsync();
}, '`let stack = new AsyncDisposableStack({}); new stack.disposeAsync()` throws TypeError');

View File

@ -0,0 +1,24 @@
// Copyright (C) 2023 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-asyncdisposablestack.prototype.disposeAsync
description: >
Property descriptor of AsyncDisposableStack.prototype.disposeAsync
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: [explicit-resource-management]
---*/
assert.sameValue(typeof AsyncDisposableStack.prototype.disposeAsync, 'function');
verifyProperty(AsyncDisposableStack.prototype, 'disposeAsync', {
enumerable: false,
writable: true,
configurable: true
});

View File

@ -0,0 +1,22 @@
// Copyright (C) 2023 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-get-asyncdisposablestack.prototype.disposed
description: >
AsyncDisposableStack.prototype.disposed.length value and descriptor.
info: |
get AsyncDisposableStack.prototype.disposed
17 ECMAScript Standard Built-in Objects
includes: [propertyHelper.js]
features: [explicit-resource-management]
---*/
var descriptor = Object.getOwnPropertyDescriptor(AsyncDisposableStack.prototype, 'disposed');
verifyProperty(descriptor.get, 'length', {
value: 0,
enumerable: false,
writable: false,
configurable: true
});

View File

@ -0,0 +1,28 @@
// Copyright (C) 2023 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-get-asyncdisposablestack.prototype.disposed
description: >
AsyncDisposableStack.prototype.disposed.name value and descriptor.
info: |
get AsyncDisposableStack.prototype.size
17 ECMAScript Standard Built-in Objects
Functions that are specified as get or set accessor functions of built-in
properties have "get " or "set " prepended to the property name string.
includes: [propertyHelper.js]
features: [explicit-resource-management]
---*/
var descriptor = Object.getOwnPropertyDescriptor(AsyncDisposableStack.prototype, 'disposed');
assert.sameValue(descriptor.get.name,
'get disposed',
'The value of `descriptor.get.name` is `get disposed`'
);
verifyNotEnumerable(descriptor.get, 'name');
verifyNotWritable(descriptor.get, 'name');
verifyConfigurable(descriptor.get, 'name');

View File

@ -0,0 +1,32 @@
// Copyright (C) 2023 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-asyncdisposablestack.prototype.move
description: AsyncDisposableStack.prototype.move.length property descriptor
info: |
AsyncDisposableStack.prototype.move ( )
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: [explicit-resource-management]
---*/
verifyProperty(AsyncDisposableStack.prototype.move, 'length', {
value: 0,
writable: false,
enumerable: false,
configurable: true
});

View File

@ -0,0 +1,31 @@
// Copyright (C) 2023 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-asyncdisposablestack.prototype.move
description: AsyncDisposableStack.prototype.move.name property descriptor
info: |
AsyncDisposableStack.prototype.move.name value and property descriptor
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, this value is the name that
is given to the function in this specification. For functions that
are specified as properties of objects, the name value is the
property name string used to access the function. [...]
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: [explicit-resource-management]
---*/
verifyProperty(AsyncDisposableStack.prototype.move, 'name', {
value: 'move',
writable: false,
enumerable: false,
configurable: true
});

View File

@ -0,0 +1,32 @@
// Copyright (C) 2023 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-asyncdisposablestack.prototype.move
description: >
AsyncDisposableStack.prototype.move 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: [Reflect.construct, explicit-resource-management, arrow-function]
---*/
assert.sameValue(
isConstructor(AsyncDisposableStack.prototype.move),
false,
'isConstructor(AsyncDisposableStack.prototype.move) must return false'
);
assert.throws(TypeError, () => {
let stack = new AsyncDisposableStack({}); new stack.move();
}, '`let stack = new AsyncDisposableStack({}); new stack.move()` throws TypeError');

View File

@ -0,0 +1,24 @@
// Copyright (C) 2023 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-asyncdisposablestack.prototype.move
description: >
Property descriptor of AsyncDisposableStack.prototype.move
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: [explicit-resource-management]
---*/
assert.sameValue(typeof AsyncDisposableStack.prototype.move, 'function');
verifyProperty(AsyncDisposableStack.prototype, 'move', {
enumerable: false,
writable: true,
configurable: true
});

View File

@ -0,0 +1,18 @@
// Copyright (C) 2023 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: The property descriptor AsyncDisposableStack.prototype
esid: sec-properties-of-the-asyncdisposablestack-constructor
info: |
This property has the attributes { [[Writable]]: false, [[Enumerable]]: false,
[[Configurable]]: false }.
features: [explicit-resource-management]
includes: [propertyHelper.js]
---*/
verifyProperty(AsyncDisposableStack, 'prototype', {
writable: false,
enumerable: false,
configurable: false
});

View File

@ -0,0 +1,32 @@
// Copyright (C) 2023 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-asyncdisposablestack.prototype.use
description: AsyncDisposableStack.prototype.use.length property descriptor
info: |
AsyncDisposableStack.prototype.use ( value )
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: [explicit-resource-management]
---*/
verifyProperty(AsyncDisposableStack.prototype.use, 'length', {
value: 1,
writable: false,
enumerable: false,
configurable: true
});

View File

@ -0,0 +1,31 @@
// Copyright (C) 2023 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-asyncdisposablestack.prototype.use
description: AsyncDisposableStack.prototype.use.name property descriptor
info: |
AsyncDisposableStack.prototype.use.name value and property descriptor
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, this value is the name that
is given to the function in this specification. For functions that
are specified as properties of objects, the name value is the
property name string used to access the function. [...]
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: [explicit-resource-management]
---*/
verifyProperty(AsyncDisposableStack.prototype.use, 'name', {
value: 'use',
writable: false,
enumerable: false,
configurable: true
});

View File

@ -0,0 +1,32 @@
// Copyright (C) 2023 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-asyncdisposablestack.prototype.use
description: >
AsyncDisposableStack.prototype.use 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: [Reflect.construct, explicit-resource-management, arrow-function]
---*/
assert.sameValue(
isConstructor(AsyncDisposableStack.prototype.use),
false,
'isConstructor(AsyncDisposableStack.prototype.use) must return false'
);
assert.throws(TypeError, () => {
let stack = new AsyncDisposableStack({}); new stack.use();
}, '`let stack = new AsyncDisposableStack({}); new stack.use()` throws TypeError');

View File

@ -0,0 +1,24 @@
// Copyright (C) 2023 Ron Buckton. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-asyncdisposablestack.prototype.use
description: >
Property descriptor of AsyncDisposableStack.prototype.use
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: [explicit-resource-management]
---*/
assert.sameValue(typeof AsyncDisposableStack.prototype.use, 'function');
verifyProperty(AsyncDisposableStack.prototype, 'use', {
enumerable: false,
writable: true,
configurable: true
});

Some files were not shown because too many files have changed in this diff Show More