1. let nextFiberID = 1;
    
  2. const fiberIDMap = new WeakMap();
    
  3. 
    
  4. function getFiberUniqueID(fiber) {
    
  5.   if (!fiberIDMap.has(fiber)) {
    
  6.     fiberIDMap.set(fiber, nextFiberID++);
    
  7.   }
    
  8.   return fiberIDMap.get(fiber);
    
  9. }
    
  10. 
    
  11. function getFriendlyTag(tag) {
    
  12.   switch (tag) {
    
  13.     case 0:
    
  14.       return '[indeterminate]';
    
  15.     case 1:
    
  16.       return '[fn]';
    
  17.     case 2:
    
  18.       return '[class]';
    
  19.     case 3:
    
  20.       return '[root]';
    
  21.     case 4:
    
  22.       return '[portal]';
    
  23.     case 5:
    
  24.       return '[host]';
    
  25.     case 6:
    
  26.       return '[text]';
    
  27.     case 7:
    
  28.       return '[coroutine]';
    
  29.     case 8:
    
  30.       return '[handler]';
    
  31.     case 9:
    
  32.       return '[yield]';
    
  33.     case 10:
    
  34.       return '[frag]';
    
  35.     default:
    
  36.       throw new Error('Unknown tag.');
    
  37.   }
    
  38. }
    
  39. 
    
  40. function getFriendlyEffect(flags) {
    
  41.   const effects = {
    
  42.     1: 'Performed Work',
    
  43.     2: 'Placement',
    
  44.     4: 'Update',
    
  45.     8: 'Deletion',
    
  46.     16: 'Content reset',
    
  47.     32: 'Callback',
    
  48.     64: 'Err',
    
  49.     128: 'Ref',
    
  50.   };
    
  51.   return Object.keys(effects)
    
  52.     .filter(flag => flag & flags)
    
  53.     .map(flag => effects[flag])
    
  54.     .join(' & ');
    
  55. }
    
  56. 
    
  57. export default function describeFibers(rootFiber, workInProgress) {
    
  58.   let descriptions = {};
    
  59.   function acknowledgeFiber(fiber) {
    
  60.     if (!fiber) {
    
  61.       return null;
    
  62.     }
    
  63.     if (!fiber.return && fiber.tag !== 3) {
    
  64.       return null;
    
  65.     }
    
  66.     const id = getFiberUniqueID(fiber);
    
  67.     if (descriptions[id]) {
    
  68.       return id;
    
  69.     }
    
  70.     descriptions[id] = {};
    
  71.     Object.assign(descriptions[id], {
    
  72.       ...fiber,
    
  73.       id: id,
    
  74.       tag: getFriendlyTag(fiber.tag),
    
  75.       flags: getFriendlyEffect(fiber.flags),
    
  76.       type: fiber.type && '<' + (fiber.type.name || fiber.type) + '>',
    
  77.       stateNode: `[${typeof fiber.stateNode}]`,
    
  78.       return: acknowledgeFiber(fiber.return),
    
  79.       child: acknowledgeFiber(fiber.child),
    
  80.       sibling: acknowledgeFiber(fiber.sibling),
    
  81.       nextEffect: acknowledgeFiber(fiber.nextEffect),
    
  82.       firstEffect: acknowledgeFiber(fiber.firstEffect),
    
  83.       lastEffect: acknowledgeFiber(fiber.lastEffect),
    
  84.       alternate: acknowledgeFiber(fiber.alternate),
    
  85.     });
    
  86.     return id;
    
  87.   }
    
  88. 
    
  89.   const rootID = acknowledgeFiber(rootFiber);
    
  90.   const workInProgressID = acknowledgeFiber(workInProgress);
    
  91. 
    
  92.   let currentIDs = new Set();
    
  93.   function markAsCurrent(id) {
    
  94.     currentIDs.add(id);
    
  95.     const fiber = descriptions[id];
    
  96.     if (fiber.sibling) {
    
  97.       markAsCurrent(fiber.sibling);
    
  98.     }
    
  99.     if (fiber.child) {
    
  100.       markAsCurrent(fiber.child);
    
  101.     }
    
  102.   }
    
  103.   markAsCurrent(rootID);
    
  104. 
    
  105.   return {
    
  106.     descriptions,
    
  107.     rootID,
    
  108.     currentIDs: Array.from(currentIDs),
    
  109.     workInProgressID,
    
  110.   };
    
  111. }