diff options
Diffstat (limited to 'js/src/tests/test262/built-ins/Promise/any')
93 files changed, 4148 insertions, 0 deletions
diff --git a/js/src/tests/test262/built-ins/Promise/any/browser.js b/js/src/tests/test262/built-ins/Promise/any/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/browser.js diff --git a/js/src/tests/test262/built-ins/Promise/any/call-reject-element-after-return.js b/js/src/tests/test262/built-ins/Promise/any/call-reject-element-after-return.js new file mode 100644 index 0000000000..ac713bac2e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/call-reject-element-after-return.js @@ -0,0 +1,51 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any-reject-element-functions +description: > + Cannot change result value of rejected Promise.any element after Promise.any() returned. +info: | + Promise.any Reject Element Functions + + Let alreadyCalled be the value of F's [[AlreadyCalled]] internal slot. + If alreadyCalled.[[value]] is true, return undefined. + Set alreadyCalled.[[value]] to true. + +features: [Promise.any] +---*/ + +let callCount = 0; +let errorArray; + +function Constructor(executor) { + executor(Test262Error.thrower, (error) => { + callCount++; + errorArray = error.errors; + }); +} +Constructor.resolve = function(v) { + return v; +}; + +let p1OnRejected; + +let p1 = { + then(onFulfilled, onRejected) { + p1OnRejected = onRejected; + onRejected("onRejectedValue"); + } +}; + +assert.sameValue(callCount, 0, "callCount before call to any()"); + +Promise.any.call(Constructor, [p1]); + +assert.sameValue(callCount, 1, "callCount after call to any()"); +assert.sameValue(errorArray[0], "onRejectedValue", "errorArray after call to any()"); + +p1OnRejected("unexpectedonRejectedValue"); + +assert.sameValue(errorArray[0], "onRejectedValue", "errorArray[0] === 'onRejectedValue', after call to p1OnRejected()"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/call-reject-element-items.js b/js/src/tests/test262/built-ins/Promise/any/call-reject-element-items.js new file mode 100644 index 0000000000..bef67aa505 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/call-reject-element-items.js @@ -0,0 +1,53 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any-reject-element-functions +description: > + Cannot change result value of rejected Promise.any elements. +info: | + Promise.any Reject Element Functions + + Let alreadyCalled be the value of F's [[AlreadyCalled]] internal slot. + If alreadyCalled.[[value]] is true, return undefined. + Set alreadyCalled.[[value]] to true. + +features: [Promise.any] +---*/ + +let callCount = 0; + +function Constructor(executor) { + function reject(error) { + callCount += 1; + assert(Array.isArray(error.errors), "error.errors is array"); + assert.sameValue(error.errors.length, 2, "error.errors length"); + assert.sameValue(error.errors[0], "expectedValue-p1", "error.errors[0]"); + assert.sameValue(error.errors[1], "expectedValue-p2", "error.errors[1]"); + } + executor(Test262Error.thrower, reject); +} +Constructor.resolve = function(v) { + return v; +}; + +let p1 = { + then(onFulfilled, onRejected) { + onRejected("expectedValue-p1"); + onRejected("unexpectedValue-p1"); + } +}; +let p2 = { + then(onFulfilled, onRejected) { + onRejected("expectedValue-p2"); + onRejected("unexpectedValue-p2"); + } +}; + +assert.sameValue(callCount, 0, "callCount before call to any()"); + +Promise.any.call(Constructor, [p1, p2]); + +assert.sameValue(callCount, 1, "callCount after call to any()"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/capability-executor-called-twice.js b/js/src/tests/test262/built-ins/Promise/any/capability-executor-called-twice.js new file mode 100644 index 0000000000..3fae3ad0b9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/capability-executor-called-twice.js @@ -0,0 +1,108 @@ +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Throws a TypeError if capabilities executor already called with non-undefined values. +info: | + Promise.any ( iterable ) + + ... + 2. Let promiseCapability be ? NewPromiseCapability(C). + ... + + GetCapabilitiesExecutor Functions + + ... + 4. If promiseCapability.[[Resolve]] is not undefined, throw a TypeError exception. + 5. If promiseCapability.[[Reject]] is not undefined, throw a TypeError exception. + 6. Set promiseCapability.[[Resolve]] to resolve. + 7. Set promiseCapability.[[Reject]] to reject. + ... +features: [Promise.any] +---*/ + +var checkPoint = ''; +function fn1(executor) { + checkPoint += 'a'; + executor(); + checkPoint += 'b'; + executor(function() {}, function() {}); + checkPoint += 'c'; +} +fn1.resolve = function() { + throw new Test262Error(); +}; +Promise.any.call(fn1, []); +assert.sameValue(checkPoint, 'abc', 'executor initially called with no arguments'); + +checkPoint = ''; +function fn2(executor) { + checkPoint += 'a'; + executor(undefined, undefined); + checkPoint += 'b'; + executor(function() {}, function() {}); + checkPoint += 'c'; +} +fn2.resolve = function() { + throw new Test262Error(); +}; +Promise.any.call(fn2, []); +assert.sameValue(checkPoint, 'abc', 'executor initially called with (undefined, undefined)'); + +checkPoint = ''; +function fn3(executor) { + checkPoint += 'a'; + executor(undefined, function() {}); + checkPoint += 'b'; + executor(function() {}, function() {}); + checkPoint += 'c'; +} +Object.defineProperty(fn3, 'resolve', { + get() { + throw new Test262Error(); + } +}); +assert.throws(TypeError, function() { + Promise.any.call(fn3, []); +}, 'executor initially called with (undefined, function)'); +assert.sameValue(checkPoint, 'ab', 'executor initially called with (undefined, function)'); + +checkPoint = ''; +function fn4(executor) { + checkPoint += 'a'; + executor(function() {}, undefined); + checkPoint += 'b'; + executor(function() {}, function() {}); + checkPoint += 'c'; +} +Object.defineProperty(fn4, 'resolve', { + get() { + throw new Test262Error(); + } +}); +assert.throws(TypeError, function() { + Promise.any.call(fn4, []); +}, 'executor initially called with (function, undefined)'); +assert.sameValue(checkPoint, 'ab', 'executor initially called with (function, undefined)'); + +checkPoint = ''; +function fn5(executor) { + checkPoint += 'a'; + executor('invalid value', 123); + checkPoint += 'b'; + executor(function() {}, function() {}); + checkPoint += 'c'; +} +Object.defineProperty(fn5, 'resolve', { + get() { + throw new Test262Error(); + } +}); +assert.throws(TypeError, function() { + Promise.any.call(fn5, []); +}, 'executor initially called with (String, Number)'); +assert.sameValue(checkPoint, 'ab', 'executor initially called with (String, Number)'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/capability-executor-not-callable.js b/js/src/tests/test262/built-ins/Promise/any/capability-executor-not-callable.js new file mode 100644 index 0000000000..cc3df69a44 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/capability-executor-not-callable.js @@ -0,0 +1,109 @@ +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Throws a TypeError if either resolve or reject capability is not callable. +info: | + Promise.any ( iterable ) + + ... + 2. Let promiseCapability be ? NewPromiseCapability(C). + ... + + NewPromiseCapability ( C ) + + ... + 5. Let executor be ! CreateBuiltinFunction(steps, « [[Capability]] »). + 6. Set executor.[[Capability]] to promiseCapability. + 7. Let promise be ? Construct(C, « executor »). + 8. If IsCallable(promiseCapability.[[Resolve]]) is false, throw a TypeError exception. + 9. If IsCallable(promiseCapability.[[Reject]]) is false, throw a TypeError exception. + ... +features: [Promise.any] +---*/ + +var checkPoint = ''; +function fn1(executor) { + checkPoint += 'a'; +} +Object.defineProperty(fn1, 'resolve', { + get() { throw new Test262Error(); } +}); +assert.throws(TypeError, function() { + Promise.any.call(fn1, []); +}, 'executor not called at all'); +assert.sameValue(checkPoint, 'a', 'executor not called at all'); + +checkPoint = ''; +function fn2(executor) { + checkPoint += 'a'; + executor(); + checkPoint += 'b'; +} +Object.defineProperty(fn2, 'resolve', { + get() { throw new Test262Error(); } +}); +assert.throws(TypeError, function() { + Promise.any.call(fn2, []); +}, 'executor called with no arguments'); +assert.sameValue(checkPoint, 'ab', 'executor called with no arguments'); + +checkPoint = ''; +function fn3(executor) { + checkPoint += 'a'; + executor(undefined, undefined); + checkPoint += 'b'; +} +Object.defineProperty(fn3, 'resolve', { + get() { throw new Test262Error(); } +}); +assert.throws(TypeError, function() { + Promise.any.call(fn3, []); +}, 'executor called with (undefined, undefined)'); +assert.sameValue(checkPoint, 'ab', 'executor called with (undefined, undefined)'); + +checkPoint = ''; +function fn4(executor) { + checkPoint += 'a'; + executor(undefined, function() {}); + checkPoint += 'b'; +} +Object.defineProperty(fn4, 'resolve', { + get() { throw new Test262Error(); } +}); +assert.throws(TypeError, function() { + Promise.any.call(fn4, []); +}, 'executor called with (undefined, function)'); +assert.sameValue(checkPoint, 'ab', 'executor called with (undefined, function)'); + +checkPoint = ''; +function fn5(executor) { + checkPoint += 'a'; + executor(function() {}, undefined); + checkPoint += 'b'; +} +Object.defineProperty(fn5, 'resolve', { + get() { throw new Test262Error(); } +}); +assert.throws(TypeError, function() { + Promise.any.call(fn5, []); +}, 'executor called with (function, undefined)'); +assert.sameValue(checkPoint, 'ab', 'executor called with (function, undefined)'); + +checkPoint = ''; +function fn6(executor) { + checkPoint += 'a'; + executor(123, 'invalid value'); + checkPoint += 'b'; +} +Object.defineProperty(fn6, 'resolve', { + get() { throw new Test262Error(); } +}); +assert.throws(TypeError, function() { + Promise.any.call(fn6, []); +}, 'executor called with (Number, String)'); +assert.sameValue(checkPoint, 'ab', 'executor called with (Number, String)'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/capability-reject-throws-no-close.js b/js/src/tests/test262/built-ins/Promise/any/capability-reject-throws-no-close.js new file mode 100644 index 0000000000..db54029624 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/capability-reject-throws-no-close.js @@ -0,0 +1,69 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-promise.any +description: > + Iterator is not closed when the "resolve" capability returns an abrupt + completion. +info: | + Let C be the this value. + Let promiseCapability be ? NewPromiseCapability(C). + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + If result is an abrupt completion, then + If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + IfAbruptRejectPromise(result, promiseCapability). + Return Completion(result). + +flags: [async] +features: [Promise.any, Symbol.iterator] +---*/ +let callCount = 0; +let nextCount = 0; +let returnCount = 0; +let iter = { + [Symbol.iterator]() { + callCount++; + return { + next() { + callCount++ + nextCount++; + return { + done: true + }; + }, + return() { + callCount++; + returnCount++; + return {}; + } + }; + } +}; + +function P(executor) { + callCount++; + return new Promise((_, reject) => { + callCount++; + executor(() => { + callCount++; + $ERROR(); + }, () => { + callCount++; + reject(new Test262Error('reject throws')); + }); + }); +}; + +P.resolve = Promise.resolve; + +Promise.any.call(P, iter).then( + () => { + $DONE('The promise should be rejected.'); +}, (reason) => { + assert.sameValue(nextCount, 1); + assert.sameValue(returnCount, 0); + assert.sameValue(callCount, 5); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/capability-resolve-throws-no-close.js b/js/src/tests/test262/built-ins/Promise/any/capability-resolve-throws-no-close.js new file mode 100644 index 0000000000..16ac4d2f0c --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/capability-resolve-throws-no-close.js @@ -0,0 +1,69 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-promise.any +description: > + Iterator is not closed when the "resolve" capability returns an abrupt + completion. +info: | + Let C be the this value. + Let promiseCapability be ? NewPromiseCapability(C). + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + If result is an abrupt completion, then + If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + IfAbruptRejectPromise(result, promiseCapability). + Return Completion(result). + +flags: [async] +features: [Promise.any, Symbol.iterator] +---*/ +let callCount = 0; +let nextCount = 0; +let returnCount = 0; +let iter = { + [Symbol.iterator]() { + callCount++; + return { + next() { + callCount++; + nextCount += 1; + return { + done: true + }; + }, + return() { + callCount++; + returnCount += 1; + return {}; + } + }; + } +}; + +function P(executor) { + callCount++; + return new Promise((_, reject) => { + callCount++; + executor(() => { + callCount++; + throw new Test262Error(); + }, (...args) => { + callCount++; + reject(...args); + }); + }); +}; + +P.resolve = Promise.resolve; + +Promise.any.call(P, iter).then( + () => { + $DONE('The promise should be rejected.'); +}, (reason) => { + assert.sameValue(nextCount, 1); + assert.sameValue(returnCount, 0); + assert.sameValue(callCount, 5); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/capability-resolve-throws-reject.js b/js/src/tests/test262/built-ins/Promise/any/capability-resolve-throws-reject.js new file mode 100644 index 0000000000..0022473869 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/capability-resolve-throws-reject.js @@ -0,0 +1,50 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-promise.any +description: > + Iterator is not closed when the "resolve" capability returns an abrupt + completion. +info: | + Let C be the this value. + Let promiseCapability be ? NewPromiseCapability(C). + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + If result is an abrupt completion, then + If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + IfAbruptRejectPromise(result, promiseCapability). + Return Completion(result). + +features: [Promise.any, Symbol.iterator] +flags: [async] +---*/ +let callCount = 0; +let thrown = new Test262Error(); +function P(executor) { + callCount++; + return new Promise((_, reject) => { + callCount++; + executor(() => { + callCount++; + throw thrown; + }, (...args) => { + callCount++; + reject(...args); + }); + }); +}; +P.resolve = Promise.resolve; + +Promise.any.call(P, [1]) + .then(() => { + $DONE('Promise incorrectly fulfilled.'); + }, (error) => { + // The error was not the result of promise + // resolution, so will not be an AggregateError + assert.sameValue(thrown, error); + assert.sameValue(callCount, 6); + }).then($DONE, $DONE); + + diff --git a/js/src/tests/test262/built-ins/Promise/any/ctx-ctor-throws.js b/js/src/tests/test262/built-ins/Promise/any/ctx-ctor-throws.js new file mode 100644 index 0000000000..213ddb1822 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/ctx-ctor-throws.js @@ -0,0 +1,27 @@ +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Promise.any invoked on a constructor value that throws an error +esid: sec-promise.any +info: | + 2. Let promiseCapability be ? NewPromiseCapability(C). + + NewPromiseCapability + + ... + 7. Let promise be ? Construct(C, « executor »). + +features: [Promise.any] +---*/ + +function CustomPromise() { + throw new Test262Error(); +} + +assert.throws(Test262Error, function() { + Promise.any.call(CustomPromise); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/ctx-ctor.js b/js/src/tests/test262/built-ins/Promise/any/ctx-ctor.js new file mode 100644 index 0000000000..6331f05194 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/ctx-ctor.js @@ -0,0 +1,36 @@ +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Promise.any invoked on a constructor value +esid: sec-promise.any +info: | + 2. Let promiseCapability be ? NewPromiseCapability(C). + ... + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + ... + 7. Return Completion(result). +features: [Promise.any, class] +---*/ + +var executor = null; +var callCount = 0; + +class SubPromise extends Promise { + constructor(a) { + super(a); + executor = a; + callCount += 1; + } +} + +var instance = Promise.any.call(SubPromise, []); + +assert.sameValue(instance.constructor, SubPromise); +assert.sameValue(instance instanceof SubPromise, true); + +assert.sameValue(callCount, 1); +assert.sameValue(typeof executor, 'function'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/ctx-non-ctor.js b/js/src/tests/test262/built-ins/Promise/any/ctx-non-ctor.js new file mode 100644 index 0000000000..6901fb55e8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/ctx-non-ctor.js @@ -0,0 +1,25 @@ +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Promise.any invoked on a non-constructor value +esid: sec-promise.any +info: | + ... + 2. Let promiseCapability be ? NewPromiseCapability(C). + + NewPromiseCapability ( C ) + + 1. If IsConstructor(C) is false, throw a TypeError exception. + +features: [Promise.any, Symbol] +---*/ + +assert.sameValue(typeof Promise.any, 'function'); + +assert.throws(TypeError, function() { + Promise.any.call(eval); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/ctx-non-object.js b/js/src/tests/test262/built-ins/Promise/any/ctx-non-object.js new file mode 100644 index 0000000000..1633081d7b --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/ctx-non-object.js @@ -0,0 +1,43 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Promise.any invoked on a non-object value +esid: sec-promise.any +info: | + ... + 2. Let promiseCapability be ? NewPromiseCapability(C). + + NewPromiseCapability ( C ) + + 1. If IsConstructor(C) is false, throw a TypeError exception. + +features: [Promise.any, Symbol] +---*/ + +assert.throws(TypeError, function() { + Promise.any.call(undefined, []); +}); + +assert.throws(TypeError, function() { + Promise.any.call(null, []); +}); + +assert.throws(TypeError, function() { + Promise.any.call(86, []); +}); + +assert.throws(TypeError, function() { + Promise.any.call('string', []); +}); + +assert.throws(TypeError, function() { + Promise.any.call(true, []); +}); + +assert.throws(TypeError, function() { + Promise.any.call(Symbol(), []); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-error-close.js b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-error-close.js new file mode 100644 index 0000000000..fd9d4b2d34 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-error-close.js @@ -0,0 +1,54 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Explicit iterator closing in response to error +esid: sec-promise.any +info: | + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + 6. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + 8. Repeat + ... + i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). +flags: [async] +features: [Promise.any, Symbol.iterator, computed-property-names, Symbol, arrow-function] +---*/ + +let error = new Test262Error(); +let nextCount = 0; +let returnCount = 0; +let iter = { + [Symbol.iterator]() { + return { + next() { + nextCount += 1; + return { + value: null, + done: false + }; + }, + return() { + returnCount += 1; + } + }; + } +}; + +Promise.resolve = function() { + throw error; +}; + +Promise.any(iter).then(() => { + $DONE('The promise should be rejected, but was resolved'); +}, (reason) => { + assert.sameValue(nextCount, 1); + assert.sameValue(returnCount, 1); + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-error-reject.js b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-error-reject.js new file mode 100644 index 0000000000..9248d0e87e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-error-reject.js @@ -0,0 +1,33 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Promise rejection in response to error +esid: sec-promise.any +info: | + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + 6. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + 8. Repeat + ... + i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + +flags: [async] +features: [Promise.any, arrow-function] +---*/ + +let error = new Test262Error(); +Promise.resolve = function() { + throw error; +}; + +Promise.any([1]).then(() => { + $DONE('The promise should be rejected, but was resolved'); + }, (reason) => { + assert.sameValue(reason, error); + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-get-error-reject.js b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-get-error-reject.js new file mode 100644 index 0000000000..175660e0c7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-get-error-reject.js @@ -0,0 +1,36 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Error retrieving the constructor's `resolve` method (rejecting promise) +esid: sec-promise.any +info: | + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + 6. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + 8. Repeat + ... + i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + +flags: [async] +features: [Promise.any, arrow-function] +---*/ + +let error = new Test262Error(); +Object.defineProperty(Promise, 'resolve', { + get() { + throw error; + } +}); + +Promise.any([1]).then(() => { + $DONE('The promise should be rejected, but was resolved'); + }, (reason) => { + assert.sameValue(reason, error); + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-get-error.js b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-get-error.js new file mode 100644 index 0000000000..976571edad --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-get-error.js @@ -0,0 +1,41 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Promise.resolve is retrieved before GetIterator call (abrupt lookup). +info: | + Promise.any ( iterable ) + + [...] + 3. Let promiseResolve be GetPromiseResolve(C). + 4. IfAbruptRejectPromise(promiseResolve, promiseCapability). + + GetPromiseResolve ( promiseConstructor ) + + [...] + 2. Let promiseResolve be ? Get(promiseConstructor, "resolve"). +flags: [async] +features: [Promise.any, Symbol.iterator] +---*/ + +const iter = { + get [Symbol.iterator]() { + throw new Test262Error('unreachable'); + }, +}; + +const resolveError = { name: 'MyError' }; +Object.defineProperty(Promise, 'resolve', { + get() { + throw resolveError; + }, +}); + +Promise.any(iter).then(() => { + throw new Test262Error('The promise should be rejected, but it was resolved'); +}, (reason) => { + assert.sameValue(reason, resolveError); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-get-once-multiple-calls.js b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-get-once-multiple-calls.js new file mode 100644 index 0000000000..1db5628464 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-get-once-multiple-calls.js @@ -0,0 +1,55 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Gets constructor's `resolve` method once from zero to many invocations. +esid: sec-promise.any +info: | + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + 6. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + 6. Let promiseResolve be ? Get(constructor, "resolve"). + 7. If ! IsCallable(promiseResolve) is false, throw a TypeError exception. + 8. Repeat + ... + i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + +flags: [async] +features: [Promise.any, arrow-function, destructuring-binding] +---*/ + +let promises = [ + Promise.reject(1), + Promise.reject(1), + Promise.reject(1), +]; +let boundPromiseResolve = Promise.resolve.bind(Promise); +let getCount = 0; +let callCount = 0; + +Object.defineProperty(Promise, 'resolve', { + configurable: true, + get() { + getCount += 1; + return function(...args) { + callCount += 1; + return boundPromiseResolve(...args); + }; + } +}); + +Promise.any(promises).then(() => { + $DONE('The promise should be rejected, but was resolved'); + }, ({errors}) => { + assert.sameValue(getCount, 1); + assert.sameValue(callCount, 3); + assert.sameValue(errors.length, 3); + }).then($DONE, $DONE); + + diff --git a/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-get-once-no-calls.js b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-get-once-no-calls.js new file mode 100644 index 0000000000..28ad29b19f --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-get-once-no-calls.js @@ -0,0 +1,50 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Gets constructor's `resolve` method once from zero to many invocations. +esid: sec-promise.any +info: | + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + 6. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + 6. Let promiseResolve be ? Get(constructor, "resolve"). + 7. If ! IsCallable(promiseResolve) is false, throw a TypeError exception. + 8. Repeat + ... + i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + +flags: [async] +features: [Promise.any, arrow-function, destructuring-binding] +---*/ + +let boundPromiseResolve = Promise.resolve.bind(Promise); +let getCount = 0; +let callCount = 0; + +Object.defineProperty(Promise, 'resolve', { + configurable: true, + get() { + getCount += 1; + return function(...args) { + callCount += 1; + return boundPromiseResolve(...args); + }; + } +}); + +Promise.any([]).then(() => { + $DONE('The promise should be rejected, but was resolved'); + }, ({errors}) => { + assert.sameValue(getCount, 1); + assert.sameValue(callCount, 0); + assert.sameValue(errors.length, 0); + }).then($DONE, $DONE); + + diff --git a/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-on-promises-every-iteration-of-custom.js b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-on-promises-every-iteration-of-custom.js new file mode 100644 index 0000000000..5a8e758a57 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-on-promises-every-iteration-of-custom.js @@ -0,0 +1,44 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Invocation of the constructor's `resolve` method for iterable with promise values +esid: sec-promise.any +info: | + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + 8. Repeat + ... + i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + +flags: [async] +features: [Promise.any, class, arrow-function] +---*/ +class Custom extends Promise {} + +let values = [1, 1, 1]; +let cresolveCallCount = 0; +let presolveCallCount = 0; +let boundCustomResolve = Custom.resolve.bind(Custom); +let boundPromiseResolve = Promise.resolve.bind(Promise); + +Custom.resolve = function(...args) { + cresolveCallCount += 1; + return boundCustomResolve(...args); +}; + +Promise.resolve = function(...args) { + presolveCallCount += 1; + return boundPromiseResolve(...args); +}; + +Promise.any.call(Custom, values) + .then(() => { + assert.sameValue(presolveCallCount, 0, '`Promise.resolve` is never invoked'); + assert.sameValue(cresolveCallCount, 3, '`Custom.resolve` invoked once for every iterated promise'); + }).then($DONE, $DONE); + diff --git a/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-on-promises-every-iteration-of-promise.js b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-on-promises-every-iteration-of-promise.js new file mode 100644 index 0000000000..337fcbd903 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-on-promises-every-iteration-of-promise.js @@ -0,0 +1,35 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Invocation of the constructor's `resolve` method for iterable with promise values +esid: sec-promise.any +info: | + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + 8. Repeat + ... + i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + +flags: [async] +features: [Promise.any, arrow-function] +---*/ + +let values = [1,1,1]; +let callCount = 0; +let boundPromiseResolve = Promise.resolve.bind(Promise); + +Promise.resolve = function(...args) { + callCount += 1; + return boundPromiseResolve(...args); +}; + +Promise.any(values) + .then(() => { + assert.sameValue(callCount, 3, '`then` invoked once for every iterated promise'); + }).then($DONE, $DONE); + diff --git a/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-on-values-every-iteration-of-custom.js b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-on-values-every-iteration-of-custom.js new file mode 100644 index 0000000000..83955852c6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-on-values-every-iteration-of-custom.js @@ -0,0 +1,44 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Invocation of the constructor's `resolve` method for iterable with non-promise values +esid: sec-promise.any +info: | + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + 8. Repeat + ... + i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + +flags: [async] +features: [Promise.any, class, arrow-function] +---*/ +class Custom extends Promise {} + +let values = [1, 2, 3]; +let cresolveCallCount = 0; +let presolveCallCount = 0; +let boundCustomResolve = Custom.resolve.bind(Custom); +let boundPromiseResolve = Promise.resolve.bind(Promise); + +Custom.resolve = function(...args) { + cresolveCallCount += 1; + return boundCustomResolve(...args); +}; + +Promise.resolve = function(...args) { + presolveCallCount += 1; + return boundPromiseResolve(...args); +}; + +Promise.any.call(Custom, values) + .then(() => { + assert.sameValue(presolveCallCount, 0, '`Promise.resolve` is never invoked'); + assert.sameValue(cresolveCallCount, 3, '`Custom.resolve` invoked once for every iterated promise'); + }).then($DONE, $DONE); + diff --git a/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-on-values-every-iteration-of-promise.js b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-on-values-every-iteration-of-promise.js new file mode 100644 index 0000000000..c4babbf46b --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-on-values-every-iteration-of-promise.js @@ -0,0 +1,35 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Invocation of the constructor's `resolve` method for iterable with non-promise values +esid: sec-promise.any +info: | + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + 8. Repeat + ... + i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + +flags: [async] +features: [Promise.any, arrow-function] +---*/ + +let values = [1, 2, 3]; +let callCount = 0; +let boundPromiseResolve = Promise.resolve.bind(Promise); + +Promise.resolve = function(...args) { + callCount += 1; + return boundPromiseResolve(...args); +}; + +Promise.any(values) + .then(() => { + assert.sameValue(callCount, 3, '`Promise.resolve` invoked once for every iterated value'); + }).then($DONE, $DONE); + diff --git a/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-return.js b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-return.js new file mode 100644 index 0000000000..ba5bd6be67 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve-return.js @@ -0,0 +1,45 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Use of the value returned by the constructor's `resolve` method. +esid: sec-promise.any +info: | + Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + + PerformPromiseAny + + Repeat + ... + i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + ... + r. Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], rejectElement »). + +features: [Promise.any] +---*/ + +let originalCallCount = 0; +let newCallCount = 0; +let P = function(executor) { + executor(function() {}, function() {}); +}; +P.resolve = function() { + return newThenable; +}; + +let originalThenable = { + then() { + originalCallCount += 1; + } +}; +let newThenable = { + then() { + newCallCount += 1; + } +}; + +Promise.any.call(P, [originalThenable]); + +assert.sameValue(originalCallCount, 0, 'original `then` method not invoked'); +assert.sameValue(newCallCount, 1, 'new `then` method invoked exactly once'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/invoke-resolve.js b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve.js new file mode 100644 index 0000000000..0fcabbf684 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/invoke-resolve.js @@ -0,0 +1,32 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Invocation of the constructor's `resolve` method +esid: sec-promise.any +info: | + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + 8. Repeat + ... + i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). + ... + r. Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], rejectElement »). + +flags: [async] +features: [Promise.any, arrow-function] +---*/ + +let boundPromiseResolve = Promise.resolve.bind(Promise); + +Promise.resolve = function(...args) { + assert.sameValue(args.length, 1, '`resolve` invoked with a single argument'); + assert.sameValue(this, Promise, '`this` value is the constructor'); + return boundPromiseResolve(...args); +}; + +Promise.any([1]).then(() => $DONE(), $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/invoke-then-error-close.js b/js/src/tests/test262/built-ins/Promise/any/invoke-then-error-close.js new file mode 100644 index 0000000000..716430d349 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/invoke-then-error-close.js @@ -0,0 +1,51 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Error thrown when invoking the instance's `then` method (closing iterator) +esid: sec-promise.any +info: | + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + 6. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + r. Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], rejectElement »). + +flags: [async] +features: [Promise.any, Symbol.iterator, arrow-function, computed-property-names, Symbol] +---*/ + +let error = new Test262Error(); +let promise = Promise.resolve(); +let returnCount = 0; +let iter = { + [Symbol.iterator]() { + return { + next() { + return { + done: false, + value: promise + }; + }, + return() { + returnCount += 1; + return {}; + } + }; + } +}; + +promise.then = function() { + throw error; +}; + +Promise.any(iter).then(() => { + $DONE('The promise should be rejected, but was resolved'); +}, (reason) => { + assert.sameValue(returnCount, 1); + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/invoke-then-error-reject.js b/js/src/tests/test262/built-ins/Promise/any/invoke-then-error-reject.js new file mode 100644 index 0000000000..ca7ab8054c --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/invoke-then-error-reject.js @@ -0,0 +1,33 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Error thrown when invoking the instance's `then` method (rejecting Promise) +esid: sec-promise.any +info: | + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + 6. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + r. Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], rejectElement »). + +flags: [async] +features: [Promise.any, arrow-function] +---*/ +let error = new Test262Error(); +let promise = Promise.resolve(); + +promise.then = function() { + throw error; +}; + +Promise.any([promise]).then(() => { + $DONE('The promise should be rejected, but was resolved'); +}, (reason) => { + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/invoke-then-get-error-close.js b/js/src/tests/test262/built-ins/Promise/any/invoke-then-get-error-close.js new file mode 100644 index 0000000000..c40020e48b --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/invoke-then-get-error-close.js @@ -0,0 +1,52 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Error thrown when accesing the instance's `then` method (closing iterator) +esid: sec-promise.any +info: | + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + 6. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + r. Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], rejectElement »). + +flags: [async] +features: [Promise.any, Symbol.iterator, arrow-function, computed-property-names, Symbol] +---*/ +let error = new Test262Error(); +let promise = Promise.resolve(); +let returnCount = 0; +let iter = { + [Symbol.iterator]() { + return { + next() { + return { + done: false, + value: promise + }; + }, + return() { + returnCount += 1; + return {}; + } + }; + } +}; + +Object.defineProperty(promise, 'then', { + get() { + throw error; + } +}); + +Promise.any(iter).then(() => { + $DONE('The promise should be rejected, but was resolved'); +}, (reason) => { + assert.sameValue(returnCount, 1); + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/invoke-then-get-error-reject.js b/js/src/tests/test262/built-ins/Promise/any/invoke-then-get-error-reject.js new file mode 100644 index 0000000000..9c42b8a7a2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/invoke-then-get-error-reject.js @@ -0,0 +1,34 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Error thrown when accessing the instance's `then` method (rejecting Promise) +esid: sec-promise.any +info: | + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + 6. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + r. Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], rejectElement »). + +flags: [async] +features: [Promise.any, arrow-function] +---*/ +let error = new Test262Error(); +let promise = Promise.resolve(); + +Object.defineProperty(promise, 'then', { + get() { + throw error; + } +}); + +Promise.any([promise]).then(() => { + $DONE('The promise should be rejected, but was resolved'); +}, (reason) => { + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/invoke-then-on-promises-every-iteration.js b/js/src/tests/test262/built-ins/Promise/any/invoke-then-on-promises-every-iteration.js new file mode 100644 index 0000000000..5b12329106 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/invoke-then-on-promises-every-iteration.js @@ -0,0 +1,42 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Invocation of the instance's `then` method +esid: sec-promise.any +info: | + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + 6. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + r. Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], rejectElement »). + +flags: [async] +features: [Promise.any, arrow-function] +---*/ + +let promises = [ + Promise.resolve(), + Promise.resolve(), + Promise.resolve(), +]; +let callCount = 0; + +promises.forEach(promise => { + let boundThen = promise.then.bind(promise); + promise.then = function(...args) { + assert.sameValue(this, promises[callCount]); + callCount += 1; + return boundThen(...args); + }; +}); + +Promise.any(promises) + .then(() => { + assert.sameValue(callCount, 3, '`then` invoked once for every iterated value'); + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/invoke-then.js b/js/src/tests/test262/built-ins/Promise/any/invoke-then.js new file mode 100644 index 0000000000..5674ea8ecb --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/invoke-then.js @@ -0,0 +1,40 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Invocation of the instance's `then` method +esid: sec-promise.any +info: | + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + 6. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + r. Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], rejectElement »). + +flags: [async] +features: [Promise.any, arrow-function] +---*/ + +let promise = Promise.resolve(); +let boundThen = promise.then.bind(promise); +let callCount = 0; + +promise.then = function(resolver, rejectElement) { + assert.sameValue(this, promise); + assert.sameValue(typeof resolver, 'function'); + assert.sameValue(resolver.length, 1, 'resolver.length is 1'); + assert.sameValue(typeof rejectElement, 'function'); + assert.sameValue(rejectElement.length, 1, 'rejectElement.length is 0'); + callCount++; + return boundThen(resolver, rejectElement); +}; + +Promise.any([promise]).then(() => { + assert.sameValue(callCount, 1); + $DONE(); +}, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/is-function.js b/js/src/tests/test262/built-ins/Promise/any/is-function.js new file mode 100644 index 0000000000..4abe039b5d --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/is-function.js @@ -0,0 +1,12 @@ +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: Promise.any is callable +features: [Promise.any] +---*/ + +assert.sameValue(typeof Promise.any, 'function'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-empty-iterable-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-empty-iterable-reject.js new file mode 100644 index 0000000000..d9f9eba172 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-empty-iterable-reject.js @@ -0,0 +1,40 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Promise.any([]) rejects with AggregateError, empty errors array. +info: | + Runtime Semantics: PerformPromiseAny ( iteratorRecord, constructor, resultCapability ) + + ... + 3. Let errors be a new empty List. + ... + 8. Repeat, + a. Let next be IteratorStep(iteratorRecord). + b. If next is an abrupt completion, set iteratorRecord.[[Done]] to true. + c. ReturnIfAbrupt(next). + d. If next is false, then + i. Set iteratorRecord.[[Done]] to true. + ii. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1. + iii. If remainingElementsCount.[[Value]] is 0, then + 1. Let error be a newly created AggregateError object. + 2. Set error.[[AggregateErrors]] to errors. + 3. Return ThrowCompletion(error). + ... + +flags: [async] +features: [AggregateError, Promise.any, arrow-function] +---*/ + +Promise.any([]) + .then( + () => $DONE('The promise should be rejected, but was resolved'), + error => { + assert.sameValue(Object.getPrototypeOf(error), AggregateError.prototype); + assert(error instanceof AggregateError); + assert.sameValue(error.errors.length, 0); + } + ).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-empty-string-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-empty-string-reject.js new file mode 100644 index 0000000000..0c2eeabd2f --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-empty-string-reject.js @@ -0,0 +1,40 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Promise.any('') rejects with AggregateError, empty errors array. +info: | + Runtime Semantics: PerformPromiseAny ( iteratorRecord, constructor, resultCapability ) + + ... + 3. Let errors be a new empty List. + ... + 8. Repeat, + a. Let next be IteratorStep(iteratorRecord). + b. If next is an abrupt completion, set iteratorRecord.[[Done]] to true. + c. ReturnIfAbrupt(next). + d. If next is false, then + i. Set iteratorRecord.[[Done]] to true. + ii. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1. + iii. If remainingElementsCount.[[Value]] is 0, then + 1. Let error be a newly created AggregateError object. + 2. Set error.[[AggregateErrors]] to errors. + 3. Return ThrowCompletion(error). + ... + +features: [AggregateError, Promise.any, arrow-function] +flags: [async] +---*/ + +Promise.any('') + .then( + () => $DONE('The promise should be rejected, but was resolved'), + error => { + assert.sameValue(Object.getPrototypeOf(error), AggregateError.prototype); + assert(error instanceof AggregateError); + assert.sameValue(error.errors.length, 0); + } + ).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-error-object-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-error-object-reject.js new file mode 100644 index 0000000000..b24b240e8d --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-error-object-reject.js @@ -0,0 +1,45 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Promise.any(new Test262Error()) rejects with TypeError. +info: | + Promise.any ( iterable ) + + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.any] +flags: [async] +---*/ + +try { + Promise.any(new Test262Error()).then(() => { + $DONE('The promise should be rejected, but was resolved'); + }, (error) => { + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-false-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-false-reject.js new file mode 100644 index 0000000000..b0f288363a --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-false-reject.js @@ -0,0 +1,37 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Promise.any(false) rejects with TypeError. +info: | + Promise.any ( iterable ) + + ... + 3. Let iteratorRecord be GetIterator(iterable). + 4. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Promise.any] +flags: [async] +---*/ + +try { + Promise.any(false).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-null-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-null-reject.js new file mode 100644 index 0000000000..9497e08423 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-null-reject.js @@ -0,0 +1,37 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Promise.any(null) rejects with TypeError. +info: | + Promise.any ( iterable ) + + ... + 3. Let iteratorRecord be GetIterator(iterable). + 4. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Promise.any] +flags: [async] +---*/ + +try { + Promise.any(null).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-number-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-number-reject.js new file mode 100644 index 0000000000..011b1c996a --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-number-reject.js @@ -0,0 +1,37 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Promise.any(number) rejects with TypeError. +info: | + Promise.any ( iterable ) + + ... + 3. Let iteratorRecord be GetIterator(iterable). + 4. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Promise.any] +flags: [async] +---*/ + +try { + Promise.any(1).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-poisoned.js b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-poisoned.js new file mode 100644 index 0000000000..6c45a22dd1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-poisoned.js @@ -0,0 +1,43 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Promise.any(poisoned iterable) rejects with whatever error is thrown. +info: | + Promise.any ( iterable ) + + ... + 3. Let iteratorRecord be GetIterator(iterable). + 4. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + ... +features: [Promise.any, Symbol, Symbol.iterator, arrow-function] +flags: [async] +---*/ + +var poison = []; +Object.defineProperty(poison, Symbol.iterator, { + get() { + throw new Test262Error(); + } +}); + +try { + Promise.any(poison).then(() => { + $DONE('The promise should be rejected, but was resolved'); + }, (error) => { + assert.sameValue(Object.getPrototypeOf(error), Test262Error.prototype); + assert(error instanceof Test262Error); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-string-resolve.js b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-string-resolve.js new file mode 100644 index 0000000000..f2009851b4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-string-resolve.js @@ -0,0 +1,37 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Promise.any('non-empty-string') resolves with the first character in the non-empty string +info: | + Promise.any ( iterable ) + + ... + 3. Let iteratorRecord be GetIterator(iterable). + 4. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Promise.any, arrow-function] +flags: [async] +---*/ + +try { + Promise.any('xyz').then(v => { + assert.sameValue(v, 'x'); + assert.sameValue(v.length, 1); + }, error => { + $DONE(`The promise should be resolved, but was rejected with error: ${error.message}`); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be resolved, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-symbol-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-symbol-reject.js new file mode 100644 index 0000000000..563fc47b95 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-symbol-reject.js @@ -0,0 +1,50 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Promise.any(Symbol()) rejects with TypeError. +info: | + Promise.any ( iterable ) + + ... + 3. Let iteratorRecord be GetIterator(iterable). + 4. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + 3. If method is not present, then + a. If hint is async, then + ... + b. Otherwise, set method to ? GetMethod(obj, @@iterator). + 4. Let iterator be ? Call(method, obj). + 5. If Type(iterator) is not Object, throw a TypeError exception. + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.any, Symbol] +flags: [async] +---*/ + +try { + Promise.any(Symbol()).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-true-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-true-reject.js new file mode 100644 index 0000000000..7986819d06 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-true-reject.js @@ -0,0 +1,50 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Promise.any(true) rejects with TypeError. +info: | + Promise.any ( iterable ) + + ... + 3. Let iteratorRecord be GetIterator(iterable). + 4. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + 3. If method is not present, then + a. If hint is async, then + ... + b. Otherwise, set method to ? GetMethod(obj, @@iterator). + 4. Let iterator be ? Call(method, obj). + 5. If Type(iterator) is not Object, throw a TypeError exception. + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.any] +flags: [async] +---*/ + +try { + Promise.any(true).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-undefined-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-undefined-reject.js new file mode 100644 index 0000000000..1fc2f71b7e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-arg-is-undefined-reject.js @@ -0,0 +1,50 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Promise.any(undefined) rejects with TypeError. +info: | + Promise.any ( iterable ) + + ... + 3. Let iteratorRecord be GetIterator(iterable). + 4. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + 3. If method is not present, then + a. If hint is async, then + ... + b. Otherwise, set method to ? GetMethod(obj, @@iterator). + 4. Let iterator be ? Call(method, obj). + 5. If Type(iterator) is not Object, throw a TypeError exception. + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.any] +flags: [async] +---*/ + +try { + Promise.any(undefined).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-assigned-false-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-assigned-false-reject.js new file mode 100644 index 0000000000..3bbbea0929 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-assigned-false-reject.js @@ -0,0 +1,54 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Reject when argument's Symbol.iterator property has the value false +info: | + Promise.any ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + 3. If method is not present, then + a. If hint is async, then + i. Set method to ? GetMethod(obj, @@asyncIterator). + ii. If method is undefined, then + 1. Let syncMethod be ? GetMethod(obj, @@iterator). + 2. Let syncIteratorRecord be ? GetIterator(obj, sync, syncMethod). + ... + 4. Let iterator be ? Call(method, obj). + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.any, Symbol.iterator, Symbol, computed-property-names] +flags: [async] +---*/ + +try { + Promise.any({ + [Symbol.iterator]: false + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-assigned-null-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-assigned-null-reject.js new file mode 100644 index 0000000000..f7d25a88fe --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-assigned-null-reject.js @@ -0,0 +1,52 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Reject when argument's Symbol.iterator property has the value null +info: | + Promise.any ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + 3. If method is not present, then + a. If hint is async, then + ... + b. Otherwise, set method to ? GetMethod(obj, @@iterator). + 4. Let iterator be ? Call(method, obj). + 5. If Type(iterator) is not Object, throw a TypeError exception. + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.any, Symbol.iterator, Symbol, computed-property-names] +flags: [async] +---*/ + +try { + Promise.any({ + [Symbol.iterator]: null + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-assigned-number-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-assigned-number-reject.js new file mode 100644 index 0000000000..f304043058 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-assigned-number-reject.js @@ -0,0 +1,52 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Reject when argument's Symbol.iterator property has the value 1 +info: | + Promise.any ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + 3. If method is not present, then + a. If hint is async, then + ... + b. Otherwise, set method to ? GetMethod(obj, @@iterator). + 4. Let iterator be ? Call(method, obj). + 5. If Type(iterator) is not Object, throw a TypeError exception. + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.any, Symbol.iterator, Symbol, computed-property-names] +flags: [async] +---*/ + +try { + Promise.any({ + [Symbol.iterator]: 1 + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-assigned-string-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-assigned-string-reject.js new file mode 100644 index 0000000000..f5444280cf --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-assigned-string-reject.js @@ -0,0 +1,52 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Reject when argument's Symbol.iterator property has the value "" +info: | + Promise.any ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + 3. If method is not present, then + a. If hint is async, then + ... + b. Otherwise, set method to ? GetMethod(obj, @@iterator). + 4. Let iterator be ? Call(method, obj). + 5. If Type(iterator) is not Object, throw a TypeError exception. + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.any, Symbol.iterator, Symbol, computed-property-names] +flags: [async] +---*/ + +try { + Promise.any({ + [Symbol.iterator]: '' + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-assigned-symbol-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-assigned-symbol-reject.js new file mode 100644 index 0000000000..748b8b780a --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-assigned-symbol-reject.js @@ -0,0 +1,52 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Reject when argument's Symbol.iterator property has the value Symbol() +info: | + Promise.any ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + 3. If method is not present, then + a. If hint is async, then + ... + b. Otherwise, set method to ? GetMethod(obj, @@iterator). + 4. Let iterator be ? Call(method, obj). + 5. If Type(iterator) is not Object, throw a TypeError exception. + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.any, Symbol, Symbol.iterator, computed-property-names] +flags: [async] +---*/ + +try { + Promise.any({ + [Symbol.iterator]: Symbol() + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-assigned-true-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-assigned-true-reject.js new file mode 100644 index 0000000000..32871ce869 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-assigned-true-reject.js @@ -0,0 +1,52 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Reject when argument's Symbol.iterator property has the value true +info: | + Promise.any ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + 3. If method is not present, then + a. If hint is async, then + ... + b. Otherwise, set method to ? GetMethod(obj, @@iterator). + 4. Let iterator be ? Call(method, obj). + 5. If Type(iterator) is not Object, throw a TypeError exception. + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.any, Symbol.iterator, Symbol, computed-property-names] +flags: [async] +---*/ + +try { + Promise.any({ + [Symbol.iterator]: true + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-assigned-undefined-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-assigned-undefined-reject.js new file mode 100644 index 0000000000..48918756b3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-assigned-undefined-reject.js @@ -0,0 +1,52 @@ +// |reftest| async +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Reject when argument's Symbol.iterator property has the value undefined +info: | + Promise.any ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + 3. If method is not present, then + a. If hint is async, then + ... + b. Otherwise, set method to ? GetMethod(obj, @@iterator). + 4. Let iterator be ? Call(method, obj). + 5. If Type(iterator) is not Object, throw a TypeError exception. + ... + + GetMethod + + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + 4. If IsCallable(func) is false, throw a TypeError exception. + + Call ( F, V [ , argumentsList ] ) + + 2. If IsCallable(F) is false, throw a TypeError exception. +features: [Promise.any, Symbol.iterator, Symbol, computed-property-names] +flags: [async] +---*/ + +try { + Promise.any({ + [Symbol.iterator]: undefined + }).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(error) { + assert.sameValue(Object.getPrototypeOf(error), TypeError.prototype); + assert(error instanceof TypeError); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-next-val-err-no-close.js b/js/src/tests/test262/built-ins/Promise/any/iter-next-val-err-no-close.js new file mode 100644 index 0000000000..73bd0c5724 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-next-val-err-no-close.js @@ -0,0 +1,64 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Error when accessing an iterator result's `value` property (not closing + iterator) +info: | + Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + If result is an abrupt completion, then + If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + IfAbruptRejectPromise(result, promiseCapability). + + ... + + Runtime Semantics: PerformPromiseAny + + ... + Repeat + Let nextValue be IteratorValue(next). + If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true. + ReturnIfAbrupt(nextValue). + +features: [Promise.any, Symbol.iterator] +flags: [async] +---*/ +let callCount = 0; +let returnCount = 0; +let error = new Test262Error(); +let poisoned = { + done: false +}; +Object.defineProperty(poisoned, 'value', { + get() { + callCount++; + throw error; + } +}); +let iterNextValThrows = { + [Symbol.iterator]() { + callCount++; + return { + next() { + callCount++; + return poisoned; + }, + return() { + returnCount++; + return {}; + } + }; + } +}; + +Promise.any(iterNextValThrows).then(() => { + $DONE('The promise should be rejected, but was resolved'); +}, (reason) => { + assert(error instanceof Test262Error); + assert.sameValue(reason, error); + assert.sameValue(callCount, 3, 'callCount === 3'); + assert.sameValue(returnCount, 0); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-next-val-err-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-next-val-err-reject.js new file mode 100644 index 0000000000..fe36877a63 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-next-val-err-reject.js @@ -0,0 +1,58 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Error when accessing an iterator result's `value` property (rejecting + promise) +info: | + Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + If result is an abrupt completion, then + If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + IfAbruptRejectPromise(result, promiseCapability). + + ... + + Runtime Semantics: PerformPromiseAny + + ... + Repeat + Let nextValue be IteratorValue(next). + If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true. + ReturnIfAbrupt(nextValue). + +features: [Promise.any, Symbol.iterator] +flags: [async] +---*/ +let callCount = 0; +let error = new Test262Error(); +let poisoned = { + done: false +}; +Object.defineProperty(poisoned, 'value', { + get() { + callCount++; + throw error; + } +}); +let iterNextValThrows = { + [Symbol.iterator]() { + callCount++; + return { + next() { + callCount++; + return poisoned; + } + }; + } +}; + +Promise.any(iterNextValThrows).then(() => { + $DONE('The promise should be rejected, but was resolved'); +}, (reason) => { + assert(error instanceof Test262Error); + assert.sameValue(reason, error); + assert.sameValue(callCount, 3, 'callCount === 3'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-returns-false-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-returns-false-reject.js new file mode 100644 index 0000000000..19657b6ceb --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-returns-false-reject.js @@ -0,0 +1,37 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Reject when argument's Symbol.iterator returns false +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... + +features: [Promise.any, Symbol.iterator] +flags: [async] +---*/ + +let callCount = 0; +Promise.any({ + [Symbol.iterator]() { + callCount++; + return false; + } +}).then(() => { + $DONE('The promise should be rejected, but was resolved'); +}, (error) => { + assert.sameValue(callCount, 1, 'callCount === 1'); + assert(error instanceof TypeError); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-returns-null-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-returns-null-reject.js new file mode 100644 index 0000000000..de20333f61 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-returns-null-reject.js @@ -0,0 +1,37 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Reject when argument's Symbol.iterator returns null +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... + +features: [Promise.any, Symbol.iterator] +flags: [async] +---*/ + +let callCount = 0; +Promise.any({ + [Symbol.iterator]() { + callCount++; + return null; + } +}).then(() => { + $DONE('The promise should be rejected, but was resolved'); +}, (error) => { + assert.sameValue(callCount, 1, 'callCount === 1'); + assert(error instanceof TypeError); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-returns-number-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-returns-number-reject.js new file mode 100644 index 0000000000..c6a68b81e6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-returns-number-reject.js @@ -0,0 +1,36 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Reject when argument's Symbol.iterator returns number +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Promise.any, Symbol.iterator] +flags: [async] +---*/ + +let callCount = 0; +Promise.any({ + [Symbol.iterator]() { + callCount++; + return 1; + } +}).then(() => { + $DONE('The promise should be rejected, but was resolved'); +}, (error) => { + assert.sameValue(callCount, 1, 'callCount === 1'); + assert(error instanceof TypeError); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-returns-string-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-returns-string-reject.js new file mode 100644 index 0000000000..645a021a1a --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-returns-string-reject.js @@ -0,0 +1,36 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Reject when argument's Symbol.iterator returns string +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Promise.any, Symbol.iterator] +flags: [async] +---*/ + +let callCount = 0; +Promise.any({ + [Symbol.iterator]() { + callCount++; + return ''; + } +}).then(() => { + $DONE('The promise should be rejected, but was resolved'); +}, (error) => { + assert.sameValue(callCount, 1, 'callCount === 1'); + assert(error instanceof TypeError); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-returns-symbol-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-returns-symbol-reject.js new file mode 100644 index 0000000000..b581992441 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-returns-symbol-reject.js @@ -0,0 +1,36 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Reject when argument's Symbol.iterator returns symbol +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Promise.any, Symbol.iterator] +flags: [async] +---*/ + +let callCount = 0; +Promise.any({ + [Symbol.iterator]() { + callCount++; + return Symbol(); + } +}).then(() => { + $DONE('The promise should be rejected, but was resolved'); +}, (error) => { + assert.sameValue(callCount, 1, 'callCount === 1'); + assert(error instanceof TypeError); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-returns-true-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-returns-true-reject.js new file mode 100644 index 0000000000..9fe8abd861 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-returns-true-reject.js @@ -0,0 +1,36 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Reject when argument's Symbol.iterator returns true +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Promise.any, Symbol.iterator] +flags: [async] +---*/ + +let callCount = 0; +Promise.any({ + [Symbol.iterator]() { + callCount++; + return true; + } +}).then(() => { + $DONE('The promise should be rejected, but was resolved'); +}, (error) => { + assert.sameValue(callCount, 1, 'callCount === 1'); + assert(error instanceof TypeError); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-returns-undefined-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-returns-undefined-reject.js new file mode 100644 index 0000000000..9d74e6a485 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-returns-undefined-reject.js @@ -0,0 +1,36 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Reject when argument's Symbol.iterator returns undefined +info: | + ... + Let iteratorRecord be GetIterator(iterable). + IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + If Type(iterator) is not Object, throw a TypeError exception. + ... +features: [Promise.any, Symbol.iterator] +flags: [async] +---*/ + +let callCount = 0; +Promise.any({ + [Symbol.iterator]() { + callCount++; + return undefined; + } +}).then(() => { + $DONE('The promise should be rejected, but was resolved'); +}, (error) => { + assert.sameValue(callCount, 1, 'callCount === 1'); + assert(error instanceof TypeError); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-step-err-no-close.js b/js/src/tests/test262/built-ins/Promise/any/iter-step-err-no-close.js new file mode 100644 index 0000000000..5dd1fd162e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-step-err-no-close.js @@ -0,0 +1,61 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Error when advancing the provided iterable (not closing iterator) +info: | + Promise.any ( iterable ) + + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + 6. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + 8. Repeat + a. Let next be IteratorStep(iteratorRecord). + b. If next is an abrupt completion, set iteratorRecord.[[done]] to true. + c. ReturnIfAbrupt(next). + +flags: [async] +features: [Promise.any, Symbol.iterator, computed-property-names, Symbol, arrow-function] +---*/ + +let returnCount = 0; +let poisonedDone = {}; +let error = new Test262Error(); +Object.defineProperties(poisonedDone, { + done: { + get() { + throw error; + } + }, + value: { + get() {} + } +}); +let iterStepThrows = { + [Symbol.iterator]() { + return { + next() { + return poisonedDone; + }, + return() { + returnCount += 1; + return {}; + } + }; + } +}; + +Promise.any(iterStepThrows).then( + () => { + $DONE('The promise should be rejected.'); +}, (reason) => { + assert.sameValue(reason, error); + assert.sameValue(returnCount, 0); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/iter-step-err-reject.js b/js/src/tests/test262/built-ins/Promise/any/iter-step-err-reject.js new file mode 100644 index 0000000000..7f3fbe4ad9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/iter-step-err-reject.js @@ -0,0 +1,57 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Error when advancing the provided iterable (rejecting promise) +info: | + Promise.any ( iterable ) + + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + 6. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + 8. Repeat + a. Let next be IteratorStep(iteratorRecord). + b. If next is an abrupt completion, set iteratorRecord.[[done]] to true. + c. ReturnIfAbrupt(next). + +flags: [async] +features: [Promise.any, Symbol.iterator, computed-property-names, Symbol, arrow-function] +---*/ + +let poisonedDone = {}; +let error = new Test262Error(); +Object.defineProperties(poisonedDone, { + done: { + get() { + throw error; + } + }, + value: { + get() { + $DONE('The `value` property should not be accessed.'); + } + } +}); +let iterStepThrows = { + [Symbol.iterator]() { + return { + next() { + return poisonedDone; + } + }; + } +}; + +Promise.any(iterStepThrows).then( + () => { + $DONE('The promise should be rejected.'); +}, (reason) => { + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/length.js b/js/src/tests/test262/built-ins/Promise/any/length.js new file mode 100644 index 0000000000..85316c7bdc --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/length.js @@ -0,0 +1,30 @@ +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: Promise.any `length` property +info: | + ES 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 }. +includes: [propertyHelper.js] +features: [Promise.any] +---*/ + +verifyProperty(Promise.any, 'length', { + configurable: true, + writable: false, + enumerable: false, + value: 1, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/name.js b/js/src/tests/test262/built-ins/Promise/any/name.js new file mode 100644 index 0000000000..f55f11b358 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/name.js @@ -0,0 +1,31 @@ +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: Promise.any `name` property +info: | + ES Section 17: + + 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 }. +includes: [propertyHelper.js] +features: [Promise.any] +---*/ + +verifyProperty(Promise.any, 'name', { + configurable: true, + writable: false, + enumerable: false, + value: 'any', +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/new-reject-function.js b/js/src/tests/test262/built-ins/Promise/any/new-reject-function.js new file mode 100644 index 0000000000..e99d027281 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/new-reject-function.js @@ -0,0 +1,53 @@ +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-performpromiseany +description: > + Each Promise.any element is called with a new Promise.any Reject Element function. +info: | + Runtime Semantics: PerformPromiseAny ( iteratorRecord, constructor, resultCapability ) + + ... + k. Let rejectElement be ! CreateBuiltinFunction(steps, « [[AlreadyCalled]], [[Index]], [[Errors]], [[Capability]], [[RemainingElements]] »). + ... + r. Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], rejectElement »). + ... + +features: [Promise.any] +---*/ + +function rejectFunction() {} + +function Constructor(executor) { + executor(rejectFunction, Test262Error.thrower); +} +Constructor.resolve = function(v) { + return v; +}; + +var callCount1 = 0; +var callCount2 = 0; +var p1OnRejected; + +var p1 = { + then(_, onRejected) { + callCount1 += 1; + p1OnRejected = onRejected; + assert.notSameValue(onRejected, rejectFunction, 'p1.then'); + } +}; +var p2 = { + then(_, onRejected) { + callCount2 += 1; + assert.notSameValue(onRejected, rejectFunction, 'p2.then'); + assert.notSameValue(onRejected, p1OnRejected, 'p1.onRejected != p2.onRejected'); + } +}; + +Promise.any.call(Constructor, [p1, p2]); +assert.sameValue(callCount1, 1, 'p1.then call count'); +assert.sameValue(callCount2, 1, 'p2.then call count'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/not-a-constructor.js b/js/src/tests/test262/built-ins/Promise/any/not-a-constructor.js new file mode 100644 index 0000000000..94e37ef3ba --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/not-a-constructor.js @@ -0,0 +1,31 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + Promise.any does not implement [[Construct]], is not new-able +info: | + ECMAScript Function Objects + + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified in + the description of a particular function. + + sec-evaluatenew + + ... + 7. If IsConstructor(constructor) is false, throw a TypeError exception. + ... +includes: [isConstructor.js] +features: [Reflect.construct, Promise.any, arrow-function] +---*/ + +assert.sameValue(isConstructor(Promise.any), false, 'isConstructor(Promise.any) must return false'); + +assert.throws(TypeError, () => { + new Promise.any([1]); +}, '`new Promise.any([1])` throws TypeError'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/prop-desc.js b/js/src/tests/test262/built-ins/Promise/any/prop-desc.js new file mode 100644 index 0000000000..89af2db227 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/prop-desc.js @@ -0,0 +1,23 @@ +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: Promise.any property descriptor +info: | + ES 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. +includes: [propertyHelper.js] +features: [Promise.any] +---*/ + +verifyProperty(Promise, 'any', { + configurable: true, + writable: true, + enumerable: false, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/reject-all-mixed.js b/js/src/tests/test262/built-ins/Promise/any/reject-all-mixed.js new file mode 100644 index 0000000000..0a4da17aa3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/reject-all-mixed.js @@ -0,0 +1,27 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Promise.any rejection reasons from various rejections are all present +flags: [async] +features: [Promise.any, arrow-function] +---*/ + +let rejections = [ + Promise.reject('a'), + new Promise((_, reject) => reject('b')), + Promise.all([Promise.reject('c')]), + Promise.resolve(Promise.reject('d')), +]; + +Promise.any(rejections) + .then( + () => $DONE('The promise should be rejected, but was resolved'), + error => { + assert.sameValue(error.errors.length, rejections.length); + assert.sameValue(error.errors.join(''), 'abcd'); + } + ).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/reject-deferred.js b/js/src/tests/test262/built-ins/Promise/any/reject-deferred.js new file mode 100644 index 0000000000..66206ac8f8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/reject-deferred.js @@ -0,0 +1,32 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-promise.any +description: Rejecting through deferred invocation of the provided resolving function +info: | + ... + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + ... + + +flags: [async] +features: [AggregateError, Promise.any, arrow-function] +---*/ + +var rejection = {}; +var thenable = { + then(_, reject) { + new Promise((resolve) => resolve()) + .then(() => reject(rejection)); + } +}; + +Promise.any([thenable]) + .then(() => { + $DONE('The promise should be rejected.'); + }, (aggregate) => { + assert(aggregate instanceof AggregateError); + assert.sameValue(aggregate.errors.length, 1); + assert.sameValue(aggregate.errors[0], rejection); + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/reject-element-function-extensible.js b/js/src/tests/test262/built-ins/Promise/any/reject-element-function-extensible.js new file mode 100644 index 0000000000..806e937f37 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/reject-element-function-extensible.js @@ -0,0 +1,31 @@ +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any-reject-element-functions +description: The [[Extensible]] slot of Promise.any Reject Element functions +info: | + 17 ECMAScript Standard Built-in Objects: + Unless specified otherwise, the [[Extensible]] internal slot + of a built-in object initially has the value true. +features: [Promise.any] +---*/ + +var rejectElementFunction; +var thenable = { + then(_, reject) { + rejectElementFunction = reject; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.any.call(NotPromise, [thenable]); + +assert(Object.isExtensible(rejectElementFunction)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/reject-element-function-length.js b/js/src/tests/test262/built-ins/Promise/any/reject-element-function-length.js new file mode 100644 index 0000000000..dce2b491c8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/reject-element-function-length.js @@ -0,0 +1,42 @@ +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any-reject-element-functions +description: The `length` property of Promise.any Reject Element functions +info: | + The length property of a Promise.any Reject Element function is 1. + + 17 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 }. +includes: [propertyHelper.js] +features: [Promise.any] +---*/ + +var rejectElementFunction; +var thenable = { + then(_, reject) { + rejectElementFunction = reject; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.any.call(NotPromise, [thenable]); + +assert.sameValue(rejectElementFunction.length, 1); + +verifyProperty(rejectElementFunction, 'length', { + value: 1, + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/reject-element-function-name.js b/js/src/tests/test262/built-ins/Promise/any/reject-element-function-name.js new file mode 100644 index 0000000000..e7b71509e9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/reject-element-function-name.js @@ -0,0 +1,41 @@ +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any-reject-element-functions +description: The `name` property of Promise.any Reject Element functions +info: | + A promise resolve function is an anonymous built-in function. + + 17 ECMAScript Standard Built-in Objects: + Every built-in function object, including constructors, has a `name` + property whose value is a String. Functions that are identified as + anonymous functions use the empty string as the value of the `name` + property. + Unless otherwise specified, the `name` property of a built-in function + object has the attributes { [[Writable]]: *false*, [[Enumerable]]: *false*, + [[Configurable]]: *true* }. +includes: [propertyHelper.js] +features: [Promise.any] +---*/ + +var rejectElementFunction; +var thenable = { + then(_, reject) { + rejectElementFunction = reject; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.any.call(NotPromise, [thenable]); + +verifyProperty(rejectElementFunction, "name", { + value: "", writable: false, enumerable: false, configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/reject-element-function-nonconstructor.js b/js/src/tests/test262/built-ins/Promise/any/reject-element-function-nonconstructor.js new file mode 100644 index 0000000000..c11012de84 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/reject-element-function-nonconstructor.js @@ -0,0 +1,35 @@ +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any-reject-element-functions +description: Promise.any Reject Element functions are not constructors +info: | + 17 ECMAScript Standard Built-in Objects: + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified + in the description of a particular function. +features: [Promise.any] +---*/ + +var rejectElementFunction; +var thenable = { + then(_, reject) { + rejectElementFunction = reject; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.any.call(NotPromise, [thenable]); + +assert.sameValue(Object.prototype.hasOwnProperty.call(rejectElementFunction, 'prototype'), false); +assert.throws(TypeError, function() { + new rejectElementFunction(); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/reject-element-function-prototype.js b/js/src/tests/test262/built-ins/Promise/any/reject-element-function-prototype.js new file mode 100644 index 0000000000..a6b147ec0e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/reject-element-function-prototype.js @@ -0,0 +1,33 @@ +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any-reject-element-functions +description: The [[Prototype]] of Promise.any Reject Element functions +info: | + 17 ECMAScript Standard Built-in Objects: + Unless otherwise specified every built-in function and every built-in + constructor has the Function prototype object, which is the initial + value of the expression Function.prototype (19.2.3), as the value of + its [[Prototype]] internal slot. +features: [Promise.any] +---*/ + +var rejectElementFunction; +var thenable = { + then(_, reject) { + rejectElementFunction = reject; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.any.call(NotPromise, [thenable]); + +assert.sameValue(Object.getPrototypeOf(rejectElementFunction), Function.prototype); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/reject-from-same-thenable.js b/js/src/tests/test262/built-ins/Promise/any/reject-from-same-thenable.js new file mode 100644 index 0000000000..9c55285599 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/reject-from-same-thenable.js @@ -0,0 +1,70 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Rejecting with a non-thenable object value +esid: sec-promise.any +info: | + PerformPromiseAny + + Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] + 1. + Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], rejectElement »). + + Promise.any Reject Element Functions + + Let alreadyCalled be F.[[AlreadyCalled]]. + If alreadyCalled.[[Value]] is true, return undefined. + Set alreadyCalled.[[Value]] to true. + ... +features: [Promise.any] +---*/ + +let callCount = 0; +let error; + +function Constructor(executor) { + function reject(result) { + callCount += 1; + error = result; + } + executor(() => {throw new Test262Error()}, reject); +} +Constructor.resolve = function(v) { + return v; +}; + +let p1OnRejected, p2OnRejected, p3OnRejected; + +let p1 = { + then(_, onRejected) { + p1OnRejected = onRejected; + } +}; +let p2 = { + then(_, onRejected) { + p2OnRejected = onRejected; + } +}; +let p3 = { + then(_, onRejected) { + p3OnRejected = onRejected; + } +}; + +assert.sameValue(callCount, 0, 'callCount before call to any()'); + +Promise.any.call(Constructor, [p1, p2, p3]); + +assert.sameValue(callCount, 0, 'callCount after call to any()'); + +p1OnRejected('p1-rejection'); +p1OnRejected('p1-rejection-unexpected-1'); +p1OnRejected('p1-rejection-unexpected-2'); + +assert.sameValue(callCount, 0, 'callCount after resolving p1'); + +p2OnRejected('p2-rejection'); +p3OnRejected('p3-rejection'); + +assert.sameValue(callCount, 1, 'callCount after resolving all elements'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/reject-ignored-deferred.js b/js/src/tests/test262/built-ins/Promise/any/reject-ignored-deferred.js new file mode 100644 index 0000000000..4e98e1ab01 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/reject-ignored-deferred.js @@ -0,0 +1,69 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-promise.any +description: > + Resolved promises ignore rejections through deferred invocation of the + provided resolving function +info: | + Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + ... + Let remainingElementsCount be a new Record { [[value]]: 1 }. + ... + 8.d ... + ii. Set remainingElementsCount.[[value]] to remainingElementsCount.[[value]] − 1. + iii. If remainingElementsCount.[[value]] is 0, + 1. Let error be a newly created AggregateError object. + 2. Perform ! DefinePropertyOrThrow(error, "errors", Property Descriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: errors }). + 3. Return ThrowCompletion(error). + ... + + Promise.any Reject Element Functions + ... + Let alreadyCalled be the value of F's [[AlreadyCalled]] internal slot. + If alreadyCalled.[[value]] is true, return undefined. + Set alreadyCalled.[[value]] to true. + ... + +flags: [async] +features: [Promise.any, arrow-function] +---*/ + +let callCount = 0; +let fulfiller = { + then(resolve) { + new Promise((resolve) => { + callCount++; + resolve(); + }) + .then(() => { + callCount++; + resolve(); + }); + } +}; +let rejector = { + then(resolve, reject) { + new Promise((resolve) => { + callCount++; + resolve(); + }) + .then(() => { + callCount++; + resolve(); + reject(); + }); + } +}; + +Promise.all([fulfiller, rejector]) + .then(() => { + assert.sameValue(callCount, 4, "callCount === 4"); + $DONE(); + }, () => { + $DONE("The promise should not be rejected."); + }); diff --git a/js/src/tests/test262/built-ins/Promise/any/reject-ignored-immed.js b/js/src/tests/test262/built-ins/Promise/any/reject-ignored-immed.js new file mode 100644 index 0000000000..11b6976871 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/reject-ignored-immed.js @@ -0,0 +1,53 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-promise.any +description: > + Resolved promises ignore rejections through immediate invocation of the + provided resolving function +info: | + Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + ... + Let remainingElementsCount be a new Record { [[value]]: 1 }. + ... + 8.d ... + ii. Set remainingElementsCount.[[value]] to remainingElementsCount.[[value]] − 1. + iii. If remainingElementsCount.[[value]] is 0, + 1. Let error be a newly created AggregateError object. + 2. Perform ! DefinePropertyOrThrow(error, "errors", Property Descriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: errors }). + 3. Return ThrowCompletion(error). + ... + + Promise.any Reject Element Functions + ... + Let alreadyCalled be the value of F's [[AlreadyCalled]] internal slot. + If alreadyCalled.[[value]] is true, return undefined. + Set alreadyCalled.[[value]] to true. + ... + +flags: [async] +features: [Promise.any, arrow-function] +---*/ + +let fulfiller = { + then(resolve) { + resolve(); + } +}; +let lateRejector = { + then(resolve, reject) { + resolve(); + reject(); + } +}; + +Promise.any([fulfiller, lateRejector]) + .then(() => { + $DONE(); + }, () => { + $DONE('The promise should not be rejected.'); + }); diff --git a/js/src/tests/test262/built-ins/Promise/any/reject-immed.js b/js/src/tests/test262/built-ins/Promise/any/reject-immed.js new file mode 100644 index 0000000000..33d445e1de --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/reject-immed.js @@ -0,0 +1,45 @@ +// |reftest| async +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-promise.any +description: Rejecting through immediate invocation of the provided resolving function +info: | + ... + Let promiseCapability be NewPromiseCapability(C). + ... + Let result be PerformPromiseAny(iteratorRecord, promiseCapability, C). + ... + + Runtime Semantics: PerformPromiseAny + ... + 8. Repeat + ... + r. Perform ? Invoke(nextPromise, "then", + « resultCapability.[[Resolve]], rejectElement »). + + + Promise.any Reject Element Functions + ... + 6. Return RejectPromise(promise, reason). +flags: [async] +features: [Promise.any, arrow-function] +---*/ + +let callCount = 0; +let thenable = { + then(_, reject) { + callCount++; + reject('reason'); + } +}; + +Promise.any([thenable]) + .then(() => { + $DONE('The promise should not be fulfilled.'); + }, (error) => { + assert.sameValue(callCount, 1, "callCount === 1"); + assert(error instanceof AggregateError, "error instanceof AggregateError"); + assert.sameValue(error.errors[0], "reason", "error.errors[0] === 'reason'"); + $DONE(); + }); diff --git a/js/src/tests/test262/built-ins/Promise/any/resolve-before-loop-exit-from-same.js b/js/src/tests/test262/built-ins/Promise/any/resolve-before-loop-exit-from-same.js new file mode 100644 index 0000000000..19e2e3779e --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/resolve-before-loop-exit-from-same.js @@ -0,0 +1,101 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Cannot tamper remainingElementsCount when Promise.all resolve element function is called twice in a row. +info: | + Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + ... + Let remainingElementsCount be a new Record { [[value]]: 1 }. + ... + 8.d ... + ii. Set remainingElementsCount.[[value]] to remainingElementsCount.[[value]] − 1. + iii. If remainingElementsCount.[[value]] is 0, + 1. Let error be a newly created AggregateError object. + 2. Perform ! DefinePropertyOrThrow(error, "errors", Property Descriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: errors }). + 3. Return ThrowCompletion(error). + ... + + Promise.any Reject Element Functions + ... + Let alreadyCalled be the value of F's [[AlreadyCalled]] internal slot. + If alreadyCalled.[[value]] is true, return undefined. + Set alreadyCalled.[[value]] to true. + ... + +features: [Promise.any, arrow-function] +---*/ + +let callCount = 0; +let errorArray; + +function Constructor(executor) { + function reject(error) { + callCount += 1; + errorArray = error.errors; + + assert(Array.isArray(error.errors), "error is array"); + assert.sameValue(error.errors.length, 3, "error.length"); + assert.sameValue(error.errors[0], "p1-rejection", "error.errors[0] === 'p1-rejection'"); + assert.sameValue(error.errors[1], "p2-rejection", "error.errors[1] === 'p2-rejection'"); + assert.sameValue(error.errors[2], "p3-rejection", "error.errors[2] === 'p3-rejection'"); + assert(error instanceof AggregateError, "error instanceof AggregateError"); + } + executor(Test262Error.thrower, reject); +} +Constructor.resolve = function(v) { + return v; +}; + +let p1OnRejected; + +let p1 = { + then(onResolved, onRejected) { + p1OnRejected = onRejected; + } +}; +let p2 = { + then(onResolved, onRejected) { + onRejected("p2-rejection"); + onRejected("unexpectedonRejectedValue"); + } +}; +let p3 = { + then(onResolved, onRejected) { + onRejected("p3-rejection"); + } +}; + +assert.sameValue(callCount, 0, "callCount before call to any()"); + +Promise.any.call(Constructor, [p1, p2, p3]); + +assert.sameValue(callCount, 0, "callCount after call to any()"); + +p1OnRejected("p1-rejection"); + +assert.sameValue(callCount, 1, "callCount after call to p1OnRejected()"); +assert.sameValue( + errorArray[0], + "p1-rejection", + "errorArray[0] === 'p1-rejection', after call to p1OnRejected(...)" +); +assert.sameValue( + errorArray[1], + "p2-rejection", + "errorArray[1] === 'p2-rejection', after call to p1OnRejected(...)" +); +assert.sameValue( + errorArray[2], + "p3-rejection", + "errorArray[2] === 'p3-rejection', after call to p1OnRejected(...)" +); + + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/resolve-before-loop-exit.js b/js/src/tests/test262/built-ins/Promise/any/resolve-before-loop-exit.js new file mode 100644 index 0000000000..07daaa55dd --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/resolve-before-loop-exit.js @@ -0,0 +1,102 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Cannot tamper remainingElementsCount when two Promise.any Reject Element Function are called in succession. +info: | + Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + ... + Let remainingElementsCount be a new Record { [[value]]: 1 }. + ... + 8.d ... + ii. Set remainingElementsCount.[[value]] to remainingElementsCount.[[value]] − 1. + iii. If remainingElementsCount.[[value]] is 0, + 1. Let error be a newly created AggregateError object. + 2. Perform ! DefinePropertyOrThrow(error, "errors", Property Descriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: errors }). + 3. Return ThrowCompletion(error). + ... + + Promise.any Reject Element Functions + ... + Let alreadyCalled be the value of F's [[AlreadyCalled]] internal slot. + If alreadyCalled.[[value]] is true, return undefined. + Set alreadyCalled.[[value]] to true. + ... + +features: [Promise.any, arrow-function] +---*/ + +let callCount = 0; +let errorArray; + +function Constructor(executor) { + function reject(error) { + callCount += 1; + errorArray = error.errors; + + assert(Array.isArray(error.errors), "error is array"); + assert.sameValue(error.errors.length, 3, "error.length"); + assert.sameValue(error.errors[0], "p1-rejection", "error.errors[0] === 'p1-rejection'"); + assert.sameValue(error.errors[1], "p2-rejection", "error.errors[1] === 'p2-rejection'"); + assert.sameValue(error.errors[2], "p3-rejection", "error.errors[2] === 'p3-rejection'"); + assert(error instanceof AggregateError, "error instanceof AggregateError"); + } + executor(Test262Error.thrower, reject); +} +Constructor.resolve = function(v) { + return v; +}; + +let p1OnRejected; + +let p1 = { + then(onResolved, onRejected) { + p1OnRejected = onRejected; + } +}; +let p2 = { + then(onResolved, onRejected) { + p1OnRejected("p1-rejection"); + onRejected("p2-rejection"); + } +}; +let p3 = { + then(onResolved, onRejected) { + onRejected("p3-rejection"); + } +}; + +assert.sameValue(callCount, 0, "callCount before call to any()"); + +Promise.any.call(Constructor, [p1, p2, p3]); + +assert.sameValue(callCount, 1, "callCount after call to any()"); +assert.sameValue(errorArray[0], "p1-rejection", "errorArray[0] === 'p1-rejection'"); +assert.sameValue(errorArray[1], "p2-rejection", "errorArray[1] === 'p2-rejection'"); +assert.sameValue(errorArray[2], "p3-rejection", "errorArray[2] === 'p3-rejection'"); + +p1OnRejected("unexpectedonRejectedValue"); + +assert.sameValue(callCount, 1, "callCount after call to p1OnRejected()"); +assert.sameValue( + errorArray[0], + "p1-rejection", + "errorArray[0] === 'p1-rejection', after call to p1OnRejected(...)" +); +assert.sameValue( + errorArray[1], + "p2-rejection", + "errorArray[1] === 'p2-rejection', after call to p1OnRejected(...)" +); +assert.sameValue( + errorArray[2], + "p3-rejection", + "errorArray[2] === 'p3-rejection', after call to p1OnRejected(...)" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/resolve-from-reject-catch.js b/js/src/tests/test262/built-ins/Promise/any/resolve-from-reject-catch.js new file mode 100644 index 0000000000..6aee6c9155 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/resolve-from-reject-catch.js @@ -0,0 +1,23 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Promise.any resolves with the first item that does not reject. +flags: [async] +features: [Promise.any, arrow-function] +---*/ + +let fulfillables = [ + Promise.reject('a'), + new Promise((resolve, reject) => reject('b')), + Promise.all([Promise.reject('c')]), + Promise.reject('d').catch(v => v), +]; + +Promise.any(fulfillables) + .then((resolution) => { + assert.sameValue(resolution, 'd'); + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/resolve-from-resolve-reject-catch.js b/js/src/tests/test262/built-ins/Promise/any/resolve-from-resolve-reject-catch.js new file mode 100644 index 0000000000..e5c6534b03 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/resolve-from-resolve-reject-catch.js @@ -0,0 +1,23 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Promise.any resolves with the first item that does not reject. +flags: [async] +features: [Promise.any, arrow-function] +---*/ + +let fulfillables = [ + Promise.reject('a'), + new Promise((resolve, reject) => reject('b')), + Promise.all([Promise.reject('c')]), + Promise.resolve(Promise.reject('d').catch(v => v)), +]; + +Promise.any(fulfillables) + .then((resolution) => { + assert.sameValue(resolution, 'd'); + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/resolve-from-same-thenable.js b/js/src/tests/test262/built-ins/Promise/any/resolve-from-same-thenable.js new file mode 100644 index 0000000000..3066d969ad --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/resolve-from-same-thenable.js @@ -0,0 +1,46 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-performpromiseany +description: > + Promise.any does not prevent resolve from being called multiple times. +features: [Promise.any, arrow-function] +includes: [promiseHelper.js] +---*/ +let callCount = 0; +let sequence = []; + +function Constructor(executor) { + function resolve(value) { + callCount += 1; + sequence.push(value); + } + executor(resolve, Test262Error.thrower); +} +Constructor.resolve = function(v) { + return v; +}; + +let pResolve; +let a = { + then(resolver, rejector) { + pResolve = resolver; + } +}; + +assert.sameValue(callCount, 0, 'callCount before call to any()'); + +Promise.any.call(Constructor, [a]); + +assert.sameValue(callCount, 0, 'callCount after call to any()'); + +pResolve(1); +pResolve(2); +pResolve(3); + +assert.sameValue(callCount, 3, 'callCount after resolving a'); +assert.sameValue(sequence.length, 3); +checkSequence(sequence); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/resolve-ignores-late-rejection-deferred.js b/js/src/tests/test262/built-ins/Promise/any/resolve-ignores-late-rejection-deferred.js new file mode 100644 index 0000000000..89339379fa --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/resolve-ignores-late-rejection-deferred.js @@ -0,0 +1,42 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Resolved promises ignore rejections through deferred invocation of the + provided resolving function +esid: sec-promise.any +info: | + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + 8. Repeat + ... + r. Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], rejectElement »). + +flags: [async] +features: [Promise.any, arrow-function] +---*/ + +var resolver = { + then(resolve) { + new Promise((resolve) => resolve()) + .then(() => resolve(42)); + } +}; +var lateRejector = { + then(resolve, reject) { + new Promise((resolve) => resolve()) + .then(() => { + resolve(9); + reject(); + }); + } +}; + +Promise.any([resolver, lateRejector]) + .then(resolution => { + assert.sameValue(resolution, 42); + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/resolve-ignores-late-rejection.js b/js/src/tests/test262/built-ins/Promise/any/resolve-ignores-late-rejection.js new file mode 100644 index 0000000000..446a12191f --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/resolve-ignores-late-rejection.js @@ -0,0 +1,38 @@ +// |reftest| async +// Copyright (C) 2019 Leo Balter, 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Resolved promises ignore rejections through immediate invocation of the + provided resolving function +esid: sec-promise.any +info: | + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + 8. Repeat + ... + r. Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], rejectElement »). + +flags: [async] +features: [Promise.any, arrow-function] +---*/ + +var resolver = { + then(resolve) { + resolve(42); + } +}; +var lateRejector = { + then(resolve, reject) { + resolve(33); + reject(); + } +}; + +Promise.any([resolver, lateRejector]) + .then(resolution => { + assert.sameValue(resolution, 42); + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/resolve-non-callable.js b/js/src/tests/test262/built-ins/Promise/any/resolve-non-callable.js new file mode 100644 index 0000000000..4baf72bb66 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/resolve-non-callable.js @@ -0,0 +1,37 @@ +// |reftest| async +// Copyright (C) 2020 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Promise.resolve is retrieved before GetIterator call (non-callable). +info: | + Promise.any ( iterable ) + + [...] + 3. Let promiseResolve be GetPromiseResolve(C). + 4. IfAbruptRejectPromise(promiseResolve, promiseCapability). + + GetPromiseResolve ( promiseConstructor ) + + [...] + 2. Let promiseResolve be ? Get(promiseConstructor, "resolve"). + 3. If IsCallable(promiseResolve) is false, throw a TypeError exception. +flags: [async] +features: [Promise.any, Symbol.iterator] +---*/ + +const iter = { + get [Symbol.iterator]() { + throw new Test262Error("unreachable"); + }, +}; + +Promise.resolve = "certainly not callable"; + +Promise.any(iter).then(() => { + throw new Test262Error("The promise should be rejected, but it was resolved"); +}, (reason) => { + assert(reason instanceof TypeError); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/resolve-non-thenable.js b/js/src/tests/test262/built-ins/Promise/any/resolve-non-thenable.js new file mode 100644 index 0000000000..e7fb6b4417 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/resolve-non-thenable.js @@ -0,0 +1,26 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a non-thenable object value +esid: sec-promise.any +info: | + PerformPromiseAny + + Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] + 1. + Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], rejectElement »). + +flags: [async] +features: [Promise.any] +---*/ + +const a = {}; +const b = {}; +const c = {}; + +Promise.any([a, b, c]) + .then((value) => { + assert.sameValue(value, a); + }, () => { + $DONE('The promise should not be rejected.'); + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/resolve-not-callable-reject-with-typeerror.js b/js/src/tests/test262/built-ins/Promise/any/resolve-not-callable-reject-with-typeerror.js new file mode 100644 index 0000000000..6623f8c160 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/resolve-not-callable-reject-with-typeerror.js @@ -0,0 +1,29 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + If the constructor's `resolve` method is not callable, reject with a TypeError. +info: | + Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAny + + Let promiseResolve be ? Get(constructor, "resolve"). + If ! IsCallable(promiseResolve) is false, throw a TypeError exception. + +flags: [async] +features: [Promise.any, arrow-function] +---*/ + +Promise.resolve = null; + +Promise.any([1]) + .then( + () => $DONE('The promise should not be resolved.'), + error => { + assert(error instanceof TypeError); + } + ).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/resolved-sequence-extra-ticks.js b/js/src/tests/test262/built-ins/Promise/any/resolved-sequence-extra-ticks.js new file mode 100644 index 0000000000..fcb54a8457 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/resolved-sequence-extra-ticks.js @@ -0,0 +1,55 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: Resolution ticks are set in a predictable sequence with extra then calls +info: | + Runtime Semantics: PerformPromiseAny ( iteratorRecord, constructor, resultCapability ) + + Let remainingElementsCount be a new Record { [[Value]]: 1 }. + ... + + Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1. + If remainingElementsCount.[[Value]] is 0, then + Let error be a newly created AggregateError object. + Perform ! DefinePropertyOrThrow(error, "errors", + Property Descriptor { + [[Configurable]]: true, + [[Enumerable]]: false, + [[Writable]]: true, + [[Value]]: errors + }). + Return ? Call(promiseCapability.[[Reject]], undefined, « error »). + ... +flags: [async] +includes: [promiseHelper.js] +features: [Promise.any] +---*/ + +let sequence = []; + +let p1 = new Promise(resolve => { + resolve({}); +}); + +sequence.push(1); + +Promise.any([p1]).then((resolved) => { + sequence.push(4); + assert.sameValue(sequence.length, 4); + checkSequence(sequence, 'Expected Promise.any().then to queue second'); +}).catch($DONE); + +p1.then(() => { + sequence.push(3); + assert.sameValue(sequence.length, 3); + checkSequence(sequence, 'Expected p1.then to queue first'); +}).then(() => { + sequence.push(5); + assert.sameValue(sequence.length, 5); + checkSequence(sequence, 'Expected final then to queue last'); +}).then($DONE, $DONE); + +sequence.push(2); diff --git a/js/src/tests/test262/built-ins/Promise/any/resolved-sequence-mixed.js b/js/src/tests/test262/built-ins/Promise/any/resolved-sequence-mixed.js new file mode 100644 index 0000000000..b993f5776b --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/resolved-sequence-mixed.js @@ -0,0 +1,70 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: > + Resolution ticks are set in a predictable sequence of mixed fulfilled and rejected promises +info: | + Runtime Semantics: PerformPromiseAny ( iteratorRecord, constructor, resultCapability ) + + Let remainingElementsCount be a new Record { [[Value]]: 1 }. + ... + + Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1. + If remainingElementsCount.[[Value]] is 0, then + Let error be a newly created AggregateError object. + Perform ! DefinePropertyOrThrow(error, "errors", + Property Descriptor { + [[Configurable]]: true, + [[Enumerable]]: false, + [[Writable]]: true, + [[Value]]: errors + }). + Return ? Call(promiseCapability.[[Reject]], undefined, « error »). + ... +flags: [async] +includes: [promiseHelper.js] +features: [Promise.any] +---*/ + +let sequence = []; + +let p1 = new Promise((_, reject) => { + reject(''); +}); +let p2 = new Promise(resolve => { + resolve(''); +}); +let p3 = new Promise((_, reject) => { + reject(''); +}); + +sequence.push(1); + +p1.catch(() => { + sequence.push(3); + assert.sameValue(sequence.length, 3); + checkSequence(sequence, 'Expected to be called first.'); +}).catch($DONE); + +Promise.any([p1, p2, p3]).then(() => { + sequence.push(6); + assert.sameValue(sequence.length, 6); + checkSequence(sequence, 'Expected to be called fourth.'); +}).then($DONE, $DONE); + +p2.then(() => { + sequence.push(4); + assert.sameValue(sequence.length, 4); + checkSequence(sequence, 'Expected to be called second.'); +}).catch($DONE); + +sequence.push(2); + +p3.catch(() => { + sequence.push(5); + assert.sameValue(sequence.length, 5); + checkSequence(sequence, 'Expected to be called third.'); +}).catch($DONE); diff --git a/js/src/tests/test262/built-ins/Promise/any/resolved-sequence-with-rejections.js b/js/src/tests/test262/built-ins/Promise/any/resolved-sequence-with-rejections.js new file mode 100644 index 0000000000..5562617df6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/resolved-sequence-with-rejections.js @@ -0,0 +1,65 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: Resolution ticks are set in a predictable sequence +info: | + Runtime Semantics: PerformPromiseAny ( iteratorRecord, constructor, resultCapability ) + + Let remainingElementsCount be a new Record { [[Value]]: 1 }. + ... + + Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1. + If remainingElementsCount.[[Value]] is 0, then + Let error be a newly created AggregateError object. + Perform ! DefinePropertyOrThrow(error, "errors", + Property Descriptor { + [[Configurable]]: true, + [[Enumerable]]: false, + [[Writable]]: true, + [[Value]]: errors + }). + Return ? Call(promiseCapability.[[Reject]], undefined, « error »). + ... +flags: [async] +includes: [promiseHelper.js] +features: [Promise.any] +---*/ + +let sequence = []; + +let p1 = new Promise((_, reject) => { + reject('foo'); +}); +let p2 = new Promise((_, reject) => { + reject('bar'); +}); + +sequence.push(1); + +p1.catch(() => { + sequence.push(3); + assert.sameValue(sequence.length, 3); + checkSequence(sequence, 'Expected to be called first.'); +}).catch($DONE); + +Promise.any([p1, p2]).then(() => { + sequence.push(5); + assert.sameValue(sequence.length, 5); + checkSequence(sequence, 'Expected to be called third.'); +}).then($DONE, outcome => { + assert(outcome instanceof AggregateError); + assert.sameValue(outcome.errors.length, 2); + assert.sameValue(outcome.errors[0], 'foo'); + assert.sameValue(outcome.errors[1], 'bar'); +}).then($DONE, $DONE); + +p2.catch(() => { + sequence.push(4); + assert.sameValue(sequence.length, 4); + checkSequence(sequence, 'Expected to be called second.'); +}).catch($DONE); + +sequence.push(2); diff --git a/js/src/tests/test262/built-ins/Promise/any/resolved-sequence.js b/js/src/tests/test262/built-ins/Promise/any/resolved-sequence.js new file mode 100644 index 0000000000..75be407c35 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/resolved-sequence.js @@ -0,0 +1,55 @@ +// |reftest| async +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: Resolution ticks are set in a predictable sequence +info: | + Runtime Semantics: PerformPromiseAny ( iteratorRecord, constructor, resultCapability ) + + Let remainingElementsCount be a new Record { [[Value]]: 1 }. + ... + 6.d ... + ii. Set remainingElementsCount.[[value]] to remainingElementsCount.[[value]] − 1. + iii. If remainingElementsCount.[[value]] is 0, then + Let error be a newly created AggregateError object. + Perform ! DefinePropertyOrThrow(error, "errors", + Property Descriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: errors }). + Return ThrowCompletion(error). + ... +flags: [async] +includes: [promiseHelper.js] +features: [Promise.any] +---*/ + +var sequence = []; + +var p1 = new Promise(resolve => { + resolve(1); +}); +var p2 = new Promise(resolve => { + resolve(2); +}); + +sequence.push(1); + +p1.then(function() { + sequence.push(3); + assert.sameValue(sequence.length, 3); +checkSequence(sequence, 'Expected to be called first.'); +}).catch($DONE); + +Promise.any([p1, p2]).then(function() { + sequence.push(5); + assert.sameValue(sequence.length, 5); + checkSequence(sequence, 'Expected to be called third.'); +}).then($DONE, $DONE); + +p2.then(function() { + sequence.push(4); + assert.sameValue(sequence.length, 4); + checkSequence(sequence, 'Expected to be called second.'); +}).catch($DONE); + +sequence.push(2); diff --git a/js/src/tests/test262/built-ins/Promise/any/returns-promise.js b/js/src/tests/test262/built-ins/Promise/any/returns-promise.js new file mode 100644 index 0000000000..cbcd937b63 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/returns-promise.js @@ -0,0 +1,26 @@ +// Copyright (C) 2019 Sergey Rubanov. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.any +description: Promise.any returns a Promise +info: | + Promise.any ( iterable ) + + 2. Let promiseCapability be ? NewPromiseCapability(C). + 3. Let iteratorRecord be GetIterator(iterable). + 4. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability). + 6. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + 7. Return Completion(result). +features: [Promise.any] +---*/ + +var p = Promise.any([]); + +assert(p instanceof Promise); +assert.sameValue(Object.getPrototypeOf(p), Promise.prototype); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Promise/any/shell.js b/js/src/tests/test262/built-ins/Promise/any/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/shell.js diff --git a/js/src/tests/test262/built-ins/Promise/any/species-get-error.js b/js/src/tests/test262/built-ins/Promise/any/species-get-error.js new file mode 100644 index 0000000000..24ce52bd69 --- /dev/null +++ b/js/src/tests/test262/built-ins/Promise/any/species-get-error.js @@ -0,0 +1,30 @@ +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Promise.any() does not access a `Symbol.species` property of the `this` value +info: | + Let C be the this value. + Let promiseCapability be ? NewPromiseCapability(C). + ... + +features: [Promise.any, Symbol.species] +---*/ +function C(executor) { + executor(() => {}, () => {}); +} + +Object.defineProperty(C, Symbol.species, { + get() { + throw new Test262Error("Getter for Symbol.species called"); + } +}); + +C.resolve = function() { + throw new Test262Error("C.resolve called unexpectedly"); +}; + +Promise.any.call(C, [1]); + +reportCompare(0, 0); |