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 } = require
LambdaTest’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!!