From 4383dda8ce50179053a972d6e20f51c868260470 Mon Sep 17 00:00:00 2001 From: Josh Story Date: Fri, 28 Apr 2023 15:57:39 -0700 Subject: [PATCH] Preinits should support a nonce option (#26744) Currently there is no way to provide a nonce when using `ReactDOM.preinit(..., { as: 'script' })` This PR adds `nonce?: string` as an option While implementing this PR I added a test to also show you can pass `integrity`. This test isn't directly related to the nonce change. --- .../src/client/ReactFiberConfigDOM.js | 2 + .../src/server/ReactFizzConfigDOM.js | 2 + packages/react-dom/src/ReactDOMDispatcher.js | 1 + .../src/__tests__/ReactDOMFloat-test.js | 100 ++++++++++++++++++ 4 files changed, 105 insertions(+) diff --git a/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js b/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js index a0ca9013067ca..67723652268dd 100644 --- a/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js +++ b/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js @@ -2203,6 +2203,7 @@ type PreinitOptions = { precedence?: string, crossOrigin?: string, integrity?: string, + nonce?: string, }; function preinit(href: string, options: PreinitOptions) { if (!enableFloat) { @@ -2355,6 +2356,7 @@ function scriptPropsFromPreinitOptions( async: true, crossOrigin: options.crossOrigin, integrity: options.integrity, + nonce: options.nonce, }; } diff --git a/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js b/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js index 0e4bf4669ec8d..2b26e47395a71 100644 --- a/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js +++ b/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js @@ -5110,6 +5110,7 @@ type PreinitOptions = { precedence?: string, crossOrigin?: string, integrity?: string, + nonce?: string, }; function preinit(href: string, options: PreinitOptions): void { if (!enableFloat) { @@ -5449,6 +5450,7 @@ function scriptPropsFromPreinitOptions( async: true, crossOrigin: options.crossOrigin, integrity: options.integrity, + nonce: options.nonce, }; } diff --git a/packages/react-dom/src/ReactDOMDispatcher.js b/packages/react-dom/src/ReactDOMDispatcher.js index fdead10cd0948..0c2b85945006b 100644 --- a/packages/react-dom/src/ReactDOMDispatcher.js +++ b/packages/react-dom/src/ReactDOMDispatcher.js @@ -20,6 +20,7 @@ export type PreinitOptions = { precedence?: string, crossOrigin?: string, integrity?: string, + nonce?: string, }; export type HostDispatcher = { diff --git a/packages/react-dom/src/__tests__/ReactDOMFloat-test.js b/packages/react-dom/src/__tests__/ReactDOMFloat-test.js index 48603d89d2252..272d7996bb7ff 100644 --- a/packages/react-dom/src/__tests__/ReactDOMFloat-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMFloat-test.js @@ -4309,6 +4309,106 @@ body { 'ReactDOM.preinit(): For `href` "foo", the options provided conflict with another call to `ReactDOM.preinit("foo", { as: "script", ... })`. React will always use the options it first encounters when preinitializing a hoistable script for a given `href` and any later options will be ignored if different. Try updating all calls to `ReactDOM.preinit()` for a given `href` to use the same options, or only call `ReactDOM.preinit()` once per `href`.\n "integrity" option value: "some hash", missing from original options\n "crossOrigin" option value: "anonymous", original option value: "use-credentials"', ]); }); + + it('accepts a `nonce` option for `as: "script"`', async () => { + function Component({src}) { + ReactDOM.preinit(src, {as: 'script', nonce: 'R4nD0m'}); + return 'hello'; + } + + await act(() => { + renderToPipeableStream( + + + + + , + { + nonce: 'R4nD0m', + }, + ).pipe(writable); + }); + + expect(getMeaningfulChildren(document)).toEqual( + + +