fix: clamp async stack trace separator repeat count (#3035)

Clamp the repeat count in `formatAsyncFragment` (`Math.max(0,
separatorLineLength - prefix.length)`) so that async stack trace
fragments with descriptions longer than 35 characters (such as React
`console.createTask` component tags) do not throw `RangeError: Invalid
count value`.

Fixes #3031
This commit is contained in:
yulunz authored and GitHub committed 2026-10-12 08:14:46 +00:00
1 parent 6f34441525
commit 93e06ab21f
3 files changed
+64 -1

No files matched your search

+2 -1
View File
@@ -438,7 +438,8 @@ function formatAsyncFragment(
const separatorLineLength = 40;
const prefix = `--- ${fragment.description || 'async'} `;
const separator = prefix + '-'.repeat(separatorLineLength - prefix.length);
const separator =
prefix + '-'.repeat(Math.max(0, separatorLineLength - prefix.length));
return [separator, ...formattedFrames];
}
@@ -321,6 +321,27 @@ at schedule (util.ts:5:2)
Note: line and column numbers use 1-based indexing
`;
exports[`ConsoleFormatter > toStringDetailed/toJSONDetailed > formats an async fragment with a description longer than the separator line toJSONDetailed 1`] = `
{
"id": 17,
"type": "error",
"text": "TypeError: Cannot read properties of undefined",
"argsCount": 0,
"args": [],
"stackTrace": "at MyVeryLongReactComponentNameThatExceedsFortyCharacters (Component.tsx:10:2)\\n--- <MyVeryLongReactComponentNameThatExceedsFortyCharacters> \\nat App (App.tsx:5:2)\\nNote: line and column numbers use 1-based indexing"
}
`;
exports[`ConsoleFormatter > toStringDetailed/toJSONDetailed > formats an async fragment with a description longer than the separator line toStringDetailed 1`] = `
ID: 17
Message: error> TypeError: Cannot read properties of undefined
### Stack trace
at MyVeryLongReactComponentNameThatExceedsFortyCharacters (Component.tsx:10:2)
--- <MyVeryLongReactComponentNameThatExceedsFortyCharacters>
at App (App.tsx:5:2)
Note: line and column numbers use 1-based indexing
`;
exports[`ConsoleFormatter > toStringDetailed/toJSONDetailed > formats frames without a name or url and unnamed async fragments toJSONDetailed 1`] = `
{
"id": 16,
+41
View File
@@ -803,5 +803,46 @@ describe('ConsoleFormatter', () => {
});
},
);
formatterTestDetailed(
'formats an async fragment with a description longer than the separator line',
async () => {
const message = createMockMessage({
type: () => 'error',
text: () => 'TypeError: Cannot read properties of undefined',
});
const stackTrace = {
syncFragment: {
frames: [
{
line: 10,
column: 2,
url: 'Component.tsx',
name: 'MyVeryLongReactComponentNameThatExceedsFortyCharacters',
},
],
},
asyncFragments: [
{
description:
'<MyVeryLongReactComponentNameThatExceedsFortyCharacters>',
frames: [
{
line: 5,
column: 2,
url: 'App.tsx',
name: 'App',
},
],
},
],
} as unknown as DevTools.StackTrace.StackTrace.StackTrace;
return await ConsoleFormatter.from(message, {
id: 17,
resolvedStackTraceForTesting: stackTrace,
});
},
);
});
});