jashkenas/coffee-script — pull request #2751 by jwalton (2013-03-01 16:07:42+00:00)
Title: Source maps for CoffeeScript

To use:

coffee -c -m file.coffee

This will generate a "file.js" and a "file.map" file, in the same directory. The "//@ sourceMappingURL" is automagically added to the .js file if you also generate a map.

## How it works:

This is obviously building on my previous changes to location awareness in the parser. The big change here is that, in nodes.coffee, we now have a `compileToFragments()` method which compiles nodes to a list of CodeFragment objects instead of to a great big string. the `compile()` method still exists, although now it's implemented in terms fo `compileToFragments()`.

A CodeFragment is just a snippet of code, and some information about where it came from. When it comes time to generate the final js file, all we need to do is cat together all the strings from all the CodeFragment objects. By keeping track of what line number/column each CodeFragment gets written to, and by using the original location data stored in the CodeFragment object, we can generate source maps.

This obviously makes the compiler a bit more complicated, but brings with it some serious advantages. Source map support is the obvious one, but also when debugging compiler problems ("Why are you putting a /n there!? WHY!?") you can do some cool tricks, like modifying this line in coffee-script.coffee:

js += fragment.code

to:

js += "[[#{fragment.type}]]fragment.code"

This will prefix every fragment with the type of node which created it, which makes it easy to figure out where something is coming from. I used this quite a bit when I was tracking down problems I'd introduced while making this change. :D

## Why write sourcemap.coffee?

There is a (https://github.com/mozilla/source-map)[source-map] implementation for Node.js from Mozilla. Why write our own implementation? Because the Mozilla version is BSD licensed; many organizations avoid BSD because of the "obnoxious BSD advertising clause", so rather than impose such a license on coffee-script (and by extension all products that use coffee-script), I just wrote my own (I'll probably flesh this out a bit more and spin it out into a separate npm module at some point, as the redux compiler would also benefit from something with a more open license.)