1// Flags: --enable-source-maps 2'use strict'; 3 4require('../common'); 5const assert = require('assert'); 6const { findSourceMap, SourceMap } = require('module'); 7const { readFileSync } = require('fs'); 8 9// findSourceMap() can lookup source-maps based on URIs, in the 10// non-exceptional case. 11{ 12 require('../fixtures/source-map/disk-relative-path.js'); 13 const sourceMap = findSourceMap( 14 require.resolve('../fixtures/source-map/disk-relative-path.js') 15 ); 16 const { 17 originalLine, 18 originalColumn, 19 originalSource 20 } = sourceMap.findEntry(0, 29); 21 assert.strictEqual(originalLine, 2); 22 assert.strictEqual(originalColumn, 4); 23 assert(originalSource.endsWith('disk.js')); 24} 25 26// findSourceMap() can be used in Error.prepareStackTrace() to lookup 27// source-map attached to error. 28{ 29 let callSite; 30 let sourceMap; 31 Error.prepareStackTrace = (error, trace) => { 32 const throwingRequireCallSite = trace[0]; 33 if (throwingRequireCallSite.getFileName().endsWith('typescript-throw.js')) { 34 sourceMap = findSourceMap(throwingRequireCallSite.getFileName(), error); 35 callSite = throwingRequireCallSite; 36 } 37 }; 38 try { 39 // Require a file that throws an exception, and has a source map. 40 require('../fixtures/source-map/typescript-throw.js'); 41 } catch (err) { 42 err.stack; // Force prepareStackTrace() to be called. 43 } 44 assert(callSite); 45 assert(sourceMap); 46 const { 47 generatedLine, 48 generatedColumn, 49 originalLine, 50 originalColumn, 51 originalSource 52 } = sourceMap.findEntry( 53 callSite.getLineNumber() - 1, 54 callSite.getColumnNumber() - 1 55 ); 56 57 assert.strictEqual(generatedLine, 19); 58 assert.strictEqual(generatedColumn, 14); 59 60 assert.strictEqual(originalLine, 17); 61 assert.strictEqual(originalColumn, 10); 62 assert(originalSource.endsWith('typescript-throw.ts')); 63} 64 65// SourceMap can be instantiated with Source Map V3 object as payload. 66{ 67 const payload = JSON.parse(readFileSync( 68 require.resolve('../fixtures/source-map/disk.map'), 'utf8' 69 )); 70 const sourceMap = new SourceMap(payload); 71 const { 72 originalLine, 73 originalColumn, 74 originalSource 75 } = sourceMap.findEntry(0, 29); 76 assert.strictEqual(originalLine, 2); 77 assert.strictEqual(originalColumn, 4); 78 assert(originalSource.endsWith('disk.js')); 79 // The stored payload should be a clone: 80 assert.strictEqual(payload.mappings, sourceMap.payload.mappings); 81 assert.notStrictEqual(payload, sourceMap.payload); 82 assert.strictEqual(payload.sources[0], sourceMap.payload.sources[0]); 83 assert.notStrictEqual(payload.sources, sourceMap.payload.sources); 84} 85 86// Test various known decodings to ensure decodeVLQ works correctly. 87{ 88 function makeMinimalMap(column) { 89 return { 90 sources: ['test.js'], 91 // Mapping from the 0th line, 0th column of the output file to the 0th 92 // source file, 0th line, ${column}th column. 93 mappings: `AAA${column}`, 94 }; 95 } 96 const knownDecodings = { 97 'A': 0, 98 'B': -2147483648, 99 'C': 1, 100 'D': -1, 101 'E': 2, 102 'F': -2, 103 104 // 2^31 - 1, maximum values 105 '+/////D': 2147483647, 106 '8/////D': 2147483646, 107 '6/////D': 2147483645, 108 '4/////D': 2147483644, 109 '2/////D': 2147483643, 110 '0/////D': 2147483642, 111 112 // -2^31 + 1, minimum values 113 '//////D': -2147483647, 114 '9/////D': -2147483646, 115 '7/////D': -2147483645, 116 '5/////D': -2147483644, 117 '3/////D': -2147483643, 118 '1/////D': -2147483642, 119 }; 120 121 for (const column in knownDecodings) { 122 const sourceMap = new SourceMap(makeMinimalMap(column)); 123 const { originalColumn } = sourceMap.findEntry(0, 0); 124 assert.strictEqual(originalColumn, knownDecodings[column]); 125 } 126} 127 128// Test that generated columns are sorted when a negative offset is 129// observed, see: https://github.com/mozilla/source-map/pull/92 130{ 131 function makeMinimalMap(generatedColumns, originalColumns) { 132 return { 133 sources: ['test.js'], 134 // Mapping from the 0th line, ${g}th column of the output file to the 0th 135 // source file, 0th line, ${column}th column. 136 mappings: generatedColumns.map((g, i) => `${g}AA${originalColumns[i]}`) 137 .join(',') 138 }; 139 } 140 // U = 10 141 // F = -2 142 // A = 0 143 // E = 2 144 const sourceMap = new SourceMap(makeMinimalMap( 145 ['U', 'F', 'F'], 146 ['A', 'E', 'E'] 147 )); 148 assert.strictEqual(sourceMap.findEntry(0, 6).originalColumn, 4); 149 assert.strictEqual(sourceMap.findEntry(0, 8).originalColumn, 2); 150 assert.strictEqual(sourceMap.findEntry(0, 10).originalColumn, 0); 151} 152