Skip to content

Commit

Permalink
Add flag to test fast jsx (#28816)
Browse files Browse the repository at this point in the history
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 [1beb73d](1beb73d)
  • Loading branch information
jackpope committed May 3, 2024
1 parent a73bb0e commit bc32eda
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 47 deletions.
9 changes: 6 additions & 3 deletions compiled/facebook-www/JSXDEVRuntime-dev.classic.js
Expand Up @@ -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;
Expand Down Expand Up @@ -941,6 +941,9 @@ var didWarnAboutElementRef;
didWarnAboutElementRef = {};
}

var enableFastJSXWithStringRefs = enableFastJSX && enableRefAsProp;
var enableFastJSXWithoutStringRefs = enableFastJSXWithStringRefs && disableStringRefs;

function hasValidRef(config) {
{
if (hasOwnProperty.call(config, 'ref')) {
Expand Down Expand Up @@ -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`,
Expand Down
9 changes: 6 additions & 3 deletions compiled/facebook-www/JSXDEVRuntime-dev.modern.js
Expand Up @@ -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;
Expand Down Expand Up @@ -944,6 +944,9 @@ var didWarnAboutElementRef;
didWarnAboutElementRef = {};
}

var enableFastJSXWithStringRefs = enableFastJSX && enableRefAsProp;
var enableFastJSXWithoutStringRefs = enableFastJSXWithStringRefs && disableStringRefs;

function hasValidRef(config) {
{
if (hasOwnProperty.call(config, 'ref')) {
Expand Down Expand Up @@ -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`,
Expand Down
2 changes: 1 addition & 1 deletion compiled/facebook-www/REVISION
@@ -1 +1 @@
73bcdfbae57545aa8f88ecdf67426275610b5573
1beb73de0f7c3261a0de37620453b102caaa6236
11 changes: 7 additions & 4 deletions compiled/facebook-www/React-dev.classic.js
Expand Up @@ -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');
Expand All @@ -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;
Expand Down Expand Up @@ -1224,6 +1224,9 @@ var didWarnAboutOldJSXRuntime;
didWarnAboutElementRef = {};
}

var enableFastJSXWithStringRefs = enableFastJSX && enableRefAsProp;
var enableFastJSXWithoutStringRefs = enableFastJSXWithStringRefs && disableStringRefs;

function hasValidRef(config) {
{
if (hasOwnProperty.call(config, 'ref')) {
Expand Down Expand Up @@ -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`,
Expand Down
11 changes: 7 additions & 4 deletions compiled/facebook-www/React-dev.modern.js
Expand Up @@ -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');
Expand All @@ -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;
Expand Down Expand Up @@ -1227,6 +1227,9 @@ var didWarnAboutOldJSXRuntime;
didWarnAboutElementRef = {};
}

var enableFastJSXWithStringRefs = enableFastJSX && enableRefAsProp;
var enableFastJSXWithoutStringRefs = enableFastJSXWithStringRefs && disableStringRefs;

function hasValidRef(config) {
{
if (hasOwnProperty.call(config, 'ref')) {
Expand Down Expand Up @@ -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`,
Expand Down
25 changes: 17 additions & 8 deletions compiled/facebook-www/React-prod.classic.js
Expand Up @@ -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"),
Expand Down Expand Up @@ -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));
Expand All @@ -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)
Expand Down Expand Up @@ -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";
25 changes: 17 additions & 8 deletions compiled/facebook-www/React-prod.modern.js
Expand Up @@ -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"),
Expand Down Expand Up @@ -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));
Expand All @@ -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)
Expand Down Expand Up @@ -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";
25 changes: 17 additions & 8 deletions compiled/facebook-www/React-profiling.classic.js
Expand Up @@ -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"),
Expand Down Expand Up @@ -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));
Expand All @@ -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)
Expand Down Expand Up @@ -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 &&
Expand Down
25 changes: 17 additions & 8 deletions compiled/facebook-www/React-profiling.modern.js
Expand Up @@ -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"),
Expand Down Expand Up @@ -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));
Expand All @@ -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)
Expand Down Expand Up @@ -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 &&
Expand Down

0 comments on commit bc32eda

Please sign in to comment.