From 8895320035c6401bc91fa84133da194ce945af4a Mon Sep 17 00:00:00 2001 From: Josh Story Date: Fri, 5 Apr 2024 13:40:26 -0700 Subject: [PATCH] Reduces the size of ReactDOMSharedIntenrals object representation to save on bundle size --- .../src/client/ReactDOMUpdatePriority.js | 6 +- .../src/client/ReactFiberConfigDOM.js | 7 +- .../ReactDOMFlightServerHostDispatcher.js | 7 +- .../src/server/ReactFizzConfigDOM.js | 7 +- .../src/shared/ReactFlightClientConfigDOM.js | 22 +-- packages/react-dom/client.js | 8 +- packages/react-dom/index.classic.fb.js | 4 +- packages/react-dom/index.modern.fb.js | 4 +- .../react-dom/src/ReactDOMSharedInternals.js | 30 +-- .../src/ReactDOMSharedInternalsFB.js | 46 +++++ packages/react-dom/src/client/ReactDOM.js | 26 +-- packages/react-dom/src/client/ReactDOMFB.js | 180 ++++++++++++++++++ .../react-dom/src/shared/ReactDOMFloat.js | 130 +++++++------ .../react-dom/src/shared/ReactDOMFlushSync.js | 12 +- packages/shared/ReactVersion.js | 16 +- scripts/rollup/forks.js | 10 +- 16 files changed, 364 insertions(+), 151 deletions(-) create mode 100644 packages/react-dom/src/ReactDOMSharedInternalsFB.js create mode 100644 packages/react-dom/src/client/ReactDOMFB.js diff --git a/packages/react-dom-bindings/src/client/ReactDOMUpdatePriority.js b/packages/react-dom-bindings/src/client/ReactDOMUpdatePriority.js index a0c4273bec604..4f422a06732e3 100644 --- a/packages/react-dom-bindings/src/client/ReactDOMUpdatePriority.js +++ b/packages/react-dom-bindings/src/client/ReactDOMUpdatePriority.js @@ -25,15 +25,15 @@ export function setCurrentUpdatePriority( // is much longer. I hope this is consistent enough to rely on across builds IntentionallyUnusedArgument?: empty, ): void { - ReactDOMSharedInternals.up = newPriority; + ReactDOMSharedInternals.p /* currentUpdatePriority */ = newPriority; } export function getCurrentUpdatePriority(): EventPriority { - return ReactDOMSharedInternals.up; + return ReactDOMSharedInternals.p; /* currentUpdatePriority */ } export function resolveUpdatePriority(): EventPriority { - const updatePriority = ReactDOMSharedInternals.up; + const updatePriority = ReactDOMSharedInternals.p; /* currentUpdatePriority */ if (updatePriority !== NoEventPriority) { return updatePriority; } diff --git a/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js b/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js index dd089a17fdd11..a12ce0c6ac29c 100644 --- a/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js +++ b/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js @@ -104,8 +104,6 @@ import escapeSelectorAttributeValueInsideDoubleQuotes from './escapeSelectorAttr import {flushSyncWork as flushSyncWorkOnAllRoots} from 'react-reconciler/src/ReactFiberWorkLoop'; import ReactDOMSharedInternals from 'shared/ReactDOMSharedInternals'; -const ReactDOMCurrentDispatcher = - ReactDOMSharedInternals.ReactDOMCurrentDispatcher; export type Type = string; export type Props = { @@ -1924,8 +1922,9 @@ function getDocumentFromRoot(root: HoistableRoot): Document { return root.ownerDocument || root; } -const previousDispatcher = ReactDOMCurrentDispatcher.current; -ReactDOMCurrentDispatcher.current = { +const previousDispatcher = + ReactDOMSharedInternals.d; /* ReactDOMCurrentDispatcher */ +ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */ = { flushSyncWork: disableLegacyMode ? flushSyncWork : previousDispatcher.flushSyncWork, diff --git a/packages/react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js b/packages/react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js index be58583396d1a..6e722abcc7159 100644 --- a/packages/react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js +++ b/packages/react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js @@ -23,11 +23,10 @@ import { } from 'react-server/src/ReactFlightServer'; import ReactDOMSharedInternals from 'shared/ReactDOMSharedInternals'; -const ReactDOMCurrentDispatcher = - ReactDOMSharedInternals.ReactDOMCurrentDispatcher; -const previousDispatcher = ReactDOMCurrentDispatcher.current; -ReactDOMCurrentDispatcher.current = { +const previousDispatcher = + ReactDOMSharedInternals.d; /* ReactDOMCurrentDispatcher */ +ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */ = { flushSyncWork: previousDispatcher.flushSyncWork, prefetchDNS, preconnect, diff --git a/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js b/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js index 92f3756ab800d..bbf93cbd47829 100644 --- a/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js +++ b/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js @@ -83,11 +83,10 @@ import {getValueDescriptorExpectingObjectForWarning} from '../shared/ReactDOMRes import {NotPending} from '../shared/ReactDOMFormActions'; import ReactDOMSharedInternals from 'shared/ReactDOMSharedInternals'; -const ReactDOMCurrentDispatcher = - ReactDOMSharedInternals.ReactDOMCurrentDispatcher; -const previousDispatcher = ReactDOMCurrentDispatcher.current; -ReactDOMCurrentDispatcher.current = { +const previousDispatcher = + ReactDOMSharedInternals.d; /* ReactDOMCurrentDispatcher */ +ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */ = { flushSyncWork: previousDispatcher.flushSyncWork, prefetchDNS, preconnect, diff --git a/packages/react-dom-bindings/src/shared/ReactFlightClientConfigDOM.js b/packages/react-dom-bindings/src/shared/ReactFlightClientConfigDOM.js index 3cc648270d0d4..17c7007e10632 100644 --- a/packages/react-dom-bindings/src/shared/ReactFlightClientConfigDOM.js +++ b/packages/react-dom-bindings/src/shared/ReactFlightClientConfigDOM.js @@ -13,8 +13,6 @@ import type {HintCode, HintModel} from '../server/ReactFlightServerConfigDOM'; import ReactDOMSharedInternals from 'shared/ReactDOMSharedInternals'; -const ReactDOMCurrentDispatcher = - ReactDOMSharedInternals.ReactDOMCurrentDispatcher; import {getCrossOriginString} from './crossOriginStrings'; @@ -22,7 +20,7 @@ export function dispatchHint( code: Code, model: HintModel, ): void { - const dispatcher = ReactDOMCurrentDispatcher.current; + const dispatcher = ReactDOMSharedInternals.d; /* ReactDOMCurrentDispatcher */ switch (code) { case 'D': { const refined = refineModel(code, model); @@ -117,10 +115,11 @@ export function preinitModuleForSSR( nonce: ?string, crossOrigin: ?string, ) { - ReactDOMCurrentDispatcher.current.preinitModuleScript(href, { - crossOrigin: getCrossOriginString(crossOrigin), - nonce, - }); + ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */ + .preinitModuleScript(href, { + crossOrigin: getCrossOriginString(crossOrigin), + nonce, + }); } export function preinitScriptForSSR( @@ -128,8 +127,9 @@ export function preinitScriptForSSR( nonce: ?string, crossOrigin: ?string, ) { - ReactDOMCurrentDispatcher.current.preinitScript(href, { - crossOrigin: getCrossOriginString(crossOrigin), - nonce, - }); + ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */ + .preinitScript(href, { + crossOrigin: getCrossOriginString(crossOrigin), + nonce, + }); } diff --git a/packages/react-dom/client.js b/packages/react-dom/client.js index f44c3668f7b17..1379aaa9d3c53 100644 --- a/packages/react-dom/client.js +++ b/packages/react-dom/client.js @@ -27,13 +27,13 @@ export function createRoot( options?: CreateRootOptions, ): RootType { if (__DEV__) { - Internals.usingClientEntryPoint = true; + (Internals: any).usingClientEntryPoint = true; } try { return createRootImpl(container, options); } finally { if (__DEV__) { - Internals.usingClientEntryPoint = false; + (Internals: any).usingClientEntryPoint = false; } } } @@ -44,13 +44,13 @@ export function hydrateRoot( options?: HydrateRootOptions, ): RootType { if (__DEV__) { - Internals.usingClientEntryPoint = true; + (Internals: any).usingClientEntryPoint = true; } try { return hydrateRootImpl(container, children, options); } finally { if (__DEV__) { - Internals.usingClientEntryPoint = false; + (Internals: any).usingClientEntryPoint = false; } } } diff --git a/packages/react-dom/index.classic.fb.js b/packages/react-dom/index.classic.fb.js index e765898d91cb8..37a39667a86fc 100644 --- a/packages/react-dom/index.classic.fb.js +++ b/packages/react-dom/index.classic.fb.js @@ -9,7 +9,7 @@ import {isEnabled} from 'react-dom-bindings/src/events/ReactDOMEventListener'; -import Internals from './src/ReactDOMSharedInternals'; +import Internals from './src/ReactDOMSharedInternalsFB'; // For classic WWW builds, include a few internals that are already in use. Object.assign((Internals: any), { @@ -32,7 +32,7 @@ export { preinit, preinitModule, version, -} from './src/client/ReactDOM'; +} from './src/client/ReactDOMFB'; export { createRoot, diff --git a/packages/react-dom/index.modern.fb.js b/packages/react-dom/index.modern.fb.js index 0bff591fac7c9..f392b0dd9490f 100644 --- a/packages/react-dom/index.modern.fb.js +++ b/packages/react-dom/index.modern.fb.js @@ -7,7 +7,7 @@ * @flow */ -export {default as __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED} from './src/ReactDOMSharedInternals'; +export {default as __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED} from './src/ReactDOMSharedInternalsFB'; export { createPortal, flushSync, @@ -23,6 +23,6 @@ export { preinit, preinitModule, version, -} from './src/client/ReactDOM'; +} from './src/client/ReactDOMFB'; export {createRoot, hydrateRoot} from './src/client/ReactDOMRootFB'; diff --git a/packages/react-dom/src/ReactDOMSharedInternals.js b/packages/react-dom/src/ReactDOMSharedInternals.js index 39faf9464a57c..58cc3e4cb1919 100644 --- a/packages/react-dom/src/ReactDOMSharedInternals.js +++ b/packages/react-dom/src/ReactDOMSharedInternals.js @@ -12,18 +12,19 @@ import type {HostDispatcher} from './shared/ReactDOMTypes'; import {NoEventPriority} from 'react-reconciler/src/ReactEventPriorities'; -type InternalsType = { - usingClientEntryPoint: boolean, - Events: [any, any, any, any, any, any], - ReactDOMCurrentDispatcher: { - current: HostDispatcher, - }, +type ReactDOMInternals = { + d /* ReactDOMCurrentDispatcher */: HostDispatcher, + p /* currentUpdatePriority */: EventPriority, findDOMNode: | null | (( componentOrElement: React$Component, ) => null | Element | Text), - up /* currentUpdatePriority */: EventPriority, + usingClientEntryPoint: boolean, +}; + +export type ReactDOMInternalsDev = ReactDOMInternals & { + usingClientEntryPoint: boolean, }; function noop() {} @@ -39,14 +40,15 @@ const DefaultDispatcher: HostDispatcher = { preinitModuleScript: noop, }; -const Internals: InternalsType = { - usingClientEntryPoint: false, - Events: (null: any), - ReactDOMCurrentDispatcher: { - current: DefaultDispatcher, - }, +const Internals: ReactDOMInternals = { + d /* ReactDOMCurrentDispatcher */: DefaultDispatcher, + p /* currentUpdatePriority */: NoEventPriority, findDOMNode: null, - up /* currentUpdatePriority */: NoEventPriority, + usingClientEntryPoint: false, }; +// if (__DEV__) { +// (Internals: any).usingClientEntryPoint = false; +// } + export default Internals; diff --git a/packages/react-dom/src/ReactDOMSharedInternalsFB.js b/packages/react-dom/src/ReactDOMSharedInternalsFB.js new file mode 100644 index 0000000000000..a49ba3bcca182 --- /dev/null +++ b/packages/react-dom/src/ReactDOMSharedInternalsFB.js @@ -0,0 +1,46 @@ +/** + * 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. + * + * @flow + */ + +import type {EventPriority} from 'react-reconciler/src/ReactEventPriorities'; +import type {HostDispatcher} from './shared/ReactDOMTypes'; + +import {NoEventPriority} from 'react-reconciler/src/ReactEventPriorities'; + +type ReactDOMInternals = { + Events: [any, any, any, any, any, any], + d /* ReactDOMCurrentDispatcher */: HostDispatcher, + p /* currentUpdatePriority */: EventPriority, + findDOMNode: + | null + | (( + componentOrElement: React$Component, + ) => null | Element | Text), +}; + +function noop() {} + +const DefaultDispatcher: HostDispatcher = { + flushSyncWork: noop, + prefetchDNS: noop, + preconnect: noop, + preload: noop, + preloadModule: noop, + preinitScript: noop, + preinitStyle: noop, + preinitModuleScript: noop, +}; + +const Internals: ReactDOMInternals = { + Events: (null: any), + d /* ReactDOMCurrentDispatcher */: DefaultDispatcher, + p /* currentUpdatePriority */: NoEventPriority, + findDOMNode: null, +}; + +export default Internals; diff --git a/packages/react-dom/src/client/ReactDOM.js b/packages/react-dom/src/client/ReactDOM.js index b294418f7a511..86979fa11f81d 100644 --- a/packages/react-dom/src/client/ReactDOM.js +++ b/packages/react-dom/src/client/ReactDOM.js @@ -34,16 +34,7 @@ import {createPortal as createPortalImpl} from 'react-reconciler/src/ReactPortal import {canUseDOM} from 'shared/ExecutionEnvironment'; import ReactVersion from 'shared/ReactVersion'; -import { - getClosestInstanceFromNode, - getInstanceFromNode, - getNodeFromInstance, - getFiberCurrentPropsFromNode, -} from 'react-dom-bindings/src/client/ReactDOMComponentTree'; -import { - enqueueStateRestore, - restoreStateIfNeeded, -} from 'react-dom-bindings/src/events/ReactDOMControlledComponent'; +import {getClosestInstanceFromNode} from 'react-dom-bindings/src/client/ReactDOMComponentTree'; import Internals from '../ReactDOMSharedInternals'; export { @@ -97,7 +88,7 @@ function createRoot( options?: CreateRootOptions, ): RootType { if (__DEV__) { - if (!Internals.usingClientEntryPoint && !__UMD__) { + if (!(Internals: any).usingClientEntryPoint && !__UMD__) { console.error( 'You are importing createRoot from "react-dom" which is not supported. ' + 'You should instead import it from "react-dom/client".', @@ -113,7 +104,7 @@ function hydrateRoot( options?: HydrateRootOptions, ): RootType { if (__DEV__) { - if (!Internals.usingClientEntryPoint && !__UMD__) { + if (!(Internals: any).usingClientEntryPoint && !__UMD__) { console.error( 'You are importing hydrateRoot from "react-dom" which is not supported. ' + 'You should instead import it from "react-dom/client".', @@ -177,17 +168,6 @@ export { runWithPriority as unstable_runWithPriority, }; -// Keep in sync with ReactTestUtils.js. -// This is an array for better minification. -Internals.Events = [ - getInstanceFromNode, - getNodeFromInstance, - getFiberCurrentPropsFromNode, - enqueueStateRestore, - restoreStateIfNeeded, - unstable_batchedUpdates, -]; - const foundDevTools = injectIntoDevTools({ findFiberByHostInstance: getClosestInstanceFromNode, bundleType: __DEV__ ? 1 : 0, diff --git a/packages/react-dom/src/client/ReactDOMFB.js b/packages/react-dom/src/client/ReactDOMFB.js new file mode 100644 index 0000000000000..e24cba3a52b46 --- /dev/null +++ b/packages/react-dom/src/client/ReactDOMFB.js @@ -0,0 +1,180 @@ +/** + * 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. + * + * @flow + */ + +import type {ReactNodeList} from 'shared/ReactTypes'; + +import {disableLegacyMode} from 'shared/ReactFeatureFlags'; +import {isValidContainer} from './ReactDOMRoot'; +import {createEventHandle} from 'react-dom-bindings/src/client/ReactDOMEventHandle'; +import {runWithPriority} from 'react-dom-bindings/src/client/ReactDOMUpdatePriority'; +import {flushSync as flushSyncIsomorphic} from '../shared/ReactDOMFlushSync'; + +import { + flushSyncFromReconciler as flushSyncWithoutWarningIfAlreadyRendering, + isAlreadyRendering, + injectIntoDevTools, + findHostInstance, +} from 'react-reconciler/src/ReactFiberReconciler'; +import {createPortal as createPortalImpl} from 'react-reconciler/src/ReactPortal'; +import {canUseDOM} from 'shared/ExecutionEnvironment'; +import ReactVersion from 'shared/ReactVersion'; + +import { + getClosestInstanceFromNode, + getInstanceFromNode, + getNodeFromInstance, + getFiberCurrentPropsFromNode, +} from 'react-dom-bindings/src/client/ReactDOMComponentTree'; +import { + enqueueStateRestore, + restoreStateIfNeeded, +} from 'react-dom-bindings/src/events/ReactDOMControlledComponent'; +import Internals from '../ReactDOMSharedInternalsFB'; + +export { + prefetchDNS, + preconnect, + preload, + preloadModule, + preinit, + preinitModule, +} from '../shared/ReactDOMFloat'; +export { + useFormStatus, + useFormState, +} from 'react-dom-bindings/src/shared/ReactDOMFormActions'; + +if (__DEV__) { + if ( + typeof Map !== 'function' || + // $FlowFixMe[prop-missing] Flow incorrectly thinks Map has no prototype + Map.prototype == null || + typeof Map.prototype.forEach !== 'function' || + typeof Set !== 'function' || + // $FlowFixMe[prop-missing] Flow incorrectly thinks Set has no prototype + Set.prototype == null || + typeof Set.prototype.clear !== 'function' || + typeof Set.prototype.forEach !== 'function' + ) { + console.error( + 'React depends on Map and Set built-in types. Make sure that you load a ' + + 'polyfill in older browsers. https://react.dev/link/react-polyfills', + ); + } +} + +function createPortal( + children: ReactNodeList, + container: Element | DocumentFragment, + key: ?string = null, +): React$Portal { + if (!isValidContainer(container)) { + throw new Error('Target container is not a DOM element.'); + } + + // TODO: pass ReactDOM portal implementation as third argument + // $FlowFixMe[incompatible-return] The Flow type is opaque but there's no way to actually create it. + return createPortalImpl(children, container, null, key); +} + +// Overload the definition to the two valid signatures. +// Warning, this opts-out of checking the function body. +declare function flushSyncFromReconciler(fn: () => R): R; +// eslint-disable-next-line no-redeclare +declare function flushSyncFromReconciler(): void; +// eslint-disable-next-line no-redeclare +function flushSyncFromReconciler(fn: (() => R) | void): R | void { + if (__DEV__) { + if (isAlreadyRendering()) { + console.error( + 'flushSync was called from inside a lifecycle method. React cannot ' + + 'flush when React is already rendering. Consider moving this call to ' + + 'a scheduler task or micro task.', + ); + } + } + return flushSyncWithoutWarningIfAlreadyRendering(fn); +} + +const flushSync: typeof flushSyncIsomorphic = disableLegacyMode + ? flushSyncIsomorphic + : flushSyncFromReconciler; + +function findDOMNode( + componentOrElement: React$Component, +): null | Element | Text { + return findHostInstance(componentOrElement); +} + +// Expose findDOMNode on internals +Internals.findDOMNode = findDOMNode; + +function unstable_batchedUpdates(fn: (a: A) => R, a: A): R { + // batchedUpdates was a legacy mode feature that is a no-op outside of + // legacy mode. In 19, we made it an actual no-op, but we're keeping it + // for now since there may be libraries that still include it. + return fn(a); +} + +export { + createPortal, + unstable_batchedUpdates, + flushSync, + ReactVersion as version, + // enableCreateEventHandleAPI + createEventHandle as unstable_createEventHandle, + // TODO: Remove this once callers migrate to alternatives. + // This should only be used by React internals. + runWithPriority as unstable_runWithPriority, +}; + +// Keep in sync with ReactTestUtils.js. +// This is an array for better minification. +Internals.Events /* Events */ = [ + getInstanceFromNode, + getNodeFromInstance, + getFiberCurrentPropsFromNode, + enqueueStateRestore, + restoreStateIfNeeded, + unstable_batchedUpdates, +]; + +const foundDevTools = injectIntoDevTools({ + findFiberByHostInstance: getClosestInstanceFromNode, + bundleType: __DEV__ ? 1 : 0, + version: ReactVersion, + rendererPackageName: 'react-dom', +}); + +if (__DEV__) { + if (!foundDevTools && canUseDOM && window.top === window.self) { + // If we're in Chrome or Firefox, provide a download link if not installed. + if ( + (navigator.userAgent.indexOf('Chrome') > -1 && + navigator.userAgent.indexOf('Edge') === -1) || + navigator.userAgent.indexOf('Firefox') > -1 + ) { + const protocol = window.location.protocol; + // Don't warn in exotic cases like chrome-extension://. + if (/^(https?|file):$/.test(protocol)) { + // eslint-disable-next-line react-internal/no-production-logging + console.info( + '%cDownload the React DevTools ' + + 'for a better development experience: ' + + 'https://react.dev/link/react-devtools' + + (protocol === 'file:' + ? '\nYou might need to use a local HTTP server (instead of file://): ' + + 'https://react.dev/link/react-devtools-faq' + : ''), + 'font-weight:bold', + ); + } + } + } +} diff --git a/packages/react-dom/src/shared/ReactDOMFloat.js b/packages/react-dom/src/shared/ReactDOMFloat.js index 4aa364af318c7..4277c91603c43 100644 --- a/packages/react-dom/src/shared/ReactDOMFloat.js +++ b/packages/react-dom/src/shared/ReactDOMFloat.js @@ -15,8 +15,6 @@ import type { } from './ReactDOMTypes'; import ReactDOMSharedInternals from 'shared/ReactDOMSharedInternals'; -const ReactDOMCurrentDispatcher = - ReactDOMSharedInternals.ReactDOMCurrentDispatcher; import { getCrossOriginString, @@ -49,7 +47,8 @@ export function prefetchDNS(href: string) { } } if (typeof href === 'string') { - ReactDOMCurrentDispatcher.current.prefetchDNS(href); + ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */ + .prefetchDNS(href); } // We don't error because preconnect needs to be resilient to being called in a variety of scopes // and the runtime may not be capable of responding. The function is optimistic and not critical @@ -79,7 +78,8 @@ export function preconnect(href: string, options?: ?PreconnectOptions) { const crossOrigin = options ? getCrossOriginString(options.crossOrigin) : null; - ReactDOMCurrentDispatcher.current.preconnect(href, crossOrigin); + ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */ + .preconnect(href, crossOrigin); } // We don't error because preconnect needs to be resilient to being called in a variety of scopes // and the runtime may not be capable of responding. The function is optimistic and not critical @@ -119,28 +119,31 @@ export function preload(href: string, options: PreloadOptions) { ) { const as = options.as; const crossOrigin = getCrossOriginStringAs(as, options.crossOrigin); - ReactDOMCurrentDispatcher.current.preload(href, as, { - crossOrigin, - integrity: - typeof options.integrity === 'string' ? options.integrity : undefined, - nonce: typeof options.nonce === 'string' ? options.nonce : undefined, - type: typeof options.type === 'string' ? options.type : undefined, - fetchPriority: - typeof options.fetchPriority === 'string' - ? options.fetchPriority - : undefined, - referrerPolicy: - typeof options.referrerPolicy === 'string' - ? options.referrerPolicy - : undefined, - imageSrcSet: - typeof options.imageSrcSet === 'string' - ? options.imageSrcSet - : undefined, - imageSizes: - typeof options.imageSizes === 'string' ? options.imageSizes : undefined, - media: typeof options.media === 'string' ? options.media : undefined, - }); + ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */ + .preload(href, as, { + crossOrigin, + integrity: + typeof options.integrity === 'string' ? options.integrity : undefined, + nonce: typeof options.nonce === 'string' ? options.nonce : undefined, + type: typeof options.type === 'string' ? options.type : undefined, + fetchPriority: + typeof options.fetchPriority === 'string' + ? options.fetchPriority + : undefined, + referrerPolicy: + typeof options.referrerPolicy === 'string' + ? options.referrerPolicy + : undefined, + imageSrcSet: + typeof options.imageSrcSet === 'string' + ? options.imageSrcSet + : undefined, + imageSizes: + typeof options.imageSizes === 'string' + ? options.imageSizes + : undefined, + media: typeof options.media === 'string' ? options.media : undefined, + }); } // We don't error because preload needs to be resilient to being called in a variety of scopes // and the runtime may not be capable of responding. The function is optimistic and not critical @@ -177,17 +180,21 @@ export function preloadModule(href: string, options?: ?PreloadModuleOptions) { options.as, options.crossOrigin, ); - ReactDOMCurrentDispatcher.current.preloadModule(href, { - as: - typeof options.as === 'string' && options.as !== 'script' - ? options.as - : undefined, - crossOrigin, - integrity: - typeof options.integrity === 'string' ? options.integrity : undefined, - }); + ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */ + .preloadModule(href, { + as: + typeof options.as === 'string' && options.as !== 'script' + ? options.as + : undefined, + crossOrigin, + integrity: + typeof options.integrity === 'string' + ? options.integrity + : undefined, + }); } else { - ReactDOMCurrentDispatcher.current.preloadModule(href); + ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */ + .preloadModule(href); } } // We don't error because preload needs to be resilient to being called in a variety of scopes @@ -224,22 +231,26 @@ export function preinit(href: string, options: PreinitOptions) { ? options.fetchPriority : undefined; if (as === 'style') { - ReactDOMCurrentDispatcher.current.preinitStyle( - href, - typeof options.precedence === 'string' ? options.precedence : undefined, - { + ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */ + .preinitStyle( + href, + typeof options.precedence === 'string' + ? options.precedence + : undefined, + { + crossOrigin, + integrity, + fetchPriority, + }, + ); + } else if (as === 'script') { + ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */ + .preinitScript(href, { crossOrigin, integrity, fetchPriority, - }, - ); - } else if (as === 'script') { - ReactDOMCurrentDispatcher.current.preinitScript(href, { - crossOrigin, - integrity, - fetchPriority, - nonce: typeof options.nonce === 'string' ? options.nonce : undefined, - }); + nonce: typeof options.nonce === 'string' ? options.nonce : undefined, + }); } } // We don't error because preinit needs to be resilient to being called in a variety of scopes @@ -299,17 +310,20 @@ export function preinitModule(href: string, options?: ?PreinitModuleOptions) { options.as, options.crossOrigin, ); - ReactDOMCurrentDispatcher.current.preinitModuleScript(href, { - crossOrigin, - integrity: - typeof options.integrity === 'string' - ? options.integrity - : undefined, - nonce: typeof options.nonce === 'string' ? options.nonce : undefined, - }); + ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */ + .preinitModuleScript(href, { + crossOrigin, + integrity: + typeof options.integrity === 'string' + ? options.integrity + : undefined, + nonce: + typeof options.nonce === 'string' ? options.nonce : undefined, + }); } } else if (options == null) { - ReactDOMCurrentDispatcher.current.preinitModuleScript(href); + ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */ + .preinitModuleScript(href); } } // We don't error because preinit needs to be resilient to being called in a variety of scopes diff --git a/packages/react-dom/src/shared/ReactDOMFlushSync.js b/packages/react-dom/src/shared/ReactDOMFlushSync.js index a746a9090f60b..626e063aed946 100644 --- a/packages/react-dom/src/shared/ReactDOMFlushSync.js +++ b/packages/react-dom/src/shared/ReactDOMFlushSync.js @@ -17,19 +17,17 @@ const ReactCurrentBatchConfig: BatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; import ReactDOMSharedInternals from 'shared/ReactDOMSharedInternals'; -const ReactDOMCurrentDispatcher = - ReactDOMSharedInternals.ReactDOMCurrentDispatcher; declare function flushSyncImpl(fn: () => R): R; declare function flushSyncImpl(void): void; function flushSyncImpl(fn: (() => R) | void): R | void { const previousTransition = ReactCurrentBatchConfig.transition; const previousUpdatePriority = - ReactDOMSharedInternals.up; /* ReactDOMCurrentUpdatePriority */ + ReactDOMSharedInternals.p; /* ReactDOMCurrentUpdatePriority */ try { ReactCurrentBatchConfig.transition = null; - ReactDOMSharedInternals.up /* ReactDOMCurrentUpdatePriority */ = + ReactDOMSharedInternals.p /* ReactDOMCurrentUpdatePriority */ = DiscreteEventPriority; if (fn) { return fn(); @@ -38,9 +36,11 @@ function flushSyncImpl(fn: (() => R) | void): R | void { } } finally { ReactCurrentBatchConfig.transition = previousTransition; - ReactDOMSharedInternals.up /* ReactDOMCurrentUpdatePriority */ = + ReactDOMSharedInternals.p /* ReactDOMCurrentUpdatePriority */ = previousUpdatePriority; - const wasInRender = ReactDOMCurrentDispatcher.current.flushSyncWork(); + const wasInRender = + ReactDOMSharedInternals.d /* ReactDOMCurrentDispatcher */ + .flushSyncWork(); if (__DEV__) { if (wasInRender) { console.error( 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/scripts/rollup/forks.js b/scripts/rollup/forks.js index 65e72e8a54d74..7cfdf58965d5d 100644 --- a/scripts/rollup/forks.js +++ b/scripts/rollup/forks.js @@ -96,7 +96,15 @@ const forks = Object.freeze({ entry === 'react-dom/src/ReactDOMServer.js' || entry === 'react-dom/unstable_testing' ) { - return './packages/react-dom/src/ReactDOMSharedInternals.js'; + if ( + bundleType === FB_WWW_DEV || + bundleType === FB_WWW_PROD || + bundleType === FB_WWW_PROFILING + ) { + return './packages/react-dom/src/ReactDOMSharedInternalsFB.js'; + } else { + return './packages/react-dom/src/ReactDOMSharedInternals.js'; + } } if ( !entry.startsWith('react-dom/') &&