/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/
/**
* WARNING:
* This file contains types that are designed for React DevTools UI and how it interacts with the backend.
* They might be used in different versions of DevTools backends.
* Be mindful of backwards compatibility when making changes.
*/
import type {Source} from 'shared/ReactElementType';
import type {
Dehydrated,
Unserializable,
} from 'react-devtools-shared/src/hydration';
export type BrowserTheme = 'dark' | 'light';
export type Wall = {
// `listen` returns the "unlisten" function.
listen: (fn: Function) => Function,
send: (event: string, payload: any, transferable?: Array<any>) => void,
};
// WARNING
// The values below are referenced by ComponentFilters (which are saved via localStorage).
// Do not change them or it will break previously saved user customizations.
// If new element types are added, use new numbers rather than re-ordering existing ones.
//
// Changing these types is also a backwards breaking change for the standalone shell,
// since the frontend and backend must share the same values-
// and the backend is embedded in certain environments (like React Native).
export const ElementTypeClass = 1;
export const ElementTypeContext = 2;
export const ElementTypeFunction = 5;
export const ElementTypeForwardRef = 6;
export const ElementTypeHostComponent = 7;
export const ElementTypeMemo = 8;
export const ElementTypeOtherOrUnknown = 9;
export const ElementTypeProfiler = 10;
export const ElementTypeRoot = 11;
export const ElementTypeSuspense = 12;
export const ElementTypeSuspenseList = 13;
export const ElementTypeTracingMarker = 14;
// Different types of elements displayed in the Elements tree.
// These types may be used to visually distinguish types,
// or to enable/disable certain functionality.
export type ElementType = 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14;
// WARNING
// The values below are referenced by ComponentFilters (which are saved via localStorage).
// Do not change them or it will break previously saved user customizations.
// If new filter types are added, use new numbers rather than re-ordering existing ones.
export const ComponentFilterElementType = 1;
export const ComponentFilterDisplayName = 2;
export const ComponentFilterLocation = 3;
export const ComponentFilterHOC = 4;
export type ComponentFilterType = 1 | 2 | 3 | 4;
// Hide all elements of types in this Set.
// We hide host components only by default.
export type ElementTypeComponentFilter = {
isEnabled: boolean,
type: 1,
value: ElementType,
};
// Hide all elements with displayNames or paths matching one or more of the RegExps in this Set.
// Path filters are only used when elements include debug source location.
export type RegExpComponentFilter = {
isEnabled: boolean,
isValid: boolean,
type: 2 | 3,
value: string,
};
export type BooleanComponentFilter = {
isEnabled: boolean,
isValid: boolean,
type: 4,
};
export type ComponentFilter =
| BooleanComponentFilter
| ElementTypeComponentFilter
| RegExpComponentFilter;
export type HookName = string | null;
// Map of hook source ("<filename>:<line-number>:<column-number>") to name.
// Hook source is used instead of the hook itself because the latter is not stable between element inspections.
// We use a Map rather than an Array because of nested hooks and traversal ordering.
export type HookSourceLocationKey = string;
export type HookNames = Map<HookSourceLocationKey, HookName>;
export type LRUCache<K, V> = {
del: (key: K) => void,
get: (key: K) => V,
has: (key: K) => boolean,
reset: () => void,
set: (key: K, value: V) => void,
};
export type StyleXPlugin = {
sources: Array<string>,
resolvedStyles: Object,
};
export type Plugins = {
stylex: StyleXPlugin | null,
};
export const StrictMode = 1;
// Each element on the frontend corresponds to a Fiber on the backend.
// Some of its information (e.g. id, type, displayName) come from the backend.
// Other bits (e.g. weight and depth) are computed on the frontend for windowing and display purposes.
// Elements are updated on a push basis– meaning the backend pushes updates to the frontend when needed.
export type Element = {
id: number,
parentID: number,
children: Array<number>,
type: ElementType,
displayName: string | null,
key: number | string | null,
hocDisplayNames: null | Array<string>,
// Should the elements children be visible in the tree?
isCollapsed: boolean,
// Owner (if available)
ownerID: number,
// How many levels deep within the tree is this element?
// This determines how much indentation (left padding) should be used in the Elements tree.
depth: number,
// How many nodes (including itself) are below this Element within the tree.
// This property is used to quickly determine the total number of Elements,
// and the Element at any given index (for windowing purposes).
weight: number,
// This element is not in a StrictMode compliant subtree.
// Only true for React versions supporting StrictMode.
isStrictModeNonCompliant: boolean,
};
export type SerializedElement = {
displayName: string | null,
id: number,
key: number | string | null,
hocDisplayNames: Array<string> | null,
type: ElementType,
};
export type OwnersList = {
id: number,
owners: Array<SerializedElement> | null,
};
export type InspectedElementResponseType =
| 'error'
| 'full-data'
| 'hydrated-path'
| 'no-change'
| 'not-found';
export type InspectedElementPath = Array<string | number>;
export type InspectedElement = {
id: number,
// Does the current renderer support editable hooks and function props?
canEditHooks: boolean,
canEditFunctionProps: boolean,
// Does the current renderer support advanced editing interface?
canEditHooksAndDeletePaths: boolean,
canEditHooksAndRenamePaths: boolean,
canEditFunctionPropsDeletePaths: boolean,
canEditFunctionPropsRenamePaths: boolean,
// Is this Error, and can its value be overridden now?
isErrored: boolean,
canToggleError: boolean,
targetErrorBoundaryID: ?number,
// Is this Suspense, and can its value be overridden now?
canToggleSuspense: boolean,
// Can view component source location.
canViewSource: boolean,
// Does the component have legacy context attached to it.
hasLegacyContext: boolean,
// Inspectable properties.
context: Object | null,
hooks: Object | null,
props: Object | null,
state: Object | null,
key: number | string | null,
errors: Array<[string, number]>,
warnings: Array<[string, number]>,
// List of owners
owners: Array<SerializedElement> | null,
// Location of component in source code.
source: Source | null,
type: ElementType,
// Meta information about the root this element belongs to.
rootType: string | null,
// Meta information about the renderer that created this element.
rendererPackageName: string | null,
rendererVersion: string | null,
// UI plugins/visualizations for the inspected element.
plugins: Plugins,
};
// TODO: Add profiling type
type Data =
| string
| Dehydrated
| Unserializable
| Array<Dehydrated>
| Array<Unserializable>
| {[string]: Data};
export type DehydratedData = {
cleaned: Array<Array<string | number>>,
data: Data,
unserializable: Array<Array<string | number>>,
};