Add inline sourcemap support

This commit is contained in:
Dylan Piercey
2015-09-27 20:08:39 -06:00
parent 36e80d7f5c
commit 347a625525
4 changed files with 33 additions and 14 deletions

View File

@@ -14,7 +14,7 @@ CoffeeScript.eval = (code, options = {}) ->
# Running code does not provide access to this scope. # Running code does not provide access to this scope.
CoffeeScript.run = (code, options = {}) -> CoffeeScript.run = (code, options = {}) ->
options.bare = on options.bare = on
options.shiftLine = on options.shiftLine = on
Function(compile code, options)() Function(compile code, options)()
@@ -24,12 +24,10 @@ return unless window?
# Include source maps where possible. If we've got a base64 encoder, a # 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. # 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 # 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 = {}) -> compile = (code, options = {}) ->
options.sourceMap = true options.inlineMap = true
options.inline = true CoffeeScript.compile code, options
{js, v3SourceMap} = CoffeeScript.compile code, options
"#{js}\n//# sourceMappingURL=data:application/json;base64,#{btoa unescape encodeURIComponent v3SourceMap}\n//# sourceURL=coffeescript"
# Load a remote script from the current domain via XHR. # Load a remote script from the current domain via XHR.
CoffeeScript.load = (url, callback, options = {}, hold = false) -> CoffeeScript.load = (url, callback, options = {}, hold = false) ->

View File

@@ -19,6 +19,15 @@ exports.FILE_EXTENSIONS = ['.coffee', '.litcoffee', '.coffee.md']
# Expose helpers for testing. # Expose helpers for testing.
exports.helpers = helpers 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 # Function wrapper to add source file information to SyntaxErrors thrown by the
# lexer/parser/compiler. # lexer/parser/compiler.
withPrettyErrors = (fn) -> withPrettyErrors = (fn) ->
@@ -42,6 +51,9 @@ exports.compile = compile = withPrettyErrors (code, options) ->
{merge, extend} = helpers {merge, extend} = helpers
options = extend {}, options options = extend {}, options
if options.inlineMap
options.sourceMap ?= yes
if options.sourceMap if options.sourceMap
map = new SourceMap map = new SourceMap
@@ -84,10 +96,17 @@ exports.compile = compile = withPrettyErrors (code, options) ->
js = "// #{header}\n#{js}" js = "// #{header}\n#{js}"
if options.sourceMap if options.sourceMap
answer = {js} v3SourceMap = map.generate(options, code)
answer.sourceMap = map
answer.v3SourceMap = map.generate(options, code) if options.inlineMap
answer 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 else
js js
@@ -181,12 +200,12 @@ if require.extensions
Use CoffeeScript.register() or require the coffee-script/register module to require #{ext} files. 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' raw = fs.readFileSync filename, 'utf8'
stripped = if raw.charCodeAt(0) is 0xFEFF then raw.substring 1 else raw stripped = if raw.charCodeAt(0) is 0xFEFF then raw.substring 1 else raw
try try
answer = compile(stripped, {filename, sourceMap, literate: helpers.isLiterate filename}) answer = compile(stripped, {filename, sourceMap, inlineMap, literate: helpers.isLiterate filename})
catch err catch err
# As the filename and code of a dynamically loaded file will be different # As the filename and code of a dynamically loaded file will be different
# from the original file compiled with CoffeeScript.run, add that # from the original file compiled with CoffeeScript.run, add that

View File

@@ -39,6 +39,7 @@ SWITCHES = [
['-i', '--interactive', 'run an interactive CoffeeScript REPL'] ['-i', '--interactive', 'run an interactive CoffeeScript REPL']
['-j', '--join [FILE]', 'concatenate the source CoffeeScript before compiling'] ['-j', '--join [FILE]', 'concatenate the source CoffeeScript before compiling']
['-m', '--map', 'generate source map and save as .js.map files'] ['-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'] ['-n', '--nodes', 'print out the parse tree that the parser produces']
[ '--nodejs [ARGS]', 'pass options directly to the "node" binary'] [ '--nodejs [ARGS]', 'pass options directly to the "node" binary']
[ '--no-header', 'suppress the "Generated by" header'] [ '--no-header', 'suppress the "Generated by" header']
@@ -413,6 +414,7 @@ compileOptions = (filename, base) ->
bare: opts.bare bare: opts.bare
header: opts.compile and not opts['no-header'] header: opts.compile and not opts['no-header']
sourceMap: opts.map sourceMap: opts.map
inlineMap: opts['inline-map']
} }
if filename if filename
if base if base

View File

@@ -5,7 +5,7 @@ path = require 'path'
# Load and run a CoffeeScript file for Node, stripping any `BOM`s. # Load and run a CoffeeScript file for Node, stripping any `BOM`s.
loadFile = (module, filename) -> loadFile = (module, filename) ->
answer = CoffeeScript._compileFile filename, false answer = CoffeeScript._compileFile filename, yes, yes
module._compile answer, filename module._compile answer, filename
# If the installed version of Node supports `require.extensions`, register # If the installed version of Node supports `require.extensions`, register