diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /js/src/tests/test262/built-ins/Iterator | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/tests/test262/built-ins/Iterator')
414 files changed, 12025 insertions, 0 deletions
diff --git a/js/src/tests/test262/built-ins/Iterator/browser.js b/js/src/tests/test262/built-ins/Iterator/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/browser.js diff --git a/js/src/tests/test262/built-ins/Iterator/constructor.js b/js/src/tests/test262/built-ins/Iterator/constructor.js new file mode 100644 index 0000000000..ba563ad495 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/constructor.js @@ -0,0 +1,14 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-iterator-constructor +description: > + The Iterator constructor is a built-in function +features: [iterator-helpers] +---*/ + +assert.sameValue(typeof Iterator, 'function', 'The value of `typeof Iterator` is "function"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/from/browser.js b/js/src/tests/test262/built-ins/Iterator/from/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/from/browser.js diff --git a/js/src/tests/test262/built-ins/Iterator/from/callable.js b/js/src/tests/test262/built-ins/Iterator/from/callable.js new file mode 100644 index 0000000000..2df78d05e7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/from/callable.js @@ -0,0 +1,15 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iterator.from +description: > + Iterator.from is callable +features: [iterator-helpers] +---*/ +function* g() {} + +Iterator.from(g()); +Iterator.from.call(null, g()); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/from/get-next-method-only-once.js b/js/src/tests/test262/built-ins/Iterator/from/get-next-method-only-once.js new file mode 100644 index 0000000000..efe706a72a --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/from/get-next-method-only-once.js @@ -0,0 +1,49 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iterator.from +description: > + Gets the next method from the underlying iterator only once +info: | + Iterator.from ( O ) + + 2. Let iteratorRecord be ? GetIteratorFlattenable(O). + +features: [iterator-helpers] +flags: [] +---*/ +let nextGets = 0; +let nextCalls = 0; + +class CountingIterator { + get next() { + ++nextGets; + let iter = (function* () { + for (let i = 1; i < 5; ++i) { + yield i; + } + })(); + return function () { + ++nextCalls; + return iter.next(); + }; + } +} + +let iterator = new CountingIterator(); + +assert.sameValue(nextGets, 0, 'The value of `nextGets` is 0'); +assert.sameValue(nextCalls, 0, 'The value of `nextCalls` is 0'); + +iterator = Iterator.from(iterator); + +assert.sameValue(nextGets, 1, 'The value of `nextGets` is 1'); +assert.sameValue(nextCalls, 0, 'The value of `nextCalls` is 0'); + +iterator.toArray(); + +assert.sameValue(nextGets, 1, 'The value of `nextGets` is 1'); +assert.sameValue(nextCalls, 5, 'The value of `nextCalls` is 5'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/from/get-next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/from/get-next-method-throws.js new file mode 100644 index 0000000000..ea590b912b --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/from/get-next-method-throws.js @@ -0,0 +1,28 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iterator.from +description: > + Underlying iterator has throwing next getter +info: | + Iterator.from ( O ) + + 4. Let iterated be ? GetIteratorDirect(O). + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator { + get next() { + throw new Test262Error(); + } +} + +let iterator = new ThrowingIterator(); + +assert.throws(Test262Error, function () { + Iterator.from(iterator); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/from/is-function.js b/js/src/tests/test262/built-ins/Iterator/from/is-function.js new file mode 100644 index 0000000000..c350a6233d --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/from/is-function.js @@ -0,0 +1,13 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iterator.from +description: > + Iterator.from is a built-in function +features: [iterator-helpers] +---*/ + +assert.sameValue(typeof Iterator.from, 'function', 'The value of `typeof Iterator.from` is "function"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/from/iterable-primitives.js b/js/src/tests/test262/built-ins/Iterator/from/iterable-primitives.js new file mode 100644 index 0000000000..e441136b91 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/from/iterable-primitives.js @@ -0,0 +1,56 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iterator.from +description: > + Iterator.from does not respect the iterability of any primitive except Strings +info: | + Iterator.from ( O ) + + 1. If O is a String, set O to ! ToObject(O). + 2. Let iteratorRecord be ? GetIteratorFlattenable(O). + +includes: [compareArray.js] +features: [iterator-helpers] +flags: [] +---*/ + +function* g() { + yield 0; +} + +Number.prototype[Symbol.iterator] = function* () { + let i = 0; + let target = this >>> 0; + while (i < target) { + yield i; + ++i; + } +}; + +assert.compareArray(Array.from(5), [0, 1, 2, 3, 4]); + +assert.throws(TypeError, function () { + Iterator.from(5); +}); + +assert.compareArray(Array.from(Iterator.from(new Number(5))), [0, 1, 2, 3, 4]); + +assert.compareArray(Array.from(Iterator.from('string')), ['s', 't', 'r', 'i', 'n', 'g']); + +const originalStringIterator = String.prototype[Symbol.iterator]; +let observedType; +Object.defineProperty(String.prototype, Symbol.iterator, { + get() { + 'use strict'; + observedType = typeof this; + return originalStringIterator; + } +}); +Iterator.from(''); +assert.sameValue(observedType, 'string'); +Iterator.from(new String('')); +assert.sameValue(observedType, 'object'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/from/iterable-to-iterator-fallback.js b/js/src/tests/test262/built-ins/Iterator/from/iterable-to-iterator-fallback.js new file mode 100644 index 0000000000..567eb7d474 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/from/iterable-to-iterator-fallback.js @@ -0,0 +1,54 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iterator.from +description: > + Iterator.from falls back to treating its parameter as an iterator if the Symbol.iterator property is null/undefined +info: | + Iterator.from ( O ) + +includes: [compareArray.js] +features: [iterator-helpers] +flags: [] +---*/ + +function* g() { + yield 0; + yield 1; + yield 2; +} + +let iter = (function () { + let n = g(); + return { + [Symbol.iterator]: 0, + next: () => n.next(), + }; +})(); + +assert.throws(TypeError, function () { + Iterator.from(iter); +}); + +iter = (function () { + let n = g(); + return { + [Symbol.iterator]: null, + next: () => n.next(), + }; +})(); + +assert.compareArray(Array.from(Iterator.from(iter)), [0, 1, 2]); + +iter = (function () { + let n = g(); + return { + [Symbol.iterator]: undefined, + next: () => n.next(), + }; +})(); + +assert.compareArray(Array.from(Iterator.from(iter)), [0, 1, 2]); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/from/length.js b/js/src/tests/test262/built-ins/Iterator/from/length.js new file mode 100644 index 0000000000..5e434e66bb --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/from/length.js @@ -0,0 +1,25 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iterator.from +description: > + Iterator.from has a "length" property whose value is 1. +info: | + ECMAScript Standard Built-in Objects + + Unless otherwise specified, the length property of a built-in + Function object has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: true }. +features: [iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator.from, 'length', { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/from/name.js b/js/src/tests/test262/built-ins/Iterator/from/name.js new file mode 100644 index 0000000000..489b62aa19 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/from/name.js @@ -0,0 +1,32 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iterator.from +description: > + The "name" property of Iterator.from +info: | + 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. + + ... + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +features: [iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator.from, 'name', { + value: 'from', + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/from/non-constructible.js b/js/src/tests/test262/built-ins/Iterator/from/non-constructible.js new file mode 100644 index 0000000000..21c14df223 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/from/non-constructible.js @@ -0,0 +1,26 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iterator.from +description: > + Iterator.from is not constructible. + + 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. +features: [iterator-helpers] +---*/ +function* g() {} + +assert.throws(TypeError, () => { + new Iterator.from(); +}); + +assert.throws(TypeError, () => { + new Iterator.from(g()); +}); + +assert.throws(TypeError, () => { + new class extends Iterator {}.from(g()); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/from/primitives.js b/js/src/tests/test262/built-ins/Iterator/from/primitives.js new file mode 100644 index 0000000000..d71f4417c9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/from/primitives.js @@ -0,0 +1,41 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iterator.from +description: > + Iterator.from throws on primitives (except Strings) +info: | + Iterator.from ( O ) + +features: [iterator-helpers] +flags: [] +---*/ + +assert.throws(TypeError, function () { + Iterator.from(null); +}); + +assert.throws(TypeError, function () { + Iterator.from(undefined); +}); + +assert.throws(TypeError, function () { + Iterator.from(0); +}); + +assert.throws(TypeError, function () { + Iterator.from(0n); +}); + +assert.throws(TypeError, function () { + Iterator.from(true); +}); + +assert.throws(TypeError, function () { + Iterator.from(Symbol()); +}); + +Iterator.from('string'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/from/prop-desc.js b/js/src/tests/test262/built-ins/Iterator/from/prop-desc.js new file mode 100644 index 0000000000..2bcc902e98 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/from/prop-desc.js @@ -0,0 +1,29 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iterator.from +description: > + Property descriptor of Iterator.from +info: | + Iterator.from + + * is the initial value of the Iterator.from property of the global object. + + 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. +features: [globalThis, iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator, 'from', { + value: Iterator.from, + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/from/proto.js b/js/src/tests/test262/built-ins/Iterator/from/proto.js new file mode 100644 index 0000000000..2f6c9f8c65 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/from/proto.js @@ -0,0 +1,18 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iterator.from +description: > + The value of the [[Prototype]] internal slot of Iterator.from is the + intrinsic object %FunctionPrototype%. +features: [iterator-helpers] +---*/ + +assert.sameValue( + Object.getPrototypeOf(Iterator.from), + Function.prototype, + 'Object.getPrototypeOf(Iterator.from) must return the value of Function.prototype' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/from/result-proto.js b/js/src/tests/test262/built-ins/Iterator/from/result-proto.js new file mode 100644 index 0000000000..60e12e0a41 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/from/result-proto.js @@ -0,0 +1,32 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iterator.from +description: > + The value of the [[Prototype]] internal slot of the return value of Iterator.from is the + intrinsic object %WrapForValidIteratorPrototype%, whose [[Prototype]] is %IteratorHelperPrototype%. +features: [iterator-helpers] +---*/ +let iter = { + next() { + return { + done: true, + value: undefined, + }; + }, +}; + +const WrapForValidIteratorPrototype = Object.getPrototypeOf(Iterator.from(iter)); + +assert.sameValue(Object.getPrototypeOf(WrapForValidIteratorPrototype), Iterator.prototype); + +class SubIterator extends Iterator {} +assert.sameValue(Object.getPrototypeOf(SubIterator.from(iter)), WrapForValidIteratorPrototype); + +function* g() {} +const GeneratorPrototype = Object.getPrototypeOf(g()); + +assert.sameValue(Object.getPrototypeOf(Iterator.from(g())), GeneratorPrototype); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/from/shell.js b/js/src/tests/test262/built-ins/Iterator/from/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/from/shell.js diff --git a/js/src/tests/test262/built-ins/Iterator/from/supports-iterable.js b/js/src/tests/test262/built-ins/Iterator/from/supports-iterable.js new file mode 100644 index 0000000000..06cfa66537 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/from/supports-iterable.js @@ -0,0 +1,18 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iterator.from +description: > + Iterator.from supports iterables +info: | + Iterator.from ( O ) + +includes: [compareArray.js] +features: [iterator-helpers] +flags: [] +---*/ +assert.compareArray(Array.from(Iterator.from([0, 1, 2, 3])), [0, 1, 2, 3]); +assert.compareArray(Array.from(Iterator.from(new String('str'))), ['s', 't', 'r']); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/from/supports-iterator.js b/js/src/tests/test262/built-ins/Iterator/from/supports-iterator.js new file mode 100644 index 0000000000..c7a30480e8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/from/supports-iterator.js @@ -0,0 +1,32 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iterator.from +description: > + Iterator.from supports non-iterable iterators +info: | + Iterator.from ( O ) + +includes: [compareArray.js] +features: [iterator-helpers] +flags: [] +---*/ + +function* g() { + yield 0; + yield 1; + yield 2; + yield 3; +} + +let n = g(); +let iter = { + next() { + return n.next(); + }, +}; + +assert.compareArray(Array.from(Iterator.from(iter)), [0, 1, 2, 3]); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/length.js b/js/src/tests/test262/built-ins/Iterator/length.js new file mode 100644 index 0000000000..17116179c2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/length.js @@ -0,0 +1,29 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-iterator-constructor +description: > + Iterator has a "length" property whose value is 0. +info: | + The Iterator Constructor + + The length property of the Iterator constructor function is 0. + ... + + ES7 section 17: Unless otherwise specified, the length property of a built-in + Function object has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: true }. +features: [iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator, 'length', { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/name.js b/js/src/tests/test262/built-ins/Iterator/name.js new file mode 100644 index 0000000000..43563b6132 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/name.js @@ -0,0 +1,33 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-iterator-constructor +description: > + The "name" property of Iterator +info: | + 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. + + ... + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +features: [iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator, 'name', { + value: 'Iterator', + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/newtarget-or-active-function-object.js b/js/src/tests/test262/built-ins/Iterator/newtarget-or-active-function-object.js new file mode 100644 index 0000000000..8b99541d87 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/newtarget-or-active-function-object.js @@ -0,0 +1,25 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-iterator +description: > + Iterator is not callable or constructable +info: | + When the Iterator function is called, the following steps are taken: + + If NewTarget is undefined or the active function object, throw a TypeError exception. + +features: [iterator-helpers] +---*/ + +assert.throws(TypeError, () => { + Iterator(); +}); + +assert.throws(TypeError, () => { + new Iterator(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prop-desc.js b/js/src/tests/test262/built-ins/Iterator/prop-desc.js new file mode 100644 index 0000000000..fc2efef324 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prop-desc.js @@ -0,0 +1,30 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-iterator-constructor +description: > + Property descriptor of Iterator +info: | + The Iterator Constructor + + * is the initial value of the Iterator property of the global object. + + 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. +features: [globalThis, iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(globalThis, 'Iterator', { + value: Iterator, + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/proto-from-ctor-realm.js b/js/src/tests/test262/built-ins/Iterator/proto-from-ctor-realm.js new file mode 100644 index 0000000000..ffae2a51cb --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/proto-from-ctor-realm.js @@ -0,0 +1,39 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-iterator +description: Default [[Prototype]] value derived from realm of the NewTarget. +features: [cross-realm, iterator-helpers, Reflect, Symbol] +---*/ + +let other = $262.createRealm().global; +let newTarget = new other.Function(); +let ai; + +newTarget.prototype = undefined; +ai = Reflect.construct(Iterator, [1], newTarget); +assert.sameValue(Object.getPrototypeOf(ai), other.Iterator.prototype); + +newTarget.prototype = null; +ai = Reflect.construct(Iterator, [1], newTarget); +assert.sameValue(Object.getPrototypeOf(ai), other.Iterator.prototype); + +newTarget.prototype = true; +ai = Reflect.construct(Iterator, [1], newTarget); +assert.sameValue(Object.getPrototypeOf(ai), other.Iterator.prototype); + +newTarget.prototype = ''; +ai = Reflect.construct(Iterator, [1], newTarget); +assert.sameValue(Object.getPrototypeOf(ai), other.Iterator.prototype); + +newTarget.prototype = Symbol(); +ai = Reflect.construct(Iterator, [1], newTarget); +assert.sameValue(Object.getPrototypeOf(ai), other.Iterator.prototype); + +newTarget.prototype = 0; +ai = Reflect.construct(Iterator, [1], newTarget); +assert.sameValue(Object.getPrototypeOf(ai), other.Iterator.prototype); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/proto.js b/js/src/tests/test262/built-ins/Iterator/proto.js new file mode 100644 index 0000000000..6e5baeff98 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/proto.js @@ -0,0 +1,19 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-properties-of-the-iterator-constructor +description: > + The value of the [[Prototype]] internal slot of the Iterator constructor is the + intrinsic object %FunctionPrototype%. +features: [iterator-helpers] +---*/ + +assert.sameValue( + Object.getPrototypeOf(Iterator), + Function.prototype, + 'Object.getPrototypeOf(Iterator) must return the value of Function.prototype' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/browser.js b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/browser.js diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/is-function.js b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/is-function.js new file mode 100644 index 0000000000..8b18d80ccd --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/is-function.js @@ -0,0 +1,15 @@ +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.some +description: > + Iterator.prototype.some is a built-in function +features: [Symbol.iterator] +---*/ +const IteratorPrototype = Object.getPrototypeOf( + Object.getPrototypeOf([][Symbol.iterator]()) +); + +assert.sameValue(typeof IteratorPrototype[Symbol.iterator], 'function'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/length.js b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/length.js new file mode 100644 index 0000000000..398404d1bb --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/length.js @@ -0,0 +1,32 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.1.2.1 +description: Length of %IteratorPrototype%[ @@iterator ] +info: | + ES6 Section 17: + 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, including optional parameters. + + [...] + + Unless otherwise specified, the length property of a built-in Function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +features: [Symbol.iterator] +includes: [propertyHelper.js] +---*/ +const IteratorPrototype = Object.getPrototypeOf( + Object.getPrototypeOf([][Symbol.iterator]()) +); + +verifyProperty(IteratorPrototype[Symbol.iterator], 'length', { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/name.js b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/name.js new file mode 100644 index 0000000000..62b78dfbd8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/name.js @@ -0,0 +1,35 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.1.2.1 +description: Descriptor for `name` property +info: | + The value of the name property of this function is "[Symbol.iterator]". + + ES6 Section 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. + + [...] + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +features: [Symbol.iterator] +includes: [propertyHelper.js] +---*/ +const IteratorPrototype = Object.getPrototypeOf( + Object.getPrototypeOf([][Symbol.iterator]()) +); + +verifyProperty(IteratorPrototype[Symbol.iterator], 'name', { + value: '[Symbol.iterator]', + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/prop-desc.js b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/prop-desc.js new file mode 100644 index 0000000000..6f08e5017d --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/prop-desc.js @@ -0,0 +1,25 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.1.2.1 +description: Property descriptor +info: | + ES6 Section 17 + + 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. +features: [Symbol.iterator] +includes: [propertyHelper.js] +---*/ +const IteratorPrototype = Object.getPrototypeOf( + Object.getPrototypeOf([][Symbol.iterator]()) +); + +verifyProperty(IteratorPrototype, Symbol.iterator, { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/return-val.js b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/return-val.js new file mode 100644 index 0000000000..a2ac55b494 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/return-val.js @@ -0,0 +1,23 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%iteratorprototype%-@@iterator +description: Return value of @@iterator on %IteratorPrototype% +info: | + %IteratorPrototype% [ @@iterator ] ( ) + 1. Return the this value. +features: [Symbol.iterator] +---*/ +const IteratorPrototype = Object.getPrototypeOf( + Object.getPrototypeOf([][Symbol.iterator]()) +); + +const getIterator = IteratorPrototype[Symbol.iterator]; + +const thisValues = [{}, Symbol(), 4, 4n, true, undefined, null]; + +for (const thisValue of thisValues) { + assert.sameValue(getIterator.call(thisValue), thisValue); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/shell.js b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.iterator/shell.js diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.toStringTag/browser.js b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.toStringTag/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.toStringTag/browser.js diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.toStringTag/prop-desc.js b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.toStringTag/prop-desc.js new file mode 100644 index 0000000000..5aaffdb1ca --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.toStringTag/prop-desc.js @@ -0,0 +1,19 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype-@@tostringtag +description: Property descriptor +info: | + `Iterator.prototype[@@toStringTag]` is an accessor property with attributes { [[Enumerable]]: *false*, [[Configurable]]: *true* } +features: [iterator-helpers] +---*/ +let desc = Object.getOwnPropertyDescriptor(Iterator.prototype, Symbol.toStringTag); +assert.sameValue(typeof desc.get, 'function'); +assert.sameValue(typeof desc.set, 'function'); +assert.sameValue(desc.configurable, true); +assert.sameValue(desc.enumerable, false); +assert.sameValue(desc.value, undefined); +assert.sameValue(desc.writable, undefined); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.toStringTag/shell.js b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.toStringTag/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.toStringTag/shell.js diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.toStringTag/weird-setter.js b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.toStringTag/weird-setter.js new file mode 100644 index 0000000000..f38db1ce10 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/Symbol.toStringTag/weird-setter.js @@ -0,0 +1,60 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-set-iteratorprototype-@@tostringtag +description: weird setter +info: | + The value of the [[Get]] attribute is a built-in function that requires no arguments. It performs the following steps when called: + 1. Return *"Iterator"*. + + The value of the [[Set]] attribute is a built-in function that takes an argument _v_. It performs the following steps when called: + 1. Perform ? SetterThatIgnoresPrototypeProperties(%Iterator.prototype%, %Symbol.toStringTag%, _v_). + 2. Return *undefined*. +features: [iterator-helpers] +---*/ + +let IteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]())) + +let sentinel = 'a'; + +let { get, set } = Object.getOwnPropertyDescriptor(Iterator.prototype, Symbol.toStringTag); + +assert.sameValue(Iterator.prototype[Symbol.toStringTag], 'Iterator'); +assert.sameValue(get.call(), 'Iterator'); + +// 1. If _this_ is not an Object, then +// 1. Throw a *TypeError* exception. +assert.throws(TypeError, () => set.call(undefined, '')); +assert.throws(TypeError, () => set.call(null, '')); +assert.throws(TypeError, () => set.call(true, '')); + +// 1. If _this_ is _home_, then +// 1. NOTE: Throwing here emulates assignment to a non-writable data property on the _home_ object in strict mode code. +// 1. Throw a *TypeError* exception. +assert.throws(TypeError, () => set.call(IteratorPrototype, '')); +assert.throws(TypeError, () => IteratorPrototype[Symbol.toStringTag] = ''); + +assert.sameValue(Iterator.prototype[Symbol.toStringTag], 'Iterator'); +assert.sameValue(get.call(), 'Iterator'); + +// 1. If _desc_ is *undefined*, then +// 1. Perform ? CreateDataPropertyOrThrow(_this_, _p_, _v_). +let FakeGeneratorPrototype = Object.create(IteratorPrototype); +Object.freeze(IteratorPrototype); +FakeGeneratorPrototype[Symbol.toStringTag] = sentinel; +assert.sameValue(FakeGeneratorPrototype[Symbol.toStringTag], sentinel); + +assert.sameValue(Iterator.prototype[Symbol.toStringTag], 'Iterator'); +assert.sameValue(get.call(), 'Iterator'); + +// 1. Else, +// 1. Perform ? Set(_this_, _p_, _v_, *true*). +let o = { [Symbol.toStringTag]: sentinel + 'a' }; +set.call(o, sentinel); +assert.sameValue(o[Symbol.toStringTag], sentinel); + +assert.sameValue(Iterator.prototype[Symbol.toStringTag], 'Iterator'); +assert.sameValue(get.call(), 'Iterator'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/browser.js b/js/src/tests/test262/built-ins/Iterator/prototype/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/browser.js diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/constructor/browser.js b/js/src/tests/test262/built-ins/Iterator/prototype/constructor/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/constructor/browser.js diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/constructor/prop-desc.js b/js/src/tests/test262/built-ins/Iterator/prototype/constructor/prop-desc.js new file mode 100644 index 0000000000..33d2c48200 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/constructor/prop-desc.js @@ -0,0 +1,19 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.constructor +description: Property descriptor +info: | + `Iterator.prototype.constructor` is an accessor property with attributes { [[Enumerable]]: *false*, [[Configurable]]: *true* } +features: [iterator-helpers] +---*/ +let desc = Object.getOwnPropertyDescriptor(Iterator.prototype, 'constructor'); +assert.sameValue(typeof desc.get, 'function'); +assert.sameValue(typeof desc.set, 'function'); +assert.sameValue(desc.configurable, true); +assert.sameValue(desc.enumerable, false); +assert.sameValue(desc.value, undefined); +assert.sameValue(desc.writable, undefined); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/constructor/shell.js b/js/src/tests/test262/built-ins/Iterator/prototype/constructor/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/constructor/shell.js diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/constructor/weird-setter.js b/js/src/tests/test262/built-ins/Iterator/prototype/constructor/weird-setter.js new file mode 100644 index 0000000000..b342d43189 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/constructor/weird-setter.js @@ -0,0 +1,60 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-set-iteratorprototype-constructor +description: weird setter +info: | + The value of the [[Get]] attribute is a built-in function that requires no arguments. It performs the following steps when called: + 1. Return %Iterator%. + + The value of the [[Set]] attribute is a built-in function that takes an argument _v_. It performs the following steps when called: + 1. Perform ? SetterThatIgnoresPrototypeProperties(%Iterator.prototype%, *"constructor"*, _v_). + 2. Return *undefined*. +features: [iterator-helpers] +---*/ + +let IteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]())) + +let sentinel = {}; + +let { get, set } = Object.getOwnPropertyDescriptor(Iterator.prototype, 'constructor'); + +assert.sameValue(Iterator.prototype.constructor, Iterator); +assert.sameValue(get.call(), Iterator); + +// 1. If _this_ is not an Object, then +// 1. Throw a *TypeError* exception. +assert.throws(TypeError, () => set.call(undefined, '')); +assert.throws(TypeError, () => set.call(null, '')); +assert.throws(TypeError, () => set.call(true, '')); + +// 1. If _this_ is _home_, then +// 1. NOTE: Throwing here emulates assignment to a non-writable data property on the _home_ object in strict mode code. +// 1. Throw a *TypeError* exception. +assert.throws(TypeError, () => set.call(IteratorPrototype, '')); +assert.throws(TypeError, () => IteratorPrototype.constructor = ''); + +assert.sameValue(Iterator.prototype.constructor, Iterator); +assert.sameValue(get.call(), Iterator); + +// 1. If _desc_ is *undefined*, then +// 1. Perform ? CreateDataPropertyOrThrow(_this_, _p_, _v_). +let FakeGeneratorPrototype = Object.create(IteratorPrototype); +Object.freeze(IteratorPrototype); +FakeGeneratorPrototype.constructor = sentinel; +assert.sameValue(FakeGeneratorPrototype.constructor, sentinel); + +assert.sameValue(Iterator.prototype.constructor, Iterator); +assert.sameValue(get.call(), Iterator); + +// 1. Else, +// 1. Perform ? Set(_this_, _p_, _v_, *true*). +let o = { constructor: sentinel + 'a' }; +set.call(o, sentinel); +assert.sameValue(o.constructor, sentinel); + +assert.sameValue(Iterator.prototype.constructor, Iterator); +assert.sameValue(get.call(), Iterator); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/argument-effect-order.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/argument-effect-order.js new file mode 100644 index 0000000000..c501a64906 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/argument-effect-order.js @@ -0,0 +1,67 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.drop +description: > + Arguments and this value are evaluated in the correct order +info: | + %Iterator.prototype%.drop ( limit ) + +includes: [compareArray.js] +features: [iterator-helpers] +flags: [] +---*/ +let effects = []; + +Iterator.prototype.drop.call( + { + get next() { + effects.push('get next'); + return function () { + return { done: true, value: undefined }; + }; + }, + }, + { + valueOf() { + effects.push('ToNumber limit'); + return 0; + }, + } +); + +assert.compareArray(effects, ['ToNumber limit', 'get next']); + +effects = []; + +assert.throws(TypeError, function () { + Iterator.prototype.drop.call(null, { + valueOf() { + effects.push('ToNumber limit'); + return 0; + }, + }); +}); + +assert.compareArray(effects, []); + +effects = []; + +assert.throws(RangeError, function () { + Iterator.prototype.drop.call( + { + get next() { + effects.push('get next'); + return function () { + return { done: true, value: undefined }; + }; + }, + }, + NaN + ); +}); + +assert.compareArray(effects, []); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/browser.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/browser.js diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/callable.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/callable.js new file mode 100644 index 0000000000..d4c4963910 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/callable.js @@ -0,0 +1,16 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.drop +description: > + Iterator.prototype.drop is callable +features: [iterator-helpers] +---*/ +function* g() {} +Iterator.prototype.drop.call(g(), 0); + +let iter = g(); +iter.drop(0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/exhaustion-does-not-call-return.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/exhaustion-does-not-call-return.js new file mode 100644 index 0000000000..93bddaa7b5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/exhaustion-does-not-call-return.js @@ -0,0 +1,63 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.drop +description: > + Underlying iterator return is not called when result iterator is exhausted +info: | + %Iterator.prototype%.drop ( limit ) + + 6.b.ii. Let next be ? IteratorStep(iterated). + 6.b.iii. If next is false, return undefined. + 6.c. Repeat, + 6.c.i. Let next be ? IteratorStep(iterated). + 6.c.ii. If next is false, return undefined. + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield 0; + yield 1; + yield 2; +} + +class TestIterator extends Iterator { + get next() { + let n = g(); + return function() { + return n.next(); + }; + } + return() { + throw new Test262Error(); + } +} + +let iterator = new TestIterator(); +iterator = iterator.drop(0); +iterator.next(); +iterator.next(); +iterator.next(); +iterator.next(); +iterator.next(); + +iterator = new TestIterator(); +iterator = iterator.drop(1); +iterator.next(); +iterator.next(); +iterator.next(); +iterator.next(); + +iterator = new TestIterator(); +iterator = iterator.drop(1).drop(1).drop(1).drop(1).drop(1); +iterator.next(); +iterator.next(); + +iterator = new TestIterator(); +iterator = iterator.drop(10); +iterator.next(); +iterator.next(); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/get-next-method-only-once.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/get-next-method-only-once.js new file mode 100644 index 0000000000..753b7c03a0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/get-next-method-only-once.js @@ -0,0 +1,44 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.drop +description: > + Gets the next method from the underlying iterator only once +info: | + %Iterator.prototype%.drop ( limit ) + + 1. Let iterated be ? GetIteratorDirect(this value). + +features: [iterator-helpers] +flags: [] +---*/ +let nextGets = 0; +let nextCalls = 0; + +class CountingIterator extends Iterator { + get next() { + ++nextGets; + let iter = (function* () { + for (let i = 1; i < 5; ++i) { + yield i; + } + })(); + return function () { + ++nextCalls; + return iter.next(); + }; + } +} + +let iterator = new CountingIterator(); + +assert.sameValue(nextGets, 0); +assert.sameValue(nextCalls, 0); + +for (const value of iterator.drop(2)); + +assert.sameValue(nextGets, 1); +assert.sameValue(nextCalls, 5); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/get-next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/get-next-method-throws.js new file mode 100644 index 0000000000..b6817af23c --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/get-next-method-throws.js @@ -0,0 +1,28 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.drop +description: > + Underlying iterator has throwing next getter +info: | + %Iterator.prototype%.drop ( limit ) + + 1. Let iterated be ? GetIteratorDirect(this value). + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + get next() { + throw new Test262Error(); + } +} + +let iterator = new ThrowingIterator(); + +assert.throws(Test262Error, function () { + iterator.drop(0); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/get-return-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/get-return-method-throws.js new file mode 100644 index 0000000000..f8349edac5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/get-return-method-throws.js @@ -0,0 +1,33 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.drop +description: > + Underlying iterator return is throwing getter +info: | + %Iterator.prototype%.drop ( limit ) + +features: [iterator-helpers] +flags: [] +---*/ +class TestIterator extends Iterator { + next() { + return { + done: false, + value: 1, + }; + } + get return() { + throw new Test262Error(); + } +} + +let iterator = new TestIterator().drop(1); +iterator.next(); + +assert.throws(Test262Error, function () { + iterator.return(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/is-function.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/is-function.js new file mode 100644 index 0000000000..9f8ca765af --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/is-function.js @@ -0,0 +1,13 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.drop +description: > + Iterator.prototype.drop is a built-in function +features: [iterator-helpers] +---*/ + +assert.sameValue(typeof Iterator.prototype.drop, 'function'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/length.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/length.js new file mode 100644 index 0000000000..ec97338db2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/length.js @@ -0,0 +1,25 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.drop +description: > + Iterator.prototype.drop has a "length" property whose value is 1. +info: | + ECMAScript Standard Built-in Objects + + Unless otherwise specified, the length property of a built-in + Function object has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: true }. +features: [iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator.prototype.drop, 'length', { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-equals-total.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-equals-total.js new file mode 100644 index 0000000000..9af5174189 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-equals-total.js @@ -0,0 +1,25 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.drop +description: > + Removes entries from this iterator, specified by limit argument. +info: | + %Iterator.prototype%.drop ( limit ) + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield 1; + yield 2; +} + +let iterator = g().drop(2); +let { value, done } = iterator.next(); + +assert.sameValue(value, undefined); +assert.sameValue(done, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-greater-than-total.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-greater-than-total.js new file mode 100644 index 0000000000..2330660728 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-greater-than-total.js @@ -0,0 +1,40 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.drop +description: > + Removes entries from this iterator, specified by limit argument. +info: | + %Iterator.prototype%.drop ( limit ) + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield 1; + yield 2; +} + +{ + let iterator = g().drop(3); + let { value, done } = iterator.next(); + assert.sameValue(value, undefined); + assert.sameValue(done, true); +} + +{ + let iterator = g().drop(Number.MAX_SAFE_INTEGER); + let { value, done } = iterator.next(); + assert.sameValue(value, undefined); + assert.sameValue(done, true); +} + +{ + let iterator = g().drop(Infinity); + let { value, done } = iterator.next(); + assert.sameValue(value, undefined); + assert.sameValue(done, true); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-less-than-total.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-less-than-total.js new file mode 100644 index 0000000000..4502bdf90d --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-less-than-total.js @@ -0,0 +1,33 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.drop +description: > + Removes entries from this iterator, specified by limit argument. +info: | + %Iterator.prototype%.drop ( limit ) + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield 1; + yield 2; +} + +let iterator = g().drop(1); + +{ + let { value, done } = iterator.next(); + assert.sameValue(value, 2); + assert.sameValue(done, false); +} + +{ + let { value, done } = iterator.next(); + assert.sameValue(value, undefined); + assert.sameValue(done, true); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-rangeerror.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-rangeerror.js new file mode 100644 index 0000000000..2bfcd62aa6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-rangeerror.js @@ -0,0 +1,39 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.drop +description: > + Throws a RangeError exception when limit argument is NaN or less than 0. +info: | + %Iterator.prototype%.drop ( limit ) + + 3. If numLimit is NaN, throw a RangeError exception. + 4. Let integerLimit be ! ToIntegerOrInfinity(numLimit). + 5. If integerLimit < 0, throw a RangeError exception. + +features: [iterator-helpers] +---*/ +let iterator = (function* () {})(); + +iterator.drop(0); +iterator.drop(-0.5); +iterator.drop(null); + +assert.throws(RangeError, () => { + iterator.drop(-1); +}); + +assert.throws(RangeError, () => { + iterator.drop(); +}); + +assert.throws(RangeError, () => { + iterator.drop(undefined); +}); + +assert.throws(RangeError, () => { + iterator.drop(NaN); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-tonumber-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-tonumber-throws.js new file mode 100644 index 0000000000..d736903a4d --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-tonumber-throws.js @@ -0,0 +1,25 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.drop +description: > + Throws a RangeError exception when limit argument valueOf throws. +info: | + %Iterator.prototype%.drop ( limit ) + + 2. Let numLimit be ? ToNumber(limit). + +features: [iterator-helpers] +---*/ +let iterator = (function* () {})(); + +assert.throws(Test262Error, () => { + iterator.drop({ + valueOf: function () { + throw new Test262Error(); + }, + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-tonumber.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-tonumber.js new file mode 100644 index 0000000000..a50d86aacd --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/limit-tonumber.js @@ -0,0 +1,40 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.drop +description: > + Converts the limit argument to a Number using ToNumber and valueOf/toString. +info: | + %Iterator.prototype%.drop ( limit ) + + 2. Let numLimit be ? ToNumber(limit). + +features: [iterator-helpers] +---*/ +function* g() { + yield 1; + yield 2; +} + +{ + let iterator = g(); + let { value, done } = iterator + .drop({ + valueOf: function () { + return 1; + }, + }) + .next(); + assert.sameValue(value, 2); + assert.sameValue(done, false); +} + +{ + let iterator = g(); + let { value, done } = iterator.drop([]).drop([1]).next(); + assert.sameValue(value, 2); + assert.sameValue(done, false); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/name.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/name.js new file mode 100644 index 0000000000..cd0e599c59 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/name.js @@ -0,0 +1,32 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.drop +description: > + The "name" property of Iterator.prototype.drop +info: | + 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. + + ... + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +features: [iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator.prototype.drop, 'name', { + value: 'drop', + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/next-method-returns-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/next-method-returns-non-object.js new file mode 100644 index 0000000000..5f7b406435 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/next-method-returns-non-object.js @@ -0,0 +1,36 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.drop +description: > + Underlying iterator next returns non-object +info: | + %Iterator.prototype%.drop ( limit ) + + 6.b.ii. Let next be ? IteratorStep(iterated). + + 6.c.i. Let next be ? IteratorStep(iterated). + +features: [iterator-helpers] +flags: [] +---*/ +class NonObjectIterator extends Iterator { + next() { + return null; + } +} + +let iterator = new NonObjectIterator().drop(0); + +assert.throws(TypeError, function () { + iterator.next(); +}); + +iterator = new NonObjectIterator().drop(2); + +assert.throws(TypeError, function () { + iterator.next(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/next-method-returns-throwing-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/next-method-returns-throwing-done.js new file mode 100644 index 0000000000..88c5a3a938 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/next-method-returns-throwing-done.js @@ -0,0 +1,44 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.drop +description: > + Underlying iterator next returns object with throwing done getter +info: | + %Iterator.prototype%.drop ( limit ) + + 6.b.ii. Let next be ? IteratorStep(iterated). + + 6.c.i. Let next be ? IteratorStep(iterated). + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + return { + get done() { + throw new Test262Error(); + }, + value: 1, + }; + } + return() { + throw new Error(); + } +} + +let iterator = new ThrowingIterator().drop(0); + +assert.throws(Test262Error, function () { + iterator.next(); +}); + +iterator = new ThrowingIterator().drop(1); + +assert.throws(Test262Error, function () { + iterator.next(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/next-method-returns-throwing-value-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/next-method-returns-throwing-value-done.js new file mode 100644 index 0000000000..3ca5d413d7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/next-method-returns-throwing-value-done.js @@ -0,0 +1,39 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.drop +description: > + Underlying iterator next returns object with throwing value getter, but is already done +info: | + %Iterator.prototype%.drop ( limit ) + + 6.c.ii. If next is false, return undefined. + +features: [iterator-helpers] +flags: [] +---*/ +class ReturnCalledError extends Error {} +class ValueGetterError extends Error {} + +class ThrowingIterator extends Iterator { + next() { + return { + done: true, + get value() { + throw new ValueGetterError(); + }, + }; + } + return() { + throw new ReturnCalledError(); + } +} + +let iterator = new ThrowingIterator().drop(0); +iterator.next(); + +iterator = new ThrowingIterator().drop(1); +iterator.next(); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/next-method-returns-throwing-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/next-method-returns-throwing-value.js new file mode 100644 index 0000000000..d645749345 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/next-method-returns-throwing-value.js @@ -0,0 +1,42 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.drop +description: > + Underlying iterator next returns object with throwing value getter +info: | + %Iterator.prototype%.drop ( limit ) + + 6.c.iii. Let completion be Completion(Yield(? IteratorValue(next))). + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + return { + done: false, + get value() { + throw new Test262Error(); + }, + }; + } + return() { + throw new Error(); + } +} + +let iterator = new ThrowingIterator().drop(0); + +assert.throws(Test262Error, function () { + iterator.next(); +}); + +iterator = new ThrowingIterator().drop(1); + +assert.throws(Test262Error, function () { + iterator.next(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/next-method-throws.js new file mode 100644 index 0000000000..cdc4bdec77 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/next-method-throws.js @@ -0,0 +1,36 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.drop +description: > + Underlying iterator has throwing next method +info: | + %Iterator.prototype%.drop ( limit ) + + 6.b.ii. Let next be ? IteratorStep(iterated). + + 6.c.i. Let next be ? IteratorStep(iterated). + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + throw new Test262Error(); + } +} + +let iterator = new ThrowingIterator().drop(0); + +assert.throws(Test262Error, function () { + iterator.next(); +}); + +iterator = new ThrowingIterator().drop(1); + +assert.throws(Test262Error, function () { + iterator.next(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/non-constructible.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/non-constructible.js new file mode 100644 index 0000000000..cb97d9d4ff --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/non-constructible.js @@ -0,0 +1,31 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.drop +description: > + Iterator.prototype.drop is not constructible. + + 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. +features: [iterator-helpers] +---*/ +function* g() {} +let iter = g(); + +assert.throws(TypeError, () => { + new iter.drop(); +}); + +assert.throws(TypeError, () => { + new iter.drop(0); +}); + +assert.throws(TypeError, () => { + new Iterator.prototype.drop(0); +}); + +assert.throws(TypeError, () => { + new class extends Iterator {}.drop(0); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/prop-desc.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/prop-desc.js new file mode 100644 index 0000000000..c3a94feb6c --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/prop-desc.js @@ -0,0 +1,28 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.drop +description: > + Property descriptor of Iterator.prototype.drop +info: | + Iterator.prototype.drop + + * is the initial value of the Iterator.prototype.drop property of the global object. + + 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. +features: [globalThis, iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator.prototype, 'drop', { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/proto.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/proto.js new file mode 100644 index 0000000000..f6fadfb5fa --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/proto.js @@ -0,0 +1,14 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.drop +description: > + The value of the [[Prototype]] internal slot of Iterator.prototype.drop is the + intrinsic object %FunctionPrototype%. +features: [iterator-helpers] +---*/ + +assert.sameValue(Object.getPrototypeOf(Iterator.prototype.drop), Function.prototype); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/result-is-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/result-is-iterator.js new file mode 100644 index 0000000000..67d99b9b96 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/result-is-iterator.js @@ -0,0 +1,14 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.drop +description: > + The value of the [[Prototype]] internal slot of the return value of Iterator.prototype.drop is the + intrinsic object %IteratorHelperPrototype%. +features: [iterator-helpers] +---*/ + +assert((function* () {})().drop(0) instanceof Iterator, 'function*(){}().drop(0) must return an Iterator'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/return-is-forwarded.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/return-is-forwarded.js new file mode 100644 index 0000000000..7aadc2f0dd --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/return-is-forwarded.js @@ -0,0 +1,57 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.drop +description: > + Underlying iterator return is called when result iterator is closed +info: | + %Iterator.prototype%.drop ( limit ) + + 6.c.iii. Let completion be Completion(Yield(? IteratorValue(next))). + 6.c.iv. IfAbruptCloseIterator(completion, iterated). + +features: [iterator-helpers] +flags: [] +---*/ +let returnCount = 0; + +class TestIterator extends Iterator { + next() { + return { + done: false, + value: 1, + }; + } + return() { + ++returnCount; + return {}; + } +} + +let iterator = new TestIterator().drop(0); +assert.sameValue(returnCount, 0); +iterator.return(); +assert.sameValue(returnCount, 1); +iterator.return(); +assert.sameValue(returnCount, 1); + +returnCount = 0; + +iterator = new TestIterator().drop(1); +assert.sameValue(returnCount, 0); +iterator.return(); +assert.sameValue(returnCount, 1); +iterator.return(); +assert.sameValue(returnCount, 1); + +returnCount = 0; + +iterator = new TestIterator().drop(1).drop(1).drop(1).drop(1).drop(1); +assert.sameValue(returnCount, 0); +iterator.return(); +assert.sameValue(returnCount, 1); +iterator.return(); +assert.sameValue(returnCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/return-is-not-forwarded-after-exhaustion.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/return-is-not-forwarded-after-exhaustion.js new file mode 100644 index 0000000000..27cb08f04b --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/return-is-not-forwarded-after-exhaustion.js @@ -0,0 +1,53 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.drop +description: > + Underlying iterator return is not called after result iterator observes that underlying iterator is exhausted +info: | + %Iterator.prototype%.drop ( limit ) + +features: [iterator-helpers] +flags: [] +---*/ +let returnCount = 0; + +class TestIterator extends Iterator { + next() { + return { + done: true, + value: undefined, + }; + } + return() { + throw new Test262Error(); + } +} + +let iterator = new TestIterator().drop(0); +assert.throws(Test262Error, function () { + iterator.return(); +}); +iterator.next(); +iterator.return(); + +iterator = new TestIterator().drop(1); +iterator.next(); +iterator.return(); + +iterator = new TestIterator().drop(1); +assert.throws(Test262Error, function () { + iterator.return(); +}); +iterator.next(); +iterator.return(); + +iterator = new TestIterator().drop(1).drop(1).drop(1).drop(1).drop(1); +assert.throws(Test262Error, function () { + iterator.return(); +}); +iterator.next(); +iterator.return(); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/shell.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/shell.js diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/this-non-callable-next.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/this-non-callable-next.js new file mode 100644 index 0000000000..57ad6431c9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/this-non-callable-next.js @@ -0,0 +1,22 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.drop +description: > + Iterator.prototype.drop throws TypeError when its this value is an object with a non-callable next +info: | + %Iterator.prototype%.drop ( limit ) + + 1. Let iterated be ? GetIteratorDirect(this value). + +features: [iterator-helpers] +flags: [] +---*/ +let iter = Iterator.prototype.drop.call({ next: 0 }, 1); + +assert.throws(TypeError, function () { + iter.next(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/this-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/this-non-object.js new file mode 100644 index 0000000000..3335b19f6e --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/this-non-object.js @@ -0,0 +1,37 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.drop +description: > + Iterator.prototype.drop throws TypeError when its this value is a non-object +info: | + %Iterator.prototype%.drop ( limit ) + + 1. Let iterated be ? GetIteratorDirect(this value). + +features: [iterator-helpers] +flags: [] +---*/ +assert.throws(TypeError, function () { + Iterator.prototype.drop.call(null, 1); +}); + +assert.throws(TypeError, function () { + Iterator.prototype.drop.call(null, { + valueOf: function () { + throw new Test262Error(); + }, + }); +}); + +Object.defineProperty(Number.prototype, 'next', { + get: function () { + throw new Test262Error(); + }, +}); +assert.throws(TypeError, function () { + Iterator.prototype.drop.call(0, 1); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/this-plain-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/this-plain-iterator.js new file mode 100644 index 0000000000..f83a4d2d8d --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/this-plain-iterator.js @@ -0,0 +1,33 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.drop +description: > + Iterator.prototype.drop supports a this value that does not inherit from Iterator.prototype but implements the iterator protocol +info: | + %Iterator.prototype%.drop ( limit ) + + 1. Let iterated be ? GetIteratorDirect(this value). + +features: [iterator-helpers] +flags: [] +---*/ +let iter = { + get next() { + let count = 3; + return function () { + --count; + return count >= 0 ? { done: false, value: count } : { done: true, value: undefined }; + }; + }, +}; + +let dropIter = Iterator.prototype.drop.call(iter, 1); + +let { done, value } = dropIter.next(); + +assert.sameValue(done, false); +assert.sameValue(value, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/throws-typeerror-when-generator-is-running.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/throws-typeerror-when-generator-is-running.js new file mode 100644 index 0000000000..ea23db0508 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/throws-typeerror-when-generator-is-running.js @@ -0,0 +1,42 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.drop +description: > + Throws a TypeError when the closure generator is already running. +info: | + %IteratorHelperPrototype%.next ( ) + 1. Return ? GeneratorResume(this value, undefined, "Iterator Helper"). + + 27.5.3.3 GeneratorResume ( generator, value, generatorBrand ) + 1. Let state be ? GeneratorValidate(generator, generatorBrand). + ... + + 27.5.3.2 GeneratorValidate ( generator, generatorBrand ) + ... + 6. If state is executing, throw a TypeError exception. + ... + +features: [iterator-helpers] +---*/ + +var enterCount = 0; + +class TestIterator extends Iterator { + next() { + enterCount++; + iter.next(); + return {done: false}; + } +} + +var iter = new TestIterator().drop(100); + +assert.throws(TypeError, function() { + iter.next(); +}); + +assert.sameValue(enterCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/underlying-iterator-advanced-in-parallel.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/underlying-iterator-advanced-in-parallel.js new file mode 100644 index 0000000000..635182e2cc --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/underlying-iterator-advanced-in-parallel.js @@ -0,0 +1,42 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.drop +description: > + Underlying iterator is advanced after calling drop +info: | + %Iterator.prototype%.drop ( limit ) + +features: [iterator-helpers] +flags: [] +---*/ +let iterator = (function* () { + for (let i = 0; i < 5; ++i) { + yield i; + } +})(); + +let dropped = iterator.drop(2); + +let { value, done } = iterator.next(); + +assert.sameValue(value, 0); +assert.sameValue(done, false); + +({ value, done } = dropped.next()); + +assert.sameValue(value, 3); +assert.sameValue(done, false); + +({ value, done } = dropped.next()); + +assert.sameValue(value, 4); +assert.sameValue(done, false); + +({ value, done } = dropped.next()); + +assert.sameValue(value, undefined); +assert.sameValue(done, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/underlying-iterator-closed-in-parallel.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/underlying-iterator-closed-in-parallel.js new file mode 100644 index 0000000000..ec68557a9d --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/underlying-iterator-closed-in-parallel.js @@ -0,0 +1,29 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.drop +description: > + Underlying iterator is closed after calling drop +info: | + %Iterator.prototype%.drop ( limit ) + +features: [iterator-helpers] +flags: [] +---*/ +let iterator = (function* () { + for (let i = 0; i < 5; ++i) { + yield i; + } +})(); + +let dropped = iterator.drop(2); + +iterator.return(); + +let { value, done } = dropped.next(); + +assert.sameValue(value, undefined); +assert.sameValue(done, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/drop/underlying-iterator-closed.js b/js/src/tests/test262/built-ins/Iterator/prototype/drop/underlying-iterator-closed.js new file mode 100644 index 0000000000..dc9298fd8e --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/drop/underlying-iterator-closed.js @@ -0,0 +1,29 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.drop +description: > + Underlying iterator is closed before calling drop +info: | + %Iterator.prototype%.drop ( limit ) + +features: [iterator-helpers] +flags: [] +---*/ +let iterator = (function* () { + for (let i = 0; i < 5; ++i) { + yield i; + } +})(); + +iterator.return(); + +let dropped = iterator.drop(2); + +let { value, done } = dropped.next(); + +assert.sameValue(value, undefined); +assert.sameValue(done, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/argument-effect-order.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/argument-effect-order.js new file mode 100644 index 0000000000..0e4ca1eddf --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/argument-effect-order.js @@ -0,0 +1,33 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.every +description: > + Arguments and this value are evaluated in the correct order +info: | + %Iterator.prototype%.every ( predicate ) + +includes: [compareArray.js] +features: [iterator-helpers] +flags: [] +---*/ +let effects = []; + +assert.throws(TypeError, function () { + Iterator.prototype.every.call( + { + get next() { + effects.push('get next'); + return function () { + return { done: true, value: undefined }; + }; + }, + }, + null + ); +}); + +assert.compareArray(effects, []); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/browser.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/browser.js diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/callable.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/callable.js new file mode 100644 index 0000000000..bb7327786d --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/callable.js @@ -0,0 +1,16 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.every +description: > + Iterator.prototype.every is callable +features: [iterator-helpers] +---*/ +function* g() {} +Iterator.prototype.every.call(g(), () => {}); + +let iter = g(); +iter.every(() => {}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/get-next-method-only-once.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/get-next-method-only-once.js new file mode 100644 index 0000000000..e3611327a5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/get-next-method-only-once.js @@ -0,0 +1,41 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.every +description: > + Gets the next method from the iterator only once +info: | + %Iterator.prototype%.every ( predicate ) + + 1. Let iterated be ? GetIteratorDirect(this value). + +features: [iterator-helpers] +flags: [] +---*/ +let nextGets = 0; + +class TestIterator extends Iterator { + get next() { + ++nextGets; + let counter = 5; + return function () { + if (counter < 0) { + return { done: true, value: undefined }; + } else { + return { done: false, value: --counter }; + } + }; + } +} + +let iterator = new TestIterator(); + +assert.sameValue(nextGets, 0); +assert.sameValue( + iterator.every(() => true), + true +); +assert.sameValue(nextGets, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/get-next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/get-next-method-throws.js new file mode 100644 index 0000000000..cce9c77972 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/get-next-method-throws.js @@ -0,0 +1,28 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.every +description: > + Iterator has throwing next getter +info: | + %Iterator.prototype%.every ( predicate ) + + 1. Let iterated be ? GetIteratorDirect(this value). + +features: [iterator-helpers] +flags: [] +---*/ +class IteratorThrows extends Iterator { + get next() { + throw new Test262Error(); + } +} + +let iterator = new IteratorThrows(); + +assert.throws(Test262Error, function () { + iterator.every(() => {}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/get-return-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/get-return-method-throws.js new file mode 100644 index 0000000000..1c22a2e0a3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/get-return-method-throws.js @@ -0,0 +1,34 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.every +description: > + Iterator has throwing return getter +info: | + %Iterator.prototype%.every ( predicate ) + + 4.f. If ToBoolean(result) is false, return ? IteratorClose(iterated, NormalCompletion(false)). + +features: [iterator-helpers] +flags: [] +---*/ +class IteratorThrows extends Iterator { + next() { + return { + done: false, + value: 0, + }; + } + get return() { + throw new Test262Error(); + } +} + +let iterator = new IteratorThrows([1, 2]); + +assert.throws(Test262Error, function () { + iterator.every(() => false); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/is-function.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/is-function.js new file mode 100644 index 0000000000..7e37497a87 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/is-function.js @@ -0,0 +1,13 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.every +description: > + Iterator.prototype.every is a built-in function +features: [iterator-helpers] +---*/ + +assert.sameValue(typeof Iterator.prototype.every, 'function'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/iterator-already-exhausted.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/iterator-already-exhausted.js new file mode 100644 index 0000000000..2a31df547b --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/iterator-already-exhausted.js @@ -0,0 +1,29 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.every +description: > + Iterator.prototype.every returns true when the iterator has already been exhausted +info: | + %Iterator.prototype%.every ( predicate ) + + 4.a. Let next be ? IteratorStep(iterated). + 4.b. If next is false, return true. + +features: [iterator-helpers] +flags: [] +---*/ +let iterator = (function* () {})(); + +let { value, done } = iterator.next(); +assert.sameValue(value, undefined); +assert.sameValue(done, true); + +let result = iterator.every(() => true); +assert.sameValue(result, true); + +result = iterator.every(() => false); +assert.sameValue(result, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/iterator-has-no-return.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/iterator-has-no-return.js new file mode 100644 index 0000000000..a58c782ab8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/iterator-has-no-return.js @@ -0,0 +1,30 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.every +description: > + The underlying iterator is sometimes unable to be closed (has no return method) +info: | + %Iterator.prototype%.every ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +let iterator = [1, 2, 3, 4, 5][Symbol.iterator](); + +assert.sameValue(iterator.return, undefined); + +let ret = iterator.every(v => v < 4); + +assert.sameValue(ret, false); + +let { done, value } = iterator.next(); +assert.sameValue(done, false); +assert.sameValue(value, 5); + +({ done, value } = iterator.next()); +assert.sameValue(done, true); +assert.sameValue(value, undefined); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/iterator-return-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/iterator-return-method-throws.js new file mode 100644 index 0000000000..d7b59f842e --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/iterator-return-method-throws.js @@ -0,0 +1,34 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.every +description: > + Iterator has throwing return +info: | + %Iterator.prototype%.every ( predicate ) + + 4.f. If ToBoolean(result) is false, return ? IteratorClose(iterated, NormalCompletion(false)). + +features: [iterator-helpers] +flags: [] +---*/ +class IteratorThrows extends Iterator { + next() { + return { + done: false, + value: 0, + }; + } + return() { + throw new Test262Error(); + } +} + +let iterator = new IteratorThrows(); + +assert.throws(Test262Error, function () { + iterator.every(() => false); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/length.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/length.js new file mode 100644 index 0000000000..fd247ed9ac --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/length.js @@ -0,0 +1,25 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.every +description: > + Iterator.prototype.every has a "length" property whose value is 1. +info: | + ECMAScript Standard Built-in Objects + + Unless otherwise specified, the length property of a built-in + Function object has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: true }. +features: [iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator.prototype.every, 'length', { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/name.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/name.js new file mode 100644 index 0000000000..7e602ff1c2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/name.js @@ -0,0 +1,32 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.every +description: > + The "name" property of Iterator.prototype.every +info: | + 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. + + ... + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +features: [iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator.prototype.every, 'name', { + value: 'every', + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/next-method-returns-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/next-method-returns-non-object.js new file mode 100644 index 0000000000..0e5c1a828a --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/next-method-returns-non-object.js @@ -0,0 +1,28 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.every +description: > + Underlying iterator next returns non-object +info: | + %Iterator.prototype%.every ( predicate ) + + 4.a. Let next be ? IteratorStep(iterated). + +features: [iterator-helpers] +flags: [] +---*/ +class NonObjectIterator extends Iterator { + next() { + return null; + } +} + +let iterator = new NonObjectIterator(); + +assert.throws(TypeError, function () { + iterator.every(() => {}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/next-method-returns-throwing-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/next-method-returns-throwing-done.js new file mode 100644 index 0000000000..e2a56600df --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/next-method-returns-throwing-done.js @@ -0,0 +1,36 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.every +description: > + Underlying iterator next returns object with throwing done getter +info: | + %Iterator.prototype%.every ( predicate ) + + 4.a. Let next be ? IteratorStep(iterated). + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + return { + get done() { + throw new Test262Error(); + }, + value: 1, + }; + } + return() { + throw new Error(); + } +} + +let iterator = new ThrowingIterator(); + +assert.throws(Test262Error, function () { + iterator.every(() => {}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/next-method-returns-throwing-value-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/next-method-returns-throwing-value-done.js new file mode 100644 index 0000000000..f7e81a6321 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/next-method-returns-throwing-value-done.js @@ -0,0 +1,33 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.every +description: > + Underlying iterator next returns object with throwing value getter, but is already done +info: | + %Iterator.prototype%.every ( predicate ) + + 4.c. Let value be ? IteratorValue(next). + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + return { + done: true, + get value() { + throw new Test262Error(); + }, + }; + } + return() { + throw new Error(); + } +} + +let iterator = new ThrowingIterator(); +iterator.every(() => {}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/next-method-returns-throwing-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/next-method-returns-throwing-value.js new file mode 100644 index 0000000000..6799ddd165 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/next-method-returns-throwing-value.js @@ -0,0 +1,36 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.every +description: > + Underlying iterator next returns object with throwing value getter +info: | + %Iterator.prototype%.every ( predicate ) + + 4.c. Let value be ? IteratorValue(next). + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + return { + done: false, + get value() { + throw new Test262Error(); + }, + }; + } + return() { + throw new Error(); + } +} + +let iterator = new ThrowingIterator(); + +assert.throws(Test262Error, function () { + iterator.every(() => {}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/next-method-throws.js new file mode 100644 index 0000000000..e883c21fc8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/next-method-throws.js @@ -0,0 +1,28 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.every +description: > + Underlying iterator has throwing next method +info: | + %Iterator.prototype%.every ( predicate ) + + 4.a. Let next be ? IteratorStep(iterated). + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + throw new Test262Error(); + } +} + +let iterator = new ThrowingIterator(); + +assert.throws(Test262Error, function () { + iterator.every(() => {}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/non-callable-predicate.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/non-callable-predicate.js new file mode 100644 index 0000000000..41be3d5e91 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/non-callable-predicate.js @@ -0,0 +1,25 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.every +description: > + Iterator.prototype.every expects to be called with a callable argument. +info: | + %Iterator.prototype%.every ( predicate ) + + 2. If IsCallable(predicate) is false, throw a TypeError exception. + +features: [iterator-helpers] +flags: [] +---*/ +let nonCallable = {}; +let iterator = (function* () { + yield 1; +})(); + +assert.throws(TypeError, function () { + iterator.every(nonCallable); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/non-constructible.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/non-constructible.js new file mode 100644 index 0000000000..b0f280ca32 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/non-constructible.js @@ -0,0 +1,31 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.every +description: > + Iterator.prototype.every is not constructible. + + 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. +features: [iterator-helpers] +---*/ +function* g() {} +let iter = g(); + +assert.throws(TypeError, () => { + new iter.every(); +}); + +assert.throws(TypeError, () => { + new iter.every(() => {}); +}); + +assert.throws(TypeError, () => { + new Iterator.prototype.every(() => {}); +}); + +assert.throws(TypeError, () => { + new class extends Iterator {}.every(() => {}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-args.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-args.js new file mode 100644 index 0000000000..8850a9ef89 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-args.js @@ -0,0 +1,46 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.every +description: > + Iterator.prototype.every predicate is passed the yielded value and a counter as arguments +info: | + %Iterator.prototype%.every ( predicate ) + + 4.d. Let result be Completion(Call(predicate, undefined, « value, 𝔽(counter) »)). + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield 'a'; + yield 'b'; + yield 'c'; +} + +let iter = g(); + +let assertionCount = 0; +let result = iter.every((v, count) => { + switch (v) { + case 'a': + assert.sameValue(count, 0); + break; + case 'b': + assert.sameValue(count, 1); + break; + case 'c': + assert.sameValue(count, 2); + break; + default: + throw new Error(); + } + ++assertionCount; + return true; +}); + +assert.sameValue(result, true); +assert.sameValue(assertionCount, 3); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-returns-falsey.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-returns-falsey.js new file mode 100644 index 0000000000..4474b4cc2f --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-returns-falsey.js @@ -0,0 +1,36 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.every +description: > + Iterator.prototype.every returns false and closes the iterator when the predicate returns falsey immediately +info: | + %Iterator.prototype%.every ( predicate ) + + 4.f. If ToBoolean(result) is false, return ? IteratorClose(iterated, NormalCompletion(false)). + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield 0; + yield 1; +} + +let iter = g(); + +let predicateCalls = 0; +let result = iter.every(v => { + ++predicateCalls; + return false; +}); + +assert.sameValue(result, false); +assert.sameValue(predicateCalls, 1); + +let { done, value } = iter.next(); +assert.sameValue(done, true); +assert.sameValue(value, undefined); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-returns-non-boolean.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-returns-non-boolean.js new file mode 100644 index 0000000000..4130445ff5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-returns-non-boolean.js @@ -0,0 +1,33 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.every +description: > + Iterator.prototype.every coerces predicate return value to boolean +info: | + %Iterator.prototype%.every ( predicate ) + + 4.f. If ToBoolean(result) is false, return ? IteratorClose(iterated, NormalCompletion(false)). + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + for (let i = 4; i >= 0; --i) { + yield i; + } +} + +let iter = g(); + +let predicateCalls = 0; +let result = iter.every(v => { + ++predicateCalls; + return v; +}); + +assert.sameValue(result, false); +assert.sameValue(predicateCalls, 5); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-returns-truthy-then-falsey.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-returns-truthy-then-falsey.js new file mode 100644 index 0000000000..df4487551c --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-returns-truthy-then-falsey.js @@ -0,0 +1,37 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.every +description: > + Iterator.prototype.every returns false and closes the iterator when the predicate returns truthy for some iterated values and falsey for others +info: | + %Iterator.prototype%.every ( predicate ) + + 4.f. If ToBoolean(result) is false, return ? IteratorClose(iterated, NormalCompletion(false)). + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + for (let i = 0; i < 5; ++i) { + yield i; + } +} + +let iter = g(); + +let predicateCalls = 0; +let result = iter.every(v => { + ++predicateCalls; + return v < 3; +}); + +assert.sameValue(result, false); +assert.sameValue(predicateCalls, 4); + +let { done, value } = iter.next(); +assert.sameValue(done, true); +assert.sameValue(value, undefined); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-returns-truthy.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-returns-truthy.js new file mode 100644 index 0000000000..1150e509e4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-returns-truthy.js @@ -0,0 +1,27 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.every +description: > + Iterator.prototype.every returns true when the predicate returns truthy for all iterated values +info: | + %Iterator.prototype%.every ( predicate ) + + 4.b. If next is false, return true. + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield 0; + yield 1; + yield 2; + yield 3; + yield 4; +} + +let result = g().every(() => true); +assert.sameValue(result, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-this.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-this.js new file mode 100644 index 0000000000..0a4dcd1c4d --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-this.js @@ -0,0 +1,36 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.every +description: > + Iterator.prototype.every predicate this value is undefined +info: | + %Iterator.prototype%.every ( predicate ) + + 4.d. Let result be Completion(Call(predicate, undefined, « value, 𝔽(counter) »)). + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield 0; +} + +let iter = g(); + +let expectedThis = function () { + return this; +}.call(undefined); + +let assertionCount = 0; +let result = iter.every(function (v, count) { + assert.sameValue(this, expectedThis); + ++assertionCount; + return true; +}); + +assert.sameValue(result, true); +assert.sameValue(assertionCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-throws-then-closing-iterator-also-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-throws-then-closing-iterator-also-throws.js new file mode 100644 index 0000000000..18973b57b9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-throws-then-closing-iterator-also-throws.js @@ -0,0 +1,42 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.every +description: > + Attempts to close iterator when predicate throws, but that throws +info: | + %Iterator.prototype%.every ( predicate ) + + 4.d. Let result be Completion(Call(predicate, undefined, « value, 𝔽(counter) »)). + 4.e. IfAbruptCloseIterator(result, iterated). + +features: [iterator-helpers] +flags: [] +---*/ +let returnCalls = 0; + +class TestIterator extends Iterator { + next() { + return { + done: false, + value: 1, + }; + } + return() { + ++returnCalls; + throw new Error(); + } +} + +let iterator = new TestIterator(); + +assert.throws(Test262Error, function () { + iterator.every(() => { + throw new Test262Error(); + }); +}); + +assert.sameValue(returnCalls, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-throws.js new file mode 100644 index 0000000000..b5a2d7ef0c --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/predicate-throws.js @@ -0,0 +1,46 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.every +description: > + Closes iterator and throws when predicate throws +info: | + %Iterator.prototype%.every ( predicate ) + + 4.d. Let result be Completion(Call(predicate, undefined, « value, 𝔽(counter) »)). + 4.e. IfAbruptCloseIterator(result, iterated). + +features: [iterator-helpers] +flags: [] +---*/ +let returnCalls = 0; + +class TestIterator extends Iterator { + next() { + return { + done: false, + value: 1, + }; + } + return() { + ++returnCalls; + return {}; + } +} + +let iterator = new TestIterator(); + +let callbackCalls = 0; + +assert.throws(Test262Error, function () { + iterator.every(() => { + ++callbackCalls; + throw new Test262Error(); + }); +}); + +assert.sameValue(callbackCalls, 1); +assert.sameValue(returnCalls, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/prop-desc.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/prop-desc.js new file mode 100644 index 0000000000..0e6e10653e --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/prop-desc.js @@ -0,0 +1,28 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.every +description: > + Property descriptor of Iterator.prototype.every +info: | + Iterator.prototype.every + + * is the initial value of the Iterator.prototype.every property of the global object. + + 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. +features: [globalThis, iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator.prototype, 'every', { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/proto.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/proto.js new file mode 100644 index 0000000000..bddd9ab52e --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/proto.js @@ -0,0 +1,14 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.every +description: > + The value of the [[Prototype]] internal slot of Iterator.prototype.every is the + intrinsic object %Function%. +features: [iterator-helpers] +---*/ + +assert.sameValue(Object.getPrototypeOf(Iterator.prototype.every), Function.prototype); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/result-is-boolean.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/result-is-boolean.js new file mode 100644 index 0000000000..005b254405 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/result-is-boolean.js @@ -0,0 +1,14 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.every +description: > + Iterator.prototype.every returns a boolean +features: [iterator-helpers] +---*/ +function* g() {} +let iter = g(); +assert.sameValue(typeof iter.every(() => {}), 'boolean'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/shell.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/shell.js diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/this-non-callable-next.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/this-non-callable-next.js new file mode 100644 index 0000000000..ddfb318819 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/this-non-callable-next.js @@ -0,0 +1,20 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.every +description: > + Iterator.prototype.every throws TypeError when its this value is an object with a non-callable next +info: | + %Iterator.prototype%.every ( predicate ) + + 1. Let iterated be ? GetIteratorDirect(this value). + +features: [iterator-helpers] +flags: [] +---*/ +assert.throws(TypeError, function () { + Iterator.prototype.every.call({ next: 0 }, () => true); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/this-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/this-non-object.js new file mode 100644 index 0000000000..4998274959 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/this-non-object.js @@ -0,0 +1,29 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.every +description: > + Iterator.prototype.every throws TypeError when its this value is a non-object +info: | + %Iterator.prototype%.every ( predicate ) + + 1. Let iterated be ? GetIteratorDirect(this value). + +features: [iterator-helpers] +flags: [] +---*/ +assert.throws(TypeError, function () { + Iterator.prototype.every.call(null, () => {}); +}); + +Object.defineProperty(Number.prototype, 'next', { + get: function () { + throw new Test262Error(); + }, +}); +assert.throws(TypeError, function () { + Iterator.prototype.every.call(0, () => {}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/every/this-plain-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/every/this-plain-iterator.js new file mode 100644 index 0000000000..ce4b742a91 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/every/this-plain-iterator.js @@ -0,0 +1,35 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.every +description: > + Iterator.prototype.every supports a this value that does not inherit from Iterator.prototype but implements the iterator protocol +info: | + %Iterator.prototype%.every ( predicate ) + + 1. Let iterated be ? GetIteratorDirect(this value). + +features: [iterator-helpers] +flags: [] +---*/ +let iter = { + get next() { + let count = 3; + return function () { + --count; + return count >= 0 ? { done: false, value: count } : { done: true, value: undefined }; + }; + }, +}; + +let predicateCalls = 0; +let result = Iterator.prototype.every.call(iter, function (v) { + ++predicateCalls; + return v; +}); + +assert.sameValue(result, false); +assert.sameValue(predicateCalls, 3); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/argument-effect-order.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/argument-effect-order.js new file mode 100644 index 0000000000..64d47cf80c --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/argument-effect-order.js @@ -0,0 +1,33 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.filter +description: > + Arguments and this value are evaluated in the correct order +info: | + %Iterator.prototype%.filter ( predicate ) + +includes: [compareArray.js] +features: [iterator-helpers] +flags: [] +---*/ +let effects = []; + +assert.throws(TypeError, function () { + Iterator.prototype.filter.call( + { + get next() { + effects.push('get next'); + return function () { + return { done: true, value: undefined }; + }; + }, + }, + null + ); +}); + +assert.compareArray(effects, []); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/browser.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/browser.js diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/callable.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/callable.js new file mode 100644 index 0000000000..399bc881a8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/callable.js @@ -0,0 +1,16 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.filter +description: > + Iterator.prototype.filter is callable +features: [iterator-helpers] +---*/ +function* g() {} +Iterator.prototype.filter.call(g(), () => false); + +let iter = g(); +iter.filter(() => false); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/exhaustion-does-not-call-return.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/exhaustion-does-not-call-return.js new file mode 100644 index 0000000000..8770acea38 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/exhaustion-does-not-call-return.js @@ -0,0 +1,40 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.filter +description: > + Underlying iterator return is not called when result iterator is exhausted +info: | + %Iterator.prototype%.filter ( predicate ) + + 3.b.i. Let next be ? IteratorStep(iterated). + 3.b.ii. If next is false, return undefined. + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield 0; + yield 1; + yield 2; +} + +class TestIterator extends Iterator { + get next() { + let n = g(); + return function() { + return n.next(); + }; + } + return() { + throw new Test262Error(); + } +} + +let iterator = new TestIterator().filter(() => false); +iterator.next(); +iterator.next(); +iterator.next(); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/get-next-method-only-once.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/get-next-method-only-once.js new file mode 100644 index 0000000000..50e2a9074a --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/get-next-method-only-once.js @@ -0,0 +1,44 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.filter +description: > + Gets the next method from the underlying iterator only once +info: | + %Iterator.prototype%.filter ( predicate ) + + 1. Let iterated be ? GetIteratorDirect(this value). + +features: [iterator-helpers] +flags: [] +---*/ +let nextGets = 0; +let nextCalls = 0; + +class CountingIterator extends Iterator { + get next() { + ++nextGets; + let iter = (function* () { + for (let i = 1; i < 5; ++i) { + yield i; + } + })(); + return function () { + ++nextCalls; + return iter.next(); + }; + } +} + +let iterator = new CountingIterator(); + +assert.sameValue(nextGets, 0); +assert.sameValue(nextCalls, 0); + +for (const value of iterator.filter(() => false)); + +assert.sameValue(nextGets, 1); +assert.sameValue(nextCalls, 5); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/get-next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/get-next-method-throws.js new file mode 100644 index 0000000000..655e75b206 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/get-next-method-throws.js @@ -0,0 +1,28 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.filter +description: > + Underlying iterator has throwing next getter +info: | + %Iterator.prototype%.filter ( predicate ) + + 1. Let iterated be ? GetIteratorDirect(this value). + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + get next() { + throw new Test262Error(); + } +} + +let iterator = new ThrowingIterator(); + +assert.throws(Test262Error, function () { + iterator.filter(() => false); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/get-return-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/get-return-method-throws.js new file mode 100644 index 0000000000..fe38093eab --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/get-return-method-throws.js @@ -0,0 +1,33 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.filter +description: > + Underlying iterator return is throwing getter +info: | + %Iterator.prototype%.filter ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +class TestIterator extends Iterator { + next() { + return { + done: false, + value: 1, + }; + } + get return() { + throw new Test262Error(); + } +} + +let iterator = new TestIterator().filter(() => true); +iterator.next(); + +assert.throws(Test262Error, function () { + iterator.return(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/is-function.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/is-function.js new file mode 100644 index 0000000000..8dd7bf1a85 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/is-function.js @@ -0,0 +1,13 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.filter +description: > + Iterator.prototype.filter is a built-in function +features: [iterator-helpers] +---*/ + +assert.sameValue(typeof Iterator.prototype.filter, 'function'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/iterator-already-exhausted.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/iterator-already-exhausted.js new file mode 100644 index 0000000000..a8682a18e7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/iterator-already-exhausted.js @@ -0,0 +1,28 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.filter +description: > + Iterator.prototype.filter returns an empty iterator when the iterator has already been exhausted +info: | + %Iterator.prototype%.filter ( predicate ) + + 3.b.i. Let next be ? IteratorStep(iterated). + 3.b.ii. If next is false, return undefined. + +features: [iterator-helpers] +flags: [] +---*/ +let iterator = (function* () {})(); + +let { value, done } = iterator.next(); +assert.sameValue(value, undefined); +assert.sameValue(done, true); + +iterator = iterator.filter(() => true); +({ value, done } = iterator.next()); +assert.sameValue(value, undefined); +assert.sameValue(done, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/iterator-return-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/iterator-return-method-throws.js new file mode 100644 index 0000000000..e8511d1cc8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/iterator-return-method-throws.js @@ -0,0 +1,32 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.filter +description: > + Iterator has throwing return +info: | + %Iterator.prototype%.filter ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +class IteratorThrows extends Iterator { + next() { + return { + done: false, + value: 0, + }; + } + return() { + throw new Test262Error(); + } +} + +let iterator = new IteratorThrows().filter(() => false); + +assert.throws(Test262Error, function () { + iterator.return(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/length.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/length.js new file mode 100644 index 0000000000..766e0beb93 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/length.js @@ -0,0 +1,25 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.filter +description: > + Iterator.prototype.filter has a "length" property whose value is 1. +info: | + ECMAScript Standard Built-in Objects + + Unless otherwise specified, the length property of a built-in + Function object has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: true }. +features: [iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator.prototype.filter, 'length', { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/name.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/name.js new file mode 100644 index 0000000000..1862cb1881 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/name.js @@ -0,0 +1,32 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.filter +description: > + The "name" property of Iterator.prototype.filter +info: | + 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. + + ... + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +features: [iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator.prototype.filter, 'name', { + value: 'filter', + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/next-method-returns-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/next-method-returns-non-object.js new file mode 100644 index 0000000000..92e5a2e63f --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/next-method-returns-non-object.js @@ -0,0 +1,28 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.filter +description: > + Underlying iterator next returns non-object +info: | + %Iterator.prototype%.filter ( predicate ) + + 3.b.i. Let next be ? IteratorStep(iterated). + +features: [iterator-helpers] +flags: [] +---*/ +class NonObjectIterator extends Iterator { + next() { + return null; + } +} + +let iterator = new NonObjectIterator().filter(() => true); + +assert.throws(TypeError, function () { + iterator.next(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/next-method-returns-throwing-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/next-method-returns-throwing-done.js new file mode 100644 index 0000000000..69af6d35c7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/next-method-returns-throwing-done.js @@ -0,0 +1,36 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.filter +description: > + Underlying iterator next returns object with throwing done getter +info: | + %Iterator.prototype%.filter ( predicate ) + + 3.b.i. Let next be ? IteratorStep(iterated). + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + return { + get done() { + throw new Test262Error(); + }, + value: 1, + }; + } + return() { + throw new Error(); + } +} + +let iterator = new ThrowingIterator().filter(() => true); + +assert.throws(Test262Error, function () { + iterator.next(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/next-method-returns-throwing-value-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/next-method-returns-throwing-value-done.js new file mode 100644 index 0000000000..daac171b28 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/next-method-returns-throwing-value-done.js @@ -0,0 +1,33 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.filter +description: > + Underlying iterator next returns object with throwing value getter, but is already done +info: | + %Iterator.prototype%.filter ( predicate ) + + 3.b.ii. If next is false, return undefined. + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + return { + done: true, + get value() { + throw new Test262Error(); + }, + }; + } + return() { + throw new Error(); + } +} + +let iterator = new ThrowingIterator().filter(() => true); +iterator.next(); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/next-method-returns-throwing-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/next-method-returns-throwing-value.js new file mode 100644 index 0000000000..5d441c9343 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/next-method-returns-throwing-value.js @@ -0,0 +1,36 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.filter +description: > + Underlying iterator next returns object with throwing value getter +info: | + %Iterator.prototype%.filter ( predicate ) + + 3.b.iii. Let value be ? IteratorValue(next). + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + return { + done: false, + get value() { + throw new Test262Error(); + }, + }; + } + return() { + throw new Error(); + } +} + +let iterator = new ThrowingIterator().filter(() => true); + +assert.throws(Test262Error, function () { + iterator.next(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/next-method-throws.js new file mode 100644 index 0000000000..59f666ab40 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/next-method-throws.js @@ -0,0 +1,28 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.filter +description: > + Underlying iterator has throwing next method +info: | + %Iterator.prototype%.filter ( predicate ) + + 3.b.i. Let next be ? IteratorStep(iterated). + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + throw new Test262Error(); + } +} + +let iterator = new ThrowingIterator().filter(() => true); + +assert.throws(Test262Error, function () { + iterator.next(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/non-callable-predicate.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/non-callable-predicate.js new file mode 100644 index 0000000000..97960b7112 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/non-callable-predicate.js @@ -0,0 +1,23 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.filter +description: > + Iterator.prototype.filter expects to be called with a callable argument. +info: | + %Iterator.prototype%.filter ( predicate ) + + 2. If IsCallable(predicate) is false, throw a TypeError exception. + +features: [iterator-helpers] +flags: [] +---*/ +let nonCallable = {}; +let iterator = (function* () {})(); + +assert.throws(TypeError, function () { + iterator.filter(nonCallable); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/non-constructible.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/non-constructible.js new file mode 100644 index 0000000000..215721e128 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/non-constructible.js @@ -0,0 +1,31 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.filter +description: > + Iterator.prototype.filter is not constructible. + + 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. +features: [iterator-helpers] +---*/ +function* g() {} +let iter = g(); + +assert.throws(TypeError, () => { + new iter.filter(); +}); + +assert.throws(TypeError, () => { + new iter.filter(() => true); +}); + +assert.throws(TypeError, () => { + new Iterator.prototype.filter(() => true); +}); + +assert.throws(TypeError, () => { + new class extends Iterator {}.filter(() => true); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-args.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-args.js new file mode 100644 index 0000000000..16be06895d --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-args.js @@ -0,0 +1,47 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.filter +description: > + Iterator.prototype.filter predicate is passed the yielded value and a counter as arguments +info: | + %Iterator.prototype%.filter ( predicate ) + + 3.b.iv. Let selected be Completion(Call(predicate, undefined, « value, 𝔽(counter) »)). + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield 'a'; + yield 'b'; + yield 'c'; +} + +let assertionCount = 0; +let iter = g().filter((v, count) => { + switch (v) { + case 'a': + assert.sameValue(count, 0); + break; + case 'b': + assert.sameValue(count, 1); + break; + case 'c': + assert.sameValue(count, 2); + break; + default: + throw new Error(); + } + ++assertionCount; + return true; +}); + +assert.sameValue(assertionCount, 0); + +for (let i of iter); + +assert.sameValue(assertionCount, 3); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-filters.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-filters.js new file mode 100644 index 0000000000..0ff02ac852 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-filters.js @@ -0,0 +1,43 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.filter +description: > + Iterator.prototype.filter returns only items for which the predicate returned true. +info: | + %Iterator.prototype%.filter ( filterer ) + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield 1; + yield 0; + yield 2; + yield 0; + yield 3; + yield 0; + yield 4; +} + +let iterator = g(); + +let predicateCalls = 0; +iterator = iterator.filter(value => { + ++predicateCalls; + return value !== 0; +}); + +let resultCount = 0; +for (let value of iterator) { + ++resultCount; + assert.sameValue(value, resultCount); +} +assert.sameValue(resultCount, 4); + +let { value, done } = iterator.next(); +assert.sameValue(value, undefined); +assert.sameValue(done, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-returns-non-boolean.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-returns-non-boolean.js new file mode 100644 index 0000000000..a4c4f44d75 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-returns-non-boolean.js @@ -0,0 +1,41 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.filter +description: > + Iterator.prototype.filter coerces predicate return value to boolean +info: | + %Iterator.prototype%.filter ( predicate ) + + 3.b.vi. If ToBoolean(selected) is true, then + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield 0; + yield 0; + yield 0; + yield 1; +} + +let iter = g(); + +let predicateCalls = 0; +iter = iter.filter(v => { + ++predicateCalls; + return v; +}); + +assert.sameValue(predicateCalls, 0); + +iter.next(); + +assert.sameValue(predicateCalls, 4); + +iter.next(); + +assert.sameValue(predicateCalls, 4); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-this.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-this.js new file mode 100644 index 0000000000..79b7ea8619 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-this.js @@ -0,0 +1,36 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.filter +description: > + Iterator.prototype.filter predicate this value is undefined +info: | + %Iterator.prototype%.filter ( predicate ) + + 3.b.iv. Let selected be Completion(Call(predicate, undefined, « value, 𝔽(counter) »)). + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield 0; +} + +let iter = g(); + +let expectedThis = function () { + return this; +}.call(undefined); + +let assertionCount = 0; +iter = iter.filter(function (v, count) { + assert.sameValue(this, expectedThis); + ++assertionCount; + return true; +}); + +iter.next(); +assert.sameValue(assertionCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-throws-then-closing-iterator-also-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-throws-then-closing-iterator-also-throws.js new file mode 100644 index 0000000000..61ffe5eba0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-throws-then-closing-iterator-also-throws.js @@ -0,0 +1,43 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.filter +description: > + Attempts to close iterator when predicate throws, but that throws +info: | + %Iterator.prototype%.filter ( predicate ) + + 3.b.v. IfAbruptCloseIterator(selected, iterated). + +features: [iterator-helpers] +flags: [] +---*/ +let returnCalls = 0; + +class TestIterator extends Iterator { + next() { + return { + done: false, + value: 1, + }; + } + return() { + ++returnCalls; + throw new Error(); + } +} + +let iterator = new TestIterator().filter(() => { + throw new Test262Error(); +}); + +assert.sameValue(returnCalls, 0); + +assert.throws(Test262Error, function () { + iterator.next(); +}); + +assert.sameValue(returnCalls, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-throws.js new file mode 100644 index 0000000000..1a998c12dc --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/predicate-throws.js @@ -0,0 +1,44 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.filter +description: > + Closes iterator and throws when predicate throws +info: | + %Iterator.prototype%.filter ( predicate ) + + 3.b.v. IfAbruptCloseIterator(selected, iterated). + +features: [iterator-helpers] +flags: [] +---*/ +let returnCalls = 0; + +class TestIterator extends Iterator { + next() { + return { + done: false, + value: 1, + }; + } + return() { + ++returnCalls; + return {}; + } +} + +let callbackCalls = 0; +let iterator = new TestIterator().filter(() => { + ++callbackCalls; + throw new Test262Error(); +}); + +assert.throws(Test262Error, function () { + iterator.next(); +}); + +assert.sameValue(callbackCalls, 1); +assert.sameValue(returnCalls, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/prop-desc.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/prop-desc.js new file mode 100644 index 0000000000..4d1ae8b770 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/prop-desc.js @@ -0,0 +1,28 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.filter +description: > + Property descriptor of Iterator.prototype.filter +info: | + Iterator.prototype.filter + + * is the initial value of the Iterator.prototype.filter property of the global object. + + 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. +features: [globalThis, iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator.prototype, 'filter', { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/proto.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/proto.js new file mode 100644 index 0000000000..e1e963c1f8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/proto.js @@ -0,0 +1,14 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.filter +description: > + The value of the [[Prototype]] internal slot of Iterator.prototype.filter is the + intrinsic object %FunctionPrototype%. +features: [iterator-helpers] +---*/ + +assert.sameValue(Object.getPrototypeOf(Iterator.prototype.filter), Function.prototype); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/result-is-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/result-is-iterator.js new file mode 100644 index 0000000000..777ed443c4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/result-is-iterator.js @@ -0,0 +1,17 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.filter +description: > + The value of the [[Prototype]] internal slot of the return value of Iterator.prototype.filter is the + intrinsic object %IteratorHelperPrototype%. +features: [iterator-helpers] +---*/ + +assert( + (function* () {})().filter(() => true) instanceof Iterator, + 'function*(){}().filter(() => true) must return an Iterator' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/return-is-forwarded.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/return-is-forwarded.js new file mode 100644 index 0000000000..2c86f273f6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/return-is-forwarded.js @@ -0,0 +1,36 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.filter +description: > + Underlying iterator return is called when result iterator is closed +info: | + %Iterator.prototype%.filter ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +let returnCount = 0; + +class TestIterator extends Iterator { + next() { + return { + done: false, + value: 1, + }; + } + return() { + ++returnCount; + return {}; + } +} + +let iterator = new TestIterator().filter(() => false); +assert.sameValue(returnCount, 0); +iterator.return(); +assert.sameValue(returnCount, 1); +iterator.return(); +assert.sameValue(returnCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/return-is-not-forwarded-after-exhaustion.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/return-is-not-forwarded-after-exhaustion.js new file mode 100644 index 0000000000..00a6a050ce --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/return-is-not-forwarded-after-exhaustion.js @@ -0,0 +1,49 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.filter +description: > + Underlying iterator return is not called after result iterator observes that underlying iterator is exhausted +info: | + %Iterator.prototype%.filter ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +let returnCount = 0; + +class TestIterator extends Iterator { + next() { + return { + done: true, + value: undefined, + }; + } + return() { + throw new Test262Error(); + } +} + +let iterator = new TestIterator().filter(() => true); +assert.throws(Test262Error, function () { + iterator.return(); +}); +iterator.next(); +iterator.return(); + +iterator = new TestIterator().filter(() => true); +iterator.next(); +iterator.return(); + +iterator = new TestIterator() + .filter(() => true) + .filter(() => true) + .filter(() => true); +assert.throws(Test262Error, function () { + iterator.return(); +}); +iterator.next(); +iterator.return(); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/shell.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/shell.js diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/this-non-callable-next.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/this-non-callable-next.js new file mode 100644 index 0000000000..f87ac0f62c --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/this-non-callable-next.js @@ -0,0 +1,22 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.filter +description: > + Iterator.prototype.filter throws TypeError when its this value is an object with a non-callable next +info: | + %Iterator.prototype%.filter ( predicate ) + + 1. Let iterated be ? GetIteratorDirect(this value). + +features: [iterator-helpers] +flags: [] +---*/ +let iter = Iterator.prototype.filter.call({ next: 0 }, () => true); + +assert.throws(TypeError, function () { + iter.next(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/this-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/this-non-object.js new file mode 100644 index 0000000000..542946348f --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/this-non-object.js @@ -0,0 +1,29 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.filter +description: > + Iterator.prototype.filter throws TypeError when its this value is a non-object +info: | + %Iterator.prototype%.filter ( predicate ) + + 1. Let iterated be ? GetIteratorDirect(this value). + +features: [iterator-helpers] +flags: [] +---*/ +assert.throws(TypeError, function () { + Iterator.prototype.filter.call(null, () => true); +}); + +Object.defineProperty(Number.prototype, 'next', { + get: function () { + throw new Test262Error(); + }, +}); +assert.throws(TypeError, function () { + Iterator.prototype.filter.call(0, () => true); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/this-plain-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/this-plain-iterator.js new file mode 100644 index 0000000000..06f2412b55 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/this-plain-iterator.js @@ -0,0 +1,36 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.filter +description: > + Iterator.prototype.filter supports a this value that does not inherit from Iterator.prototype but implements the iterator protocol +info: | + %Iterator.prototype%.filter ( predicate ) + + 1. Let iterated be ? GetIteratorDirect(this value). + +features: [iterator-helpers] +flags: [] +---*/ +let iter = { + get next() { + let count = 3; + return function () { + --count; + return count >= 0 ? { done: false, value: count } : { done: true, value: undefined }; + }; + }, +}; + +let predicateCalls = 0; +iter = Iterator.prototype.filter.call(iter, function (v) { + ++predicateCalls; + return v; +}); + +for (let e of iter); + +assert.sameValue(predicateCalls, 3); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/throws-typeerror-when-generator-is-running.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/throws-typeerror-when-generator-is-running.js new file mode 100644 index 0000000000..ed9ce10b47 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/throws-typeerror-when-generator-is-running.js @@ -0,0 +1,49 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.filter +description: > + Throws a TypeError when the closure generator is already running. +info: | + %IteratorHelperPrototype%.next ( ) + 1. Return ? GeneratorResume(this value, undefined, "Iterator Helper"). + + 27.5.3.3 GeneratorResume ( generator, value, generatorBrand ) + 1. Let state be ? GeneratorValidate(generator, generatorBrand). + ... + + 27.5.3.2 GeneratorValidate ( generator, generatorBrand ) + ... + 6. If state is executing, throw a TypeError exception. + ... + +features: [iterator-helpers] +---*/ + +var loopCount = 0; + +function* g() { + while (true) { + loopCount++; + yield; + } +} + +var enterCount = 0; + +function predicate() { + enterCount++; + iter.next(); +} + +var iter = g().filter(predicate); + +assert.throws(TypeError, function() { + iter.next(); +}); + +assert.sameValue(loopCount, 1); +assert.sameValue(enterCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/underlying-iterator-advanced-in-parallel.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/underlying-iterator-advanced-in-parallel.js new file mode 100644 index 0000000000..a34e36eed4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/underlying-iterator-advanced-in-parallel.js @@ -0,0 +1,45 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.filter +description: > + Underlying iterator is advanced after calling filter +info: | + %Iterator.prototype%.filter ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +let iterator = (function* () { + for (let i = 0; i < 5; ++i) { + yield i; + } +})(); + +let filtered = iterator.filter(() => true); + +let { value, done } = iterator.next(); + +assert.sameValue(value, 0); +assert.sameValue(done, false); + +iterator.next(); +iterator.next(); + +({ value, done } = filtered.next()); + +assert.sameValue(value, 3); +assert.sameValue(done, false); + +({ value, done } = filtered.next()); + +assert.sameValue(value, 4); +assert.sameValue(done, false); + +({ value, done } = filtered.next()); + +assert.sameValue(value, undefined); +assert.sameValue(done, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/underlying-iterator-closed-in-parallel.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/underlying-iterator-closed-in-parallel.js new file mode 100644 index 0000000000..8af0579312 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/underlying-iterator-closed-in-parallel.js @@ -0,0 +1,29 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.filter +description: > + Underlying iterator is closed after calling filter +info: | + %Iterator.prototype%.filter ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +let iterator = (function* () { + for (let i = 0; i < 5; ++i) { + yield i; + } +})(); + +let filtered = iterator.filter(() => true); + +iterator.return(); + +let { value, done } = filtered.next(); + +assert.sameValue(value, undefined); +assert.sameValue(done, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/filter/underlying-iterator-closed.js b/js/src/tests/test262/built-ins/Iterator/prototype/filter/underlying-iterator-closed.js new file mode 100644 index 0000000000..271b4895d3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/filter/underlying-iterator-closed.js @@ -0,0 +1,29 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.filter +description: > + Underlying iterator is closed before calling filter +info: | + %Iterator.prototype%.filter ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +let iterator = (function* () { + for (let i = 0; i < 5; ++i) { + yield i; + } +})(); + +iterator.return(); + +let filtered = iterator.filter(() => true); + +let { value, done } = filtered.next(); + +assert.sameValue(value, undefined); +assert.sameValue(done, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/argument-effect-order.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/argument-effect-order.js new file mode 100644 index 0000000000..589fc3eb5a --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/argument-effect-order.js @@ -0,0 +1,33 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.find +description: > + Arguments and this value are evaluated in the correct order +info: | + %Iterator.prototype%.find ( predicate ) + +includes: [compareArray.js] +features: [iterator-helpers] +flags: [] +---*/ +let effects = []; + +assert.throws(TypeError, function () { + Iterator.prototype.find.call( + { + get next() { + effects.push('get next'); + return function () { + return { done: true, value: undefined }; + }; + }, + }, + null + ); +}); + +assert.compareArray(effects, []); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/browser.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/browser.js diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/callable.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/callable.js new file mode 100644 index 0000000000..cac9017981 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/callable.js @@ -0,0 +1,16 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.find +description: > + Iterator.prototype.find is callable +features: [iterator-helpers] +---*/ +function* g() {} +Iterator.prototype.find.call(g(), () => {}); + +let iter = g(); +iter.find(() => {}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/get-next-method-only-once.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/get-next-method-only-once.js new file mode 100644 index 0000000000..39806fc806 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/get-next-method-only-once.js @@ -0,0 +1,39 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.find +description: > + Gets the next method from the iterator only once +info: | + %Iterator.prototype%.find ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +let nextGets = 0; + +class TestIterator extends Iterator { + get next() { + ++nextGets; + let counter = 5; + return function () { + if (counter < 0) { + return { done: true, value: undefined }; + } else { + return { done: false, value: --counter }; + } + }; + } +} + +let iterator = new TestIterator(); + +assert.sameValue(nextGets, 0); +assert.sameValue( + iterator.find(() => true), + 4 +); +assert.sameValue(nextGets, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/get-next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/get-next-method-throws.js new file mode 100644 index 0000000000..520f746f79 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/get-next-method-throws.js @@ -0,0 +1,26 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.find +description: > + Iterator has throwing next getter +info: | + %Iterator.prototype%.find ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +class IteratorThrows extends Iterator { + get next() { + throw new Test262Error(); + } +} + +let iterator = new IteratorThrows(); + +assert.throws(Test262Error, function () { + iterator.find(() => {}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/get-return-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/get-return-method-throws.js new file mode 100644 index 0000000000..c3493eee93 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/get-return-method-throws.js @@ -0,0 +1,32 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.find +description: > + Iterator has throwing return getter +info: | + %Iterator.prototype%.find ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +class IteratorThrows extends Iterator { + next() { + return { + done: false, + value: 0, + }; + } + get return() { + throw new Test262Error(); + } +} + +let iterator = new IteratorThrows([1, 2]); + +assert.throws(Test262Error, function () { + iterator.find(() => true); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/is-function.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/is-function.js new file mode 100644 index 0000000000..439bfde946 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/is-function.js @@ -0,0 +1,13 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.find +description: > + Iterator.prototype.find is a built-in function +features: [iterator-helpers] +---*/ + +assert.sameValue(typeof Iterator.prototype.find, 'function'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/iterator-already-exhausted.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/iterator-already-exhausted.js new file mode 100644 index 0000000000..f6b903a99a --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/iterator-already-exhausted.js @@ -0,0 +1,26 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.find +description: > + Iterator.prototype.find returns undefined when the iterator has already been exhausted +info: | + %Iterator.prototype%.find ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +let iterator = (function* () {})(); + +let { value, done } = iterator.next(); +assert.sameValue(value, undefined); +assert.sameValue(done, true); + +let result = iterator.find(() => true); +assert.sameValue(result, undefined); + +result = iterator.find(() => false); +assert.sameValue(result, undefined); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/iterator-has-no-return.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/iterator-has-no-return.js new file mode 100644 index 0000000000..620739de77 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/iterator-has-no-return.js @@ -0,0 +1,30 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.find +description: > + The underlying iterator is sometimes unable to be closed (has no return method) +info: | + %Iterator.prototype%.find ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +let iterator = [1, 2, 3, 4, 5][Symbol.iterator](); + +assert.sameValue(iterator.return, undefined); + +let ret = iterator.find(v => v > 3); + +assert.sameValue(ret, 4); + +let { done, value } = iterator.next(); +assert.sameValue(done, false); +assert.sameValue(value, 5); + +({ done, value } = iterator.next()); +assert.sameValue(done, true); +assert.sameValue(value, undefined); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/iterator-return-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/iterator-return-method-throws.js new file mode 100644 index 0000000000..52a48361ab --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/iterator-return-method-throws.js @@ -0,0 +1,32 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.find +description: > + Iterator has throwing return +info: | + %Iterator.prototype%.find ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +class IteratorThrows extends Iterator { + next() { + return { + done: false, + value: 0, + }; + } + return() { + throw new Test262Error(); + } +} + +let iterator = new IteratorThrows(); + +assert.throws(Test262Error, function () { + iterator.find(() => true); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/length.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/length.js new file mode 100644 index 0000000000..78cf4a0bac --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/length.js @@ -0,0 +1,25 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.find +description: > + Iterator.prototype.find has a "length" property whose value is 1. +info: | + ECMAScript Standard Built-in Objects + + Unless otherwise specified, the length property of a built-in + Function object has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: true }. +features: [iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator.prototype.find, 'length', { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/name.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/name.js new file mode 100644 index 0000000000..b395edbf11 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/name.js @@ -0,0 +1,32 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.find +description: > + The "name" property of Iterator.prototype.find +info: | + 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. + + ... + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +features: [iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator.prototype.find, 'name', { + value: 'find', + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/next-method-returns-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/next-method-returns-non-object.js new file mode 100644 index 0000000000..fa4e23d4b1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/next-method-returns-non-object.js @@ -0,0 +1,26 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.find +description: > + Underlying iterator next returns non-object +info: | + %Iterator.prototype%.find ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +class NonObjectIterator extends Iterator { + next() { + return null; + } +} + +let iterator = new NonObjectIterator(); + +assert.throws(TypeError, function () { + iterator.find(() => {}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/next-method-returns-throwing-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/next-method-returns-throwing-done.js new file mode 100644 index 0000000000..77958e527b --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/next-method-returns-throwing-done.js @@ -0,0 +1,34 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.find +description: > + Underlying iterator next returns object with throwing done getter +info: | + %Iterator.prototype%.find ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + return { + get done() { + throw new Test262Error(); + }, + value: 1, + }; + } + return() { + throw new Error(); + } +} + +let iterator = new ThrowingIterator(); + +assert.throws(Test262Error, function () { + iterator.find(() => {}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/next-method-returns-throwing-value-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/next-method-returns-throwing-value-done.js new file mode 100644 index 0000000000..f82b8672a9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/next-method-returns-throwing-value-done.js @@ -0,0 +1,31 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.find +description: > + Underlying iterator next returns object with throwing value getter, but is already done +info: | + %Iterator.prototype%.find ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + return { + done: true, + get value() { + throw new Test262Error(); + }, + }; + } + return() { + throw new Error(); + } +} + +let iterator = new ThrowingIterator(); +iterator.find(() => {}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/next-method-returns-throwing-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/next-method-returns-throwing-value.js new file mode 100644 index 0000000000..f71202d9e0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/next-method-returns-throwing-value.js @@ -0,0 +1,34 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.find +description: > + Underlying iterator next returns object with throwing value getter +info: | + %Iterator.prototype%.find ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + return { + done: false, + get value() { + throw new Test262Error(); + }, + }; + } + return() { + throw new Error(); + } +} + +let iterator = new ThrowingIterator(); + +assert.throws(Test262Error, function () { + iterator.find(() => {}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/next-method-throws.js new file mode 100644 index 0000000000..59ed603d9e --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/next-method-throws.js @@ -0,0 +1,26 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.find +description: > + Underlying iterator has throwing next method +info: | + %Iterator.prototype%.find ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + throw new Test262Error(); + } +} + +let iterator = new ThrowingIterator(); + +assert.throws(Test262Error, function () { + iterator.find(() => {}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/non-callable-predicate.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/non-callable-predicate.js new file mode 100644 index 0000000000..b34ba1fa0c --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/non-callable-predicate.js @@ -0,0 +1,23 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.find +description: > + Iterator.prototype.find expects to be called with a callable argument. +info: | + %Iterator.prototype%.find ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +let nonCallable = {}; +let iterator = (function* () { + yield 1; +})(); + +assert.throws(TypeError, function () { + iterator.find(nonCallable); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/non-constructible.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/non-constructible.js new file mode 100644 index 0000000000..d7e66cc5f3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/non-constructible.js @@ -0,0 +1,31 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.find +description: > + Iterator.prototype.find is not constructible. + + 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. +features: [iterator-helpers] +---*/ +function* g() {} +let iter = g(); + +assert.throws(TypeError, () => { + new iter.find(); +}); + +assert.throws(TypeError, () => { + new iter.find(() => {}); +}); + +assert.throws(TypeError, () => { + new Iterator.prototype.find(() => {}); +}); + +assert.throws(TypeError, () => { + new class extends Iterator {}.find(() => {}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-args.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-args.js new file mode 100644 index 0000000000..46346783e1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-args.js @@ -0,0 +1,44 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.find +description: > + Iterator.prototype.find predicate is passed the yielded value and a counter as arguments +info: | + %Iterator.prototype%.find ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield 'a'; + yield 'b'; + yield 'c'; +} + +let iter = g(); + +let assertionCount = 0; +let result = iter.find((v, count) => { + switch (v) { + case 'a': + assert.sameValue(count, 0); + break; + case 'b': + assert.sameValue(count, 1); + break; + case 'c': + assert.sameValue(count, 2); + break; + default: + throw new Error(); + } + ++assertionCount; + return false; +}); + +assert.sameValue(result, undefined); +assert.sameValue(assertionCount, 3); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-returns-falsey-then-truthy.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-returns-falsey-then-truthy.js new file mode 100644 index 0000000000..7a8e2a5b27 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-returns-falsey-then-truthy.js @@ -0,0 +1,35 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.find +description: > + Iterator.prototype.find returns the found value and closes the iterator when the predicate returns falsey for some iterated values and truthy for others +info: | + %Iterator.prototype%.find ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + for (let i = 0; i < 5; ++i) { + yield i; + } +} + +let iter = g(); + +let predicateCalls = 0; +let result = iter.find(v => { + ++predicateCalls; + return v > 2; +}); + +assert.sameValue(result, 3); +assert.sameValue(predicateCalls, 4); + +let { done, value } = iter.next(); +assert.sameValue(done, true); +assert.sameValue(value, undefined); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-returns-falsey.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-returns-falsey.js new file mode 100644 index 0000000000..a3518e73d9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-returns-falsey.js @@ -0,0 +1,24 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.find +description: > + Iterator.prototype.find returns undefined when the predicate returns falsey for all iterated values +info: | + %Iterator.prototype%.find ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield 0; + yield 1; + yield 2; + yield 3; +} + +let result = g().find(() => false); +assert.sameValue(result, undefined); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-returns-non-boolean.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-returns-non-boolean.js new file mode 100644 index 0000000000..1178a9cce9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-returns-non-boolean.js @@ -0,0 +1,35 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.find +description: > + Iterator.prototype.find coerces predicate return value to boolean +info: | + %Iterator.prototype%.find ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield ''; + yield null; + yield undefined; + yield 0; + yield 1; + yield 2; + yield 3; +} + +let iter = g(); + +let predicateCalls = 0; +let result = iter.find(v => { + ++predicateCalls; + return v; +}); + +assert.sameValue(result, 1); +assert.sameValue(predicateCalls, 5); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-returns-truthy.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-returns-truthy.js new file mode 100644 index 0000000000..7a5ae69ace --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-returns-truthy.js @@ -0,0 +1,35 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.find +description: > + Iterator.prototype.find returns the found value and closes the iterator when the predicate returns truthy immediately +info: | + %Iterator.prototype%.find ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield 0; + yield 1; + yield 2; +} + +let iter = g(); + +let predicateCalls = 0; +let result = iter.find(v => { + ++predicateCalls; + return true; +}); + +assert.sameValue(result, 0); +assert.sameValue(predicateCalls, 1); + +let { done, value } = iter.next(); +assert.sameValue(done, true); +assert.sameValue(value, undefined); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-this.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-this.js new file mode 100644 index 0000000000..1b4f4458c2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-this.js @@ -0,0 +1,34 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.find +description: > + Iterator.prototype.find predicate this value is undefined +info: | + %Iterator.prototype%.find ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield 0; +} + +let iter = g(); + +let expectedThis = function () { + return this; +}.call(undefined); + +let assertionCount = 0; +let result = iter.find(function (v, count) { + assert.sameValue(this, expectedThis); + ++assertionCount; + return true; +}); + +assert.sameValue(result, 0); +assert.sameValue(assertionCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-throws-then-closing-iterator-also-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-throws-then-closing-iterator-also-throws.js new file mode 100644 index 0000000000..726d133268 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-throws-then-closing-iterator-also-throws.js @@ -0,0 +1,39 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.find +description: > + Attempts to close iterator when predicate throws, but that throws +info: | + %Iterator.prototype%.find ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +let returnCalls = 0; + +class TestIterator extends Iterator { + next() { + return { + done: false, + value: 1, + }; + } + return() { + ++returnCalls; + throw new Error(); + } +} + +let iterator = new TestIterator(); + +assert.throws(Test262Error, function () { + iterator.find(() => { + throw new Test262Error(); + }); +}); + +assert.sameValue(returnCalls, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-throws.js new file mode 100644 index 0000000000..e655effbed --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/predicate-throws.js @@ -0,0 +1,43 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.find +description: > + Closes iterator and throws when predicate throws +info: | + %Iterator.prototype%.find ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +let returnCalls = 0; + +class TestIterator extends Iterator { + next() { + return { + done: false, + value: 1, + }; + } + return() { + ++returnCalls; + return {}; + } +} + +let iterator = new TestIterator(); + +let callbackCalls = 0; + +assert.throws(Test262Error, function () { + iterator.find(() => { + ++callbackCalls; + throw new Test262Error(); + }); +}); + +assert.sameValue(callbackCalls, 1); +assert.sameValue(returnCalls, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/prop-desc.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/prop-desc.js new file mode 100644 index 0000000000..3d0a15d401 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/prop-desc.js @@ -0,0 +1,28 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.find +description: > + Property descriptor of Iterator.prototype.find +info: | + Iterator.prototype.find + + * is the initial value of the Iterator.prototype.find property of the global object. + + 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. +features: [globalThis, iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator.prototype, 'find', { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/proto.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/proto.js new file mode 100644 index 0000000000..d5d04dea33 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/proto.js @@ -0,0 +1,14 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.find +description: > + The value of the [[Prototype]] internal slot of Iterator.prototype.find is the + intrinsic object %Function%. +features: [iterator-helpers] +---*/ + +assert.sameValue(Object.getPrototypeOf(Iterator.prototype.find), Function.prototype); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/shell.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/shell.js diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/this-non-callable-next.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/this-non-callable-next.js new file mode 100644 index 0000000000..d95f825f99 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/this-non-callable-next.js @@ -0,0 +1,18 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.find +description: > + Iterator.prototype.find throws TypeError when its this value is an object with a non-callable next +info: | + %Iterator.prototype%.find ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +assert.throws(TypeError, function () { + Iterator.prototype.find.call({ next: 0 }, () => true); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/this-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/this-non-object.js new file mode 100644 index 0000000000..8af78e9d6c --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/this-non-object.js @@ -0,0 +1,27 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.find +description: > + Iterator.prototype.find throws TypeError when its this value is a non-object +info: | + %Iterator.prototype%.find ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +assert.throws(TypeError, function () { + Iterator.prototype.find.call(null, () => {}); +}); + +Object.defineProperty(Number.prototype, 'next', { + get: function () { + throw new Test262Error(); + }, +}); +assert.throws(TypeError, function () { + Iterator.prototype.find.call(0, () => {}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/find/this-plain-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/find/this-plain-iterator.js new file mode 100644 index 0000000000..806cd5adce --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/find/this-plain-iterator.js @@ -0,0 +1,33 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.find +description: > + Iterator.prototype.find supports a this value that does not inherit from Iterator.prototype but implements the iterator protocol +info: | + %Iterator.prototype%.find ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +let iter = { + get next() { + let count = 3; + return function () { + --count; + return count >= 0 ? { done: false, value: count } : { done: true, value: undefined }; + }; + }, +}; + +let predicateCalls = 0; +let result = Iterator.prototype.find.call(iter, function (v) { + ++predicateCalls; + return v === 0; +}); + +assert.sameValue(result, 0); +assert.sameValue(predicateCalls, 3); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/argument-effect-order.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/argument-effect-order.js new file mode 100644 index 0000000000..6710db0923 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/argument-effect-order.js @@ -0,0 +1,45 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Arguments and this value are evaluated in the correct order +info: | + %Iterator.prototype%.flatMap ( mapper ) + + 1. Let O be the this value. + 2. If O is not an Object, throw a TypeError exception. + 3. If IsCallable(mapper) is false, throw a TypeError exception. + 4. Let iterated be ? GetIteratorDirect(O). + +includes: [compareArray.js] +features: [iterator-helpers] +flags: [] +---*/ +let effects = []; + +assert.throws(TypeError, function () { + Iterator.prototype.flatMap.call( + { + get next() { + effects.push('get next'); + return function () { + return { done: true, value: undefined }; + }; + }, + }, + { + valueOf() { + effects.push('valueOf mapper'); + return function () { + return []; + }; + }, + } + ); +}); + +assert.compareArray(effects, []); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/browser.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/browser.js diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/callable.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/callable.js new file mode 100644 index 0000000000..c5d106e83d --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/callable.js @@ -0,0 +1,16 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Iterator.prototype.flatMap is callable +features: [iterator-helpers] +---*/ +function* g() {} +Iterator.prototype.flatMap.call(g(), () => []); + +let iter = g(); +iter.flatMap(() => []); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/exhaustion-does-not-call-return.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/exhaustion-does-not-call-return.js new file mode 100644 index 0000000000..93c4516b29 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/exhaustion-does-not-call-return.js @@ -0,0 +1,37 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Underlying iterator return is not called when result iterator is exhausted +info: | + %Iterator.prototype%.flatMap ( mapper ) + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield 0; + yield 1; + yield 2; +} + +class TestIterator extends Iterator { + get next() { + let n = g(); + return function() { + return n.next(); + }; + } + return() { + throw new Test262Error(); + } +} + +let iterator = new TestIterator().flatMap(() => []); +iterator.next(); +iterator.next(); +iterator.next(); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/flattens-iterable.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/flattens-iterable.js new file mode 100644 index 0000000000..90a1f9bb5e --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/flattens-iterable.js @@ -0,0 +1,33 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Iterator.prototype.flatMap flattens iterables returned by the mapper +info: | + %Iterator.prototype%.flatMap ( mapper ) + +includes: [compareArray.js] +features: [iterator-helpers] +flags: [] +---*/ + +function* g() { + yield 0; + yield 1; + yield 2; + yield 3; +} + +let iter = g().flatMap((v, count) => { + let result = []; + for (let i = 0; i < v; ++i) { + result.push(v); + } + return result; +}); + +assert.compareArray(Array.from(iter), [1, 2, 2, 3, 3, 3]); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/flattens-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/flattens-iterator.js new file mode 100644 index 0000000000..d7d118863a --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/flattens-iterator.js @@ -0,0 +1,47 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Iterator.prototype.flatMap flattens non-iterable iterators returned by the mapper +info: | + %Iterator.prototype%.flatMap ( mapper ) + + 5.b.vi. Let innerIterator be Completion(GetIteratorFlattenable(mapped)). + +includes: [compareArray.js] +features: [iterator-helpers] +flags: [] +---*/ + +function* g() { + yield 0; + yield 1; + yield 2; + yield 3; +} + +let iter = g().flatMap((v, count) => { + let i = 0; + return { + next: function () { + if (i < v) { + ++i; + return { + value: v, + done: false, + }; + } else { + return { + value: undefined, + done: true, + }; + } + }, + }; +}); + +assert.compareArray(Array.from(iter), [1, 2, 2, 3, 3, 3]); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/flattens-only-depth-1.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/flattens-only-depth-1.js new file mode 100644 index 0000000000..e493c46020 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/flattens-only-depth-1.js @@ -0,0 +1,37 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Iterator.prototype.flatMap does not flatten recursively +info: | + %Iterator.prototype%.flatMap ( mapper ) + +includes: [compareArray.js] +features: [iterator-helpers] +flags: [] +---*/ + +let arr = [ + { + [Symbol.iterator]: function () { + throw new Test262Error(); + }, + }, + { + next: function () { + throw new Test262Error(); + }, + }, +]; + +function* g() { + yield arr; +} + +let iter = g().flatMap(v => v); + +assert.compareArray(Array.from(iter), arr); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/get-next-method-only-once.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/get-next-method-only-once.js new file mode 100644 index 0000000000..7c74ffe05f --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/get-next-method-only-once.js @@ -0,0 +1,44 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Gets the next method from the underlying iterator only once +info: | + %Iterator.prototype%.flatMap ( mapper ) + + 4. Let iterated be ? GetIteratorDirect(O). + +features: [iterator-helpers] +flags: [] +---*/ +let nextGets = 0; +let nextCalls = 0; + +class CountingIterator extends Iterator { + get next() { + ++nextGets; + let iter = (function* () { + for (let i = 1; i < 5; ++i) { + yield i; + } + })(); + return function () { + ++nextCalls; + return iter.next(); + }; + } +} + +let iterator = new CountingIterator(); + +assert.sameValue(nextGets, 0); +assert.sameValue(nextCalls, 0); + +for (const value of iterator.flatMap(() => [])); + +assert.sameValue(nextGets, 1); +assert.sameValue(nextCalls, 5); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/get-next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/get-next-method-throws.js new file mode 100644 index 0000000000..eeb650e4f5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/get-next-method-throws.js @@ -0,0 +1,28 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Underlying iterator has throwing next getter +info: | + %Iterator.prototype%.flatMap ( mapper ) + + 4. Let iterated be ? GetIteratorDirect(O). + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + get next() { + throw new Test262Error(); + } +} + +let iterator = new ThrowingIterator(); + +assert.throws(Test262Error, function () { + iterator.flatMap(() => []); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/get-return-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/get-return-method-throws.js new file mode 100644 index 0000000000..62958ecac6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/get-return-method-throws.js @@ -0,0 +1,33 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Underlying iterator return is throwing getter +info: | + %Iterator.prototype%.flatMap ( mapper ) + +features: [iterator-helpers] +flags: [] +---*/ +class TestIterator extends Iterator { + next() { + return { + done: false, + value: 1, + }; + } + get return() { + throw new Test262Error(); + } +} + +let iterator = new TestIterator().flatMap(x => [x]); +iterator.next(); + +assert.throws(Test262Error, function () { + iterator.return(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/is-function.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/is-function.js new file mode 100644 index 0000000000..7abaa964ac --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/is-function.js @@ -0,0 +1,13 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Iterator.prototype.flatMap is a built-in function +features: [iterator-helpers] +---*/ + +assert.sameValue(typeof Iterator.prototype.flatMap, 'function'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/iterable-primitives-are-not-flattened.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/iterable-primitives-are-not-flattened.js new file mode 100644 index 0000000000..96c62357ae --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/iterable-primitives-are-not-flattened.js @@ -0,0 +1,40 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Iterator.prototype.flatMap does not respect the iterability of any primitive +info: | + %Iterator.prototype%.flatMap ( mapper ) + + 5.b.vi. Let innerIterator be Completion(GetIteratorFlattenable(mapped)). + +includes: [compareArray.js] +features: [iterator-helpers] +flags: [] +---*/ + +function* g() { + yield 0; +} + +Number.prototype[Symbol.iterator] = function* () { + let i = 0; + let target = this >>> 0; + while (i < target) { + yield i; + ++i; + } +}; + +assert.compareArray(Array.from(5), [0, 1, 2, 3, 4]); + +assert.throws(TypeError, function () { + for (let unused of g().flatMap(v => 5)); +}); + +let iter = g().flatMap(v => new Number(5)); +assert.compareArray(Array.from(iter), [0, 1, 2, 3, 4]); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/iterable-to-iterator-fallback.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/iterable-to-iterator-fallback.js new file mode 100644 index 0000000000..34d870c82f --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/iterable-to-iterator-fallback.js @@ -0,0 +1,60 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Iterator.prototype.flatMap falls back to treating mapper return values as iterators if the Symbol.iterator property is null/undefined +info: | + %Iterator.prototype%.flatMap ( mapper ) + + 5.b.vi. Let innerIterator be Completion(GetIteratorFlattenable(mapped)). + +includes: [compareArray.js] +features: [iterator-helpers] +flags: [] +---*/ + +function* g() { + yield 0; +} + +function* h() { + yield 0; + yield 1; + yield 2; +} + +let iter = g().flatMap(v => { + let n = h(); + return { + [Symbol.iterator]: 0, + next: () => n.next(), + }; +}); + +assert.throws(TypeError, function () { + iter.next(); +}); + +iter = g().flatMap(v => { + let n = h(); + return { + [Symbol.iterator]: null, + next: () => n.next(), + }; +}); + +assert.compareArray(Array.from(iter), [0, 1, 2]); + +iter = g().flatMap(v => { + let n = h(); + return { + [Symbol.iterator]: undefined, + next: () => n.next(), + }; +}); + +assert.compareArray(Array.from(iter), [0, 1, 2]); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/iterator-already-exhausted.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/iterator-already-exhausted.js new file mode 100644 index 0000000000..330b9312fc --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/iterator-already-exhausted.js @@ -0,0 +1,25 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Iterator.prototype.flatMap returns an empty iterator when the iterator has already been exhausted +info: | + %Iterator.prototype%.flatMap ( mapper ) + +features: [iterator-helpers] +flags: [] +---*/ +let iterator = (function* () {})(); + +let { value, done } = iterator.next(); +assert.sameValue(value, undefined); +assert.sameValue(done, true); + +iterator = iterator.flatMap(x => [x]); +({ value, done } = iterator.next()); +assert.sameValue(value, undefined); +assert.sameValue(done, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/iterator-return-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/iterator-return-method-throws.js new file mode 100644 index 0000000000..c3b78b5c26 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/iterator-return-method-throws.js @@ -0,0 +1,32 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Iterator has throwing return +info: | + %Iterator.prototype%.flatMap ( mapper ) + +features: [iterator-helpers] +flags: [] +---*/ +class IteratorThrows extends Iterator { + next() { + return { + done: false, + value: 0, + }; + } + return() { + throw new Test262Error(); + } +} + +let iterator = new IteratorThrows().flatMap(() => []); + +assert.throws(Test262Error, function () { + iterator.return(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/length.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/length.js new file mode 100644 index 0000000000..ab4a788c55 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/length.js @@ -0,0 +1,25 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Iterator.prototype.flatMap has a "length" property whose value is 1. +info: | + ECMAScript Standard Built-in Objects + + Unless otherwise specified, the length property of a built-in + Function object has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: true }. +features: [iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator.prototype.flatMap, 'length', { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-args.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-args.js new file mode 100644 index 0000000000..52ce730739 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-args.js @@ -0,0 +1,58 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Iterator.prototype.flatMap mapper is passed the yielded value and a counter as arguments +info: | + %Iterator.prototype%.flatMap ( mapper ) + + 5.b.iv. Let mapped be Completion(Call(mapper, undefined, « value, 𝔽(counter) »)). + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield 'a'; + yield 'b'; + yield 'c'; + yield 'd'; + yield 'e'; +} + +let assertionCount = 0; +let iter = g().flatMap((v, count) => { + switch (v) { + case 'a': + assert.sameValue(count, 0); + ++assertionCount; + return [0]; + case 'b': + assert.sameValue(count, 1); + ++assertionCount; + return [0]; + case 'c': + assert.sameValue(count, 2); + ++assertionCount; + return [1, 2]; + case 'd': + assert.sameValue(count, 3); + ++assertionCount; + return [3, 4, 5]; + case 'e': + assert.sameValue(count, 4); + ++assertionCount; + return [6, 7, 8, 9]; + default: + throw new Error(); + } +}); + +assert.sameValue(assertionCount, 0); + +for (let i of iter); + +assert.sameValue(assertionCount, 5); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-returns-closed-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-returns-closed-iterator.js new file mode 100644 index 0000000000..016bcbb3c0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-returns-closed-iterator.js @@ -0,0 +1,33 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Iterator.prototype.flatMap handles closed return values from mapper and does not try to close them again +info: | + %Iterator.prototype%.flatMap ( mapper ) + +features: [iterator-helpers] +flags: [] +---*/ + +function* g() { + yield 0; + yield 1; + yield 2; +} + +let closed = g(); +closed.return(); +closed.return = function () { + throw new Test262Error(); +}; + +let iter = g().flatMap(v => closed); +let { value, done } = iter.next(); + +assert.sameValue(value, undefined); +assert.sameValue(done, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-returns-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-returns-non-object.js new file mode 100644 index 0000000000..cef235e282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-returns-non-object.js @@ -0,0 +1,37 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Iterator.prototype.flatMap mapper return value must be an object +info: | + %Iterator.prototype%.flatMap ( mapper ) + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield 0; + yield 0; + yield 0; + yield 1; +} + +let iter = g(); + +let mapperCalls = 0; +iter = iter.flatMap(v => { + ++mapperCalls; + return null; +}); + +assert.sameValue(mapperCalls, 0); + +assert.throws(TypeError, function () { + iter.next(); +}); + +assert.sameValue(mapperCalls, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-this.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-this.js new file mode 100644 index 0000000000..58a93d864d --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-this.js @@ -0,0 +1,36 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Iterator.prototype.flatMap mapper this value is undefined +info: | + %Iterator.prototype%.flatMap ( mapper ) + + 5.b.iv. Let mapped be Completion(Call(mapper, undefined, « value, 𝔽(counter) »)). + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield 0; +} + +let iter = g(); + +let expectedThis = function () { + return this; +}.call(undefined); + +let assertionCount = 0; +iter = iter.flatMap(function (v, count) { + assert.sameValue(this, expectedThis); + ++assertionCount; + return [v]; +}); + +iter.next(); +assert.sameValue(assertionCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-throws-then-closing-iterator-also-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-throws-then-closing-iterator-also-throws.js new file mode 100644 index 0000000000..584939747a --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-throws-then-closing-iterator-also-throws.js @@ -0,0 +1,43 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Attempts to close iterator when mapper throws, but that throws +info: | + %Iterator.prototype%.flatMap ( mapper ) + + 5.b.v. IfAbruptCloseIterator(mapped, iterated). + +features: [iterator-helpers] +flags: [] +---*/ +let returnCalls = 0; + +class TestIterator extends Iterator { + next() { + return { + done: false, + value: 1, + }; + } + return() { + ++returnCalls; + throw new Error(); + } +} + +let iterator = new TestIterator().flatMap(() => { + throw new Test262Error(); +}); + +assert.sameValue(returnCalls, 0); + +assert.throws(Test262Error, function () { + iterator.next(); +}); + +assert.sameValue(returnCalls, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-throws.js new file mode 100644 index 0000000000..48b367f427 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/mapper-throws.js @@ -0,0 +1,44 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Closes iterator and throws when mapper throws +info: | + %Iterator.prototype%.flatMap ( mapper ) + + 5.b.v. IfAbruptCloseIterator(mapped, iterated). + +features: [iterator-helpers] +flags: [] +---*/ +let returnCalls = 0; + +class TestIterator extends Iterator { + next() { + return { + done: false, + value: 1, + }; + } + return() { + ++returnCalls; + return {}; + } +} + +let callbackCalls = 0; +let iterator = new TestIterator().flatMap(() => { + ++callbackCalls; + throw new Test262Error(); +}); + +assert.throws(Test262Error, function () { + iterator.next(); +}); + +assert.sameValue(callbackCalls, 1); +assert.sameValue(returnCalls, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/name.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/name.js new file mode 100644 index 0000000000..30fb1fc2cb --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/name.js @@ -0,0 +1,32 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + The "name" property of Iterator.prototype.flatMap +info: | + 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. + + ... + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +features: [iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator.prototype.flatMap, 'name', { + value: 'flatMap', + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/next-method-returns-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/next-method-returns-non-object.js new file mode 100644 index 0000000000..2f32c1c21a --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/next-method-returns-non-object.js @@ -0,0 +1,26 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Underlying iterator next returns non-object +info: | + %Iterator.prototype%.flatMap ( mapper ) + +features: [iterator-helpers] +flags: [] +---*/ +class NonObjectIterator extends Iterator { + next() { + return null; + } +} + +let iterator = new NonObjectIterator().flatMap(x => [x]); + +assert.throws(TypeError, function () { + iterator.next(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-done.js new file mode 100644 index 0000000000..62fe294ed0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-done.js @@ -0,0 +1,34 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Underlying iterator next returns object with throwing done getter +info: | + %Iterator.prototype%.flatMap ( mapper ) + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + return { + get done() { + throw new Test262Error(); + }, + value: 1, + }; + } + return() { + throw new Error(); + } +} + +let iterator = new ThrowingIterator().flatMap(x => [x]); + +assert.throws(Test262Error, function () { + iterator.next(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-value-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-value-done.js new file mode 100644 index 0000000000..0a7a96a199 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-value-done.js @@ -0,0 +1,31 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Underlying iterator next returns object with throwing value getter, but is already done +info: | + %Iterator.prototype%.flatMap ( mapper ) + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + return { + done: true, + get value() { + throw new Test262Error(); + }, + }; + } + return() { + throw new Error(); + } +} + +let iterator = new ThrowingIterator().flatMap(x => [x]); +iterator.next(); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-value.js new file mode 100644 index 0000000000..549adb2967 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-value.js @@ -0,0 +1,34 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Underlying iterator next returns object with throwing value getter +info: | + %Iterator.prototype%.flatMap ( mapper ) + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + return { + done: false, + get value() { + throw new Test262Error(); + }, + }; + } + return() { + throw new Error(); + } +} + +let iterator = new ThrowingIterator().flatMap(x => [x]); + +assert.throws(Test262Error, function () { + iterator.next(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/next-method-throws.js new file mode 100644 index 0000000000..2ba2838c2f --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/next-method-throws.js @@ -0,0 +1,26 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Underlying iterator has throwing next method +info: | + %Iterator.prototype%.flatMap ( mapper ) + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + throw new Test262Error(); + } +} + +let iterator = new ThrowingIterator().flatMap(x => [x]); + +assert.throws(Test262Error, function () { + iterator.next(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/non-callable-mapper.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/non-callable-mapper.js new file mode 100644 index 0000000000..93cf478aeb --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/non-callable-mapper.js @@ -0,0 +1,23 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Iterator.prototype.flatMap expects to be called with a callable argument. +info: | + %Iterator.prototype%.flatMap ( mapper ) + + 3. If IsCallable(mapper) is false, throw a TypeError exception. + +features: [iterator-helpers] +flags: [] +---*/ +let nonCallable = {}; +let iterator = (function* () {})(); + +assert.throws(TypeError, function () { + iterator.flatMap(nonCallable); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/non-constructible.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/non-constructible.js new file mode 100644 index 0000000000..e382741aff --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/non-constructible.js @@ -0,0 +1,31 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Iterator.prototype.flatMap is not constructible. + + 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. +features: [iterator-helpers] +---*/ +function* g() {} +let iter = g(); + +assert.throws(TypeError, () => { + new iter.flatMap(); +}); + +assert.throws(TypeError, () => { + new iter.flatMap(() => []); +}); + +assert.throws(TypeError, () => { + new Iterator.prototype.flatMap(() => []); +}); + +assert.throws(TypeError, () => { + new class extends Iterator {}.flatMap(() => []); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/prop-desc.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/prop-desc.js new file mode 100644 index 0000000000..b36791590d --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/prop-desc.js @@ -0,0 +1,28 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Property descriptor of Iterator.prototype.flatMap +info: | + Iterator.prototype.flatMap + + * is the initial value of the Iterator.prototype.flatMap property of the global object. + + 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. +features: [globalThis, iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator.prototype, 'flatMap', { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/proto.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/proto.js new file mode 100644 index 0000000000..da49133d6c --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/proto.js @@ -0,0 +1,14 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + The value of the [[Prototype]] internal slot of Iterator.prototype.flatMap is the + intrinsic object %FunctionPrototype%. +features: [iterator-helpers] +---*/ + +assert.sameValue(Object.getPrototypeOf(Iterator.prototype.flatMap), Function.prototype); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/result-is-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/result-is-iterator.js new file mode 100644 index 0000000000..9fd8df791c --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/result-is-iterator.js @@ -0,0 +1,17 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + The value of the [[Prototype]] internal slot of the return value of Iterator.prototype.flatMap is the + intrinsic object %IteratorHelperPrototype%. +features: [iterator-helpers] +---*/ + +assert( + (function* () {})().flatMap(() => []) instanceof Iterator, + 'function*(){}().flatMap(() => []) must return an Iterator' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/return-is-forwarded-to-mapper-result.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/return-is-forwarded-to-mapper-result.js new file mode 100644 index 0000000000..a00b5eacca --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/return-is-forwarded-to-mapper-result.js @@ -0,0 +1,48 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Mapper returned iterator return is called when result iterator is closed +info: | + %Iterator.prototype%.flatMap ( mapper ) + +features: [iterator-helpers] +flags: [] +---*/ +let returnCount = 0; + +function* g() { + yield 0; +} + +let iter = g().flatMap(v => ({ + next() { + return { + done: false, + value: 1, + }; + }, + return() { + ++returnCount; + return {}; + }, +})); + +assert.sameValue(returnCount, 0); + +let { done, value } = iter.next(); + +assert.sameValue(done, false); +assert.sameValue(value, 1); + +assert.sameValue(returnCount, 0); + +iter.return(); +assert.sameValue(returnCount, 1); + +iter.return(); +assert.sameValue(returnCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/return-is-forwarded-to-underlying-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/return-is-forwarded-to-underlying-iterator.js new file mode 100644 index 0000000000..7681a806c8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/return-is-forwarded-to-underlying-iterator.js @@ -0,0 +1,36 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Underlying iterator return is called when result iterator is closed +info: | + %Iterator.prototype%.flatMap ( mapper ) + +features: [iterator-helpers] +flags: [] +---*/ +let returnCount = 0; + +class TestIterator extends Iterator { + next() { + return { + done: false, + value: 1, + }; + } + return() { + ++returnCount; + return {}; + } +} + +let iterator = new TestIterator().flatMap(() => []); +assert.sameValue(returnCount, 0); +iterator.return(); +assert.sameValue(returnCount, 1); +iterator.return(); +assert.sameValue(returnCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/return-is-not-forwarded-after-exhaustion.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/return-is-not-forwarded-after-exhaustion.js new file mode 100644 index 0000000000..418bc1f8d1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/return-is-not-forwarded-after-exhaustion.js @@ -0,0 +1,49 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Underlying iterator return is not called after result iterator observes that underlying iterator is exhausted +info: | + %Iterator.prototype%.flatMap ( mapper ) + +features: [iterator-helpers] +flags: [] +---*/ +let returnCount = 0; + +class TestIterator extends Iterator { + next() { + return { + done: true, + value: undefined, + }; + } + return() { + throw new Test262Error(); + } +} + +let iterator = new TestIterator().flatMap(x => [x]); +assert.throws(Test262Error, function () { + iterator.return(); +}); +iterator.next(); +iterator.return(); + +iterator = new TestIterator().flatMap(x => [x]); +iterator.next(); +iterator.return(); + +iterator = new TestIterator() + .flatMap(x => [x]) + .flatMap(x => [x]) + .flatMap(x => [x]); +assert.throws(Test262Error, function () { + iterator.return(); +}); +iterator.next(); +iterator.return(); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/shell.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/shell.js diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/strings-are-not-flattened.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/strings-are-not-flattened.js new file mode 100644 index 0000000000..31aaaf4cfd --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/strings-are-not-flattened.js @@ -0,0 +1,29 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Iterator.prototype.flatMap does not respect the iterability of primitive strings +info: | + %Iterator.prototype%.flatMap ( mapper ) + + 5.b.vi. Let innerIterator be Completion(GetIteratorFlattenable(mapped)). + +includes: [compareArray.js] +features: [iterator-helpers] +flags: [] +---*/ + +function* g() { + yield 0; +} + +assert.throws(TypeError, function () { + for (let unused of g().flatMap(v => 'string')); +}); + +let iter = g().flatMap(v => new String('string')); +assert.compareArray(Array.from(iter), ['s', 't', 'r', 'i', 'n', 'g']); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/this-non-callable-next.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/this-non-callable-next.js new file mode 100644 index 0000000000..4161d1081e --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/this-non-callable-next.js @@ -0,0 +1,20 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Iterator.prototype.flatMap throws TypeError when its this value is an object with a non-callable next +info: | + %Iterator.prototype%.flatMap ( mapper ) + +features: [iterator-helpers] +flags: [] +---*/ +let iter = Iterator.prototype.flatMap.call({ next: 0 }, () => []); + +assert.throws(TypeError, function () { + iter.next(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/this-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/this-non-object.js new file mode 100644 index 0000000000..d0eaae2dfb --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/this-non-object.js @@ -0,0 +1,29 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Iterator.prototype.flatMap throws TypeError when its this value is a non-object +info: | + %Iterator.prototype%.flatMap ( mapper ) + + 2. If O is not an Object, throw a TypeError exception. + +features: [iterator-helpers] +flags: [] +---*/ +assert.throws(TypeError, function () { + Iterator.prototype.flatMap.call(null, () => []); +}); + +Object.defineProperty(Number.prototype, 'next', { + get: function () { + throw new Test262Error(); + }, +}); +assert.throws(TypeError, function () { + Iterator.prototype.flatMap.call(0, () => []); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/this-plain-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/this-plain-iterator.js new file mode 100644 index 0000000000..405ba975f0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/this-plain-iterator.js @@ -0,0 +1,34 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Iterator.prototype.flatMap supports a this value that does not inherit from Iterator.prototype but implements the iterator protocol +info: | + %Iterator.prototype%.flatMap ( mapper ) + +features: [iterator-helpers] +flags: [] +---*/ +let iter = { + get next() { + let count = 3; + return function () { + --count; + return count >= 0 ? { done: false, value: count } : { done: true, value: undefined }; + }; + }, +}; + +let mapperCalls = 0; +iter = Iterator.prototype.flatMap.call(iter, function (v) { + ++mapperCalls; + return [v]; +}); + +for (let e of iter); + +assert.sameValue(mapperCalls, 3); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/throws-typeerror-when-generator-is-running.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/throws-typeerror-when-generator-is-running.js new file mode 100644 index 0000000000..2d404dd2e7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/throws-typeerror-when-generator-is-running.js @@ -0,0 +1,49 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatmap +description: > + Throws a TypeError when the closure generator is already running. +info: | + %IteratorHelperPrototype%.next ( ) + 1. Return ? GeneratorResume(this value, undefined, "Iterator Helper"). + + 27.5.3.3 GeneratorResume ( generator, value, generatorBrand ) + 1. Let state be ? GeneratorValidate(generator, generatorBrand). + ... + + 27.5.3.2 GeneratorValidate ( generator, generatorBrand ) + ... + 6. If state is executing, throw a TypeError exception. + ... + +features: [iterator-helpers] +---*/ + +var loopCount = 0; + +function* g() { + while (true) { + loopCount++; + yield; + } +} + +var enterCount = 0; + +function mapper() { + enterCount++; + iter.next(); +} + +var iter = g().flatMap(mapper); + +assert.throws(TypeError, function() { + iter.next(); +}); + +assert.sameValue(loopCount, 1); +assert.sameValue(enterCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/underlying-iterator-advanced-in-parallel.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/underlying-iterator-advanced-in-parallel.js new file mode 100644 index 0000000000..cc5b401319 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/underlying-iterator-advanced-in-parallel.js @@ -0,0 +1,45 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Underlying iterator is advanced after calling flatMap +info: | + %Iterator.prototype%.flatMap ( mapper ) + +features: [iterator-helpers] +flags: [] +---*/ +let iterator = (function* () { + for (let i = 0; i < 5; ++i) { + yield i; + } +})(); + +let mapped = iterator.flatMap(x => [x]); + +let { value, done } = iterator.next(); + +assert.sameValue(value, 0); +assert.sameValue(done, false); + +iterator.next(); +iterator.next(); + +({ value, done } = mapped.next()); + +assert.sameValue(value, 3); +assert.sameValue(done, false); + +({ value, done } = mapped.next()); + +assert.sameValue(value, 4); +assert.sameValue(done, false); + +({ value, done } = mapped.next()); + +assert.sameValue(value, undefined); +assert.sameValue(done, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/underlying-iterator-closed-in-parallel.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/underlying-iterator-closed-in-parallel.js new file mode 100644 index 0000000000..e20c48c844 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/underlying-iterator-closed-in-parallel.js @@ -0,0 +1,29 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Underlying iterator is closed after calling flatMap +info: | + %Iterator.prototype%.flatMap ( mapper ) + +features: [iterator-helpers] +flags: [] +---*/ +let iterator = (function* () { + for (let i = 0; i < 5; ++i) { + yield i; + } +})(); + +let mapped = iterator.flatMap(x => [x]); + +iterator.return(); + +let { value, done } = mapped.next(); + +assert.sameValue(value, undefined); +assert.sameValue(done, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/underlying-iterator-closed.js b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/underlying-iterator-closed.js new file mode 100644 index 0000000000..ab3e369a43 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/flatMap/underlying-iterator-closed.js @@ -0,0 +1,29 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.flatMap +description: > + Underlying iterator is closed before calling flatMap +info: | + %Iterator.prototype%.flatMap ( mapper ) + +features: [iterator-helpers] +flags: [] +---*/ +let iterator = (function* () { + for (let i = 0; i < 5; ++i) { + yield i; + } +})(); + +iterator.return(); + +let mapped = iterator.flatMap(() => []); + +let { value, done } = mapped.next(); + +assert.sameValue(value, undefined); +assert.sameValue(done, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/argument-effect-order.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/argument-effect-order.js new file mode 100644 index 0000000000..4f44924efa --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/argument-effect-order.js @@ -0,0 +1,38 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.forEach +description: > + Arguments and this value are evaluated in the correct order +info: | + %Iterator.prototype%.forEach ( fn ) + + 1. Let O be the this value. + 2. If O is not an Object, throw a TypeError exception. + 3. If IsCallable(fn) is false, throw a TypeError exception. + 4. Let iterated be ? GetIteratorDirect(O). + +includes: [compareArray.js] +features: [iterator-helpers] +flags: [] +---*/ +let effects = []; + +assert.throws(TypeError, function () { + Iterator.prototype.forEach.call( + { + get next() { + effects.push('get next'); + return function () { + return { done: true, value: undefined }; + }; + }, + }, + null + ); +}); + +assert.compareArray(effects, []); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/browser.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/browser.js diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/callable.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/callable.js new file mode 100644 index 0000000000..91c4030aed --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/callable.js @@ -0,0 +1,16 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.forEach +description: > + Iterator.prototype.forEach is callable +features: [iterator-helpers] +---*/ +function* g() {} +Iterator.prototype.forEach.call(g(), () => {}); + +let iter = g(); +iter.forEach(() => {}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/fn-args.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/fn-args.js new file mode 100644 index 0000000000..951ad07e27 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/fn-args.js @@ -0,0 +1,43 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.forEach +description: > + Iterator.prototype.forEach fn is passed the yielded value and a counter as arguments +info: | + %Iterator.prototype%.forEach ( fn ) + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield 'a'; + yield 'b'; + yield 'c'; +} + +let iter = g(); + +let assertionCount = 0; +let result = iter.forEach((v, count) => { + switch (v) { + case 'a': + assert.sameValue(count, 0); + break; + case 'b': + assert.sameValue(count, 1); + break; + case 'c': + assert.sameValue(count, 2); + break; + default: + throw new Error(); + } + ++assertionCount; +}); + +assert.sameValue(result, undefined); +assert.sameValue(assertionCount, 3); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/fn-called-for-each-yielded-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/fn-called-for-each-yielded-value.js new file mode 100644 index 0000000000..774f6e76c9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/fn-called-for-each-yielded-value.js @@ -0,0 +1,31 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.forEach +description: > + Iterator.prototype.forEach calls fn once for each yielded value, in order +info: | + %Iterator.prototype%.forEach ( fn ) + + 6.d. Let result be Completion(Call(fn, undefined, « value, 𝔽(counter) »)). + +includes: [compareArray.js] +features: [iterator-helpers] +flags: [] +---*/ +let effects = []; + +function* g() { + yield 'a'; + yield 'b'; + yield 'c'; +} + +g().forEach((value, count) => { + effects.push(value, count); +}); + +assert.compareArray(effects, ['a', 0, 'b', 1, 'c', 2]); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/fn-this.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/fn-this.js new file mode 100644 index 0000000000..a43b5f0b38 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/fn-this.js @@ -0,0 +1,33 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.forEach +description: > + Iterator.prototype.forEach fn this value is undefined +info: | + %Iterator.prototype%.forEach ( fn ) + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield 0; +} + +let iter = g(); + +let expectedThis = function () { + return this; +}.call(undefined); + +let assertionCount = 0; +let result = iter.forEach(function (v, count) { + assert.sameValue(this, expectedThis); + ++assertionCount; +}); + +assert.sameValue(result, undefined); +assert.sameValue(assertionCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/fn-throws-then-closing-iterator-also-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/fn-throws-then-closing-iterator-also-throws.js new file mode 100644 index 0000000000..972f61c93e --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/fn-throws-then-closing-iterator-also-throws.js @@ -0,0 +1,39 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.forEach +description: > + Attempts to close iterator when fn throws, but that throws +info: | + %Iterator.prototype%.forEach ( fn ) + +features: [iterator-helpers] +flags: [] +---*/ +let returnCalls = 0; + +class TestIterator extends Iterator { + next() { + return { + done: false, + value: 1, + }; + } + return() { + ++returnCalls; + throw new Error(); + } +} + +let iterator = new TestIterator(); + +assert.throws(Test262Error, function () { + iterator.forEach(() => { + throw new Test262Error(); + }); +}); + +assert.sameValue(returnCalls, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/fn-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/fn-throws.js new file mode 100644 index 0000000000..c7e1fe638d --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/fn-throws.js @@ -0,0 +1,43 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.forEach +description: > + Closes iterator and throws when fn throws +info: | + %Iterator.prototype%.forEach ( fn ) + +features: [iterator-helpers] +flags: [] +---*/ +let returnCalls = 0; + +class TestIterator extends Iterator { + next() { + return { + done: false, + value: 1, + }; + } + return() { + ++returnCalls; + return {}; + } +} + +let iterator = new TestIterator(); + +let callbackCalls = 0; + +assert.throws(Test262Error, function () { + iterator.forEach(() => { + ++callbackCalls; + throw new Test262Error(); + }); +}); + +assert.sameValue(callbackCalls, 1); +assert.sameValue(returnCalls, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/get-next-method-only-once.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/get-next-method-only-once.js new file mode 100644 index 0000000000..06e64bf63d --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/get-next-method-only-once.js @@ -0,0 +1,39 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.forEach +description: > + Gets the next method from the iterator only once +info: | + %Iterator.prototype%.forEach ( fn ) + +features: [iterator-helpers] +flags: [] +---*/ +let nextGets = 0; + +class TestIterator extends Iterator { + get next() { + ++nextGets; + let counter = 5; + return function () { + if (counter < 0) { + return { done: true, value: undefined }; + } else { + return { done: false, value: --counter }; + } + }; + } +} + +let iterator = new TestIterator(); + +assert.sameValue(nextGets, 0); +assert.sameValue( + iterator.forEach(() => {}), + undefined +); +assert.sameValue(nextGets, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/get-next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/get-next-method-throws.js new file mode 100644 index 0000000000..dcb1557bff --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/get-next-method-throws.js @@ -0,0 +1,26 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.forEach +description: > + Iterator has throwing next getter +info: | + %Iterator.prototype%.forEach ( fn ) + +features: [iterator-helpers] +flags: [] +---*/ +class IteratorThrows extends Iterator { + get next() { + throw new Test262Error(); + } +} + +let iterator = new IteratorThrows(); + +assert.throws(Test262Error, function () { + iterator.forEach(() => {}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/is-function.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/is-function.js new file mode 100644 index 0000000000..5a716cf888 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/is-function.js @@ -0,0 +1,13 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.forEach +description: > + Iterator.prototype.forEach is a built-in function +features: [iterator-helpers] +---*/ + +assert.sameValue(typeof Iterator.prototype.forEach, 'function'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/iterator-already-exhausted.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/iterator-already-exhausted.js new file mode 100644 index 0000000000..455d6b8474 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/iterator-already-exhausted.js @@ -0,0 +1,25 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.forEach +description: > + Iterator.prototype.forEach returns immediately when the iterator has already been exhausted +info: | + %Iterator.prototype%.forEach ( fn ) + +features: [iterator-helpers] +flags: [] +---*/ +let iterator = (function* () {})(); + +let { value, done } = iterator.next(); +assert.sameValue(value, undefined); +assert.sameValue(done, true); + +let result = iterator.forEach(() => { + throw new Error(); +}); +assert.sameValue(result, undefined); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/length.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/length.js new file mode 100644 index 0000000000..b4addf5fbb --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/length.js @@ -0,0 +1,25 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.forEach +description: > + Iterator.prototype.forEach has a "length" property whose value is 1. +info: | + ECMAScript Standard Built-in Objects + + Unless otherwise specified, the length property of a built-in + Function object has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: true }. +features: [iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator.prototype.forEach, 'length', { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/name.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/name.js new file mode 100644 index 0000000000..caeae259e0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/name.js @@ -0,0 +1,32 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.forEach +description: > + The "name" property of Iterator.prototype.forEach +info: | + 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. + + ... + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +features: [iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator.prototype.forEach, 'name', { + value: 'forEach', + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/next-method-returns-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/next-method-returns-non-object.js new file mode 100644 index 0000000000..297adffeab --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/next-method-returns-non-object.js @@ -0,0 +1,26 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.forEach +description: > + Underlying iterator next returns non-object +info: | + %Iterator.prototype%.forEach ( fn ) + +features: [iterator-helpers] +flags: [] +---*/ +class NonObjectIterator extends Iterator { + next() { + return null; + } +} + +let iterator = new NonObjectIterator(); + +assert.throws(TypeError, function () { + iterator.forEach(() => {}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/next-method-returns-throwing-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/next-method-returns-throwing-done.js new file mode 100644 index 0000000000..adec874a7c --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/next-method-returns-throwing-done.js @@ -0,0 +1,34 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.forEach +description: > + Underlying iterator next returns object with throwing done getter +info: | + %Iterator.prototype%.forEach ( fn ) + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + return { + get done() { + throw new Test262Error(); + }, + value: 1, + }; + } + return() { + throw new Error(); + } +} + +let iterator = new ThrowingIterator(); + +assert.throws(Test262Error, function () { + iterator.forEach(() => {}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/next-method-returns-throwing-value-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/next-method-returns-throwing-value-done.js new file mode 100644 index 0000000000..403e03ae5d --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/next-method-returns-throwing-value-done.js @@ -0,0 +1,31 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.forEach +description: > + Underlying iterator next returns object with throwing value getter, but is already done +info: | + %Iterator.prototype%.forEach ( fn ) + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + return { + done: true, + get value() { + throw new Test262Error(); + }, + }; + } + return() { + throw new Error(); + } +} + +let iterator = new ThrowingIterator(); +iterator.forEach(() => {}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/next-method-returns-throwing-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/next-method-returns-throwing-value.js new file mode 100644 index 0000000000..07d3061bdc --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/next-method-returns-throwing-value.js @@ -0,0 +1,34 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.forEach +description: > + Underlying iterator next returns object with throwing value getter +info: | + %Iterator.prototype%.forEach ( fn ) + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + return { + done: false, + get value() { + throw new Test262Error(); + }, + }; + } + return() { + throw new Error(); + } +} + +let iterator = new ThrowingIterator(); + +assert.throws(Test262Error, function () { + iterator.forEach(() => {}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/next-method-throws.js new file mode 100644 index 0000000000..1b77529403 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/next-method-throws.js @@ -0,0 +1,26 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.forEach +description: > + Underlying iterator has throwing next method +info: | + %Iterator.prototype%.forEach ( fn ) + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + throw new Test262Error(); + } +} + +let iterator = new ThrowingIterator(); + +assert.throws(Test262Error, function () { + iterator.forEach(() => {}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/non-callable-predicate.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/non-callable-predicate.js new file mode 100644 index 0000000000..e8bf741cc9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/non-callable-predicate.js @@ -0,0 +1,23 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.forEach +description: > + Iterator.prototype.forEach expects to be called with a callable argument. +info: | + %Iterator.prototype%.forEach ( fn ) + +features: [iterator-helpers] +flags: [] +---*/ +let nonCallable = {}; +let iterator = (function* () { + yield 1; +})(); + +assert.throws(TypeError, function () { + iterator.forEach(nonCallable); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/non-constructible.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/non-constructible.js new file mode 100644 index 0000000000..358b73aca3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/non-constructible.js @@ -0,0 +1,31 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.forEach +description: > + Iterator.prototype.forEach is not constructible. + + 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. +features: [iterator-helpers] +---*/ +function* g() {} +let iter = g(); + +assert.throws(TypeError, () => { + new iter.forEach(); +}); + +assert.throws(TypeError, () => { + new iter.forEach(() => {}); +}); + +assert.throws(TypeError, () => { + new Iterator.prototype.forEach(() => {}); +}); + +assert.throws(TypeError, () => { + new class extends Iterator {}.forEach(() => {}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/prop-desc.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/prop-desc.js new file mode 100644 index 0000000000..0d3089f8d1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/prop-desc.js @@ -0,0 +1,28 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.forEach +description: > + Property descriptor of Iterator.prototype.forEach +info: | + Iterator.prototype.forEach + + * is the initial value of the Iterator.prototype.forEach property of the global object. + + 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. +features: [globalThis, iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator.prototype, 'forEach', { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/proto.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/proto.js new file mode 100644 index 0000000000..710a20e865 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/proto.js @@ -0,0 +1,14 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.forEach +description: > + The value of the [[Prototype]] internal slot of Iterator.prototype.forEach is the + intrinsic object %Function%. +features: [iterator-helpers] +---*/ + +assert.sameValue(Object.getPrototypeOf(Iterator.prototype.forEach), Function.prototype); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/result-is-undefined.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/result-is-undefined.js new file mode 100644 index 0000000000..4e4362e44a --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/result-is-undefined.js @@ -0,0 +1,21 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.forEach +description: > + Iterator.prototype.forEach returns undefined +features: [iterator-helpers] +---*/ +function* g() {} +let iter = g(); +assert.sameValue( + iter.forEach(() => {}), + undefined +); +assert.sameValue( + iter.forEach(() => 0), + undefined +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/shell.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/shell.js diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/this-non-callable-next.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/this-non-callable-next.js new file mode 100644 index 0000000000..e91c710e9a --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/this-non-callable-next.js @@ -0,0 +1,18 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.forEach +description: > + Iterator.prototype.forEach throws TypeError when its this value is an object with a non-callable next +info: | + %Iterator.prototype%.forEach ( fn ) + +features: [iterator-helpers] +flags: [] +---*/ +assert.throws(TypeError, function () { + Iterator.prototype.forEach.call({ next: 0 }, () => true); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/this-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/this-non-object.js new file mode 100644 index 0000000000..1573a6b221 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/this-non-object.js @@ -0,0 +1,27 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.forEach +description: > + Iterator.prototype.forEach throws TypeError when its this value is a non-object +info: | + %Iterator.prototype%.forEach ( fn ) + +features: [iterator-helpers] +flags: [] +---*/ +assert.throws(TypeError, function () { + Iterator.prototype.forEach.call(null, () => {}); +}); + +Object.defineProperty(Number.prototype, 'next', { + get: function () { + throw new Test262Error(); + }, +}); +assert.throws(TypeError, function () { + Iterator.prototype.forEach.call(0, () => {}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/forEach/this-plain-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/this-plain-iterator.js new file mode 100644 index 0000000000..0f60504d28 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/forEach/this-plain-iterator.js @@ -0,0 +1,32 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.forEach +description: > + Iterator.prototype.forEach supports a this value that does not inherit from Iterator.prototype but implements the iterator protocol +info: | + %Iterator.prototype%.forEach ( fn ) + +features: [iterator-helpers] +flags: [] +---*/ +let iter = { + get next() { + let count = 3; + return function () { + --count; + return count >= 0 ? { done: false, value: count } : { done: true, value: undefined }; + }; + }, +}; + +let fnCalls = 0; +let result = Iterator.prototype.forEach.call(iter, function (v) { + ++fnCalls; +}); + +assert.sameValue(result, undefined); +assert.sameValue(fnCalls, 3); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/initial-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/initial-value.js new file mode 100644 index 0000000000..dc1113a721 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/initial-value.js @@ -0,0 +1,26 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-iterator.prototype +description: > + The initial value of Iterator.prototype is %Iterator.prototype%. +info: | + Iterator.prototype + + The initial value of Iterator.prototype is %Iterator.prototype%. + + This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }. +features: [iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator, 'prototype', { + value: Iterator.prototype, + writable: false, + enumerable: false, + configurable: false, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/argument-effect-order.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/argument-effect-order.js new file mode 100644 index 0000000000..fef19280d8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/argument-effect-order.js @@ -0,0 +1,45 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.map +description: > + Arguments and this value are evaluated in the correct order +info: | + %Iterator.prototype%.map ( mapper ) + + 1. Let O be the this value. + 2. If O is not an Object, throw a TypeError exception. + 3. If IsCallable(mapper) is false, throw a TypeError exception. + 4. Let iterated be ? GetIteratorDirect(O). + +includes: [compareArray.js] +features: [iterator-helpers] +flags: [] +---*/ +let effects = []; + +assert.throws(TypeError, function () { + Iterator.prototype.map.call( + { + get next() { + effects.push('get next'); + return function () { + return { done: true, value: undefined }; + }; + }, + }, + { + valueOf() { + effects.push('valueOf mapper'); + return function () { + return []; + }; + }, + } + ); +}); + +assert.compareArray(effects, []); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/browser.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/browser.js diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/callable.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/callable.js new file mode 100644 index 0000000000..57ebb543d3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/callable.js @@ -0,0 +1,16 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.map +description: > + Iterator.prototype.map is callable +features: [iterator-helpers] +---*/ +function* g() {} +Iterator.prototype.map.call(g(), () => 0); + +let iter = g(); +iter.map(() => 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/exhaustion-does-not-call-return.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/exhaustion-does-not-call-return.js new file mode 100644 index 0000000000..025da41336 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/exhaustion-does-not-call-return.js @@ -0,0 +1,37 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.map +description: > + Underlying iterator return is not called when result iterator is exhausted +info: | + %Iterator.prototype%.map ( mapper ) + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield 0; + yield 1; + yield 2; +} + +class TestIterator extends Iterator { + get next() { + let n = g(); + return function() { + return n.next(); + }; + } + return() { + throw new Test262Error(); + } +} + +let iterator = new TestIterator().map(() => 0); +iterator.next(); +iterator.next(); +iterator.next(); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/get-next-method-only-once.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/get-next-method-only-once.js new file mode 100644 index 0000000000..16b7c7331b --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/get-next-method-only-once.js @@ -0,0 +1,44 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.map +description: > + Gets the next method from the underlying iterator only once +info: | + %Iterator.prototype%.map ( mapper ) + + 4. Let iterated be ? GetIteratorDirect(O). + +features: [iterator-helpers] +flags: [] +---*/ +let nextGets = 0; +let nextCalls = 0; + +class CountingIterator extends Iterator { + get next() { + ++nextGets; + let iter = (function* () { + for (let i = 1; i < 5; ++i) { + yield i; + } + })(); + return function () { + ++nextCalls; + return iter.next(); + }; + } +} + +let iterator = new CountingIterator(); + +assert.sameValue(nextGets, 0); +assert.sameValue(nextCalls, 0); + +for (const value of iterator.map(() => 0)); + +assert.sameValue(nextGets, 1); +assert.sameValue(nextCalls, 5); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/get-next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/get-next-method-throws.js new file mode 100644 index 0000000000..6a804093fa --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/get-next-method-throws.js @@ -0,0 +1,28 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.map +description: > + Underlying iterator has throwing next getter +info: | + %Iterator.prototype%.map ( mapper ) + + 4. Let iterated be ? GetIteratorDirect(O). + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + get next() { + throw new Test262Error(); + } +} + +let iterator = new ThrowingIterator(); + +assert.throws(Test262Error, function () { + iterator.map(() => 0); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/get-return-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/get-return-method-throws.js new file mode 100644 index 0000000000..15aa7219d1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/get-return-method-throws.js @@ -0,0 +1,33 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.map +description: > + Underlying iterator return is throwing getter +info: | + %Iterator.prototype%.map ( mapper ) + +features: [iterator-helpers] +flags: [] +---*/ +class TestIterator extends Iterator { + next() { + return { + done: false, + value: 1, + }; + } + get return() { + throw new Test262Error(); + } +} + +let iterator = new TestIterator().map(() => 0); +iterator.next(); + +assert.throws(Test262Error, function () { + iterator.return(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/is-function.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/is-function.js new file mode 100644 index 0000000000..428a20c4c2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/is-function.js @@ -0,0 +1,13 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.map +description: > + Iterator.prototype.map is a built-in function +features: [iterator-helpers] +---*/ + +assert.sameValue(typeof Iterator.prototype.map, 'function'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/iterator-already-exhausted.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/iterator-already-exhausted.js new file mode 100644 index 0000000000..2f75050173 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/iterator-already-exhausted.js @@ -0,0 +1,25 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.map +description: > + Iterator.prototype.map returns an empty iterator when the iterator has already been exhausted +info: | + %Iterator.prototype%.map ( mapper ) + +features: [iterator-helpers] +flags: [] +---*/ +let iterator = (function* () {})(); + +let { value, done } = iterator.next(); +assert.sameValue(value, undefined); +assert.sameValue(done, true); + +iterator = iterator.map(() => 0); +({ value, done } = iterator.next()); +assert.sameValue(value, undefined); +assert.sameValue(done, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/iterator-return-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/iterator-return-method-throws.js new file mode 100644 index 0000000000..d81031c2a4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/iterator-return-method-throws.js @@ -0,0 +1,32 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.map +description: > + Iterator has throwing return +info: | + %Iterator.prototype%.map ( mapper ) + +features: [iterator-helpers] +flags: [] +---*/ +class IteratorThrows extends Iterator { + next() { + return { + done: false, + value: 0, + }; + } + return() { + throw new Test262Error(); + } +} + +let iterator = new IteratorThrows().map(() => 0); + +assert.throws(Test262Error, function () { + iterator.return(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/length.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/length.js new file mode 100644 index 0000000000..d11d3330e0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/length.js @@ -0,0 +1,25 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.map +description: > + Iterator.prototype.map has a "length" property whose value is 1. +info: | + ECMAScript Standard Built-in Objects + + Unless otherwise specified, the length property of a built-in + Function object has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: true }. +features: [iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator.prototype.map, 'length', { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/mapper-args.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/mapper-args.js new file mode 100644 index 0000000000..132fcdeeee --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/mapper-args.js @@ -0,0 +1,58 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.map +description: > + Iterator.prototype.map mapper is passed the yielded value and a counter as arguments +info: | + %Iterator.prototype%.map ( mapper ) + + 5.b.iv. Let mapped be Completion(Call(mapper, undefined, « value, 𝔽(counter) »)). + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield 'a'; + yield 'b'; + yield 'c'; + yield 'd'; + yield 'e'; +} + +let assertionCount = 0; +let iter = g().map((v, count) => { + switch (v) { + case 'a': + assert.sameValue(count, 0); + ++assertionCount; + return 0; + case 'b': + assert.sameValue(count, 1); + ++assertionCount; + return 1; + case 'c': + assert.sameValue(count, 2); + ++assertionCount; + return 2; + case 'd': + assert.sameValue(count, 3); + ++assertionCount; + return 3; + case 'e': + assert.sameValue(count, 4); + ++assertionCount; + return 4; + default: + throw new Error(); + } +}); + +assert.sameValue(assertionCount, 0); + +for (let i of iter); + +assert.sameValue(assertionCount, 5); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/mapper-this.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/mapper-this.js new file mode 100644 index 0000000000..5c7ac20423 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/mapper-this.js @@ -0,0 +1,36 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.map +description: > + Iterator.prototype.map mapper this value is undefined +info: | + %Iterator.prototype%.map ( mapper ) + + 5.b.iv. Let mapped be Completion(Call(mapper, undefined, « value, 𝔽(counter) »)). + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield 0; +} + +let iter = g(); + +let expectedThis = function () { + return this; +}.call(undefined); + +let assertionCount = 0; +iter = iter.map(function (v, count) { + assert.sameValue(this, expectedThis); + ++assertionCount; + return v; +}); + +iter.next(); +assert.sameValue(assertionCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/mapper-throws-then-closing-iterator-also-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/mapper-throws-then-closing-iterator-also-throws.js new file mode 100644 index 0000000000..22cb2cb78f --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/mapper-throws-then-closing-iterator-also-throws.js @@ -0,0 +1,43 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.map +description: > + Attempts to close iterator when mapper throws, but that throws +info: | + %Iterator.prototype%.map ( mapper ) + + 5.b.v. IfAbruptCloseIterator(mapped, iterated). + +features: [iterator-helpers] +flags: [] +---*/ +let returnCalls = 0; + +class TestIterator extends Iterator { + next() { + return { + done: false, + value: 1, + }; + } + return() { + ++returnCalls; + throw new Error(); + } +} + +let iterator = new TestIterator().map(() => { + throw new Test262Error(); +}); + +assert.sameValue(returnCalls, 0); + +assert.throws(Test262Error, function () { + iterator.next(); +}); + +assert.sameValue(returnCalls, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/mapper-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/mapper-throws.js new file mode 100644 index 0000000000..0a7eb400bd --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/mapper-throws.js @@ -0,0 +1,44 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.map +description: > + Closes iterator and throws when mapper throws +info: | + %Iterator.prototype%.map ( mapper ) + + 5.b.v. IfAbruptCloseIterator(mapped, iterated). + +features: [iterator-helpers] +flags: [] +---*/ +let returnCalls = 0; + +class TestIterator extends Iterator { + next() { + return { + done: false, + value: 1, + }; + } + return() { + ++returnCalls; + return {}; + } +} + +let callbackCalls = 0; +let iterator = new TestIterator().map(() => { + ++callbackCalls; + throw new Test262Error(); +}); + +assert.throws(Test262Error, function () { + iterator.next(); +}); + +assert.sameValue(callbackCalls, 1); +assert.sameValue(returnCalls, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/name.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/name.js new file mode 100644 index 0000000000..e48bada845 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/name.js @@ -0,0 +1,32 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.map +description: > + The "name" property of Iterator.prototype.map +info: | + 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. + + ... + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +features: [iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator.prototype.map, 'name', { + value: 'map', + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/next-method-returns-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/next-method-returns-non-object.js new file mode 100644 index 0000000000..f4404b5bae --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/next-method-returns-non-object.js @@ -0,0 +1,26 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.map +description: > + Underlying iterator next returns non-object +info: | + %Iterator.prototype%.map ( mapper ) + +features: [iterator-helpers] +flags: [] +---*/ +class NonObjectIterator extends Iterator { + next() { + return null; + } +} + +let iterator = new NonObjectIterator().map(() => 0); + +assert.throws(TypeError, function () { + iterator.next(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/next-method-returns-throwing-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/next-method-returns-throwing-done.js new file mode 100644 index 0000000000..2bb236050c --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/next-method-returns-throwing-done.js @@ -0,0 +1,34 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.map +description: > + Underlying iterator next returns object with throwing done getter +info: | + %Iterator.prototype%.map ( mapper ) + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + return { + get done() { + throw new Test262Error(); + }, + value: 1, + }; + } + return() { + throw new Error(); + } +} + +let iterator = new ThrowingIterator().map(() => 0); + +assert.throws(Test262Error, function () { + iterator.next(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/next-method-returns-throwing-value-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/next-method-returns-throwing-value-done.js new file mode 100644 index 0000000000..017fa210b6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/next-method-returns-throwing-value-done.js @@ -0,0 +1,31 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.map +description: > + Underlying iterator next returns object with throwing value getter, but is already done +info: | + %Iterator.prototype%.map ( mapper ) + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + return { + done: true, + get value() { + throw new Test262Error(); + }, + }; + } + return() { + throw new Error(); + } +} + +let iterator = new ThrowingIterator().map(() => 0); +iterator.next(); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/next-method-returns-throwing-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/next-method-returns-throwing-value.js new file mode 100644 index 0000000000..50208c73ed --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/next-method-returns-throwing-value.js @@ -0,0 +1,34 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.map +description: > + Underlying iterator next returns object with throwing value getter +info: | + %Iterator.prototype%.map ( mapper ) + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + return { + done: false, + get value() { + throw new Test262Error(); + }, + }; + } + return() { + throw new Error(); + } +} + +let iterator = new ThrowingIterator().map(() => 0); + +assert.throws(Test262Error, function () { + iterator.next(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/next-method-throws.js new file mode 100644 index 0000000000..52ad97d16d --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/next-method-throws.js @@ -0,0 +1,26 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.map +description: > + Underlying iterator has throwing next method +info: | + %Iterator.prototype%.map ( mapper ) + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + throw new Test262Error(); + } +} + +let iterator = new ThrowingIterator().map(() => 0); + +assert.throws(Test262Error, function () { + iterator.next(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/non-callable-mapper.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/non-callable-mapper.js new file mode 100644 index 0000000000..14e05228be --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/non-callable-mapper.js @@ -0,0 +1,23 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.map +description: > + Iterator.prototype.map expects to be called with a callable argument. +info: | + %Iterator.prototype%.map ( mapper ) + + 3. If IsCallable(mapper) is false, throw a TypeError exception. + +features: [iterator-helpers] +flags: [] +---*/ +let nonCallable = {}; +let iterator = (function* () {})(); + +assert.throws(TypeError, function () { + iterator.map(nonCallable); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/non-constructible.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/non-constructible.js new file mode 100644 index 0000000000..5bf482766c --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/non-constructible.js @@ -0,0 +1,31 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.map +description: > + Iterator.prototype.map is not constructible. + + 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. +features: [iterator-helpers] +---*/ +function* g() {} +let iter = g(); + +assert.throws(TypeError, () => { + new iter.map(); +}); + +assert.throws(TypeError, () => { + new iter.map(() => 0); +}); + +assert.throws(TypeError, () => { + new Iterator.prototype.map(() => 0); +}); + +assert.throws(TypeError, () => { + new class extends Iterator {}.map(() => 0); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/prop-desc.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/prop-desc.js new file mode 100644 index 0000000000..f321f9ba5a --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/prop-desc.js @@ -0,0 +1,28 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.map +description: > + Property descriptor of Iterator.prototype.map +info: | + Iterator.prototype.map + + * is the initial value of the Iterator.prototype.map property of the global object. + + 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. +features: [globalThis, iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator.prototype, 'map', { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/proto.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/proto.js new file mode 100644 index 0000000000..1e8cf63822 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/proto.js @@ -0,0 +1,14 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.map +description: > + The value of the [[Prototype]] internal slot of Iterator.prototype.map is the + intrinsic object %FunctionPrototype%. +features: [iterator-helpers] +---*/ + +assert.sameValue(Object.getPrototypeOf(Iterator.prototype.map), Function.prototype); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/result-is-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/result-is-iterator.js new file mode 100644 index 0000000000..c4aea92b89 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/result-is-iterator.js @@ -0,0 +1,14 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.map +description: > + The value of the [[Prototype]] internal slot of the return value of Iterator.prototype.map is the + intrinsic object %IteratorHelperPrototype%. +features: [iterator-helpers] +---*/ + +assert((function* () {})().map(() => 0) instanceof Iterator, 'function*(){}().map(() => 0) must return an Iterator'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/return-is-forwarded-to-underlying-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/return-is-forwarded-to-underlying-iterator.js new file mode 100644 index 0000000000..3e1cab2d40 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/return-is-forwarded-to-underlying-iterator.js @@ -0,0 +1,36 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.map +description: > + Underlying iterator return is called when result iterator is closed +info: | + %Iterator.prototype%.map ( mapper ) + +features: [iterator-helpers] +flags: [] +---*/ +let returnCount = 0; + +class TestIterator extends Iterator { + next() { + return { + done: false, + value: 1, + }; + } + return() { + ++returnCount; + return {}; + } +} + +let iterator = new TestIterator().map(() => 0); +assert.sameValue(returnCount, 0); +iterator.return(); +assert.sameValue(returnCount, 1); +iterator.return(); +assert.sameValue(returnCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/return-is-not-forwarded-after-exhaustion.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/return-is-not-forwarded-after-exhaustion.js new file mode 100644 index 0000000000..4b22864b33 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/return-is-not-forwarded-after-exhaustion.js @@ -0,0 +1,49 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.map +description: > + Underlying iterator return is not called after result iterator observes that underlying iterator is exhausted +info: | + %Iterator.prototype%.map ( mapper ) + +features: [iterator-helpers] +flags: [] +---*/ +let returnCount = 0; + +class TestIterator extends Iterator { + next() { + return { + done: true, + value: undefined, + }; + } + return() { + throw new Test262Error(); + } +} + +let iterator = new TestIterator().map(() => 0); +assert.throws(Test262Error, function () { + iterator.return(); +}); +iterator.next(); +iterator.return(); + +iterator = new TestIterator().map(() => 0); +iterator.next(); +iterator.return(); + +iterator = new TestIterator() + .map(x => x) + .map(x => x) + .map(x => x); +assert.throws(Test262Error, function () { + iterator.return(); +}); +iterator.next(); +iterator.return(); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/returned-iterator-yields-mapper-return-values.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/returned-iterator-yields-mapper-return-values.js new file mode 100644 index 0000000000..f999fd80a0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/returned-iterator-yields-mapper-return-values.js @@ -0,0 +1,39 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.map +description: > + The values returned by the mapper are the values that are yielded by the iterator returned by map +info: | + %Iterator.prototype%.map ( mapper ) + + 5.b.vi. Let completion be Completion(Yield(mapped)). + +includes: [compareArray.js] +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + for (let i = 0; i < 5; ++i) { + yield i; + } +} + +assert.compareArray(Array.from(g()), [0, 1, 2, 3, 4]); +assert.compareArray(Array.from(g().map(x => x)), [0, 1, 2, 3, 4]); +assert.compareArray(Array.from(g().map(() => 0)), [0, 0, 0, 0, 0]); +assert.compareArray( + Array.from( + g() + .map(() => 0) + .map((v, c) => c) + ), + [0, 1, 2, 3, 4] +); +assert.compareArray(Array.from(g().map(x => x * 2)), [0, 2, 4, 6, 8]); + +let obj = {}; +assert.compareArray(Array.from(g().map(() => obj)), [obj, obj, obj, obj, obj]); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/shell.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/shell.js diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/this-non-callable-next.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/this-non-callable-next.js new file mode 100644 index 0000000000..fe58985b32 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/this-non-callable-next.js @@ -0,0 +1,20 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.map +description: > + Iterator.prototype.map throws TypeError when its this value is an object with a non-callable next +info: | + %Iterator.prototype%.map ( mapper ) + +features: [iterator-helpers] +flags: [] +---*/ +let iter = Iterator.prototype.map.call({ next: 0 }, () => 0); + +assert.throws(TypeError, function () { + iter.next(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/this-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/this-non-object.js new file mode 100644 index 0000000000..cc8ab9ea47 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/this-non-object.js @@ -0,0 +1,29 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.map +description: > + Iterator.prototype.map throws TypeError when its this value is a non-object +info: | + %Iterator.prototype%.map ( mapper ) + + 2. If O is not an Object, throw a TypeError exception. + +features: [iterator-helpers] +flags: [] +---*/ +assert.throws(TypeError, function () { + Iterator.prototype.map.call(null, () => 0); +}); + +Object.defineProperty(Number.prototype, 'next', { + get: function () { + throw new Test262Error(); + }, +}); +assert.throws(TypeError, function () { + Iterator.prototype.map.call(0, () => 0); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/this-plain-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/this-plain-iterator.js new file mode 100644 index 0000000000..8a243a9889 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/this-plain-iterator.js @@ -0,0 +1,34 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.map +description: > + Iterator.prototype.map supports a this value that does not inherit from Iterator.prototype but implements the iterator protocol +info: | + %Iterator.prototype%.map ( mapper ) + +features: [iterator-helpers] +flags: [] +---*/ +let iter = { + get next() { + let count = 3; + return function () { + --count; + return count >= 0 ? { done: false, value: count } : { done: true, value: undefined }; + }; + }, +}; + +let mapperCalls = 0; +iter = Iterator.prototype.map.call(iter, function (v) { + ++mapperCalls; + return v; +}); + +for (let e of iter); + +assert.sameValue(mapperCalls, 3); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/throws-typeerror-when-generator-is-running.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/throws-typeerror-when-generator-is-running.js new file mode 100644 index 0000000000..a288c7f0ba --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/throws-typeerror-when-generator-is-running.js @@ -0,0 +1,49 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.map +description: > + Throws a TypeError when the closure generator is already running. +info: | + %IteratorHelperPrototype%.next ( ) + 1. Return ? GeneratorResume(this value, undefined, "Iterator Helper"). + + 27.5.3.3 GeneratorResume ( generator, value, generatorBrand ) + 1. Let state be ? GeneratorValidate(generator, generatorBrand). + ... + + 27.5.3.2 GeneratorValidate ( generator, generatorBrand ) + ... + 6. If state is executing, throw a TypeError exception. + ... + +features: [iterator-helpers] +---*/ + +var loopCount = 0; + +function* g() { + while (true) { + loopCount++; + yield; + } +} + +var enterCount = 0; + +function mapper() { + enterCount++; + iter.next(); +} + +var iter = g().map(mapper); + +assert.throws(TypeError, function() { + iter.next(); +}); + +assert.sameValue(loopCount, 1); +assert.sameValue(enterCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/underlying-iterator-advanced-in-parallel.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/underlying-iterator-advanced-in-parallel.js new file mode 100644 index 0000000000..e54d75fab1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/underlying-iterator-advanced-in-parallel.js @@ -0,0 +1,45 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.map +description: > + Underlying iterator is advanced after calling map +info: | + %Iterator.prototype%.map ( mapper ) + +features: [iterator-helpers] +flags: [] +---*/ +let iterator = (function* () { + for (let i = 0; i < 5; ++i) { + yield i; + } +})(); + +let mapped = iterator.map(x => x); + +let { value, done } = iterator.next(); + +assert.sameValue(value, 0); +assert.sameValue(done, false); + +iterator.next(); +iterator.next(); + +({ value, done } = mapped.next()); + +assert.sameValue(value, 3); +assert.sameValue(done, false); + +({ value, done } = mapped.next()); + +assert.sameValue(value, 4); +assert.sameValue(done, false); + +({ value, done } = mapped.next()); + +assert.sameValue(value, undefined); +assert.sameValue(done, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/underlying-iterator-closed-in-parallel.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/underlying-iterator-closed-in-parallel.js new file mode 100644 index 0000000000..090abaaaea --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/underlying-iterator-closed-in-parallel.js @@ -0,0 +1,29 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.map +description: > + Underlying iterator is closed after calling map +info: | + %Iterator.prototype%.map ( mapper ) + +features: [iterator-helpers] +flags: [] +---*/ +let iterator = (function* () { + for (let i = 0; i < 5; ++i) { + yield i; + } +})(); + +let mapped = iterator.map(() => 0); + +iterator.return(); + +let { value, done } = mapped.next(); + +assert.sameValue(value, undefined); +assert.sameValue(done, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/map/underlying-iterator-closed.js b/js/src/tests/test262/built-ins/Iterator/prototype/map/underlying-iterator-closed.js new file mode 100644 index 0000000000..478903700d --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/map/underlying-iterator-closed.js @@ -0,0 +1,29 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.map +description: > + Underlying iterator is closed before calling map +info: | + %Iterator.prototype%.map ( mapper ) + +features: [iterator-helpers] +flags: [] +---*/ +let iterator = (function* () { + for (let i = 0; i < 5; ++i) { + yield i; + } +})(); + +iterator.return(); + +let mapped = iterator.map(() => 0); + +let { value, done } = mapped.next(); + +assert.sameValue(value, undefined); +assert.sameValue(done, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/argument-effect-order.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/argument-effect-order.js new file mode 100644 index 0000000000..1f66e7c18a --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/argument-effect-order.js @@ -0,0 +1,61 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.reduce +description: > + Arguments and this value are evaluated in the correct order +info: | + %Iterator.prototype%.reduce ( reducer ) + +includes: [compareArray.js] +features: [iterator-helpers] +flags: [] +---*/ +let effects = []; + +assert.throws(TypeError, function () { + Iterator.prototype.reduce.call( + { + get next() { + effects.push('get next'); + return function () { + return { done: true, value: undefined }; + }; + }, + }, + { + valueOf() { + effects.push('reducer valueOf'); + } + }, + { + valueOf() { + effects.push('initial value valueOf'); + } + } + ); +}); + +assert.compareArray(effects, []); + +Iterator.prototype.reduce.call( + { + get next() { + effects.push('get next'); + return function () { + return { done: true, value: undefined }; + }; + }, + }, + () => {}, + { + valueOf() { + effects.push('initial value valueOf'); + } + } +); + +assert.compareArray(effects, ['get next']); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/browser.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/browser.js diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/callable.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/callable.js new file mode 100644 index 0000000000..ce5ecf8bbe --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/callable.js @@ -0,0 +1,16 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.reduce +description: > + Iterator.prototype.reduce is callable +features: [iterator-helpers] +---*/ +function* g() {} +Iterator.prototype.reduce.call(g(), () => {}, 0); + +let iter = g(); +iter.reduce(() => {}, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/get-next-method-only-once.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/get-next-method-only-once.js new file mode 100644 index 0000000000..016eebf94c --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/get-next-method-only-once.js @@ -0,0 +1,39 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.reduce +description: > + Gets the next method from the iterator only once +info: | + %Iterator.prototype%.reduce ( reducer ) + +features: [iterator-helpers] +flags: [] +---*/ +let nextGets = 0; + +class TestIterator extends Iterator { + get next() { + ++nextGets; + let counter = 5; + return function () { + if (counter <= 0) { + return { done: true, value: undefined }; + } else { + return { done: false, value: --counter }; + } + }; + } +} + +let iterator = new TestIterator(); + +assert.sameValue(nextGets, 0); +assert.sameValue( + iterator.reduce(x => x), + 4 +); +assert.sameValue(nextGets, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/get-next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/get-next-method-throws.js new file mode 100644 index 0000000000..579e567b9b --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/get-next-method-throws.js @@ -0,0 +1,26 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.reduce +description: > + Iterator has throwing next getter +info: | + %Iterator.prototype%.reduce ( reducer ) + +features: [iterator-helpers] +flags: [] +---*/ +class IteratorThrows extends Iterator { + get next() { + throw new Test262Error(); + } +} + +let iterator = new IteratorThrows(); + +assert.throws(Test262Error, function () { + iterator.reduce(() => {}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/is-function.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/is-function.js new file mode 100644 index 0000000000..9c79a4c3ab --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/is-function.js @@ -0,0 +1,13 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.reduce +description: > + Iterator.prototype.reduce is a built-in function +features: [iterator-helpers] +---*/ + +assert.sameValue(typeof Iterator.prototype.reduce, 'function'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/iterator-already-exhausted-initial-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/iterator-already-exhausted-initial-value.js new file mode 100644 index 0000000000..1d2b64374b --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/iterator-already-exhausted-initial-value.js @@ -0,0 +1,24 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.reduce +description: > + Iterator.prototype.reduce returns the initial value when the iterator has already been exhausted +info: | + %Iterator.prototype%.reduce ( reducer ) + +features: [iterator-helpers] +flags: [] +---*/ +let iterator = (function* () {})(); + +let { value, done } = iterator.next(); +assert.sameValue(value, undefined); +assert.sameValue(done, true); + +const initialValue = {}; +let result = iterator.reduce(() => {}, initialValue); +assert.sameValue(result, initialValue); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/iterator-already-exhausted-no-initial-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/iterator-already-exhausted-no-initial-value.js new file mode 100644 index 0000000000..28b2910f92 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/iterator-already-exhausted-no-initial-value.js @@ -0,0 +1,26 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.reduce +description: > + Iterator.prototype.reduce without an initial value throws when the iterator has already been exhausted +info: | + %Iterator.prototype%.reduce ( reducer ) + +features: [iterator-helpers] +flags: [] +---*/ +let iterator = (function* () {})(); + +let { value, done } = iterator.next(); +assert.sameValue(value, undefined); +assert.sameValue(done, true); + +assert.throws(TypeError, function() { + iterator.reduce(() => {}); +}); + +iterator.reduce(() => {}, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/iterator-yields-once-initial-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/iterator-yields-once-initial-value.js new file mode 100644 index 0000000000..cdaaaf409b --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/iterator-yields-once-initial-value.js @@ -0,0 +1,38 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.reduce +description: > + Iterator.prototype.reduce calls reducer once for each value yielded by the underlying iterator when passed an initial value +info: | + %Iterator.prototype%.reduce ( reducer ) + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield 'a'; +} + +let iter = g(); + +let assertionCount = 0; +let initialValue = {}; +let result = iter.reduce((memo, v, count) => { + switch (v) { + case 'a': + assert.sameValue(memo, initialValue); + assert.sameValue(count, 0); + break; + default: + throw new Error(); + } + ++assertionCount; + return v; +}, initialValue); + +assert.sameValue(result, 'a'); +assert.sameValue(assertionCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/iterator-yields-once-no-initial-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/iterator-yields-once-no-initial-value.js new file mode 100644 index 0000000000..d71a781737 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/iterator-yields-once-no-initial-value.js @@ -0,0 +1,29 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.reduce +description: > + Iterator.prototype.reduce calls reducer once for each value yielded by the underlying iterator except the first when not passed an initial value +info: | + %Iterator.prototype%.reduce ( reducer ) + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield 'a'; +} + +let iter = g(); + +let assertionCount = 0; +let result = iter.reduce((memo, v, count) => { + ++assertionCount; + return v; +}); + +assert.sameValue(result, 'a'); +assert.sameValue(assertionCount, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/length.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/length.js new file mode 100644 index 0000000000..5e1d35d57a --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/length.js @@ -0,0 +1,25 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.reduce +description: > + Iterator.prototype.reduce has a "length" property whose value is 1. +info: | + ECMAScript Standard Built-in Objects + + Unless otherwise specified, the length property of a built-in + Function object has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: true }. +features: [iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator.prototype.reduce, 'length', { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/name.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/name.js new file mode 100644 index 0000000000..3af38b0ea9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/name.js @@ -0,0 +1,32 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.reduce +description: > + The "name" property of Iterator.prototype.reduce +info: | + 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. + + ... + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +features: [iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator.prototype.reduce, 'name', { + value: 'reduce', + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/next-method-returns-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/next-method-returns-non-object.js new file mode 100644 index 0000000000..238a4cceff --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/next-method-returns-non-object.js @@ -0,0 +1,26 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.reduce +description: > + Underlying iterator next returns non-object +info: | + %Iterator.prototype%.reduce ( reducer ) + +features: [iterator-helpers] +flags: [] +---*/ +class NonObjectIterator extends Iterator { + next() { + return null; + } +} + +let iterator = new NonObjectIterator(); + +assert.throws(TypeError, function () { + iterator.reduce(() => {}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/next-method-returns-throwing-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/next-method-returns-throwing-done.js new file mode 100644 index 0000000000..e1dc0e0876 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/next-method-returns-throwing-done.js @@ -0,0 +1,34 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.reduce +description: > + Underlying iterator next returns object with throwing done getter +info: | + %Iterator.prototype%.reduce ( reducer ) + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + return { + get done() { + throw new Test262Error(); + }, + value: 1, + }; + } + return() { + throw new Error(); + } +} + +let iterator = new ThrowingIterator(); + +assert.throws(Test262Error, function () { + iterator.reduce(() => {}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/next-method-returns-throwing-value-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/next-method-returns-throwing-value-done.js new file mode 100644 index 0000000000..53c7984e64 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/next-method-returns-throwing-value-done.js @@ -0,0 +1,31 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.reduce +description: > + Underlying iterator next returns object with throwing value getter, but is already done +info: | + %Iterator.prototype%.reduce ( reducer ) + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + return { + done: true, + get value() { + throw new Test262Error(); + }, + }; + } + return() { + throw new Error(); + } +} + +let iterator = new ThrowingIterator(); +iterator.reduce(() => {}, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/next-method-returns-throwing-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/next-method-returns-throwing-value.js new file mode 100644 index 0000000000..7dd83c4881 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/next-method-returns-throwing-value.js @@ -0,0 +1,34 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.reduce +description: > + Underlying iterator next returns object with throwing value getter +info: | + %Iterator.prototype%.reduce ( reducer ) + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + return { + done: false, + get value() { + throw new Test262Error(); + }, + }; + } + return() { + throw new Error(); + } +} + +let iterator = new ThrowingIterator(); + +assert.throws(Test262Error, function () { + iterator.reduce(() => {}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/next-method-throws.js new file mode 100644 index 0000000000..6907971b8b --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/next-method-throws.js @@ -0,0 +1,30 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.reduce +description: > + Underlying iterator has throwing next method +info: | + %Iterator.prototype%.reduce ( reducer ) + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + throw new Test262Error(); + } +} + +let iterator = new ThrowingIterator(); + +assert.throws(Test262Error, function () { + iterator.reduce(() => {}); +}); + +assert.throws(Test262Error, function () { + iterator.reduce(() => {}, 0); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/non-callable-reducer.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/non-callable-reducer.js new file mode 100644 index 0000000000..424d97e44b --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/non-callable-reducer.js @@ -0,0 +1,25 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.reduce +description: > + Iterator.prototype.reduce expects to be called with a callable argument. +info: | + %Iterator.prototype%.reduce ( reducer ) + +features: [iterator-helpers] +flags: [] +---*/ +let nonCallable = {}; +let iterator = (function* () { + yield 1; +})(); + +assert.throws(TypeError, function () { + iterator.reduce(nonCallable); +}); + +iterator.reduce(() => {}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/non-constructible.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/non-constructible.js new file mode 100644 index 0000000000..cd3468b6f2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/non-constructible.js @@ -0,0 +1,35 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.reduce +description: > + Iterator.prototype.reduce is not constructible. + + 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. +features: [iterator-helpers] +---*/ +function* g() {} +let iter = g(); + +assert.throws(TypeError, () => { + new iter.reduce(); +}); + +assert.throws(TypeError, () => { + new iter.reduce(() => {}); +}); + +assert.throws(TypeError, () => { + new iter.reduce(() => {}, 0); +}); + +assert.throws(TypeError, () => { + new Iterator.prototype.reduce(() => {}, 0); +}); + +assert.throws(TypeError, () => { + new class extends Iterator {}.reduce(() => {}, 0); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/prop-desc.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/prop-desc.js new file mode 100644 index 0000000000..5578ba8ab5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/prop-desc.js @@ -0,0 +1,28 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.reduce +description: > + Property descriptor of Iterator.prototype.reduce +info: | + Iterator.prototype.reduce + + * is the initial value of the Iterator.prototype.reduce property of the global object. + + 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. +features: [globalThis, iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator.prototype, 'reduce', { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/proto.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/proto.js new file mode 100644 index 0000000000..218513991c --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/proto.js @@ -0,0 +1,14 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.reduce +description: > + The value of the [[Prototype]] internal slot of Iterator.prototype.reduce is the + intrinsic object %Function%. +features: [iterator-helpers] +---*/ + +assert.sameValue(Object.getPrototypeOf(Iterator.prototype.reduce), Function.prototype); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-args-initial-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-args-initial-value.js new file mode 100644 index 0000000000..316c32fc1d --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-args-initial-value.js @@ -0,0 +1,48 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.reduce +description: > + Iterator.prototype.reduce reducer is passed the yielded value and a counter as arguments +info: | + %Iterator.prototype%.reduce ( reducer ) + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield 'a'; + yield 'b'; + yield 'c'; +} + +let iter = g(); + +let assertionCount = 0; +let initialValue = {}; +let result = iter.reduce((memo, v, count) => { + switch (v) { + case 'a': + assert.sameValue(memo, initialValue); + assert.sameValue(count, 0); + break; + case 'b': + assert.sameValue(memo, 'a'); + assert.sameValue(count, 1); + break; + case 'c': + assert.sameValue(memo, 'b'); + assert.sameValue(count, 2); + break; + default: + throw new Error(); + } + ++assertionCount; + return v; +}, initialValue); + +assert.sameValue(result, 'c'); +assert.sameValue(assertionCount, 3); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-args-no-initial-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-args-no-initial-value.js new file mode 100644 index 0000000000..ac637391aa --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-args-no-initial-value.js @@ -0,0 +1,44 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.reduce +description: > + Iterator.prototype.reduce reducer is passed the yielded value and a counter as arguments +info: | + %Iterator.prototype%.reduce ( reducer ) + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield 'a'; + yield 'b'; + yield 'c'; +} + +let iter = g(); + +let assertionCount = 0; +let result = iter.reduce((memo, v, count) => { + switch (v) { + case 'b': + assert.sameValue(memo, 'a'); + assert.sameValue(count, 1); + break; + case 'c': + assert.sameValue(memo, 'b'); + assert.sameValue(count, 2); + break; + case 'a': + default: + throw new Error(); + } + ++assertionCount; + return v; +}); + +assert.sameValue(result, 'c'); +assert.sameValue(assertionCount, 2); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-memo-can-be-any-type.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-memo-can-be-any-type.js new file mode 100644 index 0000000000..8d2802f4de --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-memo-can-be-any-type.js @@ -0,0 +1,34 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.reduce +description: > + Iterator.prototype.reduce reducer can return any ECMAScript language value +info: | + %Iterator.prototype%.reduce ( reducer ) + +features: [iterator-helpers] +flags: [] +---*/ + +const values = [undefined, null, true, false, 0, -0, 1, NaN, Infinity, "string", Symbol(), 0n, {}, [], () => {}]; + +let iter = values[Symbol.iterator](); + +let assertionCount = 0; +let initialValue = {}; +let result = iter.reduce((memo, v, count) => { + if (count == 0) { + assert.sameValue(memo, initialValue); + } else { + assert.sameValue(memo, values[count - 1]); + } + ++assertionCount; + return v; +}, initialValue); + +assert.sameValue(result, values[values.length - 1]); +assert.sameValue(assertionCount, values.length); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-this.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-this.js new file mode 100644 index 0000000000..91cb6c7b36 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-this.js @@ -0,0 +1,35 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.reduce +description: > + Iterator.prototype.reduce reducer this value is undefined +info: | + %Iterator.prototype%.reduce ( reducer ) + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield 0; + yield 1; +} + +let iter = g(); + +let expectedThis = function () { + return this; +}.call(undefined); + +let assertionCount = 0; +let result = iter.reduce(function (memo, v, count) { + assert.sameValue(this, expectedThis); + ++assertionCount; + return memo; +}); + +assert.sameValue(result, 0); +assert.sameValue(assertionCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-throws-then-closing-iterator-also-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-throws-then-closing-iterator-also-throws.js new file mode 100644 index 0000000000..020a37db48 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-throws-then-closing-iterator-also-throws.js @@ -0,0 +1,39 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.reduce +description: > + Attempts to close iterator when reducer throws, but that throws +info: | + %Iterator.prototype%.reduce ( reducer ) + +features: [iterator-helpers] +flags: [] +---*/ +let returnCalls = 0; + +class TestIterator extends Iterator { + next() { + return { + done: false, + value: 1, + }; + } + return() { + ++returnCalls; + throw new Error(); + } +} + +let iterator = new TestIterator(); + +assert.throws(Test262Error, function () { + iterator.reduce(() => { + throw new Test262Error(); + }); +}); + +assert.sameValue(returnCalls, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-throws.js new file mode 100644 index 0000000000..a2be3a86c8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/reducer-throws.js @@ -0,0 +1,43 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.reduce +description: > + Closes iterator and throws when reducer throws +info: | + %Iterator.prototype%.reduce ( reducer ) + +features: [iterator-helpers] +flags: [] +---*/ +let returnCalls = 0; + +class TestIterator extends Iterator { + next() { + return { + done: false, + value: 1, + }; + } + return() { + ++returnCalls; + return {}; + } +} + +let iterator = new TestIterator(); + +let callbackCalls = 0; + +assert.throws(Test262Error, function () { + iterator.reduce(() => { + ++callbackCalls; + throw new Test262Error(); + }); +}); + +assert.sameValue(callbackCalls, 1); +assert.sameValue(returnCalls, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/shell.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/shell.js diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/this-non-callable-next.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/this-non-callable-next.js new file mode 100644 index 0000000000..c8ee441091 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/this-non-callable-next.js @@ -0,0 +1,18 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.reduce +description: > + Iterator.prototype.reduce throws TypeError when its this value is an object with a non-callable next +info: | + %Iterator.prototype%.reduce ( reducer ) + +features: [iterator-helpers] +flags: [] +---*/ +assert.throws(TypeError, function () { + Iterator.prototype.reduce.call({ next: 0 }, () => {}, 0); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/this-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/this-non-object.js new file mode 100644 index 0000000000..a910b83879 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/this-non-object.js @@ -0,0 +1,36 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.reduce +description: > + Iterator.prototype.reduce throws TypeError when its this value is a non-object +info: | + %Iterator.prototype%.reduce ( reducer ) + +features: [iterator-helpers] +flags: [] +---*/ +assert.throws(TypeError, function () { + Iterator.prototype.reduce.call(null, () => {}); +}); + +assert.throws(TypeError, function () { + Iterator.prototype.reduce.call(null, () => {}, 0); +}); + +Object.defineProperty(Number.prototype, 'next', { + get: function () { + throw new Test262Error(); + }, +}); + +assert.throws(TypeError, function () { + Iterator.prototype.reduce.call(0, () => {}); +}); + +assert.throws(TypeError, function () { + Iterator.prototype.reduce.call(0, () => {}, 0); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/reduce/this-plain-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/this-plain-iterator.js new file mode 100644 index 0000000000..ccd2da7c33 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/reduce/this-plain-iterator.js @@ -0,0 +1,35 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.reduce +description: > + Iterator.prototype.reduce supports a this value that does not inherit from Iterator.prototype but implements the iterator protocol +info: | + %Iterator.prototype%.reduce ( reducer ) + +includes: [compareArray.js] +features: [iterator-helpers] +flags: [] +---*/ +let iter = { + get next() { + let count = 3; + return function () { + --count; + return count >= 0 ? { done: false, value: count } : { done: true, value: undefined }; + }; + }, +}; + +let reducerCalls = 0; +let result = Iterator.prototype.reduce.call(iter, function (memo, v) { + ++reducerCalls; + memo.push(v); + return memo; +}, []); + +assert.compareArray(result, [2, 1, 0]); +assert.sameValue(reducerCalls, 3); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/shell.js b/js/src/tests/test262/built-ins/Iterator/prototype/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/shell.js diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/argument-effect-order.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/argument-effect-order.js new file mode 100644 index 0000000000..12c461697e --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/argument-effect-order.js @@ -0,0 +1,33 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.some +description: > + Arguments and this value are evaluated in the correct order +info: | + %Iterator.prototype%.some ( predicate ) + +includes: [compareArray.js] +features: [iterator-helpers] +flags: [] +---*/ +let effects = []; + +assert.throws(TypeError, function () { + Iterator.prototype.some.call( + { + get next() { + effects.push('get next'); + return function () { + return { done: true, value: undefined }; + }; + }, + }, + null + ); +}); + +assert.compareArray(effects, []); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/browser.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/browser.js diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/callable.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/callable.js new file mode 100644 index 0000000000..4b67ca0521 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/callable.js @@ -0,0 +1,16 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.some +description: > + Iterator.prototype.some is callable +features: [iterator-helpers] +---*/ +function* g() {} +Iterator.prototype.some.call(g(), () => {}); + +let iter = g(); +iter.some(() => {}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/get-next-method-only-once.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/get-next-method-only-once.js new file mode 100644 index 0000000000..00b3c28f5b --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/get-next-method-only-once.js @@ -0,0 +1,39 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.some +description: > + Gets the next method from the iterator only once +info: | + %Iterator.prototype%.some ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +let nextGets = 0; + +class TestIterator extends Iterator { + get next() { + ++nextGets; + let counter = 5; + return function () { + if (counter < 0) { + return { done: true, value: undefined }; + } else { + return { done: false, value: --counter }; + } + }; + } +} + +let iterator = new TestIterator(); + +assert.sameValue(nextGets, 0); +assert.sameValue( + iterator.some(() => true), + true +); +assert.sameValue(nextGets, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/get-next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/get-next-method-throws.js new file mode 100644 index 0000000000..dfd42bb7ab --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/get-next-method-throws.js @@ -0,0 +1,26 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.some +description: > + Iterator has throwing next getter +info: | + %Iterator.prototype%.some ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +class IteratorThrows extends Iterator { + get next() { + throw new Test262Error(); + } +} + +let iterator = new IteratorThrows(); + +assert.throws(Test262Error, function () { + iterator.some(() => {}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/get-return-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/get-return-method-throws.js new file mode 100644 index 0000000000..0493bcbed3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/get-return-method-throws.js @@ -0,0 +1,32 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.some +description: > + Iterator has throwing return getter +info: | + %Iterator.prototype%.some ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +class IteratorThrows extends Iterator { + next() { + return { + done: false, + value: 0, + }; + } + get return() { + throw new Test262Error(); + } +} + +let iterator = new IteratorThrows([1, 2]); + +assert.throws(Test262Error, function () { + iterator.some(() => true); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/is-function.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/is-function.js new file mode 100644 index 0000000000..f5f4ac676d --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/is-function.js @@ -0,0 +1,13 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.some +description: > + Iterator.prototype.some is a built-in function +features: [iterator-helpers] +---*/ + +assert.sameValue(typeof Iterator.prototype.some, 'function'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/iterator-already-exhausted.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/iterator-already-exhausted.js new file mode 100644 index 0000000000..94de3a2c98 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/iterator-already-exhausted.js @@ -0,0 +1,26 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.some +description: > + Iterator.prototype.some returns true when the iterator has already been exhausted +info: | + %Iterator.prototype%.some ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +let iterator = (function* () {})(); + +let { value, done } = iterator.next(); +assert.sameValue(value, undefined); +assert.sameValue(done, true); + +let result = iterator.some(() => true); +assert.sameValue(result, false); + +result = iterator.some(() => false); +assert.sameValue(result, false); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/iterator-has-no-return.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/iterator-has-no-return.js new file mode 100644 index 0000000000..514a887484 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/iterator-has-no-return.js @@ -0,0 +1,30 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.some +description: > + The underlying iterator is sometimes unable to be closed (has no return method) +info: | + %Iterator.prototype%.some ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +let iterator = [1, 2, 3, 4, 5][Symbol.iterator](); + +assert.sameValue(iterator.return, undefined); + +let ret = iterator.some(v => v > 3); + +assert.sameValue(ret, true); + +let { done, value } = iterator.next(); +assert.sameValue(done, false); +assert.sameValue(value, 5); + +({ done, value } = iterator.next()); +assert.sameValue(done, true); +assert.sameValue(value, undefined); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/iterator-return-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/iterator-return-method-throws.js new file mode 100644 index 0000000000..82bd47cd90 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/iterator-return-method-throws.js @@ -0,0 +1,32 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.some +description: > + Iterator has throwing return +info: | + %Iterator.prototype%.some ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +class IteratorThrows extends Iterator { + next() { + return { + done: false, + value: 0, + }; + } + return() { + throw new Test262Error(); + } +} + +let iterator = new IteratorThrows(); + +assert.throws(Test262Error, function () { + iterator.some(() => true); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/length.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/length.js new file mode 100644 index 0000000000..5c536518b4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/length.js @@ -0,0 +1,25 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.some +description: > + Iterator.prototype.some has a "length" property whose value is 1. +info: | + ECMAScript Standard Built-in Objects + + Unless otherwise specified, the length property of a built-in + Function object has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: true }. +features: [iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator.prototype.some, 'length', { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/name.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/name.js new file mode 100644 index 0000000000..0a9dc1fd41 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/name.js @@ -0,0 +1,32 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.some +description: > + The "name" property of Iterator.prototype.some +info: | + 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. + + ... + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +features: [iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator.prototype.some, 'name', { + value: 'some', + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/next-method-returns-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/next-method-returns-non-object.js new file mode 100644 index 0000000000..08317fcbd5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/next-method-returns-non-object.js @@ -0,0 +1,26 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.some +description: > + Underlying iterator next returns non-object +info: | + %Iterator.prototype%.some ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +class NonObjectIterator extends Iterator { + next() { + return null; + } +} + +let iterator = new NonObjectIterator(); + +assert.throws(TypeError, function () { + iterator.some(() => {}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/next-method-returns-throwing-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/next-method-returns-throwing-done.js new file mode 100644 index 0000000000..0932c31658 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/next-method-returns-throwing-done.js @@ -0,0 +1,34 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.some +description: > + Underlying iterator next returns object with throwing done getter +info: | + %Iterator.prototype%.some ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + return { + get done() { + throw new Test262Error(); + }, + value: 1, + }; + } + return() { + throw new Error(); + } +} + +let iterator = new ThrowingIterator(); + +assert.throws(Test262Error, function () { + iterator.some(() => {}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/next-method-returns-throwing-value-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/next-method-returns-throwing-value-done.js new file mode 100644 index 0000000000..f130e25afe --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/next-method-returns-throwing-value-done.js @@ -0,0 +1,31 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.some +description: > + Underlying iterator next returns object with throwing value getter, but is already done +info: | + %Iterator.prototype%.some ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + return { + done: true, + get value() { + throw new Test262Error(); + }, + }; + } + return() { + throw new Error(); + } +} + +let iterator = new ThrowingIterator(); +iterator.some(() => {}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/next-method-returns-throwing-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/next-method-returns-throwing-value.js new file mode 100644 index 0000000000..8ce95dec1d --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/next-method-returns-throwing-value.js @@ -0,0 +1,34 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.some +description: > + Underlying iterator next returns object with throwing value getter +info: | + %Iterator.prototype%.some ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + return { + done: false, + get value() { + throw new Test262Error(); + }, + }; + } + return() { + throw new Error(); + } +} + +let iterator = new ThrowingIterator(); + +assert.throws(Test262Error, function () { + iterator.some(() => {}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/next-method-throws.js new file mode 100644 index 0000000000..273c6d8deb --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/next-method-throws.js @@ -0,0 +1,26 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.some +description: > + Underlying iterator has throwing next method +info: | + %Iterator.prototype%.some ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + throw new Test262Error(); + } +} + +let iterator = new ThrowingIterator(); + +assert.throws(Test262Error, function () { + iterator.some(() => {}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/non-callable-predicate.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/non-callable-predicate.js new file mode 100644 index 0000000000..9a94690966 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/non-callable-predicate.js @@ -0,0 +1,23 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.some +description: > + Iterator.prototype.some expects to be called with a callable argument. +info: | + %Iterator.prototype%.some ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +let nonCallable = {}; +let iterator = (function* () { + yield 1; +})(); + +assert.throws(TypeError, function () { + iterator.some(nonCallable); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/non-constructible.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/non-constructible.js new file mode 100644 index 0000000000..0b8e53f88b --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/non-constructible.js @@ -0,0 +1,31 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.some +description: > + Iterator.prototype.some is not constructible. + + 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. +features: [iterator-helpers] +---*/ +function* g() {} +let iter = g(); + +assert.throws(TypeError, () => { + new iter.some(); +}); + +assert.throws(TypeError, () => { + new iter.some(() => {}); +}); + +assert.throws(TypeError, () => { + new Iterator.prototype.some(() => {}); +}); + +assert.throws(TypeError, () => { + new class extends Iterator {}.some(() => {}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-args.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-args.js new file mode 100644 index 0000000000..6c270d47f6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-args.js @@ -0,0 +1,44 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.some +description: > + Iterator.prototype.some predicate is passed the yielded value and a counter as arguments +info: | + %Iterator.prototype%.some ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield 'a'; + yield 'b'; + yield 'c'; +} + +let iter = g(); + +let assertionCount = 0; +let result = iter.some((v, count) => { + switch (v) { + case 'a': + assert.sameValue(count, 0); + break; + case 'b': + assert.sameValue(count, 1); + break; + case 'c': + assert.sameValue(count, 2); + break; + default: + throw new Error(); + } + ++assertionCount; + return false; +}); + +assert.sameValue(result, false); +assert.sameValue(assertionCount, 3); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-returns-falsey-then-truthy.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-returns-falsey-then-truthy.js new file mode 100644 index 0000000000..b3171a85ff --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-returns-falsey-then-truthy.js @@ -0,0 +1,35 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.some +description: > + Iterator.prototype.some returns true and closes the iterator when the predicate returns falsey for some iterated values and truthy for others +info: | + %Iterator.prototype%.some ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + for (let i = 0; i < 5; ++i) { + yield i; + } +} + +let iter = g(); + +let predicateCalls = 0; +let result = iter.some(v => { + ++predicateCalls; + return v > 2; +}); + +assert.sameValue(result, true); +assert.sameValue(predicateCalls, 4); + +let { done, value } = iter.next(); +assert.sameValue(done, true); +assert.sameValue(value, undefined); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-returns-falsey.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-returns-falsey.js new file mode 100644 index 0000000000..7b7d91a449 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-returns-falsey.js @@ -0,0 +1,24 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.some +description: > + Iterator.prototype.some returns false when the predicate returns falsey for all iterated values +info: | + %Iterator.prototype%.some ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield 0; + yield 1; + yield 2; + yield 3; +} + +let result = g().some(() => false); +assert.sameValue(result, false); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-returns-non-boolean.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-returns-non-boolean.js new file mode 100644 index 0000000000..18ee4764ba --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-returns-non-boolean.js @@ -0,0 +1,35 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.some +description: > + Iterator.prototype.some coerces predicate return value to boolean +info: | + %Iterator.prototype%.some ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield ''; + yield null; + yield undefined; + yield 0; + yield 1; + yield 2; + yield 3; +} + +let iter = g(); + +let predicateCalls = 0; +let result = iter.some(v => { + ++predicateCalls; + return v; +}); + +assert.sameValue(result, true); +assert.sameValue(predicateCalls, 5); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-returns-truthy.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-returns-truthy.js new file mode 100644 index 0000000000..25b0769304 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-returns-truthy.js @@ -0,0 +1,35 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.some +description: > + Iterator.prototype.some returns true and closes the iterator when the predicate returns truthy immediately +info: | + %Iterator.prototype%.some ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield 0; + yield 1; + yield 2; +} + +let iter = g(); + +let predicateCalls = 0; +let result = iter.some(v => { + ++predicateCalls; + return true; +}); + +assert.sameValue(result, true); +assert.sameValue(predicateCalls, 1); + +let { done, value } = iter.next(); +assert.sameValue(done, true); +assert.sameValue(value, undefined); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-this.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-this.js new file mode 100644 index 0000000000..0ae8609b55 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-this.js @@ -0,0 +1,34 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.some +description: > + Iterator.prototype.some predicate this value is undefined +info: | + %Iterator.prototype%.some ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield 0; +} + +let iter = g(); + +let expectedThis = function () { + return this; +}.call(undefined); + +let assertionCount = 0; +let result = iter.some(function (v, count) { + assert.sameValue(this, expectedThis); + ++assertionCount; + return true; +}); + +assert.sameValue(result, true); +assert.sameValue(assertionCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-throws-then-closing-iterator-also-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-throws-then-closing-iterator-also-throws.js new file mode 100644 index 0000000000..2ccd16d92a --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-throws-then-closing-iterator-also-throws.js @@ -0,0 +1,39 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.some +description: > + Attempts to close iterator when predicate throws, but that throws +info: | + %Iterator.prototype%.some ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +let returnCalls = 0; + +class TestIterator extends Iterator { + next() { + return { + done: false, + value: 1, + }; + } + return() { + ++returnCalls; + throw new Error(); + } +} + +let iterator = new TestIterator(); + +assert.throws(Test262Error, function () { + iterator.some(() => { + throw new Test262Error(); + }); +}); + +assert.sameValue(returnCalls, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-throws.js new file mode 100644 index 0000000000..a39878fa25 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/predicate-throws.js @@ -0,0 +1,43 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.some +description: > + Closes iterator and throws when predicate throws +info: | + %Iterator.prototype%.some ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +let returnCalls = 0; + +class TestIterator extends Iterator { + next() { + return { + done: false, + value: 1, + }; + } + return() { + ++returnCalls; + return {}; + } +} + +let iterator = new TestIterator(); + +let callbackCalls = 0; + +assert.throws(Test262Error, function () { + iterator.some(() => { + ++callbackCalls; + throw new Test262Error(); + }); +}); + +assert.sameValue(callbackCalls, 1); +assert.sameValue(returnCalls, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/prop-desc.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/prop-desc.js new file mode 100644 index 0000000000..ded03f7c7f --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/prop-desc.js @@ -0,0 +1,28 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.some +description: > + Property descriptor of Iterator.prototype.some +info: | + Iterator.prototype.some + + * is the initial value of the Iterator.prototype.some property of the global object. + + 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. +features: [globalThis, iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator.prototype, 'some', { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/proto.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/proto.js new file mode 100644 index 0000000000..24eeda1679 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/proto.js @@ -0,0 +1,14 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.some +description: > + The value of the [[Prototype]] internal slot of Iterator.prototype.some is the + intrinsic object %Function%. +features: [iterator-helpers] +---*/ + +assert.sameValue(Object.getPrototypeOf(Iterator.prototype.some), Function.prototype); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/result-is-boolean.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/result-is-boolean.js new file mode 100644 index 0000000000..d92e6df618 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/result-is-boolean.js @@ -0,0 +1,14 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.some +description: > + Iterator.prototype.some returns a boolean +features: [iterator-helpers] +---*/ +function* g() {} +let iter = g(); +assert.sameValue(typeof iter.some(() => {}), 'boolean'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/shell.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/shell.js diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/this-non-callable-next.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/this-non-callable-next.js new file mode 100644 index 0000000000..18e57c87a6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/this-non-callable-next.js @@ -0,0 +1,18 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.some +description: > + Iterator.prototype.some throws TypeError when its this value is an object with a non-callable next +info: | + %Iterator.prototype%.some ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +assert.throws(TypeError, function () { + Iterator.prototype.some.call({ next: 0 }, () => true); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/this-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/this-non-object.js new file mode 100644 index 0000000000..136fe18fb8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/this-non-object.js @@ -0,0 +1,27 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.some +description: > + Iterator.prototype.some throws TypeError when its this value is a non-object +info: | + %Iterator.prototype%.some ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +assert.throws(TypeError, function () { + Iterator.prototype.some.call(null, () => {}); +}); + +Object.defineProperty(Number.prototype, 'next', { + get: function () { + throw new Test262Error(); + }, +}); +assert.throws(TypeError, function () { + Iterator.prototype.some.call(0, () => {}); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/some/this-plain-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/some/this-plain-iterator.js new file mode 100644 index 0000000000..949f1dbc8e --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/some/this-plain-iterator.js @@ -0,0 +1,33 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.some +description: > + Iterator.prototype.some supports a this value that does not inherit from Iterator.prototype but implements the iterator protocol +info: | + %Iterator.prototype%.some ( predicate ) + +features: [iterator-helpers] +flags: [] +---*/ +let iter = { + get next() { + let count = 3; + return function () { + --count; + return count >= 0 ? { done: false, value: count } : { done: true, value: undefined }; + }; + }, +}; + +let predicateCalls = 0; +let result = Iterator.prototype.some.call(iter, function (v) { + ++predicateCalls; + return v === 0; +}); + +assert.sameValue(result, true); +assert.sameValue(predicateCalls, 3); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/argument-effect-order.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/argument-effect-order.js new file mode 100644 index 0000000000..942c379c79 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/argument-effect-order.js @@ -0,0 +1,75 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.take +description: > + Arguments and this value are evaluated in the correct order +info: | + %Iterator.prototype%.take ( limit ) + + 1. Let O be the this value. + 2. If O is not an Object, throw a TypeError exception. + 3. Let numLimit be ? ToNumber(limit). + 4. If numLimit is NaN, throw a RangeError exception. + 5. Let integerLimit be ! ToIntegerOrInfinity(numLimit). + 6. If integerLimit < 0, throw a RangeError exception. + 7. Let iterated be ? GetIteratorDirect(O). + +includes: [compareArray.js] +features: [iterator-helpers] +flags: [] +---*/ +let effects = []; + +Iterator.prototype.take.call( + { + get next() { + effects.push('get next'); + return function () { + return { done: true, value: undefined }; + }; + }, + }, + { + valueOf() { + effects.push('ToNumber limit'); + return 0; + }, + } +); + +assert.compareArray(effects, ['ToNumber limit', 'get next']); + +effects = []; + +assert.throws(TypeError, function () { + Iterator.prototype.take.call(null, { + valueOf() { + effects.push('ToNumber limit'); + return 0; + }, + }); +}); + +assert.compareArray(effects, []); + +effects = []; + +assert.throws(RangeError, function () { + Iterator.prototype.take.call( + { + get next() { + effects.push('get next'); + return function () { + return { done: true, value: undefined }; + }; + }, + }, + NaN + ); +}); + +assert.compareArray(effects, []); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/browser.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/browser.js diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/callable.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/callable.js new file mode 100644 index 0000000000..adb37486b4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/callable.js @@ -0,0 +1,16 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.take +description: > + Iterator.prototype.take is callable +features: [iterator-helpers] +---*/ +function* g() {} +Iterator.prototype.take.call(g(), 0); + +let iter = g(); +iter.take(0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/exhaustion-calls-return.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/exhaustion-calls-return.js new file mode 100644 index 0000000000..67a51cc926 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/exhaustion-calls-return.js @@ -0,0 +1,71 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.take +description: > + Underlying iterator return is called when result iterator is exhausted +info: | + %Iterator.prototype%.take ( limit ) + + 8.b.i. If remaining is 0, then + 8.b.i.1. Return ? IteratorClose(iterated, NormalCompletion(undefined)). + +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield 0; + yield 1; + yield 2; +} + +class TestIterator extends Iterator { + get next() { + let n = g(); + return function() { + return n.next(); + }; + } + return() { + throw new Test262Error(); + } +} + +let iterator = new TestIterator(); +iterator = iterator.take(0); +assert.throws(Test262Error, function () { + iterator.next(); +}); +iterator.next(); +iterator.next(); + +iterator = new TestIterator(); +iterator = iterator.take(1); +iterator.next(); +assert.throws(Test262Error, function () { + iterator.next(); +}); +iterator.next(); +iterator.next(); + +iterator = new TestIterator(); +iterator = iterator.take(1).take(1).take(1).take(1).take(1); +iterator.next(); +assert.throws(Test262Error, function () { + iterator.next(); +}); +iterator.next(); +iterator.next(); + +iterator = new TestIterator(); +iterator = iterator.take(5); +iterator.next(); +iterator.next(); +iterator.next(); +iterator.next(); +iterator.next(); +iterator.next(); +iterator.next(); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/get-next-method-only-once.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/get-next-method-only-once.js new file mode 100644 index 0000000000..2aba39ecde --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/get-next-method-only-once.js @@ -0,0 +1,44 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.take +description: > + Gets the next method from the underlying iterator only once +info: | + %Iterator.prototype%.take ( limit ) + + 7. Let iterated be ? GetIteratorDirect(this value). + +features: [iterator-helpers] +flags: [] +---*/ +let nextGets = 0; +let nextCalls = 0; + +class CountingIterator extends Iterator { + get next() { + ++nextGets; + let iter = (function* () { + for (let i = 1; i < 5; ++i) { + yield i; + } + })(); + return function () { + ++nextCalls; + return iter.next(); + }; + } +} + +let iterator = new CountingIterator(); + +assert.sameValue(nextGets, 0); +assert.sameValue(nextCalls, 0); + +for (const value of iterator.take(2)); + +assert.sameValue(nextGets, 1); +assert.sameValue(nextCalls, 2); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/get-next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/get-next-method-throws.js new file mode 100644 index 0000000000..75176f7aa6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/get-next-method-throws.js @@ -0,0 +1,28 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.take +description: > + Underlying iterator has throwing next getter +info: | + %Iterator.prototype%.take ( limit ) + + 7. Let iterated be ? GetIteratorDirect(this value). + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + get next() { + throw new Test262Error(); + } +} + +let iterator = new ThrowingIterator(); + +assert.throws(Test262Error, function () { + iterator.take(0); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/get-return-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/get-return-method-throws.js new file mode 100644 index 0000000000..cbd9528cd5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/get-return-method-throws.js @@ -0,0 +1,33 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.take +description: > + Underlying iterator return is throwing getter +info: | + %Iterator.prototype%.take ( limit ) + +features: [iterator-helpers] +flags: [] +---*/ +class TestIterator extends Iterator { + next() { + return { + done: false, + value: 1, + }; + } + get return() { + throw new Test262Error(); + } +} + +let iterator = new TestIterator().take(1); +iterator.next(); + +assert.throws(Test262Error, function () { + iterator.return(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/is-function.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/is-function.js new file mode 100644 index 0000000000..98d95a8360 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/is-function.js @@ -0,0 +1,13 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.take +description: > + Iterator.prototype.take is a built-in function +features: [iterator-helpers] +---*/ + +assert.sameValue(typeof Iterator.prototype.take, 'function'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/length.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/length.js new file mode 100644 index 0000000000..3bf59e4234 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/length.js @@ -0,0 +1,25 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.take +description: > + Iterator.prototype.take has a "length" property whose value is 1. +info: | + ECMAScript Standard Built-in Objects + + Unless otherwise specified, the length property of a built-in + Function object has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: true }. +features: [iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator.prototype.take, 'length', { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/limit-greater-than-or-equal-to-total.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/limit-greater-than-or-equal-to-total.js new file mode 100644 index 0000000000..431fede456 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/limit-greater-than-or-equal-to-total.js @@ -0,0 +1,30 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.take +description: > + Takes entries from this iterator until it is exhausted or the limit is reached. +info: | + %Iterator.prototype%.take ( limit ) + + 8.b.iii. Let next be ? IteratorStep(iterated). + 8.b.iv. If next is false, return undefined. + +includes: [compareArray.js] +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + yield 0; + yield 1; + yield 2; +} + +assert.compareArray(Array.from(g().take(3)), [0, 1, 2]); +assert.compareArray(Array.from(g().take(4)), [0, 1, 2]); +assert.compareArray(Array.from(g().take(5)), [0, 1, 2]); +assert.compareArray(Array.from(g().take(Number.MAX_SAFE_INTEGER)), [0, 1, 2]); +assert.compareArray(Array.from(g().take(Infinity)), [0, 1, 2]); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/limit-less-than-total.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/limit-less-than-total.js new file mode 100644 index 0000000000..008b937adb --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/limit-less-than-total.js @@ -0,0 +1,31 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.take +description: > + Takes entries from this iterator until the limit is reached. +info: | + %Iterator.prototype%.take ( limit ) + + 8.b.i If remaining is 0, then + 8.b.i.1. Return ? IteratorClose(iterated, NormalCompletion(undefined)). + +includes: [compareArray.js] +features: [iterator-helpers] +flags: [] +---*/ +function* g() { + let i = 0; + while (true) { + yield i; + ++i; + } +} + +assert.compareArray(Array.from(g().take(0)), []); +assert.compareArray(Array.from(g().take(1)), [0]); +assert.compareArray(Array.from(g().take(2)), [0, 1]); +assert.compareArray(Array.from(g().take(3)), [0, 1, 2]); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/limit-rangeerror.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/limit-rangeerror.js new file mode 100644 index 0000000000..7f7249f2f0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/limit-rangeerror.js @@ -0,0 +1,39 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.take +description: > + Throws a RangeError exception when limit argument is NaN or less than 0. +info: | + %Iterator.prototype%.take ( limit ) + + 4. If numLimit is NaN, throw a RangeError exception. + 5. Let integerLimit be ! ToIntegerOrInfinity(numLimit). + 6. If integerLimit < 0, throw a RangeError exception. + +features: [iterator-helpers] +---*/ +let iterator = (function* () {})(); + +iterator.take(0); +iterator.take(-0.5); +iterator.take(null); + +assert.throws(RangeError, () => { + iterator.take(-1); +}); + +assert.throws(RangeError, () => { + iterator.take(); +}); + +assert.throws(RangeError, () => { + iterator.take(undefined); +}); + +assert.throws(RangeError, () => { + iterator.take(NaN); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/limit-tonumber-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/limit-tonumber-throws.js new file mode 100644 index 0000000000..94e0dd22e8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/limit-tonumber-throws.js @@ -0,0 +1,25 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.take +description: > + Throws a RangeError exception when limit argument valueOf throws. +info: | + %Iterator.prototype%.take ( limit ) + + 3. Let numLimit be ? ToNumber(limit). + +features: [iterator-helpers] +---*/ +let iterator = (function* () {})(); + +assert.throws(Test262Error, () => { + iterator.take({ + valueOf: function () { + throw new Test262Error(); + }, + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/limit-tonumber.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/limit-tonumber.js new file mode 100644 index 0000000000..e6d460727c --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/limit-tonumber.js @@ -0,0 +1,64 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.take +description: > + Converts the limit argument to a Number using ToNumber and valueOf/toString. +info: | + %Iterator.prototype%.take ( limit ) + + 3. Let numLimit be ? ToNumber(limit). + +includes: [compareArray.js] +features: [iterator-helpers] +---*/ +function* g() { + yield 0; + yield 1; + yield 2; +} + +assert.compareArray( + Array.from( + g().take({ + valueOf: function () { + return 0; + }, + }) + ), + [] +); +assert.compareArray( + Array.from( + g().take({ + valueOf: function () { + return 1; + }, + }) + ), + [0] +); +assert.compareArray( + Array.from( + g().take({ + valueOf: function () { + return 2; + }, + }) + ), + [0, 1] +); +assert.compareArray(Array.from(g().take([1])), [0]); +assert.compareArray( + Array.from( + g().take({ + toString: function () { + return '1'; + }, + }) + ), + [0] +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/name.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/name.js new file mode 100644 index 0000000000..bf1606d24c --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/name.js @@ -0,0 +1,32 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.take +description: > + The "name" property of Iterator.prototype.take +info: | + 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. + + ... + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +features: [iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator.prototype.take, 'name', { + value: 'take', + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/next-method-returns-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/next-method-returns-non-object.js new file mode 100644 index 0000000000..5d54497776 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/next-method-returns-non-object.js @@ -0,0 +1,32 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.take +description: > + Underlying iterator next returns non-object +info: | + %Iterator.prototype%.take ( limit ) + + 8.b.iii. Let next be ? IteratorStep(iterated). + +features: [iterator-helpers] +flags: [] +---*/ +class NonObjectIterator extends Iterator { + next() { + return null; + } +} + +let iterator = new NonObjectIterator().take(0); + +iterator.next(); + +iterator = new NonObjectIterator().take(1); + +assert.throws(TypeError, function () { + iterator.next(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/next-method-returns-throwing-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/next-method-returns-throwing-done.js new file mode 100644 index 0000000000..8eef5f8ace --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/next-method-returns-throwing-done.js @@ -0,0 +1,45 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.take +description: > + Underlying iterator next returns object with throwing done getter +info: | + %Iterator.prototype%.take ( limit ) + + 8.b.iii. Let next be ? IteratorStep(iterated). + +features: [iterator-helpers] +flags: [] +---*/ +class ReturnCalledError extends Error {} +class DoneGetterError extends Error {} + +class ThrowingIterator extends Iterator { + next() { + return { + get done() { + throw new DoneGetterError(); + }, + value: 1, + }; + } + return() { + throw new ReturnCalledError(); + } +} + +let iterator = new ThrowingIterator().take(0); + +assert.throws(ReturnCalledError, function () { + iterator.next(); +}); + +iterator = new ThrowingIterator().take(1); + +assert.throws(DoneGetterError, function () { + iterator.next(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/next-method-returns-throwing-value-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/next-method-returns-throwing-value-done.js new file mode 100644 index 0000000000..c423d05f38 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/next-method-returns-throwing-value-done.js @@ -0,0 +1,39 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.take +description: > + Underlying iterator next returns object with throwing value getter, but is already done +info: | + %Iterator.prototype%.take ( limit ) + +features: [iterator-helpers] +flags: [] +---*/ +class ReturnCalledError extends Error {} +class ValueGetterError extends Error {} + +class ThrowingIterator extends Iterator { + next() { + return { + done: true, + get value() { + throw new ValueGetterError(); + }, + }; + } + return() { + throw new ReturnCalledError(); + } +} + +let iterator = new ThrowingIterator().take(0); +assert.throws(ReturnCalledError, function () { + iterator.next(); +}); + +iterator = new ThrowingIterator().take(1); +iterator.next(); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/next-method-returns-throwing-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/next-method-returns-throwing-value.js new file mode 100644 index 0000000000..cd3d247b12 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/next-method-returns-throwing-value.js @@ -0,0 +1,45 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.take +description: > + Underlying iterator next returns object with throwing value getter +info: | + %Iterator.prototype%.take ( limit ) + + 8.b.v. Let completion be Completion(Yield(? IteratorValue(next))). + +features: [iterator-helpers] +flags: [] +---*/ +class ReturnCalledError extends Error {} +class ValueGetterError extends Error {} + +class ThrowingIterator extends Iterator { + next() { + return { + done: false, + get value() { + throw new ValueGetterError(); + }, + }; + } + return() { + throw new ReturnCalledError(); + } +} + +let iterator = new ThrowingIterator().take(0); + +assert.throws(ReturnCalledError, function () { + iterator.next(); +}); + +iterator = new ThrowingIterator().take(1); + +assert.throws(ValueGetterError, function () { + iterator.next(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/next-method-throws.js new file mode 100644 index 0000000000..1124b663d3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/next-method-throws.js @@ -0,0 +1,32 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.take +description: > + Underlying iterator has throwing next method +info: | + %Iterator.prototype%.take ( limit ) + + 8.b.iii. Let next be ? IteratorStep(iterated). + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + throw new Test262Error(); + } +} + +let iterator = new ThrowingIterator().take(0); + +iterator.next(); + +iterator = new ThrowingIterator().take(1); + +assert.throws(Test262Error, function () { + iterator.next(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/non-constructible.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/non-constructible.js new file mode 100644 index 0000000000..be4cf34aac --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/non-constructible.js @@ -0,0 +1,31 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.take +description: > + Iterator.prototype.take is not constructible. + + 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. +features: [iterator-helpers] +---*/ +function* g() {} +let iter = g(); + +assert.throws(TypeError, () => { + new iter.take(); +}); + +assert.throws(TypeError, () => { + new iter.take(0); +}); + +assert.throws(TypeError, () => { + new Iterator.prototype.take(0); +}); + +assert.throws(TypeError, () => { + new class extends Iterator {}.take(0); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/prop-desc.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/prop-desc.js new file mode 100644 index 0000000000..4ae182c44d --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/prop-desc.js @@ -0,0 +1,28 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.take +description: > + Property descriptor of Iterator.prototype.take +info: | + Iterator.prototype.take + + * is the initial value of the Iterator.prototype.take property of the global object. + + 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. +features: [globalThis, iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator.prototype, 'take', { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/proto.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/proto.js new file mode 100644 index 0000000000..f83ce61b14 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/proto.js @@ -0,0 +1,14 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.take +description: > + The value of the [[Prototype]] internal slot of Iterator.prototype.take is the + intrinsic object %FunctionPrototype%. +features: [iterator-helpers] +---*/ + +assert.sameValue(Object.getPrototypeOf(Iterator.prototype.take), Function.prototype); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/result-is-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/result-is-iterator.js new file mode 100644 index 0000000000..a180a38e42 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/result-is-iterator.js @@ -0,0 +1,14 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.take +description: > + The value of the [[Prototype]] internal slot of the return value of Iterator.prototype.take is the + intrinsic object %IteratorHelperPrototype%. +features: [iterator-helpers] +---*/ + +assert((function* () {})().take(0) instanceof Iterator, 'function*(){}().take(0) must return an Iterator'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/return-is-forwarded.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/return-is-forwarded.js new file mode 100644 index 0000000000..77d46b2563 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/return-is-forwarded.js @@ -0,0 +1,54 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.take +description: > + Underlying iterator return is called when result iterator is closed +info: | + %Iterator.prototype%.take ( limit ) + +features: [iterator-helpers] +flags: [] +---*/ +let returnCount = 0; + +class TestIterator extends Iterator { + next() { + return { + done: false, + value: 1, + }; + } + return() { + ++returnCount; + return {}; + } +} + +let iterator = new TestIterator().take(0); +assert.sameValue(returnCount, 0); +iterator.return(); +assert.sameValue(returnCount, 1); +iterator.return(); +assert.sameValue(returnCount, 1); + +returnCount = 0; + +iterator = new TestIterator().take(1); +assert.sameValue(returnCount, 0); +iterator.return(); +assert.sameValue(returnCount, 1); +iterator.return(); +assert.sameValue(returnCount, 1); + +returnCount = 0; + +iterator = new TestIterator().take(1).take(1).take(1).take(1).take(1); +assert.sameValue(returnCount, 0); +iterator.return(); +assert.sameValue(returnCount, 1); +iterator.return(); +assert.sameValue(returnCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/return-is-not-forwarded-after-exhaustion.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/return-is-not-forwarded-after-exhaustion.js new file mode 100644 index 0000000000..edb5b7deef --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/return-is-not-forwarded-after-exhaustion.js @@ -0,0 +1,53 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.take +description: > + Underlying iterator return is not called after result iterator observes that underlying iterator is exhausted +info: | + %Iterator.prototype%.take ( limit ) + +features: [iterator-helpers] +flags: [] +---*/ +let returnCount = 0; + +class TestIterator extends Iterator { + next() { + return { + done: true, + value: undefined, + }; + } + return() { + throw new Test262Error(); + } +} + +let iterator = new TestIterator().take(0); +assert.throws(Test262Error, function () { + iterator.return(); +}); +iterator.next(); +iterator.return(); + +iterator = new TestIterator().take(1); +iterator.next(); +iterator.return(); + +iterator = new TestIterator().take(1); +assert.throws(Test262Error, function () { + iterator.return(); +}); +iterator.next(); +iterator.return(); + +iterator = new TestIterator().take(1).take(1).take(1).take(1).take(1); +assert.throws(Test262Error, function () { + iterator.return(); +}); +iterator.next(); +iterator.return(); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/shell.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/shell.js diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/this-non-callable-next.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/this-non-callable-next.js new file mode 100644 index 0000000000..6169b576ce --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/this-non-callable-next.js @@ -0,0 +1,22 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.take +description: > + Iterator.prototype.take throws TypeError when its this value is an object with a non-callable next +info: | + %Iterator.prototype%.take ( limit ) + + 7. Let iterated be ? GetIteratorDirect(this value). + +features: [iterator-helpers] +flags: [] +---*/ +let iter = Iterator.prototype.take.call({ next: 0 }, 1); + +assert.throws(TypeError, function () { + iter.next(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/this-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/this-non-object.js new file mode 100644 index 0000000000..85910af8f4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/this-non-object.js @@ -0,0 +1,37 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.take +description: > + Iterator.prototype.take throws TypeError when its this value is a non-object +info: | + %Iterator.prototype%.take ( limit ) + + 7. Let iterated be ? GetIteratorDirect(this value). + +features: [iterator-helpers] +flags: [] +---*/ +assert.throws(TypeError, function () { + Iterator.prototype.take.call(null, 1); +}); + +assert.throws(TypeError, function () { + Iterator.prototype.take.call(null, { + valueOf: function () { + throw new Test262Error(); + }, + }); +}); + +Object.defineProperty(Number.prototype, 'next', { + get: function () { + throw new Test262Error(); + }, +}); +assert.throws(TypeError, function () { + Iterator.prototype.take.call(0, 1); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/this-plain-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/this-plain-iterator.js new file mode 100644 index 0000000000..d83fea848d --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/this-plain-iterator.js @@ -0,0 +1,33 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.take +description: > + Iterator.prototype.take supports a this value that does not inherit from Iterator.prototype but implements the iterator protocol +info: | + %Iterator.prototype%.take ( limit ) + + 7. Let iterated be ? GetIteratorDirect(this value). + +features: [iterator-helpers] +flags: [] +---*/ +let iter = { + get next() { + let count = 3; + return function () { + --count; + return count >= 0 ? { done: false, value: count } : { done: true, value: undefined }; + }; + }, +}; + +let takeIter = Iterator.prototype.take.call(iter, 1); + +let { done, value } = takeIter.next(); + +assert.sameValue(done, false); +assert.sameValue(value, 2); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/throws-typeerror-when-generator-is-running.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/throws-typeerror-when-generator-is-running.js new file mode 100644 index 0000000000..9eb8e3827e --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/throws-typeerror-when-generator-is-running.js @@ -0,0 +1,42 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.take +description: > + Throws a TypeError when the closure generator is already running. +info: | + %IteratorHelperPrototype%.next ( ) + 1. Return ? GeneratorResume(this value, undefined, "Iterator Helper"). + + 27.5.3.3 GeneratorResume ( generator, value, generatorBrand ) + 1. Let state be ? GeneratorValidate(generator, generatorBrand). + ... + + 27.5.3.2 GeneratorValidate ( generator, generatorBrand ) + ... + 6. If state is executing, throw a TypeError exception. + ... + +features: [iterator-helpers] +---*/ + +var enterCount = 0; + +class TestIterator extends Iterator { + next() { + enterCount++; + iter.next(); + return {done: false}; + } +} + +var iter = new TestIterator().take(100); + +assert.throws(TypeError, function() { + iter.next(); +}); + +assert.sameValue(enterCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/underlying-iterator-advanced-in-parallel.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/underlying-iterator-advanced-in-parallel.js new file mode 100644 index 0000000000..883e9350c0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/underlying-iterator-advanced-in-parallel.js @@ -0,0 +1,42 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.take +description: > + Underlying iterator is advanced after calling take +info: | + %Iterator.prototype%.take ( limit ) + +features: [iterator-helpers] +flags: [] +---*/ +let iterator = (function* () { + for (let i = 0; i < 5; ++i) { + yield i; + } +})(); + +let taken = iterator.take(2); + +let { value, done } = iterator.next(); + +assert.sameValue(value, 0); +assert.sameValue(done, false); + +({ value, done } = taken.next()); + +assert.sameValue(value, 1); +assert.sameValue(done, false); + +({ value, done } = taken.next()); + +assert.sameValue(value, 2); +assert.sameValue(done, false); + +({ value, done } = taken.next()); + +assert.sameValue(value, undefined); +assert.sameValue(done, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/underlying-iterator-closed-in-parallel.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/underlying-iterator-closed-in-parallel.js new file mode 100644 index 0000000000..2b25b7ebba --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/underlying-iterator-closed-in-parallel.js @@ -0,0 +1,29 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.take +description: > + Underlying iterator is closed after calling take +info: | + %Iterator.prototype%.take ( limit ) + +features: [iterator-helpers] +flags: [] +---*/ +let iterator = (function* () { + for (let i = 0; i < 5; ++i) { + yield i; + } +})(); + +let taken = iterator.take(2); + +iterator.return(); + +let { value, done } = taken.next(); + +assert.sameValue(value, undefined); +assert.sameValue(done, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/take/underlying-iterator-closed.js b/js/src/tests/test262/built-ins/Iterator/prototype/take/underlying-iterator-closed.js new file mode 100644 index 0000000000..b045bf8874 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/take/underlying-iterator-closed.js @@ -0,0 +1,29 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.take +description: > + Underlying iterator is closed before calling take +info: | + %Iterator.prototype%.take ( limit ) + +features: [iterator-helpers] +flags: [] +---*/ +let iterator = (function* () { + for (let i = 0; i < 5; ++i) { + yield i; + } +})(); + +iterator.return(); + +let taken = iterator.take(2); + +let { value, done } = taken.next(); + +assert.sameValue(value, undefined); +assert.sameValue(done, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/browser.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/browser.js diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/callable.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/callable.js new file mode 100644 index 0000000000..cef99e083a --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/callable.js @@ -0,0 +1,16 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.toArray +description: > + Iterator.prototype.toArray is callable +features: [iterator-helpers] +---*/ +function* g() {} +Iterator.prototype.toArray.call(g()); + +let iter = g(); +iter.toArray(); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/get-next-method-only-once.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/get-next-method-only-once.js new file mode 100644 index 0000000000..587c8d7a3a --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/get-next-method-only-once.js @@ -0,0 +1,37 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.toArray +description: > + Gets the next method from the iterator only once +info: | + %Iterator.prototype%.toArray ( ) + +includes: [compareArray.js] +features: [iterator-helpers] +flags: [] +---*/ +let nextGets = 0; + +class TestIterator extends Iterator { + get next() { + ++nextGets; + let counter = 5; + return function () { + if (counter <= 0) { + return { done: true, value: undefined }; + } else { + return { done: false, value: --counter }; + } + }; + } +} + +let iterator = new TestIterator(); + +assert.sameValue(nextGets, 0); +assert.compareArray(iterator.toArray(), [4, 3, 2, 1, 0]); +assert.sameValue(nextGets, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/get-next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/get-next-method-throws.js new file mode 100644 index 0000000000..df4eac1bdb --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/get-next-method-throws.js @@ -0,0 +1,26 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.toArray +description: > + Iterator has throwing next getter +info: | + %Iterator.prototype%.toArray ( ) + +features: [iterator-helpers] +flags: [] +---*/ +class IteratorThrows extends Iterator { + get next() { + throw new Test262Error(); + } +} + +let iterator = new IteratorThrows(); + +assert.throws(Test262Error, function () { + iterator.toArray(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/is-function.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/is-function.js new file mode 100644 index 0000000000..70e06f968d --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/is-function.js @@ -0,0 +1,13 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.toArray +description: > + Iterator.prototype.toArray is a built-in function +features: [iterator-helpers] +---*/ + +assert.sameValue(typeof Iterator.prototype.toArray, 'function'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/iterator-already-exhausted.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/iterator-already-exhausted.js new file mode 100644 index 0000000000..78cf342b1a --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/iterator-already-exhausted.js @@ -0,0 +1,27 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.toArray +description: > + Iterator.prototype.toArray returns an empty array when the iterator has already been exhausted +info: | + %Iterator.prototype%.toArray ( ) + +includes: [compareArray.js] +features: [iterator-helpers] +flags: [] +---*/ +let iterator = (function* () {})(); + +let { value, done } = iterator.next(); +assert.sameValue(value, undefined); +assert.sameValue(done, true); + +let result = iterator.toArray(); +assert.compareArray(result, []); + +result = iterator.toArray(); +assert.compareArray(result, []); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/length.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/length.js new file mode 100644 index 0000000000..24635c44a2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/length.js @@ -0,0 +1,25 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.toArray +description: > + Iterator.prototype.toArray has a "length" property whose value is 0. +info: | + ECMAScript Standard Built-in Objects + + Unless otherwise specified, the length property of a built-in + Function object has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: true }. +features: [iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator.prototype.toArray, 'length', { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/name.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/name.js new file mode 100644 index 0000000000..a58fffdd8f --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/name.js @@ -0,0 +1,32 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.toArray +description: > + The "name" property of Iterator.prototype.toArray +info: | + 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. + + ... + + Unless otherwise specified, the name property of a built-in Function + object, if it exists, has the attributes { [[Writable]]: false, + [[Enumerable]]: false, [[Configurable]]: true }. +features: [iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator.prototype.toArray, 'name', { + value: 'toArray', + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/next-method-returns-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/next-method-returns-non-object.js new file mode 100644 index 0000000000..929bbde5f5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/next-method-returns-non-object.js @@ -0,0 +1,26 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.toArray +description: > + Underlying iterator next returns non-object +info: | + %Iterator.prototype%.toArray ( ) + +features: [iterator-helpers] +flags: [] +---*/ +class NonObjectIterator extends Iterator { + next() { + return null; + } +} + +let iterator = new NonObjectIterator(); + +assert.throws(TypeError, function () { + iterator.toArray(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/next-method-returns-throwing-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/next-method-returns-throwing-done.js new file mode 100644 index 0000000000..ad4a244488 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/next-method-returns-throwing-done.js @@ -0,0 +1,34 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.toArray +description: > + Underlying iterator next returns object with throwing done getter +info: | + %Iterator.prototype%.toArray ( ) + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + return { + get done() { + throw new Test262Error(); + }, + value: 1, + }; + } + return() { + throw new Error(); + } +} + +let iterator = new ThrowingIterator(); + +assert.throws(Test262Error, function () { + iterator.toArray(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/next-method-returns-throwing-value-done.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/next-method-returns-throwing-value-done.js new file mode 100644 index 0000000000..ffb8f05a64 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/next-method-returns-throwing-value-done.js @@ -0,0 +1,31 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.toArray +description: > + Underlying iterator next returns object with throwing value getter, but is already done +info: | + %Iterator.prototype%.toArray ( ) + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + return { + done: true, + get value() { + throw new Test262Error(); + }, + }; + } + return() { + throw new Error(); + } +} + +let iterator = new ThrowingIterator(); +iterator.toArray(); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/next-method-returns-throwing-value.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/next-method-returns-throwing-value.js new file mode 100644 index 0000000000..ab9b899827 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/next-method-returns-throwing-value.js @@ -0,0 +1,34 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.toArray +description: > + Underlying iterator next returns object with throwing value getter +info: | + %Iterator.prototype%.toArray ( ) + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + return { + done: false, + get value() { + throw new Test262Error(); + }, + }; + } + return() { + throw new Error(); + } +} + +let iterator = new ThrowingIterator(); + +assert.throws(Test262Error, function () { + iterator.toArray(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/next-method-throws.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/next-method-throws.js new file mode 100644 index 0000000000..cd16b49738 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/next-method-throws.js @@ -0,0 +1,26 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.toArray +description: > + Underlying iterator has throwing next method +info: | + %Iterator.prototype%.toArray ( ) + +features: [iterator-helpers] +flags: [] +---*/ +class ThrowingIterator extends Iterator { + next() { + throw new Test262Error(); + } +} + +let iterator = new ThrowingIterator(); + +assert.throws(Test262Error, function () { + iterator.toArray(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/non-constructible.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/non-constructible.js new file mode 100644 index 0000000000..4f30e95134 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/non-constructible.js @@ -0,0 +1,27 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.toArray +description: > + Iterator.prototype.toArray is not constructible. + + 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. +features: [iterator-helpers] +---*/ +function* g() {} +let iter = g(); + +assert.throws(TypeError, () => { + new iter.toArray(); +}); + +assert.throws(TypeError, () => { + new Iterator.prototype.toArray(); +}); + +assert.throws(TypeError, () => { + new class extends Iterator {}.toArray(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/prop-desc.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/prop-desc.js new file mode 100644 index 0000000000..ff05174204 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/prop-desc.js @@ -0,0 +1,28 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.toArray +description: > + Property descriptor of Iterator.prototype.toArray +info: | + Iterator.prototype.toArray + + * is the initial value of the Iterator.prototype.toArray property of the global object. + + 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. +features: [globalThis, iterator-helpers] +includes: [propertyHelper.js] +---*/ + +verifyProperty(Iterator.prototype, 'toArray', { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/proto.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/proto.js new file mode 100644 index 0000000000..f35bd4afa0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/proto.js @@ -0,0 +1,14 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.toArray +description: > + The value of the [[Prototype]] internal slot of Iterator.prototype.toArray is the + intrinsic object %Function%. +features: [iterator-helpers] +---*/ + +assert.sameValue(Object.getPrototypeOf(Iterator.prototype.toArray), Function.prototype); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/shell.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/shell.js diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/this-non-callable-next.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/this-non-callable-next.js new file mode 100644 index 0000000000..857f4af7f5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/this-non-callable-next.js @@ -0,0 +1,18 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.toArray +description: > + Iterator.prototype.toArray throws TypeError when its this value is an object with a non-callable next +info: | + %Iterator.prototype%.toArray ( ) + +features: [iterator-helpers] +flags: [] +---*/ +assert.throws(TypeError, function () { + Iterator.prototype.toArray.call({ next: 0 }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/this-non-object.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/this-non-object.js new file mode 100644 index 0000000000..27ff3bfdb9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/this-non-object.js @@ -0,0 +1,27 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.toArray +description: > + Iterator.prototype.toArray throws TypeError when its this value is a non-object +info: | + %Iterator.prototype%.toArray ( ) + +features: [iterator-helpers] +flags: [] +---*/ +assert.throws(TypeError, function () { + Iterator.prototype.toArray.call(null); +}); + +Object.defineProperty(Number.prototype, 'next', { + get: function () { + throw new Test262Error(); + }, +}); +assert.throws(TypeError, function () { + Iterator.prototype.toArray.call(0); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/prototype/toArray/this-plain-iterator.js b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/this-plain-iterator.js new file mode 100644 index 0000000000..85a065ba4b --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/prototype/toArray/this-plain-iterator.js @@ -0,0 +1,28 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2023 Michael Ficarra. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-iteratorprototype.toArray +description: > + Iterator.prototype.toArray supports a this value that does not inherit from Iterator.prototype but implements the iterator protocol +info: | + %Iterator.prototype%.toArray ( ) + +includes: [compareArray.js] +features: [iterator-helpers] +flags: [] +---*/ +let iter = { + get next() { + let count = 3; + return function () { + --count; + return count >= 0 ? { done: false, value: count } : { done: true, value: undefined }; + }; + }, +}; + +let result = Iterator.prototype.toArray.call(iter); +assert.compareArray(result, [2, 1, 0]); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Iterator/shell.js b/js/src/tests/test262/built-ins/Iterator/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/shell.js diff --git a/js/src/tests/test262/built-ins/Iterator/subclassable.js b/js/src/tests/test262/built-ins/Iterator/subclassable.js new file mode 100644 index 0000000000..f6f440b346 --- /dev/null +++ b/js/src/tests/test262/built-ins/Iterator/subclassable.js @@ -0,0 +1,30 @@ +// |reftest| shell-option(--enable-iterator-helpers) skip-if(!this.hasOwnProperty('Iterator')||!xulRuntime.shell) -- iterator-helpers is not enabled unconditionally, requires shell-options +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-iterator-constructor +description: > + The Iterator constructor is designed to be subclassable. +info: | + The Iterator constructor + + - is designed to be subclassable. It may be used as the value of an extends clause of a class defintion. + +features: [iterator-helpers] +---*/ + +class SubIterator extends Iterator {} + +assert.sameValue( + new SubIterator() instanceof SubIterator, + true, + 'The result of `(new SubIterator() instanceof SubIterator)` is true' +); +assert.sameValue( + new SubIterator() instanceof Iterator, + true, + 'The result of `(new SubIterator() instanceof Iterator)` is true' +); + +reportCompare(0, 0); |