@@ -31,14 +31,13 @@ import {
31
31
} from '../abstract-ops/all.mjs' ;
32
32
import {
33
33
AbruptCompletion , Completion ,
34
+ ThrowCompletion ,
34
35
IfAbruptRejectPromise ,
35
- Q ,
36
36
ReturnIfAbrupt ,
37
- X ,
37
+ Q , X ,
38
38
} from '../completion.mjs' ;
39
39
import { BootstrapConstructor } from './Bootstrap.mjs' ;
40
40
41
-
42
41
function PromiseConstructor ( [ executor = Value . undefined ] , { NewTarget } ) {
43
42
if ( NewTarget === Value . undefined ) {
44
43
return surroundingAgent . Throw ( 'TypeError' , 'ConstructorNonCallable' , this ) ;
@@ -277,6 +276,149 @@ function Promise_allSettled([iterable = Value.undefined], { thisValue }) {
277
276
return Completion ( result ) ;
278
277
}
279
278
279
+ // https://tc39.es/proposal-promise-any/#sec-promise.any-reject-element-functions
280
+ function PromiseAnyRejectElementFunctions ( [ x = Value . undefined ] ) {
281
+ // 1. Let F be the active function object.
282
+ const F = surroundingAgent . activeFunctionObject ;
283
+ // 2. Let alreadyCalled be F.[[AlreadyCalled]].
284
+ const alreadyCalled = F . AlreadyCalled ;
285
+ // 3. If alreadyCalled.[[Value]] is true, return undefined.
286
+ if ( alreadyCalled . Value ) {
287
+ return Value . undefined ;
288
+ }
289
+ // 4. Set alreadyCalled.[[Value]] to true.
290
+ alreadyCalled . Value = true ;
291
+ // 5. Let index be F.[[Index]].
292
+ const index = F . Index ;
293
+ // 6. Let errors be F.[[Errors]].
294
+ const errors = F . Errors ;
295
+ // 7. Let promiseCapability be F.[[Capability]].
296
+ const promiseCapability = F . Capability ;
297
+ // 8. Let remainingElementsCount be F.[[RemainingElements]].
298
+ const remainingElementsCount = F . RemainingElements ;
299
+ // 9. Set errors[index] to x.
300
+ errors [ index ] = x ;
301
+ // 10. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1.
302
+ remainingElementsCount . Value -= 1 ;
303
+ // 11. If remainingElementsCount.[[Value]] is 0, then
304
+ if ( remainingElementsCount . Value === 0 ) {
305
+ // a. Let error be a newly created AggregateError object.
306
+ const error = surroundingAgent . Throw ( 'AggregateError' , 'PromiseAnyRejected' ) . Value ;
307
+ // b. Set error.[[AggregateErrors]] to errors.
308
+ error . AggregateErrors = errors ;
309
+ // c. Return ? Call(promiseCapability.[[Reject]], undefined, « error »).
310
+ return Q ( Call ( promiseCapability . Reject , Value . undefined , [ error ] ) ) ;
311
+ }
312
+ // 12. Return undefined.
313
+ return Value . undefined ;
314
+ }
315
+
316
+ // https://tc39.es/proposal-promise-any/#sec-performpromiseany
317
+ function PerformPromiseAny ( iteratorRecord , constructor , resultCapability ) {
318
+ // 1. Assert: ! IsConstructor(constructor) is true.
319
+ Assert ( X ( IsConstructor ( constructor ) ) === Value . true ) ;
320
+ // 2. Assert: resultCapability is a PromiseCapability Record.
321
+ Assert ( resultCapability instanceof PromiseCapabilityRecord ) ;
322
+ // 3. Let errors be a new empty List.
323
+ const errors = [ ] ;
324
+ // 4. Let remainingElementsCount be a new Record { [[Value]]: 1 }.
325
+ const remainingElementsCount = { Value : 1 } ;
326
+ // 5. Let index be 0.
327
+ let index = 0 ;
328
+ // 6. Let promiseResolve be ? Get(constructor, "resolve").
329
+ const promiseResolve = Q ( Get ( constructor , new Value ( 'resolve' ) ) ) ;
330
+ // 7. If ! IsCallable(promiseResolve) is false, throw a TypeError exception.
331
+ if ( X ( IsCallable ( promiseResolve ) ) === Value . false ) {
332
+ return surroundingAgent . Throw ( 'TypeError' , 'NotAFunction' , promiseResolve ) ;
333
+ }
334
+ // 8. Repeat,
335
+ while ( true ) {
336
+ // a. Let next be IteratorStep(iteratorRecord).
337
+ const next = IteratorStep ( iteratorRecord ) ;
338
+ // b. If next is an abrupt completion, set iteratorRecord.[[Done]] to true.
339
+ if ( next instanceof AbruptCompletion ) {
340
+ iteratorRecord . Done = Value . true ;
341
+ }
342
+ // c. ReturnIfAbrupt(next).
343
+ ReturnIfAbrupt ( next ) ;
344
+ // d. If next is false, then
345
+ if ( next === Value . false ) {
346
+ // i. Set iteratorRecord.[[Done]] to true.
347
+ iteratorRecord . Done = Value . true ;
348
+ // ii. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1.
349
+ remainingElementsCount . Value -= 1 ;
350
+ // iii. If remainingElementsCount.[[Value]] is 0, then
351
+ if ( remainingElementsCount . Value === 0 ) {
352
+ // 1. Let error be a newly created AggregateError object.
353
+ const error = surroundingAgent . Throw ( 'AggregateError' , 'PromiseAnyRejected' ) . Value ;
354
+ // 2. Set error.[[AggregateErrors]] to errors.
355
+ error . AggregateErrors = errors ;
356
+ // 3. Return ThrowCompletion(error).
357
+ return ThrowCompletion ( error ) ;
358
+ }
359
+ // iv. Return resultCapability.[[Promise]].
360
+ return resultCapability . Promise ;
361
+ }
362
+ // e. Let nextValue be IteratorValue(next).
363
+ const nextValue = IteratorValue ( next ) ;
364
+ // f. If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true.
365
+ if ( nextValue instanceof AbruptCompletion ) {
366
+ iteratorRecord . Done = Value . true ;
367
+ }
368
+ // g. ReturnIfAbrupt(nextValue).
369
+ ReturnIfAbrupt ( nextValue ) ;
370
+ // h. Append undefined to errors.
371
+ errors . push ( Value . undefined ) ;
372
+ // i. Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »).
373
+ const nextPromise = Q ( Call ( promiseResolve , constructor , [ nextValue ] ) ) ;
374
+ // j. Let steps be the algorithm steps defined in Promise.any Reject Element Functions.
375
+ const steps = PromiseAnyRejectElementFunctions ;
376
+ // k. Let rejectElement be ! CreateBuiltinFunction(steps, « [[AlreadyCalled]], [[Index]], [[Errors]], [[Capability]], [[RemainingElements]] »).
377
+ const rejectElement = X ( CreateBuiltinFunction ( steps , [ 'AlreadyCalled' , 'Index' , 'Errors' , 'Capability' , 'RemainingElements' ] ) ) ;
378
+ // l. Set rejectElement.[[AlreadyCalled]] to a new Record { [[Value]]: false }.
379
+ rejectElement . AlreadyCalled = { Value : false } ;
380
+ // m. Set rejectElement.[[Index]] to index.
381
+ rejectElement . Index = index ;
382
+ // n. Set rejectElement.[[Errors]] to errors.
383
+ rejectElement . Errors = errors ;
384
+ // o. Set rejectElement.[[Capability]] to resultCapability.
385
+ rejectElement . Capability = resultCapability ;
386
+ // p. Set rejectElement.[[RemainingElements]] to remainingElementsCount.
387
+ rejectElement . RemainingElements = remainingElementsCount ;
388
+ // q. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] + 1.
389
+ remainingElementsCount . Value += 1 ;
390
+ // r. Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], rejectElement »).
391
+ Q ( Invoke ( nextPromise , new Value ( 'then' ) , [ resultCapability . Resolve , rejectElement ] ) ) ;
392
+ // s. Increase index by 1.
393
+ index += 1 ;
394
+ }
395
+ }
396
+
397
+ // https://tc39.es/proposal-promise-any/#sec-promise.any
398
+ function Promise_any ( [ iterable = Value . undefined ] , { thisValue } ) {
399
+ // 1. Let C be the this value.
400
+ const C = thisValue ;
401
+ // 2. Let promiseCapability be ? NewPromiseCapability(C).
402
+ const promiseCapability = Q ( NewPromiseCapability ( C ) ) ;
403
+ // 3. Let iteratorRecord be GetIterator(iterable).
404
+ const iteratorRecord = GetIterator ( iterable ) ;
405
+ // 4. IfAbruptRejectPromise(iteratorRecord, promiseCapability).
406
+ IfAbruptRejectPromise ( iteratorRecord , promiseCapability ) ;
407
+ // 5. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability).
408
+ let result = PerformPromiseAny ( iteratorRecord , C , promiseCapability ) ;
409
+ // 6. If result is an abrupt completion, then
410
+ if ( result instanceof AbruptCompletion ) {
411
+ // a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result).
412
+ if ( iteratorRecord . Done === Value . false ) {
413
+ result = IteratorClose ( iteratorRecord , result ) ;
414
+ }
415
+ // b. IfAbruptRejectPromise(result, promiseCapability).
416
+ IfAbruptRejectPromise ( result , promiseCapability ) ;
417
+ }
418
+ // 1. Return Completion(result).
419
+ return Completion ( result ) ;
420
+ }
421
+
280
422
function PerformPromiseRace ( iteratorRecord , constructor , resultCapability ) {
281
423
Assert ( IsConstructor ( constructor ) === Value . true ) ;
282
424
Assert ( resultCapability instanceof PromiseCapabilityRecord ) ;
@@ -342,6 +484,9 @@ export function BootstrapPromise(realmRec) {
342
484
const promiseConstructor = BootstrapConstructor ( realmRec , PromiseConstructor , 'Promise' , 1 , realmRec . Intrinsics [ '%Promise.prototype%' ] , [
343
485
[ 'all' , Promise_all , 1 ] ,
344
486
[ 'allSettled' , Promise_allSettled , 1 ] ,
487
+ surroundingAgent . feature ( 'Promise.any' )
488
+ ? [ 'any' , Promise_any , 1 ]
489
+ : undefined ,
345
490
[ 'race' , Promise_race , 1 ] ,
346
491
[ 'reject' , Promise_reject , 1 ] ,
347
492
[ 'resolve' , Promise_resolve , 1 ] ,
0 commit comments