@@ -254,6 +254,7 @@ export type Response = {
254254 _rowLength : number , // remaining bytes in the row. 0 indicates that we're looking for a newline.
255255 _buffer : Array < Uint8Array > , // chunks received so far as part of this row
256256 _tempRefs : void | TemporaryReferenceSet , // the set temporary references can be resolved from
257+ _debugRootTask ?: null | ConsoleTask , // DEV-only
257258} ;
258259
259260function readChunk < T > (chunk: SomeChunk< T > ): T {
@@ -614,6 +615,7 @@ function getTaskName(type: mixed): string {
614615}
615616
616617function createElement (
618+ response : Response ,
617619 type : mixed ,
618620 key : mixed ,
619621 props : mixed ,
@@ -697,9 +699,15 @@ function createElement(
697699 const callStack = buildFakeCallStack ( stack , createTaskFn ) ;
698700 // This owner should ideally have already been initialized to avoid getting
699701 // user stack frames on the stack.
700- const ownerTask = owner === null ? null : initializeFakeTask ( owner ) ;
702+ const ownerTask =
703+ owner === null ? null : initializeFakeTask ( response , owner ) ;
701704 if ( ownerTask === null ) {
702- task = callStack ( ) ;
705+ const rootTask = response . _debugRootTask ;
706+ if ( rootTask != null ) {
707+ task = rootTask . run ( callStack ) ;
708+ } else {
709+ task = callStack ( ) ;
710+ }
703711 } else {
704712 task = ownerTask . run ( callStack ) ;
705713 }
@@ -1106,6 +1114,7 @@ function parseModelTuple(
11061114 // TODO: Consider having React just directly accept these arrays as elements.
11071115 // Or even change the ReactElement type to be an array.
11081116 return createElement (
1117+ response ,
11091118 tuple [ 1 ] ,
11101119 tuple [ 2 ] ,
11111120 tuple [ 3 ] ,
@@ -1149,6 +1158,14 @@ export function createResponse(
11491158 _buffer : [ ] ,
11501159 _tempRefs : temporaryReferences ,
11511160 } ;
1161+ if ( supportsCreateTask ) {
1162+ // Any stacks that appear on the server need to be rooted somehow on the client
1163+ // so we create a root Task for this response which will be the root owner for any
1164+ // elements created by the server. We use the "use server" string to indicate that
1165+ // this is where we enter the server from the client.
1166+ // TODO: Make this string configurable.
1167+ response. _debugRootTask = ( console : any ) . createTask ( '"use server"' ) ;
1168+ }
11521169 // Don't inline this call because it causes closure to outline the call above.
11531170 response . _fromJSON = createFromJSONCallback ( response ) ;
11541171 return response ;
@@ -1730,6 +1747,7 @@ function buildFakeCallStack<T>(stack: string, innerCall: () => T): () => T {
17301747}
17311748
17321749function initializeFakeTask(
1750+ response: Response,
17331751 debugInfo: ReactComponentInfo | ReactAsyncInfo,
17341752): null | ConsoleTask {
17351753 if ( taskCache === null || typeof debugInfo . stack !== 'string' ) {
@@ -1745,7 +1763,7 @@ function initializeFakeTask(
17451763 const ownerTask =
17461764 componentInfo.owner == null
17471765 ? null
1748- : initializeFakeTask(componentInfo.owner);
1766+ : initializeFakeTask(response, componentInfo.owner);
17491767
17501768 // eslint-disable-next-line react-internal/no-production-logging
17511769 const createTaskFn = (console: any).createTask.bind(
@@ -1755,7 +1773,12 @@ function initializeFakeTask(
17551773 const callStack = buildFakeCallStack(stack, createTaskFn);
17561774
17571775 if (ownerTask === null) {
1758- return callStack ( ) ;
1776+ const rootTask = response . _debugRootTask ;
1777+ if ( rootTask != null ) {
1778+ return rootTask . run ( callStack ) ;
1779+ } else {
1780+ return callStack ( ) ;
1781+ }
17591782 } else {
17601783 return ownerTask . run ( callStack ) ;
17611784 }
@@ -1776,7 +1799,7 @@ function resolveDebugInfo(
17761799 // We eagerly initialize the fake task because this resolving happens outside any
17771800 // render phase so we're not inside a user space stack at this point. If we waited
17781801 // to initialize it when we need it, we might be inside user code.
1779- initializeFakeTask(debugInfo);
1802+ initializeFakeTask(response, debugInfo);
17801803 const chunk = getChunk(response, id);
17811804 const chunkDebugInfo: ReactDebugInfo =
17821805 chunk._debugInfo || (chunk._debugInfo = []);
@@ -1813,12 +1836,17 @@ function resolveConsoleEntry(
18131836 printToConsole.bind(null, methodName, args, env),
18141837 );
18151838 if (owner != null) {
1816- const task = initializeFakeTask ( owner ) ;
1839+ const task = initializeFakeTask ( response , owner ) ;
18171840 if ( task !== null ) {
18181841 task . run ( callStack ) ;
18191842 return ;
18201843 }
18211844 }
1845+ const rootTask = response . _debugRootTask ;
1846+ if ( rootTask != null ) {
1847+ rootTask . run ( callStack ) ;
1848+ return ;
1849+ }
18221850 callStack();
18231851}
18241852
0 commit comments