@@ -20,10 +20,14 @@ import type {FiberRoot} from './ReactInternalTypes';
20
20
import type { Lanes } from './ReactFiberLane' ;
21
21
import type { SuspenseState } from './ReactFiberSuspenseComponent.new' ;
22
22
import type { UpdateQueue } from './ReactUpdateQueue.new' ;
23
- import type { FunctionComponentUpdateQueue } from './ReactFiberHooks.new' ;
23
+ import type {
24
+ Effect as HookEffect ,
25
+ FunctionComponentUpdateQueue ,
26
+ } from './ReactFiberHooks.new' ;
24
27
import type { Wakeable } from 'shared/ReactTypes' ;
25
28
import type { ReactPriorityLevel } from './ReactInternalTypes' ;
26
29
import type { OffscreenState } from './ReactFiberOffscreenComponent' ;
30
+ import type { HookEffectTag } from './ReactHookEffectTags' ;
27
31
28
32
import { unstable_wrap as Schedule_tracing_wrap } from 'scheduler/tracing' ;
29
33
import {
@@ -77,6 +81,8 @@ import {
77
81
getCommitTime ,
78
82
recordLayoutEffectDuration ,
79
83
startLayoutEffectTimer ,
84
+ recordPassiveEffectDuration ,
85
+ startPassiveEffectTimer ,
80
86
} from './ReactProfilerTimer.new' ;
81
87
import { ProfileMode } from './ReactTypeOfMode' ;
82
88
import { commitUpdateQueue } from './ReactUpdateQueue.new' ;
@@ -121,6 +127,7 @@ import {
121
127
NoEffect as NoHookEffect ,
122
128
HasEffect as HookHasEffect ,
123
129
Layout as HookLayout ,
130
+ Passive as HookPassive ,
124
131
} from './ReactHookEffectTags' ;
125
132
import { didWarnAboutReassigningProps } from './ReactFiberBeginWork.new' ;
126
133
import {
@@ -308,7 +315,7 @@ function commitBeforeMutationLifeCycles(
308
315
) ;
309
316
}
310
317
311
- function commitHookEffectListUnmount ( tag : number , finishedWork : Fiber ) {
318
+ function commitHookEffectListUnmount ( tag : HookEffectTag , finishedWork : Fiber ) {
312
319
const updateQueue : FunctionComponentUpdateQueue | null = ( finishedWork . updateQueue : any ) ;
313
320
const lastEffect = updateQueue !== null ? updateQueue . lastEffect : null ;
314
321
if ( lastEffect !== null ) {
@@ -328,7 +335,43 @@ function commitHookEffectListUnmount(tag: number, finishedWork: Fiber) {
328
335
}
329
336
}
330
337
331
- function commitHookEffectListMount ( tag : number , finishedWork : Fiber ) {
338
+ // TODO: Remove this duplication.
339
+ function commitHookEffectListUnmount2 (
340
+ // Tags to check for when deciding whether to unmount. e.g. to skip over
341
+ // layout effects
342
+ hookEffectTag : HookEffectTag ,
343
+ fiber : Fiber ,
344
+ ) : void {
345
+ const updateQueue : FunctionComponentUpdateQueue | null = ( fiber . updateQueue : any ) ;
346
+ const lastEffect = updateQueue !== null ? updateQueue . lastEffect : null ;
347
+ if ( lastEffect !== null ) {
348
+ const firstEffect = lastEffect . next ;
349
+ let effect = firstEffect ;
350
+ do {
351
+ const { next , tag } = effect ;
352
+ if ( ( tag & hookEffectTag ) === hookEffectTag ) {
353
+ const destroy = effect . destroy ;
354
+ if ( destroy !== undefined ) {
355
+ effect . destroy = undefined ;
356
+ if (
357
+ enableProfilerTimer &&
358
+ enableProfilerCommitHooks &&
359
+ fiber . mode & ProfileMode
360
+ ) {
361
+ startPassiveEffectTimer ( ) ;
362
+ safelyCallDestroy ( fiber , destroy ) ;
363
+ recordPassiveEffectDuration ( fiber ) ;
364
+ } else {
365
+ safelyCallDestroy ( fiber , destroy ) ;
366
+ }
367
+ }
368
+ }
369
+ effect = next ;
370
+ } while ( effect !== firstEffect ) ;
371
+ }
372
+ }
373
+
374
+ function commitHookEffectListMount ( tag : HookEffectTag , finishedWork : Fiber ) {
332
375
const updateQueue : FunctionComponentUpdateQueue | null = ( finishedWork . updateQueue : any ) ;
333
376
const lastEffect = updateQueue !== null ? updateQueue . lastEffect : null ;
334
377
if ( lastEffect !== null ) {
@@ -378,6 +421,83 @@ function commitHookEffectListMount(tag: number, finishedWork: Fiber) {
378
421
}
379
422
}
380
423
424
+ function invokePassiveEffectCreate ( effect : HookEffect ) : void {
425
+ const create = effect . create ;
426
+ effect . destroy = create ( ) ;
427
+ }
428
+
429
+ // TODO: Remove this duplication.
430
+ function commitHookEffectListMount2 ( fiber : Fiber ) : void {
431
+ const updateQueue : FunctionComponentUpdateQueue | null = ( fiber . updateQueue : any ) ;
432
+ const lastEffect = updateQueue !== null ? updateQueue . lastEffect : null ;
433
+ if ( lastEffect !== null ) {
434
+ const firstEffect = lastEffect . next ;
435
+ let effect = firstEffect ;
436
+ do {
437
+ const { next , tag } = effect ;
438
+
439
+ if (
440
+ ( tag & HookPassive ) !== NoHookEffect &&
441
+ ( tag & HookHasEffect ) !== NoHookEffect
442
+ ) {
443
+ if ( __DEV__ ) {
444
+ if (
445
+ enableProfilerTimer &&
446
+ enableProfilerCommitHooks &&
447
+ fiber . mode & ProfileMode
448
+ ) {
449
+ startPassiveEffectTimer ( ) ;
450
+ invokeGuardedCallback (
451
+ null ,
452
+ invokePassiveEffectCreate ,
453
+ null ,
454
+ effect ,
455
+ ) ;
456
+ recordPassiveEffectDuration ( fiber ) ;
457
+ } else {
458
+ invokeGuardedCallback (
459
+ null ,
460
+ invokePassiveEffectCreate ,
461
+ null ,
462
+ effect ,
463
+ ) ;
464
+ }
465
+ if ( hasCaughtError ( ) ) {
466
+ invariant ( fiber !== null , 'Should be working on an effect.' ) ;
467
+ const error = clearCaughtError ( ) ;
468
+ captureCommitPhaseError ( fiber , error ) ;
469
+ }
470
+ } else {
471
+ try {
472
+ const create = effect . create ;
473
+ if (
474
+ enableProfilerTimer &&
475
+ enableProfilerCommitHooks &&
476
+ fiber . mode & ProfileMode
477
+ ) {
478
+ try {
479
+ startPassiveEffectTimer ( ) ;
480
+ effect . destroy = create ( ) ;
481
+ } finally {
482
+ recordPassiveEffectDuration ( fiber ) ;
483
+ }
484
+ } else {
485
+ effect . destroy = create ( ) ;
486
+ }
487
+ // TODO: This is missing the warning that exists in commitHookEffectListMount.
488
+ // The warning refers to useEffect but only applies to useLayoutEffect.
489
+ } catch ( error ) {
490
+ invariant ( fiber !== null , 'Should be working on an effect.' ) ;
491
+ captureCommitPhaseError ( fiber , error ) ;
492
+ }
493
+ }
494
+ }
495
+
496
+ effect = next ;
497
+ } while ( effect !== firstEffect ) ;
498
+ }
499
+ }
500
+
381
501
export function commitPassiveEffectDurations (
382
502
finishedRoot : FiberRoot ,
383
503
finishedWork : Fiber ,
@@ -1709,13 +1829,45 @@ export function isSuspenseBoundaryBeingHidden(
1709
1829
return false ;
1710
1830
}
1711
1831
1712
- function commitResetTextContent ( current : Fiber ) {
1832
+ function commitResetTextContent ( current : Fiber ) : void {
1713
1833
if ( ! supportsMutation ) {
1714
1834
return ;
1715
1835
}
1716
1836
resetTextContent ( current . stateNode ) ;
1717
1837
}
1718
1838
1839
+ function commitPassiveWork ( finishedWork : Fiber ) : void {
1840
+ switch ( finishedWork . tag ) {
1841
+ case FunctionComponent :
1842
+ case ForwardRef :
1843
+ case SimpleMemoComponent :
1844
+ case Block : {
1845
+ commitHookEffectListUnmount2 ( HookPassive | HookHasEffect , finishedWork ) ;
1846
+ }
1847
+ }
1848
+ }
1849
+
1850
+ function commitPassiveUnmount ( current : Fiber ) : void {
1851
+ switch ( current . tag ) {
1852
+ case FunctionComponent :
1853
+ case ForwardRef :
1854
+ case SimpleMemoComponent :
1855
+ case Block :
1856
+ commitHookEffectListUnmount2 ( HookPassive , current ) ;
1857
+ }
1858
+ }
1859
+
1860
+ function commitPassiveLifeCycles ( finishedWork : Fiber ) : void {
1861
+ switch ( finishedWork . tag ) {
1862
+ case FunctionComponent :
1863
+ case ForwardRef :
1864
+ case SimpleMemoComponent :
1865
+ case Block : {
1866
+ commitHookEffectListMount2 ( finishedWork ) ;
1867
+ }
1868
+ }
1869
+ }
1870
+
1719
1871
export {
1720
1872
commitBeforeMutationLifeCycles ,
1721
1873
commitResetTextContent ,
@@ -1725,4 +1877,7 @@ export {
1725
1877
commitLifeCycles ,
1726
1878
commitAttachRef ,
1727
1879
commitDetachRef ,
1880
+ commitPassiveUnmount ,
1881
+ commitPassiveWork ,
1882
+ commitPassiveLifeCycles ,
1728
1883
} ;
0 commit comments