Compare commits

...

8 Commits
2.2.4 ... 2.3.0

Author SHA1 Message Date
Geoffrey Booth
8061ecf0e2 2.3.0 (#5043)
* Move analytics initialization into docs.coffee

* Bump Bootstrap and CodeMirror versions

* Update output

* Merge CodeMirror styles

* Update CodeMirror styles

* Better flexbox layout for docs, including flex auto-sized sidebar and main column

* Minor styling fixes for Edge

* Fix scrollspy for new layout

* Update output

* Clicking on the CoffeeScript logo in the navbar should scroll to top; fix main column width on mobile

* Update output

* 2.3.0 changelog

* Update operators section for **

* Update docs for ES2018 object rest/spread

* Remove references to Node's experimental modules support

* Move the README coffee cup to the right side, so our name isn't cut off on the NPM page; update README and CONTRIBUTING text

* Update dependencies

* Add compatibility note for async generators

* Bump version to 2.3.0 and update output

* Have CI test in Node 10 instead of 9

* Somehow this gets generated slightly differently in Node 10

* Fix #4042: Update broken link
2018-04-28 18:57:15 -07:00
Geoffrey Booth
6df8f5ff17 Remove references to Node's experimental modules support 2018-04-27 10:27:20 -07:00
Geoffrey Booth
776e7e5328 Docs improvements (#5042)
* Move analytics initialization into docs.coffee

* Bump Bootstrap and CodeMirror versions

* Update output

* Merge CodeMirror styles

* Update CodeMirror styles

* Better flexbox layout for docs, including flex auto-sized sidebar and main column

* Minor styling fixes for Edge

* Fix scrollspy for new layout

* Update output

* Clicking on the CoffeeScript logo in the navbar should scroll to top; fix main column width on mobile

* Update output
2018-04-27 10:07:01 -07:00
zdenko
871079b25c Fix #4876: remove polyfill for object rest/spread (#4884)
* object rest/spread

* merge branch 'master' into 'object_rest_spread'

* explore

* Revert "merge branch 'master' into 'object_rest_spread'"

This reverts commit eeeffef55d.

* Revert "explore"

This reverts commit d21cd72aa3.

* split tests

* improvements

* unassignable rest property

* cleanup

* formatting, cleanup

* handle non-final object-destructured splat

* merge with @helixbass's branch
2018-04-23 09:50:42 -07:00
Ruben Bridgewater
be2b24310f Fix: a test relied on faulty behavior (#5028)
`assert.throws` did not test for the error message so far. This
changes it to actually test for the error message.
2018-04-10 09:21:40 -07:00
zdenko
1f9cd4eaf7 Fix #4875: Asynchronous iterators (#4893)
* async iterators

* tests; refactor 'For' grammar rules

* async iterator tests

* formatting
2018-04-08 13:42:54 -07:00
Geoffrey Booth
47c491ffa1 Regular expressions s (dotAll) flag (#4880)
* Support ES2018 regex dotall flag

* Test in Node 9

* Alphabetize regex flags

* Split regex dotall test into its own file, use new feature detection method of loading it

* Update docs to explain compatibility for ES2018 and newer Node features

* Remove unnecessary paragraph
2018-03-30 15:25:41 -07:00
Geoffrey Booth
195a46ab77 Fix #4877: Exponentiation operators (#4881)
* Passthrough exponentiation operator; remove tests that are invalid JavaScript

* Treat **= as a passthrough assignment

* Get tests passing in Node 6

* Improve scoping

* Move exponentiation tests into their own file, now that it's filtered out by Cakefile

* Restore original test
2018-03-30 00:47:40 -07:00
60 changed files with 3149 additions and 3974 deletions

View File

@@ -3,7 +3,7 @@ language: node_js
node_js:
- 6
- 8
- 9
- 10
cache:
directories:

View File

@@ -6,4 +6,9 @@
* Use the same coding style as the rest of the [codebase](https://github.com/jashkenas/coffeescript/tree/master/src). If youre just getting started with CoffeeScript, theres a nice [style guide](https://github.com/polarmobile/coffeescript-style-guide).
* In your pull request, do not add documentation to `index.html` or re-build the minified `coffeescript.js` file. Well do those things before cutting a new release. You _should,_ however, commit the updated compiled JavaScript files in `lib`.
* In your pull request, do not add documentation to `index.html` or re-build the minified `coffeescript.js` file. Well do those things before cutting a new release. You _should,_ however, commit the updated compiled JavaScript files in `lib`.
* To get started, read the guides in the wiki:
* [Hacking on the CoffeeScript Compiler](https://github.com/jashkenas/coffeescript/wiki/%5BHowTo%5D-Hacking-on-the-CoffeeScript-Compiler)
* [How parsing works](https://github.com/jashkenas/coffeescript/wiki/%5BHowTo%5D-How-parsing-works)
* [Update the docs](https://github.com/jashkenas/coffeescript/wiki/%5BHowTo%5D-Update-the-docs)

View File

@@ -452,6 +452,8 @@ runTests = (CoffeeScript) ->
skipUnless 'async () => {}', ['async.coffee', 'async_iterators.coffee']
skipUnless 'async function* generator() { yield 42; }', ['async_iterators.coffee']
skipUnless 'var a = 2 ** 2; a **= 3', ['exponentiation.coffee']
skipUnless 'var {...a} = {}', ['object_rest_spread.coffee']
skipUnless '/foo.bar/s.test("foo\tbar")', ['regex_dotall.coffee']
files = fs.readdirSync('test').filter (filename) ->
filename not in testFilesToSkip

View File

@@ -1,27 +1,27 @@
@@@@@@@ @@@@ @@@@@
{ @@@@@@@@@@ @@@ @@@
} } { @@@@ @@ @@@ @@@
{ { } } @@@@ @@@@@@@ @@@ @@@ @@@@@@ @@@@@@
} }{ { @@@@ @@@ @@ @@@@@ @@@@@@ @@@ @@ @@@@ @@
{ }{ } } @@@@ @@@@ @@ @@@ @@@ @@@ @@@ @@@ @@@
{ }{ }{ { } @@@@ @@@@ @@ @@@ @@@ @@@@@@@@ @@@@@@@@
{ { } { } { } } @@@@@ @@@@ @@ @@@ @@@ @@@ @@@
{ } { } { } @@@@@@@@@@ @@@@@@@@ @@@ @@@ @@@@@@@@ @@@@@@@@
@@@@@@ { } { } @@@@@@@ @@@@@ @@@ @@@ @@@@@ @@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@ @@@
@@ @@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@ @@@ @@@
@@ @@@@@@@@@@@@@@@@@@@@@@@@ @@@@ @@ @@@ @@@@
@@@ @@@@@@@@@@@@@@@@@@@@@ @@@@ @@@ @@ @@@@
@@@ @@@@@@@@@@@@@@@@@@ @@@@@ @@@@@ @@ @@ @@@ @@@@@@@ @@@@@
@@@ @@@@@@@@@@@@@@@@ @@@@@ @@@ @@@ @@@@@@@@ @@@@ @@@@ @@@@@@@
@@@@@@@@@@@@@@ @@@@@ @@@ @@@@ @@@@ @@@ @@@ @@@
@@@@@ @@@@ @@@@ @@@@ @@@@ @@@@ @@@@ @@@@
@@@ @@@@ @@@ @@@@ @@@@ @@@ @@@@ @@@@
@@@ @@@@ @@@@ @@@@ @@@@ @@@@ @@@@ @@@@
@@@@@@@@@ @@@@@@ @@@@ @@@@ @@@@@@@@@ @@@@
@@@ @@@@
@@@
@@@
@@@@@@@ @@@@ @@@@@
@@@@@@@@@@ @@@ @@@ {
@@@@ @@ @@@ @@@ } } {
@@@@ @@@@@@@ @@@ @@@ @@@@@@ @@@@@@ { { } }
@@@@ @@@ @@ @@@@@ @@@@@@ @@@ @@ @@@@ @@ } }{ {
@@@@ @@@@ @@ @@@ @@@ @@@ @@@ @@@ @@@ { }{ } }
@@@@ @@@@ @@ @@@ @@@ @@@@@@@@ @@@@@@@@ { }{ }{ { }
@@@@@ @@@@ @@ @@@ @@@ @@@ @@@ { { } { } { } }
@@@@@@@@@@ @@@@@@@@ @@@ @@@ @@@@@@@@ @@@@@@@@ { } { } { }
@@@@@ @@@ @@@ @@@@@ @@@@@ @@@@@@ { } { } @@@@@@@
@@@ @@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@ @@@ @@@ @@ @@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@ @@ @@@ @@@@ @@ @@@@@@@@@@@@@@@@@@@@@@@@
@@@@ @@@ @@ @@@@ @@@ @@@@@@@@@@@@@@@@@@@@@
@@@@@ @@@@@ @@ @@ @@@ @@@@@@@ @@@@@ @@@ @@@@@@@@@@@@@@@@@@
@@@@@ @@@ @@@ @@@@@@@@ @@@@ @@@@ @@@@@@@ @@@ @@@@@@@@@@@@@@@@
@@@@@ @@@ @@@@ @@@@ @@@ @@@ @@@ @@@@@@@@@@@@@@
@@@@@ @@@@ @@@@ @@@@ @@@@ @@@@ @@@@ @@@@
@@@ @@@@ @@@ @@@@ @@@@ @@@ @@@@ @@@@
@@@ @@@@ @@@@ @@@@ @@@@ @@@@ @@@@ @@@@
@@@@@@@@@ @@@@@@ @@@@ @@@@ @@@@@@@@@ @@@@
@@@ @@@@
@@@
@@@
CoffeeScript is a little language that compiles into JavaScript.
@@ -30,11 +30,13 @@ CoffeeScript is a little language that compiles into JavaScript.
Once you have Node.js installed:
```shell
# Install locally for a project:
npm install --save-dev coffeescript
# Install globally to execute .coffee files anywhere:
npm install --global coffeescript
```
Leave off the `--global` if you dont wish to install globally.
## Getting Started
Execute a script:

View File

@@ -2,7 +2,7 @@ environment:
matrix:
- nodejs_version: '6'
- nodejs_version: '8'
- nodejs_version: '9'
- nodejs_version: '10'
- nodejs_version: '' # Installs latest.
install:

View File

@@ -580,11 +580,11 @@ the ordinary <strong>Assign</strong> is that these allow numbers and strings as
o <span class="hljs-string">'Identifier'</span>
o <span class="hljs-string">'Property'</span>
o <span class="hljs-string">'ThisProperty'</span>
o <span class="hljs-string">'[ Expression ]'</span>, <span class="hljs-function">-&gt;</span> <span class="hljs-keyword">new</span> Value <span class="hljs-keyword">new</span> ComputedPropertyName $<span class="hljs-number">2</span>
]
ObjAssignable: [
o <span class="hljs-string">'SimpleObjAssignable'</span>
o <span class="hljs-string">'[ Expression ]'</span>, <span class="hljs-function">-&gt;</span> <span class="hljs-keyword">new</span> Value <span class="hljs-keyword">new</span> ComputedPropertyName $<span class="hljs-number">2</span>
o <span class="hljs-string">'AlphaNumeric'</span>
]</pre></div></div>
@@ -1492,26 +1492,31 @@ or postfix, with a single expression.</p>
</div>
<div class="content"><div class='highlight'><pre> For: [
o <span class="hljs-string">'Statement ForBody'</span>, <span class="hljs-function">-&gt;</span> <span class="hljs-keyword">new</span> For $<span class="hljs-number">1</span>, $<span class="hljs-number">2</span>
o <span class="hljs-string">'Expression ForBody'</span>, <span class="hljs-function">-&gt;</span> <span class="hljs-keyword">new</span> For $<span class="hljs-number">1</span>, $<span class="hljs-number">2</span>
o <span class="hljs-string">'ForBody Block'</span>, <span class="hljs-function">-&gt;</span> <span class="hljs-keyword">new</span> For $<span class="hljs-number">2</span>, $<span class="hljs-number">1</span>
o <span class="hljs-string">'ForLineBody Block'</span>, <span class="hljs-function">-&gt;</span> <span class="hljs-keyword">new</span> For $<span class="hljs-number">2</span>, $<span class="hljs-number">1</span>
o <span class="hljs-string">'Statement ForBody'</span>, <span class="hljs-function">-&gt;</span> $<span class="hljs-number">2.</span>addBody $<span class="hljs-number">1</span>
o <span class="hljs-string">'Expression ForBody'</span>, <span class="hljs-function">-&gt;</span> $<span class="hljs-number">2.</span>addBody $<span class="hljs-number">1</span>
o <span class="hljs-string">'ForBody Block'</span>, <span class="hljs-function">-&gt;</span> $<span class="hljs-number">1.</span>addBody $<span class="hljs-number">2</span>
o <span class="hljs-string">'ForLineBody Block'</span>, <span class="hljs-function">-&gt;</span> $<span class="hljs-number">1.</span>addBody $<span class="hljs-number">2</span>
]
ForBody: [
o <span class="hljs-string">'FOR Range'</span>, <span class="hljs-function">-&gt;</span> source: (LOC(<span class="hljs-number">2</span>) <span class="hljs-keyword">new</span> Value($<span class="hljs-number">2</span>))
o <span class="hljs-string">'FOR Range BY Expression'</span>, <span class="hljs-function">-&gt;</span> source: (LOC(<span class="hljs-number">2</span>) <span class="hljs-keyword">new</span> Value($<span class="hljs-number">2</span>)), step: $<span class="hljs-number">4</span>
o <span class="hljs-string">'ForStart ForSource'</span>, <span class="hljs-function">-&gt;</span> $<span class="hljs-number">2.</span>own = $<span class="hljs-number">1.</span>own; $<span class="hljs-number">2.</span>ownTag = $<span class="hljs-number">1.</span>ownTag; $<span class="hljs-number">2.</span>name = $<span class="hljs-number">1</span>[<span class="hljs-number">0</span>]; $<span class="hljs-number">2.</span>index = $<span class="hljs-number">1</span>[<span class="hljs-number">1</span>]; $<span class="hljs-number">2</span>
o <span class="hljs-string">'FOR Range'</span>, <span class="hljs-function">-&gt;</span> <span class="hljs-keyword">new</span> For [], source: (LOC(<span class="hljs-number">2</span>) <span class="hljs-keyword">new</span> Value($<span class="hljs-number">2</span>))
o <span class="hljs-string">'FOR Range BY Expression'</span>, <span class="hljs-function">-&gt;</span> <span class="hljs-keyword">new</span> For [], source: (LOC(<span class="hljs-number">2</span>) <span class="hljs-keyword">new</span> Value($<span class="hljs-number">2</span>)), step: $<span class="hljs-number">4</span>
o <span class="hljs-string">'ForStart ForSource'</span>, <span class="hljs-function">-&gt;</span> $<span class="hljs-number">1.</span>addSource $<span class="hljs-number">2</span>
]
ForLineBody: [
o <span class="hljs-string">'FOR Range BY ExpressionLine'</span>, <span class="hljs-function">-&gt;</span> source: (LOC(<span class="hljs-number">2</span>) <span class="hljs-keyword">new</span> Value($<span class="hljs-number">2</span>)), step: $<span class="hljs-number">4</span>
o <span class="hljs-string">'ForStart ForLineSource'</span>, <span class="hljs-function">-&gt;</span> $<span class="hljs-number">2.</span>own = $<span class="hljs-number">1.</span>own; $<span class="hljs-number">2.</span>ownTag = $<span class="hljs-number">1.</span>ownTag; $<span class="hljs-number">2.</span>name = $<span class="hljs-number">1</span>[<span class="hljs-number">0</span>]; $<span class="hljs-number">2.</span>index = $<span class="hljs-number">1</span>[<span class="hljs-number">1</span>]; $<span class="hljs-number">2</span>
o <span class="hljs-string">'FOR Range BY ExpressionLine'</span>, <span class="hljs-function">-&gt;</span> <span class="hljs-keyword">new</span> For [], source: (LOC(<span class="hljs-number">2</span>) <span class="hljs-keyword">new</span> Value($<span class="hljs-number">2</span>)), step: $<span class="hljs-number">4</span>
o <span class="hljs-string">'ForStart ForLineSource'</span>, <span class="hljs-function">-&gt;</span> $<span class="hljs-number">1.</span>addSource $<span class="hljs-number">2</span>
]
ForStart: [
o <span class="hljs-string">'FOR ForVariables'</span>, <span class="hljs-function">-&gt;</span> $<span class="hljs-number">2</span>
o <span class="hljs-string">'FOR OWN ForVariables'</span>, <span class="hljs-function">-&gt;</span> $<span class="hljs-number">3.</span>own = <span class="hljs-literal">yes</span>; $<span class="hljs-number">3.</span>ownTag = (LOC(<span class="hljs-number">2</span>) <span class="hljs-keyword">new</span> Literal($<span class="hljs-number">2</span>)); $<span class="hljs-number">3</span>
o <span class="hljs-string">'FOR ForVariables'</span>, <span class="hljs-function">-&gt;</span> <span class="hljs-keyword">new</span> For [], name: $<span class="hljs-number">2</span>[<span class="hljs-number">0</span>], index: $<span class="hljs-number">2</span>[<span class="hljs-number">1</span>]
o <span class="hljs-string">'FOR AWAIT ForVariables'</span>, <span class="hljs-function">-&gt;</span>
[name, index] = $<span class="hljs-number">3</span>
<span class="hljs-keyword">new</span> For [], {name, index, await: <span class="hljs-literal">yes</span>, awaitTag: (LOC(<span class="hljs-number">2</span>) <span class="hljs-keyword">new</span> Literal($<span class="hljs-number">2</span>))}
o <span class="hljs-string">'FOR OWN ForVariables'</span>, <span class="hljs-function">-&gt;</span>
[name, index] = $<span class="hljs-number">3</span>
<span class="hljs-keyword">new</span> For [], {name, index, own: <span class="hljs-literal">yes</span>, ownTag: (LOC(<span class="hljs-number">2</span>) <span class="hljs-keyword">new</span> Literal($<span class="hljs-number">2</span>))}
]</pre></div></div>
</li>

View File

@@ -2579,7 +2579,7 @@ HEREDOC_INDENT = <span class="hljs-regexp">/\n+([^\n\S]*)(?=\S)/g</span></pr
///</span>
REGEX_FLAGS = <span class="hljs-regexp">/^\w*/</span>
VALID_FLAGS = <span class="hljs-regexp">/^(?!.*(.).*\1)[imguy]*$/</span>
VALID_FLAGS = <span class="hljs-regexp">/^(?!.*(.).*\1)[gimsuy]*$/</span>
HEREGEX = <span class="hljs-regexp">/// ^
(?:

File diff suppressed because it is too large Load Diff

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 it is too large Load Diff

View File

@@ -1,5 +1,14 @@
## Changelog
```
releaseHeader('2018-04-29', '2.3.0', '2.2.4')
```
* This release adds support for all the new features and syntaxes in ES2018 that werent already possible in CoffeeScript. For all of the below features, make sure that you [transpile](#transpilation) unless you know that your target runtime(s) support each feature.
* Asynchronous iterators are now supported. You can now `yield` an `await` call, e.g. `do -> until file.EOF then yield await file.readLine()`.
* Object splats/destructuring, a.k.a. object rest/spread syntax, has been standardized as part of ES2018 and therefore this release removes the polyfill that had previously been supporting this syntax. Code like `{a, b, rest...} = obj` now outputs more or less just like it appears, rather than being converted into an `Object.assign` call. Note that there are [some subtle differences](https://developers.google.com/web/updates/2017/06/object-rest-spread) between the `Object.assign` polyfill and the native implementation.
* The exponentiation operator, `**`, and exponentiation assignment operator `**=` are new to JavaScript in ES2018. Now code like `a ** 3` is output as it appears, rather than being converted into `Math.pow(a, 3)` as it was before.
* The `s` (dotAll) flag is now supported in regular expressions.
```
releaseHeader('2018-03-29', '2.2.4', '2.2.3')
```

View File

@@ -1,5 +1,10 @@
### Compatibility
With the exception of [modules](#modules) (`import` and `export` statements) and [JSX](#jsx), all the modern JavaScript features that CoffeeScript supports can run natively in Node 7.6+, meaning that Node can run CoffeeScripts output without any further processing required. You can [run the tests in your browser](test.html) to see if your browser can do the same. For older browsers or older versions of Node, however, [transpilation](#transpilation) is required.
Most modern JavaScript features that CoffeeScript supports can run natively in Node 7.6+, meaning that Node can run CoffeeScripts output without any further processing required. Here are some notable exceptions:
Support for modern JavaScript syntax is important to ensure compatibility with frameworks that assume modern features. Now that CoffeeScript compiles classes to the `class` keyword, its possible to `extend` a JavaScript class; that wasnt possible in CoffeeScript 1. Parity in how language features work is also important on its own; CoffeeScript “is just JavaScript,” and so things like [function parameter default values](#breaking-changes-default-values) should behave the same in CoffeeScript as in JavaScript. Some such features behave slightly differently in JavaScript than they did in CoffeeScript 1; in such cases we are conforming with the JavaScript spec, and weve documented the differences as [breaking changes](#breaking-changes).
* [Modules](#modules) and [JSX](#jsx) always require transpilation.
* [Splats, a.k.a. object rest/spread syntax, for objects](http://coffeescript.org/#splats) are supported by Node 8.6+.
* The [regular expression `s` (dotall) flag](https://github.com/tc39/proposal-regexp-dotall-flag) is supported by Node 9+.
* [Async generator functions](https://github.com/tc39/proposal-async-iteration) are supported by Node 10+.
This list may be incomplete, and excludes versions of Node that support newer features behind flags; please refer to [node.green](http://node.green/) for full details. You can [run the tests in your browser](test.html) to see what your browser supports. It is your responsibility to ensure that your runtime supports the modern features you use; or that you [transpile](#transpilation) your code. When in doubt, transpile.

View File

@@ -1,6 +1,6 @@
## Bound (Fat Arrow) Functions
In JavaScript, the `this` keyword is dynamically scoped to mean the object that the current function is attached to. If you pass a function as a callback or attach it to a different object, the original value of `this` will be lost. If youre not familiar with this behavior, [this Digital Web article](http://64.13.255.16/articles/scope_in_javascript/) gives a good overview of the quirks.
In JavaScript, the `this` keyword is dynamically scoped to mean the object that the current function is attached to. If you pass a function as a callback or attach it to a different object, the original value of `this` will be lost. If youre not familiar with this behavior, [this Digital Web article](https://web.archive.org/web/20150316122013/http://www.digital-web.com/articles/scope_in_javascript) gives a good overview of the quirks.
The fat arrow `=>` can be used to both define a function, and to bind it to the current value of `this`, right on the spot. This is helpful when using callback-based libraries like Prototype or jQuery, for creating iterator functions to pass to `each`, or event-handler functions to use with `on`. Functions created with the fat arrow are able to access properties of the `this` where theyre defined.

View File

@@ -8,6 +8,6 @@ codeFor('modules')
<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 attach another transpiler, such as [Traceur Compiler](https://github.com/google/traceur-compiler), [Babel](http://babeljs.io/) or [Rollup](https://github.com/rollup/rollup), to convert 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.
Also note that any file with an `import` or `export` statement will be output without a [top-level function safety wrapper](#lexical-scope); in other words, importing or exporting modules will automatically trigger [bare](#usage) mode for that file. This is because per the ES2015 spec, `import` or `export` statements must occur at the topmost scope.

View File

@@ -39,7 +39,7 @@ All together now:
| `a in b` | `[].indexOf.call(b, a) >= 0` |
| `a of b` | `a in b` |
| `for a from b` | `for (a of b)` |
| `a ** b` | `Math.pow(a, b)` |
| `a ** b` | `a ** b` |
| `a // b` | `Math.floor(a / b)` |
| `a %% b` | `(a % b + b) % b` |

View File

@@ -22,4 +22,4 @@ codeFor('array_spread', 'all')
codeFor('object_spread', 'JSON.stringify(currentUser)')
```
In ECMAScript this is called [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator), and has been supported for arrays since ES2015 but is [coming soon for objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator#Spread_in_object_literals). Until object spread syntax is officially supported, the CoffeeScript compiler outputs the same polyfill as [Babels rest spread transform](https://babeljs.io/docs/plugins/transform-object-rest-spread/); but once it is supported, we will revise the compilers output. Note that there are [very subtle differences](https://developers.google.com/web/updates/2017/06/object-rest-spread) between the polyfill and the current proposal.
In ECMAScript this is called [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator), and has been supported for arrays since ES2015 and objects since ES2018.

View File

@@ -3,11 +3,11 @@
<%= include('try.html') %>
<div class="container-fluid" id="top">
<div class="row flex-nowrap">
<nav class="sidebar col-lg-3 bg-ribbed-light">
<div class="row flex-nowrap main-row">
<nav class="sidebar bg-ribbed-light">
<%= include('sidebar.html') %>
</nav>
<main class="main col-lg-9 ml-auto">
<main class="main">
<header class="d-none d-lg-block">
<p class="title-logo">
<%= include('logo.svg') %>

View File

@@ -1,7 +1,15 @@
/* Adapted from https://github.com/FarhadG/code-mirror-themes/blob/master/themes/twilight.css */
/* Adapted from https://github.com/FarhadG/code-mirror-themes/blob/master/themes/twilight.css and https://github.com/codemirror/CodeMirror/blob/master/theme/twilight.css */
/* CodeMirror general styling */
.CodeMirror,
.placeholder-code {
/* https://codemirror.net/demo/resize.html */
height: auto;
background: transparent;
font-family: 'Roboto Mono';
font-weight: 400;
line-height: 1.25;
letter-spacing: 0.3px;
color: #f8f8f8;
/* Prevent mobile Safari from zooming in on our code editors; the code is 16px naturally, but somehow being explicit about it prevents the zooming */
@@ -10,7 +18,7 @@
@media (min-width: 768px) {
.CodeMirror,
.placeholder-code {
font-size: 90%; /* Matching Bootstraps font size for code, which calculates to 14.4px */
font-size: 87.5%; /* Matching Bootstraps font size for code, which calculates to 14.4px */
}
}
.CodeMirror-lines {
@@ -21,6 +29,13 @@
margin-bottom: 1.37em;
white-space: pre-wrap;
}
.CodeMirror pre,
pre.placeholder-code {
line-height: 1.4em;
}
.CodeMirror-code:focus {
outline: none;
}
div.CodeMirror-cursor {
border-left: 3px solid #f8f8f8;
}
@@ -30,27 +45,18 @@ div.CodeMirror-cursor {
.CodeMirror-selected {
background: #ddf0ff33;
}
.cm-comment,
.placeholder-code .comment {
font-style: italic;
color: #5f5a60;
}
/* Syntax highlighting */
.cm-keyword,
.placeholder-code .keyword {
color: #cda869;
}
.cm-string,
.placeholder-code .string {
color: #8f9d6a;
}
.cm-property,
.placeholder-code .attribute {
color: #dad085;
}
.cm-atom {
color: #dad085;
}
.cm-number,
.cm-meta,
.placeholder-code .number,
.placeholder-code .built_in,
.placeholder-code .builtin-name,
@@ -61,6 +67,18 @@ div.CodeMirror-cursor {
.placeholder-code .link {
color: #dad085;
}
.cm-def {
color: #f8f8f8;
}
span.cm-variable-2,
span.cm-tag {
color: #f8f8f8;
}
span.cm-variable-3,
span.cm-def,
span.cm-type {
color: #f8f8f8;
}
.cm-operator,
.placeholder-code .punctuation,
.placeholder-code .symbol,
@@ -69,9 +87,50 @@ div.CodeMirror-cursor {
.placeholder-code .operator {
color: #cda869;
}
.cm-comment,
.placeholder-code .comment {
font-style: italic;
color: #5f5a60;
}
.cm-string,
.cm-string-2,
.placeholder-code .string {
color: #8f9d6a;
}
.cm-property,
.placeholder-code .attribute {
color: #dad085;
}
.cm-builtin {
color: #cda869;
}
.cm-tag {
color: #997643;
}
.cm-attribute {
color: #d6bb6d;
}
.cm-header {
color: #FF6400;
}
.cm-hr {
color: #AEAEAE;
}
.cm-link {
color: #ad9361;
font-style: italic;
text-decoration: none;
}
.cm-error {
border-bottom: 1px solid rgba(142, 22, 22, 0.67);
}
/* Uneditable code blocks are inverted, so use darker versions of the above */
.uneditable-code-block code {
padding: 0;
}
.uneditable-code-block .comment {
font-style: italic;
color: #837B85;

View File

@@ -1,6 +1,18 @@
unless window.location.origin # Polyfill `location.origin` for IE < 11
window.location.origin = "#{window.location.protocol}//#{window.location.hostname}"
# Initialize Google Analytics
window.GA_TRACKING_ID = 'UA-106156830-1'
window.dataLayer ?= []
window.gtag = ->
window.dataLayer.push arguments
return
window.gtag 'js', new Date()
window.gtag 'config', window.GA_TRACKING_ID
# Initialize the CoffeeScript docs interactions
$(document).ready ->
# Mobile navigation
toggleSidebar = ->
@@ -21,14 +33,14 @@ $(document).ready ->
# Initialize Scrollspy for sidebar navigation; https://getbootstrap.com/docs/4.0/components/scrollspy/
# See also http://www.codingeverything.com/2014/02/BootstrapDocsSideBar.html and http://jsfiddle.net/KyleMit/v6zhz/
$('body').scrollspy
$('.main').scrollspy
target: '#contents'
offset: Math.round $('main').css('padding-top').replace('px', '')
initializeScrollspyFromHash = (hash) ->
$("#contents a.active[href!='#{hash}']").removeClass 'show'
$(window).on 'activate.bs.scrollspy', (event, target) -> # Why `window`? https://github.com/twbs/bootstrap/issues/20086
$('.main').on 'activate.bs.scrollspy', (event, target) ->
# We only want one active link in the nav
$("#contents a.active[href!='#{target.relatedTarget}']").removeClass 'show'
$target = $("#contents a[href='#{target.relatedTarget}']")
@@ -165,6 +177,11 @@ $(document).ready ->
toggleTry yes
$('[data-close="try"]').click closeTry
$('[data-action="scroll-to-top"]').click (event) ->
return if $('#try').hasClass('show')
$('.main')[0].scrollTop = 0
setTimeout clearHash, 10
clearHash = ->
window.history.replaceState {}, document.title, window.location.pathname

View File

@@ -79,14 +79,18 @@ button:focus, .navbar-dark .navbar-toggler:focus {
}
/*
* Layout; based on https://codepen.io/Sphinxxxx/pen/WjwbEO
*/
.main-row {
height: calc(100vh - 3.5rem);
}
/*
* Sidebar
*/
.sidebar {
position: fixed;
top: 3.5em;
height: calc(100% - 3.5rem);
/* Scrollable contents if viewport is shorter than content */
overflow-y: auto;
overflow-x: hidden;
@@ -102,6 +106,9 @@ button:focus, .navbar-dark .navbar-toggler:focus {
}
@media screen and (max-width: 991px) {
.sidebar {
position: fixed;
top: 3.5em;
height: calc(100% - 3.5rem);
left: -100%;
transition: 0.25s left ease-in-out;
}
@@ -109,6 +116,11 @@ button:focus, .navbar-dark .navbar-toggler:focus {
left: 0;
}
}
@media (min-width: 992px) {
.sidebar {
flex: 0 0 auto;
}
}
.contents {
padding: 0.5em 0 0.5em 0.5em;
@@ -139,10 +151,13 @@ button:focus, .navbar-dark .navbar-toggler:focus {
*/
.main {
max-width: 100%;
padding: 1.3em;
}
@media (min-width: 992px) {
.main {
flex: 1 1 auto;
overflow: auto;
padding-right: 2em;
padding-left: 2em;
}
@@ -221,12 +236,6 @@ h3, h4, h2 time {
font-weight: 400;
}
.main section {
/* Offset the anchor so that clicking on the sidebar links dont hide the heading under the header bar */
padding-top: 2.3rem;
margin-top: -2.3rem;
}
@media (min-width: 1200px) {
.main > header, .main section > h2, .main section > h3, .main section > h4, .main section > p, .main section > blockquote, .main section > ul, .main section > table {
max-width: 80%;
@@ -246,7 +255,7 @@ code {
/*
* Code examples
* Chrome around code examples; see code.css for the styling of the code blocks themselves
*/
textarea {
@@ -281,31 +290,7 @@ textarea {
.play-button {
height: 1em;
}
.CodeMirror pre, pre.placeholder-code {
line-height: 1.4em;
}
.CodeMirror,
.placeholder-code {
/* https://codemirror.net/demo/resize.html */
height: auto;
background: transparent;
font-family: 'Roboto Mono';
font-weight: 400;
line-height: 1.25;
font-size: 0.9em;
}
@media (min-width: 768px) {
.CodeMirror,
.placeholder-code {
font-size: 1em;
}
}
.CodeMirror-code:focus {
outline: none;
width: 1em;
}
.javascript-output-column .CodeMirror-cursor {
@@ -324,6 +309,8 @@ textarea {
right: 0;
opacity: 0;
transition: opacity 0.15s ease-in-out;
z-index: -1001;
background-color: #2f2625;
}
.try-coffeescript.show {
opacity: 1;

View File

@@ -2,5 +2,5 @@
<title>
CoffeeScript Logo
</title>
<path d="M106 228.6c.5 2.3-.9 4.4-5 6.5-5.5-3.1-16.9-4.4-26.7-3.5-10.4.9-19.4 4.2-17.9 11.3 1.5 7.1 11.7 11 29.5 9.5 43.6-3.8 43.4-33.3 107.4-39 49.8-4.4 77.8 11 81.8 29.7 3.1 14.7-9.1 28.6-45.2 31.8-32 2.8-50.7-5.6-52.6-14.6-1-4.5 1.8-11.3 17.2-13.1 1.5 7 10.6 14.4 31.1 12.6 14.8-1.3 27.6-6.6 25.9-14.9-1.8-8.6-17.7-13.7-42.6-11.5-50.7 4.5-63.2 32.5-106.8 36.3-30.8 2.7-55.9-8.5-59.4-25.1-1.3-6.1-1.4-21 31.2-23.9 17.1-1.5 30.7 1.5 32.1 7.9zM-56.4 402.5c-14.3 18-20.4 38.8-19.2 59.2 1.2 20.4 11.4 37.1 26.9 50.2C-32 525-14 528.6 6.4 525c7.8-1.2 16.7-5.3 24.5-7.8-16.7 0-31-5.3-44.9-16.7-15.5-11.4-25.7-26.9-28.2-46.1-3.7-18 0-34.7 10.2-49 11.4-14.3 25.7-22 44.9-24.5 19.2-1.2 35.9 3.7 52.6 15.5-3.7-5.3-9-9-14.3-14.3-16.7-11.4-34.7-16.7-56.7-11.4-19.9 3.6-36.7 13.8-50.9 31.8zm223.6-96.3c-53.9 0-101.6-5.3-136.3-13.1-37.1-9-56.7-19.2-56.7-32.2 0-5.3 2.4-10.2 10.2-15.5-23.3 9-35.9 16.7-35.9 28.2 1.2 13.1 22 25.7 64.5 35.9 40 10.2 91.4 15.5 153 15.5 62.8 0 113-5.3 153-15.5 42.4-10.2 62.8-23.3 62.8-35.9 0-9-9-18-25.7-24.5 3.7 2.4 6.5 6.5 6.5 11.4 0 13.1-19.2 23.3-57.9 32.2-36 8.2-82.1 13.5-137.5 13.5zm153 35.9c-40 9-91.4 15.5-153 15.5-62.8 0-114.2-6.5-154.2-15.5-35.9-9-55.1-19.2-61.6-29.4 6.5 44.9 22 87.3 42.4 124.8 15.5 23.3 31 43.7 46.1 65.7 6.5 13.1 11.4 25.7 14.3 38.8 10.2 14.3 24.5 23.3 42.4 28.2 22 7.8 44.9 11.4 68.1 10.2h2.4c23.3 1.2 47.7-2.4 70.6-10.2 16.7-5.3 31-14.3 41.2-28.2h1.2c2.4-13.1 6.5-25.7 13.1-38.8 15.5-22 31-42.4 46.1-65.7 20.4-37.1 34.7-79.6 42.4-124.8-7.7 11.4-26.9 21.6-61.5 29.4z"/>
<path d="M106 228.6c.5 2.3-.9 4.4-5 6.5-5.5-3.1-16.9-4.4-26.7-3.5-10.4.9-19.4 4.2-17.9 11.3 1.5 7.1 11.7 11 29.5 9.5 43.6-3.8 43.4-33.3 107.4-39 49.8-4.4 77.8 11 81.8 29.7 3.1 14.7-9.1 28.6-45.2 31.8-32 2.8-50.7-5.6-52.6-14.6-1-4.5 1.8-11.3 17.2-13.1 1.5 7 10.6 14.4 31.1 12.6 14.8-1.3 27.6-6.6 25.9-14.9-1.8-8.6-17.7-13.7-42.6-11.5-50.7 4.5-63.2 32.5-106.8 36.3-30.8 2.7-55.9-8.5-59.4-25.1-1.3-6.1-1.4-21 31.2-23.9 17.1-1.5 30.7 1.5 32.1 7.9zM-56.4 402.5c-14.3 18-20.4 38.8-19.2 59.2 1.2 20.4 11.4 37.1 26.9 50.2C-32 525-14 528.6 6.4 525c7.8-1.2 16.7-5.3 24.5-7.8-16.7 0-31-5.3-44.9-16.7-15.5-11.4-25.7-26.9-28.2-46.1-3.7-18 0-34.7 10.2-49 11.4-14.3 25.7-22 44.9-24.5 19.2-1.2 35.9 3.7 52.6 15.5-3.7-5.3-9-9-14.3-14.3-16.7-11.4-34.7-16.7-56.7-11.4-19.9 3.6-36.7 13.8-50.9 31.8zm223.6-96.3c-53.9 0-101.6-5.3-136.3-13.1-37.1-9-56.7-19.2-56.7-32.2 0-5.3 2.4-10.2 10.2-15.5-23.3 9-35.9 16.7-35.9 28.2 1.2 13.1 22 25.7 64.5 35.9 40 10.2 91.4 15.5 153 15.5 62.8 0 113-5.3 153-15.5 42.4-10.2 62.8-23.3 62.8-35.9 0-9-9-18-25.7-24.5 3.7 2.4 6.5 6.5 6.5 11.4 0 13.1-19.2 23.3-57.9 32.2-36 8.2-82.1 13.5-137.5 13.5zm153 35.9c-40 9-91.4 15.5-153 15.5-62.8 0-114.2-6.5-154.2-15.5-35.9-9-55.1-19.2-61.6-29.4 6.5 44.9 22 87.3 42.4 124.8 15.5 23.3 31 43.7 46.1 65.7 6.5 13.1 11.4 25.7 14.3 38.8 10.2 14.3 24.5 23.3 42.4 28.2 22 7.8 44.9 11.4 68.1 10.2h2.4c23.3 1.2 47.7-2.4 70.6-10.2 16.7-5.3 31-14.3 41.2-28.2h1.2c2.4-13.1 6.5-25.7 13.1-38.8 15.5-22 31-42.4 46.1-65.7 20.4-37.1 34.7-79.6 42.4-124.8-7.7 11.4-26.9 21.6-61.5 29.4z"></path>
</svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -2,5 +2,5 @@
<title>
CoffeeScript Logo
</title>
<path d="M21.7 351.1c.1.6-.2 1.1-1.2 1.6-1.3-.7-4.1-1.1-6.4-.9-2.5.2-4.6 1-4.3 2.7.4 1.7 2.8 2.7 7.1 2.3 10.5-.9 10.4-8 25.8-9.4 12-1.1 18.7 2.6 19.6 7.1.7 3.5-2.2 6.9-10.9 7.6-7.7.7-12.2-1.4-12.6-3.5-.2-1.1.4-2.7 4.1-3.1.4 1.7 2.5 3.5 7.5 3 3.6-.3 6.6-1.6 6.2-3.6-.4-2.1-4.2-3.3-10.2-2.8-12.2 1.1-15.2 7.8-25.6 8.7-7.4.7-13.4-2-14.2-6-.3-1.5-.3-5 7.5-5.7 4-.3 7.2.4 7.6 2zm-39 41.8c-3.4 4.3-4.9 9.3-4.6 14.2.3 4.9 2.7 8.9 6.5 12 4 3.1 8.3 4 13.2 3.1 1.9-.3 4-1.3 5.9-1.9-4 0-7.4-1.3-10.8-4-3.7-2.7-6.2-6.5-6.8-11.1-.9-4.3 0-8.3 2.4-11.8 2.7-3.4 6.2-5.3 10.8-5.9 4.6-.3 8.6.9 12.6 3.7-.9-1.3-2.2-2.2-3.4-3.4-4-2.7-8.3-4-13.6-2.7-4.8 1-8.8 3.5-12.2 7.8zm53.6-23.1c-12.9 0-24.4-1.3-32.7-3.1-8.9-2.2-13.6-4.6-13.6-7.7 0-1.3.6-2.4 2.4-3.7-5.6 2.2-8.6 4-8.6 6.8.3 3.1 5.3 6.2 15.5 8.6 9.6 2.4 21.9 3.7 36.7 3.7 15.1 0 27.1-1.3 36.7-3.7 10.2-2.4 15.1-5.6 15.1-8.6 0-2.2-2.2-4.3-6.2-5.9.9.6 1.6 1.6 1.6 2.7 0 3.1-4.6 5.6-13.9 7.7-8.6 1.9-19.6 3.2-33 3.2zm36.8 8.6c-9.6 2.2-21.9 3.7-36.7 3.7-15.1 0-27.4-1.6-37-3.7-8.6-2.2-13.2-4.6-14.8-7.1 1.6 10.8 5.3 21 10.2 30 3.7 5.6 7.4 10.5 11.1 15.8 1.6 3.1 2.7 6.2 3.4 9.3 2.4 3.4 5.9 5.6 10.2 6.8 5.3 1.9 10.8 2.7 16.4 2.4h.6c5.6.3 11.5-.6 16.9-2.4 4-1.3 7.4-3.4 9.9-6.8h.3c.6-3.1 1.6-6.2 3.1-9.3 3.7-5.3 7.4-10.2 11.1-15.8 4.9-8.9 8.3-19.1 10.2-30-2 2.8-6.6 5.2-14.9 7.1zm106.2 30.1c-4.8 12.1-17.6 16.9-25.9 16.9-13.4 0-19.9-6-19.9-22.3 0-16.5 7.9-47.3 31.7-47.3 8.5 0 15.2 3.3 15.2 12.1 0 4.8-1.8 8.3-6.4 8.3-1.5 0-3.4-.4-5.2-2.4 2.2-1.1 4.2-4.9 4.2-8.3 0-2.9-1.5-5.6-5.6-5.6-10 0-18.9 23.9-18.9 42.4 0 8.3 2.2 14.2 10.9 14.2 7.1 0 13.5-3.4 17.7-9.1l2.2 1.1zm32.9-16.3c.4.2.7.2 1 .2 4.2 0 10.1-2.7 14-5.5l.8 2.4c-3.4 3.7-9.5 6.5-16.1 7.5-1.5 16.8-10.6 27.3-21.7 27.3-8.4 0-14.5-4-14.5-14.4 0-10.5 6.2-32.2 24.9-32.2 7.8.3 11.6 5.3 11.6 14.7zm-7.7 5c-1.9-.5-2.4-2-2.4-3.8 0-2.5 1.2-4.2 2.8-4.9-.2-3.8-1.1-5.3-3.4-5.3-6.5 0-12 16.6-12 25.6 0 6 1.2 7.3 4.6 7.3 4.2.1 8.9-8 10.4-18.9zm-6.6 39.7c0-8.3 7.1-11 15.8-13.6l10.9-51.9c2.7-13 10.6-15.5 16.5-15.5 4.1 0 8 2.2 9.7 5.7 3.6-4.6 8.4-5.7 12.4-5.7 5.6 0 10.8 3.9 10.8 9.8 0 1.5-.1 2.6-.3 3.7h-4.3c.1-.9.2-1.7.2-2.4 0-2.1-1.7-3.1-3.4-3.1-2 0-4.8 1.1-6.2 7.1l-1.7 7.4h9.1l-.8 3.6h-9l-10.3 49.1c-2.7 13-10.6 15.5-16.5 15.5-5.2 0-8.3-2.3-9.8-5.7-3.5 4.6-8.3 5.7-12.3 5.7-5.6.1-10.8-3.8-10.8-9.7zm9.1 1.8c1.9 0 4.2-1.8 5.4-7.1l1.1-5.3c-5.7 2-10.1 4.4-10.1 9.4 0 1.2 1.7 3 3.6 3zm21.7 0c1.9 0 4.2-1.8 5.4-7.1l2.2-10.4-9.4 1.8-1.8 8.3c-.5 2.1-1.1 4-1.8 5.6.9 1.3 3 1.8 5.4 1.8zm-1.4-18l9.4-1.7 7.7-36.8h-9l-8.1 38.5zm16.6-56.7c-2 0-4.8 1.1-6.2 7.1l-1.7 7.4h9l2.1-9.5c.2-.7.2-1.3.2-2 .1-2-1.5-3-3.4-3zm37.9 53c7.1 0 11.6-4 16.1-9.2h3.1c-5.2 8.3-12.9 16.8-25 16.8-8.5 0-14.2-4.2-14.2-14.5 0-10.5 5.9-32.3 24.6-32.3 8.1 0 10 4.2 10 8.7 0 10.5-10 18.5-20.9 19.2-.1 1.3-.2 2.5-.2 3.6 0 6.2 2.2 7.7 6.5 7.7zm5.3-34.4c-4.6 0-9.1 9.7-10.9 18.7 7-.5 13.2-7.4 13.2-15 0-2.2-.5-3.7-2.3-3.7zm28.6 33.4c3.4 0 7.8-2.3 10.8-4.8-2 10.4-8.4 13.4-15.8 13.4-8.4 0-14.1-4.2-14.1-14.5 0-10.5 5.9-32.3 24.6-32.3 8.1 0 10 4.2 10 8.7 0 10.6-10 18.5-20.9 19.2-.1.9-.2 2-.2 2.7 0 5.7 2.5 7.6 5.6 7.6zm6.2-33.4c-4.5 0-9.1 10.1-11 18.7 7.1-.4 13.3-7.3 13.3-15 0-2.2-.6-3.7-2.3-3.7zm51.3-6.7c-1.7 0-3-.6-4.2-1.9 2.4-1.5 4.1-4.8 4.1-7.8 0-3.1-1.8-6.1-6.8-6.1s-8.3 2.8-8.3 8.2c0 13.3 20.5 15.2 20.5 34.8 0 15.3-12.3 22.7-25.6 22.7-10.4 0-19.3-4.5-19.3-15.7 0-9.8 7-14.9 13.3-14.9 3.1 0 7.7 1.3 8 6-4.9 0-10.7 2.3-10.7 8.5 0 4.5 2.9 8.7 8.7 8.7 6.1 0 10.6-4.4 10.6-12 0-15.6-18.6-21.1-18.6-34.5 0-9.5 9.3-16.3 21-16.3 4.3 0 14.6.9 14.6 10.9.1 5.5-2.8 9.4-7.3 9.4zm36.2 10.3c0-2.3-.8-3.7-2.5-3.7-5.7 0-11.7 16.6-11.7 26.7 0 6.2 2.2 7.6 6.6 7.6 7.1 0 11.6-4 16.1-9.2h3.1c-5.2 8.3-12.9 16.8-25 16.8-8.5 0-14.2-4.2-14.2-14.5 0-10.6 6-32.3 24.5-32.3 8.1 0 10.1 4.2 10.1 8.3 0 4.4-2.2 6.7-4.8 6.7-1 0-2.1-.4-3.1-1.1.5-1.9.9-3.6.9-5.3zm27.7-7.6l-1.2 5.7c3.1-2.7 6.7-5.7 11-5.7 4.1 0 6.3 3.3 6.3 6.9 0 3.1-2.1 6.7-6.6 6.7-5.1 0-2.5-6-5.3-6-2.7 0-4.4 1.4-6.7 3.4l-7.2 34.6h-13.1l9.6-45.4 13.2-.2zm34.2 0l-6.6 30.9c-.3 1.2-.4 2.1-.4 2.9 0 2.5 1.2 3.3 3.7 3.3 3.5 0 6.9-3.4 8.1-8h3.8c-5.2 14.8-14.2 16.8-19.1 16.8-5.5 0-9.7-3.2-9.7-10.9 0-1.8.3-3.7.7-5.9l6.2-29.2 13.3.1zm-4.1-19.4c4 0 7.2 3.2 7.2 7.2s-3.2 7.1-7.2 7.1-7.1-3.1-7.1-7.1c-.1-4 3.2-7.2 7.1-7.2zm29.1 16l-1.5 6.9c2.6-2.3 6.1-3.9 10.7-3.9 6.2 0 11.1 3.5 11.1 14.4 0 12.2-4.7 32.1-22.3 32.1-4.5 0-6.8-1.6-7.7-3.2l-4.7 22.1-13.7 3.2 15.2-71.5 12.9-.1zm7.8 17c0-7-2.9-7.5-4.5-7.5-2 0-4.5 1.6-6.3 4.4l-5.4 25.5c.4 1 1.4 2.1 3.4 2.1 9.7 0 12.8-15.9 12.8-24.5zm27.8 17.3c-.3 1.1-.5 2.2-.5 3.1 0 1.9.7 3.2 3.1 3.2.7 0 1.7 0 2.4-.3-2.5 7.8-6.6 8.9-9.6 8.9-6.4 0-9.1-4.4-9.1-10.3 0-1.6.2-3.1.6-4.8l5.8-27.2h-3l.7-3.6h3L528 366l13.4-1.9s-1.4 6.2-3.1 14.4h5.5l-.7 3.6h-5.5l-5.7 27.4z"/>
<path d="M21.7 351.1c.1.6-.2 1.1-1.2 1.6-1.3-.7-4.1-1.1-6.4-.9-2.5.2-4.6 1-4.3 2.7.4 1.7 2.8 2.7 7.1 2.3 10.5-.9 10.4-8 25.8-9.4 12-1.1 18.7 2.6 19.6 7.1.7 3.5-2.2 6.9-10.9 7.6-7.7.7-12.2-1.4-12.6-3.5-.2-1.1.4-2.7 4.1-3.1.4 1.7 2.5 3.5 7.5 3 3.6-.3 6.6-1.6 6.2-3.6-.4-2.1-4.2-3.3-10.2-2.8-12.2 1.1-15.2 7.8-25.6 8.7-7.4.7-13.4-2-14.2-6-.3-1.5-.3-5 7.5-5.7 4-.3 7.2.4 7.6 2zm-39 41.8c-3.4 4.3-4.9 9.3-4.6 14.2.3 4.9 2.7 8.9 6.5 12 4 3.1 8.3 4 13.2 3.1 1.9-.3 4-1.3 5.9-1.9-4 0-7.4-1.3-10.8-4-3.7-2.7-6.2-6.5-6.8-11.1-.9-4.3 0-8.3 2.4-11.8 2.7-3.4 6.2-5.3 10.8-5.9 4.6-.3 8.6.9 12.6 3.7-.9-1.3-2.2-2.2-3.4-3.4-4-2.7-8.3-4-13.6-2.7-4.8 1-8.8 3.5-12.2 7.8zm53.6-23.1c-12.9 0-24.4-1.3-32.7-3.1-8.9-2.2-13.6-4.6-13.6-7.7 0-1.3.6-2.4 2.4-3.7-5.6 2.2-8.6 4-8.6 6.8.3 3.1 5.3 6.2 15.5 8.6 9.6 2.4 21.9 3.7 36.7 3.7 15.1 0 27.1-1.3 36.7-3.7 10.2-2.4 15.1-5.6 15.1-8.6 0-2.2-2.2-4.3-6.2-5.9.9.6 1.6 1.6 1.6 2.7 0 3.1-4.6 5.6-13.9 7.7-8.6 1.9-19.6 3.2-33 3.2zm36.8 8.6c-9.6 2.2-21.9 3.7-36.7 3.7-15.1 0-27.4-1.6-37-3.7-8.6-2.2-13.2-4.6-14.8-7.1 1.6 10.8 5.3 21 10.2 30 3.7 5.6 7.4 10.5 11.1 15.8 1.6 3.1 2.7 6.2 3.4 9.3 2.4 3.4 5.9 5.6 10.2 6.8 5.3 1.9 10.8 2.7 16.4 2.4h.6c5.6.3 11.5-.6 16.9-2.4 4-1.3 7.4-3.4 9.9-6.8h.3c.6-3.1 1.6-6.2 3.1-9.3 3.7-5.3 7.4-10.2 11.1-15.8 4.9-8.9 8.3-19.1 10.2-30-2 2.8-6.6 5.2-14.9 7.1zm106.2 30.1c-4.8 12.1-17.6 16.9-25.9 16.9-13.4 0-19.9-6-19.9-22.3 0-16.5 7.9-47.3 31.7-47.3 8.5 0 15.2 3.3 15.2 12.1 0 4.8-1.8 8.3-6.4 8.3-1.5 0-3.4-.4-5.2-2.4 2.2-1.1 4.2-4.9 4.2-8.3 0-2.9-1.5-5.6-5.6-5.6-10 0-18.9 23.9-18.9 42.4 0 8.3 2.2 14.2 10.9 14.2 7.1 0 13.5-3.4 17.7-9.1l2.2 1.1zm32.9-16.3c.4.2.7.2 1 .2 4.2 0 10.1-2.7 14-5.5l.8 2.4c-3.4 3.7-9.5 6.5-16.1 7.5-1.5 16.8-10.6 27.3-21.7 27.3-8.4 0-14.5-4-14.5-14.4 0-10.5 6.2-32.2 24.9-32.2 7.8.3 11.6 5.3 11.6 14.7zm-7.7 5c-1.9-.5-2.4-2-2.4-3.8 0-2.5 1.2-4.2 2.8-4.9-.2-3.8-1.1-5.3-3.4-5.3-6.5 0-12 16.6-12 25.6 0 6 1.2 7.3 4.6 7.3 4.2.1 8.9-8 10.4-18.9zm-6.6 39.7c0-8.3 7.1-11 15.8-13.6l10.9-51.9c2.7-13 10.6-15.5 16.5-15.5 4.1 0 8 2.2 9.7 5.7 3.6-4.6 8.4-5.7 12.4-5.7 5.6 0 10.8 3.9 10.8 9.8 0 1.5-.1 2.6-.3 3.7h-4.3c.1-.9.2-1.7.2-2.4 0-2.1-1.7-3.1-3.4-3.1-2 0-4.8 1.1-6.2 7.1l-1.7 7.4h9.1l-.8 3.6h-9l-10.3 49.1c-2.7 13-10.6 15.5-16.5 15.5-5.2 0-8.3-2.3-9.8-5.7-3.5 4.6-8.3 5.7-12.3 5.7-5.6.1-10.8-3.8-10.8-9.7zm9.1 1.8c1.9 0 4.2-1.8 5.4-7.1l1.1-5.3c-5.7 2-10.1 4.4-10.1 9.4 0 1.2 1.7 3 3.6 3zm21.7 0c1.9 0 4.2-1.8 5.4-7.1l2.2-10.4-9.4 1.8-1.8 8.3c-.5 2.1-1.1 4-1.8 5.6.9 1.3 3 1.8 5.4 1.8zm-1.4-18l9.4-1.7 7.7-36.8h-9l-8.1 38.5zm16.6-56.7c-2 0-4.8 1.1-6.2 7.1l-1.7 7.4h9l2.1-9.5c.2-.7.2-1.3.2-2 .1-2-1.5-3-3.4-3zm37.9 53c7.1 0 11.6-4 16.1-9.2h3.1c-5.2 8.3-12.9 16.8-25 16.8-8.5 0-14.2-4.2-14.2-14.5 0-10.5 5.9-32.3 24.6-32.3 8.1 0 10 4.2 10 8.7 0 10.5-10 18.5-20.9 19.2-.1 1.3-.2 2.5-.2 3.6 0 6.2 2.2 7.7 6.5 7.7zm5.3-34.4c-4.6 0-9.1 9.7-10.9 18.7 7-.5 13.2-7.4 13.2-15 0-2.2-.5-3.7-2.3-3.7zm28.6 33.4c3.4 0 7.8-2.3 10.8-4.8-2 10.4-8.4 13.4-15.8 13.4-8.4 0-14.1-4.2-14.1-14.5 0-10.5 5.9-32.3 24.6-32.3 8.1 0 10 4.2 10 8.7 0 10.6-10 18.5-20.9 19.2-.1.9-.2 2-.2 2.7 0 5.7 2.5 7.6 5.6 7.6zm6.2-33.4c-4.5 0-9.1 10.1-11 18.7 7.1-.4 13.3-7.3 13.3-15 0-2.2-.6-3.7-2.3-3.7zm51.3-6.7c-1.7 0-3-.6-4.2-1.9 2.4-1.5 4.1-4.8 4.1-7.8 0-3.1-1.8-6.1-6.8-6.1s-8.3 2.8-8.3 8.2c0 13.3 20.5 15.2 20.5 34.8 0 15.3-12.3 22.7-25.6 22.7-10.4 0-19.3-4.5-19.3-15.7 0-9.8 7-14.9 13.3-14.9 3.1 0 7.7 1.3 8 6-4.9 0-10.7 2.3-10.7 8.5 0 4.5 2.9 8.7 8.7 8.7 6.1 0 10.6-4.4 10.6-12 0-15.6-18.6-21.1-18.6-34.5 0-9.5 9.3-16.3 21-16.3 4.3 0 14.6.9 14.6 10.9.1 5.5-2.8 9.4-7.3 9.4zm36.2 10.3c0-2.3-.8-3.7-2.5-3.7-5.7 0-11.7 16.6-11.7 26.7 0 6.2 2.2 7.6 6.6 7.6 7.1 0 11.6-4 16.1-9.2h3.1c-5.2 8.3-12.9 16.8-25 16.8-8.5 0-14.2-4.2-14.2-14.5 0-10.6 6-32.3 24.5-32.3 8.1 0 10.1 4.2 10.1 8.3 0 4.4-2.2 6.7-4.8 6.7-1 0-2.1-.4-3.1-1.1.5-1.9.9-3.6.9-5.3zm27.7-7.6l-1.2 5.7c3.1-2.7 6.7-5.7 11-5.7 4.1 0 6.3 3.3 6.3 6.9 0 3.1-2.1 6.7-6.6 6.7-5.1 0-2.5-6-5.3-6-2.7 0-4.4 1.4-6.7 3.4l-7.2 34.6h-13.1l9.6-45.4 13.2-.2zm34.2 0l-6.6 30.9c-.3 1.2-.4 2.1-.4 2.9 0 2.5 1.2 3.3 3.7 3.3 3.5 0 6.9-3.4 8.1-8h3.8c-5.2 14.8-14.2 16.8-19.1 16.8-5.5 0-9.7-3.2-9.7-10.9 0-1.8.3-3.7.7-5.9l6.2-29.2 13.3.1zm-4.1-19.4c4 0 7.2 3.2 7.2 7.2s-3.2 7.1-7.2 7.1-7.1-3.1-7.1-7.1c-.1-4 3.2-7.2 7.1-7.2zm29.1 16l-1.5 6.9c2.6-2.3 6.1-3.9 10.7-3.9 6.2 0 11.1 3.5 11.1 14.4 0 12.2-4.7 32.1-22.3 32.1-4.5 0-6.8-1.6-7.7-3.2l-4.7 22.1-13.7 3.2 15.2-71.5 12.9-.1zm7.8 17c0-7-2.9-7.5-4.5-7.5-2 0-4.5 1.6-6.3 4.4l-5.4 25.5c.4 1 1.4 2.1 3.4 2.1 9.7 0 12.8-15.9 12.8-24.5zm27.8 17.3c-.3 1.1-.5 2.2-.5 3.1 0 1.9.7 3.2 3.1 3.2.7 0 1.7 0 2.4-.3-2.5 7.8-6.6 8.9-9.6 8.9-6.4 0-9.1-4.4-9.1-10.3 0-1.6.2-3.1.6-4.8l5.8-27.2h-3l.7-3.6h3L528 366l13.4-1.9s-1.4 6.2-3.1 14.4h5.5l-.7 3.6h-5.5l-5.7 27.4z"></path>
</svg>

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@@ -1,5 +1,5 @@
<nav class="navbar navbar-expand-lg fixed-top navbar-dark bg-dark bg-ribbed-dark site-navbar">
<a class="navbar-brand" href="#" data-close="try"><%= include('logo.svg') %></a>
<a class="navbar-brand" href="#" data-close="try" data-action="scroll-to-top"><%= include('logo.svg') %></a>
<button class="navbar-toggler" type="button" data-toggle="offcanvas" data-close="try" aria-label="Toggle sidebar">
<span class="navbar-toggler-icon"></span>
</button>

View File

@@ -1,3 +1,3 @@
<svg class="play-button" viewBox="0 0 24 24">
<path d="M2.56-0.01v24.02L21.44 11.98 2.56-0.01z"/>
<path d="M2.56-0.01v24.02L21.44 11.98 2.56-0.01z"></path>
</svg>

Before

Width:  |  Height:  |  Size: 107 B

After

Width:  |  Height:  |  Size: 112 B

View File

@@ -1,19 +1,9 @@
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js" integrity="sha384-xBuQ/xzmlsLoJpyjoggmTEz8OWUFM0/RC5BsqQBDX2v5cMvDHcMakNTNrHIW2I5f" crossorigin="anonymous"></script>
<script>
window.Popper = {}; // Remove if we want to use Bootstrap tooltips
</script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/js/bootstrap.min.js" integrity="sha384-h0AbiXch4ZDo7tp9hKZ4TsHbi047NrKGLO3SEJAg45jXxnGIfYzk4Si90RDIqNm1" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/combine/npm/codemirror@5.29.0/lib/codemirror.js,npm/codemirror@5.29.0/mode/coffeescript/coffeescript.js,npm/codemirror@5.29.0/addon/lint/coffeescript-lint.js,npm/codemirror@5.29.0/mode/javascript/javascript.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js" integrity="sha384-uefMccjFJAIv6A+rW+L4AHf99KvxDjWSu1z9VI8SKNVmz4sk7buKt/6v9KI65qnm" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/combine/npm/codemirror@5.37.0/lib/codemirror.js,npm/codemirror@5.37.0/mode/coffeescript/coffeescript.js,npm/codemirror@5.37.0/addon/lint/coffeescript-lint.js,npm/codemirror@5.37.0/mode/javascript/javascript.js"></script>
<script src="browser-compiler/coffeescript.js"></script>
<script>
<%= includeScript('docs.coffee') %>
</script>
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-106156830-1"></script>
<script>
window.GA_TRACKING_ID = 'UA-106156830-1';
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments)};
gtag('js', new Date());
gtag('config', GA_TRACKING_ID);
</script>

View File

@@ -1,8 +1,8 @@
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9gVQ4dYFwwWSjIDZnLEWnxCjeSWFphJiwGPXr1jddIhOegiu1FwO5qRGvFXOdJZ4" crossorigin="anonymous">
<!-- The CoffeeScript logo font is Googles Galada -->
<link href="https://fonts.googleapis.com/css?family=Alegreya+Sans:400,800|Lato:300,300i,400,700|Roboto+Mono:400,400i" rel="stylesheet" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/codemirror/4.5.0/codemirror.css" crossorigin="anonymous">
<link href="https://cdn.jsdelivr.net/npm/codemirror@5.37.0/lib/codemirror.css" rel="stylesheet" crossorigin="anonymous">
<style>
<%= include('docs.css') %>
<%= include('code.css') %>
<%= include('docs.css') %>
</style>

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 2.2.4
// Generated by CoffeeScript 2.3.0
(function() {
// This **Browser** compatibility layer extends core CoffeeScript functions
// to make things work smoothly when compiling code directly in the browser.

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 2.2.4
// Generated by CoffeeScript 2.3.0
(function() {
// `cake` is a simplified version of [Make](http://www.gnu.org/software/make/)
// ([Rake](http://rake.rubyforge.org/), [Jake](https://github.com/280north/jake))

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 2.2.4
// Generated by CoffeeScript 2.3.0
(function() {
// CoffeeScript can be used both on the server, as a command-line compiler based
// on Node.js/V8, or to run CoffeeScript directly in the browser. This module

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 2.2.4
// Generated by CoffeeScript 2.3.0
(function() {
// The `coffee` utility. Handles command-line compilation of CoffeeScript
// into various forms: saved into `.js` files or printed to stdout

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 2.2.4
// Generated by CoffeeScript 2.3.0
(function() {
// The CoffeeScript parser is generated by [Jison](https://github.com/zaach/jison)
// from this grammar file. Jison is a bottom-up parser generator, similar in
@@ -286,16 +286,15 @@
});
})
],
SimpleObjAssignable: [
o('Identifier'),
o('Property'),
o('ThisProperty'),
SimpleObjAssignable: [o('Identifier'), o('Property'), o('ThisProperty')],
ObjAssignable: [
o('SimpleObjAssignable'),
o('[ Expression ]',
function() {
return new Value(new ComputedPropertyName($2));
})
}),
o('AlphaNumeric')
],
ObjAssignable: [o('SimpleObjAssignable'), o('AlphaNumeric')],
// Object literal spread properties.
ObjRestValue: [
o('SimpleObjAssignable ...',
@@ -1348,77 +1347,94 @@
// Comprehensions can either be normal, with a block of expressions to execute,
// or postfix, with a single expression.
For: [
o('Statement ForBody',
o('Statement ForBody',
function() {
return new For($1,
$2);
return $2.addBody($1);
}),
o('Expression ForBody',
o('Expression ForBody',
function() {
return new For($1,
$2);
return $2.addBody($1);
}),
o('ForBody Block',
o('ForBody Block',
function() {
return new For($2,
$1);
return $1.addBody($2);
}),
o('ForLineBody Block',
function() {
return new For($2,
$1);
return $1.addBody($2);
})
],
ForBody: [
o('FOR Range',
function() {
return {
return new For([],
{
source: LOC(2)(new Value($2))
};
});
}),
o('FOR Range BY Expression',
function() {
return {
return new For([],
{
source: LOC(2)(new Value($2)),
step: $4
};
});
}),
o('ForStart ForSource',
function() {
$2.own = $1.own;
$2.ownTag = $1.ownTag;
$2.name = $1[0];
$2.index = $1[1];
return $2;
return $1.addSource($2);
})
],
ForLineBody: [
o('FOR Range BY ExpressionLine',
function() {
return {
return new For([],
{
source: LOC(2)(new Value($2)),
step: $4
};
});
}),
o('ForStart ForLineSource',
function() {
$2.own = $1.own;
$2.ownTag = $1.ownTag;
$2.name = $1[0];
$2.index = $1[1];
return $2;
return $1.addSource($2);
})
],
ForStart: [
o('FOR ForVariables',
function() {
return $2;
return new For([],
{
name: $2[0],
index: $2[1]
});
}),
o('FOR AWAIT ForVariables',
function() {
var index,
name;
[name,
index] = $3;
return new For([],
{
name,
index,
await: true,
awaitTag: LOC(2)(new Literal($2))
});
}),
o('FOR OWN ForVariables',
function() {
$3.own = true;
$3.ownTag = LOC(2)(new Literal($2));
return $3;
var index,
name;
[name,
index] = $3;
return new For([],
{
name,
index,
own: true,
ownTag: LOC(2)(new Literal($2))
});
})
],
// An array of all accepted values for a variable inside the loop.

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 2.2.4
// Generated by CoffeeScript 2.3.0
(function() {
// This file contains the common helper functions that we'd like to share among
// the **Lexer**, **Rewriter**, and the **Nodes**. Merge objects, flatten

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 2.2.4
// Generated by CoffeeScript 2.3.0
(function() {
// Node.js Implementation
var CoffeeScript, ext, fs, helpers, i, len, path, ref, universalCompile, vm,

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 2.2.4
// Generated by CoffeeScript 2.3.0
(function() {
// The CoffeeScript Lexer. Uses a series of token-matching regexes to attempt
// matches against the beginning of the source code. When a match is found,
@@ -1610,7 +1610,7 @@
REGEX_FLAGS = /^\w*/;
VALID_FLAGS = /^(?!.*(.).*\1)[imguy]*$/;
VALID_FLAGS = /^(?!.*(.).*\1)[gimsuy]*$/;
// Match any character, except those that need special handling below.
// Match `\` followed by any character.

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 2.2.4
// Generated by CoffeeScript 2.3.0
(function() {
// `nodes.coffee` contains all of the node classes for the syntax tree. Most
// nodes are created as the result of actions in the [grammar](grammar.html),
@@ -836,7 +836,7 @@
}
compileComments(fragments) {
var code, commentFragment, fragment, fragmentIndent, fragmentIndex, indent, j, k, l, len1, len2, len3, newLineIndex, onNextLine, pastFragment, pastFragmentIndex, q, r, ref1, ref2, ref3, ref4, trail, upcomingFragment, upcomingFragmentIndex;
var code, commentFragment, fragment, fragmentIndent, fragmentIndex, indent, j, k, l, len1, len2, len3, newLineIndex, onNextLine, p, pastFragment, pastFragmentIndex, q, ref1, ref2, ref3, ref4, trail, upcomingFragment, upcomingFragmentIndex;
for (fragmentIndex = j = 0, len1 = fragments.length; j < len1; fragmentIndex = ++j) {
fragment = fragments[fragmentIndex];
// Insert comments into the output at the next or previous newline.
@@ -913,8 +913,8 @@
if (!(trail && fragment.followingComments.length === 1)) {
onNextLine = false;
ref3 = fragments.slice(fragmentIndex);
for (q = 0, len2 = ref3.length; q < len2; q++) {
upcomingFragment = ref3[q];
for (p = 0, len2 = ref3.length; p < len2; p++) {
upcomingFragment = ref3[p];
if (!onNextLine) {
if (indexOf.call(upcomingFragment.code, '\n') >= 0) {
onNextLine = true;
@@ -937,11 +937,11 @@
code = fragmentIndex === 1 && /^\s+$/.test(fragments[0].code) ? '' : trail ? ' ' : `\n${fragmentIndent}`;
// Assemble properly indented comments.
code += ((function() {
var len3, r, ref4, results;
var len3, q, ref4, results;
ref4 = fragment.followingComments;
results = [];
for (r = 0, len3 = ref4.length; r < len3; r++) {
commentFragment = ref4[r];
for (q = 0, len3 = ref4.length; q < len3; q++) {
commentFragment = ref4[q];
if (commentFragment.isHereComment && commentFragment.multiline) {
results.push(multident(commentFragment.code, fragmentIndent, false));
} else {
@@ -951,7 +951,7 @@
return results;
})()).join(`\n${fragmentIndent}`).replace(/^(\s*)$/gm, '');
ref4 = fragments.slice(fragmentIndex);
for (upcomingFragmentIndex = r = 0, len3 = ref4.length; r < len3; upcomingFragmentIndex = ++r) {
for (upcomingFragmentIndex = q = 0, len3 = ref4.length; q < len3; upcomingFragmentIndex = ++q) {
upcomingFragment = ref4[upcomingFragmentIndex];
newLineIndex = upcomingFragment.code.indexOf('\n');
if (newLineIndex === -1) {
@@ -2206,8 +2206,35 @@
return false;
}
// Move rest property to the end of the list.
// `{a, rest..., b} = obj` -> `{a, b, rest...} = obj`
// `foo = ({a, rest..., b}) ->` -> `foo = {a, b, rest...}) ->`
reorderProperties() {
var i, prop, props, splatProp, splatProps;
props = this.properties;
splatProps = (function() {
var j, len1, results;
results = [];
for (i = j = 0, len1 = props.length; j < len1; i = ++j) {
prop = props[i];
if (prop instanceof Splat) {
results.push(i);
}
}
return results;
})();
if ((splatProps != null ? splatProps.length : void 0) > 1) {
props[splatProps[1]].error("multiple spread elements are disallowed");
}
splatProp = props.splice(splatProps[0], 1);
return this.objects = this.properties = [].concat(props, splatProp);
}
compileNode(o) {
var answer, i, idt, indent, isCompact, j, join, k, key, l, lastNode, len1, len2, len3, len4, node, prop, props, q, ref1, unwrappedVal, value;
var answer, i, idt, indent, isCompact, j, join, k, key, l, lastNode, len1, len2, len3, len4, node, p, prop, props, ref1, unwrappedVal, value;
if (this.hasSplat() && this.lhs) {
this.reorderProperties();
}
props = this.properties;
if (this.generated) {
for (j = 0, len1 = props.length; j < len1; j++) {
@@ -2217,10 +2244,6 @@
}
}
}
if (this.hasSplat() && !this.csx) {
// Object spread properties. https://github.com/tc39/proposal-object-rest-spread/blob/master/Spread.md
return this.compileSpread(o);
}
idt = o.indent += TAB;
lastNode = this.lastNode(this.properties);
if (this.csx) {
@@ -2254,7 +2277,7 @@
}
answer = [];
answer.push(this.makeCode(isCompact ? '' : '\n'));
for (i = q = 0, len4 = props.length; q < len4; i = ++q) {
for (i = p = 0, len4 = props.length; p < len4; i = ++p) {
prop = props[i];
join = i === props.length - 1 ? '' : isCompact ? ', ' : prop === lastNode ? '\n' : ',\n';
indent = isCompact ? '' : idt;
@@ -2285,7 +2308,7 @@
// `{ [expression] }` output as `{ [expression]: expression }`.
prop = new Assign(key, prop.base.value, 'object');
}
} else if (!(typeof prop.bareLiteral === "function" ? prop.bareLiteral(IdentifierLiteral) : void 0)) {
} else if (!(typeof prop.bareLiteral === "function" ? prop.bareLiteral(IdentifierLiteral) : void 0) && !(prop instanceof Splat)) {
prop = new Assign(prop, prop, 'object');
}
}
@@ -2337,42 +2360,6 @@
return results;
}
// Object spread properties. https://github.com/tc39/proposal-object-rest-spread/blob/master/Spread.md
// `obj2 = {a: 1, obj..., c: 3, d: 4}` → `obj2 = _extends({}, {a: 1}, obj, {c: 3, d: 4})`
compileSpread(o) {
var _extends, addSlice, j, len1, prop, propSlices, props, slices, splatSlice;
props = this.properties;
// Store object spreads.
splatSlice = [];
propSlices = [];
slices = [];
addSlice = function() {
if (propSlices.length) {
slices.push(new Obj(propSlices));
}
if (splatSlice.length) {
slices.push(...splatSlice);
}
splatSlice = [];
return propSlices = [];
};
for (j = 0, len1 = props.length; j < len1; j++) {
prop = props[j];
if (prop instanceof Splat) {
splatSlice.push(new Value(prop.name));
addSlice();
} else {
propSlices.push(prop);
}
}
addSlice();
if (!(slices[0] instanceof Obj)) {
slices.unshift(new Obj);
}
_extends = new Value(new Literal(utility('_extends', o)));
return (new Call(_extends, slices)).compileToFragments(o);
}
compileCSXAttributes(o) {
var answer, i, j, join, len1, prop, props;
props = this.properties;
@@ -2448,7 +2435,7 @@
}
compileNode(o) {
var answer, compiledObjs, fragment, fragmentIndex, fragmentIsElision, fragments, includesLineCommentsOnNonFirstElement, index, j, k, l, len1, len2, len3, len4, len5, obj, objIndex, olen, passedElision, q, r, ref1, unwrappedObj;
var answer, compiledObjs, fragment, fragmentIndex, fragmentIsElision, fragments, includesLineCommentsOnNonFirstElement, index, j, k, l, len1, len2, len3, len4, len5, obj, objIndex, olen, p, passedElision, q, ref1, unwrappedObj;
if (!this.objects.length) {
return [this.makeCode('[]')];
}
@@ -2516,7 +2503,7 @@
answer.push(...fragments);
}
if (includesLineCommentsOnNonFirstElement || indexOf.call(fragmentsToText(answer), '\n') >= 0) {
for (fragmentIndex = q = 0, len4 = answer.length; q < len4; fragmentIndex = ++q) {
for (fragmentIndex = p = 0, len4 = answer.length; p < len4; fragmentIndex = ++p) {
fragment = answer[fragmentIndex];
if (fragment.isHereComment) {
fragment.code = `${multident(fragment.code, o.indent, false)}\n${o.indent}`;
@@ -2527,8 +2514,8 @@
answer.unshift(this.makeCode(`[\n${o.indent}`));
answer.push(this.makeCode(`\n${this.tab}]`));
} else {
for (r = 0, len5 = answer.length; r < len5; r++) {
fragment = answer[r];
for (q = 0, len5 = answer.length; q < len5; q++) {
fragment = answer[q];
if (fragment.isHereComment) {
fragment.code = `${fragment.code} `;
}
@@ -3283,7 +3270,7 @@
// we've been assigned to, for correct internal references. If the variable
// has not been seen yet within the current scope, declare it.
compileNode(o) {
var answer, compiledName, hasSplat, isValue, name, objDestructAnswer, properties, prototype, ref1, ref2, ref3, ref4, ref5, val, varBase;
var answer, compiledName, isValue, name, properties, prototype, ref1, ref2, ref3, ref4, ref5, val, varBase;
isValue = this.variable instanceof Value;
if (isValue) {
// When compiling `@variable`, remember if it is part of a function parameter.
@@ -3297,19 +3284,12 @@
// know that, so that those nodes know that theyre assignable as
// destructured variables.
this.variable.base.lhs = true;
// Check if @variable contains Obj with splats.
hasSplat = this.variable.contains(function(node) {
return node instanceof Obj && node.hasSplat();
});
if (!this.variable.isAssignable() || this.variable.isArray() && hasSplat) {
return this.compileDestructuring(o);
}
if (this.variable.isObject() && hasSplat) {
// Object destructuring. Can be removed once ES proposal hits Stage 4.
objDestructAnswer = this.compileObjectDestruct(o);
}
if (objDestructAnswer) {
return objDestructAnswer;
if (!this.variable.isAssignable()) {
if (this.variable.isObject() && this.variable.base.hasSplat()) {
return this.compileObjectDestruct(o);
} else {
return this.compileDestructuring(o);
}
}
}
if (this.variable.isSplice()) {
@@ -3318,11 +3298,11 @@
if ((ref1 = this.context) === '||=' || ref1 === '&&=' || ref1 === '?=') {
return this.compileConditional(o);
}
if ((ref2 = this.context) === '**=' || ref2 === '//=' || ref2 === '%%=') {
if ((ref2 = this.context) === '//=' || ref2 === '%%=') {
return this.compileSpecialMath(o);
}
}
if (!this.context) {
if (!this.context || this.context === '**=') {
varBase = this.variable.unwrapAll();
if (!varBase.isAssignable()) {
this.variable.error(`'${this.variable.compile(o)}' can't be assigned`);
@@ -3396,124 +3376,27 @@
}
}
// Check object destructuring variable for rest elements;
// can be removed once ES proposal hits Stage 4.
// Object rest property is not assignable: `{{a}...}`
compileObjectDestruct(o) {
var fragments, getPropKey, getPropName, j, len1, restElement, restElements, result, traverseRest, value, valueRef, valueRefTemp;
// Returns a safe (cached) reference to the key for a given property
getPropKey = function(prop) {
var key;
if (prop instanceof Assign) {
[prop.variable, key] = prop.variable.cache(o);
return key;
} else {
return prop;
}
};
// Returns the name of a given property for use with excludeProps
// Property names are quoted (e.g. `a: b` -> 'a'), and everything else uses the key reference
// (e.g. `'a': b -> 'a'`, `"#{a}": b` -> <cached>`)
getPropName = function(prop) {
var cached, key;
key = getPropKey(prop);
cached = prop instanceof Assign && prop.variable !== key;
if (cached || !key.isAssignable()) {
return key;
} else {
return new Literal(`'${key.compileWithoutComments(o)}'`);
}
};
// Recursive function for searching and storing rest elements in objects.
// e.g. `{[properties...]} = source`.
traverseRest = (properties, source) => {
var base1, index, j, len1, nestedProperties, nestedSource, nestedSourceDefault, p, prop, restElements, restIndex;
restElements = [];
restIndex = void 0;
if (source.properties == null) {
source = new Value(source);
}
for (index = j = 0, len1 = properties.length; j < len1; index = ++j) {
prop = properties[index];
nestedSourceDefault = nestedSource = nestedProperties = null;
if (prop instanceof Assign) {
if (typeof (base1 = prop.value).isObject === "function" ? base1.isObject() : void 0) {
if (prop.context !== 'object') {
// prop is `k = {...} `
continue;
}
// prop is `k: {...}`
nestedProperties = prop.value.base.properties;
} else if (prop.value instanceof Assign && prop.value.variable.isObject()) {
// prop is `k: {...} = default`
nestedProperties = prop.value.variable.base.properties;
[prop.value.value, nestedSourceDefault] = prop.value.value.cache(o);
}
if (nestedProperties) {
nestedSource = new Value(source.base, source.properties.concat([new Access(getPropKey(prop))]));
if (nestedSourceDefault) {
nestedSource = new Value(new Op('?', nestedSource, nestedSourceDefault));
}
restElements.push(...traverseRest(nestedProperties, nestedSource));
}
} else if (prop instanceof Splat) {
if (restIndex != null) {
prop.error("multiple rest elements are disallowed in object destructuring");
}
restIndex = index;
restElements.push({
name: prop.name.unwrapAll(),
source,
excludeProps: new Arr((function() {
var k, len2, results;
results = [];
for (k = 0, len2 = properties.length; k < len2; k++) {
p = properties[k];
if (p !== prop) {
results.push(getPropName(p));
}
}
return results;
})())
});
}
}
if (restIndex != null) {
// Remove rest element from the properties after iteration
properties.splice(restIndex, 1);
}
return restElements;
};
// Cache the value for reuse with rest elements.
valueRefTemp = this.value.shouldCache() ? new IdentifierLiteral(o.scope.freeVariable('ref', {
reserve: false
})) : this.value.base;
// Find all rest elements.
restElements = traverseRest(this.variable.base.properties, valueRefTemp);
if (!(restElements && restElements.length > 0)) {
return false;
}
[this.value, valueRef] = this.value.cache(o);
result = new Block([this]);
for (j = 0, len1 = restElements.length; j < len1; j++) {
restElement = restElements[j];
value = new Call(new Value(new Literal(utility('objectWithoutKeys', o))), [restElement.source, restElement.excludeProps]);
result.push(new Assign(new Value(restElement.name), value, null, {
param: this.param ? 'alwaysDeclare' : null
}));
}
fragments = result.compileToFragments(o);
if (o.level === LEVEL_TOP) {
// Remove leading tab and trailing semicolon
fragments.shift();
fragments.pop();
}
return fragments;
var assigns, props, refVal, splat, splatProp;
this.variable.base.reorderProperties();
({
properties: props
} = this.variable.base);
[splat] = slice1.call(props, -1);
splatProp = splat.name;
assigns = [];
refVal = new Value(new IdentifierLiteral(o.scope.freeVariable('ref')));
props.splice(-1, 1, new Splat(refVal));
assigns.push(new Assign(new Value(new Obj(props)), this.value).compileToFragments(o, LEVEL_LIST));
assigns.push(new Assign(new Value(splatProp), refVal).compileToFragments(o, LEVEL_LIST));
return this.joinFragmentArrays(assigns, ', ');
}
// Brief implementation of recursive pattern matching, when assigning array or
// object literals to a value. Peeks at their properties to assign inner names.
compileDestructuring(o) {
var assignObjects, assigns, code, compSlice, compSplice, complexObjects, expIdx, expans, fragments, hasObjAssigns, hasObjSpreads, i, isArray, isExpans, isObject, isSplat, leftObjs, loopObjects, obj, objIsUnassignable, objects, olen, processObjects, ref, refExp, restVar, rightObjs, slicer, splats, splatsAndExpans, top, value, vvar, vvarText;
var assignObjects, assigns, code, compSlice, compSplice, complexObjects, expIdx, expans, fragments, hasObjAssigns, i, isExpans, isSplat, leftObjs, loopObjects, obj, objIsUnassignable, objects, olen, processObjects, pushAssign, ref, refExp, restVar, rightObjs, slicer, splatVar, splatVarAssign, splatVarRef, splats, splatsAndExpans, top, value, vvar, vvarText;
top = o.level === LEVEL_TOP;
({value} = this);
({objects} = this.variable.base);
@@ -3567,11 +3450,25 @@
}
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);
vvarText = fragmentsToText(vvar);
assigns = [];
pushAssign = (variable, val) => {
return assigns.push(new Assign(variable, val, null, {
param: this.param,
subpattern: true
}).compileToFragments(o, LEVEL_LIST));
};
if (isSplat) {
splatVar = objects[splats[0]].name.unwrap();
if (splatVar instanceof Arr || splatVar instanceof Obj) {
splatVarRef = new IdentifierLiteral(o.scope.freeVariable('ref'));
objects[splats[0]].name = splatVarRef;
splatVarAssign = function() {
return pushAssign(new Value(splatVar), splatVarRef);
};
}
}
// At this point, there are several things to destructure. So the `fn()` in
// `{a, b} = fn()` must be cached, for example. Make vvar into a simple
// variable if it isnt already.
@@ -3599,18 +3496,6 @@
compSlice = slicer("slice");
// Helper which outputs `[].splice` code.
compSplice = slicer("splice");
// Check if `objects` array contains object spread (`{a, r...}`), e.g. `[a, b, {c, r...}]`.
hasObjSpreads = function(objs) {
var j, len1, results;
results = [];
for (i = j = 0, len1 = objs.length; j < len1; i = ++j) {
obj = objs[i];
if (obj.base instanceof Obj && obj.base.hasSplat()) {
results.push(i);
}
}
return results;
};
// Check if `objects` array contains any instance of `Assign`, e.g. {a:1}.
hasObjAssigns = function(objs) {
var j, len1, results;
@@ -3634,16 +3519,15 @@
}
return false;
};
// `objects` are complex when there is object spread ({a...}), object assign ({a:1}),
// `objects` are complex when there is object assign ({a:1}),
// unassignable object, or just a single node.
complexObjects = function(objs) {
return hasObjSpreads(objs).length || hasObjAssigns(objs).length || objIsUnassignable(objs) || olen === 1;
return hasObjAssigns(objs).length || objIsUnassignable(objs) || olen === 1;
};
// "Complex" `objects` are processed in a loop.
// Examples: [a, b, {c, r...}, d], [a, ..., {b, r...}, c, d]
loopObjects = (objs, vvar, vvarTxt) => {
var acc, idx, j, len1, message, objSpreads, results, vval;
objSpreads = hasObjSpreads(objs);
var acc, idx, j, len1, message, results, vval;
results = [];
for (i = j = 0, len1 = objs.length; j < len1; i = ++j) {
obj = objs[i];
@@ -3673,8 +3557,6 @@
switch (false) {
case !(obj instanceof Splat):
return new Value(obj.name);
case indexOf.call(objSpreads, i) < 0:
return new Value(obj.base);
default:
return obj;
}
@@ -3692,10 +3574,7 @@
if (message) {
vvar.error(message);
}
results.push(assigns.push(new Assign(vvar, vval, null, {
param: this.param,
subpattern: true
}).compileToFragments(o, LEVEL_LIST)));
results.push(pushAssign(vvar, vval));
}
return results;
};
@@ -3704,10 +3583,7 @@
var vval;
vvar = new Value(new Arr(objs, true));
vval = vvarTxt instanceof Value ? vvarTxt : new Value(new Literal(vvarTxt));
return assigns.push(new Assign(vvar, vval, null, {
param: this.param,
subpattern: true
}).compileToFragments(o, LEVEL_LIST));
return pushAssign(vvar, vval);
};
processObjects = function(objs, vvar, vvarTxt) {
if (complexObjects(objs)) {
@@ -3755,6 +3631,9 @@
// There is no `Splat` or `Expansion` in `objects`.
processObjects(objects, vvar, vvarText);
}
if (typeof splatVarAssign === "function") {
splatVarAssign();
}
if (!(top || this.subpattern)) {
assigns.push(vvar);
}
@@ -3791,7 +3670,7 @@
}
}
// Convert special math assignment operators like `a **= b` to the equivalent
// Convert special math assignment operators like `a //= b` to the equivalent
// extended form `a = a ** b` and then compiles that.
compileSpecialMath(o) {
var left, right;
@@ -3889,8 +3768,8 @@
if ((node instanceof Op && node.isAwait()) || node instanceof AwaitReturn) {
this.isAsync = true;
}
if (this.isGenerator && this.isAsync) {
return node.error("function can't contain both yield and await");
if (node instanceof For && node.isAwait()) {
return this.isAsync = true;
}
});
}
@@ -3984,7 +3863,7 @@
}
haveSplatParam = true;
if (param.splat) {
if (param.name instanceof Arr) {
if (param.name instanceof Arr || param.name instanceof Obj) {
// Splat arrays are treated oddly by ES; deal with them the legacy
// way in the function body. TODO: Should this be handled in the
// function parameter list, and if so, how?
@@ -4046,22 +3925,7 @@
if (param.name instanceof Arr || param.name instanceof Obj) {
// This parameter is destructured.
param.name.lhs = true;
// Compile `foo({a, b...}) ->` to `foo(arg) -> {a, b...} = arg`.
// Can be removed once ES proposal hits Stage 4.
if (param.name instanceof Obj && param.name.hasSplat()) {
splatParamName = o.scope.freeVariable('arg');
o.scope.parameter(splatParamName);
ref = new Value(new IdentifierLiteral(splatParamName));
exprs.push(new Assign(new Value(param.name), ref, null, {
param: 'alwaysDeclare'
}));
// Compile `foo({a, b...} = {}) ->` to `foo(arg = {}) -> {a, b...} = arg`.
if ((param.value != null) && !param.assignedInBody) {
ref = new Assign(ref, param.value, null, {
param: true
});
}
} else if (!param.shouldCache()) {
if (!param.shouldCache()) {
param.name.eachName(function(prop) {
return o.scope.parameter(prop.value);
});
@@ -4195,10 +4059,10 @@
o.scope = methodScope;
}
answer = this.joinFragmentArrays((function() {
var len4, q, results;
var len4, p, results;
results = [];
for (q = 0, len4 = modifiers.length; q < len4; q++) {
m = modifiers[q];
for (p = 0, len4 = modifiers.length; p < len4; p++) {
m = modifiers[p];
results.push(this.makeCode(m));
}
return results;
@@ -4328,12 +4192,12 @@
// as well as be a splat, gathering up a group of parameters into an array.
exports.Param = Param = (function() {
class Param extends Base {
constructor(name1, value1, splat) {
constructor(name1, value1, splat1) {
var message, token;
super();
this.name = name1;
this.value = value1;
this.splat = splat;
this.splat = splat1;
message = isUnassignable(this.name.unwrapAll().value);
if (message) {
this.name.error(message);
@@ -4485,7 +4349,14 @@
this.name = name.compile ? name : new Literal(name);
}
shouldCache() {
return false;
}
isAssignable() {
if (this.name instanceof Obj || this.name instanceof Parens) {
return false;
}
return this.name.isAssignable() && (!this.name.isAtomic || this.name.isAtomic());
}
@@ -4800,8 +4671,6 @@
switch (this.operator) {
case '?':
return this.compileExistence(o, this.second.isDefaultValue);
case '**':
return this.compilePower(o);
case '//':
return this.compileFloorDivision(o);
case '%%':
@@ -4903,13 +4772,6 @@
return this.joinFragmentArrays(parts, '');
}
compilePower(o) {
var pow;
// Make a Math.pow call
pow = new Value(new IdentifierLiteral('Math'), [new Access(new PropertyName('pow'))]);
return new Call(pow, [this.first, this.second]).compileToFragments(o);
}
compileFloorDivision(o) {
var div, floor, second;
floor = new Value(new IdentifierLiteral('Math'), [new Access(new PropertyName('floor'))]);
@@ -5370,25 +5232,47 @@
exports.For = For = (function() {
class For extends While {
constructor(body, source) {
var attribute, j, len1, ref1, ref2, ref3;
super();
({source: this.source, guard: this.guard, step: this.step, name: this.name, index: this.index} = source);
this.addBody(body);
this.addSource(source);
}
isAwait() {
var ref1;
return (ref1 = this.await) != null ? ref1 : false;
}
addBody(body) {
this.body = Block.wrap([body]);
this.own = source.own != null;
this.object = source.object != null;
this.from = source.from != null;
return this;
}
addSource(source) {
var attr, attribs, attribute, j, k, len1, len2, ref1, ref2, ref3, ref4;
({source: this.source = false} = source);
attribs = ["name", "index", "guard", "step", "own", "ownTag", "await", "awaitTag", "object", "from"];
for (j = 0, len1 = attribs.length; j < len1; j++) {
attr = attribs[j];
this[attr] = (ref1 = source[attr]) != null ? ref1 : this[attr];
}
if (!this.source) {
return this;
}
if (this.from && this.index) {
this.index.error('cannot use index with for-from');
}
if (this.own && !this.object) {
source.ownTag.error(`cannot use own with for-${(this.from ? 'from' : 'in')}`);
this.ownTag.error(`cannot use own with for-${(this.from ? 'from' : 'in')}`);
}
if (this.object) {
[this.name, this.index] = [this.index, this.name];
}
if (((ref1 = this.index) != null ? typeof ref1.isArray === "function" ? ref1.isArray() : void 0 : void 0) || ((ref2 = this.index) != null ? typeof ref2.isObject === "function" ? ref2.isObject() : void 0 : void 0)) {
if (((ref2 = this.index) != null ? typeof ref2.isArray === "function" ? ref2.isArray() : void 0 : void 0) || ((ref3 = this.index) != null ? typeof ref3.isObject === "function" ? ref3.isObject() : void 0 : void 0)) {
this.index.error('index cannot be a pattern matching expression');
}
if (this.await && !this.from) {
this.awaitTag.error('await must be used with for-from');
}
this.range = this.source instanceof Value && this.source.base instanceof Range && !this.source.properties.length && !this.from;
this.pattern = this.name instanceof Value;
if (this.range && this.index) {
@@ -5398,21 +5282,21 @@
this.name.error('cannot pattern match over range loops');
}
this.returns = false;
ref3 = ['source', 'guard', 'step', 'name', 'index'];
ref4 = ['source', 'guard', 'step', 'name', 'index'];
// Move up any comments in the “`for` line”, i.e. the line of code with `for`,
// from any child nodes of that line up to the `for` node itself so that these
// comments get output, and get output above the `for` loop.
for (j = 0, len1 = ref3.length; j < len1; j++) {
attribute = ref3[j];
for (k = 0, len2 = ref4.length; k < len2; k++) {
attribute = ref4[k];
if (!this[attribute]) {
continue;
}
this[attribute].traverseChildren(true, (node) => {
var comment, k, len2, ref4;
var comment, l, len3, ref5;
if (node.comments) {
ref4 = node.comments;
for (k = 0, len2 = ref4.length; k < len2; k++) {
comment = ref4[k];
ref5 = node.comments;
for (l = 0, len3 = ref5.length; l < len3; l++) {
comment = ref5[l];
// These comments are buried pretty deeply, so if they happen to be
// trailing comments the line they trail will be unrecognizable when
// were done compiling this `for` loop; so just shift them up to
@@ -5424,6 +5308,7 @@
});
moveComments(this[attribute], this);
}
return this;
}
// Welcome to the hairiest method in all of CoffeeScript. Handles the inner
@@ -5431,7 +5316,7 @@
// comprehensions. Some of the generated code can be shared in common, and
// some cannot.
compileNode(o) {
var body, bodyFragments, compare, compareDown, declare, declareDown, defPart, down, forPartFragments, fragments, guardPart, idt1, increment, index, ivar, kvar, kvarAssign, last, lvar, name, namePart, ref, ref1, resultPart, returnResult, rvar, scope, source, step, stepNum, stepVar, svar, varPart;
var body, bodyFragments, compare, compareDown, declare, declareDown, defPart, down, forClose, forCode, forPartFragments, fragments, guardPart, idt1, increment, index, ivar, kvar, kvarAssign, last, lvar, name, namePart, ref, ref1, resultPart, returnResult, rvar, scope, source, step, stepNum, stepVar, svar, varPart;
body = Block.wrap([this.body]);
ref1 = body.expressions, [last] = slice1.call(ref1, -1);
if ((last != null ? last.jumps() : void 0) instanceof Return) {
@@ -5549,7 +5434,12 @@
guardPart = `\n${idt1}if (!${utility('hasProp', o)}.call(${svar}, ${kvar})) continue;`;
}
} else if (this.from) {
forPartFragments = [this.makeCode(`${kvar} of ${svar}`)];
if (this.await) {
forPartFragments = new Op('await', new Parens(new Literal(`${kvar} of ${svar}`)));
forPartFragments = forPartFragments.compileToFragments(o, LEVEL_TOP);
} else {
forPartFragments = [this.makeCode(`${kvar} of ${svar}`)];
}
}
bodyFragments = body.compileToFragments(merge(o, {
indent: idt1
@@ -5561,7 +5451,9 @@
if (resultPart) {
fragments.push(this.makeCode(resultPart));
}
fragments = fragments.concat(this.makeCode(this.tab), this.makeCode('for ('), forPartFragments, this.makeCode(`) {${guardPart}${varPart}`), bodyFragments, this.makeCode(this.tab), this.makeCode('}'));
forCode = this.await ? 'for ' : 'for (';
forClose = this.await ? '' : ')';
fragments = fragments.concat(this.makeCode(this.tab), this.makeCode(forCode), forPartFragments, this.makeCode(`${forClose} {${guardPart}${varPart}`), bodyFragments, this.makeCode(this.tab), this.makeCode('}'));
if (returnResult) {
fragments.push(this.makeCode(returnResult));
}
@@ -5806,15 +5698,9 @@
modulo: function() {
return 'function(a, b) { return (+a % (b = +b) + b) % b; }';
},
objectWithoutKeys: function() {
return "function(o, ks) { var res = {}; for (var k in o) ([].indexOf.call(ks, k) < 0 && {}.hasOwnProperty.call(o, k)) && (res[k] = o[k]); return res; }";
},
boundMethodCheck: function() {
return "function(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new Error('Bound instance method accessed before binding'); } }";
},
_extends: function() {
return "Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }";
},
// Shortcuts to speed up the lookup time for native functions.
hasProp: function() {
return '{}.hasOwnProperty';

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 2.2.4
// Generated by CoffeeScript 2.3.0
(function() {
var LONG_FLAG, MULTI_FLAG, OPTIONAL, OptionParser, SHORT_FLAG, buildRule, buildRules, normalizeArguments, repeat,
splice = [].splice;

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 2.2.4
// Generated by CoffeeScript 2.3.0
(function() {
var CoffeeScript, Module, binary, child_process, ext, findExtension, fork, getRootModule, helpers, i, len, loadFile, path, ref;

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 2.2.4
// Generated by CoffeeScript 2.3.0
(function() {
var CoffeeScript, addHistory, addMultilineHandler, fs, getCommandId, merge, nodeREPL, path, replDefaults, runInContext, sawSIGINT, transpile, updateSyntaxError, vm;

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 2.2.4
// Generated by CoffeeScript 2.3.0
(function() {
// The CoffeeScript language has a good deal of optional syntax, implicit syntax,
// and shorthand syntax. This can greatly complicate a grammar and bloat

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 2.2.4
// Generated by CoffeeScript 2.3.0
(function() {
// The **Scope** class regulates lexical scoping within CoffeeScript. As you
// generate code, you create a tree of scopes in the same shape as the nested

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 2.2.4
// Generated by CoffeeScript 2.3.0
(function() {
// Source maps allow JavaScript runtimes to match running JavaScript back to
// the original source code that corresponds to it. This can be minified

2053
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,7 @@
"compiler"
],
"author": "Jeremy Ashkenas",
"version": "2.2.4",
"version": "2.3.0",
"license": "MIT",
"engines": {
"node": ">=6"
@@ -39,17 +39,17 @@
"url": "git://github.com/jashkenas/coffeescript.git"
},
"devDependencies": {
"babel-core": "~6.26.0",
"babel-core": "~6.26.2",
"babel-preset-babili": "~0.1.4",
"babel-preset-env": "~1.6.1",
"babel-preset-minify": "^0.3.0",
"codemirror": "^5.35.0",
"babel-preset-minify": "^0.4.0",
"codemirror": "^5.37.0",
"docco": "~0.8.0",
"highlight.js": "~9.12.0",
"jison": ">=0.4.18",
"markdown-it": "~8.4.1",
"underscore": "~1.8.3",
"webpack": "~4.1.1"
"underscore": "~1.9.0",
"webpack": "~4.6.0"
},
"dependencies": {}
}

View File

@@ -216,11 +216,11 @@ grammar =
o 'Identifier'
o 'Property'
o 'ThisProperty'
o '[ Expression ]', -> new Value new ComputedPropertyName $2
]
ObjAssignable: [
o 'SimpleObjAssignable'
o '[ Expression ]', -> new Value new ComputedPropertyName $2
o 'AlphaNumeric'
]
@@ -660,26 +660,31 @@ grammar =
# Comprehensions can either be normal, with a block of expressions to execute,
# or postfix, with a single expression.
For: [
o 'Statement ForBody', -> new For $1, $2
o 'Expression ForBody', -> new For $1, $2
o 'ForBody Block', -> new For $2, $1
o 'ForLineBody Block', -> new For $2, $1
o 'Statement ForBody', -> $2.addBody $1
o 'Expression ForBody', -> $2.addBody $1
o 'ForBody Block', -> $1.addBody $2
o 'ForLineBody Block', -> $1.addBody $2
]
ForBody: [
o 'FOR Range', -> source: (LOC(2) new Value($2))
o 'FOR Range BY Expression', -> source: (LOC(2) new Value($2)), step: $4
o 'ForStart ForSource', -> $2.own = $1.own; $2.ownTag = $1.ownTag; $2.name = $1[0]; $2.index = $1[1]; $2
o 'FOR Range', -> new For [], source: (LOC(2) new Value($2))
o 'FOR Range BY Expression', -> new For [], source: (LOC(2) new Value($2)), step: $4
o 'ForStart ForSource', -> $1.addSource $2
]
ForLineBody: [
o 'FOR Range BY ExpressionLine', -> source: (LOC(2) new Value($2)), step: $4
o 'ForStart ForLineSource', -> $2.own = $1.own; $2.ownTag = $1.ownTag; $2.name = $1[0]; $2.index = $1[1]; $2
o 'FOR Range BY ExpressionLine', -> new For [], source: (LOC(2) new Value($2)), step: $4
o 'ForStart ForLineSource', -> $1.addSource $2
]
ForStart: [
o 'FOR ForVariables', -> $2
o 'FOR OWN ForVariables', -> $3.own = yes; $3.ownTag = (LOC(2) new Literal($2)); $3
o 'FOR ForVariables', -> new For [], name: $2[0], index: $2[1]
o 'FOR AWAIT ForVariables', ->
[name, index] = $3
new For [], {name, index, await: yes, awaitTag: (LOC(2) new Literal($2))}
o 'FOR OWN ForVariables', ->
[name, index] = $3
new For [], {name, index, own: yes, ownTag: (LOC(2) new Literal($2))}
]
# An array of all accepted values for a variable inside the loop.

View File

@@ -1261,7 +1261,7 @@ REGEX = /// ^
///
REGEX_FLAGS = /^\w*/
VALID_FLAGS = /^(?!.*(.).*\1)[imguy]*$/
VALID_FLAGS = /^(?!.*(.).*\1)[gimsuy]*$/
HEREGEX = /// ^
(?:

View File

@@ -1489,15 +1489,23 @@ exports.Obj = class Obj extends Base
return yes for prop in @properties when prop instanceof Splat
no
# Move rest property to the end of the list.
# `{a, rest..., b} = obj` -> `{a, b, rest...} = obj`
# `foo = ({a, rest..., b}) ->` -> `foo = {a, b, rest...}) ->`
reorderProperties: ->
props = @properties
splatProps = (i for prop, i in props when prop instanceof Splat)
props[splatProps[1]].error "multiple spread elements are disallowed" if splatProps?.length > 1
splatProp = props.splice splatProps[0], 1
@objects = @properties = [].concat props, splatProp
compileNode: (o) ->
@reorderProperties() if @hasSplat() and @lhs
props = @properties
if @generated
for node in props when node instanceof Value
node.error 'cannot have an implicit value in an implicit object'
# Object spread properties. https://github.com/tc39/proposal-object-rest-spread/blob/master/Spread.md
return @compileSpread o if @hasSplat() and not @csx
idt = o.indent += TAB
lastNode = @lastNode @properties
@@ -1558,7 +1566,7 @@ exports.Obj = class Obj extends Base
else
# `{ [expression] }` output as `{ [expression]: expression }`.
prop = new Assign key, prop.base.value, 'object'
else if not prop.bareLiteral?(IdentifierLiteral)
else if not prop.bareLiteral?(IdentifierLiteral) and prop not instanceof Splat
prop = new Assign prop, prop, 'object'
if indent then answer.push @makeCode indent
answer.push prop.compileToFragments(o, LEVEL_TOP)...
@@ -1577,30 +1585,6 @@ exports.Obj = class Obj extends Base
prop = prop.unwrapAll()
prop.eachName iterator if prop.eachName?
# Object spread properties. https://github.com/tc39/proposal-object-rest-spread/blob/master/Spread.md
# `obj2 = {a: 1, obj..., c: 3, d: 4}` → `obj2 = _extends({}, {a: 1}, obj, {c: 3, d: 4})`
compileSpread: (o) ->
props = @properties
# Store object spreads.
splatSlice = []
propSlices = []
slices = []
addSlice = ->
slices.push new Obj propSlices if propSlices.length
slices.push splatSlice... if splatSlice.length
splatSlice = []
propSlices = []
for prop in props
if prop instanceof Splat
splatSlice.push new Value prop.name
addSlice()
else
propSlices.push prop
addSlice()
slices.unshift new Obj unless slices[0] instanceof Obj
_extends = new Value new Literal utility '_extends', o
(new Call _extends, slices).compileToFragments o
compileCSXAttributes: (o) ->
props = @properties
answer = []
@@ -2213,18 +2197,17 @@ exports.Assign = class Assign extends Base
# know that, so that those nodes know that theyre assignable as
# destructured variables.
@variable.base.lhs = yes
# Check if @variable contains Obj with splats.
hasSplat = @variable.contains (node) -> node instanceof Obj and node.hasSplat()
return @compileDestructuring o if not @variable.isAssignable() or @variable.isArray() and hasSplat
# Object destructuring. Can be removed once ES proposal hits Stage 4.
objDestructAnswer = @compileObjectDestruct(o) if @variable.isObject() and hasSplat
return objDestructAnswer if objDestructAnswer
unless @variable.isAssignable()
if @variable.isObject() and @variable.base.hasSplat()
return @compileObjectDestruct o
else
return @compileDestructuring o
return @compileSplice o if @variable.isSplice()
return @compileConditional o if @context in ['||=', '&&=', '?=']
return @compileSpecialMath o if @context in ['**=', '//=', '%%=']
return @compileSpecialMath o if @context in ['//=', '%%=']
unless @context
if not @context or @context is '**='
varBase = @variable.unwrapAll()
unless varBase.isAssignable()
@variable.error "'#{@variable.compile o}' can't be assigned"
@@ -2289,92 +2272,18 @@ exports.Assign = class Assign extends Base
else
answer
# Check object destructuring variable for rest elements;
# can be removed once ES proposal hits Stage 4.
# Object rest property is not assignable: `{{a}...}`
compileObjectDestruct: (o) ->
# Returns a safe (cached) reference to the key for a given property
getPropKey = (prop) ->
if prop instanceof Assign
[prop.variable, key] = prop.variable.cache o
key
else
prop
# Returns the name of a given property for use with excludeProps
# Property names are quoted (e.g. `a: b` -> 'a'), and everything else uses the key reference
# (e.g. `'a': b -> 'a'`, `"#{a}": b` -> <cached>`)
getPropName = (prop) ->
key = getPropKey prop
cached = prop instanceof Assign and prop.variable isnt key
if cached or not key.isAssignable()
key
else
new Literal "'#{key.compileWithoutComments o}'"
# Recursive function for searching and storing rest elements in objects.
# e.g. `{[properties...]} = source`.
traverseRest = (properties, source) =>
restElements = []
restIndex = undefined
source = new Value source unless source.properties?
for prop, index in properties
nestedSourceDefault = nestedSource = nestedProperties = null
if prop instanceof Assign
# prop is `k: expr`, we need to check `expr` for nested splats
if prop.value.isObject?()
# prop is `k = {...} `
continue unless prop.context is 'object'
# prop is `k: {...}`
nestedProperties = prop.value.base.properties
else if prop.value instanceof Assign and prop.value.variable.isObject()
# prop is `k: {...} = default`
nestedProperties = prop.value.variable.base.properties
[prop.value.value, nestedSourceDefault] = prop.value.value.cache o
if nestedProperties
nestedSource = new Value source.base, source.properties.concat [new Access getPropKey prop]
nestedSource = new Value new Op '?', nestedSource, nestedSourceDefault if nestedSourceDefault
restElements.push traverseRest(nestedProperties, nestedSource)...
else if prop instanceof Splat
prop.error "multiple rest elements are disallowed in object destructuring" if restIndex?
restIndex = index
restElements.push {
name: prop.name.unwrapAll()
source
excludeProps: new Arr (getPropName p for p in properties when p isnt prop)
}
if restIndex?
# Remove rest element from the properties after iteration
properties.splice restIndex, 1
restElements
# Cache the value for reuse with rest elements.
valueRefTemp =
if @value.shouldCache()
new IdentifierLiteral o.scope.freeVariable 'ref', reserve: false
else
@value.base
# Find all rest elements.
restElements = traverseRest @variable.base.properties, valueRefTemp
return no unless restElements and restElements.length > 0
[@value, valueRef] = @value.cache o
result = new Block [@]
for restElement in restElements
value = new Call new Value(new Literal utility 'objectWithoutKeys', o), [restElement.source, restElement.excludeProps]
result.push new Assign new Value(restElement.name), value, null, param: if @param then 'alwaysDeclare' else null
fragments = result.compileToFragments o
if o.level is LEVEL_TOP
# Remove leading tab and trailing semicolon
fragments.shift()
fragments.pop()
fragments
@variable.base.reorderProperties()
{properties: props} = @variable.base
[..., splat] = props
splatProp = splat.name
assigns = []
refVal = new Value new IdentifierLiteral o.scope.freeVariable 'ref'
props.splice -1, 1, new Splat refVal
assigns.push new Assign(new Value(new Obj props), @value).compileToFragments o, LEVEL_LIST
assigns.push new Assign(new Value(splatProp), refVal).compileToFragments o, LEVEL_LIST
@joinFragmentArrays assigns, ', '
# Brief implementation of recursive pattern matching, when assigning array or
# object literals to a value. Peeks at their properties to assign inner names.
@@ -2409,12 +2318,19 @@ exports.Assign = class Assign extends Base
isSplat = splats?.length > 0
isExpans = expans?.length > 0
isObject = @variable.isObject()
isArray = @variable.isArray()
vvar = value.compileToFragments o, LEVEL_LIST
vvarText = fragmentsToText vvar
assigns = []
pushAssign = (variable, val) =>
assigns.push new Assign(variable, val, null, param: @param, subpattern: yes).compileToFragments o, LEVEL_LIST
if isSplat
splatVar = objects[splats[0]].name.unwrap()
if splatVar instanceof Arr or splatVar instanceof Obj
splatVarRef = new IdentifierLiteral o.scope.freeVariable 'ref'
objects[splats[0]].name = splatVarRef
splatVarAssign = -> pushAssign new Value(splatVar), splatVarRef
# At this point, there are several things to destructure. So the `fn()` in
# `{a, b} = fn()` must be cached, for example. Make vvar into a simple
@@ -2438,10 +2354,6 @@ exports.Assign = class Assign extends Base
# Helper which outputs `[].splice` code.
compSplice = slicer "splice"
# Check if `objects` array contains object spread (`{a, r...}`), e.g. `[a, b, {c, r...}]`.
hasObjSpreads = (objs) ->
(i for obj, i in objs when obj.base instanceof Obj and obj.base.hasSplat())
# Check if `objects` array contains any instance of `Assign`, e.g. {a:1}.
hasObjAssigns = (objs) ->
(i for obj, i in objs when obj instanceof Assign and obj.context is 'object')
@@ -2451,15 +2363,14 @@ exports.Assign = class Assign extends Base
return yes for obj in objs when not obj.isAssignable()
no
# `objects` are complex when there is object spread ({a...}), object assign ({a:1}),
# `objects` are complex when there is object assign ({a:1}),
# unassignable object, or just a single node.
complexObjects = (objs) ->
hasObjSpreads(objs).length or hasObjAssigns(objs).length or objIsUnassignable(objs) or olen is 1
hasObjAssigns(objs).length or objIsUnassignable(objs) or olen is 1
# "Complex" `objects` are processed in a loop.
# Examples: [a, b, {c, r...}, d], [a, ..., {b, r...}, c, d]
loopObjects = (objs, vvar, vvarTxt) =>
objSpreads = hasObjSpreads objs
for obj, i in objs
# `Elision` can be skipped.
continue if obj instanceof Elision
@@ -2478,20 +2389,19 @@ exports.Assign = class Assign extends Base
# `obj` is [a...], {a...} or a
vvar = switch
when obj instanceof Splat then new Value obj.name
when i in objSpreads then new Value obj.base
else obj
vval = switch
when obj instanceof Splat then compSlice(vvarTxt, i)
else new Value new Literal(vvarTxt), [new Index new NumberLiteral i]
message = isUnassignable vvar.unwrap().value
vvar.error message if message
assigns.push new Assign(vvar, vval, null, param: @param, subpattern: yes).compileToFragments o, LEVEL_LIST
pushAssign vvar, vval
# "Simple" `objects` can be split and compiled to arrays, [a, b, c] = arr, [a, b, c...] = arr
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
pushAssign vvar, vval
processObjects = (objs, vvar, vvarTxt) ->
if complexObjects objs
@@ -2528,6 +2438,7 @@ exports.Assign = class Assign extends Base
else
# There is no `Splat` or `Expansion` in `objects`.
processObjects objects, vvar, vvarText
splatVarAssign?()
assigns.push vvar unless top or @subpattern
fragments = @joinFragmentArrays assigns, ', '
if o.level < LEVEL_LIST then fragments else @wrapInParentheses fragments
@@ -2548,7 +2459,7 @@ exports.Assign = class Assign extends Base
fragments = new Op(@context[...-1], left, new Assign(right, @value, '=')).compileToFragments o
if o.level <= LEVEL_LIST then fragments else @wrapInParentheses fragments
# Convert special math assignment operators like `a **= b` to the equivalent
# Convert special math assignment operators like `a //= b` to the equivalent
# extended form `a = a ** b` and then compiles that.
compileSpecialMath: (o) ->
[left, right] = @variable.cacheReference o
@@ -2610,8 +2521,8 @@ exports.Code = class Code extends Base
@isGenerator = yes
if (node instanceof Op and node.isAwait()) or node instanceof AwaitReturn
@isAsync = yes
if @isGenerator and @isAsync
node.error "function can't contain both yield and await"
if node instanceof For and node.isAwait()
@isAsync = yes
children: ['params', 'body']
@@ -2689,7 +2600,7 @@ exports.Code = class Code extends Base
param.error 'an expansion parameter cannot be the only parameter in a function definition'
haveSplatParam = yes
if param.splat
if param.name instanceof Arr
if param.name instanceof Arr or param.name instanceof Obj
# Splat arrays are treated oddly by ES; deal with them the legacy
# way in the function body. TODO: Should this be handled in the
# function parameter list, and if so, how?
@@ -2743,17 +2654,7 @@ exports.Code = class Code extends Base
if param.name instanceof Arr or param.name instanceof Obj
# This parameter is destructured.
param.name.lhs = yes
# Compile `foo({a, b...}) ->` to `foo(arg) -> {a, b...} = arg`.
# Can be removed once ES proposal hits Stage 4.
if param.name instanceof Obj and param.name.hasSplat()
splatParamName = o.scope.freeVariable 'arg'
o.scope.parameter splatParamName
ref = new Value new IdentifierLiteral splatParamName
exprs.push new Assign new Value(param.name), ref, null, param: 'alwaysDeclare'
# Compile `foo({a, b...} = {}) ->` to `foo(arg = {}) -> {a, b...} = arg`.
if param.value? and not param.assignedInBody
ref = new Assign ref, param.value, null, param: yes
else unless param.shouldCache()
unless param.shouldCache()
param.name.eachName (prop) ->
o.scope.parameter prop.value
else
@@ -3028,7 +2929,10 @@ exports.Splat = class Splat extends Base
children: ['name']
shouldCache: -> no
isAssignable: ->
return no if @name instanceof Obj or @name instanceof Parens
@name.isAssignable() and (not @name.isAtomic or @name.isAtomic())
assigns: (name) ->
@@ -3253,7 +3157,6 @@ exports.Op = class Op extends Base
return @compileChain o if isChain
switch @operator
when '?' then @compileExistence o, @second.isDefaultValue
when '**' then @compilePower o
when '//' then @compileFloorDivision o
when '%%' then @compileModulo o
else
@@ -3320,11 +3223,6 @@ exports.Op = class Op extends Base
parts.push [@makeCode ")"] if o.level >= LEVEL_PAREN
@joinFragmentArrays parts, ''
compilePower: (o) ->
# Make a Math.pow call
pow = new Value new IdentifierLiteral('Math'), [new Access new PropertyName 'pow']
new Call(pow, [@first, @second]).compileToFragments o
compileFloorDivision: (o) ->
floor = new Value new IdentifierLiteral('Math'), [new Access new PropertyName 'floor']
second = if @second.shouldCache() then new Parens @second else @second
@@ -3621,15 +3519,27 @@ exports.StringWithInterpolations = class StringWithInterpolations extends Base
exports.For = class For extends While
constructor: (body, source) ->
super()
{@source, @guard, @step, @name, @index} = source
@body = Block.wrap [body]
@own = source.own?
@object = source.object?
@from = source.from?
@addBody body
@addSource source
children: ['body', 'source', 'guard', 'step']
isAwait: -> @await ? no
addBody: (body) ->
@body = Block.wrap [body]
this
addSource: (source) ->
{@source = no} = source
attribs = ["name", "index", "guard", "step", "own", "ownTag", "await", "awaitTag", "object", "from"]
@[attr] = source[attr] ? @[attr] for attr in attribs
return this unless @source
@index.error 'cannot use index with for-from' if @from and @index
source.ownTag.error "cannot use own with for-#{if @from then 'from' else 'in'}" if @own and not @object
@ownTag.error "cannot use own with for-#{if @from then 'from' else 'in'}" if @own and not @object
[@name, @index] = [@index, @name] if @object
@index.error 'index cannot be a pattern matching expression' if @index?.isArray?() or @index?.isObject?()
@awaitTag.error 'await must be used with for-from' if @await and not @from
@range = @source instanceof Value and @source.base instanceof Range and not @source.properties.length and not @from
@pattern = @name instanceof Value
@index.error 'indexes do not apply to range loops' if @range and @index
@@ -3648,8 +3558,7 @@ exports.For = class For extends While
comment.newLine = comment.unshift = yes for comment in node.comments
moveComments node, @[attribute]
moveComments @[attribute], @
children: ['body', 'source', 'guard', 'step']
this
# Welcome to the hairiest method in all of CoffeeScript. Handles the inner
# loop, filtering, stepping, and result saving for array, object, and range
@@ -3727,15 +3636,21 @@ exports.For = class For extends While
forPartFragments = [@makeCode("#{kvar} in #{svar}")]
guardPart = "\n#{idt1}if (!#{utility 'hasProp', o}.call(#{svar}, #{kvar})) continue;" if @own
else if @from
forPartFragments = [@makeCode("#{kvar} of #{svar}")]
if @await
forPartFragments = new Op 'await', new Parens new Literal "#{kvar} of #{svar}"
forPartFragments = forPartFragments.compileToFragments o, LEVEL_TOP
else
forPartFragments = [@makeCode("#{kvar} of #{svar}")]
bodyFragments = body.compileToFragments merge(o, indent: idt1), LEVEL_TOP
if bodyFragments and bodyFragments.length > 0
bodyFragments = [].concat @makeCode('\n'), bodyFragments, @makeCode('\n')
fragments = [@makeCode(defPart)]
fragments.push @makeCode(resultPart) if resultPart
fragments = fragments.concat @makeCode(@tab), @makeCode( 'for ('),
forPartFragments, @makeCode(") {#{guardPart}#{varPart}"), bodyFragments,
forCode = if @await then 'for ' else 'for ('
forClose = if @await then '' else ')'
fragments = fragments.concat @makeCode(@tab), @makeCode( forCode),
forPartFragments, @makeCode("#{forClose} {#{guardPart}#{varPart}"), bodyFragments,
@makeCode(@tab), @makeCode('}')
fragments.push @makeCode(returnResult) if returnResult
fragments
@@ -3872,13 +3787,7 @@ exports.If = class If extends Base
UTILITIES =
modulo: -> 'function(a, b) { return (+a % (b = +b) + b) % b; }'
objectWithoutKeys: -> "
function(o, ks) {
var res = {};
for (var k in o) ([].indexOf.call(ks, k) < 0 && {}.hasOwnProperty.call(o, k)) && (res[k] = o[k]);
return res;
}
"
boundMethodCheck: -> "
function(instance, Constructor) {
if (!(instance instanceof Constructor)) {
@@ -3886,19 +3795,6 @@ UTILITIES =
}
}
"
_extends: -> "
Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
}
"
# Shortcuts to speed up the lookup time for native functions.
hasProp: -> '{}.hasOwnProperty'

View File

@@ -185,17 +185,6 @@ test "#4787 destructuring of objects within arrays", ->
eq b, arr[1].b
deepEqual {a, b}, arr[1]
test "#4798 destructuring of objects with splat within arrays", ->
arr = [1, {a:1, b:2}]
[...,{a, r...}] = arr
eq a, 1
deepEqual r, {b:2}
[b, {q...}] = arr
eq b, 1
deepEqual q, arr[1]
eq q.b, r.b
eq q.a, a
test "destructuring assignment with splats", ->
a = {}; b = {}; c = {}; d = {}; e = {}
[x,y...,z] = [a,b,c,d,e]
@@ -264,311 +253,6 @@ test "destructuring assignment against an expression", ->
eq a, y
eq b, z
test "destructuring assignment with objects and splats: ES2015", ->
obj = {a: 1, b: 2, c: 3, d: 4, e: 5}
throws (-> CoffeeScript.compile "{a, r..., s...} = x"), null, "multiple rest elements are disallowed"
throws (-> CoffeeScript.compile "{a, r..., s..., b} = x"), null, "multiple rest elements are disallowed"
prop = "b"
{a, b, r...} = obj
eq a, 1
eq b, 2
eq r.e, obj.e
eq r.a, undefined
{d, c: x, r...} = obj
eq x, 3
eq d, 4
eq r.c, undefined
eq r.b, 2
{a, 'b': z, g = 9, r...} = obj
eq g, 9
eq z, 2
eq r.b, undefined
test "destructuring assignment with splats and default values", ->
obj = {}
c = {b: 1}
{ a: {b} = c, d...} = obj
eq b, 1
deepEqual d, {}
# Should not trigger implicit call, e.g. rest ... => rest(...)
{
a: {b} = c
d ...
} = obj
eq b, 1
deepEqual d, {}
test "destructuring assignment with splat with default value", ->
obj = {}
c = {val: 1}
{ a: {b...} = c } = obj
deepEqual b, val: 1
test "destructuring assignment with multiple splats in different objects", ->
obj = { a: {val: 1}, b: {val: 2} }
{ a: {a...}, b: {b...} } = obj
deepEqual a, val: 1
deepEqual b, val: 2
o = {
props: {
p: {
n: 1
m: 5
}
s: 6
}
}
{p: {m, q..., t = {obj...}}, r...} = o.props
eq m, o.props.p.m
deepEqual r, s: 6
deepEqual q, n: 1
deepEqual t, obj
@props = o.props
{p: {m}, r...} = @props
eq m, @props.p.m
deepEqual r, s: 6
{p: {m}, r...} = {o.props..., p:{m:9}}
eq m, 9
# Should not trigger implicit call, e.g. rest ... => rest(...)
{
a: {
a ...
}
b: {
b ...
}
} = obj
deepEqual a, val: 1
deepEqual b, val: 2
test "destructuring assignment with dynamic keys and splats", ->
i = 0
foo = -> ++i
obj = {1: 'a', 2: 'b'}
{ "#{foo()}": a, b... } = obj
eq a, 'a'
eq i, 1
deepEqual b, 2: 'b'
# Tests from https://babeljs.io/docs/plugins/transform-object-rest-spread/.
test "destructuring assignment with objects and splats: Babel tests", ->
# What Babel calls “rest properties:”
{ x, y, z... } = { x: 1, y: 2, a: 3, b: 4 }
eq x, 1
eq y, 2
deepEqual z, { a: 3, b: 4 }
# What Babel calls “spread properties:”
n = { x, y, z... }
deepEqual n, { x: 1, y: 2, a: 3, b: 4 }
# Should not trigger implicit call, e.g. rest ... => rest(...)
{ x, y, z ... } = { x: 1, y: 2, a: 3, b: 4 }
eq x, 1
eq y, 2
deepEqual z, { a: 3, b: 4 }
n = { x, y, z ... }
deepEqual n, { x: 1, y: 2, a: 3, b: 4 }
test "deep destructuring assignment with objects: ES2015", ->
a1={}; b1={}; c1={}; d1={}
obj = {
a: a1
b: {
'c': {
d: {
b1
e: c1
f: d1
}
}
}
b2: {b1, c1}
}
{a: w, b: {c: {d: {b1: bb, r1...}}}, r2...} = obj
eq r1.e, c1
eq r2.b, undefined
eq bb, b1
eq r2.b2, obj.b2
# Should not trigger implicit call, e.g. rest ... => rest(...)
{a: w, b: {c: {d: {b1: bb, r1 ...}}}, r2 ...} = obj
eq r1.e, c1
eq r2.b, undefined
eq bb, b1
eq r2.b2, obj.b2
test "deep destructuring assignment with defaults: ES2015", ->
obj =
b: { c: 1, baz: 'qux' }
foo: 'bar'
j =
f: 'world'
i =
some: 'prop'
{
a...
b: { c, d... }
e: {
f: hello
g: { h... } = i
} = j
} = obj
deepEqual a, foo: 'bar'
eq c, 1
deepEqual d, baz: 'qux'
eq hello, 'world'
deepEqual h, some: 'prop'
# Should not trigger implicit call, e.g. rest ... => rest(...)
{
a ...
b: {
c,
d ...
}
e: {
f: hello
g: {
h ...
} = i
} = j
} = obj
deepEqual a, foo: 'bar'
eq c, 1
deepEqual d, baz: 'qux'
eq hello, 'world'
deepEqual h, some: 'prop'
test "object spread properties: ES2015", ->
obj = {a: 1, b: 2, c: 3, d: 4, e: 5}
obj2 = {obj..., c:9}
eq obj2.c, 9
eq obj.a, obj2.a
# Should not trigger implicit call, e.g. rest ... => rest(...)
obj2 = {
obj ...
c:9
}
eq obj2.c, 9
eq obj.a, obj2.a
obj2 = {obj..., a: 8, c: 9, obj...}
eq obj2.c, 3
eq obj.a, obj2.a
# Should not trigger implicit call, e.g. rest ... => rest(...)
obj2 = {
obj ...
a: 8
c: 9
obj ...
}
eq obj2.c, 3
eq obj.a, obj2.a
obj3 = {obj..., b: 7, g: {obj2..., c: 1}}
eq obj3.g.c, 1
eq obj3.b, 7
deepEqual obj3.g, {obj..., c: 1}
(({a, b, r...}) ->
eq 1, a
deepEqual r, {c: 3, d: 44, e: 55}
) {obj2..., d: 44, e: 55}
obj = {a: 1, b: 2, c: {d: 3, e: 4, f: {g: 5}}}
obj4 = {a: 10, obj.c...}
eq obj4.a, 10
eq obj4.d, 3
eq obj4.f.g, 5
deepEqual obj4.f, obj.c.f
# Should not trigger implicit call, e.g. rest ... => rest(...)
(({
a
b
r ...
}) ->
eq 1, a
deepEqual r, {c: 3, d: 44, e: 55}
) {
obj2 ...
d: 44
e: 55
}
# Should not trigger implicit call, e.g. rest ... => rest(...)
obj4 = {
a: 10
obj.c ...
}
eq obj4.a, 10
eq obj4.d, 3
eq obj4.f.g, 5
deepEqual obj4.f, obj.c.f
obj5 = {obj..., ((k) -> {b: k})(99)...}
eq obj5.b, 99
deepEqual obj5.c, obj.c
# Should not trigger implicit call, e.g. rest ... => rest(...)
obj5 = {
obj ...
((k) -> {b: k})(99) ...
}
eq obj5.b, 99
deepEqual obj5.c, obj.c
fn = -> {c: {d: 33, e: 44, f: {g: 55}}}
obj6 = {obj..., fn()...}
eq obj6.c.d, 33
deepEqual obj6.c, {d: 33, e: 44, f: {g: 55}}
obj7 = {obj..., fn()..., {c: {d: 55, e: 66, f: {77}}}...}
eq obj7.c.d, 55
deepEqual obj6.c, {d: 33, e: 44, f: {g: 55}}
# Should not trigger implicit call, e.g. rest ... => rest(...)
obj7 = {
obj ...
fn() ...
{c: {d: 55, e: 66, f: {77}}} ...
}
eq obj7.c.d, 55
deepEqual obj6.c, {d: 33, e: 44, f: {g: 55}}
obj =
a:
b:
c:
d:
e: {}
obj9 = {a:1, obj.a.b.c..., g:3}
deepEqual obj9.d, {e: {}}
a = "a"
c = "c"
obj9 = {a:1, obj[a].b[c]..., g:3}
deepEqual obj9.d, {e: {}}
obj9 = {a:1, obj.a["b"].c["d"]..., g:3}
deepEqual obj9["e"], {}
test "bracket insertion when necessary", ->
[a] = [0] ? [1]
eq a, 0
@@ -916,36 +600,6 @@ test "#4566: destructuring with nested default values", ->
{e: {f = 5} = {}} = {}
eq 5, f
test "#4674: _extends utility for object spreads 1", ->
eqJS(
"{a, b..., c..., d}"
"""
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
_extends({a}, b, c, {d});
"""
)
test "#4674: _extends utility for object spreads 2", ->
_extends = -> 3
a = b: 1
c = d: 2
e = {a..., c...}
eq e.b, 1
eq e.d, 2
test "#4673: complex destructured object spread variables", ->
b = c: 1
{{a...}...} = b
eq a.c, 1
d = {}
{d.e...} = f: 1
eq d.e.f, 1
{{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']
@@ -1032,3 +686,38 @@ test "#5004: array destructuring with accessors", ->
[obj.list.middle..., d] = obj.arr
eq d, 'd'
arrayEq obj.list.middle, ['a', 'b', 'c']
test "#4884: destructured object splat", ->
[{length}...] = [1, 2, 3]
eq length, 3
[{length: len}...] = [1, 2, 3]
eq len, 3
[{length}..., three] = [1, 2, 3]
eq length, 2
eq three, 3
[{length: len}..., three] = [1, 2, 3]
eq len, 2
eq three, 3
x = [{length}..., three] = [1, 2, 3]
eq length, 2
eq three, 3
eq x[2], 3
x = [{length: len}..., three] = [1, 2, 3]
eq len, 2
eq three, 3
eq x[2], 3
test "#4884: destructured array splat", ->
[[one, two, three]...] = [1, 2, 3]
eq one, 1
eq two, 2
eq three, 3
[[one, two]..., three] = [1, 2, 3]
eq one, 1
eq two, 2
eq three, 3
x = [[one, two]..., three] = [1, 2, 3]
eq one, 1
eq two, 2
eq three, 3
eq x[2], 3

View File

@@ -0,0 +1,32 @@
# This is always fulfilled.
winLater = (val, ms) ->
new Promise (resolve) -> setTimeout (-> resolve val), ms
# This is always rejected.
failLater = (val, ms) ->
new Promise (resolve, reject) -> setTimeout (-> reject new Error val), ms
createAsyncIterable = (syncIterable) ->
for elem in syncIterable
yield await winLater elem, 50
test "async iteration", ->
foo = (x for await x from createAsyncIterable [1,2,3])
arrayEq foo, [1, 2, 3]
test "async generator functions", ->
foo = (val) ->
yield await winLater val + 1, 50
bar = (val) ->
yield await failLater val - 1, 50
a = await foo(41).next()
eq a.value, 42
try
b = do -> await bar(41).next()
b.catch (err) ->
eq "40", err.message
catch err
ok no

View File

@@ -1230,28 +1230,6 @@ test "CoffeeScript keywords cannot be used as local names in import list aliases
^^^^^^
'''
test "function cannot contain both `await` and `yield`", ->
assertErrorFormat '''
f = () ->
yield 5
await a
''', '''
[stdin]:3:3: error: function can't contain both yield and await
await a
^^^^^^^
'''
test "function cannot contain both `await` and `yield from`", ->
assertErrorFormat '''
f = () ->
yield from a
await b
''', '''
[stdin]:3:3: error: function can't contain both yield and await
await b
^^^^^^^
'''
test "cannot have `await` outside a function", ->
assertErrorFormat '''
await 1

View File

@@ -8,7 +8,7 @@ nonce = {}
# Throw
test "basic exception throwing", ->
throws (-> throw 'error'), 'error'
throws (-> throw 'error'), /^error$/
# Empty Try/Catch/Finally

View File

@@ -0,0 +1,19 @@
# The `**` and `**=` operators are only supported in Node 7.5+, so the tests
# for these exponentiation operators are split out into their own file to be
# loaded only by supported runtimes.
test "exponentiation operator", ->
eq 27, 3 ** 3
test "exponentiation operator has higher precedence than other maths operators", ->
eq 55, 1 + 3 ** 3 * 2
eq -4, -2 ** 2
eq 0, (!2) ** 2
test "exponentiation operator is right associative", ->
eq 2, 2 ** 1 ** 3
test "exponentiation operator compound assignment", ->
a = 2
a **= 3
eq 8, a

View File

@@ -127,6 +127,16 @@ test "destructured splatted parameters", ->
splatArray = ([a ...]) -> a
splatArrayRest = ([a ...],b ...) -> arrayEq(a,b); b
test "#4884: object-destructured splatted parameters", ->
f = ({length}...) -> length
eq f(4, 5, 6), 3
f = ({length: len}...) -> len
eq f(4, 5, 6), 3
f = ({length}..., last) -> [length, last]
arrayEq f(4, 5, 6), [2, 6]
f = ({length: len}..., last) -> [len, last]
arrayEq f(4, 5, 6), [2, 6]
test "@-parameters: automatically assign an argument's value to a property of the context", ->
nonce = {}
@@ -215,86 +225,6 @@ test "destructuring in function definition", ->
url: '/home', async: true, beforeSend: fn, cache: true, method: 'post', data: {}
}
test "rest element destructuring in function definition", ->
obj = {a: 1, b: 2, c: 3, d: 4, e: 5}
(({a, b, r...}) ->
eq 1, a
eq 2, b,
deepEqual r, {c: 3, d: 4, e: 5}
) obj
(({a: p, b, r...}, q) ->
eq p, 1
eq q, 9
deepEqual r, {c: 3, d: 4, e: 5}
) {a:1, b:2, c:3, d:4, e:5}, 9
# Should not trigger implicit call, e.g. rest ... => rest(...)
(({
a: p
b
r ...
}, q) ->
eq p, 1
eq q, 9
deepEqual r, {c: 3, d: 4, e: 5}
) {a:1, b:2, c:3, d:4, e:5}, 9
a1={}; b1={}; c1={}; d1={}
obj1 = {
a: a1
b: {
'c': {
d: {
b1
e: c1
f: d1
}
}
}
b2: {b1, c1}
}
(({a: w, b: {c: {d: {b1: bb, r1...}}}, r2...}) ->
eq a1, w
eq bb, b1
eq r2.b, undefined
deepEqual r1, {e: c1, f: d1}
deepEqual r2.b2, {b1, c1}
) obj1
b = 3
f = ({a, b...}) ->
f {}
eq 3, b
(({a, r...} = {}) ->
eq a, undefined
deepEqual r, {}
)()
(({a, r...} = {}) ->
eq a, 1
deepEqual r, {b: 2, c: 3}
) {a: 1, b: 2, c: 3}
f = ({a, r...} = {}) -> [a, r]
deepEqual [undefined, {}], f()
deepEqual [1, {b: 2}], f {a: 1, b: 2}
deepEqual [1, {}], f {a: 1}
f = ({a, r...} = {a: 1, b: 2}) -> [a, r]
deepEqual [1, {b:2}], f()
deepEqual [2, {}], f {a:2}
deepEqual [3, {c:5}], f {a:3, c:5}
f = ({ a: aa = 0, b: bb = 0 }) -> [aa, bb]
deepEqual [0, 0], f {}
deepEqual [0, 42], f {b:42}
deepEqual [42, 0], f {a:42}
deepEqual [42, 43], f {a:42, b:43}
test "#4005: `([a = {}]..., b) ->` weirdness", ->
fn = ([a = {}]..., b) -> [a, b]
deepEqual fn(5), [{}, 5]
@@ -550,15 +480,6 @@ test "#4413: expressions in function parameters that create generated variables
eq f(), 33
eq g(), 34
test "#4673: complex destructured object spread variables", ->
f = ({{a...}...}) ->
a
eq f(c: 1).c, 1
g = ({@y...}) ->
eq @y.b, 1
g b: 1
test "#4657: destructured array param declarations", ->
a = 1
b = 2

View File

@@ -168,7 +168,7 @@ test "`throw` can be yielded", ->
throws -> x.next()
test "symbolic operators has precedence over the `yield`", ->
symbolic = '+ - * / << >> & | || && ** ^ // or and'.split ' '
symbolic = '+ - * / << >> & | || && ^ // or and'.split ' '
compound = ("#{op}=" for op in symbolic)
relations = '< > == != <= >= is isnt'.split ' '

View File

@@ -139,7 +139,7 @@ eq 'multiline nested "interpolations" work', """multiline #{
eq 'function(){}', "#{->}".replace /\s/g, ''
ok /^a[\s\S]+b$/.test "a#{=>}b"
ok /^a[\s\S]+b$/.test "a#{ (x) -> x ** 2 }b"
ok /^a[\s\S]+b$/.test "a#{ (x) -> x %% 2 }b"
# Regular Expression Interpolation

View File

@@ -0,0 +1,420 @@
test "#4798 destructuring of objects with splat within arrays", ->
arr = [1, {a:1, b:2}]
[...,{a, r...}] = arr
eq a, 1
deepEqual r, {b:2}
[b, {q...}] = arr
eq b, 1
deepEqual q, arr[1]
eq q.b, r.b
eq q.a, a
arr2 = [arr[1]]
[{a2...}] = arr2
eq a2.a, arr2[0].a
test "destructuring assignment with objects and splats: ES2015", ->
obj = {a: 1, b: 2, c: 3, d: 4, e: 5}
throws (-> CoffeeScript.compile "{a, r..., s...} = x"), null, "multiple rest elements are disallowed"
throws (-> CoffeeScript.compile "{a, r..., s..., b} = x"), null, "multiple rest elements are disallowed"
prop = "b"
{a, b, r...} = obj
eq a, 1
eq b, 2
eq r.e, obj.e
eq r.a, undefined
{d, c: x, r...} = obj
eq x, 3
eq d, 4
eq r.c, undefined
eq r.b, 2
{a, 'b': z, g = 9, r...} = obj
eq g, 9
eq z, 2
eq r.b, undefined
test "destructuring assignment with splats and default values", ->
obj = {}
c = {b: 1}
{ a: {b} = c, d...} = obj
eq b, 1
deepEqual d, {}
# Should not trigger implicit call, e.g. rest ... => rest(...)
{
a: {b} = c
d ...
} = obj
eq b, 1
deepEqual d, {}
test "destructuring assignment with splat with default value", ->
obj = {}
c = {val: 1}
{ a: {b...} = c } = obj
deepEqual b, val: 1
test "destructuring assignment with multiple splats in different objects", ->
obj = { a: {val: 1}, b: {val: 2} }
{ a: {a...}, b: {b...} } = obj
deepEqual a, val: 1
deepEqual b, val: 2
o = {
props: {
p: {
n: 1
m: 5
}
s: 6
}
}
{p: {m, q..., t = {obj...}}, r...} = o.props
eq m, o.props.p.m
deepEqual r, s: 6
deepEqual q, n: 1
deepEqual t, obj
@props = o.props
{p: {m}, r...} = @props
eq m, @props.p.m
deepEqual r, s: 6
{p: {m}, r...} = {o.props..., p:{m:9}}
eq m, 9
# Should not trigger implicit call, e.g. rest ... => rest(...)
{
a: {
a ...
}
b: {
b ...
}
} = obj
deepEqual a, val: 1
deepEqual b, val: 2
test "destructuring assignment with dynamic keys and splats", ->
i = 0
foo = -> ++i
obj = {1: 'a', 2: 'b'}
{ "#{foo()}": a, b... } = obj
eq a, 'a'
eq i, 1
deepEqual b, 2: 'b'
# Tests from https://babeljs.io/docs/plugins/transform-object-rest-spread/.
test "destructuring assignment with objects and splats: Babel tests", ->
# What Babel calls “rest properties:”
{ x, y, z... } = { x: 1, y: 2, a: 3, b: 4 }
eq x, 1
eq y, 2
deepEqual z, { a: 3, b: 4 }
# What Babel calls “spread properties:”
n = { x, y, z... }
deepEqual n, { x: 1, y: 2, a: 3, b: 4 }
# Should not trigger implicit call, e.g. rest ... => rest(...)
{ x, y, z ... } = { x: 1, y: 2, a: 3, b: 4 }
eq x, 1
eq y, 2
deepEqual z, { a: 3, b: 4 }
n = { x, y, z ... }
deepEqual n, { x: 1, y: 2, a: 3, b: 4 }
test "deep destructuring assignment with objects: ES2015", ->
a1={}; b1={}; c1={}; d1={}
obj = {
a: a1
b: {
'c': {
d: {
b1
e: c1
f: d1
}
}
}
b2: {b1, c1}
}
{a: w, b: {c: {d: {b1: bb, r1...}}}, r2...} = obj
eq r1.e, c1
eq r2.b, undefined
eq bb, b1
eq r2.b2, obj.b2
# Should not trigger implicit call, e.g. rest ... => rest(...)
{a: w, b: {c: {d: {b1: bb, r1 ...}}}, r2 ...} = obj
eq r1.e, c1
eq r2.b, undefined
eq bb, b1
eq r2.b2, obj.b2
test "deep destructuring assignment with defaults: ES2015", ->
obj =
b: { c: 1, baz: 'qux' }
foo: 'bar'
j =
f: 'world'
i =
some: 'prop'
{
a...
b: { c, d... }
e: {
f: hello
g: { h... } = i
} = j
} = obj
deepEqual a, foo: 'bar'
eq c, 1
deepEqual d, baz: 'qux'
eq hello, 'world'
deepEqual h, some: 'prop'
# Should not trigger implicit call, e.g. rest ... => rest(...)
{
a ...
b: {
c,
d ...
}
e: {
f: hello
g: {
h ...
} = i
} = j
} = obj
deepEqual a, foo: 'bar'
eq c, 1
deepEqual d, baz: 'qux'
eq hello, 'world'
deepEqual h, some: 'prop'
test "object spread properties: ES2015", ->
obj = {a: 1, b: 2, c: 3, d: 4, e: 5}
obj2 = {obj..., c:9}
eq obj2.c, 9
eq obj.a, obj2.a
# Should not trigger implicit call, e.g. rest ... => rest(...)
obj2 = {
obj ...
c:9
}
eq obj2.c, 9
eq obj.a, obj2.a
obj2 = {obj..., a: 8, c: 9, obj...}
eq obj2.c, 3
eq obj.a, obj2.a
# Should not trigger implicit call, e.g. rest ... => rest(...)
obj2 = {
obj ...
a: 8
c: 9
obj ...
}
eq obj2.c, 3
eq obj.a, obj2.a
obj3 = {obj..., b: 7, g: {obj2..., c: 1}}
eq obj3.g.c, 1
eq obj3.b, 7
deepEqual obj3.g, {obj..., c: 1}
(({a, b, r...}) ->
eq 1, a
deepEqual r, {c: 3, d: 44, e: 55}
) {obj2..., d: 44, e: 55}
obj = {a: 1, b: 2, c: {d: 3, e: 4, f: {g: 5}}}
obj4 = {a: 10, obj.c...}
eq obj4.a, 10
eq obj4.d, 3
eq obj4.f.g, 5
deepEqual obj4.f, obj.c.f
# Should not trigger implicit call, e.g. rest ... => rest(...)
(({
a
b
r ...
}) ->
eq 1, a
deepEqual r, {c: 3, d: 44, e: 55}
) {
obj2 ...
d: 44
e: 55
}
# Should not trigger implicit call, e.g. rest ... => rest(...)
obj4 = {
a: 10
obj.c ...
}
eq obj4.a, 10
eq obj4.d, 3
eq obj4.f.g, 5
deepEqual obj4.f, obj.c.f
obj5 = {obj..., ((k) -> {b: k})(99)...}
eq obj5.b, 99
deepEqual obj5.c, obj.c
# Should not trigger implicit call, e.g. rest ... => rest(...)
obj5 = {
obj ...
((k) -> {b: k})(99) ...
}
eq obj5.b, 99
deepEqual obj5.c, obj.c
fn = -> {c: {d: 33, e: 44, f: {g: 55}}}
obj6 = {obj..., fn()...}
eq obj6.c.d, 33
deepEqual obj6.c, {d: 33, e: 44, f: {g: 55}}
obj7 = {obj..., fn()..., {c: {d: 55, e: 66, f: {77}}}...}
eq obj7.c.d, 55
deepEqual obj6.c, {d: 33, e: 44, f: {g: 55}}
# Should not trigger implicit call, e.g. rest ... => rest(...)
obj7 = {
obj ...
fn() ...
{c: {d: 55, e: 66, f: {77}}} ...
}
eq obj7.c.d, 55
deepEqual obj6.c, {d: 33, e: 44, f: {g: 55}}
obj =
a:
b:
c:
d:
e: {}
obj9 = {a:1, obj.a.b.c..., g:3}
deepEqual obj9.d, {e: {}}
a = "a"
c = "c"
obj9 = {a:1, obj[a].b[c]..., g:3}
deepEqual obj9.d, {e: {}}
obj9 = {a:1, obj.a["b"].c["d"]..., g:3}
deepEqual obj9["e"], {}
test "#4673: complex destructured object spread variables", ->
b = c: 1
{{a...}...} = b
eq a.c, 1
d = {}
{d.e...} = f: 1
eq d.e.f, 1
{{g}...} = g: 1
eq g, 1
test "rest element destructuring in function definition", ->
obj = {a: 1, b: 2, c: 3, d: 4, e: 5}
(({a, b, r...}) ->
eq 1, a
eq 2, b,
deepEqual r, {c: 3, d: 4, e: 5}
) obj
(({a: p, b, r...}, q) ->
eq p, 1
eq q, 9
deepEqual r, {c: 3, d: 4, e: 5}
) {a:1, b:2, c:3, d:4, e:5}, 9
# Should not trigger implicit call, e.g. rest ... => rest(...)
(({
a: p
b
r ...
}, q) ->
eq p, 1
eq q, 9
deepEqual r, {c: 3, d: 4, e: 5}
) {a:1, b:2, c:3, d:4, e:5}, 9
a1={}; b1={}; c1={}; d1={}
obj1 = {
a: a1
b: {
'c': {
d: {
b1
e: c1
f: d1
}
}
}
b2: {b1, c1}
}
(({a: w, b: {c: {d: {b1: bb, r1...}}}, r2...}) ->
eq a1, w
eq bb, b1
eq r2.b, undefined
deepEqual r1, {e: c1, f: d1}
deepEqual r2.b2, {b1, c1}
) obj1
b = 3
f = ({a, b...}) ->
f {}
eq 3, b
(({a, r...} = {}) ->
eq a, undefined
deepEqual r, {}
)()
(({a, r...} = {}) ->
eq a, 1
deepEqual r, {b: 2, c: 3}
) {a: 1, b: 2, c: 3}
f = ({a, r...} = {}) -> [a, r]
deepEqual [undefined, {}], f()
deepEqual [1, {b: 2}], f {a: 1, b: 2}
deepEqual [1, {}], f {a: 1}
f = ({a, r...} = {a: 1, b: 2}) -> [a, r]
deepEqual [1, {b:2}], f()
deepEqual [2, {}], f {a:2}
deepEqual [3, {c:5}], f {a:3, c:5}
f = ({ a: aa = 0, b: bb = 0 }) -> [aa, bb]
deepEqual [0, 0], f {}
deepEqual [0, 42], f {b:42}
deepEqual [42, 0], f {a:42}
deepEqual [42, 43], f {a:42, b:43}
test "#4673: complex destructured object spread variables", ->
f = ({{a...}...}) ->
a
eq f(c: 1).c, 1
g = ({@y...}) ->
eq @y.b, 1
g b: 1

View File

@@ -305,24 +305,6 @@ test "#2508: Existential access of the prototype", ->
eq NonExistent?::nothing, undefined
ok Object?::toString
test "power operator", ->
eq 27, 3 ** 3
test "power operator has higher precedence than other maths operators", ->
eq 55, 1 + 3 ** 3 * 2
eq -4, -2 ** 2
eq false, !2 ** 2
eq 0, (!2) ** 2
eq -2, ~1 ** 5
test "power operator is right associative", ->
eq 2, 2 ** 1 ** 3
test "power operator compound assignment", ->
a = 2
a **= 3
eq 8, a
test "floor division operator", ->
eq 2, 7 // 3
eq -3, -7 // 3

7
test/regex_dotall.coffee Normal file
View File

@@ -0,0 +1,7 @@
# Regex “dotall” flag, or `s`, is only supported in Node 9+, so put tests for
# the feature in their own file. The feature detection in `Cakefile` that
# causes this test to load is adapted from
# https://github.com/tc39/proposal-regexp-dotall-flag#proposed-solution.
test "dotall flag", ->
doesNotThrow -> /a.b/s.test 'a\nb'