|
| 1 | +import { expect } from 'chai'; |
| 2 | + |
| 3 | +// These import-type lines are completely erased by the TypeScript compiler |
| 4 | +// (no blank-line placeholder is left behind), so the compiled JS has fewer |
| 5 | +// lines than this source file. That shifts every subsequent line upward in |
| 6 | +// the JS output. |
| 7 | +import type { Document as _Doc } from 'bson'; |
| 8 | +import type { Collection as _Col } from '../../mongodb'; |
| 9 | +import type { MongoClient as _MC } from '../../mongodb'; |
| 10 | +import type { Db as _Db } from '../../mongodb'; |
| 11 | +import type { AggregationCursor as _AC } from '../../mongodb'; |
| 12 | +import type { FindCursor as _FC } from '../../mongodb'; |
| 13 | +import type { ChangeStream as _CS } from '../../mongodb'; |
| 14 | +import type { GridFSBucket as _GB } from '../../mongodb'; |
| 15 | +import type { ClientSession as _Sess } from '../../mongodb'; |
| 16 | +import type { AbstractCursor as _AbC } from '../../mongodb'; |
| 17 | + |
| 18 | +// ─── This Error is created at line 18 in the TypeScript source. ─────────── |
| 19 | +// The ten `import type` lines above are erased without replacement, so in |
| 20 | +// the compiled JS this falls on line 18 − 10 = line 8. |
| 21 | +// |
| 22 | +// source-map-support patches Error.prepareStackTrace so `error.stack` |
| 23 | +// already shows the correct TS line. The demo below DISABLES that patch |
| 24 | +// temporarily so we can see what V8 reports natively. |
| 25 | +// |
| 26 | +// OLD commit (no --enable-source-maps): V8 says line 8 ← WRONG |
| 27 | +// NEW commit ( --enable-source-maps): V8 says line 18 ← correct |
| 28 | +const TS_SOURCE_LINE = 18; // must match the line below |
| 29 | +const errorAtKnownLine = new Error('source-map probe'); // ← line 18 |
| 30 | + |
| 31 | +/** |
| 32 | + * Capture a raw V8 stack frame by temporarily removing |
| 33 | + * source-map-support's prepareStackTrace override so we see exactly what |
| 34 | + * V8 reports — with or without its own source-map awareness. |
| 35 | + */ |
| 36 | +function rawV8FrameOf(err: Error): { file: string | null; line: number | null; col: number | null } { |
| 37 | + const saved = Error.prepareStackTrace; |
| 38 | + // Null → V8 uses its built-in formatter (honours --enable-source-maps). |
| 39 | + Error.prepareStackTrace = undefined as unknown as typeof Error.prepareStackTrace; |
| 40 | + const raw = err.stack ?? ''; // triggers V8 formatting with no hook |
| 41 | + Error.prepareStackTrace = saved; |
| 42 | + |
| 43 | + // First "at …" line: " at Object.<anonymous> (/abs/path/file.ts:LINE:COL)" |
| 44 | + const match = raw.split('\n')[1]?.match(/\((.+):(\d+):(\d+)\)$/); |
| 45 | + if (!match) return { file: null, line: null, col: null }; |
| 46 | + return { file: match[1], line: Number(match[2]), col: Number(match[3]) }; |
| 47 | +} |
| 48 | + |
| 49 | +describe('Source map verification (NODE-7493)', function () { |
| 50 | + it('V8 native stack frame reports correct TypeScript line number', function () { |
| 51 | + const frame = rawV8FrameOf(errorAtKnownLine); |
| 52 | + |
| 53 | + console.log('\n ── raw V8 frame (prepareStackTrace bypassed) ──'); |
| 54 | + console.log(` file : ${frame.file}`); |
| 55 | + console.log(` line : ${frame.line} (TypeScript source line is ${TS_SOURCE_LINE})`); |
| 56 | + console.log(` col : ${frame.col}`); |
| 57 | + console.log( |
| 58 | + ` ${frame.line === TS_SOURCE_LINE ? '✔ line matches TS source' : `✘ line ${frame.line} ≠ TS source line ${TS_SOURCE_LINE} — source maps not applied by V8`}` |
| 59 | + ); |
| 60 | + |
| 61 | + expect(frame.line).to.equal( |
| 62 | + TS_SOURCE_LINE, |
| 63 | + `V8 reported line ${frame.line} but TypeScript source line is ${TS_SOURCE_LINE}. ` + |
| 64 | + `This means --enable-source-maps is absent and V8 is reading the compiled-JS ` + |
| 65 | + `line number instead of the original TypeScript line.` |
| 66 | + ); |
| 67 | + }); |
| 68 | +}); |
0 commit comments