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