From 6d13208ce4ff52bbcd38f4728e1fc4c82226d82b Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Tue, 9 Apr 2024 13:11:45 -0400 Subject: [PATCH 01/10] Rename CacheDispatcher to AsyncDispatcher --- .../react-reconciler/src/ReactFiberCache.js | 4 ++-- .../src/ReactFiberWorkLoop.js | 22 +++++++++---------- .../src/ReactInternalTypes.js | 2 +- packages/react-server/src/ReactFizzCache.js | 4 ++-- packages/react-server/src/ReactFizzServer.js | 10 ++++----- .../react-server/src/ReactFlightServer.js | 8 +++---- .../src/flight/ReactFlightServerCache.js | 4 ++-- .../src/ReactSuspenseTestUtils.js | 10 ++++----- packages/react/src/ReactCacheImpl.js | 2 +- packages/react/src/ReactHooks.js | 2 +- .../react/src/ReactSharedInternalsClient.js | 6 ++--- .../react/src/ReactSharedInternalsServer.js | 6 ++--- 12 files changed, 40 insertions(+), 40 deletions(-) diff --git a/packages/react-reconciler/src/ReactFiberCache.js b/packages/react-reconciler/src/ReactFiberCache.js index 3f465d8b8837c..08a1406904425 100644 --- a/packages/react-reconciler/src/ReactFiberCache.js +++ b/packages/react-reconciler/src/ReactFiberCache.js @@ -7,7 +7,7 @@ * @flow */ -import type {CacheDispatcher} from './ReactInternalTypes'; +import type {AsyncDispatcher} from './ReactInternalTypes'; import type {Cache} from './ReactFiberCacheComponent'; import {enableCache} from 'shared/ReactFeatureFlags'; @@ -27,6 +27,6 @@ function getCacheForType(resourceType: () => T): T { return cacheForType; } -export const DefaultCacheDispatcher: CacheDispatcher = { +export const DefaultAsyncDispatcher: AsyncDispatcher = { getCacheForType, }; diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.js b/packages/react-reconciler/src/ReactFiberWorkLoop.js index 8b0c8729506cc..ceb4b7f47d328 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.js @@ -203,7 +203,7 @@ import { resetHooksOnUnwind, ContextOnlyDispatcher, } from './ReactFiberHooks'; -import {DefaultCacheDispatcher} from './ReactFiberCache'; +import {DefaultAsyncDispatcher} from './ReactFiberCache'; import { createCapturedValueAtFiber, type CapturedValue, @@ -1874,19 +1874,19 @@ function popDispatcher(prevDispatcher: any) { ReactSharedInternals.H = prevDispatcher; } -function pushCacheDispatcher() { +function pushAsyncDispatcher() { if (enableCache) { - const prevCacheDispatcher = ReactSharedInternals.C; - ReactSharedInternals.C = DefaultCacheDispatcher; - return prevCacheDispatcher; + const prevAsyncDispatcher = ReactSharedInternals.A; + ReactSharedInternals.A = DefaultAsyncDispatcher; + return prevAsyncDispatcher; } else { return null; } } -function popCacheDispatcher(prevCacheDispatcher: any) { +function popAsyncDispatcher(prevAsyncDispatcher: any) { if (enableCache) { - ReactSharedInternals.C = prevCacheDispatcher; + ReactSharedInternals.A = prevAsyncDispatcher; } } @@ -1963,7 +1963,7 @@ function renderRootSync(root: FiberRoot, lanes: Lanes) { const prevExecutionContext = executionContext; executionContext |= RenderContext; const prevDispatcher = pushDispatcher(root.containerInfo); - const prevCacheDispatcher = pushCacheDispatcher(); + const prevAsyncDispatcher = pushAsyncDispatcher(); // If the root or lanes have changed, throw out the existing stack // and prepare a fresh one. Otherwise we'll continue where we left off. @@ -2061,7 +2061,7 @@ function renderRootSync(root: FiberRoot, lanes: Lanes) { executionContext = prevExecutionContext; popDispatcher(prevDispatcher); - popCacheDispatcher(prevCacheDispatcher); + popAsyncDispatcher(prevAsyncDispatcher); if (workInProgress !== null) { // This is a sync render, so we should have finished the whole tree. @@ -2104,7 +2104,7 @@ function renderRootConcurrent(root: FiberRoot, lanes: Lanes) { const prevExecutionContext = executionContext; executionContext |= RenderContext; const prevDispatcher = pushDispatcher(root.containerInfo); - const prevCacheDispatcher = pushCacheDispatcher(); + const prevAsyncDispatcher = pushAsyncDispatcher(); // If the root or lanes have changed, throw out the existing stack // and prepare a fresh one. Otherwise we'll continue where we left off. @@ -2317,7 +2317,7 @@ function renderRootConcurrent(root: FiberRoot, lanes: Lanes) { resetContextDependencies(); popDispatcher(prevDispatcher); - popCacheDispatcher(prevCacheDispatcher); + popAsyncDispatcher(prevAsyncDispatcher); executionContext = prevExecutionContext; if (__DEV__) { diff --git a/packages/react-reconciler/src/ReactInternalTypes.js b/packages/react-reconciler/src/ReactInternalTypes.js index f12b9a16c570b..db5078e3f5bd9 100644 --- a/packages/react-reconciler/src/ReactInternalTypes.js +++ b/packages/react-reconciler/src/ReactInternalTypes.js @@ -434,6 +434,6 @@ export type Dispatcher = { ) => [Awaited, (P) => void, boolean], }; -export type CacheDispatcher = { +export type AsyncDispatcher = { getCacheForType: (resourceType: () => T) => T, }; diff --git a/packages/react-server/src/ReactFizzCache.js b/packages/react-server/src/ReactFizzCache.js index 10ff0ed7c0d1a..c77b650e79419 100644 --- a/packages/react-server/src/ReactFizzCache.js +++ b/packages/react-server/src/ReactFizzCache.js @@ -7,12 +7,12 @@ * @flow */ -import type {CacheDispatcher} from 'react-reconciler/src/ReactInternalTypes'; +import type {AsyncDispatcher} from 'react-reconciler/src/ReactInternalTypes'; function getCacheForType(resourceType: () => T): T { throw new Error('Not implemented.'); } -export const DefaultCacheDispatcher: CacheDispatcher = { +export const DefaultAsyncDispatcher: AsyncDispatcher = { getCacheForType, }; diff --git a/packages/react-server/src/ReactFizzServer.js b/packages/react-server/src/ReactFizzServer.js index b6925b1c7b58b..7a1361bd12631 100644 --- a/packages/react-server/src/ReactFizzServer.js +++ b/packages/react-server/src/ReactFizzServer.js @@ -111,7 +111,7 @@ import { getActionStateCount, getActionStateMatchingIndex, } from './ReactFizzHooks'; -import {DefaultCacheDispatcher} from './ReactFizzCache'; +import {DefaultAsyncDispatcher} from './ReactFizzCache'; import {getStackByComponentStackNode} from './ReactFizzComponentStack'; import {emptyTreeContext, pushTreeContext} from './ReactFizzTreeContext'; @@ -3791,10 +3791,10 @@ export function performWork(request: Request): void { const prevContext = getActiveContext(); const prevDispatcher = ReactSharedInternals.H; ReactSharedInternals.H = HooksDispatcher; - let prevCacheDispatcher = null; + let prevAsyncDispatcher = null; if (enableCache) { - prevCacheDispatcher = ReactSharedInternals.C; - ReactSharedInternals.C = DefaultCacheDispatcher; + prevAsyncDispatcher = ReactSharedInternals.A; + ReactSharedInternals.A = DefaultAsyncDispatcher; } const prevRequest = currentRequest; @@ -3826,7 +3826,7 @@ export function performWork(request: Request): void { setCurrentResumableState(prevResumableState); ReactSharedInternals.H = prevDispatcher; if (enableCache) { - ReactSharedInternals.C = prevCacheDispatcher; + ReactSharedInternals.A = prevAsyncDispatcher; } if (__DEV__) { diff --git a/packages/react-server/src/ReactFlightServer.js b/packages/react-server/src/ReactFlightServer.js index a22faf755fd65..bfeb98a52285c 100644 --- a/packages/react-server/src/ReactFlightServer.js +++ b/packages/react-server/src/ReactFlightServer.js @@ -89,7 +89,7 @@ import { getThenableStateAfterSuspending, resetHooksForRequest, } from './ReactFlightHooks'; -import {DefaultCacheDispatcher} from './flight/ReactFlightServerCache'; +import {DefaultAsyncDispatcher} from './flight/ReactFlightServerCache'; import { getIteratorFn, @@ -360,14 +360,14 @@ export function createRequest( environmentName: void | string, ): Request { if ( - ReactSharedInternals.C !== null && - ReactSharedInternals.C !== DefaultCacheDispatcher + ReactSharedInternals.A !== null && + ReactSharedInternals.A !== DefaultAsyncDispatcher ) { throw new Error( 'Currently React only supports one RSC renderer at a time.', ); } - ReactSharedInternals.C = DefaultCacheDispatcher; + ReactSharedInternals.A = DefaultAsyncDispatcher; const abortSet: Set = new Set(); const pingedTasks: Array = []; diff --git a/packages/react-server/src/flight/ReactFlightServerCache.js b/packages/react-server/src/flight/ReactFlightServerCache.js index 5c2469a2a9864..eefc5f9f3e815 100644 --- a/packages/react-server/src/flight/ReactFlightServerCache.js +++ b/packages/react-server/src/flight/ReactFlightServerCache.js @@ -7,7 +7,7 @@ * @flow */ -import type {CacheDispatcher} from 'react-reconciler/src/ReactInternalTypes'; +import type {AsyncDispatcher} from 'react-reconciler/src/ReactInternalTypes'; import {resolveRequest, getCache} from '../ReactFlightServer'; @@ -19,7 +19,7 @@ function resolveCache(): Map { return new Map(); } -export const DefaultCacheDispatcher: CacheDispatcher = { +export const DefaultAsyncDispatcher: AsyncDispatcher = { getCacheForType(resourceType: () => T): T { const cache = resolveCache(); let entry: T | void = (cache.get(resourceType): any); diff --git a/packages/react-suspense-test-utils/src/ReactSuspenseTestUtils.js b/packages/react-suspense-test-utils/src/ReactSuspenseTestUtils.js index b3bc53006d771..35b59b61d1c21 100644 --- a/packages/react-suspense-test-utils/src/ReactSuspenseTestUtils.js +++ b/packages/react-suspense-test-utils/src/ReactSuspenseTestUtils.js @@ -7,12 +7,12 @@ * @flow */ -import type {CacheDispatcher} from 'react-reconciler/src/ReactInternalTypes'; +import type {AsyncDispatcher} from 'react-reconciler/src/ReactInternalTypes'; import ReactSharedInternals from 'shared/ReactSharedInternals'; export function waitForSuspense(fn: () => T): Promise { const cache: Map = new Map(); - const testDispatcher: CacheDispatcher = { + const testDispatcher: AsyncDispatcher = { getCacheForType(resourceType: () => R): R { let entry: R | void = (cache.get(resourceType): any); if (entry === undefined) { @@ -26,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 = ReactSharedInternals.C; - ReactSharedInternals.C = testDispatcher; + const prevDispatcher = ReactSharedInternals.A; + ReactSharedInternals.A = testDispatcher; try { const result = fn(); resolve(result); @@ -38,7 +38,7 @@ export function waitForSuspense(fn: () => T): Promise { reject(thrownValue); } } finally { - ReactSharedInternals.C = prevDispatcher; + ReactSharedInternals.A = prevDispatcher; } } retry(); diff --git a/packages/react/src/ReactCacheImpl.js b/packages/react/src/ReactCacheImpl.js index 99a3809bc9372..cc3136897e350 100644 --- a/packages/react/src/ReactCacheImpl.js +++ b/packages/react/src/ReactCacheImpl.js @@ -54,7 +54,7 @@ function createCacheNode(): CacheNode { export function cache, T>(fn: (...A) => T): (...A) => T { return function () { - const dispatcher = ReactSharedInternals.C; + const dispatcher = ReactSharedInternals.A; 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/ReactHooks.js b/packages/react/src/ReactHooks.js index 79513656cea13..93d9fa28f07f9 100644 --- a/packages/react/src/ReactHooks.js +++ b/packages/react/src/ReactHooks.js @@ -44,7 +44,7 @@ function resolveDispatcher() { } export function getCacheForType(resourceType: () => T): T { - const dispatcher = ReactSharedInternals.C; + const dispatcher = ReactSharedInternals.A; if (!dispatcher) { // If there is no dispatcher, then we treat this as not being cached. return resourceType(); diff --git a/packages/react/src/ReactSharedInternalsClient.js b/packages/react/src/ReactSharedInternalsClient.js index ea57f2fcdcc7f..5a6925b0fa626 100644 --- a/packages/react/src/ReactSharedInternalsClient.js +++ b/packages/react/src/ReactSharedInternalsClient.js @@ -8,7 +8,7 @@ */ import type {Dispatcher} from 'react-reconciler/src/ReactInternalTypes'; -import type {CacheDispatcher} from 'react-reconciler/src/ReactInternalTypes'; +import type {AsyncDispatcher} from 'react-reconciler/src/ReactInternalTypes'; import type {BatchConfigTransition} from 'react-reconciler/src/ReactFiberTracingMarkerComponent'; import type {Fiber} from 'react-reconciler/src/ReactInternalTypes'; @@ -16,7 +16,7 @@ import {disableStringRefs} from 'shared/ReactFeatureFlags'; export type SharedStateClient = { H: null | Dispatcher, // ReactCurrentDispatcher for Hooks - C: null | CacheDispatcher, // ReactCurrentCache for Cache + A: null | AsyncDispatcher, // ReactCurrentCache for Cache T: null | BatchConfigTransition, // ReactCurrentBatchConfig for Transitions // DEV-only-ish @@ -47,7 +47,7 @@ export type RendererTask = boolean => RendererTask | null; const ReactSharedInternals: SharedStateClient = ({ H: null, - C: null, + A: null, T: null, }: any); diff --git a/packages/react/src/ReactSharedInternalsServer.js b/packages/react/src/ReactSharedInternalsServer.js index be5dd91d2146b..2f032bb212779 100644 --- a/packages/react/src/ReactSharedInternalsServer.js +++ b/packages/react/src/ReactSharedInternalsServer.js @@ -8,7 +8,7 @@ */ import type {Dispatcher} from 'react-reconciler/src/ReactInternalTypes'; -import type {CacheDispatcher} from 'react-reconciler/src/ReactInternalTypes'; +import type {AsyncDispatcher} from 'react-reconciler/src/ReactInternalTypes'; import type {ReactComponentInfo} from 'shared/ReactTypes'; import type { @@ -28,7 +28,7 @@ import {disableStringRefs, enableTaint} from 'shared/ReactFeatureFlags'; export type SharedStateServer = { H: null | Dispatcher, // ReactCurrentDispatcher for Hooks - C: null | CacheDispatcher, // ReactCurrentCache for Cache + A: null | AsyncDispatcher, // ReactCurrentCache for Cache // enableTaint TaintRegistryObjects: WeakMap, @@ -49,7 +49,7 @@ export type RendererTask = boolean => RendererTask | null; const ReactSharedInternals: SharedStateServer = ({ H: null, - C: null, + A: null, }: any); if (enableTaint) { From 348b7e015881534c9beb22d9c6bc1231f936265e Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Tue, 9 Apr 2024 13:25:52 -0400 Subject: [PATCH 02/10] Add getOwner on the AsyncDispatcher --- .../react-reconciler/src/ReactFiberCache.js | 15 +++++++++++--- .../src/ReactInternalTypes.js | 2 ++ packages/react-server/src/ReactFizzCache.js | 13 ++++++++++-- .../src/flight/ReactFlightServerCache.js | 20 +++++++++++++++++-- .../src/ReactSuspenseTestUtils.js | 3 +++ 5 files changed, 46 insertions(+), 7 deletions(-) diff --git a/packages/react-reconciler/src/ReactFiberCache.js b/packages/react-reconciler/src/ReactFiberCache.js index 08a1406904425..379425fc2241a 100644 --- a/packages/react-reconciler/src/ReactFiberCache.js +++ b/packages/react-reconciler/src/ReactFiberCache.js @@ -7,13 +7,15 @@ * @flow */ -import type {AsyncDispatcher} from './ReactInternalTypes'; +import type {AsyncDispatcher, Fiber} from './ReactInternalTypes'; import type {Cache} from './ReactFiberCacheComponent'; import {enableCache} from 'shared/ReactFeatureFlags'; import {readContext} from './ReactFiberNewContext'; import {CacheContext} from './ReactFiberCacheComponent'; +import {disableStringRefs} from 'shared/ReactFeatureFlags'; + function getCacheForType(resourceType: () => T): T { if (!enableCache) { throw new Error('Not implemented.'); @@ -27,6 +29,13 @@ function getCacheForType(resourceType: () => T): T { return cacheForType; } -export const DefaultAsyncDispatcher: AsyncDispatcher = { +export const DefaultAsyncDispatcher: AsyncDispatcher = ({ getCacheForType, -}; +}: any); + +if (__DEV__ || !disableStringRefs) { + DefaultAsyncDispatcher.getOwner = (): null | Fiber => { + // TODO + return null; + }; +} diff --git a/packages/react-reconciler/src/ReactInternalTypes.js b/packages/react-reconciler/src/ReactInternalTypes.js index db5078e3f5bd9..6fa9142e2d5ee 100644 --- a/packages/react-reconciler/src/ReactInternalTypes.js +++ b/packages/react-reconciler/src/ReactInternalTypes.js @@ -436,4 +436,6 @@ export type Dispatcher = { export type AsyncDispatcher = { getCacheForType: (resourceType: () => T) => T, + // DEV-only (or !disableStringRefs) + getOwner: () => null | Fiber | ReactComponentInfo, }; diff --git a/packages/react-server/src/ReactFizzCache.js b/packages/react-server/src/ReactFizzCache.js index c77b650e79419..8e8cb2e219992 100644 --- a/packages/react-server/src/ReactFizzCache.js +++ b/packages/react-server/src/ReactFizzCache.js @@ -9,10 +9,19 @@ import type {AsyncDispatcher} from 'react-reconciler/src/ReactInternalTypes'; +import {disableStringRefs} from 'shared/ReactFeatureFlags'; + function getCacheForType(resourceType: () => T): T { throw new Error('Not implemented.'); } -export const DefaultAsyncDispatcher: AsyncDispatcher = { +export const DefaultAsyncDispatcher: AsyncDispatcher = ({ getCacheForType, -}; +}: any); + +if (__DEV__ || !disableStringRefs) { + // Fizz never tracks owner but the JSX runtime looks for this. + DefaultAsyncDispatcher.getOwner = (): null => { + return null; + }; +} diff --git a/packages/react-server/src/flight/ReactFlightServerCache.js b/packages/react-server/src/flight/ReactFlightServerCache.js index eefc5f9f3e815..8ff0cd5bc9a3a 100644 --- a/packages/react-server/src/flight/ReactFlightServerCache.js +++ b/packages/react-server/src/flight/ReactFlightServerCache.js @@ -7,10 +7,14 @@ * @flow */ +import type {ReactComponentInfo} from 'shared/ReactTypes'; + import type {AsyncDispatcher} from 'react-reconciler/src/ReactInternalTypes'; import {resolveRequest, getCache} from '../ReactFlightServer'; +import {disableStringRefs} from 'shared/ReactFeatureFlags'; + function resolveCache(): Map { const request = resolveRequest(); if (request) { @@ -19,7 +23,7 @@ function resolveCache(): Map { return new Map(); } -export const DefaultAsyncDispatcher: AsyncDispatcher = { +export const DefaultAsyncDispatcher: AsyncDispatcher = ({ getCacheForType(resourceType: () => T): T { const cache = resolveCache(); let entry: T | void = (cache.get(resourceType): any); @@ -30,4 +34,16 @@ export const DefaultAsyncDispatcher: AsyncDispatcher = { } return entry; }, -}; +}: any); + +if (__DEV__) { + DefaultAsyncDispatcher.getOwner = (): null | ReactComponentInfo => { + // TODO + return null; + }; +} else if (!disableStringRefs) { + // Server Components never use string refs but the JSX runtime looks for it. + DefaultAsyncDispatcher.getOwner = (): null | ReactComponentInfo => { + return null; + }; +} diff --git a/packages/react-suspense-test-utils/src/ReactSuspenseTestUtils.js b/packages/react-suspense-test-utils/src/ReactSuspenseTestUtils.js index 35b59b61d1c21..bc2d4bee79d02 100644 --- a/packages/react-suspense-test-utils/src/ReactSuspenseTestUtils.js +++ b/packages/react-suspense-test-utils/src/ReactSuspenseTestUtils.js @@ -22,6 +22,9 @@ export function waitForSuspense(fn: () => T): Promise { } return entry; }, + getOwner(): null { + return null; + }, }; // Not using async/await because we don't compile it. return new Promise((resolve, reject) => { From ea9c8d759b8b2e0971d744846b3ea281135dad1f Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Tue, 9 Apr 2024 13:37:16 -0400 Subject: [PATCH 03/10] Rename Cache files to AsyncDispatcher --- .../src/{ReactFiberCache.js => ReactFiberAsyncDispatcher.js} | 0 packages/react-reconciler/src/ReactFiberWorkLoop.js | 2 +- .../src/{ReactFizzCache.js => ReactFizzAsyncDispatcher.js} | 0 packages/react-server/src/ReactFizzServer.js | 2 +- packages/react-server/src/ReactFlightServer.js | 2 +- ...{ReactFlightServerCache.js => ReactFlightAsyncDispatcher.js} | 0 6 files changed, 3 insertions(+), 3 deletions(-) rename packages/react-reconciler/src/{ReactFiberCache.js => ReactFiberAsyncDispatcher.js} (100%) rename packages/react-server/src/{ReactFizzCache.js => ReactFizzAsyncDispatcher.js} (100%) rename packages/react-server/src/flight/{ReactFlightServerCache.js => ReactFlightAsyncDispatcher.js} (100%) diff --git a/packages/react-reconciler/src/ReactFiberCache.js b/packages/react-reconciler/src/ReactFiberAsyncDispatcher.js similarity index 100% rename from packages/react-reconciler/src/ReactFiberCache.js rename to packages/react-reconciler/src/ReactFiberAsyncDispatcher.js diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.js b/packages/react-reconciler/src/ReactFiberWorkLoop.js index ceb4b7f47d328..67d5b0a877c1f 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.js @@ -203,7 +203,7 @@ import { resetHooksOnUnwind, ContextOnlyDispatcher, } from './ReactFiberHooks'; -import {DefaultAsyncDispatcher} from './ReactFiberCache'; +import {DefaultAsyncDispatcher} from './ReactFiberAsyncDispatcher'; import { createCapturedValueAtFiber, type CapturedValue, diff --git a/packages/react-server/src/ReactFizzCache.js b/packages/react-server/src/ReactFizzAsyncDispatcher.js similarity index 100% rename from packages/react-server/src/ReactFizzCache.js rename to packages/react-server/src/ReactFizzAsyncDispatcher.js diff --git a/packages/react-server/src/ReactFizzServer.js b/packages/react-server/src/ReactFizzServer.js index 7a1361bd12631..a13e8c942429a 100644 --- a/packages/react-server/src/ReactFizzServer.js +++ b/packages/react-server/src/ReactFizzServer.js @@ -111,7 +111,7 @@ import { getActionStateCount, getActionStateMatchingIndex, } from './ReactFizzHooks'; -import {DefaultAsyncDispatcher} from './ReactFizzCache'; +import {DefaultAsyncDispatcher} from './ReactFizzAsyncDispatcher'; import {getStackByComponentStackNode} from './ReactFizzComponentStack'; import {emptyTreeContext, pushTreeContext} from './ReactFizzTreeContext'; diff --git a/packages/react-server/src/ReactFlightServer.js b/packages/react-server/src/ReactFlightServer.js index bfeb98a52285c..d49476110a96e 100644 --- a/packages/react-server/src/ReactFlightServer.js +++ b/packages/react-server/src/ReactFlightServer.js @@ -89,7 +89,7 @@ import { getThenableStateAfterSuspending, resetHooksForRequest, } from './ReactFlightHooks'; -import {DefaultAsyncDispatcher} from './flight/ReactFlightServerCache'; +import {DefaultAsyncDispatcher} from './flight/ReactFlightAsyncDispatcher'; import { getIteratorFn, diff --git a/packages/react-server/src/flight/ReactFlightServerCache.js b/packages/react-server/src/flight/ReactFlightAsyncDispatcher.js similarity index 100% rename from packages/react-server/src/flight/ReactFlightServerCache.js rename to packages/react-server/src/flight/ReactFlightAsyncDispatcher.js From b6996c5b7be5c98a275b1e13ee02619822ad408c Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Tue, 9 Apr 2024 13:40:56 -0400 Subject: [PATCH 04/10] Push the async dispatcher if either feature is used for this flag Basically always but we currently don't actually need it for prod on the client. --- packages/react-reconciler/src/ReactFiberWorkLoop.js | 4 ++-- packages/react-server/src/ReactFizzServer.js | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.js b/packages/react-reconciler/src/ReactFiberWorkLoop.js index 67d5b0a877c1f..3c802c25646b5 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.js @@ -1875,7 +1875,7 @@ function popDispatcher(prevDispatcher: any) { } function pushAsyncDispatcher() { - if (enableCache) { + if (enableCache || __DEV__ || !disableStringRefs) { const prevAsyncDispatcher = ReactSharedInternals.A; ReactSharedInternals.A = DefaultAsyncDispatcher; return prevAsyncDispatcher; @@ -1885,7 +1885,7 @@ function pushAsyncDispatcher() { } function popAsyncDispatcher(prevAsyncDispatcher: any) { - if (enableCache) { + if (enableCache || __DEV__ || !disableStringRefs) { ReactSharedInternals.A = prevAsyncDispatcher; } } diff --git a/packages/react-server/src/ReactFizzServer.js b/packages/react-server/src/ReactFizzServer.js index a13e8c942429a..9c8207f6bfd89 100644 --- a/packages/react-server/src/ReactFizzServer.js +++ b/packages/react-server/src/ReactFizzServer.js @@ -148,6 +148,7 @@ import { enableRefAsProp, disableDefaultPropsExceptForClasses, enableAsyncIterableChildren, + disableStringRefs, } from 'shared/ReactFeatureFlags'; import assign from 'shared/assign'; @@ -3792,7 +3793,7 @@ export function performWork(request: Request): void { const prevDispatcher = ReactSharedInternals.H; ReactSharedInternals.H = HooksDispatcher; let prevAsyncDispatcher = null; - if (enableCache) { + if (enableCache || __DEV__ || !disableStringRefs) { prevAsyncDispatcher = ReactSharedInternals.A; ReactSharedInternals.A = DefaultAsyncDispatcher; } From 399b0cb75f32bb1a97a504190df0c5f29bf582f5 Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Tue, 9 Apr 2024 13:51:22 -0400 Subject: [PATCH 05/10] Track currentOwner for Fiber locally inside the reconciler This means that usage internal to the reconciler can refer to it directly without going through the dispatcher. --- packages/react-dom/src/client/ReactDOMRootFB.js | 4 ++-- .../src/ReactNativePublicCompat.js | 6 +++--- .../src/ReactFiberAsyncDispatcher.js | 9 +++++++-- .../react-reconciler/src/ReactFiberBeginWork.js | 10 +++++----- .../src/ReactFiberTreeReflection.js | 4 ++-- packages/react-reconciler/src/ReactFiberWorkLoop.js | 13 ++++++++----- 6 files changed, 27 insertions(+), 19 deletions(-) diff --git a/packages/react-dom/src/client/ReactDOMRootFB.js b/packages/react-dom/src/client/ReactDOMRootFB.js index f41d8868279c7..51af725314a02 100644 --- a/packages/react-dom/src/client/ReactDOMRootFB.js +++ b/packages/react-dom/src/client/ReactDOMRootFB.js @@ -61,7 +61,7 @@ import {LegacyRoot} from 'react-reconciler/src/ReactRootTags'; import getComponentNameFromType from 'shared/getComponentNameFromType'; import {has as hasInstance} from 'shared/ReactInstanceMap'; -import ReactSharedInternals from 'shared/ReactSharedInternals'; +import {currentOwner} from 'react-reconciler/src/ReactFiberAsyncDispatcher'; import assign from 'shared/assign'; @@ -342,7 +342,7 @@ export function findDOMNode( componentOrElement: Element | ?React$Component, ): null | Element | Text { if (__DEV__) { - const owner = (ReactSharedInternals.owner: any); + const owner = currentOwner; if (owner !== null && owner.stateNode !== null) { const warnedAboutRefsInRender = owner.stateNode._warnedAboutRefsInRender; if (!warnedAboutRefsInRender) { diff --git a/packages/react-native-renderer/src/ReactNativePublicCompat.js b/packages/react-native-renderer/src/ReactNativePublicCompat.js index 93b85e172d414..a0c7e86085217 100644 --- a/packages/react-native-renderer/src/ReactNativePublicCompat.js +++ b/packages/react-native-renderer/src/ReactNativePublicCompat.js @@ -24,14 +24,14 @@ import { findHostInstanceWithWarning, } from 'react-reconciler/src/ReactFiberReconciler'; import {doesFiberContain} from 'react-reconciler/src/ReactFiberTreeReflection'; -import ReactSharedInternals from 'shared/ReactSharedInternals'; import getComponentNameFromType from 'shared/getComponentNameFromType'; +import {currentOwner} from 'react-reconciler/src/ReactFiberAsyncDispatcher'; export function findHostInstance_DEPRECATED( componentOrHandle: ?(ElementRef | number), ): ?ElementRef> { if (__DEV__) { - const owner = ReactSharedInternals.owner; + const owner = currentOwner; if (owner !== null && owner.stateNode !== null) { if (!owner.stateNode._warnedAboutRefsInRender) { console.error( @@ -86,7 +86,7 @@ export function findHostInstance_DEPRECATED( export function findNodeHandle(componentOrHandle: any): ?number { if (__DEV__) { - const owner = ReactSharedInternals.owner; + const owner = currentOwner; if (owner !== null && owner.stateNode !== null) { if (!owner.stateNode._warnedAboutRefsInRender) { console.error( diff --git a/packages/react-reconciler/src/ReactFiberAsyncDispatcher.js b/packages/react-reconciler/src/ReactFiberAsyncDispatcher.js index 379425fc2241a..11b71213d8a99 100644 --- a/packages/react-reconciler/src/ReactFiberAsyncDispatcher.js +++ b/packages/react-reconciler/src/ReactFiberAsyncDispatcher.js @@ -29,13 +29,18 @@ function getCacheForType(resourceType: () => T): T { return cacheForType; } +export let currentOwner: Fiber | null = null; + export const DefaultAsyncDispatcher: AsyncDispatcher = ({ getCacheForType, }: any); if (__DEV__ || !disableStringRefs) { DefaultAsyncDispatcher.getOwner = (): null | Fiber => { - // TODO - return null; + return currentOwner; }; } + +export function setCurrentOwner(fiber: null | Fiber) { + currentOwner = fiber; +} diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.js b/packages/react-reconciler/src/ReactFiberBeginWork.js index 034c853976aa8..a648bfb9d9198 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.js @@ -91,7 +91,6 @@ import { Passive, DidDefer, } from './ReactFiberFlags'; -import ReactSharedInternals from 'shared/ReactSharedInternals'; import { debugRenderPhaseSideEffectsForStrictMode, disableLegacyContext, @@ -297,6 +296,7 @@ import { pushRootMarkerInstance, TransitionTracingMarker, } from './ReactFiberTracingMarkerComponent'; +import {setCurrentOwner} from './ReactFiberAsyncDispatcher'; // A special exception that's used to unwind the stack when an update flows // into a dehydrated boundary. @@ -432,7 +432,7 @@ function updateForwardRef( markComponentRenderStarted(workInProgress); } if (__DEV__) { - ReactSharedInternals.owner = workInProgress; + setCurrentOwner(workInProgress); setIsRendering(true); nextChildren = renderWithHooks( current, @@ -1150,7 +1150,7 @@ function updateFunctionComponent( markComponentRenderStarted(workInProgress); } if (__DEV__) { - ReactSharedInternals.owner = workInProgress; + setCurrentOwner(workInProgress); setIsRendering(true); nextChildren = renderWithHooks( current, @@ -1373,7 +1373,7 @@ function finishClassComponent( // Rerender if (__DEV__ || !disableStringRefs) { - ReactSharedInternals.owner = workInProgress; + setCurrentOwner(workInProgress); } let nextChildren; if ( @@ -3419,7 +3419,7 @@ function updateContextConsumer( } let newChildren; if (__DEV__) { - ReactSharedInternals.owner = workInProgress; + setCurrentOwner(workInProgress); setIsRendering(true); newChildren = render(newValue); setIsRendering(false); diff --git a/packages/react-reconciler/src/ReactFiberTreeReflection.js b/packages/react-reconciler/src/ReactFiberTreeReflection.js index 64cc35d2c0bf4..95916dcfff694 100644 --- a/packages/react-reconciler/src/ReactFiberTreeReflection.js +++ b/packages/react-reconciler/src/ReactFiberTreeReflection.js @@ -12,7 +12,6 @@ import type {Container, SuspenseInstance} from './ReactFiberConfig'; import type {SuspenseState} from './ReactFiberSuspenseComponent'; import {get as getInstance} from 'shared/ReactInstanceMap'; -import ReactSharedInternals from 'shared/ReactSharedInternals'; import getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber'; import { ClassComponent, @@ -25,6 +24,7 @@ import { SuspenseComponent, } from './ReactWorkTags'; import {NoFlags, Placement, Hydrating} from './ReactFiberFlags'; +import {currentOwner} from './ReactFiberAsyncDispatcher'; export function getNearestMountedFiber(fiber: Fiber): null | Fiber { let node = fiber; @@ -89,7 +89,7 @@ export function isFiberMounted(fiber: Fiber): boolean { export function isMounted(component: React$Component): boolean { if (__DEV__) { - const owner = (ReactSharedInternals.owner: any); + const owner = currentOwner; 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 3c802c25646b5..13e69a85813e0 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.js @@ -203,7 +203,10 @@ import { resetHooksOnUnwind, ContextOnlyDispatcher, } from './ReactFiberHooks'; -import {DefaultAsyncDispatcher} from './ReactFiberAsyncDispatcher'; +import { + DefaultAsyncDispatcher, + setCurrentOwner, +} from './ReactFiberAsyncDispatcher'; import { createCapturedValueAtFiber, type CapturedValue, @@ -1684,7 +1687,7 @@ function handleThrow(root: FiberRoot, thrownValue: any): void { resetHooksAfterThrow(); resetCurrentDebugFiberInDEV(); if (__DEV__ || !disableStringRefs) { - ReactSharedInternals.owner = null; + setCurrentOwner(null); } if (thrownValue === SuspenseException) { @@ -2386,7 +2389,7 @@ function performUnitOfWork(unitOfWork: Fiber): void { } if (__DEV__ || !disableStringRefs) { - ReactSharedInternals.owner = null; + setCurrentOwner(null); } } @@ -2501,7 +2504,7 @@ function replaySuspendedUnitOfWork(unitOfWork: Fiber): void { } if (__DEV__ || !disableStringRefs) { - ReactSharedInternals.owner = null; + setCurrentOwner(null); } } @@ -2894,7 +2897,7 @@ function commitRootImpl( // Reset this to null before calling lifecycles if (__DEV__ || !disableStringRefs) { - ReactSharedInternals.owner = null; + setCurrentOwner(null); } // The commit phase is broken into several sub-phases. We do a separate pass From 95b36e18b8211a5068a3d97a0145a7cc57946677 Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Tue, 9 Apr 2024 13:54:27 -0400 Subject: [PATCH 06/10] Same thing for Flight This will later use AsyncLocalStorage to track this just like the cache. --- packages/react-server/src/ReactFlightServer.js | 12 ++++++++---- .../src/flight/ReactFlightAsyncDispatcher.js | 9 +++++++-- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/packages/react-server/src/ReactFlightServer.js b/packages/react-server/src/ReactFlightServer.js index d49476110a96e..5c66d56bf3075 100644 --- a/packages/react-server/src/ReactFlightServer.js +++ b/packages/react-server/src/ReactFlightServer.js @@ -89,7 +89,11 @@ import { getThenableStateAfterSuspending, resetHooksForRequest, } from './ReactFlightHooks'; -import {DefaultAsyncDispatcher} from './flight/ReactFlightAsyncDispatcher'; +import { + DefaultAsyncDispatcher, + currentOwner, + setCurrentOwner, +} from './flight/ReactFlightAsyncDispatcher'; import { getIteratorFn, @@ -158,7 +162,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 = ReactSharedInternals.owner; + const owner: null | ReactComponentInfo = currentOwner; emitConsoleChunk(request, id, methodName, owner, stack, arguments); } // $FlowFixMe[prop-missing] @@ -856,11 +860,11 @@ function renderFunctionComponent( const secondArg = undefined; let result; if (__DEV__) { - ReactSharedInternals.owner = componentDebugInfo; + setCurrentOwner(componentDebugInfo); try { result = Component(props, secondArg); } finally { - ReactSharedInternals.owner = null; + setCurrentOwner(null); } } else { result = Component(props, secondArg); diff --git a/packages/react-server/src/flight/ReactFlightAsyncDispatcher.js b/packages/react-server/src/flight/ReactFlightAsyncDispatcher.js index 8ff0cd5bc9a3a..1cdd67a82153b 100644 --- a/packages/react-server/src/flight/ReactFlightAsyncDispatcher.js +++ b/packages/react-server/src/flight/ReactFlightAsyncDispatcher.js @@ -36,10 +36,11 @@ export const DefaultAsyncDispatcher: AsyncDispatcher = ({ }, }: any); +export let currentOwner: ReactComponentInfo | null = null; + if (__DEV__) { DefaultAsyncDispatcher.getOwner = (): null | ReactComponentInfo => { - // TODO - return null; + return currentOwner; }; } else if (!disableStringRefs) { // Server Components never use string refs but the JSX runtime looks for it. @@ -47,3 +48,7 @@ if (__DEV__) { return null; }; } + +export function setCurrentOwner(componentInfo: null | ReactComponentInfo) { + currentOwner = componentInfo; +} From deb2aaeb67bd44ac783ef9531eaaac9fde9e6332 Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Tue, 9 Apr 2024 14:11:31 -0400 Subject: [PATCH 07/10] Get owner from the dispatcher in JSX We need to be careful about only getting it in branches that has the dispatcher activated and if the dispatcher is activate. --- packages/react/src/jsx/ReactJSXElement.js | 73 ++++++++++------------- 1 file changed, 30 insertions(+), 43 deletions(-) diff --git a/packages/react/src/jsx/ReactJSXElement.js b/packages/react/src/jsx/ReactJSXElement.js index 81f50489204f0..d8452a2e360a2 100644 --- a/packages/react/src/jsx/ReactJSXElement.js +++ b/packages/react/src/jsx/ReactJSXElement.js @@ -29,6 +29,17 @@ import getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFrom const REACT_CLIENT_REFERENCE = Symbol.for('react.client.reference'); +function getOwner() { + if (__DEV__ || !disableStringRefs) { + const dispatcher = ReactSharedInternals.A; + if (dispatcher === null) { + return null; + } + return dispatcher.getOwner(); + } + return null; +} + let specialPropKeyWarningShown; let specialPropRefWarningShown; let didWarnAboutStringRefs; @@ -66,16 +77,15 @@ function hasValidKey(config) { function warnIfStringRefCannotBeAutoConverted(config, self) { if (__DEV__) { + let owner; if ( !disableStringRefs && typeof config.ref === 'string' && - ReactSharedInternals.owner && + (owner = getOwner()) && self && - ReactSharedInternals.owner.stateNode !== self + owner.stateNode !== self ) { - const componentName = getComponentNameFromType( - ReactSharedInternals.owner.type, - ); + const componentName = getComponentNameFromType(owner.type); if (!didWarnAboutStringRefs[componentName]) { console.error( @@ -85,7 +95,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(ReactSharedInternals.owner.type), + getComponentNameFromType(owner.type), config.ref, ); didWarnAboutStringRefs[componentName] = true; @@ -339,7 +349,7 @@ export function jsxProd(type, config, maybeKey) { if (!enableRefAsProp) { ref = config.ref; if (!disableStringRefs) { - ref = coerceStringRef(ref, ReactSharedInternals.owner, type); + ref = coerceStringRef(ref, getOwner(), type); } } } @@ -365,11 +375,7 @@ export function jsxProd(type, config, maybeKey) { // Skip over reserved prop names if (propName !== 'key' && (enableRefAsProp || propName !== 'ref')) { if (enableRefAsProp && !disableStringRefs && propName === 'ref') { - props.ref = coerceStringRef( - config[propName], - ReactSharedInternals.owner, - type, - ); + props.ref = coerceStringRef(config[propName], getOwner(), type); } else { props[propName] = config[propName]; } @@ -389,15 +395,7 @@ export function jsxProd(type, config, maybeKey) { } } - return ReactElement( - type, - key, - ref, - undefined, - undefined, - ReactSharedInternals.owner, - props, - ); + return ReactElement(type, key, ref, undefined, undefined, getOwner(), props); } // While `jsxDEV` should never be called when running in production, we do @@ -571,7 +569,7 @@ export function jsxDEV(type, config, maybeKey, isStaticChildren, source, self) { if (!enableRefAsProp) { ref = config.ref; if (!disableStringRefs) { - ref = coerceStringRef(ref, ReactSharedInternals.owner, type); + ref = coerceStringRef(ref, getOwner(), type); } } if (!disableStringRefs) { @@ -600,11 +598,7 @@ export function jsxDEV(type, config, maybeKey, isStaticChildren, source, self) { // Skip over reserved prop names if (propName !== 'key' && (enableRefAsProp || propName !== 'ref')) { if (enableRefAsProp && !disableStringRefs && propName === 'ref') { - props.ref = coerceStringRef( - config[propName], - ReactSharedInternals.owner, - type, - ); + props.ref = coerceStringRef(config[propName], getOwner(), type); } else { props[propName] = config[propName]; } @@ -643,7 +637,7 @@ export function jsxDEV(type, config, maybeKey, isStaticChildren, source, self) { ref, self, source, - ReactSharedInternals.owner, + getOwner(), props, ); @@ -747,7 +741,7 @@ export function createElement(type, config, children) { if (!enableRefAsProp) { ref = config.ref; if (!disableStringRefs) { - ref = coerceStringRef(ref, ReactSharedInternals.owner, type); + ref = coerceStringRef(ref, getOwner(), type); } } @@ -777,11 +771,7 @@ export function createElement(type, config, children) { propName !== '__source' ) { if (enableRefAsProp && !disableStringRefs && propName === 'ref') { - props.ref = coerceStringRef( - config[propName], - ReactSharedInternals.owner, - type, - ); + props.ref = coerceStringRef(config[propName], getOwner(), type); } else { props[propName] = config[propName]; } @@ -837,7 +827,7 @@ export function createElement(type, config, children) { ref, undefined, undefined, - ReactSharedInternals.owner, + getOwner(), props, ); @@ -887,7 +877,7 @@ export function cloneElement(element, config, children) { if (config != null) { if (hasValidRef(config)) { - owner = ReactSharedInternals.owner; + owner = __DEV__ || !disableStringRefs ? getOwner() : undefined; if (!enableRefAsProp) { // Silently steal the ref from the parent. ref = config.ref; @@ -981,8 +971,9 @@ export function cloneElement(element, config, children) { function getDeclarationErrorAddendum() { if (__DEV__) { - if (ReactSharedInternals.owner) { - const name = getComponentNameFromType(ReactSharedInternals.owner.type); + const owner = getOwner(); + if (owner) { + const name = getComponentNameFromType(owner.type); if (name) { return '\n\nCheck the render method of `' + name + '`.'; } @@ -1085,11 +1076,7 @@ function validateExplicitKey(element, parentType) { // property, it may be the creator of the child that's responsible for // assigning it a key. let childOwner = ''; - if ( - element && - element._owner != null && - element._owner !== ReactSharedInternals.owner - ) { + if (element && element._owner != null && element._owner !== getOwner()) { let ownerName = null; if (typeof element._owner.tag === 'number') { ownerName = getComponentNameFromType(element._owner.type); From af3c909dc196d907baf739e21464d302db87116a Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Tue, 9 Apr 2024 14:25:39 -0400 Subject: [PATCH 08/10] Update tests of the internal states --- .../__tests__/ReactCompositeComponent-test.js | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/packages/react-dom/src/__tests__/ReactCompositeComponent-test.js b/packages/react-dom/src/__tests__/ReactCompositeComponent-test.js index 4630f9ddbc163..894afb39ba0cf 100644 --- a/packages/react-dom/src/__tests__/ReactCompositeComponent-test.js +++ b/packages/react-dom/src/__tests__/ReactCompositeComponent-test.js @@ -537,16 +537,24 @@ describe('ReactCompositeComponent', () => { }); it('should cleanup even if render() fatals', async () => { + const dispatcherEnabled = + __DEV__ || + !gate(flags => flags.disableStringRefs) || + gate(flags => flags.enableCache); + const ownerEnabled = __DEV__ || !gate(flags => flags.disableStringRefs); + + let stashedDispatcher; class BadComponent extends React.Component { render() { + // Stash the dispatcher that was available in render so we can check + // that its internals also reset. + stashedDispatcher = ReactSharedInternals.A; throw new Error(); } } const instance = ; - expect(ReactSharedInternals.owner).toBe( - __DEV__ || !gate(flags => flags.disableStringRefs) ? null : undefined, - ); + expect(ReactSharedInternals.A).toBe(dispatcherEnabled ? null : undefined); const root = ReactDOMClient.createRoot(document.createElement('div')); await expect(async () => { @@ -555,9 +563,16 @@ describe('ReactCompositeComponent', () => { }); }).rejects.toThrow(); - expect(ReactSharedInternals.owner).toBe( - __DEV__ || !gate(flags => flags.disableStringRefs) ? null : undefined, - ); + expect(ReactSharedInternals.A).toBe(dispatcherEnabled ? null : undefined); + if (dispatcherEnabled) { + if (ownerEnabled) { + expect(stashedDispatcher.getOwner()).toBe(null); + } else { + expect(stashedDispatcher.getOwner).toBe(undefined); + } + } else { + expect(stashedDispatcher).toBe(undefined); + } }); it('should call componentWillUnmount before unmounting', async () => { From 6acd079c0dfebd56033cd945923e55e0806d6c8a Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Tue, 9 Apr 2024 14:28:34 -0400 Subject: [PATCH 09/10] Remove old field from internals --- packages/react/src/ReactSharedInternalsClient.js | 10 +--------- packages/react/src/ReactSharedInternalsServer.js | 10 ++-------- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/packages/react/src/ReactSharedInternalsClient.js b/packages/react/src/ReactSharedInternalsClient.js index 5a6925b0fa626..52adec8be4b30 100644 --- a/packages/react/src/ReactSharedInternalsClient.js +++ b/packages/react/src/ReactSharedInternalsClient.js @@ -10,17 +10,13 @@ import type {Dispatcher} from 'react-reconciler/src/ReactInternalTypes'; import type {AsyncDispatcher} 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 A: null | AsyncDispatcher, // 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. + // DEV-only // ReactCurrentActQueue actQueue: null | Array, @@ -51,10 +47,6 @@ const ReactSharedInternals: SharedStateClient = ({ T: null, }: any); -if (__DEV__ || !disableStringRefs) { - ReactSharedInternals.owner = null; -} - if (__DEV__) { ReactSharedInternals.actQueue = null; ReactSharedInternals.isBatchingLegacy = false; diff --git a/packages/react/src/ReactSharedInternalsServer.js b/packages/react/src/ReactSharedInternalsServer.js index 2f032bb212779..4c63c75a0d5d2 100644 --- a/packages/react/src/ReactSharedInternalsServer.js +++ b/packages/react/src/ReactSharedInternalsServer.js @@ -9,7 +9,6 @@ import type {Dispatcher} from 'react-reconciler/src/ReactInternalTypes'; import type {AsyncDispatcher} from 'react-reconciler/src/ReactInternalTypes'; -import type {ReactComponentInfo} from 'shared/ReactTypes'; import type { Reference, @@ -24,7 +23,7 @@ import { TaintRegistryPendingRequests, } from './ReactTaintRegistry'; -import {disableStringRefs, enableTaint} from 'shared/ReactFeatureFlags'; +import {enableTaint} from 'shared/ReactFeatureFlags'; export type SharedStateServer = { H: null | Dispatcher, // ReactCurrentDispatcher for Hooks @@ -36,8 +35,7 @@ export type SharedStateServer = { TaintRegistryByteLengths: Set, TaintRegistryPendingRequests: Set, - // DEV-only-ish - owner: null | ReactComponentInfo, // ReactCurrentOwner is ReactComponentInfo in Flight, null in Fizz. Fiber/Fizz uses SharedStateClient. + // DEV-only // ReactDebugCurrentFrame setExtraStackFrame: (stack: null | string) => void, @@ -60,10 +58,6 @@ if (enableTaint) { TaintRegistryPendingRequests; } -if (__DEV__ || !disableStringRefs) { - ReactSharedInternals.owner = null; -} - if (__DEV__) { let currentExtraStackFrame = (null: null | string); ReactSharedInternals.setExtraStackFrame = function (stack: null | string) { From 76716212bbdf6cf29dc0ad6f83424ee84c313d08 Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Tue, 9 Apr 2024 14:57:03 -0400 Subject: [PATCH 10/10] Resolve cycle --- packages/react-dom/src/client/ReactDOMRootFB.js | 2 +- .../src/ReactNativePublicCompat.js | 2 +- .../src/ReactFiberAsyncDispatcher.js | 8 ++------ .../react-reconciler/src/ReactFiberBeginWork.js | 2 +- .../src/ReactFiberCurrentOwner.js | 16 ++++++++++++++++ .../src/ReactFiberTreeReflection.js | 2 +- .../react-reconciler/src/ReactFiberWorkLoop.js | 6 ++---- 7 files changed, 24 insertions(+), 14 deletions(-) create mode 100644 packages/react-reconciler/src/ReactFiberCurrentOwner.js diff --git a/packages/react-dom/src/client/ReactDOMRootFB.js b/packages/react-dom/src/client/ReactDOMRootFB.js index 51af725314a02..0aa2306665f4e 100644 --- a/packages/react-dom/src/client/ReactDOMRootFB.js +++ b/packages/react-dom/src/client/ReactDOMRootFB.js @@ -61,7 +61,7 @@ import {LegacyRoot} from 'react-reconciler/src/ReactRootTags'; import getComponentNameFromType from 'shared/getComponentNameFromType'; import {has as hasInstance} from 'shared/ReactInstanceMap'; -import {currentOwner} from 'react-reconciler/src/ReactFiberAsyncDispatcher'; +import {currentOwner} from 'react-reconciler/src/ReactFiberCurrentOwner'; import assign from 'shared/assign'; diff --git a/packages/react-native-renderer/src/ReactNativePublicCompat.js b/packages/react-native-renderer/src/ReactNativePublicCompat.js index a0c7e86085217..081ea6f7eb571 100644 --- a/packages/react-native-renderer/src/ReactNativePublicCompat.js +++ b/packages/react-native-renderer/src/ReactNativePublicCompat.js @@ -25,7 +25,7 @@ import { } from 'react-reconciler/src/ReactFiberReconciler'; import {doesFiberContain} from 'react-reconciler/src/ReactFiberTreeReflection'; import getComponentNameFromType from 'shared/getComponentNameFromType'; -import {currentOwner} from 'react-reconciler/src/ReactFiberAsyncDispatcher'; +import {currentOwner} from 'react-reconciler/src/ReactFiberCurrentOwner'; export function findHostInstance_DEPRECATED( componentOrHandle: ?(ElementRef | number), diff --git a/packages/react-reconciler/src/ReactFiberAsyncDispatcher.js b/packages/react-reconciler/src/ReactFiberAsyncDispatcher.js index 11b71213d8a99..f1c251965512c 100644 --- a/packages/react-reconciler/src/ReactFiberAsyncDispatcher.js +++ b/packages/react-reconciler/src/ReactFiberAsyncDispatcher.js @@ -16,6 +16,8 @@ import {CacheContext} from './ReactFiberCacheComponent'; import {disableStringRefs} from 'shared/ReactFeatureFlags'; +import {currentOwner} from './ReactFiberCurrentOwner'; + function getCacheForType(resourceType: () => T): T { if (!enableCache) { throw new Error('Not implemented.'); @@ -29,8 +31,6 @@ function getCacheForType(resourceType: () => T): T { return cacheForType; } -export let currentOwner: Fiber | null = null; - export const DefaultAsyncDispatcher: AsyncDispatcher = ({ getCacheForType, }: any); @@ -40,7 +40,3 @@ if (__DEV__ || !disableStringRefs) { return currentOwner; }; } - -export function setCurrentOwner(fiber: null | Fiber) { - currentOwner = fiber; -} diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.js b/packages/react-reconciler/src/ReactFiberBeginWork.js index a648bfb9d9198..b1d639583df7f 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.js @@ -296,7 +296,7 @@ import { pushRootMarkerInstance, TransitionTracingMarker, } from './ReactFiberTracingMarkerComponent'; -import {setCurrentOwner} from './ReactFiberAsyncDispatcher'; +import {setCurrentOwner} from './ReactFiberCurrentOwner'; // A special exception that's used to unwind the stack when an update flows // into a dehydrated boundary. diff --git a/packages/react-reconciler/src/ReactFiberCurrentOwner.js b/packages/react-reconciler/src/ReactFiberCurrentOwner.js new file mode 100644 index 0000000000000..0c1f3d6e3130d --- /dev/null +++ b/packages/react-reconciler/src/ReactFiberCurrentOwner.js @@ -0,0 +1,16 @@ +/** + * 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 './ReactInternalTypes'; + +export let currentOwner: Fiber | null = null; + +export function setCurrentOwner(fiber: null | Fiber) { + currentOwner = fiber; +} diff --git a/packages/react-reconciler/src/ReactFiberTreeReflection.js b/packages/react-reconciler/src/ReactFiberTreeReflection.js index 95916dcfff694..57640bd7f3b18 100644 --- a/packages/react-reconciler/src/ReactFiberTreeReflection.js +++ b/packages/react-reconciler/src/ReactFiberTreeReflection.js @@ -24,7 +24,7 @@ import { SuspenseComponent, } from './ReactWorkTags'; import {NoFlags, Placement, Hydrating} from './ReactFiberFlags'; -import {currentOwner} from './ReactFiberAsyncDispatcher'; +import {currentOwner} from './ReactFiberCurrentOwner'; export function getNearestMountedFiber(fiber: Fiber): null | Fiber { let node = fiber; diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.js b/packages/react-reconciler/src/ReactFiberWorkLoop.js index 13e69a85813e0..00391bb354ee8 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.js @@ -203,10 +203,8 @@ import { resetHooksOnUnwind, ContextOnlyDispatcher, } from './ReactFiberHooks'; -import { - DefaultAsyncDispatcher, - setCurrentOwner, -} from './ReactFiberAsyncDispatcher'; +import {DefaultAsyncDispatcher} from './ReactFiberAsyncDispatcher'; +import {setCurrentOwner} from './ReactFiberCurrentOwner'; import { createCapturedValueAtFiber, type CapturedValue,