mirror of
https://github.com/jashkenas/coffeescript.git
synced 2026-01-13 08:47:55 -05:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e6f6aa8c85 | ||
|
|
c09d8fbedb | ||
|
|
f6d63776c3 | ||
|
|
41b31c7293 | ||
|
|
ec034e2673 | ||
|
|
ff24e5ce52 | ||
|
|
ca275c2a1c | ||
|
|
63ffe0aead | ||
|
|
247b511c6a | ||
|
|
2f82b75862 | ||
|
|
294bb4754e |
60
Cakefile
60
Cakefile
@@ -66,15 +66,18 @@ build = (callback) ->
|
||||
buildParser()
|
||||
buildExceptParser callback
|
||||
|
||||
transpile = (code) ->
|
||||
transpile = (code, options = {}) ->
|
||||
options.minify = process.env.MINIFY isnt 'false'
|
||||
options.transform = process.env.TRANSFORM isnt 'false'
|
||||
babel = require '@babel/core'
|
||||
presets = []
|
||||
# Exclude the `modules` plugin in order to not break the `}(this));`
|
||||
# at the end of the `build:browser` code block.
|
||||
presets.push ['@babel/env', {modules: no}] unless process.env.TRANSFORM is 'false'
|
||||
presets.push ['minify', {mangle: no, evaluate: no, removeUndefined: no}] unless process.env.MINIFY is 'false'
|
||||
presets.push ['@babel/env', {modules: no}] if options.transform
|
||||
presets.push ['minify', {mangle: no, evaluate: no, removeUndefined: no}] if options.minify
|
||||
babelOptions =
|
||||
compact: process.env.MINIFY isnt 'false'
|
||||
compact: not options.minify
|
||||
comments: not options.minify
|
||||
presets: presets
|
||||
sourceType: 'script'
|
||||
{ code } = babel.transform code, babelOptions unless presets.length is 0
|
||||
@@ -140,13 +143,18 @@ task 'build:browser', 'merge the built scripts into a single file for use in a b
|
||||
return module.exports;
|
||||
})();
|
||||
"""
|
||||
# From here, we generate two outputs: a legacy script output for all browsers
|
||||
# and a module output for browsers that support `<script type="module">`.
|
||||
code = """
|
||||
var CoffeeScript = function() {
|
||||
function require(path){ return require[path]; }
|
||||
#{code}
|
||||
return require['./browser'];
|
||||
}();
|
||||
"""
|
||||
scriptCode = transpile """
|
||||
(function(root) {
|
||||
var CoffeeScript = function() {
|
||||
function require(path){ return require[path]; }
|
||||
#{code}
|
||||
return require['./browser'];
|
||||
}();
|
||||
#{code}
|
||||
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define(function() { return CoffeeScript; });
|
||||
@@ -155,10 +163,20 @@ task 'build:browser', 'merge the built scripts into a single file for use in a b
|
||||
}
|
||||
}(this));
|
||||
"""
|
||||
code = transpile code
|
||||
outputFolder = "docs/v#{majorVersion}/browser-compiler"
|
||||
fs.mkdirSync outputFolder unless fs.existsSync outputFolder
|
||||
fs.writeFileSync "#{outputFolder}/coffeescript.js", header + '\n' + code
|
||||
moduleCode = """
|
||||
#{code}
|
||||
|
||||
export default CoffeeScript;
|
||||
const { VERSION, compile, eval: evaluate, load, run, runScripts } = CoffeeScript;
|
||||
export { VERSION, compile, evaluate as eval, load, run, runScripts };
|
||||
"""
|
||||
for folder in ['browser-compiler', 'browser-compiler-modern']
|
||||
outputFolder = "docs/v#{majorVersion}/#{folder}"
|
||||
fs.mkdirSync outputFolder unless fs.existsSync outputFolder
|
||||
fs.writeFileSync "#{outputFolder}/coffeescript.js", """
|
||||
#{header}
|
||||
#{if folder is 'browser-compiler' then scriptCode else moduleCode}
|
||||
"""
|
||||
|
||||
task 'build:browser:full', 'merge the built scripts into a single file for use in a browser, and test it', ->
|
||||
invoke 'build:browser'
|
||||
@@ -174,11 +192,12 @@ task 'build:watch:harmony', 'watch and continually rebuild the CoffeeScript comp
|
||||
|
||||
buildDocs = (watch = no) ->
|
||||
# Constants
|
||||
indexFile = 'documentation/site/index.html'
|
||||
siteSourceFolder = "documentation/site"
|
||||
sectionsSourceFolder = 'documentation/sections'
|
||||
examplesSourceFolder = 'documentation/examples'
|
||||
outputFolder = "docs/v#{majorVersion}"
|
||||
indexFile = 'documentation/site/index.html'
|
||||
siteSourceFolder = "documentation/site"
|
||||
sectionsSourceFolder = 'documentation/sections'
|
||||
changelogSourceFolder = 'documentation/sections/changelog'
|
||||
examplesSourceFolder = 'documentation/examples'
|
||||
outputFolder = "docs/v#{majorVersion}"
|
||||
|
||||
# Helpers
|
||||
releaseHeader = (date, version, prevVersion) ->
|
||||
@@ -261,7 +280,7 @@ buildDocs = (watch = no) ->
|
||||
catch exception
|
||||
|
||||
if watch
|
||||
for target in [indexFile, siteSourceFolder, examplesSourceFolder, sectionsSourceFolder]
|
||||
for target in [indexFile, siteSourceFolder, examplesSourceFolder, sectionsSourceFolder, changelogSourceFolder]
|
||||
fs.watch target, interval: 200, renderIndex
|
||||
log 'watching...', green
|
||||
|
||||
@@ -486,6 +505,9 @@ task 'test:integrations', 'test the module integrated with other libraries and e
|
||||
webpack = require 'webpack'
|
||||
webpack {
|
||||
entry: './'
|
||||
optimization:
|
||||
# Webpack’s minification causes the CoffeeScript module to fail some tests.
|
||||
minimize: off
|
||||
output:
|
||||
path: tmpdir
|
||||
filename: 'coffeescript.js'
|
||||
|
||||
1
docs/browser-compiler-modern
Symbolic link
1
docs/browser-compiler-modern
Symbolic link
@@ -0,0 +1 @@
|
||||
v2/browser-compiler-modern
|
||||
@@ -262,7 +262,7 @@ This happens on page load.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">runScripts</span> = -></span>
|
||||
<div class="content"><div class='highlight'><pre>CoffeeScript.runScripts = <span class="hljs-function">-></span>
|
||||
scripts = <span class="hljs-built_in">window</span>.<span class="hljs-built_in">document</span>.getElementsByTagName <span class="hljs-string">'script'</span>
|
||||
coffeetypes = [<span class="hljs-string">'text/coffeescript'</span>, <span class="hljs-string">'text/literate-coffeescript'</span>]
|
||||
coffees = (s <span class="hljs-keyword">for</span> s <span class="hljs-keyword">in</span> scripts <span class="hljs-keyword">when</span> s.type <span class="hljs-keyword">in</span> coffeetypes)
|
||||
@@ -321,14 +321,19 @@ only one CoffeeScript script block to parse.</p>
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-10">¶</a>
|
||||
</div>
|
||||
<p>Listen for window load, both in decent browsers and in IE.</p>
|
||||
<p>Listen for window load, both in decent browsers and in IE.
|
||||
Only attach this event handler on startup for the
|
||||
non-ES module version of the browser compiler, to preserve
|
||||
backward compatibility while letting the ES module version
|
||||
be importable without side effects.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">if</span> <span class="hljs-built_in">window</span>.addEventListener
|
||||
<span class="hljs-built_in">window</span>.addEventListener <span class="hljs-string">'DOMContentLoaded'</span>, runScripts, <span class="hljs-literal">no</span>
|
||||
<span class="hljs-keyword">else</span>
|
||||
<span class="hljs-built_in">window</span>.attachEvent <span class="hljs-string">'onload'</span>, runScripts</pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">if</span> <span class="hljs-keyword">this</span> <span class="hljs-keyword">is</span> <span class="hljs-built_in">window</span>
|
||||
<span class="hljs-keyword">if</span> <span class="hljs-built_in">window</span>.addEventListener
|
||||
<span class="hljs-built_in">window</span>.addEventListener <span class="hljs-string">'DOMContentLoaded'</span>, CoffeeScript.runScripts, <span class="hljs-literal">no</span>
|
||||
<span class="hljs-keyword">else</span>
|
||||
<span class="hljs-built_in">window</span>.attachEvent <span class="hljs-string">'onload'</span>, CoffeeScript.runScripts</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
@@ -282,6 +282,32 @@ it’s not likely to be used. Save in form of <code>filename</code>: [<code>(sou
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-10">¶</a>
|
||||
</div>
|
||||
<p>This is exported to enable an external module to implement caching of
|
||||
compilation results. When the compiled js source is loaded from cache, the
|
||||
original coffee code should be added with this method in order to enable the
|
||||
Error.prepareStackTrace below to correctly adjust the stack trace for the
|
||||
corresponding file (the source map will be generated on demand).</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>exports.registerCompiled = registerCompiled = <span class="hljs-function"><span class="hljs-params">(filename, source, sourcemap)</span> -></span>
|
||||
|
||||
sources[filename] ?= []
|
||||
sources[filename].push source
|
||||
|
||||
<span class="hljs-keyword">if</span> sourcemap?
|
||||
sourceMaps[filename] ?= []
|
||||
sourceMaps[filename].push sourcemap</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-11">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-11">¶</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
|
||||
@@ -298,11 +324,11 @@ doing programmatic lookups.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-11">
|
||||
<li id="section-12">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-11">¶</a>
|
||||
<a class="pilcrow" href="#section-12">¶</a>
|
||||
</div>
|
||||
<p>Clone <code>options</code>, to avoid mutating the <code>options</code> object passed in.</p>
|
||||
|
||||
@@ -313,11 +339,11 @@ doing programmatic lookups.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-12">
|
||||
<li id="section-13">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-12">¶</a>
|
||||
<a class="pilcrow" href="#section-13">¶</a>
|
||||
</div>
|
||||
<p>Always generate a source map if no filename is passed in, since without a
|
||||
a filename we have no way to retrieve this source later in the event that
|
||||
@@ -330,8 +356,6 @@ we need to recompile it to get a source map for <code>prepareStackTrace</code>.<
|
||||
|
||||
checkShebangLine filename, code
|
||||
|
||||
sources[filename] ?= []
|
||||
sources[filename].push code
|
||||
map = <span class="hljs-keyword">new</span> SourceMap <span class="hljs-keyword">if</span> generateSourceMap
|
||||
|
||||
tokens = lexer.tokenize code, options</pre></div></div>
|
||||
@@ -339,11 +363,11 @@ we need to recompile it to get a source map for <code>prepareStackTrace</code>.<
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-13">
|
||||
<li id="section-14">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-13">¶</a>
|
||||
<a class="pilcrow" href="#section-14">¶</a>
|
||||
</div>
|
||||
<p>Pass a list of referenced variables, so that generated variables won’t get
|
||||
the same name.</p>
|
||||
@@ -357,11 +381,11 @@ the same name.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-14">
|
||||
<li id="section-15">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-14">¶</a>
|
||||
<a class="pilcrow" href="#section-15">¶</a>
|
||||
</div>
|
||||
<p>Check for import or export; if found, force bare mode.</p>
|
||||
|
||||
@@ -385,11 +409,11 @@ the same name.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-15">
|
||||
<li id="section-16">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-15">¶</a>
|
||||
<a class="pilcrow" href="#section-16">¶</a>
|
||||
</div>
|
||||
<p>Update the sourcemap with data from each fragment.</p>
|
||||
|
||||
@@ -400,11 +424,11 @@ the same name.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-16">
|
||||
<li id="section-17">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-16">¶</a>
|
||||
<a class="pilcrow" href="#section-17">¶</a>
|
||||
</div>
|
||||
<p>Do not include empty, whitespace, or semicolon-only fragments.</p>
|
||||
|
||||
@@ -425,11 +449,11 @@ the same name.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-17">
|
||||
<li id="section-18">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-17">¶</a>
|
||||
<a class="pilcrow" href="#section-18">¶</a>
|
||||
</div>
|
||||
<p>Copy the code from each fragment into the final JavaScript.</p>
|
||||
|
||||
@@ -443,8 +467,6 @@ the same name.</p>
|
||||
|
||||
<span class="hljs-keyword">if</span> generateSourceMap
|
||||
v3SourceMap = map.generate options, code
|
||||
sourceMaps[filename] ?= []
|
||||
sourceMaps[filename].push map
|
||||
|
||||
<span class="hljs-keyword">if</span> options.transpile
|
||||
<span class="hljs-keyword">if</span> <span class="hljs-keyword">typeof</span> options.transpile <span class="hljs-keyword">isnt</span> <span class="hljs-string">'object'</span></pre></div></div>
|
||||
@@ -452,11 +474,11 @@ the same name.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-18">
|
||||
<li id="section-19">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-18">¶</a>
|
||||
<a class="pilcrow" href="#section-19">¶</a>
|
||||
</div>
|
||||
<p>This only happens if run via the Node API and <code>transpile</code> is set to
|
||||
something other than an object.</p>
|
||||
@@ -468,11 +490,11 @@ something other than an object.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-19">
|
||||
<li id="section-20">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-19">¶</a>
|
||||
<a class="pilcrow" href="#section-20">¶</a>
|
||||
</div>
|
||||
<p>Get the reference to Babel that we have been passed if this compiler
|
||||
is run via the CLI or Node API.</p>
|
||||
@@ -487,11 +509,11 @@ is run via the CLI or Node API.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-20">
|
||||
<li id="section-21">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-20">¶</a>
|
||||
<a class="pilcrow" href="#section-21">¶</a>
|
||||
</div>
|
||||
<p>See <a href="https://github.com/babel/babel/issues/827#issuecomment-77573107">https://github.com/babel/babel/issues/827#issuecomment-77573107</a>:
|
||||
Babel can take a v3 source map object as input in <code>inputSourceMap</code>
|
||||
@@ -512,6 +534,8 @@ and it will return an <em>updated</em> v3 source map object in its output.</p>
|
||||
sourceURL = <span class="hljs-string">"//# sourceURL=<span class="hljs-subst">#{options.filename ? <span class="hljs-string">'coffeescript'</span>}</span>"</span>
|
||||
js = <span class="hljs-string">"<span class="hljs-subst">#{js}</span>\n<span class="hljs-subst">#{sourceMapDataURI}</span>\n<span class="hljs-subst">#{sourceURL}</span>"</span>
|
||||
|
||||
registerCompiled filename, code, map
|
||||
|
||||
<span class="hljs-keyword">if</span> options.sourceMap
|
||||
{
|
||||
js
|
||||
@@ -524,11 +548,11 @@ and it will return an <em>updated</em> v3 source map object in its output.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-21">
|
||||
<li id="section-22">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-21">¶</a>
|
||||
<a class="pilcrow" href="#section-22">¶</a>
|
||||
</div>
|
||||
<p>Tokenize a string of CoffeeScript code, and return the array of tokens.</p>
|
||||
|
||||
@@ -540,11 +564,11 @@ and it will return an <em>updated</em> v3 source map object in its output.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-22">
|
||||
<li id="section-23">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-22">¶</a>
|
||||
<a class="pilcrow" href="#section-23">¶</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,
|
||||
@@ -561,11 +585,11 @@ or traverse it by using <code>.traverseChildren()</code> with a callback.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-23">
|
||||
<li id="section-24">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-23">¶</a>
|
||||
<a class="pilcrow" href="#section-24">¶</a>
|
||||
</div>
|
||||
<p>This file used to export these methods; leave stubs that throw warnings
|
||||
instead. These methods have been moved into <code>index.coffee</code> to provide
|
||||
@@ -581,11 +605,11 @@ environment.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-24">
|
||||
<li id="section-25">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-24">¶</a>
|
||||
<a class="pilcrow" href="#section-25">¶</a>
|
||||
</div>
|
||||
<p>Instantiate a Lexer for our use here.</p>
|
||||
|
||||
@@ -596,11 +620,11 @@ environment.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-25">
|
||||
<li id="section-26">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-25">¶</a>
|
||||
<a class="pilcrow" href="#section-26">¶</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
|
||||
@@ -626,11 +650,11 @@ directly as a “Jison lexer.”</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-26">
|
||||
<li id="section-27">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-26">¶</a>
|
||||
<a class="pilcrow" href="#section-27">¶</a>
|
||||
</div>
|
||||
<p>Make all the AST nodes visible to the parser.</p>
|
||||
|
||||
@@ -641,11 +665,11 @@ directly as a “Jison lexer.”</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-27">
|
||||
<li id="section-28">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-27">¶</a>
|
||||
<a class="pilcrow" href="#section-28">¶</a>
|
||||
</div>
|
||||
<p>Override Jison’s default error handling function.</p>
|
||||
|
||||
@@ -656,11 +680,11 @@ directly as a “Jison lexer.”</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-28">
|
||||
<li id="section-29">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-28">¶</a>
|
||||
<a class="pilcrow" href="#section-29">¶</a>
|
||||
</div>
|
||||
<p>Disregard Jison’s message, it contains redundant line number information.
|
||||
Disregard the token, we take its value directly from the lexer in case
|
||||
@@ -684,11 +708,11 @@ the error is caused by a generated token which might refer to its origin.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-29">
|
||||
<li id="section-30">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-29">¶</a>
|
||||
<a class="pilcrow" href="#section-30">¶</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>
|
||||
@@ -702,11 +726,11 @@ from the lexer.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-30">
|
||||
<li id="section-31">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-30">¶</a>
|
||||
<a class="pilcrow" href="#section-31">¶</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>
|
||||
@@ -734,11 +758,11 @@ Modified to handle sourceMap</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-31">
|
||||
<li id="section-32">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-31">¶</a>
|
||||
<a class="pilcrow" href="#section-32">¶</a>
|
||||
</div>
|
||||
<p>Check for a sourceMap position</p>
|
||||
|
||||
@@ -781,11 +805,11 @@ Modified to handle sourceMap</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-32">
|
||||
<li id="section-33">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-32">¶</a>
|
||||
<a class="pilcrow" href="#section-33">¶</a>
|
||||
</div>
|
||||
<p>Skip files that we didn’t compile, like Node system files that appear in
|
||||
the stack trace, as they never have source maps.</p>
|
||||
@@ -800,11 +824,11 @@ the stack trace, as they never have source maps.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-33">
|
||||
<li id="section-34">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-33">¶</a>
|
||||
<a class="pilcrow" href="#section-34">¶</a>
|
||||
</div>
|
||||
<p>CoffeeScript compiled in a browser or via <code>CoffeeScript.compile</code> or <code>.run</code>
|
||||
may get compiled with <code>options.filename</code> that’s missing, which becomes
|
||||
@@ -819,11 +843,11 @@ filename of the script file. See if we have a source map cached under
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-34">
|
||||
<li id="section-35">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-34">¶</a>
|
||||
<a class="pilcrow" href="#section-35">¶</a>
|
||||
</div>
|
||||
<p>Work backwards from the most recent anonymous source maps, until we find
|
||||
one that works. This isn’t foolproof; there is a chance that multiple
|
||||
@@ -840,11 +864,11 @@ and it’s not foolproof either.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-35">
|
||||
<li id="section-36">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-35">¶</a>
|
||||
<a class="pilcrow" href="#section-36">¶</a>
|
||||
</div>
|
||||
<p>If all else fails, recompile this source to get a source map. We need the
|
||||
previous section (for <code><anonymous></code>) despite this option, because after it
|
||||
@@ -867,11 +891,11 @@ time the source map we want is the last one.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-36">
|
||||
<li id="section-37">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-36">¶</a>
|
||||
<a class="pilcrow" href="#section-37">¶</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
|
||||
|
||||
@@ -616,6 +616,7 @@ the ordinary <strong>Assign</strong> is that these allow numbers and strings as
|
||||
o <span class="hljs-string">'Super'</span>
|
||||
o <span class="hljs-string">'This'</span>
|
||||
o <span class="hljs-string">'SUPER Arguments'</span>, <span class="hljs-function">-></span> <span class="hljs-keyword">new</span> SuperCall LOC(<span class="hljs-number">1</span>)(<span class="hljs-keyword">new</span> Super), $<span class="hljs-number">2</span>, <span class="hljs-literal">no</span>, $<span class="hljs-number">1</span>
|
||||
o <span class="hljs-string">'DYNAMIC_IMPORT Arguments'</span>, <span class="hljs-function">-></span> <span class="hljs-keyword">new</span> DynamicImportCall LOC(<span class="hljs-number">1</span>)(<span class="hljs-keyword">new</span> DynamicImport), $<span class="hljs-number">2</span>
|
||||
o <span class="hljs-string">'SimpleObjAssignable Arguments'</span>, <span class="hljs-function">-></span> <span class="hljs-keyword">new</span> Call (<span class="hljs-keyword">new</span> Value $<span class="hljs-number">1</span>), $<span class="hljs-number">2</span>
|
||||
o <span class="hljs-string">'ObjSpreadExpr Arguments'</span>, <span class="hljs-function">-></span> <span class="hljs-keyword">new</span> Call $<span class="hljs-number">1</span>, $<span class="hljs-number">2</span>
|
||||
]
|
||||
@@ -1089,6 +1090,7 @@ and optional references to the superclass.</p>
|
||||
o <span class="hljs-string">'Value OptFuncExist String'</span>, <span class="hljs-function">-></span> <span class="hljs-keyword">new</span> TaggedTemplateCall $<span class="hljs-number">1</span>, $<span class="hljs-number">3</span>, $<span class="hljs-number">2</span>
|
||||
o <span class="hljs-string">'Value OptFuncExist Arguments'</span>, <span class="hljs-function">-></span> <span class="hljs-keyword">new</span> Call $<span class="hljs-number">1</span>, $<span class="hljs-number">3</span>, $<span class="hljs-number">2</span>
|
||||
o <span class="hljs-string">'SUPER OptFuncExist Arguments'</span>, <span class="hljs-function">-></span> <span class="hljs-keyword">new</span> SuperCall LOC(<span class="hljs-number">1</span>)(<span class="hljs-keyword">new</span> Super), $<span class="hljs-number">3</span>, $<span class="hljs-number">2</span>, $<span class="hljs-number">1</span>
|
||||
o <span class="hljs-string">'DYNAMIC_IMPORT Arguments'</span>, <span class="hljs-function">-></span> <span class="hljs-keyword">new</span> DynamicImportCall LOC(<span class="hljs-number">1</span>)(<span class="hljs-keyword">new</span> DynamicImport), $<span class="hljs-number">2</span>
|
||||
]</pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -1850,7 +1852,7 @@ down. Following these rules is what makes <code>2 + 3 * 4</code> parse as:</p>
|
||||
[<span class="hljs-string">'right'</span>, <span class="hljs-string">'YIELD'</span>]
|
||||
[<span class="hljs-string">'right'</span>, <span class="hljs-string">'='</span>, <span class="hljs-string">':'</span>, <span class="hljs-string">'COMPOUND_ASSIGN'</span>, <span class="hljs-string">'RETURN'</span>, <span class="hljs-string">'THROW'</span>, <span class="hljs-string">'EXTENDS'</span>]
|
||||
[<span class="hljs-string">'right'</span>, <span class="hljs-string">'FORIN'</span>, <span class="hljs-string">'FOROF'</span>, <span class="hljs-string">'FORFROM'</span>, <span class="hljs-string">'BY'</span>, <span class="hljs-string">'WHEN'</span>]
|
||||
[<span class="hljs-string">'right'</span>, <span class="hljs-string">'IF'</span>, <span class="hljs-string">'ELSE'</span>, <span class="hljs-string">'FOR'</span>, <span class="hljs-string">'WHILE'</span>, <span class="hljs-string">'UNTIL'</span>, <span class="hljs-string">'LOOP'</span>, <span class="hljs-string">'SUPER'</span>, <span class="hljs-string">'CLASS'</span>, <span class="hljs-string">'IMPORT'</span>, <span class="hljs-string">'EXPORT'</span>]
|
||||
[<span class="hljs-string">'right'</span>, <span class="hljs-string">'IF'</span>, <span class="hljs-string">'ELSE'</span>, <span class="hljs-string">'FOR'</span>, <span class="hljs-string">'WHILE'</span>, <span class="hljs-string">'UNTIL'</span>, <span class="hljs-string">'LOOP'</span>, <span class="hljs-string">'SUPER'</span>, <span class="hljs-string">'CLASS'</span>, <span class="hljs-string">'IMPORT'</span>, <span class="hljs-string">'EXPORT'</span>, <span class="hljs-string">'DYNAMIC_IMPORT'</span>]
|
||||
[<span class="hljs-string">'left'</span>, <span class="hljs-string">'POST_IF'</span>]
|
||||
]</pre></div></div>
|
||||
|
||||
|
||||
@@ -403,8 +403,7 @@ CoffeeScript.register = <span class="hljs-function">-></span> <span class="hl
|
||||
Use CoffeeScript.register() or require the coffeescript/register module to require <span class="hljs-subst">#{ext}</span> files.
|
||||
"""</span>
|
||||
|
||||
CoffeeScript._compileFile = <span class="hljs-function"><span class="hljs-params">(filename, options = {})</span> -></span>
|
||||
raw = fs.readFileSync filename, <span class="hljs-string">'utf8'</span></pre></div></div>
|
||||
CoffeeScript._compileRawFileContent = <span class="hljs-function"><span class="hljs-params">(raw, filename, options = {})</span> -></span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -450,6 +449,11 @@ information to error so it can be pretty-printed later.</p>
|
||||
|
||||
answer
|
||||
|
||||
CoffeeScript._compileFile = <span class="hljs-function"><span class="hljs-params">(filename, options = {})</span> -></span>
|
||||
raw = fs.readFileSync filename, <span class="hljs-string">'utf8'</span>
|
||||
|
||||
CoffeeScript._compileRawFileContent raw, filename, options
|
||||
|
||||
<span class="hljs-built_in">module</span>.exports = CoffeeScript</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -1296,6 +1296,9 @@ parentheses that indicate a method call from regular parentheses, and so on.</p>
|
||||
@error message, origin[<span class="hljs-number">2</span>] <span class="hljs-keyword">if</span> message
|
||||
<span class="hljs-keyword">return</span> value.length <span class="hljs-keyword">if</span> skipToken
|
||||
|
||||
<span class="hljs-keyword">if</span> value <span class="hljs-keyword">is</span> <span class="hljs-string">'('</span> <span class="hljs-keyword">and</span> prev?[<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">'IMPORT'</span>
|
||||
prev[<span class="hljs-number">0</span>] = <span class="hljs-string">'DYNAMIC_IMPORT'</span>
|
||||
|
||||
<span class="hljs-keyword">if</span> value <span class="hljs-keyword">is</span> <span class="hljs-string">'{'</span> <span class="hljs-keyword">and</span> @seenImport
|
||||
@importSpecifierList = <span class="hljs-literal">yes</span>
|
||||
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> @importSpecifierList <span class="hljs-keyword">and</span> value <span class="hljs-keyword">is</span> <span class="hljs-string">'}'</span>
|
||||
@@ -2270,8 +2273,7 @@ loop. Try to detect when <code>from</code> is a variable identifier and when it
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">isForFrom</span> = <span class="hljs-params">(prev)</span> -></span>
|
||||
<span class="hljs-keyword">if</span> prev[<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">'IDENTIFIER'</span></pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">isForFrom</span> = <span class="hljs-params">(prev)</span> -></span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -2282,13 +2284,12 @@ loop. Try to detect when <code>from</code> is a variable identifier and when it
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-88">¶</a>
|
||||
</div>
|
||||
<p><code>for i from from</code>, <code>for from from iterable</code></p>
|
||||
<p><code>for i from iterable</code></p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> prev[<span class="hljs-number">1</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">'from'</span>
|
||||
prev[<span class="hljs-number">1</span>][<span class="hljs-number">0</span>] = <span class="hljs-string">'IDENTIFIER'</span>
|
||||
<span class="hljs-literal">yes</span></pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> prev[<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">'IDENTIFIER'</span>
|
||||
<span class="hljs-literal">yes</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -2299,21 +2300,6 @@ loop. Try to detect when <code>from</code> is a variable identifier and when it
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-89">¶</a>
|
||||
</div>
|
||||
<p><code>for i from iterable</code></p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-literal">yes</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-90">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-90">¶</a>
|
||||
</div>
|
||||
<p><code>for from…</code></p>
|
||||
|
||||
</div>
|
||||
@@ -2324,11 +2310,11 @@ loop. Try to detect when <code>from</code> is a variable identifier and when it
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-91">
|
||||
<li id="section-90">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-91">¶</a>
|
||||
<a class="pilcrow" href="#section-90">¶</a>
|
||||
</div>
|
||||
<p><code>for {from}…</code>, <code>for [from]…</code>, <code>for {a, from}…</code>, <code>for {a: from}…</code></p>
|
||||
|
||||
@@ -2342,14 +2328,26 @@ loop. Try to detect when <code>from</code> is a variable identifier and when it
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-91">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-91">¶</a>
|
||||
</div>
|
||||
<h2 id="constants">Constants</h2>
|
||||
|
||||
</div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-92">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-92">¶</a>
|
||||
</div>
|
||||
<h2 id="constants">Constants</h2>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</li>
|
||||
@@ -2361,18 +2359,6 @@ loop. Try to detect when <code>from</code> is a variable identifier and when it
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-93">¶</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-94">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-94">¶</a>
|
||||
</div>
|
||||
<p>Keywords that CoffeeScript shares in common with JavaScript.</p>
|
||||
|
||||
</div>
|
||||
@@ -2389,11 +2375,11 @@ loop. Try to detect when <code>from</code> is a variable identifier and when it
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-95">
|
||||
<li id="section-94">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-95">¶</a>
|
||||
<a class="pilcrow" href="#section-94">¶</a>
|
||||
</div>
|
||||
<p>CoffeeScript-only keywords.</p>
|
||||
|
||||
@@ -2421,11 +2407,11 @@ COFFEE_KEYWORDS = COFFEE_KEYWORDS.concat COFFEE_ALIASES</pre></div></div>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-96">
|
||||
<li id="section-95">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-96">¶</a>
|
||||
<a class="pilcrow" href="#section-95">¶</a>
|
||||
</div>
|
||||
<p>The list of keywords that are reserved by JavaScript, but not used, or are
|
||||
used by CoffeeScript internally. We throw an error when these are encountered,
|
||||
@@ -2444,11 +2430,11 @@ STRICT_PROSCRIBED = [<span class="hljs-string">'arguments'</span>, <span class="
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-97">
|
||||
<li id="section-96">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-97">¶</a>
|
||||
<a class="pilcrow" href="#section-96">¶</a>
|
||||
</div>
|
||||
<p>The superset of both JavaScript keywords and reserved words, none of which may
|
||||
be used as identifiers or properties.</p>
|
||||
@@ -2460,11 +2446,11 @@ be used as identifiers or properties.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-98">
|
||||
<li id="section-97">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-98">¶</a>
|
||||
<a class="pilcrow" href="#section-97">¶</a>
|
||||
</div>
|
||||
<p>The character code of the nasty Microsoft madness otherwise known as the BOM.</p>
|
||||
|
||||
@@ -2475,11 +2461,11 @@ be used as identifiers or properties.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-99">
|
||||
<li id="section-98">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-99">¶</a>
|
||||
<a class="pilcrow" href="#section-98">¶</a>
|
||||
</div>
|
||||
<p>Token matching regexes.</p>
|
||||
|
||||
@@ -2499,11 +2485,11 @@ CSX_IDENTIFIER = <span class="hljs-regexp">/// ^
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-100">
|
||||
<li id="section-99">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-100">¶</a>
|
||||
<a class="pilcrow" href="#section-99">¶</a>
|
||||
</div>
|
||||
<p>Fragment: <></></p>
|
||||
|
||||
@@ -2550,11 +2536,11 @@ HERE_JSTOKEN = <span class="hljs-regexp">///^ ``` ((?: [^`\\] | \\[\s\S] | `
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-101">
|
||||
<li id="section-100">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-101">¶</a>
|
||||
<a class="pilcrow" href="#section-100">¶</a>
|
||||
</div>
|
||||
<p>String-matching-regexes.</p>
|
||||
|
||||
@@ -2588,11 +2574,11 @@ HEREDOC_INDENT = <span class="hljs-regexp">/\n+([^\n\S]*)(?=\S)/g</span></pr
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-102">
|
||||
<li id="section-101">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-102">¶</a>
|
||||
<a class="pilcrow" href="#section-101">¶</a>
|
||||
</div>
|
||||
<p>Regex-matching-regexes.</p>
|
||||
|
||||
@@ -2618,11 +2604,11 @@ HEREGEX = <span class="hljs-regexp">/// ^
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-103">
|
||||
<li id="section-102">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-103">¶</a>
|
||||
<a class="pilcrow" href="#section-102">¶</a>
|
||||
</div>
|
||||
<p>Match any character, except those that need special handling below.</p>
|
||||
|
||||
@@ -2633,11 +2619,11 @@ HEREGEX = <span class="hljs-regexp">/// ^
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-104">
|
||||
<li id="section-103">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-104">¶</a>
|
||||
<a class="pilcrow" href="#section-103">¶</a>
|
||||
</div>
|
||||
<p>Match <code>\</code> followed by any character.</p>
|
||||
|
||||
@@ -2648,11 +2634,11 @@ HEREGEX = <span class="hljs-regexp">/// ^
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-105">
|
||||
<li id="section-104">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-105">¶</a>
|
||||
<a class="pilcrow" href="#section-104">¶</a>
|
||||
</div>
|
||||
<p>Match any <code>/</code> except <code>///</code>.</p>
|
||||
|
||||
@@ -2663,11 +2649,11 @@ HEREGEX = <span class="hljs-regexp">/// ^
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-106">
|
||||
<li id="section-105">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-106">¶</a>
|
||||
<a class="pilcrow" href="#section-105">¶</a>
|
||||
</div>
|
||||
<p>Match <code>#</code> which is not part of interpolation, e.g. <code>#{}</code>.</p>
|
||||
|
||||
@@ -2678,11 +2664,11 @@ HEREGEX = <span class="hljs-regexp">/// ^
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-107">
|
||||
<li id="section-106">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-107">¶</a>
|
||||
<a class="pilcrow" href="#section-106">¶</a>
|
||||
</div>
|
||||
<p>Comments consume everything until the end of the line, including <code>///</code>.</p>
|
||||
|
||||
@@ -2705,11 +2691,11 @@ POSSIBLY_DIVISION = <span class="hljs-regexp">/// ^ /=?\s ///</span></pre></di
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-108">
|
||||
<li id="section-107">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-108">¶</a>
|
||||
<a class="pilcrow" href="#section-107">¶</a>
|
||||
</div>
|
||||
<p>Other regexes.</p>
|
||||
|
||||
@@ -2752,11 +2738,11 @@ TRAILING_SPACES = <span class="hljs-regexp">/\s+$/</span></pre></div></div>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-109">
|
||||
<li id="section-108">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-109">¶</a>
|
||||
<a class="pilcrow" href="#section-108">¶</a>
|
||||
</div>
|
||||
<p>Compound assignment tokens.</p>
|
||||
|
||||
@@ -2770,11 +2756,11 @@ TRAILING_SPACES = <span class="hljs-regexp">/\s+$/</span></pre></div></div>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-110">
|
||||
<li id="section-109">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-110">¶</a>
|
||||
<a class="pilcrow" href="#section-109">¶</a>
|
||||
</div>
|
||||
<p>Unary tokens.</p>
|
||||
|
||||
@@ -2787,11 +2773,11 @@ UNARY_MATH = [<span class="hljs-string">'!'</span>, <span class="hljs-string">'~
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-111">
|
||||
<li id="section-110">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-111">¶</a>
|
||||
<a class="pilcrow" href="#section-110">¶</a>
|
||||
</div>
|
||||
<p>Bit-shifting tokens.</p>
|
||||
|
||||
@@ -2802,11 +2788,11 @@ UNARY_MATH = [<span class="hljs-string">'!'</span>, <span class="hljs-string">'~
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-112">
|
||||
<li id="section-111">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-112">¶</a>
|
||||
<a class="pilcrow" href="#section-111">¶</a>
|
||||
</div>
|
||||
<p>Comparison tokens.</p>
|
||||
|
||||
@@ -2817,11 +2803,11 @@ UNARY_MATH = [<span class="hljs-string">'!'</span>, <span class="hljs-string">'~
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-113">
|
||||
<li id="section-112">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-113">¶</a>
|
||||
<a class="pilcrow" href="#section-112">¶</a>
|
||||
</div>
|
||||
<p>Mathematical tokens.</p>
|
||||
|
||||
@@ -2832,11 +2818,11 @@ UNARY_MATH = [<span class="hljs-string">'!'</span>, <span class="hljs-string">'~
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-114">
|
||||
<li id="section-113">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-114">¶</a>
|
||||
<a class="pilcrow" href="#section-113">¶</a>
|
||||
</div>
|
||||
<p>Relational tokens that are negatable with <code>not</code> prefix.</p>
|
||||
|
||||
@@ -2847,11 +2833,11 @@ UNARY_MATH = [<span class="hljs-string">'!'</span>, <span class="hljs-string">'~
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-115">
|
||||
<li id="section-114">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-115">¶</a>
|
||||
<a class="pilcrow" href="#section-114">¶</a>
|
||||
</div>
|
||||
<p>Boolean tokens.</p>
|
||||
|
||||
@@ -2862,11 +2848,11 @@ UNARY_MATH = [<span class="hljs-string">'!'</span>, <span class="hljs-string">'~
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-116">
|
||||
<li id="section-115">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-116">¶</a>
|
||||
<a class="pilcrow" href="#section-115">¶</a>
|
||||
</div>
|
||||
<p>Tokens which could legitimately be invoked or indexed. An opening
|
||||
parentheses or bracket following these tokens will be recorded as the start
|
||||
@@ -2874,7 +2860,7 @@ of a function invocation or indexing operation.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>CALLABLE = [<span class="hljs-string">'IDENTIFIER'</span>, <span class="hljs-string">'PROPERTY'</span>, <span class="hljs-string">')'</span>, <span class="hljs-string">']'</span>, <span class="hljs-string">'?'</span>, <span class="hljs-string">'@'</span>, <span class="hljs-string">'THIS'</span>, <span class="hljs-string">'SUPER'</span>]
|
||||
<div class="content"><div class='highlight'><pre>CALLABLE = [<span class="hljs-string">'IDENTIFIER'</span>, <span class="hljs-string">'PROPERTY'</span>, <span class="hljs-string">')'</span>, <span class="hljs-string">']'</span>, <span class="hljs-string">'?'</span>, <span class="hljs-string">'@'</span>, <span class="hljs-string">'THIS'</span>, <span class="hljs-string">'SUPER'</span>, <span class="hljs-string">'DYNAMIC_IMPORT'</span>]
|
||||
INDEXABLE = CALLABLE.concat [
|
||||
<span class="hljs-string">'NUMBER'</span>, <span class="hljs-string">'INFINITY'</span>, <span class="hljs-string">'NAN'</span>, <span class="hljs-string">'STRING'</span>, <span class="hljs-string">'STRING_END'</span>, <span class="hljs-string">'REGEX'</span>, <span class="hljs-string">'REGEX_END'</span>
|
||||
<span class="hljs-string">'BOOL'</span>, <span class="hljs-string">'NULL'</span>, <span class="hljs-string">'UNDEFINED'</span>, <span class="hljs-string">'}'</span>, <span class="hljs-string">'::'</span>
|
||||
@@ -2883,11 +2869,11 @@ INDEXABLE = CALLABLE.concat [
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-117">
|
||||
<li id="section-116">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-117">¶</a>
|
||||
<a class="pilcrow" href="#section-116">¶</a>
|
||||
</div>
|
||||
<p>Tokens which can be the left-hand side of a less-than comparison, i.e. <code>a<b</code>.</p>
|
||||
|
||||
@@ -2898,11 +2884,11 @@ INDEXABLE = CALLABLE.concat [
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-118">
|
||||
<li id="section-117">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-118">¶</a>
|
||||
<a class="pilcrow" href="#section-117">¶</a>
|
||||
</div>
|
||||
<p>Tokens which a regular expression will never immediately follow (except spaced
|
||||
CALLABLEs in some cases), but which a division operator can.</p>
|
||||
@@ -2915,11 +2901,11 @@ CALLABLEs in some cases), but which a division operator can.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-119">
|
||||
<li id="section-118">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-119">¶</a>
|
||||
<a class="pilcrow" href="#section-118">¶</a>
|
||||
</div>
|
||||
<p>Tokens that, when immediately preceding a <code>WHEN</code>, indicate that the <code>WHEN</code>
|
||||
occurs at the start of a line. We disambiguate these from trailing whens to
|
||||
@@ -2932,11 +2918,11 @@ avoid an ambiguity in the grammar.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-120">
|
||||
<li id="section-119">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-120">¶</a>
|
||||
<a class="pilcrow" href="#section-119">¶</a>
|
||||
</div>
|
||||
<p>Additional indent in front of these is ignored.</p>
|
||||
|
||||
@@ -2947,11 +2933,11 @@ avoid an ambiguity in the grammar.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-121">
|
||||
<li id="section-120">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-121">¶</a>
|
||||
<a class="pilcrow" href="#section-120">¶</a>
|
||||
</div>
|
||||
<p>Tokens that, when appearing at the end of a line, suppress a following TERMINATOR/INDENT token</p>
|
||||
|
||||
|
||||
@@ -542,7 +542,7 @@ the two values are raw nodes which have not been compiled.</p>
|
||||
</div>
|
||||
<p>Occasionally it may be useful to make an expression behave as if it was ‘hoisted’, whereby the
|
||||
result of the expression is available before its location in the source, but the expression’s
|
||||
variable scope corresponds the source position. This is used extensively to deal with executable
|
||||
variable scope corresponds to the source position. This is used extensively to deal with executable
|
||||
class bodies in classes.</p>
|
||||
<p>Calling this method mutates the node, proxying the <code>compileNode</code> and <code>compileToFragments</code>
|
||||
methods to store their result for later replacing the <code>target</code> node, which is returned by the
|
||||
@@ -3479,7 +3479,8 @@ are too.</p>
|
||||
compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
|
||||
<span class="hljs-keyword">return</span> [@makeCode <span class="hljs-string">'[]'</span>] <span class="hljs-keyword">unless</span> @objects.length
|
||||
o.indent += TAB
|
||||
<span class="hljs-function"> <span class="hljs-title">fragmentIsElision</span> = <span class="hljs-params">(fragment)</span> -></span> fragmentsToText(fragment).trim() <span class="hljs-keyword">is</span> <span class="hljs-string">','</span></pre></div></div>
|
||||
<span class="hljs-function"> <span class="hljs-title">fragmentIsElision</span> = <span class="hljs-params">([ fragment ])</span> -></span>
|
||||
fragment.type <span class="hljs-keyword">is</span> <span class="hljs-string">'Elision'</span> <span class="hljs-keyword">and</span> fragment.code.trim() <span class="hljs-keyword">is</span> <span class="hljs-string">','</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -3490,7 +3491,7 @@ are too.</p>
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-144">¶</a>
|
||||
</div>
|
||||
<p>Detect if <code>Elisions</code> at the beginning of the array are processed (e.g. [, , , a]).</p>
|
||||
<p>Detect if <code>Elision</code>s at the beginning of the array are processed (e.g. [, , , a]).</p>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -3587,7 +3588,7 @@ element isn’t <code>Elision</code> or last element is <code>Elision</code> (e.
|
||||
<span class="hljs-keyword">for</span> fragment, fragmentIndex <span class="hljs-keyword">in</span> answer
|
||||
<span class="hljs-keyword">if</span> fragment.isHereComment
|
||||
fragment.code = <span class="hljs-string">"<span class="hljs-subst">#{multident(fragment.code, o.indent, <span class="hljs-literal">no</span>)}</span>\n<span class="hljs-subst">#{o.indent}</span>"</span>
|
||||
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> fragment.code <span class="hljs-keyword">is</span> <span class="hljs-string">', '</span> <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> fragment?.isElision
|
||||
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> fragment.code <span class="hljs-keyword">is</span> <span class="hljs-string">', '</span> <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> fragment?.isElision <span class="hljs-keyword">and</span> fragment.type <span class="hljs-keyword">isnt</span> <span class="hljs-string">'StringLiteral'</span>
|
||||
fragment.code = <span class="hljs-string">",\n<span class="hljs-subst">#{o.indent}</span>"</span>
|
||||
answer.unshift @makeCode <span class="hljs-string">"[\n<span class="hljs-subst">#{o.indent}</span>"</span>
|
||||
answer.push @makeCode <span class="hljs-string">"\n<span class="hljs-subst">#{@tab}</span>]"</span>
|
||||
@@ -3996,7 +3997,7 @@ exports.ExecutableClassBody = <span class="hljs-class"><span class="hljs-keyword
|
||||
@body.traverseChildren <span class="hljs-literal">false</span>, <span class="hljs-function"><span class="hljs-params">(node)</span> =></span>
|
||||
<span class="hljs-keyword">if</span> node <span class="hljs-keyword">instanceof</span> ThisLiteral
|
||||
node.value = @name
|
||||
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> node <span class="hljs-keyword">instanceof</span> Code <span class="hljs-keyword">and</span> node.bound <span class="hljs-keyword">and</span> node.isStatic
|
||||
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> node <span class="hljs-keyword">instanceof</span> Code <span class="hljs-keyword">and</span> node.bound <span class="hljs-keyword">and</span> (node.isStatic <span class="hljs-keyword">or</span> <span class="hljs-keyword">not</span> node.name)
|
||||
node.context = @name</pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -4251,7 +4252,17 @@ exports.ImportNamespaceSpecifier = <span class="hljs-class"><span class="hljs-ke
|
||||
|
||||
exports.ExportSpecifier = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ExportSpecifier</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ModuleSpecifier</span></span>
|
||||
constructor: <span class="hljs-function"><span class="hljs-params">(local, exported)</span> -></span>
|
||||
<span class="hljs-keyword">super</span> local, exported, <span class="hljs-string">'export'</span></pre></div></div>
|
||||
<span class="hljs-keyword">super</span> local, exported, <span class="hljs-string">'export'</span>
|
||||
|
||||
exports.DynamicImport = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DynamicImport</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
|
||||
compileNode: <span class="hljs-function">-></span>
|
||||
[@makeCode <span class="hljs-string">'import'</span>]
|
||||
|
||||
exports.DynamicImportCall = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DynamicImportCall</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Call</span></span>
|
||||
compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
|
||||
<span class="hljs-keyword">unless</span> @args.length <span class="hljs-keyword">is</span> <span class="hljs-number">1</span>
|
||||
@error <span class="hljs-string">'import() requires exactly one argument'</span>
|
||||
<span class="hljs-keyword">super</span> o</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -5582,7 +5593,7 @@ This is usually caught via <code>Op::compileContinuation</code>, but double-chec
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> scopeVariablesCount = o.scope.variables.length
|
||||
signature.push param.compileToFragments(o)...
|
||||
signature.push param.compileToFragments(o, LEVEL_PAREN)...
|
||||
<span class="hljs-keyword">if</span> scopeVariablesCount <span class="hljs-keyword">isnt</span> o.scope.variables.length
|
||||
generatedVariables = o.scope.variables.splice scopeVariablesCount
|
||||
o.scope.parent.variables.push generatedVariables...
|
||||
|
||||
@@ -376,7 +376,7 @@ undeclared variable <code>__</code>.</p>
|
||||
vm.runInContext js, context, filename
|
||||
<span class="hljs-function">
|
||||
<span class="hljs-title">addMultilineHandler</span> = <span class="hljs-params">(repl)</span> -></span>
|
||||
{rli, inputStream, outputStream} = repl</pre></div></div>
|
||||
{inputStream, outputStream} = repl</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -412,15 +412,15 @@ undeclared variable <code>__</code>.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> nodeLineListener = rli.listeners(<span class="hljs-string">'line'</span>)[<span class="hljs-number">0</span>]
|
||||
rli.removeListener <span class="hljs-string">'line'</span>, nodeLineListener
|
||||
rli.<span class="hljs-literal">on</span> <span class="hljs-string">'line'</span>, <span class="hljs-function"><span class="hljs-params">(cmd)</span> -></span>
|
||||
<div class="content"><div class='highlight'><pre> nodeLineListener = repl.listeners(<span class="hljs-string">'line'</span>)[<span class="hljs-number">0</span>]
|
||||
repl.removeListener <span class="hljs-string">'line'</span>, nodeLineListener
|
||||
repl.<span class="hljs-literal">on</span> <span class="hljs-string">'line'</span>, <span class="hljs-function"><span class="hljs-params">(cmd)</span> -></span>
|
||||
<span class="hljs-keyword">if</span> multiline.enabled
|
||||
multiline.buffer += <span class="hljs-string">"<span class="hljs-subst">#{cmd}</span>\n"</span>
|
||||
rli.setPrompt multiline.prompt
|
||||
rli.prompt <span class="hljs-literal">true</span>
|
||||
repl.setPrompt multiline.prompt
|
||||
repl.prompt <span class="hljs-literal">true</span>
|
||||
<span class="hljs-keyword">else</span>
|
||||
rli.setPrompt origPrompt
|
||||
repl.setPrompt origPrompt
|
||||
nodeLineListener cmd
|
||||
<span class="hljs-keyword">return</span></pre></div></div>
|
||||
|
||||
@@ -456,8 +456,8 @@ undeclared variable <code>__</code>.</p>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">unless</span> multiline.buffer.match <span class="hljs-regexp">/\n/</span>
|
||||
multiline.enabled = <span class="hljs-keyword">not</span> multiline.enabled
|
||||
rli.setPrompt origPrompt
|
||||
rli.prompt <span class="hljs-literal">true</span>
|
||||
repl.setPrompt origPrompt
|
||||
repl.prompt <span class="hljs-literal">true</span>
|
||||
<span class="hljs-keyword">return</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -473,7 +473,7 @@ undeclared variable <code>__</code>.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">return</span> <span class="hljs-keyword">if</span> rli.line? <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> rli.line.match <span class="hljs-regexp">/^\s*$/</span></pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">return</span> <span class="hljs-keyword">if</span> repl.line? <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> repl.line.match <span class="hljs-regexp">/^\s*$/</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -489,10 +489,10 @@ undeclared variable <code>__</code>.</p>
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> multiline.enabled = <span class="hljs-keyword">not</span> multiline.enabled
|
||||
rli.line = <span class="hljs-string">''</span>
|
||||
rli.cursor = <span class="hljs-number">0</span>
|
||||
rli.output.cursorTo <span class="hljs-number">0</span>
|
||||
rli.output.clearLine <span class="hljs-number">1</span></pre></div></div>
|
||||
repl.line = <span class="hljs-string">''</span>
|
||||
repl.cursor = <span class="hljs-number">0</span>
|
||||
repl.output.cursorTo <span class="hljs-number">0</span>
|
||||
repl.output.clearLine <span class="hljs-number">1</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -508,12 +508,12 @@ undeclared variable <code>__</code>.</p>
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> multiline.buffer = multiline.buffer.replace <span class="hljs-regexp">/\n/g</span>, <span class="hljs-string">'\uFF00'</span>
|
||||
rli.emit <span class="hljs-string">'line'</span>, multiline.buffer
|
||||
repl.emit <span class="hljs-string">'line'</span>, multiline.buffer
|
||||
multiline.buffer = <span class="hljs-string">''</span>
|
||||
<span class="hljs-keyword">else</span>
|
||||
multiline.enabled = <span class="hljs-keyword">not</span> multiline.enabled
|
||||
rli.setPrompt multiline.initialPrompt
|
||||
rli.prompt <span class="hljs-literal">true</span>
|
||||
repl.setPrompt multiline.initialPrompt
|
||||
repl.prompt <span class="hljs-literal">true</span>
|
||||
<span class="hljs-keyword">return</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -580,7 +580,7 @@ undeclared variable <code>__</code>.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> repl.rli.history = buffer.toString().split(<span class="hljs-string">'\n'</span>).reverse()</pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre> repl.history = buffer.toString().split(<span class="hljs-string">'\n'</span>).reverse()</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -595,7 +595,7 @@ undeclared variable <code>__</code>.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> repl.rli.history.pop() <span class="hljs-keyword">if</span> stat.size > maxSize</pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre> repl.history.pop() <span class="hljs-keyword">if</span> stat.size > maxSize</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -610,13 +610,13 @@ undeclared variable <code>__</code>.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> repl.rli.history.shift() <span class="hljs-keyword">if</span> repl.rli.history[<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">''</span>
|
||||
repl.rli.historyIndex = <span class="hljs-number">-1</span>
|
||||
lastLine = repl.rli.history[<span class="hljs-number">0</span>]
|
||||
<div class="content"><div class='highlight'><pre> repl.history.shift() <span class="hljs-keyword">if</span> repl.history[<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">''</span>
|
||||
repl.historyIndex = <span class="hljs-number">-1</span>
|
||||
lastLine = repl.history[<span class="hljs-number">0</span>]
|
||||
|
||||
fd = fs.openSync filename, <span class="hljs-string">'a'</span>
|
||||
|
||||
repl.rli.addListener <span class="hljs-string">'line'</span>, <span class="hljs-function"><span class="hljs-params">(code)</span> -></span>
|
||||
repl.addListener <span class="hljs-string">'line'</span>, <span class="hljs-function"><span class="hljs-params">(code)</span> -></span>
|
||||
<span class="hljs-keyword">if</span> code <span class="hljs-keyword">and</span> code.length <span class="hljs-keyword">and</span> code <span class="hljs-keyword">isnt</span> <span class="hljs-string">'.history'</span> <span class="hljs-keyword">and</span> code <span class="hljs-keyword">isnt</span> <span class="hljs-string">'.exit'</span> <span class="hljs-keyword">and</span> lastLine <span class="hljs-keyword">isnt</span> code</pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -667,7 +667,7 @@ undeclared variable <code>__</code>.</p>
|
||||
<div class="content"><div class='highlight'><pre> repl.commands[getCommandId(repl, <span class="hljs-string">'history'</span>)] =
|
||||
help: <span class="hljs-string">'Show command history'</span>
|
||||
action: <span class="hljs-function">-></span>
|
||||
repl.outputStream.write <span class="hljs-string">"<span class="hljs-subst">#{repl.rli.history[..].reverse().join <span class="hljs-string">'\n'</span>}</span>\n"</span>
|
||||
repl.outputStream.write <span class="hljs-string">"<span class="hljs-subst">#{repl.history[..].reverse().join <span class="hljs-string">'\n'</span>}</span>\n"</span>
|
||||
repl.displayPrompt()
|
||||
<span class="hljs-function">
|
||||
<span class="hljs-title">getCommandId</span> = <span class="hljs-params">(repl, commandName)</span> -></span></pre></div></div>
|
||||
@@ -742,7 +742,7 @@ the REPL, the only applicable option is <code>transpile</code>.</p>
|
||||
opts = merge replDefaults, opts
|
||||
repl = nodeREPL.start opts
|
||||
runInContext opts.prelude, repl.context, <span class="hljs-string">'prelude'</span> <span class="hljs-keyword">if</span> opts.prelude
|
||||
repl.<span class="hljs-literal">on</span> <span class="hljs-string">'exit'</span>, <span class="hljs-function">-></span> repl.outputStream.write <span class="hljs-string">'\n'</span> <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> repl.rli.closed
|
||||
repl.<span class="hljs-literal">on</span> <span class="hljs-string">'exit'</span>, <span class="hljs-function">-></span> repl.outputStream.write <span class="hljs-string">'\n'</span> <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> repl.closed
|
||||
addMultilineHandler repl
|
||||
addHistory repl, opts.historyFile, opts.historyMaxInputSize <span class="hljs-keyword">if</span> opts.historyFile</pre></div></div>
|
||||
|
||||
|
||||
11224
docs/v2/browser-compiler-modern/coffeescript.js
Normal file
11224
docs/v2/browser-compiler-modern/coffeescript.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -3,7 +3,12 @@
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
|
||||
<title>CoffeeScript Test Suite</title>
|
||||
<script src="browser-compiler/coffeescript.js"></script>
|
||||
<script nomodule src="browser-compiler/coffeescript.js"></script>
|
||||
<script type="module">
|
||||
import CoffeeScript from './browser-compiler-modern/coffeescript.js';
|
||||
window.CoffeeScript = CoffeeScript;
|
||||
window.addEventListener('DOMContentLoaded', CoffeeScript.runScripts, false);
|
||||
</script>
|
||||
<script src="https://cdn.jsdelivr.net/underscorejs/1.8.3/underscore-min.js"></script>
|
||||
<style>
|
||||
body, pre {
|
||||
@@ -452,6 +457,12 @@ test "array elisions nested destructuring", ->
|
||||
deepEqual d, {x:2}
|
||||
arrayEq w, [1,2,4]
|
||||
|
||||
test "#5112: array elisions not detected inside strings", ->
|
||||
arr = [
|
||||
str: ", #{3}"
|
||||
]
|
||||
eq arr[0].str, ', 3'
|
||||
|
||||
# Splats in Array Literals
|
||||
|
||||
test "array splat expansions with assignments", ->
|
||||
@@ -3546,6 +3557,19 @@ test "#4609: Support new.target", ->
|
||||
new Foo()
|
||||
eq newTarget, yes
|
||||
|
||||
test "#5085: Bug: @ reference to class not maintained in do block", ->
|
||||
thisFoo = 'initial foo'
|
||||
thisBar = 'initial bar'
|
||||
fn = (o) -> o.bar()
|
||||
|
||||
class A
|
||||
@foo = 'foo assigned in class'
|
||||
do => thisFoo = @foo
|
||||
fn bar: => thisBar = @foo
|
||||
|
||||
eq thisFoo, 'foo assigned in class'
|
||||
eq thisBar, 'foo assigned in class'
|
||||
|
||||
</script>
|
||||
<script type="text/x-coffeescript" class="test" id="cluster">
|
||||
# Cluster Module
|
||||
@@ -9580,6 +9604,32 @@ test "`new.target` is only allowed meta property", ->
|
||||
^^^^^^^^^^^^^
|
||||
'''
|
||||
|
||||
test "#4834: dynamic import requires exactly one argument", ->
|
||||
assertErrorFormat '''
|
||||
import()
|
||||
''', '''
|
||||
[stdin]:1:1: error: import() requires exactly one argument
|
||||
import()
|
||||
^^^^^^^^
|
||||
'''
|
||||
|
||||
assertErrorFormat '''
|
||||
import('x', {})
|
||||
''', '''
|
||||
[stdin]:1:1: error: import() requires exactly one argument
|
||||
import('x', {})
|
||||
^^^^^^^^^^^^^^^
|
||||
'''
|
||||
|
||||
test "#4834: dynamic import requires explicit call parentheses", ->
|
||||
assertErrorFormat '''
|
||||
promise = import 'foo'
|
||||
''', '''
|
||||
[stdin]:1:23: error: unexpected end of input
|
||||
promise = import 'foo'
|
||||
^
|
||||
'''
|
||||
|
||||
</script>
|
||||
<script type="text/x-coffeescript" class="test" id="eval">
|
||||
if vm = require? 'vm'
|
||||
@@ -11724,6 +11774,10 @@ test "#4657: destructured array parameters", ->
|
||||
arrayEq result.a, [1, 2, 3]
|
||||
eq result.b, 4
|
||||
|
||||
test "#5128: default parameters of function in binary operation", ->
|
||||
foo = yes or (a, b = {}) -> null
|
||||
eq foo, yes
|
||||
|
||||
</script>
|
||||
<script type="text/x-coffeescript" class="test" id="generators">
|
||||
# Generators
|
||||
@@ -14443,6 +14497,27 @@ test "#4874: backslash `export`", ->
|
||||
} from 'underscore';
|
||||
"""
|
||||
|
||||
test "#4834: dynamic import", ->
|
||||
eqJS """
|
||||
import('module').then ->
|
||||
""",
|
||||
"""
|
||||
import('module').then(function() {});
|
||||
"""
|
||||
|
||||
eqJS """
|
||||
foo = ->
|
||||
bar = await import('bar')
|
||||
""",
|
||||
"""
|
||||
var foo;
|
||||
|
||||
foo = async function() {
|
||||
var bar;
|
||||
return bar = (await import('bar'));
|
||||
};
|
||||
"""
|
||||
|
||||
</script>
|
||||
<script type="text/x-coffeescript" class="test" id="numbers">
|
||||
# Number Literals
|
||||
@@ -14957,6 +15032,16 @@ test "#4673: complex destructured object spread variables", ->
|
||||
eq @y.b, 1
|
||||
g b: 1
|
||||
|
||||
test "#4834: dynamic import can technically be object spread", ->
|
||||
eqJS """
|
||||
x = {...import('module')}
|
||||
""",
|
||||
"""
|
||||
var x;
|
||||
|
||||
x = {...import('module')};
|
||||
"""
|
||||
|
||||
</script>
|
||||
<script type="text/x-coffeescript" class="test" id="objects">
|
||||
# Object Literals
|
||||
@@ -17138,7 +17223,7 @@ ctrlV = { ctrl: true, name: 'v'}
|
||||
|
||||
|
||||
testRepl 'reads history file', (input, output, repl) ->
|
||||
input.emitLine repl.rli.history[0]
|
||||
input.emitLine repl.history[0]
|
||||
eq '3', output.lastWrite()
|
||||
|
||||
testRepl "starts with coffee prompt", (input, output) ->
|
||||
|
||||
10
documentation/examples/dynamic_import.coffee
Normal file
10
documentation/examples/dynamic_import.coffee
Normal file
@@ -0,0 +1,10 @@
|
||||
# Your browser must support dynamic import to run this example.
|
||||
|
||||
do ->
|
||||
{ run } = await import('./browser-compiler-modern/coffeescript.js')
|
||||
run '''
|
||||
if 5 < new Date().getHours() < 9
|
||||
alert 'Time to make the coffee!'
|
||||
else
|
||||
alert 'Time to get some work done.'
|
||||
'''
|
||||
@@ -1,4 +1,4 @@
|
||||
import 'local-file.coffee'
|
||||
import './local-file.coffee'
|
||||
import 'coffeescript'
|
||||
|
||||
import _ from 'underscore'
|
||||
|
||||
8
documentation/sections/changelog/2.4.0.md
Normal file
8
documentation/sections/changelog/2.4.0.md
Normal file
@@ -0,0 +1,8 @@
|
||||
```
|
||||
releaseHeader('2019-03-29', '2.4.0', '2.3.2')
|
||||
```
|
||||
|
||||
* Dynamic `import()` expressions are now supported. The parentheses are always required, to distinguish from `import` statements. See [Modules](#dynamic-import). Note that as of this writing, the JavaScript feature itself is still Stage 3; if it changes before being fully standardized, it may change in CoffeeScript too. Using `import()` before its upstream [ECMAScript proposal](https://github.com/tc39/proposal-dynamic-import) is finalized should be considered provisional, subject to breaking changes if the proposal changes or is rejected. We have also revised our [policy](#contributing) on Stage 3 ECMAScript features, to support them when the features are [shipped](https://caniuse.com/#feat=es6-module-dynamic-import) in significant runtimes such as major browsers or Node.js.
|
||||
* There are now two browser versions of the CoffeeScript compiler: the traditional one that’s been published for years, and a new [ES module version](/browser-compiler-modern/coffeescript.js) that can be used via `import`. If your browser supports it, it is in effect on this page. A reference to the ES module browser compiler is in the `package.json` `"module"` field.
|
||||
* The Node API now exposes the previously private `registerCompiled` method, to allow plugins that use the `coffeescript` package to take advantage of CoffeeScript’s internal caching.
|
||||
* Bugfixes for commas in strings in block arrays, a reference to `@` not being maintained in a `do` block in a class, and function default parameters should no longer be wrapped by extraneous parentheses.
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Contributions are welcome! Feel free to fork [the repo](https://github.com/jashkenas/coffeescript) and submit a pull request.
|
||||
|
||||
[Some features of ECMAScript are intentionally unsupported](#unsupported). Please review both the open and closed [issues on GitHub](https://github.com/jashkenas/coffeescript/issues) to see if the feature you’re looking for has already been discussed. As a general rule, we don’t support ECMAScript syntax for features that aren’t yet finalized (at Stage 4 in the proposal approval process).
|
||||
[Some features of ECMAScript are intentionally unsupported](#unsupported). Please review both the open and closed [issues on GitHub](https://github.com/jashkenas/coffeescript/issues) to see if the feature you’re looking for has already been discussed. As a general rule, we don’t support ECMAScript syntax for features that aren’t yet finalized (at Stage 4 in the [proposal approval process](https://github.com/tc39/proposals)) or implemented in major browsers and/or Node (which can sometimes happen for features in Stage 3). Any Stage 3 features that CoffeeScript chooses to support should be considered experimental, subject to breaking changes or removal until the feature reaches Stage 4.
|
||||
|
||||
For more resources on adding to CoffeeScript, please see [the Wiki](https://github.com/jashkenas/coffeescript/wiki/%5BHowto%5D-Hacking-on-the-CoffeeScript-Compiler), especially [How The Parser Works](https://github.com/jashkenas/coffeescript/wiki/%5BHowTo%5D-How-parsing-works).
|
||||
|
||||
@@ -10,7 +10,7 @@ There are several things you can do to increase your odds of having your pull re
|
||||
|
||||
* Create tests! Any pull request should probably include basic tests to verify you didn’t break anything, or future changes won’t break your code.
|
||||
* Follow the style of the rest of the CoffeeScript codebase.
|
||||
* Ensure any ECMAScript syntax is mature (at Stage 4), with no further potential changes.
|
||||
* Ensure any ECMAScript syntax is mature (at Stage 4, or at Stage 3 with support in major browsers or runtimes).
|
||||
* Add only features that have broad utility, rather than a feature aimed at a specific use case or framework.
|
||||
|
||||
Of course, it’s entirely possible that you have a great addition, but it doesn’t fit within these constraints. Feel free to roll your own solution; you will have [plenty of company](https://github.com/jashkenas/coffeescript/wiki/In-The-Wild).
|
||||
|
||||
@@ -6,6 +6,14 @@ ES2015 modules are supported in CoffeeScript, with very similar `import` and `ex
|
||||
codeFor('modules')
|
||||
```
|
||||
|
||||
<div id="dynamic-import" class="bookmark"></div>
|
||||
|
||||
[Dynamic import](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#Dynamic_Imports) is also supported, with mandatory parentheses:
|
||||
|
||||
```
|
||||
codeFor('dynamic_import', true)
|
||||
```
|
||||
|
||||
<div id="modules-note" class="bookmark"></div>
|
||||
|
||||
Note that the CoffeeScript compiler **does not resolve modules**; writing an `import` or `export` statement in CoffeeScript will produce an `import` or `export` statement in the resulting output. It is your responsibility to [transpile](#transpilation) this ES2015 syntax into code that will work in your target runtimes.
|
||||
|
||||
@@ -207,6 +207,9 @@
|
||||
</section>
|
||||
<section id="changelog">
|
||||
<%= htmlFor('changelog') %>
|
||||
<section id="2.4.0">
|
||||
<%= htmlFor('changelog/2.4.0') %>
|
||||
</section>
|
||||
<section id="2.3.2">
|
||||
<%= htmlFor('changelog/2.3.2') %>
|
||||
</section>
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js" integrity="sha384-xBuQ/xzmlsLoJpyjoggmTEz8OWUFM0/RC5BsqQBDX2v5cMvDHcMakNTNrHIW2I5f" crossorigin="anonymous"></script>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js" integrity="sha384-tsQFqpEReu7ZLhBV2VZlAu7zcOV+rXbYlF2cqB8txI/8aZajjp4Bqd+V6D5IgvKT" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js" integrity="sha384-uefMccjFJAIv6A+rW+L4AHf99KvxDjWSu1z9VI8SKNVmz4sk7buKt/6v9KI65qnm" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/combine/npm/codemirror@5.37.0/lib/codemirror.js,npm/codemirror@5.37.0/mode/coffeescript/coffeescript.js,npm/codemirror@5.37.0/addon/lint/coffeescript-lint.js,npm/codemirror@5.37.0/mode/javascript/javascript.js"></script>
|
||||
|
||||
<script src="browser-compiler/coffeescript.js"></script>
|
||||
<script>
|
||||
<script nomodule src="./browser-compiler/coffeescript.js"></script>
|
||||
<script nomodule>
|
||||
<%= includeScript('docs.coffee') %>
|
||||
</script>
|
||||
<script type="module">
|
||||
import CoffeeScript from './browser-compiler-modern/coffeescript.js';
|
||||
<%= includeScript('docs.coffee') %>
|
||||
</script>
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-106156830-1"></script>
|
||||
|
||||
@@ -3,7 +3,12 @@
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
|
||||
<title>CoffeeScript Test Suite</title>
|
||||
<script src="browser-compiler/coffeescript.js"></script>
|
||||
<script nomodule src="browser-compiler/coffeescript.js"></script>
|
||||
<script type="module">
|
||||
import CoffeeScript from './browser-compiler-modern/coffeescript.js';
|
||||
window.CoffeeScript = CoffeeScript;
|
||||
window.addEventListener('DOMContentLoaded', CoffeeScript.runScripts, false);
|
||||
</script>
|
||||
<script src="https://cdn.jsdelivr.net/underscorejs/1.8.3/underscore-min.js"></script>
|
||||
<style>
|
||||
body, pre {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
// Generated by CoffeeScript 2.3.2
|
||||
// Generated by CoffeeScript 2.4.0
|
||||
(function() {
|
||||
// This **Browser** compatibility layer extends core CoffeeScript functions
|
||||
// to make things work smoothly when compiling code directly in the browser.
|
||||
// We add support for loading remote Coffee scripts via **XHR**, and
|
||||
// `text/coffeescript` script tags, source maps via data-URLs, and so on.
|
||||
var CoffeeScript, compile, runScripts,
|
||||
var CoffeeScript, compile,
|
||||
indexOf = [].indexOf;
|
||||
|
||||
CoffeeScript = require('./coffeescript');
|
||||
@@ -81,7 +81,7 @@
|
||||
// Activate CoffeeScript in the browser by having it compile and evaluate
|
||||
// all script tags with a content-type of `text/coffeescript`.
|
||||
// This happens on page load.
|
||||
runScripts = function() {
|
||||
CoffeeScript.runScripts = function() {
|
||||
var coffees, coffeetypes, execute, i, index, j, len, s, script, scripts;
|
||||
scripts = window.document.getElementsByTagName('script');
|
||||
coffeetypes = ['text/coffeescript', 'text/literate-coffeescript'];
|
||||
@@ -136,10 +136,16 @@
|
||||
};
|
||||
|
||||
// Listen for window load, both in decent browsers and in IE.
|
||||
if (window.addEventListener) {
|
||||
window.addEventListener('DOMContentLoaded', runScripts, false);
|
||||
} else {
|
||||
window.attachEvent('onload', runScripts);
|
||||
// Only attach this event handler on startup for the
|
||||
// non-ES module version of the browser compiler, to preserve
|
||||
// backward compatibility while letting the ES module version
|
||||
// be importable without side effects.
|
||||
if (this === window) {
|
||||
if (window.addEventListener) {
|
||||
window.addEventListener('DOMContentLoaded', CoffeeScript.runScripts, false);
|
||||
} else {
|
||||
window.attachEvent('onload', CoffeeScript.runScripts);
|
||||
}
|
||||
}
|
||||
|
||||
}).call(this);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.3.2
|
||||
// Generated by CoffeeScript 2.4.0
|
||||
(function() {
|
||||
// `cake` is a simplified version of [Make](http://www.gnu.org/software/make/)
|
||||
// ([Rake](http://rake.rubyforge.org/), [Jake](https://github.com/280north/jake))
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
// Generated by CoffeeScript 2.3.2
|
||||
// Generated by CoffeeScript 2.4.0
|
||||
(function() {
|
||||
// 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.
|
||||
var FILE_EXTENSIONS, Lexer, SourceMap, base64encode, checkShebangLine, compile, formatSourcePosition, getSourceMap, helpers, lexer, packageJson, parser, sourceMaps, sources, withPrettyErrors,
|
||||
var FILE_EXTENSIONS, Lexer, SourceMap, base64encode, checkShebangLine, compile, formatSourcePosition, getSourceMap, helpers, lexer, packageJson, parser, registerCompiled, sourceMaps, sources, withPrettyErrors,
|
||||
indexOf = [].indexOf;
|
||||
|
||||
({Lexer} = require('./lexer'));
|
||||
@@ -74,6 +74,24 @@
|
||||
// Also save source maps if generated, in form of `(source)`: [`(source map)`].
|
||||
sourceMaps = {};
|
||||
|
||||
// This is exported to enable an external module to implement caching of
|
||||
// compilation results. When the compiled js source is loaded from cache, the
|
||||
// original coffee code should be added with this method in order to enable the
|
||||
// Error.prepareStackTrace below to correctly adjust the stack trace for the
|
||||
// corresponding file (the source map will be generated on demand).
|
||||
exports.registerCompiled = registerCompiled = function(filename, source, sourcemap) {
|
||||
if (sources[filename] == null) {
|
||||
sources[filename] = [];
|
||||
}
|
||||
sources[filename].push(source);
|
||||
if (sourcemap != null) {
|
||||
if (sourceMaps[filename] == null) {
|
||||
sourceMaps[filename] = [];
|
||||
}
|
||||
return sourceMaps[filename].push(sourcemap);
|
||||
}
|
||||
};
|
||||
|
||||
// Compile CoffeeScript code to JavaScript, using the Coffee/Jison compiler.
|
||||
|
||||
// If `options.sourceMap` is specified, then `options.filename` must also be
|
||||
@@ -94,10 +112,6 @@
|
||||
generateSourceMap = options.sourceMap || options.inlineMap || (options.filename == null);
|
||||
filename = options.filename || '<anonymous>';
|
||||
checkShebangLine(filename, code);
|
||||
if (sources[filename] == null) {
|
||||
sources[filename] = [];
|
||||
}
|
||||
sources[filename].push(code);
|
||||
if (generateSourceMap) {
|
||||
map = new SourceMap;
|
||||
}
|
||||
@@ -162,10 +176,6 @@
|
||||
}
|
||||
if (generateSourceMap) {
|
||||
v3SourceMap = map.generate(options, code);
|
||||
if (sourceMaps[filename] == null) {
|
||||
sourceMaps[filename] = [];
|
||||
}
|
||||
sourceMaps[filename].push(map);
|
||||
}
|
||||
if (options.transpile) {
|
||||
if (typeof options.transpile !== 'object') {
|
||||
@@ -196,6 +206,7 @@
|
||||
sourceURL = `//# sourceURL=${(ref1 = options.filename) != null ? ref1 : 'coffeescript'}`;
|
||||
js = `${js}\n${sourceMapDataURI}\n${sourceURL}`;
|
||||
}
|
||||
registerCompiled(filename, code, map);
|
||||
if (options.sourceMap) {
|
||||
return {
|
||||
js,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.3.2
|
||||
// Generated by CoffeeScript 2.4.0
|
||||
(function() {
|
||||
// The `coffee` utility. Handles command-line compilation of CoffeeScript
|
||||
// into various forms: saved into `.js` files or printed to stdout
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.3.2
|
||||
// Generated by CoffeeScript 2.4.0
|
||||
(function() {
|
||||
// The CoffeeScript parser is generated by [Jison](https://github.com/zaach/jison)
|
||||
// from this grammar file. Jison is a bottom-up parser generator, similar in
|
||||
@@ -332,6 +332,11 @@
|
||||
false,
|
||||
$1);
|
||||
}),
|
||||
o('DYNAMIC_IMPORT Arguments',
|
||||
function() {
|
||||
return new DynamicImportCall(LOC(1)(new DynamicImport),
|
||||
$2);
|
||||
}),
|
||||
o('SimpleObjAssignable Arguments',
|
||||
function() {
|
||||
return new Call(new Value($1),
|
||||
@@ -941,6 +946,11 @@
|
||||
$3,
|
||||
$2,
|
||||
$1);
|
||||
}),
|
||||
o('DYNAMIC_IMPORT Arguments',
|
||||
function() {
|
||||
return new DynamicImportCall(LOC(1)(new DynamicImport),
|
||||
$2);
|
||||
})
|
||||
],
|
||||
// An optional existence check on a function.
|
||||
@@ -2113,7 +2123,7 @@
|
||||
// And not:
|
||||
|
||||
// (2 + 3) * 4
|
||||
operators = [['left', '.', '?.', '::', '?::'], ['left', 'CALL_START', 'CALL_END'], ['nonassoc', '++', '--'], ['left', '?'], ['right', 'UNARY'], ['right', 'AWAIT'], ['right', '**'], ['right', 'UNARY_MATH'], ['left', 'MATH'], ['left', '+', '-'], ['left', 'SHIFT'], ['left', 'RELATION'], ['left', 'COMPARE'], ['left', '&'], ['left', '^'], ['left', '|'], ['left', '&&'], ['left', '||'], ['left', 'BIN?'], ['nonassoc', 'INDENT', 'OUTDENT'], ['right', 'YIELD'], ['right', '=', ':', 'COMPOUND_ASSIGN', 'RETURN', 'THROW', 'EXTENDS'], ['right', 'FORIN', 'FOROF', 'FORFROM', 'BY', 'WHEN'], ['right', 'IF', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS', 'IMPORT', 'EXPORT'], ['left', 'POST_IF']];
|
||||
operators = [['left', '.', '?.', '::', '?::'], ['left', 'CALL_START', 'CALL_END'], ['nonassoc', '++', '--'], ['left', '?'], ['right', 'UNARY'], ['right', 'AWAIT'], ['right', '**'], ['right', 'UNARY_MATH'], ['left', 'MATH'], ['left', '+', '-'], ['left', 'SHIFT'], ['left', 'RELATION'], ['left', 'COMPARE'], ['left', '&'], ['left', '^'], ['left', '|'], ['left', '&&'], ['left', '||'], ['left', 'BIN?'], ['nonassoc', 'INDENT', 'OUTDENT'], ['right', 'YIELD'], ['right', '=', ':', 'COMPOUND_ASSIGN', 'RETURN', 'THROW', 'EXTENDS'], ['right', 'FORIN', 'FOROF', 'FORFROM', 'BY', 'WHEN'], ['right', 'IF', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS', 'IMPORT', 'EXPORT', 'DYNAMIC_IMPORT'], ['left', 'POST_IF']];
|
||||
|
||||
// Wrapping Up
|
||||
// -----------
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.3.2
|
||||
// Generated by CoffeeScript 2.4.0
|
||||
(function() {
|
||||
// This file contains the common helper functions that we'd like to share among
|
||||
// the **Lexer**, **Rewriter**, and the **Nodes**. Merge objects, flatten
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.3.2
|
||||
// Generated by CoffeeScript 2.4.0
|
||||
(function() {
|
||||
// Node.js Implementation
|
||||
var CoffeeScript, ext, fs, helpers, i, len, path, ref, universalCompile, vm,
|
||||
@@ -152,9 +152,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
CoffeeScript._compileFile = function(filename, options = {}) {
|
||||
var answer, err, raw, stripped;
|
||||
raw = fs.readFileSync(filename, 'utf8');
|
||||
CoffeeScript._compileRawFileContent = function(raw, filename, options = {}) {
|
||||
var answer, err, stripped;
|
||||
// Strip the Unicode byte order mark, if this file begins with one.
|
||||
stripped = raw.charCodeAt(0) === 0xFEFF ? raw.substring(1) : raw;
|
||||
options = Object.assign({}, options, {
|
||||
@@ -175,6 +174,12 @@
|
||||
return answer;
|
||||
};
|
||||
|
||||
CoffeeScript._compileFile = function(filename, options = {}) {
|
||||
var raw;
|
||||
raw = fs.readFileSync(filename, 'utf8');
|
||||
return CoffeeScript._compileRawFileContent(raw, filename, options);
|
||||
};
|
||||
|
||||
module.exports = CoffeeScript;
|
||||
|
||||
}).call(this);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.3.2
|
||||
// Generated by CoffeeScript 2.4.0
|
||||
(function() {
|
||||
// The CoffeeScript Lexer. Uses a series of token-matching regexes to attempt
|
||||
// matches against the beginning of the source code. When a match is found,
|
||||
@@ -889,6 +889,9 @@
|
||||
return value.length;
|
||||
}
|
||||
}
|
||||
if (value === '(' && (prev != null ? prev[0] : void 0) === 'IMPORT') {
|
||||
prev[0] = 'DYNAMIC_IMPORT';
|
||||
}
|
||||
if (value === '{' && this.seenImport) {
|
||||
this.importSpecifierList = true;
|
||||
} else if (this.importSpecifierList && value === '}') {
|
||||
@@ -1484,13 +1487,8 @@
|
||||
// “sometimes” keyword.
|
||||
isForFrom = function(prev) {
|
||||
var ref;
|
||||
// `for i from iterable`
|
||||
if (prev[0] === 'IDENTIFIER') {
|
||||
// `for i from from`, `for from from iterable`
|
||||
if (prev[1] === 'from') {
|
||||
prev[1][0] = 'IDENTIFIER';
|
||||
true;
|
||||
}
|
||||
// `for i from iterable`
|
||||
return true;
|
||||
// `for from…`
|
||||
} else if (prev[0] === 'FOR') {
|
||||
@@ -1685,7 +1683,7 @@
|
||||
// Tokens which could legitimately be invoked or indexed. An opening
|
||||
// parentheses or bracket following these tokens will be recorded as the start
|
||||
// of a function invocation or indexing operation.
|
||||
CALLABLE = ['IDENTIFIER', 'PROPERTY', ')', ']', '?', '@', 'THIS', 'SUPER'];
|
||||
CALLABLE = ['IDENTIFIER', 'PROPERTY', ')', ']', '?', '@', 'THIS', 'SUPER', 'DYNAMIC_IMPORT'];
|
||||
|
||||
INDEXABLE = CALLABLE.concat(['NUMBER', 'INFINITY', 'NAN', 'STRING', 'STRING_END', 'REGEX', 'REGEX_END', 'BOOL', 'NULL', 'UNDEFINED', '}', '::']);
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
// Generated by CoffeeScript 2.3.2
|
||||
// Generated by CoffeeScript 2.4.0
|
||||
(function() {
|
||||
// `nodes.coffee` contains all of the node classes for the syntax tree. Most
|
||||
// nodes are created as the result of actions in the [grammar](grammar.html),
|
||||
// but some are created by other nodes as a method of code generation. To convert
|
||||
// the syntax tree into a string of JavaScript code, call `compile()` on the root.
|
||||
var Access, Arr, Assign, AwaitReturn, Base, Block, BooleanLiteral, CSXTag, Call, Class, Code, CodeFragment, ComputedPropertyName, Elision, ExecutableClassBody, Existence, Expansion, ExportAllDeclaration, ExportDeclaration, ExportDefaultDeclaration, ExportNamedDeclaration, ExportSpecifier, ExportSpecifierList, Extends, For, FuncGlyph, HereComment, HoistTarget, IdentifierLiteral, If, ImportClause, ImportDeclaration, ImportDefaultSpecifier, ImportNamespaceSpecifier, ImportSpecifier, ImportSpecifierList, In, Index, InfinityLiteral, JS_FORBIDDEN, LEVEL_ACCESS, LEVEL_COND, LEVEL_LIST, LEVEL_OP, LEVEL_PAREN, LEVEL_TOP, LineComment, Literal, ModuleDeclaration, ModuleSpecifier, ModuleSpecifierList, NEGATE, NO, NaNLiteral, NullLiteral, NumberLiteral, Obj, Op, Param, Parens, PassthroughLiteral, PropertyName, Range, RegexLiteral, RegexWithInterpolations, Return, SIMPLENUM, Scope, Slice, Splat, StatementLiteral, StringLiteral, StringWithInterpolations, Super, SuperCall, Switch, TAB, THIS, TaggedTemplateCall, ThisLiteral, Throw, Try, UTILITIES, UndefinedLiteral, Value, While, YES, YieldReturn, addDataToNode, attachCommentsToNode, compact, del, ends, extend, flatten, fragmentsToText, hasLineComments, indentInitial, isLiteralArguments, isLiteralThis, isUnassignable, locationDataToString, merge, moveComments, multident, shouldCacheOrIsAssignable, some, starts, throwSyntaxError, unfoldSoak, unshiftAfterComments, utility,
|
||||
var Access, Arr, Assign, AwaitReturn, Base, Block, BooleanLiteral, CSXTag, Call, Class, Code, CodeFragment, ComputedPropertyName, DynamicImport, DynamicImportCall, Elision, ExecutableClassBody, Existence, Expansion, ExportAllDeclaration, ExportDeclaration, ExportDefaultDeclaration, ExportNamedDeclaration, ExportSpecifier, ExportSpecifierList, Extends, For, FuncGlyph, HereComment, HoistTarget, IdentifierLiteral, If, ImportClause, ImportDeclaration, ImportDefaultSpecifier, ImportNamespaceSpecifier, ImportSpecifier, ImportSpecifierList, In, Index, InfinityLiteral, JS_FORBIDDEN, LEVEL_ACCESS, LEVEL_COND, LEVEL_LIST, LEVEL_OP, LEVEL_PAREN, LEVEL_TOP, LineComment, Literal, ModuleDeclaration, ModuleSpecifier, ModuleSpecifierList, NEGATE, NO, NaNLiteral, NullLiteral, NumberLiteral, Obj, Op, Param, Parens, PassthroughLiteral, PropertyName, Range, RegexLiteral, RegexWithInterpolations, Return, SIMPLENUM, Scope, Slice, Splat, StatementLiteral, StringLiteral, StringWithInterpolations, Super, SuperCall, Switch, TAB, THIS, TaggedTemplateCall, ThisLiteral, Throw, Try, UTILITIES, UndefinedLiteral, Value, While, YES, YieldReturn, addDataToNode, attachCommentsToNode, compact, del, ends, extend, flatten, fragmentsToText, hasLineComments, indentInitial, isLiteralArguments, isLiteralThis, isUnassignable, locationDataToString, merge, moveComments, multident, shouldCacheOrIsAssignable, some, starts, throwSyntaxError, unfoldSoak, unshiftAfterComments, utility,
|
||||
indexOf = [].indexOf,
|
||||
splice = [].splice,
|
||||
slice1 = [].slice;
|
||||
@@ -282,7 +282,7 @@
|
||||
|
||||
// Occasionally it may be useful to make an expression behave as if it was 'hoisted', whereby the
|
||||
// result of the expression is available before its location in the source, but the expression's
|
||||
// variable scope corresponds the source position. This is used extensively to deal with executable
|
||||
// variable scope corresponds to the source position. This is used extensively to deal with executable
|
||||
// class bodies in classes.
|
||||
|
||||
// Calling this method mutates the node, proxying the `compileNode` and `compileToFragments`
|
||||
@@ -2469,10 +2469,10 @@
|
||||
return [this.makeCode('[]')];
|
||||
}
|
||||
o.indent += TAB;
|
||||
fragmentIsElision = function(fragment) {
|
||||
return fragmentsToText(fragment).trim() === ',';
|
||||
fragmentIsElision = function([fragment]) {
|
||||
return fragment.type === 'Elision' && fragment.code.trim() === ',';
|
||||
};
|
||||
// Detect if `Elisions` at the beginning of the array are processed (e.g. [, , , a]).
|
||||
// Detect if `Elision`s at the beginning of the array are processed (e.g. [, , , a]).
|
||||
passedElision = false;
|
||||
answer = [];
|
||||
ref1 = this.objects;
|
||||
@@ -2536,7 +2536,7 @@
|
||||
fragment = answer[fragmentIndex];
|
||||
if (fragment.isHereComment) {
|
||||
fragment.code = `${multident(fragment.code, o.indent, false)}\n${o.indent}`;
|
||||
} else if (fragment.code === ', ' && !(fragment != null ? fragment.isElision : void 0)) {
|
||||
} else if (fragment.code === ', ' && !(fragment != null ? fragment.isElision : void 0) && fragment.type !== 'StringLiteral') {
|
||||
fragment.code = `,\n${o.indent}`;
|
||||
}
|
||||
}
|
||||
@@ -2968,7 +2968,7 @@
|
||||
return this.body.traverseChildren(false, (node) => {
|
||||
if (node instanceof ThisLiteral) {
|
||||
return node.value = this.name;
|
||||
} else if (node instanceof Code && node.bound && node.isStatic) {
|
||||
} else if (node instanceof Code && node.bound && (node.isStatic || !node.name)) {
|
||||
return node.context = this.name;
|
||||
}
|
||||
});
|
||||
@@ -3262,6 +3262,23 @@
|
||||
|
||||
};
|
||||
|
||||
exports.DynamicImport = DynamicImport = class DynamicImport extends Base {
|
||||
compileNode() {
|
||||
return [this.makeCode('import')];
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
exports.DynamicImportCall = DynamicImportCall = class DynamicImportCall extends Call {
|
||||
compileNode(o) {
|
||||
if (this.args.length !== 1) {
|
||||
this.error('import() requires exactly one argument');
|
||||
}
|
||||
return super.compileNode(o);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//### Assign
|
||||
|
||||
// The **Assign** is used to assign a local variable to value, or to set the
|
||||
@@ -4058,7 +4075,7 @@
|
||||
// (e.g. `ref`), shift those into the parent scope since we can’t put a
|
||||
// `var` line inside a function parameter list.
|
||||
scopeVariablesCount = o.scope.variables.length;
|
||||
signature.push(...param.compileToFragments(o));
|
||||
signature.push(...param.compileToFragments(o, LEVEL_PAREN));
|
||||
if (scopeVariablesCount !== o.scope.variables.length) {
|
||||
generatedVariables = o.scope.variables.splice(scopeVariablesCount);
|
||||
o.scope.parent.variables.push(...generatedVariables);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.3.2
|
||||
// Generated by CoffeeScript 2.4.0
|
||||
(function() {
|
||||
var LONG_FLAG, MULTI_FLAG, OPTIONAL, OptionParser, SHORT_FLAG, buildRule, buildRules, normalizeArguments, repeat,
|
||||
splice = [].splice;
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.3.2
|
||||
// Generated by CoffeeScript 2.4.0
|
||||
(function() {
|
||||
var CoffeeScript, Module, binary, child_process, ext, findExtension, fork, getRootModule, helpers, i, len, loadFile, path, ref;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.3.2
|
||||
// Generated by CoffeeScript 2.4.0
|
||||
(function() {
|
||||
var CoffeeScript, addHistory, addMultilineHandler, fs, getCommandId, merge, nodeREPL, path, replDefaults, runInContext, sawSIGINT, transpile, updateSyntaxError, vm;
|
||||
|
||||
@@ -113,8 +113,8 @@
|
||||
};
|
||||
|
||||
addMultilineHandler = function(repl) {
|
||||
var inputStream, multiline, nodeLineListener, origPrompt, outputStream, ref, rli;
|
||||
({rli, inputStream, outputStream} = repl);
|
||||
var inputStream, multiline, nodeLineListener, origPrompt, outputStream, ref;
|
||||
({inputStream, outputStream} = repl);
|
||||
// Node 0.11.12 changed API, prompt is now _prompt.
|
||||
origPrompt = (ref = repl._prompt) != null ? ref : repl.prompt;
|
||||
multiline = {
|
||||
@@ -128,15 +128,15 @@
|
||||
buffer: ''
|
||||
};
|
||||
// Proxy node's line listener
|
||||
nodeLineListener = rli.listeners('line')[0];
|
||||
rli.removeListener('line', nodeLineListener);
|
||||
rli.on('line', function(cmd) {
|
||||
nodeLineListener = repl.listeners('line')[0];
|
||||
repl.removeListener('line', nodeLineListener);
|
||||
repl.on('line', function(cmd) {
|
||||
if (multiline.enabled) {
|
||||
multiline.buffer += `${cmd}\n`;
|
||||
rli.setPrompt(multiline.prompt);
|
||||
rli.prompt(true);
|
||||
repl.setPrompt(multiline.prompt);
|
||||
repl.prompt(true);
|
||||
} else {
|
||||
rli.setPrompt(origPrompt);
|
||||
repl.setPrompt(origPrompt);
|
||||
nodeLineListener(cmd);
|
||||
}
|
||||
});
|
||||
@@ -149,28 +149,28 @@
|
||||
// allow arbitrarily switching between modes any time before multiple lines are entered
|
||||
if (!multiline.buffer.match(/\n/)) {
|
||||
multiline.enabled = !multiline.enabled;
|
||||
rli.setPrompt(origPrompt);
|
||||
rli.prompt(true);
|
||||
repl.setPrompt(origPrompt);
|
||||
repl.prompt(true);
|
||||
return;
|
||||
}
|
||||
// no-op unless the current line is empty
|
||||
if ((rli.line != null) && !rli.line.match(/^\s*$/)) {
|
||||
if ((repl.line != null) && !repl.line.match(/^\s*$/)) {
|
||||
return;
|
||||
}
|
||||
// eval, print, loop
|
||||
multiline.enabled = !multiline.enabled;
|
||||
rli.line = '';
|
||||
rli.cursor = 0;
|
||||
rli.output.cursorTo(0);
|
||||
rli.output.clearLine(1);
|
||||
repl.line = '';
|
||||
repl.cursor = 0;
|
||||
repl.output.cursorTo(0);
|
||||
repl.output.clearLine(1);
|
||||
// XXX: multiline hack
|
||||
multiline.buffer = multiline.buffer.replace(/\n/g, '\uFF00');
|
||||
rli.emit('line', multiline.buffer);
|
||||
repl.emit('line', multiline.buffer);
|
||||
multiline.buffer = '';
|
||||
} else {
|
||||
multiline.enabled = !multiline.enabled;
|
||||
rli.setPrompt(multiline.initialPrompt);
|
||||
rli.prompt(true);
|
||||
repl.setPrompt(multiline.initialPrompt);
|
||||
repl.prompt(true);
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -189,20 +189,20 @@
|
||||
fs.readSync(readFd, buffer, 0, size, stat.size - size);
|
||||
fs.closeSync(readFd);
|
||||
// Set the history on the interpreter
|
||||
repl.rli.history = buffer.toString().split('\n').reverse();
|
||||
repl.history = buffer.toString().split('\n').reverse();
|
||||
if (stat.size > maxSize) {
|
||||
// If the history file was truncated we should pop off a potential partial line
|
||||
repl.rli.history.pop();
|
||||
repl.history.pop();
|
||||
}
|
||||
if (repl.rli.history[0] === '') {
|
||||
if (repl.history[0] === '') {
|
||||
// Shift off the final blank newline
|
||||
repl.rli.history.shift();
|
||||
repl.history.shift();
|
||||
}
|
||||
repl.rli.historyIndex = -1;
|
||||
lastLine = repl.rli.history[0];
|
||||
repl.historyIndex = -1;
|
||||
lastLine = repl.history[0];
|
||||
} catch (error) {}
|
||||
fd = fs.openSync(filename, 'a');
|
||||
repl.rli.addListener('line', function(code) {
|
||||
repl.addListener('line', function(code) {
|
||||
if (code && code.length && code !== '.history' && code !== '.exit' && lastLine !== code) {
|
||||
// Save the latest command in the file
|
||||
fs.writeSync(fd, `${code}\n`);
|
||||
@@ -220,7 +220,7 @@
|
||||
return repl.commands[getCommandId(repl, 'history')] = {
|
||||
help: 'Show command history',
|
||||
action: function() {
|
||||
repl.outputStream.write(`${repl.rli.history.slice(0).reverse().join('\n')}\n`);
|
||||
repl.outputStream.write(`${repl.history.slice(0).reverse().join('\n')}\n`);
|
||||
return repl.displayPrompt();
|
||||
}
|
||||
};
|
||||
@@ -283,7 +283,7 @@
|
||||
runInContext(opts.prelude, repl.context, 'prelude');
|
||||
}
|
||||
repl.on('exit', function() {
|
||||
if (!repl.rli.closed) {
|
||||
if (!repl.closed) {
|
||||
return repl.outputStream.write('\n');
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.3.2
|
||||
// Generated by CoffeeScript 2.4.0
|
||||
(function() {
|
||||
// The CoffeeScript language has a good deal of optional syntax, implicit syntax,
|
||||
// and shorthand syntax. This can greatly complicate a grammar and bloat
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.3.2
|
||||
// Generated by CoffeeScript 2.4.0
|
||||
(function() {
|
||||
// The **Scope** class regulates lexical scoping within CoffeeScript. As you
|
||||
// generate code, you create a tree of scopes in the same shape as the nested
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.3.2
|
||||
// Generated by CoffeeScript 2.4.0
|
||||
(function() {
|
||||
// Source maps allow JavaScript runtimes to match running JavaScript back to
|
||||
// the original source code that corresponds to it. This can be minified
|
||||
|
||||
2213
package-lock.json
generated
2213
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
17
package.json
17
package.json
@@ -8,7 +8,7 @@
|
||||
"compiler"
|
||||
],
|
||||
"author": "Jeremy Ashkenas",
|
||||
"version": "2.3.2",
|
||||
"version": "2.4.0",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
@@ -17,6 +17,7 @@
|
||||
"lib": "./lib/coffeescript"
|
||||
},
|
||||
"main": "./lib/coffeescript/index",
|
||||
"module": "./docs/v2/browser-compiler-modern/coffeescript.js",
|
||||
"browser": "./lib/coffeescript/browser",
|
||||
"bin": {
|
||||
"coffee": "./bin/coffee",
|
||||
@@ -39,16 +40,16 @@
|
||||
"url": "git://github.com/jashkenas/coffeescript.git"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.0.0",
|
||||
"@babel/preset-env": "^7.0.0",
|
||||
"babel-preset-minify": "^0.4.3",
|
||||
"codemirror": "^5.39.2",
|
||||
"@babel/core": "^7.4.0",
|
||||
"@babel/preset-env": "^7.4.2",
|
||||
"babel-preset-minify": "^0.5.0",
|
||||
"codemirror": "^5.45.0",
|
||||
"docco": "~0.8.0",
|
||||
"highlight.js": "~9.12.0",
|
||||
"jison": ">=0.4.18",
|
||||
"highlight.js": "~9.15.6",
|
||||
"jison": "^0.4.18",
|
||||
"markdown-it": "~8.4.2",
|
||||
"underscore": "~1.9.1",
|
||||
"webpack": "~4.17.2"
|
||||
"webpack": "~4.29.6"
|
||||
},
|
||||
"dependencies": {}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ CoffeeScript.load = (url, callback, options = {}, hold = false) ->
|
||||
# Activate CoffeeScript in the browser by having it compile and evaluate
|
||||
# all script tags with a content-type of `text/coffeescript`.
|
||||
# This happens on page load.
|
||||
runScripts = ->
|
||||
CoffeeScript.runScripts = ->
|
||||
scripts = window.document.getElementsByTagName 'script'
|
||||
coffeetypes = ['text/coffeescript', 'text/literate-coffeescript']
|
||||
coffees = (s for s in scripts when s.type in coffeetypes)
|
||||
@@ -96,7 +96,12 @@ runScripts = ->
|
||||
execute()
|
||||
|
||||
# Listen for window load, both in decent browsers and in IE.
|
||||
if window.addEventListener
|
||||
window.addEventListener 'DOMContentLoaded', runScripts, no
|
||||
else
|
||||
window.attachEvent 'onload', runScripts
|
||||
# Only attach this event handler on startup for the
|
||||
# non-ES module version of the browser compiler, to preserve
|
||||
# backward compatibility while letting the ES module version
|
||||
# be importable without side effects.
|
||||
if this is window
|
||||
if window.addEventListener
|
||||
window.addEventListener 'DOMContentLoaded', CoffeeScript.runScripts, no
|
||||
else
|
||||
window.attachEvent 'onload', CoffeeScript.runScripts
|
||||
|
||||
@@ -54,6 +54,20 @@ sources = {}
|
||||
# Also save source maps if generated, in form of `(source)`: [`(source map)`].
|
||||
sourceMaps = {}
|
||||
|
||||
# This is exported to enable an external module to implement caching of
|
||||
# compilation results. When the compiled js source is loaded from cache, the
|
||||
# original coffee code should be added with this method in order to enable the
|
||||
# Error.prepareStackTrace below to correctly adjust the stack trace for the
|
||||
# corresponding file (the source map will be generated on demand).
|
||||
exports.registerCompiled = registerCompiled = (filename, source, sourcemap) ->
|
||||
|
||||
sources[filename] ?= []
|
||||
sources[filename].push source
|
||||
|
||||
if sourcemap?
|
||||
sourceMaps[filename] ?= []
|
||||
sourceMaps[filename].push sourcemap
|
||||
|
||||
# Compile CoffeeScript code to JavaScript, using the Coffee/Jison compiler.
|
||||
#
|
||||
# If `options.sourceMap` is specified, then `options.filename` must also be
|
||||
@@ -75,8 +89,6 @@ exports.compile = compile = withPrettyErrors (code, options = {}) ->
|
||||
|
||||
checkShebangLine filename, code
|
||||
|
||||
sources[filename] ?= []
|
||||
sources[filename].push code
|
||||
map = new SourceMap if generateSourceMap
|
||||
|
||||
tokens = lexer.tokenize code, options
|
||||
@@ -126,8 +138,6 @@ exports.compile = compile = withPrettyErrors (code, options = {}) ->
|
||||
|
||||
if generateSourceMap
|
||||
v3SourceMap = map.generate options, code
|
||||
sourceMaps[filename] ?= []
|
||||
sourceMaps[filename].push map
|
||||
|
||||
if options.transpile
|
||||
if typeof options.transpile isnt 'object'
|
||||
@@ -158,6 +168,8 @@ exports.compile = compile = withPrettyErrors (code, options = {}) ->
|
||||
sourceURL = "//# sourceURL=#{options.filename ? 'coffeescript'}"
|
||||
js = "#{js}\n#{sourceMapDataURI}\n#{sourceURL}"
|
||||
|
||||
registerCompiled filename, code, map
|
||||
|
||||
if options.sourceMap
|
||||
{
|
||||
js
|
||||
|
||||
@@ -240,6 +240,7 @@ grammar =
|
||||
o 'Super'
|
||||
o 'This'
|
||||
o 'SUPER Arguments', -> new SuperCall LOC(1)(new Super), $2, no, $1
|
||||
o 'DYNAMIC_IMPORT Arguments', -> new DynamicImportCall LOC(1)(new DynamicImport), $2
|
||||
o 'SimpleObjAssignable Arguments', -> new Call (new Value $1), $2
|
||||
o 'ObjSpreadExpr Arguments', -> new Call $1, $2
|
||||
]
|
||||
@@ -485,6 +486,7 @@ grammar =
|
||||
o 'Value OptFuncExist String', -> new TaggedTemplateCall $1, $3, $2
|
||||
o 'Value OptFuncExist Arguments', -> new Call $1, $3, $2
|
||||
o 'SUPER OptFuncExist Arguments', -> new SuperCall LOC(1)(new Super), $3, $2, $1
|
||||
o 'DYNAMIC_IMPORT Arguments', -> new DynamicImportCall LOC(1)(new DynamicImport), $2
|
||||
]
|
||||
|
||||
# An optional existence check on a function.
|
||||
@@ -891,7 +893,7 @@ operators = [
|
||||
['right', 'YIELD']
|
||||
['right', '=', ':', 'COMPOUND_ASSIGN', 'RETURN', 'THROW', 'EXTENDS']
|
||||
['right', 'FORIN', 'FOROF', 'FORFROM', 'BY', 'WHEN']
|
||||
['right', 'IF', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS', 'IMPORT', 'EXPORT']
|
||||
['right', 'IF', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS', 'IMPORT', 'EXPORT', 'DYNAMIC_IMPORT']
|
||||
['left', 'POST_IF']
|
||||
]
|
||||
|
||||
|
||||
@@ -110,8 +110,8 @@ if require.extensions
|
||||
Use CoffeeScript.register() or require the coffeescript/register module to require #{ext} files.
|
||||
"""
|
||||
|
||||
CoffeeScript._compileFile = (filename, options = {}) ->
|
||||
raw = fs.readFileSync filename, 'utf8'
|
||||
CoffeeScript._compileRawFileContent = (raw, filename, options = {}) ->
|
||||
|
||||
# Strip the Unicode byte order mark, if this file begins with one.
|
||||
stripped = if raw.charCodeAt(0) is 0xFEFF then raw.substring 1 else raw
|
||||
|
||||
@@ -131,4 +131,9 @@ CoffeeScript._compileFile = (filename, options = {}) ->
|
||||
|
||||
answer
|
||||
|
||||
CoffeeScript._compileFile = (filename, options = {}) ->
|
||||
raw = fs.readFileSync filename, 'utf8'
|
||||
|
||||
CoffeeScript._compileRawFileContent raw, filename, options
|
||||
|
||||
module.exports = CoffeeScript
|
||||
|
||||
@@ -667,6 +667,9 @@ exports.Lexer = class Lexer
|
||||
@error message, origin[2] if message
|
||||
return value.length if skipToken
|
||||
|
||||
if value is '(' and prev?[0] is 'IMPORT'
|
||||
prev[0] = 'DYNAMIC_IMPORT'
|
||||
|
||||
if value is '{' and @seenImport
|
||||
@importSpecifierList = yes
|
||||
else if @importSpecifierList and value is '}'
|
||||
@@ -1109,12 +1112,8 @@ exports.isUnassignable = isUnassignable
|
||||
# loop. Try to detect when `from` is a variable identifier and when it is this
|
||||
# “sometimes” keyword.
|
||||
isForFrom = (prev) ->
|
||||
# `for i from iterable`
|
||||
if prev[0] is 'IDENTIFIER'
|
||||
# `for i from from`, `for from from iterable`
|
||||
if prev[1] is 'from'
|
||||
prev[1][0] = 'IDENTIFIER'
|
||||
yes
|
||||
# `for i from iterable`
|
||||
yes
|
||||
# `for from…`
|
||||
else if prev[0] is 'FOR'
|
||||
@@ -1356,7 +1355,7 @@ BOOL = ['TRUE', 'FALSE']
|
||||
# Tokens which could legitimately be invoked or indexed. An opening
|
||||
# parentheses or bracket following these tokens will be recorded as the start
|
||||
# of a function invocation or indexing operation.
|
||||
CALLABLE = ['IDENTIFIER', 'PROPERTY', ')', ']', '?', '@', 'THIS', 'SUPER']
|
||||
CALLABLE = ['IDENTIFIER', 'PROPERTY', ')', ']', '?', '@', 'THIS', 'SUPER', 'DYNAMIC_IMPORT']
|
||||
INDEXABLE = CALLABLE.concat [
|
||||
'NUMBER', 'INFINITY', 'NAN', 'STRING', 'STRING_END', 'REGEX', 'REGEX_END'
|
||||
'BOOL', 'NULL', 'UNDEFINED', '}', '::'
|
||||
|
||||
@@ -207,7 +207,7 @@ exports.Base = class Base
|
||||
|
||||
# Occasionally it may be useful to make an expression behave as if it was 'hoisted', whereby the
|
||||
# result of the expression is available before its location in the source, but the expression's
|
||||
# variable scope corresponds the source position. This is used extensively to deal with executable
|
||||
# variable scope corresponds to the source position. This is used extensively to deal with executable
|
||||
# class bodies in classes.
|
||||
#
|
||||
# Calling this method mutates the node, proxying the `compileNode` and `compileToFragments`
|
||||
@@ -1644,8 +1644,9 @@ exports.Arr = class Arr extends Base
|
||||
compileNode: (o) ->
|
||||
return [@makeCode '[]'] unless @objects.length
|
||||
o.indent += TAB
|
||||
fragmentIsElision = (fragment) -> fragmentsToText(fragment).trim() is ','
|
||||
# Detect if `Elisions` at the beginning of the array are processed (e.g. [, , , a]).
|
||||
fragmentIsElision = ([ fragment ]) ->
|
||||
fragment.type is 'Elision' and fragment.code.trim() is ','
|
||||
# Detect if `Elision`s at the beginning of the array are processed (e.g. [, , , a]).
|
||||
passedElision = no
|
||||
|
||||
answer = []
|
||||
@@ -1687,7 +1688,7 @@ exports.Arr = class Arr extends Base
|
||||
for fragment, fragmentIndex in answer
|
||||
if fragment.isHereComment
|
||||
fragment.code = "#{multident(fragment.code, o.indent, no)}\n#{o.indent}"
|
||||
else if fragment.code is ', ' and not fragment?.isElision
|
||||
else if fragment.code is ', ' and not fragment?.isElision and fragment.type isnt 'StringLiteral'
|
||||
fragment.code = ",\n#{o.indent}"
|
||||
answer.unshift @makeCode "[\n#{o.indent}"
|
||||
answer.push @makeCode "\n#{@tab}]"
|
||||
@@ -1988,7 +1989,7 @@ exports.ExecutableClassBody = class ExecutableClassBody extends Base
|
||||
@body.traverseChildren false, (node) =>
|
||||
if node instanceof ThisLiteral
|
||||
node.value = @name
|
||||
else if node instanceof Code and node.bound and node.isStatic
|
||||
else if node instanceof Code and node.bound and (node.isStatic or not node.name)
|
||||
node.context = @name
|
||||
|
||||
# Make class/prototype assignments for invalid ES properties
|
||||
@@ -2171,6 +2172,16 @@ exports.ExportSpecifier = class ExportSpecifier extends ModuleSpecifier
|
||||
constructor: (local, exported) ->
|
||||
super local, exported, 'export'
|
||||
|
||||
exports.DynamicImport = class DynamicImport extends Base
|
||||
compileNode: ->
|
||||
[@makeCode 'import']
|
||||
|
||||
exports.DynamicImportCall = class DynamicImportCall extends Call
|
||||
compileNode: (o) ->
|
||||
unless @args.length is 1
|
||||
@error 'import() requires exactly one argument'
|
||||
super o
|
||||
|
||||
#### Assign
|
||||
|
||||
# The **Assign** is used to assign a local variable to value, or to set the
|
||||
@@ -2743,7 +2754,7 @@ exports.Code = class Code extends Base
|
||||
# (e.g. `ref`), shift those into the parent scope since we can’t put a
|
||||
# `var` line inside a function parameter list.
|
||||
scopeVariablesCount = o.scope.variables.length
|
||||
signature.push param.compileToFragments(o)...
|
||||
signature.push param.compileToFragments(o, LEVEL_PAREN)...
|
||||
if scopeVariablesCount isnt o.scope.variables.length
|
||||
generatedVariables = o.scope.variables.splice scopeVariablesCount
|
||||
o.scope.parent.variables.push generatedVariables...
|
||||
|
||||
@@ -75,7 +75,7 @@ runInContext = (js, context, filename) ->
|
||||
vm.runInContext js, context, filename
|
||||
|
||||
addMultilineHandler = (repl) ->
|
||||
{rli, inputStream, outputStream} = repl
|
||||
{inputStream, outputStream} = repl
|
||||
# Node 0.11.12 changed API, prompt is now _prompt.
|
||||
origPrompt = repl._prompt ? repl.prompt
|
||||
|
||||
@@ -86,15 +86,15 @@ addMultilineHandler = (repl) ->
|
||||
buffer: ''
|
||||
|
||||
# Proxy node's line listener
|
||||
nodeLineListener = rli.listeners('line')[0]
|
||||
rli.removeListener 'line', nodeLineListener
|
||||
rli.on 'line', (cmd) ->
|
||||
nodeLineListener = repl.listeners('line')[0]
|
||||
repl.removeListener 'line', nodeLineListener
|
||||
repl.on 'line', (cmd) ->
|
||||
if multiline.enabled
|
||||
multiline.buffer += "#{cmd}\n"
|
||||
rli.setPrompt multiline.prompt
|
||||
rli.prompt true
|
||||
repl.setPrompt multiline.prompt
|
||||
repl.prompt true
|
||||
else
|
||||
rli.setPrompt origPrompt
|
||||
repl.setPrompt origPrompt
|
||||
nodeLineListener cmd
|
||||
return
|
||||
|
||||
@@ -105,25 +105,25 @@ addMultilineHandler = (repl) ->
|
||||
# allow arbitrarily switching between modes any time before multiple lines are entered
|
||||
unless multiline.buffer.match /\n/
|
||||
multiline.enabled = not multiline.enabled
|
||||
rli.setPrompt origPrompt
|
||||
rli.prompt true
|
||||
repl.setPrompt origPrompt
|
||||
repl.prompt true
|
||||
return
|
||||
# no-op unless the current line is empty
|
||||
return if rli.line? and not rli.line.match /^\s*$/
|
||||
return if repl.line? and not repl.line.match /^\s*$/
|
||||
# eval, print, loop
|
||||
multiline.enabled = not multiline.enabled
|
||||
rli.line = ''
|
||||
rli.cursor = 0
|
||||
rli.output.cursorTo 0
|
||||
rli.output.clearLine 1
|
||||
repl.line = ''
|
||||
repl.cursor = 0
|
||||
repl.output.cursorTo 0
|
||||
repl.output.clearLine 1
|
||||
# XXX: multiline hack
|
||||
multiline.buffer = multiline.buffer.replace /\n/g, '\uFF00'
|
||||
rli.emit 'line', multiline.buffer
|
||||
repl.emit 'line', multiline.buffer
|
||||
multiline.buffer = ''
|
||||
else
|
||||
multiline.enabled = not multiline.enabled
|
||||
rli.setPrompt multiline.initialPrompt
|
||||
rli.prompt true
|
||||
repl.setPrompt multiline.initialPrompt
|
||||
repl.prompt true
|
||||
return
|
||||
|
||||
# Store and load command history from a file
|
||||
@@ -139,17 +139,17 @@ addHistory = (repl, filename, maxSize) ->
|
||||
fs.readSync readFd, buffer, 0, size, stat.size - size
|
||||
fs.closeSync readFd
|
||||
# Set the history on the interpreter
|
||||
repl.rli.history = buffer.toString().split('\n').reverse()
|
||||
repl.history = buffer.toString().split('\n').reverse()
|
||||
# If the history file was truncated we should pop off a potential partial line
|
||||
repl.rli.history.pop() if stat.size > maxSize
|
||||
repl.history.pop() if stat.size > maxSize
|
||||
# Shift off the final blank newline
|
||||
repl.rli.history.shift() if repl.rli.history[0] is ''
|
||||
repl.rli.historyIndex = -1
|
||||
lastLine = repl.rli.history[0]
|
||||
repl.history.shift() if repl.history[0] is ''
|
||||
repl.historyIndex = -1
|
||||
lastLine = repl.history[0]
|
||||
|
||||
fd = fs.openSync filename, 'a'
|
||||
|
||||
repl.rli.addListener 'line', (code) ->
|
||||
repl.addListener 'line', (code) ->
|
||||
if code and code.length and code isnt '.history' and code isnt '.exit' and lastLine isnt code
|
||||
# Save the latest command in the file
|
||||
fs.writeSync fd, "#{code}\n"
|
||||
@@ -163,7 +163,7 @@ addHistory = (repl, filename, maxSize) ->
|
||||
repl.commands[getCommandId(repl, 'history')] =
|
||||
help: 'Show command history'
|
||||
action: ->
|
||||
repl.outputStream.write "#{repl.rli.history[..].reverse().join '\n'}\n"
|
||||
repl.outputStream.write "#{repl.history[..].reverse().join '\n'}\n"
|
||||
repl.displayPrompt()
|
||||
|
||||
getCommandId = (repl, commandName) ->
|
||||
@@ -212,7 +212,7 @@ module.exports =
|
||||
opts = merge replDefaults, opts
|
||||
repl = nodeREPL.start opts
|
||||
runInContext opts.prelude, repl.context, 'prelude' if opts.prelude
|
||||
repl.on 'exit', -> repl.outputStream.write '\n' if not repl.rli.closed
|
||||
repl.on 'exit', -> repl.outputStream.write '\n' if not repl.closed
|
||||
addMultilineHandler repl
|
||||
addHistory repl, opts.historyFile, opts.historyMaxInputSize if opts.historyFile
|
||||
# Adapt help inherited from the node REPL
|
||||
|
||||
@@ -115,6 +115,12 @@ test "array elisions nested destructuring", ->
|
||||
deepEqual d, {x:2}
|
||||
arrayEq w, [1,2,4]
|
||||
|
||||
test "#5112: array elisions not detected inside strings", ->
|
||||
arr = [
|
||||
str: ", #{3}"
|
||||
]
|
||||
eq arr[0].str, ', 3'
|
||||
|
||||
# Splats in Array Literals
|
||||
|
||||
test "array splat expansions with assignments", ->
|
||||
|
||||
@@ -1922,3 +1922,16 @@ test "#4609: Support new.target", ->
|
||||
|
||||
new Foo()
|
||||
eq newTarget, yes
|
||||
|
||||
test "#5085: Bug: @ reference to class not maintained in do block", ->
|
||||
thisFoo = 'initial foo'
|
||||
thisBar = 'initial bar'
|
||||
fn = (o) -> o.bar()
|
||||
|
||||
class A
|
||||
@foo = 'foo assigned in class'
|
||||
do => thisFoo = @foo
|
||||
fn bar: => thisBar = @foo
|
||||
|
||||
eq thisFoo, 'foo assigned in class'
|
||||
eq thisBar, 'foo assigned in class'
|
||||
|
||||
@@ -1925,3 +1925,29 @@ test "`new.target` is only allowed meta property", ->
|
||||
-> new.something
|
||||
^^^^^^^^^^^^^
|
||||
'''
|
||||
|
||||
test "#4834: dynamic import requires exactly one argument", ->
|
||||
assertErrorFormat '''
|
||||
import()
|
||||
''', '''
|
||||
[stdin]:1:1: error: import() requires exactly one argument
|
||||
import()
|
||||
^^^^^^^^
|
||||
'''
|
||||
|
||||
assertErrorFormat '''
|
||||
import('x', {})
|
||||
''', '''
|
||||
[stdin]:1:1: error: import() requires exactly one argument
|
||||
import('x', {})
|
||||
^^^^^^^^^^^^^^^
|
||||
'''
|
||||
|
||||
test "#4834: dynamic import requires explicit call parentheses", ->
|
||||
assertErrorFormat '''
|
||||
promise = import 'foo'
|
||||
''', '''
|
||||
[stdin]:1:23: error: unexpected end of input
|
||||
promise = import 'foo'
|
||||
^
|
||||
'''
|
||||
|
||||
@@ -493,3 +493,7 @@ test "#4657: destructured array parameters", ->
|
||||
result = f [1, 2, 3, 4]
|
||||
arrayEq result.a, [1, 2, 3]
|
||||
eq result.b, 4
|
||||
|
||||
test "#5128: default parameters of function in binary operation", ->
|
||||
foo = yes or (a, b = {}) -> null
|
||||
eq foo, yes
|
||||
|
||||
@@ -920,3 +920,24 @@ test "#4874: backslash `export`", ->
|
||||
min
|
||||
} from 'underscore';
|
||||
"""
|
||||
|
||||
test "#4834: dynamic import", ->
|
||||
eqJS """
|
||||
import('module').then ->
|
||||
""",
|
||||
"""
|
||||
import('module').then(function() {});
|
||||
"""
|
||||
|
||||
eqJS """
|
||||
foo = ->
|
||||
bar = await import('bar')
|
||||
""",
|
||||
"""
|
||||
var foo;
|
||||
|
||||
foo = async function() {
|
||||
var bar;
|
||||
return bar = (await import('bar'));
|
||||
};
|
||||
"""
|
||||
|
||||
@@ -418,3 +418,13 @@ test "#4673: complex destructured object spread variables", ->
|
||||
g = ({@y...}) ->
|
||||
eq @y.b, 1
|
||||
g b: 1
|
||||
|
||||
test "#4834: dynamic import can technically be object spread", ->
|
||||
eqJS """
|
||||
x = {...import('module')}
|
||||
""",
|
||||
"""
|
||||
var x;
|
||||
|
||||
x = {...import('module')};
|
||||
"""
|
||||
|
||||
@@ -45,7 +45,7 @@ ctrlV = { ctrl: true, name: 'v'}
|
||||
|
||||
|
||||
testRepl 'reads history file', (input, output, repl) ->
|
||||
input.emitLine repl.rli.history[0]
|
||||
input.emitLine repl.history[0]
|
||||
eq '3', output.lastWrite()
|
||||
|
||||
testRepl "starts with coffee prompt", (input, output) ->
|
||||
|
||||
Reference in New Issue
Block a user