How to use resetRenderTimer method in Playwright Internal

Best JavaScript code snippet using playwright-internal

ReactFiberWorkLoop.new.js

Source:ReactFiberWorkLoop.new.js Github

copy

Full Screen

...305// suspense heuristics and opt out of rendering more content.306const RENDER_TIMEOUT_MS = 500;307// Used to avoid traversing the return path to find the nearest Profiler ancestor during commit.308let nearestProfilerOnStack: Fiber | null = null;309function resetRenderTimer() {310 workInProgressRootRenderTargetTime = now() + RENDER_TIMEOUT_MS;311}312export function getRenderTargetTime(): number {313 return workInProgressRootRenderTargetTime;314}315let hasUncaughtError = false;316let firstUncaughtError = null;317let legacyErrorBoundariesThatAlreadyFailed: Set<mixed> | null = null;318let rootDoesHavePassiveEffects: boolean = false;319let rootWithPendingPassiveEffects: FiberRoot | null = null;320let pendingPassiveEffectsRenderPriority: ReactPriorityLevel = NoSchedulerPriority;321let pendingPassiveEffectsLanes: Lanes = NoLanes;322let rootsWithPendingDiscreteUpdates: Set<FiberRoot> | null = null;323// Use these to prevent an infinite loop of nested updates324const NESTED_UPDATE_LIMIT = 50;325let nestedUpdateCount: number = 0;326let rootWithNestedUpdates: FiberRoot | null = null;327const NESTED_PASSIVE_UPDATE_LIMIT = 50;328let nestedPassiveUpdateCount: number = 0;329// Marks the need to reschedule pending interactions at these lanes330// during the commit phase. This enables them to be traced across components331// that spawn new work during render. E.g. hidden boundaries, suspended SSR332// hydration or SuspenseList.333// TODO: Can use a bitmask instead of an array334let spawnedWorkDuringRender: null | Array<Lane | Lanes> = null;335// If two updates are scheduled within the same event, we should treat their336// event times as simultaneous, even if the actual clock time has advanced337// between the first and second call.338let currentEventTime: number = NoTimestamp;339let currentEventWipLanes: Lanes = NoLanes;340let currentEventPendingLanes: Lanes = NoLanes;341// Dev only flag that tracks if passive effects are currently being flushed.342// We warn about state updates for unmounted components differently in this case.343let isFlushingPassiveEffects = false;344let focusedInstanceHandle: null | Fiber = null;345let shouldFireAfterActiveInstanceBlur: boolean = false;346export function getWorkInProgressRoot(): FiberRoot | null {347 return workInProgressRoot;348}349export function requestEventTime() {350 if ((executionContext & (RenderContext | CommitContext)) !== NoContext) {351 // We're inside React, so it's fine to read the actual time.352 return now();353 }354 // We're not inside React, so we may be in the middle of a browser event.355 if (currentEventTime !== NoTimestamp) {356 // Use the same start time for all updates until we enter React again.357 return currentEventTime;358 }359 // This is the first update since React yielded. Compute a new start time.360 currentEventTime = now();361 return currentEventTime;362}363export function getCurrentTime() {364 return now();365}366export function requestUpdateLane(fiber: Fiber): Lane {367 // Special cases368 const mode = fiber.mode;369 if ((mode & BlockingMode) === NoMode) {370 return (SyncLane: Lane);371 } else if ((mode & ConcurrentMode) === NoMode) {372 return getCurrentPriorityLevel() === ImmediateSchedulerPriority373 ? (SyncLane: Lane)374 : (SyncBatchedLane: Lane);375 } else if (376 !deferRenderPhaseUpdateToNextBatch &&377 (executionContext & RenderContext) !== NoContext &&378 workInProgressRootRenderLanes !== NoLanes379 ) {380 // This is a render phase update. These are not officially supported. The381 // old behavior is to give this the same "thread" (expiration time) as382 // whatever is currently rendering. So if you call `setState` on a component383 // that happens later in the same render, it will flush. Ideally, we want to384 // remove the special case and treat them as if they came from an385 // interleaved event. Regardless, this pattern is not officially supported.386 // This behavior is only a fallback. The flag only exists until we can roll387 // out the setState warning, since existing code might accidentally rely on388 // the current behavior.389 return pickArbitraryLane(workInProgressRootRenderLanes);390 }391 // The algorithm for assigning an update to a lane should be stable for all392 // updates at the same priority within the same event. To do this, the inputs393 // to the algorithm must be the same. For example, we use the `renderLanes`394 // to avoid choosing a lane that is already in the middle of rendering.395 //396 // However, the "included" lanes could be mutated in between updates in the397 // same event, like if you perform an update inside `flushSync`. Or any other398 // code path that might call `prepareFreshStack`.399 //400 // The trick we use is to cache the first of each of these inputs within an401 // event. Then reset the cached values once we can be sure the event is over.402 // Our heuristic for that is whenever we enter a concurrent work loop.403 //404 // We'll do the same for `currentEventPendingLanes` below.405 if (currentEventWipLanes === NoLanes) {406 currentEventWipLanes = workInProgressRootIncludedLanes;407 }408 const isTransition = requestCurrentTransition() !== NoTransition;409 if (isTransition) {410 if (currentEventPendingLanes !== NoLanes) {411 currentEventPendingLanes =412 mostRecentlyUpdatedRoot !== null413 ? mostRecentlyUpdatedRoot.pendingLanes414 : NoLanes;415 }416 return findTransitionLane(currentEventWipLanes, currentEventPendingLanes);417 }418 // TODO: Remove this dependency on the Scheduler priority.419 // To do that, we're replacing it with an update lane priority.420 const schedulerPriority = getCurrentPriorityLevel();421 // The old behavior was using the priority level of the Scheduler.422 // This couples React to the Scheduler internals, so we're replacing it423 // with the currentUpdateLanePriority above. As an example of how this424 // could be problematic, if we're not inside `Scheduler.runWithPriority`,425 // then we'll get the priority of the current running Scheduler task,426 // which is probably not what we want.427 let lane;428 if (429 // TODO: Temporary. We're removing the concept of discrete updates.430 (executionContext & DiscreteEventContext) !== NoContext &&431 schedulerPriority === UserBlockingSchedulerPriority432 ) {433 lane = findUpdateLane(InputDiscreteLanePriority, currentEventWipLanes);434 } else {435 const schedulerLanePriority = schedulerPriorityToLanePriority(436 schedulerPriority,437 );438 if (decoupleUpdatePriorityFromScheduler) {439 // In the new strategy, we will track the current update lane priority440 // inside React and use that priority to select a lane for this update.441 // For now, we're just logging when they're different so we can assess.442 const currentUpdateLanePriority = getCurrentUpdateLanePriority();443 if (444 schedulerLanePriority !== currentUpdateLanePriority &&445 currentUpdateLanePriority !== NoLanePriority446 ) {447 if (__DEV__) {448 console.error(449 'Expected current scheduler lane priority %s to match current update lane priority %s',450 schedulerLanePriority,451 currentUpdateLanePriority,452 );453 }454 }455 }456 lane = findUpdateLane(schedulerLanePriority, currentEventWipLanes);457 }458 return lane;459}460function requestRetryLane(fiber: Fiber) {461 // This is a fork of `requestUpdateLane` designed specifically for Suspense462 // "retries" — a special update that attempts to flip a Suspense boundary463 // from its placeholder state to its primary/resolved state.464 // Special cases465 const mode = fiber.mode;466 if ((mode & BlockingMode) === NoMode) {467 return (SyncLane: Lane);468 } else if ((mode & ConcurrentMode) === NoMode) {469 return getCurrentPriorityLevel() === ImmediateSchedulerPriority470 ? (SyncLane: Lane)471 : (SyncBatchedLane: Lane);472 }473 // See `requestUpdateLane` for explanation of `currentEventWipLanes`474 if (currentEventWipLanes === NoLanes) {475 currentEventWipLanes = workInProgressRootIncludedLanes;476 }477 return findRetryLane(currentEventWipLanes);478}479export function scheduleUpdateOnFiber(480 fiber: Fiber,481 lane: Lane,482 eventTime: number,483) {484 checkForNestedUpdates();485 warnAboutRenderPhaseUpdatesInDEV(fiber);486 const root = markUpdateLaneFromFiberToRoot(fiber, lane);487 if (root === null) {488 warnAboutUpdateOnUnmountedFiberInDEV(fiber);489 return null;490 }491 // Mark that the root has a pending update.492 markRootUpdated(root, lane, eventTime);493 if (root === workInProgressRoot) {494 // Received an update to a tree that's in the middle of rendering. Mark495 // that there was an interleaved update work on this root. Unless the496 // `deferRenderPhaseUpdateToNextBatch` flag is off and this is a render497 // phase update. In that case, we don't treat render phase updates as if498 // they were interleaved, for backwards compat reasons.499 if (500 deferRenderPhaseUpdateToNextBatch ||501 (executionContext & RenderContext) === NoContext502 ) {503 workInProgressRootUpdatedLanes = mergeLanes(504 workInProgressRootUpdatedLanes,505 lane,506 );507 }508 if (workInProgressRootExitStatus === RootSuspendedWithDelay) {509 // The root already suspended with a delay, which means this render510 // definitely won't finish. Since we have a new update, let's mark it as511 // suspended now, right before marking the incoming update. This has the512 // effect of interrupting the current render and switching to the update.513 // TODO: Make sure this doesn't override pings that happen while we've514 // already started rendering.515 markRootSuspended(root, workInProgressRootRenderLanes);516 }517 }518 // TODO: requestUpdateLanePriority also reads the priority. Pass the519 // priority as an argument to that function and this one.520 const priorityLevel = getCurrentPriorityLevel();521 if (lane === SyncLane) {522 if (523 // Check if we're inside unbatchedUpdates524 (executionContext & LegacyUnbatchedContext) !== NoContext &&525 // Check if we're not already rendering526 (executionContext & (RenderContext | CommitContext)) === NoContext527 ) {528 // Register pending interactions on the root to avoid losing traced interaction data.529 schedulePendingInteractions(root, lane);530 // This is a legacy edge case. The initial mount of a ReactDOM.render-ed531 // root inside of batchedUpdates should be synchronous, but layout updates532 // should be deferred until the end of the batch.533 performSyncWorkOnRoot(root);534 } else {535 ensureRootIsScheduled(root, eventTime);536 schedulePendingInteractions(root, lane);537 if (executionContext === NoContext) {538 // Flush the synchronous work now, unless we're already working or inside539 // a batch. This is intentionally inside scheduleUpdateOnFiber instead of540 // scheduleCallbackForFiber to preserve the ability to schedule a callback541 // without immediately flushing it. We only do this for user-initiated542 // updates, to preserve historical behavior of legacy mode.543 resetRenderTimer();544 flushSyncCallbackQueue();545 }546 }547 } else {548 // Schedule a discrete update but only if it's not Sync.549 if (550 (executionContext & DiscreteEventContext) !== NoContext &&551 // Only updates at user-blocking priority or greater are considered552 // discrete, even inside a discrete event.553 (priorityLevel === UserBlockingSchedulerPriority ||554 priorityLevel === ImmediateSchedulerPriority)555 ) {556 // This is the result of a discrete event. Track the lowest priority557 // discrete update per root so we can flush them early, if needed.558 if (rootsWithPendingDiscreteUpdates === null) {559 rootsWithPendingDiscreteUpdates = new Set([root]);560 } else {561 rootsWithPendingDiscreteUpdates.add(root);562 }563 }564 // Schedule other updates after in case the callback is sync.565 ensureRootIsScheduled(root, eventTime);566 schedulePendingInteractions(root, lane);567 }568 // We use this when assigning a lane for a transition inside569 // `requestUpdateLane`. We assume it's the same as the root being updated,570 // since in the common case of a single root app it probably is. If it's not571 // the same root, then it's not a huge deal, we just might batch more stuff572 // together more than necessary.573 mostRecentlyUpdatedRoot = root;574}575// This is split into a separate function so we can mark a fiber with pending576// work without treating it as a typical update that originates from an event;577// e.g. retrying a Suspense boundary isn't an update, but it does schedule work578// on a fiber.579function markUpdateLaneFromFiberToRoot(580 sourceFiber: Fiber,581 lane: Lane,582): FiberRoot | null {583 // Update the source fiber's lanes584 sourceFiber.lanes = mergeLanes(sourceFiber.lanes, lane);585 let alternate = sourceFiber.alternate;586 if (alternate !== null) {587 alternate.lanes = mergeLanes(alternate.lanes, lane);588 }589 if (__DEV__) {590 if (591 alternate === null &&592 (sourceFiber.flags & (Placement | Hydrating)) !== NoFlags593 ) {594 warnAboutUpdateOnNotYetMountedFiberInDEV(sourceFiber);595 }596 }597 // Walk the parent path to the root and update the child expiration time.598 let node = sourceFiber;599 let parent = sourceFiber.return;600 while (parent !== null) {601 parent.childLanes = mergeLanes(parent.childLanes, lane);602 alternate = parent.alternate;603 if (alternate !== null) {604 alternate.childLanes = mergeLanes(alternate.childLanes, lane);605 } else {606 if (__DEV__) {607 if ((parent.flags & (Placement | Hydrating)) !== NoFlags) {608 warnAboutUpdateOnNotYetMountedFiberInDEV(sourceFiber);609 }610 }611 }612 node = parent;613 parent = parent.return;614 }615 if (node.tag === HostRoot) {616 const root: FiberRoot = node.stateNode;617 return root;618 } else {619 return null;620 }621}622// Use this function to schedule a task for a root. There's only one task per623// root; if a task was already scheduled, we'll check to make sure the priority624// of the existing task is the same as the priority of the next level that the625// root has work on. This function is called on every update, and right before626// exiting a task.627function ensureRootIsScheduled(root: FiberRoot, currentTime: number) {628 const existingCallbackNode = root.callbackNode;629 // Check if any lanes are being starved by other work. If so, mark them as630 // expired so we know to work on those next.631 markStarvedLanesAsExpired(root, currentTime);632 // Determine the next lanes to work on, and their priority.633 const nextLanes = getNextLanes(634 root,635 root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes,636 );637 // This returns the priority level computed during the `getNextLanes` call.638 const newCallbackPriority = returnNextLanesPriority();639 if (nextLanes === NoLanes) {640 // Special case: There's nothing to work on.641 if (existingCallbackNode !== null) {642 cancelCallback(existingCallbackNode);643 root.callbackNode = null;644 root.callbackPriority = NoLanePriority;645 }646 return;647 }648 // Check if there's an existing task. We may be able to reuse it.649 if (existingCallbackNode !== null) {650 const existingCallbackPriority = root.callbackPriority;651 if (existingCallbackPriority === newCallbackPriority) {652 // The priority hasn't changed. We can reuse the existing task. Exit.653 return;654 }655 // The priority changed. Cancel the existing callback. We'll schedule a new656 // one below.657 cancelCallback(existingCallbackNode);658 }659 // Schedule a new callback.660 let newCallbackNode;661 if (newCallbackPriority === SyncLanePriority) {662 // Special case: Sync React callbacks are scheduled on a special663 // internal queue664 newCallbackNode = scheduleSyncCallback(665 performSyncWorkOnRoot.bind(null, root),666 );667 } else if (newCallbackPriority === SyncBatchedLanePriority) {668 newCallbackNode = scheduleCallback(669 ImmediateSchedulerPriority,670 performSyncWorkOnRoot.bind(null, root),671 );672 } else {673 const schedulerPriorityLevel = lanePriorityToSchedulerPriority(674 newCallbackPriority,675 );676 newCallbackNode = scheduleCallback(677 schedulerPriorityLevel,678 performConcurrentWorkOnRoot.bind(null, root),679 );680 }681 root.callbackPriority = newCallbackPriority;682 root.callbackNode = newCallbackNode;683}684// This is the entry point for every concurrent task, i.e. anything that685// goes through Scheduler.686function performConcurrentWorkOnRoot(root) {687 // Since we know we're in a React event, we can clear the current688 // event time. The next update will compute a new event time.689 currentEventTime = NoTimestamp;690 currentEventWipLanes = NoLanes;691 currentEventPendingLanes = NoLanes;692 invariant(693 (executionContext & (RenderContext | CommitContext)) === NoContext,694 'Should not already be working.',695 );696 // Flush any pending passive effects before deciding which lanes to work on,697 // in case they schedule additional work.698 const originalCallbackNode = root.callbackNode;699 const didFlushPassiveEffects = flushPassiveEffects();700 if (didFlushPassiveEffects) {701 // Something in the passive effect phase may have canceled the current task.702 // Check if the task node for this root was changed.703 if (root.callbackNode !== originalCallbackNode) {704 // The current task was canceled. Exit. We don't need to call705 // `ensureRootIsScheduled` because the check above implies either that706 // there's a new task, or that there's no remaining work on this root.707 return null;708 } else {709 // Current task was not canceled. Continue.710 }711 }712 // Determine the next expiration time to work on, using the fields stored713 // on the root.714 let lanes = getNextLanes(715 root,716 root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes,717 );718 if (lanes === NoLanes) {719 // Defensive coding. This is never expected to happen.720 return null;721 }722 let exitStatus = renderRootConcurrent(root, lanes);723 if (724 includesSomeLane(725 workInProgressRootIncludedLanes,726 workInProgressRootUpdatedLanes,727 )728 ) {729 // The render included lanes that were updated during the render phase.730 // For example, when unhiding a hidden tree, we include all the lanes731 // that were previously skipped when the tree was hidden. That set of732 // lanes is a superset of the lanes we started rendering with.733 //734 // So we'll throw out the current work and restart.735 prepareFreshStack(root, NoLanes);736 } else if (exitStatus !== RootIncomplete) {737 if (exitStatus === RootErrored) {738 executionContext |= RetryAfterError;739 // If an error occurred during hydration,740 // discard server response and fall back to client side render.741 if (root.hydrate) {742 root.hydrate = false;743 clearContainer(root.containerInfo);744 }745 // If something threw an error, try rendering one more time. We'll render746 // synchronously to block concurrent data mutations, and we'll includes747 // all pending updates are included. If it still fails after the second748 // attempt, we'll give up and commit the resulting tree.749 lanes = getLanesToRetrySynchronouslyOnError(root);750 if (lanes !== NoLanes) {751 exitStatus = renderRootSync(root, lanes);752 }753 }754 if (exitStatus === RootFatalErrored) {755 const fatalError = workInProgressRootFatalError;756 prepareFreshStack(root, NoLanes);757 markRootSuspended(root, lanes);758 ensureRootIsScheduled(root, now());759 throw fatalError;760 }761 // We now have a consistent tree. The next step is either to commit it,762 // or, if something suspended, wait to commit it after a timeout.763 const finishedWork: Fiber = (root.current.alternate: any);764 root.finishedWork = finishedWork;765 root.finishedLanes = lanes;766 finishConcurrentRender(root, exitStatus, lanes);767 }768 ensureRootIsScheduled(root, now());769 if (root.callbackNode === originalCallbackNode) {770 // The task node scheduled for this root is the same one that's771 // currently executed. Need to return a continuation.772 return performConcurrentWorkOnRoot.bind(null, root);773 }774 return null;775}776function finishConcurrentRender(root, exitStatus, lanes) {777 switch (exitStatus) {778 case RootIncomplete:779 case RootFatalErrored: {780 invariant(false, 'Root did not complete. This is a bug in React.');781 }782 // Flow knows about invariant, so it complains if I add a break783 // statement, but eslint doesn't know about invariant, so it complains784 // if I do. eslint-disable-next-line no-fallthrough785 case RootErrored: {786 // We should have already attempted to retry this tree. If we reached787 // this point, it errored again. Commit it.788 commitRoot(root);789 break;790 }791 case RootSuspended: {792 markRootSuspended(root, lanes);793 // We have an acceptable loading state. We need to figure out if we794 // should immediately commit it or wait a bit.795 if (796 includesOnlyRetries(lanes) &&797 // do not delay if we're inside an act() scope798 !shouldForceFlushFallbacksInDEV()799 ) {800 // This render only included retries, no updates. Throttle committing801 // retries so that we don't show too many loading states too quickly.802 const msUntilTimeout =803 globalMostRecentFallbackTime + FALLBACK_THROTTLE_MS - now();804 // Don't bother with a very short suspense time.805 if (msUntilTimeout > 10) {806 const nextLanes = getNextLanes(root, NoLanes);807 if (nextLanes !== NoLanes) {808 // There's additional work on this root.809 break;810 }811 const suspendedLanes = root.suspendedLanes;812 if (!isSubsetOfLanes(suspendedLanes, lanes)) {813 // We should prefer to render the fallback of at the last814 // suspended level. Ping the last suspended level to try815 // rendering it again.816 // FIXME: What if the suspended lanes are Idle? Should not restart.817 const eventTime = requestEventTime();818 markRootPinged(root, suspendedLanes, eventTime);819 break;820 }821 // The render is suspended, it hasn't timed out, and there's no822 // lower priority work to do. Instead of committing the fallback823 // immediately, wait for more data to arrive.824 root.timeoutHandle = scheduleTimeout(825 commitRoot.bind(null, root),826 msUntilTimeout,827 );828 break;829 }830 }831 // The work expired. Commit immediately.832 commitRoot(root);833 break;834 }835 case RootSuspendedWithDelay: {836 markRootSuspended(root, lanes);837 if (includesOnlyTransitions(lanes)) {838 // This is a transition, so we should exit without committing a839 // placeholder and without scheduling a timeout. Delay indefinitely840 // until we receive more data.841 break;842 }843 if (!shouldForceFlushFallbacksInDEV()) {844 // This is not a transition, but we did trigger an avoided state.845 // Schedule a placeholder to display after a short delay, using the Just846 // Noticeable Difference.847 // TODO: Is the JND optimization worth the added complexity? If this is848 // the only reason we track the event time, then probably not.849 // Consider removing.850 const mostRecentEventTime = getMostRecentEventTime(root, lanes);851 const eventTimeMs = mostRecentEventTime;852 const timeElapsedMs = now() - eventTimeMs;853 const msUntilTimeout = jnd(timeElapsedMs) - timeElapsedMs;854 // Don't bother with a very short suspense time.855 if (msUntilTimeout > 10) {856 // Instead of committing the fallback immediately, wait for more data857 // to arrive.858 root.timeoutHandle = scheduleTimeout(859 commitRoot.bind(null, root),860 msUntilTimeout,861 );862 break;863 }864 }865 // Commit the placeholder.866 commitRoot(root);867 break;868 }869 case RootCompleted: {870 // The work completed. Ready to commit.871 commitRoot(root);872 break;873 }874 default: {875 invariant(false, 'Unknown root exit status.');876 }877 }878}879function markRootSuspended(root, suspendedLanes) {880 // When suspending, we should always exclude lanes that were pinged or (more881 // rarely, since we try to avoid it) updated during the render phase.882 // TODO: Lol maybe there's a better way to factor this besides this883 // obnoxiously named function :)884 suspendedLanes = removeLanes(suspendedLanes, workInProgressRootPingedLanes);885 suspendedLanes = removeLanes(suspendedLanes, workInProgressRootUpdatedLanes);886 markRootSuspended_dontCallThisOneDirectly(root, suspendedLanes);887}888// This is the entry point for synchronous tasks that don't go889// through Scheduler890function performSyncWorkOnRoot(root) {891 invariant(892 (executionContext & (RenderContext | CommitContext)) === NoContext,893 'Should not already be working.',894 );895 flushPassiveEffects();896 let lanes;897 let exitStatus;898 if (899 root === workInProgressRoot &&900 includesSomeLane(root.expiredLanes, workInProgressRootRenderLanes)901 ) {902 // There's a partial tree, and at least one of its lanes has expired. Finish903 // rendering it before rendering the rest of the expired work.904 lanes = workInProgressRootRenderLanes;905 exitStatus = renderRootSync(root, lanes);906 if (907 includesSomeLane(908 workInProgressRootIncludedLanes,909 workInProgressRootUpdatedLanes,910 )911 ) {912 // The render included lanes that were updated during the render phase.913 // For example, when unhiding a hidden tree, we include all the lanes914 // that were previously skipped when the tree was hidden. That set of915 // lanes is a superset of the lanes we started rendering with.916 //917 // Note that this only happens when part of the tree is rendered918 // concurrently. If the whole tree is rendered synchronously, then there919 // are no interleaved events.920 lanes = getNextLanes(root, lanes);921 exitStatus = renderRootSync(root, lanes);922 }923 } else {924 lanes = getNextLanes(root, NoLanes);925 exitStatus = renderRootSync(root, lanes);926 }927 if (root.tag !== LegacyRoot && exitStatus === RootErrored) {928 executionContext |= RetryAfterError;929 // If an error occurred during hydration,930 // discard server response and fall back to client side render.931 if (root.hydrate) {932 root.hydrate = false;933 clearContainer(root.containerInfo);934 }935 // If something threw an error, try rendering one more time. We'll render936 // synchronously to block concurrent data mutations, and we'll includes937 // all pending updates are included. If it still fails after the second938 // attempt, we'll give up and commit the resulting tree.939 lanes = getLanesToRetrySynchronouslyOnError(root);940 if (lanes !== NoLanes) {941 exitStatus = renderRootSync(root, lanes);942 }943 }944 if (exitStatus === RootFatalErrored) {945 const fatalError = workInProgressRootFatalError;946 prepareFreshStack(root, NoLanes);947 markRootSuspended(root, lanes);948 ensureRootIsScheduled(root, now());949 throw fatalError;950 }951 // We now have a consistent tree. Because this is a sync render, we952 // will commit it even if something suspended.953 const finishedWork: Fiber = (root.current.alternate: any);954 root.finishedWork = finishedWork;955 root.finishedLanes = lanes;956 commitRoot(root);957 // Before exiting, make sure there's a callback scheduled for the next958 // pending level.959 ensureRootIsScheduled(root, now());960 return null;961}962export function flushRoot(root: FiberRoot, lanes: Lanes) {963 markRootExpired(root, lanes);964 ensureRootIsScheduled(root, now());965 if ((executionContext & (RenderContext | CommitContext)) === NoContext) {966 resetRenderTimer();967 flushSyncCallbackQueue();968 }969}970export function getExecutionContext(): ExecutionContext {971 return executionContext;972}973export function flushDiscreteUpdates() {974 // TODO: Should be able to flush inside batchedUpdates, but not inside `act`.975 // However, `act` uses `batchedUpdates`, so there's no way to distinguish976 // those two cases. Need to fix this before exposing flushDiscreteUpdates977 // as a public API.978 if (979 (executionContext & (BatchedContext | RenderContext | CommitContext)) !==980 NoContext981 ) {982 if (__DEV__) {983 if ((executionContext & RenderContext) !== NoContext) {984 console.error(985 'unstable_flushDiscreteUpdates: Cannot flush updates when React is ' +986 'already rendering.',987 );988 }989 }990 // We're already rendering, so we can't synchronously flush pending work.991 // This is probably a nested event dispatch triggered by a lifecycle/effect,992 // like `el.focus()`. Exit.993 return;994 }995 flushPendingDiscreteUpdates();996 // If the discrete updates scheduled passive effects, flush them now so that997 // they fire before the next serial event.998 flushPassiveEffects();999}1000export function deferredUpdates<A>(fn: () => A): A {1001 if (decoupleUpdatePriorityFromScheduler) {1002 const previousLanePriority = getCurrentUpdateLanePriority();1003 try {1004 setCurrentUpdateLanePriority(DefaultLanePriority);1005 return runWithPriority(NormalSchedulerPriority, fn);1006 } finally {1007 setCurrentUpdateLanePriority(previousLanePriority);1008 }1009 } else {1010 return runWithPriority(NormalSchedulerPriority, fn);1011 }1012}1013function flushPendingDiscreteUpdates() {1014 if (rootsWithPendingDiscreteUpdates !== null) {1015 // For each root with pending discrete updates, schedule a callback to1016 // immediately flush them.1017 const roots = rootsWithPendingDiscreteUpdates;1018 rootsWithPendingDiscreteUpdates = null;1019 roots.forEach(root => {1020 markDiscreteUpdatesExpired(root);1021 ensureRootIsScheduled(root, now());1022 });1023 }1024 // Now flush the immediate queue.1025 flushSyncCallbackQueue();1026}1027export function batchedUpdates<A, R>(fn: A => R, a: A): R {1028 const prevExecutionContext = executionContext;1029 executionContext |= BatchedContext;1030 try {1031 return fn(a);1032 } finally {1033 executionContext = prevExecutionContext;1034 if (executionContext === NoContext) {1035 // Flush the immediate callbacks that were scheduled during this batch1036 resetRenderTimer();1037 flushSyncCallbackQueue();1038 }1039 }1040}1041export function batchedEventUpdates<A, R>(fn: A => R, a: A): R {1042 const prevExecutionContext = executionContext;1043 executionContext |= EventContext;1044 try {1045 return fn(a);1046 } finally {1047 executionContext = prevExecutionContext;1048 if (executionContext === NoContext) {1049 // Flush the immediate callbacks that were scheduled during this batch1050 resetRenderTimer();1051 flushSyncCallbackQueue();1052 }1053 }1054}1055export function discreteUpdates<A, B, C, D, R>(1056 fn: (A, B, C) => R,1057 a: A,1058 b: B,1059 c: C,1060 d: D,1061): R {1062 const prevExecutionContext = executionContext;1063 executionContext |= DiscreteEventContext;1064 if (decoupleUpdatePriorityFromScheduler) {1065 const previousLanePriority = getCurrentUpdateLanePriority();1066 try {1067 setCurrentUpdateLanePriority(InputDiscreteLanePriority);1068 return runWithPriority(1069 UserBlockingSchedulerPriority,1070 fn.bind(null, a, b, c, d),1071 );1072 } finally {1073 setCurrentUpdateLanePriority(previousLanePriority);1074 executionContext = prevExecutionContext;1075 if (executionContext === NoContext) {1076 // Flush the immediate callbacks that were scheduled during this batch1077 resetRenderTimer();1078 flushSyncCallbackQueue();1079 }1080 }1081 } else {1082 try {1083 return runWithPriority(1084 UserBlockingSchedulerPriority,1085 fn.bind(null, a, b, c, d),1086 );1087 } finally {1088 executionContext = prevExecutionContext;1089 if (executionContext === NoContext) {1090 // Flush the immediate callbacks that were scheduled during this batch1091 resetRenderTimer();1092 flushSyncCallbackQueue();1093 }1094 }1095 }1096}1097export function unbatchedUpdates<A, R>(fn: (a: A) => R, a: A): R {1098 const prevExecutionContext = executionContext;1099 executionContext &= ~BatchedContext;1100 executionContext |= LegacyUnbatchedContext;1101 try {1102 return fn(a);1103 } finally {1104 executionContext = prevExecutionContext;1105 if (executionContext === NoContext) {1106 // Flush the immediate callbacks that were scheduled during this batch1107 resetRenderTimer();1108 flushSyncCallbackQueue();1109 }1110 }1111}1112export function flushSync<A, R>(fn: A => R, a: A): R {1113 const prevExecutionContext = executionContext;1114 if ((prevExecutionContext & (RenderContext | CommitContext)) !== NoContext) {1115 if (__DEV__) {1116 console.error(1117 'flushSync was called from inside a lifecycle method. React cannot ' +1118 'flush when React is already rendering. Consider moving this call to ' +1119 'a scheduler task or micro task.',1120 );1121 }1122 return fn(a);1123 }1124 executionContext |= BatchedContext;1125 if (decoupleUpdatePriorityFromScheduler) {1126 const previousLanePriority = getCurrentUpdateLanePriority();1127 try {1128 setCurrentUpdateLanePriority(SyncLanePriority);1129 if (fn) {1130 return runWithPriority(ImmediateSchedulerPriority, fn.bind(null, a));1131 } else {1132 return (undefined: $FlowFixMe);1133 }1134 } finally {1135 setCurrentUpdateLanePriority(previousLanePriority);1136 executionContext = prevExecutionContext;1137 // Flush the immediate callbacks that were scheduled during this batch.1138 // Note that this will happen even if batchedUpdates is higher up1139 // the stack.1140 flushSyncCallbackQueue();1141 }1142 } else {1143 try {1144 if (fn) {1145 return runWithPriority(ImmediateSchedulerPriority, fn.bind(null, a));1146 } else {1147 return (undefined: $FlowFixMe);1148 }1149 } finally {1150 executionContext = prevExecutionContext;1151 // Flush the immediate callbacks that were scheduled during this batch.1152 // Note that this will happen even if batchedUpdates is higher up1153 // the stack.1154 flushSyncCallbackQueue();1155 }1156 }1157}1158export function flushControlled(fn: () => mixed): void {1159 const prevExecutionContext = executionContext;1160 executionContext |= BatchedContext;1161 if (decoupleUpdatePriorityFromScheduler) {1162 const previousLanePriority = getCurrentUpdateLanePriority();1163 try {1164 setCurrentUpdateLanePriority(SyncLanePriority);1165 runWithPriority(ImmediateSchedulerPriority, fn);1166 } finally {1167 setCurrentUpdateLanePriority(previousLanePriority);1168 executionContext = prevExecutionContext;1169 if (executionContext === NoContext) {1170 // Flush the immediate callbacks that were scheduled during this batch1171 resetRenderTimer();1172 flushSyncCallbackQueue();1173 }1174 }1175 } else {1176 try {1177 runWithPriority(ImmediateSchedulerPriority, fn);1178 } finally {1179 executionContext = prevExecutionContext;1180 if (executionContext === NoContext) {1181 // Flush the immediate callbacks that were scheduled during this batch1182 resetRenderTimer();1183 flushSyncCallbackQueue();1184 }1185 }1186 }1187}1188export function pushRenderLanes(fiber: Fiber, lanes: Lanes) {1189 pushToStack(subtreeRenderLanesCursor, subtreeRenderLanes, fiber);1190 subtreeRenderLanes = mergeLanes(subtreeRenderLanes, lanes);1191 workInProgressRootIncludedLanes = mergeLanes(1192 workInProgressRootIncludedLanes,1193 lanes,1194 );1195}1196export function popRenderLanes(fiber: Fiber) {1197 subtreeRenderLanes = subtreeRenderLanesCursor.current;1198 popFromStack(subtreeRenderLanesCursor, fiber);1199}1200function prepareFreshStack(root: FiberRoot, lanes: Lanes) {1201 root.finishedWork = null;1202 root.finishedLanes = NoLanes;1203 const timeoutHandle = root.timeoutHandle;1204 if (timeoutHandle !== noTimeout) {1205 // The root previous suspended and scheduled a timeout to commit a fallback1206 // state. Now that we have additional work, cancel the timeout.1207 root.timeoutHandle = noTimeout;1208 // $FlowFixMe Complains noTimeout is not a TimeoutID, despite the check above1209 cancelTimeout(timeoutHandle);1210 }1211 if (workInProgress !== null) {1212 let interruptedWork = workInProgress.return;1213 while (interruptedWork !== null) {1214 unwindInterruptedWork(interruptedWork);1215 interruptedWork = interruptedWork.return;1216 }1217 }1218 workInProgressRoot = root;1219 workInProgress = createWorkInProgress(root.current, null);1220 workInProgressRootRenderLanes = subtreeRenderLanes = workInProgressRootIncludedLanes = lanes;1221 workInProgressRootExitStatus = RootIncomplete;1222 workInProgressRootFatalError = null;1223 workInProgressRootSkippedLanes = NoLanes;1224 workInProgressRootUpdatedLanes = NoLanes;1225 workInProgressRootPingedLanes = NoLanes;1226 if (enableSchedulerTracing) {1227 spawnedWorkDuringRender = null;1228 }1229 if (__DEV__) {1230 ReactStrictModeWarnings.discardPendingWarnings();1231 }1232}1233function handleError(root, thrownValue): void {1234 do {1235 let erroredWork = workInProgress;1236 try {1237 // Reset module-level state that was set during the render phase.1238 resetContextDependencies();1239 resetHooksAfterThrow();1240 resetCurrentDebugFiberInDEV();1241 // TODO: I found and added this missing line while investigating a1242 // separate issue. Write a regression test using string refs.1243 ReactCurrentOwner.current = null;1244 if (erroredWork === null || erroredWork.return === null) {1245 // Expected to be working on a non-root fiber. This is a fatal error1246 // because there's no ancestor that can handle it; the root is1247 // supposed to capture all errors that weren't caught by an error1248 // boundary.1249 workInProgressRootExitStatus = RootFatalErrored;1250 workInProgressRootFatalError = thrownValue;1251 // Set `workInProgress` to null. This represents advancing to the next1252 // sibling, or the parent if there are no siblings. But since the root1253 // has no siblings nor a parent, we set it to null. Usually this is1254 // handled by `completeUnitOfWork` or `unwindWork`, but since we're1255 // intentionally not calling those, we need set it here.1256 // TODO: Consider calling `unwindWork` to pop the contexts.1257 workInProgress = null;1258 return;1259 }1260 if (enableProfilerTimer && erroredWork.mode & ProfileMode) {1261 // Record the time spent rendering before an error was thrown. This1262 // avoids inaccurate Profiler durations in the case of a1263 // suspended render.1264 stopProfilerTimerIfRunningAndRecordDelta(erroredWork, true);1265 }1266 throwException(1267 root,1268 erroredWork.return,1269 erroredWork,1270 thrownValue,1271 workInProgressRootRenderLanes,1272 );1273 completeUnitOfWork(erroredWork);1274 } catch (yetAnotherThrownValue) {1275 // Something in the return path also threw.1276 thrownValue = yetAnotherThrownValue;1277 if (workInProgress === erroredWork && erroredWork !== null) {1278 // If this boundary has already errored, then we had trouble processing1279 // the error. Bubble it to the next boundary.1280 erroredWork = erroredWork.return;1281 workInProgress = erroredWork;1282 } else {1283 erroredWork = workInProgress;1284 }1285 continue;1286 }1287 // Return to the normal work loop.1288 return;1289 } while (true);1290}1291function pushDispatcher() {1292 const prevDispatcher = ReactCurrentDispatcher.current;1293 ReactCurrentDispatcher.current = ContextOnlyDispatcher;1294 if (prevDispatcher === null) {1295 // The React isomorphic package does not include a default dispatcher.1296 // Instead the first renderer will lazily attach one, in order to give1297 // nicer error messages.1298 return ContextOnlyDispatcher;1299 } else {1300 return prevDispatcher;1301 }1302}1303function popDispatcher(prevDispatcher) {1304 ReactCurrentDispatcher.current = prevDispatcher;1305}1306function pushInteractions(root) {1307 if (enableSchedulerTracing) {1308 const prevInteractions: Set<Interaction> | null = __interactionsRef.current;1309 __interactionsRef.current = root.memoizedInteractions;1310 return prevInteractions;1311 }1312 return null;1313}1314function popInteractions(prevInteractions) {1315 if (enableSchedulerTracing) {1316 __interactionsRef.current = prevInteractions;1317 }1318}1319export function markCommitTimeOfFallback() {1320 globalMostRecentFallbackTime = now();1321}1322export function markSkippedUpdateLanes(lane: Lane | Lanes): void {1323 workInProgressRootSkippedLanes = mergeLanes(1324 lane,1325 workInProgressRootSkippedLanes,1326 );1327}1328export function renderDidSuspend(): void {1329 if (workInProgressRootExitStatus === RootIncomplete) {1330 workInProgressRootExitStatus = RootSuspended;1331 }1332}1333export function renderDidSuspendDelayIfPossible(): void {1334 if (1335 workInProgressRootExitStatus === RootIncomplete ||1336 workInProgressRootExitStatus === RootSuspended1337 ) {1338 workInProgressRootExitStatus = RootSuspendedWithDelay;1339 }1340 // Check if there are updates that we skipped tree that might have unblocked1341 // this render.1342 if (1343 workInProgressRoot !== null &&1344 (includesNonIdleWork(workInProgressRootSkippedLanes) ||1345 includesNonIdleWork(workInProgressRootUpdatedLanes))1346 ) {1347 // Mark the current render as suspended so that we switch to working on1348 // the updates that were skipped. Usually we only suspend at the end of1349 // the render phase.1350 // TODO: We should probably always mark the root as suspended immediately1351 // (inside this function), since by suspending at the end of the render1352 // phase introduces a potential mistake where we suspend lanes that were1353 // pinged or updated while we were rendering.1354 markRootSuspended(workInProgressRoot, workInProgressRootRenderLanes);1355 }1356}1357export function renderDidError() {1358 if (workInProgressRootExitStatus !== RootCompleted) {1359 workInProgressRootExitStatus = RootErrored;1360 }1361}1362// Called during render to determine if anything has suspended.1363// Returns false if we're not sure.1364export function renderHasNotSuspendedYet(): boolean {1365 // If something errored or completed, we can't really be sure,1366 // so those are false.1367 return workInProgressRootExitStatus === RootIncomplete;1368}1369function renderRootSync(root: FiberRoot, lanes: Lanes) {1370 const prevExecutionContext = executionContext;1371 executionContext |= RenderContext;1372 const prevDispatcher = pushDispatcher();1373 // If the root or lanes have changed, throw out the existing stack1374 // and prepare a fresh one. Otherwise we'll continue where we left off.1375 if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) {1376 prepareFreshStack(root, lanes);1377 startWorkOnPendingInteractions(root, lanes);1378 }1379 const prevInteractions = pushInteractions(root);1380 if (__DEV__) {1381 if (enableDebugTracing) {1382 logRenderStarted(lanes);1383 }1384 }1385 if (enableSchedulingProfiler) {1386 markRenderStarted(lanes);1387 }1388 do {1389 try {1390 workLoopSync();1391 break;1392 } catch (thrownValue) {1393 handleError(root, thrownValue);1394 }1395 } while (true);1396 resetContextDependencies();1397 if (enableSchedulerTracing) {1398 popInteractions(((prevInteractions: any): Set<Interaction>));1399 }1400 executionContext = prevExecutionContext;1401 popDispatcher(prevDispatcher);1402 if (workInProgress !== null) {1403 // This is a sync render, so we should have finished the whole tree.1404 invariant(1405 false,1406 'Cannot commit an incomplete root. This error is likely caused by a ' +1407 'bug in React. Please file an issue.',1408 );1409 }1410 if (__DEV__) {1411 if (enableDebugTracing) {1412 logRenderStopped();1413 }1414 }1415 if (enableSchedulingProfiler) {1416 markRenderStopped();1417 }1418 // Set this to null to indicate there's no in-progress render.1419 workInProgressRoot = null;1420 workInProgressRootRenderLanes = NoLanes;1421 return workInProgressRootExitStatus;1422}1423// The work loop is an extremely hot path. Tell Closure not to inline it.1424/** @noinline */1425function workLoopSync() {1426 // Already timed out, so perform work without checking if we need to yield.1427 while (workInProgress !== null) {1428 performUnitOfWork(workInProgress);1429 }1430}1431function renderRootConcurrent(root: FiberRoot, lanes: Lanes) {1432 const prevExecutionContext = executionContext;1433 executionContext |= RenderContext;1434 const prevDispatcher = pushDispatcher();1435 // If the root or lanes have changed, throw out the existing stack1436 // and prepare a fresh one. Otherwise we'll continue where we left off.1437 if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) {1438 resetRenderTimer();1439 prepareFreshStack(root, lanes);1440 startWorkOnPendingInteractions(root, lanes);1441 }1442 const prevInteractions = pushInteractions(root);1443 if (__DEV__) {1444 if (enableDebugTracing) {1445 logRenderStarted(lanes);1446 }1447 }1448 if (enableSchedulingProfiler) {1449 markRenderStarted(lanes);1450 }1451 do {1452 try {...

Full Screen

Full Screen

ReactFiberWorkLoop.old.js

Source:ReactFiberWorkLoop.old.js Github

copy

Full Screen

...62 // more and prefer CPU suspense heuristics instead.63 var workInProgressRootRenderTargetTime = Infinity; // How long a render is supposed to take before we start following CPU64 // suspense heuristics and opt out of rendering more content.65 var RENDER_TIMEOUT_MS = 500;66 function resetRenderTimer() {67 workInProgressRootRenderTargetTime = now() + RENDER_TIMEOUT_MS;68 }69 function getRenderTargetTime() {70 return workInProgressRootRenderTargetTime;71 }72 var nextEffect = null;73 var hasUncaughtError = false;74 var firstUncaughtError = null;75 var legacyErrorBoundariesThatAlreadyFailed = null;76 var rootDoesHavePassiveEffects = false;77 var rootWithPendingPassiveEffects = null;78 var pendingPassiveEffectsRenderPriority = NoPriority$1;79 var pendingPassiveEffectsLanes = NoLanes;80 var pendingPassiveHookEffectsMount = [];81 var pendingPassiveHookEffectsUnmount = [];82 var rootsWithPendingDiscreteUpdates = null; // Use these to prevent an infinite loop of nested updates83 var NESTED_UPDATE_LIMIT = 50;84 var nestedUpdateCount = 0;85 var rootWithNestedUpdates = null;86 var NESTED_PASSIVE_UPDATE_LIMIT = 50;87 var nestedPassiveUpdateCount = 0; // Marks the need to reschedule pending interactions at these lanes88 // during the commit phase. This enables them to be traced across components89 // that spawn new work during render. E.g. hidden boundaries, suspended SSR90 // hydration or SuspenseList.91 // TODO: Can use a bitmask instead of an array92 var spawnedWorkDuringRender = null; // If two updates are scheduled within the same event, we should treat their93 // event times as simultaneous, even if the actual clock time has advanced94 // between the first and second call.95 var currentEventTime = NoTimestamp;96 var currentEventWipLanes = NoLanes;97 var currentEventPendingLanes = NoLanes; // Dev only flag that tracks if passive effects are currently being flushed.98 // We warn about state updates for unmounted components differently in this case.99 var isFlushingPassiveEffects = false;100 var focusedInstanceHandle = null;101 var shouldFireAfterActiveInstanceBlur = false;102 function getWorkInProgressRoot() {103 return workInProgressRoot;104 }105 function requestEventTime() {106 if ((executionContext & (RenderContext | CommitContext)) !== NoContext) {107 // We're inside React, so it's fine to read the actual time.108 return now();109 } // We're not inside React, so we may be in the middle of a browser event.110 if (currentEventTime !== NoTimestamp) {111 // Use the same start time for all updates until we enter React again.112 return currentEventTime;113 } // This is the first update since React yielded. Compute a new start time.114 currentEventTime = now();115 return currentEventTime;116 }117 function requestUpdateLane(fiber) {118 // Special cases119 var mode = fiber.mode;120 if ((mode & BlockingMode) === NoMode) {121 return SyncLane;122 } else if ((mode & ConcurrentMode) === NoMode) {123 return getCurrentPriorityLevel() === ImmediatePriority$1 ? SyncLane : SyncBatchedLane;124 } // The algorithm for assigning an update to a lane should be stable for all125 // updates at the same priority within the same event. To do this, the inputs126 // to the algorithm must be the same. For example, we use the `renderLanes`127 // to avoid choosing a lane that is already in the middle of rendering.128 //129 // However, the "included" lanes could be mutated in between updates in the130 // same event, like if you perform an update inside `flushSync`. Or any other131 // code path that might call `prepareFreshStack`.132 //133 // The trick we use is to cache the first of each of these inputs within an134 // event. Then reset the cached values once we can be sure the event is over.135 // Our heuristic for that is whenever we enter a concurrent work loop.136 //137 // We'll do the same for `currentEventPendingLanes` below.138 if (currentEventWipLanes === NoLanes) {139 currentEventWipLanes = workInProgressRootIncludedLanes;140 }141 var isTransition = requestCurrentTransition() !== NoTransition;142 if (isTransition) {143 if (currentEventPendingLanes !== NoLanes) {144 currentEventPendingLanes = mostRecentlyUpdatedRoot !== null ? mostRecentlyUpdatedRoot.pendingLanes : NoLanes;145 }146 return findTransitionLane(currentEventWipLanes, currentEventPendingLanes);147 } // TODO: Remove this dependency on the Scheduler priority.148 // To do that, we're replacing it with an update lane priority.149 var schedulerPriority = getCurrentPriorityLevel(); // The old behavior was using the priority level of the Scheduler.150 // This couples React to the Scheduler internals, so we're replacing it151 // with the currentUpdateLanePriority above. As an example of how this152 // could be problematic, if we're not inside `Scheduler.runWithPriority`,153 // then we'll get the priority of the current running Scheduler task,154 // which is probably not what we want.155 var lane;156 if ( // TODO: Temporary. We're removing the concept of discrete updates.157 (executionContext & DiscreteEventContext) !== NoContext && schedulerPriority === UserBlockingPriority$2) {158 lane = findUpdateLane(InputDiscreteLanePriority, currentEventWipLanes);159 } else {160 var schedulerLanePriority = schedulerPriorityToLanePriority(schedulerPriority);161 lane = findUpdateLane(schedulerLanePriority, currentEventWipLanes);162 }163 return lane;164 }165 function requestRetryLane(fiber) {166 // This is a fork of `requestUpdateLane` designed specifically for Suspense167 // "retries" — a special update that attempts to flip a Suspense boundary168 // from its placeholder state to its primary/resolved state.169 // Special cases170 var mode = fiber.mode;171 if ((mode & BlockingMode) === NoMode) {172 return SyncLane;173 } else if ((mode & ConcurrentMode) === NoMode) {174 return getCurrentPriorityLevel() === ImmediatePriority$1 ? SyncLane : SyncBatchedLane;175 } // See `requestUpdateLane` for explanation of `currentEventWipLanes`176 if (currentEventWipLanes === NoLanes) {177 currentEventWipLanes = workInProgressRootIncludedLanes;178 }179 return findRetryLane(currentEventWipLanes);180 }181 function scheduleUpdateOnFiber(fiber, lane, eventTime) {182 checkForNestedUpdates();183 warnAboutRenderPhaseUpdatesInDEV(fiber);184 var root = markUpdateLaneFromFiberToRoot(fiber, lane);185 if (root === null) {186 warnAboutUpdateOnUnmountedFiberInDEV(fiber);187 return null;188 } // Mark that the root has a pending update.189 markRootUpdated(root, lane, eventTime);190 if (root === workInProgressRoot) {191 // Received an update to a tree that's in the middle of rendering. Mark192 // that there was an interleaved update work on this root. Unless the193 // `deferRenderPhaseUpdateToNextBatch` flag is off and this is a render194 // phase update. In that case, we don't treat render phase updates as if195 // they were interleaved, for backwards compat reasons.196 {197 workInProgressRootUpdatedLanes = mergeLanes(workInProgressRootUpdatedLanes, lane);198 }199 if (workInProgressRootExitStatus === RootSuspendedWithDelay) {200 // The root already suspended with a delay, which means this render201 // definitely won't finish. Since we have a new update, let's mark it as202 // suspended now, right before marking the incoming update. This has the203 // effect of interrupting the current render and switching to the update.204 // TODO: Make sure this doesn't override pings that happen while we've205 // already started rendering.206 markRootSuspended$1(root, workInProgressRootRenderLanes);207 }208 } // TODO: requestUpdateLanePriority also reads the priority. Pass the209 // priority as an argument to that function and this one.210 var priorityLevel = getCurrentPriorityLevel();211 if (lane === SyncLane) {212 if ( // Check if we're inside unbatchedUpdates213 (executionContext & LegacyUnbatchedContext) !== NoContext && // Check if we're not already rendering214 (executionContext & (RenderContext | CommitContext)) === NoContext) {215 // Register pending interactions on the root to avoid losing traced interaction data.216 schedulePendingInteractions(root, lane); // This is a legacy edge case. The initial mount of a ReactDOM.render-ed217 // root inside of batchedUpdates should be synchronous, but layout updates218 // should be deferred until the end of the batch.219 performSyncWorkOnRoot(root);220 } else {221 ensureRootIsScheduled(root, eventTime);222 schedulePendingInteractions(root, lane);223 if (executionContext === NoContext) {224 // Flush the synchronous work now, unless we're already working or inside225 // a batch. This is intentionally inside scheduleUpdateOnFiber instead of226 // scheduleCallbackForFiber to preserve the ability to schedule a callback227 // without immediately flushing it. We only do this for user-initiated228 // updates, to preserve historical behavior of legacy mode.229 resetRenderTimer();230 flushSyncCallbackQueue();231 }232 }233 } else {234 // Schedule a discrete update but only if it's not Sync.235 if ((executionContext & DiscreteEventContext) !== NoContext && ( // Only updates at user-blocking priority or greater are considered236 // discrete, even inside a discrete event.237 priorityLevel === UserBlockingPriority$2 || priorityLevel === ImmediatePriority$1)) {238 // This is the result of a discrete event. Track the lowest priority239 // discrete update per root so we can flush them early, if needed.240 if (rootsWithPendingDiscreteUpdates === null) {241 rootsWithPendingDiscreteUpdates = new Set([root]);242 } else {243 rootsWithPendingDiscreteUpdates.add(root);244 }245 } // Schedule other updates after in case the callback is sync.246 ensureRootIsScheduled(root, eventTime);247 schedulePendingInteractions(root, lane);248 } // We use this when assigning a lane for a transition inside249 // `requestUpdateLane`. We assume it's the same as the root being updated,250 // since in the common case of a single root app it probably is. If it's not251 // the same root, then it's not a huge deal, we just might batch more stuff252 // together more than necessary.253 mostRecentlyUpdatedRoot = root;254 } // This is split into a separate function so we can mark a fiber with pending255 // work without treating it as a typical update that originates from an event;256 // e.g. retrying a Suspense boundary isn't an update, but it does schedule work257 // on a fiber.258 function markUpdateLaneFromFiberToRoot(sourceFiber, lane) {259 // Update the source fiber's lanes260 sourceFiber.lanes = mergeLanes(sourceFiber.lanes, lane);261 var alternate = sourceFiber.alternate;262 if (alternate !== null) {263 alternate.lanes = mergeLanes(alternate.lanes, lane);264 }265 {266 if (alternate === null && (sourceFiber.flags & (Placement | Hydrating)) !== NoFlags) {267 warnAboutUpdateOnNotYetMountedFiberInDEV(sourceFiber);268 }269 } // Walk the parent path to the root and update the child expiration time.270 var node = sourceFiber;271 var parent = sourceFiber.return;272 while (parent !== null) {273 parent.childLanes = mergeLanes(parent.childLanes, lane);274 alternate = parent.alternate;275 if (alternate !== null) {276 alternate.childLanes = mergeLanes(alternate.childLanes, lane);277 } else {278 {279 if ((parent.flags & (Placement | Hydrating)) !== NoFlags) {280 warnAboutUpdateOnNotYetMountedFiberInDEV(sourceFiber);281 }282 }283 }284 node = parent;285 parent = parent.return;286 }287 if (node.tag === HostRoot) {288 var root = node.stateNode;289 return root;290 } else {291 return null;292 }293 } // Use this function to schedule a task for a root. There's only one task per294 // root; if a task was already scheduled, we'll check to make sure the priority295 // of the existing task is the same as the priority of the next level that the296 // root has work on. This function is called on every update, and right before297 // exiting a task.298 function ensureRootIsScheduled(root, currentTime) {299 var existingCallbackNode = root.callbackNode; // Check if any lanes are being starved by other work. If so, mark them as300 // expired so we know to work on those next.301 markStarvedLanesAsExpired(root, currentTime); // Determine the next lanes to work on, and their priority.302 var nextLanes = getNextLanes(root, root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes); // This returns the priority level computed during the `getNextLanes` call.303 var newCallbackPriority = returnNextLanesPriority();304 if (nextLanes === NoLanes) {305 // Special case: There's nothing to work on.306 if (existingCallbackNode !== null) {307 cancelCallback(existingCallbackNode);308 root.callbackNode = null;309 root.callbackPriority = NoLanePriority;310 }311 return;312 } // Check if there's an existing task. We may be able to reuse it.313 if (existingCallbackNode !== null) {314 var existingCallbackPriority = root.callbackPriority;315 if (existingCallbackPriority === newCallbackPriority) {316 // The priority hasn't changed. We can reuse the existing task. Exit.317 return;318 } // The priority changed. Cancel the existing callback. We'll schedule a new319 // one below.320 cancelCallback(existingCallbackNode);321 } // Schedule a new callback.322 var newCallbackNode;323 if (newCallbackPriority === SyncLanePriority) {324 // Special case: Sync React callbacks are scheduled on a special325 // internal queue326 newCallbackNode = scheduleSyncCallback(performSyncWorkOnRoot.bind(null, root));327 } else if (newCallbackPriority === SyncBatchedLanePriority) {328 newCallbackNode = scheduleCallback(ImmediatePriority$1, performSyncWorkOnRoot.bind(null, root));329 } else {330 var schedulerPriorityLevel = lanePriorityToSchedulerPriority(newCallbackPriority);331 newCallbackNode = scheduleCallback(schedulerPriorityLevel, performConcurrentWorkOnRoot.bind(null, root));332 }333 root.callbackPriority = newCallbackPriority;334 root.callbackNode = newCallbackNode;335 } // This is the entry point for every concurrent task, i.e. anything that336 // goes through Scheduler.337 function performConcurrentWorkOnRoot(root) {338 // Since we know we're in a React event, we can clear the current339 // event time. The next update will compute a new event time.340 currentEventTime = NoTimestamp;341 currentEventWipLanes = NoLanes;342 currentEventPendingLanes = NoLanes;343 if (!((executionContext & (RenderContext | CommitContext)) === NoContext)) {344 {345 throw Error( "Should not already be working." );346 }347 } // Flush any pending passive effects before deciding which lanes to work on,348 // in case they schedule additional work.349 var originalCallbackNode = root.callbackNode;350 var didFlushPassiveEffects = flushPassiveEffects();351 if (didFlushPassiveEffects) {352 // Something in the passive effect phase may have canceled the current task.353 // Check if the task node for this root was changed.354 if (root.callbackNode !== originalCallbackNode) {355 // The current task was canceled. Exit. We don't need to call356 // `ensureRootIsScheduled` because the check above implies either that357 // there's a new task, or that there's no remaining work on this root.358 return null;359 }360 } // Determine the next expiration time to work on, using the fields stored361 // on the root.362 var lanes = getNextLanes(root, root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes);363 if (lanes === NoLanes) {364 // Defensive coding. This is never expected to happen.365 return null;366 }367 var exitStatus = renderRootConcurrent(root, lanes);368 if (includesSomeLane(workInProgressRootIncludedLanes, workInProgressRootUpdatedLanes)) {369 // The render included lanes that were updated during the render phase.370 // For example, when unhiding a hidden tree, we include all the lanes371 // that were previously skipped when the tree was hidden. That set of372 // lanes is a superset of the lanes we started rendering with.373 //374 // So we'll throw out the current work and restart.375 prepareFreshStack(root, NoLanes);376 } else if (exitStatus !== RootIncomplete) {377 if (exitStatus === RootErrored) {378 executionContext |= RetryAfterError; // If an error occurred during hydration,379 // discard server response and fall back to client side render.380 if (root.hydrate) {381 root.hydrate = false;382 clearContainer(root.containerInfo);383 } // If something threw an error, try rendering one more time. We'll render384 // synchronously to block concurrent data mutations, and we'll includes385 // all pending updates are included. If it still fails after the second386 // attempt, we'll give up and commit the resulting tree.387 lanes = getLanesToRetrySynchronouslyOnError(root);388 if (lanes !== NoLanes) {389 exitStatus = renderRootSync(root, lanes);390 }391 }392 if (exitStatus === RootFatalErrored) {393 var fatalError = workInProgressRootFatalError;394 prepareFreshStack(root, NoLanes);395 markRootSuspended$1(root, lanes);396 ensureRootIsScheduled(root, now());397 throw fatalError;398 } // We now have a consistent tree. The next step is either to commit it,399 // or, if something suspended, wait to commit it after a timeout.400 var finishedWork = root.current.alternate;401 root.finishedWork = finishedWork;402 root.finishedLanes = lanes;403 finishConcurrentRender(root, exitStatus, lanes);404 }405 ensureRootIsScheduled(root, now());406 if (root.callbackNode === originalCallbackNode) {407 // The task node scheduled for this root is the same one that's408 // currently executed. Need to return a continuation.409 return performConcurrentWorkOnRoot.bind(null, root);410 }411 return null;412 }413 function finishConcurrentRender(root, exitStatus, lanes) {414 switch (exitStatus) {415 case RootIncomplete:416 case RootFatalErrored:417 {418 {419 {420 throw Error( "Root did not complete. This is a bug in React." );421 }422 }423 }424 // Flow knows about invariant, so it complains if I add a break425 // statement, but eslint doesn't know about invariant, so it complains426 // if I do. eslint-disable-next-line no-fallthrough427 case RootErrored:428 {429 // We should have already attempted to retry this tree. If we reached430 // this point, it errored again. Commit it.431 commitRoot(root);432 break;433 }434 case RootSuspended:435 {436 markRootSuspended$1(root, lanes); // We have an acceptable loading state. We need to figure out if we437 // should immediately commit it or wait a bit.438 if (includesOnlyRetries(lanes) && // do not delay if we're inside an act() scope439 !shouldForceFlushFallbacksInDEV()) {440 // This render only included retries, no updates. Throttle committing441 // retries so that we don't show too many loading states too quickly.442 var msUntilTimeout = globalMostRecentFallbackTime + FALLBACK_THROTTLE_MS - now(); // Don't bother with a very short suspense time.443 if (msUntilTimeout > 10) {444 var nextLanes = getNextLanes(root, NoLanes);445 if (nextLanes !== NoLanes) {446 // There's additional work on this root.447 break;448 }449 var suspendedLanes = root.suspendedLanes;450 if (!isSubsetOfLanes(suspendedLanes, lanes)) {451 // We should prefer to render the fallback of at the last452 // suspended level. Ping the last suspended level to try453 // rendering it again.454 // FIXME: What if the suspended lanes are Idle? Should not restart.455 var eventTime = requestEventTime();456 markRootPinged(root, suspendedLanes);457 break;458 } // The render is suspended, it hasn't timed out, and there's no459 // lower priority work to do. Instead of committing the fallback460 // immediately, wait for more data to arrive.461 root.timeoutHandle = scheduleTimeout(commitRoot.bind(null, root), msUntilTimeout);462 break;463 }464 } // The work expired. Commit immediately.465 commitRoot(root);466 break;467 }468 case RootSuspendedWithDelay:469 {470 markRootSuspended$1(root, lanes);471 if (includesOnlyTransitions(lanes)) {472 // This is a transition, so we should exit without committing a473 // placeholder and without scheduling a timeout. Delay indefinitely474 // until we receive more data.475 break;476 }477 if (!shouldForceFlushFallbacksInDEV()) {478 // This is not a transition, but we did trigger an avoided state.479 // Schedule a placeholder to display after a short delay, using the Just480 // Noticeable Difference.481 // TODO: Is the JND optimization worth the added complexity? If this is482 // the only reason we track the event time, then probably not.483 // Consider removing.484 var mostRecentEventTime = getMostRecentEventTime(root, lanes);485 var eventTimeMs = mostRecentEventTime;486 var timeElapsedMs = now() - eventTimeMs;487 var _msUntilTimeout = jnd(timeElapsedMs) - timeElapsedMs; // Don't bother with a very short suspense time.488 if (_msUntilTimeout > 10) {489 // Instead of committing the fallback immediately, wait for more data490 // to arrive.491 root.timeoutHandle = scheduleTimeout(commitRoot.bind(null, root), _msUntilTimeout);492 break;493 }494 } // Commit the placeholder.495 commitRoot(root);496 break;497 }498 case RootCompleted:499 {500 // The work completed. Ready to commit.501 commitRoot(root);502 break;503 }504 default:505 {506 {507 {508 throw Error( "Unknown root exit status." );509 }510 }511 }512 }513 }514 function markRootSuspended$1(root, suspendedLanes) {515 // When suspending, we should always exclude lanes that were pinged or (more516 // rarely, since we try to avoid it) updated during the render phase.517 // TODO: Lol maybe there's a better way to factor this besides this518 // obnoxiously named function :)519 suspendedLanes = removeLanes(suspendedLanes, workInProgressRootPingedLanes);520 suspendedLanes = removeLanes(suspendedLanes, workInProgressRootUpdatedLanes);521 markRootSuspended(root, suspendedLanes);522 } // This is the entry point for synchronous tasks that don't go523 // through Scheduler524 function performSyncWorkOnRoot(root) {525 if (!((executionContext & (RenderContext | CommitContext)) === NoContext)) {526 {527 throw Error( "Should not already be working." );528 }529 }530 flushPassiveEffects();531 var lanes;532 var exitStatus;533 if (root === workInProgressRoot && includesSomeLane(root.expiredLanes, workInProgressRootRenderLanes)) {534 // There's a partial tree, and at least one of its lanes has expired. Finish535 // rendering it before rendering the rest of the expired work.536 lanes = workInProgressRootRenderLanes;537 exitStatus = renderRootSync(root, lanes);538 if (includesSomeLane(workInProgressRootIncludedLanes, workInProgressRootUpdatedLanes)) {539 // The render included lanes that were updated during the render phase.540 // For example, when unhiding a hidden tree, we include all the lanes541 // that were previously skipped when the tree was hidden. That set of542 // lanes is a superset of the lanes we started rendering with.543 //544 // Note that this only happens when part of the tree is rendered545 // concurrently. If the whole tree is rendered synchronously, then there546 // are no interleaved events.547 lanes = getNextLanes(root, lanes);548 exitStatus = renderRootSync(root, lanes);549 }550 } else {551 lanes = getNextLanes(root, NoLanes);552 exitStatus = renderRootSync(root, lanes);553 }554 if (root.tag !== LegacyRoot && exitStatus === RootErrored) {555 executionContext |= RetryAfterError; // If an error occurred during hydration,556 // discard server response and fall back to client side render.557 if (root.hydrate) {558 root.hydrate = false;559 clearContainer(root.containerInfo);560 } // If something threw an error, try rendering one more time. We'll render561 // synchronously to block concurrent data mutations, and we'll includes562 // all pending updates are included. If it still fails after the second563 // attempt, we'll give up and commit the resulting tree.564 lanes = getLanesToRetrySynchronouslyOnError(root);565 if (lanes !== NoLanes) {566 exitStatus = renderRootSync(root, lanes);567 }568 }569 if (exitStatus === RootFatalErrored) {570 var fatalError = workInProgressRootFatalError;571 prepareFreshStack(root, NoLanes);572 markRootSuspended$1(root, lanes);573 ensureRootIsScheduled(root, now());574 throw fatalError;575 } // We now have a consistent tree. Because this is a sync render, we576 // will commit it even if something suspended.577 var finishedWork = root.current.alternate;578 root.finishedWork = finishedWork;579 root.finishedLanes = lanes;580 commitRoot(root); // Before exiting, make sure there's a callback scheduled for the next581 // pending level.582 ensureRootIsScheduled(root, now());583 return null;584 }585 function flushRoot(root, lanes) {586 markRootExpired(root, lanes);587 ensureRootIsScheduled(root, now());588 if ((executionContext & (RenderContext | CommitContext)) === NoContext) {589 resetRenderTimer();590 flushSyncCallbackQueue();591 }592 }593 function getExecutionContext() {594 return executionContext;595 }596 // flush react事件597 function flushDiscreteUpdates() {598 // TODO: Should be able to flush inside batchedUpdates, but not inside `act`.599 // However, `act` uses `batchedUpdates`, so there's no way to distinguish600 // those two cases. Need to fix this before exposing flushDiscreteUpdates601 // as a public API.602 if ((executionContext & (BatchedContext | RenderContext | CommitContext)) !== NoContext) {603 {604 if ((executionContext & RenderContext) !== NoContext) {605 error('unstable_flushDiscreteUpdates: Cannot flush updates when React is ' + 'already rendering.');606 }607 } // We're already rendering, so we can't synchronously flush pending work.608 // This is probably a nested event dispatch triggered by a lifecycle/effect,609 // like `el.focus()`. Exit.610 return;611 }612 flushPendingDiscreteUpdates(); // If the discrete updates scheduled passive effects, flush them now so that613 // they fire before the next serial event.614 flushPassiveEffects();615 }616 function flushPendingDiscreteUpdates() {617 if (rootsWithPendingDiscreteUpdates !== null) {618 // For each root with pending discrete updates, schedule a callback to619 // immediately flush them.620 var roots = rootsWithPendingDiscreteUpdates;621 rootsWithPendingDiscreteUpdates = null;622 roots.forEach(function (root) {623 markDiscreteUpdatesExpired(root);624 ensureRootIsScheduled(root, now());625 });626 } // Now flush the immediate queue.627 flushSyncCallbackQueue();628 }629 function batchedUpdates$1(fn, a) {630 var prevExecutionContext = executionContext;631 executionContext |= BatchedContext;632 try {633 return fn(a);634 } finally {635 executionContext = prevExecutionContext;636 if (executionContext === NoContext) {637 // Flush the immediate callbacks that were scheduled during this batch638 resetRenderTimer();639 flushSyncCallbackQueue();640 }641 }642 }643 function batchedEventUpdates$1(fn, a) {644 var prevExecutionContext = executionContext;645 executionContext |= EventContext;646 try {647 return fn(a);648 } finally {649 executionContext = prevExecutionContext;650 if (executionContext === NoContext) {651 // Flush the immediate callbacks that were scheduled during this batch652 resetRenderTimer();653 flushSyncCallbackQueue();654 }655 }656 }657 function discreteUpdates$1(fn, a, b, c, d) {658 var prevExecutionContext = executionContext;659 executionContext |= DiscreteEventContext;660 {661 try {662 return runWithPriority$1(UserBlockingPriority$2, fn.bind(null, a, b, c, d));663 } finally {664 executionContext = prevExecutionContext;665 if (executionContext === NoContext) {666 // Flush the immediate callbacks that were scheduled during this batch667 resetRenderTimer();668 flushSyncCallbackQueue();669 }670 }671 }672 }673 // 非批量更新674 function unbatchedUpdates(fn, a) {675 var prevExecutionContext = executionContext;676 executionContext &= ~BatchedContext;677 executionContext |= LegacyUnbatchedContext;678 try {679 return fn(a);680 } finally {681 executionContext = prevExecutionContext;682 if (executionContext === NoContext) {683 // Flush the immediate callbacks that were scheduled during this batch684 resetRenderTimer();685 flushSyncCallbackQueue();686 }687 }688 }689 function flushSync(fn, a) {690 var prevExecutionContext = executionContext;691 if ((prevExecutionContext & (RenderContext | CommitContext)) !== NoContext) {692 {693 error('flushSync was called from inside a lifecycle method. React cannot ' + 'flush when React is already rendering. Consider moving this call to ' + 'a scheduler task or micro task.');694 }695 return fn(a);696 }697 executionContext |= BatchedContext;698 {699 try {700 if (fn) {701 return runWithPriority$1(ImmediatePriority$1, fn.bind(null, a));702 } else {703 return undefined;704 }705 } finally {706 executionContext = prevExecutionContext; // Flush the immediate callbacks that were scheduled during this batch.707 // Note that this will happen even if batchedUpdates is higher up708 // the stack.709 flushSyncCallbackQueue();710 }711 }712 }713 function flushControlled(fn) {714 var prevExecutionContext = executionContext;715 executionContext |= BatchedContext;716 {717 try {718 runWithPriority$1(ImmediatePriority$1, fn);719 } finally {720 executionContext = prevExecutionContext;721 if (executionContext === NoContext) {722 // Flush the immediate callbacks that were scheduled during this batch723 resetRenderTimer();724 flushSyncCallbackQueue();725 }726 }727 }728 }729 function pushRenderLanes(fiber, lanes) {730 push(subtreeRenderLanesCursor, subtreeRenderLanes, fiber);731 subtreeRenderLanes = mergeLanes(subtreeRenderLanes, lanes);732 workInProgressRootIncludedLanes = mergeLanes(workInProgressRootIncludedLanes, lanes);733 }734 function popRenderLanes(fiber) {735 subtreeRenderLanes = subtreeRenderLanesCursor.current;736 pop(subtreeRenderLanesCursor, fiber);737 }738 function prepareFreshStack(root, lanes) {739 root.finishedWork = null;740 root.finishedLanes = NoLanes;741 var timeoutHandle = root.timeoutHandle;742 if (timeoutHandle !== noTimeout) {743 // The root previous suspended and scheduled a timeout to commit a fallback744 // state. Now that we have additional work, cancel the timeout.745 root.timeoutHandle = noTimeout; // $FlowFixMe Complains noTimeout is not a TimeoutID, despite the check above746 cancelTimeout(timeoutHandle);747 }748 if (workInProgress !== null) {749 var interruptedWork = workInProgress.return;750 while (interruptedWork !== null) {751 unwindInterruptedWork(interruptedWork);752 interruptedWork = interruptedWork.return;753 }754 }755 workInProgressRoot = root;756 workInProgress = createWorkInProgress(root.current, null);757 workInProgressRootRenderLanes = subtreeRenderLanes = workInProgressRootIncludedLanes = lanes;758 workInProgressRootExitStatus = RootIncomplete;759 workInProgressRootFatalError = null;760 workInProgressRootSkippedLanes = NoLanes;761 workInProgressRootUpdatedLanes = NoLanes;762 workInProgressRootPingedLanes = NoLanes;763 {764 spawnedWorkDuringRender = null;765 }766 {767 ReactStrictModeWarnings.discardPendingWarnings();768 }769 }770 function handleError(root, thrownValue) {771 do {772 var erroredWork = workInProgress;773 try {774 // Reset module-level state that was set during the render phase.775 resetContextDependencies();776 resetHooksAfterThrow();777 resetCurrentFiber(); // TODO: I found and added this missing line while investigating a778 // separate issue. Write a regression test using string refs.779 ReactCurrentOwner$2.current = null;780 if (erroredWork === null || erroredWork.return === null) {781 // Expected to be working on a non-root fiber. This is a fatal error782 // because there's no ancestor that can handle it; the root is783 // supposed to capture all errors that weren't caught by an error784 // boundary.785 workInProgressRootExitStatus = RootFatalErrored;786 workInProgressRootFatalError = thrownValue; // Set `workInProgress` to null. This represents advancing to the next787 // sibling, or the parent if there are no siblings. But since the root788 // has no siblings nor a parent, we set it to null. Usually this is789 // handled by `completeUnitOfWork` or `unwindWork`, but since we're790 // intentionally not calling those, we need set it here.791 // TODO: Consider calling `unwindWork` to pop the contexts.792 workInProgress = null;793 return;794 }795 if (enableProfilerTimer && erroredWork.mode & ProfileMode) {796 // Record the time spent rendering before an error was thrown. This797 // avoids inaccurate Profiler durations in the case of a798 // suspended render.799 stopProfilerTimerIfRunningAndRecordDelta(erroredWork, true);800 }801 throwException(root, erroredWork.return, erroredWork, thrownValue, workInProgressRootRenderLanes);802 completeUnitOfWork(erroredWork);803 } catch (yetAnotherThrownValue) {804 // Something in the return path also threw.805 thrownValue = yetAnotherThrownValue;806 if (workInProgress === erroredWork && erroredWork !== null) {807 // If this boundary has already errored, then we had trouble processing808 // the error. Bubble it to the next boundary.809 erroredWork = erroredWork.return;810 workInProgress = erroredWork;811 } else {812 erroredWork = workInProgress;813 }814 continue;815 } // Return to the normal work loop.816 return;817 } while (true);818 }819 function pushDispatcher() {820 var prevDispatcher = ReactCurrentDispatcher$2.current;821 ReactCurrentDispatcher$2.current = ContextOnlyDispatcher;822 if (prevDispatcher === null) {823 // The React isomorphic package does not include a default dispatcher.824 // Instead the first renderer will lazily attach one, in order to give825 // nicer error messages.826 return ContextOnlyDispatcher;827 } else {828 return prevDispatcher;829 }830 }831 function popDispatcher(prevDispatcher) {832 ReactCurrentDispatcher$2.current = prevDispatcher;833 }834 function pushInteractions(root) {835 {836 var prevInteractions = __interactionsRef.current;837 __interactionsRef.current = root.memoizedInteractions;838 return prevInteractions;839 }840 }841 function popInteractions(prevInteractions) {842 {843 __interactionsRef.current = prevInteractions;844 }845 }846 function markCommitTimeOfFallback() {847 globalMostRecentFallbackTime = now();848 }849 function markSkippedUpdateLanes(lane) {850 workInProgressRootSkippedLanes = mergeLanes(lane, workInProgressRootSkippedLanes);851 }852 function renderDidSuspend() {853 if (workInProgressRootExitStatus === RootIncomplete) {854 workInProgressRootExitStatus = RootSuspended;855 }856 }857 function renderDidSuspendDelayIfPossible() {858 if (workInProgressRootExitStatus === RootIncomplete || workInProgressRootExitStatus === RootSuspended) {859 workInProgressRootExitStatus = RootSuspendedWithDelay;860 } // Check if there are updates that we skipped tree that might have unblocked861 // this render.862 if (workInProgressRoot !== null && (includesNonIdleWork(workInProgressRootSkippedLanes) || includesNonIdleWork(workInProgressRootUpdatedLanes))) {863 // Mark the current render as suspended so that we switch to working on864 // the updates that were skipped. Usually we only suspend at the end of865 // the render phase.866 // TODO: We should probably always mark the root as suspended immediately867 // (inside this function), since by suspending at the end of the render868 // phase introduces a potential mistake where we suspend lanes that were869 // pinged or updated while we were rendering.870 markRootSuspended$1(workInProgressRoot, workInProgressRootRenderLanes);871 }872 }873 function renderDidError() {874 if (workInProgressRootExitStatus !== RootCompleted) {875 workInProgressRootExitStatus = RootErrored;876 }877 } // Called during render to determine if anything has suspended.878 // Returns false if we're not sure.879 function renderHasNotSuspendedYet() {880 // If something errored or completed, we can't really be sure,881 // so those are false.882 return workInProgressRootExitStatus === RootIncomplete;883 }884 function renderRootSync(root, lanes) {885 var prevExecutionContext = executionContext;886 executionContext |= RenderContext;887 var prevDispatcher = pushDispatcher(); // If the root or lanes have changed, throw out the existing stack888 // and prepare a fresh one. Otherwise we'll continue where we left off.889 if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) {890 prepareFreshStack(root, lanes);891 startWorkOnPendingInteractions(root, lanes);892 }893 var prevInteractions = pushInteractions(root);894 {895 markRenderStarted(lanes);896 }897 do {898 try {899 workLoopSync();900 break;901 } catch (thrownValue) {902 handleError(root, thrownValue);903 }904 } while (true);905 resetContextDependencies();906 {907 popInteractions(prevInteractions);908 }909 executionContext = prevExecutionContext;910 popDispatcher(prevDispatcher);911 if (workInProgress !== null) {912 // This is a sync render, so we should have finished the whole tree.913 {914 {915 throw Error( "Cannot commit an incomplete root. This error is likely caused by a bug in React. Please file an issue." );916 }917 }918 }919 {920 markRenderStopped();921 } // Set this to null to indicate there's no in-progress render.922 workInProgressRoot = null;923 workInProgressRootRenderLanes = NoLanes;924 return workInProgressRootExitStatus;925 } // The work loop is an extremely hot path. Tell Closure not to inline it.926 /** @noinline */927 function workLoopSync() {928 // Already timed out, so perform work without checking if we need to yield.929 while (workInProgress !== null) {930 performUnitOfWork(workInProgress);931 }932 }933 function renderRootConcurrent(root, lanes) {934 var prevExecutionContext = executionContext;935 executionContext |= RenderContext;936 var prevDispatcher = pushDispatcher(); // If the root or lanes have changed, throw out the existing stack937 // and prepare a fresh one. Otherwise we'll continue where we left off.938 if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) {939 resetRenderTimer();940 prepareFreshStack(root, lanes);941 startWorkOnPendingInteractions(root, lanes);942 }943 var prevInteractions = pushInteractions(root);944 {945 markRenderStarted(lanes);946 }947 do {948 try {949 workLoopConcurrent();950 break;951 } catch (thrownValue) {952 handleError(root, thrownValue);953 }...

Full Screen

Full Screen

ReactFiberWorkLoop.js

Source:ReactFiberWorkLoop.js Github

copy

Full Screen

...32 } finally {33 executionContext = prevExecutionContext;34 // if (executionContext === NoContext) {35 // // Flush the immediate callbacks that were scheduled during this batch36 // resetRenderTimer();37 // flushSyncCallbackQueue();38 // }39 }40}41export function scheduleUpdateOnFiber(fiber, lane = SyncLane, eventTime) {42 // const root = markUpdateLaneFromFiberToRoot(fiber, lane);43 // markRootUpdated(root, lane, eventTime);44 if (lane === SyncLane) {45 if (46 // Check if we're inside unbatchedUpdates47 (executionContext & LegacyUnbatchedContext) !== NoContext &&48 // Check if we're not already rendering49 (executionContext & (RenderContext | CommitContext)) === NoContext50 ) {...

Full Screen

Full Screen

Untitled-1.jsx

Source:Untitled-1.jsx Github

copy

Full Screen

...9 } finally {10 // ...11 if (executionContext === NoContext) {12 // Flush the immediate callbacks that were scheduled during this batch13 resetRenderTimer();14 flushSyncCallbackQueue();15 }16 }17}18function legacyRenderSubtreeIntoContainer(parentComponent, children, container, forceHydrate, callback) {19 //...20 let root = container._reactRootContainer;21 let fiberRoot;22 if (!root) {23 // Initial mount、24 // ... 首次挂载,创建rooFiber25 // Initial mount should not be batched.26 unbatchedUpdates(function () {27 updateContainer(children, fiberRoot, parentComponent, callback);...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1const { chromium } = require('playwright');2(async () => {3 const browser = await chromium.launch({ headless: false });4 const context = await browser.newContext();5 const page = await context.newPage();6 await page.waitForTimeout(10000);7 await page.evaluate(() => {8 window.resetRenderTimer();9 });10 await page.waitForTimeout(10000);11 await browser.close();12})();13const { chromium } = require('playwright');14(async () => {15 const browser = await chromium.launch({ headless: false });16 const context = await browser.newContext();17 const page = await context.newPage();18 await page.waitForTimeout(10000);19 await page.evaluate(() => {20 window.resetRenderTimer();21 });22 await page.waitForTimeout(10000);23 await browser.close();24})();25const { chromium } = require('playwright');26(async () => {27 const browser = await chromium.launch({ headless: false });28 const context = await browser.newContext();29 const page = await context.newPage();30 await page.waitForTimeout(10000);31 await page.evaluate(() => {32 window.resetRenderTimer();33 });34 await page.waitForTimeout(10000);35 await browser.close();36})();37const { chromium } = require('playwright');38(async () => {39 const browser = await chromium.launch({ headless: false });

Full Screen

Using AI Code Generation

copy

Full Screen

1const playwright = require("playwright");2(async () => {3 const browser = await playwright.webkit.launch();4 const context = await browser.newContext();5 const page = await context.newPage();6 await page.resetRenderTimer();7 await page.screenshot({ path: 'google.png' });8 await browser.close();9})();10const playwright = require("playwright");11(async () => {12 const browser = await playwright.webkit.launch();13 const context = await browser.newContext();14 const page = await context.newPage();15 await page.resetRenderTimer();16 await page.screenshot({ path: 'google.png' });17 await page.reload();18 await page.resetRenderTimer();19 await page.screenshot({ path: 'google2.png' });20 await browser.close();21})();

Full Screen

Using AI Code Generation

copy

Full Screen

1const { resetRenderTimer } = require('playwright/lib/server/chromium/crBrowser');2const { chromium } = require('playwright');3(async () => {4 const browser = await chromium.launch({ headless: false });5 const page = await browser.newPage();6 resetRenderTimer();7 await page.click('text=Google apps');8 await page.waitForTimeout(10000);9 await browser.close();10})();

Full Screen

Using AI Code Generation

copy

Full Screen

1const { resetRenderTimer } = require('playwright/lib/server/browserContext');2const { chromium } = require('playwright');3(async () => {4 const browser = await chromium.launch();5 const context = await browser.newContext();6 resetRenderTimer(context);7 const page = await context.newPage();8 await page.screenshot({ path: 'google.png' });9 await browser.close();10})();

Full Screen

Using AI Code Generation

copy

Full Screen

1const { resetRenderTimer } = require('playwright/lib/server/supplements/recorder/recorderApp');2resetRenderTimer();3const { resetRenderTimer } = require('playwright/lib/server/supplements/recorder/recorderApp');4resetRenderTimer();5const { resetRenderTimer } = require('playwright/lib/server/supplements/recorder/recorderApp');6resetRenderTimer();7const { resetRenderTimer } = require('playwright/lib/server/supplements/recorder/recorderApp');8resetRenderTimer();9const { resetRenderTimer } = require('playwright/lib/server/supplements/recorder/recorderApp');10resetRenderTimer();11const { resetRenderTimer } = require('playwright/lib/server/supplements/recorder/recorderApp');12resetRenderTimer();13const { resetRenderTimer } = require('playwright/lib/server/supplements/recorder/recorderApp');14resetRenderTimer();15const { resetRenderTimer } = require('playwright/lib/server/supplements/recorder/recorderApp');16resetRenderTimer();17const { resetRenderTimer } = require('playwright/lib/server/supplements/recorder/recorderApp');18resetRenderTimer();19const { resetRenderTimer } = require('playwright/lib/server/supplements/recorder/recorderApp');20resetRenderTimer();21const { resetRenderTimer } = require('playwright/lib/server/supplements/recorder/recorderApp');22resetRenderTimer();23const { resetRenderTimer } = require('playwright/lib/server/supplements/recorder/recorderApp');24resetRenderTimer();25const { resetRenderTimer } = require('playwright/lib/server/supplements/rec

Full Screen

Using AI Code Generation

copy

Full Screen

1const { chromium } = require('playwright');2const { resetRenderTimer } = require('playwright/lib/internal/render');3(async () => {4 const browser = await chromium.launch({ headless: false });5 const context = await browser.newContext();6 const page = await context.newPage();7 await resetRenderTimer(page);8 await browser.close();9})();10module.exports = { resetRenderTimer };11const { helper } = require('./helper');12const { assert } = require('../utils/utils');13const kRenderTimer = Symbol('RenderTimer');14const kRenderTimerTimeout = Symbol('RenderTimerTimeout');15const resetRenderTimer = async page => {16 assert(page, 'page', 'Page');17 await page.evaluate(() => {18 window[kRenderTimer] = 0;19 clearTimeout(window[kRenderTimerTimeout]);20 });21};22module.exports = { resetRenderTimer };23const { assert } = require('../utils/utils');24const helper = {25 getFromENV(name) {26 return process.env[name];27 },28};29module.exports = { helper };30const assert = (value, name, message) => {31 if (!value) throw new Error(`${name} ${message}`);32};33module.exports = { assert };34const assert = (value, name, message) => {35 if (!value) throw new Error(`${name} ${message}`);36};37module.exports = { assert };38const assert = (value, name, message) => {39 if (!value) throw new Error(`${name} ${message}`);40};41module.exports = { assert };42const assert = (value, name, message) => {43 if (!value) throw new Error(`${name} ${message}`);44};45module.exports = { assert };46const assert = (value, name, message) => {47 if (!value) throw new Error(`${name} ${message}`);48};49module.exports = { assert };50const assert = (value, name, message) => {51 if (!value) throw new Error(`${name} ${message}`);52};

Full Screen

Playwright tutorial

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.

Chapters:

  1. What is Playwright : Playwright is comparatively new but has gained good popularity. Get to know some history of the Playwright with some interesting facts connected with it.
  2. How To Install Playwright : Learn in detail about what basic configuration and dependencies are required for installing Playwright and run a test. Get a step-by-step direction for installing the Playwright automation framework.
  3. Playwright Futuristic Features: Launched in 2020, Playwright gained huge popularity quickly because of some obliging features such as Playwright Test Generator and Inspector, Playwright Reporter, Playwright auto-waiting mechanism and etc. Read up on those features to master Playwright testing.
  4. What is Component Testing: Component testing in Playwright is a unique feature that allows a tester to test a single component of a web application without integrating them with other elements. Learn how to perform Component testing on the Playwright automation framework.
  5. Inputs And Buttons In Playwright: Every website has Input boxes and buttons; learn about testing inputs and buttons with different scenarios and examples.
  6. Functions and Selectors in Playwright: Learn how to launch the Chromium browser with Playwright. Also, gain a better understanding of some important functions like “BrowserContext,” which allows you to run multiple browser sessions, and “newPage” which interacts with a page.
  7. Handling Alerts and Dropdowns in Playwright : Playwright interact with different types of alerts and pop-ups, such as simple, confirmation, and prompt, and different types of dropdowns, such as single selector and multi-selector get your hands-on with handling alerts and dropdown in Playright testing.
  8. Playwright vs Puppeteer: Get to know about the difference between two testing frameworks and how they are different than one another, which browsers they support, and what features they provide.
  9. Run Playwright Tests on LambdaTest: Playwright testing with LambdaTest leverages test performance to the utmost. You can run multiple Playwright tests in Parallel with the LammbdaTest test cloud. Get a step-by-step guide to run your Playwright test on the LambdaTest platform.
  10. Playwright Python Tutorial: Playwright automation framework support all major languages such as Python, JavaScript, TypeScript, .NET and etc. However, there are various advantages to Python end-to-end testing with Playwright because of its versatile utility. Get the hang of Playwright python testing with this chapter.
  11. Playwright End To End Testing Tutorial: Get your hands on with Playwright end-to-end testing and learn to use some exciting features such as TraceViewer, Debugging, Networking, Component testing, Visual testing, and many more.
  12. Playwright Video Tutorial: Watch the video tutorials on Playwright testing from experts and get a consecutive in-depth explanation of Playwright automation testing.

Run Playwright Internal automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful