Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions types/react-dom/canary.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

import React = require("react");
import ReactDOM = require(".");
import { ErrorInfo } from "./client";

export {};

Expand All @@ -50,6 +51,50 @@ declare module "." {
function browser(reason?: string | (() => unknown)): BrowserUsable;
}

declare module "./server" {
interface RenderToPipeableStreamOptions {
/**
* A callback React calls when it recovers from `browser()` by leaving a
* Suspense fallback for the browser to replace.
*/
onBrowserBailout?: ((error: unknown, errorInfo: ErrorInfo) => void) | undefined;
}

interface RenderToReadableStreamOptions {
/**
* A callback React calls when it recovers from `browser()` by leaving a
* Suspense fallback for the browser to replace.
*/
onBrowserBailout?: ((error: unknown, errorInfo: ErrorInfo) => void) | undefined;
}

interface ResumeToPipeableStreamOptions {
/**
* A callback React calls when it recovers from `browser()` by leaving a
* Suspense fallback for the browser to replace.
*/
onBrowserBailout?: ((error: unknown, errorInfo: ErrorInfo) => void) | undefined;
}
}

declare module "./static" {
interface PrerenderOptions {
/**
* A callback React calls when it recovers from `browser()` by leaving a
* Suspense fallback for the browser to replace.
*/
onBrowserBailout?: ((error: unknown, errorInfo: ErrorInfo) => void) | undefined;
}

interface ResumeOptions {
/**
* A callback React calls when it recovers from `browser()` by leaving a
* Suspense fallback for the browser to replace.
*/
onBrowserBailout?: ((error: unknown, errorInfo: ErrorInfo) => void) | undefined;
}
}

declare module "react" {
interface RendererUsable<T> {
"react-dom/browser": BrowserUsable;
Expand Down
2 changes: 1 addition & 1 deletion types/react-dom/server.browser.d.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { renderToReadableStream, renderToStaticMarkup, renderToString } from "./server";
export { renderToReadableStream, renderToStaticMarkup, renderToString, resume, version } from "./server";
10 changes: 9 additions & 1 deletion types/react-dom/server.bun.d.ts
Original file line number Diff line number Diff line change
@@ -1 +1,9 @@
export { renderToReadableStream, renderToStaticMarkup, renderToString } from "./server";
export {
renderToPipeableStream,
renderToReadableStream,
renderToStaticMarkup,
renderToString,
resume,
resumeToPipeableStream,
version,
} from "./server";
39 changes: 33 additions & 6 deletions types/react-dom/server.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,25 @@ export interface BootstrapScriptDescriptor {
crossOrigin?: string | undefined;
}

/**
* The header content passed to `onHeaders` by `renderToPipeableStream`.
* Other server rendering APIs pass a `Headers` instance instead.
* React passes an empty object when there are no resource hints to send.
*/
export interface HeadersDescriptor {
Link?: string;
}

/**
* A nonce string, or an object with separate nonces for scripts and styles.
*/
export type NonceOption =
| string
| {
script?: string | undefined;
style?: string | undefined;
};

/**
* @see {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/script/type/importmap Import maps}
*/
Expand Down Expand Up @@ -62,7 +81,7 @@ export interface ReactImportMap {
export interface RenderToPipeableStreamOptions {
identifierPrefix?: string;
namespaceURI?: string;
nonce?: string;
nonce?: NonceOption | undefined;
bootstrapScriptContent?: string;
bootstrapScripts?: Array<string | BootstrapScriptDescriptor>;
bootstrapModules?: Array<string | BootstrapScriptDescriptor>;
Expand All @@ -71,10 +90,10 @@ export interface RenderToPipeableStreamOptions {
* Must be a positive integer if specified.
* @default 2000
*/
headersLengthHint?: number | undefined;
maxHeadersLength?: number | undefined;
importMap?: ReactImportMap | undefined;
progressiveChunkSize?: number;
onHeaders?: ((headers: Headers) => void) | undefined;
onHeaders?: ((headers: HeadersDescriptor) => void) | undefined;
onShellReady?: () => void;
onShellError?: (error: unknown) => void;
onAllReady?: () => void;
Expand Down Expand Up @@ -125,7 +144,7 @@ export interface RenderToReadableStreamOptions {
identifierPrefix?: string;
importMap?: ReactImportMap | undefined;
namespaceURI?: string;
nonce?: string;
nonce?: NonceOption | undefined;
bootstrapScriptContent?: string;
bootstrapScripts?: Array<string | BootstrapScriptDescriptor>;
bootstrapModules?: Array<string | BootstrapScriptDescriptor>;
Expand All @@ -134,7 +153,7 @@ export interface RenderToReadableStreamOptions {
* Must be a positive integer if specified.
* @default 2000
*/
headersLengthHint?: number | undefined;
maxHeadersLength?: number | undefined;
progressiveChunkSize?: number;
signal?: AbortSignal;
onError?: (error: unknown, errorInfo: ErrorInfo) => string | void;
Expand All @@ -158,6 +177,14 @@ export function renderToReadableStream(

export { ResumeOptions };

export interface ResumeToPipeableStreamOptions {
nonce?: NonceOption | undefined;
onShellReady?: (() => void) | undefined;
onShellError?: ((error: unknown) => void) | undefined;
onAllReady?: (() => void) | undefined;
onError?: ((error: unknown, errorInfo: ErrorInfo) => string | void) | undefined;
}

/**
* @see {@link https://react.dev/reference/react-dom/server/resume `resume`` reference documentation}
* @version 19.2
Expand All @@ -175,7 +202,7 @@ export function resume(
export function resumeToPipeableStream(
children: React.ReactNode,
postponedState: PostponedState,
options?: ResumeOptions,
options?: ResumeToPipeableStreamOptions,
): Promise<PipeableStream>;

export const version: string;
Expand Down
2 changes: 1 addition & 1 deletion types/react-dom/server.edge.d.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { renderToReadableStream, renderToStaticMarkup, renderToString, resume } from "./server";
export { renderToReadableStream, renderToStaticMarkup, renderToString, resume, version } from "./server";
1 change: 1 addition & 0 deletions types/react-dom/server.node.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ export {
renderToString,
resume,
resumeToPipeableStream,
version,
} from "./server";
2 changes: 1 addition & 1 deletion types/react-dom/static.browser.d.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { prerender, version } from "./static";
export { prerender, resumeAndPrerender, version } from "./static";
16 changes: 13 additions & 3 deletions types/react-dom/static.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,16 @@ export interface BootstrapScriptDescriptor {
crossOrigin?: string | undefined;
}

/**
* A nonce string, or an object with separate nonces for scripts and styles.
*/
export type NonceOption =
| string
| {
script?: string | undefined;
style?: string | undefined;
};

export interface PrerenderOptions {
bootstrapScriptContent?: string;
bootstrapScripts?: Array<string | BootstrapScriptDescriptor>;
Expand All @@ -81,12 +91,12 @@ export interface PrerenderOptions {
* Must be a positive integer if specified.
* @default 2000
*/
headersLengthHint?: number | undefined;
maxHeadersLength?: number | undefined;
identifierPrefix?: string;
importMap?: ReactImportMap | undefined;
namespaceURI?: string;
onError?: (error: unknown, errorInfo: ErrorInfo) => string | void;
onHeaders?: (headers: Headers) => void | undefined;
onHeaders?: ((headers: Headers) => void) | undefined;
progressiveChunkSize?: number;
signal?: AbortSignal;
}
Expand Down Expand Up @@ -125,7 +135,7 @@ export function prerenderToNodeStream(
): Promise<PrerenderToNodeStreamResult>;

export interface ResumeOptions {
nonce?: string;
nonce?: NonceOption | undefined;
signal?: AbortSignal;
onError?: (error: unknown) => string | undefined | void;
}
Expand Down
11 changes: 11 additions & 0 deletions types/react-dom/test/canary-tests.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,14 @@ function browserUsableTests() {
// @ts-expect-error -- the reason is a string or a zero-arg initializer, not an arbitrary value
ReactDOM.browser(new Error("Only render this content in a browser"));
}

function browserBailoutTests() {
const onBrowserBailout = (error: unknown, errorInfo: ReactDOMClient.ErrorInfo) => {};

ReactDOMServer.renderToPipeableStream(React.createElement("div"), { onBrowserBailout });
ReactDOMServer.renderToReadableStream(React.createElement("div"), { onBrowserBailout });
ReactDOMServer.resume(React.createElement("div"), null as any, { onBrowserBailout });
ReactDOMServer.resumeToPipeableStream(React.createElement("div"), null as any, { onBrowserBailout });
ReactDOMStatic.prerender(React.createElement("div"), { onBrowserBailout });
ReactDOMStatic.resumeAndPrerender(React.createElement("div"), null, { onBrowserBailout });
}
37 changes: 30 additions & 7 deletions types/react-dom/test/react-dom-tests.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -108,14 +108,37 @@ describe("ReactDOMStatic", () => {
(await ReactDOMStatic.prerenderToNodeStream(React.createElement("div"))).prelude;
ReactDOMStatic.prerenderToNodeStream(React.createElement("div"), {
bootstrapScripts: ["./my-script.js"],
headersLengthHint: 4000,
maxHeadersLength: 4000,
importMap,
onHeaders(headers) {
// $ExpectType Headers
headers;
},
});
});

it("resumeToPipeableStream", async () => {
const { postponed } = await ReactDOMStatic.prerenderToNodeStream(children);
if (postponed !== null) {
ReactDOMServer.resumeToPipeableStream(children, postponed, {
nonce: { script: "script-nonce", style: "style-nonce" },
onShellReady() {},
onShellError(error) {
console.error(error);
},
onAllReady() {},
onError(error, errorInfo) {
// $ExpectType ErrorInfo
errorInfo;
return (error as { digest?: string | undefined }).digest;
},
});
ReactDOMServer.resumeToPipeableStream(children, postponed, {
// @ts-expect-error The Node.js stream variant does not support an abort signal
signal: new AbortController().signal,
});
}
});
});

describe("React dom test utils", () => {
Expand Down Expand Up @@ -254,10 +277,10 @@ function pipeableStreamDocumentedExample() {
const response: Response = {} as any;
const { pipe, abort } = ReactDOMServer.renderToPipeableStream(<App />, {
bootstrapScripts: ["/main.js"],
headersLengthHint: 4000,
maxHeadersLength: 4000,
importMap,
onHeaders(headers) {
// $ExpectType Headers
// $ExpectType HeadersDescriptor
headers;
},
onShellReady() {
Expand Down Expand Up @@ -307,10 +330,10 @@ function pipeableStreamDocumentedStringExample() {
const response: Response = {} as any;
const { pipe, abort } = ReactDOMServer.renderToPipeableStream("app", {
bootstrapScripts: ["/main.js"],
headersLengthHint: 4000,
maxHeadersLength: 4000,
importMap,
onHeaders(headers) {
// $ExpectType Headers
// $ExpectType HeadersDescriptor
headers;
},
onShellReady() {
Expand Down Expand Up @@ -354,7 +377,7 @@ async function readableStreamDocumentedExample() {
<body>Success</body>
</html>,
{
headersLengthHint: 4000,
maxHeadersLength: 4000,
importMap,
signal: controller.signal,
onError(error) {
Expand Down Expand Up @@ -392,7 +415,7 @@ async function readableStreamDocumentedStringExample() {
const stream = await ReactDOMServer.renderToReadableStream(
"app",
{
headersLengthHint: 4000,
maxHeadersLength: 4000,
importMap,
signal: controller.signal,
onError(error) {
Expand Down