Merge remote-tracking branch 'origin/zack/ssg-3' into ali/react

This commit is contained in:
Alistair Smith
2025-09-09 18:36:50 -07:00
782 changed files with 25631 additions and 13796 deletions

View File

@@ -140,64 +140,9 @@ export async function render(
...responseOptions,
});
} else {
// FIXME: this is bad and could be done way better
// FIXME: why are we even doing stream stuff is `streaming=false`, is there a way to do RSC without stream
// Set up the render abort handler for non-streaming mode
if (als) {
const store = als.getStore();
if (store) {
/*
store.renderAbort = (path: string, params: Record<string, any> | null) => {
// Create the abort error
const abortError = new (globalThis as any).RenderAbortError(path, params);
// Abort the current render
signal.aborted = abortError;
signal.abort(abortError);
rscPayload.destroy(abortError);
throw abortError;
};
*/
}
}
// Buffer the entire response and return it all at once
const htmlStream = renderToHtml(rscPayload, meta.modules, signal);
const chunks: Uint8Array[] = [];
const reader = htmlStream.getReader();
try {
let keepGoing = true;
do {
const { done, value } = await reader.read();
// Check if the render was aborted with an error
if (signal.aborted) {
// For some reason in react-server-dom the `stream.on("error")`
// handler creates a new Error???
if (signal.aborted.message !== "Connection closed.") {
// For other errors, we can handle them here or re-throw
throw signal.aborted;
}
}
keepGoing = !done;
if (!done) {
chunks.push(value);
}
} while (keepGoing);
} finally {
reader.releaseLock();
}
// Combine all chunks into a single response
const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);
const result = new Uint8Array(totalLength);
let offset = 0;
for (const chunk of chunks) {
result.set(chunk, offset);
offset += chunk.length;
}
const result = await htmlStream.bytes();
const opts = als?.getStore()?.responseOptions ?? { headers: {} };
const { headers, ...response_options } = opts;

View File

@@ -85,15 +85,7 @@ export function renderToHtml(
stream = new RscInjectionStream(rscPayload, controller);
pipe(stream);
// Promise resolved after all data is combined.
//
// We need to catch this or otherwise it results in unhandled rejection, I
// think this is a problem with `type: "direct"` as it does not happen
// when that line is commented out.
//
// This is fine because the actual error will come in cancel or onError callback elsewhere
return stream.finished.catch(() => {});
// return stream.finished;
return stream.finished;
},
cancel(err) {
if (!signal.aborted) {
@@ -169,7 +161,7 @@ class RscInjectionStream extends EventEmitter implements NodeJS.WritableStream {
const { resolve, promise, reject } = Promise.withResolvers<void>();
this.finished = promise;
this.finalize = resolve;
this.finalize = x => (controller.close(), resolve(x));
this.reject = reject;
rscPayload.on("data", this.writeRscData.bind(this));