Stage 4 Draft / August 10, 2020

Promise.any

Introduction

Promise.any() accepts an iterable of promises and returns a promise that is fulfilled by the first given promise to be fulfilled, or rejected with an AggregateError holding the rejection reasons if all of the given promises are rejected.

1 Well-Known Intrinsic Objects

Well-known intrinsics are built-in objects that are explicitly referenced by the algorithms of this specification and which usually have realm-specific identities. Unless otherwise specified each intrinsic object actually corresponds to a set of similar objects, one per realm.

Within this specification a reference such as %name% means the intrinsic object, associated with the current realm, corresponding to the name. Determination of the current realm and its intrinsics is described in 8.3. The well-known intrinsics are listed in Table 1.

Table 1: Well-Known Intrinsic Objects
Intrinsic Name Global Name ECMAScript Language Association
%AggregateError% AggregateError The AggregateError constructor (2.4.1)
%AggregateErrorPrototype% AggregateError.prototype The initial value of the prototype data property of %AggregateError%; i.e., %AggregateError.prototype%

2 Error Objects

Instances of Error objects are thrown as exceptions when runtime errors occur. The Error objects may also serve as base objects for user-defined exception classes.

When an ECMAScript implementation detects a runtime error, it throws a new instance of one of the NativeError objects defined in 2.2 or a new instance of AggregateError object defined in 2.4. Each of these objects has the structure described below, differing only in the name used as the constructor name instead of NativeError, in the name property of the prototype object, in the implementation-defined message property of the prototype object, and in the presence of the %AggregateError%-specific errors property.

2.1 Properties of Error Instances

Error instances are ordinary objects that inherit properties from the Error prototype object and have an [[ErrorData]] internal slot whose value is undefined. The only specified uses of [[ErrorData]] is to identify Error, AggregateError, and NativeError instances as Error objects within Object.prototype.toString.

2.2 Native Error Types Used in This Standard

A new instance of one of the NativeError objects below or of the AggregateError object is thrown when a runtime error is detected. All of these objects share the same structure, as described in 2.3.

2.3 NativeError Object Structure

For each error object, references to NativeError in the definition should be replaced with the appropriate error object name from 2.2.

2.3.1 Properties of NativeError Instances

NativeError instances are ordinary objects that inherit properties from their NativeError prototype object and have an [[ErrorData]] internal slot whose value is undefined. The only specified use of [[ErrorData]] is by Object.prototype.toString (19.1.3.6) to identify Error, AggregateError, or NativeError instances.

2.4 AggregateError Objects

2.4.1 The AggregateError Constructor

The AggregateError constructor:

  • is the intrinsic object %AggregateError%.
  • is the initial value of the AggregateError property of the global object.
  • creates and initializes a new AggregateError object when called as a function rather than as a constructor. Thus the function call AggregateError(…) is equivalent to the object creation expression new AggregateError(…) with the same arguments.
  • is designed to be subclassable. It may be used as the value of an extends clause of a class definition. Subclass constructors that intend to inherit the specified AggregateError behaviour must include a super call to the AggregateError constructor to create and initialize subclass instances with an [[ErrorData]] and [[AggregateErrors]] internal slots.

2.4.1.1 AggregateError ( errors, message )

When the AggregateError function is called with arguments errors and message, the following steps are taken:

  1. If NewTarget is undefined, let newTarget be the active function object, else let newTarget be NewTarget.
  2. Let O be ? OrdinaryCreateFromConstructor(newTarget, "%AggregateError.prototype%", « [[ErrorData]] »).
  3. If message is not undefined, then
    1. Let msg be ? ToString(message).
    2. Let msgDesc be the PropertyDescriptor { [[Value]]: msg, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }.
    3. Perform ! DefinePropertyOrThrow(O, "message", msgDesc).
  4. Let errorsList be ? IterableToList(errors).
  5. Perform ! DefinePropertyOrThrow(O, "errors", Property Descriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: ! CreateArrayFromList(errorsList) }).
  6. Return O.

2.4.2 Properties of the AggregateError Constructor

The AggregateError constructor:

  • has a [[Prototype]] internal slot whose value is the intrinsic object %Error%.
  • has the following properties:

2.4.2.1 AggregateError.prototype

The initial value of AggregateError.prototype is the intrinsic object %AggregateError.prototype%.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

2.4.3 Properties of the AggregateError Prototype Object

The AggregateError prototype object:

  • is the intrinsic object %AggregateError.prototype%.
  • is an ordinary object.
  • is not an Error instance or an AggregateError instance and does not have an [[ErrorData]] internal slot.
  • has a [[Prototype]] internal slot whose value is the intrinsic object %Error.prototype%.

2.4.3.1 AggregateError.prototype.constructor

The initial value of AggregateError.prototype.constructor is the intrinsic object %AggregateError%.

This property has the attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }.

2.4.3.2 AggregateError.prototype.message

The initial value of AggregateError.prototype.message is the empty String.

This property has the attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }.

2.4.3.3 AggregateError.prototype.name

The initial value of AggregateError.prototype.name is "AggregateError".

This property has the attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }.

2.4.4 Properties of AggregateError Instances

AggregateError instances are ordinary objects that inherit properties from their AggregateError prototype object and have an [[ErrorData]] internal slot whose value is undefined. The only specified use of [[ErrorData]] is by Object.prototype.toString (19.1.3.6) to identify Error, AggregateError, or NativeError instances.

3 Promise.any ( iterable )

The any function returns a promise that is fulfilled by the first given promise to be fulfilled, or rejected with an AggregateError holding the rejection reasons if all of the given promises are rejected. It resolves all elements of the passed iterable to promises as it runs this algorithm.

  1. Let C be the this value.
  2. Let promiseCapability be ? NewPromiseCapability(C).
  3. Let promiseResolve be GetPromiseResolve(C).
  4. IfAbruptRejectPromise(promiseResolve, promiseCapability).
  5. Let iteratorRecord be GetIterator(iterable).
  6. IfAbruptRejectPromise(iteratorRecord, promiseCapability).
  7. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability, promiseResolve).
  8. If result is an abrupt completion, then
    1. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result).
    2. IfAbruptRejectPromise(result, promiseCapability).
  9. Return Completion(result).
Note

The any function requires its this value to be a constructor function that supports the parameter conventions of the Promise constructor.

3.1 Runtime Semantics: PerformPromiseAny ( iteratorRecord, constructor, resultCapability, promiseResolve )

When the PerformPromiseAny abstract operation is called with arguments iteratorRecord, constructor, resultCapability, and promiseResolve, the following steps are taken:

  1. Assert: ! IsConstructor(constructor) is true.
  2. Assert: resultCapability is a PromiseCapability Record.
  3. Assert: ! IsCallable(promiseResolve) is true.
  4. Let errors be a new empty List.
  5. Let remainingElementsCount be a new Record { [[Value]]: 1 }.
  6. Let index be 0.
  7. Repeat,
    1. Let next be IteratorStep(iteratorRecord).
    2. If next is an abrupt completion, set iteratorRecord.[[Done]] to true.
    3. ReturnIfAbrupt(next).
    4. If next is false, then
      1. Set iteratorRecord.[[Done]] to true.
      2. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1.
      3. If remainingElementsCount.[[Value]] is 0, then
        1. Let error be a newly created AggregateError object.
        2. Perform ! DefinePropertyOrThrow(error, "errors", Property Descriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: ! CreateArrayFromList(errors) }).
        3. Return ThrowCompletion(error).
      4. Return resultCapability.[[Promise]].
    5. Let nextValue be IteratorValue(next).
    6. If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true.
    7. ReturnIfAbrupt(nextValue).
    8. Append undefined to errors.
    9. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »).
    10. Let steps be the algorithm steps defined in Promise.any Reject Element Functions.
    11. Let rejectElement be ! CreateBuiltinFunction(steps, « [[AlreadyCalled]], [[Index]], [[Errors]], [[Capability]], [[RemainingElements]] »).
    12. Set rejectElement.[[AlreadyCalled]] to a new Record { [[Value]]: false }.
    13. Set rejectElement.[[Index]] to index.
    14. Set rejectElement.[[Errors]] to errors.
    15. Set rejectElement.[[Capability]] to resultCapability.
    16. Set rejectElement.[[RemainingElements]] to remainingElementsCount.
    17. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] + 1.
    18. Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], rejectElement »).
    19. Increase index by 1.

3.2 Promise.any Reject Element Functions

A Promise.any reject element function is an anonymous built-in function that is used to reject a specific Promise.any element. Each Promise.any reject element function has [[Index]], [[Errors]], [[Capability]], [[RemainingElements]], and [[AlreadyCalled]] internal slots.

When a Promise.any reject element function is called with argument x, the following steps are taken:

  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.
  5. Let index be F.[[Index]].
  6. Let errors be F.[[Errors]].
  7. Let promiseCapability be F.[[Capability]].
  8. Let remainingElementsCount be F.[[RemainingElements]].
  9. Set errors[index] to x.
  10. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1.
  11. If remainingElementsCount.[[Value]] is 0, then
    1. Let error be a newly created AggregateError object.
    2. Perform ! DefinePropertyOrThrow(error, "errors", Property Descriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: ! CreateArrayFromList(errors) }).
    3. Return ? Call(promiseCapability.[[Reject]], undefined, « error »).
  12. Return undefined.

The "length" property of a Promise.any reject element function is 1.

4 Runtime Semantics: IterableToList ( items [ , method ] )

The abstract operation IterableToList performs the following steps:

  1. Let iteratorRecord be ? GetIterator(items, sync, method).
  2. If method is present, then
    1. Let iteratorRecord be ? GetIterator(items, sync, method).
  3. Else,
    1. Let iteratorRecord be ? GetIterator(items, sync).
  4. Let values be a new empty List.
  5. Let next be true.
  6. Repeat, while next is not false
    1. Set next to ? IteratorStep(iteratorRecord).
    2. If next is not false, then
      1. Let nextValue be ? IteratorValue(next).
      2. Append nextValue to the end of the List values.
  7. Return values.