Best JavaScript code snippet using playwright-internal
ReactFiberBeginWork.new.js
Source:ReactFiberBeginWork.new.js  
...1569    suspenseContext,1570    (ForceSuspenseFallback: SuspenseContext),1571  );1572}1573function getRemainingWorkInPrimaryTree(1574  current: Fiber,1575  workInProgress: Fiber,1576  renderExpirationTime,1577) {1578  const currentChildExpirationTime = current.childExpirationTime;1579  const currentSuspenseState: SuspenseState = current.memoizedState;1580  if (currentSuspenseState !== null) {1581    // This boundary already timed out. Check if this render includes the level1582    // that previously suspended.1583    const baseTime = currentSuspenseState.baseTime;1584    if (baseTime !== NoWork && baseTime < renderExpirationTime) {1585      // There's pending work at a lower level that might now be unblocked.1586      return baseTime;1587    }1588  }1589  if (currentChildExpirationTime < renderExpirationTime) {1590    // The highest priority remaining work is not part of this render. So the1591    // remaining work has not changed.1592    return currentChildExpirationTime;1593  }1594  if ((workInProgress.mode & BlockingMode) !== NoMode) {1595    // The highest priority remaining work is part of this render. Since we only1596    // keep track of the highest level, we don't know if there's a lower1597    // priority level scheduled. As a compromise, we'll render at the lowest1598    // known level in the entire tree, since that will include everything.1599    // TODO: If expirationTime were a bitmask where each bit represents a1600    // separate task thread, this would be: currentChildBits & ~renderBits1601    const root = getWorkInProgressRoot();1602    if (root !== null) {1603      const lastPendingTime = root.lastPendingTime;1604      if (lastPendingTime < renderExpirationTime) {1605        return lastPendingTime;1606      }1607    }1608  }1609  // In legacy mode, there's no work left.1610  return NoWork;1611}1612function updateSuspenseComponent(1613  current,1614  workInProgress,1615  renderExpirationTime,1616) {1617  const mode = workInProgress.mode;1618  const nextProps = workInProgress.pendingProps;1619  // This is used by DevTools to force a boundary to suspend.1620  if (__DEV__) {1621    if (shouldSuspend(workInProgress)) {1622      workInProgress.effectTag |= DidCapture;1623    }1624  }1625  let suspenseContext: SuspenseContext = suspenseStackCursor.current;1626  let nextDidTimeout = false;1627  const didSuspend = (workInProgress.effectTag & DidCapture) !== NoEffect;1628  if (1629    didSuspend ||1630    shouldRemainOnFallback(1631      suspenseContext,1632      current,1633      workInProgress,1634      renderExpirationTime,1635    )1636  ) {1637    // Something in this boundary's subtree already suspended. Switch to1638    // rendering the fallback children.1639    nextDidTimeout = true;1640    workInProgress.effectTag &= ~DidCapture;1641  } else {1642    // Attempting the main content1643    if (1644      current === null ||1645      (current.memoizedState: null | SuspenseState) !== null1646    ) {1647      // This is a new mount or this boundary is already showing a fallback state.1648      // Mark this subtree context as having at least one invisible parent that could1649      // handle the fallback state.1650      // Boundaries without fallbacks or should be avoided are not considered since1651      // they cannot handle preferred fallback states.1652      if (1653        nextProps.fallback !== undefined &&1654        nextProps.unstable_avoidThisFallback !== true1655      ) {1656        suspenseContext = addSubtreeSuspenseContext(1657          suspenseContext,1658          InvisibleParentSuspenseContext,1659        );1660      }1661    }1662  }1663  suspenseContext = setDefaultShallowSuspenseContext(suspenseContext);1664  pushSuspenseContext(workInProgress, suspenseContext);1665  // This next part is a bit confusing. If the children timeout, we switch to1666  // showing the fallback children in place of the "primary" children.1667  // However, we don't want to delete the primary children because then their1668  // state will be lost (both the React state and the host state, e.g.1669  // uncontrolled form inputs). Instead we keep them mounted and hide them.1670  // Both the fallback children AND the primary children are rendered at the1671  // same time. Once the primary children are un-suspended, we can delete1672  // the fallback children â don't need to preserve their state.1673  //1674  // The two sets of children are siblings in the host environment, but1675  // semantically, for purposes of reconciliation, they are two separate sets.1676  // So we store them using two fragment fibers.1677  //1678  // However, we want to avoid allocating extra fibers for every placeholder.1679  // They're only necessary when the children time out, because that's the1680  // only time when both sets are mounted.1681  //1682  // So, the extra fragment fibers are only used if the children time out.1683  // Otherwise, we render the primary children directly. This requires some1684  // custom reconciliation logic to preserve the state of the primary1685  // children. It's essentially a very basic form of re-parenting.1686  if (current === null) {1687    // If we're currently hydrating, try to hydrate this boundary.1688    // But only if this has a fallback.1689    if (nextProps.fallback !== undefined) {1690      tryToClaimNextHydratableInstance(workInProgress);1691      // This could've been a dehydrated suspense component.1692      if (enableSuspenseServerRenderer) {1693        const suspenseState: null | SuspenseState =1694          workInProgress.memoizedState;1695        if (suspenseState !== null) {1696          const dehydrated = suspenseState.dehydrated;1697          if (dehydrated !== null) {1698            return mountDehydratedSuspenseComponent(1699              workInProgress,1700              dehydrated,1701              renderExpirationTime,1702            );1703          }1704        }1705      }1706    }1707    // This is the initial mount. This branch is pretty simple because there's1708    // no previous state that needs to be preserved.1709    if (nextDidTimeout) {1710      // Mount separate fragments for primary and fallback children.1711      const nextFallbackChildren = nextProps.fallback;1712      const primaryChildFragment = createFiberFromFragment(1713        null,1714        mode,1715        NoWork,1716        null,1717      );1718      primaryChildFragment.return = workInProgress;1719      if ((workInProgress.mode & BlockingMode) === NoMode) {1720        // Outside of blocking mode, we commit the effects from the1721        // partially completed, timed-out tree, too.1722        const progressedState: SuspenseState = workInProgress.memoizedState;1723        const progressedPrimaryChild: Fiber | null =1724          progressedState !== null1725            ? (workInProgress.child: any).child1726            : (workInProgress.child: any);1727        primaryChildFragment.child = progressedPrimaryChild;1728        let progressedChild = progressedPrimaryChild;1729        while (progressedChild !== null) {1730          progressedChild.return = primaryChildFragment;1731          progressedChild = progressedChild.sibling;1732        }1733      }1734      const fallbackChildFragment = createFiberFromFragment(1735        nextFallbackChildren,1736        mode,1737        renderExpirationTime,1738        null,1739      );1740      fallbackChildFragment.return = workInProgress;1741      primaryChildFragment.sibling = fallbackChildFragment;1742      // Skip the primary children, and continue working on the1743      // fallback children.1744      workInProgress.memoizedState = mountSuspenseState(renderExpirationTime);1745      workInProgress.child = primaryChildFragment;1746      return fallbackChildFragment;1747    } else {1748      // Mount the primary children without an intermediate fragment fiber.1749      const nextPrimaryChildren = nextProps.children;1750      workInProgress.memoizedState = null;1751      return (workInProgress.child = mountChildFibers(1752        workInProgress,1753        null,1754        nextPrimaryChildren,1755        renderExpirationTime,1756      ));1757    }1758  } else {1759    // This is an update. This branch is more complicated because we need to1760    // ensure the state of the primary children is preserved.1761    const prevState: null | SuspenseState = current.memoizedState;1762    if (prevState !== null) {1763      if (enableSuspenseServerRenderer) {1764        const dehydrated = prevState.dehydrated;1765        if (dehydrated !== null) {1766          if (!didSuspend) {1767            return updateDehydratedSuspenseComponent(1768              current,1769              workInProgress,1770              dehydrated,1771              prevState,1772              renderExpirationTime,1773            );1774          } else if (1775            (workInProgress.memoizedState: null | SuspenseState) !== null1776          ) {1777            // Something suspended and we should still be in dehydrated mode.1778            // Leave the existing child in place.1779            workInProgress.child = current.child;1780            // The dehydrated completion pass expects this flag to be there1781            // but the normal suspense pass doesn't.1782            workInProgress.effectTag |= DidCapture;1783            return null;1784          } else {1785            // Suspended but we should no longer be in dehydrated mode.1786            // Therefore we now have to render the fallback. Wrap the children1787            // in a fragment fiber to keep them separate from the fallback1788            // children.1789            const nextFallbackChildren = nextProps.fallback;1790            const primaryChildFragment = createFiberFromFragment(1791              // It shouldn't matter what the pending props are because we aren't1792              // going to render this fragment.1793              null,1794              mode,1795              NoWork,1796              null,1797            );1798            primaryChildFragment.return = workInProgress;1799            // This is always null since we never want the previous child1800            // that we're not going to hydrate.1801            primaryChildFragment.child = null;1802            if ((workInProgress.mode & BlockingMode) === NoMode) {1803              // Outside of blocking mode, we commit the effects from the1804              // partially completed, timed-out tree, too.1805              let progressedChild = (primaryChildFragment.child =1806                workInProgress.child);1807              while (progressedChild !== null) {1808                progressedChild.return = primaryChildFragment;1809                progressedChild = progressedChild.sibling;1810              }1811            } else {1812              // We will have dropped the effect list which contains the deletion.1813              // We need to reconcile to delete the current child.1814              reconcileChildFibers(1815                workInProgress,1816                current.child,1817                null,1818                renderExpirationTime,1819              );1820            }1821            // Because primaryChildFragment is a new fiber that we're inserting as the1822            // parent of a new tree, we need to set its treeBaseDuration.1823            if (enableProfilerTimer && workInProgress.mode & ProfileMode) {1824              // treeBaseDuration is the sum of all the child tree base durations.1825              let treeBaseDuration = 0;1826              let hiddenChild = primaryChildFragment.child;1827              while (hiddenChild !== null) {1828                treeBaseDuration += hiddenChild.treeBaseDuration;1829                hiddenChild = hiddenChild.sibling;1830              }1831              primaryChildFragment.treeBaseDuration = treeBaseDuration;1832            }1833            // Create a fragment from the fallback children, too.1834            const fallbackChildFragment = createFiberFromFragment(1835              nextFallbackChildren,1836              mode,1837              renderExpirationTime,1838              null,1839            );1840            fallbackChildFragment.return = workInProgress;1841            primaryChildFragment.sibling = fallbackChildFragment;1842            fallbackChildFragment.effectTag |= Placement;1843            primaryChildFragment.childExpirationTime = getRemainingWorkInPrimaryTree(1844              current,1845              workInProgress,1846              renderExpirationTime,1847            );1848            workInProgress.memoizedState = updateSuspenseState(1849              current.memoizedState,1850              renderExpirationTime,1851            );1852            workInProgress.child = primaryChildFragment;1853            // Skip the primary children, and continue working on the1854            // fallback children.1855            return fallbackChildFragment;1856          }1857        }1858      }1859      // The current tree already timed out. That means each child set is1860      // wrapped in a fragment fiber.1861      const currentPrimaryChildFragment: Fiber = (current.child: any);1862      const currentFallbackChildFragment: Fiber = (currentPrimaryChildFragment.sibling: any);1863      if (nextDidTimeout) {1864        // Still timed out. Reuse the current primary children by cloning1865        // its fragment. We're going to skip over these entirely.1866        const nextFallbackChildren = nextProps.fallback;1867        const primaryChildFragment = createWorkInProgress(1868          currentPrimaryChildFragment,1869          currentPrimaryChildFragment.pendingProps,1870        );1871        primaryChildFragment.return = workInProgress;1872        if ((workInProgress.mode & BlockingMode) === NoMode) {1873          // Outside of blocking mode, we commit the effects from the1874          // partially completed, timed-out tree, too.1875          const progressedState: SuspenseState = workInProgress.memoizedState;1876          const progressedPrimaryChild: Fiber | null =1877            progressedState !== null1878              ? (workInProgress.child: any).child1879              : (workInProgress.child: any);1880          if (progressedPrimaryChild !== currentPrimaryChildFragment.child) {1881            primaryChildFragment.child = progressedPrimaryChild;1882            let progressedChild = progressedPrimaryChild;1883            while (progressedChild !== null) {1884              progressedChild.return = primaryChildFragment;1885              progressedChild = progressedChild.sibling;1886            }1887          }1888        }1889        // Because primaryChildFragment is a new fiber that we're inserting as the1890        // parent of a new tree, we need to set its treeBaseDuration.1891        if (enableProfilerTimer && workInProgress.mode & ProfileMode) {1892          // treeBaseDuration is the sum of all the child tree base durations.1893          let treeBaseDuration = 0;1894          let hiddenChild = primaryChildFragment.child;1895          while (hiddenChild !== null) {1896            treeBaseDuration += hiddenChild.treeBaseDuration;1897            hiddenChild = hiddenChild.sibling;1898          }1899          primaryChildFragment.treeBaseDuration = treeBaseDuration;1900        }1901        // Clone the fallback child fragment, too. These we'll continue1902        // working on.1903        const fallbackChildFragment = createWorkInProgress(1904          currentFallbackChildFragment,1905          nextFallbackChildren,1906        );1907        fallbackChildFragment.return = workInProgress;1908        primaryChildFragment.sibling = fallbackChildFragment;1909        primaryChildFragment.childExpirationTime = getRemainingWorkInPrimaryTree(1910          current,1911          workInProgress,1912          renderExpirationTime,1913        );1914        // Skip the primary children, and continue working on the1915        // fallback children.1916        workInProgress.memoizedState = updateSuspenseState(1917          current.memoizedState,1918          renderExpirationTime,1919        );1920        workInProgress.child = primaryChildFragment;1921        return fallbackChildFragment;1922      } else {1923        // No longer suspended. Switch back to showing the primary children,1924        // and remove the intermediate fragment fiber.1925        const nextPrimaryChildren = nextProps.children;1926        const currentPrimaryChild = currentPrimaryChildFragment.child;1927        const primaryChild = reconcileChildFibers(1928          workInProgress,1929          currentPrimaryChild,1930          nextPrimaryChildren,1931          renderExpirationTime,1932        );1933        // If this render doesn't suspend, we need to delete the fallback1934        // children. Wait until the complete phase, after we've confirmed the1935        // fallback is no longer needed.1936        // TODO: Would it be better to store the fallback fragment on1937        // the stateNode?1938        // Continue rendering the children, like we normally do.1939        workInProgress.memoizedState = null;1940        return (workInProgress.child = primaryChild);1941      }1942    } else {1943      // The current tree has not already timed out. That means the primary1944      // children are not wrapped in a fragment fiber.1945      const currentPrimaryChild = current.child;1946      if (nextDidTimeout) {1947        // Timed out. Wrap the children in a fragment fiber to keep them1948        // separate from the fallback children.1949        const nextFallbackChildren = nextProps.fallback;1950        const primaryChildFragment = createFiberFromFragment(1951          // It shouldn't matter what the pending props are because we aren't1952          // going to render this fragment.1953          null,1954          mode,1955          NoWork,1956          null,1957        );1958        primaryChildFragment.return = workInProgress;1959        primaryChildFragment.child = currentPrimaryChild;1960        if (currentPrimaryChild !== null) {1961          currentPrimaryChild.return = primaryChildFragment;1962        }1963        // Even though we're creating a new fiber, there are no new children,1964        // because we're reusing an already mounted tree. So we don't need to1965        // schedule a placement.1966        // primaryChildFragment.effectTag |= Placement;1967        if ((workInProgress.mode & BlockingMode) === NoMode) {1968          // Outside of blocking mode, we commit the effects from the1969          // partially completed, timed-out tree, too.1970          const progressedState: SuspenseState = workInProgress.memoizedState;1971          const progressedPrimaryChild: Fiber | null =1972            progressedState !== null1973              ? (workInProgress.child: any).child1974              : (workInProgress.child: any);1975          primaryChildFragment.child = progressedPrimaryChild;1976          let progressedChild = progressedPrimaryChild;1977          while (progressedChild !== null) {1978            progressedChild.return = primaryChildFragment;1979            progressedChild = progressedChild.sibling;1980          }1981        }1982        // Because primaryChildFragment is a new fiber that we're inserting as the1983        // parent of a new tree, we need to set its treeBaseDuration.1984        if (enableProfilerTimer && workInProgress.mode & ProfileMode) {1985          // treeBaseDuration is the sum of all the child tree base durations.1986          let treeBaseDuration = 0;1987          let hiddenChild = primaryChildFragment.child;1988          while (hiddenChild !== null) {1989            treeBaseDuration += hiddenChild.treeBaseDuration;1990            hiddenChild = hiddenChild.sibling;1991          }1992          primaryChildFragment.treeBaseDuration = treeBaseDuration;1993        }1994        // Create a fragment from the fallback children, too.1995        const fallbackChildFragment = createFiberFromFragment(1996          nextFallbackChildren,1997          mode,1998          renderExpirationTime,1999          null,2000        );2001        fallbackChildFragment.return = workInProgress;2002        primaryChildFragment.sibling = fallbackChildFragment;2003        fallbackChildFragment.effectTag |= Placement;2004        primaryChildFragment.childExpirationTime = getRemainingWorkInPrimaryTree(2005          current,2006          workInProgress,2007          renderExpirationTime,2008        );2009        // Skip the primary children, and continue working on the2010        // fallback children.2011        workInProgress.memoizedState = mountSuspenseState(renderExpirationTime);2012        workInProgress.child = primaryChildFragment;2013        return fallbackChildFragment;2014      } else {2015        // Still haven't timed out. Continue rendering the children, like we2016        // normally do.2017        workInProgress.memoizedState = null;2018        const nextPrimaryChildren = nextProps.children;...ReactFiberBeginWork.old.js
Source:ReactFiberBeginWork.old.js  
...1569    suspenseContext,1570    (ForceSuspenseFallback: SuspenseContext),1571  );1572}1573function getRemainingWorkInPrimaryTree(1574  current: Fiber,1575  workInProgress: Fiber,1576  renderExpirationTime,1577) {1578  const currentChildExpirationTime = current.childExpirationTime;1579  const currentSuspenseState: SuspenseState = current.memoizedState;1580  if (currentSuspenseState !== null) {1581    // This boundary already timed out. Check if this render includes the level1582    // that previously suspended.1583    const baseTime = currentSuspenseState.baseTime;1584    if (baseTime !== NoWork && baseTime < renderExpirationTime) {1585      // There's pending work at a lower level that might now be unblocked.1586      return baseTime;1587    }1588  }1589  if (currentChildExpirationTime < renderExpirationTime) {1590    // The highest priority remaining work is not part of this render. So the1591    // remaining work has not changed.1592    return currentChildExpirationTime;1593  }1594  if ((workInProgress.mode & BlockingMode) !== NoMode) {1595    // The highest priority remaining work is part of this render. Since we only1596    // keep track of the highest level, we don't know if there's a lower1597    // priority level scheduled. As a compromise, we'll render at the lowest1598    // known level in the entire tree, since that will include everything.1599    // TODO: If expirationTime were a bitmask where each bit represents a1600    // separate task thread, this would be: currentChildBits & ~renderBits1601    const root = getWorkInProgressRoot();1602    if (root !== null) {1603      const lastPendingTime = root.lastPendingTime;1604      if (lastPendingTime < renderExpirationTime) {1605        return lastPendingTime;1606      }1607    }1608  }1609  // In legacy mode, there's no work left.1610  return NoWork;1611}1612function updateSuspenseComponent(1613  current,1614  workInProgress,1615  renderExpirationTime,1616) {1617  const mode = workInProgress.mode;1618  const nextProps = workInProgress.pendingProps;1619  // This is used by DevTools to force a boundary to suspend.1620  if (__DEV__) {1621    if (shouldSuspend(workInProgress)) {1622      workInProgress.effectTag |= DidCapture;1623    }1624  }1625  let suspenseContext: SuspenseContext = suspenseStackCursor.current;1626  let nextDidTimeout = false;1627  const didSuspend = (workInProgress.effectTag & DidCapture) !== NoEffect;1628  if (1629    didSuspend ||1630    shouldRemainOnFallback(1631      suspenseContext,1632      current,1633      workInProgress,1634      renderExpirationTime,1635    )1636  ) {1637    // Something in this boundary's subtree already suspended. Switch to1638    // rendering the fallback children.1639    nextDidTimeout = true;1640    workInProgress.effectTag &= ~DidCapture;1641  } else {1642    // Attempting the main content1643    if (1644      current === null ||1645      (current.memoizedState: null | SuspenseState) !== null1646    ) {1647      // This is a new mount or this boundary is already showing a fallback state.1648      // Mark this subtree context as having at least one invisible parent that could1649      // handle the fallback state.1650      // Boundaries without fallbacks or should be avoided are not considered since1651      // they cannot handle preferred fallback states.1652      if (1653        nextProps.fallback !== undefined &&1654        nextProps.unstable_avoidThisFallback !== true1655      ) {1656        suspenseContext = addSubtreeSuspenseContext(1657          suspenseContext,1658          InvisibleParentSuspenseContext,1659        );1660      }1661    }1662  }1663  suspenseContext = setDefaultShallowSuspenseContext(suspenseContext);1664  pushSuspenseContext(workInProgress, suspenseContext);1665  // This next part is a bit confusing. If the children timeout, we switch to1666  // showing the fallback children in place of the "primary" children.1667  // However, we don't want to delete the primary children because then their1668  // state will be lost (both the React state and the host state, e.g.1669  // uncontrolled form inputs). Instead we keep them mounted and hide them.1670  // Both the fallback children AND the primary children are rendered at the1671  // same time. Once the primary children are un-suspended, we can delete1672  // the fallback children â don't need to preserve their state.1673  //1674  // The two sets of children are siblings in the host environment, but1675  // semantically, for purposes of reconciliation, they are two separate sets.1676  // So we store them using two fragment fibers.1677  //1678  // However, we want to avoid allocating extra fibers for every placeholder.1679  // They're only necessary when the children time out, because that's the1680  // only time when both sets are mounted.1681  //1682  // So, the extra fragment fibers are only used if the children time out.1683  // Otherwise, we render the primary children directly. This requires some1684  // custom reconciliation logic to preserve the state of the primary1685  // children. It's essentially a very basic form of re-parenting.1686  if (current === null) {1687    // If we're currently hydrating, try to hydrate this boundary.1688    // But only if this has a fallback.1689    if (nextProps.fallback !== undefined) {1690      tryToClaimNextHydratableInstance(workInProgress);1691      // This could've been a dehydrated suspense component.1692      if (enableSuspenseServerRenderer) {1693        const suspenseState: null | SuspenseState =1694          workInProgress.memoizedState;1695        if (suspenseState !== null) {1696          const dehydrated = suspenseState.dehydrated;1697          if (dehydrated !== null) {1698            return mountDehydratedSuspenseComponent(1699              workInProgress,1700              dehydrated,1701              renderExpirationTime,1702            );1703          }1704        }1705      }1706    }1707    // This is the initial mount. This branch is pretty simple because there's1708    // no previous state that needs to be preserved.1709    if (nextDidTimeout) {1710      // Mount separate fragments for primary and fallback children.1711      const nextFallbackChildren = nextProps.fallback;1712      const primaryChildFragment = createFiberFromFragment(1713        null,1714        mode,1715        NoWork,1716        null,1717      );1718      primaryChildFragment.return = workInProgress;1719      if ((workInProgress.mode & BlockingMode) === NoMode) {1720        // Outside of blocking mode, we commit the effects from the1721        // partially completed, timed-out tree, too.1722        const progressedState: SuspenseState = workInProgress.memoizedState;1723        const progressedPrimaryChild: Fiber | null =1724          progressedState !== null1725            ? (workInProgress.child: any).child1726            : (workInProgress.child: any);1727        primaryChildFragment.child = progressedPrimaryChild;1728        let progressedChild = progressedPrimaryChild;1729        while (progressedChild !== null) {1730          progressedChild.return = primaryChildFragment;1731          progressedChild = progressedChild.sibling;1732        }1733      }1734      const fallbackChildFragment = createFiberFromFragment(1735        nextFallbackChildren,1736        mode,1737        renderExpirationTime,1738        null,1739      );1740      fallbackChildFragment.return = workInProgress;1741      primaryChildFragment.sibling = fallbackChildFragment;1742      // Skip the primary children, and continue working on the1743      // fallback children.1744      workInProgress.memoizedState = mountSuspenseState(renderExpirationTime);1745      workInProgress.child = primaryChildFragment;1746      return fallbackChildFragment;1747    } else {1748      // Mount the primary children without an intermediate fragment fiber.1749      const nextPrimaryChildren = nextProps.children;1750      workInProgress.memoizedState = null;1751      return (workInProgress.child = mountChildFibers(1752        workInProgress,1753        null,1754        nextPrimaryChildren,1755        renderExpirationTime,1756      ));1757    }1758  } else {1759    // This is an update. This branch is more complicated because we need to1760    // ensure the state of the primary children is preserved.1761    const prevState: null | SuspenseState = current.memoizedState;1762    if (prevState !== null) {1763      if (enableSuspenseServerRenderer) {1764        const dehydrated = prevState.dehydrated;1765        if (dehydrated !== null) {1766          if (!didSuspend) {1767            return updateDehydratedSuspenseComponent(1768              current,1769              workInProgress,1770              dehydrated,1771              prevState,1772              renderExpirationTime,1773            );1774          } else if (1775            (workInProgress.memoizedState: null | SuspenseState) !== null1776          ) {1777            // Something suspended and we should still be in dehydrated mode.1778            // Leave the existing child in place.1779            workInProgress.child = current.child;1780            // The dehydrated completion pass expects this flag to be there1781            // but the normal suspense pass doesn't.1782            workInProgress.effectTag |= DidCapture;1783            return null;1784          } else {1785            // Suspended but we should no longer be in dehydrated mode.1786            // Therefore we now have to render the fallback. Wrap the children1787            // in a fragment fiber to keep them separate from the fallback1788            // children.1789            const nextFallbackChildren = nextProps.fallback;1790            const primaryChildFragment = createFiberFromFragment(1791              // It shouldn't matter what the pending props are because we aren't1792              // going to render this fragment.1793              null,1794              mode,1795              NoWork,1796              null,1797            );1798            primaryChildFragment.return = workInProgress;1799            // This is always null since we never want the previous child1800            // that we're not going to hydrate.1801            primaryChildFragment.child = null;1802            if ((workInProgress.mode & BlockingMode) === NoMode) {1803              // Outside of blocking mode, we commit the effects from the1804              // partially completed, timed-out tree, too.1805              let progressedChild = (primaryChildFragment.child =1806                workInProgress.child);1807              while (progressedChild !== null) {1808                progressedChild.return = primaryChildFragment;1809                progressedChild = progressedChild.sibling;1810              }1811            } else {1812              // We will have dropped the effect list which contains the deletion.1813              // We need to reconcile to delete the current child.1814              reconcileChildFibers(1815                workInProgress,1816                current.child,1817                null,1818                renderExpirationTime,1819              );1820            }1821            // Because primaryChildFragment is a new fiber that we're inserting as the1822            // parent of a new tree, we need to set its treeBaseDuration.1823            if (enableProfilerTimer && workInProgress.mode & ProfileMode) {1824              // treeBaseDuration is the sum of all the child tree base durations.1825              let treeBaseDuration = 0;1826              let hiddenChild = primaryChildFragment.child;1827              while (hiddenChild !== null) {1828                treeBaseDuration += hiddenChild.treeBaseDuration;1829                hiddenChild = hiddenChild.sibling;1830              }1831              primaryChildFragment.treeBaseDuration = treeBaseDuration;1832            }1833            // Create a fragment from the fallback children, too.1834            const fallbackChildFragment = createFiberFromFragment(1835              nextFallbackChildren,1836              mode,1837              renderExpirationTime,1838              null,1839            );1840            fallbackChildFragment.return = workInProgress;1841            primaryChildFragment.sibling = fallbackChildFragment;1842            fallbackChildFragment.effectTag |= Placement;1843            primaryChildFragment.childExpirationTime = getRemainingWorkInPrimaryTree(1844              current,1845              workInProgress,1846              renderExpirationTime,1847            );1848            workInProgress.memoizedState = updateSuspenseState(1849              current.memoizedState,1850              renderExpirationTime,1851            );1852            workInProgress.child = primaryChildFragment;1853            // Skip the primary children, and continue working on the1854            // fallback children.1855            return fallbackChildFragment;1856          }1857        }1858      }1859      // The current tree already timed out. That means each child set is1860      // wrapped in a fragment fiber.1861      const currentPrimaryChildFragment: Fiber = (current.child: any);1862      const currentFallbackChildFragment: Fiber = (currentPrimaryChildFragment.sibling: any);1863      if (nextDidTimeout) {1864        // Still timed out. Reuse the current primary children by cloning1865        // its fragment. We're going to skip over these entirely.1866        const nextFallbackChildren = nextProps.fallback;1867        const primaryChildFragment = createWorkInProgress(1868          currentPrimaryChildFragment,1869          currentPrimaryChildFragment.pendingProps,1870        );1871        primaryChildFragment.return = workInProgress;1872        if ((workInProgress.mode & BlockingMode) === NoMode) {1873          // Outside of blocking mode, we commit the effects from the1874          // partially completed, timed-out tree, too.1875          const progressedState: SuspenseState = workInProgress.memoizedState;1876          const progressedPrimaryChild: Fiber | null =1877            progressedState !== null1878              ? (workInProgress.child: any).child1879              : (workInProgress.child: any);1880          if (progressedPrimaryChild !== currentPrimaryChildFragment.child) {1881            primaryChildFragment.child = progressedPrimaryChild;1882            let progressedChild = progressedPrimaryChild;1883            while (progressedChild !== null) {1884              progressedChild.return = primaryChildFragment;1885              progressedChild = progressedChild.sibling;1886            }1887          }1888        }1889        // Because primaryChildFragment is a new fiber that we're inserting as the1890        // parent of a new tree, we need to set its treeBaseDuration.1891        if (enableProfilerTimer && workInProgress.mode & ProfileMode) {1892          // treeBaseDuration is the sum of all the child tree base durations.1893          let treeBaseDuration = 0;1894          let hiddenChild = primaryChildFragment.child;1895          while (hiddenChild !== null) {1896            treeBaseDuration += hiddenChild.treeBaseDuration;1897            hiddenChild = hiddenChild.sibling;1898          }1899          primaryChildFragment.treeBaseDuration = treeBaseDuration;1900        }1901        // Clone the fallback child fragment, too. These we'll continue1902        // working on.1903        const fallbackChildFragment = createWorkInProgress(1904          currentFallbackChildFragment,1905          nextFallbackChildren,1906        );1907        fallbackChildFragment.return = workInProgress;1908        primaryChildFragment.sibling = fallbackChildFragment;1909        primaryChildFragment.childExpirationTime = getRemainingWorkInPrimaryTree(1910          current,1911          workInProgress,1912          renderExpirationTime,1913        );1914        // Skip the primary children, and continue working on the1915        // fallback children.1916        workInProgress.memoizedState = updateSuspenseState(1917          current.memoizedState,1918          renderExpirationTime,1919        );1920        workInProgress.child = primaryChildFragment;1921        return fallbackChildFragment;1922      } else {1923        // No longer suspended. Switch back to showing the primary children,1924        // and remove the intermediate fragment fiber.1925        const nextPrimaryChildren = nextProps.children;1926        const currentPrimaryChild = currentPrimaryChildFragment.child;1927        const primaryChild = reconcileChildFibers(1928          workInProgress,1929          currentPrimaryChild,1930          nextPrimaryChildren,1931          renderExpirationTime,1932        );1933        // If this render doesn't suspend, we need to delete the fallback1934        // children. Wait until the complete phase, after we've confirmed the1935        // fallback is no longer needed.1936        // TODO: Would it be better to store the fallback fragment on1937        // the stateNode?1938        // Continue rendering the children, like we normally do.1939        workInProgress.memoizedState = null;1940        return (workInProgress.child = primaryChild);1941      }1942    } else {1943      // The current tree has not already timed out. That means the primary1944      // children are not wrapped in a fragment fiber.1945      const currentPrimaryChild = current.child;1946      if (nextDidTimeout) {1947        // Timed out. Wrap the children in a fragment fiber to keep them1948        // separate from the fallback children.1949        const nextFallbackChildren = nextProps.fallback;1950        const primaryChildFragment = createFiberFromFragment(1951          // It shouldn't matter what the pending props are because we aren't1952          // going to render this fragment.1953          null,1954          mode,1955          NoWork,1956          null,1957        );1958        primaryChildFragment.return = workInProgress;1959        primaryChildFragment.child = currentPrimaryChild;1960        if (currentPrimaryChild !== null) {1961          currentPrimaryChild.return = primaryChildFragment;1962        }1963        // Even though we're creating a new fiber, there are no new children,1964        // because we're reusing an already mounted tree. So we don't need to1965        // schedule a placement.1966        // primaryChildFragment.effectTag |= Placement;1967        if ((workInProgress.mode & BlockingMode) === NoMode) {1968          // Outside of blocking mode, we commit the effects from the1969          // partially completed, timed-out tree, too.1970          const progressedState: SuspenseState = workInProgress.memoizedState;1971          const progressedPrimaryChild: Fiber | null =1972            progressedState !== null1973              ? (workInProgress.child: any).child1974              : (workInProgress.child: any);1975          primaryChildFragment.child = progressedPrimaryChild;1976          let progressedChild = progressedPrimaryChild;1977          while (progressedChild !== null) {1978            progressedChild.return = primaryChildFragment;1979            progressedChild = progressedChild.sibling;1980          }1981        }1982        // Because primaryChildFragment is a new fiber that we're inserting as the1983        // parent of a new tree, we need to set its treeBaseDuration.1984        if (enableProfilerTimer && workInProgress.mode & ProfileMode) {1985          // treeBaseDuration is the sum of all the child tree base durations.1986          let treeBaseDuration = 0;1987          let hiddenChild = primaryChildFragment.child;1988          while (hiddenChild !== null) {1989            treeBaseDuration += hiddenChild.treeBaseDuration;1990            hiddenChild = hiddenChild.sibling;1991          }1992          primaryChildFragment.treeBaseDuration = treeBaseDuration;1993        }1994        // Create a fragment from the fallback children, too.1995        const fallbackChildFragment = createFiberFromFragment(1996          nextFallbackChildren,1997          mode,1998          renderExpirationTime,1999          null,2000        );2001        fallbackChildFragment.return = workInProgress;2002        primaryChildFragment.sibling = fallbackChildFragment;2003        fallbackChildFragment.effectTag |= Placement;2004        primaryChildFragment.childExpirationTime = getRemainingWorkInPrimaryTree(2005          current,2006          workInProgress,2007          renderExpirationTime,2008        );2009        // Skip the primary children, and continue working on the2010        // fallback children.2011        workInProgress.memoizedState = mountSuspenseState(renderExpirationTime);2012        workInProgress.child = primaryChildFragment;2013        return fallbackChildFragment;2014      } else {2015        // Still haven't timed out. Continue rendering the children, like we2016        // normally do.2017        workInProgress.memoizedState = null;2018        const nextPrimaryChildren = nextProps.children;...ReactFiberBeginWork.js
Source:ReactFiberBeginWork.js  
...1543    suspenseContext,1544    (ForceSuspenseFallback: SuspenseContext),1545  );1546}1547function getRemainingWorkInPrimaryTree(1548  current: Fiber,1549  workInProgress: Fiber,1550  renderExpirationTime,1551) {1552  const currentChildExpirationTime = current.childExpirationTime;1553  const currentSuspenseState: SuspenseState = current.memoizedState;1554  if (currentSuspenseState !== null) {1555    // This boundary already timed out. Check if this render includes the level1556    // that previously suspended.1557    const baseTime = currentSuspenseState.baseTime;1558    if (1559      baseTime !== NoWork &&1560      baseTime < renderExpirationTime &&1561      baseTime > currentChildExpirationTime1562    ) {1563      // There's pending work at a lower level that might now be unblocked.1564      return baseTime;1565    }1566  }1567  if (currentChildExpirationTime < renderExpirationTime) {1568    // The highest priority remaining work is not part of this render. So the1569    // remaining work has not changed.1570    return currentChildExpirationTime;1571  }1572  if ((workInProgress.mode & BlockingMode) !== NoMode) {1573    // The highest priority remaining work is part of this render. Since we only1574    // keep track of the highest level, we don't know if there's a lower1575    // priority level scheduled. As a compromise, we'll render at the lowest1576    // known level in the entire tree, since that will include everything.1577    // TODO: If expirationTime were a bitmask where each bit represents a1578    // separate task thread, this would be: currentChildBits & ~renderBits1579    const root = getWorkInProgressRoot();1580    if (root !== null) {1581      const lastPendingTime = root.lastPendingTime;1582      if (lastPendingTime < renderExpirationTime) {1583        return lastPendingTime;1584      }1585    }1586  }1587  // In legacy mode, there's no work left.1588  return NoWork;1589}1590function updateSuspenseComponent(1591  current,1592  workInProgress,1593  renderExpirationTime,1594) {1595  const mode = workInProgress.mode;1596  const nextProps = workInProgress.pendingProps;1597  // This is used by DevTools to force a boundary to suspend.1598  if (__DEV__) {1599    if (shouldSuspend(workInProgress)) {1600      workInProgress.effectTag |= DidCapture;1601    }1602  }1603  let suspenseContext: SuspenseContext = suspenseStackCursor.current;1604  let nextDidTimeout = false;1605  const didSuspend = (workInProgress.effectTag & DidCapture) !== NoEffect;1606  if (1607    didSuspend ||1608    shouldRemainOnFallback(1609      suspenseContext,1610      current,1611      workInProgress,1612      renderExpirationTime,1613    )1614  ) {1615    // Something in this boundary's subtree already suspended. Switch to1616    // rendering the fallback children.1617    nextDidTimeout = true;1618    workInProgress.effectTag &= ~DidCapture;1619  } else {1620    // Attempting the main content1621    if (1622      current === null ||1623      (current.memoizedState: null | SuspenseState) !== null1624    ) {1625      // This is a new mount or this boundary is already showing a fallback state.1626      // Mark this subtree context as having at least one invisible parent that could1627      // handle the fallback state.1628      // Boundaries without fallbacks or should be avoided are not considered since1629      // they cannot handle preferred fallback states.1630      if (1631        nextProps.fallback !== undefined &&1632        nextProps.unstable_avoidThisFallback !== true1633      ) {1634        suspenseContext = addSubtreeSuspenseContext(1635          suspenseContext,1636          InvisibleParentSuspenseContext,1637        );1638      }1639    }1640  }1641  suspenseContext = setDefaultShallowSuspenseContext(suspenseContext);1642  pushSuspenseContext(workInProgress, suspenseContext);1643  // This next part is a bit confusing. If the children timeout, we switch to1644  // showing the fallback children in place of the "primary" children.1645  // However, we don't want to delete the primary children because then their1646  // state will be lost (both the React state and the host state, e.g.1647  // uncontrolled form inputs). Instead we keep them mounted and hide them.1648  // Both the fallback children AND the primary children are rendered at the1649  // same time. Once the primary children are un-suspended, we can delete1650  // the fallback children â don't need to preserve their state.1651  //1652  // The two sets of children are siblings in the host environment, but1653  // semantically, for purposes of reconciliation, they are two separate sets.1654  // So we store them using two fragment fibers.1655  //1656  // However, we want to avoid allocating extra fibers for every placeholder.1657  // They're only necessary when the children time out, because that's the1658  // only time when both sets are mounted.1659  //1660  // So, the extra fragment fibers are only used if the children time out.1661  // Otherwise, we render the primary children directly. This requires some1662  // custom reconciliation logic to preserve the state of the primary1663  // children. It's essentially a very basic form of re-parenting.1664  if (current === null) {1665    // If we're currently hydrating, try to hydrate this boundary.1666    // But only if this has a fallback.1667    if (nextProps.fallback !== undefined) {1668      tryToClaimNextHydratableInstance(workInProgress);1669      // This could've been a dehydrated suspense component.1670      if (enableSuspenseServerRenderer) {1671        const suspenseState: null | SuspenseState =1672          workInProgress.memoizedState;1673        if (suspenseState !== null) {1674          const dehydrated = suspenseState.dehydrated;1675          if (dehydrated !== null) {1676            return mountDehydratedSuspenseComponent(1677              workInProgress,1678              dehydrated,1679              renderExpirationTime,1680            );1681          }1682        }1683      }1684    }1685    // This is the initial mount. This branch is pretty simple because there's1686    // no previous state that needs to be preserved.1687    if (nextDidTimeout) {1688      // Mount separate fragments for primary and fallback children.1689      const nextFallbackChildren = nextProps.fallback;1690      const primaryChildFragment = createFiberFromFragment(1691        null,1692        mode,1693        NoWork,1694        null,1695      );1696      primaryChildFragment.return = workInProgress;1697      if ((workInProgress.mode & BlockingMode) === NoMode) {1698        // Outside of blocking mode, we commit the effects from the1699        // partially completed, timed-out tree, too.1700        const progressedState: SuspenseState = workInProgress.memoizedState;1701        const progressedPrimaryChild: Fiber | null =1702          progressedState !== null1703            ? (workInProgress.child: any).child1704            : (workInProgress.child: any);1705        primaryChildFragment.child = progressedPrimaryChild;1706        let progressedChild = progressedPrimaryChild;1707        while (progressedChild !== null) {1708          progressedChild.return = primaryChildFragment;1709          progressedChild = progressedChild.sibling;1710        }1711      }1712      const fallbackChildFragment = createFiberFromFragment(1713        nextFallbackChildren,1714        mode,1715        renderExpirationTime,1716        null,1717      );1718      fallbackChildFragment.return = workInProgress;1719      primaryChildFragment.sibling = fallbackChildFragment;1720      // Skip the primary children, and continue working on the1721      // fallback children.1722      workInProgress.memoizedState = mountSuspenseState(renderExpirationTime);1723      workInProgress.child = primaryChildFragment;1724      return fallbackChildFragment;1725    } else {1726      // Mount the primary children without an intermediate fragment fiber.1727      const nextPrimaryChildren = nextProps.children;1728      workInProgress.memoizedState = null;1729      return (workInProgress.child = mountChildFibers(1730        workInProgress,1731        null,1732        nextPrimaryChildren,1733        renderExpirationTime,1734      ));1735    }1736  } else {1737    // This is an update. This branch is more complicated because we need to1738    // ensure the state of the primary children is preserved.1739    const prevState: null | SuspenseState = current.memoizedState;1740    if (prevState !== null) {1741      if (enableSuspenseServerRenderer) {1742        const dehydrated = prevState.dehydrated;1743        if (dehydrated !== null) {1744          if (!didSuspend) {1745            return updateDehydratedSuspenseComponent(1746              current,1747              workInProgress,1748              dehydrated,1749              prevState,1750              renderExpirationTime,1751            );1752          } else if (1753            (workInProgress.memoizedState: null | SuspenseState) !== null1754          ) {1755            // Something suspended and we should still be in dehydrated mode.1756            // Leave the existing child in place.1757            workInProgress.child = current.child;1758            // The dehydrated completion pass expects this flag to be there1759            // but the normal suspense pass doesn't.1760            workInProgress.effectTag |= DidCapture;1761            return null;1762          } else {1763            // Suspended but we should no longer be in dehydrated mode.1764            // Therefore we now have to render the fallback. Wrap the children1765            // in a fragment fiber to keep them separate from the fallback1766            // children.1767            const nextFallbackChildren = nextProps.fallback;1768            const primaryChildFragment = createFiberFromFragment(1769              // It shouldn't matter what the pending props are because we aren't1770              // going to render this fragment.1771              null,1772              mode,1773              NoWork,1774              null,1775            );1776            primaryChildFragment.return = workInProgress;1777            // This is always null since we never want the previous child1778            // that we're not going to hydrate.1779            primaryChildFragment.child = null;1780            if ((workInProgress.mode & BlockingMode) === NoMode) {1781              // Outside of blocking mode, we commit the effects from the1782              // partially completed, timed-out tree, too.1783              let progressedChild = (primaryChildFragment.child =1784                workInProgress.child);1785              while (progressedChild !== null) {1786                progressedChild.return = primaryChildFragment;1787                progressedChild = progressedChild.sibling;1788              }1789            } else {1790              // We will have dropped the effect list which contains the deletion.1791              // We need to reconcile to delete the current child.1792              reconcileChildFibers(1793                workInProgress,1794                current.child,1795                null,1796                renderExpirationTime,1797              );1798            }1799            // Because primaryChildFragment is a new fiber that we're inserting as the1800            // parent of a new tree, we need to set its treeBaseDuration.1801            if (enableProfilerTimer && workInProgress.mode & ProfileMode) {1802              // treeBaseDuration is the sum of all the child tree base durations.1803              let treeBaseDuration = 0;1804              let hiddenChild = primaryChildFragment.child;1805              while (hiddenChild !== null) {1806                treeBaseDuration += hiddenChild.treeBaseDuration;1807                hiddenChild = hiddenChild.sibling;1808              }1809              primaryChildFragment.treeBaseDuration = treeBaseDuration;1810            }1811            // Create a fragment from the fallback children, too.1812            const fallbackChildFragment = createFiberFromFragment(1813              nextFallbackChildren,1814              mode,1815              renderExpirationTime,1816              null,1817            );1818            fallbackChildFragment.return = workInProgress;1819            primaryChildFragment.sibling = fallbackChildFragment;1820            fallbackChildFragment.effectTag |= Placement;1821            primaryChildFragment.childExpirationTime = getRemainingWorkInPrimaryTree(1822              current,1823              workInProgress,1824              renderExpirationTime,1825            );1826            workInProgress.memoizedState = updateSuspenseState(1827              current.memoizedState,1828              renderExpirationTime,1829            );1830            workInProgress.child = primaryChildFragment;1831            // Skip the primary children, and continue working on the1832            // fallback children.1833            return fallbackChildFragment;1834          }1835        }1836      }1837      // The current tree already timed out. That means each child set is1838      // wrapped in a fragment fiber.1839      const currentPrimaryChildFragment: Fiber = (current.child: any);1840      const currentFallbackChildFragment: Fiber = (currentPrimaryChildFragment.sibling: any);1841      if (nextDidTimeout) {1842        // Still timed out. Reuse the current primary children by cloning1843        // its fragment. We're going to skip over these entirely.1844        const nextFallbackChildren = nextProps.fallback;1845        const primaryChildFragment = createWorkInProgress(1846          currentPrimaryChildFragment,1847          currentPrimaryChildFragment.pendingProps,1848        );1849        primaryChildFragment.return = workInProgress;1850        if ((workInProgress.mode & BlockingMode) === NoMode) {1851          // Outside of blocking mode, we commit the effects from the1852          // partially completed, timed-out tree, too.1853          const progressedState: SuspenseState = workInProgress.memoizedState;1854          const progressedPrimaryChild: Fiber | null =1855            progressedState !== null1856              ? (workInProgress.child: any).child1857              : (workInProgress.child: any);1858          if (progressedPrimaryChild !== currentPrimaryChildFragment.child) {1859            primaryChildFragment.child = progressedPrimaryChild;1860            let progressedChild = progressedPrimaryChild;1861            while (progressedChild !== null) {1862              progressedChild.return = primaryChildFragment;1863              progressedChild = progressedChild.sibling;1864            }1865          }1866        }1867        // Because primaryChildFragment is a new fiber that we're inserting as the1868        // parent of a new tree, we need to set its treeBaseDuration.1869        if (enableProfilerTimer && workInProgress.mode & ProfileMode) {1870          // treeBaseDuration is the sum of all the child tree base durations.1871          let treeBaseDuration = 0;1872          let hiddenChild = primaryChildFragment.child;1873          while (hiddenChild !== null) {1874            treeBaseDuration += hiddenChild.treeBaseDuration;1875            hiddenChild = hiddenChild.sibling;1876          }1877          primaryChildFragment.treeBaseDuration = treeBaseDuration;1878        }1879        // Clone the fallback child fragment, too. These we'll continue1880        // working on.1881        const fallbackChildFragment = createWorkInProgress(1882          currentFallbackChildFragment,1883          nextFallbackChildren,1884        );1885        fallbackChildFragment.return = workInProgress;1886        primaryChildFragment.sibling = fallbackChildFragment;1887        primaryChildFragment.childExpirationTime = getRemainingWorkInPrimaryTree(1888          current,1889          workInProgress,1890          renderExpirationTime,1891        );1892        // Skip the primary children, and continue working on the1893        // fallback children.1894        workInProgress.memoizedState = updateSuspenseState(1895          current.memoizedState,1896          renderExpirationTime,1897        );1898        workInProgress.child = primaryChildFragment;1899        return fallbackChildFragment;1900      } else {1901        // No longer suspended. Switch back to showing the primary children,1902        // and remove the intermediate fragment fiber.1903        const nextPrimaryChildren = nextProps.children;1904        const currentPrimaryChild = currentPrimaryChildFragment.child;1905        const primaryChild = reconcileChildFibers(1906          workInProgress,1907          currentPrimaryChild,1908          nextPrimaryChildren,1909          renderExpirationTime,1910        );1911        // If this render doesn't suspend, we need to delete the fallback1912        // children. Wait until the complete phase, after we've confirmed the1913        // fallback is no longer needed.1914        // TODO: Would it be better to store the fallback fragment on1915        // the stateNode?1916        // Continue rendering the children, like we normally do.1917        workInProgress.memoizedState = null;1918        return (workInProgress.child = primaryChild);1919      }1920    } else {1921      // The current tree has not already timed out. That means the primary1922      // children are not wrapped in a fragment fiber.1923      const currentPrimaryChild = current.child;1924      if (nextDidTimeout) {1925        // Timed out. Wrap the children in a fragment fiber to keep them1926        // separate from the fallback children.1927        const nextFallbackChildren = nextProps.fallback;1928        const primaryChildFragment = createFiberFromFragment(1929          // It shouldn't matter what the pending props are because we aren't1930          // going to render this fragment.1931          null,1932          mode,1933          NoWork,1934          null,1935        );1936        primaryChildFragment.return = workInProgress;1937        primaryChildFragment.child = currentPrimaryChild;1938        if (currentPrimaryChild !== null) {1939          currentPrimaryChild.return = primaryChildFragment;1940        }1941        // Even though we're creating a new fiber, there are no new children,1942        // because we're reusing an already mounted tree. So we don't need to1943        // schedule a placement.1944        // primaryChildFragment.effectTag |= Placement;1945        if ((workInProgress.mode & BlockingMode) === NoMode) {1946          // Outside of blocking mode, we commit the effects from the1947          // partially completed, timed-out tree, too.1948          const progressedState: SuspenseState = workInProgress.memoizedState;1949          const progressedPrimaryChild: Fiber | null =1950            progressedState !== null1951              ? (workInProgress.child: any).child1952              : (workInProgress.child: any);1953          primaryChildFragment.child = progressedPrimaryChild;1954          let progressedChild = progressedPrimaryChild;1955          while (progressedChild !== null) {1956            progressedChild.return = primaryChildFragment;1957            progressedChild = progressedChild.sibling;1958          }1959        }1960        // Because primaryChildFragment is a new fiber that we're inserting as the1961        // parent of a new tree, we need to set its treeBaseDuration.1962        if (enableProfilerTimer && workInProgress.mode & ProfileMode) {1963          // treeBaseDuration is the sum of all the child tree base durations.1964          let treeBaseDuration = 0;1965          let hiddenChild = primaryChildFragment.child;1966          while (hiddenChild !== null) {1967            treeBaseDuration += hiddenChild.treeBaseDuration;1968            hiddenChild = hiddenChild.sibling;1969          }1970          primaryChildFragment.treeBaseDuration = treeBaseDuration;1971        }1972        // Create a fragment from the fallback children, too.1973        const fallbackChildFragment = createFiberFromFragment(1974          nextFallbackChildren,1975          mode,1976          renderExpirationTime,1977          null,1978        );1979        fallbackChildFragment.return = workInProgress;1980        primaryChildFragment.sibling = fallbackChildFragment;1981        fallbackChildFragment.effectTag |= Placement;1982        primaryChildFragment.childExpirationTime = getRemainingWorkInPrimaryTree(1983          current,1984          workInProgress,1985          renderExpirationTime,1986        );1987        // Skip the primary children, and continue working on the1988        // fallback children.1989        workInProgress.memoizedState = mountSuspenseState(renderExpirationTime);1990        workInProgress.child = primaryChildFragment;1991        return fallbackChildFragment;1992      } else {1993        // Still haven't timed out. Continue rendering the children, like we1994        // normally do.1995        workInProgress.memoizedState = null;1996        const nextPrimaryChildren = nextProps.children;...Using AI Code Generation
1const { chromium } = require('playwright');2(async () => {3  const browser = await chromium.launch({4  });5  const context = await browser.newContext();6  const page = await context.newPage();7  console.log(await page._delegate.getRemainingWorkInPrimaryTree());8  await browser.close();9})();Using AI Code Generation
1const { chromium, webkit, firefox } = require('playwright');2(async () => {3  const browser = await chromium.launch();4  const context = await browser.newContext();5  const page = await context.newPage();6  await page.screenshot({ path: 'google.png' });7  await browser.close();8})();9const { chromium, webkit, firefox } = require('playwright');10(async () => {11  const browser = await chromium.launch();12  const context = await browser.newContext();13  const page = await context.newPage();14  await page.screenshot({ path: 'google.png' });15  await browser.close();16})();17const { chromium, webkit, firefox } = require('playwright');18(async () => {19  const browser = await chromium.launch();20  const context = await browser.newContext();21  const page = await context.newPage();22  await page.screenshot({ path: 'google.png' });23  await browser.close();24})();25const { chromium, webkit, firefox } = require('playwright');26(async () => {27  const browser = await chromium.launch();28  const context = await browser.newContext();29  const page = await context.newPage();30  await page.screenshot({ path: 'google.png' });31  await browser.close();32})();33const { chromium, webkit, firefox } = require('playwright');34(async () => {35  const browser = await chromium.launch();36  const context = await browser.newContext();37  const page = await context.newPage();38  await page.screenshot({ path: 'google.png' });39  await browser.close();40})();41const { chromium, webkit, firefox } = require('Using AI Code Generation
1const { getRemainingWorkInPrimaryTree } = require('playwright/lib/server/browserContext');2const { chromium } = require('playwright');3(async () => {4  const browser = await chromium.launch();5  const context = await browser.newContext();6  const page = await context.newPage();7  await page.click('text=Get started');8  await page.click('text=Docs');9  await page.click('text=API');Using AI Code Generation
1const { getRemainingWorkInPrimaryTree } = require('playwright/lib/server/chromium/crBrowser.js');2const { chromium } = require('playwright');3(async () => {4  const browser = await chromium.launch();5  const page = await browser.newPage();6  await page.waitForSelector('text=Get started');7  await page.click('text=Get started');8  await page.waitForSelector('text=Create a test project');9  await page.click('text=Create a test project');10  await page.waitForSelector('text=Playwright is a Node.js library to automate');11  await browser.close();12})();Using AI Code Generation
1const { getRemainingWorkInPrimaryTree } = require('playwright/lib/server/progress');2const { chromium } = require('playwright');3(async () => {4  const browser = await chromium.launch();5  const page = await browser.newPage();6  await page.waitForSelector('.navbar__inner');7  console.log(getRemainingWorkInPrimaryTree());8  await browser.close();9})();Using AI Code Generation
1const { getRemainingWorkInPrimaryTree } = require('playwright/lib/server/chromium/crBrowser.js');2const browser = await chromium.launch();3const page = await browser.newPage();4await page.waitForSelector('text=Get started');5const remainingWork = await getRemainingWorkInPrimaryTree(page);6console.log(remainingWork);7await browser.close();Using AI Code Generation
1const { getRemainingWorkInPrimaryTree } = require('playwright/lib/utils/progress');2const browser = await playwright.chromium.launch();3const context = await browser.newContext();4const page = await context.newPage();5await page.waitForSelector('.new-todo');6await page.type('.new-todo', 'Learn playwright');7await page.keyboard.press('Enter');8await page.type('.new-todo', 'Learn playwright internal API');9await page.keyboard.press('Enter');10await page.waitForSelector('.todo-list li:nth-child(2) .toggle');11await page.click('.todo-list li:nth-child(2) .toggle');12await page.waitForSelector('.todo-list li:nth-child(2).completed');13console.log(getRemainingWorkInPrimaryTree());14await browser.close();15const { getPendingTasks } = require('playwright/lib/utils/progress');16const browser = await playwright.chromium.launch();17const context = await browser.newContext();18const page = await context.newPage();19await page.waitForSelector('.new-todo');20await page.type('.new-todo', 'Learn playwright');21await page.keyboard.press('Enter');22await page.type('.new-todo', 'Learn playwright internal API');23await page.keyboard.press('Enter');24await page.waitForSelector('.todo-list li:nth-child(2) .toggle');25await page.click('.todo-list li:nth-child(2) .toggle');26await page.waitForSelector('.todo-list li:nth-child(2).completed');27console.log(getPendingTasks());28await browser.close();Using AI Code Generation
1const { getRemainingWorkInPrimaryTree } = require('playwright/lib/server/progress');2const { getRemainingWorkInPrimaryTree } = require('playwright/lib/server/progress');3const { getRemainingWorkInPrimaryTree } = require('playwright/lib/server/progress');4const { getRemainingWorkInPrimaryTree } = require('playwright/lib/server/progress');5const { getRemainingWorkInPrimaryTree } = require('playwright/lib/server/progress');6const { getRemainingWorkInPrimaryTree } = require('playwright/lib/server/progress');7const { getRemainingWorkInPrimaryTree } = require('playwright/lib/server/progress');8const { getRemainingWorkInPrimaryTree } = require('playwright/lib/server/progress');9const { getRemainingWorkInPrimaryTree } = require('playwright/lib/server/progress');Using AI Code Generation
1const { getRemainingWorkInPrimaryTree } = require('playwright/lib/server/supplements/recorder/recorderSupplement');2module.exports = async function(context, commands) {3  await commands.measure.stop();4  await commands.measure.stop();5  await commands.measure.stop();6  await commands.measure.stop();7};8const { getRemainingWorkInPrimaryTree } = require('playwright/lib/server/supplements/recorder/recorderSupplement');9module.exports = async function(context, commands) {10  await commands.measure.stop();11  await commands.measure.stop();12  await commands.measure.stop();13  await commands.measure.stop();14};15const { getRemainingWorkInPrimaryTree } = require('playwright/lib/server/supplements/recorder/recorderSupplement');16module.exports = async function(context, commands) {17  await commands.measure.stop();18  await commands.measure.stop();19  await commands.measure.stop();20  await commands.measure.stop();21  await commands.measure.stop();22  await commands.measure.stop();23  await commands.measure.stop();24};25const { getRemainingWorkInPrimaryTree } = requireLambdaTest’s Playwright tutorial will give you a broader idea about the Playwright automation framework, its unique features, and use cases with examples to exceed your understanding of Playwright testing. This tutorial will give A to Z guidance, from installing the Playwright framework to some best practices and advanced concepts.
Get 100 minutes of automation test minutes FREE!!
