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
--debug
compiler 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
run
ning 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 build
ensures 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
require
s 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:###
run
docco
via bin/coffee
-
modify
command.coffee
run
to allow args to be sent via "<" to the running script if the-d
option 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
--debugsource
flag (oof?)
-
not sure how this would work exactly, but some loose ideas:
-
debugsource
points to the .coffee source file or src/ folder for the running script -
if an error is encountered in the
node.js
runtime -
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