diff --git a/packages/react-markup/src/__tests__/ReactMarkupAndFlight-test.js b/packages/react-markup/src/__tests__/ReactMarkupAndFlight-test.js index 2e15c2c6338077..8e3dd20974d025 100644 --- a/packages/react-markup/src/__tests__/ReactMarkupAndFlight-test.js +++ b/packages/react-markup/src/__tests__/ReactMarkupAndFlight-test.js @@ -306,10 +306,10 @@ if (!__EXPERIMENTAL__) { gate(flags => flags.enableOwnerStacks) ? [ __DEV__ - ? '\n' + - // - ' in Indirection (at **)\n' + - ' in App (at **)' + ? '\n in Indirection (at **)' + + '\n in App (at **)' + + '\n in Preview (at **)' + + '\n in PreviewApp (at **)' : null, ] : [], diff --git a/packages/react-reconciler/src/ReactInternalTypes.js b/packages/react-reconciler/src/ReactInternalTypes.js index 54d8b3a34993ee..8ed9ee4b126d78 100644 --- a/packages/react-reconciler/src/ReactInternalTypes.js +++ b/packages/react-reconciler/src/ReactInternalTypes.js @@ -457,7 +457,7 @@ export interface AsyncCache { } export type AsyncDispatcher = { - getActiveCache: () => AsyncCache, + getActiveCache: () => AsyncCache | null, // DEV-only (or !disableStringRefs) getOwner: () => null | Fiber | ReactComponentInfo | ComponentStackNode, }; diff --git a/packages/react-server/src/ReactFizzAsyncDispatcher.js b/packages/react-server/src/ReactFizzAsyncDispatcher.js index b7343ccba0bb2a..d37acf770078e5 100644 --- a/packages/react-server/src/ReactFizzAsyncDispatcher.js +++ b/packages/react-server/src/ReactFizzAsyncDispatcher.js @@ -17,7 +17,7 @@ import {disableStringRefs} from 'shared/ReactFeatureFlags'; import {currentTaskInDEV} from './ReactFizzCurrentTask'; -function getActiveCache(): AsyncCache { +function getActiveCache(): AsyncCache | null { throw new Error('Not implemented.'); } diff --git a/packages/react-server/src/ReactFlightServer.js b/packages/react-server/src/ReactFlightServer.js index a5654d3fe44d91..2866c3a59a0bef 100644 --- a/packages/react-server/src/ReactFlightServer.js +++ b/packages/react-server/src/ReactFlightServer.js @@ -10,10 +10,12 @@ import type {Chunk, BinaryChunk, Destination} from './ReactServerStreamConfig'; import type {Postpone} from 'react/src/ReactPostpone'; +import type {AsyncCache} from 'react-reconciler/src/ReactInternalTypes'; import type {TemporaryReferenceSet} from './ReactFlightServerTemporaryReferences'; import { + disableStringRefs, enableBinaryFlight, enablePostpone, enableHalt, @@ -395,8 +397,6 @@ const { TaintRegistryPendingRequests, } = ReactSharedInternals; -ReactSharedInternals.A = DefaultAsyncDispatcher; - function throwTaintViolation(message: string) { // eslint-disable-next-line react-internal/prod-error-codes throw new Error(message); @@ -450,6 +450,24 @@ function RequestInstance( onAllReady: () => void, onFatalError: (error: mixed) => void, ) { + const previousAsyncDispatcher = ReactSharedInternals.A; + + if (previousAsyncDispatcher !== null) { + const previousActiveCache = previousAsyncDispatcher.getActiveCache(); + if (previousActiveCache !== null) { + ReactSharedInternals.A = ({ + getActiveCache(): AsyncCache | null { + return previousActiveCache; + }, + }: any); + if (__DEV__ || !disableStringRefs) { + ReactSharedInternals.A.getOwner = DefaultAsyncDispatcher.getOwner; + } + } + } else { + ReactSharedInternals.A = DefaultAsyncDispatcher; + } + if (__DEV__) { // Unlike Fizz or Fiber, we don't reset this and just keep it on permanently. // This lets it act more like the AsyncDispatcher so that we can get the diff --git a/packages/react-server/src/flight/ReactFlightAsyncDispatcher.js b/packages/react-server/src/flight/ReactFlightAsyncDispatcher.js index 5c2ff3174d1668..190304cc24b6be 100644 --- a/packages/react-server/src/flight/ReactFlightAsyncDispatcher.js +++ b/packages/react-server/src/flight/ReactFlightAsyncDispatcher.js @@ -15,54 +15,17 @@ import type { } from 'react-reconciler/src/ReactInternalTypes'; import {resolveRequest, getCache} from '../ReactFlightServer'; -import ReactSharedInternals from '../ReactSharedInternalsServer'; import {disableStringRefs} from 'shared/ReactFeatureFlags'; import {resolveOwner} from './ReactFlightCurrentOwner'; -const previousAsyncDispatcher = ReactSharedInternals.A; - -function resolveCache(): Map { +function getActiveCache(): AsyncCache | null { const request = resolveRequest(); if (request) { return getCache(request); } - return new Map(); -} - -function getActiveCache(): AsyncCache { - const outerCache: AsyncCache | null = - previousAsyncDispatcher !== null - ? previousAsyncDispatcher.getActiveCache() - : null; - - const innerCache = resolveCache(); - - if (outerCache === null) { - return innerCache; - } - - // If both caches are active, reads will prefer the outer cache - // Writes will go into both caches. - const chainedCache: AsyncCache = { - get(resourceType: Function) { - const outerEntry = outerCache.get(resourceType); - if (outerEntry !== undefined) { - return outerEntry; - } - return innerCache.get(resourceType); - }, - set(resourceType: Function, value: mixed) { - if (outerCache !== null) { - outerCache.set(resourceType, value); - } - innerCache.set(resourceType, value); - return chainedCache; - }, - }; - - return chainedCache; + return null; } export const DefaultAsyncDispatcher: AsyncDispatcher = ({ diff --git a/packages/react/src/ReactCacheImpl.js b/packages/react/src/ReactCacheImpl.js index 76f91fc5ccff02..f3d7e02f220c8c 100644 --- a/packages/react/src/ReactCacheImpl.js +++ b/packages/react/src/ReactCacheImpl.js @@ -61,13 +61,16 @@ export function cache, T>(fn: (...A) => T): (...A) => T { return fn.apply(null, arguments); } const activeCache = dispatcher.getActiveCache(); - let fnMap: WeakMap> | void = (activeCache.get( - createCacheRoot, - ): any); + let fnMap: Map> | void = + activeCache !== null + ? (activeCache.get(createCacheRoot): any) + : undefined; if (fnMap === undefined) { fnMap = createCacheRoot(); - // TODO: Warn if undefined? - activeCache.set(createCacheRoot, fnMap); + if (activeCache !== null) { + // TODO: Warn if undefined? + activeCache.set(createCacheRoot, fnMap); + } } const fnNode = fnMap.get(fn); let cacheNode: CacheNode; diff --git a/packages/react/src/ReactHooks.js b/packages/react/src/ReactHooks.js index ef5a54cb4e1f96..6543fd95a5ef32 100644 --- a/packages/react/src/ReactHooks.js +++ b/packages/react/src/ReactHooks.js @@ -54,11 +54,14 @@ export function getCacheForType(resourceType: () => T): T { return resourceType(); } const activeCache = dispatcher.getActiveCache(); - let entry: T | void = (activeCache.get(resourceType): any); + let entry: T | void = + activeCache !== null ? (activeCache.get(resourceType): any) : undefined; if (entry === undefined) { entry = resourceType(); - // TODO: Warn if undefined? - activeCache.set(resourceType, entry); + if (activeCache !== null) { + // TODO: Warn if undefined? + activeCache.set(resourceType, entry); + } } return entry; }