File size: 2,384 Bytes
b91e262 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | import { createBufferedTransformStream } from '../stream-utils/node-web-streams-helper'
import {
HMR_MESSAGE_SENT_TO_BROWSER,
type HmrMessageSentToBrowser,
} from './hot-reloader-types'
export interface ReactDebugChannelForBrowser {
readonly readable: ReadableStream<Uint8Array>
// Might also get a writable stream as return channel in the future.
}
const reactDebugChannelsByHtmlRequestId = new Map<
string,
ReactDebugChannelForBrowser
>()
export function connectReactDebugChannel(
requestId: string,
debugChannel: ReactDebugChannelForBrowser,
sendToClient: (message: HmrMessageSentToBrowser) => void
) {
const reader = debugChannel.readable
.pipeThrough(
// We're sending the chunks in batches to reduce overhead in the browser.
createBufferedTransformStream({ maxBufferByteLength: 128 * 1024 })
)
.getReader()
const stop = () => {
sendToClient({
type: HMR_MESSAGE_SENT_TO_BROWSER.REACT_DEBUG_CHUNK,
requestId,
chunk: null,
})
}
const onError = (err: unknown) => {
console.error(new Error('React debug channel stream error', { cause: err }))
stop()
}
const progress = (entry: ReadableStreamReadResult<Uint8Array>) => {
if (entry.done) {
stop()
} else {
sendToClient({
type: HMR_MESSAGE_SENT_TO_BROWSER.REACT_DEBUG_CHUNK,
requestId,
chunk: entry.value,
})
reader.read().then(progress, onError)
}
}
reader.read().then(progress, onError)
}
export function connectReactDebugChannelForHtmlRequest(
htmlRequestId: string,
sendToClient: (message: HmrMessageSentToBrowser) => void
) {
const debugChannel = reactDebugChannelsByHtmlRequestId.get(htmlRequestId)
if (!debugChannel) {
return
}
reactDebugChannelsByHtmlRequestId.delete(htmlRequestId)
connectReactDebugChannel(htmlRequestId, debugChannel, sendToClient)
}
export function setReactDebugChannelForHtmlRequest(
htmlRequestId: string,
debugChannel: ReactDebugChannelForBrowser
) {
// TODO: Clean up after a timeout, in case the client never connects, e.g.
// when CURL'ing the page, or loading the page with JavaScript disabled etc.
reactDebugChannelsByHtmlRequestId.set(htmlRequestId, debugChannel)
}
export function deleteReactDebugChannelForHtmlRequest(htmlRequestId: string) {
reactDebugChannelsByHtmlRequestId.delete(htmlRequestId)
}
|