mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Remove disableIEWorkarounds (#31756)
Based off https://github.com/facebook/react/pull/31755 This is landed everywhere.
This commit is contained in:
+17
-43
@@ -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';
|
||||
@@ -50,7 +49,6 @@ import {
|
||||
} from './ReactDOMTextarea';
|
||||
import {validateTextNesting} from './validateDOMNesting';
|
||||
import {track} from './inputValueTracking';
|
||||
import setInnerHTML from './setInnerHTML';
|
||||
import setTextContent from './setTextContent';
|
||||
import {
|
||||
createDangerousStringForStyles,
|
||||
@@ -66,7 +64,6 @@ import {validateProperties as validateUnknownProperties} from '../shared/ReactDO
|
||||
import sanitizeURL from '../shared/sanitizeURL';
|
||||
|
||||
import {
|
||||
disableIEWorkarounds,
|
||||
enableTrustedTypesIntegration,
|
||||
enableFilterEmptyStringAttributesDOM,
|
||||
} from 'shared/ReactFeatureFlags';
|
||||
@@ -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) {
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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(
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
|
||||
/* globals MSApp */
|
||||
|
||||
import {SVG_NAMESPACE} from './DOMNamespaces';
|
||||
import {enableTrustedTypesIntegration} from 'shared/ReactFeatureFlags';
|
||||
|
||||
// SVG temp container for IE lacking innerHTML
|
||||
let reusableSVGContainer: HTMLElement;
|
||||
|
||||
function setInnerHTMLImpl(
|
||||
node: Element,
|
||||
html: {valueOf(): {toString(): string, ...}, ...},
|
||||
): void {
|
||||
if (node.namespaceURI === SVG_NAMESPACE) {
|
||||
if (__DEV__) {
|
||||
if (enableTrustedTypesIntegration) {
|
||||
// TODO: reconsider the text of this warning and when it should show
|
||||
// before enabling the feature flag.
|
||||
if (typeof trustedTypes !== 'undefined') {
|
||||
console.error(
|
||||
"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.',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!('innerHTML' in node)) {
|
||||
// IE does not have innerHTML for SVG nodes, so instead we inject the
|
||||
// new markup in a temp node and then move the child nodes across into
|
||||
// the target node
|
||||
reusableSVGContainer =
|
||||
reusableSVGContainer || document.createElement('div');
|
||||
reusableSVGContainer.innerHTML =
|
||||
'<svg>' + html.valueOf().toString() + '</svg>';
|
||||
const svgNode = reusableSVGContainer.firstChild;
|
||||
while (node.firstChild) {
|
||||
node.removeChild(node.firstChild);
|
||||
}
|
||||
// $FlowFixMe[incompatible-use]
|
||||
// $FlowFixMe[incompatible-type]
|
||||
while (svgNode.firstChild) {
|
||||
node.appendChild(svgNode.firstChild);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
node.innerHTML = (html: any);
|
||||
}
|
||||
|
||||
let setInnerHTML: (
|
||||
node: Element,
|
||||
html: {valueOf(): {toString(): string, ...}, ...},
|
||||
) => void = setInnerHTMLImpl;
|
||||
// $FlowFixMe[cannot-resolve-name]
|
||||
if (typeof MSApp !== 'undefined' && MSApp.execUnsafeLocalFunction) {
|
||||
/**
|
||||
* Create a function which has 'unsafe' privileges (required by windows8 apps)
|
||||
*/
|
||||
setInnerHTML = function (
|
||||
node: Element,
|
||||
html: {valueOf(): {toString(): string, ...}, ...},
|
||||
): void {
|
||||
// $FlowFixMe[cannot-resolve-name]
|
||||
return MSApp.execUnsafeLocalFunction(function () {
|
||||
return setInnerHTMLImpl(node, html);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export default setInnerHTML;
|
||||
@@ -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');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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 () => {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user