react-test-renderer 17.0.0-rc.2 → 17.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- /** @license React v17.0.0-rc.2
1
+ /** @license React v17.0.2
2
2
  * react-test-renderer.development.js
3
3
  *
4
4
  * Copyright (c) Facebook, Inc. and its affiliates.
@@ -299,7 +299,7 @@ function getComponentName(type) {
299
299
 
300
300
  // Don't change these two values. They're used by React Dev Tools.
301
301
  var NoFlags =
302
- /* */
302
+ /* */
303
303
  0;
304
304
  var PerformedWork =
305
305
  /* */
@@ -335,6 +335,10 @@ var Snapshot =
335
335
  var Passive =
336
336
  /* */
337
337
  512; // TODO (effects) Remove this bit once the new reconciler is synced to the old.
338
+
339
+ var PassiveUnmountPendingDev =
340
+ /* */
341
+ 8192;
338
342
  var Hydrating =
339
343
  /* */
340
344
  1024;
@@ -359,33 +363,6 @@ var ShouldCapture =
359
363
  var ForceUpdateForLegacySuspense =
360
364
  /* */
361
365
  16384; // Static tags describe aspects of a fiber that are not specific to a render,
362
- // e.g. a fiber uses a passive effect (even if there are no updates on this particular render).
363
- // This enables us to defer more work in the unmount case,
364
- // since we can defer traversing the tree during layout to look for Passive effects,
365
- // and instead rely on the static flag as a signal that there may be cleanup work.
366
-
367
- var PassiveStatic =
368
- /* */
369
- 32768; // Union of side effect groupings as pertains to subtreeFlags
370
-
371
- var BeforeMutationMask =
372
- /* */
373
- 778;
374
- var MutationMask =
375
- /* */
376
- 1182;
377
- var LayoutMask =
378
- /* */
379
- 164;
380
- var PassiveMask =
381
- /* */
382
- 520; // Union of tags that don't get reset on clones.
383
- // This allows certain concepts to persist without recalculting them,
384
- // e.g. whether a subtree contains passive effects or portals.
385
-
386
- var StaticMask =
387
- /* */
388
- 32768;
389
366
 
390
367
  var enableProfilerTimer = true;
391
368
  var enableFundamentalAPI = false;
@@ -2292,7 +2269,15 @@ function laneToLanes(lane) {
2292
2269
  return lane;
2293
2270
  }
2294
2271
  function createLaneMap(initial) {
2295
- return new Array(TotalLanes).fill(initial);
2272
+ // Intentionally pushing one by one.
2273
+ // https://v8.dev/blog/elements-kinds#avoid-creating-holes
2274
+ var laneMap = [];
2275
+
2276
+ for (var i = 0; i < TotalLanes; i++) {
2277
+ laneMap.push(initial);
2278
+ }
2279
+
2280
+ return laneMap;
2296
2281
  }
2297
2282
  function markRootUpdated(root, updateLane, eventTime) {
2298
2283
  root.pendingLanes |= updateLane; // TODO: Theoretically, any update to any lane can unblock any other lane. But
@@ -2333,9 +2318,6 @@ function markRootSuspended(root, suspendedLanes) {
2333
2318
  function markRootPinged(root, pingedLanes, eventTime) {
2334
2319
  root.pingedLanes |= root.suspendedLanes & pingedLanes;
2335
2320
  }
2336
- function markRootExpired(root, expiredLanes) {
2337
- root.expiredLanes |= expiredLanes & root.pendingLanes;
2338
- }
2339
2321
  function hasDiscreteLanes(lanes) {
2340
2322
  return (lanes & InputDiscreteLanes) !== NoLanes;
2341
2323
  }
@@ -2534,7 +2516,7 @@ function flushSyncCallbackQueue() {
2534
2516
  Scheduler_cancelCallback(node);
2535
2517
  }
2536
2518
 
2537
- return flushSyncCallbackQueueImpl();
2519
+ flushSyncCallbackQueueImpl();
2538
2520
  }
2539
2521
 
2540
2522
  function flushSyncCallbackQueueImpl() {
@@ -2570,30 +2552,11 @@ function flushSyncCallbackQueueImpl() {
2570
2552
  isFlushingSyncQueue = false;
2571
2553
  }
2572
2554
  }
2573
-
2574
- return true;
2575
- } else {
2576
- return false;
2577
2555
  }
2578
2556
  }
2579
2557
 
2580
- var NoFlags$1 =
2581
- /* */
2582
- 0; // Represents whether effect should fire.
2583
-
2584
- var HasEffect =
2585
- /* */
2586
- 1; // Represents the phase in which the effect (not the clean-up) fires.
2587
-
2588
- var Layout =
2589
- /* */
2590
- 2;
2591
- var Passive$1 =
2592
- /* */
2593
- 4;
2594
-
2595
2558
  // TODO: this is special because it gets imported during build.
2596
- var ReactVersion = '17.0.0-rc.2';
2559
+ var ReactVersion = '17.0.2';
2597
2560
 
2598
2561
  var NoMode = 0;
2599
2562
  var StrictMode = 1; // TODO: Remove BlockingMode and ConcurrentMode by reading from the root
@@ -2804,7 +2767,7 @@ var ReactStrictModeWarnings = {
2804
2767
  var didWarnAboutUnsafeLifecycles = new Set();
2805
2768
 
2806
2769
  ReactStrictModeWarnings.recordUnsafeLifecycleWarnings = function (fiber, instance) {
2807
- // Dedupe strategy: Warn once per component.
2770
+ // Dedup strategy: Warn once per component.
2808
2771
  if (didWarnAboutUnsafeLifecycles.has(fiber.type)) {
2809
2772
  return;
2810
2773
  }
@@ -4600,16 +4563,24 @@ function ChildReconciler(shouldTrackSideEffects) {
4600
4563
  if (!shouldTrackSideEffects) {
4601
4564
  // Noop.
4602
4565
  return;
4603
- }
4566
+ } // Deletions are added in reversed order so we add it to the front.
4567
+ // At this point, the return fiber's effect list is empty except for
4568
+ // deletions, so we can just append the deletion to the list. The remaining
4569
+ // effects aren't added until the complete phase. Once we implement
4570
+ // resuming, this may not be true.
4604
4571
 
4605
- var deletions = returnFiber.deletions;
4606
4572
 
4607
- if (deletions === null) {
4608
- returnFiber.deletions = [childToDelete];
4609
- returnFiber.flags |= Deletion;
4573
+ var last = returnFiber.lastEffect;
4574
+
4575
+ if (last !== null) {
4576
+ last.nextEffect = childToDelete;
4577
+ returnFiber.lastEffect = childToDelete;
4610
4578
  } else {
4611
- deletions.push(childToDelete);
4579
+ returnFiber.firstEffect = returnFiber.lastEffect = childToDelete;
4612
4580
  }
4581
+
4582
+ childToDelete.nextEffect = null;
4583
+ childToDelete.flags = Deletion;
4613
4584
  }
4614
4585
 
4615
4586
  function deleteRemainingChildren(returnFiber, currentFirstChild) {
@@ -5665,13 +5636,6 @@ function popSuspenseContext(fiber) {
5665
5636
  pop(suspenseStackCursor, fiber);
5666
5637
  }
5667
5638
 
5668
- // A non-null SuspenseState means that it is blocked for one reason or another.
5669
- // - A non-null dehydrated field means it's blocked pending hydration.
5670
- // - A non-null dehydrated field can use isSuspenseInstancePending or
5671
- // isSuspenseInstanceFallback to query the reason for being dehydrated.
5672
- // - A null dehydrated field means it's blocked by something suspending and
5673
- // we're currently showing a fallback instead.
5674
-
5675
5639
  function shouldCaptureSuspense(workInProgress, hasInvisibleParent) {
5676
5640
  // If it was the primary children that just suspended, capture and render the
5677
5641
  // fallback. Otherwise, don't capture and bubble to the next boundary.
@@ -5753,6 +5717,21 @@ function findFirstSuspended(row) {
5753
5717
  return null;
5754
5718
  }
5755
5719
 
5720
+ var NoFlags$1 =
5721
+ /* */
5722
+ 0; // Represents whether effect should fire.
5723
+
5724
+ var HasEffect =
5725
+ /* */
5726
+ 1; // Represents the phase in which the effect (not the clean-up) fires.
5727
+
5728
+ var Layout =
5729
+ /* */
5730
+ 2;
5731
+ var Passive$1 =
5732
+ /* */
5733
+ 4;
5734
+
5756
5735
  var isHydrating = false;
5757
5736
 
5758
5737
  function enterHydrationState(fiber) {
@@ -6785,7 +6764,7 @@ function mountEffect(create, deps) {
6785
6764
  }
6786
6765
  }
6787
6766
 
6788
- return mountEffectImpl(Passive | PassiveStatic, Passive$1, create, deps);
6767
+ return mountEffectImpl(Update | Passive, Passive$1, create, deps);
6789
6768
  }
6790
6769
 
6791
6770
  function updateEffect(create, deps) {
@@ -6796,7 +6775,7 @@ function updateEffect(create, deps) {
6796
6775
  }
6797
6776
  }
6798
6777
 
6799
- return updateEffectImpl(Passive, Passive$1, create, deps);
6778
+ return updateEffectImpl(Update | Passive, Passive$1, create, deps);
6800
6779
  }
6801
6780
 
6802
6781
  function mountLayoutEffect(create, deps) {
@@ -8308,8 +8287,7 @@ function updateMode(current, workInProgress, renderLanes) {
8308
8287
 
8309
8288
  function updateProfiler(current, workInProgress, renderLanes) {
8310
8289
  {
8311
- // TODO: Only call onRender et al if subtree has effects
8312
- workInProgress.flags |= Update | Passive; // Reset effect durations for the next eventual effect phase.
8290
+ workInProgress.flags |= Update; // Reset effect durations for the next eventual effect phase.
8313
8291
  // These are reset during render to allow the DevTools commit hook a chance to read them,
8314
8292
 
8315
8293
  var stateNode = workInProgress.stateNode;
@@ -8906,7 +8884,8 @@ function updateSuspenseOffscreenState(prevOffscreenState, renderLanes) {
8906
8884
  return {
8907
8885
  baseLanes: mergeLanes(prevOffscreenState.baseLanes, renderLanes)
8908
8886
  };
8909
- }
8887
+ } // TODO: Probably should inline this back
8888
+
8910
8889
 
8911
8890
  function shouldRemainOnFallback(suspenseContext, current, workInProgress, renderLanes) {
8912
8891
  // If we're already showing a fallback, there are cases where we need to
@@ -8995,17 +8974,41 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) {
8995
8974
  // But only if this has a fallback.
8996
8975
  if (nextProps.fallback !== undefined) ;
8997
8976
 
8977
+ var nextPrimaryChildren = nextProps.children;
8978
+ var nextFallbackChildren = nextProps.fallback;
8979
+
8998
8980
  if (showFallback) {
8999
- var nextPrimaryChildren = nextProps.children;
9000
- var nextFallbackChildren = nextProps.fallback;
9001
8981
  var fallbackFragment = mountSuspenseFallbackChildren(workInProgress, nextPrimaryChildren, nextFallbackChildren, renderLanes);
9002
8982
  var primaryChildFragment = workInProgress.child;
9003
8983
  primaryChildFragment.memoizedState = mountSuspenseOffscreenState(renderLanes);
9004
8984
  workInProgress.memoizedState = SUSPENDED_MARKER;
9005
8985
  return fallbackFragment;
8986
+ } else if (typeof nextProps.unstable_expectedLoadTime === 'number') {
8987
+ // This is a CPU-bound tree. Skip this tree and show a placeholder to
8988
+ // unblock the surrounding content. Then immediately retry after the
8989
+ // initial commit.
8990
+ var _fallbackFragment = mountSuspenseFallbackChildren(workInProgress, nextPrimaryChildren, nextFallbackChildren, renderLanes);
8991
+
8992
+ var _primaryChildFragment = workInProgress.child;
8993
+ _primaryChildFragment.memoizedState = mountSuspenseOffscreenState(renderLanes);
8994
+ workInProgress.memoizedState = SUSPENDED_MARKER; // Since nothing actually suspended, there will nothing to ping this to
8995
+ // get it started back up to attempt the next item. While in terms of
8996
+ // priority this work has the same priority as this current render, it's
8997
+ // not part of the same transition once the transition has committed. If
8998
+ // it's sync, we still want to yield so that it can be painted.
8999
+ // Conceptually, this is really the same as pinging. We can use any
9000
+ // RetryLane even if it's the one currently rendering since we're leaving
9001
+ // it behind on this node.
9002
+
9003
+ workInProgress.lanes = SomeRetryLane;
9004
+
9005
+ {
9006
+ markSpawnedWork(SomeRetryLane);
9007
+ }
9008
+
9009
+ return _fallbackFragment;
9006
9010
  } else {
9007
- var _nextPrimaryChildren = nextProps.children;
9008
- return mountSuspensePrimaryChildren(workInProgress, _nextPrimaryChildren, renderLanes);
9011
+ return mountSuspensePrimaryChildren(workInProgress, nextPrimaryChildren, renderLanes);
9009
9012
  }
9010
9013
  } else {
9011
9014
  // This is an update.
@@ -9017,37 +9020,37 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) {
9017
9020
 
9018
9021
  if (showFallback) {
9019
9022
  var _nextFallbackChildren2 = nextProps.fallback;
9020
- var _nextPrimaryChildren3 = nextProps.children;
9023
+ var _nextPrimaryChildren2 = nextProps.children;
9021
9024
 
9022
- var _fallbackChildFragment = updateSuspenseFallbackChildren(current, workInProgress, _nextPrimaryChildren3, _nextFallbackChildren2, renderLanes);
9025
+ var _fallbackChildFragment = updateSuspenseFallbackChildren(current, workInProgress, _nextPrimaryChildren2, _nextFallbackChildren2, renderLanes);
9023
9026
 
9024
- var _primaryChildFragment2 = workInProgress.child;
9027
+ var _primaryChildFragment3 = workInProgress.child;
9025
9028
  var prevOffscreenState = current.child.memoizedState;
9026
- _primaryChildFragment2.memoizedState = prevOffscreenState === null ? mountSuspenseOffscreenState(renderLanes) : updateSuspenseOffscreenState(prevOffscreenState, renderLanes);
9027
- _primaryChildFragment2.childLanes = getRemainingWorkInPrimaryTree(current, renderLanes);
9029
+ _primaryChildFragment3.memoizedState = prevOffscreenState === null ? mountSuspenseOffscreenState(renderLanes) : updateSuspenseOffscreenState(prevOffscreenState, renderLanes);
9030
+ _primaryChildFragment3.childLanes = getRemainingWorkInPrimaryTree(current, renderLanes);
9028
9031
  workInProgress.memoizedState = SUSPENDED_MARKER;
9029
9032
  return _fallbackChildFragment;
9030
9033
  } else {
9031
- var _nextPrimaryChildren4 = nextProps.children;
9034
+ var _nextPrimaryChildren3 = nextProps.children;
9032
9035
 
9033
- var _primaryChildFragment3 = updateSuspensePrimaryChildren(current, workInProgress, _nextPrimaryChildren4, renderLanes);
9036
+ var _primaryChildFragment4 = updateSuspensePrimaryChildren(current, workInProgress, _nextPrimaryChildren3, renderLanes);
9034
9037
 
9035
9038
  workInProgress.memoizedState = null;
9036
- return _primaryChildFragment3;
9039
+ return _primaryChildFragment4;
9037
9040
  }
9038
9041
  } else {
9039
9042
  // The current tree is not already showing a fallback.
9040
9043
  if (showFallback) {
9041
9044
  // Timed out.
9042
9045
  var _nextFallbackChildren3 = nextProps.fallback;
9043
- var _nextPrimaryChildren5 = nextProps.children;
9046
+ var _nextPrimaryChildren4 = nextProps.children;
9044
9047
 
9045
- var _fallbackChildFragment2 = updateSuspenseFallbackChildren(current, workInProgress, _nextPrimaryChildren5, _nextFallbackChildren3, renderLanes);
9048
+ var _fallbackChildFragment2 = updateSuspenseFallbackChildren(current, workInProgress, _nextPrimaryChildren4, _nextFallbackChildren3, renderLanes);
9046
9049
 
9047
- var _primaryChildFragment4 = workInProgress.child;
9050
+ var _primaryChildFragment5 = workInProgress.child;
9048
9051
  var _prevOffscreenState = current.child.memoizedState;
9049
- _primaryChildFragment4.memoizedState = _prevOffscreenState === null ? mountSuspenseOffscreenState(renderLanes) : updateSuspenseOffscreenState(_prevOffscreenState, renderLanes);
9050
- _primaryChildFragment4.childLanes = getRemainingWorkInPrimaryTree(current, renderLanes); // Skip the primary children, and continue working on the
9052
+ _primaryChildFragment5.memoizedState = _prevOffscreenState === null ? mountSuspenseOffscreenState(renderLanes) : updateSuspenseOffscreenState(_prevOffscreenState, renderLanes);
9053
+ _primaryChildFragment5.childLanes = getRemainingWorkInPrimaryTree(current, renderLanes); // Skip the primary children, and continue working on the
9051
9054
  // fallback children.
9052
9055
 
9053
9056
  workInProgress.memoizedState = SUSPENDED_MARKER;
@@ -9055,12 +9058,12 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) {
9055
9058
  } else {
9056
9059
  // Still haven't timed out. Continue rendering the children, like we
9057
9060
  // normally do.
9058
- var _nextPrimaryChildren6 = nextProps.children;
9061
+ var _nextPrimaryChildren5 = nextProps.children;
9059
9062
 
9060
- var _primaryChildFragment5 = updateSuspensePrimaryChildren(current, workInProgress, _nextPrimaryChildren6, renderLanes);
9063
+ var _primaryChildFragment6 = updateSuspensePrimaryChildren(current, workInProgress, _nextPrimaryChildren5, renderLanes);
9061
9064
 
9062
9065
  workInProgress.memoizedState = null;
9063
- return _primaryChildFragment5;
9066
+ return _primaryChildFragment6;
9064
9067
  }
9065
9068
  }
9066
9069
  }
@@ -9142,15 +9145,9 @@ function updateSuspensePrimaryChildren(current, workInProgress, primaryChildren,
9142
9145
 
9143
9146
  if (currentFallbackChildFragment !== null) {
9144
9147
  // Delete the fallback child fragment
9145
- var deletions = workInProgress.deletions;
9146
-
9147
- if (deletions === null) {
9148
- workInProgress.deletions = [currentFallbackChildFragment]; // TODO (effects) Rename this to better reflect its new usage (e.g. ChildDeletions)
9149
-
9150
- workInProgress.flags |= Deletion;
9151
- } else {
9152
- deletions.push(currentFallbackChildFragment);
9153
- }
9148
+ currentFallbackChildFragment.nextEffect = null;
9149
+ currentFallbackChildFragment.flags = Deletion;
9150
+ workInProgress.firstEffect = workInProgress.lastEffect = currentFallbackChildFragment;
9154
9151
  }
9155
9152
 
9156
9153
  workInProgress.child = primaryChildFragment;
@@ -9192,16 +9189,24 @@ function updateSuspenseFallbackChildren(current, workInProgress, primaryChildren
9192
9189
  primaryChildFragment.treeBaseDuration = currentPrimaryChildFragment.treeBaseDuration;
9193
9190
  } // The fallback fiber was added as a deletion effect during the first pass.
9194
9191
  // However, since we're going to remain on the fallback, we no longer want
9195
- // to delete it.
9192
+ // to delete it. So we need to remove it from the list. Deletions are stored
9193
+ // on the same list as effects. We want to keep the effects from the primary
9194
+ // tree. So we copy the primary child fragment's effect list, which does not
9195
+ // include the fallback deletion effect.
9196
9196
 
9197
9197
 
9198
- workInProgress.deletions = null;
9199
- } else {
9200
- primaryChildFragment = createWorkInProgressOffscreenFiber(currentPrimaryChildFragment, primaryChildProps); // Since we're reusing a current tree, we need to reuse the flags, too.
9201
- // (We don't do this in legacy mode, because in legacy mode we don't re-use
9202
- // the current tree; see previous branch.)
9198
+ var progressedLastEffect = primaryChildFragment.lastEffect;
9203
9199
 
9204
- primaryChildFragment.subtreeFlags = currentPrimaryChildFragment.subtreeFlags & StaticMask;
9200
+ if (progressedLastEffect !== null) {
9201
+ workInProgress.firstEffect = primaryChildFragment.firstEffect;
9202
+ workInProgress.lastEffect = progressedLastEffect;
9203
+ progressedLastEffect.nextEffect = null;
9204
+ } else {
9205
+ // TODO: Reset this somewhere else? Lol legacy mode is so weird.
9206
+ workInProgress.firstEffect = workInProgress.lastEffect = null;
9207
+ }
9208
+ } else {
9209
+ primaryChildFragment = createWorkInProgressOffscreenFiber(currentPrimaryChildFragment, primaryChildProps);
9205
9210
  }
9206
9211
 
9207
9212
  var fallbackChildFragment;
@@ -9404,7 +9409,7 @@ function validateSuspenseListChildren(children, revealOrder) {
9404
9409
  }
9405
9410
  }
9406
9411
 
9407
- function initSuspenseListRenderState(workInProgress, isBackwards, tail, lastContentRow, tailMode) {
9412
+ function initSuspenseListRenderState(workInProgress, isBackwards, tail, lastContentRow, tailMode, lastEffectBeforeRendering) {
9408
9413
  var renderState = workInProgress.memoizedState;
9409
9414
 
9410
9415
  if (renderState === null) {
@@ -9414,7 +9419,8 @@ function initSuspenseListRenderState(workInProgress, isBackwards, tail, lastCont
9414
9419
  renderingStartTime: 0,
9415
9420
  last: lastContentRow,
9416
9421
  tail: tail,
9417
- tailMode: tailMode
9422
+ tailMode: tailMode,
9423
+ lastEffect: lastEffectBeforeRendering
9418
9424
  };
9419
9425
  } else {
9420
9426
  // We can reuse the existing object from previous renders.
@@ -9424,6 +9430,7 @@ function initSuspenseListRenderState(workInProgress, isBackwards, tail, lastCont
9424
9430
  renderState.last = lastContentRow;
9425
9431
  renderState.tail = tail;
9426
9432
  renderState.tailMode = tailMode;
9433
+ renderState.lastEffect = lastEffectBeforeRendering;
9427
9434
  }
9428
9435
  } // This can end up rendering this component multiple passes.
9429
9436
  // The first pass splits the children fibers into two sets. A head and tail.
@@ -9488,7 +9495,7 @@ function updateSuspenseListComponent(current, workInProgress, renderLanes) {
9488
9495
  }
9489
9496
 
9490
9497
  initSuspenseListRenderState(workInProgress, false, // isBackwards
9491
- tail, lastContentRow, tailMode);
9498
+ tail, lastContentRow, tailMode, workInProgress.lastEffect);
9492
9499
  break;
9493
9500
  }
9494
9501
 
@@ -9520,7 +9527,7 @@ function updateSuspenseListComponent(current, workInProgress, renderLanes) {
9520
9527
 
9521
9528
  initSuspenseListRenderState(workInProgress, true, // isBackwards
9522
9529
  _tail, null, // last
9523
- tailMode);
9530
+ tailMode, workInProgress.lastEffect);
9524
9531
  break;
9525
9532
  }
9526
9533
 
@@ -9529,7 +9536,7 @@ function updateSuspenseListComponent(current, workInProgress, renderLanes) {
9529
9536
  initSuspenseListRenderState(workInProgress, false, // isBackwards
9530
9537
  null, // tail
9531
9538
  null, // last
9532
- undefined);
9539
+ undefined, workInProgress.lastEffect);
9533
9540
  break;
9534
9541
  }
9535
9542
 
@@ -9735,16 +9742,17 @@ function remountFiber(current, oldWorkInProgress, newWorkInProgress) {
9735
9742
  // Since the old fiber is disconnected, we have to schedule it manually.
9736
9743
 
9737
9744
 
9738
- var deletions = returnFiber.deletions;
9739
-
9740
- if (deletions === null) {
9741
- returnFiber.deletions = [current]; // TODO (effects) Rename this to better reflect its new usage (e.g. ChildDeletions)
9745
+ var last = returnFiber.lastEffect;
9742
9746
 
9743
- returnFiber.flags |= Deletion;
9747
+ if (last !== null) {
9748
+ last.nextEffect = current;
9749
+ returnFiber.lastEffect = current;
9744
9750
  } else {
9745
- deletions.push(current);
9751
+ returnFiber.firstEffect = returnFiber.lastEffect = current;
9746
9752
  }
9747
9753
 
9754
+ current.nextEffect = null;
9755
+ current.flags = Deletion;
9748
9756
  newWorkInProgress.flags |= Placement; // Restart work from the new fiber.
9749
9757
 
9750
9758
  return newWorkInProgress;
@@ -9809,11 +9817,10 @@ function beginWork(current, workInProgress, renderLanes) {
9809
9817
  case Profiler:
9810
9818
  {
9811
9819
  // Profiler should only call onRender when one of its descendants actually rendered.
9812
- // TODO: Only call onRender et al if subtree has effects
9813
9820
  var hasChildWork = includesSomeLane(renderLanes, workInProgress.childLanes);
9814
9821
 
9815
9822
  if (hasChildWork) {
9816
- workInProgress.flags |= Passive | Update;
9823
+ workInProgress.flags |= Update;
9817
9824
  } // Reset effect durations for the next eventual effect phase.
9818
9825
  // These are reset during render to allow the DevTools commit hook a chance to read them,
9819
9826
 
@@ -9897,6 +9904,7 @@ function beginWork(current, workInProgress, renderLanes) {
9897
9904
  // update in the past but didn't complete it.
9898
9905
  renderState.rendering = null;
9899
9906
  renderState.tail = null;
9907
+ renderState.lastEffect = null;
9900
9908
  }
9901
9909
 
9902
9910
  pushSuspenseContext(workInProgress, suspenseStackCursor.current);
@@ -10148,7 +10156,7 @@ var updateHostText$1;
10148
10156
  }
10149
10157
  };
10150
10158
 
10151
- updateHostContainer = function (current, workInProgress) {// Noop
10159
+ updateHostContainer = function (workInProgress) {// Noop
10152
10160
  };
10153
10161
 
10154
10162
  updateHostComponent$1 = function (current, workInProgress, type, newProps, rootContainerInstance) {
@@ -10264,92 +10272,6 @@ function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) {
10264
10272
  }
10265
10273
  }
10266
10274
 
10267
- function bubbleProperties(completedWork) {
10268
- var didBailout = completedWork.alternate !== null && completedWork.alternate.child === completedWork.child;
10269
- var newChildLanes = NoLanes;
10270
- var subtreeFlags = NoFlags;
10271
-
10272
- if (!didBailout) {
10273
- // Bubble up the earliest expiration time.
10274
- if ( (completedWork.mode & ProfileMode) !== NoMode) {
10275
- // In profiling mode, resetChildExpirationTime is also used to reset
10276
- // profiler durations.
10277
- var actualDuration = completedWork.actualDuration;
10278
- var treeBaseDuration = completedWork.selfBaseDuration;
10279
- var child = completedWork.child;
10280
-
10281
- while (child !== null) {
10282
- newChildLanes = mergeLanes(newChildLanes, mergeLanes(child.lanes, child.childLanes));
10283
- subtreeFlags |= child.subtreeFlags;
10284
- subtreeFlags |= child.flags; // When a fiber is cloned, its actualDuration is reset to 0. This value will
10285
- // only be updated if work is done on the fiber (i.e. it doesn't bailout).
10286
- // When work is done, it should bubble to the parent's actualDuration. If
10287
- // the fiber has not been cloned though, (meaning no work was done), then
10288
- // this value will reflect the amount of time spent working on a previous
10289
- // render. In that case it should not bubble. We determine whether it was
10290
- // cloned by comparing the child pointer.
10291
-
10292
- actualDuration += child.actualDuration;
10293
- treeBaseDuration += child.treeBaseDuration;
10294
- child = child.sibling;
10295
- }
10296
-
10297
- completedWork.actualDuration = actualDuration;
10298
- completedWork.treeBaseDuration = treeBaseDuration;
10299
- } else {
10300
- var _child = completedWork.child;
10301
-
10302
- while (_child !== null) {
10303
- newChildLanes = mergeLanes(newChildLanes, mergeLanes(_child.lanes, _child.childLanes));
10304
- subtreeFlags |= _child.subtreeFlags;
10305
- subtreeFlags |= _child.flags;
10306
- _child = _child.sibling;
10307
- }
10308
- }
10309
-
10310
- completedWork.subtreeFlags |= subtreeFlags;
10311
- } else {
10312
- // Bubble up the earliest expiration time.
10313
- if ( (completedWork.mode & ProfileMode) !== NoMode) {
10314
- // In profiling mode, resetChildExpirationTime is also used to reset
10315
- // profiler durations.
10316
- var _treeBaseDuration = completedWork.selfBaseDuration;
10317
- var _child2 = completedWork.child;
10318
-
10319
- while (_child2 !== null) {
10320
- newChildLanes = mergeLanes(newChildLanes, mergeLanes(_child2.lanes, _child2.childLanes)); // "Static" flags share the lifetime of the fiber/hook they belong to,
10321
- // so we should bubble those up even during a bailout. All the other
10322
- // flags have a lifetime only of a single render + commit, so we should
10323
- // ignore them.
10324
-
10325
- subtreeFlags |= _child2.subtreeFlags & StaticMask;
10326
- subtreeFlags |= _child2.flags & StaticMask;
10327
- _treeBaseDuration += _child2.treeBaseDuration;
10328
- _child2 = _child2.sibling;
10329
- }
10330
-
10331
- completedWork.treeBaseDuration = _treeBaseDuration;
10332
- } else {
10333
- var _child3 = completedWork.child;
10334
-
10335
- while (_child3 !== null) {
10336
- newChildLanes = mergeLanes(newChildLanes, mergeLanes(_child3.lanes, _child3.childLanes)); // "Static" flags share the lifetime of the fiber/hook they belong to,
10337
- // so we should bubble those up even during a bailout. All the other
10338
- // flags have a lifetime only of a single render + commit, so we should
10339
- // ignore them.
10340
-
10341
- subtreeFlags |= _child3.subtreeFlags & StaticMask;
10342
- subtreeFlags |= _child3.flags & StaticMask;
10343
- _child3 = _child3.sibling;
10344
- }
10345
- }
10346
-
10347
- completedWork.subtreeFlags |= subtreeFlags;
10348
- }
10349
-
10350
- completedWork.childLanes = newChildLanes;
10351
- }
10352
-
10353
10275
  function completeWork(current, workInProgress, renderLanes) {
10354
10276
  var newProps = workInProgress.pendingProps;
10355
10277
 
@@ -10364,7 +10286,6 @@ function completeWork(current, workInProgress, renderLanes) {
10364
10286
  case Profiler:
10365
10287
  case ContextConsumer:
10366
10288
  case MemoComponent:
10367
- bubbleProperties(workInProgress);
10368
10289
  return null;
10369
10290
 
10370
10291
  case ClassComponent:
@@ -10375,7 +10296,6 @@ function completeWork(current, workInProgress, renderLanes) {
10375
10296
  popContext(workInProgress);
10376
10297
  }
10377
10298
 
10378
- bubbleProperties(workInProgress);
10379
10299
  return null;
10380
10300
  }
10381
10301
 
@@ -10409,8 +10329,7 @@ function completeWork(current, workInProgress, renderLanes) {
10409
10329
  }
10410
10330
  }
10411
10331
 
10412
- updateHostContainer(current, workInProgress);
10413
- bubbleProperties(workInProgress);
10332
+ updateHostContainer(workInProgress);
10414
10333
  return null;
10415
10334
  }
10416
10335
 
@@ -10435,7 +10354,6 @@ function completeWork(current, workInProgress, renderLanes) {
10435
10354
  } // This can happen when we abort work.
10436
10355
 
10437
10356
 
10438
- bubbleProperties(workInProgress);
10439
10357
  return null;
10440
10358
  }
10441
10359
 
@@ -10466,7 +10384,6 @@ function completeWork(current, workInProgress, renderLanes) {
10466
10384
  }
10467
10385
  }
10468
10386
 
10469
- bubbleProperties(workInProgress);
10470
10387
  return null;
10471
10388
  }
10472
10389
 
@@ -10504,7 +10421,6 @@ function completeWork(current, workInProgress, renderLanes) {
10504
10421
  }
10505
10422
  }
10506
10423
 
10507
- bubbleProperties(workInProgress);
10508
10424
  return null;
10509
10425
  }
10510
10426
 
@@ -10519,8 +10435,7 @@ function completeWork(current, workInProgress, renderLanes) {
10519
10435
 
10520
10436
  if ( (workInProgress.mode & ProfileMode) !== NoMode) {
10521
10437
  transferActualDuration(workInProgress);
10522
- } // Don't bubble properties in this case.
10523
-
10438
+ }
10524
10439
 
10525
10440
  return workInProgress;
10526
10441
  }
@@ -10575,40 +10490,22 @@ function completeWork(current, workInProgress, renderLanes) {
10575
10490
  }
10576
10491
  }
10577
10492
 
10578
- bubbleProperties(workInProgress);
10579
-
10580
- {
10581
- if ((workInProgress.mode & ProfileMode) !== NoMode) {
10582
- if (nextDidTimeout) {
10583
- // Don't count time spent in a timed out Suspense subtree as part of the base duration.
10584
- var _primaryChildFragment2 = workInProgress.child;
10585
-
10586
- if (_primaryChildFragment2 !== null) {
10587
- // $FlowFixMe Flow doens't support type casting in combiation with the -= operator
10588
- workInProgress.treeBaseDuration -= _primaryChildFragment2.treeBaseDuration;
10589
- }
10590
- }
10591
- }
10592
- }
10593
-
10594
10493
  return null;
10595
10494
  }
10596
10495
 
10597
10496
  case HostPortal:
10598
10497
  popHostContainer(workInProgress);
10599
- updateHostContainer(current, workInProgress);
10498
+ updateHostContainer(workInProgress);
10600
10499
 
10601
10500
  if (current === null) {
10602
10501
  preparePortalMount(workInProgress.stateNode.containerInfo);
10603
10502
  }
10604
10503
 
10605
- bubbleProperties(workInProgress);
10606
10504
  return null;
10607
10505
 
10608
10506
  case ContextProvider:
10609
10507
  // Pop provider fiber
10610
10508
  popProvider(workInProgress);
10611
- bubbleProperties(workInProgress);
10612
10509
  return null;
10613
10510
 
10614
10511
  case IncompleteClassComponent:
@@ -10621,7 +10518,6 @@ function completeWork(current, workInProgress, renderLanes) {
10621
10518
  popContext(workInProgress);
10622
10519
  }
10623
10520
 
10624
- bubbleProperties(workInProgress);
10625
10521
  return null;
10626
10522
  }
10627
10523
 
@@ -10633,7 +10529,6 @@ function completeWork(current, workInProgress, renderLanes) {
10633
10529
  if (renderState === null) {
10634
10530
  // We're running in the default, "independent" mode.
10635
10531
  // We don't do anything in this mode.
10636
- bubbleProperties(workInProgress);
10637
10532
  return null;
10638
10533
  }
10639
10534
 
@@ -10683,15 +10578,19 @@ function completeWork(current, workInProgress, renderLanes) {
10683
10578
  workInProgress.flags |= Update;
10684
10579
  } // Rerender the whole list, but this time, we'll force fallbacks
10685
10580
  // to stay in place.
10686
- // Reset the child fibers to their original state.
10581
+ // Reset the effect list before doing the second pass since that's now invalid.
10582
+
10583
+
10584
+ if (renderState.lastEffect === null) {
10585
+ workInProgress.firstEffect = null;
10586
+ }
10687
10587
 
10588
+ workInProgress.lastEffect = renderState.lastEffect; // Reset the child fibers to their original state.
10688
10589
 
10689
- workInProgress.subtreeFlags = NoFlags;
10690
10590
  resetChildFibers(workInProgress, renderLanes); // Set up the Suspense Context to force suspense and immediately
10691
10591
  // rerender the children.
10692
10592
 
10693
- pushSuspenseContext(workInProgress, setShallowSuspenseContext(suspenseStackCursor.current, ForceSuspenseFallback)); // Don't bubble properties in this case.
10694
-
10593
+ pushSuspenseContext(workInProgress, setShallowSuspenseContext(suspenseStackCursor.current, ForceSuspenseFallback));
10695
10594
  return workInProgress.child;
10696
10595
  }
10697
10596
 
@@ -10745,8 +10644,16 @@ function completeWork(current, workInProgress, renderLanes) {
10745
10644
 
10746
10645
  if (renderState.tail === null && renderState.tailMode === 'hidden' && !renderedTail.alternate && !getIsHydrating() // We don't cut it if we're hydrating.
10747
10646
  ) {
10748
- // We're done.
10749
- bubbleProperties(workInProgress);
10647
+ // We need to delete the row we just rendered.
10648
+ // Reset the effect list to what it was before we rendered this
10649
+ // child. The nested children have already appended themselves.
10650
+ var lastEffect = workInProgress.lastEffect = renderState.lastEffect; // Remove any effects that were appended after this point.
10651
+
10652
+ if (lastEffect !== null) {
10653
+ lastEffect.nextEffect = null;
10654
+ } // We're done.
10655
+
10656
+
10750
10657
  return null;
10751
10658
  }
10752
10659
  } else if ( // The time it took to render last row is greater than the remaining
@@ -10759,10 +10666,13 @@ function completeWork(current, workInProgress, renderLanes) {
10759
10666
  workInProgress.flags |= DidCapture;
10760
10667
  didSuspendAlready = true;
10761
10668
  cutOffTailIfNeeded(renderState, false); // Since nothing actually suspended, there will nothing to ping this
10762
- // to get it started back up to attempt the next item. If we can show
10763
- // them, then they really have the same priority as this render.
10764
- // So we'll pick it back up the very next render pass once we've had
10765
- // an opportunity to yield for paint.
10669
+ // to get it started back up to attempt the next item. While in terms
10670
+ // of priority this work has the same priority as this current render,
10671
+ // it's not part of the same transition once the transition has
10672
+ // committed. If it's sync, we still want to yield so that it can be
10673
+ // painted. Conceptually, this is really the same as pinging.
10674
+ // We can use any RetryLane even if it's the one currently rendering
10675
+ // since we're leaving it behind on this node.
10766
10676
 
10767
10677
  workInProgress.lanes = SomeRetryLane;
10768
10678
 
@@ -10799,6 +10709,7 @@ function completeWork(current, workInProgress, renderLanes) {
10799
10709
  var next = renderState.tail;
10800
10710
  renderState.rendering = next;
10801
10711
  renderState.tail = next.sibling;
10712
+ renderState.lastEffect = workInProgress.lastEffect;
10802
10713
  renderState.renderingStartTime = now();
10803
10714
  next.sibling = null; // Restore the context.
10804
10715
  // TODO: We can probably just avoid popping it instead and only
@@ -10813,12 +10724,10 @@ function completeWork(current, workInProgress, renderLanes) {
10813
10724
  }
10814
10725
 
10815
10726
  pushSuspenseContext(workInProgress, suspenseContext); // Do a pass over the next row.
10816
- // Don't bubble properties in this case.
10817
10727
 
10818
10728
  return next;
10819
10729
  }
10820
10730
 
10821
- bubbleProperties(workInProgress);
10822
10731
  return null;
10823
10732
  }
10824
10733
 
@@ -10842,21 +10751,16 @@ function completeWork(current, workInProgress, renderLanes) {
10842
10751
  case LegacyHiddenComponent:
10843
10752
  {
10844
10753
  popRenderLanes(workInProgress);
10845
- var _nextState = workInProgress.memoizedState;
10846
- var nextIsHidden = _nextState !== null;
10847
10754
 
10848
10755
  if (current !== null) {
10756
+ var _nextState = workInProgress.memoizedState;
10849
10757
  var _prevState = current.memoizedState;
10850
10758
  var prevIsHidden = _prevState !== null;
10759
+ var nextIsHidden = _nextState !== null;
10851
10760
 
10852
10761
  if (prevIsHidden !== nextIsHidden && newProps.mode !== 'unstable-defer-without-hiding') {
10853
10762
  workInProgress.flags |= Update;
10854
10763
  }
10855
- } // Don't bubble properties for hidden children.
10856
-
10857
-
10858
- if (!nextIsHidden || includesSomeLane(subtreeRenderLanes, OffscreenLane) || (workInProgress.mode & ConcurrentMode) === NoMode) {
10859
- bubbleProperties(workInProgress);
10860
10764
  }
10861
10765
 
10862
10766
  return null;
@@ -11210,7 +11114,9 @@ function attachPingListener(root, wakeable, lanes) {
11210
11114
 
11211
11115
  function throwException(root, returnFiber, sourceFiber, value, rootRenderLanes) {
11212
11116
  // The source fiber did not complete.
11213
- sourceFiber.flags |= Incomplete;
11117
+ sourceFiber.flags |= Incomplete; // Its effect list is no longer valid.
11118
+
11119
+ sourceFiber.firstEffect = sourceFiber.lastEffect = null;
11214
11120
 
11215
11121
  if (value !== null && typeof value === 'object' && typeof value.then === 'function') {
11216
11122
  // This is a wakeable.
@@ -11628,18 +11534,18 @@ var callComponentWillUnmountWithTimer = function (current, instance) {
11628
11534
  }; // Capture errors so they don't interrupt unmounting.
11629
11535
 
11630
11536
 
11631
- function safelyCallComponentWillUnmount(current, instance, nearestMountedAncestor) {
11537
+ function safelyCallComponentWillUnmount(current, instance) {
11632
11538
  {
11633
11539
  invokeGuardedCallback(null, callComponentWillUnmountWithTimer, null, current, instance);
11634
11540
 
11635
11541
  if (hasCaughtError()) {
11636
11542
  var unmountError = clearCaughtError();
11637
- captureCommitPhaseError(current, nearestMountedAncestor, unmountError);
11543
+ captureCommitPhaseError(current, unmountError);
11638
11544
  }
11639
11545
  }
11640
11546
  }
11641
11547
 
11642
- function safelyDetachRef(current, nearestMountedAncestor) {
11548
+ function safelyDetachRef(current) {
11643
11549
  var ref = current.ref;
11644
11550
 
11645
11551
  if (ref !== null) {
@@ -11649,7 +11555,7 @@ function safelyDetachRef(current, nearestMountedAncestor) {
11649
11555
 
11650
11556
  if (hasCaughtError()) {
11651
11557
  var refError = clearCaughtError();
11652
- captureCommitPhaseError(current, nearestMountedAncestor, refError);
11558
+ captureCommitPhaseError(current, refError);
11653
11559
  }
11654
11560
  }
11655
11561
  } else {
@@ -11658,13 +11564,13 @@ function safelyDetachRef(current, nearestMountedAncestor) {
11658
11564
  }
11659
11565
  }
11660
11566
 
11661
- function safelyCallDestroy(current, nearestMountedAncestor, destroy) {
11567
+ function safelyCallDestroy(current, destroy) {
11662
11568
  {
11663
11569
  invokeGuardedCallback(null, destroy, null);
11664
11570
 
11665
11571
  if (hasCaughtError()) {
11666
11572
  var error = clearCaughtError();
11667
- captureCommitPhaseError(current, nearestMountedAncestor, error);
11573
+ captureCommitPhaseError(current, error);
11668
11574
  }
11669
11575
  }
11670
11576
  }
@@ -11747,7 +11653,7 @@ function commitBeforeMutationLifeCycles(current, finishedWork) {
11747
11653
  }
11748
11654
  }
11749
11655
 
11750
- function commitHookEffectListUnmount(tag, finishedWork, nearestMountedAncestor) {
11656
+ function commitHookEffectListUnmount(tag, finishedWork) {
11751
11657
  var updateQueue = finishedWork.updateQueue;
11752
11658
  var lastEffect = updateQueue !== null ? updateQueue.lastEffect : null;
11753
11659
 
@@ -11762,45 +11668,13 @@ function commitHookEffectListUnmount(tag, finishedWork, nearestMountedAncestor)
11762
11668
  effect.destroy = undefined;
11763
11669
 
11764
11670
  if (destroy !== undefined) {
11765
- safelyCallDestroy(finishedWork, nearestMountedAncestor, destroy);
11671
+ destroy();
11766
11672
  }
11767
11673
  }
11768
11674
 
11769
11675
  effect = effect.next;
11770
11676
  } while (effect !== firstEffect);
11771
11677
  }
11772
- } // TODO: Remove this duplication.
11773
-
11774
-
11775
- function commitHookEffectListUnmount2( // Tags to check for when deciding whether to unmount. e.g. to skip over layout effects
11776
- hookFlags, fiber, nearestMountedAncestor) {
11777
- var updateQueue = fiber.updateQueue;
11778
- var lastEffect = updateQueue !== null ? updateQueue.lastEffect : null;
11779
-
11780
- if (lastEffect !== null) {
11781
- var firstEffect = lastEffect.next;
11782
- var effect = firstEffect;
11783
-
11784
- do {
11785
- var _effect = effect,
11786
- next = _effect.next,
11787
- tag = _effect.tag;
11788
-
11789
- if ((tag & hookFlags) === hookFlags) {
11790
- var destroy = effect.destroy;
11791
-
11792
- if (destroy !== undefined) {
11793
- effect.destroy = undefined;
11794
-
11795
- {
11796
- safelyCallDestroy(fiber, nearestMountedAncestor, destroy);
11797
- }
11798
- }
11799
- }
11800
-
11801
- effect = next;
11802
- } while (effect !== firstEffect);
11803
- }
11804
11678
  }
11805
11679
 
11806
11680
  function commitHookEffectListMount(tag, finishedWork) {
@@ -11841,14 +11715,8 @@ function commitHookEffectListMount(tag, finishedWork) {
11841
11715
  }
11842
11716
  }
11843
11717
 
11844
- function invokePassiveEffectCreate(effect) {
11845
- var create = effect.create;
11846
- effect.destroy = create();
11847
- } // TODO: Remove this duplication.
11848
-
11849
-
11850
- function commitHookEffectListMount2(fiber) {
11851
- var updateQueue = fiber.updateQueue;
11718
+ function schedulePassiveEffects(finishedWork) {
11719
+ var updateQueue = finishedWork.updateQueue;
11852
11720
  var lastEffect = updateQueue !== null ? updateQueue.lastEffect : null;
11853
11721
 
11854
11722
  if (lastEffect !== null) {
@@ -11856,27 +11724,13 @@ function commitHookEffectListMount2(fiber) {
11856
11724
  var effect = firstEffect;
11857
11725
 
11858
11726
  do {
11859
- var _effect2 = effect,
11860
- next = _effect2.next,
11861
- tag = _effect2.tag;
11727
+ var _effect = effect,
11728
+ next = _effect.next,
11729
+ tag = _effect.tag;
11862
11730
 
11863
11731
  if ((tag & Passive$1) !== NoFlags$1 && (tag & HasEffect) !== NoFlags$1) {
11864
- {
11865
- {
11866
- invokeGuardedCallback(null, invokePassiveEffectCreate, null, effect);
11867
- }
11868
-
11869
- if (hasCaughtError()) {
11870
- if (!(fiber !== null)) {
11871
- {
11872
- throw Error( "Should be working on an effect." );
11873
- }
11874
- }
11875
-
11876
- var error = clearCaughtError();
11877
- captureCommitPhaseError(fiber, fiber.return, error);
11878
- }
11879
- }
11732
+ enqueuePendingPassiveHookEffectUnmount(finishedWork, effect);
11733
+ enqueuePendingPassiveHookEffectMount(finishedWork, effect);
11880
11734
  }
11881
11735
 
11882
11736
  effect = next;
@@ -11899,10 +11753,7 @@ function commitLifeCycles(finishedRoot, current, finishedWork, committedLanes) {
11899
11753
  commitHookEffectListMount(Layout | HasEffect, finishedWork);
11900
11754
  }
11901
11755
 
11902
- if ((finishedWork.subtreeFlags & PassiveMask) !== NoFlags) {
11903
- schedulePassiveEffectCallback();
11904
- }
11905
-
11756
+ schedulePassiveEffects(finishedWork);
11906
11757
  return;
11907
11758
  }
11908
11759
 
@@ -12166,7 +12017,7 @@ function commitDetachRef(current) {
12166
12017
  // interrupt deletion, so it's okay
12167
12018
 
12168
12019
 
12169
- function commitUnmount(finishedRoot, current, nearestMountedAncestor, renderPriorityLevel) {
12020
+ function commitUnmount(finishedRoot, current, renderPriorityLevel) {
12170
12021
  onCommitUnmount(current);
12171
12022
 
12172
12023
  switch (current.tag) {
@@ -12186,14 +12037,16 @@ function commitUnmount(finishedRoot, current, nearestMountedAncestor, renderPrio
12186
12037
  var effect = firstEffect;
12187
12038
 
12188
12039
  do {
12189
- var _effect3 = effect,
12190
- destroy = _effect3.destroy,
12191
- tag = _effect3.tag;
12040
+ var _effect2 = effect,
12041
+ destroy = _effect2.destroy,
12042
+ tag = _effect2.tag;
12192
12043
 
12193
12044
  if (destroy !== undefined) {
12194
- if ((tag & Layout) !== NoFlags$1) {
12045
+ if ((tag & Passive$1) !== NoFlags$1) {
12046
+ enqueuePendingPassiveHookEffectUnmount(current, effect);
12047
+ } else {
12195
12048
  {
12196
- safelyCallDestroy(current, nearestMountedAncestor, destroy);
12049
+ safelyCallDestroy(current, destroy);
12197
12050
  }
12198
12051
  }
12199
12052
  }
@@ -12208,11 +12061,11 @@ function commitUnmount(finishedRoot, current, nearestMountedAncestor, renderPrio
12208
12061
 
12209
12062
  case ClassComponent:
12210
12063
  {
12211
- safelyDetachRef(current, nearestMountedAncestor);
12064
+ safelyDetachRef(current);
12212
12065
  var instance = current.stateNode;
12213
12066
 
12214
12067
  if (typeof instance.componentWillUnmount === 'function') {
12215
- safelyCallComponentWillUnmount(current, instance, nearestMountedAncestor);
12068
+ safelyCallComponentWillUnmount(current, instance);
12216
12069
  }
12217
12070
 
12218
12071
  return;
@@ -12220,7 +12073,7 @@ function commitUnmount(finishedRoot, current, nearestMountedAncestor, renderPrio
12220
12073
 
12221
12074
  case HostComponent:
12222
12075
  {
12223
- safelyDetachRef(current, nearestMountedAncestor);
12076
+ safelyDetachRef(current);
12224
12077
  return;
12225
12078
  }
12226
12079
 
@@ -12230,7 +12083,7 @@ function commitUnmount(finishedRoot, current, nearestMountedAncestor, renderPrio
12230
12083
  // We are also not using this parent because
12231
12084
  // the portal will get pushed immediately.
12232
12085
  {
12233
- unmountHostComponents(finishedRoot, current, nearestMountedAncestor);
12086
+ unmountHostComponents(finishedRoot, current);
12234
12087
  }
12235
12088
 
12236
12089
  return;
@@ -12256,7 +12109,7 @@ function commitUnmount(finishedRoot, current, nearestMountedAncestor, renderPrio
12256
12109
  }
12257
12110
  }
12258
12111
 
12259
- function commitNestedUnmounts(finishedRoot, root, nearestMountedAncestor, renderPriorityLevel) {
12112
+ function commitNestedUnmounts(finishedRoot, root, renderPriorityLevel) {
12260
12113
  // While we're inside a removed host node we don't want to call
12261
12114
  // removeChild on the inner nodes because they're removed by the top
12262
12115
  // call anyway. We also want to call componentWillUnmount on all
@@ -12265,7 +12118,7 @@ function commitNestedUnmounts(finishedRoot, root, nearestMountedAncestor, render
12265
12118
  var node = root;
12266
12119
 
12267
12120
  while (true) {
12268
- commitUnmount(finishedRoot, node, nearestMountedAncestor); // Visit children because they may contain more composite or host nodes.
12121
+ commitUnmount(finishedRoot, node); // Visit children because they may contain more composite or host nodes.
12269
12122
  // Skip portals because commitUnmount() currently visits them recursively.
12270
12123
 
12271
12124
  if (node.child !== null && ( // If we use mutation we drill down into portals using commitUnmount above.
@@ -12294,26 +12147,33 @@ function commitNestedUnmounts(finishedRoot, root, nearestMountedAncestor, render
12294
12147
  }
12295
12148
 
12296
12149
  function detachFiberMutation(fiber) {
12297
- // Cut off the return pointer to disconnect it from the tree.
12298
- // This enables us to detect and warn against state updates on an unmounted component.
12299
- // It also prevents events from bubbling from within disconnected components.
12300
- //
12301
- // Ideally, we should also clear the child pointer of the parent alternate to let this
12150
+ // Cut off the return pointers to disconnect it from the tree. Ideally, we
12151
+ // should clear the child pointer of the parent alternate to let this
12302
12152
  // get GC:ed but we don't know which for sure which parent is the current
12303
- // one so we'll settle for GC:ing the subtree of this child.
12304
- // This child itself will be GC:ed when the parent updates the next time.
12153
+ // one so we'll settle for GC:ing the subtree of this child. This child
12154
+ // itself will be GC:ed when the parent updates the next time.
12155
+ // Note: we cannot null out sibling here, otherwise it can cause issues
12156
+ // with findDOMNode and how it requires the sibling field to carry out
12157
+ // traversal in a later effect. See PR #16820. We now clear the sibling
12158
+ // field after effects, see: detachFiberAfterEffects.
12305
12159
  //
12306
- // Note that we can't clear child or sibling pointers yet.
12307
- // They're needed for passive effects and for findDOMNode.
12308
- // We defer those fields, and all other cleanup, to the passive phase (see detachFiberAfterEffects).
12309
- var alternate = fiber.alternate;
12160
+ // Don't disconnect stateNode now; it will be detached in detachFiberAfterEffects.
12161
+ // It may be required if the current component is an error boundary,
12162
+ // and one of its descendants throws while unmounting a passive effect.
12163
+ fiber.alternate = null;
12164
+ fiber.child = null;
12165
+ fiber.dependencies = null;
12166
+ fiber.firstEffect = null;
12167
+ fiber.lastEffect = null;
12168
+ fiber.memoizedProps = null;
12169
+ fiber.memoizedState = null;
12170
+ fiber.pendingProps = null;
12171
+ fiber.return = null;
12172
+ fiber.updateQueue = null;
12310
12173
 
12311
- if (alternate !== null) {
12312
- alternate.return = null;
12313
- fiber.alternate = null;
12174
+ {
12175
+ fiber._debugOwner = null;
12314
12176
  }
12315
-
12316
- fiber.return = null;
12317
12177
  }
12318
12178
 
12319
12179
  function getHostParentFiber(fiber) {
@@ -12493,7 +12353,7 @@ function insertOrAppendPlacementNode(node, before, parent) {
12493
12353
  }
12494
12354
  }
12495
12355
 
12496
- function unmountHostComponents(finishedRoot, current, nearestMountedAncestor, renderPriorityLevel) {
12356
+ function unmountHostComponents(finishedRoot, current, renderPriorityLevel) {
12497
12357
  // We only have the top Fiber that was deleted but we need to recurse down its
12498
12358
  // children to find all the terminal nodes.
12499
12359
  var node = current; // Each iteration, currentParent is populated with node's host parent if not
@@ -12542,7 +12402,7 @@ function unmountHostComponents(finishedRoot, current, nearestMountedAncestor, re
12542
12402
  }
12543
12403
 
12544
12404
  if (node.tag === HostComponent || node.tag === HostText) {
12545
- commitNestedUnmounts(finishedRoot, node, nearestMountedAncestor); // After all the children have unmounted, it is now safe to remove the
12405
+ commitNestedUnmounts(finishedRoot, node); // After all the children have unmounted, it is now safe to remove the
12546
12406
  // node from the tree.
12547
12407
 
12548
12408
  if (currentParentIsContainer) {
@@ -12563,7 +12423,7 @@ function unmountHostComponents(finishedRoot, current, nearestMountedAncestor, re
12563
12423
  continue;
12564
12424
  }
12565
12425
  } else {
12566
- commitUnmount(finishedRoot, node, nearestMountedAncestor); // Visit children because we may find more host components below.
12426
+ commitUnmount(finishedRoot, node); // Visit children because we may find more host components below.
12567
12427
 
12568
12428
  if (node.child !== null) {
12569
12429
  node.child.return = node;
@@ -12595,11 +12455,11 @@ function unmountHostComponents(finishedRoot, current, nearestMountedAncestor, re
12595
12455
  }
12596
12456
  }
12597
12457
 
12598
- function commitDeletion(finishedRoot, current, nearestMountedAncestor, renderPriorityLevel) {
12458
+ function commitDeletion(finishedRoot, current, renderPriorityLevel) {
12599
12459
  {
12600
12460
  // Recursively delete all host nodes from the parent.
12601
12461
  // Detach refs and call componentWillUnmount() on the whole subtree.
12602
- unmountHostComponents(finishedRoot, current, nearestMountedAncestor);
12462
+ unmountHostComponents(finishedRoot, current);
12603
12463
  }
12604
12464
 
12605
12465
  var alternate = current.alternate;
@@ -12625,7 +12485,7 @@ function commitWork(current, finishedWork) {
12625
12485
  // e.g. a destroy function in one component should never override a ref set
12626
12486
  // by a create function in another component during the same commit.
12627
12487
  {
12628
- commitHookEffectListUnmount(Layout | HasEffect, finishedWork, finishedWork.return);
12488
+ commitHookEffectListUnmount(Layout | HasEffect, finishedWork);
12629
12489
  }
12630
12490
 
12631
12491
  return;
@@ -12811,42 +12671,6 @@ function commitResetTextContent(current) {
12811
12671
  resetTextContent(current.stateNode);
12812
12672
  }
12813
12673
 
12814
- function commitPassiveWork(finishedWork) {
12815
- switch (finishedWork.tag) {
12816
- case FunctionComponent:
12817
- case ForwardRef:
12818
- case SimpleMemoComponent:
12819
- case Block:
12820
- {
12821
- commitHookEffectListUnmount2(Passive$1 | HasEffect, finishedWork, finishedWork.return);
12822
- break;
12823
- }
12824
- }
12825
- }
12826
-
12827
- function commitPassiveUnmount(current, nearestMountedAncestor) {
12828
- switch (current.tag) {
12829
- case FunctionComponent:
12830
- case ForwardRef:
12831
- case SimpleMemoComponent:
12832
- case Block:
12833
- commitHookEffectListUnmount2(Passive$1, current, nearestMountedAncestor);
12834
- }
12835
- }
12836
-
12837
- function commitPassiveLifeCycles(finishedRoot, finishedWork) {
12838
- switch (finishedWork.tag) {
12839
- case FunctionComponent:
12840
- case ForwardRef:
12841
- case SimpleMemoComponent:
12842
- case Block:
12843
- {
12844
- commitHookEffectListMount2(finishedWork);
12845
- break;
12846
- }
12847
- }
12848
- }
12849
-
12850
12674
  var COMPONENT_TYPE = 0;
12851
12675
  var HAS_PSEUDO_CLASS_TYPE = 1;
12852
12676
  var ROLE_TYPE = 2;
@@ -12983,6 +12807,7 @@ function resetRenderTimer() {
12983
12807
  function getRenderTargetTime() {
12984
12808
  return workInProgressRootRenderTargetTime;
12985
12809
  }
12810
+ var nextEffect = null;
12986
12811
  var hasUncaughtError = false;
12987
12812
  var firstUncaughtError = null;
12988
12813
  var legacyErrorBoundariesThatAlreadyFailed = null;
@@ -12990,6 +12815,8 @@ var rootDoesHavePassiveEffects = false;
12990
12815
  var rootWithPendingPassiveEffects = null;
12991
12816
  var pendingPassiveEffectsRenderPriority = NoPriority$1;
12992
12817
  var pendingPassiveEffectsLanes = NoLanes;
12818
+ var pendingPassiveHookEffectsMount = [];
12819
+ var pendingPassiveHookEffectsUnmount = [];
12993
12820
  var rootsWithPendingDiscreteUpdates = null; // Use these to prevent an infinite loop of nested updates
12994
12821
 
12995
12822
  var NESTED_UPDATE_LIMIT = 50;
@@ -13312,7 +13139,7 @@ function ensureRootIsScheduled(root, currentTime) {
13312
13139
  // goes through Scheduler.
13313
13140
 
13314
13141
 
13315
- function performConcurrentWorkOnRoot(root, didTimeout) {
13142
+ function performConcurrentWorkOnRoot(root) {
13316
13143
  // Since we know we're in a React event, we can clear the current
13317
13144
  // event time. The next update will compute a new event time.
13318
13145
  currentEventTime = NoTimestamp;
@@ -13348,18 +13175,6 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
13348
13175
  if (lanes === NoLanes) {
13349
13176
  // Defensive coding. This is never expected to happen.
13350
13177
  return null;
13351
- } // TODO: We only check `didTimeout` defensively, to account for a Scheduler
13352
- // bug we're still investigating. Once the bug in Scheduler is fixed,
13353
- // we can remove this, since we track expiration ourselves.
13354
-
13355
-
13356
- if ( didTimeout) {
13357
- // Something expired. Flush synchronously until there's no expired
13358
- // work left.
13359
- markRootExpired(root, lanes); // This will schedule a synchronous callback.
13360
-
13361
- ensureRootIsScheduled(root, now());
13362
- return null;
13363
13178
  }
13364
13179
 
13365
13180
  var exitStatus = renderRootConcurrent(root, lanes);
@@ -14030,6 +13845,46 @@ function completeUnitOfWork(unitOfWork) {
14030
13845
  workInProgress = next;
14031
13846
  return;
14032
13847
  }
13848
+
13849
+ resetChildLanes(completedWork);
13850
+
13851
+ if (returnFiber !== null && // Do not append effects to parents if a sibling failed to complete
13852
+ (returnFiber.flags & Incomplete) === NoFlags) {
13853
+ // Append all the effects of the subtree and this fiber onto the effect
13854
+ // list of the parent. The completion order of the children affects the
13855
+ // side-effect order.
13856
+ if (returnFiber.firstEffect === null) {
13857
+ returnFiber.firstEffect = completedWork.firstEffect;
13858
+ }
13859
+
13860
+ if (completedWork.lastEffect !== null) {
13861
+ if (returnFiber.lastEffect !== null) {
13862
+ returnFiber.lastEffect.nextEffect = completedWork.firstEffect;
13863
+ }
13864
+
13865
+ returnFiber.lastEffect = completedWork.lastEffect;
13866
+ } // If this fiber had side-effects, we append it AFTER the children's
13867
+ // side-effects. We can perform certain side-effects earlier if needed,
13868
+ // by doing multiple passes over the effect list. We don't want to
13869
+ // schedule our own side-effect on our own list because if end up
13870
+ // reusing children we'll schedule this effect onto itself since we're
13871
+ // at the end.
13872
+
13873
+
13874
+ var flags = completedWork.flags; // Skip both NoWork and PerformedWork tags when creating the effect
13875
+ // list. PerformedWork effect is read by React DevTools but shouldn't be
13876
+ // committed.
13877
+
13878
+ if (flags > PerformedWork) {
13879
+ if (returnFiber.lastEffect !== null) {
13880
+ returnFiber.lastEffect.nextEffect = completedWork;
13881
+ } else {
13882
+ returnFiber.firstEffect = completedWork;
13883
+ }
13884
+
13885
+ returnFiber.lastEffect = completedWork;
13886
+ }
13887
+ }
14033
13888
  } else {
14034
13889
  // This fiber did not complete because something threw. Pop values off
14035
13890
  // the stack without entering the complete phase. If this is a boundary,
@@ -14063,10 +13918,9 @@ function completeUnitOfWork(unitOfWork) {
14063
13918
  }
14064
13919
 
14065
13920
  if (returnFiber !== null) {
14066
- // Mark the parent fiber as incomplete
13921
+ // Mark the parent fiber as incomplete and clear its effect list.
13922
+ returnFiber.firstEffect = returnFiber.lastEffect = null;
14067
13923
  returnFiber.flags |= Incomplete;
14068
- returnFiber.subtreeFlags = NoFlags;
14069
- returnFiber.deletions = null;
14070
13924
  }
14071
13925
  }
14072
13926
 
@@ -14090,22 +13944,84 @@ function completeUnitOfWork(unitOfWork) {
14090
13944
  }
14091
13945
  }
14092
13946
 
14093
- function commitRoot(root) {
14094
- var renderPriorityLevel = getCurrentPriorityLevel();
14095
- runWithPriority(ImmediatePriority$1, commitRootImpl.bind(null, root, renderPriorityLevel));
14096
- return null;
14097
- }
13947
+ function resetChildLanes(completedWork) {
13948
+ if ( // TODO: Move this check out of the hot path by moving `resetChildLanes`
13949
+ // to switch statement in `completeWork`.
13950
+ (completedWork.tag === LegacyHiddenComponent || completedWork.tag === OffscreenComponent) && completedWork.memoizedState !== null && !includesSomeLane(subtreeRenderLanes, OffscreenLane) && (completedWork.mode & ConcurrentMode) !== NoLanes) {
13951
+ // The children of this component are hidden. Don't bubble their
13952
+ // expiration times.
13953
+ return;
13954
+ }
14098
13955
 
14099
- function commitRootImpl(root, renderPriorityLevel) {
14100
- do {
14101
- // `flushPassiveEffects` will call `flushSyncUpdateQueue` at the end, which
14102
- // means `flushPassiveEffects` will sometimes result in additional
14103
- // passive effects. So we need to keep flushing in a loop until there are
14104
- // no more pending effects.
14105
- // TODO: Might be better if `flushPassiveEffects` did not automatically
14106
- // flush synchronous work at the end, to avoid factoring hazards like this.
14107
- flushPassiveEffects();
14108
- } while (rootWithPendingPassiveEffects !== null);
13956
+ var newChildLanes = NoLanes; // Bubble up the earliest expiration time.
13957
+
13958
+ if ( (completedWork.mode & ProfileMode) !== NoMode) {
13959
+ // In profiling mode, resetChildExpirationTime is also used to reset
13960
+ // profiler durations.
13961
+ var actualDuration = completedWork.actualDuration;
13962
+ var treeBaseDuration = completedWork.selfBaseDuration; // When a fiber is cloned, its actualDuration is reset to 0. This value will
13963
+ // only be updated if work is done on the fiber (i.e. it doesn't bailout).
13964
+ // When work is done, it should bubble to the parent's actualDuration. If
13965
+ // the fiber has not been cloned though, (meaning no work was done), then
13966
+ // this value will reflect the amount of time spent working on a previous
13967
+ // render. In that case it should not bubble. We determine whether it was
13968
+ // cloned by comparing the child pointer.
13969
+
13970
+ var shouldBubbleActualDurations = completedWork.alternate === null || completedWork.child !== completedWork.alternate.child;
13971
+ var child = completedWork.child;
13972
+
13973
+ while (child !== null) {
13974
+ newChildLanes = mergeLanes(newChildLanes, mergeLanes(child.lanes, child.childLanes));
13975
+
13976
+ if (shouldBubbleActualDurations) {
13977
+ actualDuration += child.actualDuration;
13978
+ }
13979
+
13980
+ treeBaseDuration += child.treeBaseDuration;
13981
+ child = child.sibling;
13982
+ }
13983
+
13984
+ var isTimedOutSuspense = completedWork.tag === SuspenseComponent && completedWork.memoizedState !== null;
13985
+
13986
+ if (isTimedOutSuspense) {
13987
+ // Don't count time spent in a timed out Suspense subtree as part of the base duration.
13988
+ var primaryChildFragment = completedWork.child;
13989
+
13990
+ if (primaryChildFragment !== null) {
13991
+ treeBaseDuration -= primaryChildFragment.treeBaseDuration;
13992
+ }
13993
+ }
13994
+
13995
+ completedWork.actualDuration = actualDuration;
13996
+ completedWork.treeBaseDuration = treeBaseDuration;
13997
+ } else {
13998
+ var _child = completedWork.child;
13999
+
14000
+ while (_child !== null) {
14001
+ newChildLanes = mergeLanes(newChildLanes, mergeLanes(_child.lanes, _child.childLanes));
14002
+ _child = _child.sibling;
14003
+ }
14004
+ }
14005
+
14006
+ completedWork.childLanes = newChildLanes;
14007
+ }
14008
+
14009
+ function commitRoot(root) {
14010
+ var renderPriorityLevel = getCurrentPriorityLevel();
14011
+ runWithPriority(ImmediatePriority$1, commitRootImpl.bind(null, root, renderPriorityLevel));
14012
+ return null;
14013
+ }
14014
+
14015
+ function commitRootImpl(root, renderPriorityLevel) {
14016
+ do {
14017
+ // `flushPassiveEffects` will call `flushSyncUpdateQueue` at the end, which
14018
+ // means `flushPassiveEffects` will sometimes result in additional
14019
+ // passive effects. So we need to keep flushing in a loop until there are
14020
+ // no more pending effects.
14021
+ // TODO: Might be better if `flushPassiveEffects` did not automatically
14022
+ // flush synchronous work at the end, to avoid factoring hazards like this.
14023
+ flushPassiveEffects();
14024
+ } while (rootWithPendingPassiveEffects !== null);
14109
14025
 
14110
14026
  flushRenderPhaseStrictModeWarningsInDEV();
14111
14027
 
@@ -14153,17 +14069,28 @@ function commitRootImpl(root, renderPriorityLevel) {
14153
14069
  workInProgressRoot = null;
14154
14070
  workInProgress = null;
14155
14071
  workInProgressRootRenderLanes = NoLanes;
14156
- } // Check if there are any effects in the whole tree.
14157
- // TODO: This is left over from the effect list implementation, where we had
14158
- // to check for the existence of `firstEffect` to satsify Flow. I think the
14159
- // only other reason this optimization exists is because it affects profiling.
14160
- // Reconsider whether this is necessary.
14072
+ } // Get the list of effects.
14073
+
14161
14074
 
14075
+ var firstEffect;
14162
14076
 
14163
- var subtreeHasEffects = (finishedWork.subtreeFlags & (BeforeMutationMask | MutationMask | LayoutMask | PassiveMask)) !== NoFlags;
14164
- var rootHasEffect = (finishedWork.flags & (BeforeMutationMask | MutationMask | LayoutMask | PassiveMask)) !== NoFlags;
14077
+ if (finishedWork.flags > PerformedWork) {
14078
+ // A fiber's effect list consists only of its children, not itself. So if
14079
+ // the root has an effect, we need to add it to the end of the list. The
14080
+ // resulting list is the set that would belong to the root's parent, if it
14081
+ // had one; that is, all the effects in the tree including the root.
14082
+ if (finishedWork.lastEffect !== null) {
14083
+ finishedWork.lastEffect.nextEffect = finishedWork;
14084
+ firstEffect = finishedWork.firstEffect;
14085
+ } else {
14086
+ firstEffect = finishedWork;
14087
+ }
14088
+ } else {
14089
+ // There is no effect on the root.
14090
+ firstEffect = finishedWork.firstEffect;
14091
+ }
14165
14092
 
14166
- if (subtreeHasEffects || rootHasEffect) {
14093
+ if (firstEffect !== null) {
14167
14094
 
14168
14095
  var prevExecutionContext = executionContext;
14169
14096
  executionContext |= CommitContext;
@@ -14178,7 +14105,26 @@ function commitRootImpl(root, renderPriorityLevel) {
14178
14105
 
14179
14106
  focusedInstanceHandle = prepareForCommit(root.containerInfo);
14180
14107
  shouldFireAfterActiveInstanceBlur = false;
14181
- commitBeforeMutationEffects(finishedWork); // We no longer need to track the active instance fiber
14108
+ nextEffect = firstEffect;
14109
+
14110
+ do {
14111
+ {
14112
+ invokeGuardedCallback(null, commitBeforeMutationEffects, null);
14113
+
14114
+ if (hasCaughtError()) {
14115
+ if (!(nextEffect !== null)) {
14116
+ {
14117
+ throw Error( "Should be working on an effect." );
14118
+ }
14119
+ }
14120
+
14121
+ var error = clearCaughtError();
14122
+ captureCommitPhaseError(nextEffect, error);
14123
+ nextEffect = nextEffect.nextEffect;
14124
+ }
14125
+ }
14126
+ } while (nextEffect !== null); // We no longer need to track the active instance fiber
14127
+
14182
14128
 
14183
14129
  focusedInstanceHandle = null;
14184
14130
 
@@ -14189,7 +14135,26 @@ function commitRootImpl(root, renderPriorityLevel) {
14189
14135
  } // The next phase is the mutation phase, where we mutate the host tree.
14190
14136
 
14191
14137
 
14192
- commitMutationEffects(finishedWork, root, renderPriorityLevel);
14138
+ nextEffect = firstEffect;
14139
+
14140
+ do {
14141
+ {
14142
+ invokeGuardedCallback(null, commitMutationEffects, null, root, renderPriorityLevel);
14143
+
14144
+ if (hasCaughtError()) {
14145
+ if (!(nextEffect !== null)) {
14146
+ {
14147
+ throw Error( "Should be working on an effect." );
14148
+ }
14149
+ }
14150
+
14151
+ var _error = clearCaughtError();
14152
+
14153
+ captureCommitPhaseError(nextEffect, _error);
14154
+ nextEffect = nextEffect.nextEffect;
14155
+ }
14156
+ }
14157
+ } while (nextEffect !== null);
14193
14158
 
14194
14159
  resetAfterCommit(root.containerInfo); // The work-in-progress tree is now the current tree. This must come after
14195
14160
  // the mutation phase, so that the previous tree is still current during
@@ -14197,21 +14162,32 @@ function commitRootImpl(root, renderPriorityLevel) {
14197
14162
  // work is current during componentDidMount/Update.
14198
14163
 
14199
14164
  root.current = finishedWork; // The next phase is the layout phase, where we call effects that read
14165
+ // the host tree after it's been mutated. The idiomatic use case for this is
14166
+ // layout, but class component lifecycles also fire here for legacy reasons.
14200
14167
 
14201
- commitLayoutEffects(finishedWork, root, lanes);
14168
+ nextEffect = firstEffect;
14202
14169
 
14170
+ do {
14171
+ {
14172
+ invokeGuardedCallback(null, commitLayoutEffects, null, root, lanes);
14203
14173
 
14204
- if ((finishedWork.subtreeFlags & PassiveMask) !== NoFlags || (finishedWork.flags & PassiveMask) !== NoFlags) {
14205
- if (!rootDoesHavePassiveEffects) {
14206
- rootDoesHavePassiveEffects = true;
14207
- scheduleCallback(NormalPriority$1, function () {
14208
- flushPassiveEffects();
14209
- return null;
14210
- });
14174
+ if (hasCaughtError()) {
14175
+ if (!(nextEffect !== null)) {
14176
+ {
14177
+ throw Error( "Should be working on an effect." );
14178
+ }
14179
+ }
14180
+
14181
+ var _error2 = clearCaughtError();
14182
+
14183
+ captureCommitPhaseError(nextEffect, _error2);
14184
+ nextEffect = nextEffect.nextEffect;
14185
+ }
14211
14186
  }
14212
- } // Tell Scheduler to yield at the end of the frame, so the browser has an
14213
- // opportunity to paint.
14187
+ } while (nextEffect !== null);
14214
14188
 
14189
+ nextEffect = null; // Tell Scheduler to yield at the end of the frame, so the browser has an
14190
+ // opportunity to paint.
14215
14191
 
14216
14192
  requestPaint();
14217
14193
 
@@ -14240,6 +14216,22 @@ function commitRootImpl(root, renderPriorityLevel) {
14240
14216
  rootWithPendingPassiveEffects = root;
14241
14217
  pendingPassiveEffectsLanes = lanes;
14242
14218
  pendingPassiveEffectsRenderPriority = renderPriorityLevel;
14219
+ } else {
14220
+ // We are done with the effect chain at this point so let's clear the
14221
+ // nextEffect pointers to assist with GC. If we have passive effects, we'll
14222
+ // clear this in flushPassiveEffects.
14223
+ nextEffect = firstEffect;
14224
+
14225
+ while (nextEffect !== null) {
14226
+ var nextNextEffect = nextEffect.nextEffect;
14227
+ nextEffect.nextEffect = null;
14228
+
14229
+ if (nextEffect.flags & Deletion) {
14230
+ detachFiberAfterEffects(nextEffect);
14231
+ }
14232
+
14233
+ nextEffect = nextNextEffect;
14234
+ }
14243
14235
  } // Read this again, since an effect might have updated it
14244
14236
 
14245
14237
 
@@ -14295,9 +14287,9 @@ function commitRootImpl(root, renderPriorityLevel) {
14295
14287
 
14296
14288
  if (hasUncaughtError) {
14297
14289
  hasUncaughtError = false;
14298
- var error = firstUncaughtError;
14290
+ var _error3 = firstUncaughtError;
14299
14291
  firstUncaughtError = null;
14300
- throw error;
14292
+ throw _error3;
14301
14293
  }
14302
14294
 
14303
14295
  if ((executionContext & LegacyUnbatchedContext) !== NoContext) {
@@ -14315,255 +14307,151 @@ function commitRootImpl(root, renderPriorityLevel) {
14315
14307
  return null;
14316
14308
  }
14317
14309
 
14318
- function commitBeforeMutationEffects(firstChild) {
14319
- var fiber = firstChild;
14310
+ function commitBeforeMutationEffects() {
14311
+ while (nextEffect !== null) {
14312
+ var current = nextEffect.alternate;
14320
14313
 
14321
- while (fiber !== null) {
14322
- if (fiber.deletions !== null) {
14323
- commitBeforeMutationEffectsDeletions(fiber.deletions);
14324
- }
14325
-
14326
- if (fiber.child !== null) {
14327
- var primarySubtreeFlags = fiber.subtreeFlags & BeforeMutationMask;
14328
-
14329
- if (primarySubtreeFlags !== NoFlags) {
14330
- commitBeforeMutationEffects(fiber.child);
14314
+ if (!shouldFireAfterActiveInstanceBlur && focusedInstanceHandle !== null) {
14315
+ if ((nextEffect.flags & Deletion) !== NoFlags) {
14316
+ if (doesFiberContain(nextEffect, focusedInstanceHandle)) {
14317
+ shouldFireAfterActiveInstanceBlur = true;
14318
+ }
14319
+ } else {
14320
+ // TODO: Move this out of the hot path using a dedicated effect tag.
14321
+ if (nextEffect.tag === SuspenseComponent && isSuspenseBoundaryBeingHidden(current, nextEffect) && doesFiberContain(nextEffect, focusedInstanceHandle)) {
14322
+ shouldFireAfterActiveInstanceBlur = true;
14323
+ }
14331
14324
  }
14332
14325
  }
14333
14326
 
14334
- {
14335
- setCurrentFiber(fiber);
14336
- invokeGuardedCallback(null, commitBeforeMutationEffectsImpl, null, fiber);
14337
-
14338
- if (hasCaughtError()) {
14339
- var error = clearCaughtError();
14340
- captureCommitPhaseError(fiber, fiber.return, error);
14341
- }
14327
+ var flags = nextEffect.flags;
14342
14328
 
14329
+ if ((flags & Snapshot) !== NoFlags) {
14330
+ setCurrentFiber(nextEffect);
14331
+ commitBeforeMutationLifeCycles(current, nextEffect);
14343
14332
  resetCurrentFiber();
14344
14333
  }
14345
14334
 
14346
- fiber = fiber.sibling;
14347
- }
14348
- }
14349
-
14350
- function commitBeforeMutationEffectsImpl(fiber) {
14351
- var current = fiber.alternate;
14352
- var flags = fiber.flags;
14353
-
14354
- if (!shouldFireAfterActiveInstanceBlur && focusedInstanceHandle !== null) {
14355
- // Check to see if the focused element was inside of a hidden (Suspense) subtree.
14356
- // TODO: Move this out of the hot path using a dedicated effect tag.
14357
- if (fiber.tag === SuspenseComponent && isSuspenseBoundaryBeingHidden(current, fiber) && doesFiberContain(fiber, focusedInstanceHandle)) {
14358
- shouldFireAfterActiveInstanceBlur = true;
14359
- }
14360
- }
14361
-
14362
- if ((flags & Snapshot) !== NoFlags) {
14363
- setCurrentFiber(fiber);
14364
- commitBeforeMutationLifeCycles(current, fiber);
14365
- resetCurrentFiber();
14366
- }
14367
-
14368
- if ((flags & Passive) !== NoFlags) {
14369
- // If there are passive effects, schedule a callback to flush at
14370
- // the earliest opportunity.
14371
- if (!rootDoesHavePassiveEffects) {
14372
- rootDoesHavePassiveEffects = true;
14373
- scheduleCallback(NormalPriority$1, function () {
14374
- flushPassiveEffects();
14375
- return null;
14376
- });
14377
- }
14378
- }
14379
- }
14380
-
14381
- function commitBeforeMutationEffectsDeletions(deletions) {
14382
- for (var i = 0; i < deletions.length; i++) {
14383
- var fiber = deletions[i]; // TODO (effects) It would be nice to avoid calling doesFiberContain()
14384
- // Maybe we can repurpose one of the subtreeFlags positions for this instead?
14385
- // Use it to store which part of the tree the focused instance is in?
14386
- // This assumes we can safely determine that instance during the "render" phase.
14387
-
14388
- if (doesFiberContain(fiber, focusedInstanceHandle)) {
14389
- shouldFireAfterActiveInstanceBlur = true;
14390
- }
14391
- }
14392
- }
14393
-
14394
- function commitMutationEffects(firstChild, root, renderPriorityLevel) {
14395
- var fiber = firstChild;
14396
-
14397
- while (fiber !== null) {
14398
- var deletions = fiber.deletions;
14399
-
14400
- if (deletions !== null) {
14401
- commitMutationEffectsDeletions(deletions, fiber, root, renderPriorityLevel);
14402
- }
14403
-
14404
- if (fiber.child !== null) {
14405
- var mutationFlags = fiber.subtreeFlags & MutationMask;
14406
-
14407
- if (mutationFlags !== NoFlags) {
14408
- commitMutationEffects(fiber.child, root, renderPriorityLevel);
14409
- }
14410
- }
14411
-
14412
- {
14413
- setCurrentFiber(fiber);
14414
- invokeGuardedCallback(null, commitMutationEffectsImpl, null, fiber, root, renderPriorityLevel);
14415
-
14416
- if (hasCaughtError()) {
14417
- var error = clearCaughtError();
14418
- captureCommitPhaseError(fiber, fiber.return, error);
14335
+ if ((flags & Passive) !== NoFlags) {
14336
+ // If there are passive effects, schedule a callback to flush at
14337
+ // the earliest opportunity.
14338
+ if (!rootDoesHavePassiveEffects) {
14339
+ rootDoesHavePassiveEffects = true;
14340
+ scheduleCallback(NormalPriority$1, function () {
14341
+ flushPassiveEffects();
14342
+ return null;
14343
+ });
14419
14344
  }
14420
-
14421
- resetCurrentFiber();
14422
14345
  }
14423
14346
 
14424
- fiber = fiber.sibling;
14347
+ nextEffect = nextEffect.nextEffect;
14425
14348
  }
14426
14349
  }
14427
14350
 
14428
- function commitMutationEffectsImpl(fiber, root, renderPriorityLevel) {
14429
- var flags = fiber.flags;
14430
-
14431
- if (flags & ContentReset) {
14432
- commitResetTextContent(fiber);
14433
- }
14351
+ function commitMutationEffects(root, renderPriorityLevel) {
14352
+ // TODO: Should probably move the bulk of this function to commitWork.
14353
+ while (nextEffect !== null) {
14354
+ setCurrentFiber(nextEffect);
14355
+ var flags = nextEffect.flags;
14434
14356
 
14435
- if (flags & Ref) {
14436
- var current = fiber.alternate;
14437
-
14438
- if (current !== null) {
14439
- commitDetachRef(current);
14357
+ if (flags & ContentReset) {
14358
+ commitResetTextContent(nextEffect);
14440
14359
  }
14441
- } // The following switch statement is only concerned about placement,
14442
- // updates, and deletions. To avoid needing to add a case for every possible
14443
- // bitmap value, we remove the secondary effects from the effect tag and
14444
- // switch on that value.
14445
14360
 
14361
+ if (flags & Ref) {
14362
+ var current = nextEffect.alternate;
14446
14363
 
14447
- var primaryFlags = flags & (Placement | Update | Hydrating);
14364
+ if (current !== null) {
14365
+ commitDetachRef(current);
14366
+ }
14367
+ } // The following switch statement is only concerned about placement,
14368
+ // updates, and deletions. To avoid needing to add a case for every possible
14369
+ // bitmap value, we remove the secondary effects from the effect tag and
14370
+ // switch on that value.
14448
14371
 
14449
- switch (primaryFlags) {
14450
- case Placement:
14451
- {
14452
- commitPlacement(fiber); // Clear the "placement" from effect tag so that we know that this is
14453
- // inserted, before any life-cycles like componentDidMount gets called.
14454
- // TODO: findDOMNode doesn't rely on this any more but isMounted does
14455
- // and isMounted is deprecated anyway so we should be able to kill this.
14456
14372
 
14457
- fiber.flags &= ~Placement;
14458
- break;
14459
- }
14373
+ var primaryFlags = flags & (Placement | Update | Deletion | Hydrating);
14460
14374
 
14461
- case PlacementAndUpdate:
14462
- {
14463
- // Placement
14464
- commitPlacement(fiber); // Clear the "placement" from effect tag so that we know that this is
14465
- // inserted, before any life-cycles like componentDidMount gets called.
14375
+ switch (primaryFlags) {
14376
+ case Placement:
14377
+ {
14378
+ commitPlacement(nextEffect); // Clear the "placement" from effect tag so that we know that this is
14379
+ // inserted, before any life-cycles like componentDidMount gets called.
14380
+ // TODO: findDOMNode doesn't rely on this any more but isMounted does
14381
+ // and isMounted is deprecated anyway so we should be able to kill this.
14466
14382
 
14467
- fiber.flags &= ~Placement; // Update
14383
+ nextEffect.flags &= ~Placement;
14384
+ break;
14385
+ }
14468
14386
 
14469
- var _current = fiber.alternate;
14470
- commitWork(_current, fiber);
14471
- break;
14472
- }
14387
+ case PlacementAndUpdate:
14388
+ {
14389
+ // Placement
14390
+ commitPlacement(nextEffect); // Clear the "placement" from effect tag so that we know that this is
14391
+ // inserted, before any life-cycles like componentDidMount gets called.
14473
14392
 
14474
- case Hydrating:
14475
- {
14476
- fiber.flags &= ~Hydrating;
14477
- break;
14478
- }
14393
+ nextEffect.flags &= ~Placement; // Update
14479
14394
 
14480
- case HydratingAndUpdate:
14481
- {
14482
- fiber.flags &= ~Hydrating; // Update
14395
+ var _current = nextEffect.alternate;
14396
+ commitWork(_current, nextEffect);
14397
+ break;
14398
+ }
14483
14399
 
14484
- var _current2 = fiber.alternate;
14485
- commitWork(_current2, fiber);
14486
- break;
14487
- }
14400
+ case Hydrating:
14401
+ {
14402
+ nextEffect.flags &= ~Hydrating;
14403
+ break;
14404
+ }
14488
14405
 
14489
- case Update:
14490
- {
14491
- var _current3 = fiber.alternate;
14492
- commitWork(_current3, fiber);
14493
- break;
14494
- }
14495
- }
14496
- }
14406
+ case HydratingAndUpdate:
14407
+ {
14408
+ nextEffect.flags &= ~Hydrating; // Update
14497
14409
 
14498
- function commitMutationEffectsDeletions(deletions, nearestMountedAncestor, root, renderPriorityLevel) {
14499
- for (var i = 0; i < deletions.length; i++) {
14500
- var childToDelete = deletions[i];
14410
+ var _current2 = nextEffect.alternate;
14411
+ commitWork(_current2, nextEffect);
14412
+ break;
14413
+ }
14501
14414
 
14502
- {
14503
- invokeGuardedCallback(null, commitDeletion, null, root, childToDelete, nearestMountedAncestor, renderPriorityLevel);
14415
+ case Update:
14416
+ {
14417
+ var _current3 = nextEffect.alternate;
14418
+ commitWork(_current3, nextEffect);
14419
+ break;
14420
+ }
14504
14421
 
14505
- if (hasCaughtError()) {
14506
- var error = clearCaughtError();
14507
- captureCommitPhaseError(childToDelete, nearestMountedAncestor, error);
14508
- }
14422
+ case Deletion:
14423
+ {
14424
+ commitDeletion(root, nextEffect);
14425
+ break;
14426
+ }
14509
14427
  }
14510
- }
14511
- }
14512
14428
 
14513
- function schedulePassiveEffectCallback() {
14514
- if (!rootDoesHavePassiveEffects) {
14515
- rootDoesHavePassiveEffects = true;
14516
- scheduleCallback(NormalPriority$1, function () {
14517
- flushPassiveEffects();
14518
- return null;
14519
- });
14429
+ resetCurrentFiber();
14430
+ nextEffect = nextEffect.nextEffect;
14520
14431
  }
14521
14432
  }
14522
14433
 
14523
- function commitLayoutEffects(firstChild, root, committedLanes) {
14524
- var fiber = firstChild;
14434
+ function commitLayoutEffects(root, committedLanes) {
14525
14435
 
14526
- while (fiber !== null) {
14527
- if (fiber.child !== null) {
14528
- var primarySubtreeFlags = fiber.subtreeFlags & LayoutMask;
14529
14436
 
14530
- if (primarySubtreeFlags !== NoFlags) {
14531
- commitLayoutEffects(fiber.child, root, committedLanes);
14532
- }
14437
+ while (nextEffect !== null) {
14438
+ setCurrentFiber(nextEffect);
14439
+ var flags = nextEffect.flags;
14440
+
14441
+ if (flags & (Update | Callback)) {
14442
+ var current = nextEffect.alternate;
14443
+ commitLifeCycles(root, current, nextEffect);
14533
14444
  }
14534
14445
 
14535
14446
  {
14536
- setCurrentFiber(fiber);
14537
- invokeGuardedCallback(null, commitLayoutEffectsImpl, null, fiber, root, committedLanes);
14538
-
14539
- if (hasCaughtError()) {
14540
- var error = clearCaughtError();
14541
- captureCommitPhaseError(fiber, fiber.return, error);
14447
+ if (flags & Ref) {
14448
+ commitAttachRef(nextEffect);
14542
14449
  }
14543
-
14544
- resetCurrentFiber();
14545
14450
  }
14546
14451
 
14547
- fiber = fiber.sibling;
14548
- }
14549
- }
14550
-
14551
- function commitLayoutEffectsImpl(fiber, root, committedLanes) {
14552
- var flags = fiber.flags;
14553
- setCurrentFiber(fiber);
14554
-
14555
- if (flags & (Update | Callback)) {
14556
- var current = fiber.alternate;
14557
- commitLifeCycles(root, current, fiber);
14558
- }
14559
-
14560
- {
14561
- if (flags & Ref) {
14562
- commitAttachRef(fiber);
14563
- }
14452
+ resetCurrentFiber();
14453
+ nextEffect = nextEffect.nextEffect;
14564
14454
  }
14565
-
14566
- resetCurrentFiber();
14567
14455
  }
14568
14456
 
14569
14457
  function flushPassiveEffects() {
@@ -14579,87 +14467,41 @@ function flushPassiveEffects() {
14579
14467
 
14580
14468
  return false;
14581
14469
  }
14470
+ function enqueuePendingPassiveHookEffectMount(fiber, effect) {
14471
+ pendingPassiveHookEffectsMount.push(effect, fiber);
14582
14472
 
14583
- function flushPassiveMountEffects(root, firstChild) {
14584
- var fiber = firstChild;
14585
-
14586
- while (fiber !== null) {
14587
- var primarySubtreeFlags = fiber.subtreeFlags & PassiveMask;
14588
-
14589
- if (fiber.child !== null && primarySubtreeFlags !== NoFlags) {
14590
- flushPassiveMountEffects(root, fiber.child);
14591
- }
14592
-
14593
- if ((fiber.flags & Passive) !== NoFlags) {
14594
- setCurrentFiber(fiber);
14595
- commitPassiveLifeCycles(root, fiber);
14596
- resetCurrentFiber();
14597
- }
14598
-
14599
- fiber = fiber.sibling;
14473
+ if (!rootDoesHavePassiveEffects) {
14474
+ rootDoesHavePassiveEffects = true;
14475
+ scheduleCallback(NormalPriority$1, function () {
14476
+ flushPassiveEffects();
14477
+ return null;
14478
+ });
14600
14479
  }
14601
14480
  }
14481
+ function enqueuePendingPassiveHookEffectUnmount(fiber, effect) {
14482
+ pendingPassiveHookEffectsUnmount.push(effect, fiber);
14602
14483
 
14603
- function flushPassiveUnmountEffects(firstChild) {
14604
- var fiber = firstChild;
14605
-
14606
- while (fiber !== null) {
14607
- var deletions = fiber.deletions;
14608
-
14609
- if (deletions !== null) {
14610
- for (var i = 0; i < deletions.length; i++) {
14611
- var fiberToDelete = deletions[i];
14612
- flushPassiveUnmountEffectsInsideOfDeletedTree(fiberToDelete, fiber); // Now that passive effects have been processed, it's safe to detach lingering pointers.
14613
-
14614
- detachFiberAfterEffects(fiberToDelete);
14615
- }
14616
- }
14617
-
14618
- var child = fiber.child;
14619
-
14620
- if (child !== null) {
14621
- // If any children have passive effects then traverse the subtree.
14622
- // Note that this requires checking subtreeFlags of the current Fiber,
14623
- // rather than the subtreeFlags/effectsTag of the first child,
14624
- // since that would not cover passive effects in siblings.
14625
- var passiveFlags = fiber.subtreeFlags & PassiveMask;
14626
-
14627
- if (passiveFlags !== NoFlags) {
14628
- flushPassiveUnmountEffects(child);
14629
- }
14630
- }
14631
-
14632
- var primaryFlags = fiber.flags & Passive;
14484
+ {
14485
+ fiber.flags |= PassiveUnmountPendingDev;
14486
+ var alternate = fiber.alternate;
14633
14487
 
14634
- if (primaryFlags !== NoFlags) {
14635
- setCurrentFiber(fiber);
14636
- commitPassiveWork(fiber);
14637
- resetCurrentFiber();
14488
+ if (alternate !== null) {
14489
+ alternate.flags |= PassiveUnmountPendingDev;
14638
14490
  }
14639
-
14640
- fiber = fiber.sibling;
14641
14491
  }
14642
- }
14643
-
14644
- function flushPassiveUnmountEffectsInsideOfDeletedTree(fiberToDelete, nearestMountedAncestor) {
14645
- if ((fiberToDelete.subtreeFlags & PassiveStatic) !== NoFlags) {
14646
- // If any children have passive effects then traverse the subtree.
14647
- // Note that this requires checking subtreeFlags of the current Fiber,
14648
- // rather than the subtreeFlags/effectsTag of the first child,
14649
- // since that would not cover passive effects in siblings.
14650
- var child = fiberToDelete.child;
14651
14492
 
14652
- while (child !== null) {
14653
- flushPassiveUnmountEffectsInsideOfDeletedTree(child, nearestMountedAncestor);
14654
- child = child.sibling;
14655
- }
14493
+ if (!rootDoesHavePassiveEffects) {
14494
+ rootDoesHavePassiveEffects = true;
14495
+ scheduleCallback(NormalPriority$1, function () {
14496
+ flushPassiveEffects();
14497
+ return null;
14498
+ });
14656
14499
  }
14500
+ }
14657
14501
 
14658
- if ((fiberToDelete.flags & PassiveStatic) !== NoFlags) {
14659
- setCurrentFiber(fiberToDelete);
14660
- commitPassiveUnmount(fiberToDelete, nearestMountedAncestor);
14661
- resetCurrentFiber();
14662
- }
14502
+ function invokePassiveEffectCreate(effect) {
14503
+ var create = effect.create;
14504
+ effect.destroy = create();
14663
14505
  }
14664
14506
 
14665
14507
  function flushPassiveEffectsImpl() {
@@ -14690,9 +14532,97 @@ function flushPassiveEffectsImpl() {
14690
14532
  // e.g. a destroy function in one component may unintentionally override a ref
14691
14533
  // value set by a create function in another component.
14692
14534
  // Layout effects have the same constraint.
14535
+ // First pass: Destroy stale passive effects.
14536
+
14537
+ var unmountEffects = pendingPassiveHookEffectsUnmount;
14538
+ pendingPassiveHookEffectsUnmount = [];
14539
+
14540
+ for (var i = 0; i < unmountEffects.length; i += 2) {
14541
+ var _effect = unmountEffects[i];
14542
+ var fiber = unmountEffects[i + 1];
14543
+ var destroy = _effect.destroy;
14544
+ _effect.destroy = undefined;
14545
+
14546
+ {
14547
+ fiber.flags &= ~PassiveUnmountPendingDev;
14548
+ var alternate = fiber.alternate;
14549
+
14550
+ if (alternate !== null) {
14551
+ alternate.flags &= ~PassiveUnmountPendingDev;
14552
+ }
14553
+ }
14554
+
14555
+ if (typeof destroy === 'function') {
14556
+ {
14557
+ setCurrentFiber(fiber);
14558
+
14559
+ {
14560
+ invokeGuardedCallback(null, destroy, null);
14561
+ }
14562
+
14563
+ if (hasCaughtError()) {
14564
+ if (!(fiber !== null)) {
14565
+ {
14566
+ throw Error( "Should be working on an effect." );
14567
+ }
14568
+ }
14569
+
14570
+ var error = clearCaughtError();
14571
+ captureCommitPhaseError(fiber, error);
14572
+ }
14573
+
14574
+ resetCurrentFiber();
14575
+ }
14576
+ }
14577
+ } // Second pass: Create new passive effects.
14578
+
14579
+
14580
+ var mountEffects = pendingPassiveHookEffectsMount;
14581
+ pendingPassiveHookEffectsMount = [];
14582
+
14583
+ for (var _i = 0; _i < mountEffects.length; _i += 2) {
14584
+ var _effect2 = mountEffects[_i];
14585
+ var _fiber = mountEffects[_i + 1];
14586
+
14587
+ {
14588
+ setCurrentFiber(_fiber);
14589
+
14590
+ {
14591
+ invokeGuardedCallback(null, invokePassiveEffectCreate, null, _effect2);
14592
+ }
14593
+
14594
+ if (hasCaughtError()) {
14595
+ if (!(_fiber !== null)) {
14596
+ {
14597
+ throw Error( "Should be working on an effect." );
14598
+ }
14599
+ }
14693
14600
 
14694
- flushPassiveUnmountEffects(root.current);
14695
- flushPassiveMountEffects(root, root.current);
14601
+ var _error4 = clearCaughtError();
14602
+
14603
+ captureCommitPhaseError(_fiber, _error4);
14604
+ }
14605
+
14606
+ resetCurrentFiber();
14607
+ }
14608
+ } // Note: This currently assumes there are no passive effects on the root fiber
14609
+ // because the root is not part of its own effect list.
14610
+ // This could change in the future.
14611
+
14612
+
14613
+ var effect = root.current.firstEffect;
14614
+
14615
+ while (effect !== null) {
14616
+ var nextNextEffect = effect.nextEffect; // Remove nextEffect pointer to assist GC
14617
+
14618
+ effect.nextEffect = null;
14619
+
14620
+ if (effect.flags & Deletion) {
14621
+ detachFiberAfterEffects(effect);
14622
+ }
14623
+
14624
+ effect = nextNextEffect;
14625
+ }
14696
14626
 
14697
14627
  {
14698
14628
  popInteractions(prevInteractions);
@@ -14745,7 +14675,7 @@ function captureCommitPhaseErrorOnRoot(rootFiber, sourceFiber, error) {
14745
14675
  }
14746
14676
  }
14747
14677
 
14748
- function captureCommitPhaseError(sourceFiber, nearestMountedAncestor, error) {
14678
+ function captureCommitPhaseError(sourceFiber, error) {
14749
14679
  if (sourceFiber.tag === HostRoot) {
14750
14680
  // Error was thrown at the root. There is no parent, so the root
14751
14681
  // itself should capture it.
@@ -14753,11 +14683,7 @@ function captureCommitPhaseError(sourceFiber, nearestMountedAncestor, error) {
14753
14683
  return;
14754
14684
  }
14755
14685
 
14756
- var fiber = null;
14757
-
14758
- {
14759
- fiber = sourceFiber.return;
14760
- }
14686
+ var fiber = sourceFiber.return;
14761
14687
 
14762
14688
  while (fiber !== null) {
14763
14689
  if (fiber.tag === HostRoot) {
@@ -14778,6 +14704,20 @@ function captureCommitPhaseError(sourceFiber, nearestMountedAncestor, error) {
14778
14704
  markRootUpdated(root, SyncLane, eventTime);
14779
14705
  ensureRootIsScheduled(root, eventTime);
14780
14706
  schedulePendingInteractions(root, SyncLane);
14707
+ } else {
14708
+ // This component has already been unmounted.
14709
+ // We can't schedule any follow up work for the root because the fiber is already unmounted,
14710
+ // but we can still call the log-only boundary so the error isn't swallowed.
14711
+ //
14712
+ // TODO This is only a temporary bandaid for the old reconciler fork.
14713
+ // We can delete this special case once the new fork is merged.
14714
+ if (typeof instance.componentDidCatch === 'function' && !isAlreadyFailedLegacyErrorBoundary(instance)) {
14715
+ try {
14716
+ instance.componentDidCatch(error, errorInfo);
14717
+ } catch (errorToIgnore) {// TODO Ignore this error? Rethrow it?
14718
+ // This is kind of an edge case.
14719
+ }
14720
+ }
14781
14721
  }
14782
14722
 
14783
14723
  return;
@@ -14960,29 +14900,12 @@ function warnAboutUpdateOnUnmountedFiberInDEV(fiber) {
14960
14900
  if (tag !== HostRoot && tag !== ClassComponent && tag !== FunctionComponent && tag !== ForwardRef && tag !== MemoComponent && tag !== SimpleMemoComponent && tag !== Block) {
14961
14901
  // Only warn for user-defined components, not internal ones like Suspense.
14962
14902
  return;
14963
- }
14964
-
14965
- if ((fiber.flags & PassiveStatic) !== NoFlags) {
14966
- var updateQueue = fiber.updateQueue;
14903
+ } // If there are pending passive effects unmounts for this Fiber,
14904
+ // we can assume that they would have prevented this update.
14967
14905
 
14968
- if (updateQueue !== null) {
14969
- var lastEffect = updateQueue.lastEffect;
14970
14906
 
14971
- if (lastEffect !== null) {
14972
- var firstEffect = lastEffect.next;
14973
- var effect = firstEffect;
14974
-
14975
- do {
14976
- if (effect.destroy !== undefined) {
14977
- if ((effect.tag & Passive$1) !== NoFlags$1) {
14978
- return;
14979
- }
14980
- }
14981
-
14982
- effect = effect.next;
14983
- } while (effect !== firstEffect);
14984
- }
14985
- }
14907
+ if ((fiber.flags & PassiveUnmountPendingDev) !== NoFlags) {
14908
+ return;
14986
14909
  } // We show the whole stack but dedupe on the top component's name because
14987
14910
  // the problematic code almost always lies inside that component.
14988
14911
 
@@ -15442,21 +15365,8 @@ function act(callback) {
15442
15365
  }
15443
15366
 
15444
15367
  function detachFiberAfterEffects(fiber) {
15445
- // Null out fields to improve GC for references that may be lingering (e.g. DevTools).
15446
- // Note that we already cleared the return pointer in detachFiberMutation().
15447
- fiber.child = null;
15448
- fiber.deletions = null;
15449
- fiber.dependencies = null;
15450
- fiber.memoizedProps = null;
15451
- fiber.memoizedState = null;
15452
- fiber.pendingProps = null;
15453
15368
  fiber.sibling = null;
15454
15369
  fiber.stateNode = null;
15455
- fiber.updateQueue = null;
15456
-
15457
- {
15458
- fiber._debugOwner = null;
15459
- }
15460
15370
  }
15461
15371
 
15462
15372
  var resolveFamily = null; // $FlowFixMe Flow gets confused by a WeakSet feature check below.
@@ -15896,8 +15806,9 @@ function FiberNode(tag, pendingProps, key, mode) {
15896
15806
  this.mode = mode; // Effects
15897
15807
 
15898
15808
  this.flags = NoFlags;
15899
- this.subtreeFlags = NoFlags;
15900
- this.deletions = null;
15809
+ this.nextEffect = null;
15810
+ this.firstEffect = null;
15811
+ this.lastEffect = null;
15901
15812
  this.lanes = NoLanes;
15902
15813
  this.childLanes = NoLanes;
15903
15814
  this.alternate = null;
@@ -16014,9 +15925,13 @@ function createWorkInProgress(current, pendingProps) {
16014
15925
  workInProgress.pendingProps = pendingProps; // Needed because Blocks store data on type.
16015
15926
 
16016
15927
  workInProgress.type = current.type; // We already have an alternate.
15928
+ // Reset the effect tag.
15929
+
15930
+ workInProgress.flags = NoFlags; // The effect list is no longer valid.
16017
15931
 
16018
- workInProgress.subtreeFlags = NoFlags;
16019
- workInProgress.deletions = null;
15932
+ workInProgress.nextEffect = null;
15933
+ workInProgress.firstEffect = null;
15934
+ workInProgress.lastEffect = null;
16020
15935
 
16021
15936
  {
16022
15937
  // We intentionally reset, rather than copy, actualDuration & actualStartTime.
@@ -16026,11 +15941,8 @@ function createWorkInProgress(current, pendingProps) {
16026
15941
  workInProgress.actualDuration = 0;
16027
15942
  workInProgress.actualStartTime = -1;
16028
15943
  }
16029
- } // Reset all effects except static ones.
16030
- // Static effects are not specific to a render.
16031
-
15944
+ }
16032
15945
 
16033
- workInProgress.flags = current.flags & StaticMask;
16034
15946
  workInProgress.childLanes = current.childLanes;
16035
15947
  workInProgress.lanes = current.lanes;
16036
15948
  workInProgress.child = current.child;
@@ -16086,7 +15998,11 @@ function resetWorkInProgress(workInProgress, renderLanes) {
16086
15998
  // avoid doing another reconciliation.
16087
15999
  // Reset the effect tag but keep any Placement tags, since that's something
16088
16000
  // that child fiber is setting, not the reconciliation.
16089
- workInProgress.flags &= Placement;
16001
+ workInProgress.flags &= Placement; // The effect list is no longer valid.
16002
+
16003
+ workInProgress.nextEffect = null;
16004
+ workInProgress.firstEffect = null;
16005
+ workInProgress.lastEffect = null;
16090
16006
  var current = workInProgress.alternate;
16091
16007
 
16092
16008
  if (current === null) {
@@ -16094,7 +16010,6 @@ function resetWorkInProgress(workInProgress, renderLanes) {
16094
16010
  workInProgress.childLanes = NoLanes;
16095
16011
  workInProgress.lanes = renderLanes;
16096
16012
  workInProgress.child = null;
16097
- workInProgress.subtreeFlags = NoFlags;
16098
16013
  workInProgress.memoizedProps = null;
16099
16014
  workInProgress.memoizedState = null;
16100
16015
  workInProgress.updateQueue = null;
@@ -16112,8 +16027,6 @@ function resetWorkInProgress(workInProgress, renderLanes) {
16112
16027
  workInProgress.childLanes = current.childLanes;
16113
16028
  workInProgress.lanes = current.lanes;
16114
16029
  workInProgress.child = current.child;
16115
- workInProgress.subtreeFlags = current.subtreeFlags;
16116
- workInProgress.deletions = null;
16117
16030
  workInProgress.memoizedProps = current.memoizedProps;
16118
16031
  workInProgress.memoizedState = current.memoizedState;
16119
16032
  workInProgress.updateQueue = current.updateQueue; // Needed because Blocks store data on type.