|
1 | | -import type { DevToolsLogEntry, DevToolsLogEntryInput, DevToolsLogHandle, DevToolsLogsClient } from '@vitejs/devtools-kit' |
| 1 | +import type { DevToolsLogEntryInput, DevToolsLogHandle, DevToolsLogsClient } from '@vitejs/devtools-kit' |
2 | 2 | import type { DevToolsRpcClient } from '@vitejs/devtools-kit/client' |
3 | 3 |
|
4 | | -function createRpcHandle(rpc: DevToolsRpcClient, initialEntry: DevToolsLogEntry): DevToolsLogHandle { |
5 | | - let entry = initialEntry |
6 | | - return { |
7 | | - get entry() { return entry }, |
8 | | - get id() { return entry.id }, |
9 | | - async update(patch: Partial<DevToolsLogEntryInput>) { |
10 | | - const updated = await rpc.call('devtoolskit:internal:logs:update', entry.id, patch) |
11 | | - if (updated) |
12 | | - entry = updated |
13 | | - return updated ?? undefined |
14 | | - }, |
15 | | - async dismiss() { |
16 | | - await rpc.call('devtoolskit:internal:logs:remove', entry.id) |
17 | | - }, |
| 4 | +export function createClientLogsClient(rpc: DevToolsRpcClient): DevToolsLogsClient { |
| 5 | + const buffer: (() => Promise<void>)[] = [] |
| 6 | + let flushing: Promise<void> | undefined |
| 7 | + |
| 8 | + async function flush() { |
| 9 | + if (rpc.isTrusted !== true) |
| 10 | + return |
| 11 | + if (flushing === undefined) { |
| 12 | + // eslint-disable-next-line no-async-promise-executor |
| 13 | + flushing = new Promise(async (resolve) => { |
| 14 | + while (buffer.length > 0) { |
| 15 | + const op = buffer.shift()! |
| 16 | + await op() |
| 17 | + } |
| 18 | + resolve() |
| 19 | + }) |
| 20 | + } |
| 21 | + return flushing |
18 | 22 | } |
19 | | -} |
20 | 23 |
|
21 | | -export function createClientLogsClient(rpc: DevToolsRpcClient): DevToolsLogsClient { |
| 24 | + async function enqueue<T>(op: () => Promise<T>): Promise<T> { |
| 25 | + if (rpc.isTrusted === true && buffer.length !== 0) |
| 26 | + await flush() |
| 27 | + |
| 28 | + if (rpc.isTrusted === true && buffer.length === 0) |
| 29 | + return await op() |
| 30 | + |
| 31 | + return new Promise<T>((resolve) => { |
| 32 | + buffer.push(async () => { |
| 33 | + const result = await op() |
| 34 | + resolve(result) |
| 35 | + }) |
| 36 | + }) |
| 37 | + } |
| 38 | + |
| 39 | + rpc.events.on('rpc:is-trusted:updated', (isTrusted) => { |
| 40 | + if (isTrusted && buffer.length > 0) |
| 41 | + flush() |
| 42 | + }) |
| 43 | + |
22 | 44 | return { |
23 | | - async add(input: DevToolsLogEntryInput): Promise<DevToolsLogHandle> { |
24 | | - const entry = await rpc.call('devtoolskit:internal:logs:add', input) |
25 | | - return createRpcHandle(rpc, entry) |
| 45 | + add(input: DevToolsLogEntryInput): Promise<DevToolsLogHandle> { |
| 46 | + return enqueue(async () => { |
| 47 | + let entry = await rpc.call('devtoolskit:internal:logs:add', input) |
| 48 | + return { |
| 49 | + get entry() { return entry }, |
| 50 | + get id() { return entry.id }, |
| 51 | + async update(patch: Partial<DevToolsLogEntryInput>) { |
| 52 | + const updated = await rpc.call('devtoolskit:internal:logs:update', entry.id, patch) |
| 53 | + if (updated) |
| 54 | + entry = updated |
| 55 | + return updated ?? undefined |
| 56 | + }, |
| 57 | + async dismiss() { |
| 58 | + await rpc.call('devtoolskit:internal:logs:remove', entry.id) |
| 59 | + }, |
| 60 | + } |
| 61 | + }) |
26 | 62 | }, |
27 | | - async remove(id: string): Promise<void> { |
28 | | - await rpc.call('devtoolskit:internal:logs:remove', id) |
| 63 | + remove(id: string): Promise<void> { |
| 64 | + return enqueue(() => rpc.call('devtoolskit:internal:logs:remove', id)) |
29 | 65 | }, |
30 | | - async clear(): Promise<void> { |
31 | | - await rpc.call('devtoolskit:internal:logs:clear') |
| 66 | + clear(): Promise<void> { |
| 67 | + return enqueue(() => rpc.call('devtoolskit:internal:logs:clear')) |
32 | 68 | }, |
33 | 69 | } |
34 | 70 | } |
0 commit comments