Fix sourceRoot and relative path for .coffee files in generated source maps.

This commit is contained in:
Jason Walton 2013-03-06 11:05:57 -05:00
parent de8ec2beb0
commit d6e1a979e4
7 changed files with 99 additions and 32 deletions

View File

@ -1,6 +1,6 @@
// Generated by CoffeeScript 1.6.1
(function() {
var Lexer, compile, ext, fs, helpers, lexer, loadFile, parser, path, sourcemap, vm, _i, _len, _ref,
var Lexer, compile, ext, fs, generateV3SourceMapOptions, helpers, lexer, loadFile, parser, path, sourcemap, vm, _i, _len, _ref,
__hasProp = {}.hasOwnProperty;
fs = require('fs');
@ -39,16 +39,46 @@
exports.helpers = helpers;
generateV3SourceMapOptions = function(options) {
var pathDepth, sourceRoot, _j;
if (options == null) {
options = {};
}
if (!options.filename) {
return {};
} else {
if (options.jsPath) {
pathDepth = options.jsPath.split('/').length - 1;
sourceRoot = "";
if (pathDepth > 0) {
for (_j = 0; 0 <= pathDepth ? _j < pathDepth : _j > pathDepth; 0 <= pathDepth ? _j++ : _j--) {
sourceRoot += "../";
}
}
return {
sourceRoot: sourceRoot,
sourceFile: options.filename,
generatedFile: helpers.baseFileName(options.jsPath)
};
} else {
return {
sourceRoot: "",
sourceFile: helpers.baseFileName(options.filename, {
generatedFile: helpers.baseFileName(options.filename, true) + ".js"
})
};
}
}
};
exports.compile = compile = function(code, options) {
var answer, coffeeFile, currentColumn, currentLine, err, fragment, fragments, header, js, jsFile, merge, newLines, sourceMap, _j, _len1;
var answer, currentColumn, currentLine, err, fragment, fragments, header, js, merge, newLines, sourceMap, v3Options, _j, _len1;
if (options == null) {
options = {};
}
merge = exports.helpers.merge;
try {
if (options.sourceMap) {
coffeeFile = helpers.baseFileName(options.filename);
jsFile = helpers.baseFileName(options.filename, true) + ".js";
sourceMap = new sourcemap.SourceMap();
}
fragments = (parser.parse(lexer.tokenize(code, options))).compileToFragments(options);
@ -89,7 +119,8 @@
};
if (sourceMap) {
answer.sourceMap = sourceMap;
answer.v3SourceMap = sourcemap.generateV3SourceMap(sourceMap, coffeeFile, jsFile);
v3Options = generateV3SourceMapOptions(options);
answer.v3SourceMap = sourcemap.generateV3SourceMap(sourceMap, v3Options);
}
return answer;
} else {

View File

@ -149,8 +149,11 @@
compileScript = function(file, input, base) {
var compiled, err, o, options, t, task;
if (base == null) {
base = null;
}
o = opts;
options = compileOptions(file);
options = compileOptions(file, base);
try {
t = task = {
file: file,
@ -181,7 +184,7 @@
if (o.print) {
return printLine(t.output.trim());
} else if (o.compile || o.map) {
return writeJs(base, t.file, t.output, t.sourceMap);
return writeJs(base, t.file, t.output, options.jsPath, t.sourceMap);
} else if (o.lint) {
return lint(t.file, t.output);
}
@ -388,12 +391,11 @@
return path.join(dir, basename + extension);
};
writeJs = function(base, sourcePath, js, generatedSourceMap) {
var compile, jsDir, jsPath, sourceMapPath;
writeJs = function(base, sourcePath, js, jsPath, generatedSourceMap) {
var compile, jsDir, sourceMapPath;
if (generatedSourceMap == null) {
generatedSourceMap = null;
}
jsPath = outputPath(sourcePath, base);
sourceMapPath = outputPath(sourcePath, base, ".map");
jsDir = path.dirname(jsPath);
compile = function() {
@ -480,13 +482,14 @@
}
};
compileOptions = function(filename) {
compileOptions = function(filename, base) {
return {
filename: filename,
literate: helpers.isLiterate(filename),
bare: opts.bare,
header: opts.compile,
sourceMap: opts.map
sourceMap: opts.map,
jsPath: filename !== null && base !== null ? outputPath(filename, base) : null
};
};

View File

@ -113,14 +113,14 @@
})();
exports.generateV3SourceMap = function(sourceMap, sourceFile, generatedFile) {
var answer, lastGeneratedColumnWritten, lastSourceColumnWritten, lastSourceLineWritten, mappings, needComma, writingGeneratedLine;
if (sourceFile == null) {
sourceFile = null;
}
if (generatedFile == null) {
generatedFile = null;
exports.generateV3SourceMap = function(sourceMap, options) {
var answer, generatedFile, lastGeneratedColumnWritten, lastSourceColumnWritten, lastSourceLineWritten, mappings, needComma, sourceFile, sourceRoot, writingGeneratedLine;
if (options == null) {
options = {};
}
sourceRoot = options.sourceRoot || "";
sourceFile = options.sourceFile || null;
generatedFile = options.generatedFile || null;
writingGeneratedLine = 0;
lastGeneratedColumnWritten = 0;
lastSourceLineWritten = 0;
@ -150,7 +150,7 @@
answer = {
version: 3,
file: generatedFile,
sourceRoot: "",
sourceRoot: sourceRoot,
sources: sourceFile ? [sourceFile] : [],
names: [],
mappings: mappings

View File

@ -30,6 +30,30 @@ exports.VERSION = '1.6.1'
# Expose helpers for testing.
exports.helpers = helpers
generateV3SourceMapOptions = (options = {}) ->
if !options.filename
return {}
else
if options.jsPath
# jsPath is relative to the CWD. Construct a sourceRoot that gets us back to the CWD.
pathDepth = options.jsPath.split('/').length-1
sourceRoot = ""
if (pathDepth > 0) then for [0...pathDepth]
sourceRoot += "../"
return {
sourceRoot,
sourceFile: options.filename,
generatedFile: helpers.baseFileName(options.jsPath)
}
else
return {
sourceRoot: "",
sourceFile: helpers.baseFileName options.filename,
generatedFile: helpers.baseFileName(options.filename, yes) + ".js"
}
# Compile CoffeeScript code to JavaScript, using the Coffee/Jison compiler.
#
# If `options.sourceMap` is specified, then `options.filename` must also be specified.
@ -43,8 +67,6 @@ exports.compile = compile = (code, options = {}) ->
try
if options.sourceMap
coffeeFile = helpers.baseFileName options.filename
jsFile = helpers.baseFileName(options.filename, yes) + ".js"
sourceMap = new sourcemap.SourceMap()
fragments = (parser.parse lexer.tokenize(code, options)).compileToFragments options
@ -80,7 +102,8 @@ exports.compile = compile = (code, options = {}) ->
answer = {js}
if sourceMap
answer.sourceMap = sourceMap
answer.v3SourceMap = sourcemap.generateV3SourceMap sourceMap, coffeeFile, jsFile
v3Options = generateV3SourceMapOptions options
answer.v3SourceMap = sourcemap.generateV3SourceMap(sourceMap, v3Options)
answer
else
js

View File

@ -112,9 +112,9 @@ compilePath = (source, topLevel, base) ->
# Compile a single source script, containing the given code, according to the
# requested options. If evaluating the script directly sets `__filename`,
# `__dirname` and `module.filename` to be correct relative to the script's path.
compileScript = (file, input, base) ->
compileScript = (file, input, base=null) ->
o = opts
options = compileOptions file
options = compileOptions file, base
try
t = task = {file, input, options}
CoffeeScript.emit 'compile', task
@ -136,7 +136,7 @@ compileScript = (file, input, base) ->
if o.print
printLine t.output.trim()
else if o.compile || o.map
writeJs base, t.file, t.output, t.sourceMap
writeJs base, t.file, t.output, options.jsPath, t.sourceMap
else if o.lint
lint t.file, t.output
catch err
@ -264,8 +264,7 @@ outputPath = (source, base, extension=".js") ->
#
# If `generatedSourceMap` is provided, this will write a `.map` file into the
# same directory as the `.js` file.
writeJs = (base, sourcePath, js, generatedSourceMap = null) ->
jsPath = outputPath sourcePath, base
writeJs = (base, sourcePath, js, jsPath, generatedSourceMap = null) ->
sourceMapPath = outputPath sourcePath, base, ".map"
jsDir = path.dirname jsPath
compile = ->
@ -323,15 +322,18 @@ parseOptions = ->
return
# The compile-time options to pass to the CoffeeScript compiler.
compileOptions = (filename) ->
compileOptions = (filename, base) ->
{
filename
literate: helpers.isLiterate(filename)
bare: opts.bare
header: opts.compile
sourceMap: opts.map
jsPath: if (filename isnt null and base isnt null) then (outputPath filename, base) else null
}
# Start up a new Node.js instance with the arguments in `--nodejs` passed to
# the `node` binary, preserving the other options.
forkNode = ->

View File

@ -92,7 +92,11 @@ class exports.SourceMap
# Builds a V3 source map from a SourceMap object.
# Returns the generated JSON as a string.
exports.generateV3SourceMap = (sourceMap, sourceFile=null, generatedFile=null) ->
exports.generateV3SourceMap = (sourceMap, options={}) ->
sourceRoot = options.sourceRoot or ""
sourceFile = options.sourceFile or null
generatedFile = options.generatedFile or null
writingGeneratedLine = 0
lastGeneratedColumnWritten = 0
lastSourceLineWritten = 0
@ -146,7 +150,7 @@ exports.generateV3SourceMap = (sourceMap, sourceFile=null, generatedFile=null) -
answer = {
version: 3
file: generatedFile
sourceRoot: ""
sourceRoot
sources: if sourceFile then [sourceFile] else []
names: []
mappings

View File

@ -36,7 +36,11 @@ test "SourceMap tests", ->
map.addMapping [1, 9], [2, 8]
map.addMapping [3, 0], [3, 4]
eqJson (sourcemap.generateV3SourceMap map, "source.coffee", "source.js"), '{"version":3,"file":"source.js","sourceRoot":"","sources":["source.coffee"],"names":[],"mappings":"AAAA;;IACK,GAAC,CAAG;IAET"}'
testWithFilenames = sourcemap.generateV3SourceMap map, {
sourceRoot: "",
sourceFile: "source.coffee",
generatedFile: "source.js"}
eqJson testWithFilenames, '{"version":3,"file":"source.js","sourceRoot":"","sources":["source.coffee"],"names":[],"mappings":"AAAA;;IACK,GAAC,CAAG;IAET"}'
eqJson (sourcemap.generateV3SourceMap map), '{"version":3,"file":null,"sourceRoot":"","sources":[],"names":[],"mappings":"AAAA;;IACK,GAAC,CAAG;IAET"}'
# Look up a generated column - should get back the original source position.