Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tests for the asyncItems argument to Array.fromAsync. #3754

Merged
merged 9 commits into from
Mar 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions harness/temporalHelpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ function formatPropertyName(propertyKey, objectName = "") {
case "number":
return `${objectName}[${propertyKey}]`;
default:
// TODO: check if propertyKey is an integer index.
return objectName ? `${objectName}.${propertyKey}` : propertyKey;
}
}
Expand Down
44 changes: 44 additions & 0 deletions test/built-ins/Array/fromAsync/asyncitems-array-add-to-empty.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-array.fromasync
description: >
Array.fromAsync respects array mutation
info: |
Array.fromAsync
3.j.ii.3. Let next be ? Await(IteratorStep(iteratorRecord)).

IteratorStep
1. Let result be ? IteratorNext(iteratorRecord).

IteratorNext
1.a. Let result be ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]]).

%AsyncFromSyncIteratorPrototype%.next
6.a. Let result be Completion(IteratorNext(syncIteratorRecord)).

IteratorNext
1.a. Let result be ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]]).

Array.prototype [ @@iterator ] ( )
Array.prototype.values ( )
2. Return CreateArrayIterator(O, value).

CreateArrayIterator
1.b.iii. If index ≥ len, return NormalCompletion(undefined).
includes: [asyncHelpers.js, compareArray.js]
flags: [async]
features: [Array.fromAsync]
---*/

asyncTest(async function () {
const items = [];
const promise = Array.fromAsync(items);
// By the time we get here, the first next() call has already happened, and returned
// { done: true }. We then return from the loop in Array.fromAsync 3.j.ii. with the empty array,
// and the following line no longer affects that.
items.push(7);
const result = await promise;
assert.compareArray(result, []);
ptomato marked this conversation as resolved.
Show resolved Hide resolved
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-array.fromasync
description: >
Array.fromAsync respects array mutation
info: |
Array.fromAsync
3.j.ii.3. Let next be ? Await(IteratorStep(iteratorRecord)).

IteratorStep
1. Let result be ? IteratorNext(iteratorRecord).

IteratorNext
1.a. Let result be ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]]).

%AsyncFromSyncIteratorPrototype%.next
6.a. Let result be Completion(IteratorNext(syncIteratorRecord)).

IteratorNext
1.a. Let result be ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]]).

Array.prototype [ @@iterator ] ( )
Array.prototype.values ( )
2. Return CreateArrayIterator(O, value).

CreateArrayIterator
1.b.iii. If index ≥ len, return NormalCompletion(undefined).
includes: [asyncHelpers.js, compareArray.js]
flags: [async]
features: [Array.fromAsync]
---*/

asyncTest(async function () {
const items = [1];
const promise = Array.fromAsync(items);
// At this point, the first element of `items` has been read, but the iterator will take other
// changes into account.
items.push(7);
const result = await promise;
assert.compareArray(result, [1, 7]);
});
43 changes: 43 additions & 0 deletions test/built-ins/Array/fromAsync/asyncitems-array-add.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-array.fromasync
description: >
Array.fromAsync respects array mutation
info: |
Array.fromAsync
3.j.ii.3. Let next be ? Await(IteratorStep(iteratorRecord)).

IteratorStep
1. Let result be ? IteratorNext(iteratorRecord).

IteratorNext
1.a. Let result be ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]]).

%AsyncFromSyncIteratorPrototype%.next
6.a. Let result be Completion(IteratorNext(syncIteratorRecord)).

IteratorNext
1.a. Let result be ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]]).

Array.prototype [ @@iterator ] ( )
Array.prototype.values ( )
2. Return CreateArrayIterator(O, value).

CreateArrayIterator
1.b.iii. If index ≥ len, return NormalCompletion(undefined).
includes: [asyncHelpers.js, compareArray.js]
flags: [async]
features: [Array.fromAsync]
---*/

asyncTest(async function () {
const items = [1, 2, 3];
const promise = Array.fromAsync(items);
// At this point, the first element of `items` has been read, but the iterator will take other
// changes into account.
items.push(4);
const result = await promise;
assert.compareArray(result, [1, 2, 3, 4]);
});
44 changes: 44 additions & 0 deletions test/built-ins/Array/fromAsync/asyncitems-array-mutate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-array.fromasync
description: >
Array.fromAsync respects array mutation
info: |
Array.fromAsync
3.j.ii.3. Let next be ? Await(IteratorStep(iteratorRecord)).

IteratorStep
1. Let result be ? IteratorNext(iteratorRecord).

IteratorNext
1.a. Let result be ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]]).

%AsyncFromSyncIteratorPrototype%.next
6.a. Let result be Completion(IteratorNext(syncIteratorRecord)).

IteratorNext
1.a. Let result be ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]]).

Array.prototype [ @@iterator ] ( )
Array.prototype.values ( )
2. Return CreateArrayIterator(O, value).

CreateArrayIterator
1.b.iii. If index ≥ len, return NormalCompletion(undefined).
includes: [asyncHelpers.js, compareArray.js]
flags: [async]
features: [Array.fromAsync]
---*/

asyncTest(async function () {
const items = [1, 2, 3];
const promise = Array.fromAsync(items);
// At this point, the first element of `items` has been read, but the iterator will take other
// changes into account.
items[0] = 7;
items[1] = 8;
const result = await promise;
assert.compareArray(result, [1, 8, 3]);
});
43 changes: 43 additions & 0 deletions test/built-ins/Array/fromAsync/asyncitems-array-remove.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-array.fromasync
description: >
Array.fromAsync respects array mutation
info: |
Array.fromAsync
3.j.ii.3. Let next be ? Await(IteratorStep(iteratorRecord)).

IteratorStep
1. Let result be ? IteratorNext(iteratorRecord).

IteratorNext
1.a. Let result be ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]]).

%AsyncFromSyncIteratorPrototype%.next
6.a. Let result be Completion(IteratorNext(syncIteratorRecord)).

IteratorNext
1.a. Let result be ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]]).

Array.prototype [ @@iterator ] ( )
Array.prototype.values ( )
2. Return CreateArrayIterator(O, value).

CreateArrayIterator
1.b.iii. If index ≥ len, return NormalCompletion(undefined).
includes: [asyncHelpers.js, compareArray.js]
flags: [async]
features: [Array.fromAsync]
---*/

asyncTest(async function () {
const items = [1, 2, 3];
const promise = Array.fromAsync(items);
// At this point, the first element of `items` has been read, but the iterator will take other
// changes into account.
items.pop();
const result = await promise;
assert.compareArray(result, [1, 2]);
});
17 changes: 17 additions & 0 deletions test/built-ins/Array/fromAsync/asyncitems-arraybuffer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-array.fromasync
description: >
Array.fromAsync doesn't special-case ArrayBuffer
includes: [asyncHelpers.js, compareArray.js]
flags: [async]
features: [Array.fromAsync]
---*/

asyncTest(async function () {
const items = new ArrayBuffer(7);
const result = await Array.fromAsync(items);
assert.compareArray(result, []);
});
31 changes: 31 additions & 0 deletions test/built-ins/Array/fromAsync/asyncitems-arraylike-promise.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-array.fromasync
description: >
Array.fromAsync tries the various properties in order and awaits promises
includes: [asyncHelpers.js, compareArray.js, temporalHelpers.js]
flags: [async]
features: [Array.fromAsync]
---*/

asyncTest(async function () {
const actual = [];
const items = TemporalHelpers.propertyBagObserver(actual, {
length: 2,
0: Promise.resolve(2),
1: Promise.resolve(1),
}, "items");
const result = await Array.fromAsync(items);
assert.compareArray(result, [2, 1]);
assert.compareArray(actual, [
"get items[Symbol.asyncIterator]",
"get items[Symbol.iterator]",
"get items.length",
"get items.length.valueOf",
"call items.length.valueOf",
"get items.0",
"get items.1",
]);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-array.fromasync
description: >
Array.fromAsync tries the various properties in order
includes: [asyncHelpers.js, compareArray.js, temporalHelpers.js]
flags: [async]
features: [Array.fromAsync]
---*/

asyncTest(async function () {
async function * asyncGen() {
for (let i = 0; i < 4; i++) {
yield Promise.resolve(i * 2);
}
}

const actual = [];
const items = {};
TemporalHelpers.observeProperty(actual, items, Symbol.asyncIterator, asyncGen, "items");
TemporalHelpers.observeProperty(actual, items, Symbol.iterator, undefined, "items");
TemporalHelpers.observeProperty(actual, items, "length", 2, "items");
TemporalHelpers.observeProperty(actual, items, 0, 2, "items");
TemporalHelpers.observeProperty(actual, items, 1, 1, "items");
const result = await Array.fromAsync(items);
assert.compareArray(result, [0, 2, 4, 6]);
assert.compareArray(actual, [
"get items[Symbol.asyncIterator]",
]);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-array.fromasync
description: >
Array.fromAsync rejects if the @@asyncIterator property is not callable
includes: [asyncHelpers.js]
flags: [async]
features: [Array.fromAsync]
---*/

asyncTest(async function () {
for (const v of [true, "", Symbol(), 1, 1n, {}]) {
await assert.throwsAsync(TypeError,
() => Array.fromAsync({ [Symbol.asyncIterator]: v }),
`@@asyncIterator = ${typeof v}`);
}
});
30 changes: 30 additions & 0 deletions test/built-ins/Array/fromAsync/asyncitems-asynciterator-null.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-array.fromasync
description: >
Array.fromAsync tries the various properties in order
includes: [asyncHelpers.js, compareArray.js, temporalHelpers.js]
flags: [async]
features: [Array.fromAsync]
---*/

asyncTest(async function () {
const actual = [];
const items = {};
TemporalHelpers.observeProperty(actual, items, Symbol.asyncIterator, null, "items");
TemporalHelpers.observeProperty(actual, items, Symbol.iterator, undefined, "items");
TemporalHelpers.observeProperty(actual, items, "length", 2, "items");
TemporalHelpers.observeProperty(actual, items, 0, 2, "items");
TemporalHelpers.observeProperty(actual, items, 1, 1, "items");
const result = await Array.fromAsync(items);
assert.compareArray(result, [2, 1]);
assert.compareArray(actual, [
"get items[Symbol.asyncIterator]",
"get items[Symbol.iterator]",
"get items.length",
"get items[0]",
"get items[1]",
]);
});
32 changes: 32 additions & 0 deletions test/built-ins/Array/fromAsync/asyncitems-asynciterator-sync.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-array.fromasync
description: >
Array.fromAsync handles a sync iterator returned from @@asyncIterator
includes: [asyncHelpers.js, compareArray.js, temporalHelpers.js]
flags: [async]
features: [Array.fromAsync]
---*/

asyncTest(async function () {
function * syncGen() {
for (let i = 0; i < 4; i++) {
yield i * 2;
}
}

const actual = [];
const items = {};
TemporalHelpers.observeProperty(actual, items, Symbol.asyncIterator, syncGen, "items");
TemporalHelpers.observeProperty(actual, items, Symbol.iterator, undefined, "items");
TemporalHelpers.observeProperty(actual, items, "length", 2, "items");
TemporalHelpers.observeProperty(actual, items, 0, 2, "items");
TemporalHelpers.observeProperty(actual, items, 1, 1, "items");
const result = await Array.fromAsync(items);
assert.compareArray(result, [0, 2, 4, 6]);
assert.compareArray(actual, [
"get items[Symbol.asyncIterator]",
]);
});
Loading