mirror of
https://github.com/jashkenas/coffeescript.git
synced 2026-01-13 08:47:55 -05:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8061ecf0e2 | ||
|
|
6df8f5ff17 | ||
|
|
776e7e5328 | ||
|
|
871079b25c | ||
|
|
be2b24310f | ||
|
|
1f9cd4eaf7 | ||
|
|
47c491ffa1 | ||
|
|
195a46ab77 |
@@ -3,7 +3,7 @@ language: node_js
|
||||
node_js:
|
||||
- 6
|
||||
- 8
|
||||
- 9
|
||||
- 10
|
||||
|
||||
cache:
|
||||
directories:
|
||||
|
||||
@@ -6,4 +6,9 @@
|
||||
|
||||
* Use the same coding style as the rest of the [codebase](https://github.com/jashkenas/coffeescript/tree/master/src). If you’re just getting started with CoffeeScript, there’s 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. We’ll 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. We’ll 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)
|
||||
|
||||
2
Cakefile
2
Cakefile
@@ -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
|
||||
|
||||
|
||||
54
README.md
54
README.md
@@ -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 don’t wish to install globally.
|
||||
|
||||
## Getting Started
|
||||
|
||||
Execute a script:
|
||||
|
||||
@@ -2,7 +2,7 @@ environment:
|
||||
matrix:
|
||||
- nodejs_version: '6'
|
||||
- nodejs_version: '8'
|
||||
- nodejs_version: '9'
|
||||
- nodejs_version: '10'
|
||||
- nodejs_version: '' # Installs latest.
|
||||
|
||||
install:
|
||||
|
||||
@@ -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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></span> $<span class="hljs-number">2</span>
|
||||
o <span class="hljs-string">'FOR OWN ForVariables'</span>, <span class="hljs-function">-></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">-></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">-></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">-></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>
|
||||
|
||||
@@ -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
1018
docs/v2/test.html
1018
docs/v2/test.html
File diff suppressed because it is too large
Load Diff
@@ -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 weren’t 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')
|
||||
```
|
||||
|
||||
@@ -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 CoffeeScript’s 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 CoffeeScript’s 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, it’s possible to `extend` a JavaScript class; that wasn’t 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 we’ve 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.
|
||||
|
||||
@@ -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 you’re 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 you’re 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 they’re defined.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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` |
|
||||
|
||||
|
||||
@@ -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 [Babel’s rest spread transform](https://babeljs.io/docs/plugins/transform-object-rest-spread/); but once it is supported, we will revise the compiler’s 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.
|
||||
@@ -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') %>
|
||||
|
||||
@@ -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 Bootstrap’s font size for code, which calculates to 14.4px */
|
||||
font-size: 87.5%; /* Matching Bootstrap’s 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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 don’t 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;
|
||||
|
||||
@@ -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 |
@@ -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 |
@@ -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>
|
||||
|
||||
@@ -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 |
@@ -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>
|
||||
|
||||
@@ -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 Google’s 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>
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 they’re 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 isn’t 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
|
||||
// we’re 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';
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
2053
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
12
package.json
12
package.json
@@ -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": {}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -1261,7 +1261,7 @@ REGEX = /// ^
|
||||
///
|
||||
|
||||
REGEX_FLAGS = /^\w*/
|
||||
VALID_FLAGS = /^(?!.*(.).*\1)[imguy]*$/
|
||||
VALID_FLAGS = /^(?!.*(.).*\1)[gimsuy]*$/
|
||||
|
||||
HEREGEX = /// ^
|
||||
(?:
|
||||
|
||||
266
src/nodes.coffee
266
src/nodes.coffee
@@ -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 they’re 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'
|
||||
|
||||
@@ -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
|
||||
|
||||
32
test/async_iterators.coffee
Normal file
32
test/async_iterators.coffee
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -8,7 +8,7 @@ nonce = {}
|
||||
# Throw
|
||||
|
||||
test "basic exception throwing", ->
|
||||
throws (-> throw 'error'), 'error'
|
||||
throws (-> throw 'error'), /^error$/
|
||||
|
||||
|
||||
# Empty Try/Catch/Finally
|
||||
|
||||
19
test/exponentiation.coffee
Normal file
19
test/exponentiation.coffee
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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 ' '
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
420
test/object_rest_spread.coffee
Normal file
420
test/object_rest_spread.coffee
Normal 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
|
||||
@@ -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
7
test/regex_dotall.coffee
Normal 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'
|
||||
Reference in New Issue
Block a user