Best JavaScript code snippet using playwright-internal
ReactFiberScheduler.js
Source:ReactFiberScheduler.js
...699 const currentTime = requestCurrentTime();700 if (currentTime < expirationTime) {701 // Restart at the current time.702 workPhase = prevWorkPhase;703 resetContextDependencies();704 ReactCurrentDispatcher.current = prevDispatcher;705 if (enableSchedulerTracing) {706 __interactionsRef.current = ((prevInteractions: any): Set<707 Interaction,708 >);709 }710 return renderRoot.bind(null, root, currentTime);711 }712 }713 } else {714 // Since we know we're in a React event, we can clear the current715 // event time. The next update will compute a new event time.716 currentEventTime = NoWork;717 }718 do {719 try {720 if (isSync) {721 workLoopSync();722 } else {723 workLoop();724 }725 break;726 } catch (thrownValue) {727 // Reset module-level state that was set during the render phase.728 resetContextDependencies();729 resetHooks();730 const sourceFiber = workInProgress;731 if (sourceFiber === null || sourceFiber.return === null) {732 // Expected to be working on a non-root fiber. This is a fatal error733 // because there's no ancestor that can handle it; the root is734 // supposed to capture all errors that weren't caught by an error735 // boundary.736 prepareFreshStack(root, expirationTime);737 workPhase = prevWorkPhase;738 throw thrownValue;739 }740 if (enableProfilerTimer && sourceFiber.mode & ProfileMode) {741 // Record the time spent rendering before an error was thrown. This742 // avoids inaccurate Profiler durations in the case of a743 // suspended render.744 stopProfilerTimerIfRunningAndRecordDelta(sourceFiber, true);745 }746 const returnFiber = sourceFiber.return;747 throwException(748 root,749 returnFiber,750 sourceFiber,751 thrownValue,752 renderExpirationTime,753 );754 workInProgress = completeUnitOfWork(sourceFiber);755 }756 } while (true);757 workPhase = prevWorkPhase;758 resetContextDependencies();759 ReactCurrentDispatcher.current = prevDispatcher;760 if (enableSchedulerTracing) {761 __interactionsRef.current = ((prevInteractions: any): Set<Interaction>);762 }763 if (workInProgress !== null) {764 // There's still work left over. Return a continuation.765 stopInterruptedWorkLoopTimer();766 if (expirationTime !== Sync) {767 startRequestCallbackTimer();768 }769 return renderRoot.bind(null, root, expirationTime);770 }771 }772 // We now have a consistent tree. The next step is either to commit it, or, if773 // something suspended, wait to commit it after a timeout.774 stopFinishedWorkLoopTimer();775 const isLocked = resolveLocksOnRoot(root, expirationTime);776 if (isLocked) {777 // This root has a lock that prevents it from committing. Exit. If we begin778 // work on the root again, without any intervening updates, it will finish779 // without doing additional work.780 return null;781 }782 // Set this to null to indicate there's no in-progress render.783 workInProgressRoot = null;784 switch (workInProgressRootExitStatus) {785 case RootIncomplete: {786 invariant(false, 'Should have a work-in-progress.');787 }788 // Flow knows about invariant, so it compains if I add a break statement,789 // but eslint doesn't know about invariant, so it complains if I do.790 // eslint-disable-next-line no-fallthrough791 case RootErrored: {792 // An error was thrown. First check if there is lower priority work793 // scheduled on this root.794 const lastPendingTime = root.lastPendingTime;795 if (root.lastPendingTime < expirationTime) {796 // There's lower priority work. Before raising the error, try rendering797 // at the lower priority to see if it fixes it. Use a continuation to798 // maintain the existing priority and position in the queue.799 return renderRoot.bind(null, root, lastPendingTime);800 }801 if (!isSync) {802 // If we're rendering asynchronously, it's possible the error was803 // caused by tearing due to a mutation during an event. Try rendering804 // one more time without yiedling to events.805 prepareFreshStack(root, expirationTime);806 scheduleCallback(807 ImmediatePriority,808 renderRoot.bind(null, root, expirationTime),809 );810 return null;811 }812 // If we're already rendering synchronously, commit the root in its813 // errored state.814 return commitRoot.bind(null, root, expirationTime);815 }816 case RootSuspended: {817 if (!isSync) {818 const lastPendingTime = root.lastPendingTime;819 if (root.lastPendingTime < expirationTime) {820 // There's lower priority work. It might be unsuspended. Try rendering821 // at that level.822 return renderRoot.bind(null, root, lastPendingTime);823 }824 // If workInProgressRootMostRecentEventTime is Sync, that means we didn't825 // track any event times. That can happen if we retried but nothing switched826 // from fallback to content. There's no reason to delay doing no work.827 if (workInProgressRootMostRecentEventTime !== Sync) {828 let msUntilTimeout = computeMsUntilTimeout(829 workInProgressRootMostRecentEventTime,830 expirationTime,831 );832 // Don't bother with a very short suspense time.833 if (msUntilTimeout > 10) {834 // The render is suspended, it hasn't timed out, and there's no lower835 // priority work to do. Instead of committing the fallback836 // immediately, wait for more data to arrive.837 root.timeoutHandle = scheduleTimeout(838 commitRoot.bind(null, root, expirationTime),839 msUntilTimeout,840 );841 return null;842 }843 }844 }845 // The work expired. Commit immediately.846 return commitRoot.bind(null, root, expirationTime);847 }848 case RootCompleted: {849 // The work completed. Ready to commit.850 return commitRoot.bind(null, root, expirationTime);851 }852 default: {853 invariant(false, 'Unknown root exit status.');854 }855 }856}857export function markRenderEventTime(expirationTime: ExpirationTime): void {858 if (expirationTime < workInProgressRootMostRecentEventTime) {859 workInProgressRootMostRecentEventTime = expirationTime;860 }861}862export function renderDidSuspend(): void {863 if (workInProgressRootExitStatus === RootIncomplete) {864 workInProgressRootExitStatus = RootSuspended;865 }866}867export function renderDidError() {868 if (869 workInProgressRootExitStatus === RootIncomplete ||870 workInProgressRootExitStatus === RootSuspended871 ) {872 workInProgressRootExitStatus = RootErrored;873 }874}875function inferTimeFromExpirationTime(expirationTime: ExpirationTime): number {876 // We don't know exactly when the update was scheduled, but we can infer an877 // approximate start time from the expiration time.878 const earliestExpirationTimeMs = expirationTimeToMs(expirationTime);879 return earliestExpirationTimeMs - LOW_PRIORITY_EXPIRATION;880}881function workLoopSync() {882 // Already timed out, so perform work without checking if we need to yield.883 while (workInProgress !== null) {884 workInProgress = performUnitOfWork(workInProgress);885 }886}887function workLoop() {888 // Perform work until Scheduler asks us to yield889 while (workInProgress !== null && !shouldYield()) {890 workInProgress = performUnitOfWork(workInProgress);891 }892}893function performUnitOfWork(unitOfWork: Fiber): Fiber | null {894 // The current, flushed, state of this fiber is the alternate. Ideally895 // nothing should rely on this, but relying on it here means that we don't896 // need an additional field on the work in progress.897 const current = unitOfWork.alternate;898 startWorkTimer(unitOfWork);899 setCurrentDebugFiberInDEV(unitOfWork);900 let next;901 if (enableProfilerTimer && (unitOfWork.mode & ProfileMode) !== NoContext) {902 startProfilerTimer(unitOfWork);903 next = beginWork(current, unitOfWork, renderExpirationTime);904 stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, true);905 } else {906 next = beginWork(current, unitOfWork, renderExpirationTime);907 }908 resetCurrentDebugFiberInDEV();909 unitOfWork.memoizedProps = unitOfWork.pendingProps;910 if (next === null) {911 // If this doesn't spawn new work, complete the current work.912 next = completeUnitOfWork(unitOfWork);913 }914 ReactCurrentOwner.current = null;915 return next;916}917function completeUnitOfWork(unitOfWork: Fiber): Fiber | null {918 // Attempt to complete the current unit of work, then move to the next919 // sibling. If there are no more siblings, return to the parent fiber.920 workInProgress = unitOfWork;921 do {922 // The current, flushed, state of this fiber is the alternate. Ideally923 // nothing should rely on this, but relying on it here means that we don't924 // need an additional field on the work in progress.925 const current = workInProgress.alternate;926 const returnFiber = workInProgress.return;927 // Check if the work completed or if something threw.928 if ((workInProgress.effectTag & Incomplete) === NoEffect) {929 setCurrentDebugFiberInDEV(workInProgress);930 let next;931 if (932 !enableProfilerTimer ||933 (workInProgress.mode & ProfileMode) === NoContext934 ) {935 next = completeWork(current, workInProgress, renderExpirationTime);936 } else {937 startProfilerTimer(workInProgress);938 next = completeWork(current, workInProgress, renderExpirationTime);939 // Update render duration assuming we didn't error.940 stopProfilerTimerIfRunningAndRecordDelta(workInProgress, false);941 }942 stopWorkTimer(workInProgress);943 resetCurrentDebugFiberInDEV();944 resetChildExpirationTime(workInProgress);945 if (next !== null) {946 // Completing this fiber spawned new work. Work on that next.947 return next;948 }949 if (950 returnFiber !== null &&951 // Do not append effects to parents if a sibling failed to complete952 (returnFiber.effectTag & Incomplete) === NoEffect953 ) {954 // Append all the effects of the subtree and this fiber onto the effect955 // list of the parent. The completion order of the children affects the956 // side-effect order.957 if (returnFiber.firstEffect === null) {958 returnFiber.firstEffect = workInProgress.firstEffect;959 }960 if (workInProgress.lastEffect !== null) {961 if (returnFiber.lastEffect !== null) {962 returnFiber.lastEffect.nextEffect = workInProgress.firstEffect;963 }964 returnFiber.lastEffect = workInProgress.lastEffect;965 }966 // If this fiber had side-effects, we append it AFTER the children's967 // side-effects. We can perform certain side-effects earlier if needed,968 // by doing multiple passes over the effect list. We don't want to969 // schedule our own side-effect on our own list because if end up970 // reusing children we'll schedule this effect onto itself since we're971 // at the end.972 const effectTag = workInProgress.effectTag;973 // Skip both NoWork and PerformedWork tags when creating the effect974 // list. PerformedWork effect is read by React DevTools but shouldn't be975 // committed.976 if (effectTag > PerformedWork) {977 if (returnFiber.lastEffect !== null) {978 returnFiber.lastEffect.nextEffect = workInProgress;979 } else {980 returnFiber.firstEffect = workInProgress;981 }982 returnFiber.lastEffect = workInProgress;983 }984 }985 } else {986 // This fiber did not complete because something threw. Pop values off987 // the stack without entering the complete phase. If this is a boundary,988 // capture values if possible.989 const next = unwindWork(workInProgress, renderExpirationTime);990 // Because this fiber did not complete, don't reset its expiration time.991 if (992 enableProfilerTimer &&993 (workInProgress.mode & ProfileMode) !== NoContext994 ) {995 // Record the render duration for the fiber that errored.996 stopProfilerTimerIfRunningAndRecordDelta(workInProgress, false);997 // Include the time spent working on failed children before continuing.998 let actualDuration = workInProgress.actualDuration;999 let child = workInProgress.child;1000 while (child !== null) {1001 actualDuration += child.actualDuration;1002 child = child.sibling;1003 }1004 workInProgress.actualDuration = actualDuration;1005 }1006 if (next !== null) {1007 // If completing this work spawned new work, do that next. We'll come1008 // back here again.1009 // Since we're restarting, remove anything that is not a host effect1010 // from the effect tag.1011 // TODO: The name stopFailedWorkTimer is misleading because Suspense1012 // also captures and restarts.1013 stopFailedWorkTimer(workInProgress);1014 next.effectTag &= HostEffectMask;1015 return next;1016 }1017 stopWorkTimer(workInProgress);1018 if (returnFiber !== null) {1019 // Mark the parent fiber as incomplete and clear its effect list.1020 returnFiber.firstEffect = returnFiber.lastEffect = null;1021 returnFiber.effectTag |= Incomplete;1022 }1023 }1024 const siblingFiber = workInProgress.sibling;1025 if (siblingFiber !== null) {1026 // If there is more work to do in this returnFiber, do that next.1027 return siblingFiber;1028 }1029 // Otherwise, return to the parent1030 workInProgress = returnFiber;1031 } while (workInProgress !== null);1032 // We've reached the root.1033 if (workInProgressRootExitStatus === RootIncomplete) {1034 workInProgressRootExitStatus = RootCompleted;1035 }1036 return null;1037}1038function resetChildExpirationTime(completedWork: Fiber) {1039 if (1040 renderExpirationTime !== Never &&1041 completedWork.childExpirationTime === Never1042 ) {1043 // The children of this component are hidden. Don't bubble their1044 // expiration times.1045 return;1046 }1047 let newChildExpirationTime = NoWork;1048 // Bubble up the earliest expiration time.1049 if (enableProfilerTimer && (completedWork.mode & ProfileMode) !== NoContext) {1050 // In profiling mode, resetChildExpirationTime is also used to reset1051 // profiler durations.1052 let actualDuration = completedWork.actualDuration;1053 let treeBaseDuration = completedWork.selfBaseDuration;1054 // When a fiber is cloned, its actualDuration is reset to 0. This value will1055 // only be updated if work is done on the fiber (i.e. it doesn't bailout).1056 // When work is done, it should bubble to the parent's actualDuration. If1057 // the fiber has not been cloned though, (meaning no work was done), then1058 // this value will reflect the amount of time spent working on a previous1059 // render. In that case it should not bubble. We determine whether it was1060 // cloned by comparing the child pointer.1061 const shouldBubbleActualDurations =1062 completedWork.alternate === null ||1063 completedWork.child !== completedWork.alternate.child;1064 let child = completedWork.child;1065 while (child !== null) {1066 const childUpdateExpirationTime = child.expirationTime;1067 const childChildExpirationTime = child.childExpirationTime;1068 if (childUpdateExpirationTime > newChildExpirationTime) {1069 newChildExpirationTime = childUpdateExpirationTime;1070 }1071 if (childChildExpirationTime > newChildExpirationTime) {1072 newChildExpirationTime = childChildExpirationTime;1073 }1074 if (shouldBubbleActualDurations) {1075 actualDuration += child.actualDuration;1076 }1077 treeBaseDuration += child.treeBaseDuration;1078 child = child.sibling;1079 }1080 completedWork.actualDuration = actualDuration;1081 completedWork.treeBaseDuration = treeBaseDuration;1082 } else {1083 let child = completedWork.child;1084 while (child !== null) {1085 const childUpdateExpirationTime = child.expirationTime;1086 const childChildExpirationTime = child.childExpirationTime;1087 if (childUpdateExpirationTime > newChildExpirationTime) {1088 newChildExpirationTime = childUpdateExpirationTime;1089 }1090 if (childChildExpirationTime > newChildExpirationTime) {1091 newChildExpirationTime = childChildExpirationTime;1092 }1093 child = child.sibling;1094 }1095 }1096 completedWork.childExpirationTime = newChildExpirationTime;1097}1098function commitRoot(root, expirationTime) {1099 runWithPriority(1100 ImmediatePriority,1101 commitRootImpl.bind(null, root, expirationTime),1102 );1103 // If there are passive effects, schedule a callback to flush them. This goes1104 // outside commitRootImpl so that it inherits the priority of the render.1105 if (rootWithPendingPassiveEffects !== null) {1106 const priorityLevel = getCurrentPriorityLevel();1107 scheduleCallback(priorityLevel, () => {1108 flushPassiveEffects();1109 return null;1110 });1111 }1112 return null;1113}1114function commitRootImpl(root, expirationTime) {1115 flushPassiveEffects();1116 flushRenderPhaseStrictModeWarningsInDEV();1117 invariant(1118 workPhase !== RenderPhase && workPhase !== CommitPhase,1119 'Should not already be working.',1120 );1121 const finishedWork = root.current.alternate;1122 invariant(finishedWork !== null, 'Should have a work-in-progress root.');1123 // commitRoot never returns a continuation; it always finishes synchronously.1124 // So we can clear these now to allow a new callback to be scheduled.1125 root.callbackNode = null;1126 root.callbackExpirationTime = NoWork;1127 startCommitTimer();1128 // Update the first and last pending times on this root. The new first1129 // pending time is whatever is left on the root fiber.1130 const updateExpirationTimeBeforeCommit = finishedWork.expirationTime;1131 const childExpirationTimeBeforeCommit = finishedWork.childExpirationTime;1132 const firstPendingTimeBeforeCommit =1133 childExpirationTimeBeforeCommit > updateExpirationTimeBeforeCommit1134 ? childExpirationTimeBeforeCommit1135 : updateExpirationTimeBeforeCommit;1136 root.firstPendingTime = firstPendingTimeBeforeCommit;1137 if (firstPendingTimeBeforeCommit < root.lastPendingTime) {1138 // This usually means we've finished all the work, but it can also happen1139 // when something gets downprioritized during render, like a hidden tree.1140 root.lastPendingTime = firstPendingTimeBeforeCommit;1141 }1142 if (root === workInProgressRoot) {1143 // We can reset these now that they are finished.1144 workInProgressRoot = null;1145 workInProgress = null;1146 renderExpirationTime = NoWork;1147 } else {1148 // This indicates that the last root we worked on is not the same one that1149 // we're committing now. This most commonly happens when a suspended root1150 // times out.1151 }1152 // Get the list of effects.1153 let firstEffect;1154 if (finishedWork.effectTag > PerformedWork) {1155 // A fiber's effect list consists only of its children, not itself. So if1156 // the root has an effect, we need to add it to the end of the list. The1157 // resulting list is the set that would belong to the root's parent, if it1158 // had one; that is, all the effects in the tree including the root.1159 if (finishedWork.lastEffect !== null) {1160 finishedWork.lastEffect.nextEffect = finishedWork;1161 firstEffect = finishedWork.firstEffect;1162 } else {1163 firstEffect = finishedWork;1164 }1165 } else {1166 // There is no effect on the root.1167 firstEffect = finishedWork.firstEffect;1168 }1169 if (firstEffect !== null) {1170 const prevWorkPhase = workPhase;1171 workPhase = CommitPhase;1172 let prevInteractions: Set<Interaction> | null = null;1173 if (enableSchedulerTracing) {1174 prevInteractions = __interactionsRef.current;1175 __interactionsRef.current = root.memoizedInteractions;1176 }1177 // Reset this to null before calling lifecycles1178 ReactCurrentOwner.current = null;1179 // The commit phase is broken into several sub-phases. We do a separate pass1180 // of the effect list for each phase: all mutation effects come before all1181 // layout effects, and so on.1182 // The first phase a "before mutation" phase. We use this phase to read the1183 // state of the host tree right before we mutate it. This is where1184 // getSnapshotBeforeUpdate is called.1185 startCommitSnapshotEffectsTimer();1186 prepareForCommit(root.containerInfo);1187 nextEffect = firstEffect;1188 do {1189 if (__DEV__) {1190 invokeGuardedCallback(null, commitBeforeMutationEffects, null);1191 if (hasCaughtError()) {1192 invariant(nextEffect !== null, 'Should be working on an effect.');1193 const error = clearCaughtError();1194 captureCommitPhaseError(nextEffect, error);1195 nextEffect = nextEffect.nextEffect;1196 }1197 } else {1198 try {1199 commitBeforeMutationEffects();1200 } catch (error) {1201 invariant(nextEffect !== null, 'Should be working on an effect.');1202 captureCommitPhaseError(nextEffect, error);1203 nextEffect = nextEffect.nextEffect;1204 }1205 }1206 } while (nextEffect !== null);1207 stopCommitSnapshotEffectsTimer();1208 if (enableProfilerTimer) {1209 // Mark the current commit time to be shared by all Profilers in this1210 // batch. This enables them to be grouped later.1211 recordCommitTime();1212 }1213 // The next phase is the mutation phase, where we mutate the host tree.1214 startCommitHostEffectsTimer();1215 nextEffect = firstEffect;1216 do {1217 if (__DEV__) {1218 invokeGuardedCallback(null, commitMutationEffects, null);1219 if (hasCaughtError()) {1220 invariant(nextEffect !== null, 'Should be working on an effect.');1221 const error = clearCaughtError();1222 captureCommitPhaseError(nextEffect, error);1223 nextEffect = nextEffect.nextEffect;1224 }1225 } else {1226 try {1227 commitMutationEffects();1228 } catch (error) {1229 invariant(nextEffect !== null, 'Should be working on an effect.');1230 captureCommitPhaseError(nextEffect, error);1231 nextEffect = nextEffect.nextEffect;1232 }1233 }1234 } while (nextEffect !== null);1235 stopCommitHostEffectsTimer();1236 resetAfterCommit(root.containerInfo);1237 // The work-in-progress tree is now the current tree. This must come after1238 // the mutation phase, so that the previous tree is still current during1239 // componentWillUnmount, but before the layout phase, so that the finished1240 // work is current during componentDidMount/Update.1241 root.current = finishedWork;1242 // The next phase is the layout phase, where we call effects that read1243 // the host tree after it's been mutated. The idiomatic use case for this is1244 // layout, but class component lifecycles also fire here for legacy reasons.1245 startCommitLifeCyclesTimer();1246 nextEffect = firstEffect;1247 do {1248 if (__DEV__) {1249 invokeGuardedCallback(1250 null,1251 commitLayoutEffects,1252 null,1253 root,1254 expirationTime,1255 );1256 if (hasCaughtError()) {1257 invariant(nextEffect !== null, 'Should be working on an effect.');1258 const error = clearCaughtError();1259 captureCommitPhaseError(nextEffect, error);1260 nextEffect = nextEffect.nextEffect;1261 }1262 } else {1263 try {1264 commitLayoutEffects(root, expirationTime);1265 } catch (error) {1266 invariant(nextEffect !== null, 'Should be working on an effect.');1267 captureCommitPhaseError(nextEffect, error);1268 nextEffect = nextEffect.nextEffect;1269 }1270 }1271 } while (nextEffect !== null);1272 stopCommitLifeCyclesTimer();1273 nextEffect = null;1274 if (enableSchedulerTracing) {1275 __interactionsRef.current = ((prevInteractions: any): Set<Interaction>);1276 }1277 workPhase = prevWorkPhase;1278 } else {1279 // No effects.1280 root.current = finishedWork;1281 // Measure these anyway so the flamegraph explicitly shows that there were1282 // no effects.1283 // TODO: Maybe there's a better way to report this.1284 startCommitSnapshotEffectsTimer();1285 stopCommitSnapshotEffectsTimer();1286 if (enableProfilerTimer) {1287 recordCommitTime();1288 }1289 startCommitHostEffectsTimer();1290 stopCommitHostEffectsTimer();1291 startCommitLifeCyclesTimer();1292 stopCommitLifeCyclesTimer();1293 }1294 stopCommitTimer();1295 if (rootDoesHavePassiveEffects) {1296 // This commit has passive effects. Stash a reference to them. But don't1297 // schedule a callback until after flushing layout work.1298 rootDoesHavePassiveEffects = false;1299 rootWithPendingPassiveEffects = root;1300 pendingPassiveEffectsExpirationTime = expirationTime;1301 } else {1302 if (enableSchedulerTracing) {1303 // If there are no passive effects, then we can complete the pending1304 // interactions. Otherwise, we'll wait until after the passive effects1305 // are flushed.1306 finishPendingInteractions(root, expirationTime);1307 }1308 }1309 // Check if there's remaining work on this root1310 const remainingExpirationTime = root.firstPendingTime;1311 if (remainingExpirationTime !== NoWork) {1312 const currentTime = requestCurrentTime();1313 const priorityLevel = inferPriorityFromExpirationTime(1314 currentTime,1315 remainingExpirationTime,1316 );1317 scheduleCallbackForRoot(root, priorityLevel, remainingExpirationTime);1318 } else {1319 // If there's no remaining work, we can clear the set of already failed1320 // error boundaries.1321 legacyErrorBoundariesThatAlreadyFailed = null;1322 }1323 onCommitRoot(finishedWork.stateNode);1324 if (remainingExpirationTime === Sync) {1325 // Count the number of times the root synchronously re-renders without1326 // finishing. If there are too many, it indicates an infinite update loop.1327 if (root === rootWithNestedUpdates) {1328 nestedUpdateCount++;1329 } else {1330 nestedUpdateCount = 0;1331 rootWithNestedUpdates = root;1332 }1333 } else {1334 nestedUpdateCount = 0;1335 }1336 if (hasUncaughtError) {1337 hasUncaughtError = false;1338 const error = firstUncaughtError;1339 firstUncaughtError = null;1340 throw error;1341 }1342 if (workPhase === LegacyUnbatchedPhase) {1343 // This is a legacy edge case. We just committed the initial mount of1344 // a ReactDOM.render-ed root inside of batchedUpdates. The commit fired1345 // synchronously, but layout updates should be deferred until the end1346 // of the batch.1347 return null;1348 }1349 // If layout work was scheduled, flush it now.1350 flushImmediateQueue();1351 return null;1352}1353function commitBeforeMutationEffects() {1354 while (nextEffect !== null) {1355 if ((nextEffect.effectTag & Snapshot) !== NoEffect) {1356 setCurrentDebugFiberInDEV(nextEffect);1357 recordEffect();1358 const current = nextEffect.alternate;1359 commitBeforeMutationEffectOnFiber(current, nextEffect);1360 resetCurrentDebugFiberInDEV();1361 }1362 nextEffect = nextEffect.nextEffect;1363 }1364}1365function commitMutationEffects() {1366 // TODO: Should probably move the bulk of this function to commitWork.1367 while (nextEffect !== null) {1368 setCurrentDebugFiberInDEV(nextEffect);1369 const effectTag = nextEffect.effectTag;1370 if (effectTag & ContentReset) {1371 commitResetTextContent(nextEffect);1372 }1373 if (effectTag & Ref) {1374 const current = nextEffect.alternate;1375 if (current !== null) {1376 commitDetachRef(current);1377 }1378 }1379 // The following switch statement is only concerned about placement,1380 // updates, and deletions. To avoid needing to add a case for every possible1381 // bitmap value, we remove the secondary effects from the effect tag and1382 // switch on that value.1383 let primaryEffectTag = effectTag & (Placement | Update | Deletion);1384 switch (primaryEffectTag) {1385 case Placement: {1386 commitPlacement(nextEffect);1387 // Clear the "placement" from effect tag so that we know that this is1388 // inserted, before any life-cycles like componentDidMount gets called.1389 // TODO: findDOMNode doesn't rely on this any more but isMounted does1390 // and isMounted is deprecated anyway so we should be able to kill this.1391 nextEffect.effectTag &= ~Placement;1392 break;1393 }1394 case PlacementAndUpdate: {1395 // Placement1396 commitPlacement(nextEffect);1397 // Clear the "placement" from effect tag so that we know that this is1398 // inserted, before any life-cycles like componentDidMount gets called.1399 nextEffect.effectTag &= ~Placement;1400 // Update1401 const current = nextEffect.alternate;1402 commitWork(current, nextEffect);1403 break;1404 }1405 case Update: {1406 const current = nextEffect.alternate;1407 commitWork(current, nextEffect);1408 break;1409 }1410 case Deletion: {1411 commitDeletion(nextEffect);1412 break;1413 }1414 }1415 // TODO: Only record a mutation effect if primaryEffectTag is non-zero.1416 recordEffect();1417 resetCurrentDebugFiberInDEV();1418 nextEffect = nextEffect.nextEffect;1419 }1420}1421function commitLayoutEffects(1422 root: FiberRoot,1423 committedExpirationTime: ExpirationTime,1424) {1425 // TODO: Should probably move the bulk of this function to commitWork.1426 while (nextEffect !== null) {1427 setCurrentDebugFiberInDEV(nextEffect);1428 const effectTag = nextEffect.effectTag;1429 if (effectTag & (Update | Callback)) {1430 recordEffect();1431 const current = nextEffect.alternate;1432 commitLayoutEffectOnFiber(1433 root,1434 current,1435 nextEffect,1436 committedExpirationTime,1437 );1438 }1439 if (effectTag & Ref) {1440 recordEffect();1441 commitAttachRef(nextEffect);1442 }1443 if (effectTag & Passive) {1444 rootDoesHavePassiveEffects = true;1445 }1446 resetCurrentDebugFiberInDEV();1447 nextEffect = nextEffect.nextEffect;1448 }1449}1450export function flushPassiveEffects() {1451 if (rootWithPendingPassiveEffects === null) {1452 return false;1453 }1454 const root = rootWithPendingPassiveEffects;1455 const expirationTime = pendingPassiveEffectsExpirationTime;1456 rootWithPendingPassiveEffects = null;1457 pendingPassiveEffectsExpirationTime = NoWork;1458 let prevInteractions: Set<Interaction> | null = null;1459 if (enableSchedulerTracing) {1460 prevInteractions = __interactionsRef.current;1461 __interactionsRef.current = root.memoizedInteractions;1462 }1463 invariant(1464 workPhase !== RenderPhase && workPhase !== CommitPhase,1465 'Cannot flush passive effects while already rendering.',1466 );1467 const prevWorkPhase = workPhase;1468 workPhase = CommitPhase;1469 // Note: This currently assumes there are no passive effects on the root1470 // fiber, because the root is not part of its own effect list. This could1471 // change in the future.1472 let effect = root.current.firstEffect;1473 while (effect !== null) {1474 if (__DEV__) {1475 setCurrentDebugFiberInDEV(effect);1476 invokeGuardedCallback(null, commitPassiveHookEffects, null, effect);1477 if (hasCaughtError()) {1478 invariant(effect !== null, 'Should be working on an effect.');1479 const error = clearCaughtError();1480 captureCommitPhaseError(effect, error);1481 }1482 resetCurrentDebugFiberInDEV();1483 } else {1484 try {1485 commitPassiveHookEffects(effect);1486 } catch (error) {1487 invariant(effect !== null, 'Should be working on an effect.');1488 captureCommitPhaseError(effect, error);1489 }1490 }1491 effect = effect.nextEffect;1492 }1493 if (enableSchedulerTracing) {1494 __interactionsRef.current = ((prevInteractions: any): Set<Interaction>);1495 finishPendingInteractions(root, expirationTime);1496 }1497 workPhase = prevWorkPhase;1498 flushImmediateQueue();1499 // If additional passive effects were scheduled, increment a counter. If this1500 // exceeds the limit, we'll fire a warning.1501 nestedPassiveUpdateCount =1502 rootWithPendingPassiveEffects === null ? 0 : nestedPassiveUpdateCount + 1;1503 return true;1504}1505export function isAlreadyFailedLegacyErrorBoundary(instance: mixed): boolean {1506 return (1507 legacyErrorBoundariesThatAlreadyFailed !== null &&1508 legacyErrorBoundariesThatAlreadyFailed.has(instance)1509 );1510}1511export function markLegacyErrorBoundaryAsFailed(instance: mixed) {1512 if (legacyErrorBoundariesThatAlreadyFailed === null) {1513 legacyErrorBoundariesThatAlreadyFailed = new Set([instance]);1514 } else {1515 legacyErrorBoundariesThatAlreadyFailed.add(instance);1516 }1517}1518function prepareToThrowUncaughtError(error: mixed) {1519 if (!hasUncaughtError) {1520 hasUncaughtError = true;1521 firstUncaughtError = error;1522 }1523}1524export const onUncaughtError = prepareToThrowUncaughtError;1525function captureCommitPhaseErrorOnRoot(1526 rootFiber: Fiber,1527 sourceFiber: Fiber,1528 error: mixed,1529) {1530 const errorInfo = createCapturedValue(error, sourceFiber);1531 const update = createRootErrorUpdate(rootFiber, errorInfo, Sync);1532 enqueueUpdate(rootFiber, update);1533 const root = markUpdateTimeFromFiberToRoot(rootFiber, Sync);1534 if (root !== null) {1535 scheduleCallbackForRoot(root, ImmediatePriority, Sync);1536 }1537}1538export function captureCommitPhaseError(sourceFiber: Fiber, error: mixed) {1539 if (sourceFiber.tag === HostRoot) {1540 // Error was thrown at the root. There is no parent, so the root1541 // itself should capture it.1542 captureCommitPhaseErrorOnRoot(sourceFiber, sourceFiber, error);1543 return;1544 }1545 let fiber = sourceFiber.return;1546 while (fiber !== null) {1547 if (fiber.tag === HostRoot) {1548 captureCommitPhaseErrorOnRoot(fiber, sourceFiber, error);1549 return;1550 } else if (fiber.tag === ClassComponent) {1551 const ctor = fiber.type;1552 const instance = fiber.stateNode;1553 if (1554 typeof ctor.getDerivedStateFromError === 'function' ||1555 (typeof instance.componentDidCatch === 'function' &&1556 !isAlreadyFailedLegacyErrorBoundary(instance))1557 ) {1558 const errorInfo = createCapturedValue(error, sourceFiber);1559 const update = createClassErrorUpdate(1560 fiber,1561 errorInfo,1562 // TODO: This is always sync1563 Sync,1564 );1565 enqueueUpdate(fiber, update);1566 const root = markUpdateTimeFromFiberToRoot(fiber, Sync);1567 if (root !== null) {1568 scheduleCallbackForRoot(root, ImmediatePriority, Sync);1569 }1570 return;1571 }1572 }1573 fiber = fiber.return;1574 }1575}1576export function pingSuspendedRoot(1577 root: FiberRoot,1578 thenable: Thenable,1579 suspendedTime: ExpirationTime,1580) {1581 const pingCache = root.pingCache;1582 if (pingCache !== null) {1583 // The thenable resolved, so we no longer need to memoize, because it will1584 // never be thrown again.1585 pingCache.delete(thenable);1586 }1587 if (workInProgressRoot === root && renderExpirationTime === suspendedTime) {1588 // Received a ping at the same priority level at which we're currently1589 // rendering. Restart from the root. Don't need to schedule a ping because1590 // we're already working on this tree.1591 prepareFreshStack(root, renderExpirationTime);1592 return;1593 }1594 const lastPendingTime = root.lastPendingTime;1595 if (lastPendingTime < suspendedTime) {1596 // The root is no longer suspended at this time.1597 return;1598 }1599 const pingTime = root.pingTime;1600 if (pingTime !== NoWork && pingTime < suspendedTime) {1601 // There's already a lower priority ping scheduled.1602 return;1603 }1604 // Mark the time at which this ping was scheduled.1605 root.pingTime = suspendedTime;1606 const currentTime = requestCurrentTime();1607 const priorityLevel = inferPriorityFromExpirationTime(1608 currentTime,1609 suspendedTime,1610 );1611 scheduleCallbackForRoot(root, priorityLevel, suspendedTime);1612}1613export function retryTimedOutBoundary(boundaryFiber: Fiber) {1614 // The boundary fiber (a Suspense component) previously timed out and was1615 // rendered in its fallback state. One of the promises that suspended it has1616 // resolved, which means at least part of the tree was likely unblocked. Try1617 // rendering again, at a new expiration time.1618 const currentTime = requestCurrentTime();1619 const retryTime = computeExpirationForFiber(currentTime, boundaryFiber);1620 // TODO: Special case idle priority?1621 const priorityLevel = inferPriorityFromExpirationTime(currentTime, retryTime);1622 const root = markUpdateTimeFromFiberToRoot(boundaryFiber, retryTime);1623 if (root !== null) {1624 scheduleCallbackForRoot(root, priorityLevel, retryTime);1625 }1626}1627export function resolveRetryThenable(boundaryFiber: Fiber, thenable: Thenable) {1628 let retryCache: WeakSet<Thenable> | Set<Thenable> | null;1629 if (enableSuspenseServerRenderer) {1630 switch (boundaryFiber.tag) {1631 case SuspenseComponent:1632 retryCache = boundaryFiber.stateNode;1633 break;1634 case DehydratedSuspenseComponent:1635 retryCache = boundaryFiber.memoizedState;1636 break;1637 default:1638 invariant(1639 false,1640 'Pinged unknown suspense boundary type. ' +1641 'This is probably a bug in React.',1642 );1643 }1644 } else {1645 retryCache = boundaryFiber.stateNode;1646 }1647 if (retryCache !== null) {1648 // The thenable resolved, so we no longer need to memoize, because it will1649 // never be thrown again.1650 retryCache.delete(thenable);1651 }1652 retryTimedOutBoundary(boundaryFiber);1653}1654// Computes the next Just Noticeable Difference (JND) boundary.1655// The theory is that a person can't tell the difference between small differences in time.1656// Therefore, if we wait a bit longer than necessary that won't translate to a noticeable1657// difference in the experience. However, waiting for longer might mean that we can avoid1658// showing an intermediate loading state. The longer we have already waited, the harder it1659// is to tell small differences in time. Therefore, the longer we've already waited,1660// the longer we can wait additionally. At some point we have to give up though.1661// We pick a train model where the next boundary commits at a consistent schedule.1662// These particular numbers are vague estimates. We expect to adjust them based on research.1663function jnd(timeElapsed: number) {1664 return timeElapsed < 1201665 ? 1201666 : timeElapsed < 4801667 ? 4801668 : timeElapsed < 10801669 ? 10801670 : timeElapsed < 19201671 ? 19201672 : timeElapsed < 30001673 ? 30001674 : timeElapsed < 43201675 ? 43201676 : ceil(timeElapsed / 1960) * 1960;1677}1678function computeMsUntilTimeout(1679 mostRecentEventTime: ExpirationTime,1680 committedExpirationTime: ExpirationTime,1681) {1682 if (disableYielding) {1683 // Timeout immediately when yielding is disabled.1684 return 0;1685 }1686 const eventTimeMs: number = inferTimeFromExpirationTime(mostRecentEventTime);1687 const currentTimeMs: number = now();1688 const timeElapsed = currentTimeMs - eventTimeMs;1689 let msUntilTimeout = jnd(timeElapsed) - timeElapsed;1690 // Compute the time until this render pass would expire.1691 const timeUntilExpirationMs =1692 expirationTimeToMs(committedExpirationTime) - currentTimeMs;1693 // Clamp the timeout to the expiration time.1694 // TODO: Once the event time is exact instead of inferred from expiration time1695 // we don't need this.1696 if (timeUntilExpirationMs < msUntilTimeout) {1697 msUntilTimeout = timeUntilExpirationMs;1698 }1699 // This is the value that is passed to `setTimeout`.1700 return msUntilTimeout;1701}1702function checkForNestedUpdates() {1703 if (nestedUpdateCount > NESTED_UPDATE_LIMIT) {1704 nestedUpdateCount = 0;1705 rootWithNestedUpdates = null;1706 invariant(1707 false,1708 'Maximum update depth exceeded. This can happen when a component ' +1709 'repeatedly calls setState inside componentWillUpdate or ' +1710 'componentDidUpdate. React limits the number of nested updates to ' +1711 'prevent infinite loops.',1712 );1713 }1714 if (__DEV__) {1715 if (nestedPassiveUpdateCount > NESTED_PASSIVE_UPDATE_LIMIT) {1716 nestedPassiveUpdateCount = 0;1717 warning(1718 false,1719 'Maximum update depth exceeded. This can happen when a component ' +1720 "calls setState inside useEffect, but useEffect either doesn't " +1721 'have a dependency array, or one of the dependencies changes on ' +1722 'every render.',1723 );1724 }1725 }1726}1727function flushRenderPhaseStrictModeWarningsInDEV() {1728 if (__DEV__) {1729 ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings();1730 ReactStrictModeWarnings.flushLegacyContextWarning();1731 if (warnAboutDeprecatedLifecycles) {1732 ReactStrictModeWarnings.flushPendingDeprecationWarnings();1733 }1734 }1735}1736function stopFinishedWorkLoopTimer() {1737 const didCompleteRoot = true;1738 stopWorkLoopTimer(interruptedBy, didCompleteRoot);1739 interruptedBy = null;1740}1741function stopInterruptedWorkLoopTimer() {1742 // TODO: Track which fiber caused the interruption.1743 const didCompleteRoot = false;1744 stopWorkLoopTimer(interruptedBy, didCompleteRoot);1745 interruptedBy = null;1746}1747function checkForInterruption(1748 fiberThatReceivedUpdate: Fiber,1749 updateExpirationTime: ExpirationTime,1750) {1751 if (1752 enableUserTimingAPI &&1753 workInProgressRoot !== null &&1754 updateExpirationTime > renderExpirationTime1755 ) {1756 interruptedBy = fiberThatReceivedUpdate;1757 }1758}1759let didWarnStateUpdateForUnmountedComponent: Set<string> | null = null;1760function warnAboutUpdateOnUnmountedFiberInDEV(fiber) {1761 if (__DEV__) {1762 const tag = fiber.tag;1763 if (1764 tag !== HostRoot &&1765 tag !== ClassComponent &&1766 tag !== FunctionComponent &&1767 tag !== ForwardRef &&1768 tag !== MemoComponent &&1769 tag !== SimpleMemoComponent1770 ) {1771 // Only warn for user-defined components, not internal ones like Suspense.1772 return;1773 }1774 // We show the whole stack but dedupe on the top component's name because1775 // the problematic code almost always lies inside that component.1776 const componentName = getComponentName(fiber.type) || 'ReactComponent';1777 if (didWarnStateUpdateForUnmountedComponent !== null) {1778 if (didWarnStateUpdateForUnmountedComponent.has(componentName)) {1779 return;1780 }1781 didWarnStateUpdateForUnmountedComponent.add(componentName);1782 } else {1783 didWarnStateUpdateForUnmountedComponent = new Set([componentName]);1784 }1785 warningWithoutStack(1786 false,1787 "Can't perform a React state update on an unmounted component. This " +1788 'is a no-op, but it indicates a memory leak in your application. To ' +1789 'fix, cancel all subscriptions and asynchronous tasks in %s.%s',1790 tag === ClassComponent1791 ? 'the componentWillUnmount method'1792 : 'a useEffect cleanup function',1793 getStackByFiberInDevAndProd(fiber),1794 );1795 }1796}1797let beginWork;1798if (__DEV__ && replayFailedUnitOfWorkWithInvokeGuardedCallback) {1799 let dummyFiber = null;1800 beginWork = (current, unitOfWork, expirationTime) => {1801 // If a component throws an error, we replay it again in a synchronously1802 // dispatched event, so that the debugger will treat it as an uncaught1803 // error See ReactErrorUtils for more information.1804 // Before entering the begin phase, copy the work-in-progress onto a dummy1805 // fiber. If beginWork throws, we'll use this to reset the state.1806 const originalWorkInProgressCopy = assignFiberPropertiesInDEV(1807 dummyFiber,1808 unitOfWork,1809 );1810 try {1811 return originalBeginWork(current, unitOfWork, expirationTime);1812 } catch (originalError) {1813 if (1814 originalError !== null &&1815 typeof originalError === 'object' &&1816 typeof originalError.then === 'function'1817 ) {1818 // Don't replay promises. Treat everything else like an error.1819 throw originalError;1820 }1821 // Keep this code in sync with renderRoot; any changes here must have1822 // corresponding changes there.1823 resetContextDependencies();1824 resetHooks();1825 // Unwind the failed stack frame1826 unwindInterruptedWork(unitOfWork);1827 // Restore the original properties of the fiber.1828 assignFiberPropertiesInDEV(unitOfWork, originalWorkInProgressCopy);1829 if (enableProfilerTimer && unitOfWork.mode & ProfileMode) {1830 // Reset the profiler timer.1831 startProfilerTimer(unitOfWork);1832 }1833 // Run beginWork again.1834 invokeGuardedCallback(1835 null,1836 originalBeginWork,1837 null,...
ReactFiberScheduler.new.js
Source:ReactFiberScheduler.new.js
...689 const currentTime = requestCurrentTime();690 if (currentTime < expirationTime) {691 // Restart at the current time.692 workPhase = prevWorkPhase;693 resetContextDependencies();694 ReactCurrentDispatcher.current = prevDispatcher;695 if (enableSchedulerTracing) {696 __interactionsRef.current = ((prevInteractions: any): Set<697 Interaction,698 >);699 }700 return renderRoot.bind(null, root, currentTime);701 }702 }703 } else {704 // Since we know we're in a React event, we can clear the current705 // event time. The next update will compute a new event time.706 currentEventTime = NoWork;707 }708 do {709 try {710 if (isSync) {711 workLoopSync();712 } else {713 workLoop();714 }715 break;716 } catch (thrownValue) {717 // Reset module-level state that was set during the render phase.718 resetContextDependencies();719 resetHooks();720 const sourceFiber = workInProgress;721 if (sourceFiber === null || sourceFiber.return === null) {722 // Expected to be working on a non-root fiber. This is a fatal error723 // because there's no ancestor that can handle it; the root is724 // supposed to capture all errors that weren't caught by an error725 // boundary.726 prepareFreshStack(root, expirationTime);727 workPhase = prevWorkPhase;728 throw thrownValue;729 }730 if (enableProfilerTimer && sourceFiber.mode & ProfileMode) {731 // Record the time spent rendering before an error was thrown. This732 // avoids inaccurate Profiler durations in the case of a733 // suspended render.734 stopProfilerTimerIfRunningAndRecordDelta(sourceFiber, true);735 }736 const returnFiber = sourceFiber.return;737 throwException(738 root,739 returnFiber,740 sourceFiber,741 thrownValue,742 renderExpirationTime,743 );744 workInProgress = completeUnitOfWork(sourceFiber);745 }746 } while (true);747 workPhase = prevWorkPhase;748 resetContextDependencies();749 ReactCurrentDispatcher.current = prevDispatcher;750 if (enableSchedulerTracing) {751 __interactionsRef.current = ((prevInteractions: any): Set<Interaction>);752 }753 if (workInProgress !== null) {754 // There's still work left over. Return a continuation.755 stopInterruptedWorkLoopTimer();756 if (expirationTime !== Sync) {757 startRequestCallbackTimer();758 }759 return renderRoot.bind(null, root, expirationTime);760 }761 }762 // We now have a consistent tree. The next step is either to commit it, or, if763 // something suspended, wait to commit it after a timeout.764 stopFinishedWorkLoopTimer();765 const isLocked = resolveLocksOnRoot(root, expirationTime);766 if (isLocked) {767 // This root has a lock that prevents it from committing. Exit. If we begin768 // work on the root again, without any intervening updates, it will finish769 // without doing additional work.770 return null;771 }772 // Set this to null to indicate there's no in-progress render.773 workInProgressRoot = null;774 switch (workInProgressRootExitStatus) {775 case RootIncomplete: {776 invariant(false, 'Should have a work-in-progress.');777 }778 // Flow knows about invariant, so it compains if I add a break statement,779 // but eslint doesn't know about invariant, so it complains if I do.780 // eslint-disable-next-line no-fallthrough781 case RootErrored: {782 // An error was thrown. First check if there is lower priority work783 // scheduled on this root.784 const lastPendingTime = root.lastPendingTime;785 if (root.lastPendingTime < expirationTime) {786 // There's lower priority work. Before raising the error, try rendering787 // at the lower priority to see if it fixes it. Use a continuation to788 // maintain the existing priority and position in the queue.789 return renderRoot.bind(null, root, lastPendingTime);790 }791 if (!isSync) {792 // If we're rendering asynchronously, it's possible the error was793 // caused by tearing due to a mutation during an event. Try rendering794 // one more time without yiedling to events.795 prepareFreshStack(root, expirationTime);796 scheduleCallback(797 ImmediatePriority,798 renderRoot.bind(null, root, expirationTime),799 );800 return null;801 }802 // If we're already rendering synchronously, commit the root in its803 // errored state.804 return commitRoot.bind(null, root, expirationTime);805 }806 case RootSuspended: {807 const lastPendingTime = root.lastPendingTime;808 if (root.lastPendingTime < expirationTime) {809 // There's lower priority work. It might be unsuspended. Try rendering810 // at that level.811 return renderRoot.bind(null, root, lastPendingTime);812 }813 if (!isSync) {814 const msUntilTimeout = computeMsUntilTimeout(815 root,816 workInProgressRootAbsoluteTimeoutMs,817 );818 if (msUntilTimeout > 0) {819 // The render is suspended, it hasn't timed out, and there's no lower820 // priority work to do. Instead of committing the fallback821 // immediately, wait for more data to arrive.822 root.timeoutHandle = scheduleTimeout(823 commitRoot.bind(null, root, expirationTime),824 msUntilTimeout,825 );826 return null;827 }828 }829 // The work expired. Commit immediately.830 return commitRoot.bind(null, root, expirationTime);831 }832 case RootCompleted: {833 // The work completed. Ready to commit.834 return commitRoot.bind(null, root, expirationTime);835 }836 default: {837 invariant(false, 'Unknown root exit status.');838 }839 }840}841export function renderDidSuspend(842 root: FiberRoot,843 absoluteTimeoutMs: number,844 // TODO: Don't need this argument anymore845 suspendedTime: ExpirationTime,846) {847 if (848 absoluteTimeoutMs >= 0 &&849 workInProgressRootAbsoluteTimeoutMs < absoluteTimeoutMs850 ) {851 workInProgressRootAbsoluteTimeoutMs = absoluteTimeoutMs;852 if (workInProgressRootExitStatus === RootIncomplete) {853 workInProgressRootExitStatus = RootSuspended;854 }855 }856}857export function renderDidError() {858 if (859 workInProgressRootExitStatus === RootIncomplete ||860 workInProgressRootExitStatus === RootSuspended861 ) {862 workInProgressRootExitStatus = RootErrored;863 }864}865function workLoopSync() {866 // Already timed out, so perform work without checking if we need to yield.867 while (workInProgress !== null) {868 workInProgress = performUnitOfWork(workInProgress);869 }870}871function workLoop() {872 // Perform work until Scheduler asks us to yield873 while (workInProgress !== null && !shouldYield()) {874 workInProgress = performUnitOfWork(workInProgress);875 }876}877function performUnitOfWork(unitOfWork: Fiber): Fiber | null {878 // The current, flushed, state of this fiber is the alternate. Ideally879 // nothing should rely on this, but relying on it here means that we don't880 // need an additional field on the work in progress.881 const current = unitOfWork.alternate;882 startWorkTimer(unitOfWork);883 setCurrentDebugFiberInDEV(unitOfWork);884 let next;885 if (enableProfilerTimer && (unitOfWork.mode & ProfileMode) !== NoContext) {886 startProfilerTimer(unitOfWork);887 next = beginWork(current, unitOfWork, renderExpirationTime);888 stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, true);889 } else {890 next = beginWork(current, unitOfWork, renderExpirationTime);891 }892 resetCurrentDebugFiberInDEV();893 unitOfWork.memoizedProps = unitOfWork.pendingProps;894 if (next === null) {895 // If this doesn't spawn new work, complete the current work.896 next = completeUnitOfWork(unitOfWork);897 }898 ReactCurrentOwner.current = null;899 return next;900}901function completeUnitOfWork(unitOfWork: Fiber): Fiber | null {902 // Attempt to complete the current unit of work, then move to the next903 // sibling. If there are no more siblings, return to the parent fiber.904 workInProgress = unitOfWork;905 do {906 // The current, flushed, state of this fiber is the alternate. Ideally907 // nothing should rely on this, but relying on it here means that we don't908 // need an additional field on the work in progress.909 const current = workInProgress.alternate;910 const returnFiber = workInProgress.return;911 // Check if the work completed or if something threw.912 if ((workInProgress.effectTag & Incomplete) === NoEffect) {913 setCurrentDebugFiberInDEV(workInProgress);914 let next;915 if (916 !enableProfilerTimer ||917 (workInProgress.mode & ProfileMode) === NoContext918 ) {919 next = completeWork(current, workInProgress, renderExpirationTime);920 } else {921 startProfilerTimer(workInProgress);922 next = completeWork(current, workInProgress, renderExpirationTime);923 // Update render duration assuming we didn't error.924 stopProfilerTimerIfRunningAndRecordDelta(workInProgress, false);925 }926 stopWorkTimer(workInProgress);927 resetCurrentDebugFiberInDEV();928 resetChildExpirationTime(workInProgress);929 if (next !== null) {930 // Completing this fiber spawned new work. Work on that next.931 return next;932 }933 if (934 returnFiber !== null &&935 // Do not append effects to parents if a sibling failed to complete936 (returnFiber.effectTag & Incomplete) === NoEffect937 ) {938 // Append all the effects of the subtree and this fiber onto the effect939 // list of the parent. The completion order of the children affects the940 // side-effect order.941 if (returnFiber.firstEffect === null) {942 returnFiber.firstEffect = workInProgress.firstEffect;943 }944 if (workInProgress.lastEffect !== null) {945 if (returnFiber.lastEffect !== null) {946 returnFiber.lastEffect.nextEffect = workInProgress.firstEffect;947 }948 returnFiber.lastEffect = workInProgress.lastEffect;949 }950 // If this fiber had side-effects, we append it AFTER the children's951 // side-effects. We can perform certain side-effects earlier if needed,952 // by doing multiple passes over the effect list. We don't want to953 // schedule our own side-effect on our own list because if end up954 // reusing children we'll schedule this effect onto itself since we're955 // at the end.956 const effectTag = workInProgress.effectTag;957 // Skip both NoWork and PerformedWork tags when creating the effect958 // list. PerformedWork effect is read by React DevTools but shouldn't be959 // committed.960 if (effectTag > PerformedWork) {961 if (returnFiber.lastEffect !== null) {962 returnFiber.lastEffect.nextEffect = workInProgress;963 } else {964 returnFiber.firstEffect = workInProgress;965 }966 returnFiber.lastEffect = workInProgress;967 }968 }969 } else {970 // This fiber did not complete because something threw. Pop values off971 // the stack without entering the complete phase. If this is a boundary,972 // capture values if possible.973 const next = unwindWork(workInProgress, renderExpirationTime);974 // Because this fiber did not complete, don't reset its expiration time.975 if (976 enableProfilerTimer &&977 (workInProgress.mode & ProfileMode) !== NoContext978 ) {979 // Record the render duration for the fiber that errored.980 stopProfilerTimerIfRunningAndRecordDelta(workInProgress, false);981 // Include the time spent working on failed children before continuing.982 let actualDuration = workInProgress.actualDuration;983 let child = workInProgress.child;984 while (child !== null) {985 actualDuration += child.actualDuration;986 child = child.sibling;987 }988 workInProgress.actualDuration = actualDuration;989 }990 if (next !== null) {991 // If completing this work spawned new work, do that next. We'll come992 // back here again.993 // Since we're restarting, remove anything that is not a host effect994 // from the effect tag.995 // TODO: The name stopFailedWorkTimer is misleading because Suspense996 // also captures and restarts.997 stopFailedWorkTimer(workInProgress);998 next.effectTag &= HostEffectMask;999 return next;1000 }1001 stopWorkTimer(workInProgress);1002 if (returnFiber !== null) {1003 // Mark the parent fiber as incomplete and clear its effect list.1004 returnFiber.firstEffect = returnFiber.lastEffect = null;1005 returnFiber.effectTag |= Incomplete;1006 }1007 }1008 const siblingFiber = workInProgress.sibling;1009 if (siblingFiber !== null) {1010 // If there is more work to do in this returnFiber, do that next.1011 return siblingFiber;1012 }1013 // Otherwise, return to the parent1014 workInProgress = returnFiber;1015 } while (workInProgress !== null);1016 // We've reached the root.1017 if (workInProgressRootExitStatus === RootIncomplete) {1018 workInProgressRootExitStatus = RootCompleted;1019 }1020 return null;1021}1022function resetChildExpirationTime(completedWork: Fiber) {1023 if (1024 renderExpirationTime !== Never &&1025 completedWork.childExpirationTime === Never1026 ) {1027 // The children of this component are hidden. Don't bubble their1028 // expiration times.1029 return;1030 }1031 let newChildExpirationTime = NoWork;1032 // Bubble up the earliest expiration time.1033 if (enableProfilerTimer && (completedWork.mode & ProfileMode) !== NoContext) {1034 // In profiling mode, resetChildExpirationTime is also used to reset1035 // profiler durations.1036 let actualDuration = completedWork.actualDuration;1037 let treeBaseDuration = completedWork.selfBaseDuration;1038 // When a fiber is cloned, its actualDuration is reset to 0. This value will1039 // only be updated if work is done on the fiber (i.e. it doesn't bailout).1040 // When work is done, it should bubble to the parent's actualDuration. If1041 // the fiber has not been cloned though, (meaning no work was done), then1042 // this value will reflect the amount of time spent working on a previous1043 // render. In that case it should not bubble. We determine whether it was1044 // cloned by comparing the child pointer.1045 const shouldBubbleActualDurations =1046 completedWork.alternate === null ||1047 completedWork.child !== completedWork.alternate.child;1048 let child = completedWork.child;1049 while (child !== null) {1050 const childUpdateExpirationTime = child.expirationTime;1051 const childChildExpirationTime = child.childExpirationTime;1052 if (childUpdateExpirationTime > newChildExpirationTime) {1053 newChildExpirationTime = childUpdateExpirationTime;1054 }1055 if (childChildExpirationTime > newChildExpirationTime) {1056 newChildExpirationTime = childChildExpirationTime;1057 }1058 if (shouldBubbleActualDurations) {1059 actualDuration += child.actualDuration;1060 }1061 treeBaseDuration += child.treeBaseDuration;1062 child = child.sibling;1063 }1064 completedWork.actualDuration = actualDuration;1065 completedWork.treeBaseDuration = treeBaseDuration;1066 } else {1067 let child = completedWork.child;1068 while (child !== null) {1069 const childUpdateExpirationTime = child.expirationTime;1070 const childChildExpirationTime = child.childExpirationTime;1071 if (childUpdateExpirationTime > newChildExpirationTime) {1072 newChildExpirationTime = childUpdateExpirationTime;1073 }1074 if (childChildExpirationTime > newChildExpirationTime) {1075 newChildExpirationTime = childChildExpirationTime;1076 }1077 child = child.sibling;1078 }1079 }1080 completedWork.childExpirationTime = newChildExpirationTime;1081}1082function commitRoot(root, expirationTime) {1083 runWithPriority(1084 ImmediatePriority,1085 commitRootImpl.bind(null, root, expirationTime),1086 );1087 // If there are passive effects, schedule a callback to flush them. This goes1088 // outside commitRootImpl so that it inherits the priority of the render.1089 if (rootWithPendingPassiveEffects !== null) {1090 const priorityLevel = getCurrentPriorityLevel();1091 scheduleCallback(priorityLevel, () => {1092 flushPassiveEffects();1093 return null;1094 });1095 }1096 return null;1097}1098function commitRootImpl(root, expirationTime) {1099 flushPassiveEffects();1100 flushRenderPhaseStrictModeWarningsInDEV();1101 invariant(1102 workPhase !== RenderPhase && workPhase !== CommitPhase,1103 'Should not already be working.',1104 );1105 const finishedWork = root.current.alternate;1106 invariant(finishedWork !== null, 'Should have a work-in-progress root.');1107 // commitRoot never returns a continuation; it always finishes synchronously.1108 // So we can clear these now to allow a new callback to be scheduled.1109 root.callbackNode = null;1110 root.callbackExpirationTime = NoWork;1111 startCommitTimer();1112 // Update the first and last pending times on this root. The new first1113 // pending time is whatever is left on the root fiber.1114 const updateExpirationTimeBeforeCommit = finishedWork.expirationTime;1115 const childExpirationTimeBeforeCommit = finishedWork.childExpirationTime;1116 const firstPendingTimeBeforeCommit =1117 childExpirationTimeBeforeCommit > updateExpirationTimeBeforeCommit1118 ? childExpirationTimeBeforeCommit1119 : updateExpirationTimeBeforeCommit;1120 root.firstPendingTime = firstPendingTimeBeforeCommit;1121 if (firstPendingTimeBeforeCommit < root.lastPendingTime) {1122 // This usually means we've finished all the work, but it can also happen1123 // when something gets downprioritized during render, like a hidden tree.1124 root.lastPendingTime = firstPendingTimeBeforeCommit;1125 }1126 if (root === workInProgressRoot) {1127 // We can reset these now that they are finished.1128 workInProgressRoot = null;1129 workInProgress = null;1130 renderExpirationTime = NoWork;1131 } else {1132 // This indicates that the last root we worked on is not the same one that1133 // we're committing now. This most commonly happens when a suspended root1134 // times out.1135 }1136 // Get the list of effects.1137 let firstEffect;1138 if (finishedWork.effectTag > PerformedWork) {1139 // A fiber's effect list consists only of its children, not itself. So if1140 // the root has an effect, we need to add it to the end of the list. The1141 // resulting list is the set that would belong to the root's parent, if it1142 // had one; that is, all the effects in the tree including the root.1143 if (finishedWork.lastEffect !== null) {1144 finishedWork.lastEffect.nextEffect = finishedWork;1145 firstEffect = finishedWork.firstEffect;1146 } else {1147 firstEffect = finishedWork;1148 }1149 } else {1150 // There is no effect on the root.1151 firstEffect = finishedWork.firstEffect;1152 }1153 if (firstEffect !== null) {1154 const prevWorkPhase = workPhase;1155 workPhase = CommitPhase;1156 let prevInteractions: Set<Interaction> | null = null;1157 if (enableSchedulerTracing) {1158 prevInteractions = __interactionsRef.current;1159 __interactionsRef.current = root.memoizedInteractions;1160 }1161 // Reset this to null before calling lifecycles1162 ReactCurrentOwner.current = null;1163 // The commit phase is broken into several sub-phases. We do a separate pass1164 // of the effect list for each phase: all mutation effects come before all1165 // layout effects, and so on.1166 // The first phase a "before mutation" phase. We use this phase to read the1167 // state of the host tree right before we mutate it. This is where1168 // getSnapshotBeforeUpdate is called.1169 startCommitSnapshotEffectsTimer();1170 prepareForCommit(root.containerInfo);1171 nextEffect = firstEffect;1172 do {1173 if (__DEV__) {1174 invokeGuardedCallback(null, commitBeforeMutationEffects, null);1175 if (hasCaughtError()) {1176 invariant(nextEffect !== null, 'Should be working on an effect.');1177 const error = clearCaughtError();1178 captureCommitPhaseError(nextEffect, error);1179 nextEffect = nextEffect.nextEffect;1180 }1181 } else {1182 try {1183 commitBeforeMutationEffects();1184 } catch (error) {1185 invariant(nextEffect !== null, 'Should be working on an effect.');1186 captureCommitPhaseError(nextEffect, error);1187 nextEffect = nextEffect.nextEffect;1188 }1189 }1190 } while (nextEffect !== null);1191 stopCommitSnapshotEffectsTimer();1192 if (enableProfilerTimer) {1193 // Mark the current commit time to be shared by all Profilers in this1194 // batch. This enables them to be grouped later.1195 recordCommitTime();1196 }1197 // The next phase is the mutation phase, where we mutate the host tree.1198 startCommitHostEffectsTimer();1199 nextEffect = firstEffect;1200 do {1201 if (__DEV__) {1202 invokeGuardedCallback(null, commitMutationEffects, null);1203 if (hasCaughtError()) {1204 invariant(nextEffect !== null, 'Should be working on an effect.');1205 const error = clearCaughtError();1206 captureCommitPhaseError(nextEffect, error);1207 nextEffect = nextEffect.nextEffect;1208 }1209 } else {1210 try {1211 commitMutationEffects();1212 } catch (error) {1213 invariant(nextEffect !== null, 'Should be working on an effect.');1214 captureCommitPhaseError(nextEffect, error);1215 nextEffect = nextEffect.nextEffect;1216 }1217 }1218 } while (nextEffect !== null);1219 stopCommitHostEffectsTimer();1220 resetAfterCommit(root.containerInfo);1221 // The work-in-progress tree is now the current tree. This must come after1222 // the mutation phase, so that the previous tree is still current during1223 // componentWillUnmount, but before the layout phase, so that the finished1224 // work is current during componentDidMount/Update.1225 root.current = finishedWork;1226 // The next phase is the layout phase, where we call effects that read1227 // the host tree after it's been mutated. The idiomatic use case for this is1228 // layout, but class component lifecycles also fire here for legacy reasons.1229 startCommitLifeCyclesTimer();1230 nextEffect = firstEffect;1231 do {1232 if (__DEV__) {1233 invokeGuardedCallback(1234 null,1235 commitLayoutEffects,1236 null,1237 root,1238 expirationTime,1239 );1240 if (hasCaughtError()) {1241 invariant(nextEffect !== null, 'Should be working on an effect.');1242 const error = clearCaughtError();1243 captureCommitPhaseError(nextEffect, error);1244 nextEffect = nextEffect.nextEffect;1245 }1246 } else {1247 try {1248 commitLayoutEffects(root, expirationTime);1249 } catch (error) {1250 invariant(nextEffect !== null, 'Should be working on an effect.');1251 captureCommitPhaseError(nextEffect, error);1252 nextEffect = nextEffect.nextEffect;1253 }1254 }1255 } while (nextEffect !== null);1256 stopCommitLifeCyclesTimer();1257 nextEffect = null;1258 if (enableSchedulerTracing) {1259 __interactionsRef.current = ((prevInteractions: any): Set<Interaction>);1260 }1261 workPhase = prevWorkPhase;1262 } else {1263 // No effects.1264 root.current = finishedWork;1265 // Measure these anyway so the flamegraph explicitly shows that there were1266 // no effects.1267 // TODO: Maybe there's a better way to report this.1268 startCommitSnapshotEffectsTimer();1269 stopCommitSnapshotEffectsTimer();1270 if (enableProfilerTimer) {1271 recordCommitTime();1272 }1273 startCommitHostEffectsTimer();1274 stopCommitHostEffectsTimer();1275 startCommitLifeCyclesTimer();1276 stopCommitLifeCyclesTimer();1277 }1278 stopCommitTimer();1279 if (rootDoesHavePassiveEffects) {1280 // This commit has passive effects. Stash a reference to them. But don't1281 // schedule a callback until after flushing layout work.1282 rootDoesHavePassiveEffects = false;1283 rootWithPendingPassiveEffects = root;1284 pendingPassiveEffectsExpirationTime = expirationTime;1285 } else {1286 if (enableSchedulerTracing) {1287 // If there are no passive effects, then we can complete the pending1288 // interactions. Otherwise, we'll wait until after the passive effects1289 // are flushed.1290 finishPendingInteractions(root, expirationTime);1291 }1292 }1293 // Check if there's remaining work on this root1294 const remainingExpirationTime = root.firstPendingTime;1295 if (remainingExpirationTime !== NoWork) {1296 const currentTime = requestCurrentTime();1297 const priorityLevel = inferPriorityFromExpirationTime(1298 currentTime,1299 remainingExpirationTime,1300 );1301 scheduleCallbackForRoot(root, priorityLevel, remainingExpirationTime);1302 } else {1303 // If there's no remaining work, we can clear the set of already failed1304 // error boundaries.1305 legacyErrorBoundariesThatAlreadyFailed = null;1306 }1307 onCommitRoot(finishedWork.stateNode);1308 if (remainingExpirationTime === Sync) {1309 // Count the number of times the root synchronously re-renders without1310 // finishing. If there are too many, it indicates an infinite update loop.1311 if (root === rootWithNestedUpdates) {1312 nestedUpdateCount++;1313 } else {1314 nestedUpdateCount = 0;1315 rootWithNestedUpdates = root;1316 }1317 } else {1318 nestedUpdateCount = 0;1319 }1320 if (hasUncaughtError) {1321 hasUncaughtError = false;1322 const error = firstUncaughtError;1323 firstUncaughtError = null;1324 throw error;1325 }1326 if (workPhase === LegacyUnbatchedPhase) {1327 // This is a legacy edge case. We just committed the initial mount of1328 // a ReactDOM.render-ed root inside of batchedUpdates. The commit fired1329 // synchronously, but layout updates should be deferred until the end1330 // of the batch.1331 return null;1332 }1333 // If layout work was scheduled, flush it now.1334 flushImmediateQueue();1335 return null;1336}1337function commitBeforeMutationEffects() {1338 while (nextEffect !== null) {1339 if ((nextEffect.effectTag & Snapshot) !== NoEffect) {1340 setCurrentDebugFiberInDEV(nextEffect);1341 recordEffect();1342 const current = nextEffect.alternate;1343 commitBeforeMutationEffectOnFiber(current, nextEffect);1344 resetCurrentDebugFiberInDEV();1345 }1346 nextEffect = nextEffect.nextEffect;1347 }1348}1349function commitMutationEffects() {1350 // TODO: Should probably move the bulk of this function to commitWork.1351 while (nextEffect !== null) {1352 setCurrentDebugFiberInDEV(nextEffect);1353 const effectTag = nextEffect.effectTag;1354 if (effectTag & ContentReset) {1355 commitResetTextContent(nextEffect);1356 }1357 if (effectTag & Ref) {1358 const current = nextEffect.alternate;1359 if (current !== null) {1360 commitDetachRef(current);1361 }1362 }1363 // The following switch statement is only concerned about placement,1364 // updates, and deletions. To avoid needing to add a case for every possible1365 // bitmap value, we remove the secondary effects from the effect tag and1366 // switch on that value.1367 let primaryEffectTag = effectTag & (Placement | Update | Deletion);1368 switch (primaryEffectTag) {1369 case Placement: {1370 commitPlacement(nextEffect);1371 // Clear the "placement" from effect tag so that we know that this is1372 // inserted, before any life-cycles like componentDidMount gets called.1373 // TODO: findDOMNode doesn't rely on this any more but isMounted does1374 // and isMounted is deprecated anyway so we should be able to kill this.1375 nextEffect.effectTag &= ~Placement;1376 break;1377 }1378 case PlacementAndUpdate: {1379 // Placement1380 commitPlacement(nextEffect);1381 // Clear the "placement" from effect tag so that we know that this is1382 // inserted, before any life-cycles like componentDidMount gets called.1383 nextEffect.effectTag &= ~Placement;1384 // Update1385 const current = nextEffect.alternate;1386 commitWork(current, nextEffect);1387 break;1388 }1389 case Update: {1390 const current = nextEffect.alternate;1391 commitWork(current, nextEffect);1392 break;1393 }1394 case Deletion: {1395 commitDeletion(nextEffect);1396 break;1397 }1398 }1399 // TODO: Only record a mutation effect if primaryEffectTag is non-zero.1400 recordEffect();1401 resetCurrentDebugFiberInDEV();1402 nextEffect = nextEffect.nextEffect;1403 }1404}1405function commitLayoutEffects(1406 root: FiberRoot,1407 committedExpirationTime: ExpirationTime,1408) {1409 // TODO: Should probably move the bulk of this function to commitWork.1410 while (nextEffect !== null) {1411 setCurrentDebugFiberInDEV(nextEffect);1412 const effectTag = nextEffect.effectTag;1413 if (effectTag & (Update | Callback)) {1414 recordEffect();1415 const current = nextEffect.alternate;1416 commitLayoutEffectOnFiber(1417 root,1418 current,1419 nextEffect,1420 committedExpirationTime,1421 );1422 }1423 if (effectTag & Ref) {1424 recordEffect();1425 commitAttachRef(nextEffect);1426 }1427 if (effectTag & Passive) {1428 rootDoesHavePassiveEffects = true;1429 }1430 resetCurrentDebugFiberInDEV();1431 nextEffect = nextEffect.nextEffect;1432 }1433}1434export function flushPassiveEffects() {1435 if (rootWithPendingPassiveEffects === null) {1436 return false;1437 }1438 const root = rootWithPendingPassiveEffects;1439 const expirationTime = pendingPassiveEffectsExpirationTime;1440 rootWithPendingPassiveEffects = null;1441 pendingPassiveEffectsExpirationTime = NoWork;1442 let prevInteractions: Set<Interaction> | null = null;1443 if (enableSchedulerTracing) {1444 prevInteractions = __interactionsRef.current;1445 __interactionsRef.current = root.memoizedInteractions;1446 }1447 invariant(1448 workPhase !== RenderPhase && workPhase !== CommitPhase,1449 'Cannot flush passive effects while already rendering.',1450 );1451 const prevWorkPhase = workPhase;1452 workPhase = CommitPhase;1453 // Note: This currently assumes there are no passive effects on the root1454 // fiber, because the root is not part of its own effect list. This could1455 // change in the future.1456 let effect = root.current.firstEffect;1457 while (effect !== null) {1458 if (__DEV__) {1459 setCurrentDebugFiberInDEV(effect);1460 invokeGuardedCallback(null, commitPassiveHookEffects, null, effect);1461 if (hasCaughtError()) {1462 invariant(effect !== null, 'Should be working on an effect.');1463 const error = clearCaughtError();1464 captureCommitPhaseError(effect, error);1465 }1466 resetCurrentDebugFiberInDEV();1467 } else {1468 try {1469 commitPassiveHookEffects(effect);1470 } catch (error) {1471 invariant(effect !== null, 'Should be working on an effect.');1472 captureCommitPhaseError(effect, error);1473 }1474 }1475 effect = effect.nextEffect;1476 }1477 if (enableSchedulerTracing) {1478 __interactionsRef.current = ((prevInteractions: any): Set<Interaction>);1479 finishPendingInteractions(root, expirationTime);1480 }1481 workPhase = prevWorkPhase;1482 flushImmediateQueue();1483 // If additional passive effects were scheduled, increment a counter. If this1484 // exceeds the limit, we'll fire a warning.1485 nestedPassiveUpdateCount =1486 rootWithPendingPassiveEffects === null ? 0 : nestedPassiveUpdateCount + 1;1487 return true;1488}1489export function isAlreadyFailedLegacyErrorBoundary(instance: mixed): boolean {1490 return (1491 legacyErrorBoundariesThatAlreadyFailed !== null &&1492 legacyErrorBoundariesThatAlreadyFailed.has(instance)1493 );1494}1495export function markLegacyErrorBoundaryAsFailed(instance: mixed) {1496 if (legacyErrorBoundariesThatAlreadyFailed === null) {1497 legacyErrorBoundariesThatAlreadyFailed = new Set([instance]);1498 } else {1499 legacyErrorBoundariesThatAlreadyFailed.add(instance);1500 }1501}1502function prepareToThrowUncaughtError(error: mixed) {1503 if (!hasUncaughtError) {1504 hasUncaughtError = true;1505 firstUncaughtError = error;1506 }1507}1508export const onUncaughtError = prepareToThrowUncaughtError;1509function captureCommitPhaseErrorOnRoot(1510 rootFiber: Fiber,1511 sourceFiber: Fiber,1512 error: mixed,1513) {1514 const errorInfo = createCapturedValue(error, sourceFiber);1515 const update = createRootErrorUpdate(rootFiber, errorInfo, Sync);1516 enqueueUpdate(rootFiber, update);1517 const root = markUpdateTimeFromFiberToRoot(rootFiber, Sync);1518 if (root !== null) {1519 scheduleCallbackForRoot(root, ImmediatePriority, Sync);1520 }1521}1522export function captureCommitPhaseError(sourceFiber: Fiber, error: mixed) {1523 if (sourceFiber.tag === HostRoot) {1524 // Error was thrown at the root. There is no parent, so the root1525 // itself should capture it.1526 captureCommitPhaseErrorOnRoot(sourceFiber, sourceFiber, error);1527 return;1528 }1529 let fiber = sourceFiber.return;1530 while (fiber !== null) {1531 if (fiber.tag === HostRoot) {1532 captureCommitPhaseErrorOnRoot(fiber, sourceFiber, error);1533 return;1534 } else if (fiber.tag === ClassComponent) {1535 const ctor = fiber.type;1536 const instance = fiber.stateNode;1537 if (1538 typeof ctor.getDerivedStateFromError === 'function' ||1539 (typeof instance.componentDidCatch === 'function' &&1540 !isAlreadyFailedLegacyErrorBoundary(instance))1541 ) {1542 const errorInfo = createCapturedValue(error, sourceFiber);1543 const update = createClassErrorUpdate(1544 fiber,1545 errorInfo,1546 // TODO: This is always sync1547 Sync,1548 );1549 enqueueUpdate(fiber, update);1550 const root = markUpdateTimeFromFiberToRoot(fiber, Sync);1551 if (root !== null) {1552 scheduleCallbackForRoot(root, ImmediatePriority, Sync);1553 }1554 return;1555 }1556 }1557 fiber = fiber.return;1558 }1559}1560export function pingSuspendedRoot(1561 root: FiberRoot,1562 thenable: Thenable,1563 suspendedTime: ExpirationTime,1564) {1565 const pingCache = root.pingCache;1566 if (pingCache !== null) {1567 // The thenable resolved, so we no longer need to memoize, because it will1568 // never be thrown again.1569 pingCache.delete(thenable);1570 }1571 if (workInProgressRoot === root && renderExpirationTime === suspendedTime) {1572 // Received a ping at the same priority level at which we're currently1573 // rendering. Restart from the root. Don't need to schedule a ping because1574 // we're already working on this tree.1575 prepareFreshStack(root, renderExpirationTime);1576 return;1577 }1578 const lastPendingTime = root.lastPendingTime;1579 if (lastPendingTime < suspendedTime) {1580 // The root is no longer suspended at this time.1581 return;1582 }1583 const pingTime = root.pingTime;1584 if (pingTime !== NoWork && pingTime < suspendedTime) {1585 // There's already a lower priority ping scheduled.1586 return;1587 }1588 // Mark the time at which this ping was scheduled.1589 root.pingTime = suspendedTime;1590 const currentTime = requestCurrentTime();1591 const priorityLevel = inferPriorityFromExpirationTime(1592 currentTime,1593 suspendedTime,1594 );1595 scheduleCallbackForRoot(root, priorityLevel, suspendedTime);1596}1597export function retryTimedOutBoundary(boundaryFiber: Fiber) {1598 // The boundary fiber (a Suspense component) previously timed out and was1599 // rendered in its fallback state. One of the promises that suspended it has1600 // resolved, which means at least part of the tree was likely unblocked. Try1601 // rendering again, at a new expiration time.1602 const currentTime = requestCurrentTime();1603 const retryTime = computeExpirationForFiber(currentTime, boundaryFiber);1604 // TODO: Special case idle priority?1605 const priorityLevel = inferPriorityFromExpirationTime(currentTime, retryTime);1606 const root = markUpdateTimeFromFiberToRoot(boundaryFiber, retryTime);1607 if (root !== null) {1608 scheduleCallbackForRoot(root, priorityLevel, retryTime);1609 }1610}1611export function resolveRetryThenable(boundaryFiber: Fiber, thenable: Thenable) {1612 let retryCache: WeakSet<Thenable> | Set<Thenable> | null;1613 if (enableSuspenseServerRenderer) {1614 switch (boundaryFiber.tag) {1615 case SuspenseComponent:1616 retryCache = boundaryFiber.stateNode;1617 break;1618 case DehydratedSuspenseComponent:1619 retryCache = boundaryFiber.memoizedState;1620 break;1621 default:1622 invariant(1623 false,1624 'Pinged unknown suspense boundary type. ' +1625 'This is probably a bug in React.',1626 );1627 }1628 } else {1629 retryCache = boundaryFiber.stateNode;1630 }1631 if (retryCache !== null) {1632 // The thenable resolved, so we no longer need to memoize, because it will1633 // never be thrown again.1634 retryCache.delete(thenable);1635 }1636 retryTimedOutBoundary(boundaryFiber);1637}1638export function inferStartTimeFromExpirationTime(1639 root: FiberRoot,1640 expirationTime: ExpirationTime,1641) {1642 // We don't know exactly when the update was scheduled, but we can infer an1643 // approximate start time from the expiration time.1644 const earliestExpirationTimeMs = expirationTimeToMs(root.firstPendingTime);1645 // TODO: Track this on the root instead. It's more accurate, doesn't rely on1646 // assumptions about priority, and isn't coupled to Scheduler details.1647 return earliestExpirationTimeMs - LOW_PRIORITY_EXPIRATION;1648}1649function computeMsUntilTimeout(root, absoluteTimeoutMs) {1650 if (disableYielding) {1651 // Timeout immediately when yielding is disabled.1652 return 0;1653 }1654 // Find the earliest uncommitted expiration time in the tree, including1655 // work that is suspended. The timeout threshold cannot be longer than1656 // the overall expiration.1657 const earliestExpirationTimeMs = expirationTimeToMs(root.firstPendingTime);1658 if (earliestExpirationTimeMs < absoluteTimeoutMs) {1659 absoluteTimeoutMs = earliestExpirationTimeMs;1660 }1661 // Subtract the current time from the absolute timeout to get the number1662 // of milliseconds until the timeout. In other words, convert an absolute1663 // timestamp to a relative time. This is the value that is passed1664 // to `setTimeout`.1665 let msUntilTimeout = absoluteTimeoutMs - now();1666 return msUntilTimeout < 0 ? 0 : msUntilTimeout;1667}1668function checkForNestedUpdates() {1669 if (nestedUpdateCount > NESTED_UPDATE_LIMIT) {1670 nestedUpdateCount = 0;1671 rootWithNestedUpdates = null;1672 invariant(1673 false,1674 'Maximum update depth exceeded. This can happen when a component ' +1675 'repeatedly calls setState inside componentWillUpdate or ' +1676 'componentDidUpdate. React limits the number of nested updates to ' +1677 'prevent infinite loops.',1678 );1679 }1680 if (__DEV__) {1681 if (nestedPassiveUpdateCount > NESTED_PASSIVE_UPDATE_LIMIT) {1682 nestedPassiveUpdateCount = 0;1683 warning(1684 false,1685 'Maximum update depth exceeded. This can happen when a component ' +1686 "calls setState inside useEffect, but useEffect either doesn't " +1687 'have a dependency array, or one of the dependencies changes on ' +1688 'every render.',1689 );1690 }1691 }1692}1693function flushRenderPhaseStrictModeWarningsInDEV() {1694 if (__DEV__) {1695 ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings();1696 ReactStrictModeWarnings.flushLegacyContextWarning();1697 if (warnAboutDeprecatedLifecycles) {1698 ReactStrictModeWarnings.flushPendingDeprecationWarnings();1699 }1700 }1701}1702function stopFinishedWorkLoopTimer() {1703 const didCompleteRoot = true;1704 stopWorkLoopTimer(interruptedBy, didCompleteRoot);1705 interruptedBy = null;1706}1707function stopInterruptedWorkLoopTimer() {1708 // TODO: Track which fiber caused the interruption.1709 const didCompleteRoot = false;1710 stopWorkLoopTimer(interruptedBy, didCompleteRoot);1711 interruptedBy = null;1712}1713function checkForInterruption(1714 fiberThatReceivedUpdate: Fiber,1715 updateExpirationTime: ExpirationTime,1716) {1717 if (1718 enableUserTimingAPI &&1719 workInProgressRoot !== null &&1720 updateExpirationTime > renderExpirationTime1721 ) {1722 interruptedBy = fiberThatReceivedUpdate;1723 }1724}1725let didWarnStateUpdateForUnmountedComponent: Set<string> | null = null;1726function warnAboutUpdateOnUnmountedFiberInDEV(fiber) {1727 if (__DEV__) {1728 const tag = fiber.tag;1729 if (1730 tag !== HostRoot &&1731 tag !== ClassComponent &&1732 tag !== FunctionComponent &&1733 tag !== ForwardRef &&1734 tag !== MemoComponent &&1735 tag !== SimpleMemoComponent1736 ) {1737 // Only warn for user-defined components, not internal ones like Suspense.1738 return;1739 }1740 // We show the whole stack but dedupe on the top component's name because1741 // the problematic code almost always lies inside that component.1742 const componentName = getComponentName(fiber.type) || 'ReactComponent';1743 if (didWarnStateUpdateForUnmountedComponent !== null) {1744 if (didWarnStateUpdateForUnmountedComponent.has(componentName)) {1745 return;1746 }1747 didWarnStateUpdateForUnmountedComponent.add(componentName);1748 } else {1749 didWarnStateUpdateForUnmountedComponent = new Set([componentName]);1750 }1751 warningWithoutStack(1752 false,1753 "Can't perform a React state update on an unmounted component. This " +1754 'is a no-op, but it indicates a memory leak in your application. To ' +1755 'fix, cancel all subscriptions and asynchronous tasks in %s.%s',1756 tag === ClassComponent1757 ? 'the componentWillUnmount method'1758 : 'a useEffect cleanup function',1759 getStackByFiberInDevAndProd(fiber),1760 );1761 }1762}1763let beginWork;1764if (__DEV__ && replayFailedUnitOfWorkWithInvokeGuardedCallback) {1765 let dummyFiber = null;1766 beginWork = (current, unitOfWork, expirationTime) => {1767 // If a component throws an error, we replay it again in a synchronously1768 // dispatched event, so that the debugger will treat it as an uncaught1769 // error See ReactErrorUtils for more information.1770 // Before entering the begin phase, copy the work-in-progress onto a dummy1771 // fiber. If beginWork throws, we'll use this to reset the state.1772 const originalWorkInProgressCopy = assignFiberPropertiesInDEV(1773 dummyFiber,1774 unitOfWork,1775 );1776 try {1777 return originalBeginWork(current, unitOfWork, expirationTime);1778 } catch (originalError) {1779 if (1780 originalError !== null &&1781 typeof originalError === 'object' &&1782 typeof originalError.then === 'function'1783 ) {1784 // Don't replay promises. Treat everything else like an error.1785 throw originalError;1786 }1787 // Keep this code in sync with renderRoot; any changes here must have1788 // corresponding changes there.1789 resetContextDependencies();1790 resetHooks();1791 // Unwind the failed stack frame1792 unwindInterruptedWork(unitOfWork);1793 // Restore the original properties of the fiber.1794 assignFiberPropertiesInDEV(unitOfWork, originalWorkInProgressCopy);1795 if (enableProfilerTimer && unitOfWork.mode & ProfileMode) {1796 // Reset the profiler timer.1797 startProfilerTimer(unitOfWork);1798 }1799 // Run beginWork again.1800 invokeGuardedCallback(1801 null,1802 originalBeginWork,1803 null,...
ReactFiberWorkLoop.js
Source:ReactFiberWorkLoop.js
...619 } catch (thrownValue) {620 // handleError(root, thrownValue);621 }622 } while (true);623 resetContextDependencies();624 executionContext = prevExecutionContext;625 popDispatcher(prevDispatcher);626 if (workInProgress !== null) {627 invariant(628 false,629 'Cannot commit an incomplete root. This error is likely caused by a ' +630 'bug in React. Please file an issue.'631 );632 }633 workInProgressRoot = null;634 workInProgressRootRenderLanes = NoLanes;635 return workInProgressRootExitStatus;636};637const ensureRootIsScheduled = (root, currentTime) => {...
ReactFiberNewContext.new.js
Source:ReactFiberNewContext.new.js
...40let currentlyRenderingFiber: Fiber | null = null;41let lastContextDependency: ContextDependency<mixed> | null = null;42let lastContextWithAllBitsObserved: ReactContext<any> | null = null;43let isDisallowedContextReadInDEV: boolean = false;44export function resetContextDependencies(): void {45 // This is called right before React yields execution, to ensure `readContext`46 // cannot be called outside the render phase.47 currentlyRenderingFiber = null;48 lastContextDependency = null;49 lastContextWithAllBitsObserved = null;50 if (__DEV__) {51 isDisallowedContextReadInDEV = false;52 }53}54export function enterDisallowedContextReadInDEV(): void {55 if (__DEV__) {56 isDisallowedContextReadInDEV = true;57 }58}...
ReactFiberNewContext.old.js
Source:ReactFiberNewContext.old.js
...7 var currentlyRenderingFiber = null;8 var lastContextDependency = null;9 var lastContextWithAllBitsObserved = null;10 var isDisallowedContextReadInDEV = false;11 function resetContextDependencies() {12 // This is called right before React yields execution, to ensure `readContext`13 // cannot be called outside the render phase.14 currentlyRenderingFiber = null;15 lastContextDependency = null;16 lastContextWithAllBitsObserved = null;17 {18 isDisallowedContextReadInDEV = false;19 }20 }21 function enterDisallowedContextReadInDEV() {22 {23 isDisallowedContextReadInDEV = true;24 }25 }...
ReactFiberNewContext.js
Source:ReactFiberNewContext.js
1import { includesSomeLane, NoLanes } from './ReactFiberLane';2import { markWorkInProgressReceivedUpdate } from './ReactFiberBeginWork';3const invariant = require('invariant');4const MAX_SIGNED_31_BIT_INT = 1073741823;5let currentlyRenderingFiber = null;6let lastContextDependency = null;7let lastContextWithAllBitsObserved = null;8const resetContextDependencies = () => {9 currentlyRenderingFiber = null;10 lastContextDependency = null;11 lastContextWithAllBitsObserved = null;12};13const prepareToReadContext = (workInProgress, renderLanes) => {14 currentlyRenderingFiber = workInProgress;15 lastContextDependency = null;16 lastContextWithAllBitsObserved = null;17 const dependencies = workInProgress.dependencies;18 if (dependencies !== null) {19 const firstContext = dependencies.firstContext;20 if (firstContext !== null) {21 if (includesSomeLane(dependencies.lanes, renderLanes)) {22 markWorkInProgressReceivedUpdate();23 }24 dependencies.firstContext = null;25 }26 }27};28const readContext = (context, observedBits) => {29 if (lastContextWithAllBitsObserved === context) {30 // Nothing to do. We already observe everything in this context.31 } else if (observedBits === false || observedBits === 0) {32 // Do not observe any updates.33 } else {34 let resolvedObservedBits;35 if (36 typeof observedBits !== 'number' ||37 observedBits === MAX_SIGNED_31_BIT_INT38 ) {39 lastContextWithAllBitsObserved = context;40 resolvedObservedBits = MAX_SIGNED_31_BIT_INT;41 } else {42 resolvedObservedBits = observedBits;43 }44 const contextItem = {45 context: context,46 observedBits: resolvedObservedBits,47 next: null,48 };49 if (lastContextDependency === null) {50 invariant(51 currentlyRenderingFiber !== null,52 'Context can only be read while React is rendering. ' +53 'In classes, you can read it in the render method or getDerivedStateFromProps. ' +54 'In function components, you can read it directly in the function body, but not ' +55 'inside Hooks like useReducer() or useMemo().'56 );57 lastContextDependency = contextItem;58 currentlyRenderingFiber.dependencies = {59 lanes: NoLanes,60 firstContext: contextItem,61 responders: null,62 };63 } else {64 lastContextDependency = lastContextDependency.next = contextItem;65 }66 }67 return context._currentValue;68};...
Using AI Code Generation
1const { resetContextDependencies } = require('playwright/lib/server/browserContext');2const { chromium } = require('playwright');3(async () => {4 const browser = await chromium.launch();5 const context = await browser.newContext();6 await resetContextDependencies(context);7 await context.close();8 await browser.close();9})();10const { chromium } = require('playwright');11(async () => {12 const browser = await chromium.launch();13 const context = await browser.newContext();14 await context.close();15 await browser.close();16})();17 at Object.throwProtocolError (/Users/kritikaparmar/Desktop/playwright-test/node_modules/playwright/lib/server/cjs/transport.js:285:15)18 at CDPSession.dispatch (/Users/kritikaparmar/Desktop/playwright-test/node_modules/playwright/lib/server/cjs/transport.js:181:23)19 at CDPSession._onMessage (/Users/kritikaparmar/Desktop/playwright-test/node_modules/playwright/lib/server/cjs/transport.js:132:16)20 at WebSocketTransport._ws.addEventListener (/Users/kritikaparmar/Desktop/playwright-test/node_modules/playwright/lib/server/cjs/transport.js:42:24)21 at WebSocket.onMessage (/Users/kritikaparmar/Desktop/playwright-test/node_modules/ws/lib/event-target.js:132:16)22 at WebSocket.emit (events.js:315:20)23 at Receiver.receiverOnMessage (/Users/kritikaparmar/Desktop/playwright-test/node_modules/ws/lib/websocket.js:800:20)24 at Receiver.emit (events.js:315:20)25 at Receiver.dataMessage (/Users/kritikaparmar/Desktop/playwright-test/node_modules/ws/lib/receiver.js:437:14)26 at Receiver.getData (/Users/kritikaparmar/Desktop/playwright-test/node_modules/ws/lib/receiver.js:367:17)
Using AI Code Generation
1const { resetContextDependencies } = require('playwright/lib/server/browserContext');2const { chromium } = require('playwright');3(async () => {4 const browser = await chromium.launch();5 const context = await browser.newContext();6 await resetContextDependencies(context);7 await context.close();8 await browser.close();9})();10const { chromium } = require('playwright');11const { resetContextDependencies } = require('playwright/lib/server/browserContext');12describe('My test', () => {13 let browser;14 let context;15 beforeEach(async () => {16 browser = await chromium.launch();17 context = await browser.newContext();18 });19 afterEach(async () => {20 await resetContextDependencies(context);21 await context.close();22 await browser.close();23 });24 it('should work', async () => {25 const page = await context.newPage();26 await page.screenshot({ path: 'playwright.png' });27 });28});
Using AI Code Generation
1const { resetContextDependencies } = require('playwright/lib/server/browserContext');2const { chromium } = require('playwright');3(async () => {4 const browser = await chromium.launch({ headless: false });5 const context = await browser.newContext();6 await resetContextDependencies(context);7 await browser.close();8})();9const { resetContextDependencies } = require('playwright/lib/server/browserContext');10const { chromium } = require('playwright');11(async () => {12 const browser = await chromium.launch({ headless: false });13 const context = await browser.newContext();14 await resetContextDependencies(context);15 await browser.close();16})();17const { resetContextDependencies } = require('playwright/lib/server/browserContext');18const { chromium } = require('playwright');19(async () => {20 const browser = await chromium.launch({ headless: false });21 const context = await browser.newContext();22 await resetContextDependencies(context);23 await browser.close();24})();25const { resetContextDependencies } = require('playwright/lib/server/browserContext');26const { chromium } = require('playwright');27(async () => {28 const browser = await chromium.launch({ headless: false });29 const context = await browser.newContext();30 await resetContextDependencies(context);31 await browser.close();32})();33const { resetContextDependencies } = require('playwright/lib/server/browserContext');34const { chromium } = require('playwright');35(async () => {36 const browser = await chromium.launch({ headless: false });37 const context = await browser.newContext();38 await resetContextDependencies(context);39 await browser.close();40})();41const { resetContextDependencies } = require('playwright/lib/server/browserContext');42const { chromium } = require('playwright');43(async () => {44 const browser = await chromium.launch({ headless: false });45 const context = await browser.newContext();46 await resetContextDependencies(context);47 await browser.close();48})();
Using AI Code Generation
1const { resetContextDependencies } = require('playwright-core/lib/server/browserContext');2resetContextDependencies();3const { resetBrowserDependencies } = require('playwright-core/lib/server/browser');4resetBrowserDependencies();5const { resetBrowserTypeDependencies } = require('playwright-core/lib/server/browserType');6resetBrowserTypeDependencies();7const { resetServerDependencies } = require('playwright-core/lib/server/server');8resetServerDependencies();9const { resetTestState } = require('playwright-core/lib/test/test');10resetTestState();11const { resetTestTypeDependencies } = require('playwright-core/lib/test/testType');12resetTestTypeDependencies();13const { resetTraceModel } = require('playwright-core/lib/trace/traceModel');14resetTraceModel();15const { resetTracePlayer } = require('playwright-core/lib/trace/tracePlayer');16resetTracePlayer();17const { resetTraceRecorder } = require('playwright-core/lib/trace/traceRecorder');18resetTraceRecorder();19const { resetTransport } = require('playwright-core/lib/transport/transport');20resetTransport();21const { resetWebSocketTransport } = require('playwright-core/lib/transport/webSocketTransport');22resetWebSocketTransport();23const { resetBrowserServer } = require('playwright-core/lib/server/browserServer');24resetBrowserServer();25const { resetBrowserContext } = require('playwright-core/lib/server/browserContext');26resetBrowserContext();27const { resetBrowserType } = require('playwright-core/lib/server/browserType');28resetBrowserType();
Using AI Code Generation
1const { resetContextDependencies } = require("playwright/lib/server/chromium/crBrowser");2resetContextDependencies();3const { resetContextDependencies } = require("playwright/lib/server/firefox/ffBrowser");4resetContextDependencies();5const { resetContextDependencies } = require("playwright/lib/server/webkit/wkBrowser");6resetContextDependencies();7const { resetContextDependencies } = require("playwright/lib/server/chromium/crBrowser");8resetContextDependencies();9const { resetContextDependencies } = require("playwright/lib/server/firefox/ffBrowser");10resetContextDependencies();11const { resetContextDependencies } = require("playwright/lib/server/webkit/wkBrowser");12resetContextDependencies();13const { resetContextDependencies } = require("playwright/lib/server/chromium/crBrowser");14resetContextDependencies();15const { resetContextDependencies } = require("playwright/lib/server/firefox/ffBrowser");16resetContextDependencies();17const { resetContextDependencies } = require("playwright/lib/server/webkit/wkBrowser");18resetContextDependencies();19const { resetContextDependencies } = require("playwright/lib/server/chromium/crBrowser");20resetContextDependencies();21const { resetContextDependencies } = require("playwright/lib/server/firefox/ffBrowser");22resetContextDependencies();23const { resetContextDependencies } = require("playwright/lib/server/webkit/wkBrowser");24resetContextDependencies();25const { resetContextDependencies } = require("playwright/lib/server/chromium/crBrowser");26resetContextDependencies();27const { resetContextDependencies } = require("playwright/lib/server/firefox/
Using AI Code Generation
1const playwright = require('playwright');2(async () => {3 const browser = await playwright.chromium.launch();4 await browser._defaultContext.resetContextDependencies();5 await browser.close();6})();7const playwright = require('playwright');8(async () => {9 const browser = await playwright.chromium.launch();10 await browser._defaultContext.resetContextDependencies();11 await browser.close();12})();13const playwright = require('playwright');14(async () => {15 const browser = await playwright.chromium.launch();16 await browser._defaultContext.resetContextDependencies();17 await browser.close();18})();19const playwright = require('playwright');20(async () => {21 const browser = await playwright.chromium.launch();22 await browser._defaultContext.resetContextDependencies();23 await browser.close();24})();25const playwright = require('playwright');26(async () => {27 const browser = await playwright.chromium.launch();28 await browser._defaultContext.resetContextDependencies();29 await browser.close();30})();31const playwright = require('playwright');32(async () => {33 const browser = await playwright.chromium.launch();34 await browser._defaultContext.resetContextDependencies();35 await browser.close();36})();37const playwright = require('playwright');38(async () => {39 const browser = await playwright.chromium.launch();40 await browser._defaultContext.resetContextDependencies();41 await browser.close();42})();43const playwright = require('playwright');44(async () => {45 const browser = await playwright.chromium.launch();46 await browser._defaultContext.resetContextDependencies();47 await browser.close();48})();49const playwright = require('playwright');50(async () => {51 const browser = await playwright.chromium.launch();52 await browser._defaultContext.resetContextDependencies();53 await browser.close();54})();55const playwright = require('
Using AI Code Generation
1const { resetContextDependencies } = require('playwright/lib/server/browserContext');2const { chromium } = require('playwright');3const context = await chromium.launchPersistentContext('./data');4await resetContextDependencies(context);5await context.close();6await context.clearCookies();7await context.clearPermissions();8await context.clearStorageData();9await context.tracing.start({ screenshots: true, snapshots: true });10await context.tracing.stop({ path: 'trace.zip' });11await context.tracing.startChunk();12await context.tracing.stopChunk({ path: 'trace.zip' });13await context.addCookies([{14}]);15const cookies = await context.cookies();16console.log(cookies);17await context.grantPermissions(['geolocation']);18const permissions = await context.permissions();19console.log(permissions);20await context.setGeolocation({ latitude: 59.95, longitude: 30.31667 });21await context.setExtraHTTPHeaders({ foo: 'bar' });22await context.setOffline(true);23await context.setHTTPCredentials({ username: 'user', password: 'pass' });24await context.addInitScript({ path: 'inject.js' });25await context.addInitScript({ content: 'window.injected = 123;' });26await context.exposeBinding('compute', (source, ...args) => {27 return args.reduce((a, b) => a * b, 1);28});29await context.exposeFunction('compute', (...args) => {30 return args.reduce((a, b) => a * b, 1);31});32await context.route('**/*', route => route.continue());33await context.unroute('**/*');34await context.waitForEvent('page');35const page = await context.newPage();36await context.close();37await context.clearCookies();38await context.clearPermissions();39await context.clearStorageData();40await context.tracing.start({ screenshots: true, snapshots: true });41await context.tracing.stop({ path: 'trace.zip' });42await context.tracing.startChunk();43await context.tracing.stopChunk({ path: 'trace.zip' });44await context.addCookies([{
Using AI Code Generation
1const { resetContextDependencies } = require("@playwright/test/lib/server/trace/recorder/dependencies");2resetContextDependencies();3const { resetContextDependencies } = require("@playwright/test/lib/server/trace/recorder/dependencies");4resetContextDependencies();5const { resetContextDependencies } = require("@playwright/test/lib/server/trace/recorder/dependencies");6resetContextDependencies();7const { resetContextDependencies } = require("@playwright/test/lib/server/trace/recorder/dependencies");8resetContextDependencies();9const { resetContextDependencies } = require("@playwright/test/lib/server/trace/recorder/dependencies");10resetContextDependencies();11const { resetContextDependencies } = require("@playwright/test/lib/server/trace/recorder/dependencies");12resetContextDependencies();13const { resetContextDependencies } = require("@playwright/test/lib/server/trace/recorder/dependencies");14resetContextDependencies();15const { resetContextDependencies } = require("@playwright/test/lib/server/trace/recorder/dependencies");16resetContextDependencies();17const { resetContextDependencies } = require("@playwright/test/lib/server/trace/recorder/dependencies");18resetContextDependencies();19const { resetContextDependencies } = require("@playwright/test/lib/server/trace/recorder/dependencies");20resetContextDependencies();21const { resetContextDependencies } = require("@playwright/test/lib/server/trace/recorder/dependencies");22resetContextDependencies();23const { resetContextDependencies } = require("@playwright/test/lib/server/trace/recorder/dependencies");24resetContextDependencies();
LambdaTest’s Playwright tutorial will give you a broader idea about the Playwright automation framework, its unique features, and use cases with examples to exceed your understanding of Playwright testing. This tutorial will give A to Z guidance, from installing the Playwright framework to some best practices and advanced concepts.
Get 100 minutes of automation test minutes FREE!!