How to use scheduleInteractions method in Playwright Internal

Best JavaScript code snippet using playwright-internal

ReactFiberWorkLoop.js

Source:ReactFiberWorkLoop.js Github

copy

Full Screen

...1905 //循环执行 scheduleInteractions1906 for (let i = 0; i < expirationTimes.length; i++) {1907 //与schedule的交互1908 //请看:[React源码解析之scheduleWork(上)](https://juejin.im/post/5d7fa983f265da03cf7ac048)中的「六、schedulePendingInteractions()」1909 scheduleInteractions(1910 root,1911 expirationTimes[i],1912 root.memoizedInteractions,1913 );1914 }1915 }1916 }1917 // 同步调用callback1918 // 流程是在root上存取callback和expirationTime,1919 // 当新的callback调用时,比较更新expirationTime1920 //请看:[React源码解析之scheduleWork(下)](https://juejin.im/post/5d885b75f265da03e83baaa7)中的「八、scheduleCallbackForRoot()」1921 scheduleCallbackForRoot(root, priorityLevel, remainingExpirationTime);1922 }1923 //如果没有剩余的 work 的话,说明 commit 成功,那么就清除「错误边界」的 list1924 else {1925 // If there's no remaining work, we can clear the set of already failed1926 // error boundaries.1927 legacyErrorBoundariesThatAlreadyFailed = null;1928 }1929 if (enableSchedulerTracing) {1930 //当本次 commit 产生的脏作用被清除后,React就可以清除已经完成的交互1931 if (!rootDidHavePassiveEffects) {1932 // If there are no passive effects, then we can complete the pending interactions.1933 // Otherwise, we'll wait until after the passive effects are flushed.1934 // Wait to do this until after remaining work has been scheduled,1935 // so that we don't prematurely signal complete for interactions when there's e.g. hidden work.1936 //清除已经完成的交互,如果被 suspended 挂起的话,把交互留到后续呈现1937 finishPendingInteractions(root, expirationTime);1938 }1939 }1940 //devTools 相关的,可不看1941 onCommitRoot(finishedWork.stateNode, expirationTime);1942 //剩余的 work 是同步任务的话1943 if (remainingExpirationTime === Sync) {1944 // Count the number of times the root synchronously re-renders without1945 // finishing. If there are too many, it indicates an infinite update loop.1946 //计算同步 re-render 重新渲染的次数,判断是否是无限循环1947 if (root === rootWithNestedUpdates) {1948 nestedUpdateCount++;1949 } else {1950 nestedUpdateCount = 0;1951 rootWithNestedUpdates = root;1952 }1953 } else {1954 nestedUpdateCount = 0;1955 }1956 //如果捕获到错误的话,就 throw error1957 if (hasUncaughtError) {1958 hasUncaughtError = false;1959 const error = firstUncaughtError;1960 firstUncaughtError = null;1961 throw error;1962 }1963 //可不看1964 if ((executionContext & LegacyUnbatchedContext) !== NoContext) {1965 // This is a legacy edge case. We just committed the initial mount of1966 // a ReactDOM.render-ed root inside of batchedUpdates. The commit fired1967 // synchronously, but layout updates should be deferred until the end1968 // of the batch.1969 return null;1970 }1971 // If layout work was scheduled, flush it now.1972 //「layout」阶段的任务已经被调度的话,立即清除它1973 //刷新同步任务队列1974 //请看:[React源码解析之scheduleWork(下)](https://juejin.im/post/5d885b75f265da03e83baaa7)中的「十二、flushSyncCallbackQueue()」1975 flushSyncCallbackQueue();1976 return null;1977}1978//===========================================================1979//循环 effect 链,对有 Snapshot 的 effect 执行 commitBeforeMutationEffectOnFiber1980function commitBeforeMutationEffects() {1981 //循环 effect 链1982 while (nextEffect !== null) {1983 //如果 effectTag 里有 Snapshot 这个 effectTag 的话1984 //关于&,请看[前端小知识10点(2020.2.10)](https://mp.weixin.qq.com/s/tt2XcW4GF7oBBZOPwTiCcg)中的「8、JS 中的 & 是什么意思」1985 if ((nextEffect.effectTag & Snapshot) !== NoEffect) {1986 //dev 可不看1987 // setCurrentDebugFiberInDEV(nextEffect);1988 //计 effect 的数1989 recordEffect();1990 //获取当前 fiber 节点1991 const current = nextEffect.alternate;1992 commitBeforeMutationEffectOnFiber(current, nextEffect);1993 //dev 可不看1994 // resetCurrentDebugFiberInDEV();1995 }1996 nextEffect = nextEffect.nextEffect;1997 }1998}1999//提交HostComponent的 side effect,也就是 DOM 节点的操作(增删改)2000function commitMutationEffects() {2001 // TODO: Should probably move the bulk of this function to commitWork.2002 //循环 effect 链2003 while (nextEffect !== null) {2004 setCurrentDebugFiberInDEV(nextEffect);2005 const effectTag = nextEffect.effectTag;2006 //如果有文字节点,则将value 置为''2007 if (effectTag & ContentReset) {2008 commitResetTextContent(nextEffect);2009 }2010 ////将 ref 的指向置为 null2011 if (effectTag & Ref) {2012 const current = nextEffect.alternate;2013 if (current !== null) {2014 commitDetachRef(current);2015 }2016 }2017 // The following switch statement is only concerned about placement,2018 // updates, and deletions. To avoid needing to add a case for every possible2019 // bitmap value, we remove the secondary effects from the effect tag and2020 // switch on that value.2021 //以下情况是针对 替换(Placement)、更新(Update)和 删除(Deletion) 的 effectTag 的2022 let primaryEffectTag = effectTag & (Placement | Update | Deletion);2023 switch (primaryEffectTag) {2024 //插入新节点2025 case Placement: {2026 //针对该节点及子节点进行插入操作2027 commitPlacement(nextEffect);2028 // Clear the "placement" from effect tag so that we know that this is2029 // inserted, before any life-cycles like componentDidMount gets called.2030 // TODO: findDOMNode doesn't rely on this any more but isMounted does2031 // and isMounted is deprecated anyway so we should be able to kill this.2032 nextEffect.effectTag &= ~Placement;2033 break;2034 }2035 //替换并更新该节点是Placement和Update的结合,就不讲了2036 case PlacementAndUpdate: {2037 // Placement2038 //针对该节点及子节点进行插入操作2039 commitPlacement(nextEffect);2040 // Clear the "placement" from effect tag so that we know that this is2041 // inserted, before any life-cycles like componentDidMount gets called.2042 nextEffect.effectTag &= ~Placement;2043 // Update2044 const current = nextEffect.alternate;2045 //对 DOM 节点上的属性进行更新2046 commitWork(current, nextEffect);2047 break;2048 }2049 //更新节点2050 //旧节点->新节点2051 case Update: {2052 const current = nextEffect.alternate;2053 //对 DOM 节点上的属性进行更新2054 commitWork(current, nextEffect);2055 break;2056 }2057 case Deletion: {2058 //删除节点2059 commitDeletion(nextEffect);2060 break;2061 }2062 }2063 // TODO: Only record a mutation effect if primaryEffectTag is non-zero.2064 //不看2065 recordEffect();2066 //dev,不看2067 resetCurrentDebugFiberInDEV();2068 nextEffect = nextEffect.nextEffect;2069 }2070}2071//① 循环 effect 链,针对不同的 fiber 类型,进行effect.destroy()/componentDidMount()/callback/node.focus()等操作2072//② 指定 ref 的引用2073function commitLayoutEffects(2074 root: FiberRoot,2075 committedExpirationTime: ExpirationTime,2076) {2077 // TODO: Should probably move the bulk of this function to commitWork.2078 //循环 effect 链2079 while (nextEffect !== null) {2080 //dev 环境代码,不看2081 setCurrentDebugFiberInDEV(nextEffect);2082 const effectTag = nextEffect.effectTag;2083 //如果有 Update、Callback 的 effectTag 的话2084 if (effectTag & (Update | Callback)) {2085 recordEffect();2086 const current = nextEffect.alternate;2087 //重点看 FunctionComponent/ClassComponent/HostComponent2088 //① FunctionComponent——执行effect.destroy()2089 //② ClassComponent——componentDidMount()/componentDidUpdate(),effect 链——执行 setState 的 callback,capturedEffect 链执行 componentDidCatch2090 //③ HostComponent——判断是否是自动聚焦的 DOM 标签,是的话则调用 node.focus() 获取焦点2091 commitLayoutEffectOnFiber(2092 root,2093 current,2094 nextEffect,2095 committedExpirationTime,2096 );2097 }2098 //指定 ref 的引用2099 if (effectTag & Ref) {2100 recordEffect();2101 //获取 instance 实例,并指定给 ref2102 commitAttachRef(nextEffect);2103 }2104 //副作用2105 if (effectTag & Passive) {2106 rootDoesHavePassiveEffects = true;2107 }2108 //dev 环境,不看2109 resetCurrentDebugFiberInDEV();2110 nextEffect = nextEffect.nextEffect;2111 }2112}2113//清除脏作用2114export function flushPassiveEffects() {2115 if (rootWithPendingPassiveEffects === null) {2116 return false;2117 }2118 const root = rootWithPendingPassiveEffects;2119 const expirationTime = pendingPassiveEffectsExpirationTime;2120 rootWithPendingPassiveEffects = null;2121 pendingPassiveEffectsExpirationTime = NoWork;2122 let prevInteractions: Set<Interaction> | null = null;2123 if (enableSchedulerTracing) {2124 prevInteractions = __interactionsRef.current;2125 __interactionsRef.current = root.memoizedInteractions;2126 }2127 invariant(2128 (executionContext & (RenderContext | CommitContext)) === NoContext,2129 'Cannot flush passive effects while already rendering.',2130 );2131 const prevExecutionContext = executionContext;2132 executionContext |= CommitContext;2133 // Note: This currently assumes there are no passive effects on the root2134 // fiber, because the root is not part of its own effect list. This could2135 // change in the future.2136 //effect 链表上第一个有副作用的 fiber2137 //比如在 app() 中调用了 useEffect()2138 let effect = root.current.firstEffect;2139 while (effect !== null) {2140 if (__DEV__) {2141 //删除了 dev 代码2142 } else {2143 try {2144 //执行 fiber 上的副作用2145 commitPassiveHookEffects(effect);2146 } catch (error) {2147 invariant(effect !== null, 'Should be working on an effect.');2148 captureCommitPhaseError(effect, error);2149 }2150 }2151 effect = effect.nextEffect;2152 }2153 if (enableSchedulerTracing) {2154 __interactionsRef.current = ((prevInteractions: any): Set<Interaction>);2155 finishPendingInteractions(root, expirationTime);2156 }2157 executionContext = prevExecutionContext;2158 flushSyncCallbackQueue();2159 // If additional passive effects were scheduled, increment a counter. If this2160 // exceeds the limit, we'll fire a warning.2161 nestedPassiveUpdateCount =2162 rootWithPendingPassiveEffects === null ? 0 : nestedPassiveUpdateCount + 1;2163 return true;2164}2165export function isAlreadyFailedLegacyErrorBoundary(instance: mixed): boolean {2166 return (2167 legacyErrorBoundariesThatAlreadyFailed !== null &&2168 legacyErrorBoundariesThatAlreadyFailed.has(instance)2169 );2170}2171export function markLegacyErrorBoundaryAsFailed(instance: mixed) {2172 if (legacyErrorBoundariesThatAlreadyFailed === null) {2173 legacyErrorBoundariesThatAlreadyFailed = new Set([instance]);2174 } else {2175 legacyErrorBoundariesThatAlreadyFailed.add(instance);2176 }2177}2178function prepareToThrowUncaughtError(error: mixed) {2179 if (!hasUncaughtError) {2180 hasUncaughtError = true;2181 firstUncaughtError = error;2182 }2183}2184export const onUncaughtError = prepareToThrowUncaughtError;2185function captureCommitPhaseErrorOnRoot(2186 rootFiber: Fiber,2187 sourceFiber: Fiber,2188 error: mixed,2189) {2190 const errorInfo = createCapturedValue(error, sourceFiber);2191 const update = createRootErrorUpdate(rootFiber, errorInfo, Sync);2192 enqueueUpdate(rootFiber, update);2193 const root = markUpdateTimeFromFiberToRoot(rootFiber, Sync);2194 if (root !== null) {2195 scheduleCallbackForRoot(root, ImmediatePriority, Sync);2196 }2197}2198export function captureCommitPhaseError(sourceFiber: Fiber, error: mixed) {2199 if (sourceFiber.tag === HostRoot) {2200 // Error was thrown at the root. There is no parent, so the root2201 // itself should capture it.2202 captureCommitPhaseErrorOnRoot(sourceFiber, sourceFiber, error);2203 return;2204 }2205 let fiber = sourceFiber.return;2206 while (fiber !== null) {2207 if (fiber.tag === HostRoot) {2208 captureCommitPhaseErrorOnRoot(fiber, sourceFiber, error);2209 return;2210 } else if (fiber.tag === ClassComponent) {2211 const ctor = fiber.type;2212 const instance = fiber.stateNode;2213 if (2214 typeof ctor.getDerivedStateFromError === 'function' ||2215 (typeof instance.componentDidCatch === 'function' &&2216 !isAlreadyFailedLegacyErrorBoundary(instance))2217 ) {2218 const errorInfo = createCapturedValue(error, sourceFiber);2219 const update = createClassErrorUpdate(2220 fiber,2221 errorInfo,2222 // TODO: This is always sync2223 Sync,2224 );2225 enqueueUpdate(fiber, update);2226 const root = markUpdateTimeFromFiberToRoot(fiber, Sync);2227 if (root !== null) {2228 scheduleCallbackForRoot(root, ImmediatePriority, Sync);2229 }2230 return;2231 }2232 }2233 fiber = fiber.return;2234 }2235}2236export function pingSuspendedRoot(2237 root: FiberRoot,2238 thenable: Thenable,2239 suspendedTime: ExpirationTime,2240) {2241 const pingCache = root.pingCache;2242 if (pingCache !== null) {2243 // The thenable resolved, so we no longer need to memoize, because it will2244 // never be thrown again.2245 pingCache.delete(thenable);2246 }2247 if (workInProgressRoot === root && renderExpirationTime === suspendedTime) {2248 // Received a ping at the same priority level at which we're currently2249 // rendering. We might want to restart this render. This should mirror2250 // the logic of whether or not a root suspends once it completes.2251 // TODO: If we're rendering sync either due to Sync, Batched or expired,2252 // we should probably never restart.2253 // If we're suspended with delay, we'll always suspend so we can always2254 // restart. If we're suspended without any updates, it might be a retry.2255 // If it's early in the retry we can restart. We can't know for sure2256 // whether we'll eventually process an update during this render pass,2257 // but it's somewhat unlikely that we get to a ping before that, since2258 // getting to the root most update is usually very fast.2259 if (2260 workInProgressRootExitStatus === RootSuspendedWithDelay ||2261 (workInProgressRootExitStatus === RootSuspended &&2262 workInProgressRootLatestProcessedExpirationTime === Sync &&2263 now() - globalMostRecentFallbackTime < FALLBACK_THROTTLE_MS)2264 ) {2265 // Restart from the root. Don't need to schedule a ping because2266 // we're already working on this tree.2267 prepareFreshStack(root, renderExpirationTime);2268 } else {2269 // Even though we can't restart right now, we might get an2270 // opportunity later. So we mark this render as having a ping.2271 workInProgressRootHasPendingPing = true;2272 }2273 return;2274 }2275 const lastPendingTime = root.lastPendingTime;2276 if (lastPendingTime < suspendedTime) {2277 // The root is no longer suspended at this time.2278 return;2279 }2280 const pingTime = root.pingTime;2281 if (pingTime !== NoWork && pingTime < suspendedTime) {2282 // There's already a lower priority ping scheduled.2283 return;2284 }2285 // Mark the time at which this ping was scheduled.2286 root.pingTime = suspendedTime;2287 if (root.finishedExpirationTime === suspendedTime) {2288 // If there's a pending fallback waiting to commit, throw it away.2289 root.finishedExpirationTime = NoWork;2290 root.finishedWork = null;2291 }2292 const currentTime = requestCurrentTime();2293 const priorityLevel = inferPriorityFromExpirationTime(2294 currentTime,2295 suspendedTime,2296 );2297 scheduleCallbackForRoot(root, priorityLevel, suspendedTime);2298}2299export function retryTimedOutBoundary(boundaryFiber: Fiber) {2300 // The boundary fiber (a Suspense component or SuspenseList component)2301 // previously was rendered in its fallback state. One of the promises that2302 // suspended it has resolved, which means at least part of the tree was2303 // likely unblocked. Try rendering again, at a new expiration time.2304 const currentTime = requestCurrentTime();2305 const suspenseConfig = null; // Retries don't carry over the already committed update.2306 const retryTime = computeExpirationForFiber(2307 currentTime,2308 boundaryFiber,2309 suspenseConfig,2310 );2311 // TODO: Special case idle priority?2312 const priorityLevel = inferPriorityFromExpirationTime(currentTime, retryTime);2313 const root = markUpdateTimeFromFiberToRoot(boundaryFiber, retryTime);2314 if (root !== null) {2315 scheduleCallbackForRoot(root, priorityLevel, retryTime);2316 }2317}2318export function resolveRetryThenable(boundaryFiber: Fiber, thenable: Thenable) {2319 let retryCache: WeakSet<Thenable> | Set<Thenable> | null;2320 if (enableSuspenseServerRenderer) {2321 switch (boundaryFiber.tag) {2322 case SuspenseComponent:2323 retryCache = boundaryFiber.stateNode;2324 break;2325 case DehydratedSuspenseComponent:2326 retryCache = boundaryFiber.memoizedState;2327 break;2328 default:2329 invariant(2330 false,2331 'Pinged unknown suspense boundary type. ' +2332 'This is probably a bug in React.',2333 );2334 }2335 } else {2336 retryCache = boundaryFiber.stateNode;2337 }2338 if (retryCache !== null) {2339 // The thenable resolved, so we no longer need to memoize, because it will2340 // never be thrown again.2341 retryCache.delete(thenable);2342 }2343 retryTimedOutBoundary(boundaryFiber);2344}2345// Computes the next Just Noticeable Difference (JND) boundary.2346// The theory is that a person can't tell the difference between small differences in time.2347// Therefore, if we wait a bit longer than necessary that won't translate to a noticeable2348// difference in the experience. However, waiting for longer might mean that we can avoid2349// showing an intermediate loading state. The longer we have already waited, the harder it2350// is to tell small differences in time. Therefore, the longer we've already waited,2351// the longer we can wait additionally. At some point we have to give up though.2352// We pick a train model where the next boundary commits at a consistent schedule.2353// These particular numbers are vague estimates. We expect to adjust them based on research.2354function jnd(timeElapsed: number) {2355 return timeElapsed < 1202356 ? 1202357 : timeElapsed < 4802358 ? 4802359 : timeElapsed < 10802360 ? 10802361 : timeElapsed < 19202362 ? 19202363 : timeElapsed < 30002364 ? 30002365 : timeElapsed < 43202366 ? 43202367 : ceil(timeElapsed / 1960) * 1960;2368}2369function computeMsUntilSuspenseLoadingDelay(2370 mostRecentEventTime: ExpirationTime,2371 committedExpirationTime: ExpirationTime,2372 suspenseConfig: SuspenseConfig,2373) {2374 const busyMinDurationMs = (suspenseConfig.busyMinDurationMs: any) | 0;2375 if (busyMinDurationMs <= 0) {2376 return 0;2377 }2378 const busyDelayMs = (suspenseConfig.busyDelayMs: any) | 0;2379 // Compute the time until this render pass would expire.2380 const currentTimeMs: number = now();2381 const eventTimeMs: number = inferTimeFromExpirationTimeWithSuspenseConfig(2382 mostRecentEventTime,2383 suspenseConfig,2384 );2385 const timeElapsed = currentTimeMs - eventTimeMs;2386 if (timeElapsed <= busyDelayMs) {2387 // If we haven't yet waited longer than the initial delay, we don't2388 // have to wait any additional time.2389 return 0;2390 }2391 const msUntilTimeout = busyDelayMs + busyMinDurationMs - timeElapsed;2392 // This is the value that is passed to `setTimeout`.2393 return msUntilTimeout;2394}2395//防止无限循环地嵌套更新2396function checkForNestedUpdates() {2397 if (nestedUpdateCount > NESTED_UPDATE_LIMIT) {2398 nestedUpdateCount = 0;2399 rootWithNestedUpdates = null;2400 invariant(2401 false,2402 'Maximum update depth exceeded. This can happen when a component ' +2403 'repeatedly calls setState inside componentWillUpdate or ' +2404 'componentDidUpdate. React limits the number of nested updates to ' +2405 'prevent infinite loops.',2406 );2407 }2408}2409function flushRenderPhaseStrictModeWarningsInDEV() {2410 if (__DEV__) {2411 ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings();2412 ReactStrictModeWarnings.flushLegacyContextWarning();2413 if (warnAboutDeprecatedLifecycles) {2414 ReactStrictModeWarnings.flushPendingDeprecationWarnings();2415 }2416 }2417}2418function stopFinishedWorkLoopTimer() {2419 const didCompleteRoot = true;2420 stopWorkLoopTimer(interruptedBy, didCompleteRoot);2421 interruptedBy = null;2422}2423//停止计时2424function stopInterruptedWorkLoopTimer() {2425 // TODO: Track which fiber caused the interruption.2426 /*_didCompleteRoot <=> didCompleteRoot*/2427 const didCompleteRoot = false;2428 stopWorkLoopTimer(interruptedBy, didCompleteRoot);2429 interruptedBy = null;2430}2431//判断是否有高优先级任务打断当前正在执行的任务2432function checkForInterruption(2433 fiberThatReceivedUpdate: Fiber,2434 updateExpirationTime: ExpirationTime,2435) {2436 //如果任务正在执行,并且异步任务已经执行到一半了,2437 //但是现在需要把执行权交给浏览器,去执行优先级更高的任务2438 if (2439 enableUserTimingAPI &&2440 workInProgressRoot !== null &&2441 updateExpirationTime > renderExpirationTime2442 ) {2443 //打断当前任务,优先执行新的update2444 interruptedBy = fiberThatReceivedUpdate;2445 }2446}2447let didWarnStateUpdateForUnmountedComponent: Set<string> | null = null;2448function warnAboutUpdateOnUnmountedFiberInDEV(fiber) {2449 if (__DEV__) {2450 const tag = fiber.tag;2451 if (2452 tag !== HostRoot &&2453 tag !== ClassComponent &&2454 tag !== FunctionComponent &&2455 tag !== ForwardRef &&2456 tag !== MemoComponent &&2457 tag !== SimpleMemoComponent2458 ) {2459 // Only warn for user-defined components, not internal ones like Suspense.2460 return;2461 }2462 // We show the whole stack but dedupe on the top component's name because2463 // the problematic code almost always lies inside that component.2464 const componentName = getComponentName(fiber.type) || 'ReactComponent';2465 if (didWarnStateUpdateForUnmountedComponent !== null) {2466 if (didWarnStateUpdateForUnmountedComponent.has(componentName)) {2467 return;2468 }2469 didWarnStateUpdateForUnmountedComponent.add(componentName);2470 } else {2471 didWarnStateUpdateForUnmountedComponent = new Set([componentName]);2472 }2473 warningWithoutStack(2474 false,2475 "Can't perform a React state update on an unmounted component. This " +2476 'is a no-op, but it indicates a memory leak in your application. To ' +2477 'fix, cancel all subscriptions and asynchronous tasks in %s.%s',2478 tag === ClassComponent2479 ? 'the componentWillUnmount method'2480 : 'a useEffect cleanup function',2481 getStackByFiberInDevAndProd(fiber),2482 );2483 }2484}2485let beginWork;2486if (__DEV__ && replayFailedUnitOfWorkWithInvokeGuardedCallback) {2487 let dummyFiber = null;2488 beginWork = (current, unitOfWork, expirationTime) => {2489 // If a component throws an error, we replay it again in a synchronously2490 // dispatched event, so that the debugger will treat it as an uncaught2491 // error See ReactErrorUtils for more information.2492 // Before entering the begin phase, copy the work-in-progress onto a dummy2493 // fiber. If beginWork throws, we'll use this to reset the state.2494 const originalWorkInProgressCopy = assignFiberPropertiesInDEV(2495 dummyFiber,2496 unitOfWork,2497 );2498 try {2499 return originalBeginWork(current, unitOfWork, expirationTime);2500 } catch (originalError) {2501 if (2502 originalError !== null &&2503 typeof originalError === 'object' &&2504 typeof originalError.then === 'function'2505 ) {2506 // Don't replay promises. Treat everything else like an error.2507 throw originalError;2508 }2509 // Keep this code in sync with renderRoot; any changes here must have2510 // corresponding changes there.2511 resetContextDependencies();2512 resetHooks();2513 // Unwind the failed stack frame2514 unwindInterruptedWork(unitOfWork);2515 // Restore the original properties of the fiber.2516 assignFiberPropertiesInDEV(unitOfWork, originalWorkInProgressCopy);2517 if (enableProfilerTimer && unitOfWork.mode & ProfileMode) {2518 // Reset the profiler timer.2519 startProfilerTimer(unitOfWork);2520 }2521 // Run beginWork again.2522 invokeGuardedCallback(2523 null,2524 originalBeginWork,2525 null,2526 current,2527 unitOfWork,2528 expirationTime,2529 );2530 if (hasCaughtError()) {2531 const replayError = clearCaughtError();2532 // `invokeGuardedCallback` sometimes sets an expando `_suppressLogging`.2533 // Rethrow this error instead of the original one.2534 throw replayError;2535 } else {2536 // This branch is reachable if the render phase is impure.2537 throw originalError;2538 }2539 }2540 };2541} else {2542 beginWork = originalBeginWork;2543}2544let didWarnAboutUpdateInRender = false;2545let didWarnAboutUpdateInGetChildContext = false;2546function warnAboutInvalidUpdatesOnClassComponentsInDEV(fiber) {2547 if (__DEV__) {2548 if (fiber.tag === ClassComponent) {2549 switch (ReactCurrentDebugFiberPhaseInDEV) {2550 case 'getChildContext':2551 if (didWarnAboutUpdateInGetChildContext) {2552 return;2553 }2554 warningWithoutStack(2555 false,2556 'setState(...): Cannot call setState() inside getChildContext()',2557 );2558 didWarnAboutUpdateInGetChildContext = true;2559 break;2560 case 'render':2561 if (didWarnAboutUpdateInRender) {2562 return;2563 }2564 warningWithoutStack(2565 false,2566 'Cannot update during an existing state transition (such as ' +2567 'within `render`). Render methods should be a pure function of ' +2568 'props and state.',2569 );2570 didWarnAboutUpdateInRender = true;2571 break;2572 }2573 }2574 }2575}2576export const IsThisRendererActing = {current: (false: boolean)};2577export function warnIfNotScopedWithMatchingAct(fiber: Fiber): void {2578 if (__DEV__) {2579 if (2580 warnsIfNotActing === true &&2581 IsSomeRendererActing.current === true &&2582 IsThisRendererActing.current !== true2583 ) {2584 warningWithoutStack(2585 false,2586 "It looks like you're using the wrong act() around your test interactions.\n" +2587 'Be sure to use the matching version of act() corresponding to your renderer:\n\n' +2588 '// for react-dom:\n' +2589 "import {act} from 'react-dom/test-utils';\n" +2590 '//...\n' +2591 'act(() => ...);\n\n' +2592 '// for react-test-renderer:\n' +2593 "import TestRenderer from 'react-test-renderer';\n" +2594 'const {act} = TestRenderer;\n' +2595 '//...\n' +2596 'act(() => ...);' +2597 '%s',2598 getStackByFiberInDevAndProd(fiber),2599 );2600 }2601 }2602}2603export function warnIfNotCurrentlyActingEffectsInDEV(fiber: Fiber): void {2604 if (__DEV__) {2605 if (2606 warnsIfNotActing === true &&2607 (fiber.mode & StrictMode) !== NoMode &&2608 IsSomeRendererActing.current === false &&2609 IsThisRendererActing.current === false2610 ) {2611 warningWithoutStack(2612 false,2613 'An update to %s ran an effect, but was not wrapped in act(...).\n\n' +2614 'When testing, code that causes React state updates should be ' +2615 'wrapped into act(...):\n\n' +2616 'act(() => {\n' +2617 ' /* fire events that update state */\n' +2618 '});\n' +2619 '/* assert on the output */\n\n' +2620 "This ensures that you're testing the behavior the user would see " +2621 'in the browser.' +2622 ' Learn more at https://fb.me/react-wrap-tests-with-act' +2623 '%s',2624 getComponentName(fiber.type),2625 getStackByFiberInDevAndProd(fiber),2626 );2627 }2628 }2629}2630function warnIfNotCurrentlyActingUpdatesInDEV(fiber: Fiber): void {2631 if (__DEV__) {2632 if (2633 warnsIfNotActing === true &&2634 executionContext === NoContext &&2635 IsSomeRendererActing.current === false &&2636 IsThisRendererActing.current === false2637 ) {2638 warningWithoutStack(2639 false,2640 'An update to %s inside a test was not wrapped in act(...).\n\n' +2641 'When testing, code that causes React state updates should be ' +2642 'wrapped into act(...):\n\n' +2643 'act(() => {\n' +2644 ' /* fire events that update state */\n' +2645 '});\n' +2646 '/* assert on the output */\n\n' +2647 "This ensures that you're testing the behavior the user would see " +2648 'in the browser.' +2649 ' Learn more at https://fb.me/react-wrap-tests-with-act' +2650 '%s',2651 getComponentName(fiber.type),2652 getStackByFiberInDevAndProd(fiber),2653 );2654 }2655 }2656}2657export const warnIfNotCurrentlyActingUpdatesInDev = warnIfNotCurrentlyActingUpdatesInDEV;2658let componentsWithSuspendedDiscreteUpdates = null;2659export function checkForWrongSuspensePriorityInDEV(sourceFiber: Fiber) {2660 if (__DEV__) {2661 if (2662 (sourceFiber.mode & ConcurrentMode) !== NoEffect &&2663 // Check if we're currently rendering a discrete update. Ideally, all we2664 // would need to do is check the current priority level. But we currently2665 // have no rigorous way to distinguish work that was scheduled at user-2666 // blocking priority from work that expired a bit and was "upgraded" to2667 // a higher priority. That's because we don't schedule separate callbacks2668 // for every level, only the highest priority level per root. The priority2669 // of subsequent levels is inferred from the expiration time, but this is2670 // an imprecise heuristic.2671 //2672 // However, we do store the last discrete pending update per root. So we2673 // can reliably compare to that one. (If we broaden this warning to include2674 // high pri updates that aren't discrete, then this won't be sufficient.)2675 //2676 // My rationale is that it's better for this warning to have false2677 // negatives than false positives.2678 rootsWithPendingDiscreteUpdates !== null &&2679 workInProgressRoot !== null &&2680 renderExpirationTime ===2681 rootsWithPendingDiscreteUpdates.get(workInProgressRoot)2682 ) {2683 // Add the component name to a set.2684 const componentName = getComponentName(sourceFiber.type);2685 if (componentsWithSuspendedDiscreteUpdates === null) {2686 componentsWithSuspendedDiscreteUpdates = new Set([componentName]);2687 } else {2688 componentsWithSuspendedDiscreteUpdates.add(componentName);2689 }2690 }2691 }2692}2693function flushSuspensePriorityWarningInDEV() {2694 if (__DEV__) {2695 if (componentsWithSuspendedDiscreteUpdates !== null) {2696 const componentNames = [];2697 componentsWithSuspendedDiscreteUpdates.forEach(name => {2698 componentNames.push(name);2699 });2700 componentsWithSuspendedDiscreteUpdates = null;2701 // TODO: A more helpful version of this message could include the names of2702 // the component that were updated, not the ones that suspended. To do2703 // that we'd need to track all the components that updated during this2704 // render, perhaps using the same mechanism as `markRenderEventTime`.2705 warningWithoutStack(2706 false,2707 'The following components suspended during a user-blocking update: %s' +2708 '\n\n' +2709 'Updates triggered by user interactions (e.g. click events) are ' +2710 'considered user-blocking by default. They should not suspend. ' +2711 'Updates that can afford to take a bit longer should be wrapped ' +2712 'with `Scheduler.next` (or an equivalent abstraction). This ' +2713 'typically includes any update that shows new content, like ' +2714 'a navigation.' +2715 '\n\n' +2716 'Generally, you should split user interactions into at least two ' +2717 'seprate updates: a user-blocking update to provide immediate ' +2718 'feedback, and another update to perform the actual change.',2719 // TODO: Add link to React docs with more information, once it exists2720 componentNames.sort().join(', '),2721 );2722 }2723 }2724}2725function computeThreadID(root, expirationTime) {2726 // Interaction threads are unique per root and expiration time.2727 return expirationTime * 1000 + root.interactionThreadID;2728}2729export function markSpawnedWork(expirationTime: ExpirationTime) {2730 if (!enableSchedulerTracing) {2731 return;2732 }2733 if (spawnedWorkDuringRender === null) {2734 spawnedWorkDuringRender = [expirationTime];2735 } else {2736 spawnedWorkDuringRender.push(expirationTime);2737 }2738}2739//与schedule的交互2740function scheduleInteractions(root, expirationTime, interactions) {2741 if (!enableSchedulerTracing) {2742 return;2743 }2744 //当interactions存在时2745 if (interactions.size > 0) {2746 //获取FiberRoot的pendingInteractionMap属性2747 const pendingInteractionMap = root.pendingInteractionMap;2748 //获取pendingInteractions的expirationTime2749 const pendingInteractions = pendingInteractionMap.get(expirationTime);2750 //如果pendingInteractions不为空的话2751 if (pendingInteractions != null) {2752 //遍历并更新还未调度的同步任务的数量2753 interactions.forEach(interaction => {2754 if (!pendingInteractions.has(interaction)) {2755 // Update the pending async work count for previously unscheduled interaction.2756 interaction.__count++;2757 }2758 pendingInteractions.add(interaction);2759 });2760 }2761 //否则初始化pendingInteractionMap2762 //并统计当前调度中同步任务的数量2763 else {2764 pendingInteractionMap.set(expirationTime, new Set(interactions));2765 // Update the pending async work count for the current interactions.2766 interactions.forEach(interaction => {2767 interaction.__count++;2768 });2769 }2770 //计算并得出线程的id2771 const subscriber = __subscriberRef.current;2772 if (subscriber !== null) {2773 //这个暂时不看了2774 const threadID = computeThreadID(root, expirationTime);2775 //检测这些任务是否会报错2776 subscriber.onWorkScheduled(interactions, threadID);2777 }2778 }2779}2780//跟踪这些update,并计数、检测它们是否会报错2781function schedulePendingInteractions(root, expirationTime) {2782 // This is called when work is scheduled on a root.2783 // It associates the current interactions with the newly-scheduled expiration.2784 // They will be restored when that expiration is later committed.2785 //当调度开始时就执行,每调度一个update,就更新跟踪栈2786 if (!enableSchedulerTracing) {2787 return;2788 }2789 //调度的"交互"2790 scheduleInteractions(root, expirationTime, __interactionsRef.current);2791}2792//将调度优先级高的interaction加入到interactions中2793function startWorkOnPendingInteractions(root, expirationTime) {2794 // This is called when new work is started on a root.2795 if (!enableSchedulerTracing) {2796 return;2797 }2798 // Determine which interactions this batch of work currently includes, So that2799 // we can accurately attribute time spent working on it, And so that cascading2800 // work triggered during the render phase will be associated with it.2801 // 确定这批工作当前包括哪些交互,以便我们可以准确地将花费在工作上的时间归因于此,以便在渲染阶段触发的级联工作将与之相关联。2802 const interactions: Set<Interaction> = new Set();2803 root.pendingInteractionMap.forEach(2804 (scheduledInteractions, scheduledExpirationTime) => {...

Full Screen

Full Screen

ReactFiberWorkLoop.new.js

Source:ReactFiberWorkLoop.new.js Github

copy

Full Screen

...1829 if (spawnedWorkDuringRender !== null) {1830 const expirationTimes = spawnedWorkDuringRender;1831 spawnedWorkDuringRender = null;1832 for (let i = 0; i < expirationTimes.length; i++) {1833 scheduleInteractions(1834 root,1835 expirationTimes[i],1836 root.memoizedInteractions,1837 );1838 }1839 }1840 schedulePendingInteractions(root, remainingLanes);1841 }1842 } else {1843 // If there's no remaining work, we can clear the set of already failed1844 // error boundaries.1845 legacyErrorBoundariesThatAlreadyFailed = null;1846 }1847 if (__DEV__ && enableDoubleInvokingEffects) {1848 if (!rootDidHavePassiveEffects) {1849 commitDoubleInvokeEffectsInDEV(root.current, false);1850 }1851 }1852 if (enableSchedulerTracing) {1853 if (!rootDidHavePassiveEffects) {1854 // If there are no passive effects, then we can complete the pending interactions.1855 // Otherwise, we'll wait until after the passive effects are flushed.1856 // Wait to do this until after remaining work has been scheduled,1857 // so that we don't prematurely signal complete for interactions when there's e.g. hidden work.1858 finishPendingInteractions(root, lanes);1859 }1860 }1861 if (remainingLanes === SyncLane) {1862 // Count the number of times the root synchronously re-renders without1863 // finishing. If there are too many, it indicates an infinite update loop.1864 if (root === rootWithNestedUpdates) {1865 nestedUpdateCount++;1866 } else {1867 nestedUpdateCount = 0;1868 rootWithNestedUpdates = root;1869 }1870 } else {1871 nestedUpdateCount = 0;1872 }1873 onCommitRootDevTools(finishedWork.stateNode, renderPriorityLevel);1874 if (__DEV__) {1875 onCommitRootTestSelector();1876 }1877 // Always call this before exiting `commitRoot`, to ensure that any1878 // additional work on this root is scheduled.1879 ensureRootIsScheduled(root, now());1880 if (hasUncaughtError) {1881 hasUncaughtError = false;1882 const error = firstUncaughtError;1883 firstUncaughtError = null;1884 throw error;1885 }1886 if ((executionContext & LegacyUnbatchedContext) !== NoContext) {1887 if (__DEV__) {1888 if (enableDebugTracing) {1889 logCommitStopped();1890 }1891 }1892 if (enableSchedulingProfiler) {1893 markCommitStopped();1894 }1895 // This is a legacy edge case. We just committed the initial mount of1896 // a ReactDOM.render-ed root inside of batchedUpdates. The commit fired1897 // synchronously, but layout updates should be deferred until the end1898 // of the batch.1899 return null;1900 }1901 // If layout work was scheduled, flush it now.1902 flushSyncCallbackQueue();1903 if (__DEV__) {1904 if (enableDebugTracing) {1905 logCommitStopped();1906 }1907 }1908 if (enableSchedulingProfiler) {1909 markCommitStopped();1910 }1911 return null;1912}1913function commitBeforeMutationEffects(firstChild: Fiber) {1914 let fiber = firstChild;1915 while (fiber !== null) {1916 // 处理需要删除的fiber autoFocus、blur 逻辑。1917 if (fiber.deletions !== null) {1918 commitBeforeMutationEffectsDeletions(fiber.deletions);1919 }1920 // 递归调用处理子节点1921 if (fiber.child !== null) {1922 const primarySubtreeFlags = fiber.subtreeFlags & BeforeMutationMask;1923 if (primarySubtreeFlags !== NoFlags) {1924 commitBeforeMutationEffects(fiber.child);1925 }1926 }1927 if (__DEV__) {1928 setCurrentDebugFiberInDEV(fiber);1929 invokeGuardedCallback(null, commitBeforeMutationEffectsImpl, null, fiber);1930 if (hasCaughtError()) {1931 const error = clearCaughtError();1932 captureCommitPhaseError(fiber, fiber.return, error);1933 }1934 resetCurrentDebugFiberInDEV();1935 } else {1936 try {1937 // 调用 getSnapshotBeforeUpdate 生命周期1938 // 异步调度useEffect1939 commitBeforeMutationEffectsImpl(fiber);1940 } catch (error) {1941 captureCommitPhaseError(fiber, fiber.return, error);1942 }1943 }1944 // 返回兄弟节点,接着循环1945 fiber = fiber.sibling;1946 }1947}1948function commitBeforeMutationEffectsImpl(fiber: Fiber) {1949 const current = fiber.alternate;1950 const flags = fiber.flags;1951 if (!shouldFireAfterActiveInstanceBlur && focusedInstanceHandle !== null) {1952 // Check to see if the focused element was inside of a hidden (Suspense) subtree.1953 // TODO: Move this out of the hot path using a dedicated effect tag.1954 if (1955 fiber.tag === SuspenseComponent &&1956 isSuspenseBoundaryBeingHidden(current, fiber) &&1957 doesFiberContain(fiber, focusedInstanceHandle)1958 ) {1959 shouldFireAfterActiveInstanceBlur = true;1960 beforeActiveInstanceBlur();1961 }1962 }1963 if ((flags & Snapshot) !== NoFlags) {1964 setCurrentDebugFiberInDEV(fiber);1965 // 调用 getSnapshotBeforeUpdate 生命周期1966 commitBeforeMutationEffectOnFiber(current, fiber);1967 resetCurrentDebugFiberInDEV();1968 }1969 // 调度useEffect1970 if ((flags & Passive) !== NoFlags) {1971 // If there are passive effects, schedule a callback to flush at1972 // the earliest opportunity.1973 if (!rootDoesHavePassiveEffects) {1974 rootDoesHavePassiveEffects = true;1975 scheduleCallback(NormalSchedulerPriority, () => {1976 flushPassiveEffects();1977 return null;1978 });1979 }1980 }1981}1982function commitBeforeMutationEffectsDeletions(deletions: Array<Fiber>) {1983 for (let i = 0; i < deletions.length; i++) {1984 const fiber = deletions[i];1985 // TODO (effects) It would be nice to avoid calling doesFiberContain()1986 // Maybe we can repurpose one of the subtreeFlags positions for this instead?1987 // Use it to store which part of the tree the focused instance is in?1988 // This assumes we can safely determine that instance during the "render" phase.1989 if (doesFiberContain(fiber, ((focusedInstanceHandle: any): Fiber))) {1990 shouldFireAfterActiveInstanceBlur = true;1991 beforeActiveInstanceBlur();1992 }1993 }1994}1995function commitMutationEffects(1996 firstChild: Fiber,1997 root: FiberRoot,1998 renderPriorityLevel: ReactPriorityLevel,1999) {2000 let fiber = firstChild;2001 while (fiber !== null) {2002 const deletions = fiber.deletions;2003 if (deletions !== null) {2004 commitMutationEffectsDeletions(2005 deletions,2006 fiber,2007 root,2008 renderPriorityLevel,2009 );2010 }2011 if (fiber.child !== null) {2012 const mutationFlags = fiber.subtreeFlags & MutationMask;2013 if (mutationFlags !== NoFlags) {2014 commitMutationEffects(fiber.child, root, renderPriorityLevel);2015 }2016 }2017 if (__DEV__) {2018 setCurrentDebugFiberInDEV(fiber);2019 invokeGuardedCallback(2020 null,2021 commitMutationEffectsImpl,2022 null,2023 fiber,2024 root,2025 renderPriorityLevel,2026 );2027 if (hasCaughtError()) {2028 const error = clearCaughtError();2029 captureCommitPhaseError(fiber, fiber.return, error);2030 }2031 resetCurrentDebugFiberInDEV();2032 } else {2033 try {2034 commitMutationEffectsImpl(fiber, root, renderPriorityLevel);2035 } catch (error) {2036 captureCommitPhaseError(fiber, fiber.return, error);2037 }2038 }2039 fiber = fiber.sibling;2040 }2041}2042function commitMutationEffectsImpl(2043 fiber: Fiber,2044 root: FiberRoot,2045 renderPriorityLevel,2046) {2047 const flags = fiber.flags;2048 if (flags & ContentReset) {2049 commitResetTextContent(fiber);2050 }2051 if (flags & Ref) {2052 const current = fiber.alternate;2053 if (current !== null) {2054 commitDetachRef(current);2055 }2056 if (enableScopeAPI) {2057 // TODO: This is a temporary solution that allowed us to transition away from React Flare on www.2058 if (fiber.tag === ScopeComponent) {2059 commitAttachRef(fiber);2060 }2061 }2062 }2063 // The following switch statement is only concerned about placement,2064 // updates, and deletions. To avoid needing to add a case for every possible2065 // bitmap value, we remove the secondary effects from the effect tag and2066 // switch on that value.2067 const primaryFlags = flags & (Placement | Update | Hydrating);2068 switch (primaryFlags) {2069 case Placement: {2070 commitPlacement(fiber);2071 // Clear the "placement" from effect tag so that we know that this is2072 // inserted, before any life-cycles like componentDidMount gets called.2073 // TODO: findDOMNode doesn't rely on this any more but isMounted does2074 // and isMounted is deprecated anyway so we should be able to kill this.2075 fiber.flags &= ~Placement;2076 break;2077 }2078 case PlacementAndUpdate: {2079 // Placement2080 commitPlacement(fiber);2081 // Clear the "placement" from effect tag so that we know that this is2082 // inserted, before any life-cycles like componentDidMount gets called.2083 fiber.flags &= ~Placement;2084 // Update2085 const current = fiber.alternate;2086 commitWork(current, fiber);2087 break;2088 }2089 case Hydrating: {2090 fiber.flags &= ~Hydrating;2091 break;2092 }2093 case HydratingAndUpdate: {2094 fiber.flags &= ~Hydrating;2095 // Update2096 const current = fiber.alternate;2097 commitWork(current, fiber);2098 break;2099 }2100 case Update: {2101 const current = fiber.alternate;2102 commitWork(current, fiber);2103 break;2104 }2105 }2106}2107function commitMutationEffectsDeletions(2108 deletions: Array<Fiber>,2109 nearestMountedAncestor: Fiber,2110 root: FiberRoot,2111 renderPriorityLevel,2112) {2113 for (let i = 0; i < deletions.length; i++) {2114 const childToDelete = deletions[i];2115 if (__DEV__) {2116 invokeGuardedCallback(2117 null,2118 commitDeletion,2119 null,2120 root,2121 childToDelete,2122 nearestMountedAncestor,2123 renderPriorityLevel,2124 );2125 if (hasCaughtError()) {2126 const error = clearCaughtError();2127 captureCommitPhaseError(childToDelete, nearestMountedAncestor, error);2128 }2129 } else {2130 try {2131 commitDeletion(2132 root,2133 childToDelete,2134 nearestMountedAncestor,2135 renderPriorityLevel,2136 );2137 } catch (error) {2138 captureCommitPhaseError(childToDelete, nearestMountedAncestor, error);2139 }2140 }2141 }2142}2143export function schedulePassiveEffectCallback() {2144 if (!rootDoesHavePassiveEffects) {2145 rootDoesHavePassiveEffects = true;2146 scheduleCallback(NormalSchedulerPriority, () => {2147 flushPassiveEffects();2148 return null;2149 });2150 }2151}2152export function flushPassiveEffects(): boolean {2153 // Returns whether passive effects were flushed.2154 if (pendingPassiveEffectsRenderPriority !== NoSchedulerPriority) {2155 const priorityLevel =2156 pendingPassiveEffectsRenderPriority > NormalSchedulerPriority2157 ? NormalSchedulerPriority2158 : pendingPassiveEffectsRenderPriority;2159 pendingPassiveEffectsRenderPriority = NoSchedulerPriority;2160 if (decoupleUpdatePriorityFromScheduler) {2161 const previousLanePriority = getCurrentUpdateLanePriority();2162 try {2163 setCurrentUpdateLanePriority(2164 schedulerPriorityToLanePriority(priorityLevel),2165 );2166 return runWithPriority(priorityLevel, flushPassiveEffectsImpl);2167 } finally {2168 setCurrentUpdateLanePriority(previousLanePriority);2169 }2170 } else {2171 return runWithPriority(priorityLevel, flushPassiveEffectsImpl);2172 }2173 }2174 return false;2175}2176function flushPassiveMountEffects(root, firstChild: Fiber): void {2177 let fiber = firstChild;2178 while (fiber !== null) {2179 let prevProfilerOnStack = null;2180 if (enableProfilerTimer && enableProfilerCommitHooks) {2181 if (fiber.tag === Profiler) {2182 prevProfilerOnStack = nearestProfilerOnStack;2183 nearestProfilerOnStack = fiber;2184 }2185 }2186 const primarySubtreeFlags = fiber.subtreeFlags & PassiveMask;2187 if (fiber.child !== null && primarySubtreeFlags !== NoFlags) {2188 flushPassiveMountEffects(root, fiber.child);2189 }2190 if ((fiber.flags & Passive) !== NoFlags) {2191 if (__DEV__) {2192 setCurrentDebugFiberInDEV(fiber);2193 invokeGuardedCallback(2194 null,2195 commitPassiveMountOnFiber,2196 null,2197 root,2198 fiber,2199 );2200 if (hasCaughtError()) {2201 const error = clearCaughtError();2202 captureCommitPhaseError(fiber, fiber.return, error);2203 }2204 resetCurrentDebugFiberInDEV();2205 } else {2206 try {2207 commitPassiveMountOnFiber(root, fiber);2208 } catch (error) {2209 captureCommitPhaseError(fiber, fiber.return, error);2210 }2211 }2212 }2213 if (enableProfilerTimer && enableProfilerCommitHooks) {2214 if (fiber.tag === Profiler) {2215 // Bubble times to the next nearest ancestor Profiler.2216 // After we process that Profiler, we'll bubble further up.2217 if (prevProfilerOnStack !== null) {2218 prevProfilerOnStack.stateNode.passiveEffectDuration +=2219 fiber.stateNode.passiveEffectDuration;2220 }2221 nearestProfilerOnStack = prevProfilerOnStack;2222 }2223 }2224 fiber = fiber.sibling;2225 }2226}2227function flushPassiveUnmountEffects(firstChild: Fiber): void {2228 let fiber = firstChild;2229 while (fiber !== null) {2230 const deletions = fiber.deletions;2231 if (deletions !== null) {2232 for (let i = 0; i < deletions.length; i++) {2233 const fiberToDelete = deletions[i];2234 flushPassiveUnmountEffectsInsideOfDeletedTree(fiberToDelete, fiber);2235 // Now that passive effects have been processed, it's safe to detach lingering pointers.2236 detachFiberAfterEffects(fiberToDelete);2237 }2238 }2239 const child = fiber.child;2240 if (child !== null) {2241 // If any children have passive effects then traverse the subtree.2242 // Note that this requires checking subtreeFlags of the current Fiber,2243 // rather than the subtreeFlags/effectsTag of the first child,2244 // since that would not cover passive effects in siblings.2245 const passiveFlags = fiber.subtreeFlags & PassiveMask;2246 if (passiveFlags !== NoFlags) {2247 flushPassiveUnmountEffects(child);2248 }2249 }2250 const primaryFlags = fiber.flags & Passive;2251 if (primaryFlags !== NoFlags) {2252 setCurrentDebugFiberInDEV(fiber);2253 commitPassiveUnmountOnFiber(fiber);2254 resetCurrentDebugFiberInDEV();2255 }2256 fiber = fiber.sibling;2257 }2258}2259function flushPassiveUnmountEffectsInsideOfDeletedTree(2260 fiberToDelete: Fiber,2261 nearestMountedAncestor: Fiber,2262): void {2263 if ((fiberToDelete.subtreeFlags & PassiveStatic) !== NoFlags) {2264 // If any children have passive effects then traverse the subtree.2265 // Note that this requires checking subtreeFlags of the current Fiber,2266 // rather than the subtreeFlags/effectsTag of the first child,2267 // since that would not cover passive effects in siblings.2268 let child = fiberToDelete.child;2269 while (child !== null) {2270 flushPassiveUnmountEffectsInsideOfDeletedTree(2271 child,2272 nearestMountedAncestor,2273 );2274 child = child.sibling;2275 }2276 }2277 if ((fiberToDelete.flags & PassiveStatic) !== NoFlags) {2278 setCurrentDebugFiberInDEV(fiberToDelete);2279 commitPassiveUnmountInsideDeletedTreeOnFiber(2280 fiberToDelete,2281 nearestMountedAncestor,2282 );2283 resetCurrentDebugFiberInDEV();2284 }2285}2286function flushPassiveEffectsImpl() {2287 if (rootWithPendingPassiveEffects === null) {2288 return false;2289 }2290 const root = rootWithPendingPassiveEffects;2291 const lanes = pendingPassiveEffectsLanes;2292 rootWithPendingPassiveEffects = null;2293 pendingPassiveEffectsLanes = NoLanes;2294 invariant(2295 (executionContext & (RenderContext | CommitContext)) === NoContext,2296 'Cannot flush passive effects while already rendering.',2297 );2298 if (__DEV__) {2299 if (enableDebugTracing) {2300 logPassiveEffectsStarted(lanes);2301 }2302 }2303 if (enableSchedulingProfiler) {2304 markPassiveEffectsStarted(lanes);2305 }2306 if (__DEV__) {2307 isFlushingPassiveEffects = true;2308 }2309 const prevExecutionContext = executionContext;2310 executionContext |= CommitContext;2311 const prevInteractions = pushInteractions(root);2312 // It's important that ALL pending passive effect destroy functions are called2313 // before ANY passive effect create functions are called.2314 // Otherwise effects in sibling components might interfere with each other.2315 // e.g. a destroy function in one component may unintentionally override a ref2316 // value set by a create function in another component.2317 // Layout effects have the same constraint.2318 flushPassiveUnmountEffects(root.current);2319 flushPassiveMountEffects(root, root.current);2320 if (__DEV__) {2321 if (enableDebugTracing) {2322 logPassiveEffectsStopped();2323 }2324 }2325 if (enableSchedulingProfiler) {2326 markPassiveEffectsStopped();2327 }2328 if (__DEV__ && enableDoubleInvokingEffects) {2329 commitDoubleInvokeEffectsInDEV(root.current, true);2330 }2331 if (__DEV__) {2332 isFlushingPassiveEffects = false;2333 }2334 if (enableSchedulerTracing) {2335 popInteractions(((prevInteractions: any): Set<Interaction>));2336 finishPendingInteractions(root, lanes);2337 }2338 executionContext = prevExecutionContext;2339 flushSyncCallbackQueue();2340 // If additional passive effects were scheduled, increment a counter. If this2341 // exceeds the limit, we'll fire a warning.2342 nestedPassiveUpdateCount =2343 rootWithPendingPassiveEffects === null ? 0 : nestedPassiveUpdateCount + 1;2344 return true;2345}2346export function isAlreadyFailedLegacyErrorBoundary(instance: mixed): boolean {2347 return (2348 legacyErrorBoundariesThatAlreadyFailed !== null &&2349 legacyErrorBoundariesThatAlreadyFailed.has(instance)2350 );2351}2352export function markLegacyErrorBoundaryAsFailed(instance: mixed) {2353 if (legacyErrorBoundariesThatAlreadyFailed === null) {2354 legacyErrorBoundariesThatAlreadyFailed = new Set([instance]);2355 } else {2356 legacyErrorBoundariesThatAlreadyFailed.add(instance);2357 }2358}2359function prepareToThrowUncaughtError(error: mixed) {2360 if (!hasUncaughtError) {2361 hasUncaughtError = true;2362 firstUncaughtError = error;2363 }2364}2365export const onUncaughtError = prepareToThrowUncaughtError;2366function captureCommitPhaseErrorOnRoot(2367 rootFiber: Fiber,2368 sourceFiber: Fiber,2369 error: mixed,2370) {2371 const errorInfo = createCapturedValue(error, sourceFiber);2372 const update = createRootErrorUpdate(rootFiber, errorInfo, (SyncLane: Lane));2373 enqueueUpdate(rootFiber, update);2374 const eventTime = requestEventTime();2375 const root = markUpdateLaneFromFiberToRoot(rootFiber, (SyncLane: Lane));2376 if (root !== null) {2377 markRootUpdated(root, SyncLane, eventTime);2378 ensureRootIsScheduled(root, eventTime);2379 schedulePendingInteractions(root, SyncLane);2380 }2381}2382export function captureCommitPhaseError(2383 sourceFiber: Fiber,2384 nearestMountedAncestor: Fiber | null,2385 error: mixed,2386) {2387 if (sourceFiber.tag === HostRoot) {2388 // Error was thrown at the root. There is no parent, so the root2389 // itself should capture it.2390 captureCommitPhaseErrorOnRoot(sourceFiber, sourceFiber, error);2391 return;2392 }2393 let fiber = null;2394 if (skipUnmountedBoundaries) {2395 fiber = nearestMountedAncestor;2396 } else {2397 fiber = sourceFiber.return;2398 }2399 while (fiber !== null) {2400 if (fiber.tag === HostRoot) {2401 captureCommitPhaseErrorOnRoot(fiber, sourceFiber, error);2402 return;2403 } else if (fiber.tag === ClassComponent) {2404 const ctor = fiber.type;2405 const instance = fiber.stateNode;2406 if (2407 typeof ctor.getDerivedStateFromError === 'function' ||2408 (typeof instance.componentDidCatch === 'function' &&2409 !isAlreadyFailedLegacyErrorBoundary(instance))2410 ) {2411 const errorInfo = createCapturedValue(error, sourceFiber);2412 const update = createClassErrorUpdate(2413 fiber,2414 errorInfo,2415 (SyncLane: Lane),2416 );2417 enqueueUpdate(fiber, update);2418 const eventTime = requestEventTime();2419 const root = markUpdateLaneFromFiberToRoot(fiber, (SyncLane: Lane));2420 if (root !== null) {2421 markRootUpdated(root, SyncLane, eventTime);2422 ensureRootIsScheduled(root, eventTime);2423 schedulePendingInteractions(root, SyncLane);2424 }2425 return;2426 }2427 }2428 fiber = fiber.return;2429 }2430}2431export function pingSuspendedRoot(2432 root: FiberRoot,2433 wakeable: Wakeable,2434 pingedLanes: Lanes,2435) {2436 const pingCache = root.pingCache;2437 if (pingCache !== null) {2438 // The wakeable resolved, so we no longer need to memoize, because it will2439 // never be thrown again.2440 pingCache.delete(wakeable);2441 }2442 const eventTime = requestEventTime();2443 markRootPinged(root, pingedLanes, eventTime);2444 if (2445 workInProgressRoot === root &&2446 isSubsetOfLanes(workInProgressRootRenderLanes, pingedLanes)2447 ) {2448 // Received a ping at the same priority level at which we're currently2449 // rendering. We might want to restart this render. This should mirror2450 // the logic of whether or not a root suspends once it completes.2451 // TODO: If we're rendering sync either due to Sync, Batched or expired,2452 // we should probably never restart.2453 // If we're suspended with delay, or if it's a retry, we'll always suspend2454 // so we can always restart.2455 if (2456 workInProgressRootExitStatus === RootSuspendedWithDelay ||2457 (workInProgressRootExitStatus === RootSuspended &&2458 includesOnlyRetries(workInProgressRootRenderLanes) &&2459 now() - globalMostRecentFallbackTime < FALLBACK_THROTTLE_MS)2460 ) {2461 // Restart from the root.2462 prepareFreshStack(root, NoLanes);2463 } else {2464 // Even though we can't restart right now, we might get an2465 // opportunity later. So we mark this render as having a ping.2466 workInProgressRootPingedLanes = mergeLanes(2467 workInProgressRootPingedLanes,2468 pingedLanes,2469 );2470 }2471 }2472 ensureRootIsScheduled(root, eventTime);2473 schedulePendingInteractions(root, pingedLanes);2474}2475function retryTimedOutBoundary(boundaryFiber: Fiber, retryLane: Lane) {2476 // The boundary fiber (a Suspense component or SuspenseList component)2477 // previously was rendered in its fallback state. One of the promises that2478 // suspended it has resolved, which means at least part of the tree was2479 // likely unblocked. Try rendering again, at a new expiration time.2480 if (retryLane === NoLane) {2481 retryLane = requestRetryLane(boundaryFiber);2482 }2483 // TODO: Special case idle priority?2484 const eventTime = requestEventTime();2485 const root = markUpdateLaneFromFiberToRoot(boundaryFiber, retryLane);2486 if (root !== null) {2487 markRootUpdated(root, retryLane, eventTime);2488 ensureRootIsScheduled(root, eventTime);2489 schedulePendingInteractions(root, retryLane);2490 }2491}2492export function retryDehydratedSuspenseBoundary(boundaryFiber: Fiber) {2493 const suspenseState: null | SuspenseState = boundaryFiber.memoizedState;2494 let retryLane = NoLane;2495 if (suspenseState !== null) {2496 retryLane = suspenseState.retryLane;2497 }2498 retryTimedOutBoundary(boundaryFiber, retryLane);2499}2500export function resolveRetryWakeable(boundaryFiber: Fiber, wakeable: Wakeable) {2501 let retryLane = NoLane; // Default2502 let retryCache: WeakSet<Wakeable> | Set<Wakeable> | null;2503 if (enableSuspenseServerRenderer) {2504 switch (boundaryFiber.tag) {2505 case SuspenseComponent:2506 retryCache = boundaryFiber.stateNode;2507 const suspenseState: null | SuspenseState = boundaryFiber.memoizedState;2508 if (suspenseState !== null) {2509 retryLane = suspenseState.retryLane;2510 }2511 break;2512 case SuspenseListComponent:2513 retryCache = boundaryFiber.stateNode;2514 break;2515 default:2516 invariant(2517 false,2518 'Pinged unknown suspense boundary type. ' +2519 'This is probably a bug in React.',2520 );2521 }2522 } else {2523 retryCache = boundaryFiber.stateNode;2524 }2525 if (retryCache !== null) {2526 // The wakeable resolved, so we no longer need to memoize, because it will2527 // never be thrown again.2528 retryCache.delete(wakeable);2529 }2530 retryTimedOutBoundary(boundaryFiber, retryLane);2531}2532// Computes the next Just Noticeable Difference (JND) boundary.2533// The theory is that a person can't tell the difference between small differences in time.2534// Therefore, if we wait a bit longer than necessary that won't translate to a noticeable2535// difference in the experience. However, waiting for longer might mean that we can avoid2536// showing an intermediate loading state. The longer we have already waited, the harder it2537// is to tell small differences in time. Therefore, the longer we've already waited,2538// the longer we can wait additionally. At some point we have to give up though.2539// We pick a train model where the next boundary commits at a consistent schedule.2540// These particular numbers are vague estimates. We expect to adjust them based on research.2541function jnd(timeElapsed: number) {2542 return timeElapsed < 1202543 ? 1202544 : timeElapsed < 4802545 ? 4802546 : timeElapsed < 10802547 ? 10802548 : timeElapsed < 19202549 ? 19202550 : timeElapsed < 30002551 ? 30002552 : timeElapsed < 43202553 ? 43202554 : ceil(timeElapsed / 1960) * 1960;2555}2556function checkForNestedUpdates() {2557 if (nestedUpdateCount > NESTED_UPDATE_LIMIT) {2558 nestedUpdateCount = 0;2559 rootWithNestedUpdates = null;2560 invariant(2561 false,2562 'Maximum update depth exceeded. This can happen when a component ' +2563 'repeatedly calls setState inside componentWillUpdate or ' +2564 'componentDidUpdate. React limits the number of nested updates to ' +2565 'prevent infinite loops.',2566 );2567 }2568 if (__DEV__) {2569 if (nestedPassiveUpdateCount > NESTED_PASSIVE_UPDATE_LIMIT) {2570 nestedPassiveUpdateCount = 0;2571 console.error(2572 'Maximum update depth exceeded. This can happen when a component ' +2573 "calls setState inside useEffect, but useEffect either doesn't " +2574 'have a dependency array, or one of the dependencies changes on ' +2575 'every render.',2576 );2577 }2578 }2579}2580function flushRenderPhaseStrictModeWarningsInDEV() {2581 if (__DEV__) {2582 ReactStrictModeWarnings.flushLegacyContextWarning();2583 if (warnAboutDeprecatedLifecycles) {2584 ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings();2585 }2586 }2587}2588function commitDoubleInvokeEffectsInDEV(2589 fiber: Fiber,2590 hasPassiveEffects: boolean,2591) {2592 if (__DEV__ && enableDoubleInvokingEffects) {2593 setCurrentDebugFiberInDEV(fiber);2594 invokeEffectsInDev(fiber, MountLayoutDev, invokeLayoutEffectUnmountInDEV);2595 if (hasPassiveEffects) {2596 invokeEffectsInDev(2597 fiber,2598 MountPassiveDev,2599 invokePassiveEffectUnmountInDEV,2600 );2601 }2602 invokeEffectsInDev(fiber, MountLayoutDev, invokeLayoutEffectMountInDEV);2603 if (hasPassiveEffects) {2604 invokeEffectsInDev(fiber, MountPassiveDev, invokePassiveEffectMountInDEV);2605 }2606 resetCurrentDebugFiberInDEV();2607 }2608}2609function invokeEffectsInDev(2610 firstChild: Fiber,2611 fiberFlags: Flags,2612 invokeEffectFn: (fiber: Fiber) => void,2613): void {2614 if (__DEV__ && enableDoubleInvokingEffects) {2615 let fiber = firstChild;2616 while (fiber !== null) {2617 if (fiber.child !== null) {2618 const primarySubtreeFlag = fiber.subtreeFlags & fiberFlags;2619 if (primarySubtreeFlag !== NoFlags) {2620 invokeEffectsInDev(fiber.child, fiberFlags, invokeEffectFn);2621 }2622 }2623 if ((fiber.flags & fiberFlags) !== NoFlags) {2624 invokeEffectFn(fiber);2625 }2626 fiber = fiber.sibling;2627 }2628 }2629}2630let didWarnStateUpdateForNotYetMountedComponent: Set<string> | null = null;2631function warnAboutUpdateOnNotYetMountedFiberInDEV(fiber) {2632 if (__DEV__) {2633 if ((executionContext & RenderContext) !== NoContext) {2634 // We let the other warning about render phase updates deal with this one.2635 return;2636 }2637 if (!(fiber.mode & (BlockingMode | ConcurrentMode))) {2638 return;2639 }2640 const tag = fiber.tag;2641 if (2642 tag !== IndeterminateComponent &&2643 tag !== HostRoot &&2644 tag !== ClassComponent &&2645 tag !== FunctionComponent &&2646 tag !== ForwardRef &&2647 tag !== MemoComponent &&2648 tag !== SimpleMemoComponent &&2649 tag !== Block2650 ) {2651 // Only warn for user-defined components, not internal ones like Suspense.2652 return;2653 }2654 // We show the whole stack but dedupe on the top component's name because2655 // the problematic code almost always lies inside that component.2656 const componentName = getComponentName(fiber.type) || 'ReactComponent';2657 if (didWarnStateUpdateForNotYetMountedComponent !== null) {2658 if (didWarnStateUpdateForNotYetMountedComponent.has(componentName)) {2659 return;2660 }2661 didWarnStateUpdateForNotYetMountedComponent.add(componentName);2662 } else {2663 didWarnStateUpdateForNotYetMountedComponent = new Set([componentName]);2664 }2665 const previousFiber = ReactCurrentFiberCurrent;2666 try {2667 setCurrentDebugFiberInDEV(fiber);2668 console.error(2669 "Can't perform a React state update on a component that hasn't mounted yet. " +2670 'This indicates that you have a side-effect in your render function that ' +2671 'asynchronously later calls tries to update the component. Move this work to ' +2672 'useEffect instead.',2673 );2674 } finally {2675 if (previousFiber) {2676 setCurrentDebugFiberInDEV(fiber);2677 } else {2678 resetCurrentDebugFiberInDEV();2679 }2680 }2681 }2682}2683let didWarnStateUpdateForUnmountedComponent: Set<string> | null = null;2684function warnAboutUpdateOnUnmountedFiberInDEV(fiber) {2685 if (__DEV__) {2686 const tag = fiber.tag;2687 if (2688 tag !== HostRoot &&2689 tag !== ClassComponent &&2690 tag !== FunctionComponent &&2691 tag !== ForwardRef &&2692 tag !== MemoComponent &&2693 tag !== SimpleMemoComponent &&2694 tag !== Block2695 ) {2696 // Only warn for user-defined components, not internal ones like Suspense.2697 return;2698 }2699 if ((fiber.flags & PassiveStatic) !== NoFlags) {2700 const updateQueue: FunctionComponentUpdateQueue | null = (fiber.updateQueue: any);2701 if (updateQueue !== null) {2702 const lastEffect = updateQueue.lastEffect;2703 if (lastEffect !== null) {2704 const firstEffect = lastEffect.next;2705 let effect = firstEffect;2706 do {2707 if (effect.destroy !== undefined) {2708 if ((effect.tag & HookPassive) !== NoHookEffect) {2709 return;2710 }2711 }2712 effect = effect.next;2713 } while (effect !== firstEffect);2714 }2715 }2716 }2717 // We show the whole stack but dedupe on the top component's name because2718 // the problematic code almost always lies inside that component.2719 const componentName = getComponentName(fiber.type) || 'ReactComponent';2720 if (didWarnStateUpdateForUnmountedComponent !== null) {2721 if (didWarnStateUpdateForUnmountedComponent.has(componentName)) {2722 return;2723 }2724 didWarnStateUpdateForUnmountedComponent.add(componentName);2725 } else {2726 didWarnStateUpdateForUnmountedComponent = new Set([componentName]);2727 }2728 if (isFlushingPassiveEffects) {2729 // Do not warn if we are currently flushing passive effects!2730 //2731 // React can't directly detect a memory leak, but there are some clues that warn about one.2732 // One of these clues is when an unmounted React component tries to update its state.2733 // For example, if a component forgets to remove an event listener when unmounting,2734 // that listener may be called later and try to update state,2735 // at which point React would warn about the potential leak.2736 //2737 // Warning signals are the most useful when they're strong.2738 // (So we should avoid false positive warnings.)2739 // Updating state from within an effect cleanup function is sometimes a necessary pattern, e.g.:2740 // 1. Updating an ancestor that a component had registered itself with on mount.2741 // 2. Resetting state when a component is hidden after going offscreen.2742 } else {2743 const previousFiber = ReactCurrentFiberCurrent;2744 try {2745 setCurrentDebugFiberInDEV(fiber);2746 console.error(2747 "Can't perform a React state update on an unmounted component. This " +2748 'is a no-op, but it indicates a memory leak in your application. To ' +2749 'fix, cancel all subscriptions and asynchronous tasks in %s.',2750 tag === ClassComponent2751 ? 'the componentWillUnmount method'2752 : 'a useEffect cleanup function',2753 );2754 } finally {2755 if (previousFiber) {2756 setCurrentDebugFiberInDEV(fiber);2757 } else {2758 resetCurrentDebugFiberInDEV();2759 }2760 }2761 }2762 }2763}2764let beginWork;2765if (__DEV__ && replayFailedUnitOfWorkWithInvokeGuardedCallback) {2766 const dummyFiber = null;2767 beginWork = (current, unitOfWork, lanes) => {2768 // If a component throws an error, we replay it again in a synchronously2769 // dispatched event, so that the debugger will treat it as an uncaught2770 // error See ReactErrorUtils for more information.2771 // Before entering the begin phase, copy the work-in-progress onto a dummy2772 // fiber. If beginWork throws, we'll use this to reset the state.2773 const originalWorkInProgressCopy = assignFiberPropertiesInDEV(2774 dummyFiber,2775 unitOfWork,2776 );2777 try {2778 return originalBeginWork(current, unitOfWork, lanes);2779 } catch (originalError) {2780 if (2781 originalError !== null &&2782 typeof originalError === 'object' &&2783 typeof originalError.then === 'function'2784 ) {2785 // Don't replay promises. Treat everything else like an error.2786 throw originalError;2787 }2788 // Keep this code in sync with handleError; any changes here must have2789 // corresponding changes there.2790 resetContextDependencies();2791 resetHooksAfterThrow();2792 // Don't reset current debug fiber, since we're about to work on the2793 // same fiber again.2794 // Unwind the failed stack frame2795 unwindInterruptedWork(unitOfWork);2796 // Restore the original properties of the fiber.2797 assignFiberPropertiesInDEV(unitOfWork, originalWorkInProgressCopy);2798 if (enableProfilerTimer && unitOfWork.mode & ProfileMode) {2799 // Reset the profiler timer.2800 startProfilerTimer(unitOfWork);2801 }2802 // Run beginWork again.2803 invokeGuardedCallback(2804 null,2805 originalBeginWork,2806 null,2807 current,2808 unitOfWork,2809 lanes,2810 );2811 if (hasCaughtError()) {2812 const replayError = clearCaughtError();2813 // `invokeGuardedCallback` sometimes sets an expando `_suppressLogging`.2814 // Rethrow this error instead of the original one.2815 throw replayError;2816 } else {2817 // This branch is reachable if the render phase is impure.2818 throw originalError;2819 }2820 }2821 };2822} else {2823 beginWork = originalBeginWork;2824}2825let didWarnAboutUpdateInRender = false;2826let didWarnAboutUpdateInRenderForAnotherComponent;2827if (__DEV__) {2828 didWarnAboutUpdateInRenderForAnotherComponent = new Set();2829}2830function warnAboutRenderPhaseUpdatesInDEV(fiber) {2831 if (__DEV__) {2832 if (2833 ReactCurrentDebugFiberIsRenderingInDEV &&2834 (executionContext & RenderContext) !== NoContext &&2835 !getIsUpdatingOpaqueValueInRenderPhaseInDEV()2836 ) {2837 switch (fiber.tag) {2838 case FunctionComponent:2839 case ForwardRef:2840 case SimpleMemoComponent: {2841 const renderingComponentName =2842 (workInProgress && getComponentName(workInProgress.type)) ||2843 'Unknown';2844 // Dedupe by the rendering component because it's the one that needs to be fixed.2845 const dedupeKey = renderingComponentName;2846 if (!didWarnAboutUpdateInRenderForAnotherComponent.has(dedupeKey)) {2847 didWarnAboutUpdateInRenderForAnotherComponent.add(dedupeKey);2848 const setStateComponentName =2849 getComponentName(fiber.type) || 'Unknown';2850 console.error(2851 'Cannot update a component (`%s`) while rendering a ' +2852 'different component (`%s`). To locate the bad setState() call inside `%s`, ' +2853 'follow the stack trace as described in https://reactjs.org/link/setstate-in-render',2854 setStateComponentName,2855 renderingComponentName,2856 renderingComponentName,2857 );2858 }2859 break;2860 }2861 case ClassComponent: {2862 if (!didWarnAboutUpdateInRender) {2863 console.error(2864 'Cannot update during an existing state transition (such as ' +2865 'within `render`). Render methods should be a pure ' +2866 'function of props and state.',2867 );2868 didWarnAboutUpdateInRender = true;2869 }2870 break;2871 }2872 }2873 }2874 }2875}2876// a 'shared' variable that changes when act() opens/closes in tests.2877export const IsThisRendererActing = {current: (false: boolean)};2878export function warnIfNotScopedWithMatchingAct(fiber: Fiber): void {2879 if (__DEV__) {2880 if (2881 warnsIfNotActing === true &&2882 IsSomeRendererActing.current === true &&2883 IsThisRendererActing.current !== true2884 ) {2885 const previousFiber = ReactCurrentFiberCurrent;2886 try {2887 setCurrentDebugFiberInDEV(fiber);2888 console.error(2889 "It looks like you're using the wrong act() around your test interactions.\n" +2890 'Be sure to use the matching version of act() corresponding to your renderer:\n\n' +2891 '// for react-dom:\n' +2892 // Break up imports to avoid accidentally parsing them as dependencies.2893 'import {act} fr' +2894 "om 'react-dom/test-utils';\n" +2895 '// ...\n' +2896 'act(() => ...);\n\n' +2897 '// for react-test-renderer:\n' +2898 // Break up imports to avoid accidentally parsing them as dependencies.2899 'import TestRenderer fr' +2900 "om react-test-renderer';\n" +2901 'const {act} = TestRenderer;\n' +2902 '// ...\n' +2903 'act(() => ...);',2904 );2905 } finally {2906 if (previousFiber) {2907 setCurrentDebugFiberInDEV(fiber);2908 } else {2909 resetCurrentDebugFiberInDEV();2910 }2911 }2912 }2913 }2914}2915export function warnIfNotCurrentlyActingEffectsInDEV(fiber: Fiber): void {2916 if (__DEV__) {2917 if (2918 warnsIfNotActing === true &&2919 (fiber.mode & StrictMode) !== NoMode &&2920 IsSomeRendererActing.current === false &&2921 IsThisRendererActing.current === false2922 ) {2923 console.error(2924 'An update to %s ran an effect, but was not wrapped in act(...).\n\n' +2925 'When testing, code that causes React state updates should be ' +2926 'wrapped into act(...):\n\n' +2927 'act(() => {\n' +2928 ' /* fire events that update state */\n' +2929 '});\n' +2930 '/* assert on the output */\n\n' +2931 "This ensures that you're testing the behavior the user would see " +2932 'in the browser.' +2933 ' Learn more at https://reactjs.org/link/wrap-tests-with-act',2934 getComponentName(fiber.type),2935 );2936 }2937 }2938}2939function warnIfNotCurrentlyActingUpdatesInDEV(fiber: Fiber): void {2940 if (__DEV__) {2941 if (2942 warnsIfNotActing === true &&2943 executionContext === NoContext &&2944 IsSomeRendererActing.current === false &&2945 IsThisRendererActing.current === false2946 ) {2947 const previousFiber = ReactCurrentFiberCurrent;2948 try {2949 setCurrentDebugFiberInDEV(fiber);2950 console.error(2951 'An update to %s inside a test was not wrapped in act(...).\n\n' +2952 'When testing, code that causes React state updates should be ' +2953 'wrapped into act(...):\n\n' +2954 'act(() => {\n' +2955 ' /* fire events that update state */\n' +2956 '});\n' +2957 '/* assert on the output */\n\n' +2958 "This ensures that you're testing the behavior the user would see " +2959 'in the browser.' +2960 ' Learn more at https://reactjs.org/link/wrap-tests-with-act',2961 getComponentName(fiber.type),2962 );2963 } finally {2964 if (previousFiber) {2965 setCurrentDebugFiberInDEV(fiber);2966 } else {2967 resetCurrentDebugFiberInDEV();2968 }2969 }2970 }2971 }2972}2973export const warnIfNotCurrentlyActingUpdatesInDev = warnIfNotCurrentlyActingUpdatesInDEV;2974// In tests, we want to enforce a mocked scheduler.2975let didWarnAboutUnmockedScheduler = false;2976// TODO Before we release concurrent mode, revisit this and decide whether a mocked2977// scheduler is the actual recommendation. The alternative could be a testing build,2978// a new lib, or whatever; we dunno just yet. This message is for early adopters2979// to get their tests right.2980export function warnIfUnmockedScheduler(fiber: Fiber) {2981 if (__DEV__) {2982 if (2983 didWarnAboutUnmockedScheduler === false &&2984 Scheduler.unstable_flushAllWithoutAsserting === undefined2985 ) {2986 if (fiber.mode & BlockingMode || fiber.mode & ConcurrentMode) {2987 didWarnAboutUnmockedScheduler = true;2988 console.error(2989 'In Concurrent or Sync modes, the "scheduler" module needs to be mocked ' +2990 'to guarantee consistent behaviour across tests and browsers. ' +2991 'For example, with jest: \n' +2992 // Break up requires to avoid accidentally parsing them as dependencies.2993 "jest.mock('scheduler', () => require" +2994 "('scheduler/unstable_mock'));\n\n" +2995 'For more info, visit https://reactjs.org/link/mock-scheduler',2996 );2997 } else if (warnAboutUnmockedScheduler === true) {2998 didWarnAboutUnmockedScheduler = true;2999 console.error(3000 'Starting from React v18, the "scheduler" module will need to be mocked ' +3001 'to guarantee consistent behaviour across tests and browsers. ' +3002 'For example, with jest: \n' +3003 // Break up requires to avoid accidentally parsing them as dependencies.3004 "jest.mock('scheduler', () => require" +3005 "('scheduler/unstable_mock'));\n\n" +3006 'For more info, visit https://reactjs.org/link/mock-scheduler',3007 );3008 }3009 }3010 }3011}3012function computeThreadID(root: FiberRoot, lane: Lane | Lanes) {3013 // Interaction threads are unique per root and expiration time.3014 // NOTE: Intentionally unsound cast. All that matters is that it's a number3015 // and it represents a batch of work. Could make a helper function instead,3016 // but meh this is fine for now.3017 return (lane: any) * 1000 + root.interactionThreadID;3018}3019export function markSpawnedWork(lane: Lane | Lanes) {3020 if (!enableSchedulerTracing) {3021 return;3022 }3023 if (spawnedWorkDuringRender === null) {3024 spawnedWorkDuringRender = [lane];3025 } else {3026 spawnedWorkDuringRender.push(lane);3027 }3028}3029function scheduleInteractions(3030 root: FiberRoot,3031 lane: Lane | Lanes,3032 interactions: Set<Interaction>,3033) {3034 if (!enableSchedulerTracing) {3035 return;3036 }3037 if (interactions.size > 0) {3038 const pendingInteractionMap = root.pendingInteractionMap;3039 const pendingInteractions = pendingInteractionMap.get(lane);3040 if (pendingInteractions != null) {3041 interactions.forEach(interaction => {3042 if (!pendingInteractions.has(interaction)) {3043 // Update the pending async work count for previously unscheduled interaction.3044 interaction.__count++;3045 }3046 pendingInteractions.add(interaction);3047 });3048 } else {3049 pendingInteractionMap.set(lane, new Set(interactions));3050 // Update the pending async work count for the current interactions.3051 interactions.forEach(interaction => {3052 interaction.__count++;3053 });3054 }3055 const subscriber = __subscriberRef.current;3056 if (subscriber !== null) {3057 const threadID = computeThreadID(root, lane);3058 subscriber.onWorkScheduled(interactions, threadID);3059 }3060 }3061}3062function schedulePendingInteractions(root: FiberRoot, lane: Lane | Lanes) {3063 // This is called when work is scheduled on a root.3064 // It associates the current interactions with the newly-scheduled expiration.3065 // They will be restored when that expiration is later committed.3066 if (!enableSchedulerTracing) {3067 return;3068 }3069 scheduleInteractions(root, lane, __interactionsRef.current);3070}3071function startWorkOnPendingInteractions(root: FiberRoot, lanes: Lanes) {3072 // This is called when new work is started on a root.3073 if (!enableSchedulerTracing) {3074 return;3075 }3076 // Determine which interactions this batch of work currently includes, So that3077 // we can accurately attribute time spent working on it, And so that cascading3078 // work triggered during the render phase will be associated with it.3079 const interactions: Set<Interaction> = new Set();3080 root.pendingInteractionMap.forEach((scheduledInteractions, scheduledLane) => {3081 if (includesSomeLane(lanes, scheduledLane)) {3082 scheduledInteractions.forEach(interaction =>3083 interactions.add(interaction),...

Full Screen

Full Screen

ReactFiberWorkLoop.old.js

Source:ReactFiberWorkLoop.old.js Github

copy

Full Screen

...1346 if (spawnedWorkDuringRender !== null) {1347 var expirationTimes = spawnedWorkDuringRender;1348 spawnedWorkDuringRender = null;1349 for (var i = 0; i < expirationTimes.length; i++) {1350 scheduleInteractions(root, expirationTimes[i], root.memoizedInteractions);1351 }1352 }1353 schedulePendingInteractions(root, remainingLanes);1354 }1355 } else {1356 // If there's no remaining work, we can clear the set of already failed1357 // error boundaries.1358 legacyErrorBoundariesThatAlreadyFailed = null;1359 }1360 {1361 if (!rootDidHavePassiveEffects) {1362 // If there are no passive effects, then we can complete the pending interactions.1363 // Otherwise, we'll wait until after the passive effects are flushed.1364 // Wait to do this until after remaining work has been scheduled,1365 // so that we don't prematurely signal complete for interactions when there's e.g. hidden work.1366 finishPendingInteractions(root, lanes);1367 }1368 }1369 if (remainingLanes === SyncLane) {1370 // Count the number of times the root synchronously re-renders without1371 // finishing. If there are too many, it indicates an infinite update loop.1372 if (root === rootWithNestedUpdates) {1373 nestedUpdateCount++;1374 } else {1375 nestedUpdateCount = 0;1376 rootWithNestedUpdates = root;1377 }1378 } else {1379 nestedUpdateCount = 0;1380 }1381 onCommitRoot(finishedWork.stateNode, renderPriorityLevel);1382 {1383 onCommitRoot$1();1384 } // Always call this before exiting `commitRoot`, to ensure that any1385 // additional work on this root is scheduled.1386 ensureRootIsScheduled(root, now());1387 if (hasUncaughtError) {1388 hasUncaughtError = false;1389 var _error3 = firstUncaughtError;1390 firstUncaughtError = null;1391 throw _error3;1392 }1393 if ((executionContext & LegacyUnbatchedContext) !== NoContext) {1394 {1395 markCommitStopped();1396 } // This is a legacy edge case. We just committed the initial mount of1397 // a ReactDOM.render-ed root inside of batchedUpdates. The commit fired1398 // synchronously, but layout updates should be deferred until the end1399 // of the batch.1400 return null;1401 } // If layout work was scheduled, flush it now.1402 flushSyncCallbackQueue();1403 {1404 markCommitStopped();1405 }1406 return null;1407 }1408 function commitBeforeMutationEffects() {1409 while (nextEffect !== null) {1410 var current = nextEffect.alternate;1411 if (!shouldFireAfterActiveInstanceBlur && focusedInstanceHandle !== null) {1412 if ((nextEffect.flags & Deletion) !== NoFlags) {1413 if (doesFiberContain(nextEffect, focusedInstanceHandle)) {1414 shouldFireAfterActiveInstanceBlur = true;1415 }1416 } else {1417 // TODO: Move this out of the hot path using a dedicated effect tag.1418 if (nextEffect.tag === SuspenseComponent && isSuspenseBoundaryBeingHidden(current, nextEffect) && doesFiberContain(nextEffect, focusedInstanceHandle)) {1419 shouldFireAfterActiveInstanceBlur = true;1420 }1421 }1422 }1423 var flags = nextEffect.flags;1424 if ((flags & Snapshot) !== NoFlags) {1425 setCurrentFiber(nextEffect);1426 commitBeforeMutationLifeCycles(current, nextEffect);1427 resetCurrentFiber();1428 }1429 if ((flags & Passive) !== NoFlags) {1430 // If there are passive effects, schedule a callback to flush at1431 // the earliest opportunity.1432 if (!rootDoesHavePassiveEffects) {1433 rootDoesHavePassiveEffects = true;1434 scheduleCallback(NormalPriority$1, function () {1435 flushPassiveEffects();1436 return null;1437 });1438 }1439 }1440 nextEffect = nextEffect.nextEffect;1441 }1442 }1443 function commitMutationEffects(root, renderPriorityLevel) {1444 // TODO: Should probably move the bulk of this function to commitWork.1445 while (nextEffect !== null) {1446 setCurrentFiber(nextEffect);1447 var flags = nextEffect.flags;1448 if (flags & ContentReset) {1449 commitResetTextContent(nextEffect);1450 }1451 if (flags & Ref) {1452 var current = nextEffect.alternate;1453 if (current !== null) {1454 commitDetachRef(current);1455 }1456 } // The following switch statement is only concerned about placement,1457 // updates, and deletions. To avoid needing to add a case for every possible1458 // bitmap value, we remove the secondary effects from the effect tag and1459 // switch on that value.1460 var primaryFlags = flags & (Placement | Update | Deletion | Hydrating);1461 switch (primaryFlags) {1462 case Placement:1463 {1464 commitPlacement(nextEffect); // Clear the "placement" from effect tag so that we know that this is1465 // inserted, before any life-cycles like componentDidMount gets called.1466 // TODO: findDOMNode doesn't rely on this any more but isMounted does1467 // and isMounted is deprecated anyway so we should be able to kill this.1468 nextEffect.flags &= ~Placement;1469 break;1470 }1471 case PlacementAndUpdate:1472 {1473 // Placement1474 commitPlacement(nextEffect); // Clear the "placement" from effect tag so that we know that this is1475 // inserted, before any life-cycles like componentDidMount gets called.1476 nextEffect.flags &= ~Placement; // Update1477 var _current = nextEffect.alternate;1478 commitWork(_current, nextEffect);1479 break;1480 }1481 case Hydrating:1482 {1483 nextEffect.flags &= ~Hydrating;1484 break;1485 }1486 case HydratingAndUpdate:1487 {1488 nextEffect.flags &= ~Hydrating; // Update1489 var _current2 = nextEffect.alternate;1490 commitWork(_current2, nextEffect);1491 break;1492 }1493 case Update:1494 {1495 var _current3 = nextEffect.alternate;1496 commitWork(_current3, nextEffect);1497 break;1498 }1499 case Deletion:1500 {1501 commitDeletion(root, nextEffect);1502 break;1503 }1504 }1505 resetCurrentFiber();1506 nextEffect = nextEffect.nextEffect;1507 }1508 }1509 function commitLayoutEffects(root, committedLanes) {1510 {1511 markLayoutEffectsStarted(committedLanes);1512 } // TODO: Should probably move the bulk of this function to commitWork.1513 while (nextEffect !== null) {1514 setCurrentFiber(nextEffect);1515 var flags = nextEffect.flags;1516 if (flags & (Update | Callback)) {1517 var current = nextEffect.alternate;1518 commitLifeCycles(root, current, nextEffect);1519 }1520 {1521 if (flags & Ref) {1522 commitAttachRef(nextEffect);1523 }1524 }1525 resetCurrentFiber();1526 nextEffect = nextEffect.nextEffect;1527 }1528 {1529 markLayoutEffectsStopped();1530 }1531 }1532 function flushPassiveEffects() {1533 // Returns whether passive effects were flushed.1534 if (pendingPassiveEffectsRenderPriority !== NoPriority$1) {1535 var priorityLevel = pendingPassiveEffectsRenderPriority > NormalPriority$1 ? NormalPriority$1 : pendingPassiveEffectsRenderPriority;1536 pendingPassiveEffectsRenderPriority = NoPriority$1;1537 {1538 return runWithPriority$1(priorityLevel, flushPassiveEffectsImpl);1539 }1540 }1541 return false;1542 }1543 function enqueuePendingPassiveHookEffectMount(fiber, effect) {1544 pendingPassiveHookEffectsMount.push(effect, fiber);1545 if (!rootDoesHavePassiveEffects) {1546 rootDoesHavePassiveEffects = true;1547 scheduleCallback(NormalPriority$1, function () {1548 flushPassiveEffects();1549 return null;1550 });1551 }1552 }1553 function enqueuePendingPassiveHookEffectUnmount(fiber, effect) {1554 pendingPassiveHookEffectsUnmount.push(effect, fiber);1555 {1556 fiber.flags |= PassiveUnmountPendingDev;1557 var alternate = fiber.alternate;1558 if (alternate !== null) {1559 alternate.flags |= PassiveUnmountPendingDev;1560 }1561 }1562 if (!rootDoesHavePassiveEffects) {1563 rootDoesHavePassiveEffects = true;1564 scheduleCallback(NormalPriority$1, function () {1565 flushPassiveEffects();1566 return null;1567 });1568 }1569 }1570 function invokePassiveEffectCreate(effect) {1571 var create = effect.create;1572 effect.destroy = create();1573 }1574 function flushPassiveEffectsImpl() {1575 if (rootWithPendingPassiveEffects === null) {1576 return false;1577 }1578 var root = rootWithPendingPassiveEffects;1579 var lanes = pendingPassiveEffectsLanes;1580 rootWithPendingPassiveEffects = null;1581 pendingPassiveEffectsLanes = NoLanes;1582 if (!((executionContext & (RenderContext | CommitContext)) === NoContext)) {1583 {1584 throw Error( "Cannot flush passive effects while already rendering." );1585 }1586 }1587 {1588 markPassiveEffectsStarted(lanes);1589 }1590 {1591 isFlushingPassiveEffects = true;1592 }1593 var prevExecutionContext = executionContext;1594 executionContext |= CommitContext;1595 var prevInteractions = pushInteractions(root); // It's important that ALL pending passive effect destroy functions are called1596 // before ANY passive effect create functions are called.1597 // Otherwise effects in sibling components might interfere with each other.1598 // e.g. a destroy function in one component may unintentionally override a ref1599 // value set by a create function in another component.1600 // Layout effects have the same constraint.1601 // First pass: Destroy stale passive effects.1602 var unmountEffects = pendingPassiveHookEffectsUnmount;1603 pendingPassiveHookEffectsUnmount = [];1604 for (var i = 0; i < unmountEffects.length; i += 2) {1605 var _effect = unmountEffects[i];1606 var fiber = unmountEffects[i + 1];1607 var destroy = _effect.destroy;1608 _effect.destroy = undefined;1609 {1610 fiber.flags &= ~PassiveUnmountPendingDev;1611 var alternate = fiber.alternate;1612 if (alternate !== null) {1613 alternate.flags &= ~PassiveUnmountPendingDev;1614 }1615 }1616 if (typeof destroy === 'function') {1617 {1618 setCurrentFiber(fiber);1619 {1620 invokeGuardedCallback(null, destroy, null);1621 }1622 if (hasCaughtError()) {1623 if (!(fiber !== null)) {1624 {1625 throw Error( "Should be working on an effect." );1626 }1627 }1628 var error = clearCaughtError();1629 captureCommitPhaseError(fiber, error);1630 }1631 resetCurrentFiber();1632 }1633 }1634 } // Second pass: Create new passive effects.1635 var mountEffects = pendingPassiveHookEffectsMount;1636 pendingPassiveHookEffectsMount = [];1637 for (var _i = 0; _i < mountEffects.length; _i += 2) {1638 var _effect2 = mountEffects[_i];1639 var _fiber = mountEffects[_i + 1];1640 {1641 setCurrentFiber(_fiber);1642 {1643 invokeGuardedCallback(null, invokePassiveEffectCreate, null, _effect2);1644 }1645 if (hasCaughtError()) {1646 if (!(_fiber !== null)) {1647 {1648 throw Error( "Should be working on an effect." );1649 }1650 }1651 var _error4 = clearCaughtError();1652 captureCommitPhaseError(_fiber, _error4);1653 }1654 resetCurrentFiber();1655 }1656 } // Note: This currently assumes there are no passive effects on the root fiber1657 // because the root is not part of its own effect list.1658 // This could change in the future.1659 var effect = root.current.firstEffect;1660 while (effect !== null) {1661 var nextNextEffect = effect.nextEffect; // Remove nextEffect pointer to assist GC1662 effect.nextEffect = null;1663 if (effect.flags & Deletion) {1664 detachFiberAfterEffects(effect);1665 }1666 effect = nextNextEffect;1667 }1668 {1669 popInteractions(prevInteractions);1670 finishPendingInteractions(root, lanes);1671 }1672 {1673 isFlushingPassiveEffects = false;1674 }1675 {1676 markPassiveEffectsStopped();1677 }1678 executionContext = prevExecutionContext;1679 flushSyncCallbackQueue(); // If additional passive effects were scheduled, increment a counter. If this1680 // exceeds the limit, we'll fire a warning.1681 nestedPassiveUpdateCount = rootWithPendingPassiveEffects === null ? 0 : nestedPassiveUpdateCount + 1;1682 return true;1683 }1684 function isAlreadyFailedLegacyErrorBoundary(instance) {1685 return legacyErrorBoundariesThatAlreadyFailed !== null && legacyErrorBoundariesThatAlreadyFailed.has(instance);1686 }1687 function markLegacyErrorBoundaryAsFailed(instance) {1688 if (legacyErrorBoundariesThatAlreadyFailed === null) {1689 legacyErrorBoundariesThatAlreadyFailed = new Set([instance]);1690 } else {1691 legacyErrorBoundariesThatAlreadyFailed.add(instance);1692 }1693 }1694 function prepareToThrowUncaughtError(error) {1695 if (!hasUncaughtError) {1696 hasUncaughtError = true;1697 firstUncaughtError = error;1698 }1699 }1700 var onUncaughtError = prepareToThrowUncaughtError;1701 function captureCommitPhaseErrorOnRoot(rootFiber, sourceFiber, error) {1702 var errorInfo = createCapturedValue(error, sourceFiber);1703 var update = createRootErrorUpdate(rootFiber, errorInfo, SyncLane);1704 enqueueUpdate(rootFiber, update);1705 var eventTime = requestEventTime();1706 var root = markUpdateLaneFromFiberToRoot(rootFiber, SyncLane);1707 if (root !== null) {1708 markRootUpdated(root, SyncLane, eventTime);1709 ensureRootIsScheduled(root, eventTime);1710 schedulePendingInteractions(root, SyncLane);1711 }1712 }1713 function captureCommitPhaseError(sourceFiber, error) {1714 if (sourceFiber.tag === HostRoot) {1715 // Error was thrown at the root. There is no parent, so the root1716 // itself should capture it.1717 captureCommitPhaseErrorOnRoot(sourceFiber, sourceFiber, error);1718 return;1719 }1720 var fiber = sourceFiber.return;1721 while (fiber !== null) {1722 if (fiber.tag === HostRoot) {1723 captureCommitPhaseErrorOnRoot(fiber, sourceFiber, error);1724 return;1725 } else if (fiber.tag === ClassComponent) {1726 var ctor = fiber.type;1727 var instance = fiber.stateNode;1728 if (typeof ctor.getDerivedStateFromError === 'function' || typeof instance.componentDidCatch === 'function' && !isAlreadyFailedLegacyErrorBoundary(instance)) {1729 var errorInfo = createCapturedValue(error, sourceFiber);1730 var update = createClassErrorUpdate(fiber, errorInfo, SyncLane);1731 enqueueUpdate(fiber, update);1732 var eventTime = requestEventTime();1733 var root = markUpdateLaneFromFiberToRoot(fiber, SyncLane);1734 if (root !== null) {1735 markRootUpdated(root, SyncLane, eventTime);1736 ensureRootIsScheduled(root, eventTime);1737 schedulePendingInteractions(root, SyncLane);1738 } else {1739 // This component has already been unmounted.1740 // We can't schedule any follow up work for the root because the fiber is already unmounted,1741 // but we can still call the log-only boundary so the error isn't swallowed.1742 //1743 // TODO This is only a temporary bandaid for the old reconciler fork.1744 // We can delete this special case once the new fork is merged.1745 if (typeof instance.componentDidCatch === 'function' && !isAlreadyFailedLegacyErrorBoundary(instance)) {1746 try {1747 instance.componentDidCatch(error, errorInfo);1748 } catch (errorToIgnore) {// TODO Ignore this error? Rethrow it?1749 // This is kind of an edge case.1750 }1751 }1752 }1753 return;1754 }1755 }1756 fiber = fiber.return;1757 }1758 }1759 function pingSuspendedRoot(root, wakeable, pingedLanes) {1760 var pingCache = root.pingCache;1761 if (pingCache !== null) {1762 // The wakeable resolved, so we no longer need to memoize, because it will1763 // never be thrown again.1764 pingCache.delete(wakeable);1765 }1766 var eventTime = requestEventTime();1767 markRootPinged(root, pingedLanes);1768 if (workInProgressRoot === root && isSubsetOfLanes(workInProgressRootRenderLanes, pingedLanes)) {1769 // Received a ping at the same priority level at which we're currently1770 // rendering. We might want to restart this render. This should mirror1771 // the logic of whether or not a root suspends once it completes.1772 // TODO: If we're rendering sync either due to Sync, Batched or expired,1773 // we should probably never restart.1774 // If we're suspended with delay, or if it's a retry, we'll always suspend1775 // so we can always restart.1776 if (workInProgressRootExitStatus === RootSuspendedWithDelay || workInProgressRootExitStatus === RootSuspended && includesOnlyRetries(workInProgressRootRenderLanes) && now() - globalMostRecentFallbackTime < FALLBACK_THROTTLE_MS) {1777 // Restart from the root.1778 prepareFreshStack(root, NoLanes);1779 } else {1780 // Even though we can't restart right now, we might get an1781 // opportunity later. So we mark this render as having a ping.1782 workInProgressRootPingedLanes = mergeLanes(workInProgressRootPingedLanes, pingedLanes);1783 }1784 }1785 ensureRootIsScheduled(root, eventTime);1786 schedulePendingInteractions(root, pingedLanes);1787 }1788 function retryTimedOutBoundary(boundaryFiber, retryLane) {1789 // The boundary fiber (a Suspense component or SuspenseList component)1790 // previously was rendered in its fallback state. One of the promises that1791 // suspended it has resolved, which means at least part of the tree was1792 // likely unblocked. Try rendering again, at a new expiration time.1793 if (retryLane === NoLane) {1794 retryLane = requestRetryLane(boundaryFiber);1795 } // TODO: Special case idle priority?1796 var eventTime = requestEventTime();1797 var root = markUpdateLaneFromFiberToRoot(boundaryFiber, retryLane);1798 if (root !== null) {1799 markRootUpdated(root, retryLane, eventTime);1800 ensureRootIsScheduled(root, eventTime);1801 schedulePendingInteractions(root, retryLane);1802 }1803 }1804 function retryDehydratedSuspenseBoundary(boundaryFiber) {1805 var suspenseState = boundaryFiber.memoizedState;1806 var retryLane = NoLane;1807 if (suspenseState !== null) {1808 retryLane = suspenseState.retryLane;1809 }1810 retryTimedOutBoundary(boundaryFiber, retryLane);1811 }1812 function resolveRetryWakeable(boundaryFiber, wakeable) {1813 var retryLane = NoLane; // Default1814 var retryCache;1815 {1816 switch (boundaryFiber.tag) {1817 case SuspenseComponent:1818 retryCache = boundaryFiber.stateNode;1819 var suspenseState = boundaryFiber.memoizedState;1820 if (suspenseState !== null) {1821 retryLane = suspenseState.retryLane;1822 }1823 break;1824 case SuspenseListComponent:1825 retryCache = boundaryFiber.stateNode;1826 break;1827 default:1828 {1829 {1830 throw Error( "Pinged unknown suspense boundary type. This is probably a bug in React." );1831 }1832 }1833 }1834 }1835 if (retryCache !== null) {1836 // The wakeable resolved, so we no longer need to memoize, because it will1837 // never be thrown again.1838 retryCache.delete(wakeable);1839 }1840 retryTimedOutBoundary(boundaryFiber, retryLane);1841 } // Computes the next Just Noticeable Difference (JND) boundary.1842 // The theory is that a person can't tell the difference between small differences in time.1843 // Therefore, if we wait a bit longer than necessary that won't translate to a noticeable1844 // difference in the experience. However, waiting for longer might mean that we can avoid1845 // showing an intermediate loading state. The longer we have already waited, the harder it1846 // is to tell small differences in time. Therefore, the longer we've already waited,1847 // the longer we can wait additionally. At some point we have to give up though.1848 // We pick a train model where the next boundary commits at a consistent schedule.1849 // These particular numbers are vague estimates. We expect to adjust them based on research.1850 function jnd(timeElapsed) {1851 return timeElapsed < 120 ? 120 : timeElapsed < 480 ? 480 : timeElapsed < 1080 ? 1080 : timeElapsed < 1920 ? 1920 : timeElapsed < 3000 ? 3000 : timeElapsed < 4320 ? 4320 : ceil(timeElapsed / 1960) * 1960;1852 }1853 function checkForNestedUpdates() {1854 if (nestedUpdateCount > NESTED_UPDATE_LIMIT) {1855 nestedUpdateCount = 0;1856 rootWithNestedUpdates = null;1857 {1858 {1859 throw Error( "Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops." );1860 }1861 }1862 }1863 {1864 if (nestedPassiveUpdateCount > NESTED_PASSIVE_UPDATE_LIMIT) {1865 nestedPassiveUpdateCount = 0;1866 error('Maximum update depth exceeded. This can happen when a component ' + "calls setState inside useEffect, but useEffect either doesn't " + 'have a dependency array, or one of the dependencies changes on ' + 'every render.');1867 }1868 }1869 }1870 function flushRenderPhaseStrictModeWarningsInDEV() {1871 {1872 ReactStrictModeWarnings.flushLegacyContextWarning();1873 {1874 ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings();1875 }1876 }1877 }1878 var didWarnStateUpdateForNotYetMountedComponent = null;1879 function warnAboutUpdateOnNotYetMountedFiberInDEV(fiber) {1880 {1881 if ((executionContext & RenderContext) !== NoContext) {1882 // We let the other warning about render phase updates deal with this one.1883 return;1884 }1885 if (!(fiber.mode & (BlockingMode | ConcurrentMode))) {1886 return;1887 }1888 var tag = fiber.tag;1889 if (tag !== IndeterminateComponent && tag !== HostRoot && tag !== ClassComponent && tag !== FunctionComponent && tag !== ForwardRef && tag !== MemoComponent && tag !== SimpleMemoComponent && tag !== Block) {1890 // Only warn for user-defined components, not internal ones like Suspense.1891 return;1892 } // We show the whole stack but dedupe on the top component's name because1893 // the problematic code almost always lies inside that component.1894 var componentName = getComponentName(fiber.type) || 'ReactComponent';1895 if (didWarnStateUpdateForNotYetMountedComponent !== null) {1896 if (didWarnStateUpdateForNotYetMountedComponent.has(componentName)) {1897 return;1898 }1899 didWarnStateUpdateForNotYetMountedComponent.add(componentName);1900 } else {1901 didWarnStateUpdateForNotYetMountedComponent = new Set([componentName]);1902 }1903 var previousFiber = current;1904 try {1905 setCurrentFiber(fiber);1906 error("Can't perform a React state update on a component that hasn't mounted yet. " + 'This indicates that you have a side-effect in your render function that ' + 'asynchronously later calls tries to update the component. Move this work to ' + 'useEffect instead.');1907 } finally {1908 if (previousFiber) {1909 setCurrentFiber(fiber);1910 } else {1911 resetCurrentFiber();1912 }1913 }1914 }1915 }1916 var didWarnStateUpdateForUnmountedComponent = null;1917 function warnAboutUpdateOnUnmountedFiberInDEV(fiber) {1918 {1919 var tag = fiber.tag;1920 if (tag !== HostRoot && tag !== ClassComponent && tag !== FunctionComponent && tag !== ForwardRef && tag !== MemoComponent && tag !== SimpleMemoComponent && tag !== Block) {1921 // Only warn for user-defined components, not internal ones like Suspense.1922 return;1923 } // If there are pending passive effects unmounts for this Fiber,1924 // we can assume that they would have prevented this update.1925 if ((fiber.flags & PassiveUnmountPendingDev) !== NoFlags) {1926 return;1927 } // We show the whole stack but dedupe on the top component's name because1928 // the problematic code almost always lies inside that component.1929 var componentName = getComponentName(fiber.type) || 'ReactComponent';1930 if (didWarnStateUpdateForUnmountedComponent !== null) {1931 if (didWarnStateUpdateForUnmountedComponent.has(componentName)) {1932 return;1933 }1934 didWarnStateUpdateForUnmountedComponent.add(componentName);1935 } else {1936 didWarnStateUpdateForUnmountedComponent = new Set([componentName]);1937 }1938 if (isFlushingPassiveEffects) ; else {1939 var previousFiber = current;1940 try {1941 setCurrentFiber(fiber);1942 error("Can't perform a React state update on an unmounted component. This " + 'is a no-op, but it indicates a memory leak in your application. To ' + 'fix, cancel all subscriptions and asynchronous tasks in %s.', tag === ClassComponent ? 'the componentWillUnmount method' : 'a useEffect cleanup function');1943 } finally {1944 if (previousFiber) {1945 setCurrentFiber(fiber);1946 } else {1947 resetCurrentFiber();1948 }1949 }1950 }1951 }1952 }1953 var beginWork$1;1954 {1955 var dummyFiber = null;1956 beginWork$1 = function (current, unitOfWork, lanes) {1957 // If a component throws an error, we replay it again in a synchronously1958 // dispatched event, so that the debugger will treat it as an uncaught1959 // error See ReactErrorUtils for more information.1960 // Before entering the begin phase, copy the work-in-progress onto a dummy1961 // fiber. If beginWork throws, we'll use this to reset the state.1962 var originalWorkInProgressCopy = assignFiberPropertiesInDEV(dummyFiber, unitOfWork);1963 try {1964 return beginWork(current, unitOfWork, lanes);1965 } catch (originalError) {1966 if (originalError !== null && typeof originalError === 'object' && typeof originalError.then === 'function') {1967 // Don't replay promises. Treat everything else like an error.1968 throw originalError;1969 } // Keep this code in sync with handleError; any changes here must have1970 // corresponding changes there.1971 resetContextDependencies();1972 resetHooksAfterThrow(); // Don't reset current debug fiber, since we're about to work on the1973 // same fiber again.1974 // Unwind the failed stack frame1975 unwindInterruptedWork(unitOfWork); // Restore the original properties of the fiber.1976 assignFiberPropertiesInDEV(unitOfWork, originalWorkInProgressCopy);1977 if ( unitOfWork.mode & ProfileMode) {1978 // Reset the profiler timer.1979 startProfilerTimer(unitOfWork);1980 } // Run beginWork again.1981 invokeGuardedCallback(null, beginWork, null, current, unitOfWork, lanes);1982 if (hasCaughtError()) {1983 var replayError = clearCaughtError(); // `invokeGuardedCallback` sometimes sets an expando `_suppressLogging`.1984 // Rethrow this error instead of the original one.1985 throw replayError;1986 } else {1987 // This branch is reachable if the render phase is impure.1988 throw originalError;1989 }1990 }1991 };1992 }1993 var didWarnAboutUpdateInRender = false;1994 var didWarnAboutUpdateInRenderForAnotherComponent;1995 {1996 didWarnAboutUpdateInRenderForAnotherComponent = new Set();1997 }1998 function warnAboutRenderPhaseUpdatesInDEV(fiber) {1999 {2000 if (isRendering && (executionContext & RenderContext) !== NoContext && !getIsUpdatingOpaqueValueInRenderPhaseInDEV()) {2001 switch (fiber.tag) {2002 case FunctionComponent:2003 case ForwardRef:2004 case SimpleMemoComponent:2005 {2006 var renderingComponentName = workInProgress && getComponentName(workInProgress.type) || 'Unknown'; // Dedupe by the rendering component because it's the one that needs to be fixed.2007 var dedupeKey = renderingComponentName;2008 if (!didWarnAboutUpdateInRenderForAnotherComponent.has(dedupeKey)) {2009 didWarnAboutUpdateInRenderForAnotherComponent.add(dedupeKey);2010 var setStateComponentName = getComponentName(fiber.type) || 'Unknown';2011 error('Cannot update a component (`%s`) while rendering a ' + 'different component (`%s`). To locate the bad setState() call inside `%s`, ' + 'follow the stack trace as described in https://reactjs.org/link/setstate-in-render', setStateComponentName, renderingComponentName, renderingComponentName);2012 }2013 break;2014 }2015 case ClassComponent:2016 {2017 if (!didWarnAboutUpdateInRender) {2018 error('Cannot update during an existing state transition (such as ' + 'within `render`). Render methods should be a pure ' + 'function of props and state.');2019 didWarnAboutUpdateInRender = true;2020 }2021 break;2022 }2023 }2024 }2025 }2026 } // a 'shared' variable that changes when act() opens/closes in tests.2027 var IsThisRendererActing = {2028 current: false2029 };2030 function warnIfNotScopedWithMatchingAct(fiber) {2031 {2032 if ( IsSomeRendererActing.current === true && IsThisRendererActing.current !== true) {2033 var previousFiber = current;2034 try {2035 setCurrentFiber(fiber);2036 error("It looks like you're using the wrong act() around your test interactions.\n" + 'Be sure to use the matching version of act() corresponding to your renderer:\n\n' + '// for react-dom:\n' + // Break up imports to avoid accidentally parsing them as dependencies.2037 'import {act} fr' + "om 'react-dom/test-utils';\n" + '// ...\n' + 'act(() => ...);\n\n' + '// for react-test-renderer:\n' + // Break up imports to avoid accidentally parsing them as dependencies.2038 'import TestRenderer fr' + "om react-test-renderer';\n" + 'const {act} = TestRenderer;\n' + '// ...\n' + 'act(() => ...);');2039 } finally {2040 if (previousFiber) {2041 setCurrentFiber(fiber);2042 } else {2043 resetCurrentFiber();2044 }2045 }2046 }2047 }2048 }2049 function warnIfNotCurrentlyActingEffectsInDEV(fiber) {2050 {2051 if ( (fiber.mode & StrictMode) !== NoMode && IsSomeRendererActing.current === false && IsThisRendererActing.current === false) {2052 error('An update to %s ran an effect, but was not wrapped in act(...).\n\n' + 'When testing, code that causes React state updates should be ' + 'wrapped into act(...):\n\n' + 'act(() => {\n' + ' /* fire events that update state */\n' + '});\n' + '/* assert on the output */\n\n' + "This ensures that you're testing the behavior the user would see " + 'in the browser.' + ' Learn more at https://reactjs.org/link/wrap-tests-with-act', getComponentName(fiber.type));2053 }2054 }2055 }2056 function warnIfNotCurrentlyActingUpdatesInDEV(fiber) {2057 {2058 if ( executionContext === NoContext && IsSomeRendererActing.current === false && IsThisRendererActing.current === false) {2059 var previousFiber = current;2060 try {2061 setCurrentFiber(fiber);2062 error('An update to %s inside a test was not wrapped in act(...).\n\n' + 'When testing, code that causes React state updates should be ' + 'wrapped into act(...):\n\n' + 'act(() => {\n' + ' /* fire events that update state */\n' + '});\n' + '/* assert on the output */\n\n' + "This ensures that you're testing the behavior the user would see " + 'in the browser.' + ' Learn more at https://reactjs.org/link/wrap-tests-with-act', getComponentName(fiber.type));2063 } finally {2064 if (previousFiber) {2065 setCurrentFiber(fiber);2066 } else {2067 resetCurrentFiber();2068 }2069 }2070 }2071 }2072 }2073 var warnIfNotCurrentlyActingUpdatesInDev = warnIfNotCurrentlyActingUpdatesInDEV; // In tests, we want to enforce a mocked scheduler.2074 var didWarnAboutUnmockedScheduler = false; // TODO Before we release concurrent mode, revisit this and decide whether a mocked2075 // scheduler is the actual recommendation. The alternative could be a testing build,2076 // a new lib, or whatever; we dunno just yet. This message is for early adopters2077 // to get their tests right.2078 function warnIfUnmockedScheduler(fiber) {2079 {2080 if (didWarnAboutUnmockedScheduler === false && unstable_flushAllWithoutAsserting === undefined) {2081 if (fiber.mode & BlockingMode || fiber.mode & ConcurrentMode) {2082 didWarnAboutUnmockedScheduler = true;2083 error('In Concurrent or Sync modes, the "scheduler" module needs to be mocked ' + 'to guarantee consistent behaviour across tests and browsers. ' + 'For example, with jest: \n' + // Break up requires to avoid accidentally parsing them as dependencies.2084 "jest.mock('scheduler', () => require" + "('scheduler/unstable_mock'));\n\n" + 'For more info, visit https://reactjs.org/link/mock-scheduler');2085 }2086 }2087 }2088 }2089 function computeThreadID(root, lane) {2090 // Interaction threads are unique per root and expiration time.2091 // NOTE: Intentionally unsound cast. All that matters is that it's a number2092 // and it represents a batch of work. Could make a helper function instead,2093 // but meh this is fine for now.2094 return lane * 1000 + root.interactionThreadID;2095 }2096 function markSpawnedWork(lane) {2097 if (spawnedWorkDuringRender === null) {2098 spawnedWorkDuringRender = [lane];2099 } else {2100 spawnedWorkDuringRender.push(lane);2101 }2102 }2103 function scheduleInteractions(root, lane, interactions) {2104 if (interactions.size > 0) {2105 var pendingInteractionMap = root.pendingInteractionMap;2106 var pendingInteractions = pendingInteractionMap.get(lane);2107 if (pendingInteractions != null) {2108 interactions.forEach(function (interaction) {2109 if (!pendingInteractions.has(interaction)) {2110 // Update the pending async work count for previously unscheduled interaction.2111 interaction.__count++;2112 }2113 pendingInteractions.add(interaction);2114 });2115 } else {2116 pendingInteractionMap.set(lane, new Set(interactions)); // Update the pending async work count for the current interactions.2117 interactions.forEach(function (interaction) {2118 interaction.__count++;2119 });2120 }2121 var subscriber = __subscriberRef.current;2122 if (subscriber !== null) {2123 var threadID = computeThreadID(root, lane);2124 subscriber.onWorkScheduled(interactions, threadID);2125 }2126 }2127 }2128 function schedulePendingInteractions(root, lane) {2129 scheduleInteractions(root, lane, __interactionsRef.current);2130 }2131 function startWorkOnPendingInteractions(root, lanes) {2132 // we can accurately attribute time spent working on it, And so that cascading2133 // work triggered during the render phase will be associated with it.2134 var interactions = new Set();2135 root.pendingInteractionMap.forEach(function (scheduledInteractions, scheduledLane) {2136 if (includesSomeLane(lanes, scheduledLane)) {2137 scheduledInteractions.forEach(function (interaction) {2138 return interactions.add(interaction);2139 });2140 }2141 }); // Store the current set of interactions on the FiberRoot for a few reasons:2142 // We can re-use it in hot functions like performConcurrentWorkOnRoot()2143 // without having to recalculate it. We will also use it in commitWork() to...

Full Screen

Full Screen

4 - commitWork.js

Source:4 - commitWork.js Github

copy

Full Screen

...184 if (spawnedWorkDuringRender !== null) {185 const expirationTimes = spawnedWorkDuringRender;186 spawnedWorkDuringRender = null;187 for (let i = 0; i < expirationTimes.length; i++) {188 scheduleInteractions(189 root,190 expirationTimes[i],191 root.memoizedInteractions,192 );193 }194 }195 schedulePendingInteractions(root, remainingLanes);196 }197 } else {198 // If there's no remaining work, we can clear the set of already failed199 // error boundaries.200 legacyErrorBoundariesThatAlreadyFailed = null;201 }202 if (enableSchedulerTracing) {...

Full Screen

Full Screen

commitRootImpl.js

Source:commitRootImpl.js Github

copy

Full Screen

...187 if (spawnedWorkDuringRender !== null) {188 var expirationTimes = spawnedWorkDuringRender;189 spawnedWorkDuringRender = null;190 for (var i = 0; i < expirationTimes.length; i++) {191 scheduleInteractions(root, expirationTimes[i], root.memoizedInteractions);192 }193 }194 schedulePendingInteractions(root, remainingExpirationTime);195 }196 } else {197 // If there's no remaining work, we can clear the set of already failed198 // error boundaries.199 legacyErrorBoundariesThatAlreadyFailed = null;200 }201 if (enableSchedulerTracing) {202 if (!rootDidHavePassiveEffects) {203 // If there are no passive effects, then we can complete the pending interactions.204 // Otherwise, we'll wait until after the passive effects are flushed.205 // Wait to do this until after remaining work has been scheduled,...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1const playwright = require('playwright');2const { scheduleInteractions } = require('playwright/lib/internal/inspectorInstrumentation');3(async () => {4 const browser = await playwright.chromium.launch({ headless: false });5 const context = await browser.newContext();6 const page = await context.newPage();7 await scheduleInteractions(page, async (interactions) => {8 await interactions.click('text=Get started');9 await interactions.click('text=Docs');10 await interactions.click('text=API');11 });12 await browser.close();13})();14module.exports = {15 {16 use: {17 viewport: { width: 1920, height: 1080 },18 },19 },20};21const playwright = require('playwright');22const { scheduleInteractions } = require('playwright/lib/internal/inspectorInstrumentation');23test.describe('Playwright', () => {24 test('Playwright', async ({ page }) => {25 await scheduleInteractions(page, async (interactions) => {26 await interactions.click('text=Get started');27 await interactions.click('text=Docs');28 await interactions.click('text=API');29 });30 });31});32module.exports = {33 {34 use: {35 viewport: { width: 1920, height: 1080 },

Full Screen

Using AI Code Generation

copy

Full Screen

1const { scheduleInteractions } = require('playwright/lib/server/supplements/recorder/recorderSupplement');2const { chromium } = require('playwright');3(async () => {4 const browser = await chromium.launch();5 const page = await browser.newPage();6 await scheduleInteractions(page, [7 {8 selector: '#tsf > div:nth-child(2) > div > div.FPdoLc.VlcLAe > center > input[type="submit"]:nth-child(1)',9 position: { x: 0, y: 0 },10 },11 ]);12 await page.screenshot({ path: `example.png` });13 await browser.close();14})();

Full Screen

Using AI Code Generation

copy

Full Screen

1const playwright = require('playwright');2const { scheduleInteractions } = require('playwright/lib/internal/inspector/adapters/inspectorAdapter');3(async () => {4 const browser = await playwright.chromium.launch({ headless: false });5 const page = await browser.newPage();6 await page.waitForSelector('input[name="q"]');7 await scheduleInteractions(page, [8 {9 options: {10 },11 },12 ]);13 await page.screenshot({ path: 'example.png' });14 await browser.close();15})();16module.exports = {17 use: {18 },19};

Full Screen

Using AI Code Generation

copy

Full Screen

1const { scheduleInteractions } = require('playwright/lib/utils/interaction');2const { firefox } = require('playwright');3const run = async () => {4 const browser = await firefox.launch();5 const page = await browser.newPage();6 await scheduleInteractions(page, async (interactions) => {7 await interactions.click(page.locator('input[type="submit"]'));8 });9 await browser.close();10};11run();12 const { page, context } = await state.browser._defaultContextOrPage();13 at scheduleInteractions (node_modules/playwright/lib/utils/interaction.js:14:45)14 at run (test.js:13:5)15 at processTicksAndRejections (internal/process/task_queues.js:97:5)16const { scheduleInteractions } = require('playwright-core/lib/utils/interaction');

Full Screen

Using AI Code Generation

copy

Full Screen

1const { scheduleInteractions, scheduleInteraction } = require('@playwright/test/lib/workerRunner');2const { scheduleInteractions, scheduleInteraction } = require('@playwright/test');3const { scheduleInteractions, scheduleInteraction } = require('@playwright/test/lib/workerRunner');4const { scheduleInteractions, scheduleInteraction } = require('@playwright/test');5const { scheduleInteractions, scheduleInteraction } = require('@playwright/test/lib/workerRunner');6const { scheduleInteractions, scheduleInteraction } = require('@playwright/test');7const { scheduleInteractions, scheduleInteraction } = require('@playwright/test/lib/workerRunner');8const { scheduleInteractions, scheduleInteraction } = require('@playwright/test');9const { scheduleInteractions, scheduleInteraction } = require('@playwright/test/lib/workerRunner');10const { scheduleInteractions, scheduleInteraction } = require('@playwright/test');11const { scheduleInteractions, scheduleInteraction } = require('@playwright/test/lib/workerRunner');12const { scheduleInteractions, scheduleInteraction } = require('@playwright/test');13const { scheduleInteractions, scheduleInteraction } = require('@playwright/test/lib/workerRunner');14const { scheduleInteractions, scheduleInteraction } = require('@playwright/test');15const { scheduleInteractions, scheduleInteraction } = require('@playwright/test/lib/workerRunner');16const { scheduleInteractions, scheduleInteraction } = require('@playwright/test

Full Screen

Using AI Code Generation

copy

Full Screen

1const { scheduleInteractions } = require('playwright');2const { chromium } = require('playwright');3const { Interaction, Interactions } = require('playwright-interactions');4(async () => {5 const browser = await chromium.launch();6 const context = await browser.newContext();7 const page = await context.newPage();8 await scheduleInteractions(page, () => {9 return new Interactions(page)10 .click(page.locator('text=Example Domain'))11 .click(page.locator('text=More information...'))12 .click(page.locator('text=More information...'))13 .click(page.locator('text=More information...'))14 });15 await browser.close();16})();17const { chromium } = require('playwright');18const { Interaction, Interactions } = require('playwright-interactions');19(async () => {20 const browser = await chromium.launch();21 const context = await browser.newContext();22 const page = await context.newPage();23 await new Interactions(page)24 .click(page.locator('text=Example Domain'))25 .click(page.locator('text=More information...'))26 .click(page.locator('text=More information...'))27 .click(page.locator('text=More information...'))28 await browser.close();29})();30const { chromium } = require('playwright');31const { Interaction, Interactions } = require('playwright-interactions');

Full Screen

Using AI Code Generation

copy

Full Screen

1import { scheduleInteractions } from 'playwright/lib/internal';2scheduleInteractions(async () => {3});4import { scheduleInteractions } from 'playwright/lib/internal';5scheduleInteractions(async () => {6});7import { scheduleInteractions } from 'playwright/lib/internal';8scheduleInteractions(async () => {9});10import { scheduleInteractions } from 'playwright/lib/internal';11scheduleInteractions(async () => {12});13import { scheduleInteractions } from 'playwright/lib/internal';14scheduleInteractions(async () => {15});16import { scheduleInteractions } from 'playwright/lib/internal';17scheduleInteractions(async () => {18});19import { scheduleInteractions } from 'playwright/lib/internal';20scheduleInteractions(async () => {21});22import { scheduleInteractions } from 'playwright/lib/internal';23scheduleInteractions(async () => {24});25import { scheduleInteractions } from 'playwright/lib/internal';26scheduleInteractions(async () => {

Full Screen

Using AI Code Generation

copy

Full Screen

1const playwright = require('playwright');2const pw = new playwright();3const browser = pw.chromium;4const page = browser.newPage();5page.scheduleInteractions([6 { action: 'click', selector: '#foo' },7 { action: 'click', selector: '#bar' },8 { action: 'click', selector: '#baz' }9]);10page.runScheduledInteractions();11if(page.scheduledInteractionsCompleted()) {12 console.log('All interactions have been completed');13} else {14 console.log('Not all interactions have been completed');15}16page2.scheduleInteractions([17 { action: 'click', selector: '#foo' },18 { action: 'click', selector: '#bar' },19 { action: 'click', selector: '#baz' }20]);21page2.runScheduledInteractions();22if(page2.scheduledInteractionsCompleted()) {23 console.log('All interactions have been completed');24} else {25 console.log('Not all interactions have been completed');26}27page.scheduleInteractions([28 { action: 'click', selector: '#foo' },29 { action: 'click', selector: '#bar' },30 { action: 'click', selector: '#baz' }31]);32page.runScheduledInteractions();33if(page.scheduledInteractionsCompleted()) {34 console.log('All interactions have been completed');35} else {36 console.log('Not all interactions have been completed');37}

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