Match-id-97a6395f2682889472335c90b2a743d288f37fcc

This commit is contained in:
* 2022-02-17 19:27:00 +08:00 committed by *
parent f46c73cc6c
commit b0c3086a77
8 changed files with 73 additions and 100 deletions

View File

@ -6,7 +6,7 @@ import type {VNode} from './Types';
import type {Update} from './UpdateHandler'; import type {Update} from './UpdateHandler';
import {ClassComponent, TreeRoot} from './vnode/VNodeTags'; import {ClassComponent, TreeRoot} from './vnode/VNodeTags';
import {FlagUtils, Interrupted} from './vnode/VNodeFlags'; import {FlagUtils, Interrupted, DidCapture, InitFlag} from './vnode/VNodeFlags';
import {newUpdate, UpdateState, pushUpdate} from './UpdateHandler'; import {newUpdate, UpdateState, pushUpdate} from './UpdateHandler';
import {launchUpdateFromVNode, tryRenderFromRoot} from './TreeBuilder'; import {launchUpdateFromVNode, tryRenderFromRoot} from './TreeBuilder';
import {setRootThrowError} from './submit/Submit'; import {setRootThrowError} from './submit/Submit';
@ -99,7 +99,7 @@ export function handleRenderThrowError(
const ctor = vNode.type; const ctor = vNode.type;
const instance = vNode.realNode; const instance = vNode.realNode;
if ( if (
!vNode.flags.DidCapture && (vNode.flags & DidCapture) === InitFlag &&
( (
typeof ctor.getDerivedStateFromError === 'function' || typeof ctor.getDerivedStateFromError === 'function' ||
(instance !== null && typeof instance.componentDidCatch === 'function') (instance !== null && typeof instance.componentDidCatch === 'function')

View File

@ -3,7 +3,7 @@ import type { VNode } from './Types';
import { callRenderQueueImmediate, pushRenderCallback } from './taskExecutor/RenderQueue'; import { callRenderQueueImmediate, pushRenderCallback } from './taskExecutor/RenderQueue';
import { updateVNode } from './vnode/VNodeCreator'; import { updateVNode } from './vnode/VNodeCreator';
import { TreeRoot } from './vnode/VNodeTags'; import { TreeRoot } from './vnode/VNodeTags';
import { FlagUtils } from './vnode/VNodeFlags'; import { FlagUtils, InitFlag, Interrupted } from './vnode/VNodeFlags';
import { captureVNode } from './render/BaseComponent'; import { captureVNode } from './render/BaseComponent';
import { checkLoopingUpdateLimit, submitToRender } from './submit/Submit'; import { checkLoopingUpdateLimit, submitToRender } from './submit/Submit';
import { runAsyncEffects } from './submit/HookEffectHandler'; import { runAsyncEffects } from './submit/HookEffectHandler';
@ -86,13 +86,13 @@ function bubbleVNode(vNode: VNode): void {
do { do {
const parent = node.parent; const parent = node.parent;
if (!node.flags.Interrupted) { // vNode没有抛出异常 if ((node.flags & Interrupted) === InitFlag) { // vNode没有抛出异常
componentRenders[node.tag].bubbleRender(node); componentRenders[node.tag].bubbleRender(node);
// 设置node的childShouldUpdate属性 // 设置node的childShouldUpdate属性
updateChildShouldUpdate(node); updateChildShouldUpdate(node);
if (parent !== null && node !== getStartVNode() && !parent.flags.Interrupted) { if (parent !== null && node !== getStartVNode() && (parent.flags & Interrupted) === InitFlag) {
collectDirtyNodes(node, parent); collectDirtyNodes(node, parent);
} }
} }

View File

@ -20,7 +20,7 @@ import {
markComponentDidUpdate, markComponentDidUpdate,
markGetSnapshotBeforeUpdate, markGetSnapshotBeforeUpdate,
} from './class/ClassLifeCycleProcessor'; } from './class/ClassLifeCycleProcessor';
import { FlagUtils } from '../vnode/VNodeFlags'; import { FlagUtils, DidCapture } from '../vnode/VNodeFlags';
import { createVNodeChildren, markRef } from './BaseComponent'; import { createVNodeChildren, markRef } from './BaseComponent';
import { import {
createUpdateArray, createUpdateArray,
@ -73,7 +73,7 @@ function createChildren(clazz: any, processing: VNode) {
processing.state = processing.realNode.state; processing.state = processing.realNode.state;
const inst = processing.realNode; const inst = processing.realNode;
const isCatchError = processing.flags.DidCapture; const isCatchError = (processing.flags & DidCapture) === DidCapture;
// 按照已有规格如果捕获了错误却没有定义getDerivedStateFromError函数返回的child为null // 按照已有规格如果捕获了错误却没有定义getDerivedStateFromError函数返回的child为null
const newElements = isCatchError && typeof clazz.getDerivedStateFromError !== 'function' const newElements = isCatchError && typeof clazz.getDerivedStateFromError !== 'function'
@ -122,7 +122,7 @@ export function captureClassComponent(processing: VNode, clazz: any, nextProps:
const newContext = getCurrentContext(clazz, processing); const newContext = getCurrentContext(clazz, processing);
// 子节点抛出异常时如果本class是个捕获异常的处理节点这时候oldProps是null所以需要使用props // 子节点抛出异常时如果本class是个捕获异常的处理节点这时候oldProps是null所以需要使用props
let oldProps = processing.flags.DidCapture ? processing.props : processing.oldProps; let oldProps = (processing.flags & DidCapture) === DidCapture ? processing.props : processing.oldProps;
if (processing.isLazyComponent) { if (processing.isLazyComponent) {
oldProps = mergeDefaultProps(processing.type, oldProps); oldProps = mergeDefaultProps(processing.type, oldProps);
} }
@ -161,7 +161,7 @@ export function captureClassComponent(processing: VNode, clazz: any, nextProps:
inst.props = nextProps; inst.props = nextProps;
} }
// 如果捕获了 error必须更新 // 如果捕获了 error必须更新
const isCatchError = processing.flags.DidCapture; const isCatchError = (processing.flags & DidCapture) === DidCapture;
shouldUpdate = isCatchError || shouldUpdate; shouldUpdate = isCatchError || shouldUpdate;
// 更新ref // 更新ref

View File

@ -17,7 +17,7 @@ import {
SuspenseComponent, SuspenseComponent,
MemoComponent, MemoComponent,
} from '../vnode/VNodeTags'; } from '../vnode/VNodeTags';
import { FlagUtils, ResetText, Clear } from '../vnode/VNodeFlags'; import { FlagUtils, ResetText, Clear, Update } from '../vnode/VNodeFlags';
import { mergeDefaultProps } from '../render/LazyComponent'; import { mergeDefaultProps } from '../render/LazyComponent';
import { import {
submitDomUpdate, submitDomUpdate,
@ -97,7 +97,7 @@ function callAfterSubmitLifeCycles(
} }
case ClassComponent: { case ClassComponent: {
const instance = vNode.realNode; const instance = vNode.realNode;
if (vNode.flags.Update) { if ((vNode.flags & Update) === Update) {
if (vNode.isCreated) { if (vNode.isCreated) {
instance.componentDidMount(); instance.componentDidMount();
} else { } else {
@ -124,7 +124,7 @@ function callAfterSubmitLifeCycles(
return; return;
} }
case DomComponent: { case DomComponent: {
if (vNode.isCreated && vNode.flags.Update) { if (vNode.isCreated && (vNode.flags & Update) === Update) {
// button、input、select、textarea、如果有 autoFocus 属性需要focus // button、input、select、textarea、如果有 autoFocus 属性需要focus
if (shouldAutoFocus(vNode.type, vNode.props)) { if (shouldAutoFocus(vNode.type, vNode.props)) {
vNode.realNode.focus(); vNode.realNode.focus();
@ -222,7 +222,7 @@ function unmountNestedVNodes(vNode: VNode): void {
function submitAddition(vNode: VNode): void { function submitAddition(vNode: VNode): void {
const { parent, parentDom } = findDomParent(vNode); const { parent, parentDom } = findDomParent(vNode);
if (parent.flags.ResetText) { if ((vNode.flags & ResetText) === ResetText) {
// 在insert之前先reset // 在insert之前先reset
clearText(parentDom); clearText(parentDom);
FlagUtils.removeFlag(parent, ResetText); FlagUtils.removeFlag(parent, ResetText);

View File

@ -1,8 +1,6 @@
import type {VNode} from '../Types'; import type {VNode} from '../Types';
import {callRenderQueueImmediate} from '../taskExecutor/RenderQueue'; import {FlagUtils, Addition, Snapshot, ResetText, Ref, Update, Deletion, Clear, Callback} from '../vnode/VNodeFlags';
import {throwIfTrue} from '../utils/throwIfTrue';
import {FlagUtils, Addition as AdditionFlag} from '../vnode/VNodeFlags';
import {prepareForSubmit, resetAfterSubmit} from '../../dom/DOMOperator'; import {prepareForSubmit, resetAfterSubmit} from '../../dom/DOMOperator';
import {handleSubmitError} from '../ErrorHandler'; import {handleSubmitError} from '../ErrorHandler';
import { import {
@ -91,7 +89,7 @@ export function submitToRender(treeRoot) {
function beforeSubmit(dirtyNodes: Array<VNode>) { function beforeSubmit(dirtyNodes: Array<VNode>) {
dirtyNodes.forEach(node => { dirtyNodes.forEach(node => {
try { try {
if (node.flags.Snapshot) { if ((node.flags & Snapshot) === Snapshot) {
callBeforeSubmitLifeCycles(node); callBeforeSubmitLifeCycles(node);
} }
} catch (error) { } catch (error) {
@ -103,35 +101,38 @@ function beforeSubmit(dirtyNodes: Array<VNode>) {
function submit(dirtyNodes: Array<VNode>) { function submit(dirtyNodes: Array<VNode>) {
dirtyNodes.forEach(node => { dirtyNodes.forEach(node => {
try { try {
if (node.flags.ResetText) { if ((node.flags & ResetText) === ResetText) {
submitResetTextContent(node); submitResetTextContent(node);
} }
if (node.flags.Ref) { if ((node.flags & Ref) === Ref) {
if (!node.isCreated) { if (!node.isCreated) {
// 需要执行 // 需要执行
detachRef(node, true); detachRef(node, true);
} }
} }
const {Addition, Update, Deletion, Clear} = node.flags; const isAdd = (node.flags & Addition) === Addition;
if (Addition && Update) { const isUpdate = (node.flags & Update) === Update;
if (isAdd && isUpdate) {
// Addition // Addition
submitAddition(node); submitAddition(node);
FlagUtils.removeFlag(node, AdditionFlag); FlagUtils.removeFlag(node, Addition);
// Update // Update
submitUpdate(node); submitUpdate(node);
} else { } else {
if (Addition) { const isDeletion = (node.flags & Deletion) === Deletion;
const isClear = (node.flags & Clear) === Clear;
if (isAdd) {
submitAddition(node); submitAddition(node);
FlagUtils.removeFlag(node, AdditionFlag); FlagUtils.removeFlag(node, Addition);
} else if (Update) { } else if (isUpdate) {
submitUpdate(node); submitUpdate(node);
} else if (Deletion) { } else if (isDeletion) {
submitDeletion(node); submitDeletion(node);
} }
if (Clear) { if (isClear) {
submitClear(node); submitClear(node);
} }
} }
@ -144,11 +145,11 @@ function submit(dirtyNodes: Array<VNode>) {
function afterSubmit(dirtyNodes: Array<VNode>) { function afterSubmit(dirtyNodes: Array<VNode>) {
dirtyNodes.forEach(node => { dirtyNodes.forEach(node => {
try { try {
if (node.flags.Update || node.flags.Callback) { if ((node.flags & Update) === Update || (node.flags & Callback) === Callback) {
callAfterSubmitLifeCycles(node); callAfterSubmitLifeCycles(node);
} }
if (node.flags.Ref) { if ((node.flags & Ref) === Ref) {
attachRef(node); attachRef(node);
} }
} catch (error) { } catch (error) {

View File

@ -5,6 +5,7 @@ import { TreeRoot, FunctionComponent, ClassComponent, DomPortal, DomText, Contex
import type { VNodeTag } from './VNodeTags'; import type { VNodeTag } from './VNodeTags';
import type { RefType, ContextType } from '../Types'; import type { RefType, ContextType } from '../Types';
import type { Hook } from '../hooks/HookType'; import type { Hook } from '../hooks/HookType';
import { InitFlag } from './VNodeFlags';
export class VNode { export class VNode {
tag: VNodeTag; tag: VNodeTag;
@ -48,20 +49,7 @@ export class VNode {
// 因为LazyComponent会修改type属性为了在diff中判断是否可以复用需要增加一个lazyType // 因为LazyComponent会修改type属性为了在diff中判断是否可以复用需要增加一个lazyType
lazyType: any; lazyType: any;
flags: { flags = InitFlag;
Addition?: boolean;
Update?: boolean;
Deletion?: boolean;
ResetText?: boolean;
Callback?: boolean;
DidCapture?: boolean;
Ref?: boolean;
Snapshot?: boolean;
Interrupted?: boolean;
ShouldCapture?: boolean;
ForceUpdate?: boolean;
Clear?: boolean;
} = {};
clearChild: VNode | null; clearChild: VNode | null;
// one tree相关属性 // one tree相关属性
isCreated: boolean = true; isCreated: boolean = true;
@ -75,7 +63,7 @@ export class VNode {
promiseResolve: boolean; // suspense的promise是否resolve promiseResolve: boolean; // suspense的promise是否resolve
path: string = ''; // 保存从根到本节点的路径 path: string = ''; // 保存从根到本节点的路径
toUpdateNodes: Set<VNode>; // 保存要更新的节点 toUpdateNodes: Set<VNode> | null; // 保存要更新的节点
belongClassVNode: VNode | null = null; // 记录JSXElement所属class vNode处理ref的时候使用 belongClassVNode: VNode | null = null; // 记录JSXElement所属class vNode处理ref的时候使用

View File

@ -4,97 +4,79 @@
import type { VNode } from '../Types'; import type { VNode } from '../Types';
export const InitFlag = /** */ 0b000000000000;
// vNode节点的flags // vNode节点的flags
export const Addition = 'Addition'; export const Addition = /** */ 0b100000000000;
export const Update = 'Update'; export const Update = /** */ 0b010000000000;
export const Deletion = 'Deletion'; export const Deletion = /** */ 0b001000000000;
export const ResetText = 'ResetText'; export const ResetText =/** */ 0b000100000000;
export const Callback = 'Callback'; export const Callback = /** */ 0b000010000000;
export const DidCapture = 'DidCapture'; export const DidCapture =/** */ 0b000001000000;
export const Ref = 'Ref'; export const Ref = /** */ 0b000000100000;
export const Snapshot = 'Snapshot'; export const Snapshot = /** */ 0b000000010000;
// 被中断了抛出错误的vNode以及它的父vNode export const Interrupted = /** */ 0b000000001000; // 被中断了抛出错误的vNode以及它的父vNode
export const Interrupted = 'Interrupted'; export const ShouldCapture =/** */ 0b000000000100;
export const ShouldCapture = 'ShouldCapture'; export const ForceUpdate = /** */ 0b000000000010; // For suspense
// For suspense export const Clear = /** */ 0b000000000001;
export const ForceUpdate = 'ForceUpdate'; const LifecycleEffectArr = Update | Callback | Ref | Snapshot;
export const Clear = 'Clear';
const FlagArr = [Addition, Update, Deletion, Clear, ResetText, Callback,
DidCapture, Ref, Snapshot, Interrupted, ShouldCapture, ForceUpdate];
const LifecycleEffectArr = [Update, Callback, Ref, Snapshot];
function resetFlag(node) {
node.flags = {};
}
export class FlagUtils { export class FlagUtils {
static removeFlag(node: VNode, flag: string) { static removeFlag(node: VNode, flag: number) {
node.flags[flag] = false; const flags = node.flags;
node.flags = flags & (~flag);
} }
static removeLifecycleEffectFlags(node) { static removeLifecycleEffectFlags(node) {
LifecycleEffectArr.forEach(key => { const flags = node.flags;
node.flags[key] = false; node.flags = flags & (~LifecycleEffectArr);
});
} }
static hasAnyFlag(node: VNode) { // 有标志位 static hasAnyFlag(node: VNode) { // 有标志位
const flags = node.flags; return node.flags !== InitFlag;
const arrLength = FlagArr.length;
let key;
for (let i = 0; i < arrLength; i++) {
key = FlagArr[i];
if (flags[key]) {
return true;
}
}
return false;
} }
static setNoFlags(node: VNode) { static setNoFlags(node: VNode) {
resetFlag(node); node.flags = InitFlag;
} }
static markAddition(node: VNode) { static markAddition(node: VNode) {
node.flags.Addition = true; node.flags |= Addition;
} }
static setAddition(node: VNode) { static setAddition(node: VNode) {
resetFlag(node); node.flags = Addition;
node.flags.Addition = true;
} }
static markUpdate(node: VNode) { static markUpdate(node: VNode) {
node.flags.Update = true; node.flags |= Update;
} }
static setDeletion(node: VNode) { static setDeletion(node: VNode) {
resetFlag(node); node.flags = Deletion;
node.flags.Deletion = true;
} }
static markContentReset(node: VNode) { static markContentReset(node: VNode) {
node.flags.ResetText = true; node.flags |= ResetText;
} }
static markCallback(node: VNode) { static markCallback(node: VNode) {
node.flags.Callback = true; node.flags |= Callback;
} }
static markDidCapture(node: VNode) { static markDidCapture(node: VNode) {
node.flags.DidCapture = true; node.flags |= DidCapture;
} }
static markShouldCapture(node: VNode) { static markShouldCapture(node: VNode) {
node.flags.ShouldCapture = true; node.flags |= ShouldCapture;
} }
static markRef(node: VNode) { static markRef(node: VNode) {
node.flags.Ref = true; node.flags |= Ref;
} }
static markSnapshot(node: VNode) { static markSnapshot(node: VNode) {
node.flags.Snapshot = true; node.flags |= Snapshot;
} }
static markInterrupted(node: VNode) { static markInterrupted(node: VNode) {
node.flags.Interrupted = true; node.flags |= Interrupted;
} }
static markForceUpdate(node: VNode) { static markForceUpdate(node: VNode) {
node.flags.ForceUpdate = true; node.flags |= ForceUpdate;
} }
static markClear(node: VNode) { static markClear(node: VNode) {
node.flags.Clear = true; node.flags |= Clear;
} }
} }

View File

@ -7,6 +7,7 @@ import type {VNode} from '../Types';
import {DomComponent, DomPortal, DomText, TreeRoot} from './VNodeTags'; import {DomComponent, DomPortal, DomText, TreeRoot} from './VNodeTags';
import {isComment} from '../../dom/utils/Common'; import {isComment} from '../../dom/utils/Common';
import {getNearestVNode} from '../../dom/DOMInternalKeys'; import {getNearestVNode} from '../../dom/DOMInternalKeys';
import { Addition, InitFlag } from './VNodeFlags';
export function travelChildren(beginVNode: VNode, handleVNode: Function, isFinish?: Function) { export function travelChildren(beginVNode: VNode, handleVNode: Function, isFinish?: Function) {
let node: VNode | null = beginVNode; let node: VNode | null = beginVNode;
@ -92,6 +93,7 @@ export function clearVNode(vNode: VNode) {
vNode.oldState = null; vNode.oldState = null;
vNode.oldRef = null; vNode.oldRef = null;
vNode.oldChild = null; vNode.oldChild = null;
vNode.flags = InitFlag;
vNode.toUpdateNodes = null; vNode.toUpdateNodes = null;
@ -186,7 +188,7 @@ export function getSiblingDom(vNode: VNode): Element | null {
// 如果不是dom节点往下找 // 如果不是dom节点往下找
while (!isDomVNode(node)) { while (!isDomVNode(node)) {
// 如果节点也是Addition // 如果节点也是Addition
if (node.flags.Addition) { if ((node.flags & Addition) ===Addition) {
continue findSibling; continue findSibling;
} }
@ -200,7 +202,7 @@ export function getSiblingDom(vNode: VNode): Element | null {
} }
} }
if (!node.flags.Addition) { if ((node.flags & Addition) ===InitFlag) {
// 找到 // 找到
return node.realNode; return node.realNode;
} }