Skip to content

Commit 6af7037

Browse files
HenriqueLimasAndyPengc12
authored andcommitted
Add support for 'crossorigin' attribute on bootstrapScripts and bootstrapModules (facebook#26844)
base build ci job failing but this change is unrelated and I think it is just flake with the builds host application
1 parent 3bbe565 commit 6af7037

File tree

2 files changed

+89
-0
lines changed

2 files changed

+89
-0
lines changed

packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ const startScriptSrc = stringToPrecomputedChunk('<script src="');
163163
const startModuleSrc = stringToPrecomputedChunk('<script type="module" src="');
164164
const scriptNonce = stringToPrecomputedChunk('" nonce="');
165165
const scriptIntegirty = stringToPrecomputedChunk('" integrity="');
166+
const scriptCrossOrigin = stringToPrecomputedChunk('" crossorigin="');
166167
const endAsyncScript = stringToPrecomputedChunk('" async=""></script>');
167168

168169
/**
@@ -192,6 +193,7 @@ const scriptReplacer = (
192193
export type BootstrapScriptDescriptor = {
193194
src: string,
194195
integrity?: string,
196+
crossOrigin?: string,
195197
};
196198
export type ExternalRuntimeScript = {
197199
src: string,
@@ -266,6 +268,12 @@ export function createResponseState(
266268
typeof scriptConfig === 'string' ? scriptConfig : scriptConfig.src;
267269
const integrity =
268270
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+
: '';
269277

270278
preloadBootstrapScript(resources, src, nonce, integrity);
271279

@@ -285,6 +293,12 @@ export function createResponseState(
285293
stringToChunk(escapeTextForBrowser(integrity)),
286294
);
287295
}
296+
if (typeof crossOrigin === 'string') {
297+
bootstrapChunks.push(
298+
scriptCrossOrigin,
299+
stringToChunk(escapeTextForBrowser(crossOrigin)),
300+
);
301+
}
288302
bootstrapChunks.push(endAsyncScript);
289303
}
290304
}
@@ -295,6 +309,12 @@ export function createResponseState(
295309
typeof scriptConfig === 'string' ? scriptConfig : scriptConfig.src;
296310
const integrity =
297311
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+
: '';
298318

299319
preloadBootstrapModule(resources, src, nonce, integrity);
300320

@@ -315,6 +335,12 @@ export function createResponseState(
315335
stringToChunk(escapeTextForBrowser(integrity)),
316336
);
317337
}
338+
if (typeof crossOrigin === 'string') {
339+
bootstrapChunks.push(
340+
scriptCrossOrigin,
341+
stringToChunk(escapeTextForBrowser(crossOrigin)),
342+
);
343+
}
318344
bootstrapChunks.push(endAsyncScript);
319345
}
320346
}

packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3824,6 +3824,69 @@ describe('ReactDOMFizzServer', () => {
38243824
]);
38253825
});
38263826

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+
38273890
describe('bootstrapScriptContent escaping', () => {
38283891
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 () => {
38293892
window.__test_outlet = '';

0 commit comments

Comments
 (0)