Files
coffeescript/documentation/docs/coffee-script.html
2014-01-29 23:21:44 -06:00

762 lines
34 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<title>coffee-script.coffee</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
<link rel="stylesheet" media="all" href="docco.css" />
</head>
<body>
<div id="container">
<div id="background"></div>
<ul id="jump_to">
<li>
<a class="large" href="javascript:void(0);">Jump To &hellip;</a>
<a class="small" href="javascript:void(0);">+</a>
<div id="jump_wrapper">
<div id="jump_page">
<a class="source" href="browser.html">
browser.coffee
</a>
<a class="source" href="cake.html">
cake.coffee
</a>
<a class="source" href="coffee-script.html">
coffee-script.coffee
</a>
<a class="source" href="command.html">
command.coffee
</a>
<a class="source" href="grammar.html">
grammar.coffee
</a>
<a class="source" href="helpers.html">
helpers.coffee
</a>
<a class="source" href="index.html">
index.coffee
</a>
<a class="source" href="lexer.html">
lexer.coffee
</a>
<a class="source" href="nodes.html">
nodes.coffee
</a>
<a class="source" href="optparse.html">
optparse.coffee
</a>
<a class="source" href="register.html">
register.coffee
</a>
<a class="source" href="repl.html">
repl.coffee
</a>
<a class="source" href="rewriter.html">
rewriter.coffee
</a>
<a class="source" href="scope.html">
scope.litcoffee
</a>
<a class="source" href="sourcemap.html">
sourcemap.litcoffee
</a>
</div>
</li>
</ul>
<ul class="sections">
<li id="title">
<div class="annotation">
<h1>coffee-script.coffee</h1>
</div>
</li>
<li id="section-1">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-1">&#182;</a>
</div>
<p>CoffeeScript can be used both on the server, as a command-line compiler based
on Node.js/V8, or to run CoffeeScript directly in the browser. This module
contains the main entry functions for tokenizing, parsing, and compiling
source CoffeeScript into JavaScript.</p>
</div>
<div class="content"><div class='highlight'><pre>fs = <span class="hljs-built_in">require</span> <span class="hljs-string">'fs'</span>
vm = <span class="hljs-built_in">require</span> <span class="hljs-string">'vm'</span>
path = <span class="hljs-built_in">require</span> <span class="hljs-string">'path'</span>
{Lexer} = <span class="hljs-built_in">require</span> <span class="hljs-string">'./lexer'</span>
{parser} = <span class="hljs-built_in">require</span> <span class="hljs-string">'./parser'</span>
helpers = <span class="hljs-built_in">require</span> <span class="hljs-string">'./helpers'</span>
SourceMap = <span class="hljs-built_in">require</span> <span class="hljs-string">'./sourcemap'</span></pre></div></div>
</li>
<li id="section-2">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-2">&#182;</a>
</div>
<p>The current CoffeeScript version number.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.VERSION = <span class="hljs-string">'1.7.1'</span>
<span class="hljs-built_in">exports</span>.FILE_EXTENSIONS = [<span class="hljs-string">'.coffee'</span>, <span class="hljs-string">'.litcoffee'</span>, <span class="hljs-string">'.coffee.md'</span>]</pre></div></div>
</li>
<li id="section-3">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-3">&#182;</a>
</div>
<p>Expose helpers for testing.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.helpers = helpers</pre></div></div>
</li>
<li id="section-4">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-4">&#182;</a>
</div>
<p>Function wrapper to add source file information to SyntaxErrors thrown by the
lexer/parser/compiler.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">withPrettyErrors</span> = <span class="hljs-params">(fn)</span> -&gt;</span>
<span class="hljs-function"><span class="hljs-params">(code, options = {})</span> -&gt;</span>
<span class="hljs-keyword">try</span>
fn.call @, code, options
<span class="hljs-keyword">catch</span> err
<span class="hljs-keyword">throw</span> helpers.updateSyntaxError err, code, options.filename</pre></div></div>
</li>
<li id="section-5">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-5">&#182;</a>
</div>
<p>Compile CoffeeScript code to JavaScript, using the Coffee/Jison compiler.</p>
<p>If <code>options.sourceMap</code> is specified, then <code>options.filename</code> must also be specified. All
options that can be passed to <code>SourceMap#generate</code> may also be passed here.</p>
<p>This returns a javascript string, unless <code>options.sourceMap</code> is passed,
in which case this returns a <code>{js, v3SourceMap, sourceMap}</code>
object, where sourceMap is a sourcemap.coffee#SourceMap object, handy for doing programatic
lookups.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.compile = compile = withPrettyErrors <span class="hljs-function"><span class="hljs-params">(code, options)</span> -&gt;</span>
{merge, extend} = helpers
options = extend {}, options
<span class="hljs-keyword">if</span> options.sourceMap
map = <span class="hljs-keyword">new</span> SourceMap
fragments = parser.parse(lexer.tokenize code, options).compileToFragments options
currentLine = <span class="hljs-number">0</span>
currentLine += <span class="hljs-number">1</span> <span class="hljs-keyword">if</span> options.header
currentLine += <span class="hljs-number">1</span> <span class="hljs-keyword">if</span> options.shiftLine
currentColumn = <span class="hljs-number">0</span>
js = <span class="hljs-string">""</span>
<span class="hljs-keyword">for</span> fragment <span class="hljs-keyword">in</span> fragments</pre></div></div>
</li>
<li id="section-6">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-6">&#182;</a>
</div>
<p>Update the sourcemap with data from each fragment</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> options.sourceMap
<span class="hljs-keyword">if</span> fragment.locationData
map.add(
[fragment.locationData.first_line, fragment.locationData.first_column]
[currentLine, currentColumn]
{<span class="hljs-attribute">noReplace</span>: <span class="hljs-literal">true</span>})
newLines = helpers.count fragment.code, <span class="hljs-string">"\n"</span>
currentLine += newLines
<span class="hljs-keyword">if</span> newLines
currentColumn = fragment.code.length - (fragment.code.lastIndexOf(<span class="hljs-string">"\n"</span>) + <span class="hljs-number">1</span>)
<span class="hljs-keyword">else</span>
currentColumn += fragment.code.length</pre></div></div>
</li>
<li id="section-7">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-7">&#182;</a>
</div>
<p>Copy the code from each fragment into the final JavaScript.</p>
</div>
<div class="content"><div class='highlight'><pre> js += fragment.code
<span class="hljs-keyword">if</span> options.header
header = <span class="hljs-string">"Generated by CoffeeScript <span class="hljs-subst">#{<span class="hljs-property">@VERSION</span>}</span>"</span>
js = <span class="hljs-string">"// <span class="hljs-subst">#{header}</span>\n<span class="hljs-subst">#{js}</span>"</span>
<span class="hljs-keyword">if</span> options.sourceMap
answer = {js}
answer.sourceMap = map
answer.v3SourceMap = map.generate(options, code)
answer
<span class="hljs-keyword">else</span>
js</pre></div></div>
</li>
<li id="section-8">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-8">&#182;</a>
</div>
<p>Tokenize a string of CoffeeScript code, and return the array of tokens.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.tokens = withPrettyErrors <span class="hljs-function"><span class="hljs-params">(code, options)</span> -&gt;</span>
lexer.tokenize code, options</pre></div></div>
</li>
<li id="section-9">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-9">&#182;</a>
</div>
<p>Parse a string of CoffeeScript code or an array of lexed tokens, and
return the AST. You can then compile it by calling <code>.compile()</code> on the root,
or traverse it by using <code>.traverseChildren()</code> with a callback.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.nodes = withPrettyErrors <span class="hljs-function"><span class="hljs-params">(source, options)</span> -&gt;</span>
<span class="hljs-keyword">if</span> <span class="hljs-keyword">typeof</span> source <span class="hljs-keyword">is</span> <span class="hljs-string">'string'</span>
parser.parse lexer.tokenize source, options
<span class="hljs-keyword">else</span>
parser.parse source</pre></div></div>
</li>
<li id="section-10">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-10">&#182;</a>
</div>
<p>Compile and execute a string of CoffeeScript (on the server), correctly
setting <code>__filename</code>, <code>__dirname</code>, and relative <code>require()</code>.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.<span class="hljs-function"><span class="hljs-title">run</span> = <span class="hljs-params">(code, options = {})</span> -&gt;</span>
mainModule = <span class="hljs-built_in">require</span>.main</pre></div></div>
</li>
<li id="section-11">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-11">&#182;</a>
</div>
<p>Set the filename.</p>
</div>
<div class="content"><div class='highlight'><pre> mainModule.filename = process.argv[<span class="hljs-number">1</span>] =
<span class="hljs-keyword">if</span> options.filename <span class="hljs-keyword">then</span> fs.realpathSync(options.filename) <span class="hljs-keyword">else</span> <span class="hljs-string">'.'</span></pre></div></div>
</li>
<li id="section-12">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-12">&#182;</a>
</div>
<p>Clear the module cache.</p>
</div>
<div class="content"><div class='highlight'><pre> mainModule.moduleCache <span class="hljs-keyword">and</span>= {}</pre></div></div>
</li>
<li id="section-13">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-13">&#182;</a>
</div>
<p>Assign paths for node_modules loading</p>
</div>
<div class="content"><div class='highlight'><pre> dir = <span class="hljs-keyword">if</span> options.filename
path.dirname fs.realpathSync options.filename
<span class="hljs-keyword">else</span>
fs.realpathSync <span class="hljs-string">'.'</span>
mainModule.paths = <span class="hljs-built_in">require</span>(<span class="hljs-string">'module'</span>)._nodeModulePaths dir</pre></div></div>
</li>
<li id="section-14">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-14">&#182;</a>
</div>
<p>Compile.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> helpers.isCoffee(mainModule.filename) <span class="hljs-keyword">or</span> <span class="hljs-built_in">require</span>.extensions
answer = compile code, options
code = answer.js ? answer
mainModule._compile code, mainModule.filename</pre></div></div>
</li>
<li id="section-15">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-15">&#182;</a>
</div>
<p>Compile and evaluate a string of CoffeeScript (in a Node.js-like environment).
The CoffeeScript REPL uses this to run the input.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.<span class="hljs-function"><span class="hljs-title">eval</span> = <span class="hljs-params">(code, options = {})</span> -&gt;</span>
<span class="hljs-keyword">return</span> <span class="hljs-keyword">unless</span> code = code.trim()
Script = vm.Script
<span class="hljs-keyword">if</span> Script
<span class="hljs-keyword">if</span> options.sandbox?
<span class="hljs-keyword">if</span> options.sandbox <span class="hljs-keyword">instanceof</span> Script.createContext().constructor
sandbox = options.sandbox
<span class="hljs-keyword">else</span>
sandbox = Script.createContext()
sandbox[k] = v <span class="hljs-keyword">for</span> own k, v <span class="hljs-keyword">of</span> options.sandbox
sandbox.<span class="hljs-built_in">global</span> = sandbox.root = sandbox.GLOBAL = sandbox
<span class="hljs-keyword">else</span>
sandbox = <span class="hljs-built_in">global</span>
sandbox.__filename = options.filename || <span class="hljs-string">'eval'</span>
sandbox.__dirname = path.dirname sandbox.__filename</pre></div></div>
</li>
<li id="section-16">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-16">&#182;</a>
</div>
<p>define module/require only if they chose not to specify their own</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">unless</span> sandbox <span class="hljs-keyword">isnt</span> <span class="hljs-built_in">global</span> <span class="hljs-keyword">or</span> sandbox.<span class="hljs-built_in">module</span> <span class="hljs-keyword">or</span> sandbox.<span class="hljs-built_in">require</span>
Module = <span class="hljs-built_in">require</span> <span class="hljs-string">'module'</span>
sandbox.<span class="hljs-built_in">module</span> = _module = <span class="hljs-keyword">new</span> Module(options.modulename || <span class="hljs-string">'eval'</span>)
sandbox.<span class="hljs-built_in">require</span> = <span class="hljs-function"><span class="hljs-title">_require</span> = <span class="hljs-params">(path)</span> -&gt;</span> Module._load path, _module, <span class="hljs-literal">true</span>
_module.filename = sandbox.__filename
_require[r] = <span class="hljs-built_in">require</span>[r] <span class="hljs-keyword">for</span> r <span class="hljs-keyword">in</span> Object.getOwnPropertyNames <span class="hljs-built_in">require</span> <span class="hljs-keyword">when</span> r <span class="hljs-keyword">isnt</span> <span class="hljs-string">'paths'</span></pre></div></div>
</li>
<li id="section-17">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-17">&#182;</a>
</div>
<p>use the same hack node currently uses for their own REPL</p>
</div>
<div class="content"><div class='highlight'><pre> _require.paths = _module.paths = Module._nodeModulePaths process.cwd()
_require.<span class="hljs-function"><span class="hljs-title">resolve</span> = <span class="hljs-params">(request)</span> -&gt;</span> Module._resolveFilename request, _module
o = {}
o[k] = v <span class="hljs-keyword">for</span> own k, v <span class="hljs-keyword">of</span> options
o.bare = <span class="hljs-literal">on</span> <span class="hljs-comment"># ensure return value</span>
js = compile code, o
<span class="hljs-keyword">if</span> sandbox <span class="hljs-keyword">is</span> <span class="hljs-built_in">global</span>
vm.runInThisContext js
<span class="hljs-keyword">else</span>
vm.runInContext js, sandbox
<span class="hljs-built_in">exports</span>.<span class="hljs-function"><span class="hljs-title">register</span> = -&gt;</span> <span class="hljs-built_in">require</span> <span class="hljs-string">'./register'</span>
<span class="hljs-built_in">exports</span>.<span class="hljs-function"><span class="hljs-title">_compileFile</span> = <span class="hljs-params">(filename, sourceMap = <span class="hljs-literal">no</span>)</span> -&gt;</span>
raw = fs.readFileSync filename, <span class="hljs-string">'utf8'</span>
stripped = <span class="hljs-keyword">if</span> raw.charCodeAt(<span class="hljs-number">0</span>) <span class="hljs-keyword">is</span> <span class="hljs-number">0xFEFF</span> <span class="hljs-keyword">then</span> raw.substring <span class="hljs-number">1</span> <span class="hljs-keyword">else</span> raw
<span class="hljs-keyword">try</span>
answer = compile(stripped, {filename, sourceMap, <span class="hljs-attribute">literate</span>: helpers.isLiterate filename})
<span class="hljs-keyword">catch</span> err</pre></div></div>
</li>
<li id="section-18">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-18">&#182;</a>
</div>
<p>As the filename and code of a dynamically loaded file will be different
from the original file compiled with CoffeeScript.run, add that
information to error so it can be pretty-printed later.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">throw</span> helpers.updateSyntaxError err, stripped, filename
answer</pre></div></div>
</li>
<li id="section-19">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-19">&#182;</a>
</div>
<p>Instantiate a Lexer for our use here.</p>
</div>
<div class="content"><div class='highlight'><pre>lexer = <span class="hljs-keyword">new</span> Lexer</pre></div></div>
</li>
<li id="section-20">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-20">&#182;</a>
</div>
<p>The real Lexer produces a generic stream of tokens. This object provides a
thin wrapper around it, compatible with the Jison API. We can then pass it
directly as a &quot;Jison lexer&quot;.</p>
</div>
<div class="content"><div class='highlight'><pre>parser.lexer =
<span class="hljs-attribute">lex</span>:<span class="hljs-function"> -&gt;</span>
token = <span class="hljs-property">@tokens</span>[<span class="hljs-property">@pos</span>++]
<span class="hljs-keyword">if</span> token
[tag, <span class="hljs-property">@yytext</span>, <span class="hljs-property">@yylloc</span>] = token
<span class="hljs-property">@errorToken</span> = token.origin <span class="hljs-keyword">or</span> token
<span class="hljs-property">@yylineno</span> = <span class="hljs-property">@yylloc</span>.first_line
<span class="hljs-keyword">else</span>
tag = <span class="hljs-string">''</span>
tag
<span class="hljs-attribute">setInput</span>: <span class="hljs-function"><span class="hljs-params">(<span class="hljs-property">@tokens</span>)</span> -&gt;</span>
<span class="hljs-property">@pos</span> = <span class="hljs-number">0</span>
<span class="hljs-attribute">upcomingInput</span>:<span class="hljs-function"> -&gt;</span>
<span class="hljs-string">""</span></pre></div></div>
</li>
<li id="section-21">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-21">&#182;</a>
</div>
<p>Make all the AST nodes visible to the parser.</p>
</div>
<div class="content"><div class='highlight'><pre>parser.yy = <span class="hljs-built_in">require</span> <span class="hljs-string">'./nodes'</span></pre></div></div>
</li>
<li id="section-22">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-22">&#182;</a>
</div>
<p>Override Jison&#39;s default error handling function.</p>
</div>
<div class="content"><div class='highlight'><pre>parser.yy.<span class="hljs-function"><span class="hljs-title">parseError</span> = <span class="hljs-params">(message, {token})</span> -&gt;</span></pre></div></div>
</li>
<li id="section-23">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-23">&#182;</a>
</div>
<p>Disregard Jison&#39;s message, it contains redundant line numer information.
Disregard the token, we take its value directly from the lexer in case
the error is caused by a generated token which might refer to its origin.</p>
</div>
<div class="content"><div class='highlight'><pre> {errorToken, tokens} = parser.lexer
[errorTag, errorText, errorLoc] = errorToken
errorText = <span class="hljs-keyword">if</span> errorToken <span class="hljs-keyword">is</span> tokens[tokens.length - <span class="hljs-number">1</span>]
<span class="hljs-string">'end of input'</span>
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> errorTag <span class="hljs-keyword">in</span> [<span class="hljs-string">'INDENT'</span>, <span class="hljs-string">'OUTDENT'</span>]
<span class="hljs-string">'indentation'</span>
<span class="hljs-keyword">else</span>
helpers.nameWhitespaceCharacter errorText</pre></div></div>
</li>
<li id="section-24">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-24">&#182;</a>
</div>
<p>The second argument has a <code>loc</code> property, which should have the location
data for this token. Unfortunately, Jison seems to send an outdated <code>loc</code>
(from the previous token), so we take the location information directly
from the lexer.</p>
</div>
<div class="content"><div class='highlight'><pre> helpers.throwSyntaxError <span class="hljs-string">"unexpected <span class="hljs-subst">#{errorText}</span>"</span>, errorLoc</pre></div></div>
</li>
<li id="section-25">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-25">&#182;</a>
</div>
<p>Based on <a href="http://v8.googlecode.com/svn/branches/bleeding_edge/src/messages.js">http://v8.googlecode.com/svn/branches/bleeding_edge/src/messages.js</a>
Modified to handle sourceMap</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">formatSourcePosition</span> = <span class="hljs-params">(frame, getSourceMapping)</span> -&gt;</span>
fileName = <span class="hljs-literal">undefined</span>
fileLocation = <span class="hljs-string">''</span>
<span class="hljs-keyword">if</span> frame.isNative()
fileLocation = <span class="hljs-string">"native"</span>
<span class="hljs-keyword">else</span>
<span class="hljs-keyword">if</span> frame.isEval()
fileName = frame.getScriptNameOrSourceURL()
fileLocation = <span class="hljs-string">"<span class="hljs-subst">#{frame.getEvalOrigin()}</span>, "</span> <span class="hljs-keyword">unless</span> fileName
<span class="hljs-keyword">else</span>
fileName = frame.getFileName()
fileName <span class="hljs-keyword">or</span>= <span class="hljs-string">"&lt;anonymous&gt;"</span>
line = frame.getLineNumber()
column = frame.getColumnNumber()</pre></div></div>
</li>
<li id="section-26">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-26">&#182;</a>
</div>
<p>Check for a sourceMap position</p>
</div>
<div class="content"><div class='highlight'><pre> source = getSourceMapping fileName, line, column
fileLocation =
<span class="hljs-keyword">if</span> source
<span class="hljs-string">"<span class="hljs-subst">#{fileName}</span>:<span class="hljs-subst">#{source[<span class="hljs-number">0</span>]}</span>:<span class="hljs-subst">#{source[<span class="hljs-number">1</span>]}</span>"</span>
<span class="hljs-keyword">else</span>
<span class="hljs-string">"<span class="hljs-subst">#{fileName}</span>:<span class="hljs-subst">#{line}</span>:<span class="hljs-subst">#{column}</span>"</span>
functionName = frame.getFunctionName()
isConstructor = frame.isConstructor()
isMethodCall = <span class="hljs-keyword">not</span> (frame.isToplevel() <span class="hljs-keyword">or</span> isConstructor)
<span class="hljs-keyword">if</span> isMethodCall
methodName = frame.getMethodName()
typeName = frame.getTypeName()
<span class="hljs-keyword">if</span> functionName
tp = as = <span class="hljs-string">''</span>
<span class="hljs-keyword">if</span> typeName <span class="hljs-keyword">and</span> functionName.indexOf typeName
tp = <span class="hljs-string">"<span class="hljs-subst">#{typeName}</span>."</span>
<span class="hljs-keyword">if</span> methodName <span class="hljs-keyword">and</span> functionName.indexOf(<span class="hljs-string">".<span class="hljs-subst">#{methodName}</span>"</span>) <span class="hljs-keyword">isnt</span> functionName.length - methodName.length - <span class="hljs-number">1</span>
as = <span class="hljs-string">" [as <span class="hljs-subst">#{methodName}</span>]"</span>
<span class="hljs-string">"<span class="hljs-subst">#{tp}</span><span class="hljs-subst">#{functionName}</span><span class="hljs-subst">#{as}</span> (<span class="hljs-subst">#{fileLocation}</span>)"</span>
<span class="hljs-keyword">else</span>
<span class="hljs-string">"<span class="hljs-subst">#{typeName}</span>.<span class="hljs-subst">#{methodName <span class="hljs-keyword">or</span> <span class="hljs-string">'&lt;anonymous&gt;'</span>}</span> (<span class="hljs-subst">#{fileLocation}</span>)"</span>
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> isConstructor
<span class="hljs-string">"new <span class="hljs-subst">#{functionName <span class="hljs-keyword">or</span> <span class="hljs-string">'&lt;anonymous&gt;'</span>}</span> (<span class="hljs-subst">#{fileLocation}</span>)"</span>
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> functionName
<span class="hljs-string">"<span class="hljs-subst">#{functionName}</span> (<span class="hljs-subst">#{fileLocation}</span>)"</span>
<span class="hljs-keyword">else</span>
fileLocation</pre></div></div>
</li>
<li id="section-27">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-27">&#182;</a>
</div>
<p>Map of filenames -&gt; sourceMap object.</p>
</div>
<div class="content"><div class='highlight'><pre>sourceMaps = {}</pre></div></div>
</li>
<li id="section-28">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-28">&#182;</a>
</div>
<p>Generates the source map for a coffee file and stores it in the local cache variable.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">getSourceMap</span> = <span class="hljs-params">(filename)</span> -&gt;</span>
<span class="hljs-keyword">return</span> sourceMaps[filename] <span class="hljs-keyword">if</span> sourceMaps[filename]
<span class="hljs-keyword">return</span> <span class="hljs-keyword">unless</span> path?.extname(filename) <span class="hljs-keyword">in</span> <span class="hljs-built_in">exports</span>.FILE_EXTENSIONS
answer = <span class="hljs-built_in">exports</span>._compileFile filename, <span class="hljs-literal">true</span>
sourceMaps[filename] = answer.sourceMap</pre></div></div>
</li>
<li id="section-29">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-29">&#182;</a>
</div>
<p>Based on <a href="http://goo.gl/ZTx1p">michaelficarra/CoffeeScriptRedux</a>
NodeJS / V8 have no support for transforming positions in stack traces using
sourceMap, so we must monkey-patch Error to display CoffeeScript source
positions.</p>
</div>
<div class="content"><div class='highlight'><pre>Error.<span class="hljs-function"><span class="hljs-title">prepareStackTrace</span> = <span class="hljs-params">(err, stack)</span> -&gt;</span>
<span class="hljs-function"><span class="hljs-title">getSourceMapping</span> = <span class="hljs-params">(filename, line, column)</span> -&gt;</span>
sourceMap = getSourceMap filename
answer = sourceMap.sourceLocation [line - <span class="hljs-number">1</span>, column - <span class="hljs-number">1</span>] <span class="hljs-keyword">if</span> sourceMap
<span class="hljs-keyword">if</span> answer <span class="hljs-keyword">then</span> [answer[<span class="hljs-number">0</span>] + <span class="hljs-number">1</span>, answer[<span class="hljs-number">1</span>] + <span class="hljs-number">1</span>] <span class="hljs-keyword">else</span> <span class="hljs-literal">null</span>
frames = <span class="hljs-keyword">for</span> frame <span class="hljs-keyword">in</span> stack
<span class="hljs-keyword">break</span> <span class="hljs-keyword">if</span> frame.getFunction() <span class="hljs-keyword">is</span> <span class="hljs-built_in">exports</span>.run
<span class="hljs-string">" at <span class="hljs-subst">#{formatSourcePosition frame, getSourceMapping}</span>"</span>
<span class="hljs-string">"<span class="hljs-subst">#{err.name}</span>: <span class="hljs-subst">#{err.message ? <span class="hljs-string">''</span>}</span>\n<span class="hljs-subst">#{frames.join <span class="hljs-string">'\n'</span>}</span>\n"</span></pre></div></div>
</li>
</ul>
</div>
</body>
</html>