diff --git a/packages/react/src/__tests__/ReactJSXRuntime-test.js b/packages/react/src/__tests__/ReactJSXRuntime-test.js index 0ed8391f3605e..e1ca87d5d0224 100644 --- a/packages/react/src/__tests__/ReactJSXRuntime-test.js +++ b/packages/react/src/__tests__/ReactJSXRuntime-test.js @@ -375,9 +375,8 @@ describe('ReactJSXRuntime', () => { expect(didCall).toBe(false); }); - // @gate enableRefAsProp - // @gate disableStringRefs - it('does not clone props object if key is not spread', async () => { + // @gate enableFastJSX && enableRefAsProp && disableStringRefs + it('does not clone props object if key and ref is not spread', async () => { const config = { foo: 'foo', bar: 'bar', @@ -386,7 +385,7 @@ describe('ReactJSXRuntime', () => { const element = __DEV__ ? JSXDEVRuntime.jsxDEV('div', config) : JSXRuntime.jsx('div', config); - expect(element.props).toBe(config); + expect(Object.is(element.props, config)).toBe(true); const configWithKey = { foo: 'foo', diff --git a/packages/react/src/jsx/ReactJSXElement.js b/packages/react/src/jsx/ReactJSXElement.js index d8452a2e360a2..fad4d42bcc50d 100644 --- a/packages/react/src/jsx/ReactJSXElement.js +++ b/packages/react/src/jsx/ReactJSXElement.js @@ -22,6 +22,7 @@ import { enableRefAsProp, disableStringRefs, disableDefaultPropsExceptForClasses, + enableFastJSX, } from 'shared/ReactFeatureFlags'; import {checkPropStringCoercion} from 'shared/CheckStringCoercion'; import {ClassComponent} from 'react-reconciler/src/ReactWorkTags'; @@ -51,6 +52,10 @@ if (__DEV__) { didWarnAboutElementRef = {}; } +const enableFastJSXWithStringRefs = enableFastJSX && enableRefAsProp; +const enableFastJSXWithoutStringRefs = + enableFastJSXWithStringRefs && disableStringRefs; + function hasValidRef(config) { if (__DEV__) { if (hasOwnProperty.call(config, 'ref')) { @@ -355,7 +360,11 @@ export function jsxProd(type, config, maybeKey) { } let 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`, @@ -578,7 +587,11 @@ export function jsxDEV(type, config, maybeKey, isStaticChildren, source, self) { } let 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`, diff --git a/packages/shared/ReactFeatureFlags.js b/packages/shared/ReactFeatureFlags.js index bfb48e65df4a1..7606367c36969 100644 --- a/packages/shared/ReactFeatureFlags.js +++ b/packages/shared/ReactFeatureFlags.js @@ -183,6 +183,7 @@ export const enableInfiniteRenderLoopDetection = true; // during element creation. export const enableRefAsProp = true; export const disableStringRefs = true; +export const enableFastJSX = true; // Warn on any usage of ReactTestRenderer export const enableReactTestRendererWarning = true; diff --git a/packages/shared/ReactVersion.js b/packages/shared/ReactVersion.js index 13dd40e747e0d..446e5880c0c97 100644 --- a/packages/shared/ReactVersion.js +++ b/packages/shared/ReactVersion.js @@ -1,15 +1 @@ -/** - * 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. - */ - -// TODO: this is special because it gets imported during build. -// -// It exists as a placeholder so that DevTools can support work tag changes between releases. -// When we next publish a release, update the matching TODO in backend/renderer.js -// TODO: This module is used both by the release scripts and to expose a version -// at runtime. We should instead inject the version number as part of the build -// process, and use the ReactVersions.js module as the single source of truth. -export default '19.0.0'; +export default '19.0.0-PLACEHOLDER'; diff --git a/packages/shared/forks/ReactFeatureFlags.native-fb.js b/packages/shared/forks/ReactFeatureFlags.native-fb.js index dd046dc7a4ccb..189b8baceb290 100644 --- a/packages/shared/forks/ReactFeatureFlags.native-fb.js +++ b/packages/shared/forks/ReactFeatureFlags.native-fb.js @@ -97,6 +97,7 @@ export const enableServerComponentLogs = true; // because JSX is an extremely hot path. export const enableRefAsProp = false; export const disableStringRefs = false; +export const enableFastJSX = false; export const enableReactTestRendererWarning = false; export const disableLegacyMode = false; diff --git a/packages/shared/forks/ReactFeatureFlags.native-oss.js b/packages/shared/forks/ReactFeatureFlags.native-oss.js index 243f63b623d72..7b4fe447388c9 100644 --- a/packages/shared/forks/ReactFeatureFlags.native-oss.js +++ b/packages/shared/forks/ReactFeatureFlags.native-oss.js @@ -20,6 +20,7 @@ import typeof * as ExportsType from './ReactFeatureFlags.native-oss'; const __TODO_NEXT_RN_MAJOR__ = false; export const enableRefAsProp = __TODO_NEXT_RN_MAJOR__; export const disableStringRefs = __TODO_NEXT_RN_MAJOR__; +export const enableFastJSX = __TODO_NEXT_RN_MAJOR__; export const disableLegacyMode = __TODO_NEXT_RN_MAJOR__; export const disableDOMTestUtils = __TODO_NEXT_RN_MAJOR__; export const useModernStrictMode = __TODO_NEXT_RN_MAJOR__; diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.js index e80af511bb71b..ff953bcadf3b7 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.js @@ -90,6 +90,7 @@ export const renameElementSymbol = true; // const __NEXT_MAJOR__ = __EXPERIMENTAL__; export const enableRefAsProp = true; export const disableStringRefs = true; +export const enableFastJSX = true; export const disableLegacyMode = true; export const disableLegacyContext = true; export const disableDOMTestUtils = true; diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js index 2338dfcc4d557..1e92c819013bd 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js @@ -82,6 +82,7 @@ export const enableServerComponentLogs = true; export const enableRefAsProp = false; export const disableStringRefs = false; +export const enableFastJSX = false; export const enableReactTestRendererWarning = false; export const disableLegacyMode = false; diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js index dc6fcc3cec8be..ffde6a1af1d4b 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js @@ -82,6 +82,7 @@ export const enableInfiniteRenderLoopDetection = false; export const enableRefAsProp = false; export const disableStringRefs = false; +export const enableFastJSX = false; export const enableReactTestRendererWarning = false; export const disableLegacyMode = false; diff --git a/packages/shared/forks/ReactFeatureFlags.www-dynamic.js b/packages/shared/forks/ReactFeatureFlags.www-dynamic.js index af5071c47af3b..a56661e9cdee4 100644 --- a/packages/shared/forks/ReactFeatureFlags.www-dynamic.js +++ b/packages/shared/forks/ReactFeatureFlags.www-dynamic.js @@ -24,6 +24,7 @@ export const enableDO_NOT_USE_disableStrictPassiveEffect = __VARIANT__; export const enableUseDeferredValueInitialArg = __VARIANT__; export const enableRenderableContext = __VARIANT__; export const enableRefAsProp = __VARIANT__; +export const enableFastJSX = __VARIANT__; export const enableRetryLaneExpiration = __VARIANT__; export const favorSafetyOverHydrationPerf = __VARIANT__; export const disableDefaultPropsExceptForClasses = __VARIANT__; diff --git a/packages/shared/forks/ReactFeatureFlags.www.js b/packages/shared/forks/ReactFeatureFlags.www.js index 252571251f55a..b88f5559e3ff5 100644 --- a/packages/shared/forks/ReactFeatureFlags.www.js +++ b/packages/shared/forks/ReactFeatureFlags.www.js @@ -35,6 +35,7 @@ export const { favorSafetyOverHydrationPerf, disableDefaultPropsExceptForClasses, enableNoCloningMemoCache, + enableFastJSX, } = dynamicFeatureFlags; // On WWW, __EXPERIMENTAL__ is used for a new modern build.