Add flag to test fast jsx (#28816)

Following #28768, add a path to testing Fast JSX on www.

We want to measure the impact of Fast JSX and enable a path to testing
before string refs are completely removed in www (which is a work in
progress).

Without `disableStringRefs`, we need to copy any object with a `ref` key
so we can pass it through `coerceStringRef()` and copy it into the
object. This de-opt path is what is gated behind
`enableFastJSXWithStringRefs`.

The additional checks should have no perf impact in OSS as the flags
remain true there and the build output is not changed. For www, I've
benchmarked the addition of the boolean checks with values cached at
module scope. There is no significant change observed from our
benchmarks and any latency will apply to test and control branches
evenly. This added experiment complexity is temporary. We should be able
to clean it up, along with the flag checks for `enableRefAsProp` and
`disableStringRefs` shortly.

DiffTrain build for [1beb73de0f](https://github.com/facebook/react/commit/1beb73de0f7c3261a0de37620453b102caaa6236)
This commit is contained in:
jackpope
2024-05-03 14:52:18 +00:00
parent a73bb0e53e
commit bc32edada7
9 changed files with 95 additions and 47 deletions
@@ -25,8 +25,8 @@ var enableDebugTracing = dynamicFeatureFlags.enableDebugTracing,
enableTransitionTracing = dynamicFeatureFlags.enableTransitionTracing,
enableRenderableContext = dynamicFeatureFlags.enableRenderableContext,
enableRefAsProp = dynamicFeatureFlags.enableRefAsProp,
disableDefaultPropsExceptForClasses = dynamicFeatureFlags.disableDefaultPropsExceptForClasses;
// On WWW, false is used for a new modern build.
disableDefaultPropsExceptForClasses = dynamicFeatureFlags.disableDefaultPropsExceptForClasses,
enableFastJSX = dynamicFeatureFlags.enableFastJSX; // On WWW, false is used for a new modern build.
// because JSX is an extremely hot path.
var disableStringRefs = false;
@@ -941,6 +941,9 @@ var didWarnAboutElementRef;
didWarnAboutElementRef = {};
}
var enableFastJSXWithStringRefs = enableFastJSX && enableRefAsProp;
var enableFastJSXWithoutStringRefs = enableFastJSXWithStringRefs && disableStringRefs;
function hasValidRef(config) {
{
if (hasOwnProperty.call(config, 'ref')) {
@@ -1289,7 +1292,7 @@ function jsxDEV$1(type, config, maybeKey, isStaticChildren, source, self) {
var props;
if (enableRefAsProp && disableStringRefs && !('key' in config)) {
if ((enableFastJSXWithoutStringRefs || enableFastJSXWithStringRefs && !('ref' in config)) && !('key' in config)) {
// If key was not spread in, we can reuse the original props object. This
// only works for `jsx`, not `createElement`, because `jsx` is a compiler
// target and the compiler always passes a new object. For `createElement`,
@@ -25,8 +25,8 @@ var enableDebugTracing = dynamicFeatureFlags.enableDebugTracing,
enableTransitionTracing = dynamicFeatureFlags.enableTransitionTracing,
enableRenderableContext = dynamicFeatureFlags.enableRenderableContext,
enableRefAsProp = dynamicFeatureFlags.enableRefAsProp,
disableDefaultPropsExceptForClasses = dynamicFeatureFlags.disableDefaultPropsExceptForClasses;
// On WWW, true is used for a new modern build.
disableDefaultPropsExceptForClasses = dynamicFeatureFlags.disableDefaultPropsExceptForClasses,
enableFastJSX = dynamicFeatureFlags.enableFastJSX; // On WWW, true is used for a new modern build.
// because JSX is an extremely hot path.
var disableStringRefs = false;
@@ -944,6 +944,9 @@ var didWarnAboutElementRef;
didWarnAboutElementRef = {};
}
var enableFastJSXWithStringRefs = enableFastJSX && enableRefAsProp;
var enableFastJSXWithoutStringRefs = enableFastJSXWithStringRefs && disableStringRefs;
function hasValidRef(config) {
{
if (hasOwnProperty.call(config, 'ref')) {
@@ -1292,7 +1295,7 @@ function jsxDEV$1(type, config, maybeKey, isStaticChildren, source, self) {
var props;
if (enableRefAsProp && disableStringRefs && !('key' in config)) {
if ((enableFastJSXWithoutStringRefs || enableFastJSXWithStringRefs && !('ref' in config)) && !('key' in config)) {
// If key was not spread in, we can reuse the original props object. This
// only works for `jsx`, not `createElement`, because `jsx` is a compiler
// target and the compiler always passes a new object. For `createElement`,
+1 -1
View File
@@ -1 +1 @@
73bcdfbae57545aa8f88ecdf67426275610b5573
1beb73de0f7c3261a0de37620453b102caaa6236
+7 -4
View File
@@ -25,7 +25,7 @@ if (
) {
__REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error());
}
var ReactVersion = '19.0.0-www-classic-e0403cc2';
var ReactVersion = '19.0.0-www-classic-f1929680';
// Re-export dynamic flags from the www version.
var dynamicFeatureFlags = require('ReactFeatureFlags');
@@ -34,8 +34,8 @@ var enableDebugTracing = dynamicFeatureFlags.enableDebugTracing,
enableTransitionTracing = dynamicFeatureFlags.enableTransitionTracing,
enableRenderableContext = dynamicFeatureFlags.enableRenderableContext,
enableRefAsProp = dynamicFeatureFlags.enableRefAsProp,
disableDefaultPropsExceptForClasses = dynamicFeatureFlags.disableDefaultPropsExceptForClasses;
// On WWW, false is used for a new modern build.
disableDefaultPropsExceptForClasses = dynamicFeatureFlags.disableDefaultPropsExceptForClasses,
enableFastJSX = dynamicFeatureFlags.enableFastJSX; // On WWW, false is used for a new modern build.
// because JSX is an extremely hot path.
var disableStringRefs = false;
@@ -1224,6 +1224,9 @@ var didWarnAboutOldJSXRuntime;
didWarnAboutElementRef = {};
}
var enableFastJSXWithStringRefs = enableFastJSX && enableRefAsProp;
var enableFastJSXWithoutStringRefs = enableFastJSXWithStringRefs && disableStringRefs;
function hasValidRef(config) {
{
if (hasOwnProperty.call(config, 'ref')) {
@@ -1596,7 +1599,7 @@ function jsxDEV$1(type, config, maybeKey, isStaticChildren, source, self) {
var props;
if (enableRefAsProp && disableStringRefs && !('key' in config)) {
if ((enableFastJSXWithoutStringRefs || enableFastJSXWithStringRefs && !('ref' in config)) && !('key' in config)) {
// If key was not spread in, we can reuse the original props object. This
// only works for `jsx`, not `createElement`, because `jsx` is a compiler
// target and the compiler always passes a new object. For `createElement`,
+7 -4
View File
@@ -25,7 +25,7 @@ if (
) {
__REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error());
}
var ReactVersion = '19.0.0-www-modern-65139682';
var ReactVersion = '19.0.0-www-modern-1ac5c7b0';
// Re-export dynamic flags from the www version.
var dynamicFeatureFlags = require('ReactFeatureFlags');
@@ -34,8 +34,8 @@ var enableDebugTracing = dynamicFeatureFlags.enableDebugTracing,
enableTransitionTracing = dynamicFeatureFlags.enableTransitionTracing,
enableRenderableContext = dynamicFeatureFlags.enableRenderableContext,
enableRefAsProp = dynamicFeatureFlags.enableRefAsProp,
disableDefaultPropsExceptForClasses = dynamicFeatureFlags.disableDefaultPropsExceptForClasses;
// On WWW, true is used for a new modern build.
disableDefaultPropsExceptForClasses = dynamicFeatureFlags.disableDefaultPropsExceptForClasses,
enableFastJSX = dynamicFeatureFlags.enableFastJSX; // On WWW, true is used for a new modern build.
// because JSX is an extremely hot path.
var disableStringRefs = false;
@@ -1227,6 +1227,9 @@ var didWarnAboutOldJSXRuntime;
didWarnAboutElementRef = {};
}
var enableFastJSXWithStringRefs = enableFastJSX && enableRefAsProp;
var enableFastJSXWithoutStringRefs = enableFastJSXWithStringRefs && disableStringRefs;
function hasValidRef(config) {
{
if (hasOwnProperty.call(config, 'ref')) {
@@ -1599,7 +1602,7 @@ function jsxDEV$1(type, config, maybeKey, isStaticChildren, source, self) {
var props;
if (enableRefAsProp && disableStringRefs && !('key' in config)) {
if ((enableFastJSXWithoutStringRefs || enableFastJSXWithStringRefs && !('ref' in config)) && !('key' in config)) {
// If key was not spread in, we can reuse the original props object. This
// only works for `jsx`, not `createElement`, because `jsx` is a compiler
// target and the compiler always passes a new object. For `createElement`,
+17 -8
View File
@@ -17,6 +17,7 @@ var dynamicFeatureFlags = require("ReactFeatureFlags"),
enableRefAsProp = dynamicFeatureFlags.enableRefAsProp,
disableDefaultPropsExceptForClasses =
dynamicFeatureFlags.disableDefaultPropsExceptForClasses,
enableFastJSX = dynamicFeatureFlags.enableFastJSX,
REACT_LEGACY_ELEMENT_TYPE = Symbol.for("react.element"),
REACT_PORTAL_TYPE = Symbol.for("react.portal"),
REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"),
@@ -93,6 +94,8 @@ function getOwner() {
var dispatcher = ReactSharedInternals.A;
return null === dispatcher ? null : dispatcher.getOwner();
}
var enableFastJSXWithStringRefs = enableFastJSX && enableRefAsProp,
enableFastJSXWithoutStringRefs = enableFastJSXWithStringRefs && !1;
function ReactElement(type, key, _ref, self, source, owner, props) {
enableRefAsProp &&
((_ref = props.ref), (_ref = void 0 !== _ref ? _ref : null));
@@ -113,13 +116,19 @@ function jsxProd(type, config, maybeKey) {
void 0 === config.ref ||
enableRefAsProp ||
((ref = config.ref), (ref = coerceStringRef(ref, getOwner(), type)));
maybeKey = {};
for (var propName in config)
"key" === propName ||
(!enableRefAsProp && "ref" === propName) ||
(enableRefAsProp && "ref" === propName
? (maybeKey.ref = coerceStringRef(config[propName], getOwner(), type))
: (maybeKey[propName] = config[propName]));
if (
(!enableFastJSXWithoutStringRefs &&
(!enableFastJSXWithStringRefs || "ref" in config)) ||
"key" in config
) {
maybeKey = {};
for (var propName in config)
"key" === propName ||
(!enableRefAsProp && "ref" === propName) ||
(enableRefAsProp && "ref" === propName
? (maybeKey.ref = coerceStringRef(config[propName], getOwner(), type))
: (maybeKey[propName] = config[propName]));
} else maybeKey = config;
if (!disableDefaultPropsExceptForClasses && type && type.defaultProps) {
config = type.defaultProps;
for (var propName$0 in config)
@@ -675,4 +684,4 @@ exports.useSyncExternalStore = function (
exports.useTransition = function () {
return ReactSharedInternals.H.useTransition();
};
exports.version = "19.0.0-www-classic-8ffd6973";
exports.version = "19.0.0-www-classic-af056f91";
+17 -8
View File
@@ -17,6 +17,7 @@ var dynamicFeatureFlags = require("ReactFeatureFlags"),
enableRefAsProp = dynamicFeatureFlags.enableRefAsProp,
disableDefaultPropsExceptForClasses =
dynamicFeatureFlags.disableDefaultPropsExceptForClasses,
enableFastJSX = dynamicFeatureFlags.enableFastJSX,
REACT_LEGACY_ELEMENT_TYPE = Symbol.for("react.element"),
REACT_PORTAL_TYPE = Symbol.for("react.portal"),
REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"),
@@ -93,6 +94,8 @@ function getOwner() {
var dispatcher = ReactSharedInternals.A;
return null === dispatcher ? null : dispatcher.getOwner();
}
var enableFastJSXWithStringRefs = enableFastJSX && enableRefAsProp,
enableFastJSXWithoutStringRefs = enableFastJSXWithStringRefs && !1;
function ReactElement(type, key, _ref, self, source, owner, props) {
enableRefAsProp &&
((_ref = props.ref), (_ref = void 0 !== _ref ? _ref : null));
@@ -113,13 +116,19 @@ function jsxProd(type, config, maybeKey) {
void 0 === config.ref ||
enableRefAsProp ||
((ref = config.ref), (ref = coerceStringRef(ref, getOwner(), type)));
maybeKey = {};
for (var propName in config)
"key" === propName ||
(!enableRefAsProp && "ref" === propName) ||
(enableRefAsProp && "ref" === propName
? (maybeKey.ref = coerceStringRef(config[propName], getOwner(), type))
: (maybeKey[propName] = config[propName]));
if (
(!enableFastJSXWithoutStringRefs &&
(!enableFastJSXWithStringRefs || "ref" in config)) ||
"key" in config
) {
maybeKey = {};
for (var propName in config)
"key" === propName ||
(!enableRefAsProp && "ref" === propName) ||
(enableRefAsProp && "ref" === propName
? (maybeKey.ref = coerceStringRef(config[propName], getOwner(), type))
: (maybeKey[propName] = config[propName]));
} else maybeKey = config;
if (!disableDefaultPropsExceptForClasses && type && type.defaultProps) {
config = type.defaultProps;
for (var propName$0 in config)
@@ -675,4 +684,4 @@ exports.useSyncExternalStore = function (
exports.useTransition = function () {
return ReactSharedInternals.H.useTransition();
};
exports.version = "19.0.0-www-modern-8ffd6973";
exports.version = "19.0.0-www-modern-af056f91";
@@ -21,6 +21,7 @@ var dynamicFeatureFlags = require("ReactFeatureFlags"),
enableRefAsProp = dynamicFeatureFlags.enableRefAsProp,
disableDefaultPropsExceptForClasses =
dynamicFeatureFlags.disableDefaultPropsExceptForClasses,
enableFastJSX = dynamicFeatureFlags.enableFastJSX,
REACT_LEGACY_ELEMENT_TYPE = Symbol.for("react.element"),
REACT_PORTAL_TYPE = Symbol.for("react.portal"),
REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"),
@@ -97,6 +98,8 @@ function getOwner() {
var dispatcher = ReactSharedInternals.A;
return null === dispatcher ? null : dispatcher.getOwner();
}
var enableFastJSXWithStringRefs = enableFastJSX && enableRefAsProp,
enableFastJSXWithoutStringRefs = enableFastJSXWithStringRefs && !1;
function ReactElement(type, key, _ref, self, source, owner, props) {
enableRefAsProp &&
((_ref = props.ref), (_ref = void 0 !== _ref ? _ref : null));
@@ -117,13 +120,19 @@ function jsxProd(type, config, maybeKey) {
void 0 === config.ref ||
enableRefAsProp ||
((ref = config.ref), (ref = coerceStringRef(ref, getOwner(), type)));
maybeKey = {};
for (var propName in config)
"key" === propName ||
(!enableRefAsProp && "ref" === propName) ||
(enableRefAsProp && "ref" === propName
? (maybeKey.ref = coerceStringRef(config[propName], getOwner(), type))
: (maybeKey[propName] = config[propName]));
if (
(!enableFastJSXWithoutStringRefs &&
(!enableFastJSXWithStringRefs || "ref" in config)) ||
"key" in config
) {
maybeKey = {};
for (var propName in config)
"key" === propName ||
(!enableRefAsProp && "ref" === propName) ||
(enableRefAsProp && "ref" === propName
? (maybeKey.ref = coerceStringRef(config[propName], getOwner(), type))
: (maybeKey[propName] = config[propName]));
} else maybeKey = config;
if (!disableDefaultPropsExceptForClasses && type && type.defaultProps) {
config = type.defaultProps;
for (var propName$0 in config)
@@ -679,7 +688,7 @@ exports.useSyncExternalStore = function (
exports.useTransition = function () {
return ReactSharedInternals.H.useTransition();
};
exports.version = "19.0.0-www-classic-c1be9b80";
exports.version = "19.0.0-www-classic-cb3c2ab2";
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
"function" ===
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
@@ -21,6 +21,7 @@ var dynamicFeatureFlags = require("ReactFeatureFlags"),
enableRefAsProp = dynamicFeatureFlags.enableRefAsProp,
disableDefaultPropsExceptForClasses =
dynamicFeatureFlags.disableDefaultPropsExceptForClasses,
enableFastJSX = dynamicFeatureFlags.enableFastJSX,
REACT_LEGACY_ELEMENT_TYPE = Symbol.for("react.element"),
REACT_PORTAL_TYPE = Symbol.for("react.portal"),
REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"),
@@ -97,6 +98,8 @@ function getOwner() {
var dispatcher = ReactSharedInternals.A;
return null === dispatcher ? null : dispatcher.getOwner();
}
var enableFastJSXWithStringRefs = enableFastJSX && enableRefAsProp,
enableFastJSXWithoutStringRefs = enableFastJSXWithStringRefs && !1;
function ReactElement(type, key, _ref, self, source, owner, props) {
enableRefAsProp &&
((_ref = props.ref), (_ref = void 0 !== _ref ? _ref : null));
@@ -117,13 +120,19 @@ function jsxProd(type, config, maybeKey) {
void 0 === config.ref ||
enableRefAsProp ||
((ref = config.ref), (ref = coerceStringRef(ref, getOwner(), type)));
maybeKey = {};
for (var propName in config)
"key" === propName ||
(!enableRefAsProp && "ref" === propName) ||
(enableRefAsProp && "ref" === propName
? (maybeKey.ref = coerceStringRef(config[propName], getOwner(), type))
: (maybeKey[propName] = config[propName]));
if (
(!enableFastJSXWithoutStringRefs &&
(!enableFastJSXWithStringRefs || "ref" in config)) ||
"key" in config
) {
maybeKey = {};
for (var propName in config)
"key" === propName ||
(!enableRefAsProp && "ref" === propName) ||
(enableRefAsProp && "ref" === propName
? (maybeKey.ref = coerceStringRef(config[propName], getOwner(), type))
: (maybeKey[propName] = config[propName]));
} else maybeKey = config;
if (!disableDefaultPropsExceptForClasses && type && type.defaultProps) {
config = type.defaultProps;
for (var propName$0 in config)
@@ -679,7 +688,7 @@ exports.useSyncExternalStore = function (
exports.useTransition = function () {
return ReactSharedInternals.H.useTransition();
};
exports.version = "19.0.0-www-modern-c1be9b80";
exports.version = "19.0.0-www-modern-cb3c2ab2";
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
"function" ===
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&