Move getDebugInfo test util function to internal-test-utils (#34523)

In an upstack PR, I need `getDebugInfo` in another test file, so I'm
moving it to `internal-test-utils` so it can be shared.
This commit is contained in:
Hendrik Liebau 2025-09-18 21:32:36 +02:00 committed by GitHub
parent ad578aa01f
commit c03a51d836
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 426 additions and 455 deletions

View File

@ -16,6 +16,7 @@ import {
clearErrors,
createLogAssertion,
} from './consoleMock';
export {getDebugInfo} from './debugInfo';
export {act, serverAct} from './internalAct';
const {assertConsoleLogsCleared} = require('internal-test-utils/consoleMock');

View File

@ -0,0 +1,131 @@
'use strict';
const path = require('path');
const repoRoot = path.resolve(__dirname, '../../');
type DebugInfoConfig = {
ignoreProps?: boolean,
ignoreRscStreamInfo?: boolean,
useFixedTime?: boolean,
useV8Stack?: boolean,
};
function formatV8Stack(stack) {
let v8StyleStack = '';
if (stack) {
for (let i = 0; i < stack.length; i++) {
const [name] = stack[i];
if (v8StyleStack !== '') {
v8StyleStack += '\n';
}
v8StyleStack += ' in ' + name + ' (at **)';
}
}
return v8StyleStack;
}
function normalizeStack(stack) {
if (!stack) {
return stack;
}
const copy = [];
for (let i = 0; i < stack.length; i++) {
const [name, file, line, col, enclosingLine, enclosingCol] = stack[i];
copy.push([
name,
file.replace(repoRoot, ''),
line,
col,
enclosingLine,
enclosingCol,
]);
}
return copy;
}
function normalizeIOInfo(config: DebugInfoConfig, ioInfo) {
const {debugTask, debugStack, debugLocation, ...copy} = ioInfo;
if (ioInfo.stack) {
copy.stack = config.useV8Stack
? formatV8Stack(ioInfo.stack)
: normalizeStack(ioInfo.stack);
}
if (ioInfo.owner) {
copy.owner = normalizeDebugInfo(config, ioInfo.owner);
}
if (typeof ioInfo.start === 'number' && config.useFixedTime) {
copy.start = 0;
}
if (typeof ioInfo.end === 'number' && config.useFixedTime) {
copy.end = 0;
}
const promise = ioInfo.value;
if (promise) {
promise.then(); // init
if (promise.status === 'fulfilled') {
if (ioInfo.name === 'RSC stream') {
copy.byteSize = 0;
copy.value = {
value: 'stream',
};
} else {
copy.value = {
value: promise.value,
};
}
} else if (promise.status === 'rejected') {
copy.value = {
reason: promise.reason,
};
} else {
copy.value = {
status: promise.status,
};
}
}
return copy;
}
function normalizeDebugInfo(config: DebugInfoConfig, original) {
const {debugTask, debugStack, debugLocation, ...debugInfo} = original;
if (original.owner) {
debugInfo.owner = normalizeDebugInfo(config, original.owner);
}
if (original.awaited) {
debugInfo.awaited = normalizeIOInfo(config, original.awaited);
}
if (debugInfo.props && config.ignoreProps) {
debugInfo.props = {};
}
if (Array.isArray(debugInfo.stack)) {
debugInfo.stack = config.useV8Stack
? formatV8Stack(debugInfo.stack)
: normalizeStack(debugInfo.stack);
return debugInfo;
} else if (typeof debugInfo.time === 'number' && config.useFixedTime) {
return {...debugInfo, time: 0};
} else {
return debugInfo;
}
}
export function getDebugInfo(config: DebugInfoConfig, obj) {
const debugInfo = obj._debugInfo;
if (debugInfo) {
const copy = [];
for (let i = 0; i < debugInfo.length; i++) {
if (
debugInfo[i].awaited &&
debugInfo[i].awaited.name === 'RSC stream' &&
config.ignoreRscStreamInfo
) {
// Ignore RSC stream I/O info.
} else {
copy.push(normalizeDebugInfo(config, debugInfo[i]));
}
}
return copy;
}
return debugInfo;
}

View File

@ -33,20 +33,6 @@ function normalizeCodeLocInfo(str) {
);
}
function formatV8Stack(stack) {
let v8StyleStack = '';
if (stack) {
for (let i = 0; i < stack.length; i++) {
const [name] = stack[i];
if (v8StyleStack !== '') {
v8StyleStack += '\n';
}
v8StyleStack += ' in ' + name + ' (at **)';
}
}
return v8StyleStack;
}
const repoRoot = path.resolve(__dirname, '../../../../');
function normalizeReactCodeLocInfo(str) {
const repoRootForRegexp = repoRoot.replace(/\//g, '\\/');
@ -67,35 +53,6 @@ function getErrorForJestMatcher(error) {
};
}
function normalizeComponentInfo(debugInfo) {
if (Array.isArray(debugInfo.stack)) {
const {debugTask, debugStack, debugLocation, ...copy} = debugInfo;
copy.stack = formatV8Stack(debugInfo.stack);
if (debugInfo.owner) {
copy.owner = normalizeComponentInfo(debugInfo.owner);
}
return copy;
} else {
return debugInfo;
}
}
function getDebugInfo(obj) {
const debugInfo = obj._debugInfo;
if (debugInfo) {
const copy = [];
for (let i = 0; i < debugInfo.length; i++) {
if (debugInfo[i].awaited && debugInfo[i].awaited.name === 'RSC stream') {
// Ignore RSC stream I/O info.
} else {
copy.push(normalizeComponentInfo(debugInfo[i]));
}
}
return copy;
}
return debugInfo;
}
const finalizationRegistries = [];
function FinalizationRegistryMock(callback) {
this._heldValues = [];
@ -132,6 +89,7 @@ let NoErrorExpected;
let Scheduler;
let assertLog;
let assertConsoleErrorDev;
let getDebugInfo;
describe('ReactFlight', () => {
beforeEach(() => {
@ -169,6 +127,11 @@ describe('ReactFlight', () => {
assertLog = InternalTestUtils.assertLog;
assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;
getDebugInfo = InternalTestUtils.getDebugInfo.bind(null, {
useV8Stack: true,
ignoreRscStreamInfo: true,
});
ErrorBoundary = class extends React.Component {
state = {hasError: false, error: null};
static getDerivedStateFromError(error) {

View File

@ -18,50 +18,12 @@ if (typeof File === 'undefined' || typeof FormData === 'undefined') {
global.FormData = require('undici').FormData;
}
function formatV8Stack(stack) {
let v8StyleStack = '';
if (stack) {
for (let i = 0; i < stack.length; i++) {
const [name] = stack[i];
if (v8StyleStack !== '') {
v8StyleStack += '\n';
}
v8StyleStack += ' in ' + name + ' (at **)';
}
}
return v8StyleStack;
}
function normalizeComponentInfo(debugInfo) {
if (Array.isArray(debugInfo.stack)) {
const {debugTask, debugStack, ...copy} = debugInfo;
copy.stack = formatV8Stack(debugInfo.stack);
if (debugInfo.owner) {
copy.owner = normalizeComponentInfo(debugInfo.owner);
}
return copy;
} else {
return debugInfo;
}
}
function getDebugInfo(obj) {
const debugInfo = obj._debugInfo;
if (debugInfo) {
const copy = [];
for (let i = 0; i < debugInfo.length; i++) {
copy.push(normalizeComponentInfo(debugInfo[i]));
}
return copy;
}
return debugInfo;
}
let act;
let React;
let ReactNoop;
let ReactNoopFlightServer;
let ReactNoopFlightClient;
let getDebugInfo;
describe('ReactFlight', () => {
beforeEach(() => {
@ -91,6 +53,11 @@ describe('ReactFlight', () => {
ReactNoop = require('react-noop-renderer');
ReactNoopFlightClient = require('react-noop-renderer/flight-client');
act = require('internal-test-utils').act;
getDebugInfo = require('internal-test-utils').getDebugInfo.bind(null, {
useV8Stack: true,
ignoreRscStreamInfo: true,
});
});
afterEach(() => {

File diff suppressed because it is too large Load Diff