Differentiate between no-change and no-element-found when inspecting element

This commit is contained in:
Brian Vaughn
2019-04-22 15:37:55 -07:00
parent 00872e2e51
commit 7f1531044b
4 changed files with 51 additions and 34 deletions
+16 -10
View File
@@ -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) {
+2 -2
View File
@@ -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,
@@ -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);
+5
View File
@@ -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 = {|