Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 17 additions & 43 deletions packages/react-dom-bindings/src/client/ReactDOMComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import {
possibleRegistrationNames,
} from '../events/EventRegistry';

import {canUseDOM} from 'shared/ExecutionEnvironment';
import {checkHtmlStringCoercion} from 'shared/CheckStringCoercion';
import {checkAttributeStringCoercion} from 'shared/CheckStringCoercion';
import {checkControlledValueProps} from '../shared/ReactControlledValuePropTypes';
Expand Down Expand Up @@ -50,7 +49,6 @@ import {
} from './ReactDOMTextarea';
import {validateTextNesting} from './validateDOMNesting';
import {track} from './inputValueTracking';
import setInnerHTML from './setInnerHTML';
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can also delete setInnerHTML now, so I removed it in this diff.

import setTextContent from './setTextContent';
import {
createDangerousStringForStyles,
Expand All @@ -66,7 +64,6 @@ import {validateProperties as validateUnknownProperties} from '../shared/ReactDO
import sanitizeURL from '../shared/sanitizeURL';

import {
disableIEWorkarounds,
enableTrustedTypesIntegration,
enableFilterEmptyStringAttributesDOM,
} from 'shared/ReactFeatureFlags';
Expand All @@ -83,19 +80,8 @@ let didWarnFormActionTarget = false;
let didWarnFormActionMethod = false;
let didWarnForNewBooleanPropsWithEmptyValue: {[string]: boolean};
let didWarnPopoverTargetObject = false;
let canDiffStyleForHydrationWarning;
if (__DEV__) {
didWarnForNewBooleanPropsWithEmptyValue = {};
// IE 11 parses & normalizes the style attribute as opposed to other
// browsers. It adds spaces and sorts the properties in some
// non-alphabetical order. Handling that would require sorting CSS
// properties in the client & server versions or applying
// `expectedStyle` to a temporary DOM node to read its `style` attribute
// normalized. Since it only affects IE, we're skipping style warnings
// in that browser completely in favor of doing all that work.
// See https://github.com/facebook/react/issues/11807
canDiffStyleForHydrationWarning =
disableIEWorkarounds || (canUseDOM && !document.documentMode);
}

function validatePropertiesInDevelopment(type: string, props: any) {
Expand Down Expand Up @@ -579,11 +565,7 @@ function setProp(
'Can only set one of `children` or `props.dangerouslySetInnerHTML`.',
);
}
if (disableIEWorkarounds) {
domElement.innerHTML = nextHtml;
} else {
setInnerHTML(domElement, nextHtml);
}
domElement.innerHTML = nextHtml;
}
}
break;
Expand Down Expand Up @@ -939,11 +921,7 @@ function setPropOnCustomElement(
'Can only set one of `children` or `props.dangerouslySetInnerHTML`.',
);
}
if (disableIEWorkarounds) {
domElement.innerHTML = nextHtml;
} else {
setInnerHTML(domElement, nextHtml);
}
domElement.innerHTML = nextHtml;
}
}
break;
Expand Down Expand Up @@ -1931,27 +1909,23 @@ function diffHydratedStyles(
}
return;
}
if (canDiffStyleForHydrationWarning) {
// First we compare the string form and see if it's equivalent.
// This lets us bail out on anything that used to pass in this form.
// It also lets us compare anything that's not parsed by this browser.
const clientValue = createDangerousStringForStyles(value);
const serverValue = domElement.getAttribute('style');
// First we compare the string form and see if it's equivalent.
// This lets us bail out on anything that used to pass in this form.
// It also lets us compare anything that's not parsed by this browser.
const clientValue = createDangerousStringForStyles(value);
const serverValue = domElement.getAttribute('style');

if (serverValue === clientValue) {
return;
}
const normalizedClientValue =
normalizeMarkupForTextOrAttribute(clientValue);
const normalizedServerValue =
normalizeMarkupForTextOrAttribute(serverValue);
if (normalizedServerValue === normalizedClientValue) {
return;
}

// Otherwise, we create the object from the DOM for the diff view.
serverDifferences.style = getStylesObjectFromElement(domElement);
if (serverValue === clientValue) {
return;
}
const normalizedClientValue = normalizeMarkupForTextOrAttribute(clientValue);
const normalizedServerValue = normalizeMarkupForTextOrAttribute(serverValue);
if (normalizedServerValue === normalizedClientValue) {
return;
}

// Otherwise, we create the object from the DOM for the diff view.
serverDifferences.style = getStylesObjectFromElement(domElement);
}

function hydrateAttribute(
Expand Down
82 changes: 0 additions & 82 deletions packages/react-dom-bindings/src/client/setInnerHTML.js

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -27,73 +27,4 @@ describe('dangerouslySetInnerHTML', () => {
expect(container.firstChild.innerHTML).toBe('<h1>Hello</h1>');
});
});

describe('when the node does not have an innerHTML property', () => {
let innerHTMLDescriptor;

// In some versions of IE (TODO: which ones?) SVG nodes don't have
// innerHTML. To simulate this, we will take it off the Element prototype
// and put it onto the HTMLDivElement prototype. We expect that the logic
// checks for existence of innerHTML on SVG, and if one doesn't exist, falls
// back to using appendChild and removeChild.

beforeEach(() => {
innerHTMLDescriptor = Object.getOwnPropertyDescriptor(
Element.prototype,
'innerHTML',
);
delete Element.prototype.innerHTML;
Object.defineProperty(
HTMLDivElement.prototype,
'innerHTML',
innerHTMLDescriptor,
);
});

afterEach(() => {
delete HTMLDivElement.prototype.innerHTML;
Object.defineProperty(
Element.prototype,
'innerHTML',
innerHTMLDescriptor,
);
});

// @gate !disableIEWorkarounds
it('sets innerHTML on it', async () => {
const html = '<circle></circle>';
const container = document.createElementNS(
'http://www.w3.org/2000/svg',
'svg',
);
const root = ReactDOMClient.createRoot(container);
await act(() => {
root.render(<g dangerouslySetInnerHTML={{__html: html}} />);
});
const circle = container.firstChild.firstChild;
expect(circle.tagName).toBe('circle');
});

// @gate !disableIEWorkarounds
it('clears previous children', async () => {
const firstHtml = '<rect></rect>';
const secondHtml = '<circle></circle>';

const container = document.createElementNS(
'http://www.w3.org/2000/svg',
'svg',
);
const root = ReactDOMClient.createRoot(container);
await act(() => {
root.render(<g dangerouslySetInnerHTML={{__html: firstHtml}} />);
});
const rect = container.firstChild.firstChild;
expect(rect.tagName).toBe('rect');
await act(() => {
root.render(<g dangerouslySetInnerHTML={{__html: secondHtml}} />);
});
const circle = container.firstChild.firstChild;
expect(circle.tagName).toBe('circle');
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -206,56 +206,6 @@ describe('when Trusted Types are available in global object', () => {
}
});

describe('dangerouslySetInnerHTML in svg elements in Internet Explorer', () => {
let innerHTMLDescriptor;

// simulate svg elements in Internet Explorer which don't have 'innerHTML' property
beforeEach(() => {
innerHTMLDescriptor = Object.getOwnPropertyDescriptor(
Element.prototype,
'innerHTML',
);
delete Element.prototype.innerHTML;
Object.defineProperty(
HTMLDivElement.prototype,
'innerHTML',
innerHTMLDescriptor,
);
});

afterEach(() => {
delete HTMLDivElement.prototype.innerHTML;
Object.defineProperty(
Element.prototype,
'innerHTML',
innerHTMLDescriptor,
);
});

// @gate !disableIEWorkarounds
it('should log a warning', async () => {
class Component extends React.Component {
render() {
return <svg dangerouslySetInnerHTML={{__html: 'unsafe html'}} />;
}
}
const root = ReactDOMClient.createRoot(container);
await expect(async () => {
await act(() => {
root.render(<Component />);
});
}).toErrorDev(
"Using 'dangerouslySetInnerHTML' in an svg element with " +
'Trusted Types enabled in an Internet Explorer will cause ' +
'the trusted value to be converted to string. Assigning string ' +
"to 'innerHTML' will throw an error if Trusted Types are enforced. " +
"You can try to wrap your svg element inside a div and use 'dangerouslySetInnerHTML' " +
'on the enclosing div instead.',
);
expect(container.innerHTML).toBe('<svg>unsafe html</svg>');
});
});

it('should warn once when rendering script tag in jsx on client', async () => {
const root = ReactDOMClient.createRoot(container);
await expect(async () => {
Expand Down
4 changes: 0 additions & 4 deletions packages/shared/ReactFeatureFlags.js
Original file line number Diff line number Diff line change
Expand Up @@ -203,10 +203,6 @@ export const disableLegacyContextForFunctionComponents = true;
// TODO: clean up legacy <StrictMode /> once tests pass WWW.
export const useModernStrictMode = true;

// Not ready to break experimental yet.
// Remove IE and MsApp specific workarounds for innerHTML
export const disableIEWorkarounds = true;

// Filter certain DOM attributes (e.g. src, href) if their values are empty
// strings. This prevents e.g. <img src=""> from making an unnecessary HTTP
// request for certain browsers.
Expand Down
1 change: 0 additions & 1 deletion packages/shared/forks/ReactFeatureFlags.native-fb.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ export const debugRenderPhaseSideEffectsForStrictMode = __DEV__;
export const disableClientCache = true;
export const disableCommentsAsDOMContainers = true;
export const disableDefaultPropsExceptForClasses = true;
export const disableIEWorkarounds = true;
export const disableInputAttributeSyncing = false;
export const disableLegacyContext = false;
export const disableLegacyContextForFunctionComponents = false;
Expand Down
1 change: 0 additions & 1 deletion packages/shared/forks/ReactFeatureFlags.native-oss.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ export const alwaysThrottleRetries = false;
export const disableClientCache = true;
export const disableCommentsAsDOMContainers = true;
export const disableDefaultPropsExceptForClasses = true;
export const disableIEWorkarounds = true;
export const disableInputAttributeSyncing = false;
export const disableLegacyContext = true;
export const disableLegacyContextForFunctionComponents = true;
Expand Down
1 change: 0 additions & 1 deletion packages/shared/forks/ReactFeatureFlags.test-renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ export const enablePostpone = false;
export const enableHalt = false;
export const disableCommentsAsDOMContainers = true;
export const disableInputAttributeSyncing = false;
export const disableIEWorkarounds = true;
export const enableScopeAPI = false;
export const enableCreateEventHandleAPI = false;
export const enableSuspenseCallback = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ export const debugRenderPhaseSideEffectsForStrictMode = false;
export const disableClientCache = true;
export const disableCommentsAsDOMContainers = true;
export const disableDefaultPropsExceptForClasses = true;
export const disableIEWorkarounds = true;
export const disableInputAttributeSyncing = false;
export const disableLegacyContext = false;
export const disableLegacyContextForFunctionComponents = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ export const enablePostpone = false;
export const enableHalt = false;
export const disableCommentsAsDOMContainers = true;
export const disableInputAttributeSyncing = false;
export const disableIEWorkarounds = true;
export const enableScopeAPI = true;
export const enableCreateEventHandleAPI = false;
export const enableSuspenseCallback = true;
Expand Down
1 change: 0 additions & 1 deletion packages/shared/forks/ReactFeatureFlags.www.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ export const enableFabricCompleteRootInCommitPhase = false;
export const enableSuspenseAvoidThisFallback = true;
export const enableSuspenseAvoidThisFallbackFizz = false;

export const disableIEWorkarounds = true;
export const enableCPUSuspense = true;
export const enableUseMemoCacheHook = true;
export const enableUseEffectEventHook = true;
Expand Down
1 change: 0 additions & 1 deletion scripts/jest/setupTests.www.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ jest.mock('shared/ReactFeatureFlags', () => {
// These are hardcoded to true for the next release,
// but still run the tests against both variants until
// we remove the flag.
actual.disableIEWorkarounds = __VARIANT__;
actual.disableClientCache = __VARIANT__;

return actual;
Expand Down
Loading