diff --git a/packages/core/src/client/webcomponents/state/logs-client.ts b/packages/core/src/client/webcomponents/state/logs-client.ts index a0bd3362..2ddb89a1 100644 --- a/packages/core/src/client/webcomponents/state/logs-client.ts +++ b/packages/core/src/client/webcomponents/state/logs-client.ts @@ -1,34 +1,70 @@ -import type { DevToolsLogEntry, DevToolsLogEntryInput, DevToolsLogHandle, DevToolsLogsClient } from '@vitejs/devtools-kit' +import type { DevToolsLogEntryInput, DevToolsLogHandle, DevToolsLogsClient } from '@vitejs/devtools-kit' import type { DevToolsRpcClient } from '@vitejs/devtools-kit/client' -function createRpcHandle(rpc: DevToolsRpcClient, initialEntry: DevToolsLogEntry): DevToolsLogHandle { - let entry = initialEntry - return { - get entry() { return entry }, - get id() { return entry.id }, - async update(patch: Partial) { - const updated = await rpc.call('devtoolskit:internal:logs:update', entry.id, patch) - if (updated) - entry = updated - return updated ?? undefined - }, - async dismiss() { - await rpc.call('devtoolskit:internal:logs:remove', entry.id) - }, +export function createClientLogsClient(rpc: DevToolsRpcClient): DevToolsLogsClient { + const buffer: (() => Promise)[] = [] + let flushing: Promise | undefined + + async function flush() { + if (rpc.isTrusted !== true) + return + if (flushing === undefined) { + // eslint-disable-next-line no-async-promise-executor + flushing = new Promise(async (resolve) => { + while (buffer.length > 0) { + const op = buffer.shift()! + await op() + } + resolve() + }) + } + return flushing } -} -export function createClientLogsClient(rpc: DevToolsRpcClient): DevToolsLogsClient { + async function enqueue(op: () => Promise): Promise { + if (rpc.isTrusted === true && buffer.length !== 0) + await flush() + + if (rpc.isTrusted === true && buffer.length === 0) + return await op() + + return new Promise((resolve) => { + buffer.push(async () => { + const result = await op() + resolve(result) + }) + }) + } + + rpc.events.on('rpc:is-trusted:updated', (isTrusted) => { + if (isTrusted && buffer.length > 0) + flush() + }) + return { - async add(input: DevToolsLogEntryInput): Promise { - const entry = await rpc.call('devtoolskit:internal:logs:add', input) - return createRpcHandle(rpc, entry) + add(input: DevToolsLogEntryInput): Promise { + return enqueue(async () => { + let entry = await rpc.call('devtoolskit:internal:logs:add', input) + return { + get entry() { return entry }, + get id() { return entry.id }, + async update(patch: Partial) { + const updated = await rpc.call('devtoolskit:internal:logs:update', entry.id, patch) + if (updated) + entry = updated + return updated ?? undefined + }, + async dismiss() { + await rpc.call('devtoolskit:internal:logs:remove', entry.id) + }, + } + }) }, - async remove(id: string): Promise { - await rpc.call('devtoolskit:internal:logs:remove', id) + remove(id: string): Promise { + return enqueue(() => rpc.call('devtoolskit:internal:logs:remove', id)) }, - async clear(): Promise { - await rpc.call('devtoolskit:internal:logs:clear') + clear(): Promise { + return enqueue(() => rpc.call('devtoolskit:internal:logs:clear')) }, } }