diff --git a/packages/app/src/context/session-message-decoder.ts b/packages/app/src/context/session-message-decoder.ts index 37a2f94aee8..a4502b353b1 100644 --- a/packages/app/src/context/session-message-decoder.ts +++ b/packages/app/src/context/session-message-decoder.ts @@ -1,4 +1,3 @@ -import SessionMessageDecoderWorkerUrl from "./session-message-decoder.worker.ts?worker&url" import type { DecodedLegacyMessagePage } from "./session-message-decode" import type { SessionInfo } from "@opencode-ai/client/promise" import type { Session } from "@opencode-ai/sdk/v2/client" @@ -6,6 +5,7 @@ import type { Session } from "@opencode-ai/sdk/v2/client" type Response = { id: number; data?: unknown; error?: string } let worker: Worker | undefined +let workerLoad: Promise | undefined let nextID = 0 const pending = new Map void; reject: (error: Error) => void }>() @@ -29,29 +29,41 @@ function decode( const id = ++nextID return new Promise((resolve, reject) => { pending.set(id, { resolve: (value) => resolve(value as T), reject }) - getWorker().postMessage({ id, type, buffer, options }, [buffer]) + void getWorker() + .then((worker) => worker.postMessage({ id, type, buffer, options }, [buffer])) + .catch((error) => { + pending.delete(id) + reject(error instanceof Error ? error : new Error(String(error))) + }) }) } function getWorker() { - if (worker) return worker - worker = new Worker(SessionMessageDecoderWorkerUrl, { type: "module" }) - worker.onmessage = (event: MessageEvent) => { - const request = pending.get(event.data.id) - if (!request) return - pending.delete(event.data.id) - if (event.data.error) { - request.reject(new Error(event.data.error)) - return + if (worker) return Promise.resolve(worker) + if (workerLoad) return workerLoad + workerLoad = (async () => { + const { default: workerUrl } = await import("./session-message-decoder.worker.ts?worker&url") + const next = new Worker(workerUrl, { type: "module" }) + next.onmessage = (event: MessageEvent) => { + const request = pending.get(event.data.id) + if (!request) return + pending.delete(event.data.id) + if (event.data.error) { + request.reject(new Error(event.data.error)) + return + } + request.resolve(event.data.data) } - request.resolve(event.data.data) - } - worker.onerror = (event) => { - const error = new Error(event.message) - pending.forEach((request) => request.reject(error)) - pending.clear() - worker?.terminate() - worker = undefined - } - return worker + next.onerror = (event) => { + const error = new Error(event.message) + pending.forEach((request) => request.reject(error)) + pending.clear() + next.terminate() + worker = undefined + workerLoad = undefined + } + worker = next + return next + })() + return workerLoad } diff --git a/packages/app/src/utils/vcs-diff-decoder.ts b/packages/app/src/utils/vcs-diff-decoder.ts index be4abedaf03..ac577be5005 100644 --- a/packages/app/src/utils/vcs-diff-decoder.ts +++ b/packages/app/src/utils/vcs-diff-decoder.ts @@ -1,9 +1,9 @@ import type { FileDiffInfo } from "@opencode-ai/client/promise" -import VcsDiffDecoderWorkerUrl from "./vcs-diff-decoder.worker.ts?worker&url" type Response = { id: number; data?: FileDiffInfo[]; error?: string } let worker: Worker | undefined +let workerLoad: Promise | undefined let nextID = 0 const pending = new Map void; reject: (error: Error) => void }>() let lastInput = 0 @@ -19,31 +19,43 @@ export function decodeVcsDiff(buffer: ArrayBuffer) { const id = ++nextID return new Promise((resolve, reject) => { pending.set(id, { resolve, reject }) - getWorker().postMessage({ id, buffer }, [buffer]) + void getWorker() + .then((worker) => worker.postMessage({ id, buffer }, [buffer])) + .catch((error) => { + pending.delete(id) + reject(error instanceof Error ? error : new Error(String(error))) + }) }) } function getWorker() { - if (worker) return worker - worker = new Worker(VcsDiffDecoderWorkerUrl, { type: "module" }) - worker.onmessage = (event: MessageEvent) => { - const request = pending.get(event.data.id) - if (!request) return - pending.delete(event.data.id) - if (event.data.error) { - request.reject(new Error(event.data.error)) - return + if (worker) return Promise.resolve(worker) + if (workerLoad) return workerLoad + workerLoad = (async () => { + const { default: workerUrl } = await import("./vcs-diff-decoder.worker.ts?worker&url") + const next = new Worker(workerUrl, { type: "module" }) + next.onmessage = (event: MessageEvent) => { + const request = pending.get(event.data.id) + if (!request) return + pending.delete(event.data.id) + if (event.data.error) { + request.reject(new Error(event.data.error)) + return + } + resolveWhenInputIdle(request.resolve, event.data.data ?? []) } - resolveWhenInputIdle(request.resolve, event.data.data ?? []) - } - worker.onerror = (event) => { - const error = new Error(event.message) - pending.forEach((request) => request.reject(error)) - pending.clear() - worker?.terminate() - worker = undefined - } - return worker + next.onerror = (event) => { + const error = new Error(event.message) + pending.forEach((request) => request.reject(error)) + pending.clear() + next.terminate() + worker = undefined + workerLoad = undefined + } + worker = next + return next + })() + return workerLoad } function resolveWhenInputIdle(resolve: (value: FileDiffInfo[]) => void, value: FileDiffInfo[], initial = true) {