@samitouri / QOS-React-2 / commits / e6f1c33acf

[Fiber] Don't warn when rendering data block scripts (#35953)

Sebastian "Sebbie" Silbermann committed Mar 3, 2026 at 19:38 UTC e6f1c33acf81d9865863ab149d24726f43a56db0
2 files changed +66 -1
packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js
+46 -1
@@ -183,6 +183,7 @@ export type Props = {
183 checked?: boolean,
184 defaultChecked?: boolean,
185 multiple?: boolean,
186 + type?: string,
187 src?: string | Blob | MediaSource | MediaStream, // TODO: Response
188 srcSet?: string,
189 loading?: 'eager' | 'lazy',
@@ -469,6 +470,44 @@ export function createHoistableInstance(
470 }
471
472 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 +}
511 const warnedUnknownTags: {
512 [key: string]: boolean,
513 } = {
@@ -526,7 +565,13 @@ export function createInstance(
565 // set to true and it does not execute
566 const div = ownerDocument.createElement('div');
567 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 + ) {
575 console.error(
576 'Encountered a script tag while rendering React component. ' +
577 'Scripts inside React components are never executed when rendering ' +
packages/react-dom/src/client/__tests__/trustedTypes-test.internal.js
+20
@@ -248,4 +248,24 @@ describe('when Trusted Types are available in global object', () => {
248 root.render(<script>alert("I am not executed")</script>);
249 });
250 });
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 + });
271 });