@dark-engine/core
Version:
The lightweight and powerful UI rendering engine without dependencies and written in TypeScript (Browser, Node.js, Android, iOS, Windows, Linux, macOS)
94 lines (93 loc) • 2.61 kB
JavaScript
import { CLEANUP_HOST_MASK, DELETE_EFFECT_TAG, EFFECT_HOST_MASK, HOOK_DELIMETER } from '../constants';
function walk(fiber, onWalk) {
let shouldDeep = true;
let shouldStop = false;
const skip = () => (shouldDeep = false);
const stop = () => (shouldStop = true);
const stack = [fiber];
while (stack.length !== 0) {
const unit = stack.pop();
onWalk(unit, skip, stop);
if (shouldStop) break;
unit !== fiber && unit.next && stack.push(unit.next);
shouldDeep && unit.child && stack.push(unit.child);
shouldDeep = true;
}
}
function collectElements(fiber, transform) {
const elements = [];
walk(fiber, onWalkInCollectElements(elements, transform));
return elements;
}
function onWalkInCollectElements(elements, transform) {
return (fiber, skip) => {
if (fiber.el) {
!fiber.hook?.getIsPortal() && elements.push(transform(fiber));
return skip();
}
};
}
function getFiberWithElement(fiber) {
let $fiber = fiber;
while ($fiber) {
if ($fiber.el) return $fiber;
$fiber = $fiber.parent;
}
return $fiber;
}
function detectIsFiberAlive(fiber) {
let $fiber = fiber;
while ($fiber) {
if ($fiber.tag === DELETE_EFFECT_TAG) return false;
$fiber = $fiber.parent;
}
return Boolean(fiber);
}
function getSuspense(fiber, isPending) {
let suspense = fiber;
while (suspense) {
if (suspense.hook?.getIsSuspense() && (isPending ? suspense.hook.getIsPending() : true)) return suspense;
suspense = suspense.parent;
}
return null;
}
function resolveSuspense(fiber) {
return getSuspense(fiber, true) || getSuspense(fiber, false) || null;
}
function resolveBoundary(fiber) {
let boundary = fiber;
while (boundary) {
if (boundary.hook?.getIsBoundary()) return boundary;
boundary = boundary.parent;
}
return null;
}
function createHookLoc(rootId, idx, hook) {
const fiber = hook.owner;
let $fiber = fiber;
let loc = `${fiber.idx}${HOOK_DELIMETER}${idx}`;
while ($fiber) {
$fiber = $fiber.parent;
$fiber && (loc = `${$fiber.idx}.${loc}`);
}
loc = `[${rootId}]${loc}`;
return loc;
}
const createLoc = (rootId, idx, hook) => () => createHookLoc(rootId, idx, hook);
function notifyParents(fiber, alt = fiber) {
fiber.increment(alt.el ? 1 : alt.cec);
alt.mask & EFFECT_HOST_MASK && fiber.markHost(EFFECT_HOST_MASK);
alt.mask & CLEANUP_HOST_MASK && fiber.markHost(CLEANUP_HOST_MASK);
}
export {
walk,
collectElements,
getFiberWithElement,
detectIsFiberAlive,
resolveSuspense,
resolveBoundary,
createHookLoc,
createLoc,
notifyParents,
};
//# sourceMappingURL=walk.js.map