Skip to content

Commit d4d099f

Browse files
[flags] make enableTrustedTypesIntegration dynamic (facebook#35646)
Co-authored-by: Rick Hanlon <rickhanlonii@meta.com>
1 parent c0c3706 commit d4d099f

File tree

8 files changed

+93
-22
lines changed

8 files changed

+93
-22
lines changed

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,13 @@ describe('ReactDOM unknown attribute', () => {
171171
const test = () =>
172172
testUnknownAttributeAssignment(new TemporalLike(), null);
173173

174-
await expect(test).rejects.toThrowError(new TypeError('prod message'));
174+
if (gate('enableTrustedTypesIntegration') && !__DEV__) {
175+
// TODO: this still throws in DEV even though it's not toString'd in prod.
176+
await expect(test).rejects.toThrowError('2020-01-01');
177+
} else {
178+
await expect(test).rejects.toThrowError(new TypeError('prod message'));
179+
}
180+
175181
assertConsoleErrorDev([
176182
'The provided `unknown` attribute is an unsupported type TemporalLike.' +
177183
' This value must be coerced to a string before using it here.\n' +

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,14 @@ describe('ReactDOMFloat', () => {
602602
'> <script href="foo">\n' +
603603
'\n' +
604604
' in script (at **)',
605+
...(gate('enableTrustedTypesIntegration')
606+
? [
607+
'Encountered a script tag while rendering React component. ' +
608+
'Scripts inside React components are never executed when rendering on the client. ' +
609+
'Consider using template tag instead (https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template).\n' +
610+
' in script (at **)',
611+
]
612+
: []),
605613
]);
606614

607615
root.render(
@@ -2745,6 +2753,14 @@ body {
27452753
'> <script itemProp="foo">\n' +
27462754
'\n' +
27472755
' in script (at **)',
2756+
...(gate('enableTrustedTypesIntegration')
2757+
? [
2758+
'Encountered a script tag while rendering React component. ' +
2759+
'Scripts inside React components are never executed when rendering on the client. ' +
2760+
'Consider using template tag instead (https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template).\n' +
2761+
' in script (at **)',
2762+
]
2763+
: []),
27482764
]);
27492765
});
27502766

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

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2277,15 +2277,21 @@ describe('ReactDOMForm', () => {
22772277
await submit(formRef.current);
22782278
assertLog([actionFn]);
22792279

2280-
// Everything else is toString-ed
2280+
// Everything else is toString-ed, unless trusted types are enabled.
22812281
class MyAction {
22822282
toString() {
22832283
return 'stringified action';
22842284
}
22852285
}
2286-
await act(() => root.render(<Form action={new MyAction()} />));
2286+
const instance = new MyAction();
2287+
2288+
await act(() => root.render(<Form action={instance} />));
22872289
await submit(formRef.current);
2288-
assertLog(['stringified action']);
2290+
assertLog(
2291+
gate('enableTrustedTypesIntegration')
2292+
? [instance]
2293+
: ['stringified action'],
2294+
);
22892295
});
22902296

22912297
it('form actions should retain status when nested state changes', async () => {

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,11 @@ describe('ReactDOMServerIntegration - Untrusted URLs', () => {
212212
expectedToStringCalls *= 2;
213213
}
214214

215+
if (gate('enableTrustedTypesIntegration') && render === clientCleanRender) {
216+
// Trusted types does another toString.
217+
expectedToStringCalls += 1;
218+
}
219+
215220
let toStringCalls = 0;
216221
const firstIsSafe = {
217222
toString() {

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ let TogglingComponent;
1717
let act;
1818
let Scheduler;
1919
let assertLog;
20+
let assertConsoleErrorDev;
2021

2122
let container;
2223

@@ -34,6 +35,7 @@ describe('ReactEmptyComponent', () => {
3435
const InternalTestUtils = require('internal-test-utils');
3536
act = InternalTestUtils.act;
3637
assertLog = InternalTestUtils.assertLog;
38+
assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;
3739

3840
container = document.createElement('div');
3941

@@ -175,6 +177,17 @@ describe('ReactEmptyComponent', () => {
175177
});
176178
}).not.toThrow();
177179

180+
expect(container.innerHTML).toBe('<script></script>');
181+
if (gate('enableTrustedTypesIntegration')) {
182+
assertConsoleErrorDev([
183+
'Encountered a script tag while rendering React component. ' +
184+
'Scripts inside React components are never executed when rendering on the client. ' +
185+
'Consider using template tag instead (https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template).\n' +
186+
' in script (at **)\n' +
187+
' in TogglingComponent (at **)',
188+
]);
189+
}
190+
178191
const container2 = document.createElement('div');
179192
const root2 = ReactDOMClient.createRoot(container2);
180193
expect(() => {
@@ -189,6 +202,7 @@ describe('ReactEmptyComponent', () => {
189202
'mount SCRIPT',
190203
'update undefined',
191204
]);
205+
expect(container2.innerHTML).toBe('');
192206
});
193207

194208
it(

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

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
describe('when Trusted Types are available in global object', () => {
1313
let React;
1414
let ReactDOMClient;
15-
let ReactFeatureFlags;
1615
let act;
1716
let assertConsoleErrorDev;
1817
let container;
@@ -33,8 +32,6 @@ describe('when Trusted Types are available in global object', () => {
3332
isScript: () => false,
3433
isScriptURL: () => false,
3534
};
36-
ReactFeatureFlags = require('shared/ReactFeatureFlags');
37-
ReactFeatureFlags.enableTrustedTypesIntegration = true;
3835
React = require('react');
3936
ReactDOMClient = require('react-dom/client');
4037
({act, assertConsoleErrorDev} = require('internal-test-utils'));
@@ -118,7 +115,11 @@ describe('when Trusted Types are available in global object', () => {
118115
expect(setAttributeCalls[0][0]).toBe(container.firstChild);
119116
expect(setAttributeCalls[0][1]).toBe('data-foo');
120117
// Ensure it didn't get stringified when passed to a DOM sink:
121-
expect(setAttributeCalls[0][2]).toBe(ttObject1);
118+
if (gate('enableTrustedTypesIntegration')) {
119+
expect(setAttributeCalls[0][2]).toBe(ttObject1);
120+
} else {
121+
expect(setAttributeCalls[0][2]).toBe('<b>Hi</b>');
122+
}
122123

123124
setAttributeCalls.length = 0;
124125
await act(() => {
@@ -129,7 +130,11 @@ describe('when Trusted Types are available in global object', () => {
129130
expect(setAttributeCalls[0][0]).toBe(container.firstChild);
130131
expect(setAttributeCalls[0][1]).toBe('data-foo');
131132
// Ensure it didn't get stringified when passed to a DOM sink:
132-
expect(setAttributeCalls[0][2]).toBe(ttObject2);
133+
if (gate('enableTrustedTypesIntegration')) {
134+
expect(setAttributeCalls[0][2]).toBe(ttObject2);
135+
} else {
136+
expect(setAttributeCalls[0][2]).toBe('<b>Bye</b>');
137+
}
133138
} finally {
134139
Element.prototype.setAttribute = setAttribute;
135140
}
@@ -153,7 +158,11 @@ describe('when Trusted Types are available in global object', () => {
153158
expect(setAttributeCalls[0][0]).toBe(container.firstChild);
154159
expect(setAttributeCalls[0][1]).toBe('class');
155160
// Ensure it didn't get stringified when passed to a DOM sink:
156-
expect(setAttributeCalls[0][2]).toBe(ttObject1);
161+
if (gate('enableTrustedTypesIntegration')) {
162+
expect(setAttributeCalls[0][2]).toBe(ttObject1);
163+
} else {
164+
expect(setAttributeCalls[0][2]).toBe('<b>Hi</b>');
165+
}
157166

158167
setAttributeCalls.length = 0;
159168
await act(() => {
@@ -164,7 +173,11 @@ describe('when Trusted Types are available in global object', () => {
164173
expect(setAttributeCalls[0][0]).toBe(container.firstChild);
165174
expect(setAttributeCalls[0][1]).toBe('class');
166175
// Ensure it didn't get stringified when passed to a DOM sink:
167-
expect(setAttributeCalls[0][2]).toBe(ttObject2);
176+
if (gate('enableTrustedTypesIntegration')) {
177+
expect(setAttributeCalls[0][2]).toBe(ttObject2);
178+
} else {
179+
expect(setAttributeCalls[0][2]).toBe('<b>Bye</b>');
180+
}
168181
} finally {
169182
Element.prototype.setAttribute = setAttribute;
170183
}
@@ -189,7 +202,11 @@ describe('when Trusted Types are available in global object', () => {
189202
expect(setAttributeNSCalls[0][1]).toBe('http://www.w3.org/1999/xlink');
190203
expect(setAttributeNSCalls[0][2]).toBe('xlink:href');
191204
// Ensure it didn't get stringified when passed to a DOM sink:
192-
expect(setAttributeNSCalls[0][3]).toBe(ttObject1);
205+
if (gate('enableTrustedTypesIntegration')) {
206+
expect(setAttributeNSCalls[0][3]).toBe(ttObject1);
207+
} else {
208+
expect(setAttributeNSCalls[0][3]).toBe('<b>Hi</b>');
209+
}
193210

194211
setAttributeNSCalls.length = 0;
195212
await act(() => {
@@ -201,7 +218,11 @@ describe('when Trusted Types are available in global object', () => {
201218
expect(setAttributeNSCalls[0][1]).toBe('http://www.w3.org/1999/xlink');
202219
expect(setAttributeNSCalls[0][2]).toBe('xlink:href');
203220
// Ensure it didn't get stringified when passed to a DOM sink:
204-
expect(setAttributeNSCalls[0][3]).toBe(ttObject2);
221+
if (gate('enableTrustedTypesIntegration')) {
222+
expect(setAttributeNSCalls[0][3]).toBe(ttObject2);
223+
} else {
224+
expect(setAttributeNSCalls[0][3]).toBe('<b>Bye</b>');
225+
}
205226
} finally {
206227
Element.prototype.setAttributeNS = setAttributeNS;
207228
}
@@ -212,13 +233,15 @@ describe('when Trusted Types are available in global object', () => {
212233
await act(() => {
213234
root.render(<script>alert("I am not executed")</script>);
214235
});
215-
assertConsoleErrorDev([
216-
'Encountered a script tag while rendering React component. ' +
217-
'Scripts inside React components are never executed when rendering ' +
218-
'on the client. Consider using template tag instead ' +
219-
'(https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template).\n' +
220-
' in script (at **)',
221-
]);
236+
if (gate('enableTrustedTypesIntegration')) {
237+
assertConsoleErrorDev([
238+
'Encountered a script tag while rendering React component. ' +
239+
'Scripts inside React components are never executed when rendering ' +
240+
'on the client. Consider using template tag instead ' +
241+
'(https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template).\n' +
242+
' in script (at **)',
243+
]);
244+
}
222245

223246
// check that the warning is printed only once
224247
await act(() => {

packages/shared/CheckStringCoercion.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ export function checkAttributeStringCoercion(
7676
attributeName: string,
7777
): void | string {
7878
if (__DEV__) {
79+
// TODO: for enableTrustedTypesIntegration we don't toString this
80+
// so we shouldn't need the DEV warning.
7981
if (willCoercionThrow(value)) {
8082
console.error(
8183
'The provided `%s` attribute is an unsupported type %s.' +

packages/shared/forks/ReactFeatureFlags.www-dynamic.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,11 @@ export const enableScrollEndPolyfill: boolean = __VARIANT__;
3535
export const enableFragmentRefs: boolean = __VARIANT__;
3636
export const enableFragmentRefsScrollIntoView: boolean = __VARIANT__;
3737
export const enableAsyncDebugInfo: boolean = __VARIANT__;
38-
3938
export const enableInternalInstanceMap: boolean = __VARIANT__;
39+
export const enableTrustedTypesIntegration: boolean = __VARIANT__;
4040

4141
// TODO: These flags are hard-coded to the default values used in open source.
4242
// Update the tests so that they pass in either mode, then set these
4343
// to __VARIANT__.
44-
export const enableTrustedTypesIntegration: boolean = false;
4544
// You probably *don't* want to add more hardcoded ones.
4645
// Instead, try to add them above with the __VARIANT__ value.

0 commit comments

Comments
 (0)