diff --git a/lib/coffee-script/browser.js b/lib/coffee-script/browser.js index abf75d3d..abe8fa17 100644 --- a/lib/coffee-script/browser.js +++ b/lib/coffee-script/browser.js @@ -32,16 +32,13 @@ return; } - if ((typeof btoa !== "undefined" && btoa !== null) && (typeof JSON !== "undefined" && JSON !== null) && (typeof unescape !== "undefined" && unescape !== null) && (typeof encodeURIComponent !== "undefined" && encodeURIComponent !== null)) { + if ((typeof btoa !== "undefined" && btoa !== null) && (typeof JSON !== "undefined" && JSON !== null)) { compile = function(code, options) { - var js, ref, v3SourceMap; if (options == null) { options = {}; } - options.sourceMap = true; - options.inline = true; - ref = CoffeeScript.compile(code, options), js = ref.js, v3SourceMap = ref.v3SourceMap; - return js + "\n//# sourceMappingURL=data:application/json;base64," + (btoa(unescape(encodeURIComponent(v3SourceMap)))) + "\n//# sourceURL=coffeescript"; + options.inlineMap = true; + return CoffeeScript.compile(code, options); }; } diff --git a/lib/coffee-script/coffee-script.js b/lib/coffee-script/coffee-script.js index 9dd32063..eafb50a1 100644 --- a/lib/coffee-script/coffee-script.js +++ b/lib/coffee-script/coffee-script.js @@ -1,6 +1,6 @@ // Generated by CoffeeScript 1.10.0 (function() { - var Lexer, SourceMap, compile, ext, fn1, formatSourcePosition, fs, getSourceMap, helpers, i, len, lexer, parser, path, ref, sourceMaps, vm, withPrettyErrors, + var Lexer, SourceMap, base64encode, compile, ext, fn1, formatSourcePosition, fs, getSourceMap, helpers, i, len, lexer, parser, path, ref, sourceMaps, vm, withPrettyErrors, hasProp = {}.hasOwnProperty, indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; @@ -24,6 +24,17 @@ exports.helpers = helpers; + base64encode = function(src) { + switch (false) { + case typeof Buffer !== 'function': + return new Buffer(src).toString('base64'); + case typeof btoa !== 'function': + return btoa(src); + default: + throw new Error('Unable to base64 encode inline sourcemap.'); + } + }; + withPrettyErrors = function(fn) { return function(code, options) { var err; @@ -43,10 +54,11 @@ }; exports.compile = compile = withPrettyErrors(function(code, options) { - var answer, currentColumn, currentLine, extend, fragment, fragments, header, i, js, len, map, merge, newLines, token, tokens; + var answer, currentColumn, currentLine, extend, fragment, fragments, generateSourceMap, header, i, js, len, map, merge, newLines, ref, sourceMapDataURI, sourceURL, token, tokens, v3SourceMap; merge = helpers.merge, extend = helpers.extend; options = extend({}, options); - if (options.sourceMap) { + generateSourceMap = options.sourceMap || options.inlineMap; + if (generateSourceMap) { map = new SourceMap; } tokens = lexer.tokenize(code, options); @@ -73,7 +85,7 @@ js = ""; for (i = 0, len = fragments.length; i < len; i++) { fragment = fragments[i]; - if (options.sourceMap) { + if (generateSourceMap) { if (fragment.locationData && !/^[;\s]*$/.test(fragment.code)) { map.add([fragment.locationData.first_line, fragment.locationData.first_column], [currentLine, currentColumn], { noReplace: true @@ -93,12 +105,20 @@ header = "Generated by CoffeeScript " + this.VERSION; js = "// " + header + "\n" + js; } + if (generateSourceMap) { + v3SourceMap = map.generate(options, code); + } + if (options.inlineMap) { + sourceMapDataURI = "//# sourceMappingURL=data:application/json;base64," + (base64encode(v3SourceMap)); + sourceURL = "//# sourceURL=" + ((ref = options.filename) != null ? ref : 'coffeescript'); + js = js + "\n" + sourceMapDataURI + "\n" + sourceURL; + } if (options.sourceMap) { answer = { js: js }; answer.sourceMap = map; - answer.v3SourceMap = map.generate(options, code); + answer.v3SourceMap = v3SourceMap; return answer; } else { return js; @@ -218,17 +238,21 @@ } } - exports._compileFile = function(filename, sourceMap) { + exports._compileFile = function(filename, sourceMap, inlineMap) { var answer, err, raw, stripped; if (sourceMap == null) { sourceMap = false; } + if (inlineMap == null) { + inlineMap = false; + } raw = fs.readFileSync(filename, 'utf8'); stripped = raw.charCodeAt(0) === 0xFEFF ? raw.substring(1) : raw; try { answer = compile(stripped, { filename: filename, sourceMap: sourceMap, + inlineMap: inlineMap, literate: helpers.isLiterate(filename) }); } catch (error) { diff --git a/lib/coffee-script/command.js b/lib/coffee-script/command.js index ffa23a68..adcb91e9 100644 --- a/lib/coffee-script/command.js +++ b/lib/coffee-script/command.js @@ -35,7 +35,7 @@ BANNER = 'Usage: coffee [options] path/to/script.coffee -- [args]\n\nIf called without options, `coffee` will run your script.'; - SWITCHES = [['-b', '--bare', 'compile without a top-level function wrapper'], ['-c', '--compile', 'compile to JavaScript and save as .js files'], ['-e', '--eval', 'pass a string from the command line as input'], ['-h', '--help', 'display this help message'], ['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-j', '--join [FILE]', 'concatenate the source CoffeeScript before compiling'], ['-m', '--map', 'generate source map and save as .js.map files'], ['-n', '--nodes', 'print out the parse tree that the parser produces'], ['--nodejs [ARGS]', 'pass options directly to the "node" binary'], ['--no-header', 'suppress the "Generated by" header'], ['-o', '--output [DIR]', 'set the output directory for compiled JavaScript'], ['-p', '--print', 'print out the compiled JavaScript'], ['-r', '--require [MODULE*]', 'require the given module before eval or REPL'], ['-s', '--stdio', 'listen for and compile scripts over stdio'], ['-l', '--literate', 'treat stdio as literate style coffee-script'], ['-t', '--tokens', 'print out the tokens that the lexer/rewriter produce'], ['-v', '--version', 'display the version number'], ['-w', '--watch', 'watch scripts for changes and rerun commands']]; + SWITCHES = [['-b', '--bare', 'compile without a top-level function wrapper'], ['-c', '--compile', 'compile to JavaScript and save as .js files'], ['-e', '--eval', 'pass a string from the command line as input'], ['-h', '--help', 'display this help message'], ['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-j', '--join [FILE]', 'concatenate the source CoffeeScript before compiling'], ['-m', '--map', 'generate source map and save as .js.map files'], ['-M', '--inline-map', 'generate source map and include it directly in output'], ['-n', '--nodes', 'print out the parse tree that the parser produces'], ['--nodejs [ARGS]', 'pass options directly to the "node" binary'], ['--no-header', 'suppress the "Generated by" header'], ['-o', '--output [DIR]', 'set the output directory for compiled JavaScript'], ['-p', '--print', 'print out the compiled JavaScript'], ['-r', '--require [MODULE*]', 'require the given module before eval or REPL'], ['-s', '--stdio', 'listen for and compile scripts over stdio'], ['-l', '--literate', 'treat stdio as literate style coffee-script'], ['-t', '--tokens', 'print out the tokens that the lexer/rewriter produce'], ['-v', '--version', 'display the version number'], ['-w', '--watch', 'watch scripts for changes and rerun commands']]; opts = {}; @@ -559,7 +559,8 @@ literate: opts.literate || helpers.isLiterate(filename), bare: opts.bare, header: opts.compile && !opts['no-header'], - sourceMap: opts.map + sourceMap: opts.map, + inlineMap: opts['inline-map'] }; if (filename) { if (base) { diff --git a/lib/coffee-script/register.js b/lib/coffee-script/register.js index 14f75a14..93cc6e7f 100644 --- a/lib/coffee-script/register.js +++ b/lib/coffee-script/register.js @@ -12,7 +12,7 @@ loadFile = function(module, filename) { var answer; - answer = CoffeeScript._compileFile(filename, false); + answer = CoffeeScript._compileFile(filename, false, true); return module._compile(answer, filename); }; diff --git a/src/register.coffee b/src/register.coffee index f584b5a6..2cbcc662 100644 --- a/src/register.coffee +++ b/src/register.coffee @@ -5,7 +5,7 @@ path = require 'path' # Load and run a CoffeeScript file for Node, stripping any `BOM`s. loadFile = (module, filename) -> - answer = CoffeeScript._compileFile filename, yes, yes + answer = CoffeeScript._compileFile filename, no, yes module._compile answer, filename # If the installed version of Node supports `require.extensions`, register