From 64359df4e8daa3e0ce01872673d321a0b80f2d2d Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Tue, 24 Sep 2024 12:53:25 -0700 Subject: [PATCH] fix: updated typescript types for React API's --- .../src/server/app-render/action-handler.ts | 32 ++++++--- .../next/src/server/app-render/app-render.tsx | 32 +++------ .../app-render/create-error-handler.tsx | 11 ++- .../stream-utils/node-web-streams-helper.ts | 2 +- packages/next/types/$$compiled.internal.d.ts | 71 ++++++++++++++++++- packages/next/types/react-dom.d.ts | 6 +- 6 files changed, 115 insertions(+), 39 deletions(-) diff --git a/packages/next/src/server/app-render/action-handler.ts b/packages/next/src/server/app-render/action-handler.ts index 95cdaccb48ae4..e793f08aef465 100644 --- a/packages/next/src/server/app-render/action-handler.ts +++ b/packages/next/src/server/app-render/action-handler.ts @@ -565,7 +565,8 @@ export async function handleAction({ 'Cache-Control', 'no-cache, no-store, max-age=0, must-revalidate' ) - let bound = [] + + let boundActionArguments: unknown[] = [] const { actionAsyncStorage } = ComponentMod @@ -618,14 +619,18 @@ export async function handleAction({ // TODO-APP: Add streaming support const formData = await req.request.formData() if (isFetchAction) { - bound = await decodeReply(formData, serverModuleMap) + boundActionArguments = await decodeReply(formData, serverModuleMap) } else { const action = await decodeAction(formData, serverModuleMap) if (typeof action === 'function') { // Only warn if it's a server action, otherwise skip for other post requests warnBadServerActionRequest() const actionReturnedState = await action() - formState = decodeFormState(actionReturnedState, formData) + formState = decodeFormState( + actionReturnedState, + formData, + serverModuleMap + ) } // Skip the fetch path @@ -657,9 +662,12 @@ export async function handleAction({ if (isURLEncodedAction) { const formData = formDataFromSearchQueryString(actionData) - bound = await decodeReply(formData, serverModuleMap) + boundActionArguments = await decodeReply(formData, serverModuleMap) } else { - bound = await decodeReply(actionData, serverModuleMap) + boundActionArguments = await decodeReply( + actionData, + serverModuleMap + ) } } } else if ( @@ -721,7 +729,10 @@ export async function handleAction({ body.pipe(busboy) - bound = await decodeReplyFromBusboy(busboy, serverModuleMap) + boundActionArguments = await decodeReplyFromBusboy( + busboy, + serverModuleMap + ) } else { // React doesn't yet publish a busboy version of decodeAction // so we polyfill the parsing of FormData. @@ -777,9 +788,12 @@ export async function handleAction({ if (isURLEncodedAction) { const formData = formDataFromSearchQueryString(actionData) - bound = await decodeReply(formData, serverModuleMap) + boundActionArguments = await decodeReply(formData, serverModuleMap) } else { - bound = await decodeReply(actionData, serverModuleMap) + boundActionArguments = await decodeReply( + actionData, + serverModuleMap + ) } } } else { @@ -817,7 +831,7 @@ export async function handleAction({ actionId! ] - const returnVal = await actionHandler.apply(null, bound) + const returnVal = await actionHandler.apply(null, boundActionArguments) // For form actions, we need to continue rendering the page. if (isFetchAction) { diff --git a/packages/next/src/server/app-render/app-render.tsx b/packages/next/src/server/app-render/app-render.tsx index 71252f1cd9f76..75259bbe79bbc 100644 --- a/packages/next/src/server/app-render/app-render.tsx +++ b/packages/next/src/server/app-render/app-render.tsx @@ -22,7 +22,7 @@ import type { DeepReadonly } from '../../shared/lib/deep-readonly' import type { BaseNextRequest, BaseNextResponse } from '../base-http' import type { IncomingHttpHeaders } from 'http' -import React, { type ErrorInfo, type JSX } from 'react' +import React, { type JSX } from 'react' import RenderResult, { type AppPageRenderResultMetadata, @@ -506,7 +506,6 @@ async function generateDynamicFlightRenderResult( ctx.clientReferenceManifest.clientModules, { onError, - nonce: ctx.nonce, } ) @@ -1380,7 +1379,6 @@ async function renderToStream( clientReferenceManifest.clientModules, { onError: serverComponentsErrorHandler, - nonce: ctx.nonce, } ) ) @@ -1588,7 +1586,6 @@ async function renderToStream( clientReferenceManifest.clientModules, { onError: serverComponentsErrorHandler, - nonce: ctx.nonce, } ) @@ -1829,7 +1826,7 @@ async function prerenderToStream( ctx, res.statusCode === 404 ) - function voidOnError() {} + ;( prerenderAsyncStorage.run( // The store to scope @@ -1840,9 +1837,8 @@ async function prerenderToStream( firstAttemptRSCPayload, clientReferenceManifest.clientModules, { - nonce: ctx.nonce, // This render will be thrown away so we don't need to track errors or postpones - onError: voidOnError, + onError: undefined, onPostpone: undefined, // we don't care to track postpones during the prospective render because we need // to always do a final render anyway @@ -1874,13 +1870,13 @@ async function prerenderToStream( } let reactServerIsDynamic = false - function onError(err: unknown, errorInfo: ErrorInfo) { + function onError(err: unknown) { if (err === abortReason || isPrerenderInterruptedError(err)) { reactServerIsDynamic = true return } - return serverComponentsErrorHandler(err, errorInfo) + return serverComponentsErrorHandler(err) } function onPostpone(reason: string) { @@ -1909,7 +1905,6 @@ async function prerenderToStream( finalAttemptRSCPayload, clientReferenceManifest.clientModules, { - nonce: ctx.nonce, onError, onPostpone, signal: flightController.signal, @@ -1938,13 +1933,13 @@ async function prerenderToStream( dynamicTracking, } let SSRIsDynamic = false - function SSROnError(err: unknown, errorInfo: unknown) { + function SSROnError(err: unknown) { if (err === abortReason || isPrerenderInterruptedError(err)) { SSRIsDynamic = true return } - return htmlRendererErrorHandler(err, errorInfo) + return htmlRendererErrorHandler(err) } function SSROnPostpone(reason: string) { @@ -2109,13 +2104,13 @@ async function prerenderToStream( let flightController = new AbortController() let reactServerIsDynamic = false - function onError(err: unknown, errorInfo: ErrorInfo) { + function onError(err: unknown) { if (err === abortReason || isPrerenderInterruptedError(err)) { reactServerIsDynamic = true return } - return serverComponentsErrorHandler(err, errorInfo) + return serverComponentsErrorHandler(err) } dynamicTracking = createDynamicTrackingState( @@ -2149,7 +2144,6 @@ async function prerenderToStream( firstAttemptRSCPayload, clientReferenceManifest.clientModules, { - nonce: ctx.nonce, onError, signal: flightController.signal, } @@ -2216,7 +2210,6 @@ async function prerenderToStream( finalAttemptRSCPayload, clientReferenceManifest.clientModules, { - nonce: ctx.nonce, onError, signal: flightController.signal, } @@ -2254,13 +2247,13 @@ async function prerenderToStream( dynamicTracking, } let SSRIsDynamic = false - function SSROnError(err: unknown, errorInfo: unknown) { + function SSROnError(err: unknown) { if (err === abortReason || isPrerenderInterruptedError(err)) { SSRIsDynamic = true return } - return htmlRendererErrorHandler(err, errorInfo) + return htmlRendererErrorHandler(err) } function SSROnPostpone(_: string) { // We don't really support postponing when PPR is off but since experimental react @@ -2364,7 +2357,6 @@ async function prerenderToStream( clientReferenceManifest.clientModules, { onError: serverComponentsErrorHandler, - nonce: ctx.nonce, } ) )) @@ -2535,7 +2527,6 @@ async function prerenderToStream( clientReferenceManifest.clientModules, { onError: serverComponentsErrorHandler, - nonce: ctx.nonce, } ) )) @@ -2678,7 +2669,6 @@ async function prerenderToStream( clientReferenceManifest.clientModules, { onError: serverComponentsErrorHandler, - nonce: ctx.nonce, } ) diff --git a/packages/next/src/server/app-render/create-error-handler.tsx b/packages/next/src/server/app-render/create-error-handler.tsx index 9db7cbbc49f18..10597355f73cb 100644 --- a/packages/next/src/server/app-render/create-error-handler.tsx +++ b/packages/next/src/server/app-render/create-error-handler.tsx @@ -10,7 +10,7 @@ declare global { var __next_log_error__: undefined | ((err: unknown) => void) } -type ErrorHandler = (err: unknown, errorInfo: unknown) => string | undefined +type ErrorHandler = (err: unknown, errorInfo?: unknown) => string | undefined export type DigestedError = Error & { digest: string } @@ -18,13 +18,18 @@ export function createFlightReactServerErrorHandler( dev: boolean, onReactServerRenderError: (err: any) => void ): ErrorHandler { - return (err: any, errorInfo: any) => { + return (err: any, errorInfo?: unknown) => { // If the error already has a digest, respect the original digest, // so it won't get re-generated into another new error. if (!err.digest) { // TODO-APP: look at using webcrypto instead. Requires a promise to be awaited. err.digest = stringHash( - err.message + (errorInfo?.stack || err.stack || '') + err.message + + (typeof errorInfo === 'object' && + errorInfo !== null && + 'stack' in errorInfo + ? errorInfo.stack + : err.stack || '') ).toString() } diff --git a/packages/next/src/server/stream-utils/node-web-streams-helper.ts b/packages/next/src/server/stream-utils/node-web-streams-helper.ts index dc9beea33b4e8..4e07dd231c6b0 100644 --- a/packages/next/src/server/stream-utils/node-web-streams-helper.ts +++ b/packages/next/src/server/stream-utils/node-web-streams-helper.ts @@ -195,7 +195,7 @@ export function renderToInitialFizzStream({ }: { ReactDOMServer: typeof import('react-dom/server.edge') element: React.ReactElement - streamOptions?: any + streamOptions?: Parameters[1] }): Promise { return getTracer().trace(AppRenderSpan.renderToReadableStream, async () => ReactDOMServer.renderToReadableStream(element, streamOptions) diff --git a/packages/next/types/$$compiled.internal.d.ts b/packages/next/types/$$compiled.internal.d.ts index 76832e459fb4e..e1ce41f978fda 100644 --- a/packages/next/types/$$compiled.internal.d.ts +++ b/packages/next/types/$$compiled.internal.d.ts @@ -27,9 +27,76 @@ declare module 'next/dist/compiled/react-dom/server.edge' declare module 'next/dist/compiled/browserslist' declare module 'react-server-dom-webpack/client' -declare module 'react-server-dom-webpack/server.edge' +declare module 'react-server-dom-webpack/server.edge' { + export function renderToReadableStream( + model: any, + webpackMap: { + readonly [id: string]: { + readonly id: string | number + readonly chunks: readonly string[] + readonly name: string + readonly async?: boolean + } + }, + options?: { + filterStackFrame?: (url: string, functionName: string) => boolean + onError?: (error: unknown) => void + onPostpone?: (reason: string) => void + signal?: AbortSignal + } + ): ReadableStream + + type ServerManifest = {} + + export function decodeReply( + body: string | FormData, + webpackMap: ServerManifest, + options?: { + temporaryReferences?: unknown + } + ): Promise + export function decodeAction( + body: FormData, + serverManifest: ServerManifest + ): Promise<() => T> | null + export function decodeFormState( + actionResult: S, + body: FormData, + serverManifest: ServerManifest + ): Promise + + export function registerServerReference( + reference: T, + id: string, + exportName: string | null + ): unknown + + export function createClientModuleProxy(moduleId: string): unknown +} declare module 'react-server-dom-webpack/server.node' -declare module 'react-server-dom-webpack/static.edge' +declare module 'react-server-dom-webpack/static.edge' { + export function prerender( + children: any, + webpackMap: { + readonly [id: string]: { + readonly id: string | number + readonly chunks: readonly string[] + readonly name: string + readonly async?: boolean + } + }, + options?: { + environmentName?: string | (() => string) + filterStackFrame?: (url: string, functionName: string) => boolean + identifierPrefix?: string + signal?: AbortSignal + onError?: (error: unknown) => void + onPostpone?: (reason: string) => void + } + ): Promise<{ + prelude: ReadableStream + }> +} declare module 'react-server-dom-webpack/client.edge' declare module 'VAR_MODULE_GLOBAL_ERROR' diff --git a/packages/next/types/react-dom.d.ts b/packages/next/types/react-dom.d.ts index 9b811922e4d55..d7151f6d52458 100644 --- a/packages/next/types/react-dom.d.ts +++ b/packages/next/types/react-dom.d.ts @@ -17,7 +17,7 @@ declare module 'react-dom/server.edge' { export type ResumeOptions = { nonce?: string signal?: AbortSignal - onError?: (error: unknown, errorInfo: unknown) => string | undefined + onError?: (error: unknown) => string | undefined onPostpone?: (reason: string) => void unstable_externalRuntimeSrc?: string | BootstrapScriptDescriptor } @@ -42,7 +42,7 @@ declare module 'react-dom/server.edge' { bootstrapModules?: Array progressiveChunkSize?: number signal?: AbortSignal - onError?: (error: unknown, errorInfo: unknown) => string | undefined + onError?: (error: unknown) => string | undefined onPostpone?: (reason: string) => void unstable_externalRuntimeSrc?: string | BootstrapScriptDescriptor importMap?: { @@ -94,7 +94,7 @@ declare module 'react-dom/static.edge' { bootstrapModules?: Array progressiveChunkSize?: number signal?: AbortSignal - onError?: (error: unknown, errorInfo: unknown) => string | undefined + onError?: (error: unknown) => string | undefined onPostpone?: (reason: string) => void unstable_externalRuntimeSrc?: string | BootstrapScriptDescriptor importMap?: {