@samitouri / QOS-React-2 / commits / 6befd1ae62

[Float] Forward `nonce` option in `ReactDOM.preloadModule()` (#36851)

udit committed Jun 29, 2026 at 07:33 UTC 6befd1ae6299a44c49aa704564b3de09496432f8
5 files changed +37 -5
.eslintrc.js
+1
@@ -622,6 +622,7 @@ module.exports = {
622 ReadableStreamReader: 'readonly',
623 RequestInfo: 'readonly',
624 RequestOptions: 'readonly',
625 + Required: 'readonly',
626 StoreAsGlobal: 'readonly',
627 symbol: 'readonly',
628 SyntheticEvent: 'readonly',
packages/react-dom-bindings/src/shared/ReactFlightClientConfigDOM.js
+4
@@ -118,7 +118,9 @@ export function preinitModuleForSSR(
118 ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */
119 .M(/* preinitModuleScript */ href, {
120 crossOrigin: getCrossOriginString(crossOrigin),
121 + integrity: undefined,
122 nonce,
123 + fetchPriority: undefined,
124 });
125 }
126
@@ -130,6 +132,8 @@ export function preinitScriptForSSR(
132 ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */
133 .X(/* preinitScript */ href, {
134 crossOrigin: getCrossOriginString(crossOrigin),
135 + integrity: undefined,
136 + fetchPriority: undefined,
137 nonce,
138 });
139 }
packages/react-dom/src/__tests__/ReactDOMFloat-test.js
+23
@@ -6621,6 +6621,29 @@ body {
6621 );
6622 });
6623
6624 + it('supports nonce', async () => {
6625 + function App({ssr}) {
6626 + const prefix = ssr ? 'ssr ' : 'browser ';
6627 + ReactDOM.preloadModule(prefix + 'module', {nonce: 'abc'});
6628 + return <div>hello</div>;
6629 + }
6630 + await act(() => {
6631 + renderToPipeableStream(<App ssr={true} />).pipe(writable);
6632 + });
6633 + expect(getMeaningfulChildren(document.body)).toEqual(
6634 + <div id="container">
6635 + <link rel="modulepreload" href="ssr module" nonce="abc" />
6636 + <div>hello</div>
6637 + </div>,
6638 + );
6639 +
6640 + ReactDOMClient.hydrateRoot(container, <App />);
6641 + await waitForAll([]);
6642 + expect(getMeaningfulChildren(document.head)).toEqual(
6643 + <link rel="modulepreload" href="browser module" nonce="abc" />,
6644 + );
6645 + });
6646 +
6647 it('warns if you provide invalid arguments', async () => {
6648 function App() {
6649 ReactDOM.preloadModule();
packages/react-dom/src/shared/ReactDOMFloat.js
+1
@@ -192,6 +192,7 @@ export function preloadModule(href: string, options?: ?PreloadModuleOptions) {
192 typeof options.integrity === 'string'
193 ? options.integrity
194 : undefined,
195 + nonce: typeof options.nonce === 'string' ? options.nonce : undefined,
196 fetchPriority:
197 typeof options.fetchPriority === 'string'
198 ? options.fetchPriority
packages/react-dom/src/shared/ReactDOMTypes.js
+8 -5
@@ -93,21 +93,24 @@ export type HostDispatcher = {
93 L /* preload */: (
94 href: string,
95 as: string,
96 - options?: ?PreloadImplOptions,
96 + options?: ?Required<PreloadImplOptions>,
97 ) => void,
98 m /* preloadModule */: (
99 href: string,
100 - options?: ?PreloadModuleImplOptions,
100 + options?: ?Required<PreloadModuleImplOptions>,
101 ) => void,
102 S /* preinitStyle */: (
103 href: string,
104 precedence: ?string,
105 - options?: ?PreinitStyleOptions,
105 + options?: ?Required<PreinitStyleOptions>,
106 + ) => void,
107 + X /* preinitScript */: (
108 + src: string,
109 + options?: ?Required<PreinitScriptOptions>,
110 ) => void,
107 - X /* preinitScript */: (src: string, options?: ?PreinitScriptOptions) => void,
111 M /* preinitModuleScript */: (
112 src: string,
110 - options?: ?PreinitModuleScriptOptions,
113 + options?: ?Required<PreinitModuleScriptOptions>,
114 ) => void,
115 };
116