diff --git a/lib/internal/modules/cjs/loader.js b/lib/internal/modules/cjs/loader.js index f9c4a62f023a..ca5dadd5d87f 100644 --- a/lib/internal/modules/cjs/loader.js +++ b/lib/internal/modules/cjs/loader.js @@ -24,6 +24,7 @@ const { ArrayIsArray, ArrayPrototypeFilter, + ArrayPrototypeFind, ArrayPrototypeIncludes, ArrayPrototypeIndexOf, ArrayPrototypeJoin, @@ -56,6 +57,7 @@ const { StringPrototypeCharAt, StringPrototypeCharCodeAt, StringPrototypeEndsWith, + StringPrototypeIncludes, StringPrototypeIndexOf, StringPrototypeRepeat, StringPrototypeSlice, @@ -2011,11 +2013,14 @@ function loadSource(mod, filename, formatFromNode) { } function reconstructErrorStack(err, parentPath, parentSource) { - const errLine = StringPrototypeSplit( + const frames = StringPrototypeSplit( StringPrototypeSlice(err.stack, StringPrototypeIndexOf( - err.stack, ' at ')), '\n', 1)[0]; + err.stack, ' at ')), '\n'); + // Wrappers such as TracingChannel.traceSync may precede the parent frame. + const errLine = ArrayPrototypeFind( + frames, (frame) => StringPrototypeIncludes(frame, parentPath)); const { 1: line, 2: col } = - RegExpPrototypeExec(/(\d+):(\d+)\)/, errLine) || []; + RegExpPrototypeExec(/(\d+):(\d+)\)/, errLine ?? '') || []; if (line && col) { const srcLine = StringPrototypeSplit(parentSource, '\n', line)[line - 1]; const frame = `${parentPath}:${line}\n${srcLine}\n${StringPrototypeRepeat(' ', col - 1)}^\n`; diff --git a/test/es-module/test-cjs-esm-warn.js b/test/es-module/test-cjs-esm-warn.js index 0945a737fb72..cd8fbe072ab1 100644 --- a/test/es-module/test-cjs-esm-warn.js +++ b/test/es-module/test-cjs-esm-warn.js @@ -72,4 +72,24 @@ describe('CJS ↔︎ ESM interop warnings', { concurrency: !process.env.TEST_PAR assert.strictEqual(code, 1); assert.strictEqual(signal, null); }); + + it('should annotate the parent frame when require() is traced', async () => { + const { code, signal, stderr } = await spawnPromisified(execPath, [ + '--no-experimental-require-module', + '--import', + 'data:text/javascript,' + encodeURIComponent( + 'import dc from "node:diagnostics_channel";' + + 'dc.subscribe("tracing:module.require:start", () => {});'), + requiringEsm, + ]); + + assert.ok( + stderr.replace(/\r/g, '').startsWith( + `${requiringEsm}:1\nrequire('./package-type-module/esm.js');\n^\n` + ) + ); + + assert.strictEqual(code, 1); + assert.strictEqual(signal, null); + }); });