// Flags: --enable-source-maps 'use strict'; require('../common'); const assert = require('assert'); const { findSourceMap, SourceMap } = require('module'); const { readFileSync } = require('fs'); // findSourceMap() can lookup source-maps based on URIs, in the // non-exceptional case. { require('../fixtures/source-map/disk-relative-path.js'); const sourceMap = findSourceMap( require.resolve('../fixtures/source-map/disk-relative-path.js') ); const { originalLine, originalColumn, originalSource } = sourceMap.findEntry(0, 29); assert.strictEqual(originalLine, 2); assert.strictEqual(originalColumn, 4); assert(originalSource.endsWith('disk.js')); } // findSourceMap() can be used in Error.prepareStackTrace() to lookup // source-map attached to error. { let callSite; let sourceMap; Error.prepareStackTrace = (error, trace) => { const throwingRequireCallSite = trace[0]; if (throwingRequireCallSite.getFileName().endsWith('typescript-throw.js')) { sourceMap = findSourceMap(throwingRequireCallSite.getFileName(), error); callSite = throwingRequireCallSite; } }; try { // Require a file that throws an exception, and has a source map. require('../fixtures/source-map/typescript-throw.js'); } catch (err) { err.stack; // Force prepareStackTrace() to be called. } assert(callSite); assert(sourceMap); const { generatedLine, generatedColumn, originalLine, originalColumn, originalSource } = sourceMap.findEntry( callSite.getLineNumber() - 1, callSite.getColumnNumber() - 1 ); assert.strictEqual(generatedLine, 19); assert.strictEqual(generatedColumn, 14); assert.strictEqual(originalLine, 17); assert.strictEqual(originalColumn, 10); assert(originalSource.endsWith('typescript-throw.ts')); } // SourceMap can be instantiated with Source Map V3 object as payload. { const payload = JSON.parse(readFileSync( require.resolve('../fixtures/source-map/disk.map'), 'utf8' )); const sourceMap = new SourceMap(payload); const { originalLine, originalColumn, originalSource } = sourceMap.findEntry(0, 29); assert.strictEqual(originalLine, 2); assert.strictEqual(originalColumn, 4); assert(originalSource.endsWith('disk.js')); // The stored payload should be a clone: assert.strictEqual(payload.mappings, sourceMap.payload.mappings); assert.notStrictEqual(payload, sourceMap.payload); assert.strictEqual(payload.sources[0], sourceMap.payload.sources[0]); assert.notStrictEqual(payload.sources, sourceMap.payload.sources); } // Test various known decodings to ensure decodeVLQ works correctly. { function makeMinimalMap(column) { return { sources: ['test.js'], // Mapping from the 0th line, 0th column of the output file to the 0th // source file, 0th line, ${column}th column. mappings: `AAA${column}`, }; } const knownDecodings = { 'A': 0, 'B': -2147483648, 'C': 1, 'D': -1, 'E': 2, 'F': -2, // 2^31 - 1, maximum values '+/////D': 2147483647, '8/////D': 2147483646, '6/////D': 2147483645, '4/////D': 2147483644, '2/////D': 2147483643, '0/////D': 2147483642, // -2^31 + 1, minimum values '//////D': -2147483647, '9/////D': -2147483646, '7/////D': -2147483645, '5/////D': -2147483644, '3/////D': -2147483643, '1/////D': -2147483642, }; for (const column in knownDecodings) { const sourceMap = new SourceMap(makeMinimalMap(column)); const { originalColumn } = sourceMap.findEntry(0, 0); assert.strictEqual(originalColumn, knownDecodings[column]); } } // Test that generated columns are sorted when a negative offset is // observed, see: https://github.com/mozilla/source-map/pull/92 { function makeMinimalMap(generatedColumns, originalColumns) { return { sources: ['test.js'], // Mapping from the 0th line, ${g}th column of the output file to the 0th // source file, 0th line, ${column}th column. mappings: generatedColumns.map((g, i) => `${g}AA${originalColumns[i]}`) .join(',') }; } // U = 10 // F = -2 // A = 0 // E = 2 const sourceMap = new SourceMap(makeMinimalMap( ['U', 'F', 'F'], ['A', 'E', 'E'] )); assert.strictEqual(sourceMap.findEntry(0, 6).originalColumn, 4); assert.strictEqual(sourceMap.findEntry(0, 8).originalColumn, 2); assert.strictEqual(sourceMap.findEntry(0, 10).originalColumn, 0); }