diff --git a/src/browser.coffee b/src/browser.coffee index 53a16fc5..4cc92548 100644 --- a/src/browser.coffee +++ b/src/browser.coffee @@ -14,7 +14,7 @@ CoffeeScript.eval = (code, options = {}) -> # Running code does not provide access to this scope. CoffeeScript.run = (code, options = {}) -> - options.bare = on + options.bare = on options.shiftLine = on Function(compile code, options)() @@ -24,12 +24,10 @@ return unless window? # Include source maps where possible. If we've got a base64 encoder, a # JSON serializer, and tools for escaping unicode characters, we're good to go. # Ported from https://developer.mozilla.org/en-US/docs/DOM/window.btoa -if btoa? and JSON? and unescape? and encodeURIComponent? +if btoa? and JSON? compile = (code, options = {}) -> - options.sourceMap = true - options.inline = true - {js, v3SourceMap} = CoffeeScript.compile code, options - "#{js}\n//# sourceMappingURL=data:application/json;base64,#{btoa unescape encodeURIComponent v3SourceMap}\n//# sourceURL=coffeescript" + options.inlineMap = true + CoffeeScript.compile code, options # Load a remote script from the current domain via XHR. CoffeeScript.load = (url, callback, options = {}, hold = false) -> diff --git a/src/coffee-script.coffee b/src/coffee-script.coffee index 69957fd9..bddd04e7 100644 --- a/src/coffee-script.coffee +++ b/src/coffee-script.coffee @@ -19,6 +19,15 @@ exports.FILE_EXTENSIONS = ['.coffee', '.litcoffee', '.coffee.md'] # Expose helpers for testing. exports.helpers = helpers +# Function that allows for btoa in both nodejs and the browser. +base64encode = (src) -> switch + when typeof Buffer is 'function' + new Buffer(src).toString('base64') + when typeof btoa is 'function' + btoa(src) + else + throw new Error('Unable to base64 encode inline sourcemap.') + # Function wrapper to add source file information to SyntaxErrors thrown by the # lexer/parser/compiler. withPrettyErrors = (fn) -> @@ -42,7 +51,10 @@ exports.compile = compile = withPrettyErrors (code, options) -> {merge, extend} = helpers options = extend {}, options - if options.sourceMap + if options.inlineMap + options.sourceMap ?= yes + + if options.sourceMap map = new SourceMap tokens = lexer.tokenize code, options @@ -84,10 +96,17 @@ exports.compile = compile = withPrettyErrors (code, options) -> js = "// #{header}\n#{js}" if options.sourceMap - answer = {js} - answer.sourceMap = map - answer.v3SourceMap = map.generate(options, code) - answer + v3SourceMap = map.generate(options, code) + + if options.inlineMap + sourceMapDataURI = "//# sourceMappingURL=data:application/json;base64,#{base64encode v3SourceMap}" + sourceURL = "//# sourceURL=#{options.filename ? 'coffeescript'}" + "#{js}\n#{sourceMapDataURI}\n#{sourceURL}" + else + answer = {js} + answer.sourceMap = map + answer.v3SourceMap = map.generate(options, code) + answer else js @@ -181,12 +200,12 @@ if require.extensions Use CoffeeScript.register() or require the coffee-script/register module to require #{ext} files. """ -exports._compileFile = (filename, sourceMap = no) -> +exports._compileFile = (filename, sourceMap = no, inlineMap = no) -> raw = fs.readFileSync filename, 'utf8' stripped = if raw.charCodeAt(0) is 0xFEFF then raw.substring 1 else raw try - answer = compile(stripped, {filename, sourceMap, literate: helpers.isLiterate filename}) + answer = compile(stripped, {filename, sourceMap, inlineMap, literate: helpers.isLiterate filename}) catch err # As the filename and code of a dynamically loaded file will be different # from the original file compiled with CoffeeScript.run, add that diff --git a/src/command.coffee b/src/command.coffee index 4b3aeea2..3ddf6de6 100644 --- a/src/command.coffee +++ b/src/command.coffee @@ -39,6 +39,7 @@ SWITCHES = [ ['-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'] @@ -413,6 +414,7 @@ compileOptions = (filename, base) -> bare: opts.bare header: opts.compile and not opts['no-header'] sourceMap: opts.map + inlineMap: opts['inline-map'] } if filename if base diff --git a/src/register.coffee b/src/register.coffee index 1108513a..f584b5a6 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, false + answer = CoffeeScript._compileFile filename, yes, yes module._compile answer, filename # If the installed version of Node supports `require.extensions`, register