mirror of https://github.com/tc39/test262.git
Merge branch 'main' into chromium-export-99eec8f4a2
This commit is contained in:
commit
9f94490ff1
|
@ -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 }}
|
||||
|
|
|
@ -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
|
||||
/*---
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
8
LICENSE
8
LICENSE
|
@ -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
|
||||
|
|
19
features.txt
19
features.txt
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
));
|
||||
});
|
||||
};
|
||||
|
|
|
@ -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) {}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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) })`
|
||||
|
|
|
@ -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([
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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',)
|
|
@ -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', {},)
|
|
@ -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
|
||||
});
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -33,8 +33,8 @@ var child = new Con();
|
|||
|
||||
Object.defineProperty(child, "toString", {
|
||||
value: function() {
|
||||
toStringAccessed = true;
|
||||
return '1';
|
||||
toStringAccessed = true;
|
||||
return '1';
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
79
test/built-ins/Array/prototype/filter/resizable-buffer-shrink-mid-iteration.js
vendored
Normal file
79
test/built-ins/Array/prototype/filter/resizable-buffer-shrink-mid-iteration.js
vendored
Normal 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
|
||||
]);
|
||||
}
|
|
@ -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]
|
||||
---*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
92
test/built-ins/Array/prototype/includes/coerced-searchelement-fromindex-resize.js
vendored
Normal file
92
test/built-ins/Array/prototype/includes/coerced-searchelement-fromindex-resize.js
vendored
Normal 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));
|
||||
}
|
22
test/built-ins/Array/prototype/includes/resizable-buffer-special-float-values.js
vendored
Normal file
22
test/built-ins/Array/prototype/includes/resizable-buffer-special-float-values.js
vendored
Normal 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));
|
||||
}
|
|
@ -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));
|
||||
}
|
55
test/built-ins/Array/prototype/indexOf/coerced-searchelement-fromindex-grow.js
vendored
Normal file
55
test/built-ins/Array/prototype/indexOf/coerced-searchelement-fromindex-grow.js
vendored
Normal 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);
|
||||
}
|
67
test/built-ins/Array/prototype/indexOf/coerced-searchelement-fromindex-shrink.js
vendored
Normal file
67
test/built-ins/Array/prototype/indexOf/coerced-searchelement-fromindex-shrink.js
vendored
Normal 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);
|
||||
}
|
26
test/built-ins/Array/prototype/indexOf/resizable-buffer-special-float-values.js
vendored
Normal file
26
test/built-ins/Array/prototype/indexOf/resizable-buffer-special-float-values.js
vendored
Normal 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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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');
|
||||
}
|
|
@ -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..');
|
||||
}
|
|
@ -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');
|
||||
}
|
|
@ -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);
|
||||
}
|
53
test/built-ins/Array/prototype/keys/resizable-buffer-shrink-mid-iteration.js
vendored
Normal file
53
test/built-ins/Array/prototype/keys/resizable-buffer-shrink-mid-iteration.js
vendored
Normal 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);
|
||||
}
|
|
@ -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
|
||||
]);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
]);
|
||||
}
|
|
@ -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]);
|
||||
}
|
|
@ -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
|
||||
]);
|
||||
}
|
86
test/built-ins/Array/prototype/reduce/resizable-buffer-grow-mid-iteration.js
vendored
Normal file
86
test/built-ins/Array/prototype/reduce/resizable-buffer-grow-mid-iteration.js
vendored
Normal 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
|
||||
]);
|
||||
}
|
79
test/built-ins/Array/prototype/reduce/resizable-buffer-shrink-mid-iteration.js
vendored
Normal file
79
test/built-ins/Array/prototype/reduce/resizable-buffer-shrink-mid-iteration.js
vendored
Normal 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
|
||||
]);
|
||||
}
|
|
@ -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
|
||||
]);
|
||||
}
|
|
@ -37,8 +37,8 @@ function callbackfn(prevVal, curVal, idx, obj) {
|
|||
|
||||
Object.defineProperty(child, "toString", {
|
||||
value: function() {
|
||||
toStringAccessed = true;
|
||||
return '1';
|
||||
toStringAccessed = true;
|
||||
return '1';
|
||||
}
|
||||
});
|
||||
|
||||
|
|
83
test/built-ins/Array/prototype/reduceRight/resizable-buffer-grow-mid-iteration.js
vendored
Normal file
83
test/built-ins/Array/prototype/reduceRight/resizable-buffer-grow-mid-iteration.js
vendored
Normal 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
|
||||
]);
|
||||
}
|
95
test/built-ins/Array/prototype/reduceRight/resizable-buffer-shrink-mid-iteration.js
vendored
Normal file
95
test/built-ins/Array/prototype/reduceRight/resizable-buffer-shrink-mid-iteration.js
vendored
Normal 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
|
||||
]);
|
||||
}
|
|
@ -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
|
||||
]);
|
||||
}
|
|
@ -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
|
||||
]);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
]);
|
||||
}
|
|
@ -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
|
||||
]);
|
||||
}
|
74
test/built-ins/Array/prototype/some/resizable-buffer-shrink-mid-iteration.js
vendored
Normal file
74
test/built-ins/Array/prototype/some/resizable-buffer-shrink-mid-iteration.js
vendored
Normal 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]);
|
||||
}
|
|
@ -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));
|
||||
}
|
|
@ -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
|
||||
]);
|
||||
}
|
|
@ -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
|
||||
]);
|
||||
}
|
|
@ -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]));
|
||||
}
|
|
@ -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
|
||||
]);
|
||||
}
|
|
@ -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]));
|
||||
}
|
81
test/built-ins/Array/prototype/toLocaleString/user-provided-tolocalestring-grow.js
vendored
Normal file
81
test/built-ins/Array/prototype/toLocaleString/user-provided-tolocalestring-grow.js
vendored
Normal 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;
|
82
test/built-ins/Array/prototype/toLocaleString/user-provided-tolocalestring-shrink.js
vendored
Normal file
82
test/built-ins/Array/prototype/toLocaleString/user-provided-tolocalestring-shrink.js
vendored
Normal 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;
|
60
test/built-ins/Array/prototype/values/resizable-buffer-grow-mid-iteration.js
vendored
Normal file
60
test/built-ins/Array/prototype/values/resizable-buffer-grow-mid-iteration.js
vendored
Normal 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);
|
||||
}
|
52
test/built-ins/Array/prototype/values/resizable-buffer-shrink-mid-iteration.js
vendored
Normal file
52
test/built-ins/Array/prototype/values/resizable-buffer-shrink-mid-iteration.js
vendored
Normal 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);
|
||||
}
|
|
@ -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
|
||||
]);
|
||||
}
|
|
@ -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();
|
|
@ -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
|
||||
});
|
|
@ -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
|
||||
});
|
|
@ -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
|
||||
});
|
|
@ -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
|
||||
});
|
|
@ -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
|
||||
});
|
|
@ -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');
|
|
@ -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
|
||||
});
|
|
@ -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
|
||||
});
|
|
@ -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
|
||||
});
|
|
@ -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');
|
|
@ -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
|
||||
});
|
|
@ -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
|
||||
});
|
|
@ -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
|
||||
});
|
32
test/built-ins/AsyncDisposableStack/prototype/disposeAsync/not-a-constructor.js
vendored
Normal file
32
test/built-ins/AsyncDisposableStack/prototype/disposeAsync/not-a-constructor.js
vendored
Normal 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');
|
|
@ -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
|
||||
});
|
|
@ -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
|
||||
});
|
|
@ -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');
|
|
@ -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
|
||||
});
|
|
@ -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
|
||||
});
|
|
@ -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');
|
|
@ -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
|
||||
});
|
|
@ -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
|
||||
});
|
|
@ -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
|
||||
});
|
|
@ -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
|
||||
});
|
|
@ -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');
|
|
@ -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
Loading…
Reference in New Issue