-
Notifications
You must be signed in to change notification settings - Fork 1.8k
test(NODE-7493): Enable source maps for accurate test debugging #4947
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
228897f
9f81852
340248e
d5fbddd
130a107
54b538c
d017df9
f0ab685
a1be2a8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| // eslint-disable-next-line @typescript-eslint/no-require-imports | ||
| require('source-map-support').install({ | ||
| hookRequire: true | ||
| }); |
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Love the idea of checking programmatically that the correct line is reported. But the current implementation is a bit flaky: we are hard-coding |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| // These import-type lines are completely erased by the TypeScript compiler | ||
| // (no blank-line placeholder is left behind), so the compiled JS has fewer | ||
| // lines than this source file. That shifts every subsequent line upward in | ||
| // the JS output. | ||
| import type { Document as _Doc } from 'bson'; | ||
| import { expect } from 'chai'; | ||
|
|
||
| import type { | ||
| AbstractCursor as _AbC, | ||
| AggregationCursor as _AC, | ||
| ChangeStream as _CS, | ||
| ClientSession as _Sess, | ||
| Collection as _Col, | ||
| Db as _Db, | ||
| FindCursor as _FC, | ||
| GridFSBucket as _GB, | ||
| MongoClient as _MC | ||
| } from '../../mongodb'; | ||
|
|
||
| // ─── This Error is created at line 31 in the TypeScript source. ─────────── | ||
| // The twelve `import type` lines above are erased without replacement, so | ||
| // in the compiled JS this falls on line 31 − 12 = line 19. | ||
| // | ||
| // ts-node's bundled `@cspotcode/source-map-support` patches | ||
| // Error.prepareStackTrace so `error.stack` already shows the correct TS | ||
| // line. We DISABLE that patch to see what V8 reports natively. | ||
| // | ||
| // OLD commit (no --enable-source-maps): V8 says line 19 ← WRONG | ||
| // NEW commit ( --enable-source-maps): V8 says line 31 ← correct | ||
| const TS_SOURCE_LINE = 31; // must match the line below | ||
| const errorAtKnownLine = new Error('source-map probe'); // ← line 31 | ||
|
|
||
| /** | ||
| * Capture a raw V8 stack frame by temporarily removing | ||
| * `@cspotcode/source-map-support`'s prepareStackTrace override (installed | ||
| * by ts-node) so we see exactly what V8 reports — with or without its own | ||
| * source-map awareness. | ||
| */ | ||
| function rawV8FrameOf(err: Error): { | ||
| file: string | null; | ||
| line: number | null; | ||
| col: number | null; | ||
| } { | ||
| const saved = Error.prepareStackTrace; | ||
| // Null → V8 uses its built-in formatter (honours --enable-source-maps). | ||
| Error.prepareStackTrace = undefined as unknown as typeof Error.prepareStackTrace; | ||
| const raw = err.stack ?? ''; // triggers V8 formatting with no hook | ||
| Error.prepareStackTrace = saved; | ||
|
|
||
| // First "at …" line: " at Object.<anonymous> (/abs/path/file.ts:LINE:COL)" | ||
| const match = raw.split('\n')[1]?.match(/\((.+):(\d+):(\d+)\)$/); | ||
| if (!match) return { file: null, line: null, col: null }; | ||
| return { file: match[1], line: Number(match[2]), col: Number(match[3]) }; | ||
| } | ||
|
|
||
| describe('Source maps', function () { | ||
| it('report the correct line number when enabled', function () { | ||
| const frame = rawV8FrameOf(errorAtKnownLine); | ||
|
|
||
| if (process.env.VERBOSE) { | ||
| console.error('\n ── raw V8 frame (prepareStackTrace bypassed) ──'); | ||
| console.error(` file : ${frame.file}`); | ||
| console.error(` line : ${frame.line} (TypeScript source line is ${TS_SOURCE_LINE})`); | ||
| console.error(` col : ${frame.col}`); | ||
| console.error( | ||
| ` ${frame.line === TS_SOURCE_LINE ? '✔ line matches TS source' : `✘ line ${frame.line} ≠ TS source line ${TS_SOURCE_LINE} — source maps not applied by V8`}` | ||
| ); | ||
| } | ||
| expect(frame.line).to.equal( | ||
| TS_SOURCE_LINE, | ||
| `V8 reported line ${frame.line} but TypeScript source line is ${TS_SOURCE_LINE}. ` + | ||
| `This means --enable-source-maps is absent and V8 is reading the compiled-JS ` + | ||
| `line number instead of the original TypeScript line.` | ||
| ); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this change is what makes it all working well. If you get
source-map-supportback - it will produce correct lines and stack traces (so we will cover both: V8 with this flag for debuggers, and source-map-support covers test output).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, spoke over a call with @nbbeeken and I'll be pushing a change with this and/or the require hook back in places.