Adds a --debug option for .coffee scripts that outputs more helpful error messages (mapping compiled .js lines of code to the input .coffee file's lines).
This branch should be considered experimental at the moment -- it serves as a proof-of-concept and to expose additional issues with adding debugging support to CoffeeScript
Current output:
TypeError: string is not a function
at String.CALL_NON_FUNCTION (native)
at Object.<anonymous> (/Users/geraldlewis/Work/Interactive/projects/coffee-script/errs/err.coffee:10:3)
at Module._compile (module.js:420:26)
at Object.run (/Users/geraldlewis/Work/Interactive/projects/coffee-script/coffee-script/lib/coffee-script.js:68:12)
at /Users/geraldlewis/Work/Interactive/projects/coffee-script/coffee-script/lib/command.js:120:29
at /Users/geraldlewis/Work/Interactive/projects/coffee-script/coffee-script/lib/command.js:90:26
at [object Object].<anonymous> (fs.js:107:5)
at [object Object].emit (events.js:61:17)
at afterRead (fs.js:970:12)
at wrapper (fs.js:245:17)
--debug Output:
TypeError: string is not a function
in err.js on line 10
--------------------
> 10 | s();
in err.coffee on line 10
------------------------
7 |
8 |
9 | for k,v in [1,2,3]
> 10 | s()
11 | try
12 | #log undef
- Uses a few strategies outlined in #558, namely @atrefz 's
--debugcompiler option with line number comments, @andrewschaaf 's "FUGLY" option (though modified so that the end user never sees the ugly JS line number comments) - Speaking of, @andrewschaaf has done some great work on this same issue, which I'm having trouble locating at the moment
- Uses @aseemk 's suggestion for Stylus style error messages (#1351)
- Also fixes #987 (stack trace refers to [filename].js instead of [filename].coffee)
Caveats
- only works with node.js at the moment
- only works for
running andeval-ed .coffee scripts (see below) - needs a lot of testing; I've not tested it with a lot of sample bugs
Here's the branch: https://github.com/geraldalewis/coffee-script/tree/debug
Here's the commit: https://github.com/geraldalewis/coffee-script/commit/9d0fa7cc4d4b73e8de1a0a8179753ba3fa0df1b8
#What works#
###Running .coffee files###
bin/coffee -d ../errs/err.coffee
TypeError: string is not a function
in err.js on line 11
--------------------
> 11 | s();
in err.coffee on line 10
------------------------
7 |
8 |
9 | for k,v in [1,2,3]
> 10 | s()
11 | try
12 | #log undef
###Eval### ...Sort of -- this works:
bin/coffee -bed 'i = 0; undef()'
but this fails for some reason (some bug in the DebugCSFile.error, I think -- seems to happen if < 2 lines of .js)
bin/coffee -bed 'undef()'
#What doesn't work# There are a few classes of errors I'm struggling to get debug info from. I have no solutions at the moment, but some ideas below.
##Errors in CoffeeScript##
@jashkenas 's first question to me was what kind of output he'd see if there was an error in src/scope.coffee. I inserted a bug into Scope's constructor (a call to undef()), recompiled CoffeeScript, and ran coffee -bed 'i = 1'
dev:coffee-script(debugging)$ coffee -bed 'i = 1'
ReferenceError: undef is not defined
at new Scope (/Users/geraldlewis/Work/interactive/projects/coffee-script/coffee-script/lib/scope.js:10:7)
...
Clearly, debug didn't work -- we have the same node.js error message output, instead of the expected:
ReferenceError: undef is not defined
in scope.coffee on line 21
--------------------------
19 |constructor: (@parent, @expressions, @method) ->
> 21 | undef()
22 | @variables = [{name: 'arguments', type: 'arguments'}]
My mistake was forgetting that coffee uses pre-compiled .js files to run CoffeeScript. debug relies on CoffeeScript compiling a .coffee file -- the .coffee file needs to be present so that the executing .js file's line numbers can be mapped to their CoffeeScript source. Since we no longer have a reference to the original scope.coffee file, we don't have any way of associating the lines of code where an error occured in scope.js.
Compounding the issue: because debug needs to re-compile the source .coffee file(s) (to insert the line-number comments mapping the line of .js to its respective line of .coffee) a bug in the compile pipeline is a bug in debug...
###Possible Solutions###
-
cake buildensures a clean, working copy of CoffeeScript is available even if a bug is introduced into its source -
introduce a bug into the source of CoffeeScript
# in source.coffee constructor: ()-> undef() -
compile the buggy CoffeeScript via
cake build -
run a bug-free script to see if an error occurs
bin/coffee -be 'i = 1' -
on error, grab the buggy .js file from the error stack
at new Scope (coffee-script/lib/scope.js:10:7) -
somehow get the .js file's associated .coffee file
# in scope.js //@source_file:coffee-script/src/scope.coffee -
and send it to the clean working copy of CoffeeScript
-
output that debug message...
##Docco##
Debugging Docco represents a subtly different class of issues than debugging CoffeeScript. Like CoffeeScript, docco.coffee has already been compiled to docco.js when bin/docco requires it:
#!/usr/bin/env node
var path = require('path');
var fs = require('fs');
var lib = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');
process.ARGV = process.argv = process.argv.slice(2, process.argv.length);
require(lib + '/docco.js'); #completely bypasses the .coffee compilation stage
We have the same issue -- since we no longer have a reference to the original .coffee script, we don't have any way of associating the line of JavaScript code with its originating CoffeeScript line.
###Possible solutions:###
rundoccovia bin/coffee
-
modify
command.coffeerunto allow args to be sent via "<" to the running script if the-doption is set:coffee -d src/docco.coffee < src/some_project.coffee # for the `run`ning src/docco.coffee script, process.ARGV would = process.ARGV[2..]
- a
--debugsourceflag (oof?)
-
not sure how this would work exactly, but some loose ideas:
-
debugsourcepoints to the .coffee source file or src/ folder for the running script -
if an error is encountered in the
node.jsruntime -
use
process.on 'uncaughtException'to catch it and save details as "stack" -
run
coffee-script.debug ( debugsource, stack ... ) -
(this recompiles the debugsource so that the CoffeeScript lines can be associated with their JS counterparts )
docco --debugsource=src/docco.coffee src/some_project.coffee