diff --git a/src/devtools/ProfilingCache.js b/src/devtools/ProfilingCache.js index 7dd8b3d946..d313111e67 100644 --- a/src/devtools/ProfilingCache.js +++ b/src/devtools/ProfilingCache.js @@ -1,6 +1,6 @@ // @flow -import { createResource, invalidateResources } from './cache'; +import { createResource } from './cache'; import Store from './store'; import { getCommitTree, @@ -297,8 +297,11 @@ export default class ProfilingCache { }); invalidate() { - // Invalidate Susepnse caches. - invalidateResources(); + // Invalidate Suspense caches. + this.CommitDetails.clear(); + this.FiberCommits.clear(); + this.Interactions.clear(); + this.ProfilingSummary.clear(); // Invalidate non-Suspense caches too. invalidateCommitTrees(); diff --git a/src/devtools/cache.js b/src/devtools/cache.js index ee3835fec3..bf509ce8f3 100644 --- a/src/devtools/cache.js +++ b/src/devtools/cache.js @@ -39,6 +39,7 @@ type RejectedResult = {| type Result = PendingResult | ResolvedResult | RejectedResult; export type Resource = { + clear(): void, invalidate(Key): void, read(Input): Value, preload(Input): void, @@ -66,7 +67,23 @@ function readContext(Context, observedBits) { const CacheContext = createContext(null); +type Config = { + useLRU?: boolean, +}; + const entries: Map, Map> = new Map(); +const resourceConfigs: Map, Config> = new Map(); + +function getEntriesForResource(resource: any): Map { + let entriesForResource = ((entries.get(resource): any): Map); + if (entriesForResource === undefined) { + const config = resourceConfigs.get(resource); + entriesForResource = + config !== undefined && config.useLRU ? new LRU({ max: 10 }) : new Map(); + entries.set(resource, entriesForResource); + } + return entriesForResource; +} function accessResult( resource: any, @@ -74,7 +91,7 @@ function accessResult( input: Input, key: Key ): Result { - const entriesForResource = ((entries.get(resource): any): Map); + const entriesForResource = getEntriesForResource(resource); const entry = entriesForResource.get(key); if (entry === undefined) { const thenable = fetch(input); @@ -108,11 +125,15 @@ function accessResult( export function createResource( fetch: Input => Thenable, hashInput: Input => Key, - useLRU?: boolean = false + config?: Config = {} ): Resource { const resource = { + clear(): void { + entries.delete(resource); + }, + invalidate(key: Key): void { - const entriesForResource = ((entries.get(resource): any): Map); + const entriesForResource = getEntriesForResource(resource); if (entriesForResource instanceof Map) { entriesForResource.delete(key); } else { @@ -156,7 +177,7 @@ export function createResource( }, write(key: Key, value: Value): void { - const entriesForResource = ((entries.get(resource): any): Map); + const entriesForResource = getEntriesForResource(resource); const resolvedResult: ResolvedResult = { status: Resolved, @@ -167,7 +188,7 @@ export function createResource( }, }; - entries.set(resource, useLRU ? new LRU({ max: 10 }) : new Map()); + resourceConfigs.set(resource, config); return resource; } diff --git a/src/devtools/views/Components/InspectedElementContext.js b/src/devtools/views/Components/InspectedElementContext.js index fbbc572f7b..99263e4c18 100644 --- a/src/devtools/views/Components/InspectedElementContext.js +++ b/src/devtools/views/Components/InspectedElementContext.js @@ -31,6 +31,27 @@ type InProgressRequest = {| resolveFn: ResolveFn, |}; +const inProgressRequests: Map = new Map(); +const resource: Resource = createResource( + (id: number) => { + let request = inProgressRequests.get(id); + if (request != null) { + return request.promise; + } + + let resolveFn = ((null: any): ResolveFn); + const promise = new Promise(resolve => { + resolveFn = resolve; + }); + + inProgressRequests.set(id, { promise, resolveFn }); + + return promise; + }, + (id: number) => id, + { useLRU: true } +); + type Props = {| children: React$Node, |}; @@ -42,34 +63,6 @@ function InspectedElementContextController({ children }: Props) { const [count, setCount] = useState(0); - const inProgressRequests = useMemo>( - () => new Map(), - [] - ); - - const resource = useMemo>( - () => - createResource( - (id: number) => { - let request = inProgressRequests.get(id); - if (request != null) { - return request.promise; - } - - let resolveFn = ((null: any): ResolveFn); - const promise = new Promise(resolve => { - resolveFn = resolve; - }); - - inProgressRequests.set(id, { promise, resolveFn }); - - return promise; - }, - (id: number) => id - ), - [inProgressRequests] - ); - // This effect handler invalidates the suspense cache and schedules rendering updates with React. useEffect(() => { const onInspectedElement = ( @@ -103,7 +96,7 @@ function InspectedElementContextController({ children }: Props) { bridge.addListener('inspectedElement', onInspectedElement); return () => bridge.removeListener('inspectedElement', onInspectedElement); - }, [bridge, inProgressRequests, inspectedElementID, resource]); + }, [bridge, inspectedElementID]); // This effect handler polls for updates on the currently selected element. useEffect(() => {