From a241780dc249bc959c6b7e663dbe2e6deec1ab42 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Mon, 29 Apr 2019 13:08:35 -0700 Subject: [PATCH] Filter changes are applied to the renderer without reloading --- src/backend/agent.js | 12 +++++++++++- src/backend/renderer.js | 32 +++++++++++++++++++++++++++++--- src/backend/types.js | 3 ++- src/devtools/store.js | 4 +++- 4 files changed, 45 insertions(+), 6 deletions(-) diff --git a/src/backend/agent.js b/src/backend/agent.js index 5364d048c5..fed7344dbe 100644 --- a/src/backend/agent.js +++ b/src/backend/agent.js @@ -16,7 +16,7 @@ import type { RendererID, RendererInterface, } from './types'; -import type { Bridge } from '../types'; +import type { Bridge, FilterPreferences } from '../types'; const debug = (methodName, ...args) => { if (__DEBUG__) { @@ -118,6 +118,7 @@ export default class Agent extends EventEmitter { this.syncSelectionFromNativeElementsPanel ); bridge.addListener('shutdown', this.shutdown); + bridge.addListener('updateFilterPreferences', this.updateFilterPreferences); bridge.addListener('viewElementSource', this.viewElementSource); if (this._isProfiling) { @@ -489,6 +490,15 @@ export default class Agent extends EventEmitter { this._bridge.send('profilingStatus', this._isProfiling); }; + updateFilterPreferences = (filterPreferences: FilterPreferences) => { + for (let rendererID in this._rendererInterfaces) { + const renderer = ((this._rendererInterfaces[ + (rendererID: any) + ]: any): RendererInterface); + renderer.updateFilterPreferences(filterPreferences); + } + }; + viewElementSource = ({ id, rendererID }: InspectSelectParams) => { const renderer = this._rendererInterfaces[rendererID]; if (renderer == null) { diff --git a/src/backend/renderer.js b/src/backend/renderer.js index f1ee1bc7da..6a7326e3ba 100644 --- a/src/backend/renderer.js +++ b/src/backend/renderer.js @@ -48,6 +48,7 @@ import type { RendererInterface, } from './types'; import type { InspectedElement } from 'src/devtools/views/Components/types'; +import type { FilterPreferences } from 'src/types'; function getInternalReactConstants(version) { const ReactSymbols = { @@ -264,12 +265,36 @@ export function attach( } }; - const { + let { hideElementsWithTypes, - // TOOD (filter) hideElementsWithDisplayNames, - // TOOD (filter) hideElementsWithPaths, + hideElementsWithDisplayNames, + hideElementsWithPaths, } = getSavedFilterPreferences(); + // TODO (filter) We could make this more efficient. + function updateFilterPreferences(filterPreferences: FilterPreferences) { + // Recursively unmount and then re-mount all roots. + hook.getFiberRoots(rendererID).forEach(root => { + currentRootID = getFiberID(getPrimaryFiber(root.current)); + unmountFiberChildrenRecursively(root.current); + recordUnmount(root.current, false); + currentRootID = -1; + }); + + hideElementsWithTypes = filterPreferences.hideElementsWithTypes; + hideElementsWithDisplayNames = + filterPreferences.hideElementsWithDisplayNames; + hideElementsWithPaths = filterPreferences.hideElementsWithPaths; + + // Recursively re-mount all roots with new filter criteria applied. + hook.getFiberRoots(rendererID).forEach(root => { + currentRootID = getFiberID(getPrimaryFiber(root.current)); + mountFiberRecursively(root.current, null); + flushPendingEvents(root); + currentRootID = -1; + }); + } + // NOTICE Keep in sync with getDataForFiber() function shouldFilterFiber(fiber: Fiber): boolean { const { tag } = fiber; @@ -2288,5 +2313,6 @@ export function attach( setTrackedPath, startProfiling, stopProfiling, + updateFilterPreferences, }; } diff --git a/src/backend/types.js b/src/backend/types.js index ae5f395ba2..a12dda6292 100644 --- a/src/backend/types.js +++ b/src/backend/types.js @@ -1,6 +1,6 @@ // @flow -import type { ElementType } from 'src/types'; +import type { ElementType, FilterPreferences } from 'src/types'; import type { InspectedElement } from 'src/devtools/views/Components/types'; type BundleType = @@ -139,6 +139,7 @@ export type RendererInterface = { setTrackedPath: (path: Array | null) => void, startProfiling: () => void, stopProfiling: () => void, + updateFilterPreferences: (filterPreferences: FilterPreferences) => void, }; export type Handler = (data: any) => void; diff --git a/src/devtools/store.js b/src/devtools/store.js index 4752818f67..3e6a409d65 100644 --- a/src/devtools/store.js +++ b/src/devtools/store.js @@ -247,8 +247,10 @@ export default class Store extends EventEmitter { saveFilterPreferences(value); - // TODO (filter) Dump all nodes, update renderer preferences, and re-initialize tree. + // TODO (filter) Dump all nodes, update renderer preferences, and re-initialize tree. // TODO (filter) Invariant check that we aren't profiling. + // TODO (filter) Flushing every time a filter setting is changed is too expensive. We probably need an explitit configm + this._bridge.send('updateFilterPreferences', value); this.emit('filterPreferences'); }