How to use inferTimeFromExpirationTime method in Playwright Internal

Best JavaScript code snippet using playwright-internal

ReactFiberWorkLoop.js

Source:ReactFiberWorkLoop.js Github

copy

Full Screen

...1041 if (workInProgressRootExitStatus !== RootCompleted) {1042 workInProgressRootExitStatus = RootErrored;1043 }1044}1045function inferTimeFromExpirationTime(1046 expirationTime: ExpirationTime,1047 suspenseConfig: null | SuspenseConfig,1048): number {1049 // We don't know exactly when the update was scheduled, but we can infer an1050 // approximate start time from the expiration time.1051 const earliestExpirationTimeMs = expirationTimeToMs(expirationTime);1052 return (1053 earliestExpirationTimeMs -1054 (suspenseConfig !== null1055 ? suspenseConfig.timeoutMs | 0 || LOW_PRIORITY_EXPIRATION1056 : LOW_PRIORITY_EXPIRATION)1057 );1058}1059function workLoopSync() {1060 // Already timed out, so perform work without checking if we need to yield.1061 // 已经超时了,所以执行工作时不要检查是否需要让步。1062 while (workInProgress !== null) {1063 workInProgress = performUnitOfWork(workInProgress);1064 }1065}1066function workLoop() {1067 // Perform work until Scheduler asks us to yield1068 // 执行工作,直到调度器要求我们让步1069 while (workInProgress !== null && !shouldYield()) {1070 workInProgress = performUnitOfWork(workInProgress);1071 }1072}1073function performUnitOfWork(unitOfWork: Fiber): Fiber | null {1074 // The current, flushed, state of this fiber is the alternate. Ideally1075 // nothing should rely on this, but relying on it here means that we don't1076 // need an additional field on the work in progress.1077 // 该 fiber 的当前冲刷状态是交替的。1078 // 理想情况下不应该依赖于此,但是依赖于此意味着我们不需要对正在进行的工作进行额外的研究。1079 const current = unitOfWork.alternate;1080 startWorkTimer(unitOfWork);1081 setCurrentDebugFiberInDEV(unitOfWork);1082 let next;1083 if (enableProfilerTimer && (unitOfWork.mode & ProfileMode) !== NoMode) {1084 startProfilerTimer(unitOfWork);1085 next = beginWork(current, unitOfWork, renderExpirationTime);1086 stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, true);1087 } else {1088 next = beginWork(current, unitOfWork, renderExpirationTime);1089 }1090 resetCurrentDebugFiberInDEV();1091 unitOfWork.memoizedProps = unitOfWork.pendingProps;1092 if (next === null) {1093 // If this doesn't spawn new work, complete the current work.1094 // 如果这没有产生新的工作,完成当前的工作。1095 next = completeUnitOfWork(unitOfWork);1096 }1097 ReactCurrentOwner.current = null;1098 return next;1099}1100function completeUnitOfWork(unitOfWork: Fiber): Fiber | null {1101 // Attempt to complete the current unit of work, then move to the next1102 // sibling. If there are no more siblings, return to the parent fiber.1103 // 尝试完成当前的工作单元,然后移动到下一个同级。1104 // 如果没有兄弟节点,就回到 parent fiber。1105 workInProgress = unitOfWork;1106 do {1107 // The current, flushed, state of this fiber is the alternate. Ideally1108 // nothing should rely on this, but relying on it here means that we don't1109 // need an additional field on the work in progress.1110 // 该 fiber 的当前冲刷状态是交替的。1111 // 理想情况下不应该依赖于此,但是依赖于此意味着我们不需要对正在进行的工作进行额外的研究。1112 const current = workInProgress.alternate;1113 const returnFiber = workInProgress.return;1114 // Check if the work completed or if something threw.1115 // 检查工作是否完成或是否有东西抛出。1116 if ((workInProgress.effectTag & Incomplete) === NoEffect) {1117 setCurrentDebugFiberInDEV(workInProgress);1118 let next;1119 if (1120 !enableProfilerTimer ||1121 (workInProgress.mode & ProfileMode) === NoMode1122 ) {1123 next = completeWork(current, workInProgress, renderExpirationTime);1124 } else {1125 startProfilerTimer(workInProgress);1126 next = completeWork(current, workInProgress, renderExpirationTime);1127 // Update render duration assuming we didn't error.1128 stopProfilerTimerIfRunningAndRecordDelta(workInProgress, false);1129 }1130 stopWorkTimer(workInProgress);1131 resetCurrentDebugFiberInDEV();1132 resetChildExpirationTime(workInProgress);1133 if (next !== null) {1134 // Completing this fiber spawned new work. Work on that next.1135 // 完成这个 fiber 产生了新的工作。下一个工作。1136 return next;1137 }1138 if (1139 returnFiber !== null &&1140 // Do not append effects to parents if a sibling failed to complete1141 (returnFiber.effectTag & Incomplete) === NoEffect1142 ) {1143 // Append all the effects of the subtree and this fiber onto the effect1144 // list of the parent. The completion order of the children affects the1145 // side-effect order.1146 if (returnFiber.firstEffect === null) {1147 returnFiber.firstEffect = workInProgress.firstEffect;1148 }1149 if (workInProgress.lastEffect !== null) {1150 if (returnFiber.lastEffect !== null) {1151 returnFiber.lastEffect.nextEffect = workInProgress.firstEffect;1152 }1153 returnFiber.lastEffect = workInProgress.lastEffect;1154 }1155 // If this fiber had side-effects, we append it AFTER the children's1156 // side-effects. We can perform certain side-effects earlier if needed,1157 // by doing multiple passes over the effect list. We don't want to1158 // schedule our own side-effect on our own list because if end up1159 // reusing children we'll schedule this effect onto itself since we're1160 // at the end.1161 const effectTag = workInProgress.effectTag;1162 // Skip both NoWork and PerformedWork tags when creating the effect1163 // list. PerformedWork effect is read by React DevTools but shouldn't be1164 // committed.1165 if (effectTag > PerformedWork) {1166 if (returnFiber.lastEffect !== null) {1167 returnFiber.lastEffect.nextEffect = workInProgress;1168 } else {1169 returnFiber.firstEffect = workInProgress;1170 }1171 returnFiber.lastEffect = workInProgress;1172 }1173 }1174 } else {1175 // This fiber did not complete because something threw. Pop values off1176 // the stack without entering the complete phase. If this is a boundary,1177 // capture values if possible.1178 // 这个 fiber 没有完成是因为有东西抛出了。1179 // 在不进入完整阶段的情况下从堆栈中取出值。1180 // 如果这是一个边界,则尽可能捕获值。1181 const next = unwindWork(workInProgress, renderExpirationTime);1182 // Because this fiber did not complete, don't reset its expiration time.1183 // 因为这个 fiber 没有完成,所以不要重置它的过期时间。1184 if (1185 enableProfilerTimer &&1186 (workInProgress.mode & ProfileMode) !== NoMode1187 ) {1188 // Record the render duration for the fiber that errored.1189 stopProfilerTimerIfRunningAndRecordDelta(workInProgress, false);1190 // Include the time spent working on failed children before continuing.1191 let actualDuration = workInProgress.actualDuration;1192 let child = workInProgress.child;1193 while (child !== null) {1194 actualDuration += child.actualDuration;1195 child = child.sibling;1196 }1197 workInProgress.actualDuration = actualDuration;1198 }1199 if (next !== null) {1200 // If completing this work spawned new work, do that next. We'll come1201 // back here again.1202 // Since we're restarting, remove anything that is not a host effect1203 // from the effect tag.1204 // TODO: The name stopFailedWorkTimer is misleading because Suspense1205 // also captures and restarts.1206 // 如果完成这项工作产生了新的工作,那么接下来就去做。1207 // 我们还会回到这里。1208 // 因为我们正在重新启动,所以从效果标签中删除所有不是 host effect 的内容。1209 // TODO: stopFailedWorkTimer这个名称具有误导性,因为悬念也会捕获和重新启动。1210 stopFailedWorkTimer(workInProgress);1211 next.effectTag &= HostEffectMask;1212 return next;1213 }1214 stopWorkTimer(workInProgress);1215 if (returnFiber !== null) {1216 // Mark the parent fiber as incomplete and clear its effect list.1217 // 将 parent fiber 标记为不完整,并清除其作用列表。1218 returnFiber.firstEffect = returnFiber.lastEffect = null;1219 returnFiber.effectTag |= Incomplete;1220 }1221 }1222 const siblingFiber = workInProgress.sibling;1223 if (siblingFiber !== null) {1224 // If there is more work to do in this returnFiber, do that next.1225 // 如果在这方面还有更多的工作要做,那就接着做。1226 return siblingFiber;1227 }1228 // Otherwise, return to the parent1229 // 否则,返回到父进程1230 workInProgress = returnFiber;1231 } while (workInProgress !== null);1232 // We've reached the root.1233 // 我们已经到了根节点。1234 if (workInProgressRootExitStatus === RootIncomplete) {1235 workInProgressRootExitStatus = RootCompleted;1236 }1237 return null;1238}1239function resetChildExpirationTime(completedWork: Fiber) {1240 if (1241 renderExpirationTime !== Never &&1242 completedWork.childExpirationTime === Never1243 ) {1244 // The children of this component are hidden. Don't bubble their1245 // expiration times.1246 return;1247 }1248 let newChildExpirationTime = NoWork;1249 // Bubble up the earliest expiration time.1250 if (enableProfilerTimer && (completedWork.mode & ProfileMode) !== NoMode) {1251 // In profiling mode, resetChildExpirationTime is also used to reset1252 // profiler durations.1253 let actualDuration = completedWork.actualDuration;1254 let treeBaseDuration = completedWork.selfBaseDuration;1255 // When a fiber is cloned, its actualDuration is reset to 0. This value will1256 // only be updated if work is done on the fiber (i.e. it doesn't bailout).1257 // When work is done, it should bubble to the parent's actualDuration. If1258 // the fiber has not been cloned though, (meaning no work was done), then1259 // this value will reflect the amount of time spent working on a previous1260 // render. In that case it should not bubble. We determine whether it was1261 // cloned by comparing the child pointer.1262 const shouldBubbleActualDurations =1263 completedWork.alternate === null ||1264 completedWork.child !== completedWork.alternate.child;1265 let child = completedWork.child;1266 while (child !== null) {1267 const childUpdateExpirationTime = child.expirationTime;1268 const childChildExpirationTime = child.childExpirationTime;1269 if (childUpdateExpirationTime > newChildExpirationTime) {1270 newChildExpirationTime = childUpdateExpirationTime;1271 }1272 if (childChildExpirationTime > newChildExpirationTime) {1273 newChildExpirationTime = childChildExpirationTime;1274 }1275 if (shouldBubbleActualDurations) {1276 actualDuration += child.actualDuration;1277 }1278 treeBaseDuration += child.treeBaseDuration;1279 child = child.sibling;1280 }1281 completedWork.actualDuration = actualDuration;1282 completedWork.treeBaseDuration = treeBaseDuration;1283 } else {1284 let child = completedWork.child;1285 while (child !== null) {1286 const childUpdateExpirationTime = child.expirationTime;1287 const childChildExpirationTime = child.childExpirationTime;1288 if (childUpdateExpirationTime > newChildExpirationTime) {1289 newChildExpirationTime = childUpdateExpirationTime;1290 }1291 if (childChildExpirationTime > newChildExpirationTime) {1292 newChildExpirationTime = childChildExpirationTime;1293 }1294 child = child.sibling;1295 }1296 }1297 completedWork.childExpirationTime = newChildExpirationTime;1298}1299function commitRoot(root) {1300 runWithPriority(ImmediatePriority, commitRootImpl.bind(null, root));1301 // If there are passive effects, schedule a callback to flush them. This goes1302 // outside commitRootImpl so that it inherits the priority of the render.1303 // 如果有消极影响,安排一个回调来清除它们。1304 // 这超出了commitRootImpl,因此它继承了呈现的优先级。1305 if (rootWithPendingPassiveEffects !== null) {1306 const priorityLevel = getCurrentPriorityLevel();1307 scheduleCallback(priorityLevel, () => {1308 flushPassiveEffects();1309 return null;1310 });1311 }1312 return null;1313}1314function commitRootImpl(root) {1315 flushPassiveEffects();1316 flushRenderPhaseStrictModeWarningsInDEV();1317 flushSuspensePriorityWarningInDEV();1318 invariant(1319 workPhase !== RenderPhase && workPhase !== CommitPhase,1320 'Should not already be working.',1321 );1322 const finishedWork = root.finishedWork;1323 const expirationTime = root.finishedExpirationTime;1324 if (finishedWork === null) {1325 return null;1326 }1327 root.finishedWork = null;1328 root.finishedExpirationTime = NoWork;1329 invariant(1330 finishedWork !== root.current,1331 'Cannot commit the same tree as before. This error is likely caused by ' +1332 'a bug in React. Please file an issue.',1333 );1334 // commitRoot never returns a continuation; it always finishes synchronously.1335 // So we can clear these now to allow a new callback to be scheduled.1336 // commitRoot 从不返回延续;它总是同步完成。1337 // 因此我们现在可以清除这些,以便安排一个新的回调。1338 root.callbackNode = null;1339 root.callbackExpirationTime = NoWork;1340 startCommitTimer();1341 // Update the first and last pending times on this root. The new first1342 // pending time is whatever is left on the root fiber.1343 // 更新这个根目录上的第一个和最后一个挂起时间。1344 // 新的第一个挂起时间是留在根 fiber 上的时间。1345 const updateExpirationTimeBeforeCommit = finishedWork.expirationTime;1346 const childExpirationTimeBeforeCommit = finishedWork.childExpirationTime;1347 const firstPendingTimeBeforeCommit =1348 childExpirationTimeBeforeCommit > updateExpirationTimeBeforeCommit1349 ? childExpirationTimeBeforeCommit1350 : updateExpirationTimeBeforeCommit;1351 root.firstPendingTime = firstPendingTimeBeforeCommit;1352 if (firstPendingTimeBeforeCommit < root.lastPendingTime) {1353 // This usually means we've finished all the work, but it can also happen1354 // when something gets downprioritized during render, like a hidden tree.1355 // 这通常意味着我们已经完成了所有的工作,但它也可能发生在渲染过程中一些事情的优先级降低,比如隐藏的树。1356 root.lastPendingTime = firstPendingTimeBeforeCommit;1357 }1358 if (root === workInProgressRoot) {1359 // We can reset these now that they are finished.1360 // 现在这些都完成了,我们可以重新设置。1361 workInProgressRoot = null;1362 workInProgress = null;1363 renderExpirationTime = NoWork;1364 } else {1365 // This indicates that the last root we worked on is not the same one that1366 // we're committing now. This most commonly happens when a suspended root1367 // times out.1368 // 这表明我们处理的最后一个根不是我们现在提交的根。1369 // 这通常发生在挂起的根超时时。1370 }1371 // Get the list of effects.1372 // 获取效果列表。1373 let firstEffect;1374 if (finishedWork.effectTag > PerformedWork) {1375 // A fiber's effect list consists only of its children, not itself. So if1376 // the root has an effect, we need to add it to the end of the list. The1377 // resulting list is the set that would belong to the root's parent, if it1378 // had one; that is, all the effects in the tree including the root.1379 // fiber 的效果列表只包括它的子节点,而不是它本身。1380 // 因此,如果根有效果,我们需要将它添加到列表的末尾。1381 // 结果列表是根的父列表的集合,如果根有父列表的话;1382 // 也就是说,树中的所有效果,包括根。1383 if (finishedWork.lastEffect !== null) {1384 finishedWork.lastEffect.nextEffect = finishedWork;1385 firstEffect = finishedWork.firstEffect;1386 } else {1387 firstEffect = finishedWork;1388 }1389 } else {1390 // There is no effect on the root.1391 // 对根没有影响。1392 firstEffect = finishedWork.firstEffect;1393 }1394 if (firstEffect !== null) {1395 const prevWorkPhase = workPhase;1396 workPhase = CommitPhase;1397 let prevInteractions: Set<Interaction> | null = null;1398 if (enableSchedulerTracing) {1399 prevInteractions = __interactionsRef.current;1400 __interactionsRef.current = root.memoizedInteractions;1401 }1402 // Reset this to null before calling lifecycles1403 // 在调用生命周期之前将其重置为null1404 ReactCurrentOwner.current = null;1405 // The commit phase is broken into several sub-phases. We do a separate pass1406 // of the effect list for each phase: all mutation effects come before all1407 // layout effects, and so on.1408 // The first phase a "before mutation" phase. We use this phase to read the1409 // state of the host tree right before we mutate it. This is where1410 // getSnapshotBeforeUpdate is called.1411 // 提交阶段分为几个子阶段。1412 // 我们对每个阶段的效果列表进行单独的遍历:所有的突变效果都在所有布局效果之前,等等。1413 // 第一阶段是“突变前”阶段。1414 // 在对主机树进行突变之前,我们使用这个阶段来读取主机树的状态。1415 // 这就是调用getSnapshotBeforeUpdate的地方。1416 startCommitSnapshotEffectsTimer();1417 prepareForCommit(root.containerInfo);1418 nextEffect = firstEffect;1419 do {1420 if (__DEV__) {1421 invokeGuardedCallback(null, commitBeforeMutationEffects, null);1422 if (hasCaughtError()) {1423 invariant(nextEffect !== null, 'Should be working on an effect.');1424 const error = clearCaughtError();1425 captureCommitPhaseError(nextEffect, error);1426 nextEffect = nextEffect.nextEffect;1427 }1428 } else {1429 try {1430 commitBeforeMutationEffects();1431 } catch (error) {1432 invariant(nextEffect !== null, 'Should be working on an effect.');1433 captureCommitPhaseError(nextEffect, error);1434 nextEffect = nextEffect.nextEffect;1435 }1436 }1437 } while (nextEffect !== null);1438 stopCommitSnapshotEffectsTimer();1439 if (enableProfilerTimer) {1440 // Mark the current commit time to be shared by all Profilers in this1441 // batch. This enables them to be grouped later.1442 recordCommitTime();1443 }1444 // The next phase is the mutation phase, where we mutate the host tree.1445 // 下一个阶段是突变阶段,我们对宿主树进行突变。1446 startCommitHostEffectsTimer();1447 nextEffect = firstEffect;1448 do {1449 if (__DEV__) {1450 invokeGuardedCallback(null, commitMutationEffects, null);1451 if (hasCaughtError()) {1452 invariant(nextEffect !== null, 'Should be working on an effect.');1453 const error = clearCaughtError();1454 captureCommitPhaseError(nextEffect, error);1455 nextEffect = nextEffect.nextEffect;1456 }1457 } else {1458 try {1459 commitMutationEffects();1460 } catch (error) {1461 invariant(nextEffect !== null, 'Should be working on an effect.');1462 captureCommitPhaseError(nextEffect, error);1463 nextEffect = nextEffect.nextEffect;1464 }1465 }1466 } while (nextEffect !== null);1467 stopCommitHostEffectsTimer();1468 resetAfterCommit(root.containerInfo);1469 // The work-in-progress tree is now the current tree. This must come after1470 // the mutation phase, so that the previous tree is still current during1471 // componentWillUnmount, but before the layout phase, so that the finished1472 // work is current during componentDidMount/Update.1473 // 正在进行的工作树现在是当前树。1474 // 这必须在突变阶段之后进行,以便先前的树在componentWillUnmount期间仍然是当前的,1475 // 但是在布局阶段之前,以便完成的工作在componentDidMount/Update期间是当前的。1476 root.current = finishedWork;1477 // The next phase is the layout phase, where we call effects that read1478 // the host tree after it's been mutated. The idiomatic use case for this is1479 // layout, but class component lifecycles also fire here for legacy reasons.1480 // 下一个阶段是布局阶段,在这里我们调用在主机树发生突变后读取它的效果。1481 // 这里的惯用用例是layout,但是类组件的生命周期也会因为遗留问题而触发。1482 startCommitLifeCyclesTimer();1483 nextEffect = firstEffect;1484 do {1485 if (__DEV__) {1486 invokeGuardedCallback(1487 null,1488 commitLayoutEffects,1489 null,1490 root,1491 expirationTime,1492 );1493 if (hasCaughtError()) {1494 invariant(nextEffect !== null, 'Should be working on an effect.');1495 const error = clearCaughtError();1496 captureCommitPhaseError(nextEffect, error);1497 nextEffect = nextEffect.nextEffect;1498 }1499 } else {1500 try {1501 commitLayoutEffects(root, expirationTime);1502 } catch (error) {1503 invariant(nextEffect !== null, 'Should be working on an effect.');1504 captureCommitPhaseError(nextEffect, error);1505 nextEffect = nextEffect.nextEffect;1506 }1507 }1508 } while (nextEffect !== null);1509 stopCommitLifeCyclesTimer();1510 nextEffect = null;1511 if (enableSchedulerTracing) {1512 __interactionsRef.current = ((prevInteractions: any): Set<Interaction>);1513 }1514 workPhase = prevWorkPhase;1515 } else {1516 // No effects.1517 root.current = finishedWork;1518 // Measure these anyway so the flamegraph explicitly shows that there were1519 // no effects.1520 // TODO: Maybe there's a better way to report this.1521 startCommitSnapshotEffectsTimer();1522 stopCommitSnapshotEffectsTimer();1523 if (enableProfilerTimer) {1524 recordCommitTime();1525 }1526 startCommitHostEffectsTimer();1527 stopCommitHostEffectsTimer();1528 startCommitLifeCyclesTimer();1529 stopCommitLifeCyclesTimer();1530 }1531 stopCommitTimer();1532 if (rootDoesHavePassiveEffects) {1533 // This commit has passive effects. Stash a reference to them. But don't1534 // schedule a callback until after flushing layout work.1535 // 这个 commit 有消极影响。存储一个引用指向它。但是在刷新布局工作之前不要安排回调。1536 rootDoesHavePassiveEffects = false;1537 rootWithPendingPassiveEffects = root;1538 pendingPassiveEffectsExpirationTime = expirationTime;1539 } else {1540 if (enableSchedulerTracing) {1541 // If there are no passive effects, then we can complete the pending1542 // interactions. Otherwise, we'll wait until after the passive effects1543 // are flushed.1544 finishPendingInteractions(root, expirationTime);1545 }1546 }1547 // Check if there's remaining work on this root1548 // 检查这个根上是否还有剩余的工作1549 const remainingExpirationTime = root.firstPendingTime;1550 if (remainingExpirationTime !== NoWork) {1551 const currentTime = requestCurrentTime();1552 const priorityLevel = inferPriorityFromExpirationTime(1553 currentTime,1554 remainingExpirationTime,1555 );1556 scheduleCallbackForRoot(root, priorityLevel, remainingExpirationTime);1557 } else {1558 // If there's no remaining work, we can clear the set of already failed1559 // error boundaries.1560 // 如果没有剩余的工作,我们可以清除一组已经失败的错误边界。1561 legacyErrorBoundariesThatAlreadyFailed = null;1562 }1563 onCommitRoot(finishedWork.stateNode, expirationTime);1564 if (remainingExpirationTime === Sync) {1565 // Count the number of times the root synchronously re-renders without1566 // finishing. If there are too many, it indicates an infinite update loop.1567 // 计算根节点未完成同步重新呈现的次数。如果数量太多,则表示无限更新循环。1568 if (root === rootWithNestedUpdates) {1569 nestedUpdateCount++;1570 } else {1571 nestedUpdateCount = 0;1572 rootWithNestedUpdates = root;1573 }1574 } else {1575 nestedUpdateCount = 0;1576 }1577 if (hasUncaughtError) {1578 hasUncaughtError = false;1579 const error = firstUncaughtError;1580 firstUncaughtError = null;1581 throw error;1582 }1583 if (workPhase === LegacyUnbatchedPhase) {1584 // This is a legacy edge case. We just committed the initial mount of1585 // a ReactDOM.render-ed root inside of batchedUpdates. The commit fired1586 // synchronously, but layout updates should be deferred until the end1587 // of the batch.1588 // 这是一个遗留的边缘案例。1589 // 我们只是提交了 ReactDOM.render-ed root 的初始挂载在 batchedUpdates。1590 // 提交是同步触发的,但是布局更新应该延迟到批处理结束时。1591 return null;1592 }1593 // If layout work was scheduled, flush it now.1594 // 如果布局工作已经安排好了,现在就刷新它。1595 flushSyncCallbackQueue();1596 return null;1597}1598function commitBeforeMutationEffects() {1599 while (nextEffect !== null) {1600 if ((nextEffect.effectTag & Snapshot) !== NoEffect) {1601 setCurrentDebugFiberInDEV(nextEffect);1602 recordEffect();1603 const current = nextEffect.alternate;1604 commitBeforeMutationEffectOnFiber(current, nextEffect);1605 resetCurrentDebugFiberInDEV();1606 }1607 nextEffect = nextEffect.nextEffect;1608 }1609}1610function commitMutationEffects() {1611 // TODO: Should probably move the bulk of this function to commitWork.1612 while (nextEffect !== null) {1613 setCurrentDebugFiberInDEV(nextEffect);1614 const effectTag = nextEffect.effectTag;1615 if (effectTag & ContentReset) {1616 commitResetTextContent(nextEffect);1617 }1618 if (effectTag & Ref) {1619 const current = nextEffect.alternate;1620 if (current !== null) {1621 commitDetachRef(current);1622 }1623 }1624 // The following switch statement is only concerned about placement,1625 // updates, and deletions. To avoid needing to add a case for every possible1626 // bitmap value, we remove the secondary effects from the effect tag and1627 // switch on that value.1628 // 下面的switch语句只关心放置、更新和删除。1629 // 为了避免为每个可能的位图值添加大小写,我们从effect标签中删除次要的效果,并切换到该值。1630 let primaryEffectTag = effectTag & (Placement | Update | Deletion);1631 switch (primaryEffectTag) {1632 case Placement: {1633 commitPlacement(nextEffect);1634 // Clear the "placement" from effect tag so that we know that this is1635 // inserted, before any life-cycles like componentDidMount gets called.1636 // 清除effect标签上的“放置”,这样我们就知道它已经被插入了,在调用componentDidMount这样的生命周期之前。1637 // TODO: findDOMNode doesn't rely on this any more but isMounted does1638 // and isMounted is deprecated anyway so we should be able to kill this.1639 nextEffect.effectTag &= ~Placement;1640 break;1641 }1642 case PlacementAndUpdate: {1643 // Placement1644 commitPlacement(nextEffect);1645 // Clear the "placement" from effect tag so that we know that this is1646 // inserted, before any life-cycles like componentDidMount gets called.1647 // 清除effect标签上的“放置”,这样我们就知道它已经被插入了,在调用componentDidMount这样的生命周期之前。1648 nextEffect.effectTag &= ~Placement;1649 // Update1650 const current = nextEffect.alternate;1651 commitWork(current, nextEffect);1652 break;1653 }1654 case Update: {1655 const current = nextEffect.alternate;1656 commitWork(current, nextEffect);1657 break;1658 }1659 case Deletion: {1660 commitDeletion(nextEffect);1661 break;1662 }1663 }1664 // TODO: Only record a mutation effect if primaryEffectTag is non-zero.1665 recordEffect();1666 resetCurrentDebugFiberInDEV();1667 nextEffect = nextEffect.nextEffect;1668 }1669}1670function commitLayoutEffects(1671 root: FiberRoot,1672 committedExpirationTime: ExpirationTime,1673) {1674 // TODO: Should probably move the bulk of this function to commitWork.1675 while (nextEffect !== null) {1676 setCurrentDebugFiberInDEV(nextEffect);1677 const effectTag = nextEffect.effectTag;1678 if (effectTag & (Update | Callback)) {1679 recordEffect();1680 const current = nextEffect.alternate;1681 commitLayoutEffectOnFiber(1682 root,1683 current,1684 nextEffect,1685 committedExpirationTime,1686 );1687 }1688 if (effectTag & Ref) {1689 recordEffect();1690 commitAttachRef(nextEffect);1691 }1692 if (effectTag & Passive) {1693 rootDoesHavePassiveEffects = true;1694 }1695 resetCurrentDebugFiberInDEV();1696 nextEffect = nextEffect.nextEffect;1697 }1698}1699export function flushPassiveEffects() {1700 if (rootWithPendingPassiveEffects === null) {1701 return false;1702 }1703 const root = rootWithPendingPassiveEffects;1704 const expirationTime = pendingPassiveEffectsExpirationTime;1705 rootWithPendingPassiveEffects = null;1706 pendingPassiveEffectsExpirationTime = NoWork;1707 let prevInteractions: Set<Interaction> | null = null;1708 if (enableSchedulerTracing) {1709 prevInteractions = __interactionsRef.current;1710 __interactionsRef.current = root.memoizedInteractions;1711 }1712 invariant(1713 workPhase !== RenderPhase && workPhase !== CommitPhase,1714 'Cannot flush passive effects while already rendering.',1715 );1716 const prevWorkPhase = workPhase;1717 workPhase = CommitPhase;1718 // Note: This currently assumes there are no passive effects on the root1719 // fiber, because the root is not part of its own effect list. This could1720 // change in the future.1721 let effect = root.current.firstEffect;1722 while (effect !== null) {1723 if (__DEV__) {1724 setCurrentDebugFiberInDEV(effect);1725 invokeGuardedCallback(null, commitPassiveHookEffects, null, effect);1726 if (hasCaughtError()) {1727 invariant(effect !== null, 'Should be working on an effect.');1728 const error = clearCaughtError();1729 captureCommitPhaseError(effect, error);1730 }1731 resetCurrentDebugFiberInDEV();1732 } else {1733 try {1734 commitPassiveHookEffects(effect);1735 } catch (error) {1736 invariant(effect !== null, 'Should be working on an effect.');1737 captureCommitPhaseError(effect, error);1738 }1739 }1740 effect = effect.nextEffect;1741 }1742 if (enableSchedulerTracing) {1743 __interactionsRef.current = ((prevInteractions: any): Set<Interaction>);1744 finishPendingInteractions(root, expirationTime);1745 }1746 workPhase = prevWorkPhase;1747 flushSyncCallbackQueue();1748 // If additional passive effects were scheduled, increment a counter. If this1749 // exceeds the limit, we'll fire a warning.1750 nestedPassiveUpdateCount =1751 rootWithPendingPassiveEffects === null ? 0 : nestedPassiveUpdateCount + 1;1752 return true;1753}1754export function isAlreadyFailedLegacyErrorBoundary(instance: mixed): boolean {1755 return (1756 legacyErrorBoundariesThatAlreadyFailed !== null &&1757 legacyErrorBoundariesThatAlreadyFailed.has(instance)1758 );1759}1760export function markLegacyErrorBoundaryAsFailed(instance: mixed) {1761 if (legacyErrorBoundariesThatAlreadyFailed === null) {1762 legacyErrorBoundariesThatAlreadyFailed = new Set([instance]);1763 } else {1764 legacyErrorBoundariesThatAlreadyFailed.add(instance);1765 }1766}1767function prepareToThrowUncaughtError(error: mixed) {1768 if (!hasUncaughtError) {1769 hasUncaughtError = true;1770 firstUncaughtError = error;1771 }1772}1773export const onUncaughtError = prepareToThrowUncaughtError;1774function captureCommitPhaseErrorOnRoot(1775 rootFiber: Fiber,1776 sourceFiber: Fiber,1777 error: mixed,1778) {1779 const errorInfo = createCapturedValue(error, sourceFiber);1780 const update = createRootErrorUpdate(rootFiber, errorInfo, Sync);1781 enqueueUpdate(rootFiber, update);1782 const root = markUpdateTimeFromFiberToRoot(rootFiber, Sync);1783 if (root !== null) {1784 scheduleCallbackForRoot(root, ImmediatePriority, Sync);1785 }1786}1787export function captureCommitPhaseError(sourceFiber: Fiber, error: mixed) {1788 if (sourceFiber.tag === HostRoot) {1789 // Error was thrown at the root. There is no parent, so the root1790 // itself should capture it.1791 captureCommitPhaseErrorOnRoot(sourceFiber, sourceFiber, error);1792 return;1793 }1794 let fiber = sourceFiber.return;1795 while (fiber !== null) {1796 if (fiber.tag === HostRoot) {1797 captureCommitPhaseErrorOnRoot(fiber, sourceFiber, error);1798 return;1799 } else if (fiber.tag === ClassComponent) {1800 const ctor = fiber.type;1801 const instance = fiber.stateNode;1802 if (1803 typeof ctor.getDerivedStateFromError === 'function' ||1804 (typeof instance.componentDidCatch === 'function' &&1805 !isAlreadyFailedLegacyErrorBoundary(instance))1806 ) {1807 const errorInfo = createCapturedValue(error, sourceFiber);1808 const update = createClassErrorUpdate(1809 fiber,1810 errorInfo,1811 // TODO: This is always sync1812 Sync,1813 );1814 enqueueUpdate(fiber, update);1815 const root = markUpdateTimeFromFiberToRoot(fiber, Sync);1816 if (root !== null) {1817 scheduleCallbackForRoot(root, ImmediatePriority, Sync);1818 }1819 return;1820 }1821 }1822 fiber = fiber.return;1823 }1824}1825export function pingSuspendedRoot(1826 root: FiberRoot,1827 thenable: Thenable,1828 suspendedTime: ExpirationTime,1829) {1830 const pingCache = root.pingCache;1831 if (pingCache !== null) {1832 // The thenable resolved, so we no longer need to memoize, because it will1833 // never be thrown again.1834 pingCache.delete(thenable);1835 }1836 if (workInProgressRoot === root && renderExpirationTime === suspendedTime) {1837 // Received a ping at the same priority level at which we're currently1838 // rendering. Restart from the root. Don't need to schedule a ping because1839 // we're already working on this tree.1840 prepareFreshStack(root, renderExpirationTime);1841 return;1842 }1843 const lastPendingTime = root.lastPendingTime;1844 if (lastPendingTime < suspendedTime) {1845 // The root is no longer suspended at this time.1846 return;1847 }1848 const pingTime = root.pingTime;1849 if (pingTime !== NoWork && pingTime < suspendedTime) {1850 // There's already a lower priority ping scheduled.1851 return;1852 }1853 // Mark the time at which this ping was scheduled.1854 root.pingTime = suspendedTime;1855 if (root.finishedExpirationTime === suspendedTime) {1856 // If there's a pending fallback waiting to commit, throw it away.1857 root.finishedExpirationTime = NoWork;1858 root.finishedWork = null;1859 }1860 const currentTime = requestCurrentTime();1861 const priorityLevel = inferPriorityFromExpirationTime(1862 currentTime,1863 suspendedTime,1864 );1865 scheduleCallbackForRoot(root, priorityLevel, suspendedTime);1866}1867export function retryTimedOutBoundary(boundaryFiber: Fiber) {1868 // The boundary fiber (a Suspense component) previously timed out and was1869 // rendered in its fallback state. One of the promises that suspended it has1870 // resolved, which means at least part of the tree was likely unblocked. Try1871 // rendering again, at a new expiration time.1872 const currentTime = requestCurrentTime();1873 const suspenseConfig = null; // Retries don't carry over the already committed update.1874 const retryTime = computeExpirationForFiber(1875 currentTime,1876 boundaryFiber,1877 suspenseConfig,1878 );1879 // TODO: Special case idle priority?1880 const priorityLevel = inferPriorityFromExpirationTime(currentTime, retryTime);1881 const root = markUpdateTimeFromFiberToRoot(boundaryFiber, retryTime);1882 if (root !== null) {1883 scheduleCallbackForRoot(root, priorityLevel, retryTime);1884 }1885}1886export function resolveRetryThenable(boundaryFiber: Fiber, thenable: Thenable) {1887 let retryCache: WeakSet<Thenable> | Set<Thenable> | null;1888 if (enableSuspenseServerRenderer) {1889 switch (boundaryFiber.tag) {1890 case SuspenseComponent:1891 retryCache = boundaryFiber.stateNode;1892 break;1893 case DehydratedSuspenseComponent:1894 retryCache = boundaryFiber.memoizedState;1895 break;1896 default:1897 invariant(1898 false,1899 'Pinged unknown suspense boundary type. ' +1900 'This is probably a bug in React.',1901 );1902 }1903 } else {1904 retryCache = boundaryFiber.stateNode;1905 }1906 if (retryCache !== null) {1907 // The thenable resolved, so we no longer need to memoize, because it will1908 // never be thrown again.1909 retryCache.delete(thenable);1910 }1911 retryTimedOutBoundary(boundaryFiber);1912}1913// Computes the next Just Noticeable Difference (JND) boundary.1914// The theory is that a person can't tell the difference between small differences in time.1915// Therefore, if we wait a bit longer than necessary that won't translate to a noticeable1916// difference in the experience. However, waiting for longer might mean that we can avoid1917// showing an intermediate loading state. The longer we have already waited, the harder it1918// is to tell small differences in time. Therefore, the longer we've already waited,1919// the longer we can wait additionally. At some point we have to give up though.1920// We pick a train model where the next boundary commits at a consistent schedule.1921// These particular numbers are vague estimates. We expect to adjust them based on research.1922function jnd(timeElapsed: number) {1923 return timeElapsed < 1201924 ? 1201925 : timeElapsed < 4801926 ? 4801927 : timeElapsed < 10801928 ? 10801929 : timeElapsed < 19201930 ? 19201931 : timeElapsed < 30001932 ? 30001933 : timeElapsed < 43201934 ? 43201935 : ceil(timeElapsed / 1960) * 1960;1936}1937function computeMsUntilSuspenseLoadingDelay(1938 mostRecentEventTime: ExpirationTime,1939 committedExpirationTime: ExpirationTime,1940 suspenseConfig: SuspenseConfig,1941) {1942 if (disableYielding) {1943 // Timeout immediately when yielding is disabled.1944 return 0;1945 }1946 const busyMinDurationMs = (suspenseConfig.busyMinDurationMs: any) | 0;1947 if (busyMinDurationMs <= 0) {1948 return 0;1949 }1950 const busyDelayMs = (suspenseConfig.busyDelayMs: any) | 0;1951 // Compute the time until this render pass would expire.1952 // 计算这个渲染通道过期的时间。1953 const currentTimeMs: number = now();1954 const eventTimeMs: number = inferTimeFromExpirationTime(1955 mostRecentEventTime,1956 suspenseConfig,1957 );1958 const timeElapsed = currentTimeMs - eventTimeMs;1959 if (timeElapsed <= busyDelayMs) {1960 // If we haven't yet waited longer than the initial delay, we don't1961 // have to wait any additional time.1962 // 如果我们的等待时间还没有超过原定的延误时间,我们就不必再等了。1963 return 0;1964 }1965 const msUntilTimeout = busyDelayMs + busyMinDurationMs - timeElapsed;1966 // This is the value that is passed to `setTimeout`.1967 return msUntilTimeout;1968}1969function computeMsUntilTimeout(1970 mostRecentEventTime: ExpirationTime,1971 suspenseTimeout: ExpirationTime,1972 committedExpirationTime: ExpirationTime,1973 suspenseConfig: null | SuspenseConfig,1974 shouldDelay: boolean,1975) {1976 if (disableYielding) {1977 // Timeout immediately when yielding is disabled.1978 return 0;1979 }1980 // Compute the time until this render pass would expire.1981 const currentTimeMs: number = now();1982 if (suspenseTimeout !== Sync && shouldDelay) {1983 const timeUntilTimeoutMs =1984 expirationTimeToMs(suspenseTimeout) - currentTimeMs;1985 return timeUntilTimeoutMs;1986 }1987 const eventTimeMs: number = inferTimeFromExpirationTime(1988 mostRecentEventTime,1989 suspenseConfig,1990 );1991 const timeUntilExpirationMs =1992 expirationTimeToMs(committedExpirationTime) - currentTimeMs;1993 let timeElapsed = currentTimeMs - eventTimeMs;1994 if (timeElapsed < 0) {1995 // We get this wrong some time since we estimate the time.1996 timeElapsed = 0;1997 }1998 let msUntilTimeout = jnd(timeElapsed) - timeElapsed;1999 // Clamp the timeout to the expiration time.2000 // TODO: Once the event time is exact instead of inferred from expiration time2001 // we don't need this....

Full Screen

Full Screen

ReactFiberScheduler.js

Source:ReactFiberScheduler.js Github

copy

Full Screen

...871 ) {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;...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1const { chromium } = require('playwright');2(async () => {3 const browser = await chromium.launch();4 const context = await browser.newContext();5 const page = await context.newPage();6 const cookies = await page.context().cookies();7 console.log(cookies)8 await browser.close();9})();10 {11 }

Full Screen

Using AI Code Generation

copy

Full Screen

1const { chromium } = require('playwright');2(async () => {3 const browser = await chromium.launch();4 const page = await browser.newPage();5 await page.screenshot({ path: 'example.png' });6 console.log(await page.evaluate(() => window.playwright.inferTimeFromExpirationTime(0)));7 await browser.close();8})();9const { chromium } = require('playwright');10(async () => {11 const browser = await chromium.launch();12 const page = await browser.newPage();13 await page.screenshot({ path: 'example.png' });14 console.log(await page.evaluate(() => window.playwright.inferTimeFromExpirationTime(1)));15 await browser.close();16})();17const { chromium } = require('playwright');18(async () => {19 const browser = await chromium.launch();20 const page = await browser.newPage();21 await page.screenshot({ path: 'example.png' });22 console.log(await page.evaluate(() => window.playwright.inferTimeFromExpirationTime(2)));23 await browser.close();24})();25const { chromium } = require('playwright');26(async () => {27 const browser = await chromium.launch();28 const page = await browser.newPage();29 await page.screenshot({ path: 'example.png' });30 console.log(await page.evaluate(() => window.playwright.inferTimeFromExpirationTime(3)));31 await browser.close();32})();33const { chromium } = require('playwright');34(async () => {35 const browser = await chromium.launch();36 const page = await browser.newPage();37 await page.screenshot({ path: 'example.png' });

Full Screen

Using AI Code Generation

copy

Full Screen

1const { chromium } = require('playwright');2(async () => {3 const browser = await chromium.launch();4 const context = await browser.newContext();5 const page = await context.newPage();6 const internal = page._delegate;7 const expiration = internal.inferTimeFromExpirationTime('1d');8 console.log(expiration);9 await browser.close();10})();11const { chromium } = require('playwright');12(async () => {13 const browser = await chromium.launch();14 const context = await browser.newContext();15 const page = await context.newPage();16 const internal = page._delegate;17 const expiration = internal.inferTimeFromExpirationTime('1d');18 console.log(expiration);19 await browser.close();20})();21 at async Object.exports.createTarget (/home/ankit/playwright-test/node_modules/playwright-core/lib/cjs/pw-run.js:1:1271)22 at async BrowserContext._createPageInNewContext (/home/ankit/playwright-test/node_modules/playwright-core/lib/cjs/pw-run.js:1:11113)23 at async BrowserContext.newPage (/home/ankit/playwright-test/node_modules/playwright-core/lib/cjs/pw-run.js:1:10521)24 at async Object.<anonymous> (/home/ankit/playwright-test/test.js:7:15)

Full Screen

Using AI Code Generation

copy

Full Screen

1const { inferTimeFromExpirationTime } = require('playwright/lib/internal/utils');2const { inferTimeFromExpirationTime } = require('playwright/lib/internal/utils');3const time = inferTimeFromExpirationTime(120);4console.log(time);5const { inferTimeFromExpirationTime } = require('playwright/lib/internal/utils');6const time = inferTimeFromExpirationTime(120);7console.log(time);8const { inferTimeFromExpirationTime } = require('playwright/lib/internal/utils');9const time = inferTimeFromExpirationTime(120);10console.log(time);11const { inferTimeFromExpirationTime } = require('playwright/lib/internal/utils');12const time = inferTimeFromExpirationTime(120);13console.log(time);14const { inferTimeFromExpirationTime } = require('playwright/lib/internal/utils');15const time = inferTimeFromExpirationTime(120);16console.log(time);17const { inferTimeFromExpirationTime } = require('playwright/lib/internal/utils');18const time = inferTimeFromExpirationTime(120);19console.log(time);20const { inferTimeFromExpirationTime } = require('playwright/lib/internal/utils');21const time = inferTimeFromExpirationTime(120);22console.log(time);23const { inferTimeFromExpirationTime } = require('play

Full Screen

Using AI Code Generation

copy

Full Screen

1const { Playwright } = require('playwright');2const { inferTimeFromExpirationTime } = Playwright.Internal;3const time = inferTimeFromExpirationTime(3600);4console.log(time);5const { Playwright } = require('playwright');6const { inferTimeFromExpirationTime } = Playwright.Internal;7const time = inferTimeFromExpirationTime(3600);8console.log(time);9const { Playwright } = require('playwright');10const { inferTimeFromExpirationTime } = Playwright.Internal;11const time = inferTimeFromExpirationTime(3600);12console.log(time);13const { Playwright } = require('playwright');14const { inferTimeFromExpirationTime } = Playwright.Internal;15const time = inferTimeFromExpirationTime(3600);16console.log(time);17const { Playwright } = require('playwright');18const { inferTimeFromExpirationTime } = Playwright.Internal;19const time = inferTimeFromExpirationTime(3600);20console.log(time);21const { Playwright } = require('playwright');22const { inferTimeFromExpirationTime } = Playwright.Internal;23const time = inferTimeFromExpirationTime(3600);24console.log(time);25const { Playwright }

Full Screen

Using AI Code Generation

copy

Full Screen

1const { devices } = require('playwright-core');2const { inferTimeFromExpirationTime } = require('playwright-core/lib/server/frames');3const { Page } = require('playwright-core/lib/server/page');4const { Frame } = require('playwright-core/lib/server/frame');5const { JSHandle } = require('playwright-core/lib/server/jsHandle');6const iPhone = devices['iPhone 6'];7const page = new Page();8const frame = new Frame(page, 'mainFrameId', 'about:blank');9const jsHandle = new JSHandle(frame, 'object', {});10const expirationTime = 1000;11const time = inferTimeFromExpirationTime(expirationTime, jsHandle);12console.log(time);

Full Screen

Using AI Code Generation

copy

Full Screen

1const { inferTimeFromExpirationTime } = require('playwright/lib/utils/utils');2const time = inferTimeFromExpirationTime(3600);3console.log(time);4const { inferTimeFromExpirationTime } = require('playwright/lib/utils/utils');5const time = inferTimeFromExpirationTime(7200);6console.log(time);7const { inferTimeFromExpirationTime } = require('playwright/lib/utils/utils');8const time = inferTimeFromExpirationTime(10800);9console.log(time);10const { inferTimeFromExpirationTime } = require('playwright/lib/utils/utils');11const time = inferTimeFromExpirationTime(86400);12console.log(time);13const { inferTimeFromExpirationTime } = require('playwright/lib/utils/utils');14const time = inferTimeFromExpirationTime(172800);15console.log(time);16const { inferTimeFromExpirationTime } = require('playwright/lib/utils/utils');17const time = inferTimeFromExpirationTime(259200);18console.log(time);19const { inferTimeFromExpirationTime } = require('playwright/lib/utils/utils');20const time = inferTimeFromExpirationTime(604800);21console.log(time);22const { inferTimeFromExpirationTime } = require('playwright/lib/utils/utils');23const time = inferTimeFromExpirationTime(1209600);24console.log(time);

Full Screen

Using AI Code Generation

copy

Full Screen

1const {BrowserContext, Page} = require('playwright');2const {createPageInContext} = require('playwright/lib/server/browserContext');3const {createPage} = require('playwright/lib/server/page');4const {createFrame} = require('playwright/lib/server/frames');5const {createExecutionContext} = require('playwright/lib/server/executionContext');6const {createJSHandle} = require('playwright/lib/server/javascript');7const {createCDPSession} = require('playwright/lib/server/cdpsession');8const {createNetworkManager} = require('playwright/lib/server/network');9const {createTimeoutSettings} = require('playwright/lib/server/timeouts');10const {createCoverage} = require('playwright/lib/server/coverage');11const {createTracing} = require('playwright/lib/server/tracing');12const {createDownloadManager} = require('playwright/lib/server/download');13const {createFileChooser} = require('playwright/lib/server/fileChooser');14const {createAccessibility} = require('playwright/lib/server/accessibility');15const {createDialog} = require('playwright/lib/server/dialog');16const {createVideo} = require('playwright/lib/server/video');17const {createWebsocketTransport} = require('playwright/lib/server/transport');18const path = require('path');19const fs = require('fs');20const os = require('os');21const {createInProcessTransport} = require('playwright/lib/server/transport');22const {createBrowserServer} = require('playwright/lib/server/browserServer');23const {createBrowserType} = require('playwright/lib/server/browserType');24const {createBrowser} = require('playwright/lib/server/browser');25const {createBrowserContext} = require('playwright/lib/server/browserContext');26const {createPage} = require('playwright/lib/server/page');27const {createFrame} = require('playwright/lib/server/frames');28const {createExecutionContext} = require('playwright/lib/server/executionContext');29const {createJSHandle} = require('playwright/lib/server/javascript');30const {createCDPSession} = require('playwright/lib/server/cdpsession');31const {createNetworkManager} = require('playwright/lib/server/network');32const {createTimeoutSettings} = require('playwright/lib/server/timeouts');33const {createCoverage} = require('playwright/lib/server/coverage');34const {createTracing} = require('playwright

Full Screen

Playwright tutorial

LambdaTest’s Playwright tutorial will give you a broader idea about the Playwright automation framework, its unique features, and use cases with examples to exceed your understanding of Playwright testing. This tutorial will give A to Z guidance, from installing the Playwright framework to some best practices and advanced concepts.

Chapters:

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

Run Playwright Internal automation tests on LambdaTest cloud grid

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

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful