Match-id-99f806dad998480fee636e60f23301318cbd3216
This commit is contained in:
commit
6b136c517a
|
@ -1,7 +1,7 @@
|
|||
import {throwIfTrue} from '../renderer/utils/throwIfTrue';
|
||||
import {TYPE_COMMON_ELEMENT, TYPE_PORTAL} from './JSXElementType';
|
||||
import { throwIfTrue } from '../renderer/utils/throwIfTrue';
|
||||
import { TYPE_COMMON_ELEMENT, TYPE_PORTAL } from './JSXElementType';
|
||||
|
||||
import {isValidElement, JSXElement} from './JSXElement';
|
||||
import { isValidElement, JSXElement } from './JSXElement';
|
||||
|
||||
// 生成key
|
||||
function getItemKey(item: any, index: number): string {
|
||||
|
@ -12,12 +12,7 @@ function getItemKey(item: any, index: number): string {
|
|||
return '.' + index.toString(36);
|
||||
}
|
||||
|
||||
function mapChildrenToArray(
|
||||
children: any,
|
||||
arr: Array<any>,
|
||||
prefix: string,
|
||||
callback?: Function,
|
||||
): number | void {
|
||||
function mapChildrenToArray(children: any, arr: Array<any>, prefix: string, callback?: Function): number | void {
|
||||
const type = typeof children;
|
||||
switch (type) {
|
||||
// 继承原有规格,undefined和boolean类型按照null处理
|
||||
|
@ -36,44 +31,27 @@ function mapChildrenToArray(
|
|||
}
|
||||
const vtype = children.vtype;
|
||||
if (vtype === TYPE_COMMON_ELEMENT || vtype === TYPE_PORTAL) {
|
||||
callMapFun(children, arr, prefix, callback) ;
|
||||
callMapFun(children, arr, prefix, callback);
|
||||
return;
|
||||
}
|
||||
if (Array.isArray(children)) {
|
||||
processArrayChildren(children, arr, prefix, callback);
|
||||
return;
|
||||
}
|
||||
throw new Error(
|
||||
'Object is invalid as a Horizon child. '
|
||||
);
|
||||
throw new Error('Object is invalid as a Horizon child. ');
|
||||
// No Default
|
||||
}
|
||||
}
|
||||
|
||||
function processArrayChildren(
|
||||
children: any,
|
||||
arr: Array<any>,
|
||||
prefix: string,
|
||||
callback: Function,
|
||||
) {
|
||||
function processArrayChildren(children: any, arr: Array<any>, prefix: string, callback: Function) {
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
const childItem = children[i];
|
||||
const nextPrefix = prefix + getItemKey(childItem, i);
|
||||
mapChildrenToArray(
|
||||
childItem,
|
||||
arr,
|
||||
nextPrefix,
|
||||
callback,
|
||||
);
|
||||
mapChildrenToArray(childItem, arr, nextPrefix, callback);
|
||||
}
|
||||
}
|
||||
|
||||
function callMapFun(
|
||||
children: any,
|
||||
arr: Array<any>,
|
||||
prefix: string,
|
||||
callback: Function,
|
||||
) {
|
||||
function callMapFun(children: any, arr: Array<any>, prefix: string, callback: Function) {
|
||||
let mappedChild = callback(children);
|
||||
if (Array.isArray(mappedChild)) {
|
||||
// 维持原有规格,如果callback返回结果是数组,处理函数修改为返回数组item
|
||||
|
@ -83,9 +61,8 @@ function callMapFun(
|
|||
if (isValidElement(mappedChild)) {
|
||||
const childKey = prefix === '' ? getItemKey(children, 0) : '';
|
||||
const mappedKey = getItemKey(mappedChild, 0);
|
||||
const newKey = prefix + childKey + (mappedChild.key && mappedKey !== getItemKey(children, 0)
|
||||
? '.$' + mappedChild.key
|
||||
: '');
|
||||
const newKey =
|
||||
prefix + childKey + (mappedChild.key && mappedKey !== getItemKey(children, 0) ? '.$' + mappedChild.key : '');
|
||||
// 返回一个修改key的children
|
||||
mappedChild = JSXElement(
|
||||
mappedChild.type,
|
||||
|
@ -93,6 +70,7 @@ function callMapFun(
|
|||
mappedChild.ref,
|
||||
mappedChild.belongClassVNode,
|
||||
mappedChild.props,
|
||||
mappedChild.src
|
||||
);
|
||||
}
|
||||
arr.push(mappedChild);
|
||||
|
@ -100,11 +78,7 @@ function callMapFun(
|
|||
}
|
||||
|
||||
// 在 children 里的每个直接子节点上调用一个函数,并将 this 设置为 thisArg
|
||||
function mapChildren(
|
||||
children: any,
|
||||
func: Function,
|
||||
context?: any,
|
||||
): Array<any> {
|
||||
function mapChildren(children: any, func: Function, context?: any): Array<any> {
|
||||
if (children === null || children === undefined) {
|
||||
return children;
|
||||
}
|
||||
|
@ -121,27 +95,22 @@ const Children = {
|
|||
},
|
||||
map: mapChildren,
|
||||
// 并非所有元素都会计数,只计数调用callMapFun函数次数
|
||||
count: (children) => {
|
||||
count: children => {
|
||||
let n = 0;
|
||||
mapChildren(children, () => {
|
||||
n++;
|
||||
});
|
||||
return n;
|
||||
},
|
||||
only: (children) => {
|
||||
throwIfTrue(
|
||||
!isValidElement(children),
|
||||
'Horizon.Children.only function received invalid element.'
|
||||
);
|
||||
only: children => {
|
||||
throwIfTrue(!isValidElement(children), 'Horizon.Children.only function received invalid element.');
|
||||
return children;
|
||||
},
|
||||
toArray: (children) => {
|
||||
toArray: children => {
|
||||
const result = [];
|
||||
mapChildrenToArray(children, result, '', child => child);
|
||||
return result;
|
||||
},
|
||||
}
|
||||
|
||||
export {
|
||||
Children
|
||||
};
|
||||
|
||||
export { Children };
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { TYPE_COMMON_ELEMENT } from './JSXElementType';
|
||||
import { getProcessingClassVNode } from '../renderer/GlobalVar';
|
||||
|
||||
import { Source } from '../renderer/Types';
|
||||
|
||||
/**
|
||||
* vtype 节点的类型,这里固定是element
|
||||
|
@ -9,10 +9,11 @@ import { getProcessingClassVNode } from '../renderer/GlobalVar';
|
|||
* ref ref属性
|
||||
* props 其他常规属性
|
||||
*/
|
||||
export function JSXElement(type, key, ref, vNode, props) {
|
||||
export function JSXElement(type, key, ref, vNode, props, source: Source | null) {
|
||||
return {
|
||||
// 元素标识符
|
||||
vtype: TYPE_COMMON_ELEMENT,
|
||||
src: isDev ? source : null,
|
||||
|
||||
// 属于元素的内置属性
|
||||
type: type,
|
||||
|
@ -26,7 +27,8 @@ export function JSXElement(type, key, ref, vNode, props) {
|
|||
}
|
||||
|
||||
function isValidKey(key) {
|
||||
return key !== 'key' && key !== 'ref' && key !== '__source';
|
||||
const keyArray = ['key', 'ref', '__source'];
|
||||
return !keyArray.includes(key);
|
||||
}
|
||||
|
||||
function mergeDefault(sourceObj, defaultObj) {
|
||||
|
@ -66,8 +68,15 @@ function buildElement(isClone, type, setting, children) {
|
|||
if (element && element.defaultProps) {
|
||||
mergeDefault(props, element.defaultProps);
|
||||
}
|
||||
let src: Source | null = null;
|
||||
if (setting?.__source) {
|
||||
src = {
|
||||
fileName: setting.__source.fileName,
|
||||
lineNumber: setting.__source.lineNumber,
|
||||
};
|
||||
}
|
||||
|
||||
return JSXElement(element, key, ref, vNode, props);
|
||||
return JSXElement(element, key, ref, vNode, props, src);
|
||||
}
|
||||
|
||||
// 创建Element结构体,供JSX编译时调用
|
||||
|
|
|
@ -1,12 +1,5 @@
|
|||
import { travelVNodeTree } from '../renderer/vnode/VNodeUtils';
|
||||
import {
|
||||
Hook,
|
||||
Reducer,
|
||||
Ref,
|
||||
Effect,
|
||||
CallBack,
|
||||
Memo
|
||||
} from '../renderer/hooks/HookType';
|
||||
import { Hook, Reducer, Ref, Effect, CallBack, Memo } from '../renderer/hooks/HookType';
|
||||
import { VNode } from '../renderer/vnode/VNode';
|
||||
import { launchUpdateFromVNode } from '../renderer/TreeBuilder';
|
||||
import { DomComponent } from '../renderer/vnode/VNodeTags';
|
||||
|
@ -26,7 +19,7 @@ const HookName = {
|
|||
MemoHook: 'Memo',
|
||||
RefHook: 'Ref',
|
||||
ReducerHook: 'Reducer',
|
||||
CallbackHook: 'Callback'
|
||||
CallbackHook: 'Callback',
|
||||
};
|
||||
|
||||
export const helper = {
|
||||
|
@ -45,7 +38,8 @@ export const helper = {
|
|||
} else if (isRefHook(state)) {
|
||||
return { name: HookName.RefHook, hIndex, value: (state as Ref<any>).current };
|
||||
} else if (isEffectHook(state)) {
|
||||
const name = state.effectConstant == EffectConstant.LayoutEffect ? HookName.LayoutEffectHook : HookName.EffectHook;
|
||||
const name =
|
||||
state.effectConstant == EffectConstant.LayoutEffect ? HookName.LayoutEffectHook : HookName.EffectHook;
|
||||
return { name, hIndex, value: (state as Effect).effect };
|
||||
} else if (isCallbackHook(state)) {
|
||||
return { name: HookName.CallbackHook, hIndex, value: (state as CallBack<any>).func };
|
||||
|
@ -86,7 +80,7 @@ export const helper = {
|
|||
}
|
||||
if (hooks && hooks.length !== 0) {
|
||||
const logHookInfo: any[] = [];
|
||||
hooks.forEach((hook) => {
|
||||
hooks.forEach(hook => {
|
||||
const state = hook.state as Reducer<any, any>;
|
||||
if (state.trigger && state.isUseState) {
|
||||
logHookInfo.push(state.stateValue);
|
||||
|
@ -94,20 +88,26 @@ export const helper = {
|
|||
});
|
||||
info['Hooks'] = logHookInfo;
|
||||
}
|
||||
travelVNodeTree(vNode, (node: VNode) => {
|
||||
if (node.tag === DomComponent) {
|
||||
// 找到组件的第一个dom元素,返回它所在父节点的全部子节点
|
||||
const dom = node.realNode;
|
||||
info['Nodes'] = dom?.parentNode?.childNodes;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}, null, vNode, null);
|
||||
travelVNodeTree(
|
||||
vNode,
|
||||
(node: VNode) => {
|
||||
if (node.tag === DomComponent) {
|
||||
// 找到组件的第一个dom元素,返回它所在父节点的全部子节点
|
||||
const dom = node.realNode;
|
||||
info['Nodes'] = dom?.parentNode?.childNodes;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
null,
|
||||
vNode,
|
||||
null
|
||||
);
|
||||
return info;
|
||||
},
|
||||
getElementTag: (element: JSXElement) => {
|
||||
return getElementTag(element);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export function injectUpdater() {
|
||||
|
|
|
@ -3,20 +3,16 @@ export { VNode } from './vnode/VNode';
|
|||
type Trigger<A> = (A) => void;
|
||||
|
||||
export type UseStateHookType = {
|
||||
useState<S>(
|
||||
initialState: (() => S) | S
|
||||
): [S, Trigger<((S) => S) | S>];
|
||||
useState<S>(initialState: (() => S) | S): [S, Trigger<((S) => S) | S>];
|
||||
};
|
||||
export type UseReducerHookType = {
|
||||
useReducer<S, P, A>(
|
||||
reducer: (S, A) => S,
|
||||
initArg: P, init?: (P) => S,
|
||||
): [S, Trigger<A>];
|
||||
useReducer<S, P, A>(reducer: (S, A) => S, initArg: P, init?: (P) => S): [S, Trigger<A>];
|
||||
};
|
||||
export type UseContextHookType = { useContext<T>(context: ContextType<T>,): T };
|
||||
export type UseContextHookType = { useContext<T>(context: ContextType<T>): T };
|
||||
|
||||
export type JSXElement = {
|
||||
vtype: any;
|
||||
src: any;
|
||||
type: any;
|
||||
key: any;
|
||||
ref: any;
|
||||
|
@ -31,8 +27,8 @@ export type ProviderType<T> = {
|
|||
|
||||
export type ContextType<T> = {
|
||||
vtype: number;
|
||||
Consumer: ContextType<T>;
|
||||
Provider: ProviderType<T>;
|
||||
Consumer: ContextType<T> | null;
|
||||
Provider: ProviderType<T> | null;
|
||||
value: T;
|
||||
};
|
||||
|
||||
|
@ -50,7 +46,7 @@ export type RefType = {
|
|||
export interface PromiseType<R> {
|
||||
then<U>(
|
||||
onFulfill: (value: R) => void | PromiseType<U> | U,
|
||||
onReject: (error: any) => void | PromiseType<U> | U,
|
||||
onReject: (error: any) => void | PromiseType<U> | U
|
||||
): void | PromiseType<U>;
|
||||
}
|
||||
|
||||
|
@ -61,3 +57,8 @@ export interface SuspenseState {
|
|||
didCapture: boolean; // suspense是否捕获了异常
|
||||
promiseResolved: boolean; // suspense的promise是否resolve
|
||||
}
|
||||
|
||||
export type Source = {
|
||||
fileName: string;
|
||||
lineNumber: number;
|
||||
};
|
||||
|
|
|
@ -1,21 +1,19 @@
|
|||
import type {VNode} from '../Types';
|
||||
import type { Source, VNode } from '../Types';
|
||||
|
||||
import {mergeDefaultProps} from './LazyComponent';
|
||||
import {updateVNode, onlyUpdateChildVNodes, createFragmentVNode, createUndeterminedVNode} from '../vnode/VNodeCreator';
|
||||
import {shallowCompare} from '../utils/compare';
|
||||
import { mergeDefaultProps } from './LazyComponent';
|
||||
import {
|
||||
TYPE_FRAGMENT,
|
||||
TYPE_PROFILER,
|
||||
TYPE_STRICT_MODE,
|
||||
} from '../../external/JSXElementType';
|
||||
updateVNode,
|
||||
onlyUpdateChildVNodes,
|
||||
createFragmentVNode,
|
||||
createUndeterminedVNode,
|
||||
} from '../vnode/VNodeCreator';
|
||||
import { shallowCompare } from '../utils/compare';
|
||||
import { TYPE_FRAGMENT, TYPE_PROFILER, TYPE_STRICT_MODE } from '../../external/JSXElementType';
|
||||
import { markVNodePath } from '../utils/vNodePath';
|
||||
|
||||
export function bubbleRender() {}
|
||||
|
||||
export function captureMemoComponent(
|
||||
processing: VNode,
|
||||
shouldUpdate: boolean,
|
||||
): VNode | null {
|
||||
export function captureMemoComponent(processing: VNode, shouldUpdate: boolean): VNode | null {
|
||||
const Component = processing.type;
|
||||
// 合并 函数组件或类组件 的defaultProps
|
||||
const newProps = mergeDefaultProps(Component, processing.props);
|
||||
|
@ -26,7 +24,7 @@ export function captureMemoComponent(
|
|||
if (type === TYPE_STRICT_MODE || type === TYPE_FRAGMENT || type === TYPE_PROFILER) {
|
||||
newChild = createFragmentVNode(null, newProps.children);
|
||||
} else {
|
||||
newChild = createUndeterminedVNode(type, null, newProps);
|
||||
newChild = createUndeterminedVNode(type, null, newProps, processing.src);
|
||||
}
|
||||
newChild.parent = processing;
|
||||
newChild.ref = processing.ref;
|
||||
|
|
|
@ -17,10 +17,10 @@ import {
|
|||
Profiler,
|
||||
MemoComponent,
|
||||
} from './VNodeTags';
|
||||
import type { VNodeTag } from './VNodeTags';
|
||||
import type { RefType, ContextType, SuspenseState } from '../Types';
|
||||
import type { Hook } from '../hooks/HookType';
|
||||
import { InitFlag } from './VNodeFlags';
|
||||
import type {VNodeTag} from './VNodeTags';
|
||||
import type {RefType, ContextType, SuspenseState, Source} from '../Types';
|
||||
import type {Hook} from '../hooks/HookType';
|
||||
import {InitFlag} from './VNodeFlags';
|
||||
|
||||
export class VNode {
|
||||
tag: VNodeTag;
|
||||
|
@ -77,8 +77,8 @@ export class VNode {
|
|||
|
||||
// 根节点数据
|
||||
toUpdateNodes: Set<VNode> | null; // 保存要更新的节点
|
||||
delegatedEvents: Set<string>
|
||||
delegatedNativeEvents: Set<string>
|
||||
delegatedEvents: Set<string>;
|
||||
delegatedNativeEvents: Set<string>;
|
||||
|
||||
belongClassVNode: VNode | null = null; // 记录JSXElement所属class vNode,处理ref的时候使用
|
||||
|
||||
|
@ -86,6 +86,7 @@ export class VNode {
|
|||
isStoreChange: boolean;
|
||||
observers: Set<any> | null = null; // 记录这个函数组件/类组件依赖哪些Observer
|
||||
classComponentWillUnmount: Function | null; // HorizonX会在classComponentWillUnmount中清除对VNode的引入用
|
||||
src: Source | null; // 节点所在代码位置
|
||||
|
||||
constructor(tag: VNodeTag, props: any, key: null | string, realNode) {
|
||||
this.tag = tag; // 对应组件的类型,比如ClassComponent等
|
||||
|
@ -116,6 +117,7 @@ export class VNode {
|
|||
this.isStoreChange = false;
|
||||
this.observers = null;
|
||||
this.classComponentWillUnmount = null;
|
||||
this.src = null;
|
||||
break;
|
||||
case ClassComponent:
|
||||
this.realNode = null;
|
||||
|
@ -130,15 +132,18 @@ export class VNode {
|
|||
this.isStoreChange = false;
|
||||
this.observers = null;
|
||||
this.classComponentWillUnmount = null;
|
||||
this.src = null;
|
||||
break;
|
||||
case DomPortal:
|
||||
this.realNode = null;
|
||||
this.context = null;
|
||||
this.src = null;
|
||||
break;
|
||||
case DomComponent:
|
||||
this.realNode = null;
|
||||
this.changeList = null;
|
||||
this.context = null;
|
||||
this.src = null;
|
||||
break;
|
||||
case DomText:
|
||||
this.realNode = null;
|
||||
|
@ -150,14 +155,17 @@ export class VNode {
|
|||
didCapture: false,
|
||||
promiseResolved: false,
|
||||
oldChildStatus: '',
|
||||
childStatus: ''
|
||||
childStatus: '',
|
||||
};
|
||||
this.src = null;
|
||||
break;
|
||||
case ContextProvider:
|
||||
this.src = null;
|
||||
this.context = null;
|
||||
break;
|
||||
case MemoComponent:
|
||||
this.effectList = null;
|
||||
this.src = null;
|
||||
break;
|
||||
case LazyComponent:
|
||||
this.realNode = null;
|
||||
|
@ -165,6 +173,7 @@ export class VNode {
|
|||
this.isLazyComponent = true;
|
||||
this.lazyType = null;
|
||||
this.updates = null;
|
||||
this.src = null;
|
||||
break;
|
||||
case Fragment:
|
||||
break;
|
||||
|
|
|
@ -17,14 +17,17 @@ import {
|
|||
} from './VNodeTags';
|
||||
import {
|
||||
TYPE_CONTEXT,
|
||||
TYPE_FORWARD_REF, TYPE_FRAGMENT,
|
||||
TYPE_FORWARD_REF,
|
||||
TYPE_FRAGMENT,
|
||||
TYPE_LAZY,
|
||||
TYPE_MEMO, TYPE_PROFILER,
|
||||
TYPE_PROVIDER, TYPE_STRICT_MODE,
|
||||
TYPE_MEMO,
|
||||
TYPE_PROFILER,
|
||||
TYPE_PROVIDER,
|
||||
TYPE_STRICT_MODE,
|
||||
TYPE_SUSPENSE,
|
||||
} from '../../external/JSXElementType';
|
||||
import { VNode } from './VNode';
|
||||
import { JSXElement } from '../Types';
|
||||
import { JSXElement, Source } from '../Types';
|
||||
import { markVNodePath } from '../utils/vNodePath';
|
||||
|
||||
const typeLazyMap = {
|
||||
|
@ -56,7 +59,7 @@ export function getLazyVNodeTag(lazyComp: any): string {
|
|||
} else if (lazyComp !== undefined && lazyComp !== null && typeLazyMap[lazyComp.vtype]) {
|
||||
return typeLazyMap[lazyComp.vtype];
|
||||
}
|
||||
throw Error('Horizon can\'t resolve the content of lazy');
|
||||
throw Error("Horizon can't resolve the content of lazy");
|
||||
}
|
||||
|
||||
// 创建processing
|
||||
|
@ -102,11 +105,10 @@ export function createPortalVNode(portal) {
|
|||
return vNode;
|
||||
}
|
||||
|
||||
export function createUndeterminedVNode(type, key, props) {
|
||||
export function createUndeterminedVNode(type, key, props, source: Source | null): VNode {
|
||||
let vNodeTag = FunctionComponent;
|
||||
let isLazy = false;
|
||||
const componentType = typeof type;
|
||||
|
||||
if (componentType === 'function') {
|
||||
if (isClassComponent(type)) {
|
||||
vNodeTag = ClassComponent;
|
||||
|
@ -129,6 +131,8 @@ export function createUndeterminedVNode(type, key, props) {
|
|||
if (isLazy) {
|
||||
vNode.lazyType = type;
|
||||
}
|
||||
|
||||
vNode.src = isDev ? source : null;
|
||||
return vNode;
|
||||
}
|
||||
|
||||
|
@ -181,14 +185,12 @@ export function createVNode(tag: VNodeTag | string, ...secondArg) {
|
|||
}
|
||||
|
||||
export function createVNodeFromElement(element: JSXElement): VNode {
|
||||
const type = element.type;
|
||||
const key = element.key;
|
||||
const props = element.props;
|
||||
const { type, key, props, src } = element;
|
||||
|
||||
if (type === TYPE_STRICT_MODE || type === TYPE_FRAGMENT || type === TYPE_PROFILER) {
|
||||
return createFragmentVNode(key, props.children);
|
||||
} else {
|
||||
return createUndeterminedVNode(type, key, props);
|
||||
return createUndeterminedVNode(type, key, props, src);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -241,4 +243,3 @@ export function onlyUpdateChildVNodes(processing: VNode): VNode | null {
|
|||
// 子树无需工作
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
"@babel/plugin-transform-shorthand-properties": "7.16.7",
|
||||
"@babel/plugin-transform-spread": "7.16.7",
|
||||
"@babel/plugin-transform-template-literals": "7.16.7",
|
||||
"@babel/plugin-transform-react-jsx-source": "^7.16.7",
|
||||
"@babel/preset-env": "7.16.7",
|
||||
"@babel/preset-typescript": "7.16.7",
|
||||
"@rollup/plugin-babel": "^5.3.1",
|
||||
|
|
Loading…
Reference in New Issue