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