create project
This commit is contained in:
288
kitabcitab/node_modules/next/dist/server/node-web-streams-helper.js
generated
vendored
Normal file
288
kitabcitab/node_modules/next/dist/server/node-web-streams-helper.js
generated
vendored
Normal file
@@ -0,0 +1,288 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.encodeText = encodeText;
|
||||
exports.decodeText = decodeText;
|
||||
exports.readableStreamTee = readableStreamTee;
|
||||
exports.chainStreams = chainStreams;
|
||||
exports.streamFromArray = streamFromArray;
|
||||
exports.streamToString = streamToString;
|
||||
exports.createBufferedTransformStream = createBufferedTransformStream;
|
||||
exports.createInsertedHTMLStream = createInsertedHTMLStream;
|
||||
exports.renderToInitialStream = renderToInitialStream;
|
||||
exports.createDeferredSuffixStream = createDeferredSuffixStream;
|
||||
exports.createInlineDataStream = createInlineDataStream;
|
||||
exports.createSuffixStream = createSuffixStream;
|
||||
exports.createRootLayoutValidatorStream = createRootLayoutValidatorStream;
|
||||
exports.continueFromInitialStream = continueFromInitialStream;
|
||||
var _nonNullable = require("../lib/non-nullable");
|
||||
const queueTask = process.env.NEXT_RUNTIME === "edge" ? globalThis.setTimeout : setImmediate;
|
||||
function encodeText(input) {
|
||||
return new TextEncoder().encode(input);
|
||||
}
|
||||
function decodeText(input, textDecoder) {
|
||||
return textDecoder ? textDecoder.decode(input, {
|
||||
stream: true
|
||||
}) : new TextDecoder().decode(input);
|
||||
}
|
||||
function readableStreamTee(readable) {
|
||||
const transformStream = new TransformStream();
|
||||
const transformStream2 = new TransformStream();
|
||||
const writer = transformStream.writable.getWriter();
|
||||
const writer2 = transformStream2.writable.getWriter();
|
||||
const reader = readable.getReader();
|
||||
function read() {
|
||||
reader.read().then(({ done , value })=>{
|
||||
if (done) {
|
||||
writer.close();
|
||||
writer2.close();
|
||||
return;
|
||||
}
|
||||
writer.write(value);
|
||||
writer2.write(value);
|
||||
read();
|
||||
});
|
||||
}
|
||||
read();
|
||||
return [
|
||||
transformStream.readable,
|
||||
transformStream2.readable
|
||||
];
|
||||
}
|
||||
function chainStreams(streams) {
|
||||
const { readable , writable } = new TransformStream();
|
||||
let promise = Promise.resolve();
|
||||
for(let i = 0; i < streams.length; ++i){
|
||||
promise = promise.then(()=>streams[i].pipeTo(writable, {
|
||||
preventClose: i + 1 < streams.length
|
||||
}));
|
||||
}
|
||||
return readable;
|
||||
}
|
||||
function streamFromArray(strings) {
|
||||
// Note: we use a TransformStream here instead of instantiating a ReadableStream
|
||||
// because the built-in ReadableStream polyfill runs strings through TextEncoder.
|
||||
const { readable , writable } = new TransformStream();
|
||||
const writer = writable.getWriter();
|
||||
strings.forEach((str)=>writer.write(encodeText(str)));
|
||||
writer.close();
|
||||
return readable;
|
||||
}
|
||||
async function streamToString(stream) {
|
||||
const reader = stream.getReader();
|
||||
const textDecoder = new TextDecoder();
|
||||
let bufferedString = "";
|
||||
while(true){
|
||||
const { done , value } = await reader.read();
|
||||
if (done) {
|
||||
return bufferedString;
|
||||
}
|
||||
bufferedString += decodeText(value, textDecoder);
|
||||
}
|
||||
}
|
||||
function createBufferedTransformStream(transform = (v)=>v) {
|
||||
let bufferedString = "";
|
||||
let pendingFlush = null;
|
||||
const flushBuffer = (controller)=>{
|
||||
if (!pendingFlush) {
|
||||
pendingFlush = new Promise((resolve)=>{
|
||||
setTimeout(async ()=>{
|
||||
const buffered = await transform(bufferedString);
|
||||
controller.enqueue(encodeText(buffered));
|
||||
bufferedString = "";
|
||||
pendingFlush = null;
|
||||
resolve();
|
||||
}, 0);
|
||||
});
|
||||
}
|
||||
return pendingFlush;
|
||||
};
|
||||
const textDecoder = new TextDecoder();
|
||||
return new TransformStream({
|
||||
transform (chunk, controller) {
|
||||
bufferedString += decodeText(chunk, textDecoder);
|
||||
flushBuffer(controller);
|
||||
},
|
||||
flush () {
|
||||
if (pendingFlush) {
|
||||
return pendingFlush;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
function createInsertedHTMLStream(getServerInsertedHTML) {
|
||||
return new TransformStream({
|
||||
async transform (chunk, controller) {
|
||||
const insertedHTMLChunk = encodeText(await getServerInsertedHTML());
|
||||
controller.enqueue(insertedHTMLChunk);
|
||||
controller.enqueue(chunk);
|
||||
}
|
||||
});
|
||||
}
|
||||
function renderToInitialStream({ ReactDOMServer , element , streamOptions }) {
|
||||
return ReactDOMServer.renderToReadableStream(element, streamOptions);
|
||||
}
|
||||
function createHeadInsertionTransformStream(insert) {
|
||||
let inserted = false;
|
||||
let freezing = false;
|
||||
return new TransformStream({
|
||||
async transform (chunk, controller) {
|
||||
// While react is flushing chunks, we don't apply insertions
|
||||
if (freezing) {
|
||||
controller.enqueue(chunk);
|
||||
return;
|
||||
}
|
||||
const insertion = await insert();
|
||||
if (inserted) {
|
||||
controller.enqueue(encodeText(insertion));
|
||||
controller.enqueue(chunk);
|
||||
freezing = true;
|
||||
} else {
|
||||
const content = decodeText(chunk);
|
||||
const index = content.indexOf("</head>");
|
||||
if (index !== -1) {
|
||||
const insertedHeadContent = content.slice(0, index) + insertion + content.slice(index);
|
||||
controller.enqueue(encodeText(insertedHeadContent));
|
||||
freezing = true;
|
||||
inserted = true;
|
||||
}
|
||||
}
|
||||
if (!inserted) {
|
||||
controller.enqueue(chunk);
|
||||
} else {
|
||||
queueTask(()=>{
|
||||
freezing = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
function createDeferredSuffixStream(suffix) {
|
||||
let suffixFlushed = false;
|
||||
let suffixFlushTask = null;
|
||||
return new TransformStream({
|
||||
transform (chunk, controller) {
|
||||
controller.enqueue(chunk);
|
||||
if (!suffixFlushed && suffix) {
|
||||
suffixFlushed = true;
|
||||
suffixFlushTask = new Promise((res)=>{
|
||||
// NOTE: streaming flush
|
||||
// Enqueue suffix part before the major chunks are enqueued so that
|
||||
// suffix won't be flushed too early to interrupt the data stream
|
||||
setTimeout(()=>{
|
||||
controller.enqueue(encodeText(suffix));
|
||||
res();
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
flush (controller) {
|
||||
if (suffixFlushTask) return suffixFlushTask;
|
||||
if (!suffixFlushed && suffix) {
|
||||
suffixFlushed = true;
|
||||
controller.enqueue(encodeText(suffix));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
function createInlineDataStream(dataStream) {
|
||||
let dataStreamFinished = null;
|
||||
return new TransformStream({
|
||||
transform (chunk, controller) {
|
||||
controller.enqueue(chunk);
|
||||
if (!dataStreamFinished) {
|
||||
const dataStreamReader = dataStream.getReader();
|
||||
// NOTE: streaming flush
|
||||
// We are buffering here for the inlined data stream because the
|
||||
// "shell" stream might be chunkenized again by the underlying stream
|
||||
// implementation, e.g. with a specific high-water mark. To ensure it's
|
||||
// the safe timing to pipe the data stream, this extra tick is
|
||||
// necessary.
|
||||
dataStreamFinished = new Promise((res)=>setTimeout(async ()=>{
|
||||
try {
|
||||
while(true){
|
||||
const { done , value } = await dataStreamReader.read();
|
||||
if (done) {
|
||||
return res();
|
||||
}
|
||||
controller.enqueue(value);
|
||||
}
|
||||
} catch (err) {
|
||||
controller.error(err);
|
||||
}
|
||||
res();
|
||||
}, 0));
|
||||
}
|
||||
},
|
||||
flush () {
|
||||
if (dataStreamFinished) {
|
||||
return dataStreamFinished;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
function createSuffixStream(suffix) {
|
||||
return new TransformStream({
|
||||
flush (controller) {
|
||||
if (suffix) {
|
||||
controller.enqueue(encodeText(suffix));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
function createRootLayoutValidatorStream(assetPrefix = "", getTree) {
|
||||
let foundHtml = false;
|
||||
let foundBody = false;
|
||||
return new TransformStream({
|
||||
async transform (chunk, controller) {
|
||||
if (!foundHtml || !foundBody) {
|
||||
const content = decodeText(chunk);
|
||||
if (!foundHtml && content.includes("<html")) {
|
||||
foundHtml = true;
|
||||
}
|
||||
if (!foundBody && content.includes("<body")) {
|
||||
foundBody = true;
|
||||
}
|
||||
}
|
||||
controller.enqueue(chunk);
|
||||
},
|
||||
flush (controller) {
|
||||
const missingTags = [
|
||||
foundHtml ? null : "html",
|
||||
foundBody ? null : "body",
|
||||
].filter(_nonNullable.nonNullable);
|
||||
if (missingTags.length > 0) {
|
||||
controller.enqueue(encodeText(`<script>self.__next_root_layout_missing_tags_error=${JSON.stringify({
|
||||
missingTags,
|
||||
assetPrefix: assetPrefix ?? "",
|
||||
tree: getTree()
|
||||
})}</script>`));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
async function continueFromInitialStream(renderStream, { suffix , dataStream , generateStaticHTML , getServerInsertedHTML , serverInsertedHTMLToHead , validateRootLayout }) {
|
||||
const closeTag = "</body></html>";
|
||||
const suffixUnclosed = suffix ? suffix.split(closeTag)[0] : null;
|
||||
if (generateStaticHTML) {
|
||||
await renderStream.allReady;
|
||||
}
|
||||
const transforms = [
|
||||
createBufferedTransformStream(),
|
||||
getServerInsertedHTML && !serverInsertedHTMLToHead ? createInsertedHTMLStream(getServerInsertedHTML) : null,
|
||||
suffixUnclosed != null ? createDeferredSuffixStream(suffixUnclosed) : null,
|
||||
dataStream ? createInlineDataStream(dataStream) : null,
|
||||
suffixUnclosed != null ? createSuffixStream(closeTag) : null,
|
||||
createHeadInsertionTransformStream(async ()=>{
|
||||
// TODO-APP: Insert server side html to end of head in app layout rendering, to avoid
|
||||
// hydration errors. Remove this once it's ready to be handled by react itself.
|
||||
const serverInsertedHTML = getServerInsertedHTML && serverInsertedHTMLToHead ? await getServerInsertedHTML() : "";
|
||||
return serverInsertedHTML;
|
||||
}),
|
||||
validateRootLayout ? createRootLayoutValidatorStream(validateRootLayout.assetPrefix, validateRootLayout.getTree) : null,
|
||||
].filter(_nonNullable.nonNullable);
|
||||
return transforms.reduce((readable, transform)=>readable.pipeThrough(transform), renderStream);
|
||||
}
|
||||
|
||||
//# sourceMappingURL=node-web-streams-helper.js.map
|
||||
Reference in New Issue
Block a user