255
_debugRootTask?: null | ConsoleTask, // DEV-only
256
_debugFindSourceMapURL?: void | FindSourceMapURLCallback, // DEV-only
257
_replayConsole: boolean, // DEV-only
258
+ _rootEnvironmentName: string, // DEV-only, the requested environment name.
259
};
260
261
function readChunk<T>(chunk: SomeChunk<T>): T {
693
writable: true,
694
value: null,
695
});
695
- let env = '';
696
+ let env = response._rootEnvironmentName;
697
if (enableOwnerStacks) {
698
if (owner !== null && owner.env != null) {
699
// Interestingly we don't actually have the environment name of where
738
// This owner should ideally have already been initialized to avoid getting
739
// user stack frames on the stack.
740
const ownerTask =
740
- owner === null ? null : initializeFakeTask(response, owner);
741
+ owner === null ? null : initializeFakeTask(response, owner, env);
742
if (ownerTask === null) {
743
const rootTask = response._debugRootTask;
744
if (rootTask != null) {
1356
temporaryReferences: void | TemporaryReferenceSet,
1357
findSourceMapURL: void | FindSourceMapURLCallback,
1358
replayConsole: boolean,
1359
+ environmentName: void | string,
1360
) {
1361
const chunks: Map<number, SomeChunk<any>> = new Map();
1362
this._bundlerConfig = bundlerConfig;
1373
this._rowLength = 0;
1374
this._buffer = [];
1375
this._tempRefs = temporaryReferences;
1374
- if (supportsCreateTask) {
1375
- // Any stacks that appear on the server need to be rooted somehow on the client
1376
- // so we create a root Task for this response which will be the root owner for any
1377
- // elements created by the server. We use the "use server" string to indicate that
1378
- // this is where we enter the server from the client.
1379
- // TODO: Make this string configurable.
1380
- this._debugRootTask = (console: any).createTask('"use server"');
1381
- }
1376
if (__DEV__) {
1377
+ const rootEnv = environmentName === undefined ? 'Server' : environmentName;
1378
+ if (supportsCreateTask) {
1379
+ // Any stacks that appear on the server need to be rooted somehow on the client
1380
+ // so we create a root Task for this response which will be the root owner for any
1381
+ // elements created by the server. We use the "use server" string to indicate that
1382
+ // this is where we enter the server from the client.
1383
+ // TODO: Make this string configurable.
1384
+ this._debugRootTask = (console: any).createTask(
1385
+ '"use ' + rootEnv.toLowerCase() + '"',
1386
+ );
1387
+ }
1388
this._debugFindSourceMapURL = findSourceMapURL;
1389
this._replayConsole = replayConsole;
1390
+ this._rootEnvironmentName = rootEnv;
1391
}
1392
// Don't inline this call because it causes closure to outline the call above.
1393
this._fromJSON = createFromJSONCallback(this);
1402
temporaryReferences: void | TemporaryReferenceSet,
1403
findSourceMapURL: void | FindSourceMapURLCallback,
1404
replayConsole: boolean,
1405
+ environmentName: void | string,
1406
): Response {
1407
// $FlowFixMe[invalid-constructor]: the shapes are exact here but Flow doesn't like constructors
1408
return new ResponseInstance(
1414
temporaryReferences,
1415
findSourceMapURL,
1416
replayConsole,
1417
+ environmentName,
1418
);
1419
}
1420
1872
'An error occurred in the Server Components render but no message was provided',
1873
),
1874
);
1867
- const rootTask = response._debugRootTask;
1875
+ const rootTask = getRootTask(response, env);
1876
if (rootTask != null) {
1877
error = rootTask.run(callStack);
1878
} else {
2106
return callStack;
2107
}
2108
2109
+function getRootTask(
2110
+ response: Response,
2111
+ childEnvironmentName: string,
2112
+): null | ConsoleTask {
2113
+ const rootTask = response._debugRootTask;
2114
+ if (!rootTask) {
2115
+ return null;
2116
+ }
2117
+ if (response._rootEnvironmentName !== childEnvironmentName) {
2118
+ // If the root most owner component is itself in a different environment than the requested
2119
+ // environment then we create an extra task to indicate that we're transitioning into it.
2120
+ // Like if one environment just requests another environment.
2121
+ const createTaskFn = (console: any).createTask.bind(
2122
+ console,
2123
+ '"use ' + childEnvironmentName.toLowerCase() + '"',
2124
+ );
2125
+ return rootTask.run(createTaskFn);
2126
+ }
2127
+ return rootTask;
2128
+}
2129
+
2130
function initializeFakeTask(
2131
response: Response,
2132
debugInfo: ReactComponentInfo | ReactAsyncInfo,
2133
+ childEnvironmentName: string,
2134
): null | ConsoleTask {
2135
if (!supportsCreateTask) {
2136
return null;
2137
}
2138
const componentInfo: ReactComponentInfo = (debugInfo: any); // Refined
2109
- const cachedEntry = componentInfo.debugTask;
2110
- if (cachedEntry !== undefined) {
2111
- return cachedEntry;
2112
- }
2113
-
2139
if (debugInfo.stack == null) {
2140
// If this is an error, we should've really already initialized the task.
2141
// If it's null, we can't initialize a task.
2142
return null;
2143
}
2119
-
2144
const stack = debugInfo.stack;
2121
- const env = componentInfo.env == null ? '' : componentInfo.env;
2122
- const ownerTask =
2123
- componentInfo.owner == null
2124
- ? null
2125
- : initializeFakeTask(response, componentInfo.owner);
2126
-
2127
- const createTaskFn = (console: any).createTask.bind(
2128
- console,
2129
- getServerComponentTaskName(componentInfo),
2130
- );
2131
- const callStack = buildFakeCallStack(response, stack, env, createTaskFn);
2145
+ const env: string =
2146
+ componentInfo.env == null
2147
+ ? response._rootEnvironmentName
2148
+ : componentInfo.env;
2149
+ if (env !== childEnvironmentName) {
2150
+ // This is the boundary between two environments so we'll annotate the task name.
2151
+ // That is unusual so we don't cache it.
2152
+ const ownerTask =
2153
+ componentInfo.owner == null
2154
+ ? null
2155
+ : initializeFakeTask(response, componentInfo.owner, env);
2156
+ return buildFakeTask(
2157
+ response,
2158
+ ownerTask,
2159
+ stack,
2160
+ '"use ' + childEnvironmentName.toLowerCase() + '"',
2161
+ env,
2162
+ );
2163
+ } else {
2164
+ const cachedEntry = componentInfo.debugTask;
2165
+ if (cachedEntry !== undefined) {
2166
+ return cachedEntry;
2167
+ }
2168
+ const ownerTask =
2169
+ componentInfo.owner == null
2170
+ ? null
2171
+ : initializeFakeTask(response, componentInfo.owner, env);
2172
+ // $FlowFixMe[cannot-write]: We consider this part of initialization.
2173
+ return (componentInfo.debugTask = buildFakeTask(
2174
+ response,
2175
+ ownerTask,
2176
+ stack,
2177
+ getServerComponentTaskName(componentInfo),
2178
+ env,
2179
+ ));
2180
+ }
2181
+}
2182
2133
- let componentTask;
2183
+function buildFakeTask(
2184
+ response: Response,
2185
+ ownerTask: null | ConsoleTask,
2186
+ stack: ReactStackTrace,
2187
+ taskName: string,
2188
+ env: string,
2189
+): ConsoleTask {
2190
+ const createTaskFn = (console: any).createTask.bind(console, taskName);
2191
+ const callStack = buildFakeCallStack(response, stack, env, createTaskFn);
2192
if (ownerTask === null) {
2135
- const rootTask = response._debugRootTask;
2193
+ const rootTask = getRootTask(response, env);
2194
if (rootTask != null) {
2137
- componentTask = rootTask.run(callStack);
2195
+ return rootTask.run(callStack);
2196
} else {
2139
- componentTask = callStack();
2197
+ return callStack();
2198
}
2199
} else {
2142
- componentTask = ownerTask.run(callStack);
2200
+ return ownerTask.run(callStack);
2201
}
2144
- // $FlowFixMe[cannot-write]: We consider this part of initialization.
2145
- componentInfo.debugTask = componentTask;
2146
- return componentTask;
2202
}
2203
2204
const createFakeJSXCallStack = {
2271
// We eagerly initialize the fake task because this resolving happens outside any
2272
// render phase so we're not inside a user space stack at this point. If we waited
2273
// to initialize it when we need it, we might be inside user code.
2219
- initializeFakeTask(response, debugInfo);
2274
+ const env =
2275
+ debugInfo.env === undefined ? response._rootEnvironmentName : debugInfo.env;
2276
+ initializeFakeTask(response, debugInfo, env);
2277
initializeFakeStack(response, debugInfo);
2278
2279
const chunk = getChunk(response, id);
2323
printToConsole.bind(null, methodName, args, env),
2324
);
2325
if (owner != null) {
2269
- const task = initializeFakeTask(response, owner);
2326
+ const task = initializeFakeTask(response, owner, env);
2327
initializeFakeStack(response, owner);
2328
if (task !== null) {
2329
task.run(callStack);
2332
// TODO: Set the current owner so that captureOwnerStack() adds the component
2333
// stack during the replay - if needed.
2334
}
2278
- const rootTask = response._debugRootTask;
2335
+ const rootTask = getRootTask(response, env);
2336
if (rootTask != null) {
2337
rootTask.run(callStack);
2338
return;