Match-id-97a6395f2682889472335c90b2a743d288f37fcc
This commit is contained in:
parent
f46c73cc6c
commit
b0c3086a77
|
@ -6,7 +6,7 @@ import type {VNode} from './Types';
|
|||
import type {Update} from './UpdateHandler';
|
||||
|
||||
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 {launchUpdateFromVNode, tryRenderFromRoot} from './TreeBuilder';
|
||||
import {setRootThrowError} from './submit/Submit';
|
||||
|
@ -99,7 +99,7 @@ export function handleRenderThrowError(
|
|||
const ctor = vNode.type;
|
||||
const instance = vNode.realNode;
|
||||
if (
|
||||
!vNode.flags.DidCapture &&
|
||||
(vNode.flags & DidCapture) === InitFlag &&
|
||||
(
|
||||
typeof ctor.getDerivedStateFromError === 'function' ||
|
||||
(instance !== null && typeof instance.componentDidCatch === 'function')
|
||||
|
|
|
@ -3,7 +3,7 @@ import type { VNode } from './Types';
|
|||
import { callRenderQueueImmediate, pushRenderCallback } from './taskExecutor/RenderQueue';
|
||||
import { updateVNode } from './vnode/VNodeCreator';
|
||||
import { TreeRoot } from './vnode/VNodeTags';
|
||||
import { FlagUtils } from './vnode/VNodeFlags';
|
||||
import { FlagUtils, InitFlag, Interrupted } from './vnode/VNodeFlags';
|
||||
import { captureVNode } from './render/BaseComponent';
|
||||
import { checkLoopingUpdateLimit, submitToRender } from './submit/Submit';
|
||||
import { runAsyncEffects } from './submit/HookEffectHandler';
|
||||
|
@ -86,13 +86,13 @@ function bubbleVNode(vNode: VNode): void {
|
|||
do {
|
||||
const parent = node.parent;
|
||||
|
||||
if (!node.flags.Interrupted) { // vNode没有抛出异常
|
||||
if ((node.flags & Interrupted) === InitFlag) { // vNode没有抛出异常
|
||||
componentRenders[node.tag].bubbleRender(node);
|
||||
|
||||
// 设置node的childShouldUpdate属性
|
||||
updateChildShouldUpdate(node);
|
||||
|
||||
if (parent !== null && node !== getStartVNode() && !parent.flags.Interrupted) {
|
||||
if (parent !== null && node !== getStartVNode() && (parent.flags & Interrupted) === InitFlag) {
|
||||
collectDirtyNodes(node, parent);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ import {
|
|||
markComponentDidUpdate,
|
||||
markGetSnapshotBeforeUpdate,
|
||||
} from './class/ClassLifeCycleProcessor';
|
||||
import { FlagUtils } from '../vnode/VNodeFlags';
|
||||
import { FlagUtils, DidCapture } from '../vnode/VNodeFlags';
|
||||
import { createVNodeChildren, markRef } from './BaseComponent';
|
||||
import {
|
||||
createUpdateArray,
|
||||
|
@ -73,7 +73,7 @@ function createChildren(clazz: any, processing: VNode) {
|
|||
processing.state = processing.realNode.state;
|
||||
|
||||
const inst = processing.realNode;
|
||||
const isCatchError = processing.flags.DidCapture;
|
||||
const isCatchError = (processing.flags & DidCapture) === DidCapture;
|
||||
|
||||
// 按照已有规格,如果捕获了错误却没有定义getDerivedStateFromError函数,返回的child为null
|
||||
const newElements = isCatchError && typeof clazz.getDerivedStateFromError !== 'function'
|
||||
|
@ -122,7 +122,7 @@ export function captureClassComponent(processing: VNode, clazz: any, nextProps:
|
|||
const newContext = getCurrentContext(clazz, processing);
|
||||
|
||||
// 子节点抛出异常时,如果本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) {
|
||||
oldProps = mergeDefaultProps(processing.type, oldProps);
|
||||
}
|
||||
|
@ -161,7 +161,7 @@ export function captureClassComponent(processing: VNode, clazz: any, nextProps:
|
|||
inst.props = nextProps;
|
||||
}
|
||||
// 如果捕获了 error,必须更新
|
||||
const isCatchError = processing.flags.DidCapture;
|
||||
const isCatchError = (processing.flags & DidCapture) === DidCapture;
|
||||
shouldUpdate = isCatchError || shouldUpdate;
|
||||
|
||||
// 更新ref
|
||||
|
|
|
@ -17,7 +17,7 @@ import {
|
|||
SuspenseComponent,
|
||||
MemoComponent,
|
||||
} from '../vnode/VNodeTags';
|
||||
import { FlagUtils, ResetText, Clear } from '../vnode/VNodeFlags';
|
||||
import { FlagUtils, ResetText, Clear, Update } from '../vnode/VNodeFlags';
|
||||
import { mergeDefaultProps } from '../render/LazyComponent';
|
||||
import {
|
||||
submitDomUpdate,
|
||||
|
@ -97,7 +97,7 @@ function callAfterSubmitLifeCycles(
|
|||
}
|
||||
case ClassComponent: {
|
||||
const instance = vNode.realNode;
|
||||
if (vNode.flags.Update) {
|
||||
if ((vNode.flags & Update) === Update) {
|
||||
if (vNode.isCreated) {
|
||||
instance.componentDidMount();
|
||||
} else {
|
||||
|
@ -124,7 +124,7 @@ function callAfterSubmitLifeCycles(
|
|||
return;
|
||||
}
|
||||
case DomComponent: {
|
||||
if (vNode.isCreated && vNode.flags.Update) {
|
||||
if (vNode.isCreated && (vNode.flags & Update) === Update) {
|
||||
// button、input、select、textarea、如果有 autoFocus 属性需要focus
|
||||
if (shouldAutoFocus(vNode.type, vNode.props)) {
|
||||
vNode.realNode.focus();
|
||||
|
@ -222,7 +222,7 @@ function unmountNestedVNodes(vNode: VNode): void {
|
|||
function submitAddition(vNode: VNode): void {
|
||||
const { parent, parentDom } = findDomParent(vNode);
|
||||
|
||||
if (parent.flags.ResetText) {
|
||||
if ((vNode.flags & ResetText) === ResetText) {
|
||||
// 在insert之前先reset
|
||||
clearText(parentDom);
|
||||
FlagUtils.removeFlag(parent, ResetText);
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
import type {VNode} from '../Types';
|
||||
|
||||
import {callRenderQueueImmediate} from '../taskExecutor/RenderQueue';
|
||||
import {throwIfTrue} from '../utils/throwIfTrue';
|
||||
import {FlagUtils, Addition as AdditionFlag} from '../vnode/VNodeFlags';
|
||||
import {FlagUtils, Addition, Snapshot, ResetText, Ref, Update, Deletion, Clear, Callback} from '../vnode/VNodeFlags';
|
||||
import {prepareForSubmit, resetAfterSubmit} from '../../dom/DOMOperator';
|
||||
import {handleSubmitError} from '../ErrorHandler';
|
||||
import {
|
||||
|
@ -91,7 +89,7 @@ export function submitToRender(treeRoot) {
|
|||
function beforeSubmit(dirtyNodes: Array<VNode>) {
|
||||
dirtyNodes.forEach(node => {
|
||||
try {
|
||||
if (node.flags.Snapshot) {
|
||||
if ((node.flags & Snapshot) === Snapshot) {
|
||||
callBeforeSubmitLifeCycles(node);
|
||||
}
|
||||
} catch (error) {
|
||||
|
@ -103,35 +101,38 @@ function beforeSubmit(dirtyNodes: Array<VNode>) {
|
|||
function submit(dirtyNodes: Array<VNode>) {
|
||||
dirtyNodes.forEach(node => {
|
||||
try {
|
||||
if (node.flags.ResetText) {
|
||||
if ((node.flags & ResetText) === ResetText) {
|
||||
submitResetTextContent(node);
|
||||
}
|
||||
|
||||
if (node.flags.Ref) {
|
||||
if ((node.flags & Ref) === Ref) {
|
||||
if (!node.isCreated) {
|
||||
// 需要执行
|
||||
detachRef(node, true);
|
||||
}
|
||||
}
|
||||
|
||||
const {Addition, Update, Deletion, Clear} = node.flags;
|
||||
if (Addition && Update) {
|
||||
const isAdd = (node.flags & Addition) === Addition;
|
||||
const isUpdate = (node.flags & Update) === Update;
|
||||
if (isAdd && isUpdate) {
|
||||
// Addition
|
||||
submitAddition(node);
|
||||
FlagUtils.removeFlag(node, AdditionFlag);
|
||||
FlagUtils.removeFlag(node, Addition);
|
||||
|
||||
// Update
|
||||
submitUpdate(node);
|
||||
} else {
|
||||
if (Addition) {
|
||||
const isDeletion = (node.flags & Deletion) === Deletion;
|
||||
const isClear = (node.flags & Clear) === Clear;
|
||||
if (isAdd) {
|
||||
submitAddition(node);
|
||||
FlagUtils.removeFlag(node, AdditionFlag);
|
||||
} else if (Update) {
|
||||
FlagUtils.removeFlag(node, Addition);
|
||||
} else if (isUpdate) {
|
||||
submitUpdate(node);
|
||||
} else if (Deletion) {
|
||||
} else if (isDeletion) {
|
||||
submitDeletion(node);
|
||||
}
|
||||
if (Clear) {
|
||||
if (isClear) {
|
||||
submitClear(node);
|
||||
}
|
||||
}
|
||||
|
@ -144,11 +145,11 @@ function submit(dirtyNodes: Array<VNode>) {
|
|||
function afterSubmit(dirtyNodes: Array<VNode>) {
|
||||
dirtyNodes.forEach(node => {
|
||||
try {
|
||||
if (node.flags.Update || node.flags.Callback) {
|
||||
if ((node.flags & Update) === Update || (node.flags & Callback) === Callback) {
|
||||
callAfterSubmitLifeCycles(node);
|
||||
}
|
||||
|
||||
if (node.flags.Ref) {
|
||||
if ((node.flags & Ref) === Ref) {
|
||||
attachRef(node);
|
||||
}
|
||||
} catch (error) {
|
||||
|
|
|
@ -5,6 +5,7 @@ import { TreeRoot, FunctionComponent, ClassComponent, DomPortal, DomText, Contex
|
|||
import type { VNodeTag } from './VNodeTags';
|
||||
import type { RefType, ContextType } from '../Types';
|
||||
import type { Hook } from '../hooks/HookType';
|
||||
import { InitFlag } from './VNodeFlags';
|
||||
|
||||
export class VNode {
|
||||
tag: VNodeTag;
|
||||
|
@ -48,20 +49,7 @@ export class VNode {
|
|||
|
||||
// 因为LazyComponent会修改type属性,为了在diff中判断是否可以复用,需要增加一个lazyType
|
||||
lazyType: any;
|
||||
flags: {
|
||||
Addition?: boolean;
|
||||
Update?: boolean;
|
||||
Deletion?: boolean;
|
||||
ResetText?: boolean;
|
||||
Callback?: boolean;
|
||||
DidCapture?: boolean;
|
||||
Ref?: boolean;
|
||||
Snapshot?: boolean;
|
||||
Interrupted?: boolean;
|
||||
ShouldCapture?: boolean;
|
||||
ForceUpdate?: boolean;
|
||||
Clear?: boolean;
|
||||
} = {};
|
||||
flags = InitFlag;
|
||||
clearChild: VNode | null;
|
||||
// one tree相关属性
|
||||
isCreated: boolean = true;
|
||||
|
@ -75,7 +63,7 @@ export class VNode {
|
|||
promiseResolve: boolean; // suspense的promise是否resolve
|
||||
|
||||
path: string = ''; // 保存从根到本节点的路径
|
||||
toUpdateNodes: Set<VNode>; // 保存要更新的节点
|
||||
toUpdateNodes: Set<VNode> | null; // 保存要更新的节点
|
||||
|
||||
belongClassVNode: VNode | null = null; // 记录JSXElement所属class vNode,处理ref的时候使用
|
||||
|
||||
|
|
|
@ -4,97 +4,79 @@
|
|||
|
||||
import type { VNode } from '../Types';
|
||||
|
||||
|
||||
export const InitFlag = /** */ 0b000000000000;
|
||||
// vNode节点的flags
|
||||
export const Addition = 'Addition';
|
||||
export const Update = 'Update';
|
||||
export const Deletion = 'Deletion';
|
||||
export const ResetText = 'ResetText';
|
||||
export const Callback = 'Callback';
|
||||
export const DidCapture = 'DidCapture';
|
||||
export const Ref = 'Ref';
|
||||
export const Snapshot = 'Snapshot';
|
||||
// 被中断了,抛出错误的vNode以及它的父vNode
|
||||
export const Interrupted = 'Interrupted';
|
||||
export const ShouldCapture = 'ShouldCapture';
|
||||
// For suspense
|
||||
export const ForceUpdate = 'ForceUpdate';
|
||||
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 const Addition = /** */ 0b100000000000;
|
||||
export const Update = /** */ 0b010000000000;
|
||||
export const Deletion = /** */ 0b001000000000;
|
||||
export const ResetText =/** */ 0b000100000000;
|
||||
export const Callback = /** */ 0b000010000000;
|
||||
export const DidCapture =/** */ 0b000001000000;
|
||||
export const Ref = /** */ 0b000000100000;
|
||||
export const Snapshot = /** */ 0b000000010000;
|
||||
export const Interrupted = /** */ 0b000000001000; // 被中断了,抛出错误的vNode以及它的父vNode
|
||||
export const ShouldCapture =/** */ 0b000000000100;
|
||||
export const ForceUpdate = /** */ 0b000000000010; // For suspense
|
||||
export const Clear = /** */ 0b000000000001;
|
||||
const LifecycleEffectArr = Update | Callback | Ref | Snapshot;
|
||||
|
||||
export class FlagUtils {
|
||||
static removeFlag(node: VNode, flag: string) {
|
||||
node.flags[flag] = false;
|
||||
static removeFlag(node: VNode, flag: number) {
|
||||
const flags = node.flags;
|
||||
node.flags = flags & (~flag);
|
||||
}
|
||||
static removeLifecycleEffectFlags(node) {
|
||||
LifecycleEffectArr.forEach(key => {
|
||||
node.flags[key] = false;
|
||||
});
|
||||
const flags = node.flags;
|
||||
node.flags = flags & (~LifecycleEffectArr);
|
||||
}
|
||||
static hasAnyFlag(node: VNode) { // 有标志位
|
||||
const flags = node.flags;
|
||||
const arrLength = FlagArr.length;
|
||||
let key;
|
||||
for (let i = 0; i < arrLength; i++) {
|
||||
key = FlagArr[i];
|
||||
if (flags[key]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return node.flags !== InitFlag;
|
||||
}
|
||||
|
||||
static setNoFlags(node: VNode) {
|
||||
resetFlag(node);
|
||||
node.flags = InitFlag;
|
||||
}
|
||||
|
||||
static markAddition(node: VNode) {
|
||||
node.flags.Addition = true;
|
||||
node.flags |= Addition;
|
||||
}
|
||||
static setAddition(node: VNode) {
|
||||
resetFlag(node);
|
||||
node.flags.Addition = true;
|
||||
node.flags = Addition;
|
||||
}
|
||||
static markUpdate(node: VNode) {
|
||||
node.flags.Update = true;
|
||||
node.flags |= Update;
|
||||
}
|
||||
static setDeletion(node: VNode) {
|
||||
resetFlag(node);
|
||||
node.flags.Deletion = true;
|
||||
node.flags = Deletion;
|
||||
}
|
||||
static markContentReset(node: VNode) {
|
||||
node.flags.ResetText = true;
|
||||
node.flags |= ResetText;
|
||||
}
|
||||
static markCallback(node: VNode) {
|
||||
node.flags.Callback = true;
|
||||
node.flags |= Callback;
|
||||
}
|
||||
static markDidCapture(node: VNode) {
|
||||
node.flags.DidCapture = true;
|
||||
node.flags |= DidCapture;
|
||||
}
|
||||
static markShouldCapture(node: VNode) {
|
||||
node.flags.ShouldCapture = true;
|
||||
node.flags |= ShouldCapture;
|
||||
}
|
||||
static markRef(node: VNode) {
|
||||
node.flags.Ref = true;
|
||||
node.flags |= Ref;
|
||||
}
|
||||
static markSnapshot(node: VNode) {
|
||||
node.flags.Snapshot = true;
|
||||
node.flags |= Snapshot;
|
||||
}
|
||||
static markInterrupted(node: VNode) {
|
||||
node.flags.Interrupted = true;
|
||||
node.flags |= Interrupted;
|
||||
}
|
||||
static markForceUpdate(node: VNode) {
|
||||
node.flags.ForceUpdate = true;
|
||||
node.flags |= ForceUpdate;
|
||||
}
|
||||
|
||||
static markClear(node: VNode) {
|
||||
node.flags.Clear = true;
|
||||
node.flags |= Clear;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import type {VNode} from '../Types';
|
|||
import {DomComponent, DomPortal, DomText, TreeRoot} from './VNodeTags';
|
||||
import {isComment} from '../../dom/utils/Common';
|
||||
import {getNearestVNode} from '../../dom/DOMInternalKeys';
|
||||
import { Addition, InitFlag } from './VNodeFlags';
|
||||
|
||||
export function travelChildren(beginVNode: VNode, handleVNode: Function, isFinish?: Function) {
|
||||
let node: VNode | null = beginVNode;
|
||||
|
@ -92,6 +93,7 @@ export function clearVNode(vNode: VNode) {
|
|||
vNode.oldState = null;
|
||||
vNode.oldRef = null;
|
||||
vNode.oldChild = null;
|
||||
vNode.flags = InitFlag;
|
||||
|
||||
vNode.toUpdateNodes = null;
|
||||
|
||||
|
@ -186,7 +188,7 @@ export function getSiblingDom(vNode: VNode): Element | null {
|
|||
// 如果不是dom节点,往下找
|
||||
while (!isDomVNode(node)) {
|
||||
// 如果节点也是Addition
|
||||
if (node.flags.Addition) {
|
||||
if ((node.flags & Addition) ===Addition) {
|
||||
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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue