From 0fca81dc93d1bcfb1c02fb00ee21c03ba9e1247d Mon Sep 17 00:00:00 2001 From: thislight Date: Wed, 4 Dec 2024 22:57:41 +0800 Subject: [PATCH] polyfills: add Promise.withResolver --- src/platform/polyfills.ts | 21 +++++++++++++++++++++ types/lib.esnext.promise.d.ts | 26 ++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 types/lib.esnext.promise.d.ts diff --git a/src/platform/polyfills.ts b/src/platform/polyfills.ts index 032207a..1af3341 100644 --- a/src/platform/polyfills.ts +++ b/src/platform/polyfills.ts @@ -15,3 +15,24 @@ if (typeof window.crypto.randomUUID === "undefined") { ) as `${string}-${string}-${string}-${string}-${string}`; }; } + + +if (typeof Promise.withResolvers === "undefined") { + // Chrome/Edge 119, Firefox 121, Safari/iOS 17.4 + + // Promise.withResolvers is generic and works with subclasses - the typescript built-in decl + // could not handle the subclassing case. + Promise.withResolvers = function (this: AnyPromiseConstructor) { + let resolve!: PromiseWithResolvers["resolve"], reject!: PromiseWithResolvers["reject"]; + // These variables are expected to be set after `new this()` + + const promise = new this((resolve0, reject0) => { + resolve = resolve0; + reject = reject0; + }) + + return { + promise, resolve, reject + } + } +} diff --git a/types/lib.esnext.promise.d.ts b/types/lib.esnext.promise.d.ts new file mode 100644 index 0000000..5df9b56 --- /dev/null +++ b/types/lib.esnext.promise.d.ts @@ -0,0 +1,26 @@ +interface AnyPromiseWithResolvers { + promise: Instance; + resolve: (value: T | PromiseLike) => void; + reject: (reason?: any) => void; +} + +type AnyPromiseConstructor = new ( + executor: ( + resolve: PromiseWithResolvers["resolve"], + reject: PromiseWithResolvers["reject"], + ) => void, +) => Promise; + +interface PromiseConstructor { + /** + * Creates a new Promise and returns it in an object, along with its resolve and reject functions. + * @returns An object with the properties `promise`, `resolve`, and `reject`. + * + * ```ts + * const { promise, resolve, reject } = Promise.withResolvers(); + * ``` + */ + withResolvers>( + this: K, + ): AnyPromiseWithResolvers>; +}