Fix memory leak in dev server

This commit is contained in:
2026-10-16 14:25:18 +01:00
parent 3d0771f2d0
commit 5dc783fe97
36 changed files with 642 additions and 406 deletions
+15 -1
View File
@@ -77,8 +77,16 @@ export default async function genWebHTML({ component: Main, pageProps, bundledMa
let htmlBody;
let render_error;
let has_render_error = false;
const render_timeout_ms = global.BUNEXT_CONFIG.ssr_render_timeout_ms ||
AppData["DefaultSSRRenderTimeoutMs"];
// Without a deadline, a Suspense boundary that never settles keeps the
// request (and its whole render tree) alive forever. The timer is
// cleared once the render ends so finished requests don't linger.
const render_abort = new AbortController();
const render_timeout = setTimeout(() => render_abort.abort(new RenderTimeoutError(`Page render timed out after ${render_timeout_ms}ms`)), render_timeout_ms);
try {
const stream = await renderToReadableStream(final_component, {
signal: render_abort.signal,
onError(error) {
if (error?.message?.includes('unique "key" prop'))
return;
@@ -86,12 +94,16 @@ export default async function genWebHTML({ component: Main, pageProps, bundledMa
has_render_error = true;
render_error = error;
}
original_console.error(error);
// A timeout has no useful stack; it's logged upstream.
if (!(error instanceof RenderTimeoutError)) {
original_console.error(error);
}
},
});
htmlBody = await new Response(stream).text();
}
finally {
clearTimeout(render_timeout);
restoreConsole();
}
// A component crash during SSR must surface as a proper error (handled
@@ -103,6 +115,8 @@ export default async function genWebHTML({ component: Main, pageProps, bundledMa
html += htmlBody;
return html;
}
class RenderTimeoutError extends Error {
}
let original_console = console;
let silenced_renders = 0;
/**