From e2698987f2f4bed8e1c7ba42bcad4aaaa749c4b8 Mon Sep 17 00:00:00 2001 From: Amer Redzovic Date: Tue, 8 Oct 2024 17:57:47 +0200 Subject: [PATCH 1/2] Added requestWrap and sendReady. The user can await requestWrap until the Endpoint calls sendReady. --- src/comlink.ts | 93 +++++++++++++++++++++++++++++--------------------- 1 file changed, 55 insertions(+), 38 deletions(-) diff --git a/src/comlink.ts b/src/comlink.ts index 8896b71d..3e9fb262 100644 --- a/src/comlink.ts +++ b/src/comlink.ts @@ -117,25 +117,25 @@ export interface ProxyMethods { export type Remote = // Handle properties RemoteObject & - // Handle call signature (if present) - (T extends (...args: infer TArguments) => infer TReturn - ? ( - ...args: { [I in keyof TArguments]: UnproxyOrClone } - ) => Promisify>> - : unknown) & - // Handle construct signature (if present) - // The return of construct signatures is always proxied (whether marked or not) - (T extends { new (...args: infer TArguments): infer TInstance } - ? { - new ( - ...args: { - [I in keyof TArguments]: UnproxyOrClone; - } - ): Promisify>; + // Handle call signature (if present) + (T extends (...args: infer TArguments) => infer TReturn + ? ( + ...args: { [I in keyof TArguments]: UnproxyOrClone } + ) => Promisify>> + : unknown) & + // Handle construct signature (if present) + // The return of construct signatures is always proxied (whether marked or not) + (T extends { new(...args: infer TArguments): infer TInstance } + ? { + new( + ...args: { + [I in keyof TArguments]: UnproxyOrClone; } - : unknown) & - // Include additional special comlink methods available on the proxy. - ProxyMethods; + ): Promisify>; + } + : unknown) & + // Include additional special comlink methods available on the proxy. + ProxyMethods; /** * Expresses that a type can be either a sync or async. @@ -151,25 +151,25 @@ type MaybePromise = Promise | T; export type Local = // Omit the special proxy methods (they don't need to be supplied, comlink adds them) Omit, keyof ProxyMethods> & - // Handle call signatures (if present) - (T extends (...args: infer TArguments) => infer TReturn - ? ( - ...args: { [I in keyof TArguments]: ProxyOrClone } - ) => // The raw function could either be sync or async, but is always proxied automatically - MaybePromise>> - : unknown) & - // Handle construct signature (if present) - // The return of construct signatures is always proxied (whether marked or not) - (T extends { new (...args: infer TArguments): infer TInstance } - ? { - new ( - ...args: { - [I in keyof TArguments]: ProxyOrClone; - } - ): // The raw constructor could either be sync or async, but is always proxied automatically - MaybePromise>>; + // Handle call signatures (if present) + (T extends (...args: infer TArguments) => infer TReturn + ? ( + ...args: { [I in keyof TArguments]: ProxyOrClone } + ) => // The raw function could either be sync or async, but is always proxied automatically + MaybePromise>> + : unknown) & + // Handle construct signature (if present) + // The return of construct signatures is always proxied (whether marked or not) + (T extends { new(...args: infer TArguments): infer TInstance } + ? { + new( + ...args: { + [I in keyof TArguments]: ProxyOrClone; } - : unknown); + ): // The raw constructor could either be sync or async, but is always proxied automatically + MaybePromise>>; + } + : unknown); const isObject = (val: unknown): val is object => (typeof val === "object" && val !== null) || typeof val === "function"; @@ -395,6 +395,23 @@ export function wrap(ep: Endpoint, target?: any): Remote { return createProxy(ep, [], target) as any; } +export function requestWrap(ep: Endpoint, target?: any): Promise> { + return new Promise((resolve) => { + ep.addEventListener("message", function l(ev: MessageEvent) { + if (!ev.data || !ev.data.status || ev.data.status !== "ready") { + return; + } + ep.removeEventListener("message", l as any); + resolve(createProxy(ep, [], target) as any); + } as any); + }) +} + +export function sendReady(ep: Endpoint): void { + ep.postMessage({ status: "ready" }); +} + + function throwIfProxyReleased(isReleased: boolean) { if (isReleased) { throw new Error("Proxy has been released and is not useable"); @@ -410,7 +427,7 @@ function releaseEndpoint(ep: Endpoint) { } interface FinalizationRegistry { - new (cb: (heldValue: T) => void): FinalizationRegistry; + new(cb: (heldValue: T) => void): FinalizationRegistry; register( weakItem: object, heldValue: T, @@ -448,7 +465,7 @@ function unregisterProxy(proxy: object) { function createProxy( ep: Endpoint, path: (string | number | symbol)[] = [], - target: object = function () {} + target: object = function() { } ): Remote { let isProxyReleased = false; const proxy = new Proxy(target, { From a16cb4daa3a5540e98186654130cb7f782aca07f Mon Sep 17 00:00:00 2001 From: Amer Redzovic Date: Tue, 8 Oct 2024 22:39:15 +0200 Subject: [PATCH 2/2] Added the globalThis as the default value for the Endpoint of the sendReady function --- src/comlink.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/comlink.ts b/src/comlink.ts index 3e9fb262..d1165482 100644 --- a/src/comlink.ts +++ b/src/comlink.ts @@ -407,7 +407,7 @@ export function requestWrap(ep: Endpoint, target?: any): Promise> { }) } -export function sendReady(ep: Endpoint): void { +export function sendReady(ep: Endpoint = globalThis as any): void { ep.postMessage({ status: "ready" }); }