diff --git a/harness/temporalHelpers.js b/harness/temporalHelpers.js index 6e69850ef2e..41273ee0460 100644 --- a/harness/temporalHelpers.js +++ b/harness/temporalHelpers.js @@ -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; } } diff --git a/test/built-ins/Array/fromAsync/asyncitems-array-add-to-empty.js b/test/built-ins/Array/fromAsync/asyncitems-array-add-to-empty.js new file mode 100644 index 00000000000..d39b8f22ae0 --- /dev/null +++ b/test/built-ins/Array/fromAsync/asyncitems-array-add-to-empty.js @@ -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, []); +}); diff --git a/test/built-ins/Array/fromAsync/asyncitems-array-add-to-singleton.js b/test/built-ins/Array/fromAsync/asyncitems-array-add-to-singleton.js new file mode 100644 index 00000000000..09f9dc9627c --- /dev/null +++ b/test/built-ins/Array/fromAsync/asyncitems-array-add-to-singleton.js @@ -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]); +}); diff --git a/test/built-ins/Array/fromAsync/asyncitems-array-add.js b/test/built-ins/Array/fromAsync/asyncitems-array-add.js new file mode 100644 index 00000000000..fa47c6f7786 --- /dev/null +++ b/test/built-ins/Array/fromAsync/asyncitems-array-add.js @@ -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]); +}); diff --git a/test/built-ins/Array/fromAsync/asyncitems-array-mutate.js b/test/built-ins/Array/fromAsync/asyncitems-array-mutate.js new file mode 100644 index 00000000000..29a7a1180ab --- /dev/null +++ b/test/built-ins/Array/fromAsync/asyncitems-array-mutate.js @@ -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]); +}); diff --git a/test/built-ins/Array/fromAsync/asyncitems-array-remove.js b/test/built-ins/Array/fromAsync/asyncitems-array-remove.js new file mode 100644 index 00000000000..712157db4ef --- /dev/null +++ b/test/built-ins/Array/fromAsync/asyncitems-array-remove.js @@ -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]); +}); diff --git a/test/built-ins/Array/fromAsync/asyncitems-arraybuffer.js b/test/built-ins/Array/fromAsync/asyncitems-arraybuffer.js new file mode 100644 index 00000000000..30a74008279 --- /dev/null +++ b/test/built-ins/Array/fromAsync/asyncitems-arraybuffer.js @@ -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, []); +}); diff --git a/test/built-ins/Array/fromAsync/asyncitems-arraylike-promise.js b/test/built-ins/Array/fromAsync/asyncitems-arraylike-promise.js new file mode 100644 index 00000000000..932ca0b0fec --- /dev/null +++ b/test/built-ins/Array/fromAsync/asyncitems-arraylike-promise.js @@ -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", + ]); +}); diff --git a/test/built-ins/Array/fromAsync/asyncitems-asynciterator-exists.js b/test/built-ins/Array/fromAsync/asyncitems-asynciterator-exists.js new file mode 100644 index 00000000000..3ca3eb7a496 --- /dev/null +++ b/test/built-ins/Array/fromAsync/asyncitems-asynciterator-exists.js @@ -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]", + ]); +}); diff --git a/test/built-ins/Array/fromAsync/asyncitems-asynciterator-not-callable.js b/test/built-ins/Array/fromAsync/asyncitems-asynciterator-not-callable.js new file mode 100644 index 00000000000..b23280a4f4b --- /dev/null +++ b/test/built-ins/Array/fromAsync/asyncitems-asynciterator-not-callable.js @@ -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}`); + } +}); diff --git a/test/built-ins/Array/fromAsync/asyncitems-asynciterator-null.js b/test/built-ins/Array/fromAsync/asyncitems-asynciterator-null.js new file mode 100644 index 00000000000..989959d44ae --- /dev/null +++ b/test/built-ins/Array/fromAsync/asyncitems-asynciterator-null.js @@ -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]", + ]); +}); diff --git a/test/built-ins/Array/fromAsync/asyncitems-asynciterator-sync.js b/test/built-ins/Array/fromAsync/asyncitems-asynciterator-sync.js new file mode 100644 index 00000000000..d74375c55c8 --- /dev/null +++ b/test/built-ins/Array/fromAsync/asyncitems-asynciterator-sync.js @@ -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]", + ]); +}); diff --git a/test/built-ins/Array/fromAsync/asyncitems-asynciterator-throws.js b/test/built-ins/Array/fromAsync/asyncitems-asynciterator-throws.js new file mode 100644 index 00000000000..64e3f159d76 --- /dev/null +++ b/test/built-ins/Array/fromAsync/asyncitems-asynciterator-throws.js @@ -0,0 +1,16 @@ +// 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 getting the @@asyncIterator property throws +includes: [asyncHelpers.js] +flags: [async] +features: [Array.fromAsync] +---*/ + +asyncTest(async function () { + await assert.throwsAsync(Test262Error, + () => Array.fromAsync({ get [Symbol.asyncIterator]() { throw new Test262Error() } })); +}); diff --git a/test/built-ins/Array/fromAsync/asyncitems-bigint.js b/test/built-ins/Array/fromAsync/asyncitems-bigint.js new file mode 100644 index 00000000000..dbc4c02ae11 --- /dev/null +++ b/test/built-ins/Array/fromAsync/asyncitems-bigint.js @@ -0,0 +1,20 @@ +// 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 treats a BigInt as an array-like +includes: [asyncHelpers.js, compareArray.js] +flags: [async] +features: [Array.fromAsync] +---*/ + +asyncTest(async function () { + BigInt.prototype.length = 2; + BigInt.prototype[0] = 1; + BigInt.prototype[1] = 2; + + const result = await Array.fromAsync(1n); + assert.compareArray(result, [1, 2]); +}); diff --git a/test/built-ins/Array/fromAsync/asyncitems-boolean.js b/test/built-ins/Array/fromAsync/asyncitems-boolean.js new file mode 100644 index 00000000000..884fe8f0e2c --- /dev/null +++ b/test/built-ins/Array/fromAsync/asyncitems-boolean.js @@ -0,0 +1,20 @@ +// 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 treats a boolean as an array-like +includes: [asyncHelpers.js, compareArray.js] +flags: [async] +features: [Array.fromAsync] +---*/ + +asyncTest(async function () { + Boolean.prototype.length = 2; + Boolean.prototype[0] = 1; + Boolean.prototype[1] = 2; + + const result = await Array.fromAsync(true); + assert.compareArray(result, [1, 2]); +}); diff --git a/test/built-ins/Array/fromAsync/asyncitems-function.js b/test/built-ins/Array/fromAsync/asyncitems-function.js new file mode 100644 index 00000000000..f2227cb3824 --- /dev/null +++ b/test/built-ins/Array/fromAsync/asyncitems-function.js @@ -0,0 +1,21 @@ +// 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 treats a function as an array-like, reading elements up to fn.length +includes: [asyncHelpers.js, compareArray.js] +flags: [async] +features: [Array.fromAsync] +---*/ + +asyncTest(async function () { + const fn = function(a, b) {}; + fn[0] = 1; + fn[1] = 2; + fn[2] = 3; + + const result = await Array.fromAsync(fn); + assert.compareArray(result, [1, 2]); +}); diff --git a/test/built-ins/Array/fromAsync/asyncitems-iterator-exists.js b/test/built-ins/Array/fromAsync/asyncitems-iterator-exists.js new file mode 100644 index 00000000000..20b4a488e15 --- /dev/null +++ b/test/built-ins/Array/fromAsync/asyncitems-iterator-exists.js @@ -0,0 +1,33 @@ +// 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 @@iterator +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, undefined, "items"); + TemporalHelpers.observeProperty(actual, items, Symbol.iterator, syncGen, "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]", + "get items[Symbol.iterator]", + ]); +}); diff --git a/test/built-ins/Array/fromAsync/asyncitems-iterator-not-callable.js b/test/built-ins/Array/fromAsync/asyncitems-iterator-not-callable.js new file mode 100644 index 00000000000..e0eedeb24ba --- /dev/null +++ b/test/built-ins/Array/fromAsync/asyncitems-iterator-not-callable.js @@ -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 @@iterator 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.iterator]: v }), + `@@iterator = ${typeof v}`); + } +}); diff --git a/test/built-ins/Array/fromAsync/asyncitems-iterator-null.js b/test/built-ins/Array/fromAsync/asyncitems-iterator-null.js new file mode 100644 index 00000000000..357d3d39c5b --- /dev/null +++ b/test/built-ins/Array/fromAsync/asyncitems-iterator-null.js @@ -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, undefined, "items"); + TemporalHelpers.observeProperty(actual, items, Symbol.iterator, null, "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]", + ]); +}); diff --git a/test/built-ins/Array/fromAsync/asyncitems-iterator-promise.js b/test/built-ins/Array/fromAsync/asyncitems-iterator-promise.js new file mode 100644 index 00000000000..5feed624f12 --- /dev/null +++ b/test/built-ins/Array/fromAsync/asyncitems-iterator-promise.js @@ -0,0 +1,33 @@ +// 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 an async iterator returned from @@iterator +includes: [asyncHelpers.js, compareArray.js, temporalHelpers.js] +flags: [async] +features: [Array.fromAsync] +---*/ + +asyncTest(async function () { + function * asyncGen() { + for (let i = 0; i < 4; i++) { + yield Promise.resolve(i * 2); + } + } + + const actual = []; + const items = {}; + TemporalHelpers.observeProperty(actual, items, Symbol.asyncIterator, undefined, "items"); + TemporalHelpers.observeProperty(actual, items, Symbol.iterator, asyncGen, "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]", + "get items[Symbol.iterator]", + ]); +}); diff --git a/test/built-ins/Array/fromAsync/asyncitems-iterator-throws.js b/test/built-ins/Array/fromAsync/asyncitems-iterator-throws.js new file mode 100644 index 00000000000..4e187021cfa --- /dev/null +++ b/test/built-ins/Array/fromAsync/asyncitems-iterator-throws.js @@ -0,0 +1,16 @@ +// 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 getting the @@iterator property throws +includes: [asyncHelpers.js] +flags: [async] +features: [Array.fromAsync] +---*/ + +asyncTest(async function () { + await assert.throwsAsync(Test262Error, + () => Array.fromAsync({ get [Symbol.iterator]() { throw new Test262Error() } })); +}); diff --git a/test/built-ins/Array/fromAsync/asyncitems-null-undefined.js b/test/built-ins/Array/fromAsync/asyncitems-null-undefined.js new file mode 100644 index 00000000000..198deb5d5b4 --- /dev/null +++ b/test/built-ins/Array/fromAsync/asyncitems-null-undefined.js @@ -0,0 +1,18 @@ +// 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 with a TypeError if the asyncItems argument is null or undefined +info: | + 3.c. Let usingAsyncIterator be ? GetMethod(asyncItems, @@asyncIterator). +includes: [asyncHelpers.js] +flags: [async] +features: [Array.fromAsync] +---*/ + +asyncTest(async function () { + await assert.throwsAsync(TypeError, () => Array.fromAsync(null), "null asyncItems"); + await assert.throwsAsync(TypeError, () => Array.fromAsync(undefined), "undefined asyncItems"); +}); diff --git a/test/built-ins/Array/fromAsync/asyncitems-number.js b/test/built-ins/Array/fromAsync/asyncitems-number.js new file mode 100644 index 00000000000..893fafea436 --- /dev/null +++ b/test/built-ins/Array/fromAsync/asyncitems-number.js @@ -0,0 +1,20 @@ +// 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 treats a Number as an array-like +includes: [asyncHelpers.js, compareArray.js] +flags: [async] +features: [Array.fromAsync] +---*/ + +asyncTest(async function () { + Number.prototype.length = 2; + Number.prototype[0] = 1; + Number.prototype[1] = 2; + + const result = await Array.fromAsync(1); + assert.compareArray(result, [1, 2]); +}); diff --git a/test/built-ins/Array/fromAsync/asyncitems-operations.js b/test/built-ins/Array/fromAsync/asyncitems-operations.js new file mode 100644 index 00000000000..33b96b614ee --- /dev/null +++ b/test/built-ins/Array/fromAsync/asyncitems-operations.js @@ -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, undefined, "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]", + ]); +}); diff --git a/test/built-ins/Array/fromAsync/asyncitems-string.js b/test/built-ins/Array/fromAsync/asyncitems-string.js new file mode 100644 index 00000000000..4d991b070b8 --- /dev/null +++ b/test/built-ins/Array/fromAsync/asyncitems-string.js @@ -0,0 +1,16 @@ +// 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 iterates over a string +includes: [asyncHelpers.js, compareArray.js] +flags: [async] +features: [Array.fromAsync] +---*/ + +asyncTest(async function () { + const result = await Array.fromAsync("test"); + assert.compareArray(result, ["t", "e", "s", "t"]); +}); diff --git a/test/built-ins/Array/fromAsync/asyncitems-symbol.js b/test/built-ins/Array/fromAsync/asyncitems-symbol.js new file mode 100644 index 00000000000..3764f173dec --- /dev/null +++ b/test/built-ins/Array/fromAsync/asyncitems-symbol.js @@ -0,0 +1,20 @@ +// 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 treats a Symbol as an array-like +includes: [asyncHelpers.js, compareArray.js] +flags: [async] +features: [Array.fromAsync] +---*/ + +asyncTest(async function () { + Symbol.prototype.length = 2; + Symbol.prototype[0] = 1; + Symbol.prototype[1] = 2; + + const result = await Array.fromAsync(Symbol()); + assert.compareArray(result, [1, 2]); +});