Merge pull request #18 from meteor/retrieve-source-map
Allow overriding the mapping from source file to source map.
This commit is contained in:
commit
bdf2ffb6a4
@ -2,38 +2,58 @@ var SourceMapConsumer = require('source-map').SourceMapConsumer;
|
||||
var path = require('path');
|
||||
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];
|
||||
if (!sourceMap && fs.existsSync(position.source)) {
|
||||
// Get the URL of the source map
|
||||
var fileData = fs.readFileSync(position.source, 'utf8');
|
||||
var match = /\/\/[#@]\s*sourceMappingURL=(.*)\s*$/m.exec(fileData);
|
||||
if (!match) return position;
|
||||
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(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)
|
||||
if (!sourceMap) {
|
||||
// Call the (overrideable) retrieveSourceMap function to get the source map.
|
||||
var urlAndMap = retrieveSourceMap(position.source);
|
||||
if (urlAndMap) {
|
||||
sourceMap = cache[position.source] = {
|
||||
url: urlAndMap.url,
|
||||
map: new SourceMapConsumer(urlAndMap.map)
|
||||
};
|
||||
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
|
||||
// location in the original file.
|
||||
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 position;
|
||||
}
|
||||
};
|
||||
|
||||
// Parses code generated by FormatEvalOrigin(), a function inside V8:
|
||||
// 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 ?
|
||||
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
|
||||
// to support other uncaught exception handlers (in test frameworks, for
|
||||
// example). If this handler is not installed and there are no other uncaught
|
||||
|
Loading…
Reference in New Issue
Block a user