@samitouri / QOS-React-2 / commits / 90229eb925

Add support for 'crossorigin' attribute on bootstrapScripts and bootstrapModules (#26844)

base build ci job failing but this change is unrelated and I think it is just flake with the builds host application

Henrique Limas committed Jun 13, 2023 at 09:12 UTC 90229eb925e2330667fb7c023a5c4317c7ae8363
2 files changed +89
packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js
+26
@@ -163,6 +163,7 @@ const startScriptSrc = stringToPrecomputedChunk('<script src="');
163 const startModuleSrc = stringToPrecomputedChunk('<script type="module" src="');
164 const scriptNonce = stringToPrecomputedChunk('" nonce="');
165 const scriptIntegirty = stringToPrecomputedChunk('" integrity="');
166 +const scriptCrossOrigin = stringToPrecomputedChunk('" crossorigin="');
167 const endAsyncScript = stringToPrecomputedChunk('" async=""></script>');
168
169 /**
@@ -192,6 +193,7 @@ const scriptReplacer = (
193 export type BootstrapScriptDescriptor = {
194 src: string,
195 integrity?: string,
196 + crossOrigin?: string,
197 };
198 export type ExternalRuntimeScript = {
199 src: string,
@@ -266,6 +268,12 @@ export function createResponseState(
268 typeof scriptConfig === 'string' ? scriptConfig : scriptConfig.src;
269 const integrity =
270 typeof scriptConfig === 'string' ? undefined : scriptConfig.integrity;
271 + const crossOrigin =
272 + typeof scriptConfig === 'string' || scriptConfig.crossOrigin == null
273 + ? undefined
274 + : scriptConfig.crossOrigin === 'use-credentials'
275 + ? 'use-credentials'
276 + : '';
277
278 preloadBootstrapScript(resources, src, nonce, integrity);
279
@@ -285,6 +293,12 @@ export function createResponseState(
293 stringToChunk(escapeTextForBrowser(integrity)),
294 );
295 }
296 + if (typeof crossOrigin === 'string') {
297 + bootstrapChunks.push(
298 + scriptCrossOrigin,
299 + stringToChunk(escapeTextForBrowser(crossOrigin)),
300 + );
301 + }
302 bootstrapChunks.push(endAsyncScript);
303 }
304 }
@@ -295,6 +309,12 @@ export function createResponseState(
309 typeof scriptConfig === 'string' ? scriptConfig : scriptConfig.src;
310 const integrity =
311 typeof scriptConfig === 'string' ? undefined : scriptConfig.integrity;
312 + const crossOrigin =
313 + typeof scriptConfig === 'string' || scriptConfig.crossOrigin == null
314 + ? undefined
315 + : scriptConfig.crossOrigin === 'use-credentials'
316 + ? 'use-credentials'
317 + : '';
318
319 preloadBootstrapModule(resources, src, nonce, integrity);
320
@@ -315,6 +335,12 @@ export function createResponseState(
335 stringToChunk(escapeTextForBrowser(integrity)),
336 );
337 }
338 + if (typeof crossOrigin === 'string') {
339 + bootstrapChunks.push(
340 + scriptCrossOrigin,
341 + stringToChunk(escapeTextForBrowser(crossOrigin)),
342 + );
343 + }
344 bootstrapChunks.push(endAsyncScript);
345 }
346 }
packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js
+63
@@ -3824,6 +3824,69 @@ describe('ReactDOMFizzServer', () => {
3824 ]);
3825 });
3826
3827 + it('accepts a crossOrigin property for bootstrapScripts and bootstrapModules', async () => {
3828 + await act(() => {
3829 + const {pipe} = renderToPipeableStream(
3830 + <html>
3831 + <head />
3832 + <body>
3833 + <div>hello world</div>
3834 + </body>
3835 + </html>,
3836 + {
3837 + bootstrapScripts: [
3838 + 'foo',
3839 + {
3840 + src: 'bar',
3841 + },
3842 + {
3843 + src: 'baz',
3844 + crossOrigin: '',
3845 + },
3846 + {
3847 + src: 'qux',
3848 + crossOrigin: 'defaults-to-empty',
3849 + },
3850 + ],
3851 + bootstrapModules: [
3852 + 'quux',
3853 + {
3854 + src: 'corge',
3855 + },
3856 + {
3857 + src: 'grault',
3858 + crossOrigin: 'use-credentials',
3859 + },
3860 + ],
3861 + },
3862 + );
3863 + pipe(writable);
3864 + });
3865 +
3866 + expect(getVisibleChildren(document)).toEqual(
3867 + <html>
3868 + <head />
3869 + <body>
3870 + <div>hello world</div>
3871 + </body>
3872 + </html>,
3873 + );
3874 + expect(
3875 + stripExternalRuntimeInNodes(
3876 + document.getElementsByTagName('script'),
3877 + renderOptions.unstable_externalRuntimeSrc,
3878 + ).map(n => n.outerHTML),
3879 + ).toEqual([
3880 + '<script src="foo" async=""></script>',
3881 + '<script src="bar" async=""></script>',
3882 + '<script src="baz" crossorigin="" async=""></script>',
3883 + '<script src="qux" crossorigin="" async=""></script>',
3884 + '<script type="module" src="quux" async=""></script>',
3885 + '<script type="module" src="corge" async=""></script>',
3886 + '<script type="module" src="grault" crossorigin="use-credentials" async=""></script>',
3887 + ]);
3888 + });
3889 +
3890 describe('bootstrapScriptContent escaping', () => {
3891 it('the "S" in "</?[Ss]cript" strings are replaced with unicode escaped lowercase s or S depending on case, preserving case sensitivity of nearby characters', async () => {
3892 window.__test_outlet = '';