react-router
Version:
Declarative routing for React
79 lines (78 loc) • 2.42 kB
JavaScript
/**
* react-router v8.0.0
*
* Copyright (c) Remix Software Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE.md file in the root directory of this source tree.
*
* @license MIT
*/
//#region lib/rsc/html-stream/server.ts
const encoder = new TextEncoder();
const trailer = "</body></html>";
function injectRSCPayload(rscStream) {
let decoder = new TextDecoder();
let resolveFlightDataPromise;
let flightDataPromise = new Promise((resolve) => resolveFlightDataPromise = resolve);
let startedRSC = false;
let buffered = [];
let timeout = null;
function flushBufferedChunks(controller) {
for (let chunk of buffered) {
let buf = decoder.decode(chunk, { stream: true });
if (buf.endsWith(trailer)) buf = buf.slice(0, -14);
controller.enqueue(encoder.encode(buf));
}
buffered.length = 0;
timeout = null;
}
return new TransformStream({
transform(chunk, controller) {
buffered.push(chunk);
if (timeout) return;
timeout = setTimeout(async () => {
flushBufferedChunks(controller);
if (!startedRSC) {
startedRSC = true;
writeRSCStream(rscStream, controller).catch((err) => controller.error(err)).then(resolveFlightDataPromise);
}
}, 0);
},
async flush(controller) {
await flightDataPromise;
if (timeout) {
clearTimeout(timeout);
flushBufferedChunks(controller);
}
controller.enqueue(encoder.encode("</body></html>"));
}
});
}
async function writeRSCStream(rscStream, controller) {
let decoder = new TextDecoder("utf-8", { fatal: true });
const reader = rscStream.getReader();
try {
let read;
while ((read = await reader.read()) && !read.done) {
const chunk = read.value;
try {
writeChunk(JSON.stringify(decoder.decode(chunk, { stream: true })), controller);
} catch (e) {
writeChunk(`Uint8Array.from(atob(${JSON.stringify(btoa(String.fromCodePoint(...chunk)))}), m => m.codePointAt(0))`, controller);
}
}
} finally {
reader.releaseLock();
}
let remaining = decoder.decode();
if (remaining.length) writeChunk(JSON.stringify(remaining), controller);
}
function writeChunk(chunk, controller) {
controller.enqueue(encoder.encode(`<script>${escapeScript(`(self.__FLIGHT_DATA||=[]).push(${chunk})`)}<\/script>`));
}
function escapeScript(script) {
return script.replace(/<!--/g, "<\\!--").replace(/<\/(script)/gi, "</\\$1");
}
//#endregion
export { injectRSCPayload };