@@ -21,6 +21,7 @@ import type {
21
21
Thenable ,
22
22
ReactFormState ,
23
23
ReactComponentInfo ,
24
+ ReactDebugInfo ,
24
25
} from 'shared/ReactTypes' ;
25
26
import type { LazyComponent as LazyComponentType } from 'react/src/ReactLazy' ;
26
27
import type {
@@ -882,6 +883,41 @@ function createClassComponentStack(
882
883
type,
883
884
} ;
884
885
}
886
+ function createServerComponentStack (
887
+ task : Task ,
888
+ debugInfo : void | null | ReactDebugInfo ,
889
+ ) : null | ComponentStackNode {
890
+ // Build a Server Component parent stack from the debugInfo.
891
+ if ( __DEV__ ) {
892
+ let node = task . componentStack ;
893
+ if ( debugInfo != null ) {
894
+ const stack : ReactDebugInfo = debugInfo ;
895
+ for ( let i = 0 ; i < stack . length ; i ++ ) {
896
+ const componentInfo : ReactComponentInfo = ( stack [ i ] : any ) ;
897
+ if ( typeof componentInfo . name !== 'string' ) {
898
+ continue ;
899
+ }
900
+ let name = componentInfo . name ;
901
+ const env = componentInfo . env ;
902
+ if ( env ) {
903
+ name += ' (' + env + ')' ;
904
+ }
905
+ node = {
906
+ tag : 3 ,
907
+ parent : node ,
908
+ type : name ,
909
+ owner : componentInfo . owner ,
910
+ stack : componentInfo . stack ,
911
+ } ;
912
+ }
913
+ }
914
+ return node ;
915
+ }
916
+ // eslint-disable-next-line react-internal/prod-error-codes
917
+ throw new Error (
918
+ 'createServerComponentStack should never be called in production. This is a bug in React.' ,
919
+ ) ;
920
+ }
885
921
886
922
function createComponentStackFromType (
887
923
task : Task ,
@@ -1978,6 +2014,7 @@ function renderLazyComponent(
1978
2014
stack : null | Error , // DEV only
1979
2015
) : void {
1980
2016
const previousComponentStack = task . componentStack ;
2017
+ // TODO: Do we really need this stack frame? We don't on the client.
1981
2018
task . componentStack = createBuiltInComponentStack ( task , 'Lazy' , owner , stack ) ;
1982
2019
let Component ;
1983
2020
if ( __DEV__ ) {
@@ -2529,72 +2566,90 @@ function renderNodeDestructive(
2529
2566
const owner = __DEV__ ? element . _owner : null ;
2530
2567
const stack = __DEV__ && enableOwnerStacks ? element . _debugStack : null ;
2531
2568
2569
+ const previousComponentStack = task . componentStack ;
2570
+ if ( __DEV__ ) {
2571
+ task . componentStack = createServerComponentStack (
2572
+ task ,
2573
+ element . _debugInfo ,
2574
+ ) ;
2575
+ }
2576
+
2532
2577
const name = getComponentNameFromType ( type ) ;
2533
2578
const keyOrIndex =
2534
2579
key == null ? ( childIndex === - 1 ? 0 : childIndex ) : key ;
2535
2580
const keyPath = [ task . keyPath , name , keyOrIndex ] ;
2536
2581
if ( task . replay !== null ) {
2537
- if ( __DEV__ && enableOwnerStacks ) {
2538
- const debugTask : null | ConsoleTask = element . _debugTask ;
2539
- if ( debugTask ) {
2540
- debugTask . run (
2541
- replayElement . bind (
2542
- null ,
2543
- request ,
2544
- task ,
2545
- keyPath ,
2546
- name ,
2547
- keyOrIndex ,
2548
- childIndex ,
2549
- type ,
2550
- props ,
2551
- ref ,
2552
- task . replay ,
2553
- owner ,
2554
- stack ,
2555
- ) ,
2556
- ) ;
2557
- return ;
2558
- }
2582
+ const debugTask : null | ConsoleTask =
2583
+ __DEV__ && enableOwnerStacks ? element . _debugTask : null ;
2584
+ if ( debugTask ) {
2585
+ debugTask . run (
2586
+ replayElement . bind (
2587
+ null ,
2588
+ request ,
2589
+ task ,
2590
+ keyPath ,
2591
+ name ,
2592
+ keyOrIndex ,
2593
+ childIndex ,
2594
+ type ,
2595
+ props ,
2596
+ ref ,
2597
+ task . replay ,
2598
+ owner ,
2599
+ stack ,
2600
+ ) ,
2601
+ ) ;
2602
+ } else {
2603
+ replayElement (
2604
+ request ,
2605
+ task ,
2606
+ keyPath ,
2607
+ name ,
2608
+ keyOrIndex ,
2609
+ childIndex ,
2610
+ type ,
2611
+ props ,
2612
+ ref ,
2613
+ task . replay ,
2614
+ owner ,
2615
+ stack ,
2616
+ ) ;
2559
2617
}
2560
- replayElement (
2561
- request ,
2562
- task ,
2563
- keyPath ,
2564
- name ,
2565
- keyOrIndex ,
2566
- childIndex ,
2567
- type ,
2568
- props ,
2569
- ref ,
2570
- task . replay ,
2571
- owner ,
2572
- stack ,
2573
- ) ;
2574
2618
// No matches found for this node. We assume it's already emitted in the
2575
2619
// prelude and skip it during the replay.
2576
2620
} else {
2577
2621
// We're doing a plain render.
2578
- if ( __DEV__ && enableOwnerStacks ) {
2579
- const debugTask : null | ConsoleTask = element . _debugTask ;
2580
- if ( debugTask ) {
2581
- debugTask . run (
2582
- renderElement . bind (
2583
- null ,
2584
- request ,
2585
- task ,
2586
- keyPath ,
2587
- type ,
2588
- props ,
2589
- ref ,
2590
- owner ,
2591
- stack ,
2592
- ) ,
2593
- ) ;
2594
- return ;
2595
- }
2622
+ const debugTask : null | ConsoleTask =
2623
+ __DEV__ && enableOwnerStacks ? element . _debugTask : null ;
2624
+ if ( debugTask ) {
2625
+ debugTask . run (
2626
+ renderElement . bind (
2627
+ null ,
2628
+ request ,
2629
+ task ,
2630
+ keyPath ,
2631
+ type ,
2632
+ props ,
2633
+ ref ,
2634
+ owner ,
2635
+ stack ,
2636
+ ) ,
2637
+ ) ;
2638
+ } else {
2639
+ renderElement (
2640
+ request ,
2641
+ task ,
2642
+ keyPath ,
2643
+ type ,
2644
+ props ,
2645
+ ref ,
2646
+ owner ,
2647
+ stack ,
2648
+ ) ;
2596
2649
}
2597
- renderElement ( request , task , keyPath , type , props , ref , owner , stack ) ;
2650
+ }
2651
+ if ( __DEV__ ) {
2652
+ task . componentStack = previousComponentStack ;
2598
2653
}
2599
2654
return ;
2600
2655
}
@@ -2604,14 +2659,23 @@ function renderNodeDestructive(
2604
2659
'Render them conditionally so that they only appear on the client render.' ,
2605
2660
) ;
2606
2661
case REACT_LAZY_TYPE : {
2607
- const previousComponentStack = task . componentStack ;
2608
- task . componentStack = createBuiltInComponentStack (
2609
- task ,
2610
- 'Lazy' ,
2611
- null ,
2612
- null ,
2613
- ) ;
2614
2662
const lazyNode : LazyComponentType < any , any > = ( node : any ) ;
2663
+ const previousComponentStack = task . componentStack ;
2664
+ if ( __DEV__ ) {
2665
+ task . componentStack = createServerComponentStack (
2666
+ task ,
2667
+ lazyNode . _debugInfo ,
2668
+ ) ;
2669
+ }
2670
+ if ( ! __DEV__ || task . componentStack === previousComponentStack ) {
2671
+ // TODO: Do we really need this stack frame? We don't on the client.
2672
+ task . componentStack = createBuiltInComponentStack (
2673
+ task ,
2674
+ 'Lazy' ,
2675
+ null ,
2676
+ null ,
2677
+ ) ;
2678
+ }
2615
2679
let resolvedNode ;
2616
2680
if ( __DEV__ ) {
2617
2681
resolvedNode = callLazyInitInDEV ( lazyNode ) ;
@@ -2742,12 +2806,23 @@ function renderNodeDestructive(
2742
2806
// Clear any previous thenable state that was created by the unwrapping.
2743
2807
task . thenableState = null ;
2744
2808
const thenable : Thenable < ReactNodeList > = ( maybeUsable : any ) ;
2745
- return renderNodeDestructive (
2809
+ const previousComponentStack = task . componentStack ;
2810
+ if ( __DEV__ ) {
2811
+ task . componentStack = createServerComponentStack (
2812
+ task ,
2813
+ thenable . _debugInfo ,
2814
+ ) ;
2815
+ }
2816
+ const result = renderNodeDestructive(
2746
2817
request,
2747
2818
task,
2748
2819
unwrapThenable(thenable),
2749
2820
childIndex,
2750
2821
);
2822
+ if (__DEV__) {
2823
+ task . componentStack = previousComponentStack ;
2824
+ }
2825
+ return result;
2751
2826
}
2752
2827
2753
2828
if ( maybeUsable . $$typeof === REACT_CONTEXT_TYPE ) {
@@ -2978,6 +3053,15 @@ function renderChildrenArray(
2978
3053
childIndex : number ,
2979
3054
) : void {
2980
3055
const prevKeyPath = task . keyPath ;
3056
+ const previousComponentStack = task . componentStack ;
3057
+ if ( __DEV__ ) {
3058
+ // We read debugInfo from task.node instead of children because it might have been an
3059
+ // unwrapped iterable so we read from the original node.
3060
+ task . componentStack = createServerComponentStack (
3061
+ task ,
3062
+ ( task . node : any ) . _debugInfo ,
3063
+ ) ;
3064
+ }
2981
3065
if ( childIndex !== - 1 ) {
2982
3066
task . keyPath = [ task . keyPath , 'Fragment' , childIndex ] ;
2983
3067
if ( task . replay !== null ) {
@@ -2989,6 +3073,9 @@ function renderChildrenArray(
2989
3073
childIndex ,
2990
3074
) ;
2991
3075
task . keyPath = prevKeyPath ;
3076
+ if ( __DEV__ ) {
3077
+ task . componentStack = previousComponentStack ;
3078
+ }
2992
3079
return ;
2993
3080
}
2994
3081
}
@@ -3019,6 +3106,9 @@ function renderChildrenArray(
3019
3106
}
3020
3107
task . treeContext = prevTreeContext ;
3021
3108
task . keyPath = prevKeyPath ;
3109
+ if ( __DEV__ ) {
3110
+ task . componentStack = previousComponentStack ;
3111
+ }
3022
3112
return ;
3023
3113
}
3024
3114
}
@@ -3038,6 +3128,9 @@ function renderChildrenArray(
3038
3128
// only need to reset it to the previous value at the very end.
3039
3129
task . treeContext = prevTreeContext ;
3040
3130
task . keyPath = prevKeyPath ;
3131
+ if ( __DEV__ ) {
3132
+ task . componentStack = previousComponentStack ;
3133
+ }
3041
3134
}
3042
3135
3043
3136
function trackPostpone (
0 commit comments