Best JavaScript code snippet using playwright-internal
ReactFiberWorkLoop.old.js
Source:ReactFiberWorkLoop.old.js  
...1362        // If there are no passive effects, then we can complete the pending interactions.1363        // Otherwise, we'll wait until after the passive effects are flushed.1364        // Wait to do this until after remaining work has been scheduled,1365        // so that we don't prematurely signal complete for interactions when there's e.g. hidden work.1366        finishPendingInteractions(root, lanes);1367      }1368    }1369    if (remainingLanes === SyncLane) {1370      // Count the number of times the root synchronously re-renders without1371      // finishing. If there are too many, it indicates an infinite update loop.1372      if (root === rootWithNestedUpdates) {1373        nestedUpdateCount++;1374      } else {1375        nestedUpdateCount = 0;1376        rootWithNestedUpdates = root;1377      }1378    } else {1379      nestedUpdateCount = 0;1380    }1381    onCommitRoot(finishedWork.stateNode, renderPriorityLevel);1382    {1383      onCommitRoot$1();1384    } // Always call this before exiting `commitRoot`, to ensure that any1385    // additional work on this root is scheduled.1386    ensureRootIsScheduled(root, now());1387    if (hasUncaughtError) {1388      hasUncaughtError = false;1389      var _error3 = firstUncaughtError;1390      firstUncaughtError = null;1391      throw _error3;1392    }1393    if ((executionContext & LegacyUnbatchedContext) !== NoContext) {1394      {1395        markCommitStopped();1396      } // This is a legacy edge case. We just committed the initial mount of1397      // a ReactDOM.render-ed root inside of batchedUpdates. The commit fired1398      // synchronously, but layout updates should be deferred until the end1399      // of the batch.1400      return null;1401    } // If layout work was scheduled, flush it now.1402    flushSyncCallbackQueue();1403    {1404      markCommitStopped();1405    }1406    return null;1407  }1408  function commitBeforeMutationEffects() {1409    while (nextEffect !== null) {1410      var current = nextEffect.alternate;1411      if (!shouldFireAfterActiveInstanceBlur && focusedInstanceHandle !== null) {1412        if ((nextEffect.flags & Deletion) !== NoFlags) {1413          if (doesFiberContain(nextEffect, focusedInstanceHandle)) {1414            shouldFireAfterActiveInstanceBlur = true;1415          }1416        } else {1417          // TODO: Move this out of the hot path using a dedicated effect tag.1418          if (nextEffect.tag === SuspenseComponent && isSuspenseBoundaryBeingHidden(current, nextEffect) && doesFiberContain(nextEffect, focusedInstanceHandle)) {1419            shouldFireAfterActiveInstanceBlur = true;1420          }1421        }1422      }1423      var flags = nextEffect.flags;1424      if ((flags & Snapshot) !== NoFlags) {1425        setCurrentFiber(nextEffect);1426        commitBeforeMutationLifeCycles(current, nextEffect);1427        resetCurrentFiber();1428      }1429      if ((flags & Passive) !== NoFlags) {1430        // If there are passive effects, schedule a callback to flush at1431        // the earliest opportunity.1432        if (!rootDoesHavePassiveEffects) {1433          rootDoesHavePassiveEffects = true;1434          scheduleCallback(NormalPriority$1, function () {1435            flushPassiveEffects();1436            return null;1437          });1438        }1439      }1440      nextEffect = nextEffect.nextEffect;1441    }1442  }1443  function commitMutationEffects(root, renderPriorityLevel) {1444    // TODO: Should probably move the bulk of this function to commitWork.1445    while (nextEffect !== null) {1446      setCurrentFiber(nextEffect);1447      var flags = nextEffect.flags;1448      if (flags & ContentReset) {1449        commitResetTextContent(nextEffect);1450      }1451      if (flags & Ref) {1452        var current = nextEffect.alternate;1453        if (current !== null) {1454          commitDetachRef(current);1455        }1456      } // The following switch statement is only concerned about placement,1457      // updates, and deletions. To avoid needing to add a case for every possible1458      // bitmap value, we remove the secondary effects from the effect tag and1459      // switch on that value.1460      var primaryFlags = flags & (Placement | Update | Deletion | Hydrating);1461      switch (primaryFlags) {1462        case Placement:1463          {1464            commitPlacement(nextEffect); // Clear the "placement" from effect tag so that we know that this is1465            // inserted, before any life-cycles like componentDidMount gets called.1466            // TODO: findDOMNode doesn't rely on this any more but isMounted does1467            // and isMounted is deprecated anyway so we should be able to kill this.1468            nextEffect.flags &= ~Placement;1469            break;1470          }1471        case PlacementAndUpdate:1472          {1473            // Placement1474            commitPlacement(nextEffect); // Clear the "placement" from effect tag so that we know that this is1475            // inserted, before any life-cycles like componentDidMount gets called.1476            nextEffect.flags &= ~Placement; // Update1477            var _current = nextEffect.alternate;1478            commitWork(_current, nextEffect);1479            break;1480          }1481        case Hydrating:1482          {1483            nextEffect.flags &= ~Hydrating;1484            break;1485          }1486        case HydratingAndUpdate:1487          {1488            nextEffect.flags &= ~Hydrating; // Update1489            var _current2 = nextEffect.alternate;1490            commitWork(_current2, nextEffect);1491            break;1492          }1493        case Update:1494          {1495            var _current3 = nextEffect.alternate;1496            commitWork(_current3, nextEffect);1497            break;1498          }1499        case Deletion:1500          {1501            commitDeletion(root, nextEffect);1502            break;1503          }1504      }1505      resetCurrentFiber();1506      nextEffect = nextEffect.nextEffect;1507    }1508  }1509  function commitLayoutEffects(root, committedLanes) {1510    {1511      markLayoutEffectsStarted(committedLanes);1512    } // TODO: Should probably move the bulk of this function to commitWork.1513    while (nextEffect !== null) {1514      setCurrentFiber(nextEffect);1515      var flags = nextEffect.flags;1516      if (flags & (Update | Callback)) {1517        var current = nextEffect.alternate;1518        commitLifeCycles(root, current, nextEffect);1519      }1520      {1521        if (flags & Ref) {1522          commitAttachRef(nextEffect);1523        }1524      }1525      resetCurrentFiber();1526      nextEffect = nextEffect.nextEffect;1527    }1528    {1529      markLayoutEffectsStopped();1530    }1531  }1532  function flushPassiveEffects() {1533    // Returns whether passive effects were flushed.1534    if (pendingPassiveEffectsRenderPriority !== NoPriority$1) {1535      var priorityLevel = pendingPassiveEffectsRenderPriority > NormalPriority$1 ? NormalPriority$1 : pendingPassiveEffectsRenderPriority;1536      pendingPassiveEffectsRenderPriority = NoPriority$1;1537      {1538        return runWithPriority$1(priorityLevel, flushPassiveEffectsImpl);1539      }1540    }1541    return false;1542  }1543  function enqueuePendingPassiveHookEffectMount(fiber, effect) {1544    pendingPassiveHookEffectsMount.push(effect, fiber);1545    if (!rootDoesHavePassiveEffects) {1546      rootDoesHavePassiveEffects = true;1547      scheduleCallback(NormalPriority$1, function () {1548        flushPassiveEffects();1549        return null;1550      });1551    }1552  }1553  function enqueuePendingPassiveHookEffectUnmount(fiber, effect) {1554    pendingPassiveHookEffectsUnmount.push(effect, fiber);1555    {1556      fiber.flags |= PassiveUnmountPendingDev;1557      var alternate = fiber.alternate;1558      if (alternate !== null) {1559        alternate.flags |= PassiveUnmountPendingDev;1560      }1561    }1562    if (!rootDoesHavePassiveEffects) {1563      rootDoesHavePassiveEffects = true;1564      scheduleCallback(NormalPriority$1, function () {1565        flushPassiveEffects();1566        return null;1567      });1568    }1569  }1570  function invokePassiveEffectCreate(effect) {1571    var create = effect.create;1572    effect.destroy = create();1573  }1574  function flushPassiveEffectsImpl() {1575    if (rootWithPendingPassiveEffects === null) {1576      return false;1577    }1578    var root = rootWithPendingPassiveEffects;1579    var lanes = pendingPassiveEffectsLanes;1580    rootWithPendingPassiveEffects = null;1581    pendingPassiveEffectsLanes = NoLanes;1582    if (!((executionContext & (RenderContext | CommitContext)) === NoContext)) {1583      {1584        throw Error( "Cannot flush passive effects while already rendering." );1585      }1586    }1587    {1588      markPassiveEffectsStarted(lanes);1589    }1590    {1591      isFlushingPassiveEffects = true;1592    }1593    var prevExecutionContext = executionContext;1594    executionContext |= CommitContext;1595    var prevInteractions = pushInteractions(root); // It's important that ALL pending passive effect destroy functions are called1596    // before ANY passive effect create functions are called.1597    // Otherwise effects in sibling components might interfere with each other.1598    // e.g. a destroy function in one component may unintentionally override a ref1599    // value set by a create function in another component.1600    // Layout effects have the same constraint.1601    // First pass: Destroy stale passive effects.1602    var unmountEffects = pendingPassiveHookEffectsUnmount;1603    pendingPassiveHookEffectsUnmount = [];1604    for (var i = 0; i < unmountEffects.length; i += 2) {1605      var _effect = unmountEffects[i];1606      var fiber = unmountEffects[i + 1];1607      var destroy = _effect.destroy;1608      _effect.destroy = undefined;1609      {1610        fiber.flags &= ~PassiveUnmountPendingDev;1611        var alternate = fiber.alternate;1612        if (alternate !== null) {1613          alternate.flags &= ~PassiveUnmountPendingDev;1614        }1615      }1616      if (typeof destroy === 'function') {1617        {1618          setCurrentFiber(fiber);1619          {1620            invokeGuardedCallback(null, destroy, null);1621          }1622          if (hasCaughtError()) {1623            if (!(fiber !== null)) {1624              {1625                throw Error( "Should be working on an effect." );1626              }1627            }1628            var error = clearCaughtError();1629            captureCommitPhaseError(fiber, error);1630          }1631          resetCurrentFiber();1632        }1633      }1634    } // Second pass: Create new passive effects.1635    var mountEffects = pendingPassiveHookEffectsMount;1636    pendingPassiveHookEffectsMount = [];1637    for (var _i = 0; _i < mountEffects.length; _i += 2) {1638      var _effect2 = mountEffects[_i];1639      var _fiber = mountEffects[_i + 1];1640      {1641        setCurrentFiber(_fiber);1642        {1643          invokeGuardedCallback(null, invokePassiveEffectCreate, null, _effect2);1644        }1645        if (hasCaughtError()) {1646          if (!(_fiber !== null)) {1647            {1648              throw Error( "Should be working on an effect." );1649            }1650          }1651          var _error4 = clearCaughtError();1652          captureCommitPhaseError(_fiber, _error4);1653        }1654        resetCurrentFiber();1655      }1656    } // Note: This currently assumes there are no passive effects on the root fiber1657    // because the root is not part of its own effect list.1658    // This could change in the future.1659    var effect = root.current.firstEffect;1660    while (effect !== null) {1661      var nextNextEffect = effect.nextEffect; // Remove nextEffect pointer to assist GC1662      effect.nextEffect = null;1663      if (effect.flags & Deletion) {1664        detachFiberAfterEffects(effect);1665      }1666      effect = nextNextEffect;1667    }1668    {1669      popInteractions(prevInteractions);1670      finishPendingInteractions(root, lanes);1671    }1672    {1673      isFlushingPassiveEffects = false;1674    }1675    {1676      markPassiveEffectsStopped();1677    }1678    executionContext = prevExecutionContext;1679    flushSyncCallbackQueue(); // If additional passive effects were scheduled, increment a counter. If this1680    // exceeds the limit, we'll fire a warning.1681    nestedPassiveUpdateCount = rootWithPendingPassiveEffects === null ? 0 : nestedPassiveUpdateCount + 1;1682    return true;1683  }1684  function isAlreadyFailedLegacyErrorBoundary(instance) {1685    return legacyErrorBoundariesThatAlreadyFailed !== null && legacyErrorBoundariesThatAlreadyFailed.has(instance);1686  }1687  function markLegacyErrorBoundaryAsFailed(instance) {1688    if (legacyErrorBoundariesThatAlreadyFailed === null) {1689      legacyErrorBoundariesThatAlreadyFailed = new Set([instance]);1690    } else {1691      legacyErrorBoundariesThatAlreadyFailed.add(instance);1692    }1693  }1694  function prepareToThrowUncaughtError(error) {1695    if (!hasUncaughtError) {1696      hasUncaughtError = true;1697      firstUncaughtError = error;1698    }1699  }1700  var onUncaughtError = prepareToThrowUncaughtError;1701  function captureCommitPhaseErrorOnRoot(rootFiber, sourceFiber, error) {1702    var errorInfo = createCapturedValue(error, sourceFiber);1703    var update = createRootErrorUpdate(rootFiber, errorInfo, SyncLane);1704    enqueueUpdate(rootFiber, update);1705    var eventTime = requestEventTime();1706    var root = markUpdateLaneFromFiberToRoot(rootFiber, SyncLane);1707    if (root !== null) {1708      markRootUpdated(root, SyncLane, eventTime);1709      ensureRootIsScheduled(root, eventTime);1710      schedulePendingInteractions(root, SyncLane);1711    }1712  }1713  function captureCommitPhaseError(sourceFiber, error) {1714    if (sourceFiber.tag === HostRoot) {1715      // Error was thrown at the root. There is no parent, so the root1716      // itself should capture it.1717      captureCommitPhaseErrorOnRoot(sourceFiber, sourceFiber, error);1718      return;1719    }1720    var fiber = sourceFiber.return;1721    while (fiber !== null) {1722      if (fiber.tag === HostRoot) {1723        captureCommitPhaseErrorOnRoot(fiber, sourceFiber, error);1724        return;1725      } else if (fiber.tag === ClassComponent) {1726        var ctor = fiber.type;1727        var instance = fiber.stateNode;1728        if (typeof ctor.getDerivedStateFromError === 'function' || typeof instance.componentDidCatch === 'function' && !isAlreadyFailedLegacyErrorBoundary(instance)) {1729          var errorInfo = createCapturedValue(error, sourceFiber);1730          var update = createClassErrorUpdate(fiber, errorInfo, SyncLane);1731          enqueueUpdate(fiber, update);1732          var eventTime = requestEventTime();1733          var root = markUpdateLaneFromFiberToRoot(fiber, SyncLane);1734          if (root !== null) {1735            markRootUpdated(root, SyncLane, eventTime);1736            ensureRootIsScheduled(root, eventTime);1737            schedulePendingInteractions(root, SyncLane);1738          } else {1739            // This component has already been unmounted.1740            // We can't schedule any follow up work for the root because the fiber is already unmounted,1741            // but we can still call the log-only boundary so the error isn't swallowed.1742            //1743            // TODO This is only a temporary bandaid for the old reconciler fork.1744            // We can delete this special case once the new fork is merged.1745            if (typeof instance.componentDidCatch === 'function' && !isAlreadyFailedLegacyErrorBoundary(instance)) {1746              try {1747                instance.componentDidCatch(error, errorInfo);1748              } catch (errorToIgnore) {// TODO Ignore this error? Rethrow it?1749                // This is kind of an edge case.1750              }1751            }1752          }1753          return;1754        }1755      }1756      fiber = fiber.return;1757    }1758  }1759  function pingSuspendedRoot(root, wakeable, pingedLanes) {1760    var pingCache = root.pingCache;1761    if (pingCache !== null) {1762      // The wakeable resolved, so we no longer need to memoize, because it will1763      // never be thrown again.1764      pingCache.delete(wakeable);1765    }1766    var eventTime = requestEventTime();1767    markRootPinged(root, pingedLanes);1768    if (workInProgressRoot === root && isSubsetOfLanes(workInProgressRootRenderLanes, pingedLanes)) {1769      // Received a ping at the same priority level at which we're currently1770      // rendering. We might want to restart this render. This should mirror1771      // the logic of whether or not a root suspends once it completes.1772      // TODO: If we're rendering sync either due to Sync, Batched or expired,1773      // we should probably never restart.1774      // If we're suspended with delay, or if it's a retry, we'll always suspend1775      // so we can always restart.1776      if (workInProgressRootExitStatus === RootSuspendedWithDelay || workInProgressRootExitStatus === RootSuspended && includesOnlyRetries(workInProgressRootRenderLanes) && now() - globalMostRecentFallbackTime < FALLBACK_THROTTLE_MS) {1777        // Restart from the root.1778        prepareFreshStack(root, NoLanes);1779      } else {1780        // Even though we can't restart right now, we might get an1781        // opportunity later. So we mark this render as having a ping.1782        workInProgressRootPingedLanes = mergeLanes(workInProgressRootPingedLanes, pingedLanes);1783      }1784    }1785    ensureRootIsScheduled(root, eventTime);1786    schedulePendingInteractions(root, pingedLanes);1787  }1788  function retryTimedOutBoundary(boundaryFiber, retryLane) {1789    // The boundary fiber (a Suspense component or SuspenseList component)1790    // previously was rendered in its fallback state. One of the promises that1791    // suspended it has resolved, which means at least part of the tree was1792    // likely unblocked. Try rendering again, at a new expiration time.1793    if (retryLane === NoLane) {1794      retryLane = requestRetryLane(boundaryFiber);1795    } // TODO: Special case idle priority?1796    var eventTime = requestEventTime();1797    var root = markUpdateLaneFromFiberToRoot(boundaryFiber, retryLane);1798    if (root !== null) {1799      markRootUpdated(root, retryLane, eventTime);1800      ensureRootIsScheduled(root, eventTime);1801      schedulePendingInteractions(root, retryLane);1802    }1803  }1804  function retryDehydratedSuspenseBoundary(boundaryFiber) {1805    var suspenseState = boundaryFiber.memoizedState;1806    var retryLane = NoLane;1807    if (suspenseState !== null) {1808      retryLane = suspenseState.retryLane;1809    }1810    retryTimedOutBoundary(boundaryFiber, retryLane);1811  }1812  function resolveRetryWakeable(boundaryFiber, wakeable) {1813    var retryLane = NoLane; // Default1814    var retryCache;1815    {1816      switch (boundaryFiber.tag) {1817        case SuspenseComponent:1818          retryCache = boundaryFiber.stateNode;1819          var suspenseState = boundaryFiber.memoizedState;1820          if (suspenseState !== null) {1821            retryLane = suspenseState.retryLane;1822          }1823          break;1824        case SuspenseListComponent:1825          retryCache = boundaryFiber.stateNode;1826          break;1827        default:1828          {1829            {1830              throw Error( "Pinged unknown suspense boundary type. This is probably a bug in React." );1831            }1832          }1833      }1834    }1835    if (retryCache !== null) {1836      // The wakeable resolved, so we no longer need to memoize, because it will1837      // never be thrown again.1838      retryCache.delete(wakeable);1839    }1840    retryTimedOutBoundary(boundaryFiber, retryLane);1841  } // Computes the next Just Noticeable Difference (JND) boundary.1842  // The theory is that a person can't tell the difference between small differences in time.1843  // Therefore, if we wait a bit longer than necessary that won't translate to a noticeable1844  // difference in the experience. However, waiting for longer might mean that we can avoid1845  // showing an intermediate loading state. The longer we have already waited, the harder it1846  // is to tell small differences in time. Therefore, the longer we've already waited,1847  // the longer we can wait additionally. At some point we have to give up though.1848  // We pick a train model where the next boundary commits at a consistent schedule.1849  // These particular numbers are vague estimates. We expect to adjust them based on research.1850  function jnd(timeElapsed) {1851    return timeElapsed < 120 ? 120 : timeElapsed < 480 ? 480 : timeElapsed < 1080 ? 1080 : timeElapsed < 1920 ? 1920 : timeElapsed < 3000 ? 3000 : timeElapsed < 4320 ? 4320 : ceil(timeElapsed / 1960) * 1960;1852  }1853  function checkForNestedUpdates() {1854    if (nestedUpdateCount > NESTED_UPDATE_LIMIT) {1855      nestedUpdateCount = 0;1856      rootWithNestedUpdates = null;1857      {1858        {1859          throw Error( "Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops." );1860        }1861      }1862    }1863    {1864      if (nestedPassiveUpdateCount > NESTED_PASSIVE_UPDATE_LIMIT) {1865        nestedPassiveUpdateCount = 0;1866        error('Maximum update depth exceeded. This can happen when a component ' + "calls setState inside useEffect, but useEffect either doesn't " + 'have a dependency array, or one of the dependencies changes on ' + 'every render.');1867      }1868    }1869  }1870  function flushRenderPhaseStrictModeWarningsInDEV() {1871    {1872      ReactStrictModeWarnings.flushLegacyContextWarning();1873      {1874        ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings();1875      }1876    }1877  }1878  var didWarnStateUpdateForNotYetMountedComponent = null;1879  function warnAboutUpdateOnNotYetMountedFiberInDEV(fiber) {1880    {1881      if ((executionContext & RenderContext) !== NoContext) {1882        // We let the other warning about render phase updates deal with this one.1883        return;1884      }1885      if (!(fiber.mode & (BlockingMode | ConcurrentMode))) {1886        return;1887      }1888      var tag = fiber.tag;1889      if (tag !== IndeterminateComponent && tag !== HostRoot && tag !== ClassComponent && tag !== FunctionComponent && tag !== ForwardRef && tag !== MemoComponent && tag !== SimpleMemoComponent && tag !== Block) {1890        // Only warn for user-defined components, not internal ones like Suspense.1891        return;1892      } // We show the whole stack but dedupe on the top component's name because1893      // the problematic code almost always lies inside that component.1894      var componentName = getComponentName(fiber.type) || 'ReactComponent';1895      if (didWarnStateUpdateForNotYetMountedComponent !== null) {1896        if (didWarnStateUpdateForNotYetMountedComponent.has(componentName)) {1897          return;1898        }1899        didWarnStateUpdateForNotYetMountedComponent.add(componentName);1900      } else {1901        didWarnStateUpdateForNotYetMountedComponent = new Set([componentName]);1902      }1903      var previousFiber = current;1904      try {1905        setCurrentFiber(fiber);1906        error("Can't perform a React state update on a component that hasn't mounted yet. " + 'This indicates that you have a side-effect in your render function that ' + 'asynchronously later calls tries to update the component. Move this work to ' + 'useEffect instead.');1907      } finally {1908        if (previousFiber) {1909          setCurrentFiber(fiber);1910        } else {1911          resetCurrentFiber();1912        }1913      }1914    }1915  }1916  var didWarnStateUpdateForUnmountedComponent = null;1917  function warnAboutUpdateOnUnmountedFiberInDEV(fiber) {1918    {1919      var tag = fiber.tag;1920      if (tag !== HostRoot && tag !== ClassComponent && tag !== FunctionComponent && tag !== ForwardRef && tag !== MemoComponent && tag !== SimpleMemoComponent && tag !== Block) {1921        // Only warn for user-defined components, not internal ones like Suspense.1922        return;1923      } // If there are pending passive effects unmounts for this Fiber,1924      // we can assume that they would have prevented this update.1925      if ((fiber.flags & PassiveUnmountPendingDev) !== NoFlags) {1926        return;1927      } // We show the whole stack but dedupe on the top component's name because1928      // the problematic code almost always lies inside that component.1929      var componentName = getComponentName(fiber.type) || 'ReactComponent';1930      if (didWarnStateUpdateForUnmountedComponent !== null) {1931        if (didWarnStateUpdateForUnmountedComponent.has(componentName)) {1932          return;1933        }1934        didWarnStateUpdateForUnmountedComponent.add(componentName);1935      } else {1936        didWarnStateUpdateForUnmountedComponent = new Set([componentName]);1937      }1938      if (isFlushingPassiveEffects) ; else {1939        var previousFiber = current;1940        try {1941          setCurrentFiber(fiber);1942          error("Can't perform a React state update on an unmounted component. This " + 'is a no-op, but it indicates a memory leak in your application. To ' + 'fix, cancel all subscriptions and asynchronous tasks in %s.', tag === ClassComponent ? 'the componentWillUnmount method' : 'a useEffect cleanup function');1943        } finally {1944          if (previousFiber) {1945            setCurrentFiber(fiber);1946          } else {1947            resetCurrentFiber();1948          }1949        }1950      }1951    }1952  }1953  var beginWork$1;1954  {1955    var dummyFiber = null;1956    beginWork$1 = function (current, unitOfWork, lanes) {1957      // If a component throws an error, we replay it again in a synchronously1958      // dispatched event, so that the debugger will treat it as an uncaught1959      // error See ReactErrorUtils for more information.1960      // Before entering the begin phase, copy the work-in-progress onto a dummy1961      // fiber. If beginWork throws, we'll use this to reset the state.1962      var originalWorkInProgressCopy = assignFiberPropertiesInDEV(dummyFiber, unitOfWork);1963      try {1964        return beginWork(current, unitOfWork, lanes);1965      } catch (originalError) {1966        if (originalError !== null && typeof originalError === 'object' && typeof originalError.then === 'function') {1967          // Don't replay promises. Treat everything else like an error.1968          throw originalError;1969        } // Keep this code in sync with handleError; any changes here must have1970        // corresponding changes there.1971        resetContextDependencies();1972        resetHooksAfterThrow(); // Don't reset current debug fiber, since we're about to work on the1973        // same fiber again.1974        // Unwind the failed stack frame1975        unwindInterruptedWork(unitOfWork); // Restore the original properties of the fiber.1976        assignFiberPropertiesInDEV(unitOfWork, originalWorkInProgressCopy);1977        if ( unitOfWork.mode & ProfileMode) {1978          // Reset the profiler timer.1979          startProfilerTimer(unitOfWork);1980        } // Run beginWork again.1981        invokeGuardedCallback(null, beginWork, null, current, unitOfWork, lanes);1982        if (hasCaughtError()) {1983          var replayError = clearCaughtError(); // `invokeGuardedCallback` sometimes sets an expando `_suppressLogging`.1984          // Rethrow this error instead of the original one.1985          throw replayError;1986        } else {1987          // This branch is reachable if the render phase is impure.1988          throw originalError;1989        }1990      }1991    };1992  }1993  var didWarnAboutUpdateInRender = false;1994  var didWarnAboutUpdateInRenderForAnotherComponent;1995  {1996    didWarnAboutUpdateInRenderForAnotherComponent = new Set();1997  }1998  function warnAboutRenderPhaseUpdatesInDEV(fiber) {1999    {2000      if (isRendering && (executionContext & RenderContext) !== NoContext && !getIsUpdatingOpaqueValueInRenderPhaseInDEV()) {2001        switch (fiber.tag) {2002          case FunctionComponent:2003          case ForwardRef:2004          case SimpleMemoComponent:2005            {2006              var renderingComponentName = workInProgress && getComponentName(workInProgress.type) || 'Unknown'; // Dedupe by the rendering component because it's the one that needs to be fixed.2007              var dedupeKey = renderingComponentName;2008              if (!didWarnAboutUpdateInRenderForAnotherComponent.has(dedupeKey)) {2009                didWarnAboutUpdateInRenderForAnotherComponent.add(dedupeKey);2010                var setStateComponentName = getComponentName(fiber.type) || 'Unknown';2011                error('Cannot update a component (`%s`) while rendering a ' + 'different component (`%s`). To locate the bad setState() call inside `%s`, ' + 'follow the stack trace as described in https://reactjs.org/link/setstate-in-render', setStateComponentName, renderingComponentName, renderingComponentName);2012              }2013              break;2014            }2015          case ClassComponent:2016            {2017              if (!didWarnAboutUpdateInRender) {2018                error('Cannot update during an existing state transition (such as ' + 'within `render`). Render methods should be a pure ' + 'function of props and state.');2019                didWarnAboutUpdateInRender = true;2020              }2021              break;2022            }2023        }2024      }2025    }2026  } // a 'shared' variable that changes when act() opens/closes in tests.2027  var IsThisRendererActing = {2028    current: false2029  };2030  function warnIfNotScopedWithMatchingAct(fiber) {2031    {2032      if ( IsSomeRendererActing.current === true && IsThisRendererActing.current !== true) {2033        var previousFiber = current;2034        try {2035          setCurrentFiber(fiber);2036          error("It looks like you're using the wrong act() around your test interactions.\n" + 'Be sure to use the matching version of act() corresponding to your renderer:\n\n' + '// for react-dom:\n' + // Break up imports to avoid accidentally parsing them as dependencies.2037          'import {act} fr' + "om 'react-dom/test-utils';\n" + '// ...\n' + 'act(() => ...);\n\n' + '// for react-test-renderer:\n' + // Break up imports to avoid accidentally parsing them as dependencies.2038          'import TestRenderer fr' + "om react-test-renderer';\n" + 'const {act} = TestRenderer;\n' + '// ...\n' + 'act(() => ...);');2039        } finally {2040          if (previousFiber) {2041            setCurrentFiber(fiber);2042          } else {2043            resetCurrentFiber();2044          }2045        }2046      }2047    }2048  }2049  function warnIfNotCurrentlyActingEffectsInDEV(fiber) {2050    {2051      if ( (fiber.mode & StrictMode) !== NoMode && IsSomeRendererActing.current === false && IsThisRendererActing.current === false) {2052        error('An update to %s ran an effect, but was not wrapped in act(...).\n\n' + 'When testing, code that causes React state updates should be ' + 'wrapped into act(...):\n\n' + 'act(() => {\n' + '  /* fire events that update state */\n' + '});\n' + '/* assert on the output */\n\n' + "This ensures that you're testing the behavior the user would see " + 'in the browser.' + ' Learn more at https://reactjs.org/link/wrap-tests-with-act', getComponentName(fiber.type));2053      }2054    }2055  }2056  function warnIfNotCurrentlyActingUpdatesInDEV(fiber) {2057    {2058      if ( executionContext === NoContext && IsSomeRendererActing.current === false && IsThisRendererActing.current === false) {2059        var previousFiber = current;2060        try {2061          setCurrentFiber(fiber);2062          error('An update to %s inside a test was not wrapped in act(...).\n\n' + 'When testing, code that causes React state updates should be ' + 'wrapped into act(...):\n\n' + 'act(() => {\n' + '  /* fire events that update state */\n' + '});\n' + '/* assert on the output */\n\n' + "This ensures that you're testing the behavior the user would see " + 'in the browser.' + ' Learn more at https://reactjs.org/link/wrap-tests-with-act', getComponentName(fiber.type));2063        } finally {2064          if (previousFiber) {2065            setCurrentFiber(fiber);2066          } else {2067            resetCurrentFiber();2068          }2069        }2070      }2071    }2072  }2073  var warnIfNotCurrentlyActingUpdatesInDev = warnIfNotCurrentlyActingUpdatesInDEV; // In tests, we want to enforce a mocked scheduler.2074  var didWarnAboutUnmockedScheduler = false; // TODO Before we release concurrent mode, revisit this and decide whether a mocked2075  // scheduler is the actual recommendation. The alternative could be a testing build,2076  // a new lib, or whatever; we dunno just yet. This message is for early adopters2077  // to get their tests right.2078  function warnIfUnmockedScheduler(fiber) {2079    {2080      if (didWarnAboutUnmockedScheduler === false && unstable_flushAllWithoutAsserting === undefined) {2081        if (fiber.mode & BlockingMode || fiber.mode & ConcurrentMode) {2082          didWarnAboutUnmockedScheduler = true;2083          error('In Concurrent or Sync modes, the "scheduler" module needs to be mocked ' + 'to guarantee consistent behaviour across tests and browsers. ' + 'For example, with jest: \n' + // Break up requires to avoid accidentally parsing them as dependencies.2084          "jest.mock('scheduler', () => require" + "('scheduler/unstable_mock'));\n\n" + 'For more info, visit https://reactjs.org/link/mock-scheduler');2085        }2086      }2087    }2088  }2089  function computeThreadID(root, lane) {2090    // Interaction threads are unique per root and expiration time.2091    // NOTE: Intentionally unsound cast. All that matters is that it's a number2092    // and it represents a batch of work. Could make a helper function instead,2093    // but meh this is fine for now.2094    return lane * 1000 + root.interactionThreadID;2095  }2096  function markSpawnedWork(lane) {2097    if (spawnedWorkDuringRender === null) {2098      spawnedWorkDuringRender = [lane];2099    } else {2100      spawnedWorkDuringRender.push(lane);2101    }2102  }2103  function scheduleInteractions(root, lane, interactions) {2104    if (interactions.size > 0) {2105      var pendingInteractionMap = root.pendingInteractionMap;2106      var pendingInteractions = pendingInteractionMap.get(lane);2107      if (pendingInteractions != null) {2108        interactions.forEach(function (interaction) {2109          if (!pendingInteractions.has(interaction)) {2110            // Update the pending async work count for previously unscheduled interaction.2111            interaction.__count++;2112          }2113          pendingInteractions.add(interaction);2114        });2115      } else {2116        pendingInteractionMap.set(lane, new Set(interactions)); // Update the pending async work count for the current interactions.2117        interactions.forEach(function (interaction) {2118          interaction.__count++;2119        });2120      }2121      var subscriber = __subscriberRef.current;2122      if (subscriber !== null) {2123        var threadID = computeThreadID(root, lane);2124        subscriber.onWorkScheduled(interactions, threadID);2125      }2126    }2127  }2128  function schedulePendingInteractions(root, lane) {2129    scheduleInteractions(root, lane, __interactionsRef.current);2130  }2131  function startWorkOnPendingInteractions(root, lanes) {2132    // we can accurately attribute time spent working on it, And so that cascading2133    // work triggered during the render phase will be associated with it.2134    var interactions = new Set();2135    root.pendingInteractionMap.forEach(function (scheduledInteractions, scheduledLane) {2136      if (includesSomeLane(lanes, scheduledLane)) {2137        scheduledInteractions.forEach(function (interaction) {2138          return interactions.add(interaction);2139        });2140      }2141    }); // Store the current set of interactions on the FiberRoot for a few reasons:2142    // We can re-use it in hot functions like performConcurrentWorkOnRoot()2143    // without having to recalculate it. We will also use it in commitWork() to2144    // pass to any Profiler onRender() hooks. This also provides DevTools with a2145    // way to access it when the onCommitRoot() hook is called.2146    root.memoizedInteractions = interactions;2147    if (interactions.size > 0) {2148      var subscriber = __subscriberRef.current;2149      if (subscriber !== null) {2150        var threadID = computeThreadID(root, lanes);2151        try {2152          subscriber.onWorkStarted(interactions, threadID);2153        } catch (error) {2154          // If the subscriber throws, rethrow it in a separate task2155          scheduleCallback(ImmediatePriority$1, function () {2156            throw error;2157          });2158        }2159      }2160    }2161  }2162  function finishPendingInteractions(root, committedLanes) {2163    var remainingLanesAfterCommit = root.pendingLanes;2164    var subscriber;2165    try {2166      subscriber = __subscriberRef.current;2167      if (subscriber !== null && root.memoizedInteractions.size > 0) {2168        // FIXME: More than one lane can finish in a single commit.2169        var threadID = computeThreadID(root, committedLanes);2170        subscriber.onWorkStopped(root.memoizedInteractions, threadID);2171      }2172    } catch (error) {2173      // If the subscriber throws, rethrow it in a separate task2174      scheduleCallback(ImmediatePriority$1, function () {2175        throw error;2176      });...ReactFiberScheduler.js
Source:ReactFiberScheduler.js  
...1302    if (enableSchedulerTracing) {1303      // If there are no passive effects, then we can complete the pending1304      // interactions. Otherwise, we'll wait until after the passive effects1305      // are flushed.1306      finishPendingInteractions(root, expirationTime);1307    }1308  }1309  // Check if there's remaining work on this root1310  const remainingExpirationTime = root.firstPendingTime;1311  if (remainingExpirationTime !== NoWork) {1312    const currentTime = requestCurrentTime();1313    const priorityLevel = inferPriorityFromExpirationTime(1314      currentTime,1315      remainingExpirationTime,1316    );1317    scheduleCallbackForRoot(root, priorityLevel, remainingExpirationTime);1318  } else {1319    // If there's no remaining work, we can clear the set of already failed1320    // error boundaries.1321    legacyErrorBoundariesThatAlreadyFailed = null;1322  }1323  onCommitRoot(finishedWork.stateNode);1324  if (remainingExpirationTime === Sync) {1325    // Count the number of times the root synchronously re-renders without1326    // finishing. If there are too many, it indicates an infinite update loop.1327    if (root === rootWithNestedUpdates) {1328      nestedUpdateCount++;1329    } else {1330      nestedUpdateCount = 0;1331      rootWithNestedUpdates = root;1332    }1333  } else {1334    nestedUpdateCount = 0;1335  }1336  if (hasUncaughtError) {1337    hasUncaughtError = false;1338    const error = firstUncaughtError;1339    firstUncaughtError = null;1340    throw error;1341  }1342  if (workPhase === LegacyUnbatchedPhase) {1343    // This is a legacy edge case. We just committed the initial mount of1344    // a ReactDOM.render-ed root inside of batchedUpdates. The commit fired1345    // synchronously, but layout updates should be deferred until the end1346    // of the batch.1347    return null;1348  }1349  // If layout work was scheduled, flush it now.1350  flushImmediateQueue();1351  return null;1352}1353function commitBeforeMutationEffects() {1354  while (nextEffect !== null) {1355    if ((nextEffect.effectTag & Snapshot) !== NoEffect) {1356      setCurrentDebugFiberInDEV(nextEffect);1357      recordEffect();1358      const current = nextEffect.alternate;1359      commitBeforeMutationEffectOnFiber(current, nextEffect);1360      resetCurrentDebugFiberInDEV();1361    }1362    nextEffect = nextEffect.nextEffect;1363  }1364}1365function commitMutationEffects() {1366  // TODO: Should probably move the bulk of this function to commitWork.1367  while (nextEffect !== null) {1368    setCurrentDebugFiberInDEV(nextEffect);1369    const effectTag = nextEffect.effectTag;1370    if (effectTag & ContentReset) {1371      commitResetTextContent(nextEffect);1372    }1373    if (effectTag & Ref) {1374      const current = nextEffect.alternate;1375      if (current !== null) {1376        commitDetachRef(current);1377      }1378    }1379    // The following switch statement is only concerned about placement,1380    // updates, and deletions. To avoid needing to add a case for every possible1381    // bitmap value, we remove the secondary effects from the effect tag and1382    // switch on that value.1383    let primaryEffectTag = effectTag & (Placement | Update | Deletion);1384    switch (primaryEffectTag) {1385      case Placement: {1386        commitPlacement(nextEffect);1387        // Clear the "placement" from effect tag so that we know that this is1388        // inserted, before any life-cycles like componentDidMount gets called.1389        // TODO: findDOMNode doesn't rely on this any more but isMounted does1390        // and isMounted is deprecated anyway so we should be able to kill this.1391        nextEffect.effectTag &= ~Placement;1392        break;1393      }1394      case PlacementAndUpdate: {1395        // Placement1396        commitPlacement(nextEffect);1397        // Clear the "placement" from effect tag so that we know that this is1398        // inserted, before any life-cycles like componentDidMount gets called.1399        nextEffect.effectTag &= ~Placement;1400        // Update1401        const current = nextEffect.alternate;1402        commitWork(current, nextEffect);1403        break;1404      }1405      case Update: {1406        const current = nextEffect.alternate;1407        commitWork(current, nextEffect);1408        break;1409      }1410      case Deletion: {1411        commitDeletion(nextEffect);1412        break;1413      }1414    }1415    // TODO: Only record a mutation effect if primaryEffectTag is non-zero.1416    recordEffect();1417    resetCurrentDebugFiberInDEV();1418    nextEffect = nextEffect.nextEffect;1419  }1420}1421function commitLayoutEffects(1422  root: FiberRoot,1423  committedExpirationTime: ExpirationTime,1424) {1425  // TODO: Should probably move the bulk of this function to commitWork.1426  while (nextEffect !== null) {1427    setCurrentDebugFiberInDEV(nextEffect);1428    const effectTag = nextEffect.effectTag;1429    if (effectTag & (Update | Callback)) {1430      recordEffect();1431      const current = nextEffect.alternate;1432      commitLayoutEffectOnFiber(1433        root,1434        current,1435        nextEffect,1436        committedExpirationTime,1437      );1438    }1439    if (effectTag & Ref) {1440      recordEffect();1441      commitAttachRef(nextEffect);1442    }1443    if (effectTag & Passive) {1444      rootDoesHavePassiveEffects = true;1445    }1446    resetCurrentDebugFiberInDEV();1447    nextEffect = nextEffect.nextEffect;1448  }1449}1450export function flushPassiveEffects() {1451  if (rootWithPendingPassiveEffects === null) {1452    return false;1453  }1454  const root = rootWithPendingPassiveEffects;1455  const expirationTime = pendingPassiveEffectsExpirationTime;1456  rootWithPendingPassiveEffects = null;1457  pendingPassiveEffectsExpirationTime = NoWork;1458  let prevInteractions: Set<Interaction> | null = null;1459  if (enableSchedulerTracing) {1460    prevInteractions = __interactionsRef.current;1461    __interactionsRef.current = root.memoizedInteractions;1462  }1463  invariant(1464    workPhase !== RenderPhase && workPhase !== CommitPhase,1465    'Cannot flush passive effects while already rendering.',1466  );1467  const prevWorkPhase = workPhase;1468  workPhase = CommitPhase;1469  // Note: This currently assumes there are no passive effects on the root1470  // fiber, because the root is not part of its own effect list. This could1471  // change in the future.1472  let effect = root.current.firstEffect;1473  while (effect !== null) {1474    if (__DEV__) {1475      setCurrentDebugFiberInDEV(effect);1476      invokeGuardedCallback(null, commitPassiveHookEffects, null, effect);1477      if (hasCaughtError()) {1478        invariant(effect !== null, 'Should be working on an effect.');1479        const error = clearCaughtError();1480        captureCommitPhaseError(effect, error);1481      }1482      resetCurrentDebugFiberInDEV();1483    } else {1484      try {1485        commitPassiveHookEffects(effect);1486      } catch (error) {1487        invariant(effect !== null, 'Should be working on an effect.');1488        captureCommitPhaseError(effect, error);1489      }1490    }1491    effect = effect.nextEffect;1492  }1493  if (enableSchedulerTracing) {1494    __interactionsRef.current = ((prevInteractions: any): Set<Interaction>);1495    finishPendingInteractions(root, expirationTime);1496  }1497  workPhase = prevWorkPhase;1498  flushImmediateQueue();1499  // If additional passive effects were scheduled, increment a counter. If this1500  // exceeds the limit, we'll fire a warning.1501  nestedPassiveUpdateCount =1502    rootWithPendingPassiveEffects === null ? 0 : nestedPassiveUpdateCount + 1;1503  return true;1504}1505export function isAlreadyFailedLegacyErrorBoundary(instance: mixed): boolean {1506  return (1507    legacyErrorBoundariesThatAlreadyFailed !== null &&1508    legacyErrorBoundariesThatAlreadyFailed.has(instance)1509  );1510}1511export function markLegacyErrorBoundaryAsFailed(instance: mixed) {1512  if (legacyErrorBoundariesThatAlreadyFailed === null) {1513    legacyErrorBoundariesThatAlreadyFailed = new Set([instance]);1514  } else {1515    legacyErrorBoundariesThatAlreadyFailed.add(instance);1516  }1517}1518function prepareToThrowUncaughtError(error: mixed) {1519  if (!hasUncaughtError) {1520    hasUncaughtError = true;1521    firstUncaughtError = error;1522  }1523}1524export const onUncaughtError = prepareToThrowUncaughtError;1525function captureCommitPhaseErrorOnRoot(1526  rootFiber: Fiber,1527  sourceFiber: Fiber,1528  error: mixed,1529) {1530  const errorInfo = createCapturedValue(error, sourceFiber);1531  const update = createRootErrorUpdate(rootFiber, errorInfo, Sync);1532  enqueueUpdate(rootFiber, update);1533  const root = markUpdateTimeFromFiberToRoot(rootFiber, Sync);1534  if (root !== null) {1535    scheduleCallbackForRoot(root, ImmediatePriority, Sync);1536  }1537}1538export function captureCommitPhaseError(sourceFiber: Fiber, error: mixed) {1539  if (sourceFiber.tag === HostRoot) {1540    // Error was thrown at the root. There is no parent, so the root1541    // itself should capture it.1542    captureCommitPhaseErrorOnRoot(sourceFiber, sourceFiber, error);1543    return;1544  }1545  let fiber = sourceFiber.return;1546  while (fiber !== null) {1547    if (fiber.tag === HostRoot) {1548      captureCommitPhaseErrorOnRoot(fiber, sourceFiber, error);1549      return;1550    } else if (fiber.tag === ClassComponent) {1551      const ctor = fiber.type;1552      const instance = fiber.stateNode;1553      if (1554        typeof ctor.getDerivedStateFromError === 'function' ||1555        (typeof instance.componentDidCatch === 'function' &&1556          !isAlreadyFailedLegacyErrorBoundary(instance))1557      ) {1558        const errorInfo = createCapturedValue(error, sourceFiber);1559        const update = createClassErrorUpdate(1560          fiber,1561          errorInfo,1562          // TODO: This is always sync1563          Sync,1564        );1565        enqueueUpdate(fiber, update);1566        const root = markUpdateTimeFromFiberToRoot(fiber, Sync);1567        if (root !== null) {1568          scheduleCallbackForRoot(root, ImmediatePriority, Sync);1569        }1570        return;1571      }1572    }1573    fiber = fiber.return;1574  }1575}1576export function pingSuspendedRoot(1577  root: FiberRoot,1578  thenable: Thenable,1579  suspendedTime: ExpirationTime,1580) {1581  const pingCache = root.pingCache;1582  if (pingCache !== null) {1583    // The thenable resolved, so we no longer need to memoize, because it will1584    // never be thrown again.1585    pingCache.delete(thenable);1586  }1587  if (workInProgressRoot === root && renderExpirationTime === suspendedTime) {1588    // Received a ping at the same priority level at which we're currently1589    // rendering. Restart from the root. Don't need to schedule a ping because1590    // we're already working on this tree.1591    prepareFreshStack(root, renderExpirationTime);1592    return;1593  }1594  const lastPendingTime = root.lastPendingTime;1595  if (lastPendingTime < suspendedTime) {1596    // The root is no longer suspended at this time.1597    return;1598  }1599  const pingTime = root.pingTime;1600  if (pingTime !== NoWork && pingTime < suspendedTime) {1601    // There's already a lower priority ping scheduled.1602    return;1603  }1604  // Mark the time at which this ping was scheduled.1605  root.pingTime = suspendedTime;1606  const currentTime = requestCurrentTime();1607  const priorityLevel = inferPriorityFromExpirationTime(1608    currentTime,1609    suspendedTime,1610  );1611  scheduleCallbackForRoot(root, priorityLevel, suspendedTime);1612}1613export function retryTimedOutBoundary(boundaryFiber: Fiber) {1614  // The boundary fiber (a Suspense component) previously timed out and was1615  // rendered in its fallback state. One of the promises that suspended it has1616  // resolved, which means at least part of the tree was likely unblocked. Try1617  // rendering again, at a new expiration time.1618  const currentTime = requestCurrentTime();1619  const retryTime = computeExpirationForFiber(currentTime, boundaryFiber);1620  // TODO: Special case idle priority?1621  const priorityLevel = inferPriorityFromExpirationTime(currentTime, retryTime);1622  const root = markUpdateTimeFromFiberToRoot(boundaryFiber, retryTime);1623  if (root !== null) {1624    scheduleCallbackForRoot(root, priorityLevel, retryTime);1625  }1626}1627export function resolveRetryThenable(boundaryFiber: Fiber, thenable: Thenable) {1628  let retryCache: WeakSet<Thenable> | Set<Thenable> | null;1629  if (enableSuspenseServerRenderer) {1630    switch (boundaryFiber.tag) {1631      case SuspenseComponent:1632        retryCache = boundaryFiber.stateNode;1633        break;1634      case DehydratedSuspenseComponent:1635        retryCache = boundaryFiber.memoizedState;1636        break;1637      default:1638        invariant(1639          false,1640          'Pinged unknown suspense boundary type. ' +1641            'This is probably a bug in React.',1642        );1643    }1644  } else {1645    retryCache = boundaryFiber.stateNode;1646  }1647  if (retryCache !== null) {1648    // The thenable resolved, so we no longer need to memoize, because it will1649    // never be thrown again.1650    retryCache.delete(thenable);1651  }1652  retryTimedOutBoundary(boundaryFiber);1653}1654// Computes the next Just Noticeable Difference (JND) boundary.1655// The theory is that a person can't tell the difference between small differences in time.1656// Therefore, if we wait a bit longer than necessary that won't translate to a noticeable1657// difference in the experience. However, waiting for longer might mean that we can avoid1658// showing an intermediate loading state. The longer we have already waited, the harder it1659// is to tell small differences in time. Therefore, the longer we've already waited,1660// the longer we can wait additionally. At some point we have to give up though.1661// We pick a train model where the next boundary commits at a consistent schedule.1662// These particular numbers are vague estimates. We expect to adjust them based on research.1663function jnd(timeElapsed: number) {1664  return timeElapsed < 1201665    ? 1201666    : timeElapsed < 4801667      ? 4801668      : timeElapsed < 10801669        ? 10801670        : timeElapsed < 19201671          ? 19201672          : timeElapsed < 30001673            ? 30001674            : timeElapsed < 43201675              ? 43201676              : ceil(timeElapsed / 1960) * 1960;1677}1678function computeMsUntilTimeout(1679  mostRecentEventTime: ExpirationTime,1680  committedExpirationTime: ExpirationTime,1681) {1682  if (disableYielding) {1683    // Timeout immediately when yielding is disabled.1684    return 0;1685  }1686  const eventTimeMs: number = inferTimeFromExpirationTime(mostRecentEventTime);1687  const currentTimeMs: number = now();1688  const timeElapsed = currentTimeMs - eventTimeMs;1689  let msUntilTimeout = jnd(timeElapsed) - timeElapsed;1690  // Compute the time until this render pass would expire.1691  const timeUntilExpirationMs =1692    expirationTimeToMs(committedExpirationTime) - currentTimeMs;1693  // Clamp the timeout to the expiration time.1694  // TODO: Once the event time is exact instead of inferred from expiration time1695  // we don't need this.1696  if (timeUntilExpirationMs < msUntilTimeout) {1697    msUntilTimeout = timeUntilExpirationMs;1698  }1699  // This is the value that is passed to `setTimeout`.1700  return msUntilTimeout;1701}1702function checkForNestedUpdates() {1703  if (nestedUpdateCount > NESTED_UPDATE_LIMIT) {1704    nestedUpdateCount = 0;1705    rootWithNestedUpdates = null;1706    invariant(1707      false,1708      'Maximum update depth exceeded. This can happen when a component ' +1709        'repeatedly calls setState inside componentWillUpdate or ' +1710        'componentDidUpdate. React limits the number of nested updates to ' +1711        'prevent infinite loops.',1712    );1713  }1714  if (__DEV__) {1715    if (nestedPassiveUpdateCount > NESTED_PASSIVE_UPDATE_LIMIT) {1716      nestedPassiveUpdateCount = 0;1717      warning(1718        false,1719        'Maximum update depth exceeded. This can happen when a component ' +1720          "calls setState inside useEffect, but useEffect either doesn't " +1721          'have a dependency array, or one of the dependencies changes on ' +1722          'every render.',1723      );1724    }1725  }1726}1727function flushRenderPhaseStrictModeWarningsInDEV() {1728  if (__DEV__) {1729    ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings();1730    ReactStrictModeWarnings.flushLegacyContextWarning();1731    if (warnAboutDeprecatedLifecycles) {1732      ReactStrictModeWarnings.flushPendingDeprecationWarnings();1733    }1734  }1735}1736function stopFinishedWorkLoopTimer() {1737  const didCompleteRoot = true;1738  stopWorkLoopTimer(interruptedBy, didCompleteRoot);1739  interruptedBy = null;1740}1741function stopInterruptedWorkLoopTimer() {1742  // TODO: Track which fiber caused the interruption.1743  const didCompleteRoot = false;1744  stopWorkLoopTimer(interruptedBy, didCompleteRoot);1745  interruptedBy = null;1746}1747function checkForInterruption(1748  fiberThatReceivedUpdate: Fiber,1749  updateExpirationTime: ExpirationTime,1750) {1751  if (1752    enableUserTimingAPI &&1753    workInProgressRoot !== null &&1754    updateExpirationTime > renderExpirationTime1755  ) {1756    interruptedBy = fiberThatReceivedUpdate;1757  }1758}1759let didWarnStateUpdateForUnmountedComponent: Set<string> | null = null;1760function warnAboutUpdateOnUnmountedFiberInDEV(fiber) {1761  if (__DEV__) {1762    const tag = fiber.tag;1763    if (1764      tag !== HostRoot &&1765      tag !== ClassComponent &&1766      tag !== FunctionComponent &&1767      tag !== ForwardRef &&1768      tag !== MemoComponent &&1769      tag !== SimpleMemoComponent1770    ) {1771      // Only warn for user-defined components, not internal ones like Suspense.1772      return;1773    }1774    // We show the whole stack but dedupe on the top component's name because1775    // the problematic code almost always lies inside that component.1776    const componentName = getComponentName(fiber.type) || 'ReactComponent';1777    if (didWarnStateUpdateForUnmountedComponent !== null) {1778      if (didWarnStateUpdateForUnmountedComponent.has(componentName)) {1779        return;1780      }1781      didWarnStateUpdateForUnmountedComponent.add(componentName);1782    } else {1783      didWarnStateUpdateForUnmountedComponent = new Set([componentName]);1784    }1785    warningWithoutStack(1786      false,1787      "Can't perform a React state update on an unmounted component. This " +1788        'is a no-op, but it indicates a memory leak in your application. To ' +1789        'fix, cancel all subscriptions and asynchronous tasks in %s.%s',1790      tag === ClassComponent1791        ? 'the componentWillUnmount method'1792        : 'a useEffect cleanup function',1793      getStackByFiberInDevAndProd(fiber),1794    );1795  }1796}1797let beginWork;1798if (__DEV__ && replayFailedUnitOfWorkWithInvokeGuardedCallback) {1799  let dummyFiber = null;1800  beginWork = (current, unitOfWork, expirationTime) => {1801    // If a component throws an error, we replay it again in a synchronously1802    // dispatched event, so that the debugger will treat it as an uncaught1803    // error See ReactErrorUtils for more information.1804    // Before entering the begin phase, copy the work-in-progress onto a dummy1805    // fiber. If beginWork throws, we'll use this to reset the state.1806    const originalWorkInProgressCopy = assignFiberPropertiesInDEV(1807      dummyFiber,1808      unitOfWork,1809    );1810    try {1811      return originalBeginWork(current, unitOfWork, expirationTime);1812    } catch (originalError) {1813      if (1814        originalError !== null &&1815        typeof originalError === 'object' &&1816        typeof originalError.then === 'function'1817      ) {1818        // Don't replay promises. Treat everything else like an error.1819        throw originalError;1820      }1821      // Keep this code in sync with renderRoot; any changes here must have1822      // corresponding changes there.1823      resetContextDependencies();1824      resetHooks();1825      // Unwind the failed stack frame1826      unwindInterruptedWork(unitOfWork);1827      // Restore the original properties of the fiber.1828      assignFiberPropertiesInDEV(unitOfWork, originalWorkInProgressCopy);1829      if (enableProfilerTimer && unitOfWork.mode & ProfileMode) {1830        // Reset the profiler timer.1831        startProfilerTimer(unitOfWork);1832      }1833      // Run beginWork again.1834      invokeGuardedCallback(1835        null,1836        originalBeginWork,1837        null,1838        current,1839        unitOfWork,1840        expirationTime,1841      );1842      if (hasCaughtError()) {1843        const replayError = clearCaughtError();1844        // `invokeGuardedCallback` sometimes sets an expando `_suppressLogging`.1845        // Rethrow this error instead of the original one.1846        throw replayError;1847      } else {1848        // This branch is reachable if the render phase is impure.1849        throw originalError;1850      }1851    }1852  };1853} else {1854  beginWork = originalBeginWork;1855}1856let didWarnAboutUpdateInRender = false;1857let didWarnAboutUpdateInGetChildContext = false;1858function warnAboutInvalidUpdatesOnClassComponentsInDEV(fiber) {1859  if (__DEV__) {1860    if (fiber.tag === ClassComponent) {1861      switch (ReactCurrentDebugFiberPhaseInDEV) {1862        case 'getChildContext':1863          if (didWarnAboutUpdateInGetChildContext) {1864            return;1865          }1866          warningWithoutStack(1867            false,1868            'setState(...): Cannot call setState() inside getChildContext()',1869          );1870          didWarnAboutUpdateInGetChildContext = true;1871          break;1872        case 'render':1873          if (didWarnAboutUpdateInRender) {1874            return;1875          }1876          warningWithoutStack(1877            false,1878            'Cannot update during an existing state transition (such as ' +1879              'within `render`). Render methods should be a pure function of ' +1880              'props and state.',1881          );1882          didWarnAboutUpdateInRender = true;1883          break;1884      }1885    }1886  }1887}1888function warnIfNotCurrentlyActingUpdatesInDEV(fiber: Fiber): void {1889  if (__DEV__) {1890    if (1891      workPhase === NotWorking &&1892      ReactShouldWarnActingUpdates.current === false1893    ) {1894      warningWithoutStack(1895        false,1896        'An update to %s inside a test was not wrapped in act(...).\n\n' +1897          'When testing, code that causes React state updates should be ' +1898          'wrapped into act(...):\n\n' +1899          'act(() => {\n' +1900          '  /* fire events that update state */\n' +1901          '});\n' +1902          '/* assert on the output */\n\n' +1903          "This ensures that you're testing the behavior the user would see " +1904          'in the browser.' +1905          ' Learn more at https://fb.me/react-wrap-tests-with-act' +1906          '%s',1907        getComponentName(fiber.type),1908        getStackByFiberInDevAndProd(fiber),1909      );1910    }1911  }1912}1913export const warnIfNotCurrentlyActingUpdatesInDev = warnIfNotCurrentlyActingUpdatesInDEV;1914function computeThreadID(root, expirationTime) {1915  // Interaction threads are unique per root and expiration time.1916  return expirationTime * 1000 + root.interactionThreadID;1917}1918function schedulePendingInteraction(root, expirationTime) {1919  // This is called when work is scheduled on a root. It sets up a pending1920  // interaction, which is completed once the work commits.1921  if (!enableSchedulerTracing) {1922    return;1923  }1924  const interactions = __interactionsRef.current;1925  if (interactions.size > 0) {1926    const pendingInteractionMap = root.pendingInteractionMap;1927    const pendingInteractions = pendingInteractionMap.get(expirationTime);1928    if (pendingInteractions != null) {1929      interactions.forEach(interaction => {1930        if (!pendingInteractions.has(interaction)) {1931          // Update the pending async work count for previously unscheduled interaction.1932          interaction.__count++;1933        }1934        pendingInteractions.add(interaction);1935      });1936    } else {1937      pendingInteractionMap.set(expirationTime, new Set(interactions));1938      // Update the pending async work count for the current interactions.1939      interactions.forEach(interaction => {1940        interaction.__count++;1941      });1942    }1943    const subscriber = __subscriberRef.current;1944    if (subscriber !== null) {1945      const threadID = computeThreadID(root, expirationTime);1946      subscriber.onWorkScheduled(interactions, threadID);1947    }1948  }1949}1950function startWorkOnPendingInteraction(root, expirationTime) {1951  // This is called when new work is started on a root.1952  if (!enableSchedulerTracing) {1953    return;1954  }1955  // Determine which interactions this batch of work currently includes, So that1956  // we can accurately attribute time spent working on it, And so that cascading1957  // work triggered during the render phase will be associated with it.1958  const interactions: Set<Interaction> = new Set();1959  root.pendingInteractionMap.forEach(1960    (scheduledInteractions, scheduledExpirationTime) => {1961      if (scheduledExpirationTime >= expirationTime) {1962        scheduledInteractions.forEach(interaction =>1963          interactions.add(interaction),1964        );1965      }1966    },1967  );1968  // Store the current set of interactions on the FiberRoot for a few reasons:1969  // We can re-use it in hot functions like renderRoot() without having to1970  // recalculate it. We will also use it in commitWork() to pass to any Profiler1971  // onRender() hooks. This also provides DevTools with a way to access it when1972  // the onCommitRoot() hook is called.1973  root.memoizedInteractions = interactions;1974  if (interactions.size > 0) {1975    const subscriber = __subscriberRef.current;1976    if (subscriber !== null) {1977      const threadID = computeThreadID(root, expirationTime);1978      try {1979        subscriber.onWorkStarted(interactions, threadID);1980      } catch (error) {1981        // If the subscriber throws, rethrow it in a separate task1982        scheduleCallback(ImmediatePriority, () => {1983          throw error;1984        });1985      }1986    }1987  }1988}1989function finishPendingInteractions(root, committedExpirationTime) {1990  if (!enableSchedulerTracing) {1991    return;1992  }1993  const earliestRemainingTimeAfterCommit = root.firstPendingTime;1994  let subscriber;1995  try {1996    subscriber = __subscriberRef.current;1997    if (subscriber !== null && root.memoizedInteractions.size > 0) {1998      const threadID = computeThreadID(root, committedExpirationTime);1999      subscriber.onWorkStopped(root.memoizedInteractions, threadID);2000    }2001  } catch (error) {2002    // If the subscriber throws, rethrow it in a separate task2003    scheduleCallback(ImmediatePriority, () => {...ReactFiberScheduler.new.js
Source:ReactFiberScheduler.new.js  
...1286    if (enableSchedulerTracing) {1287      // If there are no passive effects, then we can complete the pending1288      // interactions. Otherwise, we'll wait until after the passive effects1289      // are flushed.1290      finishPendingInteractions(root, expirationTime);1291    }1292  }1293  // Check if there's remaining work on this root1294  const remainingExpirationTime = root.firstPendingTime;1295  if (remainingExpirationTime !== NoWork) {1296    const currentTime = requestCurrentTime();1297    const priorityLevel = inferPriorityFromExpirationTime(1298      currentTime,1299      remainingExpirationTime,1300    );1301    scheduleCallbackForRoot(root, priorityLevel, remainingExpirationTime);1302  } else {1303    // If there's no remaining work, we can clear the set of already failed1304    // error boundaries.1305    legacyErrorBoundariesThatAlreadyFailed = null;1306  }1307  onCommitRoot(finishedWork.stateNode);1308  if (remainingExpirationTime === Sync) {1309    // Count the number of times the root synchronously re-renders without1310    // finishing. If there are too many, it indicates an infinite update loop.1311    if (root === rootWithNestedUpdates) {1312      nestedUpdateCount++;1313    } else {1314      nestedUpdateCount = 0;1315      rootWithNestedUpdates = root;1316    }1317  } else {1318    nestedUpdateCount = 0;1319  }1320  if (hasUncaughtError) {1321    hasUncaughtError = false;1322    const error = firstUncaughtError;1323    firstUncaughtError = null;1324    throw error;1325  }1326  if (workPhase === LegacyUnbatchedPhase) {1327    // This is a legacy edge case. We just committed the initial mount of1328    // a ReactDOM.render-ed root inside of batchedUpdates. The commit fired1329    // synchronously, but layout updates should be deferred until the end1330    // of the batch.1331    return null;1332  }1333  // If layout work was scheduled, flush it now.1334  flushImmediateQueue();1335  return null;1336}1337function commitBeforeMutationEffects() {1338  while (nextEffect !== null) {1339    if ((nextEffect.effectTag & Snapshot) !== NoEffect) {1340      setCurrentDebugFiberInDEV(nextEffect);1341      recordEffect();1342      const current = nextEffect.alternate;1343      commitBeforeMutationEffectOnFiber(current, nextEffect);1344      resetCurrentDebugFiberInDEV();1345    }1346    nextEffect = nextEffect.nextEffect;1347  }1348}1349function commitMutationEffects() {1350  // TODO: Should probably move the bulk of this function to commitWork.1351  while (nextEffect !== null) {1352    setCurrentDebugFiberInDEV(nextEffect);1353    const effectTag = nextEffect.effectTag;1354    if (effectTag & ContentReset) {1355      commitResetTextContent(nextEffect);1356    }1357    if (effectTag & Ref) {1358      const current = nextEffect.alternate;1359      if (current !== null) {1360        commitDetachRef(current);1361      }1362    }1363    // The following switch statement is only concerned about placement,1364    // updates, and deletions. To avoid needing to add a case for every possible1365    // bitmap value, we remove the secondary effects from the effect tag and1366    // switch on that value.1367    let primaryEffectTag = effectTag & (Placement | Update | Deletion);1368    switch (primaryEffectTag) {1369      case Placement: {1370        commitPlacement(nextEffect);1371        // Clear the "placement" from effect tag so that we know that this is1372        // inserted, before any life-cycles like componentDidMount gets called.1373        // TODO: findDOMNode doesn't rely on this any more but isMounted does1374        // and isMounted is deprecated anyway so we should be able to kill this.1375        nextEffect.effectTag &= ~Placement;1376        break;1377      }1378      case PlacementAndUpdate: {1379        // Placement1380        commitPlacement(nextEffect);1381        // Clear the "placement" from effect tag so that we know that this is1382        // inserted, before any life-cycles like componentDidMount gets called.1383        nextEffect.effectTag &= ~Placement;1384        // Update1385        const current = nextEffect.alternate;1386        commitWork(current, nextEffect);1387        break;1388      }1389      case Update: {1390        const current = nextEffect.alternate;1391        commitWork(current, nextEffect);1392        break;1393      }1394      case Deletion: {1395        commitDeletion(nextEffect);1396        break;1397      }1398    }1399    // TODO: Only record a mutation effect if primaryEffectTag is non-zero.1400    recordEffect();1401    resetCurrentDebugFiberInDEV();1402    nextEffect = nextEffect.nextEffect;1403  }1404}1405function commitLayoutEffects(1406  root: FiberRoot,1407  committedExpirationTime: ExpirationTime,1408) {1409  // TODO: Should probably move the bulk of this function to commitWork.1410  while (nextEffect !== null) {1411    setCurrentDebugFiberInDEV(nextEffect);1412    const effectTag = nextEffect.effectTag;1413    if (effectTag & (Update | Callback)) {1414      recordEffect();1415      const current = nextEffect.alternate;1416      commitLayoutEffectOnFiber(1417        root,1418        current,1419        nextEffect,1420        committedExpirationTime,1421      );1422    }1423    if (effectTag & Ref) {1424      recordEffect();1425      commitAttachRef(nextEffect);1426    }1427    if (effectTag & Passive) {1428      rootDoesHavePassiveEffects = true;1429    }1430    resetCurrentDebugFiberInDEV();1431    nextEffect = nextEffect.nextEffect;1432  }1433}1434export function flushPassiveEffects() {1435  if (rootWithPendingPassiveEffects === null) {1436    return false;1437  }1438  const root = rootWithPendingPassiveEffects;1439  const expirationTime = pendingPassiveEffectsExpirationTime;1440  rootWithPendingPassiveEffects = null;1441  pendingPassiveEffectsExpirationTime = NoWork;1442  let prevInteractions: Set<Interaction> | null = null;1443  if (enableSchedulerTracing) {1444    prevInteractions = __interactionsRef.current;1445    __interactionsRef.current = root.memoizedInteractions;1446  }1447  invariant(1448    workPhase !== RenderPhase && workPhase !== CommitPhase,1449    'Cannot flush passive effects while already rendering.',1450  );1451  const prevWorkPhase = workPhase;1452  workPhase = CommitPhase;1453  // Note: This currently assumes there are no passive effects on the root1454  // fiber, because the root is not part of its own effect list. This could1455  // change in the future.1456  let effect = root.current.firstEffect;1457  while (effect !== null) {1458    if (__DEV__) {1459      setCurrentDebugFiberInDEV(effect);1460      invokeGuardedCallback(null, commitPassiveHookEffects, null, effect);1461      if (hasCaughtError()) {1462        invariant(effect !== null, 'Should be working on an effect.');1463        const error = clearCaughtError();1464        captureCommitPhaseError(effect, error);1465      }1466      resetCurrentDebugFiberInDEV();1467    } else {1468      try {1469        commitPassiveHookEffects(effect);1470      } catch (error) {1471        invariant(effect !== null, 'Should be working on an effect.');1472        captureCommitPhaseError(effect, error);1473      }1474    }1475    effect = effect.nextEffect;1476  }1477  if (enableSchedulerTracing) {1478    __interactionsRef.current = ((prevInteractions: any): Set<Interaction>);1479    finishPendingInteractions(root, expirationTime);1480  }1481  workPhase = prevWorkPhase;1482  flushImmediateQueue();1483  // If additional passive effects were scheduled, increment a counter. If this1484  // exceeds the limit, we'll fire a warning.1485  nestedPassiveUpdateCount =1486    rootWithPendingPassiveEffects === null ? 0 : nestedPassiveUpdateCount + 1;1487  return true;1488}1489export function isAlreadyFailedLegacyErrorBoundary(instance: mixed): boolean {1490  return (1491    legacyErrorBoundariesThatAlreadyFailed !== null &&1492    legacyErrorBoundariesThatAlreadyFailed.has(instance)1493  );1494}1495export function markLegacyErrorBoundaryAsFailed(instance: mixed) {1496  if (legacyErrorBoundariesThatAlreadyFailed === null) {1497    legacyErrorBoundariesThatAlreadyFailed = new Set([instance]);1498  } else {1499    legacyErrorBoundariesThatAlreadyFailed.add(instance);1500  }1501}1502function prepareToThrowUncaughtError(error: mixed) {1503  if (!hasUncaughtError) {1504    hasUncaughtError = true;1505    firstUncaughtError = error;1506  }1507}1508export const onUncaughtError = prepareToThrowUncaughtError;1509function captureCommitPhaseErrorOnRoot(1510  rootFiber: Fiber,1511  sourceFiber: Fiber,1512  error: mixed,1513) {1514  const errorInfo = createCapturedValue(error, sourceFiber);1515  const update = createRootErrorUpdate(rootFiber, errorInfo, Sync);1516  enqueueUpdate(rootFiber, update);1517  const root = markUpdateTimeFromFiberToRoot(rootFiber, Sync);1518  if (root !== null) {1519    scheduleCallbackForRoot(root, ImmediatePriority, Sync);1520  }1521}1522export function captureCommitPhaseError(sourceFiber: Fiber, error: mixed) {1523  if (sourceFiber.tag === HostRoot) {1524    // Error was thrown at the root. There is no parent, so the root1525    // itself should capture it.1526    captureCommitPhaseErrorOnRoot(sourceFiber, sourceFiber, error);1527    return;1528  }1529  let fiber = sourceFiber.return;1530  while (fiber !== null) {1531    if (fiber.tag === HostRoot) {1532      captureCommitPhaseErrorOnRoot(fiber, sourceFiber, error);1533      return;1534    } else if (fiber.tag === ClassComponent) {1535      const ctor = fiber.type;1536      const instance = fiber.stateNode;1537      if (1538        typeof ctor.getDerivedStateFromError === 'function' ||1539        (typeof instance.componentDidCatch === 'function' &&1540          !isAlreadyFailedLegacyErrorBoundary(instance))1541      ) {1542        const errorInfo = createCapturedValue(error, sourceFiber);1543        const update = createClassErrorUpdate(1544          fiber,1545          errorInfo,1546          // TODO: This is always sync1547          Sync,1548        );1549        enqueueUpdate(fiber, update);1550        const root = markUpdateTimeFromFiberToRoot(fiber, Sync);1551        if (root !== null) {1552          scheduleCallbackForRoot(root, ImmediatePriority, Sync);1553        }1554        return;1555      }1556    }1557    fiber = fiber.return;1558  }1559}1560export function pingSuspendedRoot(1561  root: FiberRoot,1562  thenable: Thenable,1563  suspendedTime: ExpirationTime,1564) {1565  const pingCache = root.pingCache;1566  if (pingCache !== null) {1567    // The thenable resolved, so we no longer need to memoize, because it will1568    // never be thrown again.1569    pingCache.delete(thenable);1570  }1571  if (workInProgressRoot === root && renderExpirationTime === suspendedTime) {1572    // Received a ping at the same priority level at which we're currently1573    // rendering. Restart from the root. Don't need to schedule a ping because1574    // we're already working on this tree.1575    prepareFreshStack(root, renderExpirationTime);1576    return;1577  }1578  const lastPendingTime = root.lastPendingTime;1579  if (lastPendingTime < suspendedTime) {1580    // The root is no longer suspended at this time.1581    return;1582  }1583  const pingTime = root.pingTime;1584  if (pingTime !== NoWork && pingTime < suspendedTime) {1585    // There's already a lower priority ping scheduled.1586    return;1587  }1588  // Mark the time at which this ping was scheduled.1589  root.pingTime = suspendedTime;1590  const currentTime = requestCurrentTime();1591  const priorityLevel = inferPriorityFromExpirationTime(1592    currentTime,1593    suspendedTime,1594  );1595  scheduleCallbackForRoot(root, priorityLevel, suspendedTime);1596}1597export function retryTimedOutBoundary(boundaryFiber: Fiber) {1598  // The boundary fiber (a Suspense component) previously timed out and was1599  // rendered in its fallback state. One of the promises that suspended it has1600  // resolved, which means at least part of the tree was likely unblocked. Try1601  // rendering again, at a new expiration time.1602  const currentTime = requestCurrentTime();1603  const retryTime = computeExpirationForFiber(currentTime, boundaryFiber);1604  // TODO: Special case idle priority?1605  const priorityLevel = inferPriorityFromExpirationTime(currentTime, retryTime);1606  const root = markUpdateTimeFromFiberToRoot(boundaryFiber, retryTime);1607  if (root !== null) {1608    scheduleCallbackForRoot(root, priorityLevel, retryTime);1609  }1610}1611export function resolveRetryThenable(boundaryFiber: Fiber, thenable: Thenable) {1612  let retryCache: WeakSet<Thenable> | Set<Thenable> | null;1613  if (enableSuspenseServerRenderer) {1614    switch (boundaryFiber.tag) {1615      case SuspenseComponent:1616        retryCache = boundaryFiber.stateNode;1617        break;1618      case DehydratedSuspenseComponent:1619        retryCache = boundaryFiber.memoizedState;1620        break;1621      default:1622        invariant(1623          false,1624          'Pinged unknown suspense boundary type. ' +1625            'This is probably a bug in React.',1626        );1627    }1628  } else {1629    retryCache = boundaryFiber.stateNode;1630  }1631  if (retryCache !== null) {1632    // The thenable resolved, so we no longer need to memoize, because it will1633    // never be thrown again.1634    retryCache.delete(thenable);1635  }1636  retryTimedOutBoundary(boundaryFiber);1637}1638export function inferStartTimeFromExpirationTime(1639  root: FiberRoot,1640  expirationTime: ExpirationTime,1641) {1642  // We don't know exactly when the update was scheduled, but we can infer an1643  // approximate start time from the expiration time.1644  const earliestExpirationTimeMs = expirationTimeToMs(root.firstPendingTime);1645  // TODO: Track this on the root instead. It's more accurate, doesn't rely on1646  // assumptions about priority, and isn't coupled to Scheduler details.1647  return earliestExpirationTimeMs - LOW_PRIORITY_EXPIRATION;1648}1649function computeMsUntilTimeout(root, absoluteTimeoutMs) {1650  if (disableYielding) {1651    // Timeout immediately when yielding is disabled.1652    return 0;1653  }1654  // Find the earliest uncommitted expiration time in the tree, including1655  // work that is suspended. The timeout threshold cannot be longer than1656  // the overall expiration.1657  const earliestExpirationTimeMs = expirationTimeToMs(root.firstPendingTime);1658  if (earliestExpirationTimeMs < absoluteTimeoutMs) {1659    absoluteTimeoutMs = earliestExpirationTimeMs;1660  }1661  // Subtract the current time from the absolute timeout to get the number1662  // of milliseconds until the timeout. In other words, convert an absolute1663  // timestamp to a relative time. This is the value that is passed1664  // to `setTimeout`.1665  let msUntilTimeout = absoluteTimeoutMs - now();1666  return msUntilTimeout < 0 ? 0 : msUntilTimeout;1667}1668function checkForNestedUpdates() {1669  if (nestedUpdateCount > NESTED_UPDATE_LIMIT) {1670    nestedUpdateCount = 0;1671    rootWithNestedUpdates = null;1672    invariant(1673      false,1674      'Maximum update depth exceeded. This can happen when a component ' +1675        'repeatedly calls setState inside componentWillUpdate or ' +1676        'componentDidUpdate. React limits the number of nested updates to ' +1677        'prevent infinite loops.',1678    );1679  }1680  if (__DEV__) {1681    if (nestedPassiveUpdateCount > NESTED_PASSIVE_UPDATE_LIMIT) {1682      nestedPassiveUpdateCount = 0;1683      warning(1684        false,1685        'Maximum update depth exceeded. This can happen when a component ' +1686          "calls setState inside useEffect, but useEffect either doesn't " +1687          'have a dependency array, or one of the dependencies changes on ' +1688          'every render.',1689      );1690    }1691  }1692}1693function flushRenderPhaseStrictModeWarningsInDEV() {1694  if (__DEV__) {1695    ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings();1696    ReactStrictModeWarnings.flushLegacyContextWarning();1697    if (warnAboutDeprecatedLifecycles) {1698      ReactStrictModeWarnings.flushPendingDeprecationWarnings();1699    }1700  }1701}1702function stopFinishedWorkLoopTimer() {1703  const didCompleteRoot = true;1704  stopWorkLoopTimer(interruptedBy, didCompleteRoot);1705  interruptedBy = null;1706}1707function stopInterruptedWorkLoopTimer() {1708  // TODO: Track which fiber caused the interruption.1709  const didCompleteRoot = false;1710  stopWorkLoopTimer(interruptedBy, didCompleteRoot);1711  interruptedBy = null;1712}1713function checkForInterruption(1714  fiberThatReceivedUpdate: Fiber,1715  updateExpirationTime: ExpirationTime,1716) {1717  if (1718    enableUserTimingAPI &&1719    workInProgressRoot !== null &&1720    updateExpirationTime > renderExpirationTime1721  ) {1722    interruptedBy = fiberThatReceivedUpdate;1723  }1724}1725let didWarnStateUpdateForUnmountedComponent: Set<string> | null = null;1726function warnAboutUpdateOnUnmountedFiberInDEV(fiber) {1727  if (__DEV__) {1728    const tag = fiber.tag;1729    if (1730      tag !== HostRoot &&1731      tag !== ClassComponent &&1732      tag !== FunctionComponent &&1733      tag !== ForwardRef &&1734      tag !== MemoComponent &&1735      tag !== SimpleMemoComponent1736    ) {1737      // Only warn for user-defined components, not internal ones like Suspense.1738      return;1739    }1740    // We show the whole stack but dedupe on the top component's name because1741    // the problematic code almost always lies inside that component.1742    const componentName = getComponentName(fiber.type) || 'ReactComponent';1743    if (didWarnStateUpdateForUnmountedComponent !== null) {1744      if (didWarnStateUpdateForUnmountedComponent.has(componentName)) {1745        return;1746      }1747      didWarnStateUpdateForUnmountedComponent.add(componentName);1748    } else {1749      didWarnStateUpdateForUnmountedComponent = new Set([componentName]);1750    }1751    warningWithoutStack(1752      false,1753      "Can't perform a React state update on an unmounted component. This " +1754        'is a no-op, but it indicates a memory leak in your application. To ' +1755        'fix, cancel all subscriptions and asynchronous tasks in %s.%s',1756      tag === ClassComponent1757        ? 'the componentWillUnmount method'1758        : 'a useEffect cleanup function',1759      getStackByFiberInDevAndProd(fiber),1760    );1761  }1762}1763let beginWork;1764if (__DEV__ && replayFailedUnitOfWorkWithInvokeGuardedCallback) {1765  let dummyFiber = null;1766  beginWork = (current, unitOfWork, expirationTime) => {1767    // If a component throws an error, we replay it again in a synchronously1768    // dispatched event, so that the debugger will treat it as an uncaught1769    // error See ReactErrorUtils for more information.1770    // Before entering the begin phase, copy the work-in-progress onto a dummy1771    // fiber. If beginWork throws, we'll use this to reset the state.1772    const originalWorkInProgressCopy = assignFiberPropertiesInDEV(1773      dummyFiber,1774      unitOfWork,1775    );1776    try {1777      return originalBeginWork(current, unitOfWork, expirationTime);1778    } catch (originalError) {1779      if (1780        originalError !== null &&1781        typeof originalError === 'object' &&1782        typeof originalError.then === 'function'1783      ) {1784        // Don't replay promises. Treat everything else like an error.1785        throw originalError;1786      }1787      // Keep this code in sync with renderRoot; any changes here must have1788      // corresponding changes there.1789      resetContextDependencies();1790      resetHooks();1791      // Unwind the failed stack frame1792      unwindInterruptedWork(unitOfWork);1793      // Restore the original properties of the fiber.1794      assignFiberPropertiesInDEV(unitOfWork, originalWorkInProgressCopy);1795      if (enableProfilerTimer && unitOfWork.mode & ProfileMode) {1796        // Reset the profiler timer.1797        startProfilerTimer(unitOfWork);1798      }1799      // Run beginWork again.1800      invokeGuardedCallback(1801        null,1802        originalBeginWork,1803        null,1804        current,1805        unitOfWork,1806        expirationTime,1807      );1808      if (hasCaughtError()) {1809        const replayError = clearCaughtError();1810        // `invokeGuardedCallback` sometimes sets an expando `_suppressLogging`.1811        // Rethrow this error instead of the original one.1812        throw replayError;1813      } else {1814        // This branch is reachable if the render phase is impure.1815        throw originalError;1816      }1817    }1818  };1819} else {1820  beginWork = originalBeginWork;1821}1822let didWarnAboutUpdateInRender = false;1823let didWarnAboutUpdateInGetChildContext = false;1824function warnAboutInvalidUpdatesOnClassComponentsInDEV(fiber) {1825  if (__DEV__) {1826    if (fiber.tag === ClassComponent) {1827      switch (ReactCurrentDebugFiberPhaseInDEV) {1828        case 'getChildContext':1829          if (didWarnAboutUpdateInGetChildContext) {1830            return;1831          }1832          warningWithoutStack(1833            false,1834            'setState(...): Cannot call setState() inside getChildContext()',1835          );1836          didWarnAboutUpdateInGetChildContext = true;1837          break;1838        case 'render':1839          if (didWarnAboutUpdateInRender) {1840            return;1841          }1842          warningWithoutStack(1843            false,1844            'Cannot update during an existing state transition (such as ' +1845              'within `render`). Render methods should be a pure function of ' +1846              'props and state.',1847          );1848          didWarnAboutUpdateInRender = true;1849          break;1850      }1851    }1852  }1853}1854function warnIfNotCurrentlyActingUpdatesInDEV(fiber: Fiber): void {1855  if (__DEV__) {1856    if (1857      workPhase === NotWorking &&1858      ReactShouldWarnActingUpdates.current === false1859    ) {1860      warningWithoutStack(1861        false,1862        'An update to %s inside a test was not wrapped in act(...).\n\n' +1863          'When testing, code that causes React state updates should be ' +1864          'wrapped into act(...):\n\n' +1865          'act(() => {\n' +1866          '  /* fire events that update state */\n' +1867          '});\n' +1868          '/* assert on the output */\n\n' +1869          "This ensures that you're testing the behavior the user would see " +1870          'in the browser.' +1871          ' Learn more at https://fb.me/react-wrap-tests-with-act' +1872          '%s',1873        getComponentName(fiber.type),1874        getStackByFiberInDevAndProd(fiber),1875      );1876    }1877  }1878}1879export const warnIfNotCurrentlyActingUpdatesInDev = warnIfNotCurrentlyActingUpdatesInDEV;1880function computeThreadID(root, expirationTime) {1881  // Interaction threads are unique per root and expiration time.1882  return expirationTime * 1000 + root.interactionThreadID;1883}1884function schedulePendingInteraction(root, expirationTime) {1885  // This is called when work is scheduled on a root. It sets up a pending1886  // interaction, which is completed once the work commits.1887  if (!enableSchedulerTracing) {1888    return;1889  }1890  const interactions = __interactionsRef.current;1891  if (interactions.size > 0) {1892    const pendingInteractionMap = root.pendingInteractionMap;1893    const pendingInteractions = pendingInteractionMap.get(expirationTime);1894    if (pendingInteractions != null) {1895      interactions.forEach(interaction => {1896        if (!pendingInteractions.has(interaction)) {1897          // Update the pending async work count for previously unscheduled interaction.1898          interaction.__count++;1899        }1900        pendingInteractions.add(interaction);1901      });1902    } else {1903      pendingInteractionMap.set(expirationTime, new Set(interactions));1904      // Update the pending async work count for the current interactions.1905      interactions.forEach(interaction => {1906        interaction.__count++;1907      });1908    }1909    const subscriber = __subscriberRef.current;1910    if (subscriber !== null) {1911      const threadID = computeThreadID(root, expirationTime);1912      subscriber.onWorkScheduled(interactions, threadID);1913    }1914  }1915}1916function startWorkOnPendingInteraction(root, expirationTime) {1917  // This is called when new work is started on a root.1918  if (!enableSchedulerTracing) {1919    return;1920  }1921  // Determine which interactions this batch of work currently includes, So that1922  // we can accurately attribute time spent working on it, And so that cascading1923  // work triggered during the render phase will be associated with it.1924  const interactions: Set<Interaction> = new Set();1925  root.pendingInteractionMap.forEach(1926    (scheduledInteractions, scheduledExpirationTime) => {1927      if (scheduledExpirationTime >= expirationTime) {1928        scheduledInteractions.forEach(interaction =>1929          interactions.add(interaction),1930        );1931      }1932    },1933  );1934  // Store the current set of interactions on the FiberRoot for a few reasons:1935  // We can re-use it in hot functions like renderRoot() without having to1936  // recalculate it. We will also use it in commitWork() to pass to any Profiler1937  // onRender() hooks. This also provides DevTools with a way to access it when1938  // the onCommitRoot() hook is called.1939  root.memoizedInteractions = interactions;1940  if (interactions.size > 0) {1941    const subscriber = __subscriberRef.current;1942    if (subscriber !== null) {1943      const threadID = computeThreadID(root, expirationTime);1944      try {1945        subscriber.onWorkStarted(interactions, threadID);1946      } catch (error) {1947        // If the subscriber throws, rethrow it in a separate task1948        scheduleCallback(ImmediatePriority, () => {1949          throw error;1950        });1951      }1952    }1953  }1954}1955function finishPendingInteractions(root, committedExpirationTime) {1956  if (!enableSchedulerTracing) {1957    return;1958  }1959  const earliestRemainingTimeAfterCommit = root.firstPendingTime;1960  let subscriber;1961  try {1962    subscriber = __subscriberRef.current;1963    if (subscriber !== null && root.memoizedInteractions.size > 0) {1964      const threadID = computeThreadID(root, committedExpirationTime);1965      subscriber.onWorkStopped(root.memoizedInteractions, threadID);1966    }1967  } catch (error) {1968    // If the subscriber throws, rethrow it in a separate task1969    scheduleCallback(ImmediatePriority, () => {...4 - commitWork.js
Source:4 - commitWork.js  
...204      // If there are no passive effects, then we can complete the pending interactions.205      // Otherwise, we'll wait until after the passive effects are flushed.206      // Wait to do this until after remaining work has been scheduled,207      // so that we don't prematurely signal complete for interactions when there's e.g. hidden work.208      finishPendingInteractions(root, lanes);209    }210  }211  if (includesSomeLane(remainingLanes, (SyncLane: Lane))) {212    if (enableProfilerTimer && enableProfilerNestedUpdatePhase) {213      markNestedUpdateScheduled();214    }215    // Count the number of times the root synchronously re-renders without216    // finishing. If there are too many, it indicates an infinite update loop.217    if (root === rootWithNestedUpdates) {218      nestedUpdateCount++;219    } else {220      nestedUpdateCount = 0;221      rootWithNestedUpdates = root;222    }223  } else {224    nestedUpdateCount = 0;225  }226  onCommitRootDevTools(finishedWork.stateNode, renderPriorityLevel);227  // Always call this before exiting `commitRoot`, to ensure that any228  // additional work on this root is scheduled.229  ensureRootIsScheduled(root, now());230  if (hasUncaughtError) {231    hasUncaughtError = false;232    const error = firstUncaughtError;233    firstUncaughtError = null;234    throw error;235  }236  if ((executionContext & LegacyUnbatchedContext) !== NoContext) {237    if (enableSchedulingProfiler) {238      markCommitStopped();239    }240    // This is a legacy edge case. We just committed the initial mount of241    // a ReactDOM.render-ed root inside of batchedUpdates. The commit fired242    // synchronously, but layout updates should be deferred until the end243    // of the batch.244    return null;245  }246  // If the passive effects are the result of a discrete render, flush them247  // synchronously at the end of the current task so that the result is248  // immediately observable. Otherwise, we assume that they are not249  // order-dependent and do not need to be observed by external systems, so we250  // can wait until after paint.251  // TODO: We can optimize this by not scheduling the callback earlier. Since we252  // currently schedule the callback in multiple places, will wait until those253  // are consolidated.254  if (255    includesSomeLane(pendingPassiveEffectsLanes, SyncLane) &&256    root.tag !== LegacyRoot257  ) {258    flushPassiveEffects();259  }260  // If layout work was scheduled, flush it now.261  flushSyncCallbackQueue();262  if (enableSchedulingProfiler) {263    markCommitStopped();264  }265  return null;266}267export function flushPassiveEffects(): boolean {268  // Returns whether passive effects were flushed.269  if (pendingPassiveEffectsLanes !== NoLanes) {270    const priority = higherEventPriority(271      DefaultEventPriority,272      lanesToEventPriority(pendingPassiveEffectsLanes),273    );274    const prevTransition = ReactCurrentBatchConfig.transition;275    const previousPriority = getCurrentUpdatePriority();276    try {277      ReactCurrentBatchConfig.transition = 0;278      setCurrentUpdatePriority(priority);279      return flushPassiveEffectsImpl();280    } finally {281      setCurrentUpdatePriority(previousPriority);282      ReactCurrentBatchConfig.transition = prevTransition;283    }284  }285  return false;286}287function flushPassiveEffectsImpl() {288  if (rootWithPendingPassiveEffects === null) {289    return false;290  }291  const root = rootWithPendingPassiveEffects;292  const lanes = pendingPassiveEffectsLanes;293  rootWithPendingPassiveEffects = null;294  pendingPassiveEffectsLanes = NoLanes;295  invariant(296    (executionContext & (RenderContext | CommitContext)) === NoContext,297    'Cannot flush passive effects while already rendering.',298  );299  if (enableSchedulingProfiler) {300    markPassiveEffectsStarted(lanes);301  }302  const prevExecutionContext = executionContext;303  executionContext |= CommitContext;304  const prevInteractions = pushInteractions(root);305  commitPassiveUnmountEffects(root.current);306  commitPassiveMountEffects(root, root.current);307  // TODO: Move to commitPassiveMountEffects308  if (enableProfilerTimer && enableProfilerCommitHooks) {309    const profilerEffects = pendingPassiveProfilerEffects;310    pendingPassiveProfilerEffects = [];311    for (let i = 0; i < profilerEffects.length; i++) {312      const fiber = ((profilerEffects[i]: any): Fiber);313      commitPassiveEffectDurations(root, fiber);314    }315  }316  if (enableSchedulerTracing) {317    popInteractions(((prevInteractions: any): Set<Interaction>));318    finishPendingInteractions(root, lanes);319  }320  if (enableSchedulingProfiler) {321    markPassiveEffectsStopped();322  }323  executionContext = prevExecutionContext;324  flushSyncCallbackQueue();325  // If additional passive effects were scheduled, increment a counter. If this326  // exceeds the limit, we'll fire a warning.327  nestedPassiveUpdateCount =328    rootWithPendingPassiveEffects === null ? 0 : nestedPassiveUpdateCount + 1;329  return true;...commitRootImpl.js
Source:commitRootImpl.js  
...203            // If there are no passive effects, then we can complete the pending interactions.204            // Otherwise, we'll wait until after the passive effects are flushed.205            // Wait to do this until after remaining work has been scheduled,206            // so that we don't prematurely signal complete for interactions when there's e.g. hidden work.207            finishPendingInteractions(root, expirationTime);208        }209    }210    if (remainingExpirationTime === Sync) {211        // Count the number of times the root synchronously re-renders without212        // finishing. If there are too many, it indicates an infinite update loop.213        if (root === rootWithNestedUpdates) {214            nestedUpdateCount++;215        } else {216            nestedUpdateCount = 0;217            rootWithNestedUpdates = root;218        }219    } else {220        nestedUpdateCount = 0;221    }...flushPassiveEffectsImpl.js
Source:flushPassiveEffectsImpl.js  
...41        effect = nextNextEffect;42    }43    if (enableSchedulerTracing) {44        popInteractions(prevInteractions);45        finishPendingInteractions(root, expirationTime);46    }47    executionContext = prevExecutionContext;48    flushSyncCallbackQueue(); // If additional passive effects were scheduled, increment a counter. If this49    // exceeds the limit, we'll fire a warning.50    nestedPassiveUpdateCount = rootWithPendingPassiveEffects === null ? 0 : nestedPassiveUpdateCount + 1;51    return true;...ReactNativeRenderer-profiling.js
Source:ReactNativeRenderer-profiling.js  
...5     }6   }7+  performWork(0, !0);8 }9 function finishPendingInteractions(root, committedExpirationTime) {...ReactFabric-profiling.js
Source:ReactFabric-profiling.js  
...5     }6   }7+  performWork(0, !0);8 }9 function finishPendingInteractions(root, committedExpirationTime) {...Using AI Code Generation
1const { chromium } = 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.waitForLoadState('networkidle');7  await page.evaluate(() => {8    return new Promise((resolve) => {9      setTimeout(() => {10        console.log('done');11        resolve();12      }, 5000);13    });14  });15  await page._delegate._connection.send('Playwright.finishPendingInteractions');16  await page.screenshot({ path: 'screenshot.png' });17  await browser.close();18})();19Error: Protocol error (Playwright.finishPendingInteractions): 'Playwright.finishPendingInteractions' wasn't found20const { chromium } = require('playwright');21(async () => {22  const browser = await chromium.launch();23  const context = await browser.newContext();24  const page = await context.newPage();25  await page.waitForLoadState('networkidle');26  await page.evaluate(() => {27    return new Promise((resolve) => {28      setTimeout(() => {29        console.log('done');30        resolve();31      }, 5000);32    });33  });34  await page._delegate._connection.send('Playwright.finishPendingInteractions');35  await page.screenshot({ path: 'screenshot.png' });36  await browser.close();37})();38Error: Protocol error (Playwright.finishPendingInteractions): 'Playwright.finishPendingInteractions' wasn't found39const { chromium } = require('playwrightUsing AI Code Generation
1const { chromium } = 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: "example.png" });7  await browser.close();8  await context._browserContext._browser._defaultContext._connection._transport._ws._finishPendingInteractions()9})();Using AI Code Generation
1const { chromium } = require('playwright');2const playwright = 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=About');8  await page.waitForNavigation();9  await playwright._finishPendingInteractions();10  await browser.close();11})();12@karthik-bhagavathula Thank you! I tried it, but it seems that the _finishPendingInteractions method is not available in the playwright package. I'm using version 1.12.3. I tried to import it from the playwright-core package, but I got this error:13Error: Protocol error (DOM.describeNode): Node with given id does not belong to the document14module.exports = {Using AI Code Generation
1const { finishPendingInteractions } = require('playwright/lib/server/frames');2const { chromium } = require('playwright');3(async () => {4  const browser = await chromium.launch();5  const page = await browser.newPage();6  await page.click('input[name="q"]');7  await page.keyboard.type('Hello World');8  await finishPendingInteractions(page);9  await browser.close();10})();11const { test, expect } = require('@playwright/test');12test('should finish pending interactions', async ({ page }) => {13  await page.click('input[name="q"]');14  await page.keyboard.type('Hello World');15  await page.finishPendingInteractions();16  expect(await page.$('input[name="q"]')).toBeTruthy();17});18import { test, expect } from '@playwright/test';19test('should finish pending interactions', async ({ page }) => {20  await page.click('input[name="q"]');21  await page.keyboard.type('Hello World');22  await page.finishPendingInteractions();23  expect(await page.$('input[name="q"]')).toBeTruthy();24});25const { test, expect } = require('@playwright/test');26test('should finish pending interactions', async ({ page }) => {27  await page.click('input[name="q"]');28  await page.keyboard.type('Hello World');29  await page.finishPendingInteractions();30  expect(await page.$('input[name="q"]')).toBeTruthy();31});32import { test, expect } from '@playwright/test';33test('should finish pending interactions', async ({ page }) => {34  await page.click('input[name="q"]');35  await page.keyboard.type('Hello World');36  await page.finishPendingInteractions();37  expect(await page.$('input[name="q"]')).toBeTruthy();38});39const { test, expect } = require('@playwright/test');40test('should finish pending interactions', async ({ page }) => {41  await page.click('input[name="q"]');42  await page.keyboard.type('Hello World');Using AI Code Generation
1const { finishPendingInteractions } = require('playwright');2await finishPendingInteractions();3const { finishPendingInteractions } = require('playwright');4await finishPendingInteractions();5const { finishPendingInteractions } = require('playwright');6await finishPendingInteractions();7const { finishPendingInteractions } = require('playwright');8await finishPendingInteractions();9const { finishPendingInteractions } = require('playwright');10await finishPendingInteractions();11const { finishPendingInteractions } = require('playwright');12await finishPendingInteractions();13const { finishPendingInteractions } = require('playwright');14await finishPendingInteractions();15const { finishPendingInteractions } = require('playwright');16await finishPendingInteractions();17const { finishPendingInteractions } = require('playwright');18await finishPendingInteractions();19const { finishPendingInteractions } = require('playwright');20await finishPendingInteractions();21const { finishPendingInteractions } = require('playwright');22await finishPendingInteractions();23const { finishPendingInteractions } = require('playwright');24await finishPendingInteractions();25const { finishPendingInteractions } = require('playwright');26await finishPendingInteractions();27const { finishPendingInteractions } = require('playwright');28await finishPendingInteractions();29const { finishPendingInteractions } = require('playwright');30await finishPendingInteractions();Using AI Code Generation
1import { chromium } from 'playwright';2(async () => {3  const browser = await chromium.launch();4  const context = await browser.newContext();5  await context.addInitScript(() => {6    window.__finishPendingInteractions = () => {7      return new Promise((resolve) => {8        window.requestIdleCallback(resolve);9      });10    };11  });12  const page = await context.newPage();13  await page.evaluate(() => {14    const input = document.querySelector('input');15    input.value = 'Hello World!';16    input.dispatchEvent(new Event('input'));17  });18  await page.__finishPendingInteractions();19  await page.screenshot({ path: 'google.png' });20  await browser.close();21})();Using AI Code Generation
1const {chromium} = require('playwright');2const {finishPendingInteractions} = require('playwright/lib/internal/inspectorInstrumentation');3(async () => {4  const browser = await chromium.launch();5  const context = await browser.newContext();6  const page = await context.newPage();7  await page.click('input[type="text"]');8  await page.type('input[type="text"]', 'This is a test');9  await finishPendingInteractions();10  await browser.close();11})();Using AI Code Generation
1async function main() {2  const browser = await chromium.launch();3  const context = await browser.newContext();4  const page = await context.newPage();5  await page.click('text=Get started');6  await page.waitForSelector('text=Install with npm');7  await context.close();8  await browser.close();9}10main();11async function main() {12  const browser = await chromium.launch();13  const context = await browser.newContext();14  const page = await context.newPage();15  await page.click('text=Get started');16  await page.waitForSelector('text=Install with npm');17  await context.close();18  await browser.close();19}20main();21async function main() {22  const browser = await chromium.launch();23  const context = await browser.newContext();24  const page = await context.newPage();25  await page.click('text=Get started');26  await page.waitForSelector('text=Install with npm');27  await context.close();28  await browser.close();29}30main();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!!
