Skip to content

Instantly share code, notes, and snippets.

@WeiGrand
Last active June 25, 2019 12:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save WeiGrand/f4d6255a371356485ed6d79a40e36083 to your computer and use it in GitHub Desktop.
Save WeiGrand/f4d6255a371356485ed6d79a40e36083 to your computer and use it in GitHub Desktop.
Fiber (虚拟栈实现)
const a1 = {name: 'a1', child: null, sibling: null, return: null};
const b1 = {name: 'b1', child: null, sibling: null, return: null};
const b2 = {name: 'b2', child: null, sibling: null, return: null};
const b3 = {name: 'b3', child: null, sibling: null, return: null};
const c1 = {name: 'c1', child: null, sibling: null, return: null};
const c2 = {name: 'c2', child: null, sibling: null, return: null};
const d1 = {name: 'd1', child: null, sibling: null, return: null};
const d2 = {name: 'd2', child: null, sibling: null, return: null};
a1.child = b1;
b1.sibling = b2;
b2.sibling = b3;
b2.child = c1;
b3.child = c2;
c1.child = d1;
d1.sibling = d2;
b1.return = b2.return = b3.return = a1;
c1.return = b2;
d1.return = d2.return = c1;
c2.return = b3;
/**
* a1 ---
* |
* |
* b1
* |
* |
* b2 ---
* | |
* | |
* | c1 ---
* | |
* | |
* | d1
* | |
* | |
* | d2
* b3 ---
* |
* |
* c2
*/
// workInProgress 当前用遍历的 Fiber 树
const log = console.log;
let nextUnitOfWork = a1;
// performUnitOfWork -> beginWork -> completeUnitOfWork -> completeWork
const workLoop = () => {
while (nextUnitOfWork !== null) {
nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
}
}
/**
* 用来遍历 Fiber 节点
* 深度优先访问子节点
* 子节点为空则开始执行 work
* @param workInProgress
* @returns {*}
*/
const performUnitOfWork = workInProgress => {
let next = beginWork(workInProgress);
if (next === null) {
next = completeUnitOfWork(workInProgress);
}
return next;
}
const beginWork = workInProgress => {
log('Work performed for ' + workInProgress.name);
return workInProgress.child;
}
/**
* 用来执行 work
* 执行完 work 看当前节点是否有相邻节点
* 有相邻节点则遍历相邻节点
* 无相邻节点则看是否有父节点
* 有父节点则将 workInProgress 设为 其父节点
* 没有父节点当前已经当了根节点 返回 空 结束循环
* @param workInProgress
* @returns {null|*}
*/
const completeUnitOfWork = workInProgress => {
while (true) {
let returnFiber = workInProgress.return;
let siblingFiber = workInProgress.sibling;
nextUnitOfWork = completeWork(workInProgress);
if (siblingFiber !== null) {
return siblingFiber;
} else if (returnFiber !== null) {
workInProgress = returnFiber;
} else {
return null;
}
}
}
const completeWork = workInProgress => {
log('Work completed for ' + workInProgress.name);
return null;
}
workLoop();
// Output
// Work performed for a1
// Work performed for b1
// Work completed for b1
// Work performed for b2
// Work performed for c1
// Work performed for d1
// Work completed for d1
// Work performed for d2
// Work completed for d2
// Work completed for c1
// Work completed for b2
// Work performed for b3
// Work performed for c2
// Work completed for c2
// Work completed for b3
// Work completed for a1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment