diff --git a/libs/horizon/src/external/devtools.ts b/libs/horizon/src/external/devtools.ts index 10e70e80..1bc367ba 100644 --- a/libs/horizon/src/external/devtools.ts +++ b/libs/horizon/src/external/devtools.ts @@ -1,27 +1,37 @@ import { travelVNodeTree } from '../renderer/vnode/VNodeUtils'; -import { Hook, Reducer, Ref } from '../renderer/hooks/HookType'; +import { Hook, Reducer, Ref, Effect, CallBack } from '../renderer/hooks/HookType'; import { VNode } from '../renderer/vnode/VNode'; import { launchUpdateFromVNode } from '../renderer/TreeBuilder'; import { DomComponent } from '../renderer/vnode/VNodeTags'; +import { getElementTag } from '../renderer/vnode/VNodeCreator'; +import { JSXElement } from '../renderer/Types'; + +const isEffectHook = (state: any): state is Effect => !!state.effect; +const isRefHook = (state: any): state is Ref => state.hasOwnProperty('current'); +const isCallbackHook = (state: any): state is CallBack => state.func !== undefined; export const helper = { - travelVNodeTree: (rootVNode, fun) => { - travelVNodeTree(rootVNode, fun, null, rootVNode, null); + travelVNodeTree: (rootVNode, fun, childFilter: ((node: VNode) => boolean) | null = null) => { + travelVNodeTree(rootVNode, fun, childFilter, rootVNode, null); }, // 获取 hook 名,hIndex值和存储的值 - // 目前只处理 useState和useRef - getHookInfo:(hook: Hook) => { + getHookInfo: (hook: Hook) => { const { hIndex, state } = hook; if ((state as Reducer).trigger) { if ((state as Reducer).isUseState) { - return {name: 'state', hIndex, value: (state as Reducer).stateValue}; + return { name: 'State', hIndex, value: (state as Reducer).stateValue }; } - } else if ((state as Ref).current) { - return {name: 'ref', hIndex, value: (state as Ref).current}; + } else if (isRefHook(state)) { + return { name: 'Ref', hIndex, value: (state as Ref).current }; + } else if (isEffectHook(state)) { + const name = state.effectConstant == 2 ? 'LayoutEffect' : 'Effect'; + return { name, hIndex, value: (state as Effect).effect }; + } else if (isCallbackHook(state)) { + return { name:'Callback', hIndex, value: (state as CallBack).func }; } return null; }, - updateProps: (vNode: VNode, props: any) =>{ + updateProps: (vNode: VNode, props: any) => { vNode.devProps = props; launchUpdateFromVNode(vNode); }, @@ -44,7 +54,7 @@ export const helper = { }, getComponentInfo: (vNode: VNode) => { const { props, state, hooks } = vNode; - const info:any = {}; + const info: any = {}; if (props && Object.keys(props).length !== 0) { info['Props'] = props; } @@ -53,7 +63,7 @@ export const helper = { } if (hooks && hooks.length !== 0) { const logHookInfo: any[] = []; - hooks.forEach((hook) =>{ + hooks.forEach((hook) => { const state = hook.state as Reducer; if (state.trigger && state.isUseState) { logHookInfo.push(state.stateValue); @@ -72,6 +82,9 @@ export const helper = { }, null, vNode, null); return info; }, + getElementTag: (element: JSXElement) => { + return getElementTag(element); + } }; export function injectUpdater() { diff --git a/libs/horizon/src/renderer/hooks/HookType.ts b/libs/horizon/src/renderer/hooks/HookType.ts index e965fdf1..dce9e1c8 100644 --- a/libs/horizon/src/renderer/hooks/HookType.ts +++ b/libs/horizon/src/renderer/hooks/HookType.ts @@ -1,5 +1,5 @@ import {EffectConstant} from './EffectConstant'; - +type ValueOf = T[keyof T]; export interface Hook { state: Reducer | Effect | Memo | CallBack | Ref; hIndex: number; @@ -25,7 +25,7 @@ export type Effect = { effect: () => (() => void) | void; removeEffect: (() => void) | void; dependencies: Array | null; - effectConstant: typeof EffectConstant; + effectConstant: ValueOf; }; export type Memo = { diff --git a/libs/horizon/src/renderer/vnode/VNodeCreator.ts b/libs/horizon/src/renderer/vnode/VNodeCreator.ts index 8b7ad630..c5b4c306 100644 --- a/libs/horizon/src/renderer/vnode/VNodeCreator.ts +++ b/libs/horizon/src/renderer/vnode/VNodeCreator.ts @@ -132,6 +132,31 @@ export function createUndeterminedVNode(type, key, props) { return vNode; } +export function getElementTag(element: JSXElement): string { + const type = element.type; + + if (type === TYPE_STRICT_MODE || type === TYPE_FRAGMENT || type === TYPE_PROFILER) { + return Fragment; + } else { + let vNodeTag = FunctionComponent; + const componentType = typeof type; + + if (componentType === 'function') { + if (isClassComponent(type)) { + vNodeTag = ClassComponent; + } + } else if (componentType === 'string') { + vNodeTag = DomComponent; + } else if (type === TYPE_SUSPENSE) { + vNodeTag = SuspenseComponent; + } else if (componentType === 'object' && type !== null && typeMap[type.vtype]) { + vNodeTag = typeMap[type.vtype]; + } + + return vNodeTag; + } +} + export function createTreeRootVNode(container) { const vNode = newVirtualNode(TreeRoot, null, null, container); vNode.path = '0';