diff --git a/packages/react-cache/src/ReactCacheOld.js b/packages/react-cache/src/ReactCacheOld.js index 523a9f48c1cd5..78d8403afd0f6 100644 --- a/packages/react-cache/src/ReactCacheOld.js +++ b/packages/react-cache/src/ReactCacheOld.js @@ -44,12 +44,11 @@ const Pending = 0; const Resolved = 1; const Rejected = 2; -const ReactCurrentDispatcher = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED - .ReactCurrentDispatcher; +const SharedInternals = + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; function readContext(Context: ReactContext) { - const dispatcher = ReactCurrentDispatcher.current; + const dispatcher = SharedInternals.H; if (dispatcher === null) { // This wasn't being minified but we're going to retire this package anyway. // eslint-disable-next-line react-internal/prod-error-codes diff --git a/packages/react-debug-tools/src/ReactDebugHooks.js b/packages/react-debug-tools/src/ReactDebugHooks.js index 8d7477490da21..cb9d940354060 100644 --- a/packages/react-debug-tools/src/ReactDebugHooks.js +++ b/packages/react-debug-tools/src/ReactDebugHooks.js @@ -37,7 +37,7 @@ import { } from 'shared/ReactSymbols'; import hasOwnProperty from 'shared/hasOwnProperty'; -type CurrentDispatcherRef = typeof ReactSharedInternals.ReactCurrentDispatcher; +type CurrentDispatcherRef = typeof ReactSharedInternals; // Used to track hooks called during a render @@ -1075,11 +1075,11 @@ export function inspectHooks( // DevTools will pass the current renderer's injected dispatcher. // Other apps might compile debug hooks as part of their app though. if (currentDispatcher == null) { - currentDispatcher = ReactSharedInternals.ReactCurrentDispatcher; + currentDispatcher = ReactSharedInternals; } - const previousDispatcher = currentDispatcher.current; - currentDispatcher.current = DispatcherProxy; + const previousDispatcher = currentDispatcher.H; + currentDispatcher.H = DispatcherProxy; let readHookLog; let ancestorStackError; @@ -1093,7 +1093,7 @@ export function inspectHooks( readHookLog = hookLog; hookLog = []; // $FlowFixMe[incompatible-use] found when upgrading Flow - currentDispatcher.current = previousDispatcher; + currentDispatcher.H = previousDispatcher; } const rootStack = ErrorStackParser.parse(ancestorStackError); return buildTree(rootStack, readHookLog); @@ -1129,9 +1129,9 @@ function inspectHooksOfForwardRef( ref: Ref, currentDispatcher: CurrentDispatcherRef, ): HooksTree { - const previousDispatcher = currentDispatcher.current; + const previousDispatcher = currentDispatcher.H; let readHookLog; - currentDispatcher.current = DispatcherProxy; + currentDispatcher.H = DispatcherProxy; let ancestorStackError; try { ancestorStackError = new Error(); @@ -1141,7 +1141,7 @@ function inspectHooksOfForwardRef( } finally { readHookLog = hookLog; hookLog = []; - currentDispatcher.current = previousDispatcher; + currentDispatcher.H = previousDispatcher; } const rootStack = ErrorStackParser.parse(ancestorStackError); return buildTree(rootStack, readHookLog); @@ -1169,7 +1169,7 @@ export function inspectHooksOfFiber( // DevTools will pass the current renderer's injected dispatcher. // Other apps might compile debug hooks as part of their app though. if (currentDispatcher == null) { - currentDispatcher = ReactSharedInternals.ReactCurrentDispatcher; + currentDispatcher = ReactSharedInternals; } if ( diff --git a/packages/react-debug-tools/src/__tests__/ReactHooksInspection-test.js b/packages/react-debug-tools/src/__tests__/ReactHooksInspection-test.js index 79c1261c3b063..a1f194c35c1da 100644 --- a/packages/react-debug-tools/src/__tests__/ReactHooksInspection-test.js +++ b/packages/react-debug-tools/src/__tests__/ReactHooksInspection-test.js @@ -453,39 +453,6 @@ describe('ReactHooksInspection', () => { `); }); - it('should support an injected dispatcher', () => { - const initial = { - useState() { - throw new Error("Should've been proxied"); - }, - }; - let current = initial; - let getterCalls = 0; - const setterCalls = []; - const FakeDispatcherRef = { - get current() { - getterCalls++; - return current; - }, - set current(value) { - setterCalls.push(value); - current = value; - }, - }; - - function Foo(props) { - const [state] = FakeDispatcherRef.current.useState('hello world'); - return
{state}
; - } - - ReactDebugTools.inspectHooks(Foo, {}, FakeDispatcherRef); - - expect(getterCalls).toBe(2); - expect(setterCalls).toHaveLength(2); - expect(setterCalls[0]).not.toBe(initial); - expect(setterCalls[1]).toBe(initial); - }); - it('should inspect use() calls for Promise and Context', async () => { const MyContext = React.createContext('hi'); const promise = Promise.resolve('world'); diff --git a/packages/react-debug-tools/src/__tests__/ReactHooksInspectionIntegration-test.js b/packages/react-debug-tools/src/__tests__/ReactHooksInspectionIntegration-test.js index 95ac5e066e06b..2adcce742e87e 100644 --- a/packages/react-debug-tools/src/__tests__/ReactHooksInspectionIntegration-test.js +++ b/packages/react-debug-tools/src/__tests__/ReactHooksInspectionIntegration-test.js @@ -2345,61 +2345,6 @@ describe('ReactHooksInspectionIntegration', () => { `); }); - it('should support an injected dispatcher', async () => { - function Foo(props) { - const [state] = React.useState('hello world'); - return
{state}
; - } - - const initial = {}; - let current = initial; - let getterCalls = 0; - const setterCalls = []; - const FakeDispatcherRef = { - get current() { - getterCalls++; - return current; - }, - set current(value) { - setterCalls.push(value); - current = value; - }, - }; - - let renderer; - await act(() => { - renderer = ReactTestRenderer.create(, { - unstable_isConcurrent: true, - }); - }); - const childFiber = renderer.root._currentFiber(); - - let didCatch = false; - - try { - ReactDebugTools.inspectHooksOfFiber(childFiber, FakeDispatcherRef); - } catch (error) { - expect(error.message).toBe('Error rendering inspected component'); - expect(error.cause).toBeInstanceOf(Error); - expect(error.cause.message).toBe( - 'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' + - ' one of the following reasons:\n' + - '1. You might have mismatching versions of React and the renderer (such as React DOM)\n' + - '2. You might be breaking the Rules of Hooks\n' + - '3. You might have more than one copy of React in the same app\n' + - 'See https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem.', - ); - didCatch = true; - } - // avoid false positive if no error was thrown at all - expect(didCatch).toBe(true); - - expect(getterCalls).toBe(1); - expect(setterCalls).toHaveLength(2); - expect(setterCalls[0]).not.toBe(initial); - expect(setterCalls[1]).toBe(initial); - }); - // This test case is based on an open source bug report: // https://github.com/facebookincubator/redux-react-hook/issues/34#issuecomment-466693787 it('should properly advance the current hook for useContext', async () => { diff --git a/packages/react-devtools-shared/src/backend/DevToolsComponentStackFrame.js b/packages/react-devtools-shared/src/backend/DevToolsComponentStackFrame.js index 316245492c64f..c23f71ab62551 100644 --- a/packages/react-devtools-shared/src/backend/DevToolsComponentStackFrame.js +++ b/packages/react-devtools-shared/src/backend/DevToolsComponentStackFrame.js @@ -86,8 +86,8 @@ export function describeNativeComponentFrame( // Note that unlike the code this was forked from (in ReactComponentStackFrame) // DevTools should override the dispatcher even when DevTools is compiled in production mode, // because the app itself may be in development mode and log errors/warnings. - const previousDispatcher = currentDispatcherRef.current; - currentDispatcherRef.current = null; + const previousDispatcher = currentDispatcherRef.H; + currentDispatcherRef.H = null; disableLogs(); // NOTE: keep in sync with the implementation in ReactComponentStackFrame @@ -270,7 +270,7 @@ export function describeNativeComponentFrame( Error.prepareStackTrace = previousPrepareStackTrace; - currentDispatcherRef.current = previousDispatcher; + currentDispatcherRef.H = previousDispatcher; reenableLogs(); } // Fallback to just using the name if we couldn't make it throw. diff --git a/packages/react-devtools-shared/src/backend/console.js b/packages/react-devtools-shared/src/backend/console.js index 3b669b218cd68..27e212b33a935 100644 --- a/packages/react-devtools-shared/src/backend/console.js +++ b/packages/react-devtools-shared/src/backend/console.js @@ -9,6 +9,7 @@ import type {Fiber} from 'react-reconciler/src/ReactInternalTypes'; import type { + LegacyDispatcherRef, CurrentDispatcherRef, ReactRenderer, WorkTagMap, @@ -16,7 +17,7 @@ import type { } from './types'; import {format, formatWithStyles} from './utils'; -import {getInternalReactConstants} from './renderer'; +import {getInternalReactConstants, getDispatcherRef} from './renderer'; import {getStackByFiberInDevAndProd} from './DevToolsFiberComponentStack'; import {consoleManagedByDevToolsDuringStrictMode} from 'react-devtools-feature-flags'; import {castBool, castBrowserTheme} from '../utils'; @@ -75,7 +76,7 @@ type OnErrorOrWarning = ( const injectedRenderers: Map< ReactRenderer, { - currentDispatcherRef: CurrentDispatcherRef, + currentDispatcherRef: LegacyDispatcherRef | CurrentDispatcherRef, getCurrentFiber: () => Fiber | null, onErrorOrWarning: ?OnErrorOrWarning, workTagMap: WorkTagMap, @@ -215,12 +216,9 @@ export function patch({ // Search for the first renderer that has a current Fiber. // We don't handle the edge case of stacks for more than one (e.g. interleaved renderers?) // eslint-disable-next-line no-for-of-loops/no-for-of-loops - for (const { - currentDispatcherRef, - getCurrentFiber, - onErrorOrWarning, - workTagMap, - } of injectedRenderers.values()) { + for (const renderer of injectedRenderers.values()) { + const currentDispatcherRef = getDispatcherRef(renderer); + const {getCurrentFiber, onErrorOrWarning, workTagMap} = renderer; const current: ?Fiber = getCurrentFiber(); if (current != null) { try { @@ -241,7 +239,7 @@ export function patch({ const componentStack = getStackByFiberInDevAndProd( workTagMap, current, - currentDispatcherRef, + (currentDispatcherRef: any), ); if (componentStack !== '') { if (isStrictModeOverride(args, method)) { diff --git a/packages/react-devtools-shared/src/backend/renderer.js b/packages/react-devtools-shared/src/backend/renderer.js index 1f333d1271d67..1d1bcb15eb39b 100644 --- a/packages/react-devtools-shared/src/backend/renderer.js +++ b/packages/react-devtools-shared/src/backend/renderer.js @@ -119,6 +119,8 @@ import type { RendererInterface, SerializedElement, WorkTagMap, + CurrentDispatcherRef, + LegacyDispatcherRef, } from './types'; import type { ComponentFilter, @@ -140,6 +142,31 @@ type ReactPriorityLevelsType = { NoPriority: number, }; +export function getDispatcherRef(renderer: { + +currentDispatcherRef?: LegacyDispatcherRef | CurrentDispatcherRef, + ... +}): void | CurrentDispatcherRef { + if (renderer.currentDispatcherRef === undefined) { + return undefined; + } + const injectedRef = renderer.currentDispatcherRef; + if ( + typeof injectedRef.H === 'undefined' && + typeof injectedRef.current !== 'undefined' + ) { + // We got a legacy dispatcher injected, let's create a wrapper proxy to translate. + return { + get H() { + return (injectedRef: any).current; + }, + set H(value) { + (injectedRef: any).current = value; + }, + }; + } + return (injectedRef: any); +} + function getFiberFlags(fiber: Fiber): number { // The name of this field changed from "effectTag" to "flags" return fiber.flags !== undefined ? fiber.flags : (fiber: any).effectTag; @@ -694,7 +721,7 @@ export function attach( getDisplayNameForFiber, getIsProfiling: () => isProfiling, getLaneLabelMap, - currentDispatcherRef: renderer.currentDispatcherRef, + currentDispatcherRef: getDispatcherRef(renderer), workTagMap: ReactTypeOfWork, reactVersion: version, }); @@ -3344,10 +3371,7 @@ export function attach( } try { - hooks = inspectHooksOfFiber( - fiber, - (renderer.currentDispatcherRef: any), - ); + hooks = inspectHooksOfFiber(fiber, getDispatcherRef(renderer)); } finally { // Restore original console functionality. for (const method in originalConsoleMethods) { @@ -4571,7 +4595,7 @@ export function attach( function getComponentStackForFiber(fiber: Fiber): string | null { let componentStack = fiberToComponentStackMap.get(fiber); if (componentStack == null) { - const dispatcherRef = renderer.currentDispatcherRef; + const dispatcherRef = getDispatcherRef(renderer); if (dispatcherRef == null) { return null; } diff --git a/packages/react-devtools-shared/src/backend/types.js b/packages/react-devtools-shared/src/backend/types.js index c006cf53e3d5b..f11f631cd9621 100644 --- a/packages/react-devtools-shared/src/backend/types.js +++ b/packages/react-devtools-shared/src/backend/types.js @@ -87,7 +87,12 @@ export type NativeType = Object; export type RendererID = number; type Dispatcher = any; -export type CurrentDispatcherRef = {current: null | Dispatcher}; +export type LegacyDispatcherRef = {current: null | Dispatcher}; +type SharedInternalsSubset = { + H: null | Dispatcher, + ... +}; +export type CurrentDispatcherRef = SharedInternalsSubset; export type GetDisplayNameForFiberID = ( id: number, @@ -155,7 +160,7 @@ export type ReactRenderer = { scheduleUpdate?: ?(fiber: Object) => void, setSuspenseHandler?: ?(shouldSuspend: (fiber: Object) => boolean) => void, // Only injected by React v16.8+ in order to support hooks inspection. - currentDispatcherRef?: CurrentDispatcherRef, + currentDispatcherRef?: LegacyDispatcherRef | CurrentDispatcherRef, // Only injected by React v16.9+ in DEV mode. // Enables DevTools to append owners-only component stack to error messages. getCurrentFiber?: () => Fiber | null, diff --git a/packages/react-devtools-shared/src/devtools/cache.js b/packages/react-devtools-shared/src/devtools/cache.js index a11032caf5907..cae03a8877f1f 100644 --- a/packages/react-devtools-shared/src/devtools/cache.js +++ b/packages/react-devtools-shared/src/devtools/cache.js @@ -59,11 +59,11 @@ const Pending = 0; const Resolved = 1; const Rejected = 2; -const ReactCurrentDispatcher = (React: any) - .__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentDispatcher; +const ReactSharedInternals = (React: any) + .__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; function readContext(Context: ReactContext) { - const dispatcher = ReactCurrentDispatcher.current; + const dispatcher = ReactSharedInternals.H; if (dispatcher === null) { throw new Error( 'react-cache: read and preload may only be called from within a ' + diff --git a/packages/react-dom-bindings/src/events/ReactDOMEventListener.js b/packages/react-dom-bindings/src/events/ReactDOMEventListener.js index 525f7bd358c90..9f8601bb1d75e 100644 --- a/packages/react-dom-bindings/src/events/ReactDOMEventListener.js +++ b/packages/react-dom-bindings/src/events/ReactDOMEventListener.js @@ -56,8 +56,6 @@ import { import ReactSharedInternals from 'shared/ReactSharedInternals'; import {isRootDehydrated} from 'react-reconciler/src/ReactFiberShellHydration'; -const {ReactCurrentBatchConfig} = ReactSharedInternals; - // TODO: can we stop exporting these? let _enabled: boolean = true; @@ -117,15 +115,15 @@ function dispatchDiscreteEvent( container: EventTarget, nativeEvent: AnyNativeEvent, ) { - const prevTransition = ReactCurrentBatchConfig.transition; - ReactCurrentBatchConfig.transition = null; + const prevTransition = ReactSharedInternals.T; + ReactSharedInternals.T = null; const previousPriority = getCurrentUpdatePriority(); try { setCurrentUpdatePriority(DiscreteEventPriority); dispatchEvent(domEventName, eventSystemFlags, container, nativeEvent); } finally { setCurrentUpdatePriority(previousPriority); - ReactCurrentBatchConfig.transition = prevTransition; + ReactSharedInternals.T = prevTransition; } } @@ -135,15 +133,15 @@ function dispatchContinuousEvent( container: EventTarget, nativeEvent: AnyNativeEvent, ) { - const prevTransition = ReactCurrentBatchConfig.transition; - ReactCurrentBatchConfig.transition = null; + const prevTransition = ReactSharedInternals.T; + ReactSharedInternals.T = null; const previousPriority = getCurrentUpdatePriority(); try { setCurrentUpdatePriority(ContinuousEventPriority); dispatchEvent(domEventName, eventSystemFlags, container, nativeEvent); } finally { setCurrentUpdatePriority(previousPriority); - ReactCurrentBatchConfig.transition = prevTransition; + ReactSharedInternals.T = prevTransition; } } diff --git a/packages/react-dom-bindings/src/shared/ReactDOMFormActions.js b/packages/react-dom-bindings/src/shared/ReactDOMFormActions.js index 284eaff1bb6bb..42967f7ce499b 100644 --- a/packages/react-dom-bindings/src/shared/ReactDOMFormActions.js +++ b/packages/react-dom-bindings/src/shared/ReactDOMFormActions.js @@ -13,8 +13,6 @@ import type {Awaited} from 'shared/ReactTypes'; import {enableAsyncActions} from 'shared/ReactFeatureFlags'; import ReactSharedInternals from 'shared/ReactSharedInternals'; -const ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher; - type FormStatusNotPending = {| pending: false, data: null, @@ -47,7 +45,7 @@ export const NotPending: FormStatus = __DEV__ function resolveDispatcher() { // Copied from react/src/ReactHooks.js. It's the same thing but in a // different package. - const dispatcher = ReactCurrentDispatcher.current; + const dispatcher = ReactSharedInternals.H; if (__DEV__) { if (dispatcher === null) { console.error( diff --git a/packages/react-dom/src/__tests__/ReactCompositeComponent-test.js b/packages/react-dom/src/__tests__/ReactCompositeComponent-test.js index ba3118bc651b0..030573a38075d 100644 --- a/packages/react-dom/src/__tests__/ReactCompositeComponent-test.js +++ b/packages/react-dom/src/__tests__/ReactCompositeComponent-test.js @@ -14,7 +14,7 @@ let MorphingComponent; let React; let ReactDOM; let ReactDOMClient; -let ReactCurrentOwner; +let ReactSharedInternals; let Scheduler; let assertLog; let act; @@ -67,9 +67,8 @@ describe('ReactCompositeComponent', () => { React = require('react'); ReactDOM = require('react-dom'); ReactDOMClient = require('react-dom/client'); - ReactCurrentOwner = - require('react').__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED - .ReactCurrentOwner; + ReactSharedInternals = + require('react').__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; Scheduler = require('scheduler'); assertLog = require('internal-test-utils').assertLog; act = require('internal-test-utils').act; @@ -545,7 +544,9 @@ describe('ReactCompositeComponent', () => { } const instance = ; - expect(ReactCurrentOwner.current).toBe(null); + expect(ReactSharedInternals.owner).toBe( + __DEV__ || !gate(flags => flags.disableStringRefs) ? null : undefined, + ); const root = ReactDOMClient.createRoot(document.createElement('div')); await expect(async () => { @@ -554,7 +555,9 @@ describe('ReactCompositeComponent', () => { }); }).rejects.toThrow(); - expect(ReactCurrentOwner.current).toBe(null); + expect(ReactSharedInternals.owner).toBe( + __DEV__ || !gate(flags => flags.disableStringRefs) ? null : undefined, + ); }); it('should call componentWillUnmount before unmounting', async () => { diff --git a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationHooks-test.js b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationHooks-test.js index 9bd7d2ec3f027..464e71ed43f70 100644 --- a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationHooks-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationHooks-test.js @@ -775,8 +775,7 @@ describe('ReactDOMServerHooks', () => { describe('readContext', () => { function readContext(Context) { const dispatcher = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED - .ReactCurrentDispatcher.current; + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.H; return dispatcher.readContext(Context); } diff --git a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationNewContext-test.js b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationNewContext-test.js index df4deff9e23d4..850b52e3be8fb 100644 --- a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationNewContext-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationNewContext-test.js @@ -161,8 +161,7 @@ describe('ReactDOMServerIntegration', () => { itRenders('readContext() in different components', async render => { function readContext(Ctx) { const dispatcher = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED - .ReactCurrentDispatcher.current; + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.H; return dispatcher.readContext(Ctx); } diff --git a/packages/react-dom/src/__tests__/ReactServerRendering-test.js b/packages/react-dom/src/__tests__/ReactServerRendering-test.js index efacdb8be9a4e..3dd1ca5ac3f8b 100644 --- a/packages/react-dom/src/__tests__/ReactServerRendering-test.js +++ b/packages/react-dom/src/__tests__/ReactServerRendering-test.js @@ -13,7 +13,7 @@ let React; let ReactDOMServer; let PropTypes; -let ReactCurrentDispatcher; +let ReactSharedInternals; describe('ReactDOMServer', () => { beforeEach(() => { @@ -21,9 +21,8 @@ describe('ReactDOMServer', () => { React = require('react'); PropTypes = require('prop-types'); ReactDOMServer = require('react-dom/server'); - ReactCurrentDispatcher = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED - .ReactCurrentDispatcher; + ReactSharedInternals = + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; }); describe('renderToString', () => { @@ -420,7 +419,7 @@ describe('ReactDOMServer', () => { const Context = React.createContext(0); function readContext(context) { - return ReactCurrentDispatcher.current.readContext(context); + return ReactSharedInternals.H.readContext(context); } function Consumer(props) { diff --git a/packages/react-dom/src/client/ReactDOMRootFB.js b/packages/react-dom/src/client/ReactDOMRootFB.js index 2d6f5187be229..38fe67c0a5b26 100644 --- a/packages/react-dom/src/client/ReactDOMRootFB.js +++ b/packages/react-dom/src/client/ReactDOMRootFB.js @@ -154,8 +154,6 @@ export function hydrateRoot( ); } -const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; - let topLevelUpdateWarnings; if (__DEV__) { @@ -344,7 +342,7 @@ export function findDOMNode( componentOrElement: Element | ?React$Component, ): null | Element | Text { if (__DEV__) { - const owner = (ReactCurrentOwner.current: any); + const owner = (ReactSharedInternals.owner: any); if (owner !== null && owner.stateNode !== null) { const warnedAboutRefsInRender = owner.stateNode._warnedAboutRefsInRender; if (!warnedAboutRefsInRender) { diff --git a/packages/react-dom/src/shared/ReactDOMFlushSync.js b/packages/react-dom/src/shared/ReactDOMFlushSync.js index c81e35c7e7d5a..a09ba546a81ac 100644 --- a/packages/react-dom/src/shared/ReactDOMFlushSync.js +++ b/packages/react-dom/src/shared/ReactDOMFlushSync.js @@ -7,26 +7,22 @@ * @flow */ -import type {BatchConfig} from 'react/src/ReactCurrentBatchConfig'; - import {disableLegacyMode} from 'shared/ReactFeatureFlags'; import {DiscreteEventPriority} from 'react-reconciler/src/ReactEventPriorities'; import ReactSharedInternals from 'shared/ReactSharedInternals'; -const ReactCurrentBatchConfig: BatchConfig = - ReactSharedInternals.ReactCurrentBatchConfig; import ReactDOMSharedInternals from 'shared/ReactDOMSharedInternals'; declare function flushSyncImpl(fn: () => R): R; declare function flushSyncImpl(void): void; function flushSyncImpl(fn: (() => R) | void): R | void { - const previousTransition = ReactCurrentBatchConfig.transition; + const previousTransition = ReactSharedInternals.T; const previousUpdatePriority = ReactDOMSharedInternals.p; /* ReactDOMCurrentUpdatePriority */ try { - ReactCurrentBatchConfig.transition = null; + ReactSharedInternals.T = null; ReactDOMSharedInternals.p /* ReactDOMCurrentUpdatePriority */ = DiscreteEventPriority; if (fn) { @@ -35,7 +31,7 @@ function flushSyncImpl(fn: (() => R) | void): R | void { return undefined; } } finally { - ReactCurrentBatchConfig.transition = previousTransition; + ReactSharedInternals.T = previousTransition; ReactDOMSharedInternals.p /* ReactDOMCurrentUpdatePriority */ = previousUpdatePriority; const wasInRender = diff --git a/packages/react-native-renderer/src/ReactNativePublicCompat.js b/packages/react-native-renderer/src/ReactNativePublicCompat.js index 7a3871a4d1ea3..93b85e172d414 100644 --- a/packages/react-native-renderer/src/ReactNativePublicCompat.js +++ b/packages/react-native-renderer/src/ReactNativePublicCompat.js @@ -27,13 +27,11 @@ import {doesFiberContain} from 'react-reconciler/src/ReactFiberTreeReflection'; import ReactSharedInternals from 'shared/ReactSharedInternals'; import getComponentNameFromType from 'shared/getComponentNameFromType'; -const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; - export function findHostInstance_DEPRECATED( componentOrHandle: ?(ElementRef | number), ): ?ElementRef> { if (__DEV__) { - const owner = ReactCurrentOwner.current; + const owner = ReactSharedInternals.owner; if (owner !== null && owner.stateNode !== null) { if (!owner.stateNode._warnedAboutRefsInRender) { console.error( @@ -88,7 +86,7 @@ export function findHostInstance_DEPRECATED( export function findNodeHandle(componentOrHandle: any): ?number { if (__DEV__) { - const owner = ReactCurrentOwner.current; + const owner = ReactSharedInternals.owner; if (owner !== null && owner.stateNode !== null) { if (!owner.stateNode._warnedAboutRefsInRender) { console.error( diff --git a/packages/react-noop-renderer/src/createReactNoop.js b/packages/react-noop-renderer/src/createReactNoop.js index 9bb0a5fc1ca26..f64499c6dc801 100644 --- a/packages/react-noop-renderer/src/createReactNoop.js +++ b/packages/react-noop-renderer/src/createReactNoop.js @@ -42,7 +42,6 @@ import { } from 'shared/ReactFeatureFlags'; import ReactSharedInternals from 'shared/ReactSharedInternals'; -const ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; type Container = { rootID: string, @@ -948,10 +947,10 @@ function createReactNoop(reconciler: Function, useMutation: boolean) { } } if (disableLegacyMode) { - const previousTransition = ReactCurrentBatchConfig.transition; + const previousTransition = ReactSharedInternals.T; const preivousEventPriority = currentEventPriority; try { - ReactCurrentBatchConfig.transition = null; + ReactSharedInternals.T = null; currentEventPriority = DiscreteEventPriority; if (fn) { return fn(); @@ -959,7 +958,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) { return undefined; } } finally { - ReactCurrentBatchConfig.transition = previousTransition; + ReactSharedInternals.T = previousTransition; currentEventPriority = preivousEventPriority; NoopRenderer.flushSyncWork(); } diff --git a/packages/react-reconciler/src/ReactCurrentFiber.js b/packages/react-reconciler/src/ReactCurrentFiber.js index c52d55c0cce73..5baa696b28b53 100644 --- a/packages/react-reconciler/src/ReactCurrentFiber.js +++ b/packages/react-reconciler/src/ReactCurrentFiber.js @@ -13,8 +13,6 @@ import ReactSharedInternals from 'shared/ReactSharedInternals'; import {getStackByFiberInDevAndProd} from './ReactFiberComponentStack'; import {getComponentNameFromOwner} from 'react-reconciler/src/getComponentNameFromFiber'; -const ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; - export let current: Fiber | null = null; export let isRendering: boolean = false; @@ -45,7 +43,7 @@ function getCurrentFiberStackInDev(): string { export function resetCurrentFiber() { if (__DEV__) { - ReactDebugCurrentFrame.getCurrentStack = null; + ReactSharedInternals.getCurrentStack = null; current = null; isRendering = false; } @@ -53,7 +51,7 @@ export function resetCurrentFiber() { export function setCurrentFiber(fiber: Fiber | null) { if (__DEV__) { - ReactDebugCurrentFrame.getCurrentStack = + ReactSharedInternals.getCurrentStack = fiber === null ? null : getCurrentFiberStackInDev; current = fiber; isRendering = false; diff --git a/packages/react-reconciler/src/ReactFiberAct.js b/packages/react-reconciler/src/ReactFiberAct.js index 117a7fc05196b..b611d7472b095 100644 --- a/packages/react-reconciler/src/ReactFiberAct.js +++ b/packages/react-reconciler/src/ReactFiberAct.js @@ -13,8 +13,6 @@ import ReactSharedInternals from 'shared/ReactSharedInternals'; import {warnsIfNotActing} from './ReactFiberConfig'; -const {ReactCurrentActQueue} = ReactSharedInternals; - export function isLegacyActEnvironment(fiber: Fiber): boolean { if (__DEV__) { // Legacy mode. We preserve the behavior of React 17's act. It assumes an @@ -47,7 +45,10 @@ export function isConcurrentActEnvironment(): void | boolean { IS_REACT_ACT_ENVIRONMENT : undefined; - if (!isReactActEnvironmentGlobal && ReactCurrentActQueue.current !== null) { + if ( + !isReactActEnvironmentGlobal && + ReactSharedInternals.actQueue !== null + ) { // TODO: Include link to relevant documentation page. console.error( 'The current testing environment is not configured to support ' + diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.js b/packages/react-reconciler/src/ReactFiberBeginWork.js index 840a317c0ed11..21964cc456e3e 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.js @@ -110,6 +110,7 @@ import { enableRefAsProp, disableLegacyMode, disableDefaultPropsExceptForClasses, + disableStringRefs, } from 'shared/ReactFeatureFlags'; import isArray from 'shared/isArray'; import shallowEqual from 'shared/shallowEqual'; @@ -297,8 +298,6 @@ import { TransitionTracingMarker, } from './ReactFiberTracingMarkerComponent'; -const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; - // A special exception that's used to unwind the stack when an update flows // into a dehydrated boundary. export const SelectiveHydrationException: mixed = new Error( @@ -433,7 +432,7 @@ function updateForwardRef( markComponentRenderStarted(workInProgress); } if (__DEV__) { - ReactCurrentOwner.current = workInProgress; + ReactSharedInternals.owner = workInProgress; setIsRendering(true); nextChildren = renderWithHooks( current, @@ -1132,7 +1131,7 @@ function updateFunctionComponent( markComponentRenderStarted(workInProgress); } if (__DEV__) { - ReactCurrentOwner.current = workInProgress; + ReactSharedInternals.owner = workInProgress; setIsRendering(true); nextChildren = renderWithHooks( current, @@ -1354,7 +1353,9 @@ function finishClassComponent( const instance = workInProgress.stateNode; // Rerender - ReactCurrentOwner.current = workInProgress; + if (__DEV__ || !disableStringRefs) { + ReactSharedInternals.owner = workInProgress; + } let nextChildren; if ( didCaptureError && @@ -3399,7 +3400,7 @@ function updateContextConsumer( } let newChildren; if (__DEV__) { - ReactCurrentOwner.current = workInProgress; + ReactSharedInternals.owner = workInProgress; setIsRendering(true); newChildren = render(newValue); setIsRendering(false); diff --git a/packages/react-reconciler/src/ReactFiberErrorLogger.js b/packages/react-reconciler/src/ReactFiberErrorLogger.js index 6b2da6508dd3c..381346e6b4a95 100644 --- a/packages/react-reconciler/src/ReactFiberErrorLogger.js +++ b/packages/react-reconciler/src/ReactFiberErrorLogger.js @@ -17,7 +17,6 @@ import {ClassComponent} from './ReactWorkTags'; import reportGlobalError from 'shared/reportGlobalError'; import ReactSharedInternals from 'shared/ReactSharedInternals'; -const {ReactCurrentActQueue} = ReactSharedInternals; // Side-channel since I'm not sure we want to make this part of the public API let componentName: null | string = null; @@ -111,10 +110,10 @@ export function logUncaughtError( errorBoundaryName = null; } const error = (errorInfo.value: any); - if (__DEV__ && ReactCurrentActQueue.current !== null) { + if (__DEV__ && ReactSharedInternals.actQueue !== null) { // For uncaught errors inside act, we track them on the act and then // rethrow them into the test. - ReactCurrentActQueue.thrownErrors.push(error); + ReactSharedInternals.thrownErrors.push(error); return; } const onUncaughtError = root.onUncaughtError; diff --git a/packages/react-reconciler/src/ReactFiberHooks.js b/packages/react-reconciler/src/ReactFiberHooks.js index 0d4e803a7a130..009ecf1903e80 100644 --- a/packages/react-reconciler/src/ReactFiberHooks.js +++ b/packages/react-reconciler/src/ReactFiberHooks.js @@ -157,8 +157,6 @@ import { requestCurrentTransition, } from './ReactFiberTransition'; -const {ReactCurrentDispatcher, ReactCurrentBatchConfig} = ReactSharedInternals; - export type Update = { lane: Lane, revertLane: Lane, @@ -537,19 +535,19 @@ export function renderWithHooks( // so memoizedState would be null during updates and mounts. if (__DEV__) { if (current !== null && current.memoizedState !== null) { - ReactCurrentDispatcher.current = HooksDispatcherOnUpdateInDEV; + ReactSharedInternals.H = HooksDispatcherOnUpdateInDEV; } else if (hookTypesDev !== null) { // This dispatcher handles an edge case where a component is updating, // but no stateful hooks have been used. // We want to match the production code behavior (which will use HooksDispatcherOnMount), // but with the extra DEV validation to ensure hooks ordering hasn't changed. // This dispatcher does that. - ReactCurrentDispatcher.current = HooksDispatcherOnMountWithHookTypesInDEV; + ReactSharedInternals.H = HooksDispatcherOnMountWithHookTypesInDEV; } else { - ReactCurrentDispatcher.current = HooksDispatcherOnMountInDEV; + ReactSharedInternals.H = HooksDispatcherOnMountInDEV; } } else { - ReactCurrentDispatcher.current = + ReactSharedInternals.H = current === null || current.memoizedState === null ? HooksDispatcherOnMount : HooksDispatcherOnUpdate; @@ -633,7 +631,7 @@ function finishRenderingHooks( // We can assume the previous dispatcher is always this one, since we set it // at the beginning of the render phase and there's no re-entrance. - ReactCurrentDispatcher.current = ContextOnlyDispatcher; + ReactSharedInternals.H = ContextOnlyDispatcher; // This check uses currentHook so that it works the same in DEV and prod bundles. // hookTypesDev could catch more cases (e.g. context) but only in DEV bundles. @@ -815,7 +813,7 @@ function renderWithHooksAgain( hookTypesUpdateIndexDev = -1; } - ReactCurrentDispatcher.current = __DEV__ + ReactSharedInternals.H = __DEV__ ? HooksDispatcherOnRerenderInDEV : HooksDispatcherOnRerender; @@ -846,7 +844,7 @@ export function TransitionAwareHostComponent(): TransitionStatus { if (!enableAsyncActions) { throw new Error('Not implemented.'); } - const dispatcher = ReactCurrentDispatcher.current; + const dispatcher: any = ReactSharedInternals.H; const [maybeThenable] = dispatcher.useState(); if (typeof maybeThenable.then === 'function') { const thenable: Thenable = (maybeThenable: any); @@ -898,7 +896,7 @@ export function resetHooksAfterThrow(): void { // We can assume the previous dispatcher is always this one, since we set it // at the beginning of the render phase and there's no re-entrance. - ReactCurrentDispatcher.current = ContextOnlyDispatcher; + ReactSharedInternals.H = ContextOnlyDispatcher; } export function resetHooksOnUnwind(workInProgress: Fiber): void { @@ -1074,9 +1072,9 @@ function useThenable(thenable: Thenable): T { // time (perhaps because it threw). Subsequent Hook calls should use the // mount dispatcher. if (__DEV__) { - ReactCurrentDispatcher.current = HooksDispatcherOnMountInDEV; + ReactSharedInternals.H = HooksDispatcherOnMountInDEV; } else { - ReactCurrentDispatcher.current = HooksDispatcherOnMount; + ReactSharedInternals.H = HooksDispatcherOnMount; } } return result; @@ -1977,13 +1975,13 @@ function runActionStateAction( const prevState = actionQueue.state; // This is a fork of startTransition - const prevTransition = ReactCurrentBatchConfig.transition; + const prevTransition = ReactSharedInternals.T; const currentTransition: BatchConfigTransition = { _callbacks: new Set<(BatchConfigTransition, mixed) => mixed>(), }; - ReactCurrentBatchConfig.transition = currentTransition; + ReactSharedInternals.T = currentTransition; if (__DEV__) { - ReactCurrentBatchConfig.transition._updatedFibers = new Set(); + ReactSharedInternals.T._updatedFibers = new Set(); } // Optimistically update the pending state, similar to useTransition. @@ -2049,7 +2047,7 @@ function runActionStateAction( (setState: any), ); } finally { - ReactCurrentBatchConfig.transition = prevTransition; + ReactSharedInternals.T = prevTransition; if (__DEV__) { if (prevTransition === null && currentTransition._updatedFibers) { @@ -2795,7 +2793,7 @@ function startTransition( higherEventPriority(previousPriority, ContinuousEventPriority), ); - const prevTransition = ReactCurrentBatchConfig.transition; + const prevTransition = ReactSharedInternals.T; const currentTransition: BatchConfigTransition = { _callbacks: new Set<(BatchConfigTransition, mixed) => mixed>(), }; @@ -2807,23 +2805,23 @@ function startTransition( // optimistic update anyway to make it less likely the behavior accidentally // diverges; for example, both an optimistic update and this one should // share the same lane. - ReactCurrentBatchConfig.transition = currentTransition; + ReactSharedInternals.T = currentTransition; dispatchOptimisticSetState(fiber, false, queue, pendingState); } else { - ReactCurrentBatchConfig.transition = null; + ReactSharedInternals.T = null; dispatchSetState(fiber, queue, pendingState); - ReactCurrentBatchConfig.transition = currentTransition; + ReactSharedInternals.T = currentTransition; } if (enableTransitionTracing) { if (options !== undefined && options.name !== undefined) { - ReactCurrentBatchConfig.transition.name = options.name; - ReactCurrentBatchConfig.transition.startTime = now(); + currentTransition.name = options.name; + currentTransition.startTime = now(); } } if (__DEV__) { - ReactCurrentBatchConfig.transition._updatedFibers = new Set(); + currentTransition._updatedFibers = new Set(); } try { @@ -2879,7 +2877,7 @@ function startTransition( } finally { setCurrentUpdatePriority(previousPriority); - ReactCurrentBatchConfig.transition = prevTransition; + ReactSharedInternals.T = prevTransition; if (__DEV__) { if (prevTransition === null && currentTransition._updatedFibers) { @@ -3216,11 +3214,10 @@ function dispatchSetState( // same as the current state, we may be able to bail out entirely. const lastRenderedReducer = queue.lastRenderedReducer; if (lastRenderedReducer !== null) { - let prevDispatcher; + let prevDispatcher = null; if (__DEV__) { - prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = - InvalidNestedHooksDispatcherOnUpdateInDEV; + prevDispatcher = ReactSharedInternals.H; + ReactSharedInternals.H = InvalidNestedHooksDispatcherOnUpdateInDEV; } try { const currentState: S = (queue.lastRenderedState: any); @@ -3244,7 +3241,7 @@ function dispatchSetState( // Suppress the error. It will throw again in the render phase. } finally { if (__DEV__) { - ReactCurrentDispatcher.current = prevDispatcher; + ReactSharedInternals.H = prevDispatcher; } } } @@ -3657,12 +3654,12 @@ if (__DEV__) { currentHookNameInDev = 'useMemo'; mountHookTypesDev(); checkDepsAreArrayDev(deps); - const prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV; + const prevDispatcher = ReactSharedInternals.H; + ReactSharedInternals.H = InvalidNestedHooksDispatcherOnMountInDEV; try { return mountMemo(create, deps); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactSharedInternals.H = prevDispatcher; } }, useReducer( @@ -3672,12 +3669,12 @@ if (__DEV__) { ): [S, Dispatch] { currentHookNameInDev = 'useReducer'; mountHookTypesDev(); - const prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV; + const prevDispatcher = ReactSharedInternals.H; + ReactSharedInternals.H = InvalidNestedHooksDispatcherOnMountInDEV; try { return mountReducer(reducer, initialArg, init); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactSharedInternals.H = prevDispatcher; } }, useRef(initialValue: T): {current: T} { @@ -3690,12 +3687,12 @@ if (__DEV__) { ): [S, Dispatch>] { currentHookNameInDev = 'useState'; mountHookTypesDev(); - const prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV; + const prevDispatcher = ReactSharedInternals.H; + ReactSharedInternals.H = InvalidNestedHooksDispatcherOnMountInDEV; try { return mountState(initialState); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactSharedInternals.H = prevDispatcher; } }, useDebugValue(value: T, formatterFn: ?(value: T) => mixed): void { @@ -3836,12 +3833,12 @@ if (__DEV__) { useMemo(create: () => T, deps: Array | void | null): T { currentHookNameInDev = 'useMemo'; updateHookTypesDev(); - const prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV; + const prevDispatcher = ReactSharedInternals.H; + ReactSharedInternals.H = InvalidNestedHooksDispatcherOnMountInDEV; try { return mountMemo(create, deps); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactSharedInternals.H = prevDispatcher; } }, useReducer( @@ -3851,12 +3848,12 @@ if (__DEV__) { ): [S, Dispatch] { currentHookNameInDev = 'useReducer'; updateHookTypesDev(); - const prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV; + const prevDispatcher = ReactSharedInternals.H; + ReactSharedInternals.H = InvalidNestedHooksDispatcherOnMountInDEV; try { return mountReducer(reducer, initialArg, init); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactSharedInternals.H = prevDispatcher; } }, useRef(initialValue: T): {current: T} { @@ -3869,12 +3866,12 @@ if (__DEV__) { ): [S, Dispatch>] { currentHookNameInDev = 'useState'; updateHookTypesDev(); - const prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV; + const prevDispatcher = ReactSharedInternals.H; + ReactSharedInternals.H = InvalidNestedHooksDispatcherOnMountInDEV; try { return mountState(initialState); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactSharedInternals.H = prevDispatcher; } }, useDebugValue(value: T, formatterFn: ?(value: T) => mixed): void { @@ -4017,13 +4014,12 @@ if (__DEV__) { useMemo(create: () => T, deps: Array | void | null): T { currentHookNameInDev = 'useMemo'; updateHookTypesDev(); - const prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = - InvalidNestedHooksDispatcherOnUpdateInDEV; + const prevDispatcher = ReactSharedInternals.H; + ReactSharedInternals.H = InvalidNestedHooksDispatcherOnUpdateInDEV; try { return updateMemo(create, deps); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactSharedInternals.H = prevDispatcher; } }, useReducer( @@ -4033,13 +4029,12 @@ if (__DEV__) { ): [S, Dispatch] { currentHookNameInDev = 'useReducer'; updateHookTypesDev(); - const prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = - InvalidNestedHooksDispatcherOnUpdateInDEV; + const prevDispatcher = ReactSharedInternals.H; + ReactSharedInternals.H = InvalidNestedHooksDispatcherOnUpdateInDEV; try { return updateReducer(reducer, initialArg, init); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactSharedInternals.H = prevDispatcher; } }, useRef(initialValue: T): {current: T} { @@ -4052,13 +4047,12 @@ if (__DEV__) { ): [S, Dispatch>] { currentHookNameInDev = 'useState'; updateHookTypesDev(); - const prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = - InvalidNestedHooksDispatcherOnUpdateInDEV; + const prevDispatcher = ReactSharedInternals.H; + ReactSharedInternals.H = InvalidNestedHooksDispatcherOnUpdateInDEV; try { return updateState(initialState); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactSharedInternals.H = prevDispatcher; } }, useDebugValue(value: T, formatterFn: ?(value: T) => mixed): void { @@ -4200,13 +4194,12 @@ if (__DEV__) { useMemo(create: () => T, deps: Array | void | null): T { currentHookNameInDev = 'useMemo'; updateHookTypesDev(); - const prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = - InvalidNestedHooksDispatcherOnRerenderInDEV; + const prevDispatcher = ReactSharedInternals.H; + ReactSharedInternals.H = InvalidNestedHooksDispatcherOnRerenderInDEV; try { return updateMemo(create, deps); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactSharedInternals.H = prevDispatcher; } }, useReducer( @@ -4216,13 +4209,12 @@ if (__DEV__) { ): [S, Dispatch] { currentHookNameInDev = 'useReducer'; updateHookTypesDev(); - const prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = - InvalidNestedHooksDispatcherOnRerenderInDEV; + const prevDispatcher = ReactSharedInternals.H; + ReactSharedInternals.H = InvalidNestedHooksDispatcherOnRerenderInDEV; try { return rerenderReducer(reducer, initialArg, init); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactSharedInternals.H = prevDispatcher; } }, useRef(initialValue: T): {current: T} { @@ -4235,13 +4227,12 @@ if (__DEV__) { ): [S, Dispatch>] { currentHookNameInDev = 'useState'; updateHookTypesDev(); - const prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = - InvalidNestedHooksDispatcherOnRerenderInDEV; + const prevDispatcher = ReactSharedInternals.H; + ReactSharedInternals.H = InvalidNestedHooksDispatcherOnRerenderInDEV; try { return rerenderState(initialState); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactSharedInternals.H = prevDispatcher; } }, useDebugValue(value: T, formatterFn: ?(value: T) => mixed): void { @@ -4394,12 +4385,12 @@ if (__DEV__) { currentHookNameInDev = 'useMemo'; warnInvalidHookAccess(); mountHookTypesDev(); - const prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV; + const prevDispatcher = ReactSharedInternals.H; + ReactSharedInternals.H = InvalidNestedHooksDispatcherOnMountInDEV; try { return mountMemo(create, deps); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactSharedInternals.H = prevDispatcher; } }, useReducer( @@ -4410,12 +4401,12 @@ if (__DEV__) { currentHookNameInDev = 'useReducer'; warnInvalidHookAccess(); mountHookTypesDev(); - const prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV; + const prevDispatcher = ReactSharedInternals.H; + ReactSharedInternals.H = InvalidNestedHooksDispatcherOnMountInDEV; try { return mountReducer(reducer, initialArg, init); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactSharedInternals.H = prevDispatcher; } }, useRef(initialValue: T): {current: T} { @@ -4430,12 +4421,12 @@ if (__DEV__) { currentHookNameInDev = 'useState'; warnInvalidHookAccess(); mountHookTypesDev(); - const prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV; + const prevDispatcher = ReactSharedInternals.H; + ReactSharedInternals.H = InvalidNestedHooksDispatcherOnMountInDEV; try { return mountState(initialState); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactSharedInternals.H = prevDispatcher; } }, useDebugValue(value: T, formatterFn: ?(value: T) => mixed): void { @@ -4600,13 +4591,12 @@ if (__DEV__) { currentHookNameInDev = 'useMemo'; warnInvalidHookAccess(); updateHookTypesDev(); - const prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = - InvalidNestedHooksDispatcherOnUpdateInDEV; + const prevDispatcher = ReactSharedInternals.H; + ReactSharedInternals.H = InvalidNestedHooksDispatcherOnUpdateInDEV; try { return updateMemo(create, deps); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactSharedInternals.H = prevDispatcher; } }, useReducer( @@ -4617,13 +4607,12 @@ if (__DEV__) { currentHookNameInDev = 'useReducer'; warnInvalidHookAccess(); updateHookTypesDev(); - const prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = - InvalidNestedHooksDispatcherOnUpdateInDEV; + const prevDispatcher = ReactSharedInternals.H; + ReactSharedInternals.H = InvalidNestedHooksDispatcherOnUpdateInDEV; try { return updateReducer(reducer, initialArg, init); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactSharedInternals.H = prevDispatcher; } }, useRef(initialValue: T): {current: T} { @@ -4638,13 +4627,12 @@ if (__DEV__) { currentHookNameInDev = 'useState'; warnInvalidHookAccess(); updateHookTypesDev(); - const prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = - InvalidNestedHooksDispatcherOnUpdateInDEV; + const prevDispatcher = ReactSharedInternals.H; + ReactSharedInternals.H = InvalidNestedHooksDispatcherOnUpdateInDEV; try { return updateState(initialState); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactSharedInternals.H = prevDispatcher; } }, useDebugValue(value: T, formatterFn: ?(value: T) => mixed): void { @@ -4809,13 +4797,12 @@ if (__DEV__) { currentHookNameInDev = 'useMemo'; warnInvalidHookAccess(); updateHookTypesDev(); - const prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = - InvalidNestedHooksDispatcherOnUpdateInDEV; + const prevDispatcher = ReactSharedInternals.H; + ReactSharedInternals.H = InvalidNestedHooksDispatcherOnUpdateInDEV; try { return updateMemo(create, deps); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactSharedInternals.H = prevDispatcher; } }, useReducer( @@ -4826,13 +4813,12 @@ if (__DEV__) { currentHookNameInDev = 'useReducer'; warnInvalidHookAccess(); updateHookTypesDev(); - const prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = - InvalidNestedHooksDispatcherOnUpdateInDEV; + const prevDispatcher = ReactSharedInternals.H; + ReactSharedInternals.H = InvalidNestedHooksDispatcherOnUpdateInDEV; try { return rerenderReducer(reducer, initialArg, init); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactSharedInternals.H = prevDispatcher; } }, useRef(initialValue: T): {current: T} { @@ -4847,13 +4833,12 @@ if (__DEV__) { currentHookNameInDev = 'useState'; warnInvalidHookAccess(); updateHookTypesDev(); - const prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = - InvalidNestedHooksDispatcherOnUpdateInDEV; + const prevDispatcher = ReactSharedInternals.H; + ReactSharedInternals.H = InvalidNestedHooksDispatcherOnUpdateInDEV; try { return rerenderState(initialState); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactSharedInternals.H = prevDispatcher; } }, useDebugValue(value: T, formatterFn: ?(value: T) => mixed): void { diff --git a/packages/react-reconciler/src/ReactFiberReconciler.js b/packages/react-reconciler/src/ReactFiberReconciler.js index fc2eb5bef39e0..641f229b6dea3 100644 --- a/packages/react-reconciler/src/ReactFiberReconciler.js +++ b/packages/react-reconciler/src/ReactFiberReconciler.js @@ -859,7 +859,6 @@ function getCurrentFiberForDevTools() { export function injectIntoDevTools(devToolsConfig: DevToolsConfig): boolean { const {findFiberByHostInstance} = devToolsConfig; - const {ReactCurrentDispatcher} = ReactSharedInternals; return injectInternals({ bundleType: devToolsConfig.bundleType, @@ -875,7 +874,7 @@ export function injectIntoDevTools(devToolsConfig: DevToolsConfig): boolean { setErrorHandler, setSuspenseHandler, scheduleUpdate, - currentDispatcherRef: ReactCurrentDispatcher, + currentDispatcherRef: ReactSharedInternals, findHostInstanceByFiber, findFiberByHostInstance: findFiberByHostInstance || emptyFindFiberByHostInstance, diff --git a/packages/react-reconciler/src/ReactFiberRootScheduler.js b/packages/react-reconciler/src/ReactFiberRootScheduler.js index 12f7660596664..eee02d2cb162a 100644 --- a/packages/react-reconciler/src/ReactFiberRootScheduler.js +++ b/packages/react-reconciler/src/ReactFiberRootScheduler.js @@ -62,7 +62,6 @@ import { } from './ReactFiberConfig'; import ReactSharedInternals from 'shared/ReactSharedInternals'; -const {ReactCurrentActQueue} = ReactSharedInternals; // A linked list of all the roots with pending work. In an idiomatic app, // there's only a single root, but we do support multi root apps, hence this @@ -111,7 +110,7 @@ export function ensureRootIsScheduled(root: FiberRoot): void { // At the end of the current event, go through each of the roots and ensure // there's a task scheduled for each one at the correct priority. - if (__DEV__ && ReactCurrentActQueue.current !== null) { + if (__DEV__ && ReactSharedInternals.actQueue !== null) { // We're inside an `act` scope. if (!didScheduleMicrotask_act) { didScheduleMicrotask_act = true; @@ -135,11 +134,11 @@ export function ensureRootIsScheduled(root: FiberRoot): void { if ( __DEV__ && !disableLegacyMode && - ReactCurrentActQueue.isBatchingLegacy && + ReactSharedInternals.isBatchingLegacy && root.tag === LegacyRoot ) { // Special `act` case: Record whenever a legacy update is scheduled. - ReactCurrentActQueue.didScheduleLegacyUpdate = true; + ReactSharedInternals.didScheduleLegacyUpdate = true; } } @@ -333,7 +332,7 @@ function scheduleTaskForRootDuringMicrotask( // on the `act` queue. !( __DEV__ && - ReactCurrentActQueue.current !== null && + ReactSharedInternals.actQueue !== null && existingCallbackNode !== fakeActCallbackNode ) ) { @@ -403,11 +402,11 @@ function scheduleCallback( priorityLevel: PriorityLevel, callback: RenderTaskFn, ) { - if (__DEV__ && ReactCurrentActQueue.current !== null) { + if (__DEV__ && ReactSharedInternals.actQueue !== null) { // Special case: We're inside an `act` scope (a testing utility). // Instead of scheduling work in the host environment, add it to a // fake internal queue that's managed by the `act` implementation. - ReactCurrentActQueue.current.push(callback); + ReactSharedInternals.actQueue.push(callback); return fakeActCallbackNode; } else { return Scheduler_scheduleCallback(priorityLevel, callback); @@ -424,13 +423,13 @@ function cancelCallback(callbackNode: mixed) { } function scheduleImmediateTask(cb: () => mixed) { - if (__DEV__ && ReactCurrentActQueue.current !== null) { + if (__DEV__ && ReactSharedInternals.actQueue !== null) { // Special case: Inside an `act` scope, we push microtasks to the fake `act` // callback queue. This is because we currently support calling `act` // without awaiting the result. The plan is to deprecate that, and require // that you always await the result so that the microtasks have a chance to // run. But it hasn't happened yet. - ReactCurrentActQueue.current.push(() => { + ReactSharedInternals.actQueue.push(() => { cb(); return null; }); diff --git a/packages/react-reconciler/src/ReactFiberThenable.js b/packages/react-reconciler/src/ReactFiberThenable.js index e34d9ad5e2275..8c302e99a32fc 100644 --- a/packages/react-reconciler/src/ReactFiberThenable.js +++ b/packages/react-reconciler/src/ReactFiberThenable.js @@ -17,7 +17,6 @@ import type { import {getWorkInProgressRoot} from './ReactFiberWorkLoop'; import ReactSharedInternals from 'shared/ReactSharedInternals'; -const {ReactCurrentActQueue} = ReactSharedInternals; opaque type ThenableStateDev = { didWarnAboutUncachedPromise: boolean, @@ -95,8 +94,8 @@ export function trackUsedThenable( thenable: Thenable, index: number, ): T { - if (__DEV__ && ReactCurrentActQueue.current !== null) { - ReactCurrentActQueue.didUsePromise = true; + if (__DEV__ && ReactSharedInternals.actQueue !== null) { + ReactSharedInternals.didUsePromise = true; } const trackedThenables = getThenablesFromState(thenableState); const previous = trackedThenables[index]; diff --git a/packages/react-reconciler/src/ReactFiberTracingMarkerComponent.js b/packages/react-reconciler/src/ReactFiberTracingMarkerComponent.js index 5b6548fadb682..4a0da4958991e 100644 --- a/packages/react-reconciler/src/ReactFiberTracingMarkerComponent.js +++ b/packages/react-reconciler/src/ReactFiberTracingMarkerComponent.js @@ -40,6 +40,7 @@ export type PendingTransitionCallbacks = { export type Transition = { name: string, startTime: number, + ... }; export type BatchConfigTransition = { diff --git a/packages/react-reconciler/src/ReactFiberTransition.js b/packages/react-reconciler/src/ReactFiberTransition.js index 6179e9daf5105..df30ae5ddef35 100644 --- a/packages/react-reconciler/src/ReactFiberTransition.js +++ b/packages/react-reconciler/src/ReactFiberTransition.js @@ -36,16 +36,14 @@ import { import ReactSharedInternals from 'shared/ReactSharedInternals'; import {entangleAsyncAction} from './ReactFiberAsyncAction'; -const {ReactCurrentBatchConfig} = ReactSharedInternals; - export const NoTransition = null; export function requestCurrentTransition(): BatchConfigTransition | null { - const transition = ReactCurrentBatchConfig.transition; + const transition = ReactSharedInternals.T; if (transition !== null) { // Whenever a transition update is scheduled, register a callback on the // transition object so we can get the return value of the scope function. - transition._callbacks.add(handleAsyncAction); + transition._callbacks.add((handleAsyncAction: any)); } return transition; } diff --git a/packages/react-reconciler/src/ReactFiberTreeReflection.js b/packages/react-reconciler/src/ReactFiberTreeReflection.js index ba13faf68ca24..64cc35d2c0bf4 100644 --- a/packages/react-reconciler/src/ReactFiberTreeReflection.js +++ b/packages/react-reconciler/src/ReactFiberTreeReflection.js @@ -26,8 +26,6 @@ import { } from './ReactWorkTags'; import {NoFlags, Placement, Hydrating} from './ReactFiberFlags'; -const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; - export function getNearestMountedFiber(fiber: Fiber): null | Fiber { let node = fiber; let nearestMounted: null | Fiber = fiber; @@ -91,7 +89,7 @@ export function isFiberMounted(fiber: Fiber): boolean { export function isMounted(component: React$Component): boolean { if (__DEV__) { - const owner = (ReactCurrentOwner.current: any); + const owner = (ReactSharedInternals.owner: any); if (owner !== null && owner.tag === ClassComponent) { const ownerFiber: Fiber = owner; const instance = ownerFiber.stateNode; diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.js b/packages/react-reconciler/src/ReactFiberWorkLoop.js index e3f1396bc7f1d..17c1760755a7f 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.js @@ -9,7 +9,6 @@ import {REACT_STRICT_MODE_TYPE} from 'shared/ReactSymbols'; -import type {BatchConfig} from 'react/src/ReactCurrentBatchConfig'; import type {Wakeable, Thenable} from 'shared/ReactTypes'; import type {Fiber, FiberRoot} from './ReactInternalTypes'; import type {Lanes, Lane} from './ReactFiberLane'; @@ -42,6 +41,7 @@ import { enableInfiniteRenderLoopDetection, disableLegacyMode, disableDefaultPropsExceptForClasses, + disableStringRefs, } from 'shared/ReactFeatureFlags'; import ReactSharedInternals from 'shared/ReactSharedInternals'; import is from 'shared/objectIs'; @@ -282,13 +282,6 @@ import {logUncaughtError} from './ReactFiberErrorLogger'; const PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map; -const ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher; -const ReactCurrentCache = ReactSharedInternals.ReactCurrentCache; -const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; -const ReactCurrentBatchConfig: BatchConfig = - ReactSharedInternals.ReactCurrentBatchConfig; -const ReactCurrentActQueue = ReactSharedInternals.ReactCurrentActQueue; - type ExecutionContext = number; export const NoContext = /* */ 0b000; @@ -628,7 +621,6 @@ export function requestUpdateLane(fiber: Fiber): Lane { if (!transition._updatedFibers) { transition._updatedFibers = new Set(); } - transition._updatedFibers.add(fiber); } @@ -769,7 +761,7 @@ export function scheduleUpdateOnFiber( warnIfUpdatesNotWrappedWithActDEV(fiber); if (enableTransitionTracing) { - const transition = ReactCurrentBatchConfig.transition; + const transition = ReactSharedInternals.T; if (transition !== null && transition.name != null) { if (transition.startTime === -1) { transition.startTime = now(); @@ -812,7 +804,7 @@ export function scheduleUpdateOnFiber( !disableLegacyMode && (fiber.mode & ConcurrentMode) === NoMode ) { - if (__DEV__ && ReactCurrentActQueue.isBatchingLegacy) { + if (__DEV__ && ReactSharedInternals.isBatchingLegacy) { // Treat `act` as if it's inside `batchedUpdates`, even in legacy mode. } else { // Flush the synchronous work now, unless we're already working or inside @@ -1431,16 +1423,15 @@ export function getExecutionContext(): ExecutionContext { } export function deferredUpdates(fn: () => A): A { - const prevTransition = ReactCurrentBatchConfig.transition; - + const prevTransition = ReactSharedInternals.T; const previousPriority = getCurrentUpdatePriority(); try { setCurrentUpdatePriority(DefaultEventPriority); - ReactCurrentBatchConfig.transition = null; + ReactSharedInternals.T = null; return fn(); } finally { setCurrentUpdatePriority(previousPriority); - ReactCurrentBatchConfig.transition = prevTransition; + ReactSharedInternals.T = prevTransition; } } @@ -1461,7 +1452,7 @@ export function batchedUpdates(fn: A => R, a: A): R { if ( executionContext === NoContext && // Treat `act` as if it's inside `batchedUpdates`, even in legacy mode. - !(__DEV__ && ReactCurrentActQueue.isBatchingLegacy) + !(__DEV__ && ReactSharedInternals.isBatchingLegacy) ) { resetRenderTimer(); flushSyncWorkOnLegacyRootsOnly(); @@ -1477,15 +1468,15 @@ export function discreteUpdates( c: C, d: D, ): R { - const prevTransition = ReactCurrentBatchConfig.transition; + const prevTransition = ReactSharedInternals.T; const previousPriority = getCurrentUpdatePriority(); try { setCurrentUpdatePriority(DiscreteEventPriority); - ReactCurrentBatchConfig.transition = null; + ReactSharedInternals.T = null; return fn(a, b, c, d); } finally { setCurrentUpdatePriority(previousPriority); - ReactCurrentBatchConfig.transition = prevTransition; + ReactSharedInternals.T = prevTransition; if (executionContext === NoContext) { resetRenderTimer(); } @@ -1514,12 +1505,12 @@ export function flushSyncFromReconciler(fn: (() => R) | void): R | void { const prevExecutionContext = executionContext; executionContext |= BatchedContext; - const prevTransition = ReactCurrentBatchConfig.transition; + const prevTransition = ReactSharedInternals.T; const previousPriority = getCurrentUpdatePriority(); try { setCurrentUpdatePriority(DiscreteEventPriority); - ReactCurrentBatchConfig.transition = null; + ReactSharedInternals.T = null; if (fn) { return fn(); } else { @@ -1527,7 +1518,7 @@ export function flushSyncFromReconciler(fn: (() => R) | void): R | void { } } finally { setCurrentUpdatePriority(previousPriority); - ReactCurrentBatchConfig.transition = prevTransition; + ReactSharedInternals.T = prevTransition; executionContext = prevExecutionContext; // Flush the immediate callbacks that were scheduled during this batch. @@ -1679,7 +1670,9 @@ function handleThrow(root: FiberRoot, thrownValue: any): void { // when React is executing user code. resetHooksAfterThrow(); resetCurrentDebugFiberInDEV(); - ReactCurrentOwner.current = null; + if (__DEV__ || !disableStringRefs) { + ReactSharedInternals.owner = null; + } if (thrownValue === SuspenseException) { // This is a special type of exception used for Suspense. For historical @@ -1852,8 +1845,8 @@ export function shouldRemainOnPreviousScreen(): boolean { } function pushDispatcher(container: any) { - const prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = ContextOnlyDispatcher; + const prevDispatcher = ReactSharedInternals.H; + ReactSharedInternals.H = ContextOnlyDispatcher; if (prevDispatcher === null) { // The React isomorphic package does not include a default dispatcher. // Instead the first renderer will lazily attach one, in order to give @@ -1865,13 +1858,13 @@ function pushDispatcher(container: any) { } function popDispatcher(prevDispatcher: any) { - ReactCurrentDispatcher.current = prevDispatcher; + ReactSharedInternals.H = prevDispatcher; } function pushCacheDispatcher() { if (enableCache) { - const prevCacheDispatcher = ReactCurrentCache.current; - ReactCurrentCache.current = DefaultCacheDispatcher; + const prevCacheDispatcher = ReactSharedInternals.C; + ReactSharedInternals.C = DefaultCacheDispatcher; return prevCacheDispatcher; } else { return null; @@ -1880,7 +1873,7 @@ function pushCacheDispatcher() { function popCacheDispatcher(prevCacheDispatcher: any) { if (enableCache) { - ReactCurrentCache.current = prevCacheDispatcher; + ReactSharedInternals.C = prevCacheDispatcher; } } @@ -2293,7 +2286,7 @@ function renderRootConcurrent(root: FiberRoot, lanes: Lanes) { } } - if (__DEV__ && ReactCurrentActQueue.current !== null) { + if (__DEV__ && ReactSharedInternals.actQueue !== null) { // `act` special case: If we're inside an `act` scope, don't consult // `shouldYield`. Always keep working until the render is complete. // This is not just an optimization: in a unit test environment, we @@ -2379,7 +2372,9 @@ function performUnitOfWork(unitOfWork: Fiber): void { workInProgress = next; } - ReactCurrentOwner.current = null; + if (__DEV__ || !disableStringRefs) { + ReactSharedInternals.owner = null; + } } function replaySuspendedUnitOfWork(unitOfWork: Fiber): void { @@ -2492,7 +2487,9 @@ function replaySuspendedUnitOfWork(unitOfWork: Fiber): void { workInProgress = next; } - ReactCurrentOwner.current = null; + if (__DEV__ || !disableStringRefs) { + ReactSharedInternals.owner = null; + } } function throwAndUnwindWorkLoop( @@ -2710,12 +2707,11 @@ function commitRoot( ) { // TODO: This no longer makes any sense. We already wrap the mutation and // layout phases. Should be able to remove. - const prevTransition = ReactCurrentBatchConfig.transition; - + const prevTransition = ReactSharedInternals.T; const previousUpdateLanePriority = getCurrentUpdatePriority(); try { setCurrentUpdatePriority(DiscreteEventPriority); - ReactCurrentBatchConfig.transition = null; + ReactSharedInternals.T = null; commitRootImpl( root, recoverableErrors, @@ -2725,7 +2721,7 @@ function commitRoot( spawnedLane, ); } finally { - ReactCurrentBatchConfig.transition = prevTransition; + ReactSharedInternals.T = prevTransition; setCurrentUpdatePriority(previousUpdateLanePriority); } @@ -2875,8 +2871,8 @@ function commitRootImpl( NoFlags; if (subtreeHasEffects || rootHasEffect) { - const prevTransition = ReactCurrentBatchConfig.transition; - ReactCurrentBatchConfig.transition = null; + const prevTransition = ReactSharedInternals.T; + ReactSharedInternals.T = null; const previousPriority = getCurrentUpdatePriority(); setCurrentUpdatePriority(DiscreteEventPriority); @@ -2884,7 +2880,9 @@ function commitRootImpl( executionContext |= CommitContext; // Reset this to null before calling lifecycles - ReactCurrentOwner.current = null; + if (__DEV__ || !disableStringRefs) { + ReactSharedInternals.owner = null; + } // The commit phase is broken into several sub-phases. We do a separate pass // of the effect list for each phase: all mutation effects come before all @@ -2950,7 +2948,7 @@ function commitRootImpl( // Reset the priority to the previous non-sync value. setCurrentUpdatePriority(previousPriority); - ReactCurrentBatchConfig.transition = prevTransition; + ReactSharedInternals.T = prevTransition; } else { // No effects. root.current = finishedWork; @@ -3180,16 +3178,16 @@ export function flushPassiveEffects(): boolean { const renderPriority = lanesToEventPriority(pendingPassiveEffectsLanes); const priority = lowerEventPriority(DefaultEventPriority, renderPriority); - const prevTransition = ReactCurrentBatchConfig.transition; + const prevTransition = ReactSharedInternals.T; const previousPriority = getCurrentUpdatePriority(); try { setCurrentUpdatePriority(priority); - ReactCurrentBatchConfig.transition = null; + ReactSharedInternals.T = null; return flushPassiveEffectsImpl(); } finally { setCurrentUpdatePriority(previousPriority); - ReactCurrentBatchConfig.transition = prevTransition; + ReactSharedInternals.T = prevTransition; // Once passive effects have run for the tree - giving components a // chance to retain cache instances they use - release the pooled @@ -3921,7 +3919,7 @@ function scheduleCallback(priorityLevel: any, callback) { if (__DEV__) { // If we're currently inside an `act` scope, bypass Scheduler and push to // the `act` queue instead. - const actQueue = ReactCurrentActQueue.current; + const actQueue = ReactSharedInternals.actQueue; if (actQueue !== null) { actQueue.push(callback); return fakeActCallbackNode; @@ -3936,7 +3934,7 @@ function scheduleCallback(priorityLevel: any, callback) { function shouldForceFlushFallbacksInDEV() { // Never force flush in production. This function should get stripped out. - return __DEV__ && ReactCurrentActQueue.current !== null; + return __DEV__ && ReactSharedInternals.actQueue !== null; } function warnIfUpdatesNotWrappedWithActDEV(fiber: Fiber): void { @@ -3968,7 +3966,7 @@ function warnIfUpdatesNotWrappedWithActDEV(fiber: Fiber): void { } } - if (ReactCurrentActQueue.current === null) { + if (ReactSharedInternals.actQueue === null) { const previousFiber = ReactCurrentFiberCurrent; try { setCurrentDebugFiberInDEV(fiber); @@ -4001,7 +3999,7 @@ function warnIfSuspenseResolutionNotWrappedWithActDEV(root: FiberRoot): void { if ( (disableLegacyMode || root.tag !== LegacyRoot) && isConcurrentActEnvironment() && - ReactCurrentActQueue.current === null + ReactSharedInternals.actQueue === null ) { console.error( 'A suspended resource finished loading inside a test, but the event ' + diff --git a/packages/react-reconciler/src/__tests__/ReactHooks-test.internal.js b/packages/react-reconciler/src/__tests__/ReactHooks-test.internal.js index b63a8b23476e4..2b72ddbf726a4 100644 --- a/packages/react-reconciler/src/__tests__/ReactHooks-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactHooks-test.internal.js @@ -948,14 +948,13 @@ describe('ReactHooks', () => { it('warns when reading context inside useMemo', async () => { const {useMemo, createContext} = React; - const ReactCurrentDispatcher = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED - .ReactCurrentDispatcher; + const ReactSharedInternals = + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; const ThemeContext = createContext('light'); function App() { return useMemo(() => { - return ReactCurrentDispatcher.current.readContext(ThemeContext); + return ReactSharedInternals.H.readContext(ThemeContext); }, []); } @@ -968,18 +967,17 @@ describe('ReactHooks', () => { it('warns when reading context inside useMemo after reading outside it', async () => { const {useMemo, createContext} = React; - const ReactCurrentDispatcher = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED - .ReactCurrentDispatcher; + const ReactSharedInternals = + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; const ThemeContext = createContext('light'); let firstRead, secondRead; function App() { - firstRead = ReactCurrentDispatcher.current.readContext(ThemeContext); + firstRead = ReactSharedInternals.H.readContext(ThemeContext); useMemo(() => {}); - secondRead = ReactCurrentDispatcher.current.readContext(ThemeContext); + secondRead = ReactSharedInternals.H.readContext(ThemeContext); return useMemo(() => { - return ReactCurrentDispatcher.current.readContext(ThemeContext); + return ReactSharedInternals.H.readContext(ThemeContext); }, []); } @@ -995,14 +993,13 @@ describe('ReactHooks', () => { // Throws because there's no runtime cost for being strict here. it('throws when reading context inside useEffect', async () => { const {useEffect, createContext} = React; - const ReactCurrentDispatcher = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED - .ReactCurrentDispatcher; + const ReactSharedInternals = + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; const ThemeContext = createContext('light'); function App() { useEffect(() => { - ReactCurrentDispatcher.current.readContext(ThemeContext); + ReactSharedInternals.H.readContext(ThemeContext); }); return null; } @@ -1017,14 +1014,13 @@ describe('ReactHooks', () => { // Throws because there's no runtime cost for being strict here. it('throws when reading context inside useLayoutEffect', async () => { const {useLayoutEffect, createContext} = React; - const ReactCurrentDispatcher = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED - .ReactCurrentDispatcher; + const ReactSharedInternals = + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; const ThemeContext = createContext('light'); function App() { useLayoutEffect(() => { - ReactCurrentDispatcher.current.readContext(ThemeContext); + ReactSharedInternals.H.readContext(ThemeContext); }); return null; } @@ -1041,14 +1037,13 @@ describe('ReactHooks', () => { it('warns when reading context inside useReducer', async () => { const {useReducer, createContext} = React; - const ReactCurrentDispatcher = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED - .ReactCurrentDispatcher; + const ReactSharedInternals = + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; const ThemeContext = createContext('light'); function App() { const [state, dispatch] = useReducer((s, action) => { - ReactCurrentDispatcher.current.readContext(ThemeContext); + ReactSharedInternals.H.readContext(ThemeContext); return action; }, 0); if (state === 0) { @@ -1069,9 +1064,8 @@ describe('ReactHooks', () => { const {useState, createContext} = React; const ThemeContext = createContext('light'); - const ReactCurrentDispatcher = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED - .ReactCurrentDispatcher; + const ReactSharedInternals = + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; let _setState; function Fn() { @@ -1082,9 +1076,7 @@ describe('ReactHooks', () => { class Cls extends React.Component { render() { - _setState(() => - ReactCurrentDispatcher.current.readContext(ThemeContext), - ); + _setState(() => ReactSharedInternals.H.readContext(ThemeContext)); return null; } @@ -1162,15 +1154,14 @@ describe('ReactHooks', () => { }); it('resets warning internal state when interrupted by an error', async () => { - const ReactCurrentDispatcher = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED - .ReactCurrentDispatcher; + const ReactSharedInternals = + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; const ThemeContext = React.createContext('light'); function App() { React.useMemo(() => { // Trigger warnings - ReactCurrentDispatcher.current.readContext(ThemeContext); + ReactSharedInternals.H.readContext(ThemeContext); React.useRef(); // Interrupt exit from a Hook throw new Error('No.'); @@ -1251,14 +1242,13 @@ describe('ReactHooks', () => { it('warns when reading context inside useMemo', async () => { const {useMemo, createContext} = React; - const ReactCurrentDispatcher = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED - .ReactCurrentDispatcher; + const ReactSharedInternals = + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; const ThemeContext = createContext('light'); function App() { return useMemo(() => { - return ReactCurrentDispatcher.current.readContext(ThemeContext); + return ReactSharedInternals.H.readContext(ThemeContext); }, []); } diff --git a/packages/react-reconciler/src/__tests__/ReactMemo-test.js b/packages/react-reconciler/src/__tests__/ReactMemo-test.js index e8d8ef384aa44..74ef98125b7c9 100644 --- a/packages/react-reconciler/src/__tests__/ReactMemo-test.js +++ b/packages/react-reconciler/src/__tests__/ReactMemo-test.js @@ -138,8 +138,7 @@ describe('memo', () => { function readContext(Context) { const dispatcher = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED - .ReactCurrentDispatcher.current; + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.H; return dispatcher.readContext(Context); } diff --git a/packages/react-reconciler/src/__tests__/ReactNewContext-test.js b/packages/react-reconciler/src/__tests__/ReactNewContext-test.js index 492e7b232432c..6f8462607cc06 100644 --- a/packages/react-reconciler/src/__tests__/ReactNewContext-test.js +++ b/packages/react-reconciler/src/__tests__/ReactNewContext-test.js @@ -49,8 +49,7 @@ describe('ReactNewContext', () => { function readContext(Context) { const dispatcher = - React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED - .ReactCurrentDispatcher.current; + React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.H; return dispatcher.readContext(Context); } diff --git a/packages/react-server-dom-turbopack/src/ReactFlightTurbopackNodeRegister.js b/packages/react-server-dom-turbopack/src/ReactFlightTurbopackNodeRegister.js index 68c692530d6c5..d8056ffa9a03d 100644 --- a/packages/react-server-dom-turbopack/src/ReactFlightTurbopackNodeRegister.js +++ b/packages/react-server-dom-turbopack/src/ReactFlightTurbopackNodeRegister.js @@ -44,7 +44,7 @@ module.exports = function register() { }).body; } catch (x) { // eslint-disable-next-line react-internal/no-production-logging - console.error('Error parsing %s %s', url, x.message); + console['error']('Error parsing %s %s', url, x.message); return originalCompile.apply(this, arguments); } diff --git a/packages/react-server-dom-webpack/src/ReactFlightWebpackNodeRegister.js b/packages/react-server-dom-webpack/src/ReactFlightWebpackNodeRegister.js index 39598e0e85ec0..36753e3c99ac9 100644 --- a/packages/react-server-dom-webpack/src/ReactFlightWebpackNodeRegister.js +++ b/packages/react-server-dom-webpack/src/ReactFlightWebpackNodeRegister.js @@ -44,7 +44,7 @@ module.exports = function register() { }).body; } catch (x) { // eslint-disable-next-line react-internal/no-production-logging - console.error('Error parsing %s %s', url, x.message); + console['error']('Error parsing %s %s', url, x.message); return originalCompile.apply(this, arguments); } diff --git a/packages/react-server/src/ReactFizzServer.js b/packages/react-server/src/ReactFizzServer.js index a322d57df695f..223d63a4c1084 100644 --- a/packages/react-server/src/ReactFizzServer.js +++ b/packages/react-server/src/ReactFizzServer.js @@ -152,10 +152,6 @@ import isArray from 'shared/isArray'; import {SuspenseException, getSuspendedThenable} from './ReactFizzThenable'; import type {Postpone} from 'react/src/ReactPostpone'; -const ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher; -const ReactCurrentCache = ReactSharedInternals.ReactCurrentCache; -const ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; - // Linked list representing the identity of a component given the component/tag name and key. // The name might be minified but we assume that it's going to be the same generated name. Typically // because it's just the same compiled output in practice. @@ -3665,21 +3661,21 @@ export function performWork(request: Request): void { return; } const prevContext = getActiveContext(); - const prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = HooksDispatcher; - let prevCacheDispatcher; + const prevDispatcher = ReactSharedInternals.H; + ReactSharedInternals.H = HooksDispatcher; + let prevCacheDispatcher = null; if (enableCache) { - prevCacheDispatcher = ReactCurrentCache.current; - ReactCurrentCache.current = DefaultCacheDispatcher; + prevCacheDispatcher = ReactSharedInternals.C; + ReactSharedInternals.C = DefaultCacheDispatcher; } const prevRequest = currentRequest; currentRequest = request; - let prevGetCurrentStackImpl; + let prevGetCurrentStackImpl = null; if (__DEV__) { - prevGetCurrentStackImpl = ReactDebugCurrentFrame.getCurrentStack; - ReactDebugCurrentFrame.getCurrentStack = getCurrentStackInDEV; + prevGetCurrentStackImpl = ReactSharedInternals.getCurrentStack; + ReactSharedInternals.getCurrentStack = getCurrentStackInDEV; } const prevResumableState = currentResumableState; setCurrentResumableState(request.resumableState); @@ -3700,13 +3696,13 @@ export function performWork(request: Request): void { fatalError(request, error); } finally { setCurrentResumableState(prevResumableState); - ReactCurrentDispatcher.current = prevDispatcher; + ReactSharedInternals.H = prevDispatcher; if (enableCache) { - ReactCurrentCache.current = prevCacheDispatcher; + ReactSharedInternals.C = prevCacheDispatcher; } if (__DEV__) { - ReactDebugCurrentFrame.getCurrentStack = prevGetCurrentStackImpl; + ReactSharedInternals.getCurrentStack = prevGetCurrentStackImpl; } if (prevDispatcher === HooksDispatcher) { // This means that we were in a reentrant work loop. This could happen diff --git a/packages/react-server/src/ReactFlightServer.js b/packages/react-server/src/ReactFlightServer.js index 5c14276f330b9..900793d24c0b5 100644 --- a/packages/react-server/src/ReactFlightServer.js +++ b/packages/react-server/src/ReactFlightServer.js @@ -108,8 +108,9 @@ import { objectName, } from 'shared/ReactSerializationErrors'; -import ReactSharedInternals from 'shared/ReactSharedInternals'; -import ReactServerSharedInternals from './ReactServerSharedInternals'; +import type {SharedStateServer} from 'react/src/ReactSharedInternalsServer'; +import ReactSharedInternalsImpl from 'shared/ReactSharedInternals'; +const ReactSharedInternals: SharedStateServer = (ReactSharedInternalsImpl: any); import isArray from 'shared/isArray'; import getPrototypeOf from 'shared/getPrototypeOf'; import binaryToComparableString from 'shared/binaryToComparableString'; @@ -154,7 +155,7 @@ function patchConsole(consoleInst: typeof console, methodName: string) { // We don't currently use this id for anything but we emit it so that we can later // refer to previous logs in debug info to associate them with a component. const id = request.nextChunkId++; - const owner: null | ReactComponentInfo = ReactCurrentOwner.current; + const owner: null | ReactComponentInfo = ReactSharedInternals.owner; emitConsoleChunk(request, id, methodName, owner, stack, arguments); } // $FlowFixMe[prop-missing] @@ -305,10 +306,7 @@ const { TaintRegistryValues, TaintRegistryByteLengths, TaintRegistryPendingRequests, - ReactCurrentCache, -} = ReactServerSharedInternals; -const ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher; -const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; +} = ReactSharedInternals; function throwTaintViolation(message: string) { // eslint-disable-next-line react-internal/prod-error-codes @@ -354,14 +352,14 @@ export function createRequest( environmentName: void | string, ): Request { if ( - ReactCurrentCache.current !== null && - ReactCurrentCache.current !== DefaultCacheDispatcher + ReactSharedInternals.C !== null && + ReactSharedInternals.C !== DefaultCacheDispatcher ) { throw new Error( 'Currently React only supports one RSC renderer at a time.', ); } - ReactCurrentCache.current = DefaultCacheDispatcher; + ReactSharedInternals.C = DefaultCacheDispatcher; const abortSet: Set = new Set(); const pingedTasks: Array = []; @@ -644,11 +642,11 @@ function renderFunctionComponent( const secondArg = undefined; let result; if (__DEV__) { - ReactCurrentOwner.current = componentDebugInfo; + ReactSharedInternals.owner = componentDebugInfo; try { result = Component(props, secondArg); } finally { - ReactCurrentOwner.current = null; + ReactSharedInternals.owner = null; } } else { result = Component(props, secondArg); @@ -2492,8 +2490,8 @@ function retryTask(request: Request, task: Task): void { } function performWork(request: Request): void { - const prevDispatcher = ReactCurrentDispatcher.current; - ReactCurrentDispatcher.current = HooksDispatcher; + const prevDispatcher = ReactSharedInternals.H; + ReactSharedInternals.H = HooksDispatcher; const prevRequest = currentRequest; currentRequest = request; prepareToUseHooksForRequest(request); @@ -2512,7 +2510,7 @@ function performWork(request: Request): void { logRecoverableError(request, error); fatalError(request, error); } finally { - ReactCurrentDispatcher.current = prevDispatcher; + ReactSharedInternals.H = prevDispatcher; resetHooksForRequest(); currentRequest = prevRequest; } diff --git a/packages/react-server/src/ReactServerSharedInternals.js b/packages/react-server/src/ReactServerSharedInternals.js deleted file mode 100644 index 6d1a5a7c6858a..0000000000000 --- a/packages/react-server/src/ReactServerSharedInternals.js +++ /dev/null @@ -1,24 +0,0 @@ -/** - * 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 * as React from 'react'; - -const ReactSharedServerInternals = - // $FlowFixMe: It's defined in the one we resolve to. - React.__SECRET_SERVER_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; - -if (!ReactSharedServerInternals) { - throw new Error( - 'The "react" package in this environment is not configured correctly. ' + - 'The "react-server" condition must be enabled in any environment that ' + - 'runs React Server Components.', - ); -} - -export default ReactSharedServerInternals; diff --git a/packages/react-suspense-test-utils/src/ReactSuspenseTestUtils.js b/packages/react-suspense-test-utils/src/ReactSuspenseTestUtils.js index 1f0c650dec3ca..b3bc53006d771 100644 --- a/packages/react-suspense-test-utils/src/ReactSuspenseTestUtils.js +++ b/packages/react-suspense-test-utils/src/ReactSuspenseTestUtils.js @@ -10,8 +10,6 @@ import type {CacheDispatcher} from 'react-reconciler/src/ReactInternalTypes'; import ReactSharedInternals from 'shared/ReactSharedInternals'; -const ReactCurrentCache = ReactSharedInternals.ReactCurrentCache; - export function waitForSuspense(fn: () => T): Promise { const cache: Map = new Map(); const testDispatcher: CacheDispatcher = { @@ -28,8 +26,8 @@ export function waitForSuspense(fn: () => T): Promise { // Not using async/await because we don't compile it. return new Promise((resolve, reject) => { function retry() { - const prevDispatcher = ReactCurrentCache.current; - ReactCurrentCache.current = testDispatcher; + const prevDispatcher = ReactSharedInternals.C; + ReactSharedInternals.C = testDispatcher; try { const result = fn(); resolve(result); @@ -40,7 +38,7 @@ export function waitForSuspense(fn: () => T): Promise { reject(thrownValue); } } finally { - ReactCurrentCache.current = prevDispatcher; + ReactSharedInternals.C = prevDispatcher; } } retry(); diff --git a/packages/react/src/ReactAct.js b/packages/react/src/ReactAct.js index 6a98a21ac29dd..c4c8a98d53150 100644 --- a/packages/react/src/ReactAct.js +++ b/packages/react/src/ReactAct.js @@ -8,8 +8,8 @@ */ import type {Thenable} from 'shared/ReactTypes'; -import type {RendererTask} from './ReactCurrentActQueue'; -import ReactCurrentActQueue from './ReactCurrentActQueue'; +import type {RendererTask} from './ReactSharedInternalsClient'; +import ReactSharedInternals from './ReactSharedInternalsClient'; import queueMacrotask from 'shared/enqueueTask'; import {disableLegacyMode} from 'shared/ReactFeatureFlags'; @@ -31,7 +31,7 @@ function aggregateErrors(errors: Array): mixed { export function act(callback: () => T | Thenable): Thenable { if (__DEV__) { - // When ReactCurrentActQueue.current is not null, it signals to React that + // When ReactSharedInternals.actQueue is not null, it signals to React that // we're currently inside an `act` scope. React will push all its tasks to // this queue instead of scheduling them with platform APIs. // @@ -41,19 +41,19 @@ export function act(callback: () => T | Thenable): Thenable { // // If we're already inside an `act` scope, reuse the existing queue. const prevIsBatchingLegacy = !disableLegacyMode - ? ReactCurrentActQueue.isBatchingLegacy + ? ReactSharedInternals.isBatchingLegacy : false; - const prevActQueue = ReactCurrentActQueue.current; + const prevActQueue = ReactSharedInternals.actQueue; const prevActScopeDepth = actScopeDepth; actScopeDepth++; - const queue = (ReactCurrentActQueue.current = + const queue = (ReactSharedInternals.actQueue = prevActQueue !== null ? prevActQueue : []); // Used to reproduce behavior of `batchedUpdates` in legacy mode. Only // set to `true` while the given callback is executed, not for updates // triggered during an async event, because this is how the legacy // implementation of `act` behaved. if (!disableLegacyMode) { - ReactCurrentActQueue.isBatchingLegacy = true; + ReactSharedInternals.isBatchingLegacy = true; } let result; @@ -65,11 +65,11 @@ export function act(callback: () => T | Thenable): Thenable { // only place we ever read this fields is just below, right after running // the callback. So we don't need to reset after the callback runs. if (!disableLegacyMode) { - ReactCurrentActQueue.didScheduleLegacyUpdate = false; + ReactSharedInternals.didScheduleLegacyUpdate = false; } result = callback(); const didScheduleLegacyUpdate = !disableLegacyMode - ? ReactCurrentActQueue.didScheduleLegacyUpdate + ? ReactSharedInternals.didScheduleLegacyUpdate : false; // Replicate behavior of original `act` implementation in legacy mode, @@ -83,22 +83,22 @@ export function act(callback: () => T | Thenable): Thenable { // that's how it worked before version 18. Yes, it's confusing! We should // delete legacy mode!! if (!disableLegacyMode) { - ReactCurrentActQueue.isBatchingLegacy = prevIsBatchingLegacy; + ReactSharedInternals.isBatchingLegacy = prevIsBatchingLegacy; } } catch (error) { // `isBatchingLegacy` gets reset using the regular stack, not the async // one used to track `act` scopes. Why, you may be wondering? Because // that's how it worked before version 18. Yes, it's confusing! We should // delete legacy mode!! - ReactCurrentActQueue.thrownErrors.push(error); + ReactSharedInternals.thrownErrors.push(error); } - if (ReactCurrentActQueue.thrownErrors.length > 0) { + if (ReactSharedInternals.thrownErrors.length > 0) { if (!disableLegacyMode) { - ReactCurrentActQueue.isBatchingLegacy = prevIsBatchingLegacy; + ReactSharedInternals.isBatchingLegacy = prevIsBatchingLegacy; } popActScope(prevActQueue, prevActScopeDepth); - const thrownError = aggregateErrors(ReactCurrentActQueue.thrownErrors); - ReactCurrentActQueue.thrownErrors.length = 0; + const thrownError = aggregateErrors(ReactSharedInternals.thrownErrors); + ReactSharedInternals.thrownErrors.length = 0; throw thrownError; } @@ -149,13 +149,13 @@ export function act(callback: () => T | Thenable): Thenable { // `thenable` might not be a real promise, and `flushActQueue` // might throw, so we need to wrap `flushActQueue` in a // try/catch. - ReactCurrentActQueue.thrownErrors.push(error); + ReactSharedInternals.thrownErrors.push(error); } - if (ReactCurrentActQueue.thrownErrors.length > 0) { + if (ReactSharedInternals.thrownErrors.length > 0) { const thrownError = aggregateErrors( - ReactCurrentActQueue.thrownErrors, + ReactSharedInternals.thrownErrors, ); - ReactCurrentActQueue.thrownErrors.length = 0; + ReactSharedInternals.thrownErrors.length = 0; reject(thrownError); } } else { @@ -164,11 +164,11 @@ export function act(callback: () => T | Thenable): Thenable { }, error => { popActScope(prevActQueue, prevActScopeDepth); - if (ReactCurrentActQueue.thrownErrors.length > 0) { + if (ReactSharedInternals.thrownErrors.length > 0) { const thrownError = aggregateErrors( - ReactCurrentActQueue.thrownErrors, + ReactSharedInternals.thrownErrors, ); - ReactCurrentActQueue.thrownErrors.length = 0; + ReactSharedInternals.thrownErrors.length = 0; reject(thrownError); } else { reject(error); @@ -222,12 +222,12 @@ export function act(callback: () => T | Thenable): Thenable { // // TODO: In a future version, consider always requiring all `act` calls // to be awaited, regardless of whether the callback is sync or async. - ReactCurrentActQueue.current = null; + ReactSharedInternals.actQueue = null; } - if (ReactCurrentActQueue.thrownErrors.length > 0) { - const thrownError = aggregateErrors(ReactCurrentActQueue.thrownErrors); - ReactCurrentActQueue.thrownErrors.length = 0; + if (ReactSharedInternals.thrownErrors.length > 0) { + const thrownError = aggregateErrors(ReactSharedInternals.thrownErrors); + ReactSharedInternals.thrownErrors.length = 0; throw thrownError; } @@ -237,7 +237,7 @@ export function act(callback: () => T | Thenable): Thenable { if (prevActScopeDepth === 0) { // If the `act` call is awaited, restore the queue we were // using before (see long comment above) so we can flush it. - ReactCurrentActQueue.current = queue; + ReactSharedInternals.actQueue = queue; queueMacrotask(() => // Recursively flush tasks scheduled by a microtask. recursivelyFlushAsyncActWork(returnValue, resolve, reject), @@ -275,7 +275,7 @@ function recursivelyFlushAsyncActWork( ) { if (__DEV__) { // Check if any tasks were scheduled asynchronously. - const queue = ReactCurrentActQueue.current; + const queue = ReactSharedInternals.actQueue; if (queue !== null) { if (queue.length !== 0) { // Async tasks were scheduled, mostly likely in a microtask. @@ -290,16 +290,16 @@ function recursivelyFlushAsyncActWork( return; } catch (error) { // Leave remaining tasks on the queue if something throws. - ReactCurrentActQueue.thrownErrors.push(error); + ReactSharedInternals.thrownErrors.push(error); } } else { // The queue is empty. We can finish. - ReactCurrentActQueue.current = null; + ReactSharedInternals.actQueue = null; } } - if (ReactCurrentActQueue.thrownErrors.length > 0) { - const thrownError = aggregateErrors(ReactCurrentActQueue.thrownErrors); - ReactCurrentActQueue.thrownErrors.length = 0; + if (ReactSharedInternals.thrownErrors.length > 0) { + const thrownError = aggregateErrors(ReactSharedInternals.thrownErrors); + ReactSharedInternals.thrownErrors.length = 0; reject(thrownError); } else { resolve(returnValue); @@ -318,10 +318,10 @@ function flushActQueue(queue: Array) { for (; i < queue.length; i++) { let callback: RendererTask = queue[i]; do { - ReactCurrentActQueue.didUsePromise = false; + ReactSharedInternals.didUsePromise = false; const continuation = callback(false); if (continuation !== null) { - if (ReactCurrentActQueue.didUsePromise) { + if (ReactSharedInternals.didUsePromise) { // The component just suspended. Yield to the main thread in // case the promise is already resolved. If so, it will ping in // a microtask and we can resume without unwinding the stack. @@ -340,7 +340,7 @@ function flushActQueue(queue: Array) { } catch (error) { // If something throws, leave the remaining callbacks on the queue. queue.splice(0, i + 1); - ReactCurrentActQueue.thrownErrors.push(error); + ReactSharedInternals.thrownErrors.push(error); } finally { isFlushing = false; } diff --git a/packages/react/src/ReactCacheImpl.js b/packages/react/src/ReactCacheImpl.js index c998aa4c87b26..99a3809bc9372 100644 --- a/packages/react/src/ReactCacheImpl.js +++ b/packages/react/src/ReactCacheImpl.js @@ -7,7 +7,7 @@ * @flow */ -import ReactCurrentCache from './ReactCurrentCache'; +import ReactSharedInternals from 'shared/ReactSharedInternals'; const UNTERMINATED = 0; const TERMINATED = 1; @@ -54,7 +54,7 @@ function createCacheNode(): CacheNode { export function cache, T>(fn: (...A) => T): (...A) => T { return function () { - const dispatcher = ReactCurrentCache.current; + const dispatcher = ReactSharedInternals.C; if (!dispatcher) { // If there is no dispatcher, then we treat this as not being cached. // $FlowFixMe[incompatible-call]: We don't want to use rest arguments since we transpile the code. diff --git a/packages/react/src/ReactCurrentActQueue.js b/packages/react/src/ReactCurrentActQueue.js deleted file mode 100644 index ee1dff7180250..0000000000000 --- a/packages/react/src/ReactCurrentActQueue.js +++ /dev/null @@ -1,28 +0,0 @@ -/** - * 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 - */ - -export type RendererTask = boolean => RendererTask | null; - -const ReactCurrentActQueue = { - current: (null: null | Array), - - // Used to reproduce behavior of `batchedUpdates` in legacy mode. - isBatchingLegacy: false, - didScheduleLegacyUpdate: false, - - // Tracks whether something called `use` during the current batch of work. - // Determines whether we should yield to microtasks to unwrap already resolved - // promises without suspending. - didUsePromise: false, - - // Track first uncaught error within this act - thrownErrors: ([]: Array), -}; - -export default ReactCurrentActQueue; diff --git a/packages/react/src/ReactCurrentBatchConfig.js b/packages/react/src/ReactCurrentBatchConfig.js deleted file mode 100644 index debd21e4fa200..0000000000000 --- a/packages/react/src/ReactCurrentBatchConfig.js +++ /dev/null @@ -1,23 +0,0 @@ -/** - * 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 {BatchConfigTransition} from 'react-reconciler/src/ReactFiberTracingMarkerComponent'; - -export type BatchConfig = { - transition: BatchConfigTransition | null, -}; -/** - * Keeps track of the current batch's configuration such as how long an update - * should suspend for if it needs to. - */ -const ReactCurrentBatchConfig: BatchConfig = { - transition: null, -}; - -export default ReactCurrentBatchConfig; diff --git a/packages/react/src/ReactCurrentCache.js b/packages/react/src/ReactCurrentCache.js deleted file mode 100644 index f933b1bf61a41..0000000000000 --- a/packages/react/src/ReactCurrentCache.js +++ /dev/null @@ -1,19 +0,0 @@ -/** - * 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 {CacheDispatcher} from 'react-reconciler/src/ReactInternalTypes'; - -/** - * Keeps track of the current Cache dispatcher. - */ -const ReactCurrentCache = { - current: (null: null | CacheDispatcher), -}; - -export default ReactCurrentCache; diff --git a/packages/react/src/ReactCurrentDispatcher.js b/packages/react/src/ReactCurrentDispatcher.js deleted file mode 100644 index 400de4281bcfa..0000000000000 --- a/packages/react/src/ReactCurrentDispatcher.js +++ /dev/null @@ -1,19 +0,0 @@ -/** - * 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 {Dispatcher} from 'react-reconciler/src/ReactInternalTypes'; - -/** - * Keeps track of the current dispatcher. - */ -const ReactCurrentDispatcher = { - current: (null: null | Dispatcher), -}; - -export default ReactCurrentDispatcher; diff --git a/packages/react/src/ReactCurrentOwner.js b/packages/react/src/ReactCurrentOwner.js deleted file mode 100644 index 1fcc25d5e0d9a..0000000000000 --- a/packages/react/src/ReactCurrentOwner.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * 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 {Fiber} from 'react-reconciler/src/ReactInternalTypes'; - -/** - * Keeps track of the current owner. - * - * The current owner is the component who should own any components that are - * currently being constructed. - */ -const ReactCurrentOwner = { - /** - * @internal - * @type {ReactComponent} - */ - current: (null: null | Fiber), -}; - -export default ReactCurrentOwner; diff --git a/packages/react/src/ReactDebugCurrentFrame.js b/packages/react/src/ReactDebugCurrentFrame.js deleted file mode 100644 index c9b35594a34dc..0000000000000 --- a/packages/react/src/ReactDebugCurrentFrame.js +++ /dev/null @@ -1,51 +0,0 @@ -/** - * 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 - */ - -const ReactDebugCurrentFrame: { - setExtraStackFrame?: (stack: null | string) => void, - getCurrentStack?: null | (() => string), - getStackAddendum?: () => string, -} = {}; - -let currentExtraStackFrame = (null: null | string); - -export function setExtraStackFrame(stack: null | string): void { - if (__DEV__) { - currentExtraStackFrame = stack; - } -} - -if (__DEV__) { - ReactDebugCurrentFrame.setExtraStackFrame = function (stack: null | string) { - if (__DEV__) { - currentExtraStackFrame = stack; - } - }; - // Stack implementation injected by the current renderer. - ReactDebugCurrentFrame.getCurrentStack = (null: null | (() => string)); - - ReactDebugCurrentFrame.getStackAddendum = function (): string { - let stack = ''; - - // Add an extra top frame while an element is being validated - if (currentExtraStackFrame) { - stack += currentExtraStackFrame; - } - - // Delegate to the injected renderer-specific implementation - const impl = ReactDebugCurrentFrame.getCurrentStack; - if (impl) { - stack += impl() || ''; - } - - return stack; - }; -} - -export default ReactDebugCurrentFrame; diff --git a/packages/react/src/ReactFetch.js b/packages/react/src/ReactFetch.js index 31678d9327d55..e5cb1f6dd49e3 100644 --- a/packages/react/src/ReactFetch.js +++ b/packages/react/src/ReactFetch.js @@ -12,7 +12,7 @@ import { enableFetchInstrumentation, } from 'shared/ReactFeatureFlags'; -import ReactCurrentCache from './ReactCurrentCache'; +import ReactSharedInternals from 'shared/ReactSharedInternals'; function createFetchCache(): Map> { return new Map(); @@ -46,7 +46,7 @@ if (enableCache && enableFetchInstrumentation) { resource: URL | RequestInfo, options?: RequestOptions, ) { - const dispatcher = ReactCurrentCache.current; + const dispatcher = ReactSharedInternals.C; if (!dispatcher) { // We're outside a cached scope. return originalFetch(resource, options); diff --git a/packages/react/src/ReactHooks.js b/packages/react/src/ReactHooks.js index 4c102569631fd..79513656cea13 100644 --- a/packages/react/src/ReactHooks.js +++ b/packages/react/src/ReactHooks.js @@ -16,15 +16,15 @@ import type { } from 'shared/ReactTypes'; import {REACT_CONSUMER_TYPE} from 'shared/ReactSymbols'; -import ReactCurrentDispatcher from './ReactCurrentDispatcher'; -import ReactCurrentCache from './ReactCurrentCache'; +import ReactSharedInternals from 'shared/ReactSharedInternals'; + import {enableAsyncActions} from 'shared/ReactFeatureFlags'; type BasicStateAction = (S => S) | S; type Dispatch = A => void; function resolveDispatcher() { - const dispatcher = ReactCurrentDispatcher.current; + const dispatcher = ReactSharedInternals.H; if (__DEV__) { if (dispatcher === null) { console.error( @@ -44,7 +44,7 @@ function resolveDispatcher() { } export function getCacheForType(resourceType: () => T): T { - const dispatcher = ReactCurrentCache.current; + const dispatcher = ReactSharedInternals.C; if (!dispatcher) { // If there is no dispatcher, then we treat this as not being cached. return resourceType(); diff --git a/packages/react/src/ReactServer.experimental.js b/packages/react/src/ReactServer.experimental.js index 7db8332da9ad8..76b11004b2cc9 100644 --- a/packages/react/src/ReactServer.experimental.js +++ b/packages/react/src/ReactServer.experimental.js @@ -12,8 +12,6 @@ import './ReactFetch'; export {default as __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED} from './ReactSharedInternalsServer'; -export {default as __SECRET_SERVER_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED} from './ReactServerSharedInternals'; - import {forEach, map, count, toArray, only} from './ReactChildren'; import { REACT_FRAGMENT_TYPE, diff --git a/packages/react/src/ReactServer.js b/packages/react/src/ReactServer.js index 0c5eacbba23d0..a63651d54c33a 100644 --- a/packages/react/src/ReactServer.js +++ b/packages/react/src/ReactServer.js @@ -12,8 +12,6 @@ import './ReactFetch'; export {default as __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED} from './ReactSharedInternalsServer'; -export {default as __SECRET_SERVER_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED} from './ReactServerSharedInternals'; - import {forEach, map, count, toArray, only} from './ReactChildren'; import { REACT_FRAGMENT_TYPE, diff --git a/packages/react/src/ReactServerSharedInternals.js b/packages/react/src/ReactServerSharedInternals.js deleted file mode 100644 index 28ccb732ca7b3..0000000000000 --- a/packages/react/src/ReactServerSharedInternals.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - * 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. - */ - -import ReactCurrentCache from './ReactCurrentCache'; -import { - TaintRegistryObjects, - TaintRegistryValues, - TaintRegistryByteLengths, - TaintRegistryPendingRequests, -} from './ReactTaintRegistry'; - -import {enableTaint} from 'shared/ReactFeatureFlags'; - -const ReactServerSharedInternals = { - ReactCurrentCache, -}; - -if (enableTaint) { - ReactServerSharedInternals.TaintRegistryObjects = TaintRegistryObjects; - ReactServerSharedInternals.TaintRegistryValues = TaintRegistryValues; - ReactServerSharedInternals.TaintRegistryByteLengths = - TaintRegistryByteLengths; - ReactServerSharedInternals.TaintRegistryPendingRequests = - TaintRegistryPendingRequests; -} - -export default ReactServerSharedInternals; diff --git a/packages/react/src/ReactSharedInternalsClient.js b/packages/react/src/ReactSharedInternalsClient.js index 3311a8188b014..ea57f2fcdcc7f 100644 --- a/packages/react/src/ReactSharedInternalsClient.js +++ b/packages/react/src/ReactSharedInternalsClient.js @@ -3,25 +3,88 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. + * + * @flow */ -import ReactCurrentDispatcher from './ReactCurrentDispatcher'; -import ReactCurrentCache from './ReactCurrentCache'; -import ReactCurrentBatchConfig from './ReactCurrentBatchConfig'; -import ReactCurrentActQueue from './ReactCurrentActQueue'; -import ReactCurrentOwner from './ReactCurrentOwner'; -import ReactDebugCurrentFrame from './ReactDebugCurrentFrame'; - -const ReactSharedInternals = { - ReactCurrentDispatcher, - ReactCurrentCache, - ReactCurrentBatchConfig, - ReactCurrentOwner, +import type {Dispatcher} from 'react-reconciler/src/ReactInternalTypes'; +import type {CacheDispatcher} from 'react-reconciler/src/ReactInternalTypes'; +import type {BatchConfigTransition} from 'react-reconciler/src/ReactFiberTracingMarkerComponent'; +import type {Fiber} from 'react-reconciler/src/ReactInternalTypes'; + +import {disableStringRefs} from 'shared/ReactFeatureFlags'; + +export type SharedStateClient = { + H: null | Dispatcher, // ReactCurrentDispatcher for Hooks + C: null | CacheDispatcher, // ReactCurrentCache for Cache + T: null | BatchConfigTransition, // ReactCurrentBatchConfig for Transitions + + // DEV-only-ish + owner: null | Fiber, // ReactCurrentOwner is Fiber on the Client, null in Fizz. Flight uses SharedStateServer. + + // ReactCurrentActQueue + actQueue: null | Array, + + // Used to reproduce behavior of `batchedUpdates` in legacy mode. + isBatchingLegacy: boolean, + didScheduleLegacyUpdate: boolean, + + // Tracks whether something called `use` during the current batch of work. + // Determines whether we should yield to microtasks to unwrap already resolved + // promises without suspending. + didUsePromise: boolean, + + // Track first uncaught error within this act + thrownErrors: Array, + + // ReactDebugCurrentFrame + setExtraStackFrame: (stack: null | string) => void, + getCurrentStack: null | (() => string), + getStackAddendum: () => string, }; +export type RendererTask = boolean => RendererTask | null; + +const ReactSharedInternals: SharedStateClient = ({ + H: null, + C: null, + T: null, +}: any); + +if (__DEV__ || !disableStringRefs) { + ReactSharedInternals.owner = null; +} + if (__DEV__) { - ReactSharedInternals.ReactDebugCurrentFrame = ReactDebugCurrentFrame; - ReactSharedInternals.ReactCurrentActQueue = ReactCurrentActQueue; + ReactSharedInternals.actQueue = null; + ReactSharedInternals.isBatchingLegacy = false; + ReactSharedInternals.didScheduleLegacyUpdate = false; + ReactSharedInternals.didUsePromise = false; + ReactSharedInternals.thrownErrors = []; + + let currentExtraStackFrame = (null: null | string); + ReactSharedInternals.setExtraStackFrame = function (stack: null | string) { + currentExtraStackFrame = stack; + }; + // Stack implementation injected by the current renderer. + ReactSharedInternals.getCurrentStack = (null: null | (() => string)); + + ReactSharedInternals.getStackAddendum = function (): string { + let stack = ''; + + // Add an extra top frame while an element is being validated + if (currentExtraStackFrame) { + stack += currentExtraStackFrame; + } + + // Delegate to the injected renderer-specific implementation + const impl = ReactSharedInternals.getCurrentStack; + if (impl) { + stack += impl() || ''; + } + + return stack; + }; } export default ReactSharedInternals; diff --git a/packages/react/src/ReactSharedInternalsServer.js b/packages/react/src/ReactSharedInternalsServer.js index 64a85be5e266e..be5dd91d2146b 100644 --- a/packages/react/src/ReactSharedInternalsServer.js +++ b/packages/react/src/ReactSharedInternalsServer.js @@ -3,19 +3,91 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. + * + * @flow */ -import ReactCurrentDispatcher from './ReactCurrentDispatcher'; -import ReactCurrentOwner from './ReactCurrentOwner'; -import ReactDebugCurrentFrame from './ReactDebugCurrentFrame'; +import type {Dispatcher} from 'react-reconciler/src/ReactInternalTypes'; +import type {CacheDispatcher} from 'react-reconciler/src/ReactInternalTypes'; +import type {ReactComponentInfo} from 'shared/ReactTypes'; + +import type { + Reference, + TaintEntry, + RequestCleanupQueue, +} from './ReactTaintRegistry'; + +import { + TaintRegistryObjects, + TaintRegistryValues, + TaintRegistryByteLengths, + TaintRegistryPendingRequests, +} from './ReactTaintRegistry'; + +import {disableStringRefs, enableTaint} from 'shared/ReactFeatureFlags'; + +export type SharedStateServer = { + H: null | Dispatcher, // ReactCurrentDispatcher for Hooks + C: null | CacheDispatcher, // ReactCurrentCache for Cache -const ReactSharedInternals = { - ReactCurrentDispatcher, - ReactCurrentOwner, + // enableTaint + TaintRegistryObjects: WeakMap, + TaintRegistryValues: Map, + TaintRegistryByteLengths: Set, + TaintRegistryPendingRequests: Set, + + // DEV-only-ish + owner: null | ReactComponentInfo, // ReactCurrentOwner is ReactComponentInfo in Flight, null in Fizz. Fiber/Fizz uses SharedStateClient. + + // ReactDebugCurrentFrame + setExtraStackFrame: (stack: null | string) => void, + getCurrentStack: null | (() => string), + getStackAddendum: () => string, }; +export type RendererTask = boolean => RendererTask | null; + +const ReactSharedInternals: SharedStateServer = ({ + H: null, + C: null, +}: any); + +if (enableTaint) { + ReactSharedInternals.TaintRegistryObjects = TaintRegistryObjects; + ReactSharedInternals.TaintRegistryValues = TaintRegistryValues; + ReactSharedInternals.TaintRegistryByteLengths = TaintRegistryByteLengths; + ReactSharedInternals.TaintRegistryPendingRequests = + TaintRegistryPendingRequests; +} + +if (__DEV__ || !disableStringRefs) { + ReactSharedInternals.owner = null; +} + if (__DEV__) { - ReactSharedInternals.ReactDebugCurrentFrame = ReactDebugCurrentFrame; + let currentExtraStackFrame = (null: null | string); + ReactSharedInternals.setExtraStackFrame = function (stack: null | string) { + currentExtraStackFrame = stack; + }; + // Stack implementation injected by the current renderer. + ReactSharedInternals.getCurrentStack = (null: null | (() => string)); + + ReactSharedInternals.getStackAddendum = function (): string { + let stack = ''; + + // Add an extra top frame while an element is being validated + if (currentExtraStackFrame) { + stack += currentExtraStackFrame; + } + + // Delegate to the injected renderer-specific implementation + const impl = ReactSharedInternals.getCurrentStack; + if (impl) { + stack += impl() || ''; + } + + return stack; + }; } export default ReactSharedInternals; diff --git a/packages/react/src/ReactStartTransition.js b/packages/react/src/ReactStartTransition.js index 968cc6d812cf9..5311e1d29ad77 100644 --- a/packages/react/src/ReactStartTransition.js +++ b/packages/react/src/ReactStartTransition.js @@ -9,7 +9,8 @@ import type {BatchConfigTransition} from 'react-reconciler/src/ReactFiberTracingMarkerComponent'; import type {StartTransitionOptions} from 'shared/ReactTypes'; -import ReactCurrentBatchConfig from './ReactCurrentBatchConfig'; +import ReactSharedInternals from 'shared/ReactSharedInternals'; + import { enableAsyncActions, enableTransitionTracing, @@ -21,26 +22,26 @@ export function startTransition( scope: () => void, options?: StartTransitionOptions, ) { - const prevTransition = ReactCurrentBatchConfig.transition; + const prevTransition = ReactSharedInternals.T; // Each renderer registers a callback to receive the return value of // the scope function. This is used to implement async actions. const callbacks = new Set<(BatchConfigTransition, mixed) => mixed>(); const transition: BatchConfigTransition = { _callbacks: callbacks, }; - ReactCurrentBatchConfig.transition = transition; - const currentTransition = ReactCurrentBatchConfig.transition; + ReactSharedInternals.T = transition; + const currentTransition = ReactSharedInternals.T; if (__DEV__) { - ReactCurrentBatchConfig.transition._updatedFibers = new Set(); + ReactSharedInternals.T._updatedFibers = new Set(); } if (enableTransitionTracing) { if (options !== undefined && options.name !== undefined) { // $FlowFixMe[incompatible-use] found when upgrading Flow - ReactCurrentBatchConfig.transition.name = options.name; + ReactSharedInternals.T.name = options.name; // $FlowFixMe[incompatible-use] found when upgrading Flow - ReactCurrentBatchConfig.transition.startTime = -1; + ReactSharedInternals.T.startTime = -1; } } @@ -59,7 +60,7 @@ export function startTransition( reportGlobalError(error); } finally { warnAboutTransitionSubscriptions(prevTransition, currentTransition); - ReactCurrentBatchConfig.transition = prevTransition; + ReactSharedInternals.T = prevTransition; } } else { // When async actions are not enabled, startTransition does not @@ -68,7 +69,7 @@ export function startTransition( scope(); } finally { warnAboutTransitionSubscriptions(prevTransition, currentTransition); - ReactCurrentBatchConfig.transition = prevTransition; + ReactSharedInternals.T = prevTransition; } } } diff --git a/packages/react/src/ReactTaint.js b/packages/react/src/ReactTaint.js index 399acb8f01431..1664578317238 100644 --- a/packages/react/src/ReactTaint.js +++ b/packages/react/src/ReactTaint.js @@ -13,13 +13,13 @@ import getPrototypeOf from 'shared/getPrototypeOf'; import binaryToComparableString from 'shared/binaryToComparableString'; -import ReactServerSharedInternals from './ReactServerSharedInternals'; +import ReactSharedInternals from './ReactSharedInternalsServer'; const { TaintRegistryObjects, TaintRegistryValues, TaintRegistryByteLengths, TaintRegistryPendingRequests, -} = ReactServerSharedInternals; +} = ReactSharedInternals; interface Reference {} diff --git a/packages/react/src/ReactTaintRegistry.js b/packages/react/src/ReactTaintRegistry.js index d600e640b523c..1ea8172be1fd3 100644 --- a/packages/react/src/ReactTaintRegistry.js +++ b/packages/react/src/ReactTaintRegistry.js @@ -7,9 +7,9 @@ * @flow */ -interface Reference {} +export interface Reference {} -type TaintEntry = { +export type TaintEntry = { message: string, count: number, }; @@ -23,5 +23,5 @@ export const TaintRegistryByteLengths: Set = new Set(); // When a value is finalized, it means that it has been removed from any global caches. // No future requests can get a handle on it but any ongoing requests can still have // a handle on it. It's still tainted until that happens. -type RequestCleanupQueue = Array; +export type RequestCleanupQueue = Array; export const TaintRegistryPendingRequests: Set = new Set(); diff --git a/packages/react/src/forks/ReactSharedInternalsClient.umd.js b/packages/react/src/forks/ReactSharedInternalsClient.umd.js index fe8f6d677f905..cca7797a61f04 100644 --- a/packages/react/src/forks/ReactSharedInternalsClient.umd.js +++ b/packages/react/src/forks/ReactSharedInternalsClient.umd.js @@ -3,21 +3,56 @@ * * 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 {Dispatcher} from 'react-reconciler/src/ReactInternalTypes'; +import type {CacheDispatcher} from 'react-reconciler/src/ReactInternalTypes'; +import type {BatchConfigTransition} from 'react-reconciler/src/ReactFiberTracingMarkerComponent'; +import type {Fiber} from 'react-reconciler/src/ReactInternalTypes'; + import * as Scheduler from 'scheduler'; -import ReactCurrentDispatcher from '../ReactCurrentDispatcher'; -import ReactCurrentCache from '../ReactCurrentCache'; -import ReactCurrentActQueue from '../ReactCurrentActQueue'; -import ReactCurrentOwner from '../ReactCurrentOwner'; -import ReactDebugCurrentFrame from '../ReactDebugCurrentFrame'; -import ReactCurrentBatchConfig from '../ReactCurrentBatchConfig'; - -const ReactSharedInternalsClient = { - ReactCurrentDispatcher, - ReactCurrentCache, - ReactCurrentOwner, - ReactCurrentBatchConfig, + +import {disableStringRefs} from 'shared/ReactFeatureFlags'; + +export type SharedStateClient = { + H: null | Dispatcher, // ReactCurrentDispatcher for Hooks + C: null | CacheDispatcher, // ReactCurrentCache for Cache + T: null | BatchConfigTransition, // ReactCurrentBatchConfig for Transitions + + // DEV-only-ish + owner?: null | Fiber, // ReactCurrentOwner is Fiber on the Client, null in Fizz. Flight uses SharedStateServer. + + // ReactCurrentActQueue + actQueue?: null | Array, + + // Used to reproduce behavior of `batchedUpdates` in legacy mode. + isBatchingLegacy?: boolean, + didScheduleLegacyUpdate?: boolean, + + // Tracks whether something called `use` during the current batch of work. + // Determines whether we should yield to microtasks to unwrap already resolved + // promises without suspending. + didUsePromise?: boolean, + + // Track first uncaught error within this act + thrownErrors?: Array, + + // ReactDebugCurrentFrame + setExtraStackFrame?: (stack: null | string) => void, + getCurrentStack?: null | (() => string), + getStackAddendum?: () => string, + + Scheduler: any, +}; + +export type RendererTask = boolean => RendererTask | null; + +const ReactSharedInternals: SharedStateClient = { + H: null, + C: null, + T: null, // Re-export the schedule API(s) for UMD bundles. // This avoids introducing a dependency on a new UMD global in a minor update, @@ -27,9 +62,40 @@ const ReactSharedInternalsClient = { Scheduler, }; +if (__DEV__ || !disableStringRefs) { + ReactSharedInternals.owner = null; +} + if (__DEV__) { - ReactSharedInternalsClient.ReactCurrentActQueue = ReactCurrentActQueue; - ReactSharedInternalsClient.ReactDebugCurrentFrame = ReactDebugCurrentFrame; + ReactSharedInternals.actQueue = null; + ReactSharedInternals.isBatchingLegacy = false; + ReactSharedInternals.didScheduleLegacyUpdate = false; + ReactSharedInternals.didUsePromise = false; + ReactSharedInternals.thrownErrors = []; + + let currentExtraStackFrame = (null: null | string); + ReactSharedInternals.setExtraStackFrame = function (stack: null | string) { + currentExtraStackFrame = stack; + }; + // Stack implementation injected by the current renderer. + ReactSharedInternals.getCurrentStack = (null: null | (() => string)); + + ReactSharedInternals.getStackAddendum = function (): string { + let stack = ''; + + // Add an extra top frame while an element is being validated + if (currentExtraStackFrame) { + stack += currentExtraStackFrame; + } + + // Delegate to the injected renderer-specific implementation + const impl = ReactSharedInternals.getCurrentStack; + if (impl) { + stack += impl() || ''; + } + + return stack; + }; } -export default ReactSharedInternalsClient; +export default ReactSharedInternals; diff --git a/packages/react/src/jsx/ReactJSXElement.js b/packages/react/src/jsx/ReactJSXElement.js index ae9b3b531d80d..d7b70e0f39784 100644 --- a/packages/react/src/jsx/ReactJSXElement.js +++ b/packages/react/src/jsx/ReactJSXElement.js @@ -27,9 +27,6 @@ import {checkPropStringCoercion} from 'shared/CheckStringCoercion'; import {ClassComponent} from 'react-reconciler/src/ReactWorkTags'; import getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber'; -const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; -const ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; - const REACT_CLIENT_REFERENCE = Symbol.for('react.client.reference'); let specialPropKeyWarningShown; @@ -71,12 +68,12 @@ function warnIfStringRefCannotBeAutoConverted(config, self) { if ( !disableStringRefs && typeof config.ref === 'string' && - ReactCurrentOwner.current && + ReactSharedInternals.owner && self && - ReactCurrentOwner.current.stateNode !== self + ReactSharedInternals.owner.stateNode !== self ) { const componentName = getComponentNameFromType( - ReactCurrentOwner.current.type, + ReactSharedInternals.owner.type, ); if (!didWarnAboutStringRefs[componentName]) { @@ -87,7 +84,7 @@ function warnIfStringRefCannotBeAutoConverted(config, self) { 'We ask you to manually fix this case by using useRef() or createRef() instead. ' + 'Learn more about using refs safely here: ' + 'https://react.dev/link/strict-mode-string-ref', - getComponentNameFromType(ReactCurrentOwner.current.type), + getComponentNameFromType(ReactSharedInternals.owner.type), config.ref, ); didWarnAboutStringRefs[componentName] = true; @@ -341,7 +338,7 @@ export function jsxProd(type, config, maybeKey) { if (!enableRefAsProp) { ref = config.ref; if (!disableStringRefs) { - ref = coerceStringRef(ref, ReactCurrentOwner.current, type); + ref = coerceStringRef(ref, ReactSharedInternals.owner, type); } } } @@ -369,7 +366,7 @@ export function jsxProd(type, config, maybeKey) { if (enableRefAsProp && !disableStringRefs && propName === 'ref') { props.ref = coerceStringRef( config[propName], - ReactCurrentOwner.current, + ReactSharedInternals.owner, type, ); } else { @@ -397,7 +394,7 @@ export function jsxProd(type, config, maybeKey) { ref, undefined, undefined, - ReactCurrentOwner.current, + ReactSharedInternals.owner, props, ); } @@ -573,7 +570,7 @@ export function jsxDEV(type, config, maybeKey, isStaticChildren, source, self) { if (!enableRefAsProp) { ref = config.ref; if (!disableStringRefs) { - ref = coerceStringRef(ref, ReactCurrentOwner.current, type); + ref = coerceStringRef(ref, ReactSharedInternals.owner, type); } } if (!disableStringRefs) { @@ -604,7 +601,7 @@ export function jsxDEV(type, config, maybeKey, isStaticChildren, source, self) { if (enableRefAsProp && !disableStringRefs && propName === 'ref') { props.ref = coerceStringRef( config[propName], - ReactCurrentOwner.current, + ReactSharedInternals.owner, type, ); } else { @@ -645,7 +642,7 @@ export function jsxDEV(type, config, maybeKey, isStaticChildren, source, self) { ref, self, source, - ReactCurrentOwner.current, + ReactSharedInternals.owner, props, ); @@ -729,7 +726,7 @@ export function createElement(type, config, children) { if (!enableRefAsProp) { ref = config.ref; if (!disableStringRefs) { - ref = coerceStringRef(ref, ReactCurrentOwner.current, type); + ref = coerceStringRef(ref, ReactSharedInternals.owner, type); } } @@ -761,7 +758,7 @@ export function createElement(type, config, children) { if (enableRefAsProp && !disableStringRefs && propName === 'ref') { props.ref = coerceStringRef( config[propName], - ReactCurrentOwner.current, + ReactSharedInternals.owner, type, ); } else { @@ -819,7 +816,7 @@ export function createElement(type, config, children) { ref, undefined, undefined, - ReactCurrentOwner.current, + ReactSharedInternals.owner, props, ); @@ -963,8 +960,8 @@ export function cloneElement(element, config, children) { function getDeclarationErrorAddendum() { if (__DEV__) { - if (ReactCurrentOwner.current) { - const name = getComponentNameFromType(ReactCurrentOwner.current.type); + if (ReactSharedInternals.owner) { + const name = getComponentNameFromType(ReactSharedInternals.owner.type); if (name) { return '\n\nCheck the render method of `' + name + '`.'; } @@ -1068,7 +1065,7 @@ function validateExplicitKey(element, parentType) { if ( element && element._owner != null && - element._owner !== ReactCurrentOwner.current + element._owner !== ReactSharedInternals.owner ) { let ownerName = null; if (typeof element._owner.tag === 'number') { @@ -1099,9 +1096,9 @@ function setCurrentlyValidatingElement(element) { element.type, owner ? owner.type : null, ); - ReactDebugCurrentFrame.setExtraStackFrame(stack); + ReactSharedInternals.setExtraStackFrame(stack); } else { - ReactDebugCurrentFrame.setExtraStackFrame(null); + ReactSharedInternals.setExtraStackFrame(null); } } } diff --git a/packages/shared/ReactComponentStackFrame.js b/packages/shared/ReactComponentStackFrame.js index b103b760e9954..ac77727d386a4 100644 --- a/packages/shared/ReactComponentStackFrame.js +++ b/packages/shared/ReactComponentStackFrame.js @@ -23,8 +23,6 @@ import {disableLogs, reenableLogs} from 'shared/ConsolePatchingDev'; import ReactSharedInternals from 'shared/ReactSharedInternals'; -const {ReactCurrentDispatcher} = ReactSharedInternals; - let prefix; export function describeBuiltInComponentFrame(name: string): string { if (enableComponentStackLocations) { @@ -86,13 +84,13 @@ export function describeNativeComponentFrame( const previousPrepareStackTrace = Error.prepareStackTrace; // $FlowFixMe[incompatible-type] It does accept undefined. Error.prepareStackTrace = undefined; - let previousDispatcher; + let previousDispatcher = null; if (__DEV__) { - previousDispatcher = ReactCurrentDispatcher.current; + previousDispatcher = ReactSharedInternals.H; // Set the dispatcher in DEV because this might be call in the render function // for warnings. - ReactCurrentDispatcher.current = null; + ReactSharedInternals.H = null; disableLogs(); } @@ -272,7 +270,7 @@ export function describeNativeComponentFrame( } finally { reentry = false; if (__DEV__) { - ReactCurrentDispatcher.current = previousDispatcher; + ReactSharedInternals.H = previousDispatcher; reenableLogs(); } Error.prepareStackTrace = previousPrepareStackTrace; diff --git a/packages/shared/consoleWithStackDev.js b/packages/shared/consoleWithStackDev.js index 06f881b5d7a21..d815d8796d809 100644 --- a/packages/shared/consoleWithStackDev.js +++ b/packages/shared/consoleWithStackDev.js @@ -40,8 +40,7 @@ function printWarning(level, format, args) { // When changing this logic, you might want to also // update consoleWithStackDev.www.js as well. if (__DEV__) { - const ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; - const stack = ReactDebugCurrentFrame.getStackAddendum(); + const stack = ReactSharedInternals.getStackAddendum(); if (stack !== '') { format += '%s'; args = args.concat([stack]); diff --git a/packages/shared/forks/Scheduler.umd.js b/packages/shared/forks/Scheduler.umd.js index 0c6480fcf0c82..c202753d82520 100644 --- a/packages/shared/forks/Scheduler.umd.js +++ b/packages/shared/forks/Scheduler.umd.js @@ -36,7 +36,7 @@ const { unstable_flushAllWithoutAsserting, log, unstable_setDisableYieldValue, -} = ReactInternals.Scheduler; +} = ((ReactInternals: any).Scheduler: any); export { unstable_cancelCallback, diff --git a/packages/shared/forks/consoleWithStackDev.www.js b/packages/shared/forks/consoleWithStackDev.www.js index d7022d0529df3..7c0a40fe2a118 100644 --- a/packages/shared/forks/consoleWithStackDev.www.js +++ b/packages/shared/forks/consoleWithStackDev.www.js @@ -38,9 +38,7 @@ function printWarning(level, format, args) { React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; // Defensive in case this is fired before React is initialized. if (ReactSharedInternals != null) { - const ReactDebugCurrentFrame = - ReactSharedInternals.ReactDebugCurrentFrame; - const stack = ReactDebugCurrentFrame.getStackAddendum(); + const stack = ReactSharedInternals.getStackAddendum(); if (stack !== '') { format += '%s'; args.push(stack); diff --git a/scripts/jest/setupHostConfigs.js b/scripts/jest/setupHostConfigs.js index 1c4acabde5bbd..8f2d508856e6f 100644 --- a/scripts/jest/setupHostConfigs.js +++ b/scripts/jest/setupHostConfigs.js @@ -46,6 +46,11 @@ function mockReact() { ); return jest.requireActual(resolvedEntryPoint); }); + // Make it possible to import this module inside + // the React package itself. + jest.mock('shared/ReactSharedInternals', () => { + return jest.requireActual('react/src/ReactSharedInternalsClient'); + }); } // When we want to unmock React we really need to mock it again. @@ -54,6 +59,10 @@ global.__unmockReact = mockReact; mockReact(); jest.mock('react/react.react-server', () => { + // If we're requiring an RSC environment, use those internals instead. + jest.mock('shared/ReactSharedInternals', () => { + return jest.requireActual('react/src/ReactSharedInternalsServer'); + }); const resolvedEntryPoint = resolveEntryFork( require.resolve('react/src/ReactServer'), global.__WWW__ @@ -161,11 +170,13 @@ inlinedHostConfigs.forEach(rendererInfo => { }); }); -// Make it possible to import this module inside -// the React package itself. -jest.mock('shared/ReactSharedInternals', () => - jest.requireActual('react/src/ReactSharedInternalsClient') -); +jest.mock('react-server/src/ReactFlightServer', () => { + // If we're requiring an RSC environment, use those internals instead. + jest.mock('shared/ReactSharedInternals', () => { + return jest.requireActual('react/src/ReactSharedInternalsServer'); + }); + return jest.requireActual('react-server/src/ReactFlightServer'); +}); // Make it possible to import this module inside // the ReactDOM package itself.