Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/internal-test-utils/ReactInternalTestUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');

Expand Down
131 changes: 131 additions & 0 deletions packages/internal-test-utils/debugInfo.js
Original file line number Diff line number Diff line change
@@ -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;
}
49 changes: 6 additions & 43 deletions packages/react-client/src/__tests__/ReactFlight-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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, '\\/');
Expand All @@ -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 = [];
Expand Down Expand Up @@ -132,6 +89,7 @@ let NoErrorExpected;
let Scheduler;
let assertLog;
let assertConsoleErrorDev;
let getDebugInfo;

describe('ReactFlight', () => {
beforeEach(() => {
Expand Down Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(() => {
Expand Down Expand Up @@ -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(() => {
Expand Down
Loading
Loading