Skip to content

Commit 1beb73d

Browse files
authored
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.
1 parent 1d618a9 commit 1beb73d

10 files changed

+26
-6
lines changed

packages/react/src/__tests__/ReactJSXRuntime-test.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -375,9 +375,8 @@ describe('ReactJSXRuntime', () => {
375375
expect(didCall).toBe(false);
376376
});
377377

378-
// @gate enableRefAsProp
379-
// @gate disableStringRefs
380-
it('does not clone props object if key is not spread', async () => {
378+
// @gate enableFastJSX && enableRefAsProp
379+
it('does not clone props object if key and ref is not spread', async () => {
381380
const config = {
382381
foo: 'foo',
383382
bar: 'bar',
@@ -386,7 +385,7 @@ describe('ReactJSXRuntime', () => {
386385
const element = __DEV__
387386
? JSXDEVRuntime.jsxDEV('div', config)
388387
: JSXRuntime.jsx('div', config);
389-
expect(element.props).toBe(config);
388+
expect(Object.is(element.props, config)).toBe(true);
390389

391390
const configWithKey = {
392391
foo: 'foo',

packages/react/src/jsx/ReactJSXElement.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
enableRefAsProp,
2323
disableStringRefs,
2424
disableDefaultPropsExceptForClasses,
25+
enableFastJSX,
2526
} from 'shared/ReactFeatureFlags';
2627
import {checkPropStringCoercion} from 'shared/CheckStringCoercion';
2728
import {ClassComponent} from 'react-reconciler/src/ReactWorkTags';
@@ -51,6 +52,10 @@ if (__DEV__) {
5152
didWarnAboutElementRef = {};
5253
}
5354

55+
const enableFastJSXWithStringRefs = enableFastJSX && enableRefAsProp;
56+
const enableFastJSXWithoutStringRefs =
57+
enableFastJSXWithStringRefs && disableStringRefs;
58+
5459
function hasValidRef(config) {
5560
if (__DEV__) {
5661
if (hasOwnProperty.call(config, 'ref')) {
@@ -355,7 +360,11 @@ export function jsxProd(type, config, maybeKey) {
355360
}
356361

357362
let props;
358-
if (enableRefAsProp && disableStringRefs && !('key' in config)) {
363+
if (
364+
(enableFastJSXWithoutStringRefs ||
365+
(enableFastJSXWithStringRefs && !('ref' in config))) &&
366+
!('key' in config)
367+
) {
359368
// If key was not spread in, we can reuse the original props object. This
360369
// only works for `jsx`, not `createElement`, because `jsx` is a compiler
361370
// target and the compiler always passes a new object. For `createElement`,
@@ -578,7 +587,11 @@ export function jsxDEV(type, config, maybeKey, isStaticChildren, source, self) {
578587
}
579588

580589
let props;
581-
if (enableRefAsProp && disableStringRefs && !('key' in config)) {
590+
if (
591+
(enableFastJSXWithoutStringRefs ||
592+
(enableFastJSXWithStringRefs && !('ref' in config))) &&
593+
!('key' in config)
594+
) {
582595
// If key was not spread in, we can reuse the original props object. This
583596
// only works for `jsx`, not `createElement`, because `jsx` is a compiler
584597
// target and the compiler always passes a new object. For `createElement`,

packages/shared/ReactFeatureFlags.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ export const enableInfiniteRenderLoopDetection = true;
185185
// during element creation.
186186
export const enableRefAsProp = true;
187187
export const disableStringRefs = true;
188+
export const enableFastJSX = true;
188189

189190
// Warn on any usage of ReactTestRenderer
190191
export const enableReactTestRendererWarning = true;

packages/shared/forks/ReactFeatureFlags.native-fb.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ export const enableServerComponentLogs = true;
9898
// because JSX is an extremely hot path.
9999
export const enableRefAsProp = false;
100100
export const disableStringRefs = false;
101+
export const enableFastJSX = false;
101102

102103
export const enableReactTestRendererWarning = false;
103104
export const disableLegacyMode = false;

packages/shared/forks/ReactFeatureFlags.native-oss.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import typeof * as ExportsType from './ReactFeatureFlags.native-oss';
2020
const __TODO_NEXT_RN_MAJOR__ = false;
2121
export const enableRefAsProp = __TODO_NEXT_RN_MAJOR__;
2222
export const disableStringRefs = __TODO_NEXT_RN_MAJOR__;
23+
export const enableFastJSX = __TODO_NEXT_RN_MAJOR__;
2324
export const disableLegacyMode = __TODO_NEXT_RN_MAJOR__;
2425
export const disableDOMTestUtils = __TODO_NEXT_RN_MAJOR__;
2526
export const useModernStrictMode = __TODO_NEXT_RN_MAJOR__;

packages/shared/forks/ReactFeatureFlags.test-renderer.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ export const renameElementSymbol = true;
9191
// const __NEXT_MAJOR__ = __EXPERIMENTAL__;
9292
export const enableRefAsProp = true;
9393
export const disableStringRefs = true;
94+
export const enableFastJSX = true;
9495
export const disableLegacyMode = true;
9596
export const disableLegacyContext = true;
9697
export const disableDOMTestUtils = true;

packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ export const enableServerComponentLogs = true;
8282

8383
export const enableRefAsProp = false;
8484
export const disableStringRefs = false;
85+
export const enableFastJSX = false;
8586

8687
export const enableReactTestRendererWarning = false;
8788
export const disableLegacyMode = false;

packages/shared/forks/ReactFeatureFlags.test-renderer.www.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ export const enableInfiniteRenderLoopDetection = false;
8282

8383
export const enableRefAsProp = false;
8484
export const disableStringRefs = false;
85+
export const enableFastJSX = false;
8586

8687
export const enableReactTestRendererWarning = false;
8788
export const disableLegacyMode = false;

packages/shared/forks/ReactFeatureFlags.www-dynamic.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export const enableDO_NOT_USE_disableStrictPassiveEffect = __VARIANT__;
2424
export const enableUseDeferredValueInitialArg = __VARIANT__;
2525
export const enableRenderableContext = __VARIANT__;
2626
export const enableRefAsProp = __VARIANT__;
27+
export const enableFastJSX = __VARIANT__;
2728
export const enableRetryLaneExpiration = __VARIANT__;
2829
export const favorSafetyOverHydrationPerf = __VARIANT__;
2930
export const disableDefaultPropsExceptForClasses = __VARIANT__;

packages/shared/forks/ReactFeatureFlags.www.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export const {
3636
disableDefaultPropsExceptForClasses,
3737
enableNoCloningMemoCache,
3838
enableAddPropertiesFastPath,
39+
enableFastJSX,
3940
} = dynamicFeatureFlags;
4041

4142
// On WWW, __EXPERIMENTAL__ is used for a new modern build.

0 commit comments

Comments
 (0)