Match-id-e5f256f484c40e75367de107774839a066267d89

This commit is contained in:
* 2022-02-17 14:09:18 +08:00 committed by *
commit 4795d103bd
12 changed files with 118 additions and 87 deletions

View File

@ -71,7 +71,7 @@ export function handleRenderThrowError(
// vNode抛出了异常标记Interrupted中断
FlagUtils.markInterrupted(sourceVNode);
// dirtyNodes 不再有效
sourceVNode.dirtyNodes = [];
sourceVNode.dirtyNodes = null;
// error是个promise
if (error !== null && typeof error === 'object' && typeof error.then === 'function') {

View File

@ -57,10 +57,23 @@ function resetProcessingVariables(startUpdateVNode: VNode) {
// 收集有变化的节点在submit阶段继续处理
function collectDirtyNodes(vNode: VNode, parent: VNode): void {
// 将子树和此vNode的所有效果附加到父树的效果列表中子项的完成顺序会影响副作用顺序。
parent.dirtyNodes.push(...vNode.dirtyNodes);
const dirtyNodes = vNode.dirtyNodes;
if (dirtyNodes !== null && dirtyNodes.length) {
if (parent.dirtyNodes === null) {
parent.dirtyNodes = [...vNode.dirtyNodes];
} else {
parent.dirtyNodes.push(...vNode.dirtyNodes);
}
dirtyNodes.length = 0;
vNode.dirtyNodes = null;
}
if (FlagUtils.hasAnyFlag(vNode)) {
parent.dirtyNodes.push(vNode);
if (parent.dirtyNodes === null) {
parent.dirtyNodes = [vNode];
} else {
parent.dirtyNodes.push(vNode);
}
}
}

View File

@ -72,7 +72,11 @@ function calcState(
function collectCallbacks(vNode: VNode, update: Update) {
if (update.callback !== null) {
FlagUtils.markCallback(vNode);
vNode.stateCallbacks.push(update.callback);
if (vNode.stateCallbacks === null) {
vNode.stateCallbacks = [update.callback];
} else {
vNode.stateCallbacks.push(update.callback);
}
}
}

View File

@ -4,17 +4,19 @@ import {throwNotInFuncError} from '../../hooks/BaseHook';
// 重置依赖
export function resetDepContexts(vNode: VNode): void {
vNode.depContexts = [];
vNode.depContexts = null;
}
// 收集依赖
function collectDeps<T>(vNode: VNode, context: ContextType<T>) {
const depContexts = vNode.depContexts;
if (!depContexts.length) {
if (depContexts === null) {
vNode.depContexts = [context];
} else {
vNode.isDepContextChange = false;
}
if (!depContexts.includes(context)) {
depContexts.push(context);
if (!depContexts.includes(context)) {
depContexts.push(context);
}
}
}

View File

@ -27,6 +27,10 @@ function isNoKeyFragment(child: any) {
// 清除单个节点
function deleteVNode(parentNode: VNode, delVNode: VNode): void {
FlagUtils.setDeletion(delVNode);
if (parentNode.dirtyNodes === null) {
parentNode.dirtyNodes = [delVNode];
return;
}
parentNode.dirtyNodes.push(delVNode);
}

View File

@ -50,7 +50,7 @@ function handleContextChange(processing: VNode, context: ContextType<any>): void
// 从vNode开始遍历
travelVNodeTree(vNode, node => {
const depContexts = node.depContexts;
if (depContexts.length) {
if (depContexts && depContexts.length) {
isMatch = matchDependencies(depContexts, context, node) ?? isMatch;
}
}, node =>

View File

@ -27,23 +27,24 @@ export function isSchedulingEffects() {
export function callUseEffects(vNode: VNode) {
const effectList: EffectList = vNode.effectList;
effectList.forEach(effect => {
const {effectConstant} = effect;
if (
(effectConstant & EffectConstant.Effect) !== EffectConstant.NoEffect &&
(effectConstant & EffectConstant.DepsChange) !== EffectConstant.NoEffect
) {
hookEffects.push(effect);
hookRemoveEffects.push(effect);
// 异步调用
if (!isScheduling) {
isScheduling = true;
runAsync(runAsyncEffects);
if (effectList !== null) {
effectList.forEach(effect => {
const {effectConstant} = effect;
if (
(effectConstant & EffectConstant.Effect) !== EffectConstant.NoEffect &&
(effectConstant & EffectConstant.DepsChange) !== EffectConstant.NoEffect
) {
hookEffects.push(effect);
hookRemoveEffects.push(effect);
// 异步调用
if (!isScheduling) {
isScheduling = true;
runAsync(runAsyncEffects);
}
}
}
});
});
}
}
export function runAsyncEffects() {
@ -85,23 +86,24 @@ export function runAsyncEffects() {
// 在销毁vNode的时候调用remove
export function callEffectRemove(vNode: VNode) {
const effectList: EffectList = vNode.effectList;
effectList.forEach(effect => {
const {removeEffect, effectConstant} = effect;
if (removeEffect !== undefined) {
if ((effectConstant & EffectConstant.Effect) !== EffectConstant.NoEffect) { // 如果是useEffect就异步调用
hookRemoveEffects.push(effect);
if (!isScheduling) {
isScheduling = true;
runAsync(runAsyncEffects);
if (effectList !== null) {
effectList.forEach(effect => {
const {removeEffect, effectConstant} = effect;
if (removeEffect !== undefined) {
if ((effectConstant & EffectConstant.Effect) !== EffectConstant.NoEffect) { // 如果是useEffect就异步调用
hookRemoveEffects.push(effect);
if (!isScheduling) {
isScheduling = true;
runAsync(runAsyncEffects);
}
} else { // 是useLayoutEffect直接执行
removeEffect();
}
} else { // 是useLayoutEffect直接执行
removeEffect();
}
}
});
});
}
}
// 同步执行UseLayoutEffect的remove
@ -109,26 +111,29 @@ export function callUseLayoutEffectRemove(vNode: VNode) {
const effectList: EffectList = vNode.effectList;
const layoutLabel = EffectConstant.LayoutEffect | EffectConstant.DepsChange;
effectList.forEach(effect => {
if ((effect.effectConstant & layoutLabel) === layoutLabel) {
const remove = effect.removeEffect;
effect.removeEffect = undefined;
if (typeof remove === 'function') {
remove();
if (effectList !== null) {
effectList.forEach(effect => {
if ((effect.effectConstant & layoutLabel) === layoutLabel) {
const remove = effect.removeEffect;
effect.removeEffect = undefined;
if (typeof remove === 'function') {
remove();
}
}
}
});
});
}
}
// 同步执行UseLayoutEffect
export function callUseLayoutEffectCreate(vNode: VNode) {
const effectList: EffectList = vNode.effectList;
const layoutLabel = EffectConstant.LayoutEffect | EffectConstant.DepsChange;
effectList.forEach(effect => {
if ((effect.effectConstant & layoutLabel) === layoutLabel) {
const create = effect.effect;
effect.removeEffect = create();
}
});
if (effectList !== null) {
const layoutLabel = EffectConstant.LayoutEffect | EffectConstant.DepsChange;
effectList.forEach(effect => {
if ((effect.effectConstant & layoutLabel) === layoutLabel) {
const create = effect.effect;
effect.removeEffect = create();
}
});
}
}

View File

@ -72,13 +72,14 @@ function callBeforeSubmitLifeCycles(
// 调用vNode.stateCallbacks
function callStateCallback(vNode: VNode, obj: any): void {
const stateCallbacks = vNode.stateCallbacks;
vNode.stateCallbacks = [];
stateCallbacks.forEach(callback => {
if (typeof callback === 'function') {
callback.call(obj);
}
});
vNode.stateCallbacks = null;
if (stateCallbacks !== null) {
stateCallbacks.forEach(callback => {
if (typeof callback === 'function') {
callback.call(obj);
}
});
}
}
// 调用界面变化后的生命周期

View File

@ -40,11 +40,15 @@ export function submitToRender(treeRoot) {
if (FlagUtils.hasAnyFlag(startVNode)) {
// 把自己加上
startVNode.dirtyNodes.push(startVNode);
if (startVNode.dirtyNodes === null) {
startVNode.dirtyNodes = [startVNode];
} else {
startVNode.dirtyNodes.push(startVNode);
}
}
const dirtyNodes = startVNode.dirtyNodes;
if (dirtyNodes.length) {
if (dirtyNodes !== null && dirtyNodes.length) {
const preMode = copyExecuteMode();
changeMode(InRender, true);
@ -60,7 +64,9 @@ export function submitToRender(treeRoot) {
// after submit阶段
afterSubmit(dirtyNodes);
setExecuteMode(preMode)
setExecuteMode(preMode);
dirtyNodes.length = 0;
startVNode.dirtyNodes = null;
}
if (isSchedulingEffects()) {

View File

@ -25,17 +25,17 @@ export class VNode {
suspensePromises: any = null; // suspense组件的promise列表
changeList: any = null; // DOM的变更列表
effectList: any[] = []; // useEffect 的更新数组
effectList: any[] | null = null; // useEffect 的更新数组
updates: any[] | null = null; // TreeRoot和ClassComponent使用的更新数组
stateCallbacks: any[] = []; // 存放存在setState的第二个参数和HorizonDOM.render的第三个参数所在的node数组
stateCallbacks: any[] | null = null; // 存放存在setState的第二个参数和HorizonDOM.render的第三个参数所在的node数组
isForceUpdate: boolean = false; // 是否使用强制更新
state: any = null; // ClassComponent和TreeRoot的状态
hooks: Array<Hook<any, any>> = []; // 保存hook
hooks: Array<Hook<any, any>> | null = null; // 保存hook
suspenseChildStatus: string = ''; // Suspense的Children是否显示
depContexts: Array<ContextType<any>> = []; // FunctionComponent和ClassComponent对context的依赖列表
depContexts: Array<ContextType<any>> | null = null; // FunctionComponent和ClassComponent对context的依赖列表
isDepContextChange: boolean = false; // context是否变更
dirtyNodes: Array<VNode> = []; // 需要改动的节点数组
dirtyNodes: Array<VNode> | null = null; // 需要改动的节点数组
shouldUpdate: boolean = false;
childShouldUpdate: boolean = false;
outerDom: any;
@ -65,7 +65,7 @@ export class VNode {
clearChild: VNode | null = null;
// one tree相关属性
isCreated: boolean = true;
oldHooks: Array<Hook<any, any>> = []; // 保存上一次执行的hook
oldHooks: Array<Hook<any, any>> | null = []; // 保存上一次执行的hook
oldState: any = null;
oldRef: RefType | ((handle: any) => void) | null = null;
suspenseChildThrow = false;
@ -74,7 +74,7 @@ export class VNode {
suspenseDidCapture: boolean = false; // suspense是否捕获了异常
promiseResolve: boolean = false; // suspense的promise是否resolve
path: Array<number> = []; // 保存从根到本节点的路径
path: string = ''; // 保存从根到本节点的路径
toUpdateNodes: Set<VNode> | null = null; // 保存要更新的节点
belongClassVNode: VNode | null = null; // 记录JSXElement所属class vNode处理ref的时候使用

View File

@ -78,7 +78,7 @@ export function updateVNode(vNode: VNode, vNodeProps?: any): VNode {
vNode.oldRef = vNode.ref;
FlagUtils.setNoFlags(vNode);
vNode.dirtyNodes = [];
vNode.dirtyNodes = null;
vNode.isCreated = false;
return vNode;
@ -143,7 +143,7 @@ export function createUndeterminedVNode(type, key, props) {
export function createTreeRootVNode(container) {
const vNode = newVirtualNode(TreeRoot, null, null, container);
vNode.path.push(0);
vNode.path += 0;
createUpdateArray(vNode);
return vNode;
}
@ -155,7 +155,7 @@ export function createVNode(tag: VNodeTag | string, ...secondArg) {
case TreeRoot:
// 创建treeRoot
vNode = newVirtualNode(TreeRoot, null, null, secondArg[0]);
vNode.path.push(0);
vNode.path += 0;
createUpdateArray(vNode);
break;
@ -165,7 +165,7 @@ export function createVNode(tag: VNodeTag | string, ...secondArg) {
}
export function updateVNodePath(vNode: VNode) {
vNode.path = [...vNode.parent.path, vNode.cIndex];
vNode.path = vNode.parent.path + vNode.cIndex;
}
export function createVNodeFromElement(element: JSXElement): VNode {

View File

@ -79,28 +79,24 @@ export function travelVNodeTree(
export function clearVNode(vNode: VNode) {
vNode.child = null;
vNode.next = null;
vNode.depContexts = [];
vNode.dirtyNodes = [];
vNode.depContexts = null;
vNode.dirtyNodes = null;
vNode.state = null;
vNode.hooks = [];
vNode.suspenseChildStatus = '';
vNode.hooks = null;
vNode.props = null;
vNode.parent = null;
vNode.suspensePromises = null;
vNode.changeList = null;
vNode.effectList = [];
vNode.effectList = null;
vNode.updates = null;
vNode.realNode = null;
vNode.oldProps = null;
vNode.oldHooks = [];
vNode.oldHooks = null;
vNode.oldState = null;
vNode.oldRef = null;
vNode.suspenseChildThrow = false;
vNode.oldSuspenseChildStatus = '';
vNode.oldChild = null;
vNode.path = [];
vNode.toUpdateNodes = null;
vNode.belongClassVNode = null;