diff --git a/packages/react-dom/src/__tests__/ReactDOMAttribute-test.js b/packages/react-dom/src/__tests__/ReactDOMAttribute-test.js index cd1d055c09d..63baa38c710 100644 --- a/packages/react-dom/src/__tests__/ReactDOMAttribute-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMAttribute-test.js @@ -171,7 +171,13 @@ describe('ReactDOM unknown attribute', () => { const test = () => testUnknownAttributeAssignment(new TemporalLike(), null); - await expect(test).rejects.toThrowError(new TypeError('prod message')); + if (gate('enableTrustedTypesIntegration') && !__DEV__) { + // TODO: this still throws in DEV even though it's not toString'd in prod. + await expect(test).rejects.toThrowError('2020-01-01'); + } else { + await expect(test).rejects.toThrowError(new TypeError('prod message')); + } + assertConsoleErrorDev([ 'The provided `unknown` attribute is an unsupported type TemporalLike.' + ' This value must be coerced to a string before using it here.\n' + diff --git a/packages/react-dom/src/__tests__/ReactDOMFloat-test.js b/packages/react-dom/src/__tests__/ReactDOMFloat-test.js index ed3d3e08805..e2065efa69c 100644 --- a/packages/react-dom/src/__tests__/ReactDOMFloat-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMFloat-test.js @@ -608,6 +608,14 @@ describe('ReactDOMFloat', () => { '> '); + if (gate('enableTrustedTypesIntegration')) { + assertConsoleErrorDev([ + 'Encountered a script tag while rendering React component. ' + + 'Scripts inside React components are never executed when rendering on the client. ' + + 'Consider using template tag instead (https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template).\n' + + ' in script (at **)\n' + + ' in TogglingComponent (at **)', + ]); + } + const container2 = document.createElement('div'); const root2 = ReactDOMClient.createRoot(container2); expect(() => { @@ -189,6 +202,7 @@ describe('ReactEmptyComponent', () => { 'mount SCRIPT', 'update undefined', ]); + expect(container2.innerHTML).toBe(''); }); it( diff --git a/packages/react-dom/src/client/__tests__/trustedTypes-test.internal.js b/packages/react-dom/src/client/__tests__/trustedTypes-test.internal.js index 5a43a9ec2f0..06744581ae9 100644 --- a/packages/react-dom/src/client/__tests__/trustedTypes-test.internal.js +++ b/packages/react-dom/src/client/__tests__/trustedTypes-test.internal.js @@ -12,7 +12,6 @@ describe('when Trusted Types are available in global object', () => { let React; let ReactDOMClient; - let ReactFeatureFlags; let act; let assertConsoleErrorDev; let container; @@ -33,8 +32,6 @@ describe('when Trusted Types are available in global object', () => { isScript: () => false, isScriptURL: () => false, }; - ReactFeatureFlags = require('shared/ReactFeatureFlags'); - ReactFeatureFlags.enableTrustedTypesIntegration = true; React = require('react'); ReactDOMClient = require('react-dom/client'); ({act, assertConsoleErrorDev} = require('internal-test-utils')); @@ -118,7 +115,11 @@ describe('when Trusted Types are available in global object', () => { expect(setAttributeCalls[0][0]).toBe(container.firstChild); expect(setAttributeCalls[0][1]).toBe('data-foo'); // Ensure it didn't get stringified when passed to a DOM sink: - expect(setAttributeCalls[0][2]).toBe(ttObject1); + if (gate('enableTrustedTypesIntegration')) { + expect(setAttributeCalls[0][2]).toBe(ttObject1); + } else { + expect(setAttributeCalls[0][2]).toBe('Hi'); + } setAttributeCalls.length = 0; await act(() => { @@ -129,7 +130,11 @@ describe('when Trusted Types are available in global object', () => { expect(setAttributeCalls[0][0]).toBe(container.firstChild); expect(setAttributeCalls[0][1]).toBe('data-foo'); // Ensure it didn't get stringified when passed to a DOM sink: - expect(setAttributeCalls[0][2]).toBe(ttObject2); + if (gate('enableTrustedTypesIntegration')) { + expect(setAttributeCalls[0][2]).toBe(ttObject2); + } else { + expect(setAttributeCalls[0][2]).toBe('Bye'); + } } finally { Element.prototype.setAttribute = setAttribute; } @@ -153,7 +158,11 @@ describe('when Trusted Types are available in global object', () => { expect(setAttributeCalls[0][0]).toBe(container.firstChild); expect(setAttributeCalls[0][1]).toBe('class'); // Ensure it didn't get stringified when passed to a DOM sink: - expect(setAttributeCalls[0][2]).toBe(ttObject1); + if (gate('enableTrustedTypesIntegration')) { + expect(setAttributeCalls[0][2]).toBe(ttObject1); + } else { + expect(setAttributeCalls[0][2]).toBe('Hi'); + } setAttributeCalls.length = 0; await act(() => { @@ -164,7 +173,11 @@ describe('when Trusted Types are available in global object', () => { expect(setAttributeCalls[0][0]).toBe(container.firstChild); expect(setAttributeCalls[0][1]).toBe('class'); // Ensure it didn't get stringified when passed to a DOM sink: - expect(setAttributeCalls[0][2]).toBe(ttObject2); + if (gate('enableTrustedTypesIntegration')) { + expect(setAttributeCalls[0][2]).toBe(ttObject2); + } else { + expect(setAttributeCalls[0][2]).toBe('Bye'); + } } finally { Element.prototype.setAttribute = setAttribute; } @@ -189,7 +202,11 @@ describe('when Trusted Types are available in global object', () => { expect(setAttributeNSCalls[0][1]).toBe('http://www.w3.org/1999/xlink'); expect(setAttributeNSCalls[0][2]).toBe('xlink:href'); // Ensure it didn't get stringified when passed to a DOM sink: - expect(setAttributeNSCalls[0][3]).toBe(ttObject1); + if (gate('enableTrustedTypesIntegration')) { + expect(setAttributeNSCalls[0][3]).toBe(ttObject1); + } else { + expect(setAttributeNSCalls[0][3]).toBe('Hi'); + } setAttributeNSCalls.length = 0; await act(() => { @@ -201,7 +218,11 @@ describe('when Trusted Types are available in global object', () => { expect(setAttributeNSCalls[0][1]).toBe('http://www.w3.org/1999/xlink'); expect(setAttributeNSCalls[0][2]).toBe('xlink:href'); // Ensure it didn't get stringified when passed to a DOM sink: - expect(setAttributeNSCalls[0][3]).toBe(ttObject2); + if (gate('enableTrustedTypesIntegration')) { + expect(setAttributeNSCalls[0][3]).toBe(ttObject2); + } else { + expect(setAttributeNSCalls[0][3]).toBe('Bye'); + } } finally { Element.prototype.setAttributeNS = setAttributeNS; } @@ -212,13 +233,15 @@ describe('when Trusted Types are available in global object', () => { await act(() => { root.render(); }); - assertConsoleErrorDev([ - 'Encountered a script tag while rendering React component. ' + - 'Scripts inside React components are never executed when rendering ' + - 'on the client. Consider using template tag instead ' + - '(https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template).\n' + - ' in script (at **)', - ]); + if (gate('enableTrustedTypesIntegration')) { + assertConsoleErrorDev([ + 'Encountered a script tag while rendering React component. ' + + 'Scripts inside React components are never executed when rendering ' + + 'on the client. Consider using template tag instead ' + + '(https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template).\n' + + ' in script (at **)', + ]); + } // check that the warning is printed only once await act(() => { diff --git a/packages/shared/CheckStringCoercion.js b/packages/shared/CheckStringCoercion.js index a186d6755d9..0165d8b19c1 100644 --- a/packages/shared/CheckStringCoercion.js +++ b/packages/shared/CheckStringCoercion.js @@ -76,6 +76,8 @@ export function checkAttributeStringCoercion( attributeName: string, ): void | string { if (__DEV__) { + // TODO: for enableTrustedTypesIntegration we don't toString this + // so we shouldn't need the DEV warning. if (willCoercionThrow(value)) { console.error( 'The provided `%s` attribute is an unsupported type %s.' + diff --git a/packages/shared/forks/ReactFeatureFlags.www-dynamic.js b/packages/shared/forks/ReactFeatureFlags.www-dynamic.js index a8d829ee3e3..3a6c456c928 100644 --- a/packages/shared/forks/ReactFeatureFlags.www-dynamic.js +++ b/packages/shared/forks/ReactFeatureFlags.www-dynamic.js @@ -35,12 +35,11 @@ export const enableScrollEndPolyfill: boolean = __VARIANT__; export const enableFragmentRefs: boolean = __VARIANT__; export const enableFragmentRefsScrollIntoView: boolean = __VARIANT__; export const enableAsyncDebugInfo: boolean = __VARIANT__; - export const enableInternalInstanceMap: boolean = __VARIANT__; +export const enableTrustedTypesIntegration: boolean = __VARIANT__; // TODO: These flags are hard-coded to the default values used in open source. // Update the tests so that they pass in either mode, then set these // to __VARIANT__. -export const enableTrustedTypesIntegration: boolean = false; // You probably *don't* want to add more hardcoded ones. // Instead, try to add them above with the __VARIANT__ value.