Skip to content

Commit bc25880

Browse files
committed
Add support for 'crossorigin' attribute on bootstrapScripts and bootstrapModules
1 parent 535c038 commit bc25880

File tree

2 files changed

+76
-0
lines changed

2 files changed

+76
-0
lines changed

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

Lines changed: 18 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,
@@ -265,6 +267,8 @@ export function createResponseState(
265267
typeof scriptConfig === 'string' ? scriptConfig : scriptConfig.src;
266268
const integrity =
267269
typeof scriptConfig === 'string' ? undefined : scriptConfig.integrity;
270+
const crossOrigin =
271+
typeof scriptConfig === 'string' ? undefined : scriptConfig.crossOrigin;
268272

269273
bootstrapChunks.push(
270274
startScriptSrc,
@@ -282,6 +286,12 @@ export function createResponseState(
282286
stringToChunk(escapeTextForBrowser(integrity)),
283287
);
284288
}
289+
if (crossOrigin) {
290+
bootstrapChunks.push(
291+
scriptCrossOrigin,
292+
stringToChunk(escapeTextForBrowser(crossOrigin)),
293+
);
294+
}
285295
bootstrapChunks.push(endAsyncScript);
286296
}
287297
}
@@ -292,6 +302,8 @@ export function createResponseState(
292302
typeof scriptConfig === 'string' ? scriptConfig : scriptConfig.src;
293303
const integrity =
294304
typeof scriptConfig === 'string' ? undefined : scriptConfig.integrity;
305+
const crossOrigin =
306+
typeof scriptConfig === 'string' ? undefined : scriptConfig.crossOrigin;
295307

296308
bootstrapChunks.push(
297309
startModuleSrc,
@@ -310,6 +322,12 @@ export function createResponseState(
310322
stringToChunk(escapeTextForBrowser(integrity)),
311323
);
312324
}
325+
if (crossOrigin) {
326+
bootstrapChunks.push(
327+
scriptCrossOrigin,
328+
stringToChunk(escapeTextForBrowser(crossOrigin)),
329+
);
330+
}
313331
bootstrapChunks.push(endAsyncScript);
314332
}
315333
}

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

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3777,6 +3777,64 @@ describe('ReactDOMFizzServer', () => {
37773777
]);
37783778
});
37793779

3780+
it('accepts a crossOrigin property for bootstrapScripts and bootstrapModules', async () => {
3781+
await act(() => {
3782+
const {pipe} = renderToPipeableStream(
3783+
<html>
3784+
<head />
3785+
<body>
3786+
<div>hello world</div>
3787+
</body>
3788+
</html>,
3789+
{
3790+
bootstrapScripts: [
3791+
'foo',
3792+
{
3793+
src: 'bar',
3794+
},
3795+
{
3796+
src: 'baz',
3797+
crossOrigin: 'anonymous',
3798+
},
3799+
],
3800+
bootstrapModules: [
3801+
'quux',
3802+
{
3803+
src: 'corge',
3804+
},
3805+
{
3806+
src: 'grault',
3807+
crossOrigin: 'use-credentials',
3808+
},
3809+
],
3810+
},
3811+
);
3812+
pipe(writable);
3813+
});
3814+
3815+
expect(getVisibleChildren(document)).toEqual(
3816+
<html>
3817+
<head />
3818+
<body>
3819+
<div>hello world</div>
3820+
</body>
3821+
</html>,
3822+
);
3823+
expect(
3824+
stripExternalRuntimeInNodes(
3825+
document.getElementsByTagName('script'),
3826+
renderOptions.unstable_externalRuntimeSrc,
3827+
).map(n => n.outerHTML),
3828+
).toEqual([
3829+
'<script src="foo" async=""></script>',
3830+
'<script src="bar" async=""></script>',
3831+
'<script src="baz" crossorigin="anonymous" async=""></script>',
3832+
'<script type="module" src="quux" async=""></script>',
3833+
'<script type="module" src="corge" async=""></script>',
3834+
'<script type="module" src="grault" crossorigin="use-credentials" async=""></script>',
3835+
]);
3836+
});
3837+
37803838
describe('bootstrapScriptContent escaping', () => {
37813839
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 () => {
37823840
window.__test_outlet = '';

0 commit comments

Comments
 (0)