From c5f34e8ada46ffa939b00a8b47a809913bba10a7 Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Thu, 27 Aug 2026 07:48:10 +0800 Subject: [PATCH] fix(inspector): preserve event stream replay order --- .../src/worker/inspection/network-store.ts | 29 +++---------------- .../inspector/tests/network.host.spec.ts | 11 +++++-- 2 files changed, 13 insertions(+), 27 deletions(-) diff --git a/packages/experimental/inspector/src/worker/inspection/network-store.ts b/packages/experimental/inspector/src/worker/inspection/network-store.ts index 581c0d2bad..db9caf7bbd 100644 --- a/packages/experimental/inspector/src/worker/inspection/network-store.ts +++ b/packages/experimental/inspector/src/worker/inspection/network-store.ts @@ -69,10 +69,7 @@ export type NetworkStoreEvent = } | { readonly type: 'request-evicted'; readonly requestKey: string } -type JournalNetworkEvent = Exclude -type ReplayableNetworkEvent = Exclude +type JournalNetworkEvent = Exclude interface CapturedRequest { readonly key: string @@ -140,26 +137,8 @@ export class NetworkStore implements InspectorRecordConsumer { * Read retained request lifecycle events. * @returns Events in observation order. */ - replay(): readonly ReplayableNetworkEvent[] { - const replay: ReplayableNetworkEvent[] = [] - for (const event of this.journal) { - replay.push(event) - if (event.type !== 'response-received' || event.mimeType !== 'text/event-stream') continue - const request = this.requests.get(event.requestKey) as CapturedRequest - const messages = new InspectorEventSourceParser().push(Buffer.concat(request.responseBody)) - let eventId = 0 - for (const message of messages) { - replay.push({ - type: 'event-source-message', - requestKey: request.key, - requestId: request.requestId, - timestampMs: event.timestampMs, - ...message, - eventId: String(++eventId), - }) - } - } - return replay + replay(): readonly JournalNetworkEvent[] { + return this.journal } /** @@ -274,7 +253,7 @@ export class NetworkStore implements InspectorRecordConsumer { const bytes = this.appendBody(request, 'response', data) const byteLength = bytes.byteLength for (const message of request.eventSourceParser?.push(bytes) ?? []) { - this.emit({ + this.publish({ type: 'event-source-message', requestKey: key, requestId: request.requestId, diff --git a/packages/experimental/inspector/tests/network.host.spec.ts b/packages/experimental/inspector/tests/network.host.spec.ts index f9fddf5799..69b34b440d 100644 --- a/packages/experimental/inspector/tests/network.host.spec.ts +++ b/packages/experimental/inspector/tests/network.host.spec.ts @@ -129,9 +129,16 @@ describe('Inspector Network domain', () => { .filter(call => call[0] === 'Network.eventSourceMessageReceived') .map(call => call[1] as unknown)) .toEqual([ - expect.objectContaining({ eventName: 'message', eventId: '1', data: 'first' }), - expect.objectContaining({ eventName: 'update', eventId: '2', data: 'second\nline' }), + expect.objectContaining({ timestamp: 0.003, eventName: 'message', eventId: '1', data: 'first' }), + expect.objectContaining({ timestamp: 0.004, eventName: 'update', eventId: '2', data: 'second\nline' }), ]) + expect(replay.mock.calls.map(call => String(call[0]))).toEqual([ + 'Network.requestWillBeSent', + 'Network.responseReceived', + 'Network.eventSourceMessageReceived', + 'Network.eventSourceMessageReceived', + 'Network.loadingFinished', + ]) }) it('bounds active request metadata and does not retain per-chunk events for replay', () => {