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..f97cd7a856a --- /dev/null +++ b/test/built-ins/Promise/allKeyed/arg-is-function.js @@ -0,0 +1,40 @@ +// 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. +includes: [asyncHelpers.js] +flags: [async] +features: [await-dictionary] +---*/ + +function fn() {} +fn.key = Promise.resolve('val'); + +asyncTest(function() { + return 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); + }); +}); 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..80ee7cfc746 --- /dev/null +++ b/test/built-ins/Promise/allKeyed/arg-not-object-reject-bigint.js @@ -0,0 +1,25 @@ +// 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]]. +includes: [asyncHelpers.js] +flags: [async] +features: [await-dictionary, BigInt] +---*/ + +asyncTest(function() { + return assert.throwsAsync(TypeError, function() { + return Promise.allKeyed(0n); + }, 'BigInt'); +}); 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..b6e02874f63 --- /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]]. +includes: [asyncHelpers.js] +flags: [async] +features: [await-dictionary, Symbol] +---*/ + +asyncTest(function() { + function check(value, msg) { + return assert.throwsAsync(TypeError, function() { + return Promise.allKeyed(value); + }, msg); + } + + return check(undefined, 'undefined') + .then(function() { return check(null, 'null'); }) + .then(function() { return check(86, 'number'); }) + .then(function() { return check('string', 'string'); }) + .then(function() { return check(true, 'boolean'); }) + .then(function() { return check(Symbol(), 'symbol'); }); +}); 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..ca69ded0553 --- /dev/null +++ b/test/built-ins/Promise/allKeyed/key-order-preserved.js @@ -0,0 +1,60 @@ +// 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: [asyncHelpers.js, 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'); + +asyncTest(function() { + return 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'); + }); +}); 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..5234f0488a3 --- /dev/null +++ b/test/built-ins/Promise/allKeyed/non-enumerable-properties-ignored.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-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: [asyncHelpers.js, compareArray.js] +flags: [async] +features: [await-dictionary] +---*/ + +var input = { + visible: Promise.resolve(2) +}; + +Object.defineProperty(input, 'hidden', { + enumerable: false, + value: Promise.resolve(1) +}); + +asyncTest(function() { + return 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); + }); +}); 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..caaddf433e2 --- /dev/null +++ b/test/built-ins/Promise/allKeyed/prototype-keys-ignored.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: > + 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: [asyncHelpers.js, compareArray.js] +flags: [async] +features: [await-dictionary] +---*/ + +var proto = { inherited: Promise.resolve('nope') }; +var input = Object.create(proto); +input.own = Promise.resolve('yes'); + +asyncTest(function() { + return 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); + }); +}); 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..4885b606849 --- /dev/null +++ b/test/built-ins/Promise/allKeyed/reject-deferred.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: 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 »). +includes: [asyncHelpers.js] +flags: [async] +features: [await-dictionary] +---*/ + +var error = new Test262Error(); + +var p = new Promise(function(_, reject) { + Promise.resolve().then(function() { + reject(error); + }); +}); + +asyncTest(function() { + return Promise.allKeyed({ key: p }).then(function() { + throw new Test262Error('The promise should not be fulfilled.'); + }, function(reason) { + assert.sameValue(reason, error); + }); +}); 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..b57d21f4f8d --- /dev/null +++ b/test/built-ins/Promise/allKeyed/reject-immed.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 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 »). +includes: [asyncHelpers.js] +flags: [async] +features: [await-dictionary] +---*/ + +var error = new Test262Error(); + +var p = new Promise(function(_, reject) { + reject(error); +}); + +asyncTest(function() { + return Promise.allKeyed({ key: p }).then(function() { + throw new Test262Error('The promise should not be fulfilled.'); + }, function(reason) { + assert.sameValue(reason, error); + }); +}); 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..20d57413a28 --- /dev/null +++ b/test/built-ins/Promise/allKeyed/resolve-not-callable-reject-with-typeerror.js @@ -0,0 +1,31 @@ +// 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. +includes: [asyncHelpers.js] +flags: [async] +features: [await-dictionary] +---*/ + +Promise.resolve = null; + +asyncTest(function() { + return assert.throwsAsync(TypeError, function() { + return Promise.allKeyed({ key: 1 }); + }); +}); 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..b74f51f321f --- /dev/null +++ b/test/built-ins/Promise/allKeyed/resolves-empty-object.js @@ -0,0 +1,29 @@ +// 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: [asyncHelpers.js, compareArray.js] +flags: [async] +features: [await-dictionary] +---*/ + +asyncTest(function() { + return Promise.allKeyed({}).then(function(result) { + assert.sameValue(Object.getPrototypeOf(result), null); + assert.sameValue(result.hasOwnProperty, undefined); + assert.compareArray(Reflect.ownKeys(result), []); + }); +}); 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..e9a4aadab1c --- /dev/null +++ b/test/built-ins/Promise/allKeyed/symbol-keys.js @@ -0,0 +1,45 @@ +// 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 and ignores non-enumerable ones +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: [asyncHelpers.js] +flags: [async] +features: [await-dictionary, Symbol] +---*/ + +var sym = Symbol('s'); +var hiddenSym = Symbol('hidden'); +var input = { str: Promise.resolve(1) }; +input[sym] = Promise.resolve(2); +Object.defineProperty(input, hiddenSym, { + enumerable: false, + value: Promise.resolve(3) +}); + +asyncTest(function() { + return 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); + assert.sameValue(Object.prototype.hasOwnProperty.call(result, hiddenSym), false); + }); +}); 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..738f5347090 --- /dev/null +++ b/test/built-ins/Promise/allSettledKeyed/arg-is-function.js @@ -0,0 +1,41 @@ +// 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. +includes: [asyncHelpers.js] +flags: [async] +features: [await-dictionary] +---*/ + +function fn() {} +fn.key = Promise.resolve('val'); + +asyncTest(function() { + return 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); + }); +}); 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..0a563f0745e --- /dev/null +++ b/test/built-ins/Promise/allSettledKeyed/arg-not-object-reject-bigint.js @@ -0,0 +1,25 @@ +// 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]]. +includes: [asyncHelpers.js] +flags: [async] +features: [await-dictionary, BigInt] +---*/ + +asyncTest(function() { + return assert.throwsAsync(TypeError, function() { + return Promise.allSettledKeyed(0n); + }, 'BigInt'); +}); 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..16ee7079743 --- /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]]. +includes: [asyncHelpers.js] +flags: [async] +features: [await-dictionary, Symbol] +---*/ + +asyncTest(function() { + function check(value, msg) { + return assert.throwsAsync(TypeError, function() { + return Promise.allSettledKeyed(value); + }, msg); + } + + return check(undefined, 'undefined') + .then(function() { return check(null, 'null'); }) + .then(function() { return check(86, 'number'); }) + .then(function() { return check('string', 'string'); }) + .then(function() { return check(true, 'boolean'); }) + .then(function() { return check(Symbol(), 'symbol'); }); +}); 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..c6ee28e485b --- /dev/null +++ b/test/built-ins/Promise/allSettledKeyed/key-order-preserved.js @@ -0,0 +1,63 @@ +// 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: [asyncHelpers.js, 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'); + +asyncTest(function() { + return 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'); + }); +}); 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..d997ae9ffbe --- /dev/null +++ b/test/built-ins/Promise/allSettledKeyed/non-enumerable-properties-ignored.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 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: [asyncHelpers.js, compareArray.js] +flags: [async] +features: [await-dictionary] +---*/ + +var input = { + visible: Promise.resolve(2) +}; + +Object.defineProperty(input, 'hidden', { + enumerable: false, + value: Promise.resolve(1) +}); + +asyncTest(function() { + return 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); + }); +}); 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..d2f32d49593 --- /dev/null +++ b/test/built-ins/Promise/allSettledKeyed/prototype-keys-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.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: [asyncHelpers.js, compareArray.js] +flags: [async] +features: [await-dictionary] +---*/ + +var proto = { inherited: Promise.resolve('nope') }; +var input = Object.create(proto); +input.own = Promise.resolve('yes'); + +asyncTest(function() { + return 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); + }); +}); 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..133e395373b --- /dev/null +++ b/test/built-ins/Promise/allSettledKeyed/resolve-not-callable-reject-with-typeerror.js @@ -0,0 +1,31 @@ +// 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. +includes: [asyncHelpers.js] +flags: [async] +features: [await-dictionary] +---*/ + +Promise.resolve = null; + +asyncTest(function() { + return assert.throwsAsync(TypeError, function() { + return Promise.allSettledKeyed({ key: 1 }); + }); +}); 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..d64b8b9ed65 --- /dev/null +++ b/test/built-ins/Promise/allSettledKeyed/resolved-all-fulfilled.js @@ -0,0 +1,45 @@ +// 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: [asyncHelpers.js, compareArray.js] +flags: [async] +features: [await-dictionary] +---*/ + +var obj = {}; +var input = { + first: Promise.resolve(1), + second: Promise.resolve('test262'), + third: Promise.resolve(obj) +}; + +asyncTest(function() { + return 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); + }); +}); 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..8266173a2e5 --- /dev/null +++ b/test/built-ins/Promise/allSettledKeyed/resolved-all-mixed.js @@ -0,0 +1,67 @@ +// 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: [asyncHelpers.js, 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) +}; + +asyncTest(function() { + return 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); + }); +}); 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..e2624c0fa6e --- /dev/null +++ b/test/built-ins/Promise/allSettledKeyed/resolved-all-rejected.js @@ -0,0 +1,45 @@ +// 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: [asyncHelpers.js, compareArray.js] +flags: [async] +features: [await-dictionary] +---*/ + +var obj = {}; +var input = { + first: Promise.reject(1), + second: Promise.reject('test262'), + third: Promise.reject(obj) +}; + +asyncTest(function() { + return 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); + }); +}); 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..f98a91c5254 --- /dev/null +++ b/test/built-ins/Promise/allSettledKeyed/resolves-empty-object.js @@ -0,0 +1,29 @@ +// 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: [asyncHelpers.js, compareArray.js] +flags: [async] +features: [await-dictionary] +---*/ + +asyncTest(function() { + return Promise.allSettledKeyed({}).then(function(result) { + assert.sameValue(Object.getPrototypeOf(result), null); + assert.sameValue(result.hasOwnProperty, undefined); + assert.compareArray(Reflect.ownKeys(result), []); + }); +}); 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..37f4c06a4e9 --- /dev/null +++ b/test/built-ins/Promise/allSettledKeyed/symbol-keys.js @@ -0,0 +1,47 @@ +// 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 and ignores non-enumerable ones +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: [asyncHelpers.js] +flags: [async] +features: [await-dictionary, Symbol] +---*/ + +var sym = Symbol('s'); +var hiddenSym = Symbol('hidden'); +var input = { str: Promise.resolve(1) }; +input[sym] = Promise.resolve(2); +Object.defineProperty(input, hiddenSym, { + enumerable: false, + value: Promise.resolve(3) +}); + +asyncTest(function() { + return 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); + assert.sameValue(Object.prototype.hasOwnProperty.call(result, hiddenSym), false); + }); +});