Match-id-58a32cd0f1a9a827dc84ad9a30326c16ae0d7417
This commit is contained in:
parent
a58338f11d
commit
a0a5f1470a
|
@ -6,11 +6,14 @@ import {
|
||||||
RequestComponentAttrs,
|
RequestComponentAttrs,
|
||||||
ComponentAttrs,
|
ComponentAttrs,
|
||||||
DevToolHook,
|
DevToolHook,
|
||||||
DevToolContentScript, ModifyAttrs, ModifyHooks, ModifyState,
|
DevToolContentScript,
|
||||||
|
ModifyAttrs,
|
||||||
|
ModifyHooks,
|
||||||
|
ModifyState,
|
||||||
|
ModifyProps,
|
||||||
} from '../utils/constants';
|
} from '../utils/constants';
|
||||||
import { VNode } from '../../../horizon/src/renderer/vnode/VNode';
|
import { VNode } from '../../../horizon/src/renderer/vnode/VNode';
|
||||||
import { parseVNodeAttrs } from '../parser/parseAttr';
|
import { parseVNodeAttrs } from '../parser/parseAttr';
|
||||||
import { Reducer } from '../../../horizon/src/renderer/hooks/HookType';
|
|
||||||
|
|
||||||
const roots = [];
|
const roots = [];
|
||||||
|
|
||||||
|
@ -22,7 +25,7 @@ function addIfNotInclude(treeRoot: VNode) {
|
||||||
|
|
||||||
function send() {
|
function send() {
|
||||||
const result = roots.reduce((pre, current) => {
|
const result = roots.reduce((pre, current) => {
|
||||||
const info = parseTreeRoot(current);
|
const info = parseTreeRoot(helper.travelVNodeTree ,current);
|
||||||
pre.push(info);
|
pre.push(info);
|
||||||
return pre;
|
return pre;
|
||||||
}, []);
|
}, []);
|
||||||
|
@ -55,6 +58,34 @@ function parseCompAttrs(id: number) {
|
||||||
postMessage(ComponentAttrs, parsedAttrs);
|
postMessage(ComponentAttrs, parsedAttrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function calculateNextValue(editValue, value, attrPath) {
|
||||||
|
let nextState;
|
||||||
|
const editValueType = typeof editValue;
|
||||||
|
if (editValueType === 'string' || editValueType === 'undefined' || editValueType === 'boolean') {
|
||||||
|
nextState = value;
|
||||||
|
} else if (editValueType === 'number') {
|
||||||
|
const numValue = Number(value);
|
||||||
|
nextState = isNaN(numValue) ? value : numValue; // 如果能转为数字,转数字,不能转数字,用原值
|
||||||
|
} else if(editValueType === 'object') {
|
||||||
|
if (editValue === null) {
|
||||||
|
nextState = value;
|
||||||
|
} else {
|
||||||
|
const newValue = Array.isArray(editValue) ? [...editValue] : {...editValue};
|
||||||
|
// 遍历读取到直接指向需要修改值的对象
|
||||||
|
let attr = newValue;
|
||||||
|
for(let i = 0; i < attrPath.length - 1; i++) {
|
||||||
|
attr = attr[attrPath[i]];
|
||||||
|
}
|
||||||
|
// 修改对象上的值
|
||||||
|
attr[attrPath[attrPath.length - 1]] = value;
|
||||||
|
nextState = newValue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error('The devTool tried to edit a non-editable value, this is a bug, please report', editValue);
|
||||||
|
}
|
||||||
|
return nextState;
|
||||||
|
}
|
||||||
|
|
||||||
function modifyVNodeAttrs(data) {
|
function modifyVNodeAttrs(data) {
|
||||||
const {type, id, value, path} = data;
|
const {type, id, value, path} = data;
|
||||||
const vNode = queryVNode(id);
|
const vNode = queryVNode(id);
|
||||||
|
@ -62,49 +93,39 @@ function modifyVNodeAttrs(data) {
|
||||||
console.error('Do not find match vNode, this is a bug, please report us');
|
console.error('Do not find match vNode, this is a bug, please report us');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (type === ModifyHooks) {
|
if (type === ModifyProps) {
|
||||||
|
const nextProps = calculateNextValue(vNode.props, value, path);
|
||||||
|
helper.updateProps(vNode, nextProps);
|
||||||
|
} else if (type === ModifyHooks) {
|
||||||
const hooks = vNode.hooks;
|
const hooks = vNode.hooks;
|
||||||
const editHook = hooks[path[0]];
|
const editHook = hooks[path[0]];
|
||||||
if ((editHook.state as Reducer<any, any>).trigger) {
|
const hookInfo = helper.getHookInfo(editHook);
|
||||||
const editState = editHook.state as Reducer<any, any>;
|
if (hookInfo) {
|
||||||
const editValue = editState.stateValue;
|
const editValue = hookInfo.value;
|
||||||
const editValueType = typeof editValue;
|
// path 的第一个值指向 hIndex,从第二个值才开始指向具体属性访问路径
|
||||||
if (editValueType === 'string') {
|
const nextState = calculateNextValue(editValue, value, path.slice(1));
|
||||||
editState.trigger(value);
|
helper.updateHooks(vNode, path[0], nextState);
|
||||||
} else if (editValueType === 'number') {
|
} else {
|
||||||
const numValue = Number(value);
|
console.error('The devTool tried to edit a non-editable hook, this is a bug, please report', hooks);
|
||||||
const targetValue = isNaN(numValue) ? value : numValue; // 如果能转为数字,转数字,不能转数字,用原值
|
|
||||||
editState.trigger(targetValue);
|
|
||||||
} else if(editValueType === 'object') {
|
|
||||||
if (editValue === null) {
|
|
||||||
editState.trigger(value);
|
|
||||||
} else {
|
|
||||||
const newValue = {...editValue};
|
|
||||||
// 遍历读取到直接指向需要修改值的对象
|
|
||||||
const attrPath = path.slice(1);
|
|
||||||
let attr = newValue;
|
|
||||||
for(let i = 0; i < attrPath.length - 1; i++) {
|
|
||||||
attr = attr[attrPath[i]];
|
|
||||||
}
|
|
||||||
// 修改对象上的值
|
|
||||||
attr[attrPath[attrPath.length - 1]] = value;
|
|
||||||
editState.trigger(newValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if (type === ModifyState) {
|
} else if (type === ModifyState) {
|
||||||
const instance = vNode.realNode;
|
const oldState = vNode.state || {};
|
||||||
const oldState = instance.state || {};
|
const nextState = {...oldState};
|
||||||
const nextState = Object.assign({}, oldState);
|
|
||||||
let accessRef = nextState;
|
let accessRef = nextState;
|
||||||
for(let i = 0; i < path.length - 1; i++) {
|
for(let i = 0; i < path.length - 1; i++) {
|
||||||
accessRef = accessRef[path[i]];
|
accessRef = accessRef[path[i]];
|
||||||
}
|
}
|
||||||
accessRef[path[path.length - 1]] = value;
|
accessRef[path[path.length - 1]] = value;
|
||||||
instance.setState(nextState);
|
helper.updateState(vNode, nextState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let helper;
|
||||||
|
|
||||||
|
function init(horizonHelper) {
|
||||||
|
helper = horizonHelper;
|
||||||
|
}
|
||||||
|
|
||||||
function injectHook() {
|
function injectHook() {
|
||||||
if (window.__HORIZON_DEV_HOOK__) {
|
if (window.__HORIZON_DEV_HOOK__) {
|
||||||
return;
|
return;
|
||||||
|
@ -112,6 +133,7 @@ function injectHook() {
|
||||||
Object.defineProperty(window, '__HORIZON_DEV_HOOK__', {
|
Object.defineProperty(window, '__HORIZON_DEV_HOOK__', {
|
||||||
enumerable: false,
|
enumerable: false,
|
||||||
value: {
|
value: {
|
||||||
|
init,
|
||||||
addIfNotInclude,
|
addIfNotInclude,
|
||||||
send,
|
send,
|
||||||
deleteVNode,
|
deleteVNode,
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import { travelVNodeTree } from '../../../horizon/src/renderer/vnode/VNodeUtils';
|
|
||||||
import { VNode } from '../../../horizon/src/renderer/vnode/VNode';
|
import { VNode } from '../../../horizon/src/renderer/vnode/VNode';
|
||||||
import { ClassComponent, FunctionComponent } from '../../../horizon/src/renderer/vnode/VNodeTags';
|
import { ClassComponent, FunctionComponent } from '../../../horizon/src/renderer/vnode/VNodeTags';
|
||||||
|
|
||||||
|
@ -32,7 +31,7 @@ function getParentUserComponent(node: VNode) {
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseTreeRoot(treeRoot: VNode) {
|
function parseTreeRoot(travelVNodeTree, treeRoot: VNode) {
|
||||||
const result: any[] = [];
|
const result: any[] = [];
|
||||||
travelVNodeTree(treeRoot, (node: VNode) => {
|
travelVNodeTree(treeRoot, (node: VNode) => {
|
||||||
const tag = node.tag;
|
const tag = node.tag;
|
||||||
|
@ -57,7 +56,7 @@ function parseTreeRoot(treeRoot: VNode) {
|
||||||
VNodeToIdMap.set(node, id);
|
VNodeToIdMap.set(node, id);
|
||||||
IdToVNodeMap.set(id, node);
|
IdToVNodeMap.set(id, node);
|
||||||
}
|
}
|
||||||
}, null, treeRoot, null);
|
});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ import { createContext } from './src/renderer/components/context/CreateContext';
|
||||||
import { lazy } from './src/renderer/components/Lazy';
|
import { lazy } from './src/renderer/components/Lazy';
|
||||||
import { forwardRef } from './src/renderer/components/ForwardRef';
|
import { forwardRef } from './src/renderer/components/ForwardRef';
|
||||||
import { memo } from './src/renderer/components/Memo';
|
import { memo } from './src/renderer/components/Memo';
|
||||||
|
import './src/external/devtools';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
useCallback,
|
useCallback,
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
import { travelVNodeTree } from '../renderer/vnode/VNodeUtils';
|
||||||
|
import { Hook, Reducer, Ref } from '../renderer/hooks/HookType';
|
||||||
|
import { VNode } from '../renderer/vnode/VNode';
|
||||||
|
import { launchUpdateFromVNode } from '../renderer/TreeBuilder';
|
||||||
|
|
||||||
|
export const helper = {
|
||||||
|
travelVNodeTree: (rootVNode, fun) => {
|
||||||
|
travelVNodeTree(rootVNode, fun, null, rootVNode, null);
|
||||||
|
},
|
||||||
|
// 获取 hook 名,hIndex值和存储的值
|
||||||
|
// 目前只处理 useState和useRef
|
||||||
|
getHookInfo:(hook: Hook<any, any>) => {
|
||||||
|
const { hIndex, state } = hook;
|
||||||
|
if ((state as Reducer<any, any>).trigger) {
|
||||||
|
if ((state as Reducer<any, any>).isUseState) {
|
||||||
|
return {name: 'state', hIndex, value: (state as Reducer<any, any>).stateValue};
|
||||||
|
}
|
||||||
|
} else if ((state as Ref<any>).current) {
|
||||||
|
return {name: 'ref', hIndex, value: (state as Ref<any>).current};
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
updateProps: (vNode: VNode, props: any) =>{
|
||||||
|
vNode.devProps = props;
|
||||||
|
launchUpdateFromVNode(vNode);
|
||||||
|
},
|
||||||
|
updateState: (vNode: VNode, nextState) => {
|
||||||
|
const instance = vNode.realNode;
|
||||||
|
instance.setState(nextState);
|
||||||
|
},
|
||||||
|
updateHooks: (vNode: VNode, hIndex, nextState) => {
|
||||||
|
const hooks = vNode.hooks;
|
||||||
|
if (hooks) {
|
||||||
|
const editHook = hooks[hIndex];
|
||||||
|
const editState = editHook.state as Reducer<any, any>;
|
||||||
|
// 暂时只支持更新 useState 的值
|
||||||
|
if (editState.trigger && editState.isUseState) {
|
||||||
|
editState.trigger(nextState);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error('Target vNode is not a hook vNode: ', vNode);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function injectUpdater() {
|
||||||
|
const hook = window.__HORIZON_DEV_HOOK__;
|
||||||
|
if (hook) {
|
||||||
|
hook.init(helper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
injectUpdater();
|
|
@ -236,7 +236,11 @@ function buildVNodeTree(treeRoot: VNode) {
|
||||||
|
|
||||||
// 重置环境变量,为重新进行深度遍历做准备
|
// 重置环境变量,为重新进行深度遍历做准备
|
||||||
resetProcessingVariables(startVNode);
|
resetProcessingVariables(startVNode);
|
||||||
|
// devProps 用于插件手动更新props值
|
||||||
|
if (startVNode.devProps !== undefined) {
|
||||||
|
startVNode.props = startVNode.devProps;
|
||||||
|
startVNode.devProps = undefined;
|
||||||
|
}
|
||||||
while (processing !== null) {
|
while (processing !== null) {
|
||||||
try {
|
try {
|
||||||
while (processing !== null) {
|
while (processing !== null) {
|
||||||
|
|
|
@ -70,7 +70,7 @@ export class VNode {
|
||||||
oldRef: RefType | ((handle: any) => void) | null = null;
|
oldRef: RefType | ((handle: any) => void) | null = null;
|
||||||
oldChild: VNode | null = null;
|
oldChild: VNode | null = null;
|
||||||
promiseResolve: boolean; // suspense的promise是否resolve
|
promiseResolve: boolean; // suspense的promise是否resolve
|
||||||
|
devProps: any; // 用于dev插件临时保存更新props值
|
||||||
suspenseState: SuspenseState;
|
suspenseState: SuspenseState;
|
||||||
|
|
||||||
path = ''; // 保存从根到本节点的路径
|
path = ''; // 保存从根到本节点的路径
|
||||||
|
|
Loading…
Reference in New Issue