diff options
Diffstat (limited to 'js/src/tests/non262/AsyncIterator/prototype/reduce')
20 files changed, 401 insertions, 0 deletions
diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/accumulator-set-to-initial-value.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/accumulator-set-to-initial-value.js new file mode 100644 index 0000000000..943094aabc --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/accumulator-set-to-initial-value.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +const reducer = (acc, _) => acc; +async function* gen() { + yield 1; + yield 2; + yield 3; +} + +gen().reduce(reducer, 0).then(value => assertEq(value, 0)); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/async-writes.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/async-writes.js new file mode 100644 index 0000000000..2328cc3521 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/async-writes.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +let x = {a: () => true}; + +async function* gen() { + yield x.a(); + yield x.a(); +} + +gen().reduce(() => {}, 0).then( + () => assertEq(true, false, 'expected error'), + err => assertEq(err instanceof Error, true), +); + +x.a = () => { + throw Error(); +}; + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/check-fn-after-getting-iterator.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/check-fn-after-getting-iterator.js new file mode 100644 index 0000000000..4a5484f786 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/check-fn-after-getting-iterator.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +const log = []; +const handlerProxy = new Proxy({}, { + get: (target, key, receiver) => (...args) => { + log.push(`${key}: ${args[1]?.toString()}`); + return Reflect[key](...args); + }, +}); + +class TestIterator extends AsyncIterator { + next() { + return Promise.resolve({ done: this.closed }); + } +} + +const iter = new Proxy(new TestIterator(), handlerProxy); +iter.reduce(1).then(() => assertEq(true, false, 'expected error'), err => { + assertEq(err instanceof TypeError, true); + assertEq( + log.join('\n'), + `get: reduce +get: next` + ); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/descriptor.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/descriptor.js new file mode 100644 index 0000000000..6472c1a14d --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/descriptor.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +/*--- + Descriptor property of AsyncIterator.prototype.reduce +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(AsyncIterator.prototype, 'reduce'); +assertEq(typeof propDesc.value, 'function'); +assertEq(propDesc.writable, true); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/empty-iterator-without-initial-value-throws.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/empty-iterator-without-initial-value-throws.js new file mode 100644 index 0000000000..c54fccba20 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/empty-iterator-without-initial-value-throws.js @@ -0,0 +1,9 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +async function* gen() {} +gen().reduce((x, y) => x + y).then(() => assertEq(true, false, 'expected error'), err => { + assertEq(err instanceof TypeError, true); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/error-from-correct-realm.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/error-from-correct-realm.js new file mode 100644 index 0000000000..16c0ac51a9 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/error-from-correct-realm.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +const otherGlobal = newGlobal({newCompartment: true}); +assertEq(TypeError !== otherGlobal.TypeError, true); + +async function *gen() {} + +gen().reduce().then(() => assertEq(true, false, 'expected error'), err => { + assertEq(err instanceof TypeError, true); +}); + +otherGlobal.AsyncIterator.prototype.reduce.call(gen()).then(() => assertEq(true, false, 'expected error'), err => { + assertEq( + err instanceof otherGlobal.TypeError, + true, + 'TypeError comes from the realm of the method.', + ); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/interleaving-calls.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/interleaving-calls.js new file mode 100644 index 0000000000..8961c69903 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/interleaving-calls.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +const log = []; +async function* gen(n) { + log.push(`${n}`); + yield 1; + log.push(`${n}`); + yield 2; +} + +Promise.all([gen(1).reduce(() => {}, 0), gen(2).reduce(() => {}, 0)]).then( + () => { + assertEq( + log.join(' '), + '1 2 1 2', + ); + }, + err => { + throw err; + } +); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/iterator-empty-return-initial-value.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/iterator-empty-return-initial-value.js new file mode 100644 index 0000000000..b664d25729 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/iterator-empty-return-initial-value.js @@ -0,0 +1,9 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +const reducer = (x, y) => 0; +async function *gen() {} + +gen().reduce(reducer, 1).then(result => assertEq(result, 1)); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/iterator-next-return-non-object-throws.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/iterator-next-return-non-object-throws.js new file mode 100644 index 0000000000..57c244d603 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/iterator-next-return-non-object-throws.js @@ -0,0 +1,31 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +class TestIterator extends AsyncIterator { + constructor(value) { + super(); + this.value = value; + } + + next() { + return Promise.resolve(this.value); + } +} + +const sum = (x, y) => x + y; +function check(value) { + const iter = new TestIterator(value); + iter.reduce(sum).then(() => assertEq(true, false, 'expected error'), err => { + assertEq(err instanceof TypeError, true); + }); +} + +check(); +check(undefined); +check(null); +check(0); +check(false); +check(''); +check(Symbol('')); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/left-associative.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/left-associative.js new file mode 100644 index 0000000000..91147a1fba --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/left-associative.js @@ -0,0 +1,15 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +async function* gen() { + yield 1; + yield 2; + yield 3; +} + +gen().reduce((x, y) => `(${x}+${y})`, 0) + .then(result => assertEq(result, '(((0+1)+2)+3)')); +gen().reduce((x, y) => `(${x}+${y})`) + .then(result => assertEq(result, '((1+2)+3)')); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/length.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/length.js new file mode 100644 index 0000000000..022df65164 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/length.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +/*--- + The `length` property of AsyncIterator.prototype.reduce. +info: | + ES7 section 17: Unless otherwise specified, the length property of a built-in + Function object has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: true }. +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(AsyncIterator.prototype.reduce, 'length'); +assertEq(propDesc.value, 1); +assertEq(propDesc.writable, false); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/name.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/name.js new file mode 100644 index 0000000000..aada19b46d --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/name.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +/*--- + `name` property of AsyncIterator.prototype.reduce. +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(AsyncIterator.prototype.reduce, 'name'); +assertEq(propDesc.value, 'reduce'); +assertEq(propDesc.writable, false); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/next-throws-iterator-not-closed.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/next-throws-iterator-not-closed.js new file mode 100644 index 0000000000..796cdb1895 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/next-throws-iterator-not-closed.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +class TestIterator extends AsyncIterator { + next() { + throw new Error(); + } + + closed = false; + return() { + this.closed = true; + } +} + +const sum = (x, y) => x + y; +const iter = new TestIterator(); + +assertEq(iter.closed, false); +iter.reduce(sum).then(() => assertEq(true, false, 'expected error'), err => { + assertEq(err instanceof Error, true); + assertEq(iter.closed, false); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/no-initial-value-set-accumulator-to-first-value.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/no-initial-value-set-accumulator-to-first-value.js new file mode 100644 index 0000000000..0e480dbe4a --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/no-initial-value-set-accumulator-to-first-value.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +const reducer = (acc, _) => acc; +async function* gen() { + yield 1; + yield 2; + yield 3; +} + +gen().reduce(reducer).then(result => assertEq(result, 1)); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/proxy.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/proxy.js new file mode 100644 index 0000000000..b1e6d52495 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/proxy.js @@ -0,0 +1,44 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +// +// This test checks that %Iterator.prototype%.reduce only gets the `next` method off of the +// iterator once, and never accesses the @@iterator property. +const log = []; +const handlerProxy = new Proxy({}, { + get: (target, key, receiver) => (...args) => { + log.push(`${key}: ${args[1]?.toString()}`); + return Reflect[key](...args); + }, +}); + +class Counter extends AsyncIterator { + value = 0; + next() { + const value = this.value; + if (value < 2) { + this.value = value + 1; + return Promise.resolve({done: false, value}); + } + return Promise.resolve({done: true}); + } +} + +const iter = new Proxy(new Counter(), handlerProxy); +iter.reduce((x, y) => x + y).then(() => { + assertEq( + log.join('\n'), + `get: reduce +get: next +get: value +set: value +getOwnPropertyDescriptor: value +defineProperty: value +get: value +set: value +getOwnPropertyDescriptor: value +defineProperty: value +get: value` + ); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/reduce.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/reduce.js new file mode 100644 index 0000000000..d2382e4d53 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/reduce.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +const reducer = (acc, value) => acc + value; +async function* gen() { + yield 1; + yield 2; + yield 3; +} + +gen().reduce(reducer, 0).then(result => assertEq(result, 6)); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/reducer-not-callable-throws.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/reducer-not-callable-throws.js new file mode 100644 index 0000000000..c7fb2005d8 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/reducer-not-callable-throws.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +async function *gen() {} + +function check(fn) { + gen().reduce(fn).then(() => { + throw new Error('every should have thrown'); + }, + err => { + assertEq(err instanceof TypeError, true); + }); +} + +check(); +check(undefined); +check(null); +check(0); +check(false); +check(''); +check(Symbol('')); +check({}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/reducer-throws-iterator-closed.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/reducer-throws-iterator-closed.js new file mode 100644 index 0000000000..2a55a89850 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/reducer-throws-iterator-closed.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +class TestIterator extends AsyncIterator { + next() { + return Promise.resolve({ done: this.closed, value: undefined }); + } + + closed = false; + return() { + this.closed = true; + } +} + +const reducer = (x, y) => { throw new Error(); }; +const iter = new TestIterator(); + +assertEq(iter.closed, false); +iter.reduce(reducer).then(() => assertEq(true, false, 'expected error'), err => { + assertEq(err instanceof Error, true); + assertEq(iter.closed, true); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/this-not-iterator-throws.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/this-not-iterator-throws.js new file mode 100644 index 0000000000..7f95920fbd --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/this-not-iterator-throws.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +const sum = (x, y) => x + y; +function check(x) { + AsyncIterator.prototype.reduce.call(x, sum).then( + () => assertEq(true, false, 'expected error'), + err => { + assertEq(err instanceof TypeError, true); + } + ); +} + +check(); +check(undefined); +check({}); +check({next: 0}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/value-throws-iterator-not-closed.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/value-throws-iterator-not-closed.js new file mode 100644 index 0000000000..bfe4a9213f --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/value-throws-iterator-not-closed.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +class TestError extends Error {} +class TestIterator extends AsyncIterator { + next() { + return Promise.resolve({ + done: false, + get value() { + throw new TestError(); + } + }); + } + + closed = false; + return() { + closed = true; + } +} + +const iterator = new TestIterator(); +assertEq(iterator.closed, false, 'iterator starts unclosed'); +iterator.reduce((x, y) => x + y, 0).then(() => assertEq(true, false, 'expected error'), err => { + assertEq(err instanceof TestError, true); + assertEq(iterator.closed, false, 'iterator remains unclosed'); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); |