diff --git a/features.txt b/features.txt index 8a2140066f..ca410bae32 100644 --- a/features.txt +++ b/features.txt @@ -7,6 +7,10 @@ # # https://github.com/tc39/process-document +# Promise.allSettled +# https://github.com/tc39/proposal-promise-allSettled +Promise.allSettled + # Hashbang Grammar # https://github.com/tc39/proposal-hashbang hashbang diff --git a/harness/promiseHelper.js b/harness/promiseHelper.js index 66ae36daf9..2979663e57 100644 --- a/harness/promiseHelper.js +++ b/harness/promiseHelper.js @@ -18,3 +18,57 @@ function checkSequence(arr, message) { return true; } + +function checkSettledPromises(settleds, expected, message) { + const prefix = message ? `${message}: ` : ''; + + assert.sameValue(Array.isArray(settleds), true, `${prefix}Settled values is an array`); + + assert.sameValue( + settleds.length, + expected.length, + `${prefix}The settled values has a different length than expected` + ); + + settleds.forEach((settled, i) => { + assert.sameValue( + Object.prototype.hasOwnProperty.call(settled, 'status'), + true, + `${prefix}The settled value has a property status` + ); + + assert.sameValue(settled.status, expected[i].status, `${prefix}status for item ${i}`); + + if (settled.status === 'fulfilled') { + assert.sameValue( + Object.prototype.hasOwnProperty.call(settled, 'value'), + true, + `${prefix}The fulfilled promise has a property named value` + ); + + assert.sameValue( + Object.prototype.hasOwnProperty.call(settled, 'reason'), + false, + `${prefix}The fulfilled promise has no property named reason` + ); + + assert.sameValue(settled.value, expected[i].value, `${prefix}value for item ${i}`); + } else { + assert.sameValue(settled.status, 'rejected', `${prefix}Valid statuses are only fulfilled or rejected`); + + assert.sameValue( + Object.prototype.hasOwnProperty.call(settled, 'value'), + false, + `${prefix}The fulfilled promise has no property named value` + ); + + assert.sameValue( + Object.prototype.hasOwnProperty.call(settled, 'reason'), + true, + `${prefix}The fulfilled promise has a property named reason` + ); + + assert.sameValue(settled.reason, expected[i].reason, `${prefix}Reason value for item ${i}`); + } + }); +} diff --git a/test/built-ins/Promise/allSettled/call-resolve-element-after-return.js b/test/built-ins/Promise/allSettled/call-resolve-element-after-return.js new file mode 100644 index 0000000000..cc883f4157 --- /dev/null +++ b/test/built-ins/Promise/allSettled/call-resolve-element-after-return.js @@ -0,0 +1,55 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled-resolve-element-functions +description: > + Cannot change result value of resolved Promise.allSettled element after Promise.allSettled() returned. +info: | + Promise.allSettled Resolve Element Functions + + 1. Let F be the active function object. + 2. Let alreadyCalled be F.[[AlreadyCalled]]. + 3. If alreadyCalled.[[Value]] is true, return undefined. + 4. Set alreadyCalled.[[Value]] to true. + ... +includes: [promiseHelper.js] +features: [Promise.allSettled] +---*/ + +var callCount = 0; +var valuesArray; +var expected = [{ status: 'fulfilled', value: 'expectedValue' }]; + +function Constructor(executor) { + function resolve(values) { + callCount += 1; + valuesArray = values; + checkSettledPromises(values, expected, 'values'); + } + executor(resolve, $ERROR); +} +Constructor.resolve = function(v) { + return v; +}; + +var p1OnFulfilled; + +var p1 = { + then(onFulfilled, onRejected) { + p1OnFulfilled = onFulfilled; + onFulfilled('expectedValue'); + } +}; + +assert.sameValue(callCount, 0, 'callCount before call to all()'); + +Promise.allSettled.call(Constructor, [p1]); + +assert.sameValue(callCount, 1, 'callCount after call to all()'); +checkSettledPromises(valuesArray, expected, 'valuesArray after call to all()'); + +p1OnFulfilled('unexpectedValue'); + +assert.sameValue(callCount, 1, 'callCount after call to onFulfilled()'); +checkSettledPromises(valuesArray, expected, 'valuesArray after call to onFulfilled()'); diff --git a/test/built-ins/Promise/allSettled/call-resolve-element-items.js b/test/built-ins/Promise/allSettled/call-resolve-element-items.js new file mode 100644 index 0000000000..eb7e8217db --- /dev/null +++ b/test/built-ins/Promise/allSettled/call-resolve-element-items.js @@ -0,0 +1,59 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled-resolve-element-functions +description: > + Cannot change result value of resolved Promise.allSettled elements. +info: | + Promise.allSettled Resolve Element Functions + + 1. Let F be the active function object. + 2. Let alreadyCalled be F.[[AlreadyCalled]]. + 3. If alreadyCalled.[[Value]] is true, return undefined. + 4. Set alreadyCalled.[[Value]] to true. + ... +includes: [promiseHelper.js] +features: [Promise.allSettled] +---*/ + +var callCount = 0; + +function Constructor(executor) { + function resolve(values) { + callCount += 1; + checkSettledPromises(values, [ + { + status: 'fulfilled', + value: 'expectedValue-p1' + }, + { + status: 'fulfilled', + value: 'expectedValue-p2' + } + ], 'values'); + } + executor(resolve, $ERROR); +} +Constructor.resolve = function(v) { + return v; +}; + +var p1 = { + then(onFulfilled, onRejected) { + onFulfilled('expectedValue-p1'); + onFulfilled('unexpectedValue-p1'); + } +}; +var p2 = { + then(onFulfilled, onRejected) { + onFulfilled('expectedValue-p2'); + onFulfilled('unexpectedValue-p2'); + } +}; + +assert.sameValue(callCount, 0, 'callCount before call to all()'); + +Promise.allSettled.call(Constructor, [p1, p2]); + +assert.sameValue(callCount, 1, 'callCount after call to all()'); diff --git a/test/built-ins/Promise/allSettled/call-resolve-element.js b/test/built-ins/Promise/allSettled/call-resolve-element.js new file mode 100644 index 0000000000..d6cd51f24c --- /dev/null +++ b/test/built-ins/Promise/allSettled/call-resolve-element.js @@ -0,0 +1,49 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled-resolve-element-functions +description: > + Cannot change result value of resolved Promise.allSettled element. +info: | + Promise.allSettled Resolve Element Functions + + 1. Let F be the active function object. + 2. Let alreadyCalled be F.[[AlreadyCalled]]. + 3. If alreadyCalled.[[Value]] is true, return undefined. + 4. Set alreadyCalled.[[Value]] to true. + ... +includes: [promiseHelper.js] +features: [Promise.allSettled] +---*/ + +var callCount = 0; + +function Constructor(executor) { + function resolve(values) { + callCount += 1; + checkSettledPromises(values, [ + { + status: 'fulfilled', + value: 'expectedValue' + } + ], 'values'); + } + executor(resolve, $ERROR); +} +Constructor.resolve = function(v) { + return v; +}; + +var p1 = { + then(onFulfilled, onRejected) { + onFulfilled('expectedValue'); + onFulfilled('unexpectedValue'); + } +}; + +assert.sameValue(callCount, 0, 'callCount before call to all()'); + +Promise.allSettled.call(Constructor, [p1]); + +assert.sameValue(callCount, 1, 'callCount after call to all()'); diff --git a/test/built-ins/Promise/allSettled/capability-executor-called-twice.js b/test/built-ins/Promise/allSettled/capability-executor-called-twice.js new file mode 100644 index 0000000000..5212bf0c0e --- /dev/null +++ b/test/built-ins/Promise/allSettled/capability-executor-called-twice.js @@ -0,0 +1,80 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Throws a TypeError if capabilities executor already called with non-undefined values. +info: | + Promise.allSettled ( iterable ) + + ... + 3. 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.allSettled] +---*/ + +var checkPoint = ''; +Promise.allSettled.call(function(executor) { + checkPoint += 'a'; + executor(); + checkPoint += 'b'; + executor(function() {}, function() {}); + checkPoint += 'c'; +}, []); +assert.sameValue(checkPoint, 'abc', 'executor initially called with no arguments'); + +var checkPoint = ''; +Promise.allSettled.call(function(executor) { + checkPoint += 'a'; + executor(undefined, undefined); + checkPoint += 'b'; + executor(function() {}, function() {}); + checkPoint += 'c'; +}, []); +assert.sameValue(checkPoint, 'abc', 'executor initially called with (undefined, undefined)'); + +var checkPoint = ''; +assert.throws(TypeError, function() { + Promise.allSettled.call(function(executor) { + checkPoint += 'a'; + executor(undefined, function() {}); + checkPoint += 'b'; + executor(function() {}, function() {}); + checkPoint += 'c'; + }, []); +}, 'executor initially called with (undefined, function)'); +assert.sameValue(checkPoint, 'ab', 'executor initially called with (undefined, function)'); + +var checkPoint = ''; +assert.throws(TypeError, function() { + Promise.allSettled.call(function(executor) { + checkPoint += 'a'; + executor(function() {}, undefined); + checkPoint += 'b'; + executor(function() {}, function() {}); + checkPoint += 'c'; + }, []); +}, 'executor initially called with (function, undefined)'); +assert.sameValue(checkPoint, 'ab', 'executor initially called with (function, undefined)'); + +var checkPoint = ''; +assert.throws(TypeError, function() { + Promise.allSettled.call(function(executor) { + checkPoint += 'a'; + executor('invalid value', 123); + checkPoint += 'b'; + executor(function() {}, function() {}); + checkPoint += 'c'; + }, []); +}, 'executor initially called with (String, Number)'); +assert.sameValue(checkPoint, 'ab', 'executor initially called with (String, Number)'); diff --git a/test/built-ins/Promise/allSettled/capability-executor-not-callable.js b/test/built-ins/Promise/allSettled/capability-executor-not-callable.js new file mode 100644 index 0000000000..9826c9abe4 --- /dev/null +++ b/test/built-ins/Promise/allSettled/capability-executor-not-callable.js @@ -0,0 +1,83 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Throws a TypeError if either resolve or reject capability is not callable. +info: | + Promise.allSettled ( iterable ) + + ... + 3. 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.allSettled] +---*/ + +var checkPoint = ''; +assert.throws(TypeError, function() { + Promise.allSettled.call(function(executor) { + checkPoint += 'a'; + }, []); +}, 'executor not called at all'); +assert.sameValue(checkPoint, 'a', 'executor not called at all'); + +var checkPoint = ''; +assert.throws(TypeError, function() { + Promise.allSettled.call(function(executor) { + checkPoint += 'a'; + executor(); + checkPoint += 'b'; + }, []); +}, 'executor called with no arguments'); +assert.sameValue(checkPoint, 'ab', 'executor called with no arguments'); + +var checkPoint = ''; +assert.throws(TypeError, function() { + Promise.allSettled.call(function(executor) { + checkPoint += 'a'; + executor(undefined, undefined); + checkPoint += 'b'; + }, []); +}, 'executor called with (undefined, undefined)'); +assert.sameValue(checkPoint, 'ab', 'executor called with (undefined, undefined)'); + +var checkPoint = ''; +assert.throws(TypeError, function() { + Promise.allSettled.call(function(executor) { + checkPoint += 'a'; + executor(undefined, function() {}); + checkPoint += 'b'; + }, []); +}, 'executor called with (undefined, function)'); +assert.sameValue(checkPoint, 'ab', 'executor called with (undefined, function)'); + +var checkPoint = ''; +assert.throws(TypeError, function() { + Promise.allSettled.call(function(executor) { + checkPoint += 'a'; + executor(function() {}, undefined); + checkPoint += 'b'; + }, []); +}, 'executor called with (function, undefined)'); +assert.sameValue(checkPoint, 'ab', 'executor called with (function, undefined)'); + +var checkPoint = ''; +assert.throws(TypeError, function() { + Promise.allSettled.call(function(executor) { + checkPoint += 'a'; + executor(123, 'invalid value'); + checkPoint += 'b'; + }, []); +}, 'executor called with (Number, String)'); +assert.sameValue(checkPoint, 'ab', 'executor called with (Number, String)'); diff --git a/test/built-ins/Promise/allSettled/capability-resolve-throws-no-close.js b/test/built-ins/Promise/allSettled/capability-resolve-throws-no-close.js new file mode 100644 index 0000000000..1b6b578db5 --- /dev/null +++ b/test/built-ins/Promise/allSettled/capability-resolve-throws-no-close.js @@ -0,0 +1,60 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-promise.allsettled +description: > + Iterator is not closed when the "resolve" capability returns an abrupt + completion. +info: | + ... + 3. Let promiseCapability be ? NewPromiseCapability(C). + ... + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + 7. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + 8. Return Completion(result). + + Runtime Semantics: PerformPromiseAllSettled + + ... + 6. Repeat + ... + d. If next is false, then + ... + iii. If remainingElementsCount.[[Value]] is 0, then + 1. Let valuesArray be CreateArrayFromList(values). + 2. Perform ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »). + + IfAbruptRejectPromise + + 1. IfAbruptRejectPromise(value, capability). +features: [Promise.allSettled, Symbol.iterator] +---*/ + +var returnCount = 0; +var iter = {}; +iter[Symbol.iterator] = function() { + return { + next() { + return { + done: true + }; + }, + return() { + returnCount += 1; + return {}; + } + }; +}; +var P = function(executor) { + return new Promise(function(_, reject) { + executor(function() { + throw new Test262Error(); + }, reject); + }); +}; + +Promise.allSettled.call(P, iter); + +assert.sameValue(returnCount, 0); diff --git a/test/built-ins/Promise/allSettled/capability-resolve-throws-reject.js b/test/built-ins/Promise/allSettled/capability-resolve-throws-reject.js new file mode 100644 index 0000000000..ea0e53ea03 --- /dev/null +++ b/test/built-ins/Promise/allSettled/capability-resolve-throws-reject.js @@ -0,0 +1,55 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-promise.allsettled +description: > + Promise is rejected when the "resolve" capability returns an abrupt + completion. +info: | + ... + 3. Let promiseCapability be ? NewPromiseCapability(C). + ... + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + 7. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + 8. Return Completion(result). + + Runtime Semantics: PerformPromiseAllSettled + + ... + 6. Repeat + ... + d. If next is false, then + ... + iii. If remainingElementsCount.[[Value]] is 0, then + 1. Let valuesArray be CreateArrayFromList(values). + 2. Perform ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »). + + + IfAbruptRejectPromise + + 1. IfAbruptRejectPromise(value, capability). +flags: [async] +features: [Promise.allSettled] +---*/ + +var thrown = new Test262Error(); +var P = function(executor) { + return new Promise(function(_, reject) { + executor(function() { + throw thrown; + }, reject); + }); +}; + +Promise.allSettled.call(P, []) + .then(function() { + $DONE('Promise incorrectly fulfilled.'); + }, function(reason) { + if (reason !== thrown) { + $DONE('Promise rejected with incorrect "reason."'); + return; + } + $DONE(); + }); diff --git a/test/built-ins/Promise/allSettled/ctx-ctor-throws.js b/test/built-ins/Promise/allSettled/ctx-ctor-throws.js new file mode 100644 index 0000000000..663e88a8b8 --- /dev/null +++ b/test/built-ins/Promise/allSettled/ctx-ctor-throws.js @@ -0,0 +1,24 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Promise.allSettled invoked on a constructor value that throws an error +esid: sec-promise.allsettled +info: | + 3. Let promiseCapability be ? NewPromiseCapability(C). + + NewPromiseCapability + + ... + 7. Let promise be ? Construct(C, « executor »). +features: [Promise.allSettled] +---*/ + +var CustomPromise = function() { + throw new Test262Error(); +}; + +assert.throws(Test262Error, function() { + Promise.allSettled.call(CustomPromise); +}); diff --git a/test/built-ins/Promise/allSettled/ctx-ctor.js b/test/built-ins/Promise/allSettled/ctx-ctor.js new file mode 100644 index 0000000000..4cbca92d4d --- /dev/null +++ b/test/built-ins/Promise/allSettled/ctx-ctor.js @@ -0,0 +1,34 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Promise.allSettled invoked on a constructor value +esid: sec-promise.allsettled +info: | + 3. Let promiseCapability be ? NewPromiseCapability(C). + ... + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + ... + 8. Return Completion(result). +features: [Promise.allSettled, class] +---*/ + +var executor = null; +var callCount = 0; + +class SubPromise extends Promise { + constructor(a) { + super(a); + executor = a; + callCount += 1; + } +} + +var instance = Promise.allSettled.call(SubPromise, []); + +assert.sameValue(instance.constructor, SubPromise); +assert.sameValue(instance instanceof SubPromise, true); + +assert.sameValue(callCount, 1); +assert.sameValue(typeof executor, 'function'); diff --git a/test/built-ins/Promise/allSettled/ctx-non-ctor.js b/test/built-ins/Promise/allSettled/ctx-non-ctor.js new file mode 100644 index 0000000000..06d69ed5fb --- /dev/null +++ b/test/built-ins/Promise/allSettled/ctx-non-ctor.js @@ -0,0 +1,20 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Promise.allSettled invoked on a non-constructor value +esid: sec-promise.allsettled +info: | + ... + 3. Let promiseCapability be ? NewPromiseCapability(C). + + NewPromiseCapability ( C ) + + 1. If IsConstructor(C) is false, throw a TypeError exception. +features: [Promise.allSettled] +---*/ + +assert.throws(TypeError, function() { + Promise.allSettled.call(eval); +}); diff --git a/test/built-ins/Promise/allSettled/ctx-non-object.js b/test/built-ins/Promise/allSettled/ctx-non-object.js new file mode 100644 index 0000000000..1fd59f109c --- /dev/null +++ b/test/built-ins/Promise/allSettled/ctx-non-object.js @@ -0,0 +1,36 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Promise.allSettled invoked on a non-object value +esid: sec-promise.allsettled +info: | + 1. Let C be the this value. + 2. If Type(C) is not Object, throw a TypeError exception. +features: [Promise.allSettled, Symbol] +---*/ + +assert.throws(TypeError, function() { + Promise.allSettled.call(undefined, []); +}); + +assert.throws(TypeError, function() { + Promise.allSettled.call(null, []); +}); + +assert.throws(TypeError, function() { + Promise.allSettled.call(86, []); +}); + +assert.throws(TypeError, function() { + Promise.allSettled.call('string', []); +}); + +assert.throws(TypeError, function() { + Promise.allSettled.call(true, []); +}); + +assert.throws(TypeError, function() { + Promise.allSettled.call(Symbol(), []); +}); diff --git a/test/built-ins/Promise/allSettled/does-not-invoke-array-setters.js b/test/built-ins/Promise/allSettled/does-not-invoke-array-setters.js new file mode 100644 index 0000000000..6f15e72fd1 --- /dev/null +++ b/test/built-ins/Promise/allSettled/does-not-invoke-array-setters.js @@ -0,0 +1,46 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-performpromiseallsettled +description: > + Indexed setter properties on Array.prototype are not invoked. +info: | + Promise.allSettled ( iterable ) + + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + 7. 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: PerformPromiseAllSettled ( iteratorRecord, constructor, resultCapability ) + + ... + 4. Let remainingElementsCount be a new Record { [[value]]: 1 }. + ... + 6.d ... + ii. Set remainingElementsCount.[[value]] to remainingElementsCount.[[value]] − 1. + iii. If remainingElementsCount.[[value]] is 0, + 1. Let valuesArray be CreateArrayFromList(values). + ... + ... + + 7.3.16 CreateArrayFromList (elements) + ... + 4. For each element e of elements + a. Let status be CreateDataProperty(array, ToString(n), e). + b. Assert: status is true. + ... +flags: [async] +features: [Promise.allSettled] +---*/ + +Object.defineProperty(Array.prototype, 0, { + set() { + throw new Test262Error('Setter on Array.prototype called'); + } +}); + +Promise.allSettled([42]).then(function() { + $DONE(); +}, $DONE); diff --git a/test/built-ins/Promise/allSettled/invoke-resolve-error-close.js b/test/built-ins/Promise/allSettled/invoke-resolve-error-close.js new file mode 100644 index 0000000000..d9048c21b2 --- /dev/null +++ b/test/built-ins/Promise/allSettled/invoke-resolve-error-close.js @@ -0,0 +1,44 @@ +// Copyright (C) 2019 Leo Balter. 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.allsettled +info: | + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + 7. 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: PerformPromiseAllSettled + + 6. Repeat + ... + i. Let nextPromise be ? Invoke(constructor, "resolve", « nextValue »). +features: [Promise.allSettled, Symbol.iterator] +---*/ + +var iterDoneSpy = {}; +var callCount = 0; +iterDoneSpy[Symbol.iterator] = function() { + return { + next() { + return { + value: null, + done: false + }; + }, + return() { + callCount += 1; + } + }; +}; + +Promise.resolve = function() { + throw new Error(); +}; + +Promise.allSettled(iterDoneSpy); + +assert.sameValue(callCount, 1); diff --git a/test/built-ins/Promise/allSettled/invoke-resolve-error-reject.js b/test/built-ins/Promise/allSettled/invoke-resolve-error-reject.js new file mode 100644 index 0000000000..5a63c4f44e --- /dev/null +++ b/test/built-ins/Promise/allSettled/invoke-resolve-error-reject.js @@ -0,0 +1,34 @@ +// Copyright (C) 2019 Leo Balter. 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.allsettled +info: | + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + 7. 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: PerformPromiseAllSettled + + 6. Repeat + ... + i. Let nextPromise be ? Invoke(constructor, "resolve", « nextValue »). +flags: [async] +features: [Promise.allSettled] +---*/ + +var thrown = new Test262Error(); +Promise.resolve = function() { + throw thrown; +}; + +Promise.allSettled([1]) + .then(function() { + $ERROR('The promise should not be fulfilled.'); + }, function(reason) { + if (reason !== thrown) { + $ERROR('The promise should be rejected with the thrown error object'); + } + }).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allSettled/invoke-resolve-get-error-close.js b/test/built-ins/Promise/allSettled/invoke-resolve-get-error-close.js new file mode 100644 index 0000000000..c09fdcd774 --- /dev/null +++ b/test/built-ins/Promise/allSettled/invoke-resolve-get-error-close.js @@ -0,0 +1,45 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Error retrieving the constructor's `resolve` method (closing iterator) +esid: sec-promise.allsettled +info: | + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + 7. 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: PerformPromiseAllSettled + + 6. Repeat + ... + i. Let nextPromise be ? Invoke(constructor, "resolve", « nextValue »). +features: [Promise.allSettled, Symbol.iterator] +---*/ + +var iter = {}; +var returnCount = 0; +iter[Symbol.iterator] = function() { + return { + next() { + return { + done: false + }; + }, + return() { + returnCount += 1; + return {}; + } + }; +}; +Object.defineProperty(Promise, 'resolve', { + get() { + throw new Test262Error(); + } +}); + +Promise.allSettled(iter); + +assert.sameValue(returnCount, 1); diff --git a/test/built-ins/Promise/allSettled/invoke-resolve-get-error-reject.js b/test/built-ins/Promise/allSettled/invoke-resolve-get-error-reject.js new file mode 100644 index 0000000000..32964668ad --- /dev/null +++ b/test/built-ins/Promise/allSettled/invoke-resolve-get-error-reject.js @@ -0,0 +1,34 @@ +// Copyright (C) 2019 Leo Balter. 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.allsettled +info: | + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + 7. 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: PerformPromiseAllSettled + + 6. Repeat + ... + i. Let nextPromise be ? Invoke(constructor, "resolve", « nextValue »). +flags: [async] +features: [Promise.allSettled] +---*/ + +var error = new Test262Error(); +Object.defineProperty(Promise, 'resolve', { + get() { + throw error; + } +}); + +Promise.allSettled([new Promise(function() {})]).then(function() { + $ERROR('The promise should be rejected'); +}, function(reason) { + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allSettled/invoke-resolve-get-once-multiple-calls.js b/test/built-ins/Promise/allSettled/invoke-resolve-get-once-multiple-calls.js new file mode 100644 index 0000000000..8a11600d10 --- /dev/null +++ b/test/built-ins/Promise/allSettled/invoke-resolve-get-once-multiple-calls.js @@ -0,0 +1,47 @@ +// Copyright (C) 2019 Leo Balter. 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.allsettled +info: | + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAllSettled + + 6. Let promiseResolve be ? Get(constructor, `"resolve"`). + 7. 1. If IsCallable(promiseResolve) is false, throw a TypeError exception. + 8. Repeat + ... + i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). +features: [Promise.allSettled] +---*/ + +var p1 = Promise.resolve(1); +var p2 = Promise.resolve(1); +var p3 = Promise.reject(1); +var p4 = Promise.resolve(1); +var resolve = Promise.resolve; +var getCount = 0; +var callCount = 0; + +Object.defineProperty(Promise, 'resolve', { + configurable: true, + get() { + getCount += 1; + return function() { + callCount += 1; + return resolve.apply(Promise, arguments); + }; + } +}); + +Promise.allSettled([p1, p2, p3, p4]); + +assert.sameValue( + getCount, 1, 'Got `resolve` only once for each iterated value' +); +assert.sameValue( + callCount, 4, '`resolve` invoked once for each iterated value' +); diff --git a/test/built-ins/Promise/allSettled/invoke-resolve-get-once-no-calls.js b/test/built-ins/Promise/allSettled/invoke-resolve-get-once-no-calls.js new file mode 100644 index 0000000000..b5d48a8112 --- /dev/null +++ b/test/built-ins/Promise/allSettled/invoke-resolve-get-once-no-calls.js @@ -0,0 +1,43 @@ +// Copyright (C) 2019 Leo Balter. 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.allsettled +info: | + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAllSettled + + 6. Let promiseResolve be ? Get(constructor, `"resolve"`). + 7. 1. If IsCallable(promiseResolve) is false, throw a TypeError exception. + 8. Repeat + ... + i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »). +features: [Promise.allSettled] +---*/ + +var resolve = Promise.resolve; +var getCount = 0; +var callCount = 0; + +Object.defineProperty(Promise, 'resolve', { + configurable: true, + get() { + getCount += 1; + return function() { + callCount += 1; + return resolve.apply(Promise, arguments); + }; + } +}); + +Promise.allSettled([]); + +assert.sameValue( + getCount, 1, 'Got `resolve` only once for each iterated value' +); +assert.sameValue( + callCount, 0, '`resolve` not called for empty iterator' +); diff --git a/test/built-ins/Promise/allSettled/invoke-resolve-return.js b/test/built-ins/Promise/allSettled/invoke-resolve-return.js new file mode 100644 index 0000000000..c3b3911aa1 --- /dev/null +++ b/test/built-ins/Promise/allSettled/invoke-resolve-return.js @@ -0,0 +1,42 @@ +// Copyright (C) 2019 Leo Balter. 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.allsettled +info: | + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAllSettled + + 6. Repeat + ... + i. Let nextPromise be ? Invoke(constructor, "resolve", « nextValue »). + ... + z. Perform ? Invoke(nextPromise, "then", « resolveElement, rejectElement »). +features: [Promise.allSettled] +---*/ + +var originalCallCount = 0; +var newCallCount = 0; +var P = function(executor) { + executor(function() {}, function() {}); +}; +P.resolve = function() { + return newThenable; +}; + +var originalThenable = { + then() { + originalCallCount += 1; + } +}; +var newThenable = { + then() { + newCallCount += 1; + } +}; + +Promise.allSettled.call(P, [originalThenable]); + +assert.sameValue(originalCallCount, 0, 'original `then` method not invoked'); +assert.sameValue(newCallCount, 1, 'new `then` method invoked exactly once'); diff --git a/test/built-ins/Promise/allSettled/invoke-resolve.js b/test/built-ins/Promise/allSettled/invoke-resolve.js new file mode 100644 index 0000000000..afb809efa5 --- /dev/null +++ b/test/built-ins/Promise/allSettled/invoke-resolve.js @@ -0,0 +1,52 @@ +// Copyright (C) 2019 Leo Balter. 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.allsettled +info: | + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAllSettled + + 6. Repeat + ... + i. Let nextPromise be ? Invoke(constructor, "resolve", « nextValue »). + ... + z. Perform ? Invoke(nextPromise, "then", « resolveElement, rejectElement »). +features: [Promise.allSettled] +---*/ + +var p1 = new Promise(function() {}); +var p2 = new Promise(function() {}); +var p3 = new Promise(function() {}); +var resolve = Promise.resolve; +var callCount = 0; +var current = p1; +var next = p2; +var afterNext = p3; + +Promise.resolve = function(nextValue) { + assert.sameValue( + nextValue, current, '`resolve` invoked with next iterated value' + ); + assert.sameValue( + arguments.length, 1, '`resolve` invoked with a single argument' + ); + assert.sameValue(this, Promise, '`this` value is the constructor'); + + current = next; + next = afterNext; + afterNext = null; + + callCount += 1; + + return resolve.apply(Promise, arguments); +}; + +Promise.allSettled([p1, p2, p3]); + +assert.sameValue( + callCount, 3, '`resolve` invoked once for each iterated value' +); diff --git a/test/built-ins/Promise/allSettled/invoke-then-error-close.js b/test/built-ins/Promise/allSettled/invoke-then-error-close.js new file mode 100644 index 0000000000..fe8f156cb9 --- /dev/null +++ b/test/built-ins/Promise/allSettled/invoke-then-error-close.js @@ -0,0 +1,43 @@ +// Copyright (C) 2019 Leo Balter. 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.allsettled +info: | + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + 7. 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: PerformPromiseAllSettled + + z. Perform ? Invoke(nextPromise, "then", « resolveElement, rejectElement »). +features: [Promise.allSettled, Symbol.iterator] +---*/ + +var promise = new Promise(function() {}); +var returnCount = 0; +var iter = {}; +iter[Symbol.iterator] = function() { + return { + next() { + return { + done: false, + value: promise + }; + }, + return() { + returnCount += 1; + return {}; + } + }; +}; + +promise.then = function() { + throw new Test262Error(); +}; + +Promise.allSettled(iter); + +assert.sameValue(returnCount, 1); diff --git a/test/built-ins/Promise/allSettled/invoke-then-error-reject.js b/test/built-ins/Promise/allSettled/invoke-then-error-reject.js new file mode 100644 index 0000000000..3d29e9dde0 --- /dev/null +++ b/test/built-ins/Promise/allSettled/invoke-then-error-reject.js @@ -0,0 +1,32 @@ +// Copyright (C) 2019 Leo Balter. 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.allsettled +info: | + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + 7. 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: PerformPromiseAllSettled + + z. Perform ? Invoke(nextPromise, "then", « resolveElement, rejectElement »). +flags: [async] +features: [Promise.allSettled] +---*/ + +var promise = new Promise(function() {}); +var error = new Test262Error(); + +promise.then = function() { + throw error; +}; + +Promise.allSettled([promise]).then(function() { + throw new Test262Error('The promise should be rejected'); +}, function(reason) { + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allSettled/invoke-then-get-error-close.js b/test/built-ins/Promise/allSettled/invoke-then-get-error-close.js new file mode 100644 index 0000000000..8a5b173e4e --- /dev/null +++ b/test/built-ins/Promise/allSettled/invoke-then-get-error-close.js @@ -0,0 +1,45 @@ +// Copyright (C) 2019 Leo Balter. 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.allsettled +info: | + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + 7. 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: PerformPromiseAllSettled + + z. Perform ? Invoke(nextPromise, "then", « resolveElement, rejectElement »). +features: [Promise.allSettled, Symbol.iterator] +---*/ + +var promise = new Promise(function() {}); +var returnCount = 0; +var iter = {}; +iter[Symbol.iterator] = function() { + return { + next() { + return { + done: false, + value: promise + }; + }, + return() { + returnCount += 1; + return {}; + } + }; +}; + +Object.defineProperty(promise, 'then', { + get() { + throw new Test262Error(); + } +}); + +Promise.allSettled(iter); + +assert.sameValue(returnCount, 1); diff --git a/test/built-ins/Promise/allSettled/invoke-then-get-error-reject.js b/test/built-ins/Promise/allSettled/invoke-then-get-error-reject.js new file mode 100644 index 0000000000..b4aeb88608 --- /dev/null +++ b/test/built-ins/Promise/allSettled/invoke-then-get-error-reject.js @@ -0,0 +1,33 @@ +// Copyright (C) 2019 Leo Balter. 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.allsettled +info: | + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + 7. 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: PerformPromiseAllSettled + + z. Perform ? Invoke(nextPromise, "then", « resolveElement, rejectElement »). +flags: [async] +features: [Promise.allSettled] +---*/ + +var promise = new Promise(function() {}); +var error = new Test262Error(); + +Object.defineProperty(promise, 'then', { + get() { + throw error; + } +}); + +Promise.allSettled([promise]).then(function() { + $ERROR('The promise should be rejected'); +}, function(reason) { + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allSettled/invoke-then.js b/test/built-ins/Promise/allSettled/invoke-then.js new file mode 100644 index 0000000000..e5650a15a0 --- /dev/null +++ b/test/built-ins/Promise/allSettled/invoke-then.js @@ -0,0 +1,53 @@ +// Copyright (C) 2019 Leo Balter. 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.allsettled +info: | + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + 7. 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: PerformPromiseAllSettled + + z. Perform ? Invoke(nextPromise, "then", « resolveElement, rejectElement »). +features: [Promise.allSettled] +---*/ + +var p1 = new Promise(function() {}); +var p2 = new Promise(function() {}); +var p3 = new Promise(function() {}); +var callCount = 0; +var currentThis = p1; +var nextThis = p2; +var afterNextThis = p3; + +p1.then = p2.then = p3.then = function(a, b) { + assert.sameValue(typeof a, 'function', 'type of first argument'); + assert.sameValue( + a.length, + 1, + 'The length property of a promise resolve function is 1.' + ); + assert.sameValue(typeof b, 'function', 'type of second argument'); + assert.sameValue( + b.length, + 1, + 'The length property of a promise reject function is 1.' + ); + assert.sameValue(arguments.length, 2, '`then` invoked with two arguments'); + assert.sameValue(this, currentThis, '`this` value'); + + currentThis = nextThis; + nextThis = afterNextThis; + afterNextThis = null; + + callCount += 1; +}; + +Promise.allSettled([p1, p2, p3]); + +assert.sameValue(callCount, 3, '`then` invoked once for every iterated value'); diff --git a/test/built-ins/Promise/allSettled/is-function.js b/test/built-ins/Promise/allSettled/is-function.js new file mode 100644 index 0000000000..4321d87b3e --- /dev/null +++ b/test/built-ins/Promise/allSettled/is-function.js @@ -0,0 +1,10 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: Promise.allSettled is callable +features: [Promise.allSettled] +---*/ + +assert.sameValue(typeof Promise.allSettled, 'function'); diff --git a/test/built-ins/Promise/allSettled/iter-arg-is-false-reject.js b/test/built-ins/Promise/allSettled/iter-arg-is-false-reject.js new file mode 100644 index 0000000000..75b93a08e1 --- /dev/null +++ b/test/built-ins/Promise/allSettled/iter-arg-is-false-reject.js @@ -0,0 +1,36 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument is `false` +info: | + Promise.allSettled ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. 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.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled(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/test/built-ins/Promise/allSettled/iter-arg-is-null-reject.js b/test/built-ins/Promise/allSettled/iter-arg-is-null-reject.js new file mode 100644 index 0000000000..414882e73b --- /dev/null +++ b/test/built-ins/Promise/allSettled/iter-arg-is-null-reject.js @@ -0,0 +1,36 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument is `null` +info: | + Promise.allSettled ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. 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.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled(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/test/built-ins/Promise/allSettled/iter-arg-is-number-reject.js b/test/built-ins/Promise/allSettled/iter-arg-is-number-reject.js new file mode 100644 index 0000000000..805896b04f --- /dev/null +++ b/test/built-ins/Promise/allSettled/iter-arg-is-number-reject.js @@ -0,0 +1,36 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument is a number +info: | + Promise.allSettled ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. 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.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled(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/test/built-ins/Promise/allSettled/iter-arg-is-poisoned.js b/test/built-ins/Promise/allSettled/iter-arg-is-poisoned.js new file mode 100644 index 0000000000..295903bcf7 --- /dev/null +++ b/test/built-ins/Promise/allSettled/iter-arg-is-poisoned.js @@ -0,0 +1,42 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject with abrupt completion from GetIterator +info: | + Promise.allSettled ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + ... + + #sec-getiterator + GetIterator ( obj [ , hint [ , method ] ] ) + + ... + Let iterator be ? Call(method, obj). + ... +features: [Promise.allSettled, Symbol.iterator] +flags: [async] +---*/ + +var poison = []; +var error = new Test262Error(); +Object.defineProperty(poison, Symbol.iterator, { + get() { + throw error; + } +}); + +try { + Promise.allSettled(poison).then(function() { + $DONE('The promise should be rejected, but was resolved'); + }, function(err) { + assert.sameValue(err, error); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be rejected, but threw an exception: ${error.message}`); +} diff --git a/test/built-ins/Promise/allSettled/iter-arg-is-string-resolve.js b/test/built-ins/Promise/allSettled/iter-arg-is-string-resolve.js new file mode 100644 index 0000000000..f7fc024b95 --- /dev/null +++ b/test/built-ins/Promise/allSettled/iter-arg-is-string-resolve.js @@ -0,0 +1,35 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Resolve when argument is a string +info: | + Promise.allSettled ( iterable ) + + ... + 4. Let iteratorRecord be GetIterator(iterable). + 5. 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.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled('').then(function(v) { + assert.sameValue(v.length, 0); + }, function() { + $DONE('The promise should be resolved, but was rejected'); + }).then($DONE, $DONE); +} catch (error) { + $DONE(`The promise should be resolved, but threw an exception: ${error.message}`); +} diff --git a/test/built-ins/Promise/allSettled/iter-arg-is-symbol-reject.js b/test/built-ins/Promise/allSettled/iter-arg-is-symbol-reject.js new file mode 100644 index 0000000000..36843a466d --- /dev/null +++ b/test/built-ins/Promise/allSettled/iter-arg-is-symbol-reject.js @@ -0,0 +1,49 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument is a symbol +info: | + Promise.allSettled ( 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.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled(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/test/built-ins/Promise/allSettled/iter-arg-is-true-reject.js b/test/built-ins/Promise/allSettled/iter-arg-is-true-reject.js new file mode 100644 index 0000000000..3e204cdccb --- /dev/null +++ b/test/built-ins/Promise/allSettled/iter-arg-is-true-reject.js @@ -0,0 +1,49 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument is `true` +info: | + Promise.allSettled ( 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.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled(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/test/built-ins/Promise/allSettled/iter-arg-is-undefined-reject.js b/test/built-ins/Promise/allSettled/iter-arg-is-undefined-reject.js new file mode 100644 index 0000000000..a9be3c504b --- /dev/null +++ b/test/built-ins/Promise/allSettled/iter-arg-is-undefined-reject.js @@ -0,0 +1,49 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument is `undefined` +info: | + Promise.allSettled ( 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.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled(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/test/built-ins/Promise/allSettled/iter-assigned-false-reject.js b/test/built-ins/Promise/allSettled/iter-assigned-false-reject.js new file mode 100644 index 0000000000..8be75d1521 --- /dev/null +++ b/test/built-ins/Promise/allSettled/iter-assigned-false-reject.js @@ -0,0 +1,53 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument's Symbol.iterator property has the value false +info: | + Promise.allSettled ( 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.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled({ + [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/test/built-ins/Promise/allSettled/iter-assigned-null-reject.js b/test/built-ins/Promise/allSettled/iter-assigned-null-reject.js new file mode 100644 index 0000000000..08cc4f2012 --- /dev/null +++ b/test/built-ins/Promise/allSettled/iter-assigned-null-reject.js @@ -0,0 +1,51 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument's Symbol.iterator property has the value null +info: | + Promise.allSettled ( 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.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled({ + [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/test/built-ins/Promise/allSettled/iter-assigned-number-reject.js b/test/built-ins/Promise/allSettled/iter-assigned-number-reject.js new file mode 100644 index 0000000000..3c1c928264 --- /dev/null +++ b/test/built-ins/Promise/allSettled/iter-assigned-number-reject.js @@ -0,0 +1,51 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument's Symbol.iterator property has the value 1 +info: | + Promise.allSettled ( 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.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled({ + [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/test/built-ins/Promise/allSettled/iter-assigned-string-reject.js b/test/built-ins/Promise/allSettled/iter-assigned-string-reject.js new file mode 100644 index 0000000000..1110f1b670 --- /dev/null +++ b/test/built-ins/Promise/allSettled/iter-assigned-string-reject.js @@ -0,0 +1,51 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument's Symbol.iterator property has the value "" +info: | + Promise.allSettled ( 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.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled({ + [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/test/built-ins/Promise/allSettled/iter-assigned-symbol-reject.js b/test/built-ins/Promise/allSettled/iter-assigned-symbol-reject.js new file mode 100644 index 0000000000..acab7c72f6 --- /dev/null +++ b/test/built-ins/Promise/allSettled/iter-assigned-symbol-reject.js @@ -0,0 +1,51 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument's Symbol.iterator property has the value Symbol() +info: | + Promise.allSettled ( 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.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled({ + [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/test/built-ins/Promise/allSettled/iter-assigned-true-reject.js b/test/built-ins/Promise/allSettled/iter-assigned-true-reject.js new file mode 100644 index 0000000000..b57abdd2b7 --- /dev/null +++ b/test/built-ins/Promise/allSettled/iter-assigned-true-reject.js @@ -0,0 +1,51 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument's Symbol.iterator property has the value true +info: | + Promise.allSettled ( 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.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled({ + [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/test/built-ins/Promise/allSettled/iter-assigned-undefined-reject.js b/test/built-ins/Promise/allSettled/iter-assigned-undefined-reject.js new file mode 100644 index 0000000000..6e370f093a --- /dev/null +++ b/test/built-ins/Promise/allSettled/iter-assigned-undefined-reject.js @@ -0,0 +1,51 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument's Symbol.iterator property has the value undefined +info: | + Promise.allSettled ( 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.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled({ + [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/test/built-ins/Promise/allSettled/iter-next-err-reject.js b/test/built-ins/Promise/allSettled/iter-next-err-reject.js new file mode 100644 index 0000000000..e079bd3bc5 --- /dev/null +++ b/test/built-ins/Promise/allSettled/iter-next-err-reject.js @@ -0,0 +1,54 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Error when call an iterator next step (rejecting promise) +info: | + Promise.allSettled ( iterable ) + + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + 7. 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: PerformPromiseAllSettled + + ... + 6. Repeat + a. Let next be IteratorStep(iteratorRecord). + b. If next is an abrupt completion, set iteratorRecord.[[Done]] to true. + c. ReturnIfAbrupt(next). + ... + + IteratorStep ( iteratorRecord ) + + 1. Let result be ? IteratorNext(iteratorRecord). + + IteratorNext ( iteratorRecord [ , value ] ) + + 1. If value is not present, then + a. Let result be ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]], « »). + 2. Else, + a. Let result be ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]], « value »). + ... +features: [Promise.allSettled, Symbol.iterator] +flags: [async] +---*/ + +var iterNextValThrows = {}; +var error = new Test262Error(); +iterNextValThrows[Symbol.iterator] = function() { + return { + next() { + throw error; + } + }; +}; + +Promise.allSettled(iterNextValThrows).then(function() { + $DONE('The promise should be rejected.'); +}, function(reason) { + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allSettled/iter-next-val-err-no-close.js b/test/built-ins/Promise/allSettled/iter-next-val-err-no-close.js new file mode 100644 index 0000000000..12e99f6571 --- /dev/null +++ b/test/built-ins/Promise/allSettled/iter-next-val-err-no-close.js @@ -0,0 +1,56 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Error when accessing an iterator result's `value` property (not closing + iterator) +info: | + Promise.allSettled ( iterable ) + + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + 7. 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: PerformPromiseAllSettled + + ... + 6. Repeat + ... + e. Let nextValue be IteratorValue(next). + f. If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true. + g. ReturnIfAbrupt(nextValue). +features: [Promise.allSettled, Symbol.iterator] +---*/ + +var iterNextValThrows = {}; +var returnCount = 0; +var nextCount = 0; +var poisonedVal = { + done: false +}; +var error = new Test262Error(); +Object.defineProperty(poisonedVal, 'value', { + get() { + throw error; + } +}); +iterNextValThrows[Symbol.iterator] = function() { + return { + next() { + nextCount += 1; + return poisonedVal; + }, + return() { + returnCount += 1; + return {}; + } + }; +}; + +Promise.allSettled(iterNextValThrows); + +assert.sameValue(returnCount, 0); +assert.sameValue(nextCount, 1); diff --git a/test/built-ins/Promise/allSettled/iter-next-val-err-reject.js b/test/built-ins/Promise/allSettled/iter-next-val-err-reject.js new file mode 100644 index 0000000000..b7e1b643c1 --- /dev/null +++ b/test/built-ins/Promise/allSettled/iter-next-val-err-reject.js @@ -0,0 +1,50 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Error when accessing an iterator result's `value` property (rejecting promise) +info: | + Promise.allSettled ( iterable ) + + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + 7. 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: PerformPromiseAllSettled + + ... + 6. Repeat + ... + e. Let nextValue be IteratorValue(next). + f. If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true. + g. ReturnIfAbrupt(nextValue). +features: [Promise.allSettled, Symbol.iterator] +flags: [async] +---*/ + +var iterNextValThrows = {}; +var poisonedVal = { + done: false +}; +var error = new Test262Error(); +Object.defineProperty(poisonedVal, 'value', { + get() { + throw error; + } +}); +iterNextValThrows[Symbol.iterator] = function() { + return { + next() { + return poisonedVal; + } + }; +}; + +Promise.allSettled(iterNextValThrows).then(function() { + $DONE('The promise should be rejected.'); +}, function(reason) { + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allSettled/iter-returns-false-reject.js b/test/built-ins/Promise/allSettled/iter-returns-false-reject.js new file mode 100644 index 0000000000..ae9fb35160 --- /dev/null +++ b/test/built-ins/Promise/allSettled/iter-returns-false-reject.js @@ -0,0 +1,53 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument's Symbol.iterator returns false +info: | + Promise.allSettled ( 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.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled({ + [Symbol.iterator]() { + return 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/test/built-ins/Promise/allSettled/iter-returns-null-reject.js b/test/built-ins/Promise/allSettled/iter-returns-null-reject.js new file mode 100644 index 0000000000..618c3256b7 --- /dev/null +++ b/test/built-ins/Promise/allSettled/iter-returns-null-reject.js @@ -0,0 +1,53 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument's Symbol.iterator returns null +info: | + Promise.allSettled ( 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.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled({ + [Symbol.iterator]() { + return 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/test/built-ins/Promise/allSettled/iter-returns-number-reject.js b/test/built-ins/Promise/allSettled/iter-returns-number-reject.js new file mode 100644 index 0000000000..5890fe3e76 --- /dev/null +++ b/test/built-ins/Promise/allSettled/iter-returns-number-reject.js @@ -0,0 +1,53 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument's Symbol.iterator returns a number +info: | + Promise.allSettled ( 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.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled({ + [Symbol.iterator]() { + return 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/test/built-ins/Promise/allSettled/iter-returns-string-reject.js b/test/built-ins/Promise/allSettled/iter-returns-string-reject.js new file mode 100644 index 0000000000..b2dbce3df0 --- /dev/null +++ b/test/built-ins/Promise/allSettled/iter-returns-string-reject.js @@ -0,0 +1,53 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument's Symbol.iterator returns a string +info: | + Promise.allSettled ( 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.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled({ + [Symbol.iterator]() { + return ''; + } + }).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/test/built-ins/Promise/allSettled/iter-returns-symbol-reject.js b/test/built-ins/Promise/allSettled/iter-returns-symbol-reject.js new file mode 100644 index 0000000000..8a7d5f01b3 --- /dev/null +++ b/test/built-ins/Promise/allSettled/iter-returns-symbol-reject.js @@ -0,0 +1,53 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument's Symbol.iterator returns a symbol +info: | + Promise.allSettled ( 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.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled({ + [Symbol.iterator]() { + return 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/test/built-ins/Promise/allSettled/iter-returns-true-reject.js b/test/built-ins/Promise/allSettled/iter-returns-true-reject.js new file mode 100644 index 0000000000..29b97cd4e4 --- /dev/null +++ b/test/built-ins/Promise/allSettled/iter-returns-true-reject.js @@ -0,0 +1,53 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument's Symbol.iterator returns true +info: | + Promise.allSettled ( 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.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled({ + [Symbol.iterator]() { + return 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/test/built-ins/Promise/allSettled/iter-returns-undefined-reject.js b/test/built-ins/Promise/allSettled/iter-returns-undefined-reject.js new file mode 100644 index 0000000000..6c0cc439a0 --- /dev/null +++ b/test/built-ins/Promise/allSettled/iter-returns-undefined-reject.js @@ -0,0 +1,53 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Reject when argument's Symbol.iterator returns undefined +info: | + Promise.allSettled ( 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.allSettled, Symbol.iterator] +flags: [async] +---*/ + +try { + Promise.allSettled({ + [Symbol.iterator]() { + return 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/test/built-ins/Promise/allSettled/iter-step-err-no-close.js b/test/built-ins/Promise/allSettled/iter-step-err-no-close.js new file mode 100644 index 0000000000..2ebfa0502f --- /dev/null +++ b/test/built-ins/Promise/allSettled/iter-step-err-no-close.js @@ -0,0 +1,52 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Error when advancing the provided iterable (not closing iterator) +info: | + Promise.allSettled ( iterable ) + + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + 7. 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: PerformPromiseAllSettled + + 6. Repeat + a. Let next be IteratorStep(iteratorRecord). + b. If next is an abrupt completion, set iteratorRecord.[[done]] to true. + c. ReturnIfAbrupt(next). +features: [Promise.allSettled, Symbol.iterator] +---*/ + +var iterStepThrows = {}; +var poisonedDone = {}; +var returnCount = 0; +var error = new Test262Error(); +Object.defineProperty(poisonedDone, 'done', { + get() { + throw error; + } +}); +Object.defineProperty(poisonedDone, 'value', { + get() {} +}); + +iterStepThrows[Symbol.iterator] = function() { + return { + next() { + return poisonedDone; + }, + return() { + returnCount += 1; + return {}; + } + }; +}; + +Promise.allSettled(iterStepThrows); + +assert.sameValue(returnCount, 0); diff --git a/test/built-ins/Promise/allSettled/iter-step-err-reject.js b/test/built-ins/Promise/allSettled/iter-step-err-reject.js new file mode 100644 index 0000000000..1ffbf64756 --- /dev/null +++ b/test/built-ins/Promise/allSettled/iter-step-err-reject.js @@ -0,0 +1,52 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Error when advancing the provided iterable (rejecting promise) +info: | + Promise.allSettled ( iterable ) + + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + 7. 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: PerformPromiseAllSettled + + 6. Repeat + a. Let next be IteratorStep(iteratorRecord). + b. If next is an abrupt completion, set iteratorRecord.[[done]] to true. + c. ReturnIfAbrupt(next). +features: [Promise.allSettled, Symbol.iterator] +flags: [async] +---*/ + +var iterStepThrows = {}; +var poisonedDone = {}; +var error = new Test262Error(); +Object.defineProperty(poisonedDone, 'done', { + get() { + throw error; + } +}); +Object.defineProperty(poisonedDone, 'value', { + get() { + $DONE('The `value` property should not be accessed.'); + } +}); + +iterStepThrows[Symbol.iterator] = function() { + return { + next() { + return poisonedDone; + } + }; +}; + +Promise.allSettled(iterStepThrows).then(function() { + $DONE('The promise should be rejected.'); +}, function(reason) { + assert.sameValue(reason, error); +}).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allSettled/length.js b/test/built-ins/Promise/allSettled/length.js new file mode 100644 index 0000000000..db4cf62bae --- /dev/null +++ b/test/built-ins/Promise/allSettled/length.js @@ -0,0 +1,28 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: Promise.allSettled `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.allSettled] +---*/ + +verifyProperty(Promise.allSettled, 'length', { + configurable: true, + writable: false, + enumerable: false, + value: 1, +}); diff --git a/test/built-ins/Promise/allSettled/name.js b/test/built-ins/Promise/allSettled/name.js new file mode 100644 index 0000000000..cc14c34697 --- /dev/null +++ b/test/built-ins/Promise/allSettled/name.js @@ -0,0 +1,29 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: Promise.allSettled `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.allSettled] +---*/ + +verifyProperty(Promise.allSettled, 'name', { + configurable: true, + writable: false, + enumerable: false, + value: 'allSettled', +}); diff --git a/test/built-ins/Promise/allSettled/new-reject-function.js b/test/built-ins/Promise/allSettled/new-reject-function.js new file mode 100644 index 0000000000..2cb9428a25 --- /dev/null +++ b/test/built-ins/Promise/allSettled/new-reject-function.js @@ -0,0 +1,48 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-performpromiseallsettled +description: > + Each Promise.allSettled element is called with a new Promise.allSettled Reject Element function. +info: | + Runtime Semantics: PerformPromiseAllSettled ( iteratorRecord, constructor, resultCapability ) + + ... + z. Perform ? Invoke(nextPromise, "then", « resolveElement, rejectElement »). + ... +features: [Promise.allSettled] +---*/ + +function rejectFunction() {} + +function Constructor(executor) { + executor(rejectFunction, $ERROR); +} +Constructor.resolve = function(v) { + return v; +}; + +var callCount1 = 0, + 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.allSettled.call(Constructor, [p1, p2]); + +assert.sameValue(callCount1, 1, 'p1.then call count'); +assert.sameValue(callCount2, 1, 'p2.then call count'); diff --git a/test/built-ins/Promise/allSettled/new-resolve-function.js b/test/built-ins/Promise/allSettled/new-resolve-function.js new file mode 100644 index 0000000000..eaacff1cb5 --- /dev/null +++ b/test/built-ins/Promise/allSettled/new-resolve-function.js @@ -0,0 +1,50 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-performpromiseallsettled +description: > + Each Promise.allSettled element is called with a new Promise.allSettled Resolve Element function. +info: | + Runtime Semantics: PerformPromiseAllSettled ( iteratorRecord, constructor, resultCapability ) + + ... + k Let resolveElement be ! CreateBuiltinFunction(steps, « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »). + ... + z. Perform ? Invoke(nextPromise, "then", « resolveElement, rejectElement »). + ... +features: [Promise.allSettled] +---*/ + +function resolveFunction() {} + +function Constructor(executor) { + executor(resolveFunction, $ERROR); +} +Constructor.resolve = function(v) { + return v; +}; + +var callCount1 = 0, + callCount2 = 0; +var p1OnFulfilled; + +var p1 = { + then(onFulfilled, onRejected) { + callCount1 += 1; + p1OnFulfilled = onFulfilled; + assert.notSameValue(onFulfilled, resolveFunction, 'p1.then'); + } +}; +var p2 = { + then(onFulfilled, onRejected) { + callCount2 += 1; + assert.notSameValue(onFulfilled, resolveFunction, 'p2.then'); + assert.notSameValue(onFulfilled, p1OnFulfilled, 'p1.onFulfilled != p2.onFulfilled'); + } +}; + +Promise.allSettled.call(Constructor, [p1, p2]); + +assert.sameValue(callCount1, 1, 'p1.then call count'); +assert.sameValue(callCount2, 1, 'p2.then call count'); diff --git a/test/built-ins/Promise/allSettled/prop-desc.js b/test/built-ins/Promise/allSettled/prop-desc.js new file mode 100644 index 0000000000..ec9e8c5d57 --- /dev/null +++ b/test/built-ins/Promise/allSettled/prop-desc.js @@ -0,0 +1,21 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: Promise.allSettled 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.allSettled] +---*/ + +verifyProperty(Promise, 'allSettled', { + configurable: true, + writable: true, + enumerable: false, +}); diff --git a/test/built-ins/Promise/allSettled/reject-deferred.js b/test/built-ins/Promise/allSettled/reject-deferred.js new file mode 100644 index 0000000000..6b26b91e90 --- /dev/null +++ b/test/built-ins/Promise/allSettled/reject-deferred.js @@ -0,0 +1,47 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Rejecting through deferred invocation of the provided resolving function +esid: sec-promise.allsettled +info: | + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAllSettled + + 6. Repeat + ... + z. Perform ? Invoke(nextPromise, "then", « resolveElement, rejectElement »). + + Promise.allSettled Reject Element Functions + + 9. Let obj be ! ObjectCreate(%ObjectPrototype%). + 10. Perform ! CreateDataProperty(obj, "status", "rejected"). + 11. Perform ! CreateDataProperty(obj, "reason", x). + 12. Set values[index] to be obj. + 13. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1. + 14. If remainingElementsCount.[[Value]] is 0, then + a. Let valuesArray be CreateArrayFromList(values). + b. Return ? Call(promiseCapability.[[Resolve]], undefined, « valuesArray »). +flags: [async] +features: [Promise.allSettled] +---*/ + +var simulation = {}; +var thenable = { + then(_, reject) { + new Promise(function(resolve) { + resolve(); + }) + .then(function() { + reject(simulation); + }); + } +}; + +Promise.allSettled([thenable]) + .then((settleds) => { + assert.sameValue(settleds.length, 1); + assert.sameValue(settleds[0].status, 'rejected'); + assert.sameValue(settleds[0].reason, simulation); + $DONE(); + }).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allSettled/reject-element-function-extensible.js b/test/built-ins/Promise/allSettled/reject-element-function-extensible.js new file mode 100644 index 0000000000..55533a7610 --- /dev/null +++ b/test/built-ins/Promise/allSettled/reject-element-function-extensible.js @@ -0,0 +1,29 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled-reject-element-functions +description: The [[Extensible]] slot of Promise.allSettled 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.allSettled] +---*/ + +var rejectElementFunction; +var thenable = { + then(_, reject) { + rejectElementFunction = reject; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.allSettled.call(NotPromise, [thenable]); + +assert(Object.isExtensible(rejectElementFunction)); diff --git a/test/built-ins/Promise/allSettled/reject-element-function-length.js b/test/built-ins/Promise/allSettled/reject-element-function-length.js new file mode 100644 index 0000000000..bf416b303d --- /dev/null +++ b/test/built-ins/Promise/allSettled/reject-element-function-length.js @@ -0,0 +1,40 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled-reject-element-functions +description: The `length` property of Promise.allSettled Reject Element functions +info: | + The length property of a Promise.allSettled 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.allSettled] +---*/ + +var rejectElementFunction; +var thenable = { + then(_, reject) { + rejectElementFunction = reject; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.allSettled.call(NotPromise, [thenable]); + +assert.sameValue(rejectElementFunction.length, 1); + +verifyProperty(rejectElementFunction, 'length', { + value: 1, + enumerable: false, + writable: false, + configurable: true, +}); diff --git a/test/built-ins/Promise/allSettled/reject-element-function-name.js b/test/built-ins/Promise/allSettled/reject-element-function-name.js new file mode 100644 index 0000000000..79944bb09f --- /dev/null +++ b/test/built-ins/Promise/allSettled/reject-element-function-name.js @@ -0,0 +1,32 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled-reject-element-functions +description: The `name` property of Promise.allSettled 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, that is not + identified as an anonymous function has a name property whose value + is a String. +features: [Promise.allSettled] +---*/ + +var rejectElementFunction; +var thenable = { + then(_, reject) { + rejectElementFunction = reject; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.allSettled.call(NotPromise, [thenable]); + +assert.sameValue(Object.prototype.hasOwnProperty.call(rejectElementFunction, 'name'), false); diff --git a/test/built-ins/Promise/allSettled/reject-element-function-nonconstructor.js b/test/built-ins/Promise/allSettled/reject-element-function-nonconstructor.js new file mode 100644 index 0000000000..11a3e235ee --- /dev/null +++ b/test/built-ins/Promise/allSettled/reject-element-function-nonconstructor.js @@ -0,0 +1,33 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled-reject-element-functions +description: Promise.allSettled 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.allSettled] +---*/ + +var rejectElementFunction; +var thenable = { + then(_, reject) { + rejectElementFunction = reject; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.allSettled.call(NotPromise, [thenable]); + +assert.sameValue(Object.prototype.hasOwnProperty.call(rejectElementFunction, 'prototype'), false); +assert.throws(TypeError, function() { + new rejectElementFunction(); +}); diff --git a/test/built-ins/Promise/allSettled/reject-element-function-prototype.js b/test/built-ins/Promise/allSettled/reject-element-function-prototype.js new file mode 100644 index 0000000000..e4cf73915e --- /dev/null +++ b/test/built-ins/Promise/allSettled/reject-element-function-prototype.js @@ -0,0 +1,31 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled-reject-element-functions +description: The [[Prototype]] of Promise.allSettled 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.allSettled] +---*/ + +var rejectElementFunction; +var thenable = { + then(_, reject) { + rejectElementFunction = reject; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.allSettled.call(NotPromise, [thenable]); + +assert.sameValue(Object.getPrototypeOf(rejectElementFunction), Function.prototype); diff --git a/test/built-ins/Promise/allSettled/reject-ignored-deferred.js b/test/built-ins/Promise/allSettled/reject-ignored-deferred.js new file mode 100644 index 0000000000..72ed7dbf83 --- /dev/null +++ b/test/built-ins/Promise/allSettled/reject-ignored-deferred.js @@ -0,0 +1,53 @@ +// Copyright (C) 2019 Leo Balter. 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.allsettled +info: | + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAllSettled + + 6. Repeat + ... + z. Perform ? Invoke(nextPromise, "then", « resolveElement, rejectElement »). +flags: [async] +features: [Promise.allSettled] +---*/ + +var simulation = {}; + +var fulfiller = { + then(resolve) { + new Promise(function(resolve) { + resolve(); + }) + .then(function() { + resolve(42); + }); + } +}; +var rejector = { + then(resolve, reject) { + new Promise(function(resolve) { + resolve(); + }) + .then(function() { + resolve(simulation); + reject(); + }); + } +}; + +Promise.allSettled([fulfiller, rejector]) + .then((settleds) => { + assert.sameValue(settleds.length, 2); + assert.sameValue(settleds[0].status, 'fulfilled'); + assert.sameValue(settleds[0].value, 42); + assert.sameValue(settleds[1].status, 'fulfilled'); + assert.sameValue(settleds[1].value, simulation); + $DONE(); + }).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allSettled/reject-ignored-immed.js b/test/built-ins/Promise/allSettled/reject-ignored-immed.js new file mode 100644 index 0000000000..a060e69a94 --- /dev/null +++ b/test/built-ins/Promise/allSettled/reject-ignored-immed.js @@ -0,0 +1,44 @@ +// Copyright (C) 2019 Leo Balter. 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.allsettled +info: | + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAllSettled + + 6. Repeat + ... + z. Perform ? Invoke(nextPromise, "then", « resolveElement, rejectElement »). +flags: [async] +features: [Promise.allSettled] +---*/ + +var simulation = {}; + +var fulfiller = { + then(resolve) { + resolve(42); + } +}; + +var lateRejector = { + then(resolve, reject) { + resolve(simulation); + reject(); + } +}; + +Promise.allSettled([fulfiller, lateRejector]) + .then((settleds) => { + assert.sameValue(settleds.length, 2); + assert.sameValue(settleds[0].status, 'fulfilled'); + assert.sameValue(settleds[0].value, 42); + assert.sameValue(settleds[1].status, 'fulfilled'); + assert.sameValue(settleds[1].value, simulation); + $DONE(); + }).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allSettled/reject-immed.js b/test/built-ins/Promise/allSettled/reject-immed.js new file mode 100644 index 0000000000..2629aefaaf --- /dev/null +++ b/test/built-ins/Promise/allSettled/reject-immed.js @@ -0,0 +1,31 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Rejecting through immediate invocation of the provided resolving function +esid: sec-promise.allsettled +info: | + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + + Runtime Semantics: PerformPromiseAllSettled + + 6. Repeat + ... + z. Perform ? Invoke(nextPromise, "then", « resolveElement, rejectElement »). +flags: [async] +includes: [promiseHelper.js] +features: [Promise.allSettled] +---*/ + +var simulation = {}; +var thenable = { + then(_, reject) { + reject(simulation); + } +}; + +Promise.allSettled([thenable]) + .then((settleds) => { + checkSettledPromises(settleds, [{ status: 'rejected', reason: simulation }]); + $DONE(); + }).then($DONE, $DONE); \ No newline at end of file diff --git a/test/built-ins/Promise/allSettled/resolve-before-loop-exit-from-same.js b/test/built-ins/Promise/allSettled/resolve-before-loop-exit-from-same.js new file mode 100644 index 0000000000..872a4df74b --- /dev/null +++ b/test/built-ins/Promise/allSettled/resolve-before-loop-exit-from-same.js @@ -0,0 +1,83 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-performpromiseallsettled +description: > + Cannot tamper remainingElementsCount when Promise.allSettled resolve element function is called twice in a row. +info: | + Runtime Semantics: PerformPromiseAllSettled ( iteratorRecord, constructor, resultCapability ) + + 4. 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 + 1. Let valuesArray be CreateArrayFromList(values). + 2. Perform ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »). + ... + + Promise.allSettled Resolve Element Functions + + 2. Let alreadyCalled be F.[[AlreadyCalled]]. + 3. If alreadyCalled.[[Value]] is true, return undefined. + 4. Set alreadyCalled.[[Value]] to true. + ... +includes: [promiseHelper.js] +features: [Promise.allSettled] +---*/ + +var callCount = 0; + +function Constructor(executor) { + function resolve(values) { + callCount += 1; + checkSettledPromises(values, [ + { + status: 'fulfilled', + value: 'p1-fulfill' + }, + { + status: 'fulfilled', + value: 'p2-fulfill' + }, + { + status: 'fulfilled', + value: 'p3-fulfill' + } + ], 'values'); + } + executor(resolve, $ERROR); +} +Constructor.resolve = function(v) { + return v; +}; + +var p1OnFulfilled; + +var p1 = { + then(onFulfilled, onRejected) { + p1OnFulfilled = onFulfilled; + } +}; +var p2 = { + then(onFulfilled, onRejected) { + onFulfilled('p2-fulfill'); + onFulfilled('p2-fulfill-unexpected'); + } +}; +var p3 = { + then(onFulfilled, onRejected) { + onFulfilled('p3-fulfill'); + } +}; + +assert.sameValue(callCount, 0, 'callCount before call to all()'); + +Promise.allSettled.call(Constructor, [p1, p2, p3]); + +assert.sameValue(callCount, 0, 'callCount after call to all()'); + +p1OnFulfilled('p1-fulfill'); + +assert.sameValue(callCount, 1, 'callCount after resolving p1'); diff --git a/test/built-ins/Promise/allSettled/resolve-before-loop-exit.js b/test/built-ins/Promise/allSettled/resolve-before-loop-exit.js new file mode 100644 index 0000000000..07c443fc6d --- /dev/null +++ b/test/built-ins/Promise/allSettled/resolve-before-loop-exit.js @@ -0,0 +1,79 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-performpromiseallsettled +description: > + Cannot tamper remainingElementsCount when two Promise.allSettled resolve element functions are called in succession. +info: | + Runtime Semantics: PerformPromiseAllSettled ( iteratorRecord, constructor, resultCapability ) + + 4. 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 + 1. Let valuesArray be CreateArrayFromList(values). + 2. Perform ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »). + ... + + Promise.allSettled Resolve Element Functions + + 2. Let alreadyCalled be F.[[AlreadyCalled]]. + 3. If alreadyCalled.[[Value]] is true, return undefined. + 4. Set alreadyCalled.[[Value]] to true. + ... +includes: [promiseHelper.js] +features: [Promise.allSettled] +---*/ + +var callCount = 0; + +function Constructor(executor) { + function resolve(values) { + callCount += 1; + checkSettledPromises(values, [ + { + status: 'fulfilled', + value: 'p1-fulfill' + }, + { + status: 'fulfilled', + value: 'p2-fulfill' + }, + { + status: 'fulfilled', + value: 'p3-fulfill' + } + ], 'values'); + } + executor(resolve, $ERROR); +} +Constructor.resolve = function(v) { + return v; +}; + +var p1OnFulfilled; + +var p1 = { + then(onFulfilled, onRejected) { + p1OnFulfilled = onFulfilled; + } +}; +var p2 = { + then(onFulfilled, onRejected) { + p1OnFulfilled('p1-fulfill'); + onFulfilled('p2-fulfill'); + } +}; +var p3 = { + then(onFulfilled, onRejected) { + onFulfilled('p3-fulfill'); + } +}; + +assert.sameValue(callCount, 0, 'callCount before call to all()'); + +Promise.allSettled.call(Constructor, [p1, p2, p3]); + +assert.sameValue(callCount, 1, 'callCount after call to all()'); diff --git a/test/built-ins/Promise/allSettled/resolve-element-function-extensible.js b/test/built-ins/Promise/allSettled/resolve-element-function-extensible.js new file mode 100644 index 0000000000..915311ccde --- /dev/null +++ b/test/built-ins/Promise/allSettled/resolve-element-function-extensible.js @@ -0,0 +1,29 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled-resolve-element-functions +description: The [[Extensible]] slot of Promise.allSettled Resolve 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.allSettled] +---*/ + +var resolveElementFunction; +var thenable = { + then(fulfill) { + resolveElementFunction = fulfill; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.allSettled.call(NotPromise, [thenable]); + +assert(Object.isExtensible(resolveElementFunction)); diff --git a/test/built-ins/Promise/allSettled/resolve-element-function-length.js b/test/built-ins/Promise/allSettled/resolve-element-function-length.js new file mode 100644 index 0000000000..bd989ce186 --- /dev/null +++ b/test/built-ins/Promise/allSettled/resolve-element-function-length.js @@ -0,0 +1,38 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled-resolve-element-functions +description: The `length` property of Promise.allSettled Resolve Element functions +info: | + The length property of a Promise.allSettled resolve 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.allSettled] +---*/ + +var resolveElementFunction; +var thenable = { + then(fulfill) { + resolveElementFunction = fulfill; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.allSettled.call(NotPromise, [thenable]); + +verifyProperty(resolveElementFunction, 'length', { + value: 1, + enumerable: false, + writable: false, + configurable: true, +}); diff --git a/test/built-ins/Promise/allSettled/resolve-element-function-name.js b/test/built-ins/Promise/allSettled/resolve-element-function-name.js new file mode 100644 index 0000000000..76ff9fb83c --- /dev/null +++ b/test/built-ins/Promise/allSettled/resolve-element-function-name.js @@ -0,0 +1,35 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled-resolve-element-functions +description: The `name` property of Promise.allSettled Resolve 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, that is not + identified as an anonymous function has a name property whose value + is a String. +features: [Promise.allSettled] +---*/ + +var resolveElementFunction; +var thenable = { + then(fulfill) { + resolveElementFunction = fulfill; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.allSettled.call(NotPromise, [thenable]); + +assert.sameValue( + Object.prototype.hasOwnProperty.call(resolveElementFunction, 'name'), + false +); diff --git a/test/built-ins/Promise/allSettled/resolve-element-function-nonconstructor.js b/test/built-ins/Promise/allSettled/resolve-element-function-nonconstructor.js new file mode 100644 index 0000000000..319840110f --- /dev/null +++ b/test/built-ins/Promise/allSettled/resolve-element-function-nonconstructor.js @@ -0,0 +1,33 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled-resolve-element-functions +description: Promise.allSettled Resolve 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.allSettled] +---*/ + +var resolveElementFunction; +var thenable = { + then(fulfill) { + resolveElementFunction = fulfill; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.allSettled.call(NotPromise, [thenable]); + +assert.sameValue(Object.prototype.hasOwnProperty.call(resolveElementFunction, 'prototype'), false); +assert.throws(TypeError, function() { + new resolveElementFunction(); +}); diff --git a/test/built-ins/Promise/allSettled/resolve-element-function-prototype.js b/test/built-ins/Promise/allSettled/resolve-element-function-prototype.js new file mode 100644 index 0000000000..0e50f063a6 --- /dev/null +++ b/test/built-ins/Promise/allSettled/resolve-element-function-prototype.js @@ -0,0 +1,31 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled-resolve-element-functions +description: The [[Prototype]] of Promise.allSettled Resolve 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.allSettled] +---*/ + +var resolveElementFunction; +var thenable = { + then(fulfill) { + resolveElementFunction = fulfill; + } +}; + +function NotPromise(executor) { + executor(function() {}, function() {}); +} +NotPromise.resolve = function(v) { + return v; +}; +Promise.allSettled.call(NotPromise, [thenable]); + +assert.sameValue(Object.getPrototypeOf(resolveElementFunction), Function.prototype); diff --git a/test/built-ins/Promise/allSettled/resolve-from-same-thenable.js b/test/built-ins/Promise/allSettled/resolve-from-same-thenable.js new file mode 100644 index 0000000000..b23e69bb25 --- /dev/null +++ b/test/built-ins/Promise/allSettled/resolve-from-same-thenable.js @@ -0,0 +1,89 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-performpromiseallsettled +description: > + Cannot tamper remainingElementsCount when Promise.allSettled resolve element function is called multiple times. +info: | + Runtime Semantics: PerformPromiseAllSettled ( iteratorRecord, constructor, resultCapability ) + + 4. 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 + 1. Let valuesArray be CreateArrayFromList(values). + 2. Perform ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »). + ... + + Promise.allSettled Resolve Element Functions + + 2. Let alreadyCalled be F.[[AlreadyCalled]]. + 3. If alreadyCalled.[[Value]] is true, return undefined. + 4. Set alreadyCalled.[[Value]] to true. + ... +includes: [promiseHelper.js] +features: [Promise.allSettled] +---*/ + +var callCount = 0; + +function Constructor(executor) { + function resolve(values) { + callCount += 1; + checkSettledPromises(values, [ + { + status: 'fulfilled', + value: 'p1-fulfill' + }, + { + status: 'fulfilled', + value: 'p2-fulfill' + }, + { + status: 'fulfilled', + value: 'p3-fulfill' + } + ], 'values'); + } + executor(resolve, $ERROR); +} +Constructor.resolve = function(v) { + return v; +}; + +var p1OnFulfilled, p2OnFulfilled, p3OnFulfilled; + +var p1 = { + then(onFulfilled, onRejected) { + p1OnFulfilled = onFulfilled; + } +}; +var p2 = { + then(onFulfilled, onRejected) { + p2OnFulfilled = onFulfilled; + } +}; +var p3 = { + then(onFulfilled, onRejected) { + p3OnFulfilled = onFulfilled; + } +}; + +assert.sameValue(callCount, 0, 'callCount before call to all()'); + +Promise.allSettled.call(Constructor, [p1, p2, p3]); + +assert.sameValue(callCount, 0, 'callCount after call to all()'); + +p1OnFulfilled('p1-fulfill'); +p1OnFulfilled('p1-fulfill-unexpected-1'); +p1OnFulfilled('p1-fulfill-unexpected-2'); + +assert.sameValue(callCount, 0, 'callCount after resolving p1'); + +p2OnFulfilled('p2-fulfill'); +p3OnFulfilled('p3-fulfill'); + +assert.sameValue(callCount, 1, 'callCount after resolving all elements'); diff --git a/test/built-ins/Promise/allSettled/resolve-non-thenable.js b/test/built-ins/Promise/allSettled/resolve-non-thenable.js new file mode 100644 index 0000000000..8dae32d8cc --- /dev/null +++ b/test/built-ins/Promise/allSettled/resolve-non-thenable.js @@ -0,0 +1,39 @@ +// Copyright (C) 2019 Leo Balter. 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.allsettled +info: | + Promise.allSettled Resolve Element Functions + + 14. If remainingElementsCount.[[Value]] is 0, then + a. Let valuesArray be ! CreateArrayFromList(values). + b. Return ? Call(promiseCapability.[[Resolve]], undefined, « valuesArray »). +flags: [async] +includes: [compareArray.js, promiseHelper.js] +features: [Promise.allSettled] +---*/ + +var v1 = {}; +var v2 = {}; +var v3 = {}; + +Promise.allSettled([v1, v2, v3]) + .then(function(values) { + checkSettledPromises(values, [ + { + status: 'fulfilled', + value: v1 + }, + { + status: 'fulfilled', + value: v2 + }, + { + status: 'fulfilled', + value: v3 + } + ], 'values'); + }, function() { + $DONE('The promise should not be rejected.'); + }).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allSettled/resolve-poisoned-then.js b/test/built-ins/Promise/allSettled/resolve-poisoned-then.js new file mode 100644 index 0000000000..442f67cd74 --- /dev/null +++ b/test/built-ins/Promise/allSettled/resolve-poisoned-then.js @@ -0,0 +1,46 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with an object with a "poisoned" `then` property +esid: sec-promise.allsettled +info: | + Runtime Semantics: PerformPromiseAllSettled ( iteratorRecord, constructor, resultCapability ) + + 4. 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 + 1. Let valuesArray be CreateArrayFromList(values). + 2. Perform ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »). + ... +flags: [async] +features: [Promise.allSettled] +---*/ + +var value = {}; +var promise; + +try { + Object.defineProperty(Array.prototype, 'then', { + get() { + throw value; + }, + configurable: true + }); + + promise = Promise.allSettled([]); +} finally { + delete Array.prototype.then; +} + +promise.then(function() { + $DONE('The promise should not be fulfilled.'); +}, function(val) { + if (val !== value) { + $DONE('The promise should be rejected with the expected value.'); + return; + } + + $DONE(); +}); diff --git a/test/built-ins/Promise/allSettled/resolve-thenable.js b/test/built-ins/Promise/allSettled/resolve-thenable.js new file mode 100644 index 0000000000..9aa3ccd5b0 --- /dev/null +++ b/test/built-ins/Promise/allSettled/resolve-thenable.js @@ -0,0 +1,29 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Resolving with a thenable object value +esid: sec-promise.allsettled +info: | + Let promiseCapability be NewPromiseCapability(C). +flags: [async] +features: [Promise.allSettled] +---*/ + +var value = {}; +var promise; + +try { + Array.prototype.then = function(resolve) { + resolve(value); + }; + + promise = Promise.allSettled([]); +} finally { + delete Array.prototype.then; +} + +promise.then(function(val) { + assert.sameValue(val, value); +}, function() { + $DONE('The promise should not be rejected.'); +}).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allSettled/resolved-all-fulfilled.js b/test/built-ins/Promise/allSettled/resolved-all-fulfilled.js new file mode 100644 index 0000000000..6f16b18854 --- /dev/null +++ b/test/built-ins/Promise/allSettled/resolved-all-fulfilled.js @@ -0,0 +1,64 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Resolution is a collection of all the settled values (all fulfilled) +info: | + Runtime Semantics: PerformPromiseAllSettled + + 6. Repeat, + ... + j. Let steps be the algorithm steps defined in Promise.allSettled Resolve Element Functions. + k. Let resolveElement be ! CreateBuiltinFunction(steps, « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »). + ... + r. Let rejectSteps be the algorithm steps defined in Promise.allSettled Reject Element Functions. + s. Let rejectElement be ! CreateBuiltinFunction(rejectSteps, « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »). + ... + z. Perform ? Invoke(nextPromise, "then", « resolveElement, rejectElement »). + + Promise.allSettled Resolve Element Functions + + 9. Let obj be ! ObjectCreate(%ObjectPrototype%). + 10. Perform ! CreateDataProperty(obj, "status", "fulfilled"). + 11. Perform ! CreateDataProperty(obj, "value", x). + 12. Set values[index] to be obj. + 13. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1. + 14. If remainingElementsCount.[[Value]] is 0, then + a. Let valuesArray be ! CreateArrayFromList(values). + b. Return ? Call(promiseCapability.[[Resolve]], undefined, « valuesArray »). + + Promise.allSettled Reject Element Functions + + 9. Let obj be ! ObjectCreate(%ObjectPrototype%). + 10. Perform ! CreateDataProperty(obj, "status", "rejected"). + 11. Perform ! CreateDataProperty(obj, "reason", x). + 12. Set values[index] to be obj. + 13. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1. + 14. If remainingElementsCount.[[Value]] is 0, then + a. Let valuesArray be CreateArrayFromList(values). + b. Return ? Call(promiseCapability.[[Resolve]], undefined, « valuesArray »). +flags: [async] +includes: [promiseHelper.js] +features: [Promise.allSettled] +---*/ + +var obj = {}; +var p1 = new Promise(function(resolve) { + resolve(1); +}); +var p2 = new Promise(function(resolve) { + resolve('test262'); +}); +var p3 = new Promise(function(resolve) { + resolve(obj); +}); + +Promise.allSettled([p1, p2, p3]).then(function(settled) { + checkSettledPromises(settled, [ + { status: 'fulfilled', value: 1 }, + { status: 'fulfilled', value: 'test262' }, + { status: 'fulfilled', value: obj } + ], 'settled'); +}).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allSettled/resolved-all-mixed.js b/test/built-ins/Promise/allSettled/resolved-all-mixed.js new file mode 100644 index 0000000000..e2e5369735 --- /dev/null +++ b/test/built-ins/Promise/allSettled/resolved-all-mixed.js @@ -0,0 +1,77 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Resolution is a collection of all the settled values (fulfilled and rejected) +info: | + Runtime Semantics: PerformPromiseAllSettled + + 6. Repeat, + ... + j. Let steps be the algorithm steps defined in Promise.allSettled Resolve Element Functions. + k. Let resolveElement be ! CreateBuiltinFunction(steps, « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »). + ... + r. Let rejectSteps be the algorithm steps defined in Promise.allSettled Reject Element Functions. + s. Let rejectElement be ! CreateBuiltinFunction(rejectSteps, « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »). + ... + z. Perform ? Invoke(nextPromise, "then", « resolveElement, rejectElement »). + + Promise.allSettled Resolve Element Functions + + 9. Let obj be ! ObjectCreate(%ObjectPrototype%). + 10. Perform ! CreateDataProperty(obj, "status", "fulfilled"). + 11. Perform ! CreateDataProperty(obj, "value", x). + 12. Set values[index] to be obj. + 13. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1. + 14. If remainingElementsCount.[[Value]] is 0, then + a. Let valuesArray be ! CreateArrayFromList(values). + b. Return ? Call(promiseCapability.[[Resolve]], undefined, « valuesArray »). + + Promise.allSettled Reject Element Functions + + 9. Let obj be ! ObjectCreate(%ObjectPrototype%). + 10. Perform ! CreateDataProperty(obj, "status", "rejected"). + 11. Perform ! CreateDataProperty(obj, "reason", x). + 12. Set values[index] to be obj. + 13. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1. + 14. If remainingElementsCount.[[Value]] is 0, then + a. Let valuesArray be CreateArrayFromList(values). + b. Return ? Call(promiseCapability.[[Resolve]], undefined, « valuesArray »). +flags: [async] +includes: [promiseHelper.js] +features: [Promise.allSettled] +---*/ + +var obj1 = {}; +var obj2 = {}; +var r1 = new Promise(function(_, reject) { + reject(1); +}); +var f1 = new Promise(function(resolve) { + resolve(2); +}); +var f2 = new Promise(function(resolve) { + resolve('tc39'); +}); +var r2 = new Promise(function(_, reject) { + reject('test262'); +}); +var r3 = new Promise(function(_, reject) { + reject(obj1); +}); +var f3 = new Promise(function(resolve) { + resolve(obj2); +}); + +Promise.allSettled([r1, f1, f2, r2, r3, f3]).then(function(settled) { + checkSettledPromises(settled, [ + { status: 'rejected', reason: 1 }, + { status: 'fulfilled', value: 2 }, + { status: 'fulfilled', value: 'tc39' }, + { status: 'rejected', reason: 'test262' }, + { status: 'rejected', reason: obj1 }, + { status: 'fulfilled', value: obj2 } + ], 'settled'); +}).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allSettled/resolved-all-rejected.js b/test/built-ins/Promise/allSettled/resolved-all-rejected.js new file mode 100644 index 0000000000..ba9a91f22f --- /dev/null +++ b/test/built-ins/Promise/allSettled/resolved-all-rejected.js @@ -0,0 +1,64 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Resolution is a collection of all the settled values (fulfiled and rejected promises) +info: | + Runtime Semantics: PerformPromiseAllSettled + + 6. Repeat, + ... + j. Let steps be the algorithm steps defined in Promise.allSettled Resolve Element Functions. + k. Let resolveElement be ! CreateBuiltinFunction(steps, « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »). + ... + r. Let rejectSteps be the algorithm steps defined in Promise.allSettled Reject Element Functions. + s. Let rejectElement be ! CreateBuiltinFunction(rejectSteps, « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »). + ... + z. Perform ? Invoke(nextPromise, "then", « resolveElement, rejectElement »). + + Promise.allSettled Resolve Element Functions + + 9. Let obj be ! ObjectCreate(%ObjectPrototype%). + 10. Perform ! CreateDataProperty(obj, "status", "fulfilled"). + 11. Perform ! CreateDataProperty(obj, "value", x). + 12. Set values[index] to be obj. + 13. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1. + 14. If remainingElementsCount.[[Value]] is 0, then + a. Let valuesArray be ! CreateArrayFromList(values). + b. Return ? Call(promiseCapability.[[Resolve]], undefined, « valuesArray »). + + Promise.allSettled Reject Element Functions + + 9. Let obj be ! ObjectCreate(%ObjectPrototype%). + 10. Perform ! CreateDataProperty(obj, "status", "rejected"). + 11. Perform ! CreateDataProperty(obj, "reason", x). + 12. Set values[index] to be obj. + 13. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1. + 14. If remainingElementsCount.[[Value]] is 0, then + a. Let valuesArray be CreateArrayFromList(values). + b. Return ? Call(promiseCapability.[[Resolve]], undefined, « valuesArray »). +flags: [async] +includes: [promiseHelper.js] +features: [Promise.allSettled] +---*/ + +var obj = {}; +var p1 = new Promise(function(_, reject) { + reject(1); +}); +var p2 = new Promise(function(_, reject) { + reject('test262'); +}); +var p3 = new Promise(function(_, reject) { + reject(obj); +}); + +Promise.allSettled([p1, p2, p3]).then(function(settled) { + checkSettledPromises(settled, [ + { status: 'rejected', reason: 1 }, + { status: 'rejected', reason: 'test262' }, + { status: 'rejected', reason: obj } + ], 'settled'); +}).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allSettled/resolved-immed.js b/test/built-ins/Promise/allSettled/resolved-immed.js new file mode 100644 index 0000000000..2401141501 --- /dev/null +++ b/test/built-ins/Promise/allSettled/resolved-immed.js @@ -0,0 +1,25 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: Promise.allSettled([]) returns immediately +includes: [promiseHelper.js] +flags: [async] +features: [Promise.allSettled] +---*/ + +var sequence = []; + +Promise.allSettled([]).then(function() { + sequence.push(2); +}).catch($DONE); + +Promise.resolve().then(function() { + sequence.push(3); +}).then(function() { + sequence.push(4); + checkSequence(sequence, 'Promises resolved in unexpected sequence'); +}).then($DONE, $DONE); + +sequence.push(1); diff --git a/test/built-ins/Promise/allSettled/resolved-sequence-extra-ticks.js b/test/built-ins/Promise/allSettled/resolved-sequence-extra-ticks.js new file mode 100644 index 0000000000..ecb288d960 --- /dev/null +++ b/test/built-ins/Promise/allSettled/resolved-sequence-extra-ticks.js @@ -0,0 +1,44 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: Resolution ticks are set in a predictable sequence with extra then calls +info: | + Runtime Semantics: PerformPromiseAllSettled ( iteratorRecord, constructor, resultCapability ) + + 4. 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 + 1. Let valuesArray be CreateArrayFromList(values). + 2. Perform ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »). + ... +flags: [async] +includes: [promiseHelper.js] +features: [Promise.allSettled] +---*/ + +var sequence = []; + +var p1 = new Promise(function(resolve) { + resolve({}); +}); + +sequence.push(1); + +Promise.allSettled([p1]).then(function(resolved) { + sequence.push(4); + checkSequence(sequence, 'Expected Promise.allSettled().then to queue second'); +}).catch($DONE); + +p1.then(function() { + sequence.push(3); + checkSequence(sequence, 'Expected p1.then to queue first'); +}).then(function() { + sequence.push(5); + checkSequence(sequence, 'Expected final then to queue last'); +}).then($DONE, $DONE); + +sequence.push(2); diff --git a/test/built-ins/Promise/allSettled/resolved-sequence-mixed.js b/test/built-ins/Promise/allSettled/resolved-sequence-mixed.js new file mode 100644 index 0000000000..ebbfb79113 --- /dev/null +++ b/test/built-ins/Promise/allSettled/resolved-sequence-mixed.js @@ -0,0 +1,58 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Resolution ticks are set in a predictable sequence of mixed fulfilled and rejected promises +info: | + Runtime Semantics: PerformPromiseAllSettled ( iteratorRecord, constructor, resultCapability ) + + 4. 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 + 1. Let valuesArray be CreateArrayFromList(values). + 2. Perform ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »). + ... +flags: [async] +includes: [promiseHelper.js] +features: [Promise.allSettled] +---*/ + +var sequence = []; + +var p1 = new Promise(function(_, reject) { + reject(''); +}); +var p2 = new Promise(function(resolve) { + resolve(''); +}); +var p3 = new Promise(function(_, reject) { + reject(''); +}); + +sequence.push(1); + +p1.catch(function() { + sequence.push(3); + checkSequence(sequence, 'Expected to be called first.'); +}).catch($DONE); + +Promise.allSettled([p1, p2, p3]).then(function() { + sequence.push(6); + checkSequence(sequence, 'Expected to be called fourth.'); +}).then($DONE, $DONE); + +p2.then(function() { + sequence.push(4); + checkSequence(sequence, 'Expected to be called second.'); +}).catch($DONE); + +sequence.push(2); + +p3.catch(function() { + sequence.push(5); + checkSequence(sequence, 'Expected to be called third.'); +}).catch($DONE); diff --git a/test/built-ins/Promise/allSettled/resolved-sequence-with-rejections.js b/test/built-ins/Promise/allSettled/resolved-sequence-with-rejections.js new file mode 100644 index 0000000000..3e8dd02a7f --- /dev/null +++ b/test/built-ins/Promise/allSettled/resolved-sequence-with-rejections.js @@ -0,0 +1,49 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: Resolution ticks are set in a predictable sequence +info: | + Runtime Semantics: PerformPromiseAllSettled ( iteratorRecord, constructor, resultCapability ) + + 4. 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 + 1. Let valuesArray be CreateArrayFromList(values). + 2. Perform ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »). + ... +flags: [async] +includes: [promiseHelper.js] +features: [Promise.allSettled] +---*/ + +var sequence = []; + +var p1 = new Promise(function(_, reject) { + reject('foo'); +}); +var p2 = new Promise(function(_, reject) { + reject('bar'); +}); + +sequence.push(1); + +p1.catch(function() { + sequence.push(3); + checkSequence(sequence, 'Expected to be called first.'); +}).catch($DONE); + +Promise.allSettled([p1, p2]).then(function() { + sequence.push(5); + checkSequence(sequence, 'Expected to be called third.'); +}).then($DONE, $DONE); + +p2.catch(function() { + sequence.push(4); + checkSequence(sequence, 'Expected to be called second.'); +}).catch($DONE); + +sequence.push(2); diff --git a/test/built-ins/Promise/allSettled/resolved-sequence.js b/test/built-ins/Promise/allSettled/resolved-sequence.js new file mode 100644 index 0000000000..2ea0382121 --- /dev/null +++ b/test/built-ins/Promise/allSettled/resolved-sequence.js @@ -0,0 +1,49 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: Resolution ticks are set in a predictable sequence +info: | + Runtime Semantics: PerformPromiseAllSettled ( iteratorRecord, constructor, resultCapability ) + + 4. 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 + 1. Let valuesArray be CreateArrayFromList(values). + 2. Perform ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »). + ... +flags: [async] +includes: [promiseHelper.js] +features: [Promise.allSettled] +---*/ + +var sequence = []; + +var p1 = new Promise(function(resolve) { + resolve(1); +}); +var p2 = new Promise(function(resolve) { + resolve(2); +}); + +sequence.push(1); + +p1.then(function() { + sequence.push(3); + checkSequence(sequence, 'Expected to be called first.'); +}).catch($DONE); + +Promise.allSettled([p1, p2]).then(function() { + sequence.push(5); + checkSequence(sequence, 'Expected to be called third.'); +}).then($DONE, $DONE); + +p2.then(function() { + sequence.push(4); + checkSequence(sequence, 'Expected to be called second.'); +}).catch($DONE); + +sequence.push(2); diff --git a/test/built-ins/Promise/allSettled/resolved-then-catch-finally.js b/test/built-ins/Promise/allSettled/resolved-then-catch-finally.js new file mode 100644 index 0000000000..2868d3a4a4 --- /dev/null +++ b/test/built-ins/Promise/allSettled/resolved-then-catch-finally.js @@ -0,0 +1,69 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: > + Resolution is a collection of all the settled values (all fulfilled) +info: | + Runtime Semantics: PerformPromiseAllSettled + + 6. Repeat, + ... + j. Let steps be the algorithm steps defined in Promise.allSettled Resolve Element Functions. + k. Let resolveElement be ! CreateBuiltinFunction(steps, « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »). + ... + r. Let rejectSteps be the algorithm steps defined in Promise.allSettled Reject Element Functions. + s. Let rejectElement be ! CreateBuiltinFunction(rejectSteps, « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »). + ... + z. Perform ? Invoke(nextPromise, "then", « resolveElement, rejectElement »). + + Promise.allSettled Resolve Element Functions + + 9. Let obj be ! ObjectCreate(%ObjectPrototype%). + 10. Perform ! CreateDataProperty(obj, "status", "fulfilled"). + 11. Perform ! CreateDataProperty(obj, "value", x). + 12. Set values[index] to be obj. + 13. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1. + 14. If remainingElementsCount.[[Value]] is 0, then + a. Let valuesArray be ! CreateArrayFromList(values). + b. Return ? Call(promiseCapability.[[Resolve]], undefined, « valuesArray »). + + Promise.allSettled Reject Element Functions + + 9. Let obj be ! ObjectCreate(%ObjectPrototype%). + 10. Perform ! CreateDataProperty(obj, "status", "rejected"). + 11. Perform ! CreateDataProperty(obj, "reason", x). + 12. Set values[index] to be obj. + 13. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1. + 14. If remainingElementsCount.[[Value]] is 0, then + a. Let valuesArray be CreateArrayFromList(values). + b. Return ? Call(promiseCapability.[[Resolve]], undefined, « valuesArray »). +flags: [async] +includes: [promiseHelper.js] +features: [Promise.allSettled] +---*/ + +var p0 = Promise.resolve(2).then(v => v + 1); +var p1 = Promise.reject(21).catch(v => v * 2); +var p2 = Promise.resolve('nope').then(() => { throw 'foo' }); +var p3 = Promise.reject('yes').then(() => { throw 'nope'; }); +var p4 = Promise.resolve('here').finally(() => 'nope'); +var p5 = Promise.reject('here too').finally(() => 'nope'); +var p6 = Promise.resolve('nope').finally(() => { throw 'finally'; }); +var p7 = Promise.reject('nope').finally(() => { throw 'finally after rejected'; }); +var p8 = Promise.reject(1).then(() => 'nope', () => 0); + +Promise.allSettled([p0, p1, p2, p3, p4, p5, p6, p7, p8]).then(function(settled) { + checkSettledPromises(settled, [ + { status: 'fulfilled', value: 3 }, + { status: 'fulfilled', value: 42 }, + { status: 'rejected', reason: 'foo' }, + { status: 'rejected', reason: 'yes' }, + { status: 'fulfilled', value: 'here' }, + { status: 'rejected', reason: 'here too' }, + { status: 'rejected', reason: 'finally' }, + { status: 'rejected', reason: 'finally after rejected' }, + { status: 'fulfilled', value: 0 }, + ], 'settled'); +}).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allSettled/resolves-empty-array.js b/test/built-ins/Promise/allSettled/resolves-empty-array.js new file mode 100644 index 0000000000..49540e206f --- /dev/null +++ b/test/built-ins/Promise/allSettled/resolves-empty-array.js @@ -0,0 +1,27 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: Promise.allSettled([]) returns a Promise for an empty array +info: | + Runtime Semantics: PerformPromiseAllSettled ( iteratorRecord, constructor, resultCapability ) + + 4. 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 + 1. Let valuesArray be CreateArrayFromList(values). + 2. Perform ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »). + ... +flags: [async] +includes: [promiseHelper.js] +features: [Promise.allSettled] +---*/ + +var arg = []; + +Promise.allSettled(arg).then(function(result) { + checkSettledPromises(result, []); +}).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allSettled/resolves-to-array.js b/test/built-ins/Promise/allSettled/resolves-to-array.js new file mode 100644 index 0000000000..f7acc7625e --- /dev/null +++ b/test/built-ins/Promise/allSettled/resolves-to-array.js @@ -0,0 +1,28 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: Promise.allSettled returned a promise resolves into an array +info: | + Runtime Semantics: PerformPromiseAllSettled ( iteratorRecord, constructor, resultCapability ) + + 4. 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 + 1. Let valuesArray be CreateArrayFromList(values). + 2. Perform ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »). + ... +flags: [async] +features: [Promise.allSettled] +---*/ + +var arg = []; + +Promise.allSettled([]).then(function(result) { + assert(Array.isArray(result)); + assert.sameValue(Object.getPrototypeOf(result), Array.prototype); + assert.notSameValue(result, arg, 'the resolved array is a new array'); +}).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allSettled/returns-promise.js b/test/built-ins/Promise/allSettled/returns-promise.js new file mode 100644 index 0000000000..7c7cf8fcb5 --- /dev/null +++ b/test/built-ins/Promise/allSettled/returns-promise.js @@ -0,0 +1,24 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettled +description: Promise.allSettled returns a Promise +info: | + Promise.allSettled ( iterable ) + + 3. Let promiseCapability be ? NewPromiseCapability(C). + 4. Let iteratorRecord be GetIterator(iterable). + 5. IfAbruptRejectPromise(iteratorRecord, promiseCapability). + 6. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability). + 7. If result is an abrupt completion, then + a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result). + b. IfAbruptRejectPromise(result, promiseCapability). + 8. Return Completion(result). +features: [Promise.allSettled] +---*/ + +var p = Promise.allSettled([]); + +assert(p instanceof Promise); +assert.sameValue(Object.getPrototypeOf(p), Promise.prototype); diff --git a/test/built-ins/Promise/allSettled/species-get-error.js b/test/built-ins/Promise/allSettled/species-get-error.js new file mode 100644 index 0000000000..8f003f32d0 --- /dev/null +++ b/test/built-ins/Promise/allSettled/species-get-error.js @@ -0,0 +1,25 @@ +// Copyright (C) 2019 Leo Balter. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Promise.allSettled() does not retrieve `Symbol.species` property of the `this` value +esid: sec-promise.allsettled +info: | + 1. Let C be the this value. + 2. If Type(C) is not Object, throw a TypeError exception. + 3. Let promiseCapability be ? NewPromiseCapability(C). + ... +features: [Promise.allSettled, Symbol.species] +---*/ + +function C(executor) { + executor(function() {}, function() {}); +} +Object.defineProperty(C, Symbol.species, { + get() { + throw new Test262Error('Getter for Symbol.species called'); + } +}); + +Promise.allSettled.call(C, []);