Allow overriding the mapping from source file to source map.
This is done with the new retrieveSourceMap option to sourcemap.install. This is useful if you have another way of finding your source maps (and can avoid sync reads). Also, allow source maps to not have an URL, and don't write to a global named mapSourcePosition.
This commit is contained in:
parent
51db253332
commit
1cf5ce0f7d
@ -2,38 +2,58 @@ var SourceMapConsumer = require('source-map').SourceMapConsumer;
|
|||||||
var path = require('path');
|
var path = require('path');
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
|
|
||||||
exports.mapSourcePosition = mapSourcePosition = function(cache, position) {
|
// Can be overridden by the retrieveSourceMap option to install. Takes a
|
||||||
|
// generated source filename; returns a {map, optional url} object, or null if
|
||||||
|
// there is no source map. The map field may be either a string or the parsed
|
||||||
|
// JSON object (ie, it must be a valid argument to the SourceMapConsumer
|
||||||
|
// constructor).
|
||||||
|
var retrieveSourceMap = function (source) {
|
||||||
|
if (!fs.existsSync(source))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// Get the URL of the source map
|
||||||
|
var fileData = fs.readFileSync(source, 'utf8');
|
||||||
|
var match = /\/\/[#@]\s*sourceMappingURL=(.*)\s*$/m.exec(fileData);
|
||||||
|
if (!match) return null;
|
||||||
|
var sourceMappingURL = match[1];
|
||||||
|
|
||||||
|
// Read the contents of the source map
|
||||||
|
var sourceMapData;
|
||||||
|
var dataUrlPrefix = "data:application/json;base64,";
|
||||||
|
if (sourceMappingURL.slice(0, dataUrlPrefix.length).toLowerCase() == dataUrlPrefix) {
|
||||||
|
// Support source map URL as a data url
|
||||||
|
sourceMapData = new Buffer(sourceMappingURL.slice(dataUrlPrefix.length), "base64").toString();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Support source map URLs relative to the source URL
|
||||||
|
var dir = path.dirname(source);
|
||||||
|
sourceMappingURL = path.resolve(dir, sourceMappingURL);
|
||||||
|
|
||||||
|
if (fs.existsSync(sourceMappingURL)) {
|
||||||
|
sourceMapData = fs.readFileSync(sourceMappingURL, 'utf8');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sourceMapData) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
url: sourceMappingURL,
|
||||||
|
map: sourceMapData
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var mapSourcePosition = exports.mapSourcePosition = function(cache, position) {
|
||||||
var sourceMap = cache[position.source];
|
var sourceMap = cache[position.source];
|
||||||
if (!sourceMap && fs.existsSync(position.source)) {
|
if (!sourceMap) {
|
||||||
// Get the URL of the source map
|
// Call the (overrideable) retrieveSourceMap function to get the source map.
|
||||||
var fileData = fs.readFileSync(position.source, 'utf8');
|
var urlAndMap = retrieveSourceMap(position.source);
|
||||||
var match = /\/\/[#@]\s*sourceMappingURL=(.*)\s*$/m.exec(fileData);
|
if (urlAndMap) {
|
||||||
if (!match) return position;
|
sourceMap = cache[position.source] = {
|
||||||
var sourceMappingURL = match[1];
|
url: urlAndMap.url,
|
||||||
|
map: new SourceMapConsumer(urlAndMap.map)
|
||||||
// Read the contents of the source map
|
|
||||||
var sourceMapData;
|
|
||||||
var dataUrlPrefix = "data:application/json;base64,";
|
|
||||||
if (sourceMappingURL.slice(0, dataUrlPrefix.length).toLowerCase() == dataUrlPrefix) {
|
|
||||||
// Support source map URL as a data url
|
|
||||||
sourceMapData = new Buffer(sourceMappingURL.slice(dataUrlPrefix.length), "base64").toString();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Support source map URLs relative to the source URL
|
|
||||||
var dir = path.dirname(position.source);
|
|
||||||
sourceMappingURL = path.resolve(dir, sourceMappingURL);
|
|
||||||
|
|
||||||
if (fs.existsSync(sourceMappingURL)) {
|
|
||||||
sourceMapData = fs.readFileSync(sourceMappingURL, 'utf8');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sourceMapData) {
|
|
||||||
sourceMap = {
|
|
||||||
url: sourceMappingURL,
|
|
||||||
map: new SourceMapConsumer(sourceMapData)
|
|
||||||
};
|
};
|
||||||
cache[position.source] = sourceMap;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,13 +67,15 @@ exports.mapSourcePosition = mapSourcePosition = function(cache, position) {
|
|||||||
// better to give a precise location in the compiled file than a vague
|
// better to give a precise location in the compiled file than a vague
|
||||||
// location in the original file.
|
// location in the original file.
|
||||||
if (originalPosition.source !== null) {
|
if (originalPosition.source !== null) {
|
||||||
originalPosition.source = path.resolve(path.dirname(sourceMap.url), originalPosition.source);
|
if (sourceMap.url) {
|
||||||
|
originalPosition.source = path.resolve(path.dirname(sourceMap.url), originalPosition.source);
|
||||||
|
}
|
||||||
return originalPosition;
|
return originalPosition;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return position;
|
return position;
|
||||||
}
|
};
|
||||||
|
|
||||||
// Parses code generated by FormatEvalOrigin(), a function inside V8:
|
// Parses code generated by FormatEvalOrigin(), a function inside V8:
|
||||||
// https://code.google.com/p/v8/source/browse/trunk/src/messages.js
|
// https://code.google.com/p/v8/source/browse/trunk/src/messages.js
|
||||||
@ -162,6 +184,11 @@ exports.install = function(options) {
|
|||||||
var installHandler = 'handleUncaughtExceptions' in options ?
|
var installHandler = 'handleUncaughtExceptions' in options ?
|
||||||
options.handleUncaughtExceptions : true;
|
options.handleUncaughtExceptions : true;
|
||||||
|
|
||||||
|
// Allow source maps to be found by methods other than reading the files
|
||||||
|
// directly from disk.
|
||||||
|
if (options.retrieveSourceMap)
|
||||||
|
retrieveSourceMap = options.retrieveSourceMap;
|
||||||
|
|
||||||
// Provide the option to not install the uncaught exception handler. This is
|
// Provide the option to not install the uncaught exception handler. This is
|
||||||
// to support other uncaught exception handlers (in test frameworks, for
|
// to support other uncaught exception handlers (in test frameworks, for
|
||||||
// example). If this handler is not installed and there are no other uncaught
|
// example). If this handler is not installed and there are no other uncaught
|
||||||
|
Loading…
Reference in New Issue
Block a user