@@ -86,14 +86,19 @@ import isArray from 'shared/isArray';
86
86
87
87
import * as React from 'react' ;
88
88
89
+ import type { SharedStateServer } from 'react/src/ReactSharedInternalsServer' ;
90
+ import type { SharedStateClient } from 'react/src/ReactSharedInternalsClient' ;
91
+
89
92
// TODO: This is an unfortunate hack. We shouldn't feature detect the internals
90
93
// like this. It's just that for now we support the same build of the Flight
91
94
// client both in the RSC environment, in the SSR environments as well as the
92
95
// browser client. We should probably have a separate RSC build. This is DEV
93
96
// only though.
94
- const ReactSharedInternals =
97
+ const ReactSharedInteralsServer : void | SharedStateServer = ( React : any )
98
+ . __SERVER_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE ;
99
+ const ReactSharedInternals : SharedStateServer | SharedStateClient =
95
100
React . __CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE ||
96
- React.__SERVER_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE ;
101
+ ReactSharedInteralsServer ;
97
102
98
103
export type { CallServerCallback , EncodeFormActionCallback } ;
99
104
@@ -277,6 +282,8 @@ export type Response = {
277
282
_rowLength : number , // remaining bytes in the row. 0 indicates that we're looking for a newline.
278
283
_buffer : Array < Uint8Array > , // chunks received so far as part of this row
279
284
_tempRefs : void | TemporaryReferenceSet , // the set temporary references can be resolved from
285
+ _debugRootOwner ?: null | ReactComponentInfo , // DEV-only
286
+ _debugRootStack ?: null | Error , // DEV-only
280
287
_debugRootTask ?: null | ConsoleTask , // DEV-only
281
288
_debugFindSourceMapURL ?: void | FindSourceMapURLCallback , // DEV-only
282
289
_replayConsole : boolean , // DEV-only
@@ -672,7 +679,7 @@ function createElement(
672
679
type,
673
680
key,
674
681
props,
675
- _owner: owner,
682
+ _owner : __DEV__ && owner === null ? response . _debugRootOwner : owner ,
676
683
} : any ) ;
677
684
Object . defineProperty ( element , 'ref' , {
678
685
enumerable : false ,
@@ -699,7 +706,7 @@ function createElement(
699
706
props,
700
707
701
708
// Record the component responsible for creating this element.
702
- _owner: owner,
709
+ _owner : __DEV__ && owner === null ? response . _debugRootOwner : owner ,
703
710
} : any ) ;
704
711
}
705
712
@@ -733,7 +740,11 @@ function createElement(
733
740
env = owner . env ;
734
741
}
735
742
let normalizedStackTrace : null | Error = null ;
736
- if (stack !== null) {
743
+ if ( owner === null && response . _debugRootStack != null ) {
744
+ // We override the stack if we override the owner since the stack where the root JSX
745
+ // was created on the server isn't very useful but where the request was made is.
746
+ normalizedStackTrace = response . _debugRootStack ;
747
+ } else if ( stack !== null ) {
737
748
// We create a fake stack and then create an Error object inside of it.
738
749
// This means that the stack trace is now normalized into the native format
739
750
// of the browser and the stack frames will have been registered with
@@ -821,8 +832,10 @@ function createElement(
821
832
if ( enableOwnerStacks ) {
822
833
// $FlowFixMe[cannot-write]
823
834
erroredComponent . debugStack = element . _debugStack ;
824
- // $FlowFixMe[cannot-write]
825
- erroredComponent.debugTask = element._debugTask;
835
+ if ( supportsCreateTask ) {
836
+ // $FlowFixMe[cannot-write]
837
+ erroredComponent . debugTask = element . _debugTask ;
838
+ }
826
839
}
827
840
erroredChunk . _debugInfo = [ erroredComponent ] ;
828
841
}
@@ -998,8 +1011,10 @@ function waitForReference<T>(
998
1011
if ( enableOwnerStacks ) {
999
1012
// $FlowFixMe[cannot-write]
1000
1013
erroredComponent . debugStack = element . _debugStack ;
1001
- // $FlowFixMe[cannot-write]
1002
- erroredComponent.debugTask = element._debugTask;
1014
+ if ( supportsCreateTask ) {
1015
+ // $FlowFixMe[cannot-write]
1016
+ erroredComponent . debugTask = element . _debugTask ;
1017
+ }
1003
1018
}
1004
1019
const chunkDebugInfo : ReactDebugInfo =
1005
1020
chunk . _debugInfo || ( chunk . _debugInfo = [ ] ) ;
@@ -1408,6 +1423,25 @@ function ResponseInstance(
1408
1423
this . _buffer = [ ] ;
1409
1424
this . _tempRefs = temporaryReferences ;
1410
1425
if ( __DEV__ ) {
1426
+ // TODO: The Flight Client can be used in a Client Environment too and we should really support
1427
+ // getting the owner there as well, but currently the owner of ReactComponentInfo is typed as only
1428
+ // supporting other ReactComponentInfo as owners (and not Fiber or Fizz's ComponentStackNode).
1429
+ // We need to update all the callsites consuming ReactComponentInfo owners to support those.
1430
+ // In the meantime we only check ReactSharedInteralsServer since we know that in an RSC environment
1431
+ // the only owners will be ReactComponentInfo.
1432
+ const rootOwner : null | ReactComponentInfo =
1433
+ ReactSharedInteralsServer === undefined ||
1434
+ ReactSharedInteralsServer . A === null
1435
+ ? null
1436
+ : ( ReactSharedInteralsServer . A . getOwner ( ) : any ) ;
1437
+
1438
+ this . _debugRootOwner = rootOwner ;
1439
+ this . _debugRootStack =
1440
+ rootOwner !== null
1441
+ ? // TODO: Consider passing the top frame in so we can avoid internals showing up.
1442
+ new Error ( 'react-stack-top-frame' )
1443
+ : null ;
1444
+
1411
1445
const rootEnv = environmentName === undefined ? 'Server' : environmentName ;
1412
1446
if ( supportsCreateTask ) {
1413
1447
// Any stacks that appear on the server need to be rooted somehow on the client
@@ -2308,7 +2342,16 @@ function resolveDebugInfo(
2308
2342
const env =
2309
2343
debugInfo . env === undefined ? response . _rootEnvironmentName : debugInfo . env ;
2310
2344
initializeFakeTask ( response , debugInfo , env ) ;
2311
- initializeFakeStack(response, debugInfo);
2345
+ if ( debugInfo . owner === null && response . _debugRootOwner != null ) {
2346
+ // $FlowFixMe
2347
+ debugInfo . owner = response . _debugRootOwner ;
2348
+ // We override the stack if we override the owner since the stack where the root JSX
2349
+ // was created on the server isn't very useful but where the request was made is.
2350
+ // $FlowFixMe
2351
+ debugInfo . debugStack = response . _debugRootStack ;
2352
+ } else {
2353
+ initializeFakeStack ( response , debugInfo ) ;
2354
+ }
2312
2355
2313
2356
const chunk = getChunk ( response , id ) ;
2314
2357
const chunkDebugInfo : ReactDebugInfo =
@@ -2344,7 +2387,8 @@ const replayConsoleWithCallStack = {
2344
2387
// There really shouldn't be anything else on the stack atm.
2345
2388
const prevStack = ReactSharedInternals . getCurrentStack ;
2346
2389
ReactSharedInternals . getCurrentStack = getCurrentStackInDEV ;
2347
- currentOwnerInDEV = owner;
2390
+ currentOwnerInDEV =
2391
+ owner === null ? ( response . _debugRootOwner : any ) : owner ;
2348
2392
2349
2393
try {
2350
2394
const callStack = buildFakeCallStack (
0 commit comments