mirror of
https://github.com/nodejs/node.git
synced 2024-11-21 21:19:50 +01:00
9053943931
Fix: #48460 PR-URL: https://github.com/nodejs/node/pull/48461 Fixes: https://github.com/nodejs/node/issues/48460 Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
249 lines
7.4 KiB
JavaScript
249 lines
7.4 KiB
JavaScript
// Flags: --enable-source-maps
|
|
'use strict';
|
|
|
|
const common = require('../common');
|
|
const assert = require('assert');
|
|
const { findSourceMap, SourceMap } = require('module');
|
|
const { readFileSync } = require('fs');
|
|
|
|
// It should throw with invalid args.
|
|
{
|
|
[1, true, 'foo'].forEach((invalidArg) =>
|
|
assert.throws(
|
|
() => new SourceMap(invalidArg),
|
|
{
|
|
code: 'ERR_INVALID_ARG_TYPE',
|
|
name: 'TypeError',
|
|
message: 'The "payload" argument must be of type object.' +
|
|
common.invalidArgTypeHelper(invalidArg)
|
|
}
|
|
)
|
|
);
|
|
}
|
|
|
|
// `findSourceMap()` should return undefined when no source map is found.
|
|
{
|
|
const files = [
|
|
__filename,
|
|
'',
|
|
'invalid-file',
|
|
];
|
|
for (const file of files) {
|
|
const sourceMap = findSourceMap(file);
|
|
assert.strictEqual(sourceMap, undefined);
|
|
}
|
|
}
|
|
|
|
// 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'));
|
|
const {
|
|
fileName,
|
|
lineNumber,
|
|
columnNumber,
|
|
} = sourceMap.findOrigin(1, 30);
|
|
assert.strictEqual(fileName, originalSource);
|
|
assert.strictEqual(lineNumber, 3);
|
|
assert.strictEqual(columnNumber, 6);
|
|
assert(Array.isArray(sourceMap.lineLengths));
|
|
assert(!sourceMap.lineLengths.some((len) => (typeof len !== 'number')));
|
|
}
|
|
|
|
// 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());
|
|
callSite = throwingRequireCallSite;
|
|
}
|
|
};
|
|
try {
|
|
// Require a file that throws an exception, and has a source map.
|
|
require('../fixtures/source-map/typescript-throw.js');
|
|
} catch (err) {
|
|
// eslint-disable-next-line no-unused-expressions
|
|
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'));
|
|
|
|
const {
|
|
fileName,
|
|
lineNumber,
|
|
columnNumber,
|
|
} = sourceMap.findOrigin(
|
|
callSite.getLineNumber(),
|
|
callSite.getColumnNumber()
|
|
);
|
|
assert.strictEqual(fileName, originalSource);
|
|
assert.strictEqual(lineNumber, 18);
|
|
assert.strictEqual(columnNumber, 11);
|
|
}
|
|
|
|
// 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 lineLengths = readFileSync(
|
|
require.resolve('../fixtures/source-map/disk.map'), 'utf8'
|
|
).replace(/\n$/, '').split('\n').map((l) => l.length);
|
|
const sourceMap = new SourceMap(payload, { lineLengths });
|
|
const {
|
|
originalLine,
|
|
originalColumn,
|
|
originalSource
|
|
} = sourceMap.findEntry(0, 29);
|
|
assert.strictEqual(originalLine, 2);
|
|
assert.strictEqual(originalColumn, 4);
|
|
assert(originalSource.endsWith('disk.js'));
|
|
const sourceMapLineLengths = sourceMap.lineLengths;
|
|
for (let i = 0; i < sourceMapLineLengths.length; i++) {
|
|
assert.strictEqual(sourceMapLineLengths[i], lineLengths[i]);
|
|
}
|
|
assert.strictEqual(sourceMapLineLengths.length, lineLengths.length);
|
|
// 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);
|
|
}
|
|
|
|
// findEntry() and findOrigin() must return empty object instead of
|
|
// error when receiving a malformed mappings.
|
|
{
|
|
const payload = JSON.parse(readFileSync(
|
|
require.resolve('../fixtures/source-map/disk.map'), 'utf8'
|
|
));
|
|
payload.mappings = ';;;;;;;;;';
|
|
|
|
const sourceMap = new SourceMap(payload);
|
|
const result = sourceMap.findEntry(0, 5);
|
|
assert.strictEqual(typeof result, 'object');
|
|
assert.strictEqual(Object.keys(result).length, 0);
|
|
const origin = sourceMap.findOrigin(0, 5);
|
|
assert.strictEqual(typeof origin, 'object');
|
|
assert.strictEqual(Object.keys(origin).length, 0);
|
|
}
|
|
|
|
// SourceMap can be instantiated with Index Source Map V3 object as payload.
|
|
{
|
|
const payload = JSON.parse(readFileSync(
|
|
require.resolve('../fixtures/source-map/disk-index.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('section.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);
|
|
}
|