rag-context-optimizer / frontend /node_modules /next /dist /esm /server /app-render /app-render-prerender-utils.js
| import { InvariantError } from '../../shared/lib/invariant-error'; | |
| /** | |
| * This is a utility function to make scheduling sequential tasks that run back to back easier. | |
| * We schedule on the same queue (setImmediate) at the same time to ensure no other events can sneak in between. | |
| */ export function prerenderAndAbortInSequentialTasks(prerender, abort) { | |
| if (process.env.NEXT_RUNTIME === 'edge') { | |
| throw Object.defineProperty(new InvariantError('`prerenderAndAbortInSequentialTasks` should not be called in edge runtime.'), "__NEXT_ERROR_CODE", { | |
| value: "E538", | |
| enumerable: false, | |
| configurable: true | |
| }); | |
| } else { | |
| return new Promise((resolve, reject)=>{ | |
| let pendingResult; | |
| setImmediate(()=>{ | |
| try { | |
| pendingResult = prerender(); | |
| pendingResult.catch(()=>{}); | |
| } catch (err) { | |
| reject(err); | |
| } | |
| }); | |
| setImmediate(()=>{ | |
| abort(); | |
| resolve(pendingResult); | |
| }); | |
| }); | |
| } | |
| } | |
| /** | |
| * Like `prerenderAndAbortInSequentialTasks`, but with another task between `prerender` and `abort`, | |
| * which allows us to move a part of the render into a separate task. | |
| */ export function prerenderAndAbortInSequentialTasksWithStages(prerender, advanceStage, abort) { | |
| if (process.env.NEXT_RUNTIME === 'edge') { | |
| throw Object.defineProperty(new InvariantError('`prerenderAndAbortInSequentialTasksWithStages` should not be called in edge runtime.'), "__NEXT_ERROR_CODE", { | |
| value: "E778", | |
| enumerable: false, | |
| configurable: true | |
| }); | |
| } else { | |
| return new Promise((resolve, reject)=>{ | |
| let pendingResult; | |
| setImmediate(()=>{ | |
| try { | |
| pendingResult = prerender(); | |
| pendingResult.catch(()=>{}); | |
| } catch (err) { | |
| reject(err); | |
| } | |
| }); | |
| setImmediate(()=>{ | |
| advanceStage(); | |
| }); | |
| setImmediate(()=>{ | |
| abort(); | |
| resolve(pendingResult); | |
| }); | |
| }); | |
| } | |
| } | |
| // React's RSC prerender function will emit an incomplete flight stream when using `prerender`. If the connection | |
| // closes then whatever hanging chunks exist will be errored. This is because prerender (an experimental feature) | |
| // has not yet implemented a concept of resume. For now we will simulate a paused connection by wrapping the stream | |
| // in one that doesn't close even when the underlying is complete. | |
| export class ReactServerResult { | |
| constructor(stream){ | |
| this._stream = stream; | |
| } | |
| tee() { | |
| if (this._stream === null) { | |
| throw Object.defineProperty(new Error('Cannot tee a ReactServerResult that has already been consumed'), "__NEXT_ERROR_CODE", { | |
| value: "E106", | |
| enumerable: false, | |
| configurable: true | |
| }); | |
| } | |
| const tee = this._stream.tee(); | |
| this._stream = tee[0]; | |
| return tee[1]; | |
| } | |
| consume() { | |
| if (this._stream === null) { | |
| throw Object.defineProperty(new Error('Cannot consume a ReactServerResult that has already been consumed'), "__NEXT_ERROR_CODE", { | |
| value: "E470", | |
| enumerable: false, | |
| configurable: true | |
| }); | |
| } | |
| const stream = this._stream; | |
| this._stream = null; | |
| return stream; | |
| } | |
| } | |
| export async function createReactServerPrerenderResult(underlying) { | |
| const chunks = []; | |
| const { prelude } = await underlying; | |
| const reader = prelude.getReader(); | |
| while(true){ | |
| const { done, value } = await reader.read(); | |
| if (done) { | |
| return new ReactServerPrerenderResult(chunks); | |
| } else { | |
| chunks.push(value); | |
| } | |
| } | |
| } | |
| export async function createReactServerPrerenderResultFromRender(underlying) { | |
| const chunks = []; | |
| const reader = underlying.getReader(); | |
| while(true){ | |
| const { done, value } = await reader.read(); | |
| if (done) { | |
| break; | |
| } else { | |
| chunks.push(value); | |
| } | |
| } | |
| return new ReactServerPrerenderResult(chunks); | |
| } | |
| export class ReactServerPrerenderResult { | |
| assertChunks(expression) { | |
| if (this._chunks === null) { | |
| throw Object.defineProperty(new InvariantError(`Cannot \`${expression}\` on a ReactServerPrerenderResult that has already been consumed.`), "__NEXT_ERROR_CODE", { | |
| value: "E593", | |
| enumerable: false, | |
| configurable: true | |
| }); | |
| } | |
| return this._chunks; | |
| } | |
| consumeChunks(expression) { | |
| const chunks = this.assertChunks(expression); | |
| this.consume(); | |
| return chunks; | |
| } | |
| consume() { | |
| this._chunks = null; | |
| } | |
| constructor(chunks){ | |
| this._chunks = chunks; | |
| } | |
| asUnclosingStream() { | |
| const chunks = this.assertChunks('asUnclosingStream()'); | |
| return createUnclosingStream(chunks); | |
| } | |
| consumeAsUnclosingStream() { | |
| const chunks = this.consumeChunks('consumeAsUnclosingStream()'); | |
| return createUnclosingStream(chunks); | |
| } | |
| asStream() { | |
| const chunks = this.assertChunks('asStream()'); | |
| return createClosingStream(chunks); | |
| } | |
| consumeAsStream() { | |
| const chunks = this.consumeChunks('consumeAsStream()'); | |
| return createClosingStream(chunks); | |
| } | |
| } | |
| function createUnclosingStream(chunks) { | |
| let i = 0; | |
| return new ReadableStream({ | |
| async pull (controller) { | |
| if (i < chunks.length) { | |
| controller.enqueue(chunks[i++]); | |
| } | |
| // we intentionally keep the stream open. The consumer will clear | |
| // out chunks once finished and the remaining memory will be GC'd | |
| // when this object goes out of scope | |
| } | |
| }); | |
| } | |
| function createClosingStream(chunks) { | |
| let i = 0; | |
| return new ReadableStream({ | |
| async pull (controller) { | |
| if (i < chunks.length) { | |
| controller.enqueue(chunks[i++]); | |
| } else { | |
| controller.close(); | |
| } | |
| } | |
| }); | |
| } | |
| export async function processPrelude(unprocessedPrelude) { | |
| const [prelude, peek] = unprocessedPrelude.tee(); | |
| const reader = peek.getReader(); | |
| const firstResult = await reader.read(); | |
| reader.cancel(); | |
| const preludeIsEmpty = firstResult.done === true; | |
| return { | |
| prelude, | |
| preludeIsEmpty | |
| }; | |
| } | |
| //# sourceMappingURL=app-render-prerender-utils.js.map |