mirror of
https://github.com/jashkenas/coffeescript.git
synced 2026-01-14 09:17:55 -05:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a73f66bc11 | ||
|
|
ba094126e2 | ||
|
|
794f65fbd7 |
@@ -2947,7 +2947,11 @@ needed to iterate over the values in the range. Used by comprehensions.</p>
|
||||
idx = del o, <span class="hljs-string">'index'</span>
|
||||
idxName = del o, <span class="hljs-string">'name'</span>
|
||||
namedIndex = idxName <span class="hljs-keyword">and</span> idxName <span class="hljs-keyword">isnt</span> idx
|
||||
varPart = <span class="hljs-string">"<span class="hljs-subst">#{idx}</span> = <span class="hljs-subst">#{@fromC}</span>"</span>
|
||||
varPart =
|
||||
<span class="hljs-keyword">if</span> known <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> namedIndex
|
||||
<span class="hljs-string">"var <span class="hljs-subst">#{idx}</span> = <span class="hljs-subst">#{@fromC}</span>"</span>
|
||||
<span class="hljs-keyword">else</span>
|
||||
<span class="hljs-string">"<span class="hljs-subst">#{idx}</span> = <span class="hljs-subst">#{@fromC}</span>"</span>
|
||||
varPart += <span class="hljs-string">", <span class="hljs-subst">#{@toC}</span>"</span> <span class="hljs-keyword">if</span> @toC <span class="hljs-keyword">isnt</span> @toVar
|
||||
varPart += <span class="hljs-string">", <span class="hljs-subst">#{@step}</span>"</span> <span class="hljs-keyword">if</span> @step <span class="hljs-keyword">isnt</span> @stepVar
|
||||
[lt, gt] = [<span class="hljs-string">"<span class="hljs-subst">#{idx}</span> <<span class="hljs-subst">#{@equals}</span>"</span>, <span class="hljs-string">"<span class="hljs-subst">#{idx}</span> ><span class="hljs-subst">#{@equals}</span>"</span>]</pre></div></div>
|
||||
@@ -4955,8 +4959,8 @@ Examples: [a, b, c…, d, e, f…], [a, b, …, c, d, …], [a, b, …, c, d, e
|
||||
|
||||
<div class="content"><div class='highlight'><pre> objects[splatsAndExpans.sort()[<span class="hljs-number">1</span>]].error <span class="hljs-string">"multiple splats/expansions are disallowed in an assignment"</span>
|
||||
|
||||
isSplat = splats.length
|
||||
isExpans = expans.length
|
||||
isSplat = splats?.length > <span class="hljs-number">0</span>
|
||||
isExpans = expans?.length > <span class="hljs-number">0</span>
|
||||
isObject = @variable.isObject()
|
||||
isArray = @variable.isArray()
|
||||
|
||||
@@ -5101,7 +5105,7 @@ Examples: [a, b, {c, r…}, d], [a, …, {b, r…}, c, d]</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-function"> <span class="hljs-title">loopObjects</span> = <span class="hljs-params">(objs, vvarTxt)</span> =></span>
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-function"> <span class="hljs-title">loopObjects</span> = <span class="hljs-params">(objs, vvar, vvarTxt)</span> =></span>
|
||||
objSpreads = hasObjSpreads objs
|
||||
<span class="hljs-keyword">for</span> obj, i <span class="hljs-keyword">in</span> objs</pre></div></div>
|
||||
|
||||
@@ -5182,16 +5186,16 @@ Examples: [a, b, {c, r…}, d], [a, …, {b, r…}, c, d]</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-function"> <span class="hljs-title">assignObjects</span> = <span class="hljs-params">(objs, vvarTxt)</span> =></span>
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-function"> <span class="hljs-title">assignObjects</span> = <span class="hljs-params">(objs, vvar, vvarTxt)</span> =></span>
|
||||
vvar = <span class="hljs-keyword">new</span> Value <span class="hljs-keyword">new</span> Arr(objs, <span class="hljs-literal">yes</span>)
|
||||
vval = <span class="hljs-keyword">if</span> vvarTxt <span class="hljs-keyword">instanceof</span> Value <span class="hljs-keyword">then</span> vvarTxt <span class="hljs-keyword">else</span> <span class="hljs-keyword">new</span> Value <span class="hljs-keyword">new</span> Literal(vvarTxt)
|
||||
assigns.push <span class="hljs-keyword">new</span> Assign(vvar, vval, <span class="hljs-literal">null</span>, param: @param, subpattern: <span class="hljs-literal">yes</span>).compileToFragments o, LEVEL_LIST
|
||||
<span class="hljs-function">
|
||||
<span class="hljs-title">processObjects</span> = <span class="hljs-params">(objs, vvarTxt)</span> -></span>
|
||||
<span class="hljs-title">processObjects</span> = <span class="hljs-params">(objs, vvar, vvarTxt)</span> -></span>
|
||||
<span class="hljs-keyword">if</span> complexObjects objs
|
||||
loopObjects objs, vvarTxt
|
||||
loopObjects objs, vvar, vvarTxt
|
||||
<span class="hljs-keyword">else</span>
|
||||
assignObjects objs, vvarTxt</pre></div></div>
|
||||
assignObjects objs, vvar, vvarTxt</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -5220,7 +5224,7 @@ b) <code>Expansion</code>
|
||||
expIdx = splatsAndExpans[<span class="hljs-number">0</span>]
|
||||
leftObjs = objects.slice <span class="hljs-number">0</span>, expIdx + (<span class="hljs-keyword">if</span> isSplat <span class="hljs-keyword">then</span> <span class="hljs-number">1</span> <span class="hljs-keyword">else</span> <span class="hljs-number">0</span>)
|
||||
rightObjs = objects.slice expIdx + <span class="hljs-number">1</span>
|
||||
processObjects leftObjs, vvarText <span class="hljs-keyword">if</span> leftObjs.length <span class="hljs-keyword">isnt</span> <span class="hljs-number">0</span>
|
||||
processObjects leftObjs, vvar, vvarText <span class="hljs-keyword">if</span> leftObjs.length <span class="hljs-keyword">isnt</span> <span class="hljs-number">0</span>
|
||||
<span class="hljs-keyword">if</span> rightObjs.length <span class="hljs-keyword">isnt</span> <span class="hljs-number">0</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -5243,7 +5247,7 @@ b) <code>Expansion</code>
|
||||
restVar = refExp
|
||||
refExp = o.scope.freeVariable <span class="hljs-string">'ref'</span>
|
||||
assigns.push [@makeCode(refExp + <span class="hljs-string">' = '</span>), restVar.compileToFragments(o, LEVEL_LIST)...]
|
||||
processObjects rightObjs, refExp
|
||||
processObjects rightObjs, vvar, refExp
|
||||
<span class="hljs-keyword">else</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -5259,7 +5263,7 @@ b) <code>Expansion</code>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> processObjects objects, vvarText
|
||||
<div class="content"><div class='highlight'><pre> processObjects objects, vvar, vvarText
|
||||
assigns.push vvar <span class="hljs-keyword">unless</span> top <span class="hljs-keyword">or</span> @subpattern
|
||||
fragments = @joinFragmentArrays assigns, <span class="hljs-string">', '</span>
|
||||
<span class="hljs-keyword">if</span> o.level < LEVEL_LIST <span class="hljs-keyword">then</span> fragments <span class="hljs-keyword">else</span> @wrapInParentheses fragments</pre></div></div>
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -646,7 +646,7 @@ div.CodeMirror-cursor {
|
||||
<section id="overview">
|
||||
<p><strong>CoffeeScript is a little language that compiles into JavaScript.</strong> Underneath that awkward Java-esque patina, JavaScript has always had a gorgeous heart. CoffeeScript is an attempt to expose the good parts of JavaScript in a simple way.</p>
|
||||
<p>The golden rule of CoffeeScript is: <em>“It’s just JavaScript.”</em> The code compiles one-to-one into the equivalent JS, and there is no interpretation at runtime. You can use any existing JavaScript library seamlessly from CoffeeScript (and vice-versa). The compiled output is readable, pretty-printed, and tends to run as fast or faster than the equivalent handwritten JavaScript.</p>
|
||||
<p><strong>Latest Version:</strong> <a href="https://github.com/jashkenas/coffeescript/tarball/2.2.0">2.2.0</a></p>
|
||||
<p><strong>Latest Version:</strong> <a href="https://github.com/jashkenas/coffeescript/tarball/2.2.1">2.2.1</a></p>
|
||||
<blockquote class="uneditable-code-block"><pre><code class="language-bash"><span class="comment"># Install locally for a project:</span>
|
||||
npm install --save-dev coffeescript
|
||||
|
||||
@@ -4790,7 +4790,7 @@ The CoffeeScript logo is available in SVG for use in presentations.</li>
|
||||
</section>
|
||||
<section id="annotated-source">
|
||||
<h2>Annotated Source</h2>
|
||||
<p>You can browse the CoffeeScript 2.2.0 source in readable, annotated form <a href="annotated-source/">here</a>. You can also jump directly to a particular source file:</p>
|
||||
<p>You can browse the CoffeeScript 2.2.1 source in readable, annotated form <a href="annotated-source/">here</a>. You can also jump directly to a particular source file:</p>
|
||||
<ul>
|
||||
<li><a href="annotated-source/grammar.html">Grammar Rules — src/grammar</a></li>
|
||||
<li><a href="annotated-source/lexer.html">Lexing Tokens — src/lexer</a></li>
|
||||
@@ -5467,6 +5467,14 @@ x = <span class="number">2</span> + <span class="number">2</span>
|
||||
</section>
|
||||
<section id="changelog">
|
||||
<h2>Changelog</h2>
|
||||
<div class="anchor" id="2.2.1"></div>
|
||||
<h2 class="header">
|
||||
<a href="https://github.com/jashkenas/coffeescript/compare/2.1.0...2.2.1">2.2.1</a>
|
||||
<span class="timestamp"> — <time datetime="2018-02-06">February 6, 2018</time></span>
|
||||
</h2><ul>
|
||||
<li>Bugfix for regression in 2.2.0 involving an error thrown by the compiler in certain cases when using destructuring with a splat or expansion in an array.</li>
|
||||
<li>Bugfix for regression in 2.2.0 where in certain cases a range iterator variable was declared in the global scope.</li>
|
||||
</ul>
|
||||
<div class="anchor" id="2.2.0"></div>
|
||||
<h2 class="header">
|
||||
<a href="https://github.com/jashkenas/coffeescript/compare/2.1.1...2.2.0">2.2.0</a>
|
||||
|
||||
@@ -1573,6 +1573,46 @@ test "#4673: complex destructured object spread variables", ->
|
||||
{{g}...} = g: 1
|
||||
eq g, 1
|
||||
|
||||
test "#4878: Compile error when using destructuring with a splat or expansion in an array", ->
|
||||
arr = ['a', 'b', 'c', 'd']
|
||||
|
||||
f1 = (list) ->
|
||||
[first, ..., last] = list
|
||||
|
||||
f2 = (list) ->
|
||||
[first..., last] = list
|
||||
|
||||
f3 = (list) ->
|
||||
([first, ...] = list); first
|
||||
|
||||
f4 = (list) ->
|
||||
([first, ...rest] = list); rest
|
||||
|
||||
arrayEq f1(arr), arr
|
||||
arrayEq f2(arr), arr
|
||||
arrayEq f3(arr), 'a'
|
||||
arrayEq f4(arr), ['b', 'c', 'd']
|
||||
|
||||
foo = (list) ->
|
||||
ret =
|
||||
if list?.length > 0
|
||||
[first, ..., last] = list
|
||||
[first, last]
|
||||
else
|
||||
[]
|
||||
|
||||
arrayEq foo(arr), ['a', 'd']
|
||||
|
||||
bar = (list) ->
|
||||
ret =
|
||||
if list?.length > 0
|
||||
[first, ...rest] = list
|
||||
[first, rest]
|
||||
else
|
||||
[]
|
||||
|
||||
arrayEq bar(arr), ['a', ['b', 'c', 'd']]
|
||||
|
||||
</script>
|
||||
<script type="text/x-coffeescript" class="test" id="async">
|
||||
# Functions that contain the `await` keyword will compile into async functions,
|
||||
@@ -16173,6 +16213,13 @@ test "#2047: from, to and step as variables", ->
|
||||
r = (x for x in [b..a] by step)
|
||||
arrayEq r, []
|
||||
|
||||
test "#4884: Range not declaring var for the 'i'", ->
|
||||
'use strict'
|
||||
[0..21].forEach (idx) ->
|
||||
idx + 1
|
||||
|
||||
eq global.i, undefined
|
||||
|
||||
</script>
|
||||
<script type="text/x-coffeescript" class="test" id="regexps">
|
||||
# Regular Expression Literals
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
## Changelog
|
||||
|
||||
```
|
||||
releaseHeader('2018-02-06', '2.2.1', '2.1.0')
|
||||
```
|
||||
* Bugfix for regression in 2.2.0 involving an error thrown by the compiler in certain cases when using destructuring with a splat or expansion in an array.
|
||||
* Bugfix for regression in 2.2.0 where in certain cases a range iterator variable was declared in the global scope.
|
||||
|
||||
```
|
||||
releaseHeader('2018-02-01', '2.2.0', '2.1.1')
|
||||
```
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.2.0
|
||||
// Generated by CoffeeScript 2.2.1
|
||||
(function() {
|
||||
// This **Browser** compatibility layer extends core CoffeeScript functions
|
||||
// to make things work smoothly when compiling code directly in the browser.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.2.0
|
||||
// Generated by CoffeeScript 2.2.1
|
||||
(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,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.2.0
|
||||
// Generated by CoffeeScript 2.2.1
|
||||
(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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.2.0
|
||||
// Generated by CoffeeScript 2.2.1
|
||||
(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.2.0
|
||||
// Generated by CoffeeScript 2.2.1
|
||||
(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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.2.0
|
||||
// Generated by CoffeeScript 2.2.1
|
||||
(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.2.0
|
||||
// Generated by CoffeeScript 2.2.1
|
||||
(function() {
|
||||
// Node.js Implementation
|
||||
var CoffeeScript, ext, fs, helpers, i, len, path, ref, universalCompile, vm,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.2.0
|
||||
// Generated by CoffeeScript 2.2.1
|
||||
(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,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.2.0
|
||||
// Generated by CoffeeScript 2.2.1
|
||||
(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),
|
||||
@@ -2043,7 +2043,7 @@
|
||||
idx = del(o, 'index');
|
||||
idxName = del(o, 'name');
|
||||
namedIndex = idxName && idxName !== idx;
|
||||
varPart = `${idx} = ${this.fromC}`;
|
||||
varPart = known && !namedIndex ? `var ${idx} = ${this.fromC}` : `${idx} = ${this.fromC}`;
|
||||
if (this.toC !== this.toVar) {
|
||||
varPart += `, ${this.toC}`;
|
||||
}
|
||||
@@ -3575,8 +3575,8 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
// Sort 'splatsAndExpans' so we can show error at first disallowed token.
|
||||
objects[splatsAndExpans.sort()[1]].error("multiple splats/expansions are disallowed in an assignment");
|
||||
}
|
||||
isSplat = splats.length;
|
||||
isExpans = expans.length;
|
||||
isSplat = (splats != null ? splats.length : void 0) > 0;
|
||||
isExpans = (expans != null ? expans.length : void 0) > 0;
|
||||
isObject = this.variable.isObject();
|
||||
isArray = this.variable.isArray();
|
||||
vvar = value.compileToFragments(o, LEVEL_LIST);
|
||||
@@ -3648,7 +3648,7 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
};
|
||||
// "Complex" `objects` are processed in a loop.
|
||||
// Examples: [a, b, {c, r...}, d], [a, ..., {b, r...}, c, d]
|
||||
loopObjects = (objs, vvarTxt) => {
|
||||
loopObjects = (objs, vvar, vvarTxt) => {
|
||||
var acc, idx, j, len1, message, objSpreads, results, vval;
|
||||
objSpreads = hasObjSpreads(objs);
|
||||
results = [];
|
||||
@@ -3707,7 +3707,7 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
return results;
|
||||
};
|
||||
// "Simple" `objects` can be split and compiled to arrays, [a, b, c] = arr, [a, b, c...] = arr
|
||||
assignObjects = (objs, vvarTxt) => {
|
||||
assignObjects = (objs, vvar, vvarTxt) => {
|
||||
var vval;
|
||||
vvar = new Value(new Arr(objs, true));
|
||||
vval = vvarTxt instanceof Value ? vvarTxt : new Value(new Literal(vvarTxt));
|
||||
@@ -3716,11 +3716,11 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
subpattern: true
|
||||
}).compileToFragments(o, LEVEL_LIST));
|
||||
};
|
||||
processObjects = function(objs, vvarTxt) {
|
||||
processObjects = function(objs, vvar, vvarTxt) {
|
||||
if (complexObjects(objs)) {
|
||||
return loopObjects(objs, vvarTxt);
|
||||
return loopObjects(objs, vvar, vvarTxt);
|
||||
} else {
|
||||
return assignObjects(objs, vvarTxt);
|
||||
return assignObjects(objs, vvar, vvarTxt);
|
||||
}
|
||||
};
|
||||
// In case there is `Splat` or `Expansion` in `objects`,
|
||||
@@ -3739,7 +3739,7 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
leftObjs = objects.slice(0, expIdx + (isSplat ? 1 : 0));
|
||||
rightObjs = objects.slice(expIdx + 1);
|
||||
if (leftObjs.length !== 0) {
|
||||
processObjects(leftObjs, vvarText);
|
||||
processObjects(leftObjs, vvar, vvarText);
|
||||
}
|
||||
if (rightObjs.length !== 0) {
|
||||
// Slice or splice `objects`.
|
||||
@@ -3756,11 +3756,11 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
refExp = o.scope.freeVariable('ref');
|
||||
assigns.push([this.makeCode(refExp + ' = '), ...restVar.compileToFragments(o, LEVEL_LIST)]);
|
||||
}
|
||||
processObjects(rightObjs, refExp);
|
||||
processObjects(rightObjs, vvar, refExp);
|
||||
}
|
||||
} else {
|
||||
// There is no `Splat` or `Expansion` in `objects`.
|
||||
processObjects(objects, vvarText);
|
||||
processObjects(objects, vvar, vvarText);
|
||||
}
|
||||
if (!(top || this.subpattern)) {
|
||||
assigns.push(vvar);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.2.0
|
||||
// Generated by CoffeeScript 2.2.1
|
||||
(function() {
|
||||
var LONG_FLAG, MULTI_FLAG, OPTIONAL, OptionParser, SHORT_FLAG, buildRule, buildRules, normalizeArguments, repeat,
|
||||
splice = [].splice;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.2.0
|
||||
// Generated by CoffeeScript 2.2.1
|
||||
(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.2.0
|
||||
// Generated by CoffeeScript 2.2.1
|
||||
(function() {
|
||||
var CoffeeScript, addHistory, addMultilineHandler, fs, getCommandId, merge, nodeREPL, path, replDefaults, runInContext, sawSIGINT, transpile, updateSyntaxError, vm;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.2.0
|
||||
// Generated by CoffeeScript 2.2.1
|
||||
(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.2.0
|
||||
// Generated by CoffeeScript 2.2.1
|
||||
(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.2.0
|
||||
// Generated by CoffeeScript 2.2.1
|
||||
(function() {
|
||||
// Source maps allow JavaScript runtimes to match running JavaScript back to
|
||||
// the original source code that corresponds to it. This can be minified
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"compiler"
|
||||
],
|
||||
"author": "Jeremy Ashkenas",
|
||||
"version": "2.2.0",
|
||||
"version": "2.2.1",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
|
||||
@@ -1353,7 +1353,11 @@ exports.Range = class Range extends Base
|
||||
idx = del o, 'index'
|
||||
idxName = del o, 'name'
|
||||
namedIndex = idxName and idxName isnt idx
|
||||
varPart = "#{idx} = #{@fromC}"
|
||||
varPart =
|
||||
if known and not namedIndex
|
||||
"var #{idx} = #{@fromC}"
|
||||
else
|
||||
"#{idx} = #{@fromC}"
|
||||
varPart += ", #{@toC}" if @toC isnt @toVar
|
||||
varPart += ", #{@step}" if @step isnt @stepVar
|
||||
[lt, gt] = ["#{idx} <#{@equals}", "#{idx} >#{@equals}"]
|
||||
@@ -2408,8 +2412,8 @@ exports.Assign = class Assign extends Base
|
||||
# Sort 'splatsAndExpans' so we can show error at first disallowed token.
|
||||
objects[splatsAndExpans.sort()[1]].error "multiple splats/expansions are disallowed in an assignment"
|
||||
|
||||
isSplat = splats.length
|
||||
isExpans = expans.length
|
||||
isSplat = splats?.length > 0
|
||||
isExpans = expans?.length > 0
|
||||
isObject = @variable.isObject()
|
||||
isArray = @variable.isArray()
|
||||
|
||||
@@ -2458,7 +2462,7 @@ exports.Assign = class Assign extends Base
|
||||
|
||||
# "Complex" `objects` are processed in a loop.
|
||||
# Examples: [a, b, {c, r...}, d], [a, ..., {b, r...}, c, d]
|
||||
loopObjects = (objs, vvarTxt) =>
|
||||
loopObjects = (objs, vvar, vvarTxt) =>
|
||||
objSpreads = hasObjSpreads objs
|
||||
for obj, i in objs
|
||||
# `Elision` can be skipped.
|
||||
@@ -2488,16 +2492,16 @@ exports.Assign = class Assign extends Base
|
||||
assigns.push new Assign(vvar, vval, null, param: @param, subpattern: yes).compileToFragments o, LEVEL_LIST
|
||||
|
||||
# "Simple" `objects` can be split and compiled to arrays, [a, b, c] = arr, [a, b, c...] = arr
|
||||
assignObjects = (objs, vvarTxt) =>
|
||||
assignObjects = (objs, vvar, vvarTxt) =>
|
||||
vvar = new Value new Arr(objs, yes)
|
||||
vval = if vvarTxt instanceof Value then vvarTxt else new Value new Literal(vvarTxt)
|
||||
assigns.push new Assign(vvar, vval, null, param: @param, subpattern: yes).compileToFragments o, LEVEL_LIST
|
||||
|
||||
processObjects = (objs, vvarTxt) ->
|
||||
processObjects = (objs, vvar, vvarTxt) ->
|
||||
if complexObjects objs
|
||||
loopObjects objs, vvarTxt
|
||||
loopObjects objs, vvar, vvarTxt
|
||||
else
|
||||
assignObjects objs, vvarTxt
|
||||
assignObjects objs, vvar, vvarTxt
|
||||
|
||||
# In case there is `Splat` or `Expansion` in `objects`,
|
||||
# we can split array in two simple subarrays.
|
||||
@@ -2514,7 +2518,7 @@ exports.Assign = class Assign extends Base
|
||||
expIdx = splatsAndExpans[0]
|
||||
leftObjs = objects.slice 0, expIdx + (if isSplat then 1 else 0)
|
||||
rightObjs = objects.slice expIdx + 1
|
||||
processObjects leftObjs, vvarText if leftObjs.length isnt 0
|
||||
processObjects leftObjs, vvar, vvarText if leftObjs.length isnt 0
|
||||
if rightObjs.length isnt 0
|
||||
# Slice or splice `objects`.
|
||||
refExp = switch
|
||||
@@ -2524,10 +2528,10 @@ exports.Assign = class Assign extends Base
|
||||
restVar = refExp
|
||||
refExp = o.scope.freeVariable 'ref'
|
||||
assigns.push [@makeCode(refExp + ' = '), restVar.compileToFragments(o, LEVEL_LIST)...]
|
||||
processObjects rightObjs, refExp
|
||||
processObjects rightObjs, vvar, refExp
|
||||
else
|
||||
# There is no `Splat` or `Expansion` in `objects`.
|
||||
processObjects objects, vvarText
|
||||
processObjects objects, vvar, vvarText
|
||||
assigns.push vvar unless top or @subpattern
|
||||
fragments = @joinFragmentArrays assigns, ', '
|
||||
if o.level < LEVEL_LIST then fragments else @wrapInParentheses fragments
|
||||
|
||||
@@ -945,3 +945,43 @@ test "#4673: complex destructured object spread variables", ->
|
||||
|
||||
{{g}...} = g: 1
|
||||
eq g, 1
|
||||
|
||||
test "#4878: Compile error when using destructuring with a splat or expansion in an array", ->
|
||||
arr = ['a', 'b', 'c', 'd']
|
||||
|
||||
f1 = (list) ->
|
||||
[first, ..., last] = list
|
||||
|
||||
f2 = (list) ->
|
||||
[first..., last] = list
|
||||
|
||||
f3 = (list) ->
|
||||
([first, ...] = list); first
|
||||
|
||||
f4 = (list) ->
|
||||
([first, ...rest] = list); rest
|
||||
|
||||
arrayEq f1(arr), arr
|
||||
arrayEq f2(arr), arr
|
||||
arrayEq f3(arr), 'a'
|
||||
arrayEq f4(arr), ['b', 'c', 'd']
|
||||
|
||||
foo = (list) ->
|
||||
ret =
|
||||
if list?.length > 0
|
||||
[first, ..., last] = list
|
||||
[first, last]
|
||||
else
|
||||
[]
|
||||
|
||||
arrayEq foo(arr), ['a', 'd']
|
||||
|
||||
bar = (list) ->
|
||||
ret =
|
||||
if list?.length > 0
|
||||
[first, ...rest] = list
|
||||
[first, rest]
|
||||
else
|
||||
[]
|
||||
|
||||
arrayEq bar(arr), ['a', ['b', 'c', 'd']]
|
||||
|
||||
@@ -195,3 +195,10 @@ test "#2047: from, to and step as variables", ->
|
||||
step = 0
|
||||
r = (x for x in [b..a] by step)
|
||||
arrayEq r, []
|
||||
|
||||
test "#4884: Range not declaring var for the 'i'", ->
|
||||
'use strict'
|
||||
[0..21].forEach (idx) ->
|
||||
idx + 1
|
||||
|
||||
eq global.i, undefined
|
||||
|
||||
Reference in New Issue
Block a user