let nextFiberID = 1; const fiberIDMap = new WeakMap(); function getFiberUniqueID(fiber) { if (!fiberIDMap.has(fiber)) { fiberIDMap.set(fiber, nextFiberID++); } return fiberIDMap.get(fiber); } function getFriendlyTag(tag) { switch (tag) { case 0: return '[indeterminate]'; case 1: return '[fn]'; case 2: return '[class]'; case 3: return '[root]'; case 4: return '[portal]'; case 5: return '[host]'; case 6: return '[text]'; case 7: return '[coroutine]'; case 8: return '[handler]'; case 9: return '[yield]'; case 10: return '[frag]'; default: throw new Error('Unknown tag.'); } } function getFriendlyEffect(flags) { const effects = { 1: 'Performed Work', 2: 'Placement', 4: 'Update', 8: 'Deletion', 16: 'Content reset', 32: 'Callback', 64: 'Err', 128: 'Ref', }; return Object.keys(effects) .filter(flag => flag & flags) .map(flag => effects[flag]) .join(' & '); } export default function describeFibers(rootFiber, workInProgress) { let descriptions = {}; function acknowledgeFiber(fiber) { if (!fiber) { return null; } if (!fiber.return && fiber.tag !== 3) { return null; } const id = getFiberUniqueID(fiber); if (descriptions[id]) { return id; } descriptions[id] = {}; Object.assign(descriptions[id], { ...fiber, id: id, tag: getFriendlyTag(fiber.tag), flags: getFriendlyEffect(fiber.flags), type: fiber.type && '<' + (fiber.type.name || fiber.type) + '>', stateNode: `[${typeof fiber.stateNode}]`, return: acknowledgeFiber(fiber.return), child: acknowledgeFiber(fiber.child), sibling: acknowledgeFiber(fiber.sibling), nextEffect: acknowledgeFiber(fiber.nextEffect), firstEffect: acknowledgeFiber(fiber.firstEffect), lastEffect: acknowledgeFiber(fiber.lastEffect), alternate: acknowledgeFiber(fiber.alternate), }); return id; } const rootID = acknowledgeFiber(rootFiber); const workInProgressID = acknowledgeFiber(workInProgress); let currentIDs = new Set(); function markAsCurrent(id) { currentIDs.add(id); const fiber = descriptions[id]; if (fiber.sibling) { markAsCurrent(fiber.sibling); } if (fiber.child) { markAsCurrent(fiber.child); } } markAsCurrent(rootID); return { descriptions, rootID, currentIDs: Array.from(currentIDs), workInProgressID, }; }