|
7 | 7 | * @noflow |
8 | 8 | * @nolint |
9 | 9 | * @preventMunge |
10 | | - * @generated SignedSource<<cfbc1c43d4da5c44f22471790ecd61bf>> |
| 10 | + * @generated SignedSource<<a30628fd998018c262d2437b0c9edc0e>> |
11 | 11 | */ |
12 | 12 |
|
13 | 13 | "use strict"; |
@@ -3238,7 +3238,9 @@ to return true:wantsResponderID| | |
3238 | 3238 | dynamicFlags.passChildrenWhenCloningPersistedNodes, |
3239 | 3239 | useMicrotasksForSchedulingInFabric = |
3240 | 3240 | dynamicFlags.useMicrotasksForSchedulingInFabric, |
3241 | | - enableUnifiedSyncLane = dynamicFlags.enableUnifiedSyncLane; // The rest of the flags are static for better dead code elimination. |
| 3241 | + enableUnifiedSyncLane = dynamicFlags.enableUnifiedSyncLane, |
| 3242 | + enableInfiniteRenderLoopDetection = |
| 3243 | + dynamicFlags.enableInfiniteRenderLoopDetection; // The rest of the flags are static for better dead code elimination. |
3242 | 3244 | var enableSchedulingProfiler = true; |
3243 | 3245 | var enableProfilerTimer = true; |
3244 | 3246 | var enableProfilerCommitHooks = true; |
@@ -23748,6 +23750,10 @@ to return true:wantsResponderID| | |
23748 | 23750 | var workInProgressRootRecoverableErrors = null; // Tracks when an update occurs during the render phase. |
23749 | 23751 |
|
23750 | 23752 | var workInProgressRootDidIncludeRecursiveRenderUpdate = false; // Thacks when an update occurs during the commit phase. It's a separate |
| 23753 | + // variable from the one for renders because the commit phase may run |
| 23754 | + // concurrently to a render phase. |
| 23755 | + |
| 23756 | + var didIncludeCommitPhaseUpdate = false; // The most recent time we either committed a fallback, or when a fallback was |
23751 | 23757 | // filled in with the resolved UI. This lets us throttle the appearance of new |
23752 | 23758 | // content as it streams in, to minimize jank. |
23753 | 23759 | // TODO: Think of a better name for this variable? |
@@ -24439,10 +24445,36 @@ to return true:wantsResponderID| | |
24439 | 24445 |
|
24440 | 24446 | function markRootUpdated(root, updatedLanes) { |
24441 | 24447 | markRootUpdated$1(root, updatedLanes); |
| 24448 | + |
| 24449 | + if (enableInfiniteRenderLoopDetection) { |
| 24450 | + // Check for recursive updates |
| 24451 | + if (executionContext & RenderContext) { |
| 24452 | + workInProgressRootDidIncludeRecursiveRenderUpdate = true; |
| 24453 | + } else if (executionContext & CommitContext) { |
| 24454 | + didIncludeCommitPhaseUpdate = true; |
| 24455 | + } |
| 24456 | + |
| 24457 | + throwIfInfiniteUpdateLoopDetected(); |
| 24458 | + } |
24442 | 24459 | } |
24443 | 24460 |
|
24444 | 24461 | function markRootPinged(root, pingedLanes) { |
24445 | 24462 | markRootPinged$1(root, pingedLanes); |
| 24463 | + |
| 24464 | + if (enableInfiniteRenderLoopDetection) { |
| 24465 | + // Check for recursive pings. Pings are conceptually different from updates in |
| 24466 | + // other contexts but we call it an "update" in this context because |
| 24467 | + // repeatedly pinging a suspended render can cause a recursive render loop. |
| 24468 | + // The relevant property is that it can result in a new render attempt |
| 24469 | + // being scheduled. |
| 24470 | + if (executionContext & RenderContext) { |
| 24471 | + workInProgressRootDidIncludeRecursiveRenderUpdate = true; |
| 24472 | + } else if (executionContext & CommitContext) { |
| 24473 | + didIncludeCommitPhaseUpdate = true; |
| 24474 | + } |
| 24475 | + |
| 24476 | + throwIfInfiniteUpdateLoopDetected(); |
| 24477 | + } |
24446 | 24478 | } |
24447 | 24479 |
|
24448 | 24480 | function markRootSuspended(root, suspendedLanes, spawnedLane) { |
@@ -25796,6 +25828,8 @@ to return true:wantsResponderID| | |
25796 | 25828 | remainingLanes = mergeLanes(remainingLanes, concurrentlyUpdatedLanes); |
25797 | 25829 | markRootFinished(root, remainingLanes, spawnedLane); // Reset this before firing side effects so we can detect recursive updates. |
25798 | 25830 |
|
| 25831 | + didIncludeCommitPhaseUpdate = false; |
| 25832 | + |
25799 | 25833 | if (root === workInProgressRoot) { |
25800 | 25834 | // We can reset these now that they are finished. |
25801 | 25835 | workInProgressRoot = null; |
@@ -25987,9 +26021,10 @@ to return true:wantsResponderID| | |
25987 | 26021 | // Check if there was a recursive update spawned by this render, in either |
25988 | 26022 | // the render phase or the commit phase. We track these explicitly because |
25989 | 26023 | // we can't infer from the remaining lanes alone. |
25990 | | - // Was the finished render the result of an update (not hydration)? |
25991 | | - includesSomeLane(lanes, UpdateLanes) && // Did it schedule a sync update? |
25992 | | - includesSomeLane(remainingLanes, SyncUpdateLanes) |
| 26024 | + (enableInfiniteRenderLoopDetection && |
| 26025 | + (didIncludeRenderPhaseUpdate || didIncludeCommitPhaseUpdate)) || // Was the finished render the result of an update (not hydration)? |
| 26026 | + (includesSomeLane(lanes, UpdateLanes) && // Did it schedule a sync update? |
| 26027 | + includesSomeLane(remainingLanes, SyncUpdateLanes)) |
25993 | 26028 | ) { |
25994 | 26029 | { |
25995 | 26030 | markNestedUpdateScheduled(); |
@@ -26422,6 +26457,19 @@ to return true:wantsResponderID| | |
26422 | 26457 | rootWithNestedUpdates = null; |
26423 | 26458 | rootWithPassiveNestedUpdates = null; |
26424 | 26459 |
|
| 26460 | + if (enableInfiniteRenderLoopDetection) { |
| 26461 | + if (executionContext & RenderContext && workInProgressRoot !== null) { |
| 26462 | + // We're in the render phase. Disable the concurrent error recovery |
| 26463 | + // mechanism to ensure that the error we're about to throw gets handled. |
| 26464 | + // We need it to trigger the nearest error boundary so that the infinite |
| 26465 | + // update loop is broken. |
| 26466 | + workInProgressRoot.errorRecoveryDisabledLanes = mergeLanes( |
| 26467 | + workInProgressRoot.errorRecoveryDisabledLanes, |
| 26468 | + workInProgressRootRenderLanes |
| 26469 | + ); |
| 26470 | + } |
| 26471 | + } |
| 26472 | + |
26425 | 26473 | throw new Error( |
26426 | 26474 | "Maximum update depth exceeded. This can happen when a component " + |
26427 | 26475 | "repeatedly calls setState inside componentWillUpdate or " + |
@@ -28042,7 +28090,7 @@ to return true:wantsResponderID| | |
28042 | 28090 | return root; |
28043 | 28091 | } |
28044 | 28092 |
|
28045 | | - var ReactVersion = "18.3.0-canary-26c89f2f"; |
| 28093 | + var ReactVersion = "18.3.0-canary-b1191c0d"; |
28046 | 28094 |
|
28047 | 28095 | function createPortal$1( |
28048 | 28096 | children, |
|
0 commit comments