Match-id-8d414d34e1e31da012f05c0990166fc2746380a1

This commit is contained in:
* 2023-06-13 11:21:07 +08:00
commit e79a882c8a
21 changed files with 138 additions and 133 deletions

View File

@ -84,3 +84,7 @@ const types = ['button', 'input', 'select', 'textarea'];
export function shouldAutoFocus(tagName: string, props: Props): boolean { export function shouldAutoFocus(tagName: string, props: Props): boolean {
return types.includes(tagName) ? Boolean(props.autoFocus) : false; return types.includes(tagName) ? Boolean(props.autoFocus) : false;
} }
export function isNotNull(object: any): boolean {
return object !== null && object !== undefined;
}

View File

@ -73,7 +73,7 @@ export function isInvalidValue(
propDetails: PropDetails | null, propDetails: PropDetails | null,
isNativeTag: boolean isNativeTag: boolean
): boolean { ): boolean {
if (value == null) { if (value === null || value === undefined) {
return true; return true;
} }
@ -104,7 +104,7 @@ export function validateProps(type, props) {
} }
// style属性必须是对象 // style属性必须是对象
if (props.style != null && typeof props.style !== 'object') { if (props.style !== null && props.style !== undefined && typeof props.style !== 'object') {
throw new Error('style should be a object.'); throw new Error('style should be a object.');
} }

View File

@ -29,7 +29,7 @@ function getInitValue(dom: HTMLInputElement, props: Props) {
export function getInputPropsWithoutValue(dom: HTMLInputElement, props: Props) { export function getInputPropsWithoutValue(dom: HTMLInputElement, props: Props) {
// checked属于必填属性无法置 // checked属于必填属性无法置
let { checked } = props; let { checked } = props;
if (checked == null) { if (checked === undefined) {
checked = getInitValue(dom, props).initChecked; checked = getInitValue(dom, props).initChecked;
} }
@ -45,12 +45,12 @@ export function getInputPropsWithoutValue(dom: HTMLInputElement, props: Props) {
export function updateInputValue(dom: HTMLInputElement, props: Props) { export function updateInputValue(dom: HTMLInputElement, props: Props) {
const { value, checked } = props; const { value, checked } = props;
if (value != null) { if (value !== undefined) {
// 处理 dom.value 逻辑 // 处理 dom.value 逻辑
if (dom.value !== String(value)) { if (dom.value !== String(value)) {
dom.value = String(value); dom.value = String(value);
} }
} else if (checked != null) { } else if (checked !== undefined) {
updateCommonProp(dom, 'checked', checked, true); updateCommonProp(dom, 'checked', checked, true);
} }
} }
@ -60,7 +60,7 @@ export function setInitInputValue(dom: HTMLInputElement, props: Props) {
const { value, defaultValue } = props; const { value, defaultValue } = props;
const { initValue, initChecked } = getInitValue(dom, props); const { initValue, initChecked } = getInitValue(dom, props);
if (value != null || defaultValue != null) { if (value !== undefined || defaultValue !== undefined) {
// value 的使用优先级 value 属性 > defaultValue 属性 > 空字符串 // value 的使用优先级 value 属性 > defaultValue 属性 > 空字符串
const initValueStr = String(initValue); const initValueStr = String(initValue);

View File

@ -69,18 +69,18 @@ export function updateSelectValue(dom: HorizonSelect, props: Props, isInit = fal
dom._multiple = newMultiple; dom._multiple = newMultiple;
// 设置了 value 属性 // 设置了 value 属性
if (value != null) { if (value !== null && value !== undefined) {
updateValue(dom.options, value, newMultiple); updateValue(dom.options, value, newMultiple);
} else if (oldMultiple !== newMultiple) { } else if (oldMultiple !== newMultiple) {
// 修改了 multiple 属性 // 修改了 multiple 属性
// 切换 multiple 之后,如果设置了 defaultValue 需要重新应用 // 切换 multiple 之后,如果设置了 defaultValue 需要重新应用
if (defaultValue != null) { if (defaultValue !== null && defaultValue !== undefined) {
updateValue(dom.options, defaultValue, newMultiple); updateValue(dom.options, defaultValue, newMultiple);
} else { } else {
// 恢复到未选定状态 // 恢复到未选定状态
updateValue(dom.options, newMultiple ? [] : '', newMultiple); updateValue(dom.options, newMultiple ? [] : '', newMultiple);
} }
} else if (isInit && defaultValue != null) { } else if (isInit && defaultValue !== null && defaultValue !== undefined) {
// 设置了 defaultValue 属性 // 设置了 defaultValue 属性
updateValue(dom.options, defaultValue, newMultiple); updateValue(dom.options, defaultValue, newMultiple);
} }

View File

@ -19,7 +19,7 @@ import { Props } from '../utils/Interface';
function getInitValue(props: Props) { function getInitValue(props: Props) {
const { value } = props; const { value } = props;
if (value == null) { if (value === undefined) {
const { defaultValue, children } = props; const { defaultValue, children } = props;
let initValue = defaultValue; let initValue = defaultValue;
@ -30,7 +30,7 @@ function getInitValue(props: Props) {
} }
// defaultValue 属性未配置,置为空字符串 // defaultValue 属性未配置,置为空字符串
initValue = initValue != null ? initValue : ''; initValue = initValue ?? '';
return initValue; return initValue;
} else { } else {
return value; return value;

View File

@ -62,13 +62,6 @@ function isCaptureEvent(horizonEventName) {
return horizonEventName.slice(-7) === 'Capture'; return horizonEventName.slice(-7) === 'Capture';
} }
// 利用冒泡事件模拟不冒泡事件,需要直接在根节点绑定
export function listenSimulatedDelegatedEvents(root: VNode) {
for (let i = 0; i < simulatedDelegatedEvents.length; i++) {
lazyDelegateOnRoot(root, simulatedDelegatedEvents[i]);
}
}
// 事件懒委托,当用户定义事件后,再进行委托到根节点 // 事件懒委托,当用户定义事件后,再进行委托到根节点
export function lazyDelegateOnRoot(currentRoot: VNode, eventName: string) { export function lazyDelegateOnRoot(currentRoot: VNode, eventName: string) {
currentRoot.delegatedEvents.add(eventName); currentRoot.delegatedEvents.add(eventName);
@ -80,11 +73,8 @@ export function lazyDelegateOnRoot(currentRoot: VNode, eventName: string) {
const nativeFullName = isCapture ? nativeEvent + 'capture' : nativeEvent; const nativeFullName = isCapture ? nativeEvent + 'capture' : nativeEvent;
// 事件存储在DOM节点属性避免多个VNode(root和portal)对应同一个DOM, 造成事件重复监听 // 事件存储在DOM节点属性避免多个VNode(root和portal)对应同一个DOM, 造成事件重复监听
let events = currentRoot.realNode.$EV; currentRoot.realNode.$EV = currentRoot.realNode.$EV ?? {};
const events = currentRoot.realNode.$EV;
if (!events) {
events = (currentRoot.realNode as any).$EV = {};
}
if (!events[nativeFullName]) { if (!events[nativeFullName]) {
events[nativeFullName] = listenToNativeEvent(nativeEvent, currentRoot.realNode, isCapture); events[nativeFullName] = listenToNativeEvent(nativeEvent, currentRoot.realNode, isCapture);
@ -92,6 +82,13 @@ export function lazyDelegateOnRoot(currentRoot: VNode, eventName: string) {
}); });
} }
// 利用冒泡事件模拟不冒泡事件,需要直接在根节点绑定
export function listenSimulatedDelegatedEvents(root: VNode) {
for (let i = 0; i < simulatedDelegatedEvents.length; i++) {
lazyDelegateOnRoot(root, simulatedDelegatedEvents[i]);
}
}
// 通过horizon事件名获取到native事件名 // 通过horizon事件名获取到native事件名
function getNativeEvtName(horizonEventName, capture) { function getNativeEvtName(horizonEventName, capture) {
let nativeName; let nativeName;

View File

@ -14,7 +14,7 @@
*/ */
import { getVNodeProps } from '../dom/DOMInternalKeys'; import { getVNodeProps } from '../dom/DOMInternalKeys';
import { getDomTag } from '../dom/utils/Common'; import { getDomTag, isNotNull } from '../dom/utils/Common';
import { Props } from '../dom/utils/Interface'; import { Props } from '../dom/utils/Interface';
import { updateTextareaValue } from '../dom/valueHandler/TextareaValueHandler'; import { updateTextareaValue } from '../dom/valueHandler/TextareaValueHandler';
import { updateInputHandlerIfChanged } from '../dom/valueHandler/ValueChangeHandler'; import { updateInputHandlerIfChanged } from '../dom/valueHandler/ValueChangeHandler';
@ -41,14 +41,14 @@ function controlInputValue(inputDom: HTMLInputElement, props: Props) {
const { name, type } = props; const { name, type } = props;
// 如果是 radio找出同一form内name相同的Radio更新它们Handler的Value // 如果是 radio找出同一form内name相同的Radio更新它们Handler的Value
if (type === 'radio' && name != null) { if (type === 'radio' && isNotNull(name)) {
const radioList = document.querySelectorAll<HTMLInputElement>(`input[type="radio"][name="${name}"]`); const radioList = document.querySelectorAll<HTMLInputElement>(`input[type="radio"][name="${name}"]`);
for (let i = 0; i < radioList.length; i++) { for (let i = 0; i < radioList.length; i++) {
const radio = radioList[i]; const radio = radioList[i];
if (radio === inputDom) { if (radio === inputDom) {
continue; continue;
} }
if (radio.form != null && inputDom.form != null && radio.form !== inputDom.form) { if (isNotNull(radio.form) && isNotNull(inputDom.form) && radio.form !== inputDom.form) {
continue; continue;
} }

View File

@ -87,34 +87,30 @@ export function getListenersFromTree(
return listeners; return listeners;
} }
// 获取enter和leave事件队列
export function collectMouseListeners( // 获取父节点
leaveEvent: null | WrappedEvent, function getParent(inst: VNode | null): VNode | null {
enterEvent: null | WrappedEvent, if (inst === null) {
from: VNode | null, return null;
to: VNode | null,
): ListenerUnitList {
// 确定公共父节点,作为在树上遍历的终点
const commonParent = from && to ? getCommonAncestor(from, to) : null;
let leaveEventList: ListenerUnitList = [];
if (from && leaveEvent) {
// 遍历树获取绑定的leave事件
leaveEventList = getMouseListenersFromTree(
leaveEvent,
from,
commonParent,
);
} }
let enterEventList: ListenerUnitList = []; do {
if (to && enterEvent) { inst = inst.parent;
// 先触发父节点enter事件所以需要逆序 } while (inst && inst.tag !== DomComponent);
enterEventList = getMouseListenersFromTree( return inst || null;
enterEvent,
to,
commonParent,
).reverse();
} }
return [...leaveEventList, ...enterEventList];
// 寻找两个节点的共同最近祖先如果没有则返回null
function getCommonAncestor(instA: VNode, instB: VNode): VNode | null {
const parentsSet = new Set<VNode>();
for (let tempA: VNode | null = instA; tempA; tempA = getParent(tempA)) {
parentsSet.add(tempA);
}
for (let tempB: VNode | null = instB; tempB; tempB = getParent(tempB)) {
if (parentsSet.has(tempB)) {
return tempB;
}
}
return null;
} }
function getMouseListenersFromTree( function getMouseListenersFromTree(
@ -149,27 +145,32 @@ function getMouseListenersFromTree(
return listeners; return listeners;
} }
// 寻找两个节点的共同最近祖先如果没有则返回null // 获取enter和leave事件队列
function getCommonAncestor(instA: VNode, instB: VNode): VNode | null { export function collectMouseListeners(
const parentsSet = new Set<VNode>(); leaveEvent: null | WrappedEvent,
for (let tempA: VNode | null = instA; tempA; tempA = getParent(tempA)) { enterEvent: null | WrappedEvent,
parentsSet.add(tempA); from: VNode | null,
to: VNode | null,
): ListenerUnitList {
// 确定公共父节点,作为在树上遍历的终点
const commonParent = from && to ? getCommonAncestor(from, to) : null;
let leaveEventList: ListenerUnitList = [];
if (from && leaveEvent) {
// 遍历树获取绑定的leave事件
leaveEventList = getMouseListenersFromTree(
leaveEvent,
from,
commonParent,
);
} }
for (let tempB: VNode | null = instB; tempB; tempB = getParent(tempB)) { let enterEventList: ListenerUnitList = [];
if (parentsSet.has(tempB)) { if (to && enterEvent) {
return tempB; // 先触发父节点enter事件所以需要逆序
enterEventList = getMouseListenersFromTree(
enterEvent,
to,
commonParent,
).reverse();
} }
} return [...leaveEventList, ...enterEventList];
return null;
}
// 获取父节点
function getParent(inst: VNode | null): VNode | null {
if (inst === null) {
return null;
}
do {
inst = inst.parent;
} while (inst && inst.tag !== DomComponent);
return inst || null;
} }

View File

@ -139,7 +139,7 @@ function bubbleVNode(vNode: VNode): void {
node = parent; node = parent;
// 更新processing抛出异常时可以使用 // 更新processing抛出异常时可以使用
processing = node; processing = node;
} while (node !== null); } while (node);
// 修改结果 // 修改结果
if (getBuildResult() === BuildInComplete) { if (getBuildResult() === BuildInComplete) {
@ -180,7 +180,7 @@ function getChildByIndex(vNode: VNode, idx: number) {
let node = vNode.child; let node = vNode.child;
for (let i = 0; i < idx; i++) { for (let i = 0; i < idx; i++) {
// 场景当组件被销毁业务若异步定时器调用setState修改状态可能出现路径错误此处进行保护。 // 场景当组件被销毁业务若异步定时器调用setState修改状态可能出现路径错误此处进行保护。
if (node == null) { if (node === null || node === undefined) {
return null; return null;
} }
@ -225,7 +225,7 @@ export function calcStartUpdateVNode(treeRoot: VNode) {
const pathIndex = Number(startNodePath[i]); const pathIndex = Number(startNodePath[i]);
node = getChildByIndex(node, pathIndex)!; node = getChildByIndex(node, pathIndex)!;
// 路径错误时,回退到从根更新 // 路径错误时,回退到从根更新
if (node == null) { if (node === null) {
return treeRoot; return treeRoot;
} }
} }

View File

@ -182,6 +182,10 @@ function getNewNode(parentNode: VNode, newChild: any, oldNode: VNode | null) {
} }
break; break;
} }
break;
}
default: {
break;
} }
} }
@ -374,7 +378,7 @@ function diffArrayNodesHandler(parentNode: VNode, firstChild: VNode | null, newC
// 4. 新节点还有一部分,但是老节点已经没有了 // 4. 新节点还有一部分,但是老节点已经没有了
if (oldNode === null) { if (oldNode === null) {
let isDirectAdd = false; let isDirectAdd = false;
// TODO: 是否可以扩大至非dom类型节点 // 是否可以扩大至非dom类型节点待确认
// 如果dom节点在上次添加前没有节点说明本次添加时可以直接添加到最后不需要通过 getSiblingDom 函数找到 before 节点 // 如果dom节点在上次添加前没有节点说明本次添加时可以直接添加到最后不需要通过 getSiblingDom 函数找到 before 节点
if ( if (
parentNode.tag === DomComponent && parentNode.tag === DomComponent &&
@ -513,7 +517,7 @@ function diffIteratorNodesHandler(
} }
// 新节点是字符串类型 // 新节点是字符串类型
function diffStringNodeHandler(parentNode: VNode, newChild: any, firstChildVNode: VNode, isComparing: boolean) { function diffStringNodeHandler(parentNode: VNode, newChild: any, firstChildVNode: VNode | null, isComparing: boolean) {
let newTextNode: VNode | null = null; let newTextNode: VNode | null = null;
// 第一个vNode是Text则复用 // 第一个vNode是Text则复用
@ -560,7 +564,7 @@ function diffObjectNodeHandler(
} }
let resultNode: VNode | null = null; let resultNode: VNode | null = null;
let startDelVNode = firstChildVNode; let startDelVNode: VNode | null = firstChildVNode;
if (newChild.vtype === TYPE_COMMON_ELEMENT) { if (newChild.vtype === TYPE_COMMON_ELEMENT) {
if (canReuseNode) { if (canReuseNode) {
// 可以复用 // 可以复用

View File

@ -52,7 +52,7 @@ export function createHook(state: any = null): Hook<any, any> {
return currentHook; return currentHook;
} }
export function getNextHook(hook: Hook<any, any>, hooks: Array<Hook<any, any>>) { export function getNextHook(hook: Hook<any, any>, hooks: Array<Hook<any, any>>): Hook<any, any> | null {
return hooks[hook.hIndex + 1] || null; return hooks[hook.hIndex + 1] || null;
} }

View File

@ -17,12 +17,9 @@ import { useLayoutEffectImpl } from './UseEffectHook';
import { getHookStage } from './HookStage'; import { getHookStage } from './HookStage';
import { throwNotInFuncError } from './BaseHook'; import { throwNotInFuncError } from './BaseHook';
import type { Ref } from './HookType'; import type { Ref } from './HookType';
import { isNotNull } from '../../dom/utils/Common';
function isNotNull(object: any): boolean { function effectFunc<R>(func: () => R, ref: Ref<R> | ((any) => any) | null): (() => void) | null {
return object !== null && object !== undefined;
}
function effectFunc<R>(func: () => R, ref: Ref<R> | ((any) => any) | null): (() => void) | void {
if (typeof ref === 'function') { if (typeof ref === 'function') {
const value = func(); const value = func();
ref(value); ref(value);
@ -37,6 +34,7 @@ function effectFunc<R>(func: () => R, ref: Ref<R> | ((any) => any) | null): (()
ref.current = null; ref.current = null;
}; };
} }
return null;
} }
export function useImperativeHandleImpl<R>( export function useImperativeHandleImpl<R>(

View File

@ -64,7 +64,7 @@ function handleContextChange(processing: VNode, context: ContextType<any>): void
node => { node => {
const depContexts = node.depContexts; const depContexts = node.depContexts;
if (depContexts && depContexts.length) { if (depContexts && depContexts.length) {
isMatch = matchDependencies(depContexts, context, node) ?? isMatch; isMatch = matchDependencies(depContexts, context, node) || isMatch;
} }
}, },
node => node =>

View File

@ -54,7 +54,7 @@ export function bubbleRender(processing: VNode) {
const type = processing.type; const type = processing.type;
const newProps = processing.props; const newProps = processing.props;
if (!processing.isCreated && processing.realNode != null) { if (!processing.isCreated && processing.realNode !== null) {
// 更新dom属性 // 更新dom属性
updateDom(processing, type, newProps); updateDom(processing, type, newProps);

View File

@ -18,6 +18,7 @@ import type { VNode } from '../Types';
import { throwIfTrue } from '../utils/throwIfTrue'; import { throwIfTrue } from '../utils/throwIfTrue';
import { newTextDom } from '../../dom/DOMOperator'; import { newTextDom } from '../../dom/DOMOperator';
import { FlagUtils } from '../vnode/VNodeFlags'; import { FlagUtils } from '../vnode/VNodeFlags';
import { isNull } from '../../dom/utils/Common';
export function captureRender(): VNode | null { export function captureRender(): VNode | null {
return null; return null;
@ -26,7 +27,7 @@ export function captureRender(): VNode | null {
export function bubbleRender(processing: VNode) { export function bubbleRender(processing: VNode) {
const newText = processing.props; const newText = processing.props;
if (!processing.isCreated && processing.realNode != null) { if (!processing.isCreated && processing.realNode !== null) {
// 更新 // 更新
const oldText = processing.oldProps; const oldText = processing.oldProps;
// 如果文本不同,将其标记为更新 // 如果文本不同,将其标记为更新

View File

@ -165,7 +165,7 @@ function canCapturePromise(vNode: VNode | null): boolean {
// 处理Suspense子组件抛出的promise // 处理Suspense子组件抛出的promise
export function handleSuspenseChildThrowError(parent: VNode, processing: VNode, promise: PromiseType<any>): boolean { export function handleSuspenseChildThrowError(parent: VNode, processing: VNode, promise: PromiseType<any>): boolean {
let vNode = parent; let vNode: VNode | null = parent;
// 向上找到最近的不在fallback状态的Suspense并触发重新渲染 // 向上找到最近的不在fallback状态的Suspense并触发重新渲染
do { do {

View File

@ -35,7 +35,7 @@ export function callDerivedStateFromProps(
const newState = getDerivedStateFromProps(nextProps, oldState); const newState = getDerivedStateFromProps(nextProps, oldState);
// 组件未返回state,需要返回旧的preState // 组件未返回state,需要返回旧的preState
processing.state = newState === null || newState === undefined ? oldState : { ...oldState, ...newState }; processing.state = newState ? { ...oldState, ...newState } : oldState;
} }
} }

View File

@ -35,7 +35,7 @@ function callRenderQueue() {
try { try {
let callback; let callback;
while ((callback = renderQueue.shift())) { while (callback = renderQueue.shift()) {
callback(); callback();
} }

View File

@ -63,12 +63,12 @@ export function add(node: Node): void {
export function first(): Node | null { export function first(): Node | null {
const val: Node | null | undefined = taskQueue[0]; const val: Node | null | undefined = taskQueue[0];
return val !== undefined ? val : null; return val ?? null;
} }
export function shift(): Node | null { export function shift(): Node | null {
const val = taskQueue.shift(); const val = taskQueue.shift();
return val !== undefined ? val : null; return val ?? null;
} }
export function remove(node: Node) { export function remove(node: Node) {

View File

@ -136,7 +136,7 @@ export function createUndeterminedVNode(type, key, props, source: Source | null)
vNodeTag = typeMap[type.vtype]; vNodeTag = typeMap[type.vtype];
isLazy = type.vtype === TYPE_LAZY; isLazy = type.vtype === TYPE_LAZY;
} else { } else {
throw Error(`Component type is invalid, got: ${type == null ? type : componentType}`); throw Error(`Component type is invalid, got: ${type === null || type === undefined ? type : componentType}`);
} }
const vNode = newVirtualNode(vNodeTag, key, props); const vNode = newVirtualNode(vNodeTag, key, props);
@ -183,7 +183,7 @@ export function createTreeRootVNode(container) {
return vNode; return vNode;
} }
// TODO: 暂时保留给测试用例使用,后续修改测试用例 // 暂时保留给测试用例使用,后续修改测试用例
export function createVNode(tag: VNodeTag | string, ...secondArg) { export function createVNode(tag: VNodeTag | string, ...secondArg) {
let vNode = null; let vNode = null;
switch (tag) { switch (tag) {

View File

@ -36,71 +36,71 @@ export const ForceUpdate = /** */ 1 << 12; // For suspense
export const Clear = /** */ 1 << 13; export const Clear = /** */ 1 << 13;
const LifecycleEffectArr = Update | Callback | Ref | Snapshot; const LifecycleEffectArr = Update | Callback | Ref | Snapshot;
export class FlagUtils { export const FlagUtils = {
static removeFlag(node: VNode, flag: number) { removeFlag(node: VNode, flag: number) {
node.flags &= ~flag; node.flags &= ~flag;
} },
static removeLifecycleEffectFlags(node) { removeLifecycleEffectFlags(node) {
node.flags &= ~LifecycleEffectArr; node.flags &= ~LifecycleEffectArr;
} },
static hasAnyFlag(node: VNode) { hasAnyFlag(node: VNode) {
// 有标志位 // 有标志位
return node.flags !== InitFlag; return node.flags !== InitFlag;
} },
static hasFlag(node: VNode, flag) { hasFlag(node: VNode, flag) {
return (node.flags & flag) !== 0; return (node.flags & flag) !== 0;
} },
static setNoFlags(node: VNode) { setNoFlags(node: VNode) {
node.flags = InitFlag; node.flags = InitFlag;
} },
static markAddition(node: VNode) { markAddition(node: VNode) {
node.flags |= Addition; node.flags |= Addition;
} },
static setAddition(node: VNode) { setAddition(node: VNode) {
node.flags = Addition; node.flags = Addition;
} },
static markDirectAddition(node: VNode) { markDirectAddition(node: VNode) {
node.flags |= DirectAddition; node.flags |= DirectAddition;
} },
static markUpdate(node: VNode) { markUpdate(node: VNode) {
node.flags |= Update; node.flags |= Update;
} },
static setDeletion(node: VNode) { setDeletion(node: VNode) {
node.flags = Deletion; node.flags = Deletion;
} },
static markContentReset(node: VNode) { markContentReset(node: VNode) {
node.flags |= ResetText; node.flags |= ResetText;
} },
static markCallback(node: VNode) { markCallback(node: VNode) {
node.flags |= Callback; node.flags |= Callback;
} },
static markDidCapture(node: VNode) { markDidCapture(node: VNode) {
node.flags |= DidCapture; node.flags |= DidCapture;
} },
static markShouldCapture(node: VNode) { markShouldCapture(node: VNode) {
node.flags |= ShouldCapture; node.flags |= ShouldCapture;
} },
static markRef(node: VNode) { markRef(node: VNode) {
node.flags |= Ref; node.flags |= Ref;
} },
static markSnapshot(node: VNode) { markSnapshot(node: VNode) {
node.flags |= Snapshot; node.flags |= Snapshot;
} },
static markInterrupted(node: VNode) { markInterrupted(node: VNode) {
node.flags |= Interrupted; node.flags |= Interrupted;
} },
static markForceUpdate(node: VNode) { markForceUpdate(node: VNode) {
node.flags |= ForceUpdate; node.flags |= ForceUpdate;
} },
static markClear(node: VNode) { markClear(node: VNode) {
node.flags |= Clear; node.flags |= Clear;
} }
} }