mirror of
https://github.com/facebook/react.git
synced 2026-02-26 07:25:30 +00:00
[flags] make enableTrustedTypesIntegration dynamic (#35646)
Co-authored-by: Rick Hanlon <rickhanlonii@meta.com>
This commit is contained in:
@@ -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' +
|
||||
|
||||
@@ -602,6 +602,14 @@ describe('ReactDOMFloat', () => {
|
||||
'> <script href="foo">\n' +
|
||||
'\n' +
|
||||
' in script (at **)',
|
||||
...(gate('enableTrustedTypesIntegration')
|
||||
? [
|
||||
'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 **)',
|
||||
]
|
||||
: []),
|
||||
]);
|
||||
|
||||
root.render(
|
||||
@@ -2745,6 +2753,14 @@ body {
|
||||
'> <script itemProp="foo">\n' +
|
||||
'\n' +
|
||||
' in script (at **)',
|
||||
...(gate('enableTrustedTypesIntegration')
|
||||
? [
|
||||
'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 **)',
|
||||
]
|
||||
: []),
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
@@ -2277,15 +2277,21 @@ describe('ReactDOMForm', () => {
|
||||
await submit(formRef.current);
|
||||
assertLog([actionFn]);
|
||||
|
||||
// Everything else is toString-ed
|
||||
// Everything else is toString-ed, unless trusted types are enabled.
|
||||
class MyAction {
|
||||
toString() {
|
||||
return 'stringified action';
|
||||
}
|
||||
}
|
||||
await act(() => root.render(<Form action={new MyAction()} />));
|
||||
const instance = new MyAction();
|
||||
|
||||
await act(() => root.render(<Form action={instance} />));
|
||||
await submit(formRef.current);
|
||||
assertLog(['stringified action']);
|
||||
assertLog(
|
||||
gate('enableTrustedTypesIntegration')
|
||||
? [instance]
|
||||
: ['stringified action'],
|
||||
);
|
||||
});
|
||||
|
||||
it('form actions should retain status when nested state changes', async () => {
|
||||
|
||||
@@ -212,6 +212,11 @@ describe('ReactDOMServerIntegration - Untrusted URLs', () => {
|
||||
expectedToStringCalls *= 2;
|
||||
}
|
||||
|
||||
if (gate('enableTrustedTypesIntegration') && render === clientCleanRender) {
|
||||
// Trusted types does another toString.
|
||||
expectedToStringCalls += 1;
|
||||
}
|
||||
|
||||
let toStringCalls = 0;
|
||||
const firstIsSafe = {
|
||||
toString() {
|
||||
|
||||
@@ -17,6 +17,7 @@ let TogglingComponent;
|
||||
let act;
|
||||
let Scheduler;
|
||||
let assertLog;
|
||||
let assertConsoleErrorDev;
|
||||
|
||||
let container;
|
||||
|
||||
@@ -34,6 +35,7 @@ describe('ReactEmptyComponent', () => {
|
||||
const InternalTestUtils = require('internal-test-utils');
|
||||
act = InternalTestUtils.act;
|
||||
assertLog = InternalTestUtils.assertLog;
|
||||
assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;
|
||||
|
||||
container = document.createElement('div');
|
||||
|
||||
@@ -175,6 +177,17 @@ describe('ReactEmptyComponent', () => {
|
||||
});
|
||||
}).not.toThrow();
|
||||
|
||||
expect(container.innerHTML).toBe('<script></script>');
|
||||
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(
|
||||
|
||||
@@ -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('<b>Hi</b>');
|
||||
}
|
||||
|
||||
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('<b>Bye</b>');
|
||||
}
|
||||
} 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('<b>Hi</b>');
|
||||
}
|
||||
|
||||
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('<b>Bye</b>');
|
||||
}
|
||||
} 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('<b>Hi</b>');
|
||||
}
|
||||
|
||||
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('<b>Bye</b>');
|
||||
}
|
||||
} finally {
|
||||
Element.prototype.setAttributeNS = setAttributeNS;
|
||||
}
|
||||
@@ -212,13 +233,15 @@ describe('when Trusted Types are available in global object', () => {
|
||||
await act(() => {
|
||||
root.render(<script>alert("I am not executed")</script>);
|
||||
});
|
||||
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(() => {
|
||||
|
||||
@@ -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.' +
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user