Skip to content

[pull] main from facebook:main #174

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jun 4, 2025
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,7 @@ module.exports = {
TimeoutID: 'readonly',
WheelEventHandler: 'readonly',
FinalizationRegistry: 'readonly',
Exclude: 'readonly',
Omit: 'readonly',
Keyframe: 'readonly',
PropertyIndexedKeyframes: 'readonly',
Expand Down
4 changes: 2 additions & 2 deletions fixtures/fizz/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
"prettier": "1.19.1"
},
"scripts": {
"predev": "cp -r ../../build/oss-experimental/* ./node_modules/",
"prestart": "cp -r ../../build/oss-experimental/* ./node_modules/",
"predev": "cp -r ../../build/oss-experimental/* ./node_modules/ && rm -rf node_modules/.cache;",
"prestart": "cp -r ../../build/oss-experimental/* ./node_modules/ && rm -rf node_modules/.cache;",
"dev": "concurrently \"npm run dev:server\" \"npm run dev:bundler\"",
"start": "concurrently \"npm run start:server\" \"npm run start:bundler\"",
"dev:server": "cross-env NODE_ENV=development nodemon -- --inspect server/server.js",
Expand Down
4 changes: 2 additions & 2 deletions fixtures/flight-esm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
"webpack-sources": "^3.2.0"
},
"scripts": {
"predev": "cp -r ../../build/oss-experimental/* ./node_modules/",
"prestart": "cp -r ../../build/oss-experimental/* ./node_modules/",
"predev": "cp -r ../../build/oss-experimental/* ./node_modules/ && rm -rf node_modules/.cache;",
"prestart": "cp -r ../../build/oss-experimental/* ./node_modules/ && rm -rf node_modules/.cache;",
"dev": "concurrently \"npm run dev:region\" \"npm run dev:global\"",
"dev:global": "NODE_ENV=development BUILD_PATH=dist node server/global",
"dev:region": "NODE_ENV=development BUILD_PATH=dist nodemon --watch src --watch dist -- --enable-source-maps --experimental-loader ./loader/region.js --conditions=react-server server/region",
Expand Down
4 changes: 2 additions & 2 deletions fixtures/flight/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@
"@playwright/test": "^1.51.1"
},
"scripts": {
"predev": "cp -r ../../build/oss-experimental/* ./node_modules/",
"prebuild": "cp -r ../../build/oss-experimental/* ./node_modules/",
"predev": "cp -r ../../build/oss-experimental/* ./node_modules/ && rm -rf node_modules/.cache;",
"prebuild": "cp -r ../../build/oss-experimental/* ./node_modules/ && rm -rf node_modules/.cache;",
"dev": "concurrently \"npm run dev:region\" \"npm run dev:global\"",
"dev:global": "NODE_ENV=development BUILD_PATH=dist node --experimental-loader ./loader/global.js --inspect=127.0.0.1:9230 server/global",
"dev:region": "NODE_ENV=development BUILD_PATH=dist nodemon --watch src --watch dist -- --enable-source-maps --experimental-loader ./loader/region.js --conditions=react-server --inspect=127.0.0.1:9229 server/region",
Expand Down
2 changes: 1 addition & 1 deletion fixtures/owner-stacks/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"web-vitals": "^2.1.0"
},
"scripts": {
"prestart": "cp -a ../../build/oss-experimental/. node_modules",
"prestart": "cp -a ../../build/oss-experimental/. node_modules && rm -rf node_modules/.cache;",
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
Expand Down
2 changes: 1 addition & 1 deletion fixtures/ssr/src/components/LargeContent.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import React, {

export default function LargeContent() {
return (
<SuspenseList revealOrder="forwards">
<SuspenseList revealOrder="forwards" tail="visible">
<Suspense fallback={null}>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris
Expand Down
6 changes: 3 additions & 3 deletions fixtures/view-transition/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@
]
},
"scripts": {
"predev": "cp -r ../../build/oss-experimental/* ./node_modules/",
"prestart": "cp -r ../../build/oss-experimental/* ./node_modules/",
"prebuild": "cp -r ../../build/oss-experimental/* ./node_modules/",
"predev": "cp -r ../../build/oss-experimental/* ./node_modules/ && rm -rf node_modules/.cache;",
"prestart": "cp -r ../../build/oss-experimental/* ./node_modules/ && rm -rf node_modules/.cache;",
"prebuild": "cp -r ../../build/oss-experimental/* ./node_modules/ && rm -rf node_modules/.cache;",
"dev": "concurrently \"npm run dev:server\" \"npm run dev:client\"",
"dev:client": "BROWSER=none PORT=3001 react-scripts start",
"dev:server": "NODE_ENV=development node server",
Expand Down
96 changes: 78 additions & 18 deletions packages/react-client/src/ReactFlightClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ import {
logComponentRender,
logDedupedComponentRender,
logComponentErrored,
logIOInfo,
logComponentAwait,
} from './ReactFlightPerformanceTrack';

import {
Expand Down Expand Up @@ -675,11 +677,11 @@ function nullRefGetter() {
}

function getIOInfoTaskName(ioInfo: ReactIOInfo): string {
return ''; // TODO
return ioInfo.name || 'unknown';
}

function getAsyncInfoTaskName(asyncInfo: ReactAsyncInfo): string {
return 'await'; // We could be smarter about this and give it a name like `then` or `Promise.all`.
return 'await ' + getIOInfoTaskName(asyncInfo.awaited);
}

function getServerComponentTaskName(componentInfo: ReactComponentInfo): string {
Expand Down Expand Up @@ -811,7 +813,13 @@ function createElement(
console,
getTaskName(type),
);
const callStack = buildFakeCallStack(response, stack, env, createTaskFn);
const callStack = buildFakeCallStack(
response,
stack,
env,
false,
createTaskFn,
);
// This owner should ideally have already been initialized to avoid getting
// user stack frames on the stack.
const ownerTask =
Expand Down Expand Up @@ -2132,6 +2140,7 @@ function resolveErrorDev(
response,
stack,
env,
false,
// $FlowFixMe[incompatible-use]
Error.bind(
null,
Expand Down Expand Up @@ -2194,6 +2203,7 @@ function resolvePostponeDev(
response,
stack,
env,
false,
// $FlowFixMe[incompatible-use]
Error.bind(null, reason || ''),
);
Expand Down Expand Up @@ -2402,12 +2412,17 @@ function buildFakeCallStack<T>(
response: Response,
stack: ReactStackTrace,
environmentName: string,
useEnclosingLine: boolean,
innerCall: () => T,
): () => T {
let callStack = innerCall;
for (let i = 0; i < stack.length; i++) {
const frame = stack[i];
const frameKey = frame.join('-') + '-' + environmentName;
const frameKey =
frame.join('-') +
'-' +
environmentName +
(useEnclosingLine ? '-e' : '-n');
let fn = fakeFunctionCache.get(frameKey);
if (fn === undefined) {
const [name, filename, line, col, enclosingLine, enclosingCol] = frame;
Expand All @@ -2421,8 +2436,8 @@ function buildFakeCallStack<T>(
sourceMap,
line,
col,
enclosingLine,
enclosingCol,
useEnclosingLine ? line : enclosingLine,
useEnclosingLine ? col : enclosingCol,
environmentName,
);
// TODO: This cache should technically live on the response since the _debugFindSourceMapURL
Expand Down Expand Up @@ -2468,6 +2483,15 @@ function initializeFakeTask(
// If it's null, we can't initialize a task.
return null;
}

// Workaround for a bug where Chrome Performance tracking uses the enclosing line/column
// instead of the callsite. For ReactAsyncInfo/ReactIOInfo, the only thing we're going
// to use the fake task for is the Performance tracking so we encode the enclosing line/
// column at the callsite to get a better line number. We could do this for Components too
// but we're going to use those for other things too like console logs and it's not worth
// duplicating. If this bug is every fixed in Chrome, this should be set to false.
const useEnclosingLine = debugInfo.key === undefined;

const stack = debugInfo.stack;
const env: string =
debugInfo.env == null ? response._rootEnvironmentName : debugInfo.env;
Expand All @@ -2484,6 +2508,7 @@ function initializeFakeTask(
stack,
'"use ' + childEnvironmentName.toLowerCase() + '"',
env,
useEnclosingLine,
);
} else {
const cachedEntry = debugInfo.debugTask;
Expand All @@ -2508,6 +2533,7 @@ function initializeFakeTask(
stack,
taskName,
env,
useEnclosingLine,
));
}
}
Expand All @@ -2518,9 +2544,16 @@ function buildFakeTask(
stack: ReactStackTrace,
taskName: string,
env: string,
useEnclosingLine: boolean,
): ConsoleTask {
const createTaskFn = (console: any).createTask.bind(console, taskName);
const callStack = buildFakeCallStack(response, stack, env, createTaskFn);
const callStack = buildFakeCallStack(
response,
stack,
env,
useEnclosingLine,
createTaskFn,
);
if (ownerTask === null) {
const rootTask = getRootTask(response, env);
if (rootTask != null) {
Expand All @@ -2543,6 +2576,7 @@ const createFakeJSXCallStack = {
response,
stack,
environmentName,
false,
fakeJSXCallSite,
);
return callStackForError();
Expand Down Expand Up @@ -2615,14 +2649,15 @@ function resolveDebugInfo(
initializeFakeTask(response, componentInfoOrAsyncInfo, env);
}
if (debugInfo.owner === null && response._debugRootOwner != null) {
// $FlowFixMe[prop-missing] By narrowing `owner` to `null`, we narrowed `debugInfo` to `ReactComponentInfo`
const componentInfo: ReactComponentInfo = debugInfo;
const componentInfoOrAsyncInfo: ReactComponentInfo | ReactAsyncInfo =
// $FlowFixMe: By narrowing `owner` to `null`, we narrowed `debugInfo` to `ReactComponentInfo`
debugInfo;
// $FlowFixMe[cannot-write]
componentInfo.owner = response._debugRootOwner;
componentInfoOrAsyncInfo.owner = response._debugRootOwner;
// We override the stack if we override the owner since the stack where the root JSX
// was created on the server isn't very useful but where the request was made is.
// $FlowFixMe[cannot-write]
componentInfo.debugStack = response._debugRootStack;
componentInfoOrAsyncInfo.debugStack = response._debugRootStack;
} else if (debugInfo.stack !== undefined) {
const componentInfoOrAsyncInfo: ReactComponentInfo | ReactAsyncInfo =
// $FlowFixMe[incompatible-type]
Expand Down Expand Up @@ -2678,6 +2713,7 @@ const replayConsoleWithCallStack = {
response,
stackTrace,
env,
false,
bindToConsole(methodName, args, env),
);
if (owner != null) {
Expand Down Expand Up @@ -2756,19 +2792,18 @@ function resolveConsoleEntry(

function initializeIOInfo(response: Response, ioInfo: ReactIOInfo): void {
const env =
// TODO: Pass env through I/O info.
// ioInfo.env !== undefined ? ioInfo.env :
response._rootEnvironmentName;
ioInfo.env === undefined ? response._rootEnvironmentName : ioInfo.env;
if (ioInfo.stack !== undefined) {
initializeFakeTask(response, ioInfo, env);
initializeFakeStack(response, ioInfo);
}
// TODO: Initialize owner.
// Adjust the time to the current environment's time space.
// $FlowFixMe[cannot-write]
ioInfo.start += response._timeOrigin;
// $FlowFixMe[cannot-write]
ioInfo.end += response._timeOrigin;

logIOInfo(ioInfo, response._rootEnvironmentName);
}

function resolveIOInfo(
Expand Down Expand Up @@ -2890,6 +2925,7 @@ function flushComponentPerformance(
trackIdx,
parentEndTime,
previousEndTime,
response._rootEnvironmentName,
);
}
// Since we didn't bump the track this time, we just return the same track.
Expand Down Expand Up @@ -2969,9 +3005,12 @@ function flushComponentPerformance(
for (let i = debugInfo.length - 1; i >= 0; i--) {
const info = debugInfo[i];
if (typeof info.time === 'number') {
endTime = info.time;
if (endTime > childrenEndTime) {
childrenEndTime = endTime;
if (info.time > childrenEndTime) {
childrenEndTime = info.time;
}
if (endTime === 0) {
// Last timestamp is the end of the last component.
endTime = info.time;
}
}
if (typeof info.name === 'string' && i > 0) {
Expand Down Expand Up @@ -3009,8 +3048,29 @@ function flushComponentPerformance(
}
// Track the root most component of the result for deduping logging.
result.component = componentInfo;
// Set the end time of the previous component to the start of the previous.
endTime = startTime;
}
isLastComponent = false;
} else if (info.awaited && i > 0 && i < debugInfo.length - 2) {
// $FlowFixMe: Refined.
const asyncInfo: ReactAsyncInfo = info;
const startTimeInfo = debugInfo[i - 1];
const endTimeInfo = debugInfo[i + 1];
if (
typeof startTimeInfo.time === 'number' &&
typeof endTimeInfo.time === 'number'
) {
const awaitStartTime = startTimeInfo.time;
const awaitEndTime = endTimeInfo.time;
logComponentAwait(
asyncInfo,
trackIdx,
awaitStartTime,
awaitEndTime,
response._rootEnvironmentName,
);
}
}
}
}
Expand Down
Loading
Loading