diff --git a/src/backend/renderer.js b/src/backend/renderer.js index f700bbf8be..2c353d4ace 100644 --- a/src/backend/renderer.js +++ b/src/backend/renderer.js @@ -40,7 +40,10 @@ import type { ReactRenderer, RendererInterface, } from './types'; -import type { InspectedElement } from 'src/devtools/views/Components/types'; +import type { + InspectedElement, + InspectedElementResponse, +} from 'src/devtools/views/Components/types'; function getInternalReactConstants(version) { const ReactSymbols = { @@ -1649,27 +1652,30 @@ export function attach( let inspectedElementID: number | null = null; let hasInspectedElementChanged: boolean = false; - function inspectElement(id: number): InspectedElement | null { + function inspectElement(id: number): InspectedElementResponse | null { if (inspectedElementID === id && !hasInspectedElementChanged) { // Optimization: Don't resend (and reserialize) unchanged props. - return null; + return { + id, + inspectedElement: null, + }; } inspectedElementID = id; hasInspectedElementChanged = false; - let result = inspectElementRaw(id); - if (result === null) { + let inspectedElement = inspectElementRaw(id); + if (inspectedElement === null) { return null; } // TODO Review sanitization approach for the below inspectable values. - result.context = cleanForBridge(result.context); - result.hooks = cleanForBridge(result.hooks); - result.props = cleanForBridge(result.props); - result.state = cleanForBridge(result.state); + inspectedElement.context = cleanForBridge(inspectedElement.context); + inspectedElement.hooks = cleanForBridge(inspectedElement.hooks); + inspectedElement.props = cleanForBridge(inspectedElement.props); + inspectedElement.state = cleanForBridge(inspectedElement.state); - return result; + return { id, inspectedElement }; } function logElementToConsole(id) { diff --git a/src/backend/types.js b/src/backend/types.js index bd4562eef7..93b283cd21 100644 --- a/src/backend/types.js +++ b/src/backend/types.js @@ -1,7 +1,7 @@ // @flow import type { ElementType } from 'src/devtools/types'; -import type { InspectedElement } from 'src/devtools/views/Components/types'; +import type { InspectedElementResponse } from 'src/devtools/views/Components/types'; type BundleType = | 0 // PROD @@ -105,7 +105,7 @@ export type RendererInterface = { getProfilingSummary: (rootID: number) => ProfilingSummary, handleCommitFiberRoot: (fiber: Object) => void, handleCommitFiberUnmount: (fiber: Object) => void, - inspectElement: (id: number) => InspectedElement | null, + inspectElement: (id: number) => InspectedElementResponse | null, logElementToConsole: (id: number) => void, overrideSuspense: (id: number, forceFallback: boolean) => void, prepareViewElementSource: (id: number) => void, diff --git a/src/devtools/views/Components/InspectedElementContext.js b/src/devtools/views/Components/InspectedElementContext.js index ec6619fa0a..0ef21d598b 100644 --- a/src/devtools/views/Components/InspectedElementContext.js +++ b/src/devtools/views/Components/InspectedElementContext.js @@ -15,6 +15,7 @@ import { TreeStateContext } from './TreeContext'; import type { DehydratedData, InspectedElement, + InspectedElementResponse, } from 'src/devtools/views/Components/types'; import type { Resource } from '../../cache'; @@ -70,29 +71,32 @@ function InspectedElementContextController({ children }: Props) { // This effect handler invalidates the suspense cache and schedules rendering updates with React. useEffect(() => { const onInspectedElement = ( - inspectedElementRaw: InspectedElement | null + inspectedElementResponse: InspectedElementResponse | null ) => { - if (inspectedElementRaw != null) { - const id = inspectedElementRaw.id; + if (inspectedElementResponse != null) { + let { inspectedElement } = inspectedElementResponse; + if (inspectedElement !== null) { + const id = inspectedElement.id; - const inspectedElement = (({ - ...inspectedElementRaw, - context: hydrateHelper(inspectedElementRaw.context), - hooks: hydrateHelper(inspectedElementRaw.hooks), - props: hydrateHelper(inspectedElementRaw.props), - state: hydrateHelper(inspectedElementRaw.state), - }: any): InspectedElement); + inspectedElement = (({ + ...inspectedElement, + context: hydrateHelper(inspectedElement.context), + hooks: hydrateHelper(inspectedElement.hooks), + props: hydrateHelper(inspectedElement.props), + state: hydrateHelper(inspectedElement.state), + }: any): InspectedElement); - const request = inProgressRequests.get(id); - if (request != null) { - inProgressRequests.delete(id); - request.resolveFn(inspectedElement); - } else { - resource.write(id, inspectedElement); + const request = inProgressRequests.get(id); + if (request != null) { + inProgressRequests.delete(id); + request.resolveFn(inspectedElement); + } else { + resource.write(id, inspectedElement); - // Schedule update with React if the curently-selected element has been invalidated. - if (id === selectedElementID) { - setCount(count => count + 1); + // Schedule update with React if the curently-selected element has been invalidated. + if (id === selectedElementID) { + setCount(count => count + 1); + } } } } @@ -122,10 +126,12 @@ function InspectedElementContextController({ children }: Props) { // We'll poll for an update in the response handler below. sendRequest(); - const onInspectedElement = (inspectedElement: InspectedElement | null) => { + const onInspectedElement = ( + inspectedElementResponse: InspectedElementResponse | null + ) => { if ( - inspectedElement !== null && - inspectedElement.id === selectedElementID + inspectedElementResponse !== null && + inspectedElementResponse.id === selectedElementID ) { // If this is the element we requested, wait a little bit and then ask for an update. timeoutID = setTimeout(sendRequest, 1000); diff --git a/src/devtools/views/Components/types.js b/src/devtools/views/Components/types.js index ca3c7e3df0..9953834f6b 100644 --- a/src/devtools/views/Components/types.js +++ b/src/devtools/views/Components/types.js @@ -65,6 +65,11 @@ export type InspectedElement = {| source: Object | null, |}; +export type InspectedElementResponse = {| + id: number, + inspectedElement: InspectedElement | null, +|}; + // TODO: Add profiling type export type DehydratedData = {|