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.
@@ -295,7 +295,7 @@
295
295
 
296
296
  // Don't change these two values. They're used by React Dev Tools.
297
297
  var NoFlags =
298
- /* */
298
+ /* */
299
299
  0;
300
300
  var PerformedWork =
301
301
  /* */
@@ -331,6 +331,10 @@
331
331
  var Passive =
332
332
  /* */
333
333
  512; // TODO (effects) Remove this bit once the new reconciler is synced to the old.
334
+
335
+ var PassiveUnmountPendingDev =
336
+ /* */
337
+ 8192;
334
338
  var Hydrating =
335
339
  /* */
336
340
  1024;
@@ -355,33 +359,6 @@
355
359
  var ForceUpdateForLegacySuspense =
356
360
  /* */
357
361
  16384; // Static tags describe aspects of a fiber that are not specific to a render,
358
- // e.g. a fiber uses a passive effect (even if there are no updates on this particular render).
359
- // This enables us to defer more work in the unmount case,
360
- // since we can defer traversing the tree during layout to look for Passive effects,
361
- // and instead rely on the static flag as a signal that there may be cleanup work.
362
-
363
- var PassiveStatic =
364
- /* */
365
- 32768; // Union of side effect groupings as pertains to subtreeFlags
366
-
367
- var BeforeMutationMask =
368
- /* */
369
- 778;
370
- var MutationMask =
371
- /* */
372
- 1182;
373
- var LayoutMask =
374
- /* */
375
- 164;
376
- var PassiveMask =
377
- /* */
378
- 520; // Union of tags that don't get reset on clones.
379
- // This allows certain concepts to persist without recalculting them,
380
- // e.g. whether a subtree contains passive effects or portals.
381
-
382
- var StaticMask =
383
- /* */
384
- 32768;
385
362
 
386
363
  var enableProfilerTimer = true;
387
364
  var enableFundamentalAPI = false;
@@ -2300,7 +2277,15 @@
2300
2277
  return lane;
2301
2278
  }
2302
2279
  function createLaneMap(initial) {
2303
- return new Array(TotalLanes).fill(initial);
2280
+ // Intentionally pushing one by one.
2281
+ // https://v8.dev/blog/elements-kinds#avoid-creating-holes
2282
+ var laneMap = [];
2283
+
2284
+ for (var i = 0; i < TotalLanes; i++) {
2285
+ laneMap.push(initial);
2286
+ }
2287
+
2288
+ return laneMap;
2304
2289
  }
2305
2290
  function markRootUpdated(root, updateLane, eventTime) {
2306
2291
  root.pendingLanes |= updateLane; // TODO: Theoretically, any update to any lane can unblock any other lane. But
@@ -2341,9 +2326,6 @@
2341
2326
  function markRootPinged(root, pingedLanes, eventTime) {
2342
2327
  root.pingedLanes |= root.suspendedLanes & pingedLanes;
2343
2328
  }
2344
- function markRootExpired(root, expiredLanes) {
2345
- root.expiredLanes |= expiredLanes & root.pendingLanes;
2346
- }
2347
2329
  function hasDiscreteLanes(lanes) {
2348
2330
  return (lanes & InputDiscreteLanes) !== NoLanes;
2349
2331
  }
@@ -2542,7 +2524,7 @@
2542
2524
  Scheduler_cancelCallback(node);
2543
2525
  }
2544
2526
 
2545
- return flushSyncCallbackQueueImpl();
2527
+ flushSyncCallbackQueueImpl();
2546
2528
  }
2547
2529
 
2548
2530
  function flushSyncCallbackQueueImpl() {
@@ -2578,30 +2560,11 @@
2578
2560
  isFlushingSyncQueue = false;
2579
2561
  }
2580
2562
  }
2581
-
2582
- return true;
2583
- } else {
2584
- return false;
2585
2563
  }
2586
2564
  }
2587
2565
 
2588
- var NoFlags$1 =
2589
- /* */
2590
- 0; // Represents whether effect should fire.
2591
-
2592
- var HasEffect =
2593
- /* */
2594
- 1; // Represents the phase in which the effect (not the clean-up) fires.
2595
-
2596
- var Layout =
2597
- /* */
2598
- 2;
2599
- var Passive$1 =
2600
- /* */
2601
- 4;
2602
-
2603
2566
  // TODO: this is special because it gets imported during build.
2604
- var ReactVersion = '17.0.0-rc.2';
2567
+ var ReactVersion = '17.0.2';
2605
2568
 
2606
2569
  var NoMode = 0;
2607
2570
  var StrictMode = 1; // TODO: Remove BlockingMode and ConcurrentMode by reading from the root
@@ -2812,7 +2775,7 @@
2812
2775
  var didWarnAboutUnsafeLifecycles = new Set();
2813
2776
 
2814
2777
  ReactStrictModeWarnings.recordUnsafeLifecycleWarnings = function (fiber, instance) {
2815
- // Dedupe strategy: Warn once per component.
2778
+ // Dedup strategy: Warn once per component.
2816
2779
  if (didWarnAboutUnsafeLifecycles.has(fiber.type)) {
2817
2780
  return;
2818
2781
  }
@@ -4608,16 +4571,24 @@
4608
4571
  if (!shouldTrackSideEffects) {
4609
4572
  // Noop.
4610
4573
  return;
4611
- }
4574
+ } // Deletions are added in reversed order so we add it to the front.
4575
+ // At this point, the return fiber's effect list is empty except for
4576
+ // deletions, so we can just append the deletion to the list. The remaining
4577
+ // effects aren't added until the complete phase. Once we implement
4578
+ // resuming, this may not be true.
4612
4579
 
4613
- var deletions = returnFiber.deletions;
4614
4580
 
4615
- if (deletions === null) {
4616
- returnFiber.deletions = [childToDelete];
4617
- returnFiber.flags |= Deletion;
4581
+ var last = returnFiber.lastEffect;
4582
+
4583
+ if (last !== null) {
4584
+ last.nextEffect = childToDelete;
4585
+ returnFiber.lastEffect = childToDelete;
4618
4586
  } else {
4619
- deletions.push(childToDelete);
4587
+ returnFiber.firstEffect = returnFiber.lastEffect = childToDelete;
4620
4588
  }
4589
+
4590
+ childToDelete.nextEffect = null;
4591
+ childToDelete.flags = Deletion;
4621
4592
  }
4622
4593
 
4623
4594
  function deleteRemainingChildren(returnFiber, currentFirstChild) {
@@ -5673,13 +5644,6 @@
5673
5644
  pop(suspenseStackCursor, fiber);
5674
5645
  }
5675
5646
 
5676
- // A non-null SuspenseState means that it is blocked for one reason or another.
5677
- // - A non-null dehydrated field means it's blocked pending hydration.
5678
- // - A non-null dehydrated field can use isSuspenseInstancePending or
5679
- // isSuspenseInstanceFallback to query the reason for being dehydrated.
5680
- // - A null dehydrated field means it's blocked by something suspending and
5681
- // we're currently showing a fallback instead.
5682
-
5683
5647
  function shouldCaptureSuspense(workInProgress, hasInvisibleParent) {
5684
5648
  // If it was the primary children that just suspended, capture and render the
5685
5649
  // fallback. Otherwise, don't capture and bubble to the next boundary.
@@ -5761,6 +5725,21 @@
5761
5725
  return null;
5762
5726
  }
5763
5727
 
5728
+ var NoFlags$1 =
5729
+ /* */
5730
+ 0; // Represents whether effect should fire.
5731
+
5732
+ var HasEffect =
5733
+ /* */
5734
+ 1; // Represents the phase in which the effect (not the clean-up) fires.
5735
+
5736
+ var Layout =
5737
+ /* */
5738
+ 2;
5739
+ var Passive$1 =
5740
+ /* */
5741
+ 4;
5742
+
5764
5743
  var isHydrating = false;
5765
5744
 
5766
5745
  function enterHydrationState(fiber) {
@@ -6793,7 +6772,7 @@
6793
6772
  }
6794
6773
  }
6795
6774
 
6796
- return mountEffectImpl(Passive | PassiveStatic, Passive$1, create, deps);
6775
+ return mountEffectImpl(Update | Passive, Passive$1, create, deps);
6797
6776
  }
6798
6777
 
6799
6778
  function updateEffect(create, deps) {
@@ -6804,7 +6783,7 @@
6804
6783
  }
6805
6784
  }
6806
6785
 
6807
- return updateEffectImpl(Passive, Passive$1, create, deps);
6786
+ return updateEffectImpl(Update | Passive, Passive$1, create, deps);
6808
6787
  }
6809
6788
 
6810
6789
  function mountLayoutEffect(create, deps) {
@@ -8316,8 +8295,7 @@
8316
8295
 
8317
8296
  function updateProfiler(current, workInProgress, renderLanes) {
8318
8297
  {
8319
- // TODO: Only call onRender et al if subtree has effects
8320
- workInProgress.flags |= Update | Passive; // Reset effect durations for the next eventual effect phase.
8298
+ workInProgress.flags |= Update; // Reset effect durations for the next eventual effect phase.
8321
8299
  // These are reset during render to allow the DevTools commit hook a chance to read them,
8322
8300
 
8323
8301
  var stateNode = workInProgress.stateNode;
@@ -8914,7 +8892,8 @@
8914
8892
  return {
8915
8893
  baseLanes: mergeLanes(prevOffscreenState.baseLanes, renderLanes)
8916
8894
  };
8917
- }
8895
+ } // TODO: Probably should inline this back
8896
+
8918
8897
 
8919
8898
  function shouldRemainOnFallback(suspenseContext, current, workInProgress, renderLanes) {
8920
8899
  // If we're already showing a fallback, there are cases where we need to
@@ -9003,17 +8982,41 @@
9003
8982
  // But only if this has a fallback.
9004
8983
  if (nextProps.fallback !== undefined) ;
9005
8984
 
8985
+ var nextPrimaryChildren = nextProps.children;
8986
+ var nextFallbackChildren = nextProps.fallback;
8987
+
9006
8988
  if (showFallback) {
9007
- var nextPrimaryChildren = nextProps.children;
9008
- var nextFallbackChildren = nextProps.fallback;
9009
8989
  var fallbackFragment = mountSuspenseFallbackChildren(workInProgress, nextPrimaryChildren, nextFallbackChildren, renderLanes);
9010
8990
  var primaryChildFragment = workInProgress.child;
9011
8991
  primaryChildFragment.memoizedState = mountSuspenseOffscreenState(renderLanes);
9012
8992
  workInProgress.memoizedState = SUSPENDED_MARKER;
9013
8993
  return fallbackFragment;
8994
+ } else if (typeof nextProps.unstable_expectedLoadTime === 'number') {
8995
+ // This is a CPU-bound tree. Skip this tree and show a placeholder to
8996
+ // unblock the surrounding content. Then immediately retry after the
8997
+ // initial commit.
8998
+ var _fallbackFragment = mountSuspenseFallbackChildren(workInProgress, nextPrimaryChildren, nextFallbackChildren, renderLanes);
8999
+
9000
+ var _primaryChildFragment = workInProgress.child;
9001
+ _primaryChildFragment.memoizedState = mountSuspenseOffscreenState(renderLanes);
9002
+ workInProgress.memoizedState = SUSPENDED_MARKER; // Since nothing actually suspended, there will nothing to ping this to
9003
+ // get it started back up to attempt the next item. While in terms of
9004
+ // priority this work has the same priority as this current render, it's
9005
+ // not part of the same transition once the transition has committed. If
9006
+ // it's sync, we still want to yield so that it can be painted.
9007
+ // Conceptually, this is really the same as pinging. We can use any
9008
+ // RetryLane even if it's the one currently rendering since we're leaving
9009
+ // it behind on this node.
9010
+
9011
+ workInProgress.lanes = SomeRetryLane;
9012
+
9013
+ {
9014
+ markSpawnedWork(SomeRetryLane);
9015
+ }
9016
+
9017
+ return _fallbackFragment;
9014
9018
  } else {
9015
- var _nextPrimaryChildren = nextProps.children;
9016
- return mountSuspensePrimaryChildren(workInProgress, _nextPrimaryChildren, renderLanes);
9019
+ return mountSuspensePrimaryChildren(workInProgress, nextPrimaryChildren, renderLanes);
9017
9020
  }
9018
9021
  } else {
9019
9022
  // This is an update.
@@ -9025,37 +9028,37 @@
9025
9028
 
9026
9029
  if (showFallback) {
9027
9030
  var _nextFallbackChildren2 = nextProps.fallback;
9028
- var _nextPrimaryChildren3 = nextProps.children;
9031
+ var _nextPrimaryChildren2 = nextProps.children;
9029
9032
 
9030
- var _fallbackChildFragment = updateSuspenseFallbackChildren(current, workInProgress, _nextPrimaryChildren3, _nextFallbackChildren2, renderLanes);
9033
+ var _fallbackChildFragment = updateSuspenseFallbackChildren(current, workInProgress, _nextPrimaryChildren2, _nextFallbackChildren2, renderLanes);
9031
9034
 
9032
- var _primaryChildFragment2 = workInProgress.child;
9035
+ var _primaryChildFragment3 = workInProgress.child;
9033
9036
  var prevOffscreenState = current.child.memoizedState;
9034
- _primaryChildFragment2.memoizedState = prevOffscreenState === null ? mountSuspenseOffscreenState(renderLanes) : updateSuspenseOffscreenState(prevOffscreenState, renderLanes);
9035
- _primaryChildFragment2.childLanes = getRemainingWorkInPrimaryTree(current, renderLanes);
9037
+ _primaryChildFragment3.memoizedState = prevOffscreenState === null ? mountSuspenseOffscreenState(renderLanes) : updateSuspenseOffscreenState(prevOffscreenState, renderLanes);
9038
+ _primaryChildFragment3.childLanes = getRemainingWorkInPrimaryTree(current, renderLanes);
9036
9039
  workInProgress.memoizedState = SUSPENDED_MARKER;
9037
9040
  return _fallbackChildFragment;
9038
9041
  } else {
9039
- var _nextPrimaryChildren4 = nextProps.children;
9042
+ var _nextPrimaryChildren3 = nextProps.children;
9040
9043
 
9041
- var _primaryChildFragment3 = updateSuspensePrimaryChildren(current, workInProgress, _nextPrimaryChildren4, renderLanes);
9044
+ var _primaryChildFragment4 = updateSuspensePrimaryChildren(current, workInProgress, _nextPrimaryChildren3, renderLanes);
9042
9045
 
9043
9046
  workInProgress.memoizedState = null;
9044
- return _primaryChildFragment3;
9047
+ return _primaryChildFragment4;
9045
9048
  }
9046
9049
  } else {
9047
9050
  // The current tree is not already showing a fallback.
9048
9051
  if (showFallback) {
9049
9052
  // Timed out.
9050
9053
  var _nextFallbackChildren3 = nextProps.fallback;
9051
- var _nextPrimaryChildren5 = nextProps.children;
9054
+ var _nextPrimaryChildren4 = nextProps.children;
9052
9055
 
9053
- var _fallbackChildFragment2 = updateSuspenseFallbackChildren(current, workInProgress, _nextPrimaryChildren5, _nextFallbackChildren3, renderLanes);
9056
+ var _fallbackChildFragment2 = updateSuspenseFallbackChildren(current, workInProgress, _nextPrimaryChildren4, _nextFallbackChildren3, renderLanes);
9054
9057
 
9055
- var _primaryChildFragment4 = workInProgress.child;
9058
+ var _primaryChildFragment5 = workInProgress.child;
9056
9059
  var _prevOffscreenState = current.child.memoizedState;
9057
- _primaryChildFragment4.memoizedState = _prevOffscreenState === null ? mountSuspenseOffscreenState(renderLanes) : updateSuspenseOffscreenState(_prevOffscreenState, renderLanes);
9058
- _primaryChildFragment4.childLanes = getRemainingWorkInPrimaryTree(current, renderLanes); // Skip the primary children, and continue working on the
9060
+ _primaryChildFragment5.memoizedState = _prevOffscreenState === null ? mountSuspenseOffscreenState(renderLanes) : updateSuspenseOffscreenState(_prevOffscreenState, renderLanes);
9061
+ _primaryChildFragment5.childLanes = getRemainingWorkInPrimaryTree(current, renderLanes); // Skip the primary children, and continue working on the
9059
9062
  // fallback children.
9060
9063
 
9061
9064
  workInProgress.memoizedState = SUSPENDED_MARKER;
@@ -9063,12 +9066,12 @@
9063
9066
  } else {
9064
9067
  // Still haven't timed out. Continue rendering the children, like we
9065
9068
  // normally do.
9066
- var _nextPrimaryChildren6 = nextProps.children;
9069
+ var _nextPrimaryChildren5 = nextProps.children;
9067
9070
 
9068
- var _primaryChildFragment5 = updateSuspensePrimaryChildren(current, workInProgress, _nextPrimaryChildren6, renderLanes);
9071
+ var _primaryChildFragment6 = updateSuspensePrimaryChildren(current, workInProgress, _nextPrimaryChildren5, renderLanes);
9069
9072
 
9070
9073
  workInProgress.memoizedState = null;
9071
- return _primaryChildFragment5;
9074
+ return _primaryChildFragment6;
9072
9075
  }
9073
9076
  }
9074
9077
  }
@@ -9150,15 +9153,9 @@
9150
9153
 
9151
9154
  if (currentFallbackChildFragment !== null) {
9152
9155
  // Delete the fallback child fragment
9153
- var deletions = workInProgress.deletions;
9154
-
9155
- if (deletions === null) {
9156
- workInProgress.deletions = [currentFallbackChildFragment]; // TODO (effects) Rename this to better reflect its new usage (e.g. ChildDeletions)
9157
-
9158
- workInProgress.flags |= Deletion;
9159
- } else {
9160
- deletions.push(currentFallbackChildFragment);
9161
- }
9156
+ currentFallbackChildFragment.nextEffect = null;
9157
+ currentFallbackChildFragment.flags = Deletion;
9158
+ workInProgress.firstEffect = workInProgress.lastEffect = currentFallbackChildFragment;
9162
9159
  }
9163
9160
 
9164
9161
  workInProgress.child = primaryChildFragment;
@@ -9200,16 +9197,24 @@
9200
9197
  primaryChildFragment.treeBaseDuration = currentPrimaryChildFragment.treeBaseDuration;
9201
9198
  } // The fallback fiber was added as a deletion effect during the first pass.
9202
9199
  // However, since we're going to remain on the fallback, we no longer want
9203
- // to delete it.
9200
+ // to delete it. So we need to remove it from the list. Deletions are stored
9201
+ // on the same list as effects. We want to keep the effects from the primary
9202
+ // tree. So we copy the primary child fragment's effect list, which does not
9203
+ // include the fallback deletion effect.
9204
9204
 
9205
9205
 
9206
- workInProgress.deletions = null;
9207
- } else {
9208
- primaryChildFragment = createWorkInProgressOffscreenFiber(currentPrimaryChildFragment, primaryChildProps); // Since we're reusing a current tree, we need to reuse the flags, too.
9209
- // (We don't do this in legacy mode, because in legacy mode we don't re-use
9210
- // the current tree; see previous branch.)
9206
+ var progressedLastEffect = primaryChildFragment.lastEffect;
9211
9207
 
9212
- primaryChildFragment.subtreeFlags = currentPrimaryChildFragment.subtreeFlags & StaticMask;
9208
+ if (progressedLastEffect !== null) {
9209
+ workInProgress.firstEffect = primaryChildFragment.firstEffect;
9210
+ workInProgress.lastEffect = progressedLastEffect;
9211
+ progressedLastEffect.nextEffect = null;
9212
+ } else {
9213
+ // TODO: Reset this somewhere else? Lol legacy mode is so weird.
9214
+ workInProgress.firstEffect = workInProgress.lastEffect = null;
9215
+ }
9216
+ } else {
9217
+ primaryChildFragment = createWorkInProgressOffscreenFiber(currentPrimaryChildFragment, primaryChildProps);
9213
9218
  }
9214
9219
 
9215
9220
  var fallbackChildFragment;
@@ -9412,7 +9417,7 @@
9412
9417
  }
9413
9418
  }
9414
9419
 
9415
- function initSuspenseListRenderState(workInProgress, isBackwards, tail, lastContentRow, tailMode) {
9420
+ function initSuspenseListRenderState(workInProgress, isBackwards, tail, lastContentRow, tailMode, lastEffectBeforeRendering) {
9416
9421
  var renderState = workInProgress.memoizedState;
9417
9422
 
9418
9423
  if (renderState === null) {
@@ -9422,7 +9427,8 @@
9422
9427
  renderingStartTime: 0,
9423
9428
  last: lastContentRow,
9424
9429
  tail: tail,
9425
- tailMode: tailMode
9430
+ tailMode: tailMode,
9431
+ lastEffect: lastEffectBeforeRendering
9426
9432
  };
9427
9433
  } else {
9428
9434
  // We can reuse the existing object from previous renders.
@@ -9432,6 +9438,7 @@
9432
9438
  renderState.last = lastContentRow;
9433
9439
  renderState.tail = tail;
9434
9440
  renderState.tailMode = tailMode;
9441
+ renderState.lastEffect = lastEffectBeforeRendering;
9435
9442
  }
9436
9443
  } // This can end up rendering this component multiple passes.
9437
9444
  // The first pass splits the children fibers into two sets. A head and tail.
@@ -9496,7 +9503,7 @@
9496
9503
  }
9497
9504
 
9498
9505
  initSuspenseListRenderState(workInProgress, false, // isBackwards
9499
- tail, lastContentRow, tailMode);
9506
+ tail, lastContentRow, tailMode, workInProgress.lastEffect);
9500
9507
  break;
9501
9508
  }
9502
9509
 
@@ -9528,7 +9535,7 @@
9528
9535
 
9529
9536
  initSuspenseListRenderState(workInProgress, true, // isBackwards
9530
9537
  _tail, null, // last
9531
- tailMode);
9538
+ tailMode, workInProgress.lastEffect);
9532
9539
  break;
9533
9540
  }
9534
9541
 
@@ -9537,7 +9544,7 @@
9537
9544
  initSuspenseListRenderState(workInProgress, false, // isBackwards
9538
9545
  null, // tail
9539
9546
  null, // last
9540
- undefined);
9547
+ undefined, workInProgress.lastEffect);
9541
9548
  break;
9542
9549
  }
9543
9550
 
@@ -9743,16 +9750,17 @@
9743
9750
  // Since the old fiber is disconnected, we have to schedule it manually.
9744
9751
 
9745
9752
 
9746
- var deletions = returnFiber.deletions;
9747
-
9748
- if (deletions === null) {
9749
- returnFiber.deletions = [current]; // TODO (effects) Rename this to better reflect its new usage (e.g. ChildDeletions)
9753
+ var last = returnFiber.lastEffect;
9750
9754
 
9751
- returnFiber.flags |= Deletion;
9755
+ if (last !== null) {
9756
+ last.nextEffect = current;
9757
+ returnFiber.lastEffect = current;
9752
9758
  } else {
9753
- deletions.push(current);
9759
+ returnFiber.firstEffect = returnFiber.lastEffect = current;
9754
9760
  }
9755
9761
 
9762
+ current.nextEffect = null;
9763
+ current.flags = Deletion;
9756
9764
  newWorkInProgress.flags |= Placement; // Restart work from the new fiber.
9757
9765
 
9758
9766
  return newWorkInProgress;
@@ -9817,11 +9825,10 @@
9817
9825
  case Profiler:
9818
9826
  {
9819
9827
  // Profiler should only call onRender when one of its descendants actually rendered.
9820
- // TODO: Only call onRender et al if subtree has effects
9821
9828
  var hasChildWork = includesSomeLane(renderLanes, workInProgress.childLanes);
9822
9829
 
9823
9830
  if (hasChildWork) {
9824
- workInProgress.flags |= Passive | Update;
9831
+ workInProgress.flags |= Update;
9825
9832
  } // Reset effect durations for the next eventual effect phase.
9826
9833
  // These are reset during render to allow the DevTools commit hook a chance to read them,
9827
9834
 
@@ -9905,6 +9912,7 @@
9905
9912
  // update in the past but didn't complete it.
9906
9913
  renderState.rendering = null;
9907
9914
  renderState.tail = null;
9915
+ renderState.lastEffect = null;
9908
9916
  }
9909
9917
 
9910
9918
  pushSuspenseContext(workInProgress, suspenseStackCursor.current);
@@ -10156,7 +10164,7 @@
10156
10164
  }
10157
10165
  };
10158
10166
 
10159
- updateHostContainer = function (current, workInProgress) {// Noop
10167
+ updateHostContainer = function (workInProgress) {// Noop
10160
10168
  };
10161
10169
 
10162
10170
  updateHostComponent$1 = function (current, workInProgress, type, newProps, rootContainerInstance) {
@@ -10272,92 +10280,6 @@
10272
10280
  }
10273
10281
  }
10274
10282
 
10275
- function bubbleProperties(completedWork) {
10276
- var didBailout = completedWork.alternate !== null && completedWork.alternate.child === completedWork.child;
10277
- var newChildLanes = NoLanes;
10278
- var subtreeFlags = NoFlags;
10279
-
10280
- if (!didBailout) {
10281
- // Bubble up the earliest expiration time.
10282
- if ( (completedWork.mode & ProfileMode) !== NoMode) {
10283
- // In profiling mode, resetChildExpirationTime is also used to reset
10284
- // profiler durations.
10285
- var actualDuration = completedWork.actualDuration;
10286
- var treeBaseDuration = completedWork.selfBaseDuration;
10287
- var child = completedWork.child;
10288
-
10289
- while (child !== null) {
10290
- newChildLanes = mergeLanes(newChildLanes, mergeLanes(child.lanes, child.childLanes));
10291
- subtreeFlags |= child.subtreeFlags;
10292
- subtreeFlags |= child.flags; // When a fiber is cloned, its actualDuration is reset to 0. This value will
10293
- // only be updated if work is done on the fiber (i.e. it doesn't bailout).
10294
- // When work is done, it should bubble to the parent's actualDuration. If
10295
- // the fiber has not been cloned though, (meaning no work was done), then
10296
- // this value will reflect the amount of time spent working on a previous
10297
- // render. In that case it should not bubble. We determine whether it was
10298
- // cloned by comparing the child pointer.
10299
-
10300
- actualDuration += child.actualDuration;
10301
- treeBaseDuration += child.treeBaseDuration;
10302
- child = child.sibling;
10303
- }
10304
-
10305
- completedWork.actualDuration = actualDuration;
10306
- completedWork.treeBaseDuration = treeBaseDuration;
10307
- } else {
10308
- var _child = completedWork.child;
10309
-
10310
- while (_child !== null) {
10311
- newChildLanes = mergeLanes(newChildLanes, mergeLanes(_child.lanes, _child.childLanes));
10312
- subtreeFlags |= _child.subtreeFlags;
10313
- subtreeFlags |= _child.flags;
10314
- _child = _child.sibling;
10315
- }
10316
- }
10317
-
10318
- completedWork.subtreeFlags |= subtreeFlags;
10319
- } else {
10320
- // Bubble up the earliest expiration time.
10321
- if ( (completedWork.mode & ProfileMode) !== NoMode) {
10322
- // In profiling mode, resetChildExpirationTime is also used to reset
10323
- // profiler durations.
10324
- var _treeBaseDuration = completedWork.selfBaseDuration;
10325
- var _child2 = completedWork.child;
10326
-
10327
- while (_child2 !== null) {
10328
- newChildLanes = mergeLanes(newChildLanes, mergeLanes(_child2.lanes, _child2.childLanes)); // "Static" flags share the lifetime of the fiber/hook they belong to,
10329
- // so we should bubble those up even during a bailout. All the other
10330
- // flags have a lifetime only of a single render + commit, so we should
10331
- // ignore them.
10332
-
10333
- subtreeFlags |= _child2.subtreeFlags & StaticMask;
10334
- subtreeFlags |= _child2.flags & StaticMask;
10335
- _treeBaseDuration += _child2.treeBaseDuration;
10336
- _child2 = _child2.sibling;
10337
- }
10338
-
10339
- completedWork.treeBaseDuration = _treeBaseDuration;
10340
- } else {
10341
- var _child3 = completedWork.child;
10342
-
10343
- while (_child3 !== null) {
10344
- newChildLanes = mergeLanes(newChildLanes, mergeLanes(_child3.lanes, _child3.childLanes)); // "Static" flags share the lifetime of the fiber/hook they belong to,
10345
- // so we should bubble those up even during a bailout. All the other
10346
- // flags have a lifetime only of a single render + commit, so we should
10347
- // ignore them.
10348
-
10349
- subtreeFlags |= _child3.subtreeFlags & StaticMask;
10350
- subtreeFlags |= _child3.flags & StaticMask;
10351
- _child3 = _child3.sibling;
10352
- }
10353
- }
10354
-
10355
- completedWork.subtreeFlags |= subtreeFlags;
10356
- }
10357
-
10358
- completedWork.childLanes = newChildLanes;
10359
- }
10360
-
10361
10283
  function completeWork(current, workInProgress, renderLanes) {
10362
10284
  var newProps = workInProgress.pendingProps;
10363
10285
 
@@ -10372,7 +10294,6 @@
10372
10294
  case Profiler:
10373
10295
  case ContextConsumer:
10374
10296
  case MemoComponent:
10375
- bubbleProperties(workInProgress);
10376
10297
  return null;
10377
10298
 
10378
10299
  case ClassComponent:
@@ -10383,7 +10304,6 @@
10383
10304
  popContext(workInProgress);
10384
10305
  }
10385
10306
 
10386
- bubbleProperties(workInProgress);
10387
10307
  return null;
10388
10308
  }
10389
10309
 
@@ -10417,8 +10337,7 @@
10417
10337
  }
10418
10338
  }
10419
10339
 
10420
- updateHostContainer(current, workInProgress);
10421
- bubbleProperties(workInProgress);
10340
+ updateHostContainer(workInProgress);
10422
10341
  return null;
10423
10342
  }
10424
10343
 
@@ -10443,7 +10362,6 @@
10443
10362
  } // This can happen when we abort work.
10444
10363
 
10445
10364
 
10446
- bubbleProperties(workInProgress);
10447
10365
  return null;
10448
10366
  }
10449
10367
 
@@ -10474,7 +10392,6 @@
10474
10392
  }
10475
10393
  }
10476
10394
 
10477
- bubbleProperties(workInProgress);
10478
10395
  return null;
10479
10396
  }
10480
10397
 
@@ -10512,7 +10429,6 @@
10512
10429
  }
10513
10430
  }
10514
10431
 
10515
- bubbleProperties(workInProgress);
10516
10432
  return null;
10517
10433
  }
10518
10434
 
@@ -10527,8 +10443,7 @@
10527
10443
 
10528
10444
  if ( (workInProgress.mode & ProfileMode) !== NoMode) {
10529
10445
  transferActualDuration(workInProgress);
10530
- } // Don't bubble properties in this case.
10531
-
10446
+ }
10532
10447
 
10533
10448
  return workInProgress;
10534
10449
  }
@@ -10583,40 +10498,22 @@
10583
10498
  }
10584
10499
  }
10585
10500
 
10586
- bubbleProperties(workInProgress);
10587
-
10588
- {
10589
- if ((workInProgress.mode & ProfileMode) !== NoMode) {
10590
- if (nextDidTimeout) {
10591
- // Don't count time spent in a timed out Suspense subtree as part of the base duration.
10592
- var _primaryChildFragment2 = workInProgress.child;
10593
-
10594
- if (_primaryChildFragment2 !== null) {
10595
- // $FlowFixMe Flow doens't support type casting in combiation with the -= operator
10596
- workInProgress.treeBaseDuration -= _primaryChildFragment2.treeBaseDuration;
10597
- }
10598
- }
10599
- }
10600
- }
10601
-
10602
10501
  return null;
10603
10502
  }
10604
10503
 
10605
10504
  case HostPortal:
10606
10505
  popHostContainer(workInProgress);
10607
- updateHostContainer(current, workInProgress);
10506
+ updateHostContainer(workInProgress);
10608
10507
 
10609
10508
  if (current === null) {
10610
10509
  preparePortalMount(workInProgress.stateNode.containerInfo);
10611
10510
  }
10612
10511
 
10613
- bubbleProperties(workInProgress);
10614
10512
  return null;
10615
10513
 
10616
10514
  case ContextProvider:
10617
10515
  // Pop provider fiber
10618
10516
  popProvider(workInProgress);
10619
- bubbleProperties(workInProgress);
10620
10517
  return null;
10621
10518
 
10622
10519
  case IncompleteClassComponent:
@@ -10629,7 +10526,6 @@
10629
10526
  popContext(workInProgress);
10630
10527
  }
10631
10528
 
10632
- bubbleProperties(workInProgress);
10633
10529
  return null;
10634
10530
  }
10635
10531
 
@@ -10641,7 +10537,6 @@
10641
10537
  if (renderState === null) {
10642
10538
  // We're running in the default, "independent" mode.
10643
10539
  // We don't do anything in this mode.
10644
- bubbleProperties(workInProgress);
10645
10540
  return null;
10646
10541
  }
10647
10542
 
@@ -10691,15 +10586,19 @@
10691
10586
  workInProgress.flags |= Update;
10692
10587
  } // Rerender the whole list, but this time, we'll force fallbacks
10693
10588
  // to stay in place.
10694
- // Reset the child fibers to their original state.
10589
+ // Reset the effect list before doing the second pass since that's now invalid.
10590
+
10591
+
10592
+ if (renderState.lastEffect === null) {
10593
+ workInProgress.firstEffect = null;
10594
+ }
10695
10595
 
10596
+ workInProgress.lastEffect = renderState.lastEffect; // Reset the child fibers to their original state.
10696
10597
 
10697
- workInProgress.subtreeFlags = NoFlags;
10698
10598
  resetChildFibers(workInProgress, renderLanes); // Set up the Suspense Context to force suspense and immediately
10699
10599
  // rerender the children.
10700
10600
 
10701
- pushSuspenseContext(workInProgress, setShallowSuspenseContext(suspenseStackCursor.current, ForceSuspenseFallback)); // Don't bubble properties in this case.
10702
-
10601
+ pushSuspenseContext(workInProgress, setShallowSuspenseContext(suspenseStackCursor.current, ForceSuspenseFallback));
10703
10602
  return workInProgress.child;
10704
10603
  }
10705
10604
 
@@ -10753,8 +10652,16 @@
10753
10652
 
10754
10653
  if (renderState.tail === null && renderState.tailMode === 'hidden' && !renderedTail.alternate && !getIsHydrating() // We don't cut it if we're hydrating.
10755
10654
  ) {
10756
- // We're done.
10757
- bubbleProperties(workInProgress);
10655
+ // We need to delete the row we just rendered.
10656
+ // Reset the effect list to what it was before we rendered this
10657
+ // child. The nested children have already appended themselves.
10658
+ var lastEffect = workInProgress.lastEffect = renderState.lastEffect; // Remove any effects that were appended after this point.
10659
+
10660
+ if (lastEffect !== null) {
10661
+ lastEffect.nextEffect = null;
10662
+ } // We're done.
10663
+
10664
+
10758
10665
  return null;
10759
10666
  }
10760
10667
  } else if ( // The time it took to render last row is greater than the remaining
@@ -10767,10 +10674,13 @@
10767
10674
  workInProgress.flags |= DidCapture;
10768
10675
  didSuspendAlready = true;
10769
10676
  cutOffTailIfNeeded(renderState, false); // Since nothing actually suspended, there will nothing to ping this
10770
- // to get it started back up to attempt the next item. If we can show
10771
- // them, then they really have the same priority as this render.
10772
- // So we'll pick it back up the very next render pass once we've had
10773
- // an opportunity to yield for paint.
10677
+ // to get it started back up to attempt the next item. While in terms
10678
+ // of priority this work has the same priority as this current render,
10679
+ // it's not part of the same transition once the transition has
10680
+ // committed. If it's sync, we still want to yield so that it can be
10681
+ // painted. Conceptually, this is really the same as pinging.
10682
+ // We can use any RetryLane even if it's the one currently rendering
10683
+ // since we're leaving it behind on this node.
10774
10684
 
10775
10685
  workInProgress.lanes = SomeRetryLane;
10776
10686
 
@@ -10807,6 +10717,7 @@
10807
10717
  var next = renderState.tail;
10808
10718
  renderState.rendering = next;
10809
10719
  renderState.tail = next.sibling;
10720
+ renderState.lastEffect = workInProgress.lastEffect;
10810
10721
  renderState.renderingStartTime = now();
10811
10722
  next.sibling = null; // Restore the context.
10812
10723
  // TODO: We can probably just avoid popping it instead and only
@@ -10821,12 +10732,10 @@
10821
10732
  }
10822
10733
 
10823
10734
  pushSuspenseContext(workInProgress, suspenseContext); // Do a pass over the next row.
10824
- // Don't bubble properties in this case.
10825
10735
 
10826
10736
  return next;
10827
10737
  }
10828
10738
 
10829
- bubbleProperties(workInProgress);
10830
10739
  return null;
10831
10740
  }
10832
10741
 
@@ -10850,21 +10759,16 @@
10850
10759
  case LegacyHiddenComponent:
10851
10760
  {
10852
10761
  popRenderLanes(workInProgress);
10853
- var _nextState = workInProgress.memoizedState;
10854
- var nextIsHidden = _nextState !== null;
10855
10762
 
10856
10763
  if (current !== null) {
10764
+ var _nextState = workInProgress.memoizedState;
10857
10765
  var _prevState = current.memoizedState;
10858
10766
  var prevIsHidden = _prevState !== null;
10767
+ var nextIsHidden = _nextState !== null;
10859
10768
 
10860
10769
  if (prevIsHidden !== nextIsHidden && newProps.mode !== 'unstable-defer-without-hiding') {
10861
10770
  workInProgress.flags |= Update;
10862
10771
  }
10863
- } // Don't bubble properties for hidden children.
10864
-
10865
-
10866
- if (!nextIsHidden || includesSomeLane(subtreeRenderLanes, OffscreenLane) || (workInProgress.mode & ConcurrentMode) === NoMode) {
10867
- bubbleProperties(workInProgress);
10868
10772
  }
10869
10773
 
10870
10774
  return null;
@@ -11218,7 +11122,9 @@
11218
11122
 
11219
11123
  function throwException(root, returnFiber, sourceFiber, value, rootRenderLanes) {
11220
11124
  // The source fiber did not complete.
11221
- sourceFiber.flags |= Incomplete;
11125
+ sourceFiber.flags |= Incomplete; // Its effect list is no longer valid.
11126
+
11127
+ sourceFiber.firstEffect = sourceFiber.lastEffect = null;
11222
11128
 
11223
11129
  if (value !== null && typeof value === 'object' && typeof value.then === 'function') {
11224
11130
  // This is a wakeable.
@@ -11636,18 +11542,18 @@
11636
11542
  }; // Capture errors so they don't interrupt unmounting.
11637
11543
 
11638
11544
 
11639
- function safelyCallComponentWillUnmount(current, instance, nearestMountedAncestor) {
11545
+ function safelyCallComponentWillUnmount(current, instance) {
11640
11546
  {
11641
11547
  invokeGuardedCallback(null, callComponentWillUnmountWithTimer, null, current, instance);
11642
11548
 
11643
11549
  if (hasCaughtError()) {
11644
11550
  var unmountError = clearCaughtError();
11645
- captureCommitPhaseError(current, nearestMountedAncestor, unmountError);
11551
+ captureCommitPhaseError(current, unmountError);
11646
11552
  }
11647
11553
  }
11648
11554
  }
11649
11555
 
11650
- function safelyDetachRef(current, nearestMountedAncestor) {
11556
+ function safelyDetachRef(current) {
11651
11557
  var ref = current.ref;
11652
11558
 
11653
11559
  if (ref !== null) {
@@ -11657,7 +11563,7 @@
11657
11563
 
11658
11564
  if (hasCaughtError()) {
11659
11565
  var refError = clearCaughtError();
11660
- captureCommitPhaseError(current, nearestMountedAncestor, refError);
11566
+ captureCommitPhaseError(current, refError);
11661
11567
  }
11662
11568
  }
11663
11569
  } else {
@@ -11666,13 +11572,13 @@
11666
11572
  }
11667
11573
  }
11668
11574
 
11669
- function safelyCallDestroy(current, nearestMountedAncestor, destroy) {
11575
+ function safelyCallDestroy(current, destroy) {
11670
11576
  {
11671
11577
  invokeGuardedCallback(null, destroy, null);
11672
11578
 
11673
11579
  if (hasCaughtError()) {
11674
11580
  var error = clearCaughtError();
11675
- captureCommitPhaseError(current, nearestMountedAncestor, error);
11581
+ captureCommitPhaseError(current, error);
11676
11582
  }
11677
11583
  }
11678
11584
  }
@@ -11755,7 +11661,7 @@
11755
11661
  }
11756
11662
  }
11757
11663
 
11758
- function commitHookEffectListUnmount(tag, finishedWork, nearestMountedAncestor) {
11664
+ function commitHookEffectListUnmount(tag, finishedWork) {
11759
11665
  var updateQueue = finishedWork.updateQueue;
11760
11666
  var lastEffect = updateQueue !== null ? updateQueue.lastEffect : null;
11761
11667
 
@@ -11770,45 +11676,13 @@
11770
11676
  effect.destroy = undefined;
11771
11677
 
11772
11678
  if (destroy !== undefined) {
11773
- safelyCallDestroy(finishedWork, nearestMountedAncestor, destroy);
11679
+ destroy();
11774
11680
  }
11775
11681
  }
11776
11682
 
11777
11683
  effect = effect.next;
11778
11684
  } while (effect !== firstEffect);
11779
11685
  }
11780
- } // TODO: Remove this duplication.
11781
-
11782
-
11783
- function commitHookEffectListUnmount2( // Tags to check for when deciding whether to unmount. e.g. to skip over layout effects
11784
- hookFlags, fiber, nearestMountedAncestor) {
11785
- var updateQueue = fiber.updateQueue;
11786
- var lastEffect = updateQueue !== null ? updateQueue.lastEffect : null;
11787
-
11788
- if (lastEffect !== null) {
11789
- var firstEffect = lastEffect.next;
11790
- var effect = firstEffect;
11791
-
11792
- do {
11793
- var _effect = effect,
11794
- next = _effect.next,
11795
- tag = _effect.tag;
11796
-
11797
- if ((tag & hookFlags) === hookFlags) {
11798
- var destroy = effect.destroy;
11799
-
11800
- if (destroy !== undefined) {
11801
- effect.destroy = undefined;
11802
-
11803
- {
11804
- safelyCallDestroy(fiber, nearestMountedAncestor, destroy);
11805
- }
11806
- }
11807
- }
11808
-
11809
- effect = next;
11810
- } while (effect !== firstEffect);
11811
- }
11812
11686
  }
11813
11687
 
11814
11688
  function commitHookEffectListMount(tag, finishedWork) {
@@ -11849,14 +11723,8 @@
11849
11723
  }
11850
11724
  }
11851
11725
 
11852
- function invokePassiveEffectCreate(effect) {
11853
- var create = effect.create;
11854
- effect.destroy = create();
11855
- } // TODO: Remove this duplication.
11856
-
11857
-
11858
- function commitHookEffectListMount2(fiber) {
11859
- var updateQueue = fiber.updateQueue;
11726
+ function schedulePassiveEffects(finishedWork) {
11727
+ var updateQueue = finishedWork.updateQueue;
11860
11728
  var lastEffect = updateQueue !== null ? updateQueue.lastEffect : null;
11861
11729
 
11862
11730
  if (lastEffect !== null) {
@@ -11864,27 +11732,13 @@
11864
11732
  var effect = firstEffect;
11865
11733
 
11866
11734
  do {
11867
- var _effect2 = effect,
11868
- next = _effect2.next,
11869
- tag = _effect2.tag;
11735
+ var _effect = effect,
11736
+ next = _effect.next,
11737
+ tag = _effect.tag;
11870
11738
 
11871
11739
  if ((tag & Passive$1) !== NoFlags$1 && (tag & HasEffect) !== NoFlags$1) {
11872
- {
11873
- {
11874
- invokeGuardedCallback(null, invokePassiveEffectCreate, null, effect);
11875
- }
11876
-
11877
- if (hasCaughtError()) {
11878
- if (!(fiber !== null)) {
11879
- {
11880
- throw Error( "Should be working on an effect." );
11881
- }
11882
- }
11883
-
11884
- var error = clearCaughtError();
11885
- captureCommitPhaseError(fiber, fiber.return, error);
11886
- }
11887
- }
11740
+ enqueuePendingPassiveHookEffectUnmount(finishedWork, effect);
11741
+ enqueuePendingPassiveHookEffectMount(finishedWork, effect);
11888
11742
  }
11889
11743
 
11890
11744
  effect = next;
@@ -11907,10 +11761,7 @@
11907
11761
  commitHookEffectListMount(Layout | HasEffect, finishedWork);
11908
11762
  }
11909
11763
 
11910
- if ((finishedWork.subtreeFlags & PassiveMask) !== NoFlags) {
11911
- schedulePassiveEffectCallback();
11912
- }
11913
-
11764
+ schedulePassiveEffects(finishedWork);
11914
11765
  return;
11915
11766
  }
11916
11767
 
@@ -12174,7 +12025,7 @@
12174
12025
  // interrupt deletion, so it's okay
12175
12026
 
12176
12027
 
12177
- function commitUnmount(finishedRoot, current, nearestMountedAncestor, renderPriorityLevel) {
12028
+ function commitUnmount(finishedRoot, current, renderPriorityLevel) {
12178
12029
  onCommitUnmount(current);
12179
12030
 
12180
12031
  switch (current.tag) {
@@ -12194,14 +12045,16 @@
12194
12045
  var effect = firstEffect;
12195
12046
 
12196
12047
  do {
12197
- var _effect3 = effect,
12198
- destroy = _effect3.destroy,
12199
- tag = _effect3.tag;
12048
+ var _effect2 = effect,
12049
+ destroy = _effect2.destroy,
12050
+ tag = _effect2.tag;
12200
12051
 
12201
12052
  if (destroy !== undefined) {
12202
- if ((tag & Layout) !== NoFlags$1) {
12053
+ if ((tag & Passive$1) !== NoFlags$1) {
12054
+ enqueuePendingPassiveHookEffectUnmount(current, effect);
12055
+ } else {
12203
12056
  {
12204
- safelyCallDestroy(current, nearestMountedAncestor, destroy);
12057
+ safelyCallDestroy(current, destroy);
12205
12058
  }
12206
12059
  }
12207
12060
  }
@@ -12216,11 +12069,11 @@
12216
12069
 
12217
12070
  case ClassComponent:
12218
12071
  {
12219
- safelyDetachRef(current, nearestMountedAncestor);
12072
+ safelyDetachRef(current);
12220
12073
  var instance = current.stateNode;
12221
12074
 
12222
12075
  if (typeof instance.componentWillUnmount === 'function') {
12223
- safelyCallComponentWillUnmount(current, instance, nearestMountedAncestor);
12076
+ safelyCallComponentWillUnmount(current, instance);
12224
12077
  }
12225
12078
 
12226
12079
  return;
@@ -12228,7 +12081,7 @@
12228
12081
 
12229
12082
  case HostComponent:
12230
12083
  {
12231
- safelyDetachRef(current, nearestMountedAncestor);
12084
+ safelyDetachRef(current);
12232
12085
  return;
12233
12086
  }
12234
12087
 
@@ -12238,7 +12091,7 @@
12238
12091
  // We are also not using this parent because
12239
12092
  // the portal will get pushed immediately.
12240
12093
  {
12241
- unmountHostComponents(finishedRoot, current, nearestMountedAncestor);
12094
+ unmountHostComponents(finishedRoot, current);
12242
12095
  }
12243
12096
 
12244
12097
  return;
@@ -12264,7 +12117,7 @@
12264
12117
  }
12265
12118
  }
12266
12119
 
12267
- function commitNestedUnmounts(finishedRoot, root, nearestMountedAncestor, renderPriorityLevel) {
12120
+ function commitNestedUnmounts(finishedRoot, root, renderPriorityLevel) {
12268
12121
  // While we're inside a removed host node we don't want to call
12269
12122
  // removeChild on the inner nodes because they're removed by the top
12270
12123
  // call anyway. We also want to call componentWillUnmount on all
@@ -12273,7 +12126,7 @@
12273
12126
  var node = root;
12274
12127
 
12275
12128
  while (true) {
12276
- commitUnmount(finishedRoot, node, nearestMountedAncestor); // Visit children because they may contain more composite or host nodes.
12129
+ commitUnmount(finishedRoot, node); // Visit children because they may contain more composite or host nodes.
12277
12130
  // Skip portals because commitUnmount() currently visits them recursively.
12278
12131
 
12279
12132
  if (node.child !== null && ( // If we use mutation we drill down into portals using commitUnmount above.
@@ -12302,26 +12155,33 @@
12302
12155
  }
12303
12156
 
12304
12157
  function detachFiberMutation(fiber) {
12305
- // Cut off the return pointer to disconnect it from the tree.
12306
- // This enables us to detect and warn against state updates on an unmounted component.
12307
- // It also prevents events from bubbling from within disconnected components.
12308
- //
12309
- // Ideally, we should also clear the child pointer of the parent alternate to let this
12158
+ // Cut off the return pointers to disconnect it from the tree. Ideally, we
12159
+ // should clear the child pointer of the parent alternate to let this
12310
12160
  // get GC:ed but we don't know which for sure which parent is the current
12311
- // one so we'll settle for GC:ing the subtree of this child.
12312
- // This child itself will be GC:ed when the parent updates the next time.
12161
+ // one so we'll settle for GC:ing the subtree of this child. This child
12162
+ // itself will be GC:ed when the parent updates the next time.
12163
+ // Note: we cannot null out sibling here, otherwise it can cause issues
12164
+ // with findDOMNode and how it requires the sibling field to carry out
12165
+ // traversal in a later effect. See PR #16820. We now clear the sibling
12166
+ // field after effects, see: detachFiberAfterEffects.
12313
12167
  //
12314
- // Note that we can't clear child or sibling pointers yet.
12315
- // They're needed for passive effects and for findDOMNode.
12316
- // We defer those fields, and all other cleanup, to the passive phase (see detachFiberAfterEffects).
12317
- var alternate = fiber.alternate;
12168
+ // Don't disconnect stateNode now; it will be detached in detachFiberAfterEffects.
12169
+ // It may be required if the current component is an error boundary,
12170
+ // and one of its descendants throws while unmounting a passive effect.
12171
+ fiber.alternate = null;
12172
+ fiber.child = null;
12173
+ fiber.dependencies = null;
12174
+ fiber.firstEffect = null;
12175
+ fiber.lastEffect = null;
12176
+ fiber.memoizedProps = null;
12177
+ fiber.memoizedState = null;
12178
+ fiber.pendingProps = null;
12179
+ fiber.return = null;
12180
+ fiber.updateQueue = null;
12318
12181
 
12319
- if (alternate !== null) {
12320
- alternate.return = null;
12321
- fiber.alternate = null;
12182
+ {
12183
+ fiber._debugOwner = null;
12322
12184
  }
12323
-
12324
- fiber.return = null;
12325
12185
  }
12326
12186
 
12327
12187
  function getHostParentFiber(fiber) {
@@ -12501,7 +12361,7 @@
12501
12361
  }
12502
12362
  }
12503
12363
 
12504
- function unmountHostComponents(finishedRoot, current, nearestMountedAncestor, renderPriorityLevel) {
12364
+ function unmountHostComponents(finishedRoot, current, renderPriorityLevel) {
12505
12365
  // We only have the top Fiber that was deleted but we need to recurse down its
12506
12366
  // children to find all the terminal nodes.
12507
12367
  var node = current; // Each iteration, currentParent is populated with node's host parent if not
@@ -12550,7 +12410,7 @@
12550
12410
  }
12551
12411
 
12552
12412
  if (node.tag === HostComponent || node.tag === HostText) {
12553
- commitNestedUnmounts(finishedRoot, node, nearestMountedAncestor); // After all the children have unmounted, it is now safe to remove the
12413
+ commitNestedUnmounts(finishedRoot, node); // After all the children have unmounted, it is now safe to remove the
12554
12414
  // node from the tree.
12555
12415
 
12556
12416
  if (currentParentIsContainer) {
@@ -12571,7 +12431,7 @@
12571
12431
  continue;
12572
12432
  }
12573
12433
  } else {
12574
- commitUnmount(finishedRoot, node, nearestMountedAncestor); // Visit children because we may find more host components below.
12434
+ commitUnmount(finishedRoot, node); // Visit children because we may find more host components below.
12575
12435
 
12576
12436
  if (node.child !== null) {
12577
12437
  node.child.return = node;
@@ -12603,11 +12463,11 @@
12603
12463
  }
12604
12464
  }
12605
12465
 
12606
- function commitDeletion(finishedRoot, current, nearestMountedAncestor, renderPriorityLevel) {
12466
+ function commitDeletion(finishedRoot, current, renderPriorityLevel) {
12607
12467
  {
12608
12468
  // Recursively delete all host nodes from the parent.
12609
12469
  // Detach refs and call componentWillUnmount() on the whole subtree.
12610
- unmountHostComponents(finishedRoot, current, nearestMountedAncestor);
12470
+ unmountHostComponents(finishedRoot, current);
12611
12471
  }
12612
12472
 
12613
12473
  var alternate = current.alternate;
@@ -12633,7 +12493,7 @@
12633
12493
  // e.g. a destroy function in one component should never override a ref set
12634
12494
  // by a create function in another component during the same commit.
12635
12495
  {
12636
- commitHookEffectListUnmount(Layout | HasEffect, finishedWork, finishedWork.return);
12496
+ commitHookEffectListUnmount(Layout | HasEffect, finishedWork);
12637
12497
  }
12638
12498
 
12639
12499
  return;
@@ -12819,42 +12679,6 @@
12819
12679
  resetTextContent(current.stateNode);
12820
12680
  }
12821
12681
 
12822
- function commitPassiveWork(finishedWork) {
12823
- switch (finishedWork.tag) {
12824
- case FunctionComponent:
12825
- case ForwardRef:
12826
- case SimpleMemoComponent:
12827
- case Block:
12828
- {
12829
- commitHookEffectListUnmount2(Passive$1 | HasEffect, finishedWork, finishedWork.return);
12830
- break;
12831
- }
12832
- }
12833
- }
12834
-
12835
- function commitPassiveUnmount(current, nearestMountedAncestor) {
12836
- switch (current.tag) {
12837
- case FunctionComponent:
12838
- case ForwardRef:
12839
- case SimpleMemoComponent:
12840
- case Block:
12841
- commitHookEffectListUnmount2(Passive$1, current, nearestMountedAncestor);
12842
- }
12843
- }
12844
-
12845
- function commitPassiveLifeCycles(finishedRoot, finishedWork) {
12846
- switch (finishedWork.tag) {
12847
- case FunctionComponent:
12848
- case ForwardRef:
12849
- case SimpleMemoComponent:
12850
- case Block:
12851
- {
12852
- commitHookEffectListMount2(finishedWork);
12853
- break;
12854
- }
12855
- }
12856
- }
12857
-
12858
12682
  var COMPONENT_TYPE = 0;
12859
12683
  var HAS_PSEUDO_CLASS_TYPE = 1;
12860
12684
  var ROLE_TYPE = 2;
@@ -12991,6 +12815,7 @@
12991
12815
  function getRenderTargetTime() {
12992
12816
  return workInProgressRootRenderTargetTime;
12993
12817
  }
12818
+ var nextEffect = null;
12994
12819
  var hasUncaughtError = false;
12995
12820
  var firstUncaughtError = null;
12996
12821
  var legacyErrorBoundariesThatAlreadyFailed = null;
@@ -12998,6 +12823,8 @@
12998
12823
  var rootWithPendingPassiveEffects = null;
12999
12824
  var pendingPassiveEffectsRenderPriority = NoPriority$1;
13000
12825
  var pendingPassiveEffectsLanes = NoLanes;
12826
+ var pendingPassiveHookEffectsMount = [];
12827
+ var pendingPassiveHookEffectsUnmount = [];
13001
12828
  var rootsWithPendingDiscreteUpdates = null; // Use these to prevent an infinite loop of nested updates
13002
12829
 
13003
12830
  var NESTED_UPDATE_LIMIT = 50;
@@ -13320,7 +13147,7 @@
13320
13147
  // goes through Scheduler.
13321
13148
 
13322
13149
 
13323
- function performConcurrentWorkOnRoot(root, didTimeout) {
13150
+ function performConcurrentWorkOnRoot(root) {
13324
13151
  // Since we know we're in a React event, we can clear the current
13325
13152
  // event time. The next update will compute a new event time.
13326
13153
  currentEventTime = NoTimestamp;
@@ -13356,18 +13183,6 @@
13356
13183
  if (lanes === NoLanes) {
13357
13184
  // Defensive coding. This is never expected to happen.
13358
13185
  return null;
13359
- } // TODO: We only check `didTimeout` defensively, to account for a Scheduler
13360
- // bug we're still investigating. Once the bug in Scheduler is fixed,
13361
- // we can remove this, since we track expiration ourselves.
13362
-
13363
-
13364
- if ( didTimeout) {
13365
- // Something expired. Flush synchronously until there's no expired
13366
- // work left.
13367
- markRootExpired(root, lanes); // This will schedule a synchronous callback.
13368
-
13369
- ensureRootIsScheduled(root, now());
13370
- return null;
13371
13186
  }
13372
13187
 
13373
13188
  var exitStatus = renderRootConcurrent(root, lanes);
@@ -14038,6 +13853,46 @@
14038
13853
  workInProgress = next;
14039
13854
  return;
14040
13855
  }
13856
+
13857
+ resetChildLanes(completedWork);
13858
+
13859
+ if (returnFiber !== null && // Do not append effects to parents if a sibling failed to complete
13860
+ (returnFiber.flags & Incomplete) === NoFlags) {
13861
+ // Append all the effects of the subtree and this fiber onto the effect
13862
+ // list of the parent. The completion order of the children affects the
13863
+ // side-effect order.
13864
+ if (returnFiber.firstEffect === null) {
13865
+ returnFiber.firstEffect = completedWork.firstEffect;
13866
+ }
13867
+
13868
+ if (completedWork.lastEffect !== null) {
13869
+ if (returnFiber.lastEffect !== null) {
13870
+ returnFiber.lastEffect.nextEffect = completedWork.firstEffect;
13871
+ }
13872
+
13873
+ returnFiber.lastEffect = completedWork.lastEffect;
13874
+ } // If this fiber had side-effects, we append it AFTER the children's
13875
+ // side-effects. We can perform certain side-effects earlier if needed,
13876
+ // by doing multiple passes over the effect list. We don't want to
13877
+ // schedule our own side-effect on our own list because if end up
13878
+ // reusing children we'll schedule this effect onto itself since we're
13879
+ // at the end.
13880
+
13881
+
13882
+ var flags = completedWork.flags; // Skip both NoWork and PerformedWork tags when creating the effect
13883
+ // list. PerformedWork effect is read by React DevTools but shouldn't be
13884
+ // committed.
13885
+
13886
+ if (flags > PerformedWork) {
13887
+ if (returnFiber.lastEffect !== null) {
13888
+ returnFiber.lastEffect.nextEffect = completedWork;
13889
+ } else {
13890
+ returnFiber.firstEffect = completedWork;
13891
+ }
13892
+
13893
+ returnFiber.lastEffect = completedWork;
13894
+ }
13895
+ }
14041
13896
  } else {
14042
13897
  // This fiber did not complete because something threw. Pop values off
14043
13898
  // the stack without entering the complete phase. If this is a boundary,
@@ -14071,10 +13926,9 @@
14071
13926
  }
14072
13927
 
14073
13928
  if (returnFiber !== null) {
14074
- // Mark the parent fiber as incomplete
13929
+ // Mark the parent fiber as incomplete and clear its effect list.
13930
+ returnFiber.firstEffect = returnFiber.lastEffect = null;
14075
13931
  returnFiber.flags |= Incomplete;
14076
- returnFiber.subtreeFlags = NoFlags;
14077
- returnFiber.deletions = null;
14078
13932
  }
14079
13933
  }
14080
13934
 
@@ -14098,22 +13952,84 @@
14098
13952
  }
14099
13953
  }
14100
13954
 
14101
- function commitRoot(root) {
14102
- var renderPriorityLevel = getCurrentPriorityLevel();
14103
- runWithPriority(ImmediatePriority$1, commitRootImpl.bind(null, root, renderPriorityLevel));
14104
- return null;
14105
- }
13955
+ function resetChildLanes(completedWork) {
13956
+ if ( // TODO: Move this check out of the hot path by moving `resetChildLanes`
13957
+ // to switch statement in `completeWork`.
13958
+ (completedWork.tag === LegacyHiddenComponent || completedWork.tag === OffscreenComponent) && completedWork.memoizedState !== null && !includesSomeLane(subtreeRenderLanes, OffscreenLane) && (completedWork.mode & ConcurrentMode) !== NoLanes) {
13959
+ // The children of this component are hidden. Don't bubble their
13960
+ // expiration times.
13961
+ return;
13962
+ }
14106
13963
 
14107
- function commitRootImpl(root, renderPriorityLevel) {
14108
- do {
14109
- // `flushPassiveEffects` will call `flushSyncUpdateQueue` at the end, which
14110
- // means `flushPassiveEffects` will sometimes result in additional
14111
- // passive effects. So we need to keep flushing in a loop until there are
14112
- // no more pending effects.
14113
- // TODO: Might be better if `flushPassiveEffects` did not automatically
14114
- // flush synchronous work at the end, to avoid factoring hazards like this.
14115
- flushPassiveEffects();
14116
- } while (rootWithPendingPassiveEffects !== null);
13964
+ var newChildLanes = NoLanes; // Bubble up the earliest expiration time.
13965
+
13966
+ if ( (completedWork.mode & ProfileMode) !== NoMode) {
13967
+ // In profiling mode, resetChildExpirationTime is also used to reset
13968
+ // profiler durations.
13969
+ var actualDuration = completedWork.actualDuration;
13970
+ var treeBaseDuration = completedWork.selfBaseDuration; // When a fiber is cloned, its actualDuration is reset to 0. This value will
13971
+ // only be updated if work is done on the fiber (i.e. it doesn't bailout).
13972
+ // When work is done, it should bubble to the parent's actualDuration. If
13973
+ // the fiber has not been cloned though, (meaning no work was done), then
13974
+ // this value will reflect the amount of time spent working on a previous
13975
+ // render. In that case it should not bubble. We determine whether it was
13976
+ // cloned by comparing the child pointer.
13977
+
13978
+ var shouldBubbleActualDurations = completedWork.alternate === null || completedWork.child !== completedWork.alternate.child;
13979
+ var child = completedWork.child;
13980
+
13981
+ while (child !== null) {
13982
+ newChildLanes = mergeLanes(newChildLanes, mergeLanes(child.lanes, child.childLanes));
13983
+
13984
+ if (shouldBubbleActualDurations) {
13985
+ actualDuration += child.actualDuration;
13986
+ }
13987
+
13988
+ treeBaseDuration += child.treeBaseDuration;
13989
+ child = child.sibling;
13990
+ }
13991
+
13992
+ var isTimedOutSuspense = completedWork.tag === SuspenseComponent && completedWork.memoizedState !== null;
13993
+
13994
+ if (isTimedOutSuspense) {
13995
+ // Don't count time spent in a timed out Suspense subtree as part of the base duration.
13996
+ var primaryChildFragment = completedWork.child;
13997
+
13998
+ if (primaryChildFragment !== null) {
13999
+ treeBaseDuration -= primaryChildFragment.treeBaseDuration;
14000
+ }
14001
+ }
14002
+
14003
+ completedWork.actualDuration = actualDuration;
14004
+ completedWork.treeBaseDuration = treeBaseDuration;
14005
+ } else {
14006
+ var _child = completedWork.child;
14007
+
14008
+ while (_child !== null) {
14009
+ newChildLanes = mergeLanes(newChildLanes, mergeLanes(_child.lanes, _child.childLanes));
14010
+ _child = _child.sibling;
14011
+ }
14012
+ }
14013
+
14014
+ completedWork.childLanes = newChildLanes;
14015
+ }
14016
+
14017
+ function commitRoot(root) {
14018
+ var renderPriorityLevel = getCurrentPriorityLevel();
14019
+ runWithPriority(ImmediatePriority$1, commitRootImpl.bind(null, root, renderPriorityLevel));
14020
+ return null;
14021
+ }
14022
+
14023
+ function commitRootImpl(root, renderPriorityLevel) {
14024
+ do {
14025
+ // `flushPassiveEffects` will call `flushSyncUpdateQueue` at the end, which
14026
+ // means `flushPassiveEffects` will sometimes result in additional
14027
+ // passive effects. So we need to keep flushing in a loop until there are
14028
+ // no more pending effects.
14029
+ // TODO: Might be better if `flushPassiveEffects` did not automatically
14030
+ // flush synchronous work at the end, to avoid factoring hazards like this.
14031
+ flushPassiveEffects();
14032
+ } while (rootWithPendingPassiveEffects !== null);
14117
14033
 
14118
14034
  flushRenderPhaseStrictModeWarningsInDEV();
14119
14035
 
@@ -14161,17 +14077,28 @@
14161
14077
  workInProgressRoot = null;
14162
14078
  workInProgress = null;
14163
14079
  workInProgressRootRenderLanes = NoLanes;
14164
- } // Check if there are any effects in the whole tree.
14165
- // TODO: This is left over from the effect list implementation, where we had
14166
- // to check for the existence of `firstEffect` to satsify Flow. I think the
14167
- // only other reason this optimization exists is because it affects profiling.
14168
- // Reconsider whether this is necessary.
14080
+ } // Get the list of effects.
14081
+
14169
14082
 
14083
+ var firstEffect;
14170
14084
 
14171
- var subtreeHasEffects = (finishedWork.subtreeFlags & (BeforeMutationMask | MutationMask | LayoutMask | PassiveMask)) !== NoFlags;
14172
- var rootHasEffect = (finishedWork.flags & (BeforeMutationMask | MutationMask | LayoutMask | PassiveMask)) !== NoFlags;
14085
+ if (finishedWork.flags > PerformedWork) {
14086
+ // A fiber's effect list consists only of its children, not itself. So if
14087
+ // the root has an effect, we need to add it to the end of the list. The
14088
+ // resulting list is the set that would belong to the root's parent, if it
14089
+ // had one; that is, all the effects in the tree including the root.
14090
+ if (finishedWork.lastEffect !== null) {
14091
+ finishedWork.lastEffect.nextEffect = finishedWork;
14092
+ firstEffect = finishedWork.firstEffect;
14093
+ } else {
14094
+ firstEffect = finishedWork;
14095
+ }
14096
+ } else {
14097
+ // There is no effect on the root.
14098
+ firstEffect = finishedWork.firstEffect;
14099
+ }
14173
14100
 
14174
- if (subtreeHasEffects || rootHasEffect) {
14101
+ if (firstEffect !== null) {
14175
14102
 
14176
14103
  var prevExecutionContext = executionContext;
14177
14104
  executionContext |= CommitContext;
@@ -14186,7 +14113,26 @@
14186
14113
 
14187
14114
  focusedInstanceHandle = prepareForCommit(root.containerInfo);
14188
14115
  shouldFireAfterActiveInstanceBlur = false;
14189
- commitBeforeMutationEffects(finishedWork); // We no longer need to track the active instance fiber
14116
+ nextEffect = firstEffect;
14117
+
14118
+ do {
14119
+ {
14120
+ invokeGuardedCallback(null, commitBeforeMutationEffects, null);
14121
+
14122
+ if (hasCaughtError()) {
14123
+ if (!(nextEffect !== null)) {
14124
+ {
14125
+ throw Error( "Should be working on an effect." );
14126
+ }
14127
+ }
14128
+
14129
+ var error = clearCaughtError();
14130
+ captureCommitPhaseError(nextEffect, error);
14131
+ nextEffect = nextEffect.nextEffect;
14132
+ }
14133
+ }
14134
+ } while (nextEffect !== null); // We no longer need to track the active instance fiber
14135
+
14190
14136
 
14191
14137
  focusedInstanceHandle = null;
14192
14138
 
@@ -14197,7 +14143,26 @@
14197
14143
  } // The next phase is the mutation phase, where we mutate the host tree.
14198
14144
 
14199
14145
 
14200
- commitMutationEffects(finishedWork, root, renderPriorityLevel);
14146
+ nextEffect = firstEffect;
14147
+
14148
+ do {
14149
+ {
14150
+ invokeGuardedCallback(null, commitMutationEffects, null, root, renderPriorityLevel);
14151
+
14152
+ if (hasCaughtError()) {
14153
+ if (!(nextEffect !== null)) {
14154
+ {
14155
+ throw Error( "Should be working on an effect." );
14156
+ }
14157
+ }
14158
+
14159
+ var _error = clearCaughtError();
14160
+
14161
+ captureCommitPhaseError(nextEffect, _error);
14162
+ nextEffect = nextEffect.nextEffect;
14163
+ }
14164
+ }
14165
+ } while (nextEffect !== null);
14201
14166
 
14202
14167
  resetAfterCommit(root.containerInfo); // The work-in-progress tree is now the current tree. This must come after
14203
14168
  // the mutation phase, so that the previous tree is still current during
@@ -14205,21 +14170,32 @@
14205
14170
  // work is current during componentDidMount/Update.
14206
14171
 
14207
14172
  root.current = finishedWork; // The next phase is the layout phase, where we call effects that read
14173
+ // the host tree after it's been mutated. The idiomatic use case for this is
14174
+ // layout, but class component lifecycles also fire here for legacy reasons.
14208
14175
 
14209
- commitLayoutEffects(finishedWork, root, lanes);
14176
+ nextEffect = firstEffect;
14210
14177
 
14178
+ do {
14179
+ {
14180
+ invokeGuardedCallback(null, commitLayoutEffects, null, root, lanes);
14211
14181
 
14212
- if ((finishedWork.subtreeFlags & PassiveMask) !== NoFlags || (finishedWork.flags & PassiveMask) !== NoFlags) {
14213
- if (!rootDoesHavePassiveEffects) {
14214
- rootDoesHavePassiveEffects = true;
14215
- scheduleCallback(NormalPriority$1, function () {
14216
- flushPassiveEffects();
14217
- return null;
14218
- });
14182
+ if (hasCaughtError()) {
14183
+ if (!(nextEffect !== null)) {
14184
+ {
14185
+ throw Error( "Should be working on an effect." );
14186
+ }
14187
+ }
14188
+
14189
+ var _error2 = clearCaughtError();
14190
+
14191
+ captureCommitPhaseError(nextEffect, _error2);
14192
+ nextEffect = nextEffect.nextEffect;
14193
+ }
14219
14194
  }
14220
- } // Tell Scheduler to yield at the end of the frame, so the browser has an
14221
- // opportunity to paint.
14195
+ } while (nextEffect !== null);
14222
14196
 
14197
+ nextEffect = null; // Tell Scheduler to yield at the end of the frame, so the browser has an
14198
+ // opportunity to paint.
14223
14199
 
14224
14200
  requestPaint();
14225
14201
 
@@ -14248,6 +14224,22 @@
14248
14224
  rootWithPendingPassiveEffects = root;
14249
14225
  pendingPassiveEffectsLanes = lanes;
14250
14226
  pendingPassiveEffectsRenderPriority = renderPriorityLevel;
14227
+ } else {
14228
+ // We are done with the effect chain at this point so let's clear the
14229
+ // nextEffect pointers to assist with GC. If we have passive effects, we'll
14230
+ // clear this in flushPassiveEffects.
14231
+ nextEffect = firstEffect;
14232
+
14233
+ while (nextEffect !== null) {
14234
+ var nextNextEffect = nextEffect.nextEffect;
14235
+ nextEffect.nextEffect = null;
14236
+
14237
+ if (nextEffect.flags & Deletion) {
14238
+ detachFiberAfterEffects(nextEffect);
14239
+ }
14240
+
14241
+ nextEffect = nextNextEffect;
14242
+ }
14251
14243
  } // Read this again, since an effect might have updated it
14252
14244
 
14253
14245
 
@@ -14303,9 +14295,9 @@
14303
14295
 
14304
14296
  if (hasUncaughtError) {
14305
14297
  hasUncaughtError = false;
14306
- var error = firstUncaughtError;
14298
+ var _error3 = firstUncaughtError;
14307
14299
  firstUncaughtError = null;
14308
- throw error;
14300
+ throw _error3;
14309
14301
  }
14310
14302
 
14311
14303
  if ((executionContext & LegacyUnbatchedContext) !== NoContext) {
@@ -14323,255 +14315,151 @@
14323
14315
  return null;
14324
14316
  }
14325
14317
 
14326
- function commitBeforeMutationEffects(firstChild) {
14327
- var fiber = firstChild;
14318
+ function commitBeforeMutationEffects() {
14319
+ while (nextEffect !== null) {
14320
+ var current = nextEffect.alternate;
14328
14321
 
14329
- while (fiber !== null) {
14330
- if (fiber.deletions !== null) {
14331
- commitBeforeMutationEffectsDeletions(fiber.deletions);
14332
- }
14333
-
14334
- if (fiber.child !== null) {
14335
- var primarySubtreeFlags = fiber.subtreeFlags & BeforeMutationMask;
14336
-
14337
- if (primarySubtreeFlags !== NoFlags) {
14338
- commitBeforeMutationEffects(fiber.child);
14322
+ if (!shouldFireAfterActiveInstanceBlur && focusedInstanceHandle !== null) {
14323
+ if ((nextEffect.flags & Deletion) !== NoFlags) {
14324
+ if (doesFiberContain(nextEffect, focusedInstanceHandle)) {
14325
+ shouldFireAfterActiveInstanceBlur = true;
14326
+ }
14327
+ } else {
14328
+ // TODO: Move this out of the hot path using a dedicated effect tag.
14329
+ if (nextEffect.tag === SuspenseComponent && isSuspenseBoundaryBeingHidden(current, nextEffect) && doesFiberContain(nextEffect, focusedInstanceHandle)) {
14330
+ shouldFireAfterActiveInstanceBlur = true;
14331
+ }
14339
14332
  }
14340
14333
  }
14341
14334
 
14342
- {
14343
- setCurrentFiber(fiber);
14344
- invokeGuardedCallback(null, commitBeforeMutationEffectsImpl, null, fiber);
14345
-
14346
- if (hasCaughtError()) {
14347
- var error = clearCaughtError();
14348
- captureCommitPhaseError(fiber, fiber.return, error);
14349
- }
14335
+ var flags = nextEffect.flags;
14350
14336
 
14337
+ if ((flags & Snapshot) !== NoFlags) {
14338
+ setCurrentFiber(nextEffect);
14339
+ commitBeforeMutationLifeCycles(current, nextEffect);
14351
14340
  resetCurrentFiber();
14352
14341
  }
14353
14342
 
14354
- fiber = fiber.sibling;
14355
- }
14356
- }
14357
-
14358
- function commitBeforeMutationEffectsImpl(fiber) {
14359
- var current = fiber.alternate;
14360
- var flags = fiber.flags;
14361
-
14362
- if (!shouldFireAfterActiveInstanceBlur && focusedInstanceHandle !== null) {
14363
- // Check to see if the focused element was inside of a hidden (Suspense) subtree.
14364
- // TODO: Move this out of the hot path using a dedicated effect tag.
14365
- if (fiber.tag === SuspenseComponent && isSuspenseBoundaryBeingHidden(current, fiber) && doesFiberContain(fiber, focusedInstanceHandle)) {
14366
- shouldFireAfterActiveInstanceBlur = true;
14367
- }
14368
- }
14369
-
14370
- if ((flags & Snapshot) !== NoFlags) {
14371
- setCurrentFiber(fiber);
14372
- commitBeforeMutationLifeCycles(current, fiber);
14373
- resetCurrentFiber();
14374
- }
14375
-
14376
- if ((flags & Passive) !== NoFlags) {
14377
- // If there are passive effects, schedule a callback to flush at
14378
- // the earliest opportunity.
14379
- if (!rootDoesHavePassiveEffects) {
14380
- rootDoesHavePassiveEffects = true;
14381
- scheduleCallback(NormalPriority$1, function () {
14382
- flushPassiveEffects();
14383
- return null;
14384
- });
14385
- }
14386
- }
14387
- }
14388
-
14389
- function commitBeforeMutationEffectsDeletions(deletions) {
14390
- for (var i = 0; i < deletions.length; i++) {
14391
- var fiber = deletions[i]; // TODO (effects) It would be nice to avoid calling doesFiberContain()
14392
- // Maybe we can repurpose one of the subtreeFlags positions for this instead?
14393
- // Use it to store which part of the tree the focused instance is in?
14394
- // This assumes we can safely determine that instance during the "render" phase.
14395
-
14396
- if (doesFiberContain(fiber, focusedInstanceHandle)) {
14397
- shouldFireAfterActiveInstanceBlur = true;
14398
- }
14399
- }
14400
- }
14401
-
14402
- function commitMutationEffects(firstChild, root, renderPriorityLevel) {
14403
- var fiber = firstChild;
14404
-
14405
- while (fiber !== null) {
14406
- var deletions = fiber.deletions;
14407
-
14408
- if (deletions !== null) {
14409
- commitMutationEffectsDeletions(deletions, fiber, root, renderPriorityLevel);
14410
- }
14411
-
14412
- if (fiber.child !== null) {
14413
- var mutationFlags = fiber.subtreeFlags & MutationMask;
14414
-
14415
- if (mutationFlags !== NoFlags) {
14416
- commitMutationEffects(fiber.child, root, renderPriorityLevel);
14417
- }
14418
- }
14419
-
14420
- {
14421
- setCurrentFiber(fiber);
14422
- invokeGuardedCallback(null, commitMutationEffectsImpl, null, fiber, root, renderPriorityLevel);
14423
-
14424
- if (hasCaughtError()) {
14425
- var error = clearCaughtError();
14426
- captureCommitPhaseError(fiber, fiber.return, error);
14343
+ if ((flags & Passive) !== NoFlags) {
14344
+ // If there are passive effects, schedule a callback to flush at
14345
+ // the earliest opportunity.
14346
+ if (!rootDoesHavePassiveEffects) {
14347
+ rootDoesHavePassiveEffects = true;
14348
+ scheduleCallback(NormalPriority$1, function () {
14349
+ flushPassiveEffects();
14350
+ return null;
14351
+ });
14427
14352
  }
14428
-
14429
- resetCurrentFiber();
14430
14353
  }
14431
14354
 
14432
- fiber = fiber.sibling;
14355
+ nextEffect = nextEffect.nextEffect;
14433
14356
  }
14434
14357
  }
14435
14358
 
14436
- function commitMutationEffectsImpl(fiber, root, renderPriorityLevel) {
14437
- var flags = fiber.flags;
14438
-
14439
- if (flags & ContentReset) {
14440
- commitResetTextContent(fiber);
14441
- }
14359
+ function commitMutationEffects(root, renderPriorityLevel) {
14360
+ // TODO: Should probably move the bulk of this function to commitWork.
14361
+ while (nextEffect !== null) {
14362
+ setCurrentFiber(nextEffect);
14363
+ var flags = nextEffect.flags;
14442
14364
 
14443
- if (flags & Ref) {
14444
- var current = fiber.alternate;
14445
-
14446
- if (current !== null) {
14447
- commitDetachRef(current);
14365
+ if (flags & ContentReset) {
14366
+ commitResetTextContent(nextEffect);
14448
14367
  }
14449
- } // The following switch statement is only concerned about placement,
14450
- // updates, and deletions. To avoid needing to add a case for every possible
14451
- // bitmap value, we remove the secondary effects from the effect tag and
14452
- // switch on that value.
14453
14368
 
14369
+ if (flags & Ref) {
14370
+ var current = nextEffect.alternate;
14454
14371
 
14455
- var primaryFlags = flags & (Placement | Update | Hydrating);
14372
+ if (current !== null) {
14373
+ commitDetachRef(current);
14374
+ }
14375
+ } // The following switch statement is only concerned about placement,
14376
+ // updates, and deletions. To avoid needing to add a case for every possible
14377
+ // bitmap value, we remove the secondary effects from the effect tag and
14378
+ // switch on that value.
14456
14379
 
14457
- switch (primaryFlags) {
14458
- case Placement:
14459
- {
14460
- commitPlacement(fiber); // Clear the "placement" from effect tag so that we know that this is
14461
- // inserted, before any life-cycles like componentDidMount gets called.
14462
- // TODO: findDOMNode doesn't rely on this any more but isMounted does
14463
- // and isMounted is deprecated anyway so we should be able to kill this.
14464
14380
 
14465
- fiber.flags &= ~Placement;
14466
- break;
14467
- }
14381
+ var primaryFlags = flags & (Placement | Update | Deletion | Hydrating);
14468
14382
 
14469
- case PlacementAndUpdate:
14470
- {
14471
- // Placement
14472
- commitPlacement(fiber); // Clear the "placement" from effect tag so that we know that this is
14473
- // inserted, before any life-cycles like componentDidMount gets called.
14383
+ switch (primaryFlags) {
14384
+ case Placement:
14385
+ {
14386
+ commitPlacement(nextEffect); // Clear the "placement" from effect tag so that we know that this is
14387
+ // inserted, before any life-cycles like componentDidMount gets called.
14388
+ // TODO: findDOMNode doesn't rely on this any more but isMounted does
14389
+ // and isMounted is deprecated anyway so we should be able to kill this.
14474
14390
 
14475
- fiber.flags &= ~Placement; // Update
14391
+ nextEffect.flags &= ~Placement;
14392
+ break;
14393
+ }
14476
14394
 
14477
- var _current = fiber.alternate;
14478
- commitWork(_current, fiber);
14479
- break;
14480
- }
14395
+ case PlacementAndUpdate:
14396
+ {
14397
+ // Placement
14398
+ commitPlacement(nextEffect); // Clear the "placement" from effect tag so that we know that this is
14399
+ // inserted, before any life-cycles like componentDidMount gets called.
14481
14400
 
14482
- case Hydrating:
14483
- {
14484
- fiber.flags &= ~Hydrating;
14485
- break;
14486
- }
14401
+ nextEffect.flags &= ~Placement; // Update
14487
14402
 
14488
- case HydratingAndUpdate:
14489
- {
14490
- fiber.flags &= ~Hydrating; // Update
14403
+ var _current = nextEffect.alternate;
14404
+ commitWork(_current, nextEffect);
14405
+ break;
14406
+ }
14491
14407
 
14492
- var _current2 = fiber.alternate;
14493
- commitWork(_current2, fiber);
14494
- break;
14495
- }
14408
+ case Hydrating:
14409
+ {
14410
+ nextEffect.flags &= ~Hydrating;
14411
+ break;
14412
+ }
14496
14413
 
14497
- case Update:
14498
- {
14499
- var _current3 = fiber.alternate;
14500
- commitWork(_current3, fiber);
14501
- break;
14502
- }
14503
- }
14504
- }
14414
+ case HydratingAndUpdate:
14415
+ {
14416
+ nextEffect.flags &= ~Hydrating; // Update
14505
14417
 
14506
- function commitMutationEffectsDeletions(deletions, nearestMountedAncestor, root, renderPriorityLevel) {
14507
- for (var i = 0; i < deletions.length; i++) {
14508
- var childToDelete = deletions[i];
14418
+ var _current2 = nextEffect.alternate;
14419
+ commitWork(_current2, nextEffect);
14420
+ break;
14421
+ }
14509
14422
 
14510
- {
14511
- invokeGuardedCallback(null, commitDeletion, null, root, childToDelete, nearestMountedAncestor, renderPriorityLevel);
14423
+ case Update:
14424
+ {
14425
+ var _current3 = nextEffect.alternate;
14426
+ commitWork(_current3, nextEffect);
14427
+ break;
14428
+ }
14512
14429
 
14513
- if (hasCaughtError()) {
14514
- var error = clearCaughtError();
14515
- captureCommitPhaseError(childToDelete, nearestMountedAncestor, error);
14516
- }
14430
+ case Deletion:
14431
+ {
14432
+ commitDeletion(root, nextEffect);
14433
+ break;
14434
+ }
14517
14435
  }
14518
- }
14519
- }
14520
14436
 
14521
- function schedulePassiveEffectCallback() {
14522
- if (!rootDoesHavePassiveEffects) {
14523
- rootDoesHavePassiveEffects = true;
14524
- scheduleCallback(NormalPriority$1, function () {
14525
- flushPassiveEffects();
14526
- return null;
14527
- });
14437
+ resetCurrentFiber();
14438
+ nextEffect = nextEffect.nextEffect;
14528
14439
  }
14529
14440
  }
14530
14441
 
14531
- function commitLayoutEffects(firstChild, root, committedLanes) {
14532
- var fiber = firstChild;
14442
+ function commitLayoutEffects(root, committedLanes) {
14533
14443
 
14534
- while (fiber !== null) {
14535
- if (fiber.child !== null) {
14536
- var primarySubtreeFlags = fiber.subtreeFlags & LayoutMask;
14537
14444
 
14538
- if (primarySubtreeFlags !== NoFlags) {
14539
- commitLayoutEffects(fiber.child, root, committedLanes);
14540
- }
14445
+ while (nextEffect !== null) {
14446
+ setCurrentFiber(nextEffect);
14447
+ var flags = nextEffect.flags;
14448
+
14449
+ if (flags & (Update | Callback)) {
14450
+ var current = nextEffect.alternate;
14451
+ commitLifeCycles(root, current, nextEffect);
14541
14452
  }
14542
14453
 
14543
14454
  {
14544
- setCurrentFiber(fiber);
14545
- invokeGuardedCallback(null, commitLayoutEffectsImpl, null, fiber, root, committedLanes);
14546
-
14547
- if (hasCaughtError()) {
14548
- var error = clearCaughtError();
14549
- captureCommitPhaseError(fiber, fiber.return, error);
14455
+ if (flags & Ref) {
14456
+ commitAttachRef(nextEffect);
14550
14457
  }
14551
-
14552
- resetCurrentFiber();
14553
14458
  }
14554
14459
 
14555
- fiber = fiber.sibling;
14556
- }
14557
- }
14558
-
14559
- function commitLayoutEffectsImpl(fiber, root, committedLanes) {
14560
- var flags = fiber.flags;
14561
- setCurrentFiber(fiber);
14562
-
14563
- if (flags & (Update | Callback)) {
14564
- var current = fiber.alternate;
14565
- commitLifeCycles(root, current, fiber);
14566
- }
14567
-
14568
- {
14569
- if (flags & Ref) {
14570
- commitAttachRef(fiber);
14571
- }
14460
+ resetCurrentFiber();
14461
+ nextEffect = nextEffect.nextEffect;
14572
14462
  }
14573
-
14574
- resetCurrentFiber();
14575
14463
  }
14576
14464
 
14577
14465
  function flushPassiveEffects() {
@@ -14587,87 +14475,41 @@
14587
14475
 
14588
14476
  return false;
14589
14477
  }
14478
+ function enqueuePendingPassiveHookEffectMount(fiber, effect) {
14479
+ pendingPassiveHookEffectsMount.push(effect, fiber);
14590
14480
 
14591
- function flushPassiveMountEffects(root, firstChild) {
14592
- var fiber = firstChild;
14593
-
14594
- while (fiber !== null) {
14595
- var primarySubtreeFlags = fiber.subtreeFlags & PassiveMask;
14596
-
14597
- if (fiber.child !== null && primarySubtreeFlags !== NoFlags) {
14598
- flushPassiveMountEffects(root, fiber.child);
14599
- }
14600
-
14601
- if ((fiber.flags & Passive) !== NoFlags) {
14602
- setCurrentFiber(fiber);
14603
- commitPassiveLifeCycles(root, fiber);
14604
- resetCurrentFiber();
14605
- }
14606
-
14607
- fiber = fiber.sibling;
14481
+ if (!rootDoesHavePassiveEffects) {
14482
+ rootDoesHavePassiveEffects = true;
14483
+ scheduleCallback(NormalPriority$1, function () {
14484
+ flushPassiveEffects();
14485
+ return null;
14486
+ });
14608
14487
  }
14609
14488
  }
14489
+ function enqueuePendingPassiveHookEffectUnmount(fiber, effect) {
14490
+ pendingPassiveHookEffectsUnmount.push(effect, fiber);
14610
14491
 
14611
- function flushPassiveUnmountEffects(firstChild) {
14612
- var fiber = firstChild;
14613
-
14614
- while (fiber !== null) {
14615
- var deletions = fiber.deletions;
14616
-
14617
- if (deletions !== null) {
14618
- for (var i = 0; i < deletions.length; i++) {
14619
- var fiberToDelete = deletions[i];
14620
- flushPassiveUnmountEffectsInsideOfDeletedTree(fiberToDelete, fiber); // Now that passive effects have been processed, it's safe to detach lingering pointers.
14621
-
14622
- detachFiberAfterEffects(fiberToDelete);
14623
- }
14624
- }
14625
-
14626
- var child = fiber.child;
14627
-
14628
- if (child !== null) {
14629
- // If any children have passive effects then traverse the subtree.
14630
- // Note that this requires checking subtreeFlags of the current Fiber,
14631
- // rather than the subtreeFlags/effectsTag of the first child,
14632
- // since that would not cover passive effects in siblings.
14633
- var passiveFlags = fiber.subtreeFlags & PassiveMask;
14634
-
14635
- if (passiveFlags !== NoFlags) {
14636
- flushPassiveUnmountEffects(child);
14637
- }
14638
- }
14639
-
14640
- var primaryFlags = fiber.flags & Passive;
14492
+ {
14493
+ fiber.flags |= PassiveUnmountPendingDev;
14494
+ var alternate = fiber.alternate;
14641
14495
 
14642
- if (primaryFlags !== NoFlags) {
14643
- setCurrentFiber(fiber);
14644
- commitPassiveWork(fiber);
14645
- resetCurrentFiber();
14496
+ if (alternate !== null) {
14497
+ alternate.flags |= PassiveUnmountPendingDev;
14646
14498
  }
14647
-
14648
- fiber = fiber.sibling;
14649
14499
  }
14650
- }
14651
-
14652
- function flushPassiveUnmountEffectsInsideOfDeletedTree(fiberToDelete, nearestMountedAncestor) {
14653
- if ((fiberToDelete.subtreeFlags & PassiveStatic) !== NoFlags) {
14654
- // If any children have passive effects then traverse the subtree.
14655
- // Note that this requires checking subtreeFlags of the current Fiber,
14656
- // rather than the subtreeFlags/effectsTag of the first child,
14657
- // since that would not cover passive effects in siblings.
14658
- var child = fiberToDelete.child;
14659
14500
 
14660
- while (child !== null) {
14661
- flushPassiveUnmountEffectsInsideOfDeletedTree(child, nearestMountedAncestor);
14662
- child = child.sibling;
14663
- }
14501
+ if (!rootDoesHavePassiveEffects) {
14502
+ rootDoesHavePassiveEffects = true;
14503
+ scheduleCallback(NormalPriority$1, function () {
14504
+ flushPassiveEffects();
14505
+ return null;
14506
+ });
14664
14507
  }
14508
+ }
14665
14509
 
14666
- if ((fiberToDelete.flags & PassiveStatic) !== NoFlags) {
14667
- setCurrentFiber(fiberToDelete);
14668
- commitPassiveUnmount(fiberToDelete, nearestMountedAncestor);
14669
- resetCurrentFiber();
14670
- }
14510
+ function invokePassiveEffectCreate(effect) {
14511
+ var create = effect.create;
14512
+ effect.destroy = create();
14671
14513
  }
14672
14514
 
14673
14515
  function flushPassiveEffectsImpl() {
@@ -14698,9 +14540,97 @@
14698
14540
  // e.g. a destroy function in one component may unintentionally override a ref
14699
14541
  // value set by a create function in another component.
14700
14542
  // Layout effects have the same constraint.
14543
+ // First pass: Destroy stale passive effects.
14544
+
14545
+ var unmountEffects = pendingPassiveHookEffectsUnmount;
14546
+ pendingPassiveHookEffectsUnmount = [];
14547
+
14548
+ for (var i = 0; i < unmountEffects.length; i += 2) {
14549
+ var _effect = unmountEffects[i];
14550
+ var fiber = unmountEffects[i + 1];
14551
+ var destroy = _effect.destroy;
14552
+ _effect.destroy = undefined;
14553
+
14554
+ {
14555
+ fiber.flags &= ~PassiveUnmountPendingDev;
14556
+ var alternate = fiber.alternate;
14557
+
14558
+ if (alternate !== null) {
14559
+ alternate.flags &= ~PassiveUnmountPendingDev;
14560
+ }
14561
+ }
14562
+
14563
+ if (typeof destroy === 'function') {
14564
+ {
14565
+ setCurrentFiber(fiber);
14566
+
14567
+ {
14568
+ invokeGuardedCallback(null, destroy, null);
14569
+ }
14570
+
14571
+ if (hasCaughtError()) {
14572
+ if (!(fiber !== null)) {
14573
+ {
14574
+ throw Error( "Should be working on an effect." );
14575
+ }
14576
+ }
14577
+
14578
+ var error = clearCaughtError();
14579
+ captureCommitPhaseError(fiber, error);
14580
+ }
14581
+
14582
+ resetCurrentFiber();
14583
+ }
14584
+ }
14585
+ } // Second pass: Create new passive effects.
14586
+
14587
+
14588
+ var mountEffects = pendingPassiveHookEffectsMount;
14589
+ pendingPassiveHookEffectsMount = [];
14590
+
14591
+ for (var _i = 0; _i < mountEffects.length; _i += 2) {
14592
+ var _effect2 = mountEffects[_i];
14593
+ var _fiber = mountEffects[_i + 1];
14594
+
14595
+ {
14596
+ setCurrentFiber(_fiber);
14597
+
14598
+ {
14599
+ invokeGuardedCallback(null, invokePassiveEffectCreate, null, _effect2);
14600
+ }
14601
+
14602
+ if (hasCaughtError()) {
14603
+ if (!(_fiber !== null)) {
14604
+ {
14605
+ throw Error( "Should be working on an effect." );
14606
+ }
14607
+ }
14701
14608
 
14702
- flushPassiveUnmountEffects(root.current);
14703
- flushPassiveMountEffects(root, root.current);
14609
+ var _error4 = clearCaughtError();
14610
+
14611
+ captureCommitPhaseError(_fiber, _error4);
14612
+ }
14613
+
14614
+ resetCurrentFiber();
14615
+ }
14616
+ } // Note: This currently assumes there are no passive effects on the root fiber
14617
+ // because the root is not part of its own effect list.
14618
+ // This could change in the future.
14619
+
14620
+
14621
+ var effect = root.current.firstEffect;
14622
+
14623
+ while (effect !== null) {
14624
+ var nextNextEffect = effect.nextEffect; // Remove nextEffect pointer to assist GC
14625
+
14626
+ effect.nextEffect = null;
14627
+
14628
+ if (effect.flags & Deletion) {
14629
+ detachFiberAfterEffects(effect);
14630
+ }
14631
+
14632
+ effect = nextNextEffect;
14633
+ }
14704
14634
 
14705
14635
  {
14706
14636
  popInteractions(prevInteractions);
@@ -14753,7 +14683,7 @@
14753
14683
  }
14754
14684
  }
14755
14685
 
14756
- function captureCommitPhaseError(sourceFiber, nearestMountedAncestor, error) {
14686
+ function captureCommitPhaseError(sourceFiber, error) {
14757
14687
  if (sourceFiber.tag === HostRoot) {
14758
14688
  // Error was thrown at the root. There is no parent, so the root
14759
14689
  // itself should capture it.
@@ -14761,11 +14691,7 @@
14761
14691
  return;
14762
14692
  }
14763
14693
 
14764
- var fiber = null;
14765
-
14766
- {
14767
- fiber = sourceFiber.return;
14768
- }
14694
+ var fiber = sourceFiber.return;
14769
14695
 
14770
14696
  while (fiber !== null) {
14771
14697
  if (fiber.tag === HostRoot) {
@@ -14786,6 +14712,20 @@
14786
14712
  markRootUpdated(root, SyncLane, eventTime);
14787
14713
  ensureRootIsScheduled(root, eventTime);
14788
14714
  schedulePendingInteractions(root, SyncLane);
14715
+ } else {
14716
+ // This component has already been unmounted.
14717
+ // We can't schedule any follow up work for the root because the fiber is already unmounted,
14718
+ // but we can still call the log-only boundary so the error isn't swallowed.
14719
+ //
14720
+ // TODO This is only a temporary bandaid for the old reconciler fork.
14721
+ // We can delete this special case once the new fork is merged.
14722
+ if (typeof instance.componentDidCatch === 'function' && !isAlreadyFailedLegacyErrorBoundary(instance)) {
14723
+ try {
14724
+ instance.componentDidCatch(error, errorInfo);
14725
+ } catch (errorToIgnore) {// TODO Ignore this error? Rethrow it?
14726
+ // This is kind of an edge case.
14727
+ }
14728
+ }
14789
14729
  }
14790
14730
 
14791
14731
  return;
@@ -14968,29 +14908,12 @@
14968
14908
  if (tag !== HostRoot && tag !== ClassComponent && tag !== FunctionComponent && tag !== ForwardRef && tag !== MemoComponent && tag !== SimpleMemoComponent && tag !== Block) {
14969
14909
  // Only warn for user-defined components, not internal ones like Suspense.
14970
14910
  return;
14971
- }
14972
-
14973
- if ((fiber.flags & PassiveStatic) !== NoFlags) {
14974
- var updateQueue = fiber.updateQueue;
14911
+ } // If there are pending passive effects unmounts for this Fiber,
14912
+ // we can assume that they would have prevented this update.
14975
14913
 
14976
- if (updateQueue !== null) {
14977
- var lastEffect = updateQueue.lastEffect;
14978
14914
 
14979
- if (lastEffect !== null) {
14980
- var firstEffect = lastEffect.next;
14981
- var effect = firstEffect;
14982
-
14983
- do {
14984
- if (effect.destroy !== undefined) {
14985
- if ((effect.tag & Passive$1) !== NoFlags$1) {
14986
- return;
14987
- }
14988
- }
14989
-
14990
- effect = effect.next;
14991
- } while (effect !== firstEffect);
14992
- }
14993
- }
14915
+ if ((fiber.flags & PassiveUnmountPendingDev) !== NoFlags) {
14916
+ return;
14994
14917
  } // We show the whole stack but dedupe on the top component's name because
14995
14918
  // the problematic code almost always lies inside that component.
14996
14919
 
@@ -15450,21 +15373,8 @@
15450
15373
  }
15451
15374
 
15452
15375
  function detachFiberAfterEffects(fiber) {
15453
- // Null out fields to improve GC for references that may be lingering (e.g. DevTools).
15454
- // Note that we already cleared the return pointer in detachFiberMutation().
15455
- fiber.child = null;
15456
- fiber.deletions = null;
15457
- fiber.dependencies = null;
15458
- fiber.memoizedProps = null;
15459
- fiber.memoizedState = null;
15460
- fiber.pendingProps = null;
15461
15376
  fiber.sibling = null;
15462
15377
  fiber.stateNode = null;
15463
- fiber.updateQueue = null;
15464
-
15465
- {
15466
- fiber._debugOwner = null;
15467
- }
15468
15378
  }
15469
15379
 
15470
15380
  var resolveFamily = null; // $FlowFixMe Flow gets confused by a WeakSet feature check below.
@@ -15904,8 +15814,9 @@
15904
15814
  this.mode = mode; // Effects
15905
15815
 
15906
15816
  this.flags = NoFlags;
15907
- this.subtreeFlags = NoFlags;
15908
- this.deletions = null;
15817
+ this.nextEffect = null;
15818
+ this.firstEffect = null;
15819
+ this.lastEffect = null;
15909
15820
  this.lanes = NoLanes;
15910
15821
  this.childLanes = NoLanes;
15911
15822
  this.alternate = null;
@@ -16022,9 +15933,13 @@
16022
15933
  workInProgress.pendingProps = pendingProps; // Needed because Blocks store data on type.
16023
15934
 
16024
15935
  workInProgress.type = current.type; // We already have an alternate.
15936
+ // Reset the effect tag.
15937
+
15938
+ workInProgress.flags = NoFlags; // The effect list is no longer valid.
16025
15939
 
16026
- workInProgress.subtreeFlags = NoFlags;
16027
- workInProgress.deletions = null;
15940
+ workInProgress.nextEffect = null;
15941
+ workInProgress.firstEffect = null;
15942
+ workInProgress.lastEffect = null;
16028
15943
 
16029
15944
  {
16030
15945
  // We intentionally reset, rather than copy, actualDuration & actualStartTime.
@@ -16034,11 +15949,8 @@
16034
15949
  workInProgress.actualDuration = 0;
16035
15950
  workInProgress.actualStartTime = -1;
16036
15951
  }
16037
- } // Reset all effects except static ones.
16038
- // Static effects are not specific to a render.
16039
-
15952
+ }
16040
15953
 
16041
- workInProgress.flags = current.flags & StaticMask;
16042
15954
  workInProgress.childLanes = current.childLanes;
16043
15955
  workInProgress.lanes = current.lanes;
16044
15956
  workInProgress.child = current.child;
@@ -16094,7 +16006,11 @@
16094
16006
  // avoid doing another reconciliation.
16095
16007
  // Reset the effect tag but keep any Placement tags, since that's something
16096
16008
  // that child fiber is setting, not the reconciliation.
16097
- workInProgress.flags &= Placement;
16009
+ workInProgress.flags &= Placement; // The effect list is no longer valid.
16010
+
16011
+ workInProgress.nextEffect = null;
16012
+ workInProgress.firstEffect = null;
16013
+ workInProgress.lastEffect = null;
16098
16014
  var current = workInProgress.alternate;
16099
16015
 
16100
16016
  if (current === null) {
@@ -16102,7 +16018,6 @@
16102
16018
  workInProgress.childLanes = NoLanes;
16103
16019
  workInProgress.lanes = renderLanes;
16104
16020
  workInProgress.child = null;
16105
- workInProgress.subtreeFlags = NoFlags;
16106
16021
  workInProgress.memoizedProps = null;
16107
16022
  workInProgress.memoizedState = null;
16108
16023
  workInProgress.updateQueue = null;
@@ -16120,8 +16035,6 @@
16120
16035
  workInProgress.childLanes = current.childLanes;
16121
16036
  workInProgress.lanes = current.lanes;
16122
16037
  workInProgress.child = current.child;
16123
- workInProgress.subtreeFlags = current.subtreeFlags;
16124
- workInProgress.deletions = null;
16125
16038
  workInProgress.memoizedProps = current.memoizedProps;
16126
16039
  workInProgress.memoizedState = current.memoizedState;
16127
16040
  workInProgress.updateQueue = current.updateQueue; // Needed because Blocks store data on type.