Match-id-6e2cdb6edac0f6149760a50d07e710180a3f70b9
This commit is contained in:
commit
89c90b001e
|
@ -227,6 +227,8 @@ function buildVNodeTree(treeRoot: VNode) {
|
|||
}
|
||||
} while (true);
|
||||
|
||||
processing = null;
|
||||
|
||||
setExecuteMode(preMode);
|
||||
}
|
||||
|
||||
|
@ -272,7 +274,7 @@ export function launchUpdateFromVNode(vNode: VNode) {
|
|||
}
|
||||
|
||||
// 保存待刷新的节点
|
||||
treeRoot.toUpdateNodes.add(vNode);
|
||||
treeRoot.toUpdateNodes?.add(vNode);
|
||||
|
||||
if (checkMode(BySync) && // 非批量
|
||||
!checkMode(InRender)) { // 不是渲染阶段触发
|
||||
|
|
|
@ -160,39 +160,26 @@ function hideOrUnhideAllChildren(vNode, isHidden) {
|
|||
function attachRef(vNode: VNode) {
|
||||
const ref = vNode.ref;
|
||||
|
||||
if (ref !== null) {
|
||||
const instance = vNode.realNode;
|
||||
|
||||
let refType = typeof ref;
|
||||
if (refType === 'function') {
|
||||
ref(instance);
|
||||
} else if (refType === 'object') {
|
||||
(<RefType>ref).current = instance;
|
||||
} else {
|
||||
if (vNode.belongClassVNode && vNode.belongClassVNode.realNode) {
|
||||
vNode.belongClassVNode.realNode.refs[String(ref)] = instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
handleRef(vNode, ref, vNode.realNode);
|
||||
}
|
||||
|
||||
function detachRef(vNode: VNode, isOldRef?: boolean) {
|
||||
let ref = (isOldRef ? vNode.oldRef : vNode.ref);
|
||||
|
||||
if (ref !== null) {
|
||||
let refType = typeof ref;
|
||||
handleRef(vNode, ref, null);
|
||||
}
|
||||
|
||||
function handleRef(vNode: VNode, ref, val) {
|
||||
if (ref !== null && ref !== undefined) {
|
||||
const refType = typeof ref;
|
||||
|
||||
if (refType === 'function') {
|
||||
try {
|
||||
ref(null);
|
||||
} catch (error) {
|
||||
handleSubmitError(vNode, error);
|
||||
}
|
||||
ref(val);
|
||||
} else if (refType === 'object') {
|
||||
(<RefType>ref).current = null;
|
||||
(<RefType>ref).current = val;
|
||||
} else {
|
||||
if (vNode.belongClassVNode && vNode.belongClassVNode.realNode) {
|
||||
vNode.belongClassVNode.realNode.refs[String(ref)] = null;
|
||||
vNode.belongClassVNode.realNode.refs[String(ref)] = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,13 +35,10 @@ let lastRoot: VNode | null = null;
|
|||
|
||||
export function submitToRender(treeRoot) {
|
||||
treeRoot.shouldUpdate = treeRoot.childShouldUpdate;
|
||||
|
||||
const startVNode = getStartVNode();
|
||||
|
||||
// 置空task,让才能加入新的render任务
|
||||
treeRoot.task = null;
|
||||
|
||||
setProcessing(null);
|
||||
const startVNode = getStartVNode();
|
||||
|
||||
if (FlagUtils.hasAnyFlag(startVNode)) {
|
||||
// 把自己加上
|
||||
|
|
|
@ -2,65 +2,45 @@
|
|||
* 浏览器相关实现
|
||||
*/
|
||||
|
||||
export let now;
|
||||
|
||||
if (typeof performance === 'object' && typeof performance.now === 'function') {
|
||||
const localPerformance = performance;
|
||||
now = () => localPerformance.now();
|
||||
} else {
|
||||
const localDate = Date;
|
||||
const initialTime = localDate.now();
|
||||
now = () => localDate.now() - initialTime;
|
||||
}
|
||||
|
||||
let isMessageLoopRunning = false;
|
||||
let browserCallback = null;
|
||||
|
||||
// 默认每次只运行5ms
|
||||
const runTime = 5;
|
||||
let deadline = 0;
|
||||
|
||||
export function isOverTime() {
|
||||
return now() >= deadline;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 1、设置deadline;2、回调TaskExecutor传过来的browserCallback
|
||||
const callRenderTasks = () => {
|
||||
if (browserCallback == null) {
|
||||
if (browserCallback === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentTime = now();
|
||||
// 计算deadline
|
||||
deadline = currentTime + runTime;
|
||||
try {
|
||||
// 执行callback
|
||||
const hasMoreTask = browserCallback(
|
||||
currentTime,
|
||||
);
|
||||
const hasMoreTask = browserCallback();
|
||||
|
||||
if (!hasMoreTask) { // 没有更多task
|
||||
isMessageLoopRunning = false;
|
||||
browserCallback = null;
|
||||
} else {
|
||||
// 还有task,继续调用
|
||||
port.postMessage(null);
|
||||
port2.postMessage(null);
|
||||
}
|
||||
} catch (error) {
|
||||
port.postMessage(null);
|
||||
port2.postMessage(null);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
const channel = new MessageChannel();
|
||||
const port = channel.port2;
|
||||
channel.port1.onmessage = callRenderTasks;
|
||||
const { port1, port2 } = new MessageChannel();
|
||||
port1.onmessage = callRenderTasks;
|
||||
|
||||
export function requestBrowserCallback(callback) {
|
||||
browserCallback = callback;
|
||||
|
||||
if (!isMessageLoopRunning) {
|
||||
isMessageLoopRunning = true;
|
||||
port.postMessage(null);
|
||||
port2.postMessage(null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,9 +46,7 @@ function callRenderQueue() {
|
|||
try {
|
||||
for (; i < renderQueue.length; i++) {
|
||||
let callback = renderQueue[i];
|
||||
do {
|
||||
callback = callback();
|
||||
} while (callback !== null);
|
||||
callback();
|
||||
}
|
||||
renderQueue = null;
|
||||
} catch (error) {
|
||||
|
|
|
@ -5,10 +5,9 @@
|
|||
import {
|
||||
requestBrowserCallback,
|
||||
isOverTime,
|
||||
now,
|
||||
} from './BrowserAsync';
|
||||
|
||||
import {add, shift, first} from './TaskQueue';
|
||||
import { add, shift, first, remove } from './TaskQueue';
|
||||
|
||||
const ImmediatePriority = 1;
|
||||
const NormalPriority = 10;
|
||||
|
@ -16,89 +15,65 @@ const NormalPriority = 10;
|
|||
// 用于控制插入任务的顺序
|
||||
let idCounter = 1;
|
||||
|
||||
let currentPriorityLevel = NormalPriority;
|
||||
|
||||
// 正在执行task
|
||||
let isProcessing = false;
|
||||
|
||||
// 调度中,等待浏览器回调
|
||||
let isScheduling = false;
|
||||
|
||||
function runSync(callback, priorityLevel = NormalPriority) {
|
||||
const previousPriorityLevel = currentPriorityLevel;
|
||||
currentPriorityLevel = priorityLevel;
|
||||
|
||||
try {
|
||||
return callback();
|
||||
} finally {
|
||||
currentPriorityLevel = previousPriorityLevel;
|
||||
}
|
||||
}
|
||||
let isWaiting = false;
|
||||
|
||||
function runAsync(callback, priorityLevel= NormalPriority ) {
|
||||
let timeout;
|
||||
let increment;
|
||||
switch (priorityLevel) {
|
||||
case ImmediatePriority:
|
||||
timeout = -1;
|
||||
increment = -1;
|
||||
break;
|
||||
case NormalPriority:
|
||||
default:
|
||||
timeout = 5000;
|
||||
increment = 10000;
|
||||
break;
|
||||
}
|
||||
|
||||
const task = {
|
||||
id: idCounter++,
|
||||
callback,
|
||||
priorityLevel,
|
||||
expirationTime: now() + timeout,
|
||||
order: idCounter + increment,
|
||||
};
|
||||
|
||||
add(task);
|
||||
|
||||
if (!isScheduling && !isProcessing) {
|
||||
isScheduling = true;
|
||||
if (!isWaiting && !isProcessing) {
|
||||
isWaiting = true;
|
||||
requestBrowserCallback(callTasks);
|
||||
}
|
||||
|
||||
return task;
|
||||
}
|
||||
|
||||
function callTasks(initialTime) {
|
||||
isScheduling = false;
|
||||
function callTasks() {
|
||||
isWaiting = false;
|
||||
isProcessing = true;
|
||||
|
||||
let task = null;
|
||||
const previousPriorityLevel = currentPriorityLevel;
|
||||
try {
|
||||
let currentTime = initialTime;
|
||||
task = first();
|
||||
|
||||
// 循环执行task
|
||||
while (task !== null) {
|
||||
if (
|
||||
task.expirationTime > currentTime &&
|
||||
isOverTime()
|
||||
) {
|
||||
// 任务的过期时间大于当前时间(没达到此任务的过期时间)且超过了deadline
|
||||
if (isOverTime()) {
|
||||
// 超过了deadline
|
||||
break;
|
||||
}
|
||||
|
||||
const callback = task.callback;
|
||||
if (typeof callback === 'function') {
|
||||
if (callback !== null) {
|
||||
task.callback = null;
|
||||
currentPriorityLevel = task.priorityLevel;
|
||||
const didUserCallbackTimeout = task.expirationTime <= currentTime;
|
||||
|
||||
const continuationCallback = callback(didUserCallbackTimeout);
|
||||
currentTime = now();
|
||||
// 执行callback返回函数,重置callback
|
||||
if (typeof continuationCallback === 'function') {
|
||||
task.callback = continuationCallback;
|
||||
} else {
|
||||
callback();
|
||||
|
||||
if (task === first()) {
|
||||
shift();
|
||||
}
|
||||
} else { // 执行任务中可能插入了新任务
|
||||
remove(task);
|
||||
}
|
||||
} else {
|
||||
shift();
|
||||
|
@ -110,8 +85,6 @@ function callTasks(initialTime) {
|
|||
// 返回是否还有任务,如果有,说明是被中断了
|
||||
return task !== null;
|
||||
} finally {
|
||||
task = null;
|
||||
currentPriorityLevel = previousPriorityLevel;
|
||||
isProcessing = false;
|
||||
}
|
||||
}
|
||||
|
@ -120,16 +93,9 @@ function cancelTask(task) {
|
|||
task.callback = null;
|
||||
}
|
||||
|
||||
function getCurrentPriorityLevel() {
|
||||
return currentPriorityLevel;
|
||||
}
|
||||
|
||||
export {
|
||||
ImmediatePriority,
|
||||
NormalPriority,
|
||||
runSync,
|
||||
runAsync,
|
||||
cancelTask,
|
||||
getCurrentPriorityLevel,
|
||||
now,
|
||||
};
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
type Queue = Array<Node>;
|
||||
type Node = {
|
||||
id: number;
|
||||
expirationTime: number;
|
||||
order: number;
|
||||
};
|
||||
|
||||
// 任务队列
|
||||
|
@ -15,9 +15,7 @@ export function add(node: Node): void {
|
|||
// 查找第一个大于等于 value 的下标,都比 value 小则返回 -1
|
||||
const idx = getBiggerIdx(node);
|
||||
|
||||
if (idx === 0) {
|
||||
taskQueue.unshift(node);
|
||||
} else if (idx === -1) {
|
||||
if (idx === -1) {
|
||||
taskQueue.push(node);
|
||||
} else {
|
||||
taskQueue.splice(idx, 0, node);
|
||||
|
@ -32,11 +30,12 @@ function getBiggerIdx(node: Node) {
|
|||
while (left <= right) {
|
||||
const middle = left + ((right - left) >> 1);
|
||||
|
||||
if (compare(taskQueue[middle], node) > 0)
|
||||
if (compare(taskQueue[middle], node) > 0) {
|
||||
right = middle - 1;
|
||||
else
|
||||
} else {
|
||||
left = middle + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return (left < taskQueue.length) ? left : -1;
|
||||
}
|
||||
|
@ -51,8 +50,12 @@ export function shift(): Node | null {
|
|||
return val !== undefined ? val : null;
|
||||
}
|
||||
|
||||
export function remove(node: Node) {
|
||||
taskQueue.splice(taskQueue.indexOf(node), 1);
|
||||
}
|
||||
|
||||
function compare(a: Node, b: Node) {
|
||||
// 优先先用index排序,其次用id
|
||||
const diff = a.expirationTime - b.expirationTime;
|
||||
const diff = a.order - b.order;
|
||||
return diff !== 0 ? diff : a.id - b.id;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue