diff options
author | Kenta Moriuchi <moriken@kimamass.com> | 2023-03-13 19:24:31 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-03-13 19:24:31 +0900 |
commit | e5673f5ed85774831234fe70290d5802bbd47c15 (patch) | |
tree | 59a8deb3e81bc596ec73afcaae01de9a1cb1e845 /core | |
parent | bcb6ee9d0864f490f6da47cbe2593310b21333ff (diff) |
fix(core): `SafePromiseAll` to be unaffected by `Array#@@iterator` (#17542)
Diffstat (limited to 'core')
-rw-r--r-- | core/00_primordials.js | 80 | ||||
-rw-r--r-- | core/01_core.js | 3 | ||||
-rw-r--r-- | core/internal.d.ts | 4 |
3 files changed, 72 insertions, 15 deletions
diff --git a/core/00_primordials.js b/core/00_primordials.js index 243f40e88..f49a11de4 100644 --- a/core/00_primordials.js +++ b/core/00_primordials.js @@ -329,10 +329,11 @@ return SafeIterator; }; - primordials.SafeArrayIterator = createSafeIterator( + const SafeArrayIterator = createSafeIterator( primordials.ArrayPrototypeSymbolIterator, primordials.ArrayIteratorPrototypeNext, ); + primordials.SafeArrayIterator = SafeArrayIterator; primordials.SafeSetIterator = createSafeIterator( primordials.SetPrototypeSymbolIterator, primordials.SetIteratorPrototypeNext, @@ -479,29 +480,80 @@ primordials.PromisePrototypeCatch = (thisPromise, onRejected) => PromisePrototypeThen(thisPromise, undefined, onRejected); + const arrayToSafePromiseIterable = (array) => + new SafeArrayIterator( + ArrayPrototypeMap( + array, + (p) => { + if (ObjectPrototypeIsPrototypeOf(PromisePrototype, p)) { + return new SafePromise((c, d) => PromisePrototypeThen(p, c, d)); + } + return p; + }, + ), + ); + /** * Creates a Promise that is resolved with an array of results when all of the * provided Promises resolve, or rejected when any Promise is rejected. - * @param {unknown[]} values An array of Promises. - * @returns A new Promise. + * @template T + * @param {Array<T | PromiseLike<T>>} values + * @returns {Promise<Awaited<T>[]>} */ primordials.SafePromiseAll = (values) => // Wrapping on a new Promise is necessary to not expose the SafePromise // prototype to user-land. new Promise((a, b) => - SafePromise.all( - ArrayPrototypeMap( - values, - (p) => { - if (ObjectPrototypeIsPrototypeOf(PromisePrototype, p)) { - return new SafePromise((c, d) => PromisePrototypeThen(p, c, d)); - } - return p; - }, - ), - ).then(a, b) + SafePromise.all(arrayToSafePromiseIterable(values)).then(a, b) ); + // NOTE: Uncomment the following functions when you need to use them + + // /** + // * Creates a Promise that is resolved with an array of results when all + // * of the provided Promises resolve or reject. + // * @template T + // * @param {Array<T | PromiseLike<T>>} values + // * @returns {Promise<PromiseSettledResult<T>[]>} + // */ + // primordials.SafePromiseAllSettled = (values) => + // // Wrapping on a new Promise is necessary to not expose the SafePromise + // // prototype to user-land. + // new Promise((a, b) => + // SafePromise.allSettled(arrayToSafePromiseIterable(values)).then(a, b) + // ); + + // /** + // * The any function returns a promise that is fulfilled by the first given + // * promise to be fulfilled, or rejected with an AggregateError containing + // * an array of 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. + // * @template T + // * @param {T} values + // * @returns {Promise<Awaited<T[number]>>} + // */ + // primordials.SafePromiseAny = (values) => + // // Wrapping on a new Promise is necessary to not expose the SafePromise + // // prototype to user-land. + // new Promise((a, b) => + // SafePromise.any(arrayToSafePromiseIterable(values)).then(a, b) + // ); + + // /** + // * Creates a Promise that is resolved or rejected when any of the provided + // * Promises are resolved or rejected. + // * @template T + // * @param {T} values + // * @returns {Promise<Awaited<T[number]>>} + // */ + // primordials.SafePromiseRace = (values) => + // // Wrapping on a new Promise is necessary to not expose the SafePromise + // // prototype to user-land. + // new Promise((a, b) => + // SafePromise.race(arrayToSafePromiseIterable(values)).then(a, b) + // ); + /** * Attaches a callback that is invoked when the Promise is settled (fulfilled or * rejected). The resolved value cannot be modified from the callback. diff --git a/core/01_core.js b/core/01_core.js index 07ab758f1..a13bdc8dd 100644 --- a/core/01_core.js +++ b/core/01_core.js @@ -21,6 +21,7 @@ PromisePrototypeThen, RangeError, ReferenceError, + SafeArrayIterator, SafePromisePrototypeFinally, setQueueMicrotask, StringPrototypeSlice, @@ -198,7 +199,7 @@ const id = rollPromiseId(); let promise = PromisePrototypeThen(setPromise(id), unwrapOpResult); try { - ops[name](id, ...args); + ops[name](id, ...new SafeArrayIterator(args)); } catch (err) { // Cleanup the just-created promise getPromise(id); diff --git a/core/internal.d.ts b/core/internal.d.ts index a91ac6244..e34cfbe71 100644 --- a/core/internal.d.ts +++ b/core/internal.d.ts @@ -75,6 +75,10 @@ declare namespace __bootstrap { typeof globalThis.FinalizationRegistry; export const SafeWeakRef: typeof globalThis.WeakRef; export const SafePromiseAll: typeof Promise.all; + // NOTE: Uncomment the following functions when you need to use them + // export const SafePromiseAllSettled: typeof Promise.allSettled; + // export const SafePromiseAny: typeof Promise.any; + // export const SafePromiseRace: typeof Promise.race; export const SafePromisePrototypeFinally: UncurryThis< Promise.prototype.finally >; |