mirror of
https://github.com/jashkenas/coffeescript.git
synced 2026-01-13 08:47:55 -05:00
Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8061ecf0e2 | ||
|
|
6df8f5ff17 | ||
|
|
776e7e5328 | ||
|
|
871079b25c | ||
|
|
be2b24310f | ||
|
|
1f9cd4eaf7 | ||
|
|
47c491ffa1 | ||
|
|
195a46ab77 | ||
|
|
e5aa758dda | ||
|
|
001f97ac39 | ||
|
|
ce66a499de | ||
|
|
0268505119 | ||
|
|
5a43b2d7c5 | ||
|
|
820942c3d0 | ||
|
|
1869f3121d | ||
|
|
4c0363fb7c | ||
|
|
746b0c7cc6 | ||
|
|
b2fe7772c5 | ||
|
|
23479eb486 | ||
|
|
63b8543d73 | ||
|
|
7542a75ff8 | ||
|
|
0875039d52 | ||
|
|
e0833c29ce | ||
|
|
72ab6feb2f | ||
|
|
eb7009268d | ||
|
|
571e9df335 |
@@ -3,6 +3,7 @@ language: node_js
|
||||
node_js:
|
||||
- 6
|
||||
- 8
|
||||
- 10
|
||||
|
||||
cache:
|
||||
directories:
|
||||
@@ -14,5 +15,6 @@ script:
|
||||
- node ./bin/cake build:full
|
||||
- node ./bin/cake build:browser
|
||||
- node ./bin/cake test
|
||||
- node --harmony ./bin/cake test
|
||||
- node ./bin/cake test:browser
|
||||
- node ./bin/cake test:integrations
|
||||
|
||||
46
CODE_OF_CONDUCT.md
Normal file
46
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at maintainers@coffeescript.org. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
||||
@@ -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)
|
||||
|
||||
24
Cakefile
24
Cakefile
@@ -425,12 +425,6 @@ runTests = (CoffeeScript) ->
|
||||
catch err
|
||||
onFail description, fn, err
|
||||
|
||||
global.supportsAsync = try
|
||||
new Function('async () => {}')()
|
||||
yes
|
||||
catch
|
||||
no
|
||||
|
||||
helpers.extend global, require './test/support/helpers'
|
||||
|
||||
# When all the tests have run, collect and print errors.
|
||||
@@ -448,10 +442,20 @@ runTests = (CoffeeScript) ->
|
||||
console.log " #{source}" if source
|
||||
return
|
||||
|
||||
# Run every test in the `test` folder, recording failures.
|
||||
files = fs.readdirSync 'test'
|
||||
unless global.supportsAsync # Except for async tests, if async isn’t supported.
|
||||
files = files.filter (filename) -> filename isnt 'async.coffee'
|
||||
# Run every test in the `test` folder, recording failures, except for files
|
||||
# we’re skipping because the features to be tested are unsupported in the
|
||||
# current Node runtime.
|
||||
testFilesToSkip = []
|
||||
skipUnless = (featureDetect, filenames) ->
|
||||
unless (try new Function featureDetect)
|
||||
testFilesToSkip = testFilesToSkip.concat filenames
|
||||
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
|
||||
|
||||
startTime = Date.now()
|
||||
for file in files when helpers.isCoffee file
|
||||
|
||||
62
ISSUE_TEMPLATE.md
Normal file
62
ISSUE_TEMPLATE.md
Normal file
@@ -0,0 +1,62 @@
|
||||
<!---
|
||||
Thanks for filing an issue 😄! Before you submit, please read the following:
|
||||
|
||||
Search open/closed issues before submitting since someone might have asked the same thing before!
|
||||
Our issues history stretches back to 2009, so the odds are good that your topic has come up.
|
||||
|
||||
If you have a support request or question please use Stack Overflow:
|
||||
https://stackoverflow.com/questions/tagged/coffeescript
|
||||
|
||||
Issues on GitHub are only related to problems of the CoffeeScript compiler itself and we cannot answer
|
||||
support questions here.
|
||||
-->
|
||||
|
||||
Choose one: is this a bug report or feature request?
|
||||
|
||||
<!---
|
||||
Provide a general summary of the issue in the title above.
|
||||
|
||||
For bugs, please also preface your title with “Bug:”. For feature requests, please preface your title
|
||||
with “Proposal:”. Once your issue is reviewed, a maintainer will edit the title to refer to the part
|
||||
of the codebase most relevant to the issue (if applicable).
|
||||
|
||||
If your request is that CoffeeScript support a new feature recently arrived to JavaScript, please note
|
||||
that we generally only add features that have reached Stage 4 in the specification (in other words,
|
||||
the syntax is finalized and the feature is approved to be part of the next ES release). You can still
|
||||
open an issue, but it will likely be tagged with “[Awaiting Stage 4]” until the relevant ES feature is
|
||||
approved for release. See http://coffeescript.org/#contributing
|
||||
|
||||
There are also a handful of JavaScript features that CoffeeScript intentionally does not support.
|
||||
Please do not open issues regarding these. They’re listed in http://coffeescript.org/#unsupported
|
||||
-->
|
||||
|
||||
### Input Code
|
||||
<!--- If you're describing a bug, please let us know which sample code reproduces your problem. -->
|
||||
<!--- If you have link from http://coffeescript.org/#try or a standalone repo please include that! -->
|
||||
|
||||
```coffee
|
||||
your (code) => here
|
||||
```
|
||||
|
||||
### Expected Behavior
|
||||
<!--- If you’re describing a bug, tell us what should happen. -->
|
||||
<!--- If you’re suggesting a change/improvement, tell us how it should work. -->
|
||||
|
||||
### Current Behavior
|
||||
<!--- If describing a bug, tell us what happens instead of the expected behavior. -->
|
||||
<!--- If suggesting a change/improvement, explain the difference from current behavior. -->
|
||||
|
||||
### Possible Solution
|
||||
<!--- Not obligatory, but suggest a fix/reason for the bug, -->
|
||||
<!--- or ideas how to implement the addition or change. -->
|
||||
|
||||
### Context
|
||||
<!--- How has this issue affected you? What are you trying to accomplish? -->
|
||||
<!--- Providing context helps us come up with a solution that is most useful in the real world. -->
|
||||
|
||||
### Environment
|
||||
<!--- For bugs, please let us know what version of CoffeeScript you’re running: `coffee -v`. -->
|
||||
<!--- If you think it might be relevant, please also let us know your version of Node. -->
|
||||
|
||||
* CoffeeScript version:
|
||||
* Node.js version:
|
||||
2
LICENSE
2
LICENSE
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2009-2017 Jeremy Ashkenas
|
||||
Copyright (c) 2009-2018 Jeremy Ashkenas
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
|
||||
22
PULL_REQUEST_TEMPLATE.md
Normal file
22
PULL_REQUEST_TEMPLATE.md
Normal file
@@ -0,0 +1,22 @@
|
||||
<!--
|
||||
Before making a PR please make sure to read our contributing guidelines:
|
||||
http://coffeescript.org/#contributing
|
||||
|
||||
For issue references: Add a comma-separated list of a
|
||||
[closing word](https://help.github.com/articles/closing-issues-via-commit-messages/) followed by
|
||||
the ticket number fixed by the PR. It should be underlined in the preview if done correctly.
|
||||
|
||||
All new features require tests. All but the most trivial bug fixes should also have new or updated tests.
|
||||
|
||||
Ensure that all new code you add to the compiler can be run in the minimum version of Node listed in
|
||||
`package.json`. New tests can require newer Node runtimes, but you may need to ensure that such tests
|
||||
only run in supported runtimes; see `Cakefile` for examples of how to filter out certain tests in
|
||||
runtimes that don’t support them.
|
||||
|
||||
Please follow the code style of the rest of the CoffeeScript codebase. Write comments in complete
|
||||
sentences using Markdown, as the comments become the [annotated source](http://coffeescript.org/#annotated-source).
|
||||
For tests proving a bug is fixed, please mention the issue number in the test description (see examples
|
||||
in the codebase).
|
||||
|
||||
Describe your changes below in as much detail as possible.
|
||||
-->
|
||||
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,6 +2,7 @@ environment:
|
||||
matrix:
|
||||
- nodejs_version: '6'
|
||||
- nodejs_version: '8'
|
||||
- nodejs_version: '10'
|
||||
- nodejs_version: '' # Installs latest.
|
||||
|
||||
install:
|
||||
@@ -19,6 +20,7 @@ test_script:
|
||||
- node ./bin/cake build:full
|
||||
- node ./bin/cake build:browser
|
||||
- node ./bin/cake test
|
||||
- node --harmony ./bin/cake test
|
||||
- node ./bin/cake test:browser
|
||||
- node ./bin/cake test:integrations
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -920,10 +920,10 @@ can close multiple indents, so we need to know how far in we happen to be.</p>
|
||||
indent = match[<span class="hljs-number">0</span>]
|
||||
|
||||
prev = @prev()
|
||||
backslash = prev? <span class="hljs-keyword">and</span> prev[<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">'\\'</span>
|
||||
backslash = prev?[<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">'\\'</span>
|
||||
@seenFor = <span class="hljs-literal">no</span> <span class="hljs-keyword">unless</span> backslash <span class="hljs-keyword">and</span> @seenFor
|
||||
@seenImport = <span class="hljs-literal">no</span> <span class="hljs-keyword">unless</span> @importSpecifierList
|
||||
@seenExport = <span class="hljs-literal">no</span> <span class="hljs-keyword">unless</span> @exportSpecifierList
|
||||
@seenImport = <span class="hljs-literal">no</span> <span class="hljs-keyword">unless</span> (backslash <span class="hljs-keyword">and</span> @seenImport) <span class="hljs-keyword">or</span> @importSpecifierList
|
||||
@seenExport = <span class="hljs-literal">no</span> <span class="hljs-keyword">unless</span> (backslash <span class="hljs-keyword">and</span> @seenExport) <span class="hljs-keyword">or</span> @exportSpecifierList
|
||||
|
||||
size = indent.length - <span class="hljs-number">1</span> - indent.lastIndexOf <span class="hljs-string">'\n'</span>
|
||||
noNewlines = @unfinished()
|
||||
@@ -944,7 +944,7 @@ can close multiple indents, so we need to know how far in we happen to be.</p>
|
||||
|
||||
<span class="hljs-keyword">if</span> size > @indent
|
||||
<span class="hljs-keyword">if</span> noNewlines
|
||||
@indebt = size - @indent
|
||||
@indebt = size - @indent <span class="hljs-keyword">unless</span> backslash
|
||||
@suppressNewlines()
|
||||
<span class="hljs-keyword">return</span> indent.length
|
||||
<span class="hljs-keyword">unless</span> @tokens.length
|
||||
@@ -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
1342
docs/v2/test.html
1342
docs/v2/test.html
File diff suppressed because it is too large
Load Diff
@@ -6,4 +6,4 @@ Object.defineProperty screen, 'height',
|
||||
get: ->
|
||||
this.width / this.ratio
|
||||
set: (val) ->
|
||||
this.width = val / this.ratio
|
||||
this.width = val * this.ratio
|
||||
|
||||
@@ -1,7 +1,34 @@
|
||||
## Changelog
|
||||
|
||||
```
|
||||
releaseHeader('2018-02-06', '2.2.1', '2.1.0')
|
||||
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')
|
||||
```
|
||||
* When the `by` value in a `for` loop is a literal number, e.g. `for x in [2..1] by -1`, fewer checks are necessary to determine if the loop is in range.
|
||||
* Bugfix for regression in 2.2.0 where a statement inside parentheses, e.g. `(fn(); break) while condition`, was compiling. Pure statements like `break` or `return` cannot turn a parenthesized block into an expression, and should throw an error.
|
||||
|
||||
```
|
||||
releaseHeader('2018-03-11', '2.2.3', '2.2.2')
|
||||
```
|
||||
* Bugfix for object destructuring with an empty array as a key’s value: `{ key: [] } = obj`.
|
||||
* Bugfix for array destructuring onto targets attached to `this`: `[ @most... , @penultimate, @last ] = arr`.
|
||||
|
||||
```
|
||||
releaseHeader('2018-02-21', '2.2.2', '2.2.1')
|
||||
```
|
||||
* Bugfix for regression in 2.2.0 where a range with a `by` (step) value that increments or decrements in the opposite direction as the range was returning an array containing the first value of the range, whereas it should be returning an empty array. In other words, `x for x in [2..1] by 1` should equal `[]`, not `[2]` (because the step value is positive 1, counting up, whereas the range goes from 2 to 1, counting down).
|
||||
* Bugfixes for allowing backslashes in `import` and `export` statements and lines that trigger the start of an indented block, like an `if` statement.
|
||||
|
||||
```
|
||||
releaseHeader('2018-02-06', '2.2.1', '2.2.0')
|
||||
```
|
||||
* Bugfix for regression in 2.2.0 involving an error thrown by the compiler in certain cases when using destructuring with a splat or expansion in an array.
|
||||
* Bugfix for regression in 2.2.0 where in certain cases a range iterator variable was declared in the global scope.
|
||||
|
||||
@@ -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.1
|
||||
// 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.1
|
||||
// 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.1
|
||||
// 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.1
|
||||
// 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.1
|
||||
// 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.1
|
||||
// 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.1
|
||||
// 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.1
|
||||
// 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,
|
||||
@@ -593,14 +593,14 @@
|
||||
}
|
||||
indent = match[0];
|
||||
prev = this.prev();
|
||||
backslash = (prev != null) && prev[0] === '\\';
|
||||
backslash = (prev != null ? prev[0] : void 0) === '\\';
|
||||
if (!(backslash && this.seenFor)) {
|
||||
this.seenFor = false;
|
||||
}
|
||||
if (!this.importSpecifierList) {
|
||||
if (!((backslash && this.seenImport) || this.importSpecifierList)) {
|
||||
this.seenImport = false;
|
||||
}
|
||||
if (!this.exportSpecifierList) {
|
||||
if (!((backslash && this.seenExport) || this.exportSpecifierList)) {
|
||||
this.seenExport = false;
|
||||
}
|
||||
size = indent.length - 1 - indent.lastIndexOf('\n');
|
||||
@@ -629,7 +629,9 @@
|
||||
}
|
||||
if (size > this.indent) {
|
||||
if (noNewlines) {
|
||||
this.indebt = size - this.indent;
|
||||
if (!backslash) {
|
||||
this.indebt = size - this.indent;
|
||||
}
|
||||
this.suppressNewlines();
|
||||
return indent.length;
|
||||
}
|
||||
@@ -1608,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.1
|
||||
// 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) {
|
||||
@@ -1267,15 +1267,6 @@
|
||||
if (!props && base instanceof Value) {
|
||||
return base;
|
||||
}
|
||||
if (base instanceof Parens && base.contains(function(n) {
|
||||
return n instanceof StatementLiteral;
|
||||
})) {
|
||||
// When `Parens` block includes a `StatementLiteral` (e.g. `(b; break) for a in arr`),
|
||||
// it won't compile since `Parens` (`(b; break)`) is compiled as `Value` and
|
||||
// pure statement (`break`) can't be used in an expression.
|
||||
// For this reasons, we return `Block` instead of `Parens`.
|
||||
return base.unwrap();
|
||||
}
|
||||
this.base = base;
|
||||
this.properties = props || [];
|
||||
if (tag) {
|
||||
@@ -2031,7 +2022,7 @@
|
||||
// When compiled normally, the range returns the contents of the *for loop*
|
||||
// needed to iterate over the values in the range. Used by comprehensions.
|
||||
compileNode(o) {
|
||||
var cond, condPart, from, gt, idx, idxName, known, lowerBound, lt, namedIndex, stepCond, stepPart, to, upperBound, varPart;
|
||||
var cond, condPart, from, gt, idx, idxName, known, lowerBound, lt, namedIndex, ref1, ref2, stepCond, stepNotZero, stepPart, to, upperBound, varPart;
|
||||
if (!this.fromVar) {
|
||||
this.compileVariables(o);
|
||||
}
|
||||
@@ -2054,12 +2045,11 @@
|
||||
// Generate the condition.
|
||||
[from, to] = [this.fromNum, this.toNum];
|
||||
// Always check if the `step` isn't zero to avoid the infinite loop.
|
||||
stepCond = this.stepNum ? `${this.stepNum} !== 0` : `${this.stepVar} !== 0`;
|
||||
condPart = known ? this.step == null ? from <= to ? `${lt} ${to}` : `${gt} ${ // from < to
|
||||
to}` : (lowerBound = `${from} <= ${idx} && ${lt} ${// from > to
|
||||
to}`, upperBound = `${from} >= ${idx} && ${gt} ${to}`, from <= to ? `${stepCond} && ${lowerBound}` : `${stepCond} && ${// from < to
|
||||
upperBound}`) : (lowerBound = `${this.fromVar} <= ${idx} && ${lt} ${// from > to
|
||||
this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `${stepCond} && (${this.fromVar} <= ${this.toVar} ? ${lowerBound} : ${upperBound})`);
|
||||
stepNotZero = `${(ref1 = this.stepNum) != null ? ref1 : this.stepVar} !== 0`;
|
||||
stepCond = `${(ref2 = this.stepNum) != null ? ref2 : this.stepVar} > 0`;
|
||||
lowerBound = `${lt} ${(known ? to : this.toVar)}`;
|
||||
upperBound = `${gt} ${(known ? to : this.toVar)}`;
|
||||
condPart = this.step != null ? (this.stepNum != null) && this.stepNum !== 0 ? this.stepNum > 0 ? `${lowerBound}` : `${upperBound}` : `${stepNotZero} && (${stepCond} ? ${lowerBound} : ${upperBound})` : known ? `${(from <= to ? lt : gt)} ${to}` : `(${this.fromVar} <= ${this.toVar} ? ${lowerBound} : ${upperBound})`;
|
||||
cond = this.stepVar ? `${this.stepVar} > 0` : `${this.fromVar} <= ${this.toVar}`;
|
||||
// Generate the step.
|
||||
stepPart = this.stepVar ? `${idx} += ${this.stepVar}` : known ? namedIndex ? from <= to ? `++${idx}` : `--${idx}` : from <= to ? `${idx}++` : `${idx}--` : namedIndex ? `${cond} ? ++${idx} : --${idx}` : `${cond} ? ${idx}++ : ${idx}--`;
|
||||
@@ -2180,7 +2170,7 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
}
|
||||
|
||||
isAssignable() {
|
||||
var j, len1, message, prop, ref1;
|
||||
var j, len1, message, prop, ref1, ref2;
|
||||
ref1 = this.properties;
|
||||
for (j = 0, len1 = ref1.length; j < len1; j++) {
|
||||
prop = ref1[j];
|
||||
@@ -2189,7 +2179,7 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
if (message) {
|
||||
prop.error(message);
|
||||
}
|
||||
if (prop instanceof Assign && prop.context === 'object') {
|
||||
if (prop instanceof Assign && prop.context === 'object' && !(((ref2 = prop.value) != null ? ref2.base : void 0) instanceof Arr)) {
|
||||
prop = prop.value;
|
||||
}
|
||||
if (!prop.isAssignable()) {
|
||||
@@ -2216,8 +2206,35 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
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++) {
|
||||
@@ -2227,10 +2244,6 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
}
|
||||
}
|
||||
}
|
||||
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) {
|
||||
@@ -2264,7 +2277,7 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
}
|
||||
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;
|
||||
@@ -2295,7 +2308,7 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
// `{ [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');
|
||||
}
|
||||
}
|
||||
@@ -2347,42 +2360,6 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
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;
|
||||
@@ -2458,7 +2435,7 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
}
|
||||
|
||||
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('[]')];
|
||||
}
|
||||
@@ -2526,7 +2503,7 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
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}`;
|
||||
@@ -2537,8 +2514,8 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
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} `;
|
||||
}
|
||||
@@ -3293,7 +3270,7 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
// 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.
|
||||
@@ -3307,19 +3284,12 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
// 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()) {
|
||||
@@ -3328,11 +3298,11 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
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`);
|
||||
@@ -3406,124 +3376,27 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
@@ -3577,11 +3450,25 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
}
|
||||
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.
|
||||
@@ -3594,7 +3481,10 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
slicer = function(type) {
|
||||
return function(vvar, start, end = false) {
|
||||
var args, slice;
|
||||
args = [new IdentifierLiteral(vvar), new NumberLiteral(start)];
|
||||
if (!(vvar instanceof Value)) {
|
||||
vvar = new IdentifierLiteral(vvar);
|
||||
}
|
||||
args = [vvar, new NumberLiteral(start)];
|
||||
if (end) {
|
||||
args.push(new NumberLiteral(end));
|
||||
}
|
||||
@@ -3606,18 +3496,6 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
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;
|
||||
@@ -3641,16 +3519,15 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
}
|
||||
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];
|
||||
@@ -3680,8 +3557,6 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
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;
|
||||
}
|
||||
@@ -3699,10 +3574,7 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
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;
|
||||
};
|
||||
@@ -3711,10 +3583,7 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
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)) {
|
||||
@@ -3746,7 +3615,7 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
refExp = (function() {
|
||||
switch (false) {
|
||||
case !isSplat:
|
||||
return compSplice(objects[expIdx].unwrapAll().value, rightObjs.length * -1);
|
||||
return compSplice(new Value(objects[expIdx].name), rightObjs.length * -1);
|
||||
case !isExpans:
|
||||
return compSlice(vvarText, rightObjs.length * -1);
|
||||
}
|
||||
@@ -3762,6 +3631,9 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
// There is no `Splat` or `Expansion` in `objects`.
|
||||
processObjects(objects, vvar, vvarText);
|
||||
}
|
||||
if (typeof splatVarAssign === "function") {
|
||||
splatVarAssign();
|
||||
}
|
||||
if (!(top || this.subpattern)) {
|
||||
assigns.push(vvar);
|
||||
}
|
||||
@@ -3798,7 +3670,7 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
@@ -3896,8 +3768,8 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
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;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -3991,7 +3863,7 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
}
|
||||
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?
|
||||
@@ -4053,22 +3925,7 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
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);
|
||||
});
|
||||
@@ -4202,10 +4059,10 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
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;
|
||||
@@ -4335,12 +4192,12 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
// 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);
|
||||
@@ -4492,7 +4349,14 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
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());
|
||||
}
|
||||
|
||||
@@ -4807,8 +4671,6 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
switch (this.operator) {
|
||||
case '?':
|
||||
return this.compileExistence(o, this.second.isDefaultValue);
|
||||
case '**':
|
||||
return this.compilePower(o);
|
||||
case '//':
|
||||
return this.compileFloorDivision(o);
|
||||
case '%%':
|
||||
@@ -4910,13 +4772,6 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
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'))]);
|
||||
@@ -5377,25 +5232,47 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
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) {
|
||||
@@ -5405,21 +5282,21 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
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
|
||||
@@ -5431,6 +5308,7 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
});
|
||||
moveComments(this[attribute], this);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
// Welcome to the hairiest method in all of CoffeeScript. Handles the inner
|
||||
@@ -5438,7 +5316,7 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
// 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) {
|
||||
@@ -5556,7 +5434,12 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
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
|
||||
@@ -5568,7 +5451,9 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
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));
|
||||
}
|
||||
@@ -5813,15 +5698,9 @@ this.toVar}`, upperBound = `${this.fromVar} >= ${idx} && ${gt} ${this.toVar}`, `
|
||||
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.1
|
||||
// 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.1
|
||||
// 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.1
|
||||
// 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.1
|
||||
// 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
|
||||
@@ -218,7 +218,7 @@
|
||||
indexOfTag(i, ...pattern) {
|
||||
var fuzz, j, k, ref, ref1;
|
||||
fuzz = 0;
|
||||
for (j = k = 0, ref = pattern.length; undefined !== 0 && (0 <= ref ? 0 <= k && k < ref : 0 >= k && k > ref); j = 0 <= ref ? ++k : --k) {
|
||||
for (j = k = 0, ref = pattern.length; (0 <= ref ? k < ref : k > ref); j = 0 <= ref ? ++k : --k) {
|
||||
if (pattern[j] == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 2.2.1
|
||||
// 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.1
|
||||
// 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
|
||||
|
||||
3849
package-lock.json
generated
3849
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
14
package.json
14
package.json
@@ -8,7 +8,7 @@
|
||||
"compiler"
|
||||
],
|
||||
"author": "Jeremy Ashkenas",
|
||||
"version": "2.2.1",
|
||||
"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.32.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.0",
|
||||
"underscore": "~1.8.3",
|
||||
"webpack": "~3.10.0"
|
||||
"markdown-it": "~8.4.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.
|
||||
|
||||
@@ -454,10 +454,10 @@ exports.Lexer = class Lexer
|
||||
indent = match[0]
|
||||
|
||||
prev = @prev()
|
||||
backslash = prev? and prev[0] is '\\'
|
||||
backslash = prev?[0] is '\\'
|
||||
@seenFor = no unless backslash and @seenFor
|
||||
@seenImport = no unless @importSpecifierList
|
||||
@seenExport = no unless @exportSpecifierList
|
||||
@seenImport = no unless (backslash and @seenImport) or @importSpecifierList
|
||||
@seenExport = no unless (backslash and @seenExport) or @exportSpecifierList
|
||||
|
||||
size = indent.length - 1 - indent.lastIndexOf '\n'
|
||||
noNewlines = @unfinished()
|
||||
@@ -478,7 +478,7 @@ exports.Lexer = class Lexer
|
||||
|
||||
if size > @indent
|
||||
if noNewlines
|
||||
@indebt = size - @indent
|
||||
@indebt = size - @indent unless backslash
|
||||
@suppressNewlines()
|
||||
return indent.length
|
||||
unless @tokens.length
|
||||
@@ -1261,7 +1261,7 @@ REGEX = /// ^
|
||||
///
|
||||
|
||||
REGEX_FLAGS = /^\w*/
|
||||
VALID_FLAGS = /^(?!.*(.).*\1)[imguy]*$/
|
||||
VALID_FLAGS = /^(?!.*(.).*\1)[gimsuy]*$/
|
||||
|
||||
HEREGEX = /// ^
|
||||
(?:
|
||||
|
||||
306
src/nodes.coffee
306
src/nodes.coffee
@@ -863,11 +863,6 @@ exports.Value = class Value extends Base
|
||||
constructor: (base, props, tag, isDefaultValue = no) ->
|
||||
super()
|
||||
return base if not props and base instanceof Value
|
||||
# When `Parens` block includes a `StatementLiteral` (e.g. `(b; break) for a in arr`),
|
||||
# it won't compile since `Parens` (`(b; break)`) is compiled as `Value` and
|
||||
# pure statement (`break`) can't be used in an expression.
|
||||
# For this reasons, we return `Block` instead of `Parens`.
|
||||
return base.unwrap() if base instanceof Parens and base.contains (n) -> n instanceof StatementLiteral
|
||||
@base = base
|
||||
@properties = props or []
|
||||
@[tag] = yes if tag
|
||||
@@ -1365,23 +1360,21 @@ exports.Range = class Range extends Base
|
||||
# Generate the condition.
|
||||
[from, to] = [@fromNum, @toNum]
|
||||
# Always check if the `step` isn't zero to avoid the infinite loop.
|
||||
stepCond = if @stepNum then "#{@stepNum} !== 0" else "#{@stepVar} !== 0"
|
||||
stepNotZero = "#{ @stepNum ? @stepVar } !== 0"
|
||||
stepCond = "#{ @stepNum ? @stepVar } > 0"
|
||||
lowerBound = "#{lt} #{ if known then to else @toVar }"
|
||||
upperBound = "#{gt} #{ if known then to else @toVar }"
|
||||
condPart =
|
||||
if known
|
||||
unless @step?
|
||||
if from <= to then "#{lt} #{to}" else "#{gt} #{to}"
|
||||
if @step?
|
||||
if @stepNum? and @stepNum isnt 0
|
||||
if @stepNum > 0 then "#{lowerBound}" else "#{upperBound}"
|
||||
else
|
||||
# from < to
|
||||
lowerBound = "#{from} <= #{idx} && #{lt} #{to}"
|
||||
# from > to
|
||||
upperBound = "#{from} >= #{idx} && #{gt} #{to}"
|
||||
if from <= to then "#{stepCond} && #{lowerBound}" else "#{stepCond} && #{upperBound}"
|
||||
"#{stepNotZero} && (#{stepCond} ? #{lowerBound} : #{upperBound})"
|
||||
else
|
||||
# from < to
|
||||
lowerBound = "#{@fromVar} <= #{idx} && #{lt} #{@toVar}"
|
||||
# from > to
|
||||
upperBound = "#{@fromVar} >= #{idx} && #{gt} #{@toVar}"
|
||||
"#{stepCond} && (#{@fromVar} <= #{@toVar} ? #{lowerBound} : #{upperBound})"
|
||||
if known
|
||||
"#{ if from <= to then lt else gt } #{to}"
|
||||
else
|
||||
"(#{@fromVar} <= #{@toVar} ? #{lowerBound} : #{upperBound})"
|
||||
|
||||
cond = if @stepVar then "#{@stepVar} > 0" else "#{@fromVar} <= #{@toVar}"
|
||||
|
||||
@@ -1482,7 +1475,9 @@ exports.Obj = class Obj extends Base
|
||||
message = isUnassignable prop.unwrapAll().value
|
||||
prop.error message if message
|
||||
|
||||
prop = prop.value if prop instanceof Assign and prop.context is 'object'
|
||||
prop = prop.value if prop instanceof Assign and
|
||||
prop.context is 'object' and
|
||||
prop.value?.base not instanceof Arr
|
||||
return no unless prop.isAssignable()
|
||||
yes
|
||||
|
||||
@@ -1494,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
|
||||
|
||||
@@ -1563,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)...
|
||||
@@ -1582,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 = []
|
||||
@@ -2218,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"
|
||||
@@ -2294,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.
|
||||
@@ -2414,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
|
||||
@@ -2431,7 +2342,8 @@ exports.Assign = class Assign extends Base
|
||||
vvarText = ref
|
||||
|
||||
slicer = (type) -> (vvar, start, end = no) ->
|
||||
args = [new IdentifierLiteral(vvar), new NumberLiteral(start)]
|
||||
vvar = new IdentifierLiteral vvar unless vvar instanceof Value
|
||||
args = [vvar, new NumberLiteral(start)]
|
||||
args.push new NumberLiteral end if end
|
||||
slice = new Value (new IdentifierLiteral utility type, o), [new Access new PropertyName 'call']
|
||||
new Value new Call slice, args
|
||||
@@ -2442,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')
|
||||
@@ -2455,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
|
||||
@@ -2482,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
|
||||
@@ -2522,7 +2428,7 @@ exports.Assign = class Assign extends Base
|
||||
if rightObjs.length isnt 0
|
||||
# Slice or splice `objects`.
|
||||
refExp = switch
|
||||
when isSplat then compSplice objects[expIdx].unwrapAll().value, rightObjs.length * -1
|
||||
when isSplat then compSplice new Value(objects[expIdx].name), rightObjs.length * -1
|
||||
when isExpans then compSlice vvarText, rightObjs.length * -1
|
||||
if complexObjects rightObjs
|
||||
restVar = refExp
|
||||
@@ -2532,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
|
||||
@@ -2552,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
|
||||
@@ -2614,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']
|
||||
|
||||
@@ -2693,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?
|
||||
@@ -2747,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
|
||||
@@ -3032,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) ->
|
||||
@@ -3257,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
|
||||
@@ -3324,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
|
||||
@@ -3625,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
|
||||
@@ -3652,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
|
||||
@@ -3731,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
|
||||
@@ -3876,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)) {
|
||||
@@ -3890,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']
|
||||
|
||||
@@ -959,7 +613,7 @@ test "#4878: Compile error when using destructuring with a splat or expansion in
|
||||
([first, ...] = list); first
|
||||
|
||||
f4 = (list) ->
|
||||
([first, ...rest] = list); rest
|
||||
([first, rest...] = list); rest
|
||||
|
||||
arrayEq f1(arr), arr
|
||||
arrayEq f2(arr), arr
|
||||
@@ -979,9 +633,91 @@ test "#4878: Compile error when using destructuring with a splat or expansion in
|
||||
bar = (list) ->
|
||||
ret =
|
||||
if list?.length > 0
|
||||
[first, ...rest] = list
|
||||
[first, rest...] = list
|
||||
[first, rest]
|
||||
else
|
||||
[]
|
||||
|
||||
arrayEq bar(arr), ['a', ['b', 'c', 'd']]
|
||||
|
||||
test "destructuring assignment with an empty array in object", ->
|
||||
obj =
|
||||
a1: [1, 2]
|
||||
b1: 3
|
||||
|
||||
{a1:[], b1} = obj
|
||||
eq 'undefined', typeof a1
|
||||
eq b1, 3
|
||||
|
||||
obj =
|
||||
a2:
|
||||
b2: [1, 2]
|
||||
c2: 3
|
||||
|
||||
{a2: {b2:[]}, c2} = obj
|
||||
eq 'undefined', typeof b2
|
||||
eq c2, 3
|
||||
|
||||
test "#5004: array destructuring with accessors", ->
|
||||
obj =
|
||||
arr: ['a', 'b', 'c', 'd']
|
||||
list: {}
|
||||
f1: ->
|
||||
[@first, @rest...] = @arr
|
||||
f2: ->
|
||||
[@second, @third..., @last] = @rest
|
||||
f3: ->
|
||||
[@list.a, @list.middle..., @list.d] = @arr
|
||||
|
||||
obj.f1()
|
||||
eq obj.first, 'a'
|
||||
arrayEq obj.rest, ['b', 'c', 'd']
|
||||
|
||||
obj.f2()
|
||||
eq obj.second, 'b'
|
||||
arrayEq obj.third, ['c']
|
||||
eq obj.last, 'd'
|
||||
|
||||
obj.f3()
|
||||
eq obj.list.a, 'a'
|
||||
arrayEq obj.list.middle, ['b', 'c']
|
||||
eq obj.list.d, 'd'
|
||||
|
||||
[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
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
# Functions that contain the `await` keyword will compile into async functions,
|
||||
# supported by Node 7.6+, Chrome 55+, Firefox 52+, Safari 10.1+ and Edge.
|
||||
# But runtimes that don’t support the `await` keyword will throw an error,
|
||||
# even if we put `return unless global.supportsAsync` at the top of this file.
|
||||
# Therefore we need to prevent runtimes which will choke on such code from even
|
||||
# But runtimes that don’t support the `await` keyword will throw an error just
|
||||
# from parsing this file, even without executing it, even if we put
|
||||
# `return unless try new Function 'async () => {}'` at the top of this file.
|
||||
# Therefore we need to prevent runtimes which will choke on such code from
|
||||
# parsing it, which is handled in `Cakefile`.
|
||||
|
||||
|
||||
|
||||
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
|
||||
@@ -266,6 +266,7 @@ test "classes with value'd constructors", ->
|
||||
inner = ++counter
|
||||
->
|
||||
@value = inner
|
||||
@
|
||||
|
||||
class One
|
||||
constructor: classMaker()
|
||||
|
||||
@@ -1112,37 +1112,6 @@ test "#3921: `switch`", ->
|
||||
else "none"
|
||||
eq "five", c
|
||||
|
||||
# Issue #3441: Parentheses wrapping expression throw invalid error in `then` clause
|
||||
test "#3441: `StatementLiteral` in parentheses", ->
|
||||
i = 0
|
||||
r1 = ((i++; break) while i < 10)
|
||||
arrayEq r1, []
|
||||
|
||||
i = 0
|
||||
r2 = ((i++; continue) while i < 10)
|
||||
arrayEq r2, []
|
||||
|
||||
i = 0
|
||||
r4 = while i < 10 then (i++; break)
|
||||
arrayEq r4, []
|
||||
|
||||
i = 0
|
||||
r5 = while i < 10 then (i++; continue)
|
||||
arrayEq r5, []
|
||||
|
||||
arr = [0..9]
|
||||
r6 = ((a; break) for a in arr)
|
||||
arrayEq r6, []
|
||||
|
||||
r7 = ((a; continue) for a in arr)
|
||||
arrayEq r7, []
|
||||
|
||||
r8 = for a in arr then (a; break)
|
||||
arrayEq r8, []
|
||||
|
||||
r9 = for a in arr then (a; continue)
|
||||
arrayEq r9, []
|
||||
|
||||
# Issue #3909: backslash to break line in `for` loops throw syntax error
|
||||
test "#3909: backslash `for own ... of`", ->
|
||||
|
||||
@@ -1287,3 +1256,56 @@ test "#4871: `else if` no longer output together ", ->
|
||||
2;
|
||||
}
|
||||
'''
|
||||
|
||||
test "#4898: Lexer: backslash line continuation is inconsistent", ->
|
||||
if ( \
|
||||
false \
|
||||
or \
|
||||
true \
|
||||
)
|
||||
a = 42
|
||||
|
||||
eq a, 42
|
||||
|
||||
if ( \
|
||||
false \
|
||||
or \
|
||||
true \
|
||||
)
|
||||
b = 42
|
||||
|
||||
eq b, 42
|
||||
|
||||
if ( \
|
||||
false \
|
||||
or \
|
||||
true \
|
||||
)
|
||||
c = 42
|
||||
|
||||
eq c, 42
|
||||
|
||||
if \
|
||||
false \
|
||||
or \
|
||||
true
|
||||
d = 42
|
||||
|
||||
eq d, 42
|
||||
|
||||
if \
|
||||
false or \
|
||||
true
|
||||
e = 42
|
||||
|
||||
eq e, 42
|
||||
|
||||
if \
|
||||
false or \
|
||||
true \
|
||||
then \
|
||||
f = 42 \
|
||||
else
|
||||
f = 24
|
||||
|
||||
eq f, 42
|
||||
|
||||
@@ -962,6 +962,42 @@ test "#4097: `yield return` as an expression", ->
|
||||
^^^^^^^^^^^^
|
||||
'''
|
||||
|
||||
test "#5013: `await return` as an expression", ->
|
||||
assertErrorFormat '''
|
||||
-> (await return)
|
||||
''', '''
|
||||
[stdin]:1:5: error: cannot use a pure statement in an expression
|
||||
-> (await return)
|
||||
^^^^^^^^^^^^
|
||||
'''
|
||||
|
||||
test "#5013: `return` as an expression", ->
|
||||
assertErrorFormat '''
|
||||
-> (return)
|
||||
''', '''
|
||||
[stdin]:1:5: error: cannot use a pure statement in an expression
|
||||
-> (return)
|
||||
^^^^^^
|
||||
'''
|
||||
|
||||
test "#5013: `break` as an expression", ->
|
||||
assertErrorFormat '''
|
||||
(b = 1; break) for b in a
|
||||
''', '''
|
||||
[stdin]:1:9: error: cannot use a pure statement in an expression
|
||||
(b = 1; break) for b in a
|
||||
^^^^^
|
||||
'''
|
||||
|
||||
test "#5013: `continue` as an expression", ->
|
||||
assertErrorFormat '''
|
||||
(b = 1; continue) for b in a
|
||||
''', '''
|
||||
[stdin]:1:9: error: cannot use a pure statement in an expression
|
||||
(b = 1; continue) for b in a
|
||||
^^^^^^^^
|
||||
'''
|
||||
|
||||
test "`&&=` and `||=` with a space in-between", ->
|
||||
assertErrorFormat '''
|
||||
a = 0
|
||||
@@ -1194,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
|
||||
|
||||
|
||||
@@ -853,3 +853,70 @@ test "#4491: import- and export-specific lexing should stop after import/export
|
||||
|
||||
from('foo');
|
||||
"""
|
||||
|
||||
# Issue #4874: Backslash not supported in import or export statements
|
||||
test "#4874: backslash `import`", ->
|
||||
|
||||
eqJS """
|
||||
import foo \
|
||||
from 'lib'
|
||||
|
||||
foo a
|
||||
""",
|
||||
"""
|
||||
import foo from 'lib';
|
||||
|
||||
foo(a);
|
||||
"""
|
||||
|
||||
eqJS """
|
||||
import \
|
||||
foo \
|
||||
from \
|
||||
'lib'
|
||||
|
||||
foo a
|
||||
""",
|
||||
"""
|
||||
import foo from 'lib';
|
||||
|
||||
foo(a);
|
||||
"""
|
||||
|
||||
eqJS """
|
||||
import \
|
||||
utilityBelt \
|
||||
, {
|
||||
each
|
||||
} from \
|
||||
'underscore'
|
||||
""",
|
||||
"""
|
||||
import utilityBelt, {
|
||||
each
|
||||
} from 'underscore';
|
||||
"""
|
||||
|
||||
test "#4874: backslash `export`", ->
|
||||
eqJS """
|
||||
export \
|
||||
* \
|
||||
from \
|
||||
'underscore'
|
||||
""",
|
||||
"""
|
||||
export * from 'underscore';
|
||||
"""
|
||||
|
||||
eqJS """
|
||||
export \
|
||||
{ max, min } \
|
||||
from \
|
||||
'underscore'
|
||||
""",
|
||||
"""
|
||||
export {
|
||||
max,
|
||||
min
|
||||
} from 'underscore';
|
||||
"""
|
||||
|
||||
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
|
||||
|
||||
@@ -130,43 +130,43 @@ test "#2047: Infinite loop possible when `for` loop with `range` uses variables"
|
||||
|
||||
testData = [
|
||||
[1, 5, 1, [1..5]]
|
||||
[1, 5, -1, [1]]
|
||||
[1, 5, -1, []]
|
||||
[1, 5, up, [1..5]]
|
||||
[1, 5, down, [1]]
|
||||
[1, 5, down, []]
|
||||
|
||||
[a, 5, 1, [1..5]]
|
||||
[a, 5, -1, [1]]
|
||||
[a, 5, -1, []]
|
||||
[a, 5, up, [1..5]]
|
||||
[a, 5, down, [1]]
|
||||
[a, 5, down, []]
|
||||
|
||||
[1, b, 1, [1..5]]
|
||||
[1, b, -1, [1]]
|
||||
[1, b, -1, []]
|
||||
[1, b, up, [1..5]]
|
||||
[1, b, down, [1]]
|
||||
[1, b, down, []]
|
||||
|
||||
[a, b, 1, [1..5]]
|
||||
[a, b, -1, [1]]
|
||||
[a, b, -1, []]
|
||||
[a, b, up, [1..5]]
|
||||
[a, b, down, [1]]
|
||||
[a, b, down, []]
|
||||
|
||||
[5, 1, 1, [5]]
|
||||
[5, 1, 1, []]
|
||||
[5, 1, -1, [5..1]]
|
||||
[5, 1, up, [5]]
|
||||
[5, 1, up, []]
|
||||
[5, 1, down, [5..1]]
|
||||
|
||||
[5, a, 1, [5]]
|
||||
[5, a, 1, []]
|
||||
[5, a, -1, [5..1]]
|
||||
[5, a, up, [5]]
|
||||
[5, a, up, []]
|
||||
[5, a, down, [5..1]]
|
||||
|
||||
[b, 1, 1, [5]]
|
||||
[b, 1, 1, []]
|
||||
[b, 1, -1, [5..1]]
|
||||
[b, 1, up, [5]]
|
||||
[b, 1, up, []]
|
||||
[b, 1, down, [5..1]]
|
||||
|
||||
[b, a, 1, [5]]
|
||||
[b, a, 1, []]
|
||||
[b, a, -1, [5..1]]
|
||||
[b, a, up, [5]]
|
||||
[b, a, up, []]
|
||||
[b, a, down, [5..1]]
|
||||
]
|
||||
|
||||
@@ -182,10 +182,10 @@ test "#2047: from, to and step as variables", ->
|
||||
arrayEq r, [1..5]
|
||||
|
||||
r = (x for x in [a..b] by down)
|
||||
arrayEq r, [1]
|
||||
arrayEq r, []
|
||||
|
||||
r = (x for x in [b..a] by up)
|
||||
arrayEq r, [5]
|
||||
arrayEq r, []
|
||||
|
||||
r = (x for x in [b..a] by down)
|
||||
arrayEq r, [5..1]
|
||||
@@ -202,3 +202,43 @@ test "#4884: Range not declaring var for the 'i'", ->
|
||||
idx + 1
|
||||
|
||||
eq global.i, undefined
|
||||
|
||||
test "#4889: `for` loop unexpected behavior", ->
|
||||
n = 1
|
||||
result = []
|
||||
for i in [0..n]
|
||||
result.push i
|
||||
for j in [(i+1)..n]
|
||||
result.push j
|
||||
|
||||
arrayEq result, [0,1,1,2,1]
|
||||
|
||||
test "#4889: `for` loop unexpected behavior with `by 1` on second loop", ->
|
||||
n = 1
|
||||
result = []
|
||||
for i in [0..n]
|
||||
result.push i
|
||||
for j in [(i+1)..n] by 1
|
||||
result.push j
|
||||
|
||||
arrayEq result, [0,1,1]
|
||||
|
||||
test "countdown example from docs", ->
|
||||
countdown = (num for num in [10..1])
|
||||
arrayEq countdown, [10,9,8,7,6,5,4,3,2,1]
|
||||
|
||||
test "counting up when the range goes down returns an empty array", ->
|
||||
countdown = (num for num in [10..1] by 1)
|
||||
arrayEq countdown, []
|
||||
|
||||
test "counting down when the range goes up returns an empty array", ->
|
||||
countup = (num for num in [1..10] by -1)
|
||||
arrayEq countup, []
|
||||
|
||||
test "counting down by too much returns just the first value", ->
|
||||
countdown = (num for num in [10..1] by -100)
|
||||
arrayEq countdown, [10]
|
||||
|
||||
test "counting up by too much returns just the first value", ->
|
||||
countup = (num for num in [1..10] by 100)
|
||||
arrayEq countup, [1]
|
||||
|
||||
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'
|
||||
@@ -124,7 +124,7 @@ testRepl "keeps running after runtime error", (input, output) ->
|
||||
eq 'undefined', output.lastWrite()
|
||||
|
||||
testRepl "#4604: wraps an async function", (input, output) ->
|
||||
return unless global.supportsAsync
|
||||
return unless try new Function 'async () => {}' # Feature detect support for async functions.
|
||||
input.emitLine 'await new Promise (resolve) -> setTimeout (-> resolve 33), 10'
|
||||
setTimeout ->
|
||||
eq '33', output.lastWrite()
|
||||
|
||||
Reference in New Issue
Block a user