diff --git a/test/built-ins/Promise/allKeyed/arg-is-function.js b/test/built-ins/Promise/allKeyed/arg-is-function.js new file mode 100644 index 00000000000..018f0d7ef62 --- /dev/null +++ b/test/built-ins/Promise/allKeyed/arg-is-function.js @@ -0,0 +1,37 @@ +// Copyright (C) 2026 Danial Asaria (Bloomberg LP). All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allkeyed +description: > + Promise.allKeyed accepts a function argument with enumerable own properties +info: | + Promise.allKeyed ( promises ) + + ... + 5. If promises is not an Object, then + a. ...Reject... + ... + + Functions are objects, so they pass the type check. Only own enumerable + properties are traversed; built-in function properties (name, length, + prototype) are non-enumerable by default and should be excluded. +flags: [async] +features: [await-dictionary] +---*/ + +function fn() {} +fn.key = Promise.resolve('val'); + +Promise.allKeyed(fn).then(function(result) { + assert.sameValue(Object.getPrototypeOf(result), null); + + var keys = Reflect.ownKeys(result); + assert.sameValue(keys.length, 1); + assert.sameValue(keys[0], 'key'); + assert.sameValue(result.key, 'val'); + + assert.sameValue(Object.prototype.hasOwnProperty.call(result, 'name'), false); + assert.sameValue(Object.prototype.hasOwnProperty.call(result, 'length'), false); + assert.sameValue(Object.prototype.hasOwnProperty.call(result, 'prototype'), false); +}).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allKeyed/arg-not-object-reject-bigint.js b/test/built-ins/Promise/allKeyed/arg-not-object-reject-bigint.js new file mode 100644 index 00000000000..5d58572c3ba --- /dev/null +++ b/test/built-ins/Promise/allKeyed/arg-not-object-reject-bigint.js @@ -0,0 +1,24 @@ +// Copyright (C) 2026 Danial Asaria (Bloomberg LP). All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allkeyed +description: > + Promise.allKeyed rejects when the promises argument is a BigInt +info: | + Promise.allKeyed ( promises ) + + ... + 5. If promises is not an Object, then + a. Let error be a newly created TypeError object. + b. Perform ? Call(promiseCapability.[[Reject]], undefined, « error »). + c. Return promiseCapability.[[Promise]]. +flags: [async] +features: [await-dictionary, BigInt] +---*/ + +Promise.allKeyed(0n).then(function() { + throw new Test262Error('The promise should be rejected for BigInt'); +}, function(error) { + assert(error instanceof TypeError, 'rejects with TypeError for BigInt'); +}).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allKeyed/arg-not-object-reject.js b/test/built-ins/Promise/allKeyed/arg-not-object-reject.js new file mode 100644 index 00000000000..3148004961e --- /dev/null +++ b/test/built-ins/Promise/allKeyed/arg-not-object-reject.js @@ -0,0 +1,34 @@ +// Copyright (C) 2026 Danial Asaria (Bloomberg LP). All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allkeyed +description: > + Promise.allKeyed rejects when the promises argument is not an Object +info: | + Promise.allKeyed ( promises ) + + ... + 5. If promises is not an Object, then + a. Let error be a newly created TypeError object. + b. Perform ? Call(promiseCapability.[[Reject]], undefined, « error »). + c. Return promiseCapability.[[Promise]]. +flags: [async] +features: [await-dictionary, Symbol] +---*/ + +function checkRejects(value) { + return Promise.allKeyed(value).then(function() { + throw new Test262Error('The promise should be rejected for ' + typeof value); + }, function(error) { + assert(error instanceof TypeError, 'rejects with TypeError for ' + typeof value); + }); +} + +checkRejects(undefined) + .then(function() { return checkRejects(null); }) + .then(function() { return checkRejects(86); }) + .then(function() { return checkRejects('string'); }) + .then(function() { return checkRejects(true); }) + .then(function() { return checkRejects(Symbol()); }) + .then($DONE, $DONE); diff --git a/test/built-ins/Promise/allKeyed/ctx-non-ctor.js b/test/built-ins/Promise/allKeyed/ctx-non-ctor.js new file mode 100644 index 00000000000..b9ca7f6b064 --- /dev/null +++ b/test/built-ins/Promise/allKeyed/ctx-non-ctor.js @@ -0,0 +1,22 @@ +// Copyright (C) 2026 Danial Asaria (Bloomberg LP). All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allkeyed +description: > + Promise.allKeyed invoked on a non-constructor value +info: | + Promise.allKeyed ( promises ) + + 1. Let C be the this value. + 2. Let promiseCapability be ? NewPromiseCapability(C). + + NewPromiseCapability ( C ) + + 1. If IsConstructor(C) is false, throw a TypeError exception. +features: [await-dictionary] +---*/ + +assert.throws(TypeError, function() { + Promise.allKeyed.call(eval); +}); diff --git a/test/built-ins/Promise/allKeyed/key-order-preserved.js b/test/built-ins/Promise/allKeyed/key-order-preserved.js new file mode 100644 index 00000000000..afd8943ef27 --- /dev/null +++ b/test/built-ins/Promise/allKeyed/key-order-preserved.js @@ -0,0 +1,58 @@ +// Copyright (C) 2026 Danial Asaria (Bloomberg LP). All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-performpromiseallkeyed +description: > + Promise.allKeyed result key order matches property key order, not settlement order +info: | + PerformPromiseAllKeyed ( variant, promises, constructor, resultCapability, promiseResolve ) + + ... + 1. Let allKeys be ? promises.[[OwnPropertyKeys]](). + ... + 6. For each element key of allKeys, do + ... + b. If desc is not undefined and desc.[[Enumerable]] is true, then + ... + ii. Append key to keys. + ... + ... + ... + 8. If remainingElementsCount.[[Value]] = 0, then + ... + b. Let result be CreateKeyedPromiseCombinatorResultObject(keys, values). +includes: [compareArray.js] +flags: [async] +features: [await-dictionary] +---*/ + +var resolveFirst; +var resolveSecond; +var resolveThird; + +var input = { + first: new Promise(function(resolve) { + resolveFirst = resolve; + }), + second: new Promise(function(resolve) { + resolveSecond = resolve; + }), + third: new Promise(function(resolve) { + resolveThird = resolve; + }) +}; + +var combined = Promise.allKeyed(input); + +resolveSecond('second'); +resolveThird('third'); +resolveFirst('first'); + +combined.then(function(result) { + assert.sameValue(Object.getPrototypeOf(result), null); + assert.compareArray(Object.keys(result), ['first', 'second', 'third']); + assert.sameValue(result.first, 'first'); + assert.sameValue(result.second, 'second'); + assert.sameValue(result.third, 'third'); +}).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allKeyed/non-enumerable-properties-ignored.js b/test/built-ins/Promise/allKeyed/non-enumerable-properties-ignored.js new file mode 100644 index 00000000000..b0f4fada187 --- /dev/null +++ b/test/built-ins/Promise/allKeyed/non-enumerable-properties-ignored.js @@ -0,0 +1,35 @@ +// Copyright (C) 2026 Danial Asaria (Bloomberg LP). All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-performpromiseallkeyed +description: > + Promise.allKeyed ignores non-enumerable own properties +info: | + PerformPromiseAllKeyed ( variant, promises, constructor, resultCapability, promiseResolve ) + + ... + 6. For each element key of allKeys, do + a. Let desc be ? promises.[[GetOwnProperty]](key). + b. If desc is not undefined and desc.[[Enumerable]] is true, then + ... +includes: [compareArray.js] +flags: [async] +features: [await-dictionary] +---*/ + +var input = { + visible: Promise.resolve(2) +}; + +Object.defineProperty(input, 'hidden', { + enumerable: false, + value: Promise.resolve(1) +}); + +Promise.allKeyed(input).then(function(result) { + assert.sameValue(Object.getPrototypeOf(result), null); + assert.compareArray(Object.keys(result), ['visible']); + assert.sameValue(result.visible, 2); + assert.sameValue(Object.prototype.hasOwnProperty.call(result, 'hidden'), false); +}).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allKeyed/prototype-keys-ignored.js b/test/built-ins/Promise/allKeyed/prototype-keys-ignored.js new file mode 100644 index 00000000000..c0b104ccd5a --- /dev/null +++ b/test/built-ins/Promise/allKeyed/prototype-keys-ignored.js @@ -0,0 +1,32 @@ +// Copyright (C) 2026 Danial Asaria (Bloomberg LP). All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-performpromiseallkeyed +description: > + Promise.allKeyed ignores inherited prototype properties +info: | + PerformPromiseAllKeyed ( variant, promises, constructor, resultCapability, promiseResolve ) + + ... + 1. Let allKeys be ? promises.[[OwnPropertyKeys]](). + ... + 6. For each element key of allKeys, do + a. Let desc be ? promises.[[GetOwnProperty]](key). + b. If desc is not undefined and desc.[[Enumerable]] is true, then + ... +includes: [compareArray.js] +flags: [async] +features: [await-dictionary] +---*/ + +var proto = { inherited: Promise.resolve('nope') }; +var input = Object.create(proto); +input.own = Promise.resolve('yes'); + +Promise.allKeyed(input).then(function(result) { + assert.sameValue(Object.getPrototypeOf(result), null); + assert.compareArray(Object.keys(result), ['own']); + assert.sameValue(result.own, 'yes'); + assert.sameValue(Object.prototype.hasOwnProperty.call(result, 'inherited'), false); +}).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allKeyed/reject-deferred.js b/test/built-ins/Promise/allKeyed/reject-deferred.js new file mode 100644 index 00000000000..0676aab6713 --- /dev/null +++ b/test/built-ins/Promise/allKeyed/reject-deferred.js @@ -0,0 +1,36 @@ +// Copyright (C) 2026 Danial Asaria (Bloomberg LP). All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-performpromiseallkeyed +description: Rejecting from an asynchronously rejected input promise +info: | + PerformPromiseAllKeyed ( variant, promises, constructor, resultCapability, promiseResolve ) + + ... + 6. For each element key of allKeys, do + ... + b. If desc is not undefined and desc.[[Enumerable]] is true, then + ... + 8. If variant is all, then + a. Let onRejected be resultCapability.[[Reject]]. + ... + 11. Perform ? Invoke(nextPromise, "then", « onFulfilled, onRejected »). +flags: [async] +features: [await-dictionary] +---*/ + +var error = new Test262Error(); + +var p = new Promise(function(_, reject) { + Promise.resolve().then(function() { + reject(error); + }); +}); + +Promise.allKeyed({ key: p }) + .then(function() { + throw new Test262Error('The promise should not be fulfilled.'); + }, function(reason) { + assert.sameValue(reason, error); + }).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allKeyed/reject-immed.js b/test/built-ins/Promise/allKeyed/reject-immed.js new file mode 100644 index 00000000000..c297893a758 --- /dev/null +++ b/test/built-ins/Promise/allKeyed/reject-immed.js @@ -0,0 +1,34 @@ +// Copyright (C) 2026 Danial Asaria (Bloomberg LP). All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-performpromiseallkeyed +description: Rejecting from a synchronously rejected input promise +info: | + PerformPromiseAllKeyed ( variant, promises, constructor, resultCapability, promiseResolve ) + + ... + 6. For each element key of allKeys, do + ... + b. If desc is not undefined and desc.[[Enumerable]] is true, then + ... + 8. If variant is all, then + a. Let onRejected be resultCapability.[[Reject]]. + ... + 11. Perform ? Invoke(nextPromise, "then", « onFulfilled, onRejected »). +flags: [async] +features: [await-dictionary] +---*/ + +var error = new Test262Error(); + +var p = new Promise(function(_, reject) { + reject(error); +}); + +Promise.allKeyed({ key: p }) + .then(function() { + throw new Test262Error('The promise should not be fulfilled.'); + }, function(reason) { + assert.sameValue(reason, error); + }).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allKeyed/resolve-not-callable-reject-with-typeerror.js b/test/built-ins/Promise/allKeyed/resolve-not-callable-reject-with-typeerror.js new file mode 100644 index 00000000000..126c958409b --- /dev/null +++ b/test/built-ins/Promise/allKeyed/resolve-not-callable-reject-with-typeerror.js @@ -0,0 +1,34 @@ +// Copyright (C) 2026 Danial Asaria (Bloomberg LP). All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allkeyed +description: > + If the constructor's `resolve` method is not callable, reject with a TypeError. +info: | + Promise.allKeyed ( promises ) + + ... + 3. Let promiseResolve be Completion(GetPromiseResolve(C)). + 4. IfAbruptRejectPromise(promiseResolve, promiseCapability). + ... + + GetPromiseResolve ( promiseConstructor ) + + ... + 3. If IsCallable(promiseResolve) is false, throw a TypeError exception. +flags: [async] +features: [await-dictionary] +---*/ + +Promise.resolve = null; + +Promise.allKeyed({ key: 1 }) + .then( + function() { + $DONE('The promise should not be resolved.'); + }, + function(error) { + assert(error instanceof TypeError); + } + ).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allKeyed/resolves-empty-object.js b/test/built-ins/Promise/allKeyed/resolves-empty-object.js new file mode 100644 index 00000000000..4ca381d616d --- /dev/null +++ b/test/built-ins/Promise/allKeyed/resolves-empty-object.js @@ -0,0 +1,27 @@ +// Copyright (C) 2026 Danial Asaria (Bloomberg LP). All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-performpromiseallkeyed +description: > + Promise.allKeyed resolves an empty object to an empty null-prototype object +info: | + PerformPromiseAllKeyed ( variant, promises, constructor, resultCapability, promiseResolve ) + + ... + 1. Let allKeys be ? promises.[[OwnPropertyKeys]](). + ... + 7. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1. + 8. If remainingElementsCount.[[Value]] = 0, then + a. Let result be CreateKeyedPromiseCombinatorResultObject(keys, values). + b. Perform ? Call(resultCapability.[[Resolve]], undefined, « result »). +includes: [compareArray.js] +flags: [async] +features: [await-dictionary] +---*/ + +Promise.allKeyed({}).then(function(result) { + assert.sameValue(Object.getPrototypeOf(result), null); + assert.sameValue(result.hasOwnProperty, undefined); + assert.compareArray(Reflect.ownKeys(result), []); +}).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allKeyed/symbol-keys.js b/test/built-ins/Promise/allKeyed/symbol-keys.js new file mode 100644 index 00000000000..331ed2e575e --- /dev/null +++ b/test/built-ins/Promise/allKeyed/symbol-keys.js @@ -0,0 +1,36 @@ +// Copyright (C) 2026 Danial Asaria (Bloomberg LP). All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-performpromiseallkeyed +description: > + Promise.allKeyed includes enumerable symbol-keyed properties +info: | + PerformPromiseAllKeyed ( variant, promises, constructor, resultCapability, promiseResolve ) + + ... + 1. Let allKeys be ? promises.[[OwnPropertyKeys]](). + ... + 6. For each element key of allKeys, do + a. Let desc be ? promises.[[GetOwnProperty]](key). + b. If desc is not undefined and desc.[[Enumerable]] is true, then + ... +flags: [async] +features: [await-dictionary, Symbol] +---*/ + +var sym = Symbol('s'); +var input = { str: Promise.resolve(1) }; +input[sym] = Promise.resolve(2); + +Promise.allKeyed(input).then(function(result) { + assert.sameValue(Object.getPrototypeOf(result), null); + + var keys = Reflect.ownKeys(result); + assert.sameValue(keys.length, 2); + assert.sameValue(keys[0], 'str'); + assert.sameValue(keys[1], sym); + + assert.sameValue(result.str, 1); + assert.sameValue(result[sym], 2); +}).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allSettledKeyed/arg-is-function.js b/test/built-ins/Promise/allSettledKeyed/arg-is-function.js new file mode 100644 index 00000000000..9cd7a7f9d38 --- /dev/null +++ b/test/built-ins/Promise/allSettledKeyed/arg-is-function.js @@ -0,0 +1,38 @@ +// Copyright (C) 2026 Danial Asaria (Bloomberg LP). All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettledkeyed +description: > + Promise.allSettledKeyed accepts a function argument with enumerable own properties +info: | + Promise.allSettledKeyed ( promises ) + + ... + 5. If promises is not an Object, then + a. ...Reject... + ... + + Functions are objects, so they pass the type check. Only own enumerable + properties are traversed; built-in function properties (name, length, + prototype) are non-enumerable by default and should be excluded. +flags: [async] +features: [await-dictionary] +---*/ + +function fn() {} +fn.key = Promise.resolve('val'); + +Promise.allSettledKeyed(fn).then(function(result) { + assert.sameValue(Object.getPrototypeOf(result), null); + + var keys = Reflect.ownKeys(result); + assert.sameValue(keys.length, 1); + assert.sameValue(keys[0], 'key'); + assert.sameValue(result.key.status, 'fulfilled'); + assert.sameValue(result.key.value, 'val'); + + assert.sameValue(Object.prototype.hasOwnProperty.call(result, 'name'), false); + assert.sameValue(Object.prototype.hasOwnProperty.call(result, 'length'), false); + assert.sameValue(Object.prototype.hasOwnProperty.call(result, 'prototype'), false); +}).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allSettledKeyed/arg-not-object-reject-bigint.js b/test/built-ins/Promise/allSettledKeyed/arg-not-object-reject-bigint.js new file mode 100644 index 00000000000..1b67fdad255 --- /dev/null +++ b/test/built-ins/Promise/allSettledKeyed/arg-not-object-reject-bigint.js @@ -0,0 +1,24 @@ +// Copyright (C) 2026 Danial Asaria (Bloomberg LP). All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettledkeyed +description: > + Promise.allSettledKeyed rejects when the promises argument is a BigInt +info: | + Promise.allSettledKeyed ( promises ) + + ... + 5. If promises is not an Object, then + a. Let error be a newly created TypeError object. + b. Perform ? Call(promiseCapability.[[Reject]], undefined, « error »). + c. Return promiseCapability.[[Promise]]. +flags: [async] +features: [await-dictionary, BigInt] +---*/ + +Promise.allSettledKeyed(0n).then(function() { + throw new Test262Error('The promise should be rejected for BigInt'); +}, function(error) { + assert(error instanceof TypeError, 'rejects with TypeError for BigInt'); +}).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allSettledKeyed/arg-not-object-reject.js b/test/built-ins/Promise/allSettledKeyed/arg-not-object-reject.js new file mode 100644 index 00000000000..7ab4f791609 --- /dev/null +++ b/test/built-ins/Promise/allSettledKeyed/arg-not-object-reject.js @@ -0,0 +1,34 @@ +// Copyright (C) 2026 Danial Asaria (Bloomberg LP). All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettledkeyed +description: > + Promise.allSettledKeyed rejects when the promises argument is not an Object +info: | + Promise.allSettledKeyed ( promises ) + + ... + 5. If promises is not an Object, then + a. Let error be a newly created TypeError object. + b. Perform ? Call(promiseCapability.[[Reject]], undefined, « error »). + c. Return promiseCapability.[[Promise]]. +flags: [async] +features: [await-dictionary, Symbol] +---*/ + +function checkRejects(value) { + return Promise.allSettledKeyed(value).then(function() { + throw new Test262Error('The promise should be rejected for ' + typeof value); + }, function(error) { + assert(error instanceof TypeError, 'rejects with TypeError for ' + typeof value); + }); +} + +checkRejects(undefined) + .then(function() { return checkRejects(null); }) + .then(function() { return checkRejects(86); }) + .then(function() { return checkRejects('string'); }) + .then(function() { return checkRejects(true); }) + .then(function() { return checkRejects(Symbol()); }) + .then($DONE, $DONE); diff --git a/test/built-ins/Promise/allSettledKeyed/ctx-non-ctor.js b/test/built-ins/Promise/allSettledKeyed/ctx-non-ctor.js new file mode 100644 index 00000000000..356ad7cee42 --- /dev/null +++ b/test/built-ins/Promise/allSettledKeyed/ctx-non-ctor.js @@ -0,0 +1,22 @@ +// Copyright (C) 2026 Danial Asaria (Bloomberg LP). All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettledkeyed +description: > + Promise.allSettledKeyed invoked on a non-constructor value +info: | + Promise.allSettledKeyed ( promises ) + + 1. Let C be the this value. + 2. Let promiseCapability be ? NewPromiseCapability(C). + + NewPromiseCapability ( C ) + + 1. If IsConstructor(C) is false, throw a TypeError exception. +features: [await-dictionary] +---*/ + +assert.throws(TypeError, function() { + Promise.allSettledKeyed.call(eval); +}); diff --git a/test/built-ins/Promise/allSettledKeyed/key-order-preserved.js b/test/built-ins/Promise/allSettledKeyed/key-order-preserved.js new file mode 100644 index 00000000000..75e590ded2a --- /dev/null +++ b/test/built-ins/Promise/allSettledKeyed/key-order-preserved.js @@ -0,0 +1,61 @@ +// Copyright (C) 2026 Danial Asaria (Bloomberg LP). All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-performpromiseallkeyed +description: > + Promise.allSettledKeyed result key order matches property key order, not settlement order +info: | + PerformPromiseAllKeyed ( variant, promises, constructor, resultCapability, promiseResolve ) + + ... + 1. Let allKeys be ? promises.[[OwnPropertyKeys]](). + ... + 6. For each element key of allKeys, do + ... + b. If desc is not undefined and desc.[[Enumerable]] is true, then + ... + ii. Append key to keys. + ... + ... + ... + 8. If remainingElementsCount.[[Value]] = 0, then + ... + b. Let result be CreateKeyedPromiseCombinatorResultObject(keys, values). +includes: [compareArray.js] +flags: [async] +features: [await-dictionary] +---*/ + +var resolveFirst; +var resolveSecond; +var resolveThird; + +var input = { + first: new Promise(function(resolve) { + resolveFirst = resolve; + }), + second: new Promise(function(resolve) { + resolveSecond = resolve; + }), + third: new Promise(function(resolve) { + resolveThird = resolve; + }) +}; + +var combined = Promise.allSettledKeyed(input); + +resolveSecond('second'); +resolveThird('third'); +resolveFirst('first'); + +combined.then(function(result) { + assert.sameValue(Object.getPrototypeOf(result), null); + assert.compareArray(Object.keys(result), ['first', 'second', 'third']); + assert.sameValue(result.first.status, 'fulfilled'); + assert.sameValue(result.first.value, 'first'); + assert.sameValue(result.second.status, 'fulfilled'); + assert.sameValue(result.second.value, 'second'); + assert.sameValue(result.third.status, 'fulfilled'); + assert.sameValue(result.third.value, 'third'); +}).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allSettledKeyed/non-enumerable-properties-ignored.js b/test/built-ins/Promise/allSettledKeyed/non-enumerable-properties-ignored.js new file mode 100644 index 00000000000..cb063e280aa --- /dev/null +++ b/test/built-ins/Promise/allSettledKeyed/non-enumerable-properties-ignored.js @@ -0,0 +1,36 @@ +// Copyright (C) 2026 Danial Asaria (Bloomberg LP). All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-performpromiseallkeyed +description: > + Promise.allSettledKeyed ignores non-enumerable own properties +info: | + PerformPromiseAllKeyed ( variant, promises, constructor, resultCapability, promiseResolve ) + + ... + 6. For each element key of allKeys, do + a. Let desc be ? promises.[[GetOwnProperty]](key). + b. If desc is not undefined and desc.[[Enumerable]] is true, then + ... +includes: [compareArray.js] +flags: [async] +features: [await-dictionary] +---*/ + +var input = { + visible: Promise.resolve(2) +}; + +Object.defineProperty(input, 'hidden', { + enumerable: false, + value: Promise.resolve(1) +}); + +Promise.allSettledKeyed(input).then(function(result) { + assert.sameValue(Object.getPrototypeOf(result), null); + assert.compareArray(Object.keys(result), ['visible']); + assert.sameValue(result.visible.status, 'fulfilled'); + assert.sameValue(result.visible.value, 2); + assert.sameValue(Object.prototype.hasOwnProperty.call(result, 'hidden'), false); +}).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allSettledKeyed/prototype-keys-ignored.js b/test/built-ins/Promise/allSettledKeyed/prototype-keys-ignored.js new file mode 100644 index 00000000000..3a35872c857 --- /dev/null +++ b/test/built-ins/Promise/allSettledKeyed/prototype-keys-ignored.js @@ -0,0 +1,33 @@ +// Copyright (C) 2026 Danial Asaria (Bloomberg LP). All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-performpromiseallkeyed +description: > + Promise.allSettledKeyed ignores inherited prototype properties +info: | + PerformPromiseAllKeyed ( variant, promises, constructor, resultCapability, promiseResolve ) + + ... + 1. Let allKeys be ? promises.[[OwnPropertyKeys]](). + ... + 6. For each element key of allKeys, do + a. Let desc be ? promises.[[GetOwnProperty]](key). + b. If desc is not undefined and desc.[[Enumerable]] is true, then + ... +includes: [compareArray.js] +flags: [async] +features: [await-dictionary] +---*/ + +var proto = { inherited: Promise.resolve('nope') }; +var input = Object.create(proto); +input.own = Promise.resolve('yes'); + +Promise.allSettledKeyed(input).then(function(result) { + assert.sameValue(Object.getPrototypeOf(result), null); + assert.compareArray(Object.keys(result), ['own']); + assert.sameValue(result.own.status, 'fulfilled'); + assert.sameValue(result.own.value, 'yes'); + assert.sameValue(Object.prototype.hasOwnProperty.call(result, 'inherited'), false); +}).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allSettledKeyed/resolve-not-callable-reject-with-typeerror.js b/test/built-ins/Promise/allSettledKeyed/resolve-not-callable-reject-with-typeerror.js new file mode 100644 index 00000000000..b070f7394c2 --- /dev/null +++ b/test/built-ins/Promise/allSettledKeyed/resolve-not-callable-reject-with-typeerror.js @@ -0,0 +1,34 @@ +// Copyright (C) 2026 Danial Asaria (Bloomberg LP). All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-promise.allsettledkeyed +description: > + If the constructor's `resolve` method is not callable, reject with a TypeError. +info: | + Promise.allSettledKeyed ( promises ) + + ... + 3. Let promiseResolve be Completion(GetPromiseResolve(C)). + 4. IfAbruptRejectPromise(promiseResolve, promiseCapability). + ... + + GetPromiseResolve ( promiseConstructor ) + + ... + 3. If IsCallable(promiseResolve) is false, throw a TypeError exception. +flags: [async] +features: [await-dictionary] +---*/ + +Promise.resolve = null; + +Promise.allSettledKeyed({ key: 1 }) + .then( + function() { + $DONE('The promise should not be resolved.'); + }, + function(error) { + assert(error instanceof TypeError); + } + ).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allSettledKeyed/resolved-all-fulfilled.js b/test/built-ins/Promise/allSettledKeyed/resolved-all-fulfilled.js new file mode 100644 index 00000000000..6d2009fd823 --- /dev/null +++ b/test/built-ins/Promise/allSettledKeyed/resolved-all-fulfilled.js @@ -0,0 +1,43 @@ +// Copyright (C) 2026 Danial Asaria (Bloomberg LP). All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-performpromiseallkeyed +description: > + Resolution is a collection of all the settled keyed values (all fulfilled) +info: | + PerformPromiseAllKeyed ( variant, promises, constructor, resultCapability, promiseResolve ) + + ... + If variant is all-settled, then + Let onRejected be a new Abstract Closure ... + ... + The onFulfilled closure for all-settled: + Let obj be OrdinaryObjectCreate(%Object.prototype%). + Perform ! CreateDataPropertyOrThrow(obj, "status", "fulfilled"). + Perform ! CreateDataPropertyOrThrow(obj, "value", x). +includes: [compareArray.js] +flags: [async] +features: [await-dictionary] +---*/ + +var obj = {}; +var input = { + first: Promise.resolve(1), + second: Promise.resolve('test262'), + third: Promise.resolve(obj) +}; + +Promise.allSettledKeyed(input).then(function(settled) { + assert.sameValue(Object.getPrototypeOf(settled), null); + assert.compareArray(Object.keys(settled), ['first', 'second', 'third']); + + assert.sameValue(settled.first.status, 'fulfilled'); + assert.sameValue(settled.first.value, 1); + + assert.sameValue(settled.second.status, 'fulfilled'); + assert.sameValue(settled.second.value, 'test262'); + + assert.sameValue(settled.third.status, 'fulfilled'); + assert.sameValue(settled.third.value, obj); +}).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allSettledKeyed/resolved-all-mixed.js b/test/built-ins/Promise/allSettledKeyed/resolved-all-mixed.js new file mode 100644 index 00000000000..518f31d34bf --- /dev/null +++ b/test/built-ins/Promise/allSettledKeyed/resolved-all-mixed.js @@ -0,0 +1,65 @@ +// Copyright (C) 2026 Danial Asaria (Bloomberg LP). All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-performpromiseallkeyed +description: > + Resolution is a collection of all the settled keyed values (fulfilled and rejected) +info: | + PerformPromiseAllKeyed ( variant, promises, constructor, resultCapability, promiseResolve ) + + ... + 6. For each element key of allKeys, do + ... + b. If desc is not undefined and desc.[[Enumerable]] is true, then + ... + 11. Perform ? Invoke(nextPromise, "then", « onFulfilled, onRejected »). + ... + 8. If remainingElementsCount.[[Value]] = 0, then + ... + b. Let result be CreateKeyedPromiseCombinatorResultObject(keys, values). +includes: [compareArray.js] +flags: [async] +features: [await-dictionary] +---*/ + +var obj1 = {}; +var obj2 = {}; +var input = { + first: Promise.reject(1), + second: Promise.resolve(2), + third: Promise.resolve('tc39'), + fourth: Promise.reject('test262'), + fifth: Promise.reject(obj1), + sixth: Promise.resolve(obj2) +}; + +Promise.allSettledKeyed(input).then(function(settled) { + assert.sameValue(Object.getPrototypeOf(settled), null); + assert.compareArray(Object.keys(settled), [ + 'first', + 'second', + 'third', + 'fourth', + 'fifth', + 'sixth' + ]); + + assert.sameValue(settled.first.status, 'rejected'); + assert.sameValue(settled.first.reason, 1); + + assert.sameValue(settled.second.status, 'fulfilled'); + assert.sameValue(settled.second.value, 2); + + assert.sameValue(settled.third.status, 'fulfilled'); + assert.sameValue(settled.third.value, 'tc39'); + + assert.sameValue(settled.fourth.status, 'rejected'); + assert.sameValue(settled.fourth.reason, 'test262'); + + assert.sameValue(settled.fifth.status, 'rejected'); + assert.sameValue(settled.fifth.reason, obj1); + + assert.sameValue(settled.sixth.status, 'fulfilled'); + assert.sameValue(settled.sixth.value, obj2); +}).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allSettledKeyed/resolved-all-rejected.js b/test/built-ins/Promise/allSettledKeyed/resolved-all-rejected.js new file mode 100644 index 00000000000..6ad66495139 --- /dev/null +++ b/test/built-ins/Promise/allSettledKeyed/resolved-all-rejected.js @@ -0,0 +1,43 @@ +// Copyright (C) 2026 Danial Asaria (Bloomberg LP). All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-performpromiseallkeyed +description: > + Resolution is a collection of all the settled keyed values (all rejected) +info: | + PerformPromiseAllKeyed ( variant, promises, constructor, resultCapability, promiseResolve ) + + ... + If variant is all-settled, then + Let onRejected be a new Abstract Closure ... + ... + The onRejected closure: + Let obj be OrdinaryObjectCreate(%Object.prototype%). + Perform ! CreateDataPropertyOrThrow(obj, "status", "rejected"). + Perform ! CreateDataPropertyOrThrow(obj, "reason", x). +includes: [compareArray.js] +flags: [async] +features: [await-dictionary] +---*/ + +var obj = {}; +var input = { + first: Promise.reject(1), + second: Promise.reject('test262'), + third: Promise.reject(obj) +}; + +Promise.allSettledKeyed(input).then(function(settled) { + assert.sameValue(Object.getPrototypeOf(settled), null); + assert.compareArray(Object.keys(settled), ['first', 'second', 'third']); + + assert.sameValue(settled.first.status, 'rejected'); + assert.sameValue(settled.first.reason, 1); + + assert.sameValue(settled.second.status, 'rejected'); + assert.sameValue(settled.second.reason, 'test262'); + + assert.sameValue(settled.third.status, 'rejected'); + assert.sameValue(settled.third.reason, obj); +}).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allSettledKeyed/resolves-empty-object.js b/test/built-ins/Promise/allSettledKeyed/resolves-empty-object.js new file mode 100644 index 00000000000..71247d4a3c2 --- /dev/null +++ b/test/built-ins/Promise/allSettledKeyed/resolves-empty-object.js @@ -0,0 +1,27 @@ +// Copyright (C) 2026 Danial Asaria (Bloomberg LP). All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-performpromiseallkeyed +description: > + Promise.allSettledKeyed resolves an empty object to an empty null-prototype object +info: | + PerformPromiseAllKeyed ( variant, promises, constructor, resultCapability, promiseResolve ) + + ... + 1. Let allKeys be ? promises.[[OwnPropertyKeys]](). + ... + 7. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1. + 8. If remainingElementsCount.[[Value]] = 0, then + a. Let result be CreateKeyedPromiseCombinatorResultObject(keys, values). + b. Perform ? Call(resultCapability.[[Resolve]], undefined, « result »). +includes: [compareArray.js] +flags: [async] +features: [await-dictionary] +---*/ + +Promise.allSettledKeyed({}).then(function(result) { + assert.sameValue(Object.getPrototypeOf(result), null); + assert.sameValue(result.hasOwnProperty, undefined); + assert.compareArray(Reflect.ownKeys(result), []); +}).then($DONE, $DONE); diff --git a/test/built-ins/Promise/allSettledKeyed/symbol-keys.js b/test/built-ins/Promise/allSettledKeyed/symbol-keys.js new file mode 100644 index 00000000000..1c91114fea5 --- /dev/null +++ b/test/built-ins/Promise/allSettledKeyed/symbol-keys.js @@ -0,0 +1,38 @@ +// Copyright (C) 2026 Danial Asaria (Bloomberg LP). All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-performpromiseallkeyed +description: > + Promise.allSettledKeyed includes enumerable symbol-keyed properties +info: | + PerformPromiseAllKeyed ( variant, promises, constructor, resultCapability, promiseResolve ) + + ... + 1. Let allKeys be ? promises.[[OwnPropertyKeys]](). + ... + 6. For each element key of allKeys, do + a. Let desc be ? promises.[[GetOwnProperty]](key). + b. If desc is not undefined and desc.[[Enumerable]] is true, then + ... +flags: [async] +features: [await-dictionary, Symbol] +---*/ + +var sym = Symbol('s'); +var input = { str: Promise.resolve(1) }; +input[sym] = Promise.resolve(2); + +Promise.allSettledKeyed(input).then(function(result) { + assert.sameValue(Object.getPrototypeOf(result), null); + + var keys = Reflect.ownKeys(result); + assert.sameValue(keys.length, 2); + assert.sameValue(keys[0], 'str'); + assert.sameValue(keys[1], sym); + + assert.sameValue(result.str.status, 'fulfilled'); + assert.sameValue(result.str.value, 1); + assert.sameValue(result[sym].status, 'fulfilled'); + assert.sameValue(result[sym].value, 2); +}).then($DONE, $DONE);