@@ -261,6 +261,7 @@ function copyPrototype(src, dest, prefix) {
261
261
/* eslint-enable node-core/prefer-primordials */
262
262
263
263
const {
264
+ Array : ArrayConstructor ,
264
265
ArrayPrototypeForEach,
265
266
ArrayPrototypeMap,
266
267
FinalizationRegistry,
@@ -272,6 +273,7 @@ const {
272
273
ObjectSetPrototypeOf,
273
274
Promise,
274
275
PromisePrototypeThen,
276
+ PromiseResolve,
275
277
ReflectApply,
276
278
ReflectConstruct,
277
279
ReflectSet,
@@ -466,9 +468,10 @@ const arrayToSafePromiseIterable = (promises, mapFn) =>
466
468
) ;
467
469
468
470
/**
469
- * @param {Promise<any>[] } promises
470
- * @param {(v: Promise<any>, k: number) => Promise<any> } [mapFn]
471
- * @returns {Promise<any[]> }
471
+ * @template T,U
472
+ * @param {Array<T | PromiseLike<T>> } promises
473
+ * @param {(v: T|PromiseLike<T>, k: number) => U|PromiseLike<U> } [mapFn]
474
+ * @returns {Promise<Awaited<U>[]> }
472
475
*/
473
476
primordials . SafePromiseAll = ( promises , mapFn ) =>
474
477
// Wrapping on a new Promise is necessary to not expose the SafePromise
@@ -478,8 +481,56 @@ primordials.SafePromiseAll = (promises, mapFn) =>
478
481
) ;
479
482
480
483
/**
481
- * @param {Promise<any>[] } promises
482
- * @param {(v: Promise<any>, k: number) => Promise<any> } [mapFn]
484
+ * Should only be used for internal functions, this would produce similar
485
+ * results as `Promise.all` but without prototype pollution, and the return
486
+ * value is not a genuine Array but an array-like object.
487
+ * @template T,U
488
+ * @param {ArrayLike<T | PromiseLike<T>> } promises
489
+ * @param {(v: T|PromiseLike<T>, k: number) => U|PromiseLike<U> } [mapFn]
490
+ * @returns {Promise<ArrayLike<Awaited<U>>> }
491
+ */
492
+ primordials . SafePromiseAllReturnArrayLike = ( promises , mapFn ) =>
493
+ new Promise ( ( resolve , reject ) => {
494
+ const { length } = promises ;
495
+
496
+ const returnVal = ArrayConstructor ( length ) ;
497
+ ObjectSetPrototypeOf ( returnVal , null ) ;
498
+ if ( length === 0 ) resolve ( returnVal ) ;
499
+
500
+ let pendingPromises = length ;
501
+ for ( let i = 0 ; i < length ; i ++ ) {
502
+ const promise = mapFn != null ? mapFn ( promises [ i ] , i ) : promises [ i ] ;
503
+ PromisePrototypeThen ( PromiseResolve ( promise ) , ( result ) => {
504
+ returnVal [ i ] = result ;
505
+ if ( -- pendingPromises === 0 ) resolve ( returnVal ) ;
506
+ } , reject ) ;
507
+ }
508
+ } ) ;
509
+
510
+ /**
511
+ * Should only be used when we only care about waiting for all the promises to
512
+ * resolve, not what value they resolve to.
513
+ * @template T,U
514
+ * @param {ArrayLike<T | PromiseLike<T>> } promises
515
+ * @param {(v: T|PromiseLike<T>, k: number) => U|PromiseLike<U> } [mapFn]
516
+ * @returns {Promise<void> }
517
+ */
518
+ primordials . SafePromiseAllReturnVoid = ( promises , mapFn ) =>
519
+ new Promise ( ( resolve , reject ) => {
520
+ let pendingPromises = promises . length ;
521
+ if ( pendingPromises === 0 ) resolve ( ) ;
522
+ for ( let i = 0 ; i < promises . length ; i ++ ) {
523
+ const promise = mapFn != null ? mapFn ( promises [ i ] , i ) : promises [ i ] ;
524
+ PromisePrototypeThen ( PromiseResolve ( promise ) , ( ) => {
525
+ if ( -- pendingPromises === 0 ) resolve ( ) ;
526
+ } , reject ) ;
527
+ }
528
+ } ) ;
529
+
530
+ /**
531
+ * @template T,U
532
+ * @param {Array<T|PromiseLike<T>> } promises
533
+ * @param {(v: T|PromiseLike<T>, k: number) => U|PromiseLike<U> } [mapFn]
483
534
* @returns {Promise<PromiseSettledResult<any>[]> }
484
535
*/
485
536
primordials . SafePromiseAllSettled = ( promises , mapFn ) =>
@@ -490,9 +541,28 @@ primordials.SafePromiseAllSettled = (promises, mapFn) =>
490
541
) ;
491
542
492
543
/**
493
- * @param {Promise<any>[] } promises
494
- * @param {(v: Promise<any>, k: number) => Promise<any> } [mapFn]
495
- * @returns {Promise<any> }
544
+ * Should only be used when we only care about waiting for all the promises to
545
+ * settle, not what value they resolve or reject to.
546
+ * @template T,U
547
+ * @param {ArrayLike<T|PromiseLike<T>> } promises
548
+ * @param {(v: T|PromiseLike<T>, k: number) => U|PromiseLike<U> } [mapFn]
549
+ * @returns {Promise<void> }
550
+ */
551
+ primordials . SafePromiseAllSettledReturnVoid = async ( promises , mapFn ) => {
552
+ for ( let i = 0 ; i < promises . length ; i ++ ) {
553
+ try {
554
+ await ( mapFn != null ? mapFn ( promises [ i ] , i ) : promises [ i ] ) ;
555
+ } catch {
556
+ // In all settled, we can ignore errors.
557
+ }
558
+ }
559
+ } ;
560
+
561
+ /**
562
+ * @template T,U
563
+ * @param {Array<T|PromiseLike<T>> } promises
564
+ * @param {(v: T|PromiseLike<T>, k: number) => U|PromiseLike<U> } [mapFn]
565
+ * @returns {Promise<Awaited<U>> }
496
566
*/
497
567
primordials . SafePromiseAny = ( promises , mapFn ) =>
498
568
// Wrapping on a new Promise is necessary to not expose the SafePromise
@@ -502,9 +572,10 @@ primordials.SafePromiseAny = (promises, mapFn) =>
502
572
) ;
503
573
504
574
/**
505
- * @param {Promise<any>[] } promises
506
- * @param {(v: Promise<any>, k: number) => Promise<any> } [mapFn]
507
- * @returns {Promise<any> }
575
+ * @template T,U
576
+ * @param {Array<T|PromiseLike<T>> } promises
577
+ * @param {(v: T|PromiseLike<T>, k: number) => U|PromiseLike<U> } [mapFn]
578
+ * @returns {Promise<Awaited<U>> }
508
579
*/
509
580
primordials . SafePromiseRace = ( promises , mapFn ) =>
510
581
// Wrapping on a new Promise is necessary to not expose the SafePromise
0 commit comments