jashkenas--coffeescript/documentation/docs/coffee-script.html

785 lines
36 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!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_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>
</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.8.0'</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></pre></div></div>
</li>
<li id="section-18">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-18">&#182;</a>
</div>
<p>Throw error with deprecation warning when depending upon implicit <code>require.extensions</code> registration</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">if</span> <span class="hljs-built_in">require</span>.extensions
<span class="hljs-keyword">for</span> ext <span class="hljs-keyword">in</span> <span class="hljs-property">@FILE_EXTENSIONS</span>
<span class="hljs-built_in">require</span>.extensions[ext] ?=<span class="hljs-function"> -&gt;</span>
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Error <span class="hljs-string">"""
Use CoffeeScript.register() or require the coffee-script/register module to require <span class="hljs-subst">#{ext}</span> files.
"""</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-19">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-19">&#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-20">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-20">&#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-21">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-21">&#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 “Jison lexer”.</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-22">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-22">&#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-23">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-23">&#182;</a>
</div>
<p>Override Jisons 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-24">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-24">&#182;</a>
</div>
<p>Disregard Jisons 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-25">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-25">&#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-26">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-26">&#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-27">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-27">&#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-28">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-28">&#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-29">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-29">&#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-30">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-30">&#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.toString()}</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>