Skip to content

Commit e6f1c33

Browse files
authored
[Fiber] Don't warn when rendering data block scripts (facebook#35953)
1 parent 4cc5b7a commit e6f1c33

2 files changed

Lines changed: 66 additions & 1 deletion

File tree

packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ export type Props = {
183183
checked?: boolean,
184184
defaultChecked?: boolean,
185185
multiple?: boolean,
186+
type?: string,
186187
src?: string | Blob | MediaSource | MediaStream, // TODO: Response
187188
srcSet?: string,
188189
loading?: 'eager' | 'lazy',
@@ -469,6 +470,44 @@ export function createHoistableInstance(
469470
}
470471

471472
let didWarnScriptTags = false;
473+
function isScriptDataBlock(props: Props): boolean {
474+
const scriptType = props.type;
475+
if (typeof scriptType !== 'string' || scriptType === '') {
476+
return false;
477+
}
478+
const lower = scriptType.toLowerCase();
479+
// Special non-MIME keywords recognized by the HTML spec
480+
// TODO: May be fine to also not warn about having these types be parsed as "parser-inserted"
481+
if (
482+
lower === 'module' ||
483+
lower === 'importmap' ||
484+
lower === 'speculationrules'
485+
) {
486+
return false;
487+
}
488+
// JavaScript MIME types per https://mimesniff.spec.whatwg.org/#javascript-mime-type
489+
switch (lower) {
490+
case 'application/ecmascript':
491+
case 'application/javascript':
492+
case 'application/x-ecmascript':
493+
case 'application/x-javascript':
494+
case 'text/ecmascript':
495+
case 'text/javascript':
496+
case 'text/javascript1.0':
497+
case 'text/javascript1.1':
498+
case 'text/javascript1.2':
499+
case 'text/javascript1.3':
500+
case 'text/javascript1.4':
501+
case 'text/javascript1.5':
502+
case 'text/jscript':
503+
case 'text/livescript':
504+
case 'text/x-ecmascript':
505+
case 'text/x-javascript':
506+
return false;
507+
}
508+
// Any other non-empty type value means this is a data block
509+
return true;
510+
}
472511
const warnedUnknownTags: {
473512
[key: string]: boolean,
474513
} = {
@@ -526,7 +565,13 @@ export function createInstance(
526565
// set to true and it does not execute
527566
const div = ownerDocument.createElement('div');
528567
if (__DEV__) {
529-
if (enableTrustedTypesIntegration && !didWarnScriptTags) {
568+
if (
569+
enableTrustedTypesIntegration &&
570+
!didWarnScriptTags &&
571+
// Data block scripts are not executed by UAs anyway so
572+
// we don't need to warn: https://html.spec.whatwg.org/multipage/scripting.html#attr-script-type
573+
!isScriptDataBlock(props)
574+
) {
530575
console.error(
531576
'Encountered a script tag while rendering React component. ' +
532577
'Scripts inside React components are never executed when rendering ' +

packages/react-dom/src/client/__tests__/trustedTypes-test.internal.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,4 +248,24 @@ describe('when Trusted Types are available in global object', () => {
248248
root.render(<script>alert("I am not executed")</script>);
249249
});
250250
});
251+
252+
it('should not warn when rendering a data block script tag', async () => {
253+
const root = ReactDOMClient.createRoot(container);
254+
await act(() => {
255+
root.render(
256+
<script type="application/json">{'{"key": "value"}'}</script>,
257+
);
258+
});
259+
});
260+
261+
it('should not warn when rendering a ld+json script tag', async () => {
262+
const root = ReactDOMClient.createRoot(container);
263+
await act(() => {
264+
root.render(
265+
<script type="application/ld+json">
266+
{'{"@context": "https://schema.org"}'}
267+
</script>,
268+
);
269+
});
270+
});
251271
});

0 commit comments

Comments
 (0)