ES module version of compiler for use in browsers; dynamic import() docs; revised Stage 3 policy (#5177)

* Build both a legacy and modern browser compiler

* Dynamic import example and documentation

* Update the docs to use the modern browser compiler if the browser supports it

* Update policy regarding Stage 3 features

* This never made sense, and assigning a string to index 0 *of a string* throws in Module mode (and silently does nothing in Script mode) so remove this unneeded code that throws when compiling `fn for i from from iterable` in Module mode

* Have browser-based tests use the ES module version if supported

* Simplify building logic

* Update output

* For the ES module version of the browser compiler, don't automatically attach the runScripts event handler

* Consistent comments

* Fix comment
This commit is contained in:
Geoffrey Booth 2019-03-26 23:55:31 -07:00 committed by GitHub
parent 41b31c7293
commit f6d63776c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 11668 additions and 219 deletions

View File

@ -66,15 +66,18 @@ build = (callback) ->
buildParser() buildParser()
buildExceptParser callback 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' babel = require '@babel/core'
presets = [] presets = []
# Exclude the `modules` plugin in order to not break the `}(this));` # Exclude the `modules` plugin in order to not break the `}(this));`
# at the end of the `build:browser` code block. # at the end of the `build:browser` code block.
presets.push ['@babel/env', {modules: no}] unless process.env.TRANSFORM is 'false' presets.push ['@babel/env', {modules: no}] if options.transform
presets.push ['minify', {mangle: no, evaluate: no, removeUndefined: no}] unless process.env.MINIFY is 'false' presets.push ['minify', {mangle: no, evaluate: no, removeUndefined: no}] if options.minify
babelOptions = babelOptions =
compact: process.env.MINIFY isnt 'false' compact: not options.minify
comments: not options.minify
presets: presets presets: presets
sourceType: 'script' sourceType: 'script'
{ code } = babel.transform code, babelOptions unless presets.length is 0 { 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; 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 = """ code = """
var CoffeeScript = function() {
function require(path){ return require[path]; }
#{code}
return require['./browser'];
}();
"""
scriptCode = transpile """
(function(root) { (function(root) {
var CoffeeScript = function() { #{code}
function require(path){ return require[path]; }
#{code}
return require['./browser'];
}();
if (typeof define === 'function' && define.amd) { if (typeof define === 'function' && define.amd) {
define(function() { return CoffeeScript; }); 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)); }(this));
""" """
code = transpile code moduleCode = """
outputFolder = "docs/v#{majorVersion}/browser-compiler" #{code}
fs.mkdirSync outputFolder unless fs.existsSync outputFolder
fs.writeFileSync "#{outputFolder}/coffeescript.js", header + '\n' + 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', -> task 'build:browser:full', 'merge the built scripts into a single file for use in a browser, and test it', ->
invoke 'build:browser' invoke 'build:browser'

View File

@ -0,0 +1 @@
v2/browser-compiler-modern

View File

@ -262,7 +262,7 @@ This happens on page load.</p>
</div> </div>
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">runScripts</span> = -&gt;</span> <div class="content"><div class='highlight'><pre>CoffeeScript.runScripts = <span class="hljs-function">-&gt;</span>
scripts = <span class="hljs-built_in">window</span>.<span class="hljs-built_in">document</span>.getElementsByTagName <span class="hljs-string">'script'</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>] 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) 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 "> <div class="pilwrap ">
<a class="pilcrow" href="#section-10">&#182;</a> <a class="pilcrow" href="#section-10">&#182;</a>
</div> </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>
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">if</span> <span class="hljs-built_in">window</span>.addEventListener <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-built_in">window</span>.addEventListener <span class="hljs-string">'DOMContentLoaded'</span>, runScripts, <span class="hljs-literal">no</span> <span class="hljs-keyword">if</span> <span class="hljs-built_in">window</span>.addEventListener
<span class="hljs-keyword">else</span> <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-built_in">window</span>.attachEvent <span class="hljs-string">'onload'</span>, runScripts</pre></div></div> <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> </li>

View File

@ -282,6 +282,32 @@ its not likely to be used. Save in form of <code>filename</code>: [<code>(sou
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-10">&#182;</a> <a class="pilcrow" href="#section-10">&#182;</a>
</div> </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> -&gt;</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">&#182;</a>
</div>
<p>Compile CoffeeScript code to JavaScript, using the Coffee/Jison compiler.</p> <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 <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 specified. All options that can be passed to <code>SourceMap#generate</code> may also
@ -298,11 +324,11 @@ doing programmatic lookups.</p>
</li> </li>
<li id="section-11"> <li id="section-12">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-11">&#182;</a> <a class="pilcrow" href="#section-12">&#182;</a>
</div> </div>
<p>Clone <code>options</code>, to avoid mutating the <code>options</code> object passed in.</p> <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>
<li id="section-12"> <li id="section-13">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-12">&#182;</a> <a class="pilcrow" href="#section-13">&#182;</a>
</div> </div>
<p>Always generate a source map if no filename is passed in, since without a <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 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 checkShebangLine filename, code
sources[filename] ?= []
sources[filename].push code
map = <span class="hljs-keyword">new</span> SourceMap <span class="hljs-keyword">if</span> generateSourceMap map = <span class="hljs-keyword">new</span> SourceMap <span class="hljs-keyword">if</span> generateSourceMap
tokens = lexer.tokenize code, options</pre></div></div> 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>
<li id="section-13"> <li id="section-14">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-13">&#182;</a> <a class="pilcrow" href="#section-14">&#182;</a>
</div> </div>
<p>Pass a list of referenced variables, so that generated variables wont get <p>Pass a list of referenced variables, so that generated variables wont get
the same name.</p> the same name.</p>
@ -357,11 +381,11 @@ the same name.</p>
</li> </li>
<li id="section-14"> <li id="section-15">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-14">&#182;</a> <a class="pilcrow" href="#section-15">&#182;</a>
</div> </div>
<p>Check for import or export; if found, force bare mode.</p> <p>Check for import or export; if found, force bare mode.</p>
@ -385,11 +409,11 @@ the same name.</p>
</li> </li>
<li id="section-15"> <li id="section-16">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-15">&#182;</a> <a class="pilcrow" href="#section-16">&#182;</a>
</div> </div>
<p>Update the sourcemap with data from each fragment.</p> <p>Update the sourcemap with data from each fragment.</p>
@ -400,11 +424,11 @@ the same name.</p>
</li> </li>
<li id="section-16"> <li id="section-17">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-16">&#182;</a> <a class="pilcrow" href="#section-17">&#182;</a>
</div> </div>
<p>Do not include empty, whitespace, or semicolon-only fragments.</p> <p>Do not include empty, whitespace, or semicolon-only fragments.</p>
@ -425,11 +449,11 @@ the same name.</p>
</li> </li>
<li id="section-17"> <li id="section-18">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-17">&#182;</a> <a class="pilcrow" href="#section-18">&#182;</a>
</div> </div>
<p>Copy the code from each fragment into the final JavaScript.</p> <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 <span class="hljs-keyword">if</span> generateSourceMap
v3SourceMap = map.generate options, code 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> 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> <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>
<li id="section-18"> <li id="section-19">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-18">&#182;</a> <a class="pilcrow" href="#section-19">&#182;</a>
</div> </div>
<p>This only happens if run via the Node API and <code>transpile</code> is set to <p>This only happens if run via the Node API and <code>transpile</code> is set to
something other than an object.</p> something other than an object.</p>
@ -468,11 +490,11 @@ something other than an object.</p>
</li> </li>
<li id="section-19"> <li id="section-20">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-19">&#182;</a> <a class="pilcrow" href="#section-20">&#182;</a>
</div> </div>
<p>Get the reference to Babel that we have been passed if this compiler <p>Get the reference to Babel that we have been passed if this compiler
is run via the CLI or Node API.</p> is run via the CLI or Node API.</p>
@ -487,11 +509,11 @@ is run via the CLI or Node API.</p>
</li> </li>
<li id="section-20"> <li id="section-21">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-20">&#182;</a> <a class="pilcrow" href="#section-21">&#182;</a>
</div> </div>
<p>See <a href="https://github.com/babel/babel/issues/827#issuecomment-77573107">https://github.com/babel/babel/issues/827#issuecomment-77573107</a>: <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> 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> 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> 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 <span class="hljs-keyword">if</span> options.sourceMap
{ {
js js
@ -524,11 +548,11 @@ and it will return an <em>updated</em> v3 source map object in its output.</p>
</li> </li>
<li id="section-21"> <li id="section-22">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-21">&#182;</a> <a class="pilcrow" href="#section-22">&#182;</a>
</div> </div>
<p>Tokenize a string of CoffeeScript code, and return the array of tokens.</p> <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>
<li id="section-22"> <li id="section-23">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-22">&#182;</a> <a class="pilcrow" href="#section-23">&#182;</a>
</div> </div>
<p>Parse a string of CoffeeScript code or an array of lexed tokens, and <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, 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>
<li id="section-23"> <li id="section-24">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-23">&#182;</a> <a class="pilcrow" href="#section-24">&#182;</a>
</div> </div>
<p>This file used to export these methods; leave stubs that throw warnings <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 instead. These methods have been moved into <code>index.coffee</code> to provide
@ -581,11 +605,11 @@ environment.</p>
</li> </li>
<li id="section-24"> <li id="section-25">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-24">&#182;</a> <a class="pilcrow" href="#section-25">&#182;</a>
</div> </div>
<p>Instantiate a Lexer for our use here.</p> <p>Instantiate a Lexer for our use here.</p>
@ -596,11 +620,11 @@ environment.</p>
</li> </li>
<li id="section-25"> <li id="section-26">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-25">&#182;</a> <a class="pilcrow" href="#section-26">&#182;</a>
</div> </div>
<p>The real Lexer produces a generic stream of tokens. This object provides a <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 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>
<li id="section-26"> <li id="section-27">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-26">&#182;</a> <a class="pilcrow" href="#section-27">&#182;</a>
</div> </div>
<p>Make all the AST nodes visible to the parser.</p> <p>Make all the AST nodes visible to the parser.</p>
@ -641,11 +665,11 @@ directly as a “Jison lexer.”</p>
</li> </li>
<li id="section-27"> <li id="section-28">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-27">&#182;</a> <a class="pilcrow" href="#section-28">&#182;</a>
</div> </div>
<p>Override Jisons default error handling function.</p> <p>Override Jisons default error handling function.</p>
@ -656,11 +680,11 @@ directly as a “Jison lexer.”</p>
</li> </li>
<li id="section-28"> <li id="section-29">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-28">&#182;</a> <a class="pilcrow" href="#section-29">&#182;</a>
</div> </div>
<p>Disregard Jisons message, it contains redundant line number information. <p>Disregard Jisons message, it contains redundant line number information.
Disregard the token, we take its value directly from the lexer in case 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>
<li id="section-29"> <li id="section-30">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-29">&#182;</a> <a class="pilcrow" href="#section-30">&#182;</a>
</div> </div>
<p>The second argument has a <code>loc</code> property, which should have the location <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> data for this token. Unfortunately, Jison seems to send an outdated <code>loc</code>
@ -702,11 +726,11 @@ from the lexer.</p>
</li> </li>
<li id="section-30"> <li id="section-31">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-30">&#182;</a> <a class="pilcrow" href="#section-31">&#182;</a>
</div> </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> <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> Modified to handle sourceMap</p>
@ -734,11 +758,11 @@ Modified to handle sourceMap</p>
</li> </li>
<li id="section-31"> <li id="section-32">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-31">&#182;</a> <a class="pilcrow" href="#section-32">&#182;</a>
</div> </div>
<p>Check for a sourceMap position</p> <p>Check for a sourceMap position</p>
@ -781,11 +805,11 @@ Modified to handle sourceMap</p>
</li> </li>
<li id="section-32"> <li id="section-33">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-32">&#182;</a> <a class="pilcrow" href="#section-33">&#182;</a>
</div> </div>
<p>Skip files that we didnt compile, like Node system files that appear in <p>Skip files that we didnt compile, like Node system files that appear in
the stack trace, as they never have source maps.</p> 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>
<li id="section-33"> <li id="section-34">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-33">&#182;</a> <a class="pilcrow" href="#section-34">&#182;</a>
</div> </div>
<p>CoffeeScript compiled in a browser or via <code>CoffeeScript.compile</code> or <code>.run</code> <p>CoffeeScript compiled in a browser or via <code>CoffeeScript.compile</code> or <code>.run</code>
may get compiled with <code>options.filename</code> thats missing, which becomes may get compiled with <code>options.filename</code> thats missing, which becomes
@ -819,11 +843,11 @@ filename of the script file. See if we have a source map cached under
</li> </li>
<li id="section-34"> <li id="section-35">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-34">&#182;</a> <a class="pilcrow" href="#section-35">&#182;</a>
</div> </div>
<p>Work backwards from the most recent anonymous source maps, until we find <p>Work backwards from the most recent anonymous source maps, until we find
one that works. This isnt foolproof; there is a chance that multiple one that works. This isnt foolproof; there is a chance that multiple
@ -840,11 +864,11 @@ and its not foolproof either.</p>
</li> </li>
<li id="section-35"> <li id="section-36">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-35">&#182;</a> <a class="pilcrow" href="#section-36">&#182;</a>
</div> </div>
<p>If all else fails, recompile this source to get a source map. We need the <p>If all else fails, recompile this source to get a source map. We need the
previous section (for <code>&lt;anonymous&gt;</code>) despite this option, because after it previous section (for <code>&lt;anonymous&gt;</code>) despite this option, because after it
@ -867,11 +891,11 @@ time the source map we want is the last one.</p>
</li> </li>
<li id="section-36"> <li id="section-37">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-36">&#182;</a> <a class="pilcrow" href="#section-37">&#182;</a>
</div> </div>
<p>Based on <a href="http://goo.gl/ZTx1p">michaelficarra/CoffeeScriptRedux</a> <p>Based on <a href="http://goo.gl/ZTx1p">michaelficarra/CoffeeScriptRedux</a>
NodeJS / V8 have no support for transforming positions in stack traces using NodeJS / V8 have no support for transforming positions in stack traces using

View File

@ -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">'Super'</span>
o <span class="hljs-string">'This'</span> o <span class="hljs-string">'This'</span>
o <span class="hljs-string">'SUPER Arguments'</span>, <span class="hljs-function">-&gt;</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">'SUPER Arguments'</span>, <span class="hljs-function">-&gt;</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">-&gt;</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">-&gt;</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">'SimpleObjAssignable Arguments'</span>, <span class="hljs-function">-&gt;</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">-&gt;</span> <span class="hljs-keyword">new</span> Call $<span class="hljs-number">1</span>, $<span class="hljs-number">2</span> o <span class="hljs-string">'ObjSpreadExpr Arguments'</span>, <span class="hljs-function">-&gt;</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">-&gt;</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 String'</span>, <span class="hljs-function">-&gt;</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">-&gt;</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">'Value OptFuncExist Arguments'</span>, <span class="hljs-function">-&gt;</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">-&gt;</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">'SUPER OptFuncExist Arguments'</span>, <span class="hljs-function">-&gt;</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">-&gt;</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> ]</pre></div></div>
</li> </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">'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">'='</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">'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>] [<span class="hljs-string">'left'</span>, <span class="hljs-string">'POST_IF'</span>]
]</pre></div></div> ]</pre></div></div>

View File

@ -403,8 +403,7 @@ CoffeeScript.register = <span class="hljs-function">-&gt;</span> <span class="hl
Use CoffeeScript.register() or require the coffeescript/register module to require <span class="hljs-subst">#{ext}</span> files. Use CoffeeScript.register() or require the coffeescript/register module to require <span class="hljs-subst">#{ext}</span> files.
"""</span> """</span>
CoffeeScript._compileFile = <span class="hljs-function"><span class="hljs-params">(filename, options = {})</span> -&gt;</span> CoffeeScript._compileRawFileContent = <span class="hljs-function"><span class="hljs-params">(raw, filename, options = {})</span> -&gt;</span></pre></div></div>
raw = fs.readFileSync filename, <span class="hljs-string">'utf8'</span></pre></div></div>
</li> </li>
@ -450,6 +449,11 @@ information to error so it can be pretty-printed later.</p>
answer answer
CoffeeScript._compileFile = <span class="hljs-function"><span class="hljs-params">(filename, options = {})</span> -&gt;</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> <span class="hljs-built_in">module</span>.exports = CoffeeScript</pre></div></div>
</li> </li>

View File

@ -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 @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">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 <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> @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> <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>
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">isForFrom</span> = <span class="hljs-params">(prev)</span> -&gt;</span> <div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">isForFrom</span> = <span class="hljs-params">(prev)</span> -&gt;</span></pre></div></div>
<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>
</li> </li>
@ -2282,13 +2284,12 @@ loop. Try to detect when <code>from</code> is a variable identifier and when it
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-88">&#182;</a> <a class="pilcrow" href="#section-88">&#182;</a>
</div> </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>
<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> <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>
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>
<span class="hljs-literal">yes</span></pre></div></div>
</li> </li>
@ -2299,21 +2300,6 @@ loop. Try to detect when <code>from</code> is a variable identifier and when it
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-89">&#182;</a> <a class="pilcrow" href="#section-89">&#182;</a>
</div> </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">&#182;</a>
</div>
<p><code>for from…</code></p> <p><code>for from…</code></p>
</div> </div>
@ -2324,11 +2310,11 @@ loop. Try to detect when <code>from</code> is a variable identifier and when it
</li> </li>
<li id="section-91"> <li id="section-90">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-91">&#182;</a> <a class="pilcrow" href="#section-90">&#182;</a>
</div> </div>
<p><code>for {from}…</code>, <code>for [from]…</code>, <code>for {a, from}…</code>, <code>for {a: from}…</code></p> <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>
<li id="section-91">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-91">&#182;</a>
</div>
<h2 id="constants">Constants</h2>
</div>
</li>
<li id="section-92"> <li id="section-92">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-92">&#182;</a> <a class="pilcrow" href="#section-92">&#182;</a>
</div> </div>
<h2 id="constants">Constants</h2>
</div> </div>
</li> </li>
@ -2361,18 +2359,6 @@ loop. Try to detect when <code>from</code> is a variable identifier and when it
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-93">&#182;</a> <a class="pilcrow" href="#section-93">&#182;</a>
</div> </div>
</div>
</li>
<li id="section-94">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-94">&#182;</a>
</div>
<p>Keywords that CoffeeScript shares in common with JavaScript.</p> <p>Keywords that CoffeeScript shares in common with JavaScript.</p>
</div> </div>
@ -2389,11 +2375,11 @@ loop. Try to detect when <code>from</code> is a variable identifier and when it
</li> </li>
<li id="section-95"> <li id="section-94">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-95">&#182;</a> <a class="pilcrow" href="#section-94">&#182;</a>
</div> </div>
<p>CoffeeScript-only keywords.</p> <p>CoffeeScript-only keywords.</p>
@ -2421,11 +2407,11 @@ COFFEE_KEYWORDS = COFFEE_KEYWORDS.concat COFFEE_ALIASES</pre></div></div>
</li> </li>
<li id="section-96"> <li id="section-95">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-96">&#182;</a> <a class="pilcrow" href="#section-95">&#182;</a>
</div> </div>
<p>The list of keywords that are reserved by JavaScript, but not used, or are <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, 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>
<li id="section-97"> <li id="section-96">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-97">&#182;</a> <a class="pilcrow" href="#section-96">&#182;</a>
</div> </div>
<p>The superset of both JavaScript keywords and reserved words, none of which may <p>The superset of both JavaScript keywords and reserved words, none of which may
be used as identifiers or properties.</p> be used as identifiers or properties.</p>
@ -2460,11 +2446,11 @@ be used as identifiers or properties.</p>
</li> </li>
<li id="section-98"> <li id="section-97">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-98">&#182;</a> <a class="pilcrow" href="#section-97">&#182;</a>
</div> </div>
<p>The character code of the nasty Microsoft madness otherwise known as the BOM.</p> <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>
<li id="section-99"> <li id="section-98">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-99">&#182;</a> <a class="pilcrow" href="#section-98">&#182;</a>
</div> </div>
<p>Token matching regexes.</p> <p>Token matching regexes.</p>
@ -2499,11 +2485,11 @@ CSX_IDENTIFIER = <span class="hljs-regexp">/// ^
</li> </li>
<li id="section-100"> <li id="section-99">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-100">&#182;</a> <a class="pilcrow" href="#section-99">&#182;</a>
</div> </div>
<p>Fragment: &lt;&gt;&lt;/&gt;</p> <p>Fragment: &lt;&gt;&lt;/&gt;</p>
@ -2550,11 +2536,11 @@ HERE_JSTOKEN = <span class="hljs-regexp">///^ ``` ((?: [^`\\] | \\[\s\S] | `
</li> </li>
<li id="section-101"> <li id="section-100">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-101">&#182;</a> <a class="pilcrow" href="#section-100">&#182;</a>
</div> </div>
<p>String-matching-regexes.</p> <p>String-matching-regexes.</p>
@ -2588,11 +2574,11 @@ HEREDOC_INDENT = <span class="hljs-regexp">/\n+([^\n\S]*)(?=\S)/g</span></pr
</li> </li>
<li id="section-102"> <li id="section-101">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-102">&#182;</a> <a class="pilcrow" href="#section-101">&#182;</a>
</div> </div>
<p>Regex-matching-regexes.</p> <p>Regex-matching-regexes.</p>
@ -2618,11 +2604,11 @@ HEREGEX = <span class="hljs-regexp">/// ^
</li> </li>
<li id="section-103"> <li id="section-102">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-103">&#182;</a> <a class="pilcrow" href="#section-102">&#182;</a>
</div> </div>
<p>Match any character, except those that need special handling below.</p> <p>Match any character, except those that need special handling below.</p>
@ -2633,11 +2619,11 @@ HEREGEX = <span class="hljs-regexp">/// ^
</li> </li>
<li id="section-104"> <li id="section-103">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-104">&#182;</a> <a class="pilcrow" href="#section-103">&#182;</a>
</div> </div>
<p>Match <code>\</code> followed by any character.</p> <p>Match <code>\</code> followed by any character.</p>
@ -2648,11 +2634,11 @@ HEREGEX = <span class="hljs-regexp">/// ^
</li> </li>
<li id="section-105"> <li id="section-104">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-105">&#182;</a> <a class="pilcrow" href="#section-104">&#182;</a>
</div> </div>
<p>Match any <code>/</code> except <code>///</code>.</p> <p>Match any <code>/</code> except <code>///</code>.</p>
@ -2663,11 +2649,11 @@ HEREGEX = <span class="hljs-regexp">/// ^
</li> </li>
<li id="section-106"> <li id="section-105">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-106">&#182;</a> <a class="pilcrow" href="#section-105">&#182;</a>
</div> </div>
<p>Match <code>#</code> which is not part of interpolation, e.g. <code>#{}</code>.</p> <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>
<li id="section-107"> <li id="section-106">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-107">&#182;</a> <a class="pilcrow" href="#section-106">&#182;</a>
</div> </div>
<p>Comments consume everything until the end of the line, including <code>///</code>.</p> <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>
<li id="section-108"> <li id="section-107">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-108">&#182;</a> <a class="pilcrow" href="#section-107">&#182;</a>
</div> </div>
<p>Other regexes.</p> <p>Other regexes.</p>
@ -2752,11 +2738,11 @@ TRAILING_SPACES = <span class="hljs-regexp">/\s+$/</span></pre></div></div>
</li> </li>
<li id="section-109"> <li id="section-108">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-109">&#182;</a> <a class="pilcrow" href="#section-108">&#182;</a>
</div> </div>
<p>Compound assignment tokens.</p> <p>Compound assignment tokens.</p>
@ -2770,11 +2756,11 @@ TRAILING_SPACES = <span class="hljs-regexp">/\s+$/</span></pre></div></div>
</li> </li>
<li id="section-110"> <li id="section-109">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-110">&#182;</a> <a class="pilcrow" href="#section-109">&#182;</a>
</div> </div>
<p>Unary tokens.</p> <p>Unary tokens.</p>
@ -2787,11 +2773,11 @@ UNARY_MATH = [<span class="hljs-string">'!'</span>, <span class="hljs-string">'~
</li> </li>
<li id="section-111"> <li id="section-110">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-111">&#182;</a> <a class="pilcrow" href="#section-110">&#182;</a>
</div> </div>
<p>Bit-shifting tokens.</p> <p>Bit-shifting tokens.</p>
@ -2802,11 +2788,11 @@ UNARY_MATH = [<span class="hljs-string">'!'</span>, <span class="hljs-string">'~
</li> </li>
<li id="section-112"> <li id="section-111">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-112">&#182;</a> <a class="pilcrow" href="#section-111">&#182;</a>
</div> </div>
<p>Comparison tokens.</p> <p>Comparison tokens.</p>
@ -2817,11 +2803,11 @@ UNARY_MATH = [<span class="hljs-string">'!'</span>, <span class="hljs-string">'~
</li> </li>
<li id="section-113"> <li id="section-112">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-113">&#182;</a> <a class="pilcrow" href="#section-112">&#182;</a>
</div> </div>
<p>Mathematical tokens.</p> <p>Mathematical tokens.</p>
@ -2832,11 +2818,11 @@ UNARY_MATH = [<span class="hljs-string">'!'</span>, <span class="hljs-string">'~
</li> </li>
<li id="section-114"> <li id="section-113">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-114">&#182;</a> <a class="pilcrow" href="#section-113">&#182;</a>
</div> </div>
<p>Relational tokens that are negatable with <code>not</code> prefix.</p> <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>
<li id="section-115"> <li id="section-114">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-115">&#182;</a> <a class="pilcrow" href="#section-114">&#182;</a>
</div> </div>
<p>Boolean tokens.</p> <p>Boolean tokens.</p>
@ -2862,11 +2848,11 @@ UNARY_MATH = [<span class="hljs-string">'!'</span>, <span class="hljs-string">'~
</li> </li>
<li id="section-116"> <li id="section-115">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-116">&#182;</a> <a class="pilcrow" href="#section-115">&#182;</a>
</div> </div>
<p>Tokens which could legitimately be invoked or indexed. An opening <p>Tokens which could legitimately be invoked or indexed. An opening
parentheses or bracket following these tokens will be recorded as the start 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>
<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 [ 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">'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> <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>
<li id="section-117"> <li id="section-116">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-117">&#182;</a> <a class="pilcrow" href="#section-116">&#182;</a>
</div> </div>
<p>Tokens which can be the left-hand side of a less-than comparison, i.e. <code>a&lt;b</code>.</p> <p>Tokens which can be the left-hand side of a less-than comparison, i.e. <code>a&lt;b</code>.</p>
@ -2898,11 +2884,11 @@ INDEXABLE = CALLABLE.concat [
</li> </li>
<li id="section-118"> <li id="section-117">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-118">&#182;</a> <a class="pilcrow" href="#section-117">&#182;</a>
</div> </div>
<p>Tokens which a regular expression will never immediately follow (except spaced <p>Tokens which a regular expression will never immediately follow (except spaced
CALLABLEs in some cases), but which a division operator can.</p> 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>
<li id="section-119"> <li id="section-118">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-119">&#182;</a> <a class="pilcrow" href="#section-118">&#182;</a>
</div> </div>
<p>Tokens that, when immediately preceding a <code>WHEN</code>, indicate that the <code>WHEN</code> <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 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>
<li id="section-120"> <li id="section-119">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-120">&#182;</a> <a class="pilcrow" href="#section-119">&#182;</a>
</div> </div>
<p>Additional indent in front of these is ignored.</p> <p>Additional indent in front of these is ignored.</p>
@ -2947,11 +2933,11 @@ avoid an ambiguity in the grammar.</p>
</li> </li>
<li id="section-121"> <li id="section-120">
<div class="annotation"> <div class="annotation">
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-121">&#182;</a> <a class="pilcrow" href="#section-120">&#182;</a>
</div> </div>
<p>Tokens that, when appearing at the end of a line, suppress a following TERMINATOR/INDENT token</p> <p>Tokens that, when appearing at the end of a line, suppress a following TERMINATOR/INDENT token</p>

View File

@ -542,7 +542,7 @@ the two values are raw nodes which have not been compiled.</p>
</div> </div>
<p>Occasionally it may be useful to make an expression behave as if it was hoisted, whereby the <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 expressions result of the expression is available before its location in the source, but the expressions
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> class bodies in classes.</p>
<p>Calling this method mutates the node, proxying the <code>compileNode</code> and <code>compileToFragments</code> <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 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> -&gt;</span> compileNode: <span class="hljs-function"><span class="hljs-params">(o)</span> -&gt;</span>
<span class="hljs-keyword">return</span> [@makeCode <span class="hljs-string">'[]'</span>] <span class="hljs-keyword">unless</span> @objects.length <span class="hljs-keyword">return</span> [@makeCode <span class="hljs-string">'[]'</span>] <span class="hljs-keyword">unless</span> @objects.length
o.indent += TAB o.indent += TAB
<span class="hljs-function"> <span class="hljs-title">fragmentIsElision</span> = <span class="hljs-params">(fragment)</span> -&gt;</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> -&gt;</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> </li>
@ -3490,7 +3491,7 @@ are too.</p>
<div class="pilwrap "> <div class="pilwrap ">
<a class="pilcrow" href="#section-144">&#182;</a> <a class="pilcrow" href="#section-144">&#182;</a>
</div> </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> </div>
@ -3587,7 +3588,7 @@ element isnt <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">for</span> fragment, fragmentIndex <span class="hljs-keyword">in</span> answer
<span class="hljs-keyword">if</span> fragment.isHereComment <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> 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> 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.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> 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> =&gt;</span> @body.traverseChildren <span class="hljs-literal">false</span>, <span class="hljs-function"><span class="hljs-params">(node)</span> =&gt;</span>
<span class="hljs-keyword">if</span> node <span class="hljs-keyword">instanceof</span> ThisLiteral <span class="hljs-keyword">if</span> node <span class="hljs-keyword">instanceof</span> ThisLiteral
node.value = @name 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> node.context = @name</pre></div></div>
</li> </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> 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> -&gt;</span> constructor: <span class="hljs-function"><span class="hljs-params">(local, exported)</span> -&gt;</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">-&gt;</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> -&gt;</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> </li>
@ -5582,7 +5593,7 @@ This is usually caught via <code>Op::compileContinuation</code>, but double-chec
</div> </div>
<div class="content"><div class='highlight'><pre> scopeVariablesCount = o.scope.variables.length <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 <span class="hljs-keyword">if</span> scopeVariablesCount <span class="hljs-keyword">isnt</span> o.scope.variables.length
generatedVariables = o.scope.variables.splice scopeVariablesCount generatedVariables = o.scope.variables.splice scopeVariablesCount
o.scope.parent.variables.push generatedVariables... o.scope.parent.variables.push generatedVariables...

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

View File

@ -3,7 +3,12 @@
<head> <head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<title>CoffeeScript Test Suite</title> <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> <script src="https://cdn.jsdelivr.net/underscorejs/1.8.3/underscore-min.js"></script>
<style> <style>
body, pre { body, pre {
@ -452,6 +457,12 @@ test "array elisions nested destructuring", ->
deepEqual d, {x:2} deepEqual d, {x:2}
arrayEq w, [1,2,4] 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 # Splats in Array Literals
test "array splat expansions with assignments", -> test "array splat expansions with assignments", ->
@ -3546,6 +3557,19 @@ test "#4609: Support new.target", ->
new Foo() new Foo()
eq newTarget, yes 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>
<script type="text/x-coffeescript" class="test" id="cluster"> <script type="text/x-coffeescript" class="test" id="cluster">
# Cluster Module # 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>
<script type="text/x-coffeescript" class="test" id="eval"> <script type="text/x-coffeescript" class="test" id="eval">
if vm = require? 'vm' if vm = require? 'vm'
@ -11724,6 +11774,10 @@ test "#4657: destructured array parameters", ->
arrayEq result.a, [1, 2, 3] arrayEq result.a, [1, 2, 3]
eq result.b, 4 eq result.b, 4
test "#5128: default parameters of function in binary operation", ->
foo = yes or (a, b = {}) -> null
eq foo, yes
</script> </script>
<script type="text/x-coffeescript" class="test" id="generators"> <script type="text/x-coffeescript" class="test" id="generators">
# Generators # Generators
@ -14443,6 +14497,27 @@ test "#4874: backslash `export`", ->
} from 'underscore'; } 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>
<script type="text/x-coffeescript" class="test" id="numbers"> <script type="text/x-coffeescript" class="test" id="numbers">
# Number Literals # Number Literals
@ -14957,6 +15032,16 @@ test "#4673: complex destructured object spread variables", ->
eq @y.b, 1 eq @y.b, 1
g 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>
<script type="text/x-coffeescript" class="test" id="objects"> <script type="text/x-coffeescript" class="test" id="objects">
# Object Literals # Object Literals
@ -17138,7 +17223,7 @@ ctrlV = { ctrl: true, name: 'v'}
testRepl 'reads history file', (input, output, repl) -> testRepl 'reads history file', (input, output, repl) ->
input.emitLine repl.rli.history[0] input.emitLine repl.history[0]
eq '3', output.lastWrite() eq '3', output.lastWrite()
testRepl "starts with coffee prompt", (input, output) -> testRepl "starts with coffee prompt", (input, output) ->

View 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.'
'''

View File

@ -1,4 +1,4 @@
import 'local-file.coffee' import './local-file.coffee'
import 'coffeescript' import 'coffeescript'
import _ from 'underscore' import _ from 'underscore'

View File

@ -2,7 +2,7 @@
Contributions are welcome! Feel free to fork [the repo](https://github.com/jashkenas/coffeescript) and submit a pull request. 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 youre looking for has already been discussed. As a general rule, we dont support ECMAScript syntax for features that arent 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 youre looking for has already been discussed. As a general rule, we dont support ECMAScript syntax for features that arent 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). 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 didnt break anything, or future changes wont break your code. * Create tests! Any pull request should probably include basic tests to verify you didnt break anything, or future changes wont break your code.
* Follow the style of the rest of the CoffeeScript codebase. * 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. * Add only features that have broad utility, rather than a feature aimed at a specific use case or framework.
Of course, its entirely possible that you have a great addition, but it doesnt 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). Of course, its entirely possible that you have a great addition, but it doesnt 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).

View File

@ -6,6 +6,12 @@ ES2015 modules are supported in CoffeeScript, with very similar `import` and `ex
codeFor('modules') codeFor('modules')
``` ```
[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> <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. 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.

View File

@ -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://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="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 nomodule src="./browser-compiler/coffeescript.js"></script>
<script> <script nomodule>
<%= includeScript('docs.coffee') %> <%= includeScript('docs.coffee') %>
</script> </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> <script async src="https://www.googletagmanager.com/gtag/js?id=UA-106156830-1"></script>

View File

@ -3,7 +3,12 @@
<head> <head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<title>CoffeeScript Test Suite</title> <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> <script src="https://cdn.jsdelivr.net/underscorejs/1.8.3/underscore-min.js"></script>
<style> <style>
body, pre { body, pre {

View File

@ -4,7 +4,7 @@
// to make things work smoothly when compiling code directly in the browser. // to make things work smoothly when compiling code directly in the browser.
// We add support for loading remote Coffee scripts via **XHR**, and // We add support for loading remote Coffee scripts via **XHR**, and
// `text/coffeescript` script tags, source maps via data-URLs, and so on. // `text/coffeescript` script tags, source maps via data-URLs, and so on.
var CoffeeScript, compile, runScripts, var CoffeeScript, compile,
indexOf = [].indexOf; indexOf = [].indexOf;
CoffeeScript = require('./coffeescript'); CoffeeScript = require('./coffeescript');
@ -81,7 +81,7 @@
// Activate CoffeeScript in the browser by having it compile and evaluate // Activate CoffeeScript in the browser by having it compile and evaluate
// all script tags with a content-type of `text/coffeescript`. // all script tags with a content-type of `text/coffeescript`.
// This happens on page load. // This happens on page load.
runScripts = function() { CoffeeScript.runScripts = function() {
var coffees, coffeetypes, execute, i, index, j, len, s, script, scripts; var coffees, coffeetypes, execute, i, index, j, len, s, script, scripts;
scripts = window.document.getElementsByTagName('script'); scripts = window.document.getElementsByTagName('script');
coffeetypes = ['text/coffeescript', 'text/literate-coffeescript']; coffeetypes = ['text/coffeescript', 'text/literate-coffeescript'];
@ -136,10 +136,16 @@
}; };
// Listen for window load, both in decent browsers and in IE. // Listen for window load, both in decent browsers and in IE.
if (window.addEventListener) { // Only attach this event handler on startup for the
window.addEventListener('DOMContentLoaded', runScripts, false); // non-ES module version of the browser compiler, to preserve
} else { // backward compatibility while letting the ES module version
window.attachEvent('onload', runScripts); // 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); }).call(this);

View File

@ -1487,13 +1487,8 @@
// “sometimes” keyword. // “sometimes” keyword.
isForFrom = function(prev) { isForFrom = function(prev) {
var ref; var ref;
// `for i from iterable`
if (prev[0] === 'IDENTIFIER') { 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; return true;
// `for from…` // `for from…`
} else if (prev[0] === 'FOR') { } else if (prev[0] === 'FOR') {

View File

@ -17,6 +17,7 @@
"lib": "./lib/coffeescript" "lib": "./lib/coffeescript"
}, },
"main": "./lib/coffeescript/index", "main": "./lib/coffeescript/index",
"module": "./docs/v2/browser-compiler-modern/coffeescript.js",
"browser": "./lib/coffeescript/browser", "browser": "./lib/coffeescript/browser",
"bin": { "bin": {
"coffee": "./bin/coffee", "coffee": "./bin/coffee",

View File

@ -58,7 +58,7 @@ CoffeeScript.load = (url, callback, options = {}, hold = false) ->
# Activate CoffeeScript in the browser by having it compile and evaluate # Activate CoffeeScript in the browser by having it compile and evaluate
# all script tags with a content-type of `text/coffeescript`. # all script tags with a content-type of `text/coffeescript`.
# This happens on page load. # This happens on page load.
runScripts = -> CoffeeScript.runScripts = ->
scripts = window.document.getElementsByTagName 'script' scripts = window.document.getElementsByTagName 'script'
coffeetypes = ['text/coffeescript', 'text/literate-coffeescript'] coffeetypes = ['text/coffeescript', 'text/literate-coffeescript']
coffees = (s for s in scripts when s.type in coffeetypes) coffees = (s for s in scripts when s.type in coffeetypes)
@ -96,7 +96,12 @@ runScripts = ->
execute() execute()
# Listen for window load, both in decent browsers and in IE. # Listen for window load, both in decent browsers and in IE.
if window.addEventListener # Only attach this event handler on startup for the
window.addEventListener 'DOMContentLoaded', runScripts, no # non-ES module version of the browser compiler, to preserve
else # backward compatibility while letting the ES module version
window.attachEvent 'onload', runScripts # be importable without side effects.
if this is window
if window.addEventListener
window.addEventListener 'DOMContentLoaded', CoffeeScript.runScripts, no
else
window.attachEvent 'onload', CoffeeScript.runScripts

View File

@ -1112,12 +1112,8 @@ exports.isUnassignable = isUnassignable
# loop. Try to detect when `from` is a variable identifier and when it is this # loop. Try to detect when `from` is a variable identifier and when it is this
# sometimes keyword. # sometimes keyword.
isForFrom = (prev) -> isForFrom = (prev) ->
# `for i from iterable`
if prev[0] is 'IDENTIFIER' 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 yes
# `for from` # `for from`
else if prev[0] is 'FOR' else if prev[0] is 'FOR'