From d9b663c9c3749e2ff2f6bee727d48a53768c0a59 Mon Sep 17 00:00:00 2001 From: sebmarkbage Date: Thu, 30 Mar 2023 22:43:52 +0000 Subject: [PATCH] Limit the meaning of "custom element" to not include `is` (#26524) This PR has a bunch of surrounding refactoring. See individual commits. The main change is that we no longer special case `typeof is === 'string'` as a special case according to the `enableCustomElementPropertySupport` flag. Effectively this means that you can't use custom properties/events, other than the ones React knows about on `` extensions. This is unfortunate but there's too many paths that are forked in inconsistent ways since we fork based on tag name. I think __the solution is to let all React elements set unknown properties/events in the same way as this flag__ but that's a bigger change than this flag implies. Since `is` is not universally supported yet anyway, this doesn't seem like a huge loss. Attributes still work. We still support passing the `is` prop and turn that into the appropriate createElement call. @josepharhar DiffTrain build for [43a70a610dd2cc298ab5592deebfbf8f7bbac127](https://github.com/facebook/react/commit/43a70a610dd2cc298ab5592deebfbf8f7bbac127) --- compiled/facebook-www/REVISION | 2 +- compiled/facebook-www/React-dev.modern.js | 2 +- compiled/facebook-www/ReactART-dev.classic.js | 2 +- compiled/facebook-www/ReactART-prod.modern.js | 4 +- compiled/facebook-www/ReactDOM-dev.classic.js | 412 ++++++++---------- compiled/facebook-www/ReactDOM-dev.modern.js | 412 ++++++++---------- .../facebook-www/ReactDOM-prod.classic.js | 270 ++++++------ compiled/facebook-www/ReactDOM-prod.modern.js | 270 ++++++------ .../ReactDOM-profiling.classic.js | 256 +++++------ .../facebook-www/ReactDOM-profiling.modern.js | 256 +++++------ .../ReactDOMServer-dev.classic.js | 16 +- .../facebook-www/ReactDOMServer-dev.modern.js | 16 +- .../ReactDOMServer-prod.classic.js | 4 +- .../ReactDOMServer-prod.modern.js | 4 +- .../ReactDOMServerStreaming-dev.modern.js | 14 +- .../ReactDOMServerStreaming-prod.modern.js | 2 +- .../ReactDOMTesting-dev.classic.js | 412 ++++++++---------- .../ReactDOMTesting-dev.modern.js | 412 ++++++++---------- .../ReactDOMTesting-prod.classic.js | 270 ++++++------ .../ReactDOMTesting-prod.modern.js | 270 ++++++------ .../ReactTestRenderer-dev.modern.js | 2 +- compiled/facebook-www/WARNINGS | 3 +- 22 files changed, 1477 insertions(+), 1834 deletions(-) diff --git a/compiled/facebook-www/REVISION b/compiled/facebook-www/REVISION index 176c4f3de34af..51bbf4e636808 100644 --- a/compiled/facebook-www/REVISION +++ b/compiled/facebook-www/REVISION @@ -1 +1 @@ -1a1d61fed98a02c9b1bac029d0bc11c3e4db896d +43a70a610dd2cc298ab5592deebfbf8f7bbac127 diff --git a/compiled/facebook-www/React-dev.modern.js b/compiled/facebook-www/React-dev.modern.js index 4952cb703ab6e..17806c543b3db 100644 --- a/compiled/facebook-www/React-dev.modern.js +++ b/compiled/facebook-www/React-dev.modern.js @@ -27,7 +27,7 @@ if ( } "use strict"; -var ReactVersion = "18.3.0-www-modern-8f5a57f2"; +var ReactVersion = "18.3.0-www-modern-b298fcd9"; // ATTENTION // When adding new symbols to this file, diff --git a/compiled/facebook-www/ReactART-dev.classic.js b/compiled/facebook-www/ReactART-dev.classic.js index 2319b4237fb84..7886e7dc1157e 100644 --- a/compiled/facebook-www/ReactART-dev.classic.js +++ b/compiled/facebook-www/ReactART-dev.classic.js @@ -69,7 +69,7 @@ function _assertThisInitialized(self) { return self; } -var ReactVersion = "18.3.0-www-classic-26d7a5d5"; +var ReactVersion = "18.3.0-www-classic-8643ce3a"; var LegacyRoot = 0; var ConcurrentRoot = 1; diff --git a/compiled/facebook-www/ReactART-prod.modern.js b/compiled/facebook-www/ReactART-prod.modern.js index c17cd1d589db5..7d738d7dcf2ad 100644 --- a/compiled/facebook-www/ReactART-prod.modern.js +++ b/compiled/facebook-www/ReactART-prod.modern.js @@ -9688,7 +9688,7 @@ var slice = Array.prototype.slice, return null; }, bundleType: 0, - version: "18.3.0-www-modern-132fb191", + version: "18.3.0-www-modern-b8a2f36f", rendererPackageName: "react-art" }; var internals$jscomp$inline_1304 = { @@ -9719,7 +9719,7 @@ var internals$jscomp$inline_1304 = { scheduleRoot: null, setRefreshHandler: null, getCurrentFiber: null, - reconcilerVersion: "18.3.0-www-modern-132fb191" + reconcilerVersion: "18.3.0-www-modern-b8a2f36f" }; if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { var hook$jscomp$inline_1305 = __REACT_DEVTOOLS_GLOBAL_HOOK__; diff --git a/compiled/facebook-www/ReactDOM-dev.classic.js b/compiled/facebook-www/ReactDOM-dev.classic.js index 6e7a4723eaae7..0ababccc7850e 100644 --- a/compiled/facebook-www/ReactDOM-dev.classic.js +++ b/compiled/facebook-www/ReactDOM-dev.classic.js @@ -3635,11 +3635,6 @@ function getValueForAttributeOnCustomComponent(node, name, expected) { return expected === undefined ? undefined : null; } - if (enableCustomElementPropertySupport && name === "className") { - // className is a special cased property on the server to render as an attribute. - name = "class"; - } - var value = node.getAttribute(name); if (enableCustomElementPropertySupport) { @@ -3840,11 +3835,7 @@ function setValueForAttribute(node, name, value) { } } function setValueForPropertyOnCustomComponent(node, name, value) { - if ( - enableCustomElementPropertySupport && - name[0] === "o" && - name[1] === "n" - ) { + if (name[0] === "o" && name[1] === "n") { var useCapture = name.endsWith("Capture"); var eventName = name.substr(2, useCapture ? name.length - 9 : undefined); var prevProps = getFiberCurrentPropsFromNode(node); @@ -3870,45 +3861,17 @@ function setValueForPropertyOnCustomComponent(node, name, value) { } } - if (enableCustomElementPropertySupport && name in node) { + if (name in node) { node[name] = value; return; } - if (isAttributeNameSafe(name)) { - // shouldRemoveAttribute - if (value === null) { - node.removeAttribute(name); - return; - } - - switch (typeof value) { - case "undefined": - case "function": - case "symbol": - // eslint-disable-line - node.removeAttribute(name); - return; - - case "boolean": { - if (enableCustomElementPropertySupport) { - if (value === true) { - node.setAttribute(name, ""); - return; - } - - node.removeAttribute(name); - return; - } - } - } - - { - checkAttributeStringCoercion(value, name); - } + if (value === true) { + node.setAttribute(name, ""); + return; + } // From here, it's the same as any attribute - node.setAttribute(name, enableTrustedTypesIntegration ? value : "" + value); - } + setValueForAttribute(node, name, value); } var ReactCurrentDispatcher$2 = ReactSharedInternals.ReactCurrentDispatcher; @@ -5974,9 +5937,9 @@ function validateShorthandPropertyCollisionInDev(styleUpdates, nextStyles) { } } -function isCustomComponent(tagName, props) { +function isCustomElement(tagName, props) { if (tagName.indexOf("-") === -1) { - return typeof props.is === "string"; + return false; } switch (tagName) { @@ -7011,7 +6974,7 @@ function warnUnknownProperties(type, props, eventRegistry) { } function validateProperties(type, props, eventRegistry) { - if (isCustomComponent(type, props)) { + if (isCustomElement(type) || typeof props.is === "string") { return; } @@ -7019,21 +6982,10 @@ function validateProperties(type, props, eventRegistry) { } var didWarnInvalidHydration = false; -var didWarnScriptTags = false; -var warnedUnknownTags; var canDiffStyleForHydrationWarning; { - warnedUnknownTags = { - // There are working polyfills for . Let people use it. - dialog: true, - // Electron ships a custom tag to display external web content in - // an isolated frame and process. - // This tag is not present in non Electron environments such as JSDom which - // is often used for testing purposes. - // @see https://electronjs.org/docs/api/webview-tag - webview: true - }; // IE 11 parses & normalizes the style attribute as opposed to other + // 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 @@ -7041,7 +6993,6 @@ var canDiffStyleForHydrationWarning; // 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); } @@ -7201,11 +7152,6 @@ function checkForUnmatchedText( throw new Error("Text content does not match server-rendered HTML."); } } -function getOwnerDocumentFromRootContainer(rootContainerElement) { - return rootContainerElement.nodeType === DOCUMENT_NODE - ? rootContainerElement - : rootContainerElement.ownerDocument; -} function noop$2() {} @@ -7222,7 +7168,7 @@ function trapClickOnNonInteractiveElement(node) { node.onclick = noop$2; } -function setProp(domElement, tag, key, value, isCustomComponentTag, props) { +function setProp(domElement, tag, key, value, isCustomElementTag, props) { switch (key) { case "style": { if (value != null && typeof value !== "object") { @@ -7370,8 +7316,17 @@ function setProp(domElement, tag, key, value, isCustomComponentTag, props) { warnForInvalidEventListener(key, value); } } else { - if (isCustomComponentTag) { - setValueForPropertyOnCustomComponent(domElement, key, value); + if (isCustomElementTag) { + if (enableCustomElementPropertySupport) { + setValueForPropertyOnCustomComponent(domElement, key, value); + } else { + if (typeof value === "boolean") { + // Special case before the new flag is on + value = "" + value; + } + + setValueForAttribute(domElement, key, value); + } } else { if ( // shouldIgnoreAttribute @@ -7394,134 +7349,8 @@ function setProp(domElement, tag, key, value, isCustomComponentTag, props) { } } } -} // creates a script element that won't execute - -function createPotentiallyInlineScriptElement(ownerDocument) { - // Create the script via .innerHTML so its "parser-inserted" flag is - // set to true and it does not execute - var div = ownerDocument.createElement("div"); - - { - if (enableTrustedTypesIntegration && !didWarnScriptTags) { - error( - "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)." - ); - - didWarnScriptTags = true; - } - } - - div.innerHTML = "