From 8ad81738303203518a281a326d1c7b780b1e125d Mon Sep 17 00:00:00 2001 From: eps1lon Date: Wed, 22 May 2024 23:39:02 +0200 Subject: [PATCH] Only use temporary references where necessary --- .../src/server/app-render/action-handler.ts | 32 +++++++++++++------ .../next/src/server/app-render/app-render.tsx | 11 ++++--- .../next/src/server/app-render/encryption.ts | 5 +-- .../server/app-render/react-server.node.ts | 1 + 4 files changed, 31 insertions(+), 18 deletions(-) diff --git a/packages/next/src/server/app-render/action-handler.ts b/packages/next/src/server/app-render/action-handler.ts index 9056f02ec2de02..ba59f88a719eef 100644 --- a/packages/next/src/server/app-render/action-handler.ts +++ b/packages/next/src/server/app-render/action-handler.ts @@ -379,7 +379,6 @@ export async function handleAction({ requestStore, serverActions, ctx, - temporaryReferences, }: { req: BaseNextRequest res: BaseNextResponse @@ -390,7 +389,6 @@ export async function handleAction({ requestStore: RequestStore serverActions?: ServerActionsConfig ctx: AppRenderContext - temporaryReferences: unknown }): Promise< | undefined | { @@ -400,6 +398,7 @@ export async function handleAction({ type: 'done' result: RenderResult | undefined formState?: any + temporaryReferences: unknown } > { const contentType = req.headers['content-type'] @@ -515,6 +514,7 @@ export async function handleAction({ // if the page was not revalidated, we can skip the rendering the flight tree skipFlight: !staticGenerationStore.pathWasRevalidated, }), + temporaryReferences: undefined, } } @@ -556,6 +556,7 @@ export async function handleAction({ ctx.renderOpts.basePath, staticGenerationStore ), + temporaryReferences: undefined, } } } @@ -569,10 +570,16 @@ export async function handleAction({ isWebNextRequest(req) ) { // Use react-server-dom-webpack/server.edge - const { decodeReply, decodeAction, decodeFormState } = ComponentMod + const { + createTemporaryReferenceSet, + decodeReply, + decodeAction, + decodeFormState, + } = ComponentMod if (!req.body) { throw new Error('invariant: Missing request body.') } + const temporaryReferences = createTemporaryReferenceSet() // TODO: add body limit @@ -581,7 +588,7 @@ export async function handleAction({ const formData = await req.request.formData() if (isFetchAction) { bound = await decodeReply(formData, serverModuleMap, { - temporaryReferences: temporaryReferences, + temporaryReferences, }) } else { const action = await decodeAction(formData, serverModuleMap) @@ -622,11 +629,11 @@ export async function handleAction({ if (isURLEncodedAction) { const formData = formDataFromSearchQueryString(actionData) bound = await decodeReply(formData, serverModuleMap, { - temporaryReferences: temporaryReferences, + temporaryReferences, }) } else { bound = await decodeReply(actionData, serverModuleMap, { - temporaryReferences: temporaryReferences, + temporaryReferences, }) } } @@ -638,11 +645,13 @@ export async function handleAction({ ) { // Use react-server-dom-webpack/server.node which supports streaming const { + createTemporaryReferenceSet, decodeReply, decodeReplyFromBusboy, decodeAction, decodeFormState, } = require(`./react-server.node`) + const temporaryReferences = createTemporaryReferenceSet() const { Transform } = require('node:stream') as typeof import('node:stream') @@ -690,7 +699,7 @@ export async function handleAction({ body.pipe(busboy) bound = await decodeReplyFromBusboy(busboy, serverModuleMap, { - temporaryReferences: temporaryReferences, + temporaryReferences, }) } else { // React doesn't yet publish a busboy version of decodeAction @@ -748,11 +757,11 @@ export async function handleAction({ if (isURLEncodedAction) { const formData = formDataFromSearchQueryString(actionData) bound = await decodeReply(formData, serverModuleMap, { - temporaryReferences: temporaryReferences, + temporaryReferences, }) } else { bound = await decodeReply(actionData, serverModuleMap, { - temporaryReferences: temporaryReferences, + temporaryReferences, }) } } @@ -813,6 +822,7 @@ export async function handleAction({ type: 'done', result: actionResult, formState, + temporaryReferences: undefined, } } catch (err) { if (isRedirectError(err)) { @@ -839,6 +849,7 @@ export async function handleAction({ ctx.renderOpts.basePath, staticGenerationStore ), + temporaryReferences: undefined, } } @@ -856,6 +867,7 @@ export async function handleAction({ return { type: 'done', result: RenderResult.fromStatic(''), + temporaryReferences: undefined, } } else if (isNotFoundError(err)) { res.statusCode = 404 @@ -883,6 +895,7 @@ export async function handleAction({ actionResult: promise, asNotFound: true, }), + temporaryReferences: undefined, } } return { @@ -917,6 +930,7 @@ export async function handleAction({ skipFlight: !staticGenerationStore.pathWasRevalidated || actionWasForwarded, }), + temporaryReferences: undefined, } } diff --git a/packages/next/src/server/app-render/app-render.tsx b/packages/next/src/server/app-render/app-render.tsx index 7cf5a099e16c3b..c463f9f41bbd61 100644 --- a/packages/next/src/server/app-render/app-render.tsx +++ b/packages/next/src/server/app-render/app-render.tsx @@ -388,6 +388,7 @@ type RenderToStreamOptions = { asNotFound: boolean tree: LoaderTree formState: any + temporaryReferences: unknown } /** @@ -906,8 +907,6 @@ async function renderToHTMLOrFlightImpl( getTracer().getRootSpanAttributes()?.set('next.route', pagePath) - const temporaryReferences = ComponentMod.createTemporaryReferenceSet() - const renderToStream = getTracer().wrap( AppRenderSpan.getBodyResult, { @@ -961,7 +960,6 @@ async function renderToHTMLOrFlightImpl( { onError: serverComponentsErrorHandler, nonce, - temporaryReferences: temporaryReferences, } ) @@ -1294,7 +1292,6 @@ async function renderToHTMLOrFlightImpl( { onError: serverComponentsErrorHandler, nonce, - temporaryReferences: temporaryReferences, } ) @@ -1368,7 +1365,6 @@ async function renderToHTMLOrFlightImpl( requestStore, serverActions, ctx, - temporaryReferences, }) let formState: null | any = null @@ -1379,6 +1375,7 @@ async function renderToHTMLOrFlightImpl( asNotFound: true, tree: notFoundLoaderTree, formState, + temporaryReferences: undefined, }) return new RenderResult(response.stream, { metadata }) @@ -1400,6 +1397,10 @@ async function renderToHTMLOrFlightImpl( asNotFound: isNotFoundPath, tree: loaderTree, formState, + temporaryReferences: + actionRequestResult !== undefined + ? actionRequestResult.temporaryReferences + : undefined, }) // If we have pending revalidates, wait until they are all resolved. diff --git a/packages/next/src/server/app-render/encryption.ts b/packages/next/src/server/app-render/encryption.ts index 55813246f61c81..59ffb87369d35f 100644 --- a/packages/next/src/server/app-render/encryption.ts +++ b/packages/next/src/server/app-render/encryption.ts @@ -120,10 +120,7 @@ export async function decryptActionBoundArgs( // This extra step ensures that the server references are recovered. const serverModuleMap = getServerModuleMap() const transformed = await decodeReply( - await encodeReply(deserialized, { - // TODO: How is decryptActionBoundArgs used? Do we need to support temporary references here? - temporaryReferences: undefined, - }), + await encodeReply(deserialized), serverModuleMap ) diff --git a/packages/next/src/server/app-render/react-server.node.ts b/packages/next/src/server/app-render/react-server.node.ts index 404aa7a87a8827..29e42af3891f37 100644 --- a/packages/next/src/server/app-render/react-server.node.ts +++ b/packages/next/src/server/app-render/react-server.node.ts @@ -2,6 +2,7 @@ // eslint-disable-next-line import/no-extraneous-dependencies export { + createTemporaryReferenceSet, decodeReply, decodeReplyFromBusboy, decodeAction,