@ -2,38 +2,58 @@ var SourceMapConsumer = require('source-map').SourceMapConsumer;
var path = require ( 'path' ) ;
var fs = require ( 'fs' ) ;
exports . mapSourcePosition = 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 ) ;
// 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 ( fs . existsSync ( sourceMappingURL ) ) {
sourceMapData = fs . readFileSync ( sourceMappingURL , 'utf8' ) ;
}
}
if ( ! sourceMapData ) {
return null ;
}
if ( sourceMapData ) {
sourceMap = {
url : sourceMappingURL ,
map : new SourceMapConsumer ( sourceMapData )
return {
url : sourceMappingURL ,
map : sourceMapData
} ;
} ;
var mapSourcePosition = exports . mapSourcePosition = function ( cache , position ) {
var sourceMap = cache [ position . source ] ;
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