From d50323eb845c5fde0d720cae888bf35dedd05506 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Markb=C3=A5ge?= Date: Mon, 8 Apr 2024 19:23:23 -0400 Subject: [PATCH] Flatten ReactSharedInternals (#28783) This is similar to #28771 but for isomorphic. We need a make over for these dispatchers anyway so this is the first step. Also helps flush out some internals usage that will break anyway. It flattens the inner mutable objects onto the ReactSharedInternals. --- packages/react-cache/src/ReactCacheOld.js | 7 +- .../react-debug-tools/src/ReactDebugHooks.js | 18 +- .../__tests__/ReactHooksInspection-test.js | 33 --- .../ReactHooksInspectionIntegration-test.js | 55 ----- .../backend/DevToolsComponentStackFrame.js | 6 +- .../src/backend/console.js | 16 +- .../src/backend/renderer.js | 36 +++- .../src/backend/types.js | 9 +- .../src/devtools/cache.js | 6 +- .../src/events/ReactDOMEventListener.js | 14 +- .../src/shared/ReactDOMFormActions.js | 4 +- .../__tests__/ReactCompositeComponent-test.js | 15 +- .../ReactDOMServerIntegrationHooks-test.js | 3 +- ...eactDOMServerIntegrationNewContext-test.js | 3 +- .../__tests__/ReactServerRendering-test.js | 9 +- .../react-dom/src/client/ReactDOMRootFB.js | 4 +- .../react-dom/src/shared/ReactDOMFlushSync.js | 10 +- .../src/ReactNativePublicCompat.js | 6 +- .../src/createReactNoop.js | 7 +- .../react-reconciler/src/ReactCurrentFiber.js | 6 +- .../react-reconciler/src/ReactFiberAct.js | 7 +- .../src/ReactFiberBeginWork.js | 13 +- .../src/ReactFiberErrorLogger.js | 5 +- .../react-reconciler/src/ReactFiberHooks.js | 193 ++++++++---------- .../src/ReactFiberReconciler.js | 3 +- .../src/ReactFiberRootScheduler.js | 17 +- .../src/ReactFiberThenable.js | 5 +- .../src/ReactFiberTracingMarkerComponent.js | 1 + .../src/ReactFiberTransition.js | 6 +- .../src/ReactFiberTreeReflection.js | 4 +- .../src/ReactFiberWorkLoop.js | 92 ++++----- .../src/__tests__/ReactHooks-test.internal.js | 62 +++--- .../src/__tests__/ReactMemo-test.js | 3 +- .../src/__tests__/ReactNewContext-test.js | 3 +- .../src/ReactFlightTurbopackNodeRegister.js | 2 +- .../src/ReactFlightWebpackNodeRegister.js | 2 +- packages/react-server/src/ReactFizzServer.js | 26 +-- .../react-server/src/ReactFlightServer.js | 28 ++- .../src/ReactServerSharedInternals.js | 24 --- .../src/ReactSuspenseTestUtils.js | 8 +- packages/react/src/ReactAct.js | 72 +++---- packages/react/src/ReactCacheImpl.js | 4 +- packages/react/src/ReactCurrentActQueue.js | 28 --- packages/react/src/ReactCurrentBatchConfig.js | 23 --- packages/react/src/ReactCurrentCache.js | 19 -- packages/react/src/ReactCurrentDispatcher.js | 19 -- packages/react/src/ReactCurrentOwner.js | 26 --- packages/react/src/ReactDebugCurrentFrame.js | 51 ----- packages/react/src/ReactFetch.js | 4 +- packages/react/src/ReactHooks.js | 8 +- .../react/src/ReactServer.experimental.js | 2 - packages/react/src/ReactServer.js | 2 - .../react/src/ReactServerSharedInternals.js | 31 --- .../react/src/ReactSharedInternalsClient.js | 91 +++++++-- .../react/src/ReactSharedInternalsServer.js | 86 +++++++- packages/react/src/ReactStartTransition.js | 19 +- packages/react/src/ReactTaint.js | 4 +- packages/react/src/ReactTaintRegistry.js | 6 +- .../forks/ReactSharedInternalsClient.umd.js | 96 +++++++-- packages/react/src/jsx/ReactJSXElement.js | 41 ++-- packages/shared/ReactComponentStackFrame.js | 10 +- packages/shared/consoleWithStackDev.js | 3 +- packages/shared/forks/Scheduler.umd.js | 2 +- .../shared/forks/consoleWithStackDev.www.js | 4 +- scripts/jest/setupHostConfigs.js | 21 +- 65 files changed, 652 insertions(+), 791 deletions(-) delete mode 100644 packages/react-server/src/ReactServerSharedInternals.js delete mode 100644 packages/react/src/ReactCurrentActQueue.js delete mode 100644 packages/react/src/ReactCurrentBatchConfig.js delete mode 100644 packages/react/src/ReactCurrentCache.js delete mode 100644 packages/react/src/ReactCurrentDispatcher.js delete mode 100644 packages/react/src/ReactCurrentOwner.js delete mode 100644 packages/react/src/ReactDebugCurrentFrame.js delete mode 100644 packages/react/src/ReactServerSharedInternals.js 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 bca50c2540567..b429db3326b5e 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, ); @@ -876,7 +873,7 @@ export function cloneElement(element, config, children) { ref = coerceStringRef(ref, owner, element.type); } } - owner = ReactCurrentOwner.current; + owner = ReactSharedInternals.owner; } if (hasValidKey(config)) { if (__DEV__) { @@ -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.