Skip to content

Commit b68e0d1

Browse files
BridgeARtargos
authored andcommitted
util: fix error's namespaced node_modules highlighting using inspect
When inspecting errors, node_modules are highlighted with an underscore. So far namespaced modules only highlighted the namespace but not the rest of the module name. This is fixed by matching the full name. As drive-by it improves the performance slightly by removing the regular expression in favor of indexOf to identify the right spot. PR-URL: #59446 Reviewed-By: Jordan Harband <ljharb@gmail.com>
1 parent ebe9272 commit b68e0d1

File tree

2 files changed

+41
-13
lines changed

2 files changed

+41
-13
lines changed

lib/internal/util/inspect.js

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,6 @@ const keyStrRegExp = /^[a-zA-Z_][a-zA-Z_0-9]*$/;
250250
const numberRegExp = /^(0|[1-9][0-9]*)$/;
251251

252252
const coreModuleRegExp = /^ {4}at (?:[^/\\(]+ \(|)node:(.+):\d+:\d+\)?$/;
253-
const nodeModulesRegExp = /[/\\]node_modules[/\\](.+?)(?=[/\\])/g;
254253

255254
const classRegExp = /^(\s+[^(]*?)\s*{/;
256255
// eslint-disable-next-line node-core/no-unescaped-regexp-dot
@@ -1423,16 +1422,45 @@ function removeDuplicateErrorKeys(ctx, keys, err, stack) {
14231422

14241423
function markNodeModules(ctx, line) {
14251424
let tempLine = '';
1426-
let nodeModule;
1427-
let pos = 0;
1428-
while ((nodeModule = nodeModulesRegExp.exec(line)) !== null) {
1429-
// '/node_modules/'.length === 14
1430-
tempLine += StringPrototypeSlice(line, pos, nodeModule.index + 14);
1431-
tempLine += ctx.stylize(nodeModule[1], 'module');
1432-
pos = nodeModule.index + nodeModule[0].length;
1433-
}
1434-
if (pos !== 0) {
1435-
line = tempLine + StringPrototypeSlice(line, pos);
1425+
let lastPos = 0;
1426+
let searchFrom = 0;
1427+
1428+
while (true) {
1429+
const nodeModulePosition = StringPrototypeIndexOf(line, 'node_modules', searchFrom);
1430+
if (nodeModulePosition === -1) {
1431+
break;
1432+
}
1433+
1434+
// Ensure it's a path segment: must have a path separator before and after
1435+
const separator = line[nodeModulePosition - 1];
1436+
const after = line[nodeModulePosition + 12]; // 'node_modules'.length === 12
1437+
1438+
if ((after !== '/' && after !== '\\') || (separator !== '/' && separator !== '\\')) {
1439+
// Not a proper segment; continue searching
1440+
searchFrom = nodeModulePosition + 1;
1441+
continue;
1442+
}
1443+
1444+
const moduleStart = nodeModulePosition + 13; // Include trailing separator
1445+
1446+
// Append up to and including '/node_modules/'
1447+
tempLine += StringPrototypeSlice(line, lastPos, moduleStart);
1448+
1449+
let moduleEnd = StringPrototypeIndexOf(line, separator, moduleStart);
1450+
if (line[moduleStart] === '@') {
1451+
// Namespaced modules have an extra slash: @namespace/package
1452+
moduleEnd = StringPrototypeIndexOf(line, separator, moduleEnd + 1);
1453+
}
1454+
1455+
const nodeModule = StringPrototypeSlice(line, moduleStart, moduleEnd);
1456+
tempLine += ctx.stylize(nodeModule, 'module');
1457+
1458+
lastPos = moduleEnd;
1459+
searchFrom = moduleEnd;
1460+
}
1461+
1462+
if (lastPos !== 0) {
1463+
line = tempLine + StringPrototypeSlice(line, lastPos);
14361464
}
14371465
return line;
14381466
}

test/parallel/test-util-inspect.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2837,7 +2837,7 @@ assert.strictEqual(
28372837
// Use a fake stack to verify the expected colored outcome.
28382838
const stack = [
28392839
'Error: CWD is grayed out, even cwd that are percent encoded!',
2840-
' at A.<anonymous> (/test/node_modules/foo/node_modules/bar/baz.js:2:7)',
2840+
' at A.<anonymous> (/test/node_modules/foo/node_modules/@namespace/bar/baz.js:2:7)',
28412841
' at Module._compile (node:internal/modules/cjs/loader:827:30)',
28422842
' at Fancy (node:vm:697:32)',
28432843
// This file is not an actual Node.js core file.
@@ -2862,7 +2862,7 @@ assert.strictEqual(
28622862
}
28632863
const escapedCWD = util.inspect(process.cwd()).slice(1, -1);
28642864
util.inspect(err, { colors: true }).split('\n').forEach((line, i) => {
2865-
let expected = stack[i].replace(/node_modules\/([^/]+)/gi, (_, m) => {
2865+
let expected = stack[i].replace(/node_modules\/(@[^/]+\/[^/]+|[^/]+)/gi, (_, m) => {
28662866
return `node_modules/\u001b[4m${m}\u001b[24m`;
28672867
}).replaceAll(new RegExp(`(\\(?${escapedCWD}(\\\\|/))`, 'gi'), (_, m) => {
28682868
return `\x1B[90m${m}\x1B[39m`;

0 commit comments

Comments
 (0)