diff --git a/.eslintrc.yaml b/.eslintrc.yaml
index 9167f21c5dd00f..d8442ff3a18c44 100644
--- a/.eslintrc.yaml
+++ b/.eslintrc.yaml
@@ -40,7 +40,7 @@ rules:
eqeqeq: [2, smart]
no-fallthrough: 2
no-global-assign: 2
- no-multi-spaces: 2
+ no-multi-spaces: [2, {ignoreEOLComments: true}]
no-octal: 2
no-proto: 2
no-redeclare: 2
@@ -98,11 +98,18 @@ rules:
func-call-spacing: 2
func-name-matching: 2
func-style: [2, declaration, {allowArrowFunctions: true}]
- indent: [2, 2, {ArrayExpression: first,
- CallExpression: {arguments: first},
- MemberExpression: 1,
- ObjectExpression: first,
- SwitchCase: 1}]
+ # indent: [2, 2, {ArrayExpression: first,
+ # CallExpression: {arguments: first},
+ # FunctionDeclaration: {parameters: first},
+ # FunctionExpression: {parameters: first},
+ # MemberExpression: off,
+ # ObjectExpression: first,
+ # SwitchCase: 1}]
+ indent-legacy: [2, 2, {ArrayExpression: first,
+ CallExpression: {arguments: first},
+ MemberExpression: 1,
+ ObjectExpression: first,
+ SwitchCase: 1}]
key-spacing: [2, {mode: minimum}]
keyword-spacing: 2
linebreak-style: [2, unix]
@@ -122,7 +129,7 @@ rules:
}, {
selector: "ThrowStatement > CallExpression[callee.name=/Error$/]",
message: "Use new keyword when throwing an Error."
- }]
+ }]
no-tabs: 2
no-trailing-spaces: 2
one-var-declaration-per-line: 2
@@ -131,7 +138,11 @@ rules:
semi: 2
semi-spacing: 2
space-before-blocks: [2, always]
- space-before-function-paren: [2, never]
+ space-before-function-paren: [2, {
+ "anonymous": "never",
+ "named": "never",
+ "asyncArrow": "always"
+ }]
space-in-parens: [2, never]
space-infix-ops: 2
space-unary-ops: 2
diff --git a/BUILDING.md b/BUILDING.md
index a00b00a5f8bc44..9c1fb6899911c4 100644
--- a/BUILDING.md
+++ b/BUILDING.md
@@ -33,6 +33,10 @@ Support is divided into three tiers:
### Supported platforms
+The community does not build or test against end of life distributions (EoL).
+Thus we do not recommend that you use Node on end of life or unsupported platforms
+in production.
+
| System | Support type | Version | Architectures | Notes |
|--------------|--------------|----------------------------------|----------------------|------------------|
| GNU/Linux | Tier 1 | kernel >= 2.6.32, glibc >= 2.12 | x86, x64, arm, arm64 | |
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7190fd564b7eeb..eae65afceb6f52 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -27,8 +27,9 @@ release.
+8.1.3
8.1.2
8.1.1
8.1.0
@@ -24,6 +25,85 @@
* [io.js](CHANGELOG_IOJS.md)
* [Archive](CHANGELOG_ARCHIVE.md)
+
+## 2017-06-??, Version 8.1.3 (Current), @addaleax
+
+### Notable changes
+
+* **Stream**
+ Two regressions with the `stream` module have been fixed:
+ * The `finish` event will now always be emitted after the `error` event
+ if one is emitted:
+ [[`0a9e96e86c`](https://github.com/nodejs/node/commit/0a9e96e86c)]
+ [#13850](https://github.com/nodejs/node/pull/13850)
+ * In object mode, readable streams can now use `undefined` again.
+ [[`5840138e70`](https://github.com/nodejs/node/commit/5840138e70)]
+ [#13760](https://github.com/nodejs/node/pull/13760)
+
+### Commits
+
+* [[`11f45623ac`](https://github.com/nodejs/node/commit/11f45623ac)] - **benchmark**: remove needless RegExp capturing (Vse Mozhet Byt) [#13718](https://github.com/nodejs/node/pull/13718)
+* [[`2ce236e173`](https://github.com/nodejs/node/commit/2ce236e173)] - **build**: check for linter in bin rather than lib (Rich Trott) [#13645](https://github.com/nodejs/node/pull/13645)
+* [[`18f073f0fe`](https://github.com/nodejs/node/commit/18f073f0fe)] - **build**: fail linter if linting not available (Gibson Fahnestock) [#13658](https://github.com/nodejs/node/pull/13658)
+* [[`465bd48b14`](https://github.com/nodejs/node/commit/465bd48b14)] - **configure**: add mips64el to valid_arch (Aditya Anand) [#13620](https://github.com/nodejs/node/pull/13620)
+* [[`1fe455f525`](https://github.com/nodejs/node/commit/1fe455f525)] - **dgram**: change parameter name in set(Multicast)TTL (Tobias Nießen) [#13747](https://github.com/nodejs/node/pull/13747)
+* [[`a63e54a94c`](https://github.com/nodejs/node/commit/a63e54a94c)] - **doc**: update backporting guide (Refael Ackermann) [#13749](https://github.com/nodejs/node/pull/13749)
+* [[`0bb53a7aa2`](https://github.com/nodejs/node/commit/0bb53a7aa2)] - **doc**: make socket IPC examples more robust (cjihrig) [#13196](https://github.com/nodejs/node/pull/13196)
+* [[`57b7285400`](https://github.com/nodejs/node/commit/57b7285400)] - **doc**: mention rebasing of v?.x-staging post release (Anna Henningsen) [#13742](https://github.com/nodejs/node/pull/13742)
+* [[`cb932835d5`](https://github.com/nodejs/node/commit/cb932835d5)] - **doc**: `path.relative` uses `cwd` (DuanPengfei) [#13714](https://github.com/nodejs/node/pull/13714)
+* [[`61714acbe5`](https://github.com/nodejs/node/commit/61714acbe5)] - **doc**: add hasIntl to test/common/README.md (Daniel Bevenius) [#13699](https://github.com/nodejs/node/pull/13699)
+* [[`2a95cfb4ef`](https://github.com/nodejs/node/commit/2a95cfb4ef)] - **doc**: fix typo in changelog (Teddy Katz) [#13713](https://github.com/nodejs/node/pull/13713)
+* [[`31ae193b99`](https://github.com/nodejs/node/commit/31ae193b99)] - **doc**: small makeover for onboarding.md (Anna Henningsen) [#13413](https://github.com/nodejs/node/pull/13413)
+* [[`c27ffadf8e`](https://github.com/nodejs/node/commit/c27ffadf8e)] - **doc**: fix a few n-api doc issues (Michael Dawson) [#13650](https://github.com/nodejs/node/pull/13650)
+* [[`c142f1d316`](https://github.com/nodejs/node/commit/c142f1d316)] - **doc**: fix minor issues reported in #9538 (Tobias Nießen) [#13491](https://github.com/nodejs/node/pull/13491)
+* [[`f28dd8e680`](https://github.com/nodejs/node/commit/f28dd8e680)] - **doc**: fixes a typo in the async_hooks documentation (Chris Young) [#13666](https://github.com/nodejs/node/pull/13666)
+* [[`58e177cde1`](https://github.com/nodejs/node/commit/58e177cde1)] - **doc**: document and test that methods return this (Sam Roberts) [#13531](https://github.com/nodejs/node/pull/13531)
+* [[`f5f2a0e968`](https://github.com/nodejs/node/commit/f5f2a0e968)] - **doc**: sort and update /cc list for inspector issues (Aditya Anand) [#13632](https://github.com/nodejs/node/pull/13632)
+* [[`dc06a0a85a`](https://github.com/nodejs/node/commit/dc06a0a85a)] - **doc**: note that EoL platforms are not supported (Gibson Fahnestock) [#12672](https://github.com/nodejs/node/pull/12672)
+* [[`9b74dded0d`](https://github.com/nodejs/node/commit/9b74dded0d)] - **doc**: update async_hooks providers list (Anna Henningsen) [#13561](https://github.com/nodejs/node/pull/13561)
+* [[`cc922310e3`](https://github.com/nodejs/node/commit/cc922310e3)] - **doc**: fix out of date napi_callback doc (XadillaX) [#13570](https://github.com/nodejs/node/pull/13570)
+* [[`8cb7d96569`](https://github.com/nodejs/node/commit/8cb7d96569)] - **fs**: don't conflate data and callback in appendFile (Nikolai Vavilov) [#11607](https://github.com/nodejs/node/pull/11607)
+* [[`233545a81c`](https://github.com/nodejs/node/commit/233545a81c)] - **inspector,cluster**: fix inspect port assignment (cornholio) [#13619](https://github.com/nodejs/node/pull/13619)
+* [[`cbe7c5c617`](https://github.com/nodejs/node/commit/cbe7c5c617)] - **lib**: correct typo in createSecureContext (Daniel Bevenius) [#13653](https://github.com/nodejs/node/pull/13653)
+* [[`f49dd21b2f`](https://github.com/nodejs/node/commit/f49dd21b2f)] - **n-api**: avoid crash in napi_escape_scope() (Michael Dawson) [#13651](https://github.com/nodejs/node/pull/13651)
+* [[`28166770bd`](https://github.com/nodejs/node/commit/28166770bd)] - **net**: fix abort on bad address input (Ruben Bridgewater) [#13726](https://github.com/nodejs/node/pull/13726)
+* [[`e786926de9`](https://github.com/nodejs/node/commit/e786926de9)] - **readline,repl,url,util**: remove needless capturing (Vse Mozhet Byt) [#13718](https://github.com/nodejs/node/pull/13718)
+* [[`3322191d2f`](https://github.com/nodejs/node/commit/3322191d2f)] - **src**: don't set --icu_case_mapping flag on startup (Ben Noordhuis) [#13698](https://github.com/nodejs/node/pull/13698)
+* [[`a27a35b997`](https://github.com/nodejs/node/commit/a27a35b997)] - **src**: fix decoding base64 with whitespace (Nikolai Vavilov) [#13660](https://github.com/nodejs/node/pull/13660)
+* [[`5b3e5fac38`](https://github.com/nodejs/node/commit/5b3e5fac38)] - **src**: remove void casts for clear_error_on_return (Daniel Bevenius) [#13669](https://github.com/nodejs/node/pull/13669)
+* [[`0a9e96e86c`](https://github.com/nodejs/node/commit/0a9e96e86c)] - **stream**: finish must always follow error (Matteo Collina) [#13850](https://github.com/nodejs/node/pull/13850)
+* [[`5840138e70`](https://github.com/nodejs/node/commit/5840138e70)] - **stream**: fix `undefined` in Readable object mode (Anna Henningsen) [#13760](https://github.com/nodejs/node/pull/13760)
+* [[`f1d96f0b2a`](https://github.com/nodejs/node/commit/f1d96f0b2a)] - **test**: refactor test-http-set-timeout-server (Rich Trott) [#13802](https://github.com/nodejs/node/pull/13802)
+* [[`b23f2461cb`](https://github.com/nodejs/node/commit/b23f2461cb)] - **test**: refactor test-stream2-writable (Rich Trott) [#13823](https://github.com/nodejs/node/pull/13823)
+* [[`9ff9782f66`](https://github.com/nodejs/node/commit/9ff9782f66)] - **test**: remove common module from test it thwarts (Rich Trott) [#13748](https://github.com/nodejs/node/pull/13748)
+* [[`1f32d9ef5b`](https://github.com/nodejs/node/commit/1f32d9ef5b)] - **test**: fix RegExp nits (Vse Mozhet Byt) [#13770](https://github.com/nodejs/node/pull/13770)
+* [[`3306fd1d97`](https://github.com/nodejs/node/commit/3306fd1d97)] - **test**: accommodate AIX by watching file (Rich Trott) [#13766](https://github.com/nodejs/node/pull/13766)
+* [[`c8b134bc6d`](https://github.com/nodejs/node/commit/c8b134bc6d)] - **test**: remove node-tap lookalike (cjihrig) [#13707](https://github.com/nodejs/node/pull/13707)
+* [[`d4a05b2d9c`](https://github.com/nodejs/node/commit/d4a05b2d9c)] - **test**: make test-http(s)-set-timeout-server alike (jklepatch) [#13625](https://github.com/nodejs/node/pull/13625)
+* [[`d0f39cc38a`](https://github.com/nodejs/node/commit/d0f39cc38a)] - **test**: delete outdated fixtures/stdio-filter.js (Vse Mozhet Byt) [#13712](https://github.com/nodejs/node/pull/13712)
+* [[`b2a5399760`](https://github.com/nodejs/node/commit/b2a5399760)] - **test**: refactor test-fs-watch-stop-sync (Rich Trott) [#13689](https://github.com/nodejs/node/pull/13689)
+* [[`10aee10c0c`](https://github.com/nodejs/node/commit/10aee10c0c)] - **test**: check zlib version for createDeflateRaw (Daniel Bevenius) [#13697](https://github.com/nodejs/node/pull/13697)
+* [[`0d3b52e9de`](https://github.com/nodejs/node/commit/0d3b52e9de)] - **test**: add hasIntl to failing test (Daniel Bevenius) [#13699](https://github.com/nodejs/node/pull/13699)
+* [[`70fb1bd038`](https://github.com/nodejs/node/commit/70fb1bd038)] - **test**: improve http test reliability (Brian White) [#13693](https://github.com/nodejs/node/pull/13693)
+* [[`5e59c2d21d`](https://github.com/nodejs/node/commit/5e59c2d21d)] - **test**: increase coverage for internal/module.js (Tamás Hódi) [#13673](https://github.com/nodejs/node/pull/13673)
+* [[`ba20627520`](https://github.com/nodejs/node/commit/ba20627520)] - **test**: refactor test-fs-read-stream (Rich Trott) [#13643](https://github.com/nodejs/node/pull/13643)
+* [[`e203e392d7`](https://github.com/nodejs/node/commit/e203e392d7)] - **test**: refactor test-cluster-worker-isconnected.js (cjihrig) [#13685](https://github.com/nodejs/node/pull/13685)
+* [[`80e6524ff0`](https://github.com/nodejs/node/commit/80e6524ff0)] - **test**: fix nits in test-fs-mkdir-rmdir.js (Vse Mozhet Byt) [#13680](https://github.com/nodejs/node/pull/13680)
+* [[`406c09aacb`](https://github.com/nodejs/node/commit/406c09aacb)] - **test**: fix test-inspector-port-zero-cluster (Refael Ackermann) [#13373](https://github.com/nodejs/node/pull/13373)
+* [[`af46cf621b`](https://github.com/nodejs/node/commit/af46cf621b)] - **test**: refactor test-fs-watch-stop-async (Rich Trott) [#13661](https://github.com/nodejs/node/pull/13661)
+* [[`6920d5c9f9`](https://github.com/nodejs/node/commit/6920d5c9f9)] - **test**: change deprecated method to recommended (Rich Trott) [#13649](https://github.com/nodejs/node/pull/13649)
+* [[`0d87b3102a`](https://github.com/nodejs/node/commit/0d87b3102a)] - **test**: refactor test-fs-read-stream-inherit (Rich Trott) [#13618](https://github.com/nodejs/node/pull/13618)
+* [[`80fa13b93f`](https://github.com/nodejs/node/commit/80fa13b93f)] - **test**: use mustNotCall() in test-fs-watch (Rich Trott) [#13595](https://github.com/nodejs/node/pull/13595)
+* [[`7874360ca2`](https://github.com/nodejs/node/commit/7874360ca2)] - **test**: add mustCall() to child-process test (Rich Trott) [#13605](https://github.com/nodejs/node/pull/13605)
+* [[`5cb3fac396`](https://github.com/nodejs/node/commit/5cb3fac396)] - **test**: use mustNotCall in test-http-eof-on-connect (Rich Trott) [#13587](https://github.com/nodejs/node/pull/13587)
+* [[`4afa7483b1`](https://github.com/nodejs/node/commit/4afa7483b1)] - **test**: increase bufsize in child process write test (Rich Trott) [#13626](https://github.com/nodejs/node/pull/13626)
+* [[`0ef687e858`](https://github.com/nodejs/node/commit/0ef687e858)] - **tools**: fix error in custom ESLint rule (Rich Trott) [#13758](https://github.com/nodejs/node/pull/13758)
+* [[`b171e728e5`](https://github.com/nodejs/node/commit/b171e728e5)] - **tools**: apply stricter indentation rules to tools (Rich Trott) [#13758](https://github.com/nodejs/node/pull/13758)
+* [[`9c2abc3e29`](https://github.com/nodejs/node/commit/9c2abc3e29)] - **tools**: fix indentation in required-modules.js (Rich Trott) [#13758](https://github.com/nodejs/node/pull/13758)
+* [[`ff568d4b63`](https://github.com/nodejs/node/commit/ff568d4b63)] - **tools**: update ESLint to v4.0.0 (Rich Trott) [#13645](https://github.com/nodejs/node/pull/13645)
+* [[`c046a21321`](https://github.com/nodejs/node/commit/c046a21321)] - **util**: ignore invalid format specifiers (Michaël Zasso) [#13674](https://github.com/nodejs/node/pull/13674)
+* [[`c68e472b76`](https://github.com/nodejs/node/commit/c68e472b76)] - **v8**: fix RegExp nits in v8_prof_polyfill.js (Vse Mozhet Byt) [#13709](https://github.com/nodejs/node/pull/13709)
+
## 2017-06-15, Version 8.1.2 (Current), @rvagg
diff --git a/doc/guides/backporting-to-release-lines.md b/doc/guides/backporting-to-release-lines.md
index e7e51eb32ff488..4b5694f0ad486d 100644
--- a/doc/guides/backporting-to-release-lines.md
+++ b/doc/guides/backporting-to-release-lines.md
@@ -6,58 +6,49 @@ Each release line has a staging branch that the releaser will use as a scratch
pad while preparing a release. The branch name is formatted as follows:
`vN.x-staging` where `N` is the major release number.
-### Active staging branches
-
-| Release Line | Staging Branch |
-| ------------ | -------------- |
-| `v7.x` | `v7.x-staging` |
-| `v6.x` | `v6.x-staging` |
-| `v4.x` | `v4.x-staging` |
+*Note*: For the active staging branches see the [LTS Schedule][].
## What needs to be backported?
If a cherry-pick from master does not land cleanly on a staging branch, the
releaser will mark the pull request with a particular label for that release
-line, specifying to our tooling that this pull request should not be included.
-The releaser will then add a comment that a backport is needed.
+line (e.g. `backport-requested-vN.x`), specifying to our tooling that this
+pull request should not be included. The releaser will then add a comment
+requesting that a backport pull request be made.
## What can be backported?
The "Current" release line is much more lenient than the LTS release lines in
-what can be landed. Our LTS release lines (v4.x and v6.x as of March 2017)
-require that commits mature in a Current release for at least 2 weeks before
-they can be landed on staging. If the commit can not be cherry-picked from
-master a manual backport will need to be submitted. Please see the [LTS Plan][]
-for more information. After that time, if the commit can be cherry-picked
-cleanly from master, then nothing needs to be done. If not, a backport pull
-request will need to be submitted.
+what can be landed. Our LTS release lines (see the [LTS Plan][])
+require that commits mature in the Current release for at least 2 weeks before
+they can be landed in an LTS staging branch. Only after "maturation" will those
+commits be cherry-picked or backported.
## How to submit a backport pull request
-For these steps, let's assume that a backport is needed for the v7.x release
-line. All commands will use the v7.x-staging branch as the target branch.
-In order to submit a backport pull request to another branch, simply replace
-that with the staging branch for the targeted release line.
+For the following steps, let's assume that a backport is needed for the v6.x
+release line. All commands will use the `v6.x-staging` branch as the target
+branch. In order to submit a backport pull request to another branch, simply
+replace that with the staging branch for the targeted release line.
-* Checkout the staging branch for the targeted release line
-* Make sure that the local staging branch is up to date with the remote
-* Create a new branch off of the staging branch
+1. Checkout the staging branch for the targeted release line
+2. Make sure that the local staging branch is up to date with the remote
+3. Create a new branch off of the staging branch
```shell
# Assuming your fork of Node.js is checked out in $NODE_DIR,
# the origin remote points to your fork, and the upstream remote points
# to git://github.com/nodejs/node
cd $NODE_DIR
-# Fails if you already have a v7.x-staging
-git branch v7.x-staging upstream/v7.x-staging
-git checkout v7.x-staging
-git reset --hard upstream/v7.x-staging
-# We want to backport pr #10157
-git checkout -b backport-10157-to-v7.x
+# If v6.x-staging is checked out `pull` should be used instead of `fetch`
+git fetch upstream v6.x-staging:v6.x-staging -f
+# Assume we want to backport PR #10157
+git checkout -b backport-10157-to-v6.x v6.x-staging
```
-* After creating the branch, apply the changes to the branch. The cherry-pick
- will likely fail due to conflicts. In that case, you will see something this:
+4. After creating the branch, apply the changes to the branch. The cherry-pick
+ will likely fail due to conflicts. In that case, you will see something
+ like this:
```shell
# Say the $SHA is 773cdc31ef
@@ -68,25 +59,28 @@ hint: with 'git add ' or 'git rm '
hint: and commit the result with 'git commit'
```
-* Make the required changes to remove the conflicts, add the files to the index
- using `git add`, and then commit the changes. That can be done with
- `git cherry-pick --continue`.
-* Leave the commit message as is. If you think it should be modified, comment
- in the Pull Request.
-* Make sure `make -j4 test` passes
-* Push the changes to your fork and open a pull request.
-* Be sure to target the `v7.x-staging` branch in the pull request.
-
-### Helpful Hints
-
-* Please include the backport target in the pull request title in the following
- format: `(v7.x backport) `
- * Ex. `(v4.x backport) process: improve performance of nextTick`
-* Please check the checkbox labelled "Allow edits from maintainers".
- This is the easiest way to to avoid constant rebases.
-
-In the event the backport pull request is different than the original,
-the backport pull request should be reviewed the same way a new pull request
-is reviewed.
-
+5. Make the required changes to remove the conflicts, add the files to the index
+ using `git add`, and then commit the changes. That can be done with
+ `git cherry-pick --continue`.
+6. Leave the commit message as is. If you think it should be modified, comment
+ in the Pull Request.
+7. Make sure `make -j4 test` passes.
+8. Push the changes to your fork
+9. Open a pull request:
+ 1. Be sure to target the `v6.x-staging` branch in the pull request.
+ 2. Include the backport target in the pull request title in the following
+ format — `[v6.x backport] `.
+ Example: `[v6.x backport] process: improve performance of nextTick`
+ 3. Check the checkbox labelled "Allow edits from maintainers".
+ 4. In the description add a reference to the original PR
+ 5. Run a [`node-test-pull-request`][] CI job (with `REBASE_ONTO` set to the
+ default ``)
+10. If during the review process conflicts arise, use the following to rebase:
+ `git pull --rebase upstream v6.x-staging`
+
+After the PR lands replace the `backport-requested-v6.x` label on the original
+PR with `backported-to-v6.x`.
+
+[LTS Schedule]: https://github.com/nodejs/LTS/#lts-schedule1
[LTS Plan]: https://github.com/nodejs/LTS#lts-plan
+[`node-test-pull-request`]: https://ci.nodejs.org/job/node-test-pull-request/build
diff --git a/doc/onboarding-extras.md b/doc/onboarding-extras.md
index 3f174843397b3d..2eafe2ffabd1ea 100644
--- a/doc/onboarding-extras.md
+++ b/doc/onboarding-extras.md
@@ -14,11 +14,12 @@
| `lib/dgram` | @cjihrig, @mcollina |
| `lib/domains` | @misterdjules |
| `lib/fs`, `src/{fs,file}` | @nodejs/fs |
-| `lib/internal/url`, `src/node_url` | @nodejs/url |
| `lib/{_}http{*}` | @nodejs/http |
+| `lib/inspector.js`, `src/inspector_*` | @nodejs/v8-inspector |
+| `lib/internal/url`, `src/node_url` | @nodejs/url |
| `lib/net` | @bnoordhuis, @indutny, @nodejs/streams |
-| `lib/{_}stream{*}` | @nodejs/streams |
| `lib/repl` | @addaleax, @fishrock123 |
+| `lib/{_}stream{*}` | @nodejs/streams |
| `lib/timers` | @fishrock123, @misterdjules |
| `lib/util` | @bnoordhuis, @cjihrig, @evanlucas |
| `lib/zlib` | @addaleax, @bnoordhuis, @indutny |
@@ -29,14 +30,13 @@
| `tools/eslint`, `.eslintrc` | @not-an-aardvark, @silverwind, @trott |
| async_hooks | @nodejs/async_hooks for bugs/reviews (+ @nodejs/diagnostics for API) |
| performance | @nodejs/performance |
-| upgrading V8 | @nodejs/v8, @nodejs/post-mortem |
-| upgrading npm | @fishrock123, @MylesBorins |
+| platform specific | @nodejs/platform-{aix,arm,freebsd,macos,ppc,smartos,s390,windows} |
+| python code | @nodejs/python |
| upgrading c-ares | @jbergstroem |
| upgrading http-parser | @jbergstroem, @nodejs/http |
| upgrading libuv | @saghul |
-| python code | @nodejs/python |
-| platform specific | @nodejs/platform-{aix,arm,freebsd,macos,ppc,smartos,s390,windows} |
-
+| upgrading npm | @fishrock123, @MylesBorins |
+| upgrading V8 | @nodejs/v8, @nodejs/post-mortem |
When things need extra attention, are controversial, or `semver-major`: @nodejs/ctc
diff --git a/doc/onboarding.md b/doc/onboarding.md
index e6bef3f631a2ac..e1e10d88b30243 100644
--- a/doc/onboarding.md
+++ b/doc/onboarding.md
@@ -13,7 +13,9 @@ onboarding session.
## Fifteen minutes before the onboarding session
* Prior to the onboarding session, add the new Collaborator to
- [the Collaborators team](https://github.com/orgs/nodejs/teams/collaborators).
+ [the Collaborators team](https://github.com/orgs/nodejs/teams/collaborators),
+ and to [the Members team](https://github.com/orgs/nodejs/teams/members) if
+ they are not already part of it.
Note that this is the step that gives the account elevated privileges, so
do not perform this step (or any subsequent steps) unless two-factor
authentication is enabled on the new Collaborator's GitHub account.
@@ -21,8 +23,7 @@ onboarding session.
## Onboarding session
-* **thank you** for doing this
-* will cover:
+* This session will cover:
* [local setup](#local-setup)
* [project goals & values](#project-goals--values)
* [managing the issue tracker](#managing-the-issue-tracker)
@@ -32,33 +33,37 @@ onboarding session.
## Local setup
* git:
- * make sure you have whitespace=fix: `git config --global --add apply.whitespace fix`
- * usually PR from your own github fork
+ * Make sure you have whitespace=fix: `git config --global --add apply.whitespace fix`
+ * Always continue to PR from your own github fork
+ * Branches in the nodejs/node repository are only for release lines
* [See "Updating Node.js from Upstream"](./onboarding-extras.md#updating-nodejs-from-upstream)
- * make new branches for all commits you make!
+ * Make a new branch for each PR you submit.
- * notifications:
- * use [https://github.com/notifications](https://github.com/notifications) or set up email
- * watching the main repo will flood your inbox, so be prepared
+ * Notifications:
+ * Use [https://github.com/notifications](https://github.com/notifications) or set up email
+ * Watching the main repo will flood your inbox (several hundred notifications on typical weekdays), so be prepared
- * `#node-dev` on [webchat.freenode.net](https://webchat.freenode.net/) is the best place to interact with the CTC / other collaborators
+ * `#node-dev` on [webchat.freenode.net](https://webchat.freenode.net/) is the best place to interact with the CTC / other Collaborators
+ * If there are any questions after the session, a good place to ask is there!
+ * Presence is not mandatory, but please drop a note there if force-pushing to `master`
## Project goals & values
- * collaborators are effectively part owners
- * the project has the goals of its contributors
+ * Collaborators are the collective owners of the project
+ * The project has the goals of its contributors
- * but, there are some higher-level goals and values
- * not everything belongs in core (if it can be done reasonably in userland, let it stay in userland)
- * empathy towards users matters (this is in part why we onboard people)
- * generally: try to be nice to people
+ * There are some higher-level goals and values
+ * Empathy towards users matters (this is in part why we onboard people)
+ * Generally: try to be nice to people!
+ * The best outcome is for people who come to our issue tracker to feel like they can come back again.
+
+ * We have a [Code of Conduct][] that you are expected to follow *and* hold others accountable to
## Managing the issue tracker
- * you have (mostly) free rein – don't hesitate to close an issue if you are confident that it should be closed
- * **IMPORTANT**: be nice about closing issues, let people know why, and that issues and PRs can be reopened if necessary
- * Still need to follow the Code of Conduct
+ * You have (mostly) free rein; don't hesitate to close an issue if you are confident that it should be closed
+ * Be nice about closing issues! Let people know why, and that issues and PRs can be reopened if necessary
* [**See "Labels"**](./onboarding-extras.md#labels)
* There is [a bot](https://github.com/nodejs-github-bot/github-bot) that applies subsystem labels (for example, `doc`, `test`, `assert`, or `buffer`) so that we know what parts of the code base the pull request modifies. It is not perfect, of course. Feel free to apply relevant labels and remove irrelevant labels from pull requests and issues.
@@ -69,9 +74,11 @@ onboarding session.
* When adding a semver label, add a comment explaining why you're adding it. Do it right away so you don't forget!
* [**See "Who to CC in issues"**](./onboarding-extras.md#who-to-cc-in-issues)
- * will also come more naturally over time
+ * This will come more naturally over time
+ * For many of the teams listed there, you can ask to be added if you are interested
+ * Some are WGs with some process around adding people, others are only there for notifications
- * When a discussion gets heated, you can request that other collaborators keep an eye on it by opening an issue at the private [nodejs/moderation](https://github.com/nodejs/moderation) repository.
+ * When a discussion gets heated, you can request that other Collaborators keep an eye on it by opening an issue at the private [nodejs/moderation](https://github.com/nodejs/moderation) repository.
* This is a repository to which all members of the `nodejs` GitHub organization (not just Collaborators on Node.js core) have access. Its contents should not be shared externally.
* You can find the full moderation policy [here](https://github.com/nodejs/TSC/blob/master/Moderation-Policy.md).
@@ -100,18 +107,24 @@ onboarding session.
(especially if it just has nits left).
* Approving a change
* Collaborators indicate that they have reviewed and approve of the
- the changes in a pull request by commenting with `LGTM`, which stands
- for "looks good to me".
- * You have the power to `LGTM` another collaborator's (including TSC/CTC
- members) work.
- * You may not `LGTM` your own pull requests.
- * You have the power to `LGTM` anyone else's pull requests.
-
- * What belongs in node:
- * opinions vary, but I find the following helpful:
- * if node itself needs it (due to historic reasons), then it belongs in node
- * that is to say, url is there because of http, freelist is there because of http, et al
- * also, things that cannot be done outside of core, or only with significant pain (example: async-wrap)
+ the changes in a pull request using Github’s approval interface
+ * Some people like to comment `LGTM` (“Looks Good To Me”)
+ * You have the authority to approve any other collaborator’s work.
+ * You cannot approve your own pull requests.
+ * When explicitly using `Changes requested`, show empathy – comments will
+ usually be addressed even if you don’t use it.
+ * If you do, it is nice if you are available later to check whether your
+ comments have been addressed
+ * If you see that the requested changes have been made, you can clear another collaborator's
+ `Changes requested` review.
+ * Use `Changes requested` to indicate that you are considering some of
+ your comments to block the PR from landing.
+
+ * What belongs in Node.js:
+ * Opinions vary – it’s good to have a broad collaborator base for that reason!
+ * If Node.js itself needs it (due to historic reasons), then it belongs in Node.js
+ * That is to say, url is there because of http, freelist is there because of http, etc.
+ * Things that cannot be done outside of core, or only with significant pain (for example `async_hooks`)
* Continuous Integration (CI) Testing:
* [https://ci.nodejs.org/](https://ci.nodejs.org/)
@@ -136,26 +149,30 @@ onboarding session.
## Exercise: Make a PR adding yourself to the README
- * Example: [https://github.com/nodejs/node/commit/7b09aade8468e1c930f36b9c81e6ac2ed5bc8732](https://github.com/nodejs/node/commit/7b09aade8468e1c930f36b9c81e6ac2ed5bc8732)
- * For raw commit message: `git log 7b09aade8468e1c930f36b9c81e6ac2ed5bc8732 -1`
+ * Example: [https://github.com/nodejs/node/commit/ce986de829457c39257cd205067602e765768fb0](https://github.com/nodejs/node/commit/ce986de829457c39257cd205067602e765768fb0)
+ * For raw commit message: `git log ce986de829457c39257cd205067602e765768fb0 -1`
* Collaborators are in alphabetical order by GitHub username.
* Optionally, include your personal pronouns.
* Label your pull request with the `doc` subsystem label.
* Run CI on your PR.
- * After a `LGTM` or two, land the PR.
+ * After one or two approvals, land the PR.
* Be sure to add the `PR-URL: ` and appropriate `Reviewed-By:` metadata!
+ * [`core-validate-commit`][] helps a lot with this – install and use it if you can!
+ * If you use Chrome, [`node-review`][] fetches the metadata for you
## Final notes
- * don't worry about making mistakes: everybody makes them, there's a lot to internalize and that takes time (and we recognize that!)
- * very few (no?) mistakes are unrecoverable
- * the existing collaborators trust you and are grateful for your help!
- * other repos:
- * [https://github.com/nodejs/dev-policy](https://github.com/nodejs/dev-policy)
- * [https://github.com/nodejs/NG](https://github.com/nodejs/NG)
- * [https://github.com/nodejs/api](https://github.com/nodejs/api)
+ * Don't worry about making mistakes: everybody makes them, there's a lot to internalize and that takes time (and we recognize that!)
+ * Almost any mistake you could make can be fixed or reverted.
+ * The existing Collaborators trust you and are grateful for your help!
+ * Other repositories:
+ * [https://github.com/nodejs/CTC](https://github.com/nodejs/CTC)
* [https://github.com/nodejs/build](https://github.com/nodejs/build)
- * [https://github.com/nodejs/docs](https://github.com/nodejs/docs)
* [https://github.com/nodejs/nodejs.org](https://github.com/nodejs/nodejs.org)
* [https://github.com/nodejs/readable-stream](https://github.com/nodejs/readable-stream)
* [https://github.com/nodejs/LTS](https://github.com/nodejs/LTS)
+ * [https://github.com/nodejs/citgm](https://github.com/nodejs/citgm)
+
+[Code of Conduct]: https://github.com/nodejs/TSC/blob/master/CODE_OF_CONDUCT.md
+[`core-validate-commit`]: https://github.com/evanlucas/core-validate-commit
+[`node-review`]: https://github.com/evanlucas/node-review
diff --git a/doc/releases.md b/doc/releases.md
index f1f82fdb9816bb..d2dd317fdb416b 100644
--- a/doc/releases.md
+++ b/doc/releases.md
@@ -253,7 +253,7 @@ PR-URL:
This sets up the branch so that nightly builds are produced with the next version number _and_ a pre-release tag.
-Merge your release branch into the stable branch that you are releasing from (not master).
+Merge your release proposal branch into the stable branch that you are releasing from (e.g. `v8.x`), and rebase the corresponding staging branch (`v8.x-staging`) on top of that.
Cherry-pick the release commit to `master`. After cherry-picking, edit `src/node_version.h` to ensure the version macros contain whatever values were previously on `master`. `NODE_VERSION_IS_RELEASE` should be `0`.
diff --git a/lib/_stream_readable.js b/lib/_stream_readable.js
index 900f42e1713954..a308e8baeda452 100644
--- a/lib/_stream_readable.js
+++ b/lib/_stream_readable.js
@@ -215,8 +215,8 @@ function readableAddChunk(stream, chunk, encoding, addToFront, skipChunkCheck) {
stream.emit('error', er);
} else if (state.objectMode || chunk && chunk.length > 0) {
if (typeof chunk !== 'string' &&
- Object.getPrototypeOf(chunk) !== Buffer.prototype &&
- !state.objectMode) {
+ !state.objectMode &&
+ Object.getPrototypeOf(chunk) !== Buffer.prototype) {
chunk = Stream._uint8ArrayToBuffer(chunk);
}
diff --git a/lib/_stream_writable.js b/lib/_stream_writable.js
index 615f5a37624f31..78ab13d9063c67 100644
--- a/lib/_stream_writable.js
+++ b/lib/_stream_writable.js
@@ -374,18 +374,26 @@ function doWrite(stream, state, writev, len, chunk, encoding, cb) {
function onwriteError(stream, state, sync, er, cb) {
--state.pendingcb;
- if (sync)
- process.nextTick(afterError, stream, state, cb, er);
- else
- afterError(stream, state, cb, er);
-
- stream._writableState.errorEmitted = true;
- stream.emit('error', er);
-}
-function afterError(stream, state, cb, err) {
- cb(err);
- finishMaybe(stream, state);
+ if (sync) {
+ // defer the callback if we are being called synchronously
+ // to avoid piling up things on the stack
+ process.nextTick(cb, er);
+ // this can emit finish, and it will always happen
+ // after error
+ process.nextTick(finishMaybe, stream, state);
+ stream._writableState.errorEmitted = true;
+ stream.emit('error', er);
+ } else {
+ // the caller expect this to happen before if
+ // it is async
+ cb(er);
+ stream._writableState.errorEmitted = true;
+ stream.emit('error', er);
+ // this can emit finish, but finish must
+ // always follow error
+ finishMaybe(stream, state);
+ }
}
function onwriteStateUpdate(state) {
diff --git a/lib/_tls_common.js b/lib/_tls_common.js
index 2f0b17b111a420..afcc5bc5fa2f96 100644
--- a/lib/_tls_common.js
+++ b/lib/_tls_common.js
@@ -91,7 +91,7 @@ exports.createSecureContext = function createSecureContext(options, context) {
}
// NOTE: It is important to set the key after the cert.
- // `ssl_set_pkey` returns `0` when the key does not much the cert, but
+ // `ssl_set_pkey` returns `0` when the key does not match the cert, but
// `ssl_set_cert` returns `1` and nullifies the key in the SSL structure
// which leads to the crash later on.
if (options.key) {
diff --git a/lib/dgram.js b/lib/dgram.js
index 0d93ca28748e87..55753b177279a9 100644
--- a/lib/dgram.js
+++ b/lib/dgram.js
@@ -524,35 +524,31 @@ Socket.prototype.setBroadcast = function(arg) {
};
-Socket.prototype.setTTL = function(arg) {
- if (typeof arg !== 'number') {
- throw new errors.TypeError('ERR_INVALID_ARG_TYPE',
- 'arg',
- 'number');
+Socket.prototype.setTTL = function(ttl) {
+ if (typeof ttl !== 'number') {
+ throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'ttl', 'number', ttl);
}
- var err = this._handle.setTTL(arg);
+ var err = this._handle.setTTL(ttl);
if (err) {
throw errnoException(err, 'setTTL');
}
- return arg;
+ return ttl;
};
-Socket.prototype.setMulticastTTL = function(arg) {
- if (typeof arg !== 'number') {
- throw new errors.TypeError('ERR_INVALID_ARG_TYPE',
- 'arg',
- 'number');
+Socket.prototype.setMulticastTTL = function(ttl) {
+ if (typeof ttl !== 'number') {
+ throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'ttl', 'number', ttl);
}
- var err = this._handle.setMulticastTTL(arg);
+ var err = this._handle.setMulticastTTL(ttl);
if (err) {
throw errnoException(err, 'setMulticastTTL');
}
- return arg;
+ return ttl;
};
diff --git a/lib/fs.js b/lib/fs.js
index 6273c975c120ce..25dad8bf2c8410 100644
--- a/lib/fs.js
+++ b/lib/fs.js
@@ -1320,7 +1320,7 @@ fs.writeFileSync = function(path, data, options) {
};
fs.appendFile = function(path, data, options, callback) {
- callback = maybeCallback(arguments[arguments.length - 1]);
+ callback = maybeCallback(callback || options);
options = getOptions(options, { encoding: 'utf8', mode: 0o666, flag: 'a' });
// Don't make changes directly on options object
diff --git a/lib/internal/cluster/master.js b/lib/internal/cluster/master.js
index 05bba01c4ed6e8..2d1e2d3097f75b 100644
--- a/lib/internal/cluster/master.js
+++ b/lib/internal/cluster/master.js
@@ -96,26 +96,16 @@ function setupSettingsNT(settings) {
}
function createWorkerProcess(id, env) {
- var workerEnv = util._extend({}, process.env);
- var execArgv = cluster.settings.execArgv.slice();
- var debugPort = 0;
- var debugArgvRE =
- /^(--inspect|--inspect-(brk|port)|--debug|--debug-(brk|port))(=\d+)?$/;
+ const workerEnv = util._extend({}, process.env);
+ const execArgv = cluster.settings.execArgv.slice();
+ const debugArgRegex = /--inspect(?:-brk|-port)?|--debug-port/;
util._extend(workerEnv, env);
workerEnv.NODE_UNIQUE_ID = '' + id;
- for (var i = 0; i < execArgv.length; i++) {
- const match = execArgv[i].match(debugArgvRE);
-
- if (match) {
- if (debugPort === 0) {
- debugPort = process.debugPort + debugPortOffset;
- ++debugPortOffset;
- }
-
- execArgv[i] = match[1] + '=' + debugPort;
- }
+ if (execArgv.some((arg) => arg.match(debugArgRegex))) {
+ execArgv.push(`--inspect-port=${process.debugPort + debugPortOffset}`);
+ debugPortOffset++;
}
return fork(cluster.settings.exec, cluster.settings.args, {
diff --git a/lib/internal/url.js b/lib/internal/url.js
index 14c22e4ff467b6..7d7c79149a5c4f 100644
--- a/lib/internal/url.js
+++ b/lib/internal/url.js
@@ -51,7 +51,7 @@ const IteratorPrototype = Object.getPrototypeOf(
);
const unpairedSurrogateRe =
- /([^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])/;
+ /(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])/;
function toUSVString(val) {
const str = `${val}`;
// As of V8 5.5, `str.search()` (and `unpairedSurrogateRe[@@search]()`) are
diff --git a/lib/internal/v8_prof_polyfill.js b/lib/internal/v8_prof_polyfill.js
index 34cd10337f12a1..e77f1f76bcb9ee 100644
--- a/lib/internal/v8_prof_polyfill.js
+++ b/lib/internal/v8_prof_polyfill.js
@@ -105,12 +105,13 @@ function versionCheck() {
function macCppfiltNm(out) {
// Re-grouped copy-paste from `tickprocessor.js`
const FUNC_RE = /^([0-9a-fA-F]{8,16} [iItT] )(.*)$/gm;
+ const CLEAN_RE = /^[0-9a-fA-F]{8,16} [iItT] /;
let entries = out.match(FUNC_RE);
if (entries === null)
return out;
entries = entries.map((entry) => {
- return entry.replace(/^[0-9a-fA-F]{8,16} [iItT] /, '')
+ return entry.replace(CLEAN_RE, '')
});
let filtered;
@@ -123,7 +124,7 @@ function macCppfiltNm(out) {
}
let i = 0;
- filtered = filtered.split(/\n/g);
+ filtered = filtered.split('\n');
return out.replace(FUNC_RE, (all, prefix, postfix) => {
return prefix + (filtered[i++] || postfix);
});
diff --git a/lib/net.js b/lib/net.js
index 67c231ef25607a..19f69aaaad73b8 100644
--- a/lib/net.js
+++ b/lib/net.js
@@ -42,6 +42,7 @@ const WriteWrap = process.binding('stream_wrap').WriteWrap;
const async_id_symbol = process.binding('async_wrap').async_id_symbol;
const { newUid, setInitTriggerId } = require('async_hooks');
const nextTick = require('internal/process/next_tick').nextTick;
+const errors = require('internal/errors');
var cluster;
var dns;
@@ -964,8 +965,9 @@ Socket.prototype.connect = function() {
this._sockname = null;
}
- var pipe = !!options.path;
- debug('pipe', pipe, options.path);
+ const path = options.path;
+ var pipe = !!path;
+ debug('pipe', pipe, path);
if (!this._handle) {
this._handle = pipe ? new Pipe() : new TCP();
@@ -982,7 +984,13 @@ Socket.prototype.connect = function() {
this.writable = true;
if (pipe) {
- internalConnect(this, options.path);
+ if (typeof path !== 'string') {
+ throw new errors.TypeError('ERR_INVALID_ARG_TYPE',
+ 'options.path',
+ 'string',
+ path);
+ }
+ internalConnect(this, path);
} else {
lookupAndConnect(this, options);
}
diff --git a/lib/readline.js b/lib/readline.js
index 60864f40afdbc1..133ef1cf3f6c6e 100644
--- a/lib/readline.js
+++ b/lib/readline.js
@@ -541,7 +541,7 @@ function commonPrefix(strings) {
Interface.prototype._wordLeft = function() {
if (this.cursor > 0) {
var leading = this.line.slice(0, this.cursor);
- var match = leading.match(/([^\w\s]+|\w+|)\s*$/);
+ var match = leading.match(/(?:[^\w\s]+|\w+|)\s*$/);
this._moveCursor(-match[0].length);
}
};
@@ -550,7 +550,7 @@ Interface.prototype._wordLeft = function() {
Interface.prototype._wordRight = function() {
if (this.cursor < this.line.length) {
var trailing = this.line.slice(this.cursor);
- var match = trailing.match(/^(\s+|\W+|\w+)\s*/);
+ var match = trailing.match(/^(?:\s+|\W+|\w+)\s*/);
this._moveCursor(match[0].length);
}
};
@@ -577,7 +577,7 @@ Interface.prototype._deleteRight = function() {
Interface.prototype._deleteWordLeft = function() {
if (this.cursor > 0) {
var leading = this.line.slice(0, this.cursor);
- var match = leading.match(/([^\w\s]+|\w+|)\s*$/);
+ var match = leading.match(/(?:[^\w\s]+|\w+|)\s*$/);
leading = leading.slice(0, leading.length - match[0].length);
this.line = leading + this.line.slice(this.cursor, this.line.length);
this.cursor = leading.length;
@@ -589,7 +589,7 @@ Interface.prototype._deleteWordLeft = function() {
Interface.prototype._deleteWordRight = function() {
if (this.cursor < this.line.length) {
var trailing = this.line.slice(this.cursor);
- var match = trailing.match(/^(\s+|\W+|\w+)\s*/);
+ var match = trailing.match(/^(?:\s+|\W+|\w+)\s*/);
this.line = this.line.slice(0, this.cursor) +
trailing.slice(match[0].length);
this._refreshLine();
diff --git a/lib/repl.js b/lib/repl.js
index 90ca02027a68ce..cf19e6f1999a07 100644
--- a/lib/repl.js
+++ b/lib/repl.js
@@ -679,9 +679,9 @@ ArrayStream.prototype.writable = true;
ArrayStream.prototype.resume = function() {};
ArrayStream.prototype.write = function() {};
-const requireRE = /\brequire\s*\(['"](([\w@./-]+\/)?([\w@./-]*))/;
+const requireRE = /\brequire\s*\(['"](([\w@./-]+\/)?(?:[\w@./-]*))/;
const simpleExpressionRE =
- /(([a-zA-Z_$](?:\w|\$)*)\.)*([a-zA-Z_$](?:\w|\$)*)\.?$/;
+ /(?:[a-zA-Z_$](?:\w|\$)*\.)*[a-zA-Z_$](?:\w|\$)*\.?$/;
function intFilter(item) {
// filters out anything not starting with A-Z, a-z, $ or _
@@ -752,7 +752,7 @@ function complete(line, callback) {
} else if (match = line.match(requireRE)) {
// require('...')
const exts = Object.keys(this.context.require.extensions);
- var indexRe = new RegExp('^index(' + exts.map(regexpEscape).join('|') +
+ var indexRe = new RegExp('^index(?:' + exts.map(regexpEscape).join('|') +
')$');
var versionedFileNamesRe = /-\d+\.\d+/;
diff --git a/lib/url.js b/lib/url.js
index 6227c8a057a4ce..633d3a40a493bc 100644
--- a/lib/url.js
+++ b/lib/url.js
@@ -56,7 +56,7 @@ function Url() {
// define these here so at least they only have to be
// compiled once on the first module load.
-const protocolPattern = /^([a-z0-9.+-]+:)/i;
+const protocolPattern = /^[a-z0-9.+-]+:/i;
const portPattern = /:[0-9]*$/;
const hostPattern = /^\/\/[^@/]+@[^@/]+/;
diff --git a/lib/util.js b/lib/util.js
index d6d8b9de006042..c998888e8e4798 100644
--- a/lib/util.js
+++ b/lib/util.js
@@ -112,6 +112,12 @@ exports.format = function(f) {
str += f.slice(lastPos, i);
str += '%';
break;
+ default: // any other character is not a correct placeholder
+ if (lastPos < i)
+ str += f.slice(lastPos, i);
+ str += '%';
+ lastPos = i = i + 1;
+ continue;
}
lastPos = i = i + 2;
continue;
@@ -791,7 +797,7 @@ function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
if (array) {
str = str.replace(/\n/g, '\n ');
} else {
- str = str.replace(/(^|\n)/g, '\n ');
+ str = str.replace(/^|\n/g, '\n ');
}
}
} else {
@@ -803,13 +809,13 @@ function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
return str;
}
name = JSON.stringify('' + key);
- if (/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/.test(name)) {
+ if (/^"[a-zA-Z_][a-zA-Z_0-9]*"$/.test(name)) {
name = name.substr(1, name.length - 2);
name = ctx.stylize(name, 'name');
} else {
name = name.replace(/'/g, "\\'")
.replace(/\\"/g, '"')
- .replace(/(^"|"$)/g, "'")
+ .replace(/^"|"$/g, "'")
.replace(/\\\\/g, '\\');
name = ctx.stylize(name, 'string');
}
diff --git a/src/base64.h b/src/base64.h
index 2e0f8e3858209e..89c6251ef8fea6 100644
--- a/src/base64.h
+++ b/src/base64.h
@@ -99,10 +99,9 @@ size_t base64_decode_fast(char* const dst, const size_t dstlen,
unbase64(src[i + 3]);
// If MSB is set, input contains whitespace or is not valid base64.
if (v & 0x80808080) {
- const size_t old_i = i;
if (!base64_decode_group_slow(dst, dstlen, src, srclen, &i, &k))
return k;
- max_i = old_i + (srclen - i) / 4 * 4; // Align max_i again.
+ max_i = i + (srclen - i) / 4 * 4; // Align max_i again.
} else {
dst[k + 0] = ((v >> 22) & 0xFC) | ((v >> 20) & 0x03);
dst[k + 1] = ((v >> 12) & 0xF0) | ((v >> 10) & 0x0F);
diff --git a/src/node.cc b/src/node.cc
index bbce10220fe175..beeebe6923a18e 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -242,7 +242,7 @@ static double prog_start_time;
static Mutex node_isolate_mutex;
static v8::Isolate* node_isolate;
-static node::DebugOptions debug_options;
+node::DebugOptions debug_options;
static struct {
#if NODE_USE_V8_PLATFORM
@@ -4305,14 +4305,6 @@ void Init(int* argc,
// Make inherited handles noninheritable.
uv_disable_stdio_inheritance();
-#if defined(NODE_HAVE_I18N_SUPPORT)
- // Set the ICU casing flag early
- // so the user can disable a flag --foo at run-time by passing
- // --no_foo from the command line.
- const char icu_case_mapping[] = "--icu_case_mapping";
- V8::SetFlagsFromString(icu_case_mapping, sizeof(icu_case_mapping) - 1);
-#endif
-
#if defined(NODE_V8_OPTIONS)
// Should come before the call to V8::SetFlagsFromCommandLine()
// so the user can disable a flag --foo at run-time by passing
diff --git a/src/node_api.cc b/src/node_api.cc
index 0c8abd0998e734..9c579cde726869 100644
--- a/src/node_api.cc
+++ b/src/node_api.cc
@@ -17,6 +17,7 @@
#include
#include "uv.h"
#include "node_api.h"
+#include "node_internals.h"
#define NAPI_VERSION 1
@@ -156,14 +157,20 @@ class HandleScopeWrapper {
// across different versions.
class EscapableHandleScopeWrapper {
public:
- explicit EscapableHandleScopeWrapper(v8::Isolate* isolate) : scope(isolate) {}
+ explicit EscapableHandleScopeWrapper(v8::Isolate* isolate)
+ : scope(isolate), escape_called_(false) {}
+ bool escape_called() const {
+ return escape_called_;
+ }
template
v8::Local Escape(v8::Local handle) {
+ escape_called_ = true;
return scope.Escape(handle);
}
private:
v8::EscapableHandleScope scope;
+ bool escape_called_;
};
napi_handle_scope JsHandleScopeFromV8HandleScope(HandleScopeWrapper* s) {
@@ -718,7 +725,8 @@ const char* error_messages[] = {nullptr,
"An array was expected",
"Unknown failure",
"An exception is pending",
- "The async work item was cancelled"};
+ "The async work item was cancelled",
+ "napi_escape_handle already called on scope"};
static napi_status napi_clear_last_error(napi_env env) {
CHECK_ENV(env);
@@ -746,10 +754,14 @@ napi_status napi_get_last_error_info(napi_env env,
CHECK_ENV(env);
CHECK_ARG(env, result);
+ // you must update this assert to reference the last message
+ // in the napi_status enum each time a new error message is added.
+ // We don't have a napi_status_last as this would result in an ABI
+ // change each time a message was added.
static_assert(
- (sizeof (error_messages) / sizeof (*error_messages)) == napi_status_last,
+ node::arraysize(error_messages) == napi_escape_called_twice + 1,
"Count of error messages must match count of error values");
- assert(env->last_error.error_code < napi_status_last);
+ assert(env->last_error.error_code <= napi_escape_called_twice);
// Wait until someone requests the last error information to fetch the error
// message string
@@ -2211,9 +2223,12 @@ napi_status napi_escape_handle(napi_env env,
v8impl::EscapableHandleScopeWrapper* s =
v8impl::V8EscapableHandleScopeFromJsEscapableHandleScope(scope);
- *result = v8impl::JsValueFromV8LocalValue(
- s->Escape(v8impl::V8LocalValueFromJsValue(escapee)));
- return napi_clear_last_error(env);
+ if (!s->escape_called()) {
+ *result = v8impl::JsValueFromV8LocalValue(
+ s->Escape(v8impl::V8LocalValueFromJsValue(escapee)));
+ return napi_clear_last_error(env);
+ }
+ return napi_set_last_error(env, napi_escape_called_twice);
}
napi_status napi_new_instance(napi_env env,
diff --git a/src/node_api_types.h b/src/node_api_types.h
index 4bf1b8263139d8..43102c519c03f9 100644
--- a/src/node_api_types.h
+++ b/src/node_api_types.h
@@ -67,7 +67,7 @@ typedef enum {
napi_generic_failure,
napi_pending_exception,
napi_cancelled,
- napi_status_last
+ napi_escape_called_twice
} napi_status;
typedef napi_value (*napi_callback)(napi_env env,
diff --git a/src/node_config.cc b/src/node_config.cc
index f4729a64fe6bcb..b309171282182a 100644
--- a/src/node_config.cc
+++ b/src/node_config.cc
@@ -4,11 +4,14 @@
#include "env-inl.h"
#include "util.h"
#include "util-inl.h"
+#include "node_debug_options.h"
namespace node {
+using v8::Boolean;
using v8::Context;
+using v8::Integer;
using v8::Local;
using v8::Object;
using v8::ReadOnly;
@@ -62,6 +65,27 @@ static void InitConfig(Local target,
target->DefineOwnProperty(env->context(), name, value).FromJust();
}
+ Local debugOptions = Object::New(env->isolate());
+
+ target->DefineOwnProperty(env->context(),
+ OneByteString(env->isolate(), "debugOptions"),
+ debugOptions).FromJust();
+
+ debugOptions->DefineOwnProperty(env->context(),
+ OneByteString(env->isolate(), "host"),
+ String::NewFromUtf8(env->isolate(),
+ debug_options.host_name().c_str())).FromJust();
+
+ debugOptions->DefineOwnProperty(env->context(),
+ OneByteString(env->isolate(), "port"),
+ Integer::New(env->isolate(),
+ debug_options.port())).FromJust();
+
+ debugOptions->DefineOwnProperty(env->context(),
+ OneByteString(env->isolate(), "inspectorEnabled"),
+ Boolean::New(env->isolate(),
+ debug_options.inspector_enabled())).FromJust();
+
if (config_expose_internals)
READONLY_BOOLEAN_PROPERTY("exposeInternals");
} // InitConfig
diff --git a/src/node_crypto.cc b/src/node_crypto.cc
index 579ba3c65da640..9d196c10cc8c3f 100644
--- a/src/node_crypto.cc
+++ b/src/node_crypto.cc
@@ -768,7 +768,6 @@ void SecureContext::AddCACert(const FunctionCallbackInfo& args) {
SecureContext* sc;
ASSIGN_OR_RETURN_UNWRAP(&sc, args.Holder());
ClearErrorOnReturn clear_error_on_return;
- (void) &clear_error_on_return; // Silence compiler warning.
if (args.Length() != 1) {
return env->ThrowTypeError("CA certificate argument is mandatory");
@@ -806,7 +805,6 @@ void SecureContext::AddCRL(const FunctionCallbackInfo& args) {
}
ClearErrorOnReturn clear_error_on_return;
- (void) &clear_error_on_return; // Silence compiler warning.
BIO *bio = LoadBIO(env, args[0]);
if (!bio)
@@ -872,7 +870,6 @@ void SecureContext::AddRootCerts(const FunctionCallbackInfo& args) {
SecureContext* sc;
ASSIGN_OR_RETURN_UNWRAP(&sc, args.Holder());
ClearErrorOnReturn clear_error_on_return;
- (void) &clear_error_on_return; // Silence compiler warning.
if (!root_cert_store) {
root_cert_store = NewRootCertStore();
@@ -901,7 +898,6 @@ void SecureContext::SetCiphers(const FunctionCallbackInfo& args) {
ASSIGN_OR_RETURN_UNWRAP(&sc, args.Holder());
Environment* env = sc->env();
ClearErrorOnReturn clear_error_on_return;
- (void) &clear_error_on_return; // Silence compiler warning.
if (args.Length() != 1) {
return env->ThrowTypeError("Ciphers argument is mandatory");
@@ -948,7 +944,6 @@ void SecureContext::SetDHParam(const FunctionCallbackInfo& args) {
ASSIGN_OR_RETURN_UNWRAP(&sc, args.This());
Environment* env = sc->env();
ClearErrorOnReturn clear_error_on_return;
- (void) &clear_error_on_return; // Silence compiler warning.
// Auto DH is not supported in openssl 1.0.1, so dhparam needs
// to be specified explicitly
@@ -1073,7 +1068,6 @@ void SecureContext::LoadPKCS12(const FunctionCallbackInfo& args) {
SecureContext* sc;
ASSIGN_OR_RETURN_UNWRAP(&sc, args.Holder());
ClearErrorOnReturn clear_error_on_return;
- (void) &clear_error_on_return; // Silence compiler warning.
if (args.Length() < 1) {
return env->ThrowTypeError("PFX certificate argument is mandatory");
@@ -1697,7 +1691,6 @@ void SSLWrap ::GetPeerCertificate(
Environment* env = w->ssl_env();
ClearErrorOnReturn clear_error_on_return;
- (void) &clear_error_on_return; // Silence unused variable warning.
Local result;
Local info;
@@ -1894,7 +1887,6 @@ void SSLWrap ::Renegotiate(const FunctionCallbackInfo& args) {
ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder());
ClearErrorOnReturn clear_error_on_return;
- (void) &clear_error_on_return; // Silence unused variable warning.
bool yes = SSL_renegotiate(w->ssl_) == 1;
args.GetReturnValue().Set(yes);
@@ -2644,7 +2636,6 @@ int Connection::HandleSSLError(const char* func,
ZeroStatus zs,
SyscallStatus ss) {
ClearErrorOnReturn clear_error_on_return;
- (void) &clear_error_on_return; // Silence unused variable warning.
if (rv > 0)
return rv;
@@ -4259,7 +4250,6 @@ void Sign::SignFinal(const FunctionCallbackInfo& args) {
md_value = new unsigned char[md_len];
ClearErrorOnReturn clear_error_on_return;
- (void) &clear_error_on_return; // Silence compiler warning.
Error err = sign->SignFinal(
buf,
@@ -4382,7 +4372,6 @@ SignBase::Error Verify::VerifyFinal(const char* key_pem,
return kSignNotInitialised;
ClearErrorOnReturn clear_error_on_return;
- (void) &clear_error_on_return; // Silence compiler warning.
EVP_PKEY* pkey = nullptr;
BIO* bp = nullptr;
@@ -4614,7 +4603,6 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo& args) {
size_t out_len = 0;
ClearErrorOnReturn clear_error_on_return;
- (void) &clear_error_on_return; // Silence compiler warning.
bool r = Cipher(
kbuf,
@@ -4922,7 +4910,6 @@ void DiffieHellman::ComputeSecret(const FunctionCallbackInfo& args) {
}
ClearErrorOnReturn clear_error_on_return;
- (void) &clear_error_on_return; // Silence compiler warning.
BIGNUM* key = nullptr;
if (args.Length() == 0) {
@@ -6165,7 +6152,6 @@ void SetEngine(const FunctionCallbackInfo& args) {
unsigned int flags = args[1]->Uint32Value();
ClearErrorOnReturn clear_error_on_return;
- (void) &clear_error_on_return; // Silence compiler warning.
const node::Utf8Value engine_id(env->isolate(), args[0]);
ENGINE* engine = ENGINE_by_id(*engine_id);
diff --git a/src/node_internals.h b/src/node_internals.h
index a08ab45affe96e..297e6fc307796a 100644
--- a/src/node_internals.h
+++ b/src/node_internals.h
@@ -30,6 +30,7 @@
#include "uv.h"
#include "v8.h"
#include "tracing/trace_event.h"
+#include "node_debug_options.h"
#include
#include
@@ -83,6 +84,11 @@ extern bool config_pending_deprecation;
// Tells whether it is safe to call v8::Isolate::GetCurrent().
extern bool v8_initialized;
+// Contains initial debug options.
+// Set in node.cc.
+// Used in node_config.cc.
+extern node::DebugOptions debug_options;
+
// Forward declaration
class Environment;
diff --git a/src/node_version.h b/src/node_version.h
index 5af1a9bcb3274a..dd8caa6074e537 100644
--- a/src/node_version.h
+++ b/src/node_version.h
@@ -26,7 +26,7 @@
#define NODE_MINOR_VERSION 1
#define NODE_PATCH_VERSION 3
-#define NODE_VERSION_IS_RELEASE 0
+#define NODE_VERSION_IS_RELEASE 1
#ifndef NODE_STRINGIFY
#define NODE_STRINGIFY(n) NODE_STRINGIFY_HELPER(n)
diff --git a/test/addons-napi/test_handle_scope/test.js b/test/addons-napi/test_handle_scope/test.js
index 20bee78882f071..cb687d0bcbf413 100644
--- a/test/addons-napi/test_handle_scope/test.js
+++ b/test/addons-napi/test_handle_scope/test.js
@@ -10,6 +10,12 @@ testHandleScope.NewScope();
assert.ok(testHandleScope.NewScopeEscape() instanceof Object);
+assert.throws(
+ () => {
+ testHandleScope.NewScopeEscapeTwice();
+ },
+ Error);
+
assert.throws(
() => {
testHandleScope.NewScopeWithException(() => { throw new RangeError(); });
diff --git a/test/addons-napi/test_handle_scope/test_handle_scope.c b/test/addons-napi/test_handle_scope/test_handle_scope.c
index 6bcee16fda713e..6637da82316185 100644
--- a/test/addons-napi/test_handle_scope/test_handle_scope.c
+++ b/test/addons-napi/test_handle_scope/test_handle_scope.c
@@ -29,6 +29,19 @@ napi_value NewScopeEscape(napi_env env, napi_callback_info info) {
return escapee;
}
+napi_value NewScopeEscapeTwice(napi_env env, napi_callback_info info) {
+ napi_escapable_handle_scope scope;
+ napi_value output = NULL;
+ napi_value escapee = NULL;
+
+ NAPI_CALL(env, napi_open_escapable_handle_scope(env, &scope));
+ NAPI_CALL(env, napi_create_object(env, &output));
+ NAPI_CALL(env, napi_escape_handle(env, scope, output, &escapee));
+ NAPI_CALL(env, napi_escape_handle(env, scope, output, &escapee));
+ NAPI_CALL(env, napi_close_escapable_handle_scope(env, scope));
+ return escapee;
+}
+
napi_value NewScopeWithException(napi_env env, napi_callback_info info) {
napi_handle_scope scope;
size_t argc;
@@ -57,6 +70,7 @@ void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
napi_property_descriptor properties[] = {
DECLARE_NAPI_PROPERTY("NewScope", NewScope),
DECLARE_NAPI_PROPERTY("NewScopeEscape", NewScopeEscape),
+ DECLARE_NAPI_PROPERTY("NewScopeEscapeTwice", NewScopeEscapeTwice),
DECLARE_NAPI_PROPERTY("NewScopeWithException", NewScopeWithException),
};
diff --git a/test/async-hooks/test-fseventwrap.js b/test/async-hooks/test-fseventwrap.js
index 2eb1abad6573a8..acb579c6ae227f 100644
--- a/test/async-hooks/test-fseventwrap.js
+++ b/test/async-hooks/test-fseventwrap.js
@@ -1,6 +1,6 @@
'use strict';
-
require('../common');
+
const assert = require('assert');
const initHooks = require('./init-hooks');
const tick = require('./tick');
@@ -10,7 +10,7 @@ const fs = require('fs');
const hooks = initHooks();
hooks.enable();
-const watcher = fs.watch(__dirname, onwatcherChanged);
+const watcher = fs.watch(__filename, onwatcherChanged);
function onwatcherChanged() { }
watcher.close();
diff --git a/test/common/README.md b/test/common/README.md
index 3e1e1bbe9c96af..f418115ce31805 100644
--- a/test/common/README.md
+++ b/test/common/README.md
@@ -106,6 +106,16 @@ Checks for 'openssl'.
Checks `hasCrypto` and `crypto` with fips.
+### hasIntl
+* return [<Boolean>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Boolean_type)
+
+Checks if [internationalization] is supported.
+
+### hasSmallICU
+* return [<Boolean>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Boolean_type)
+
+Checks `hasIntl` and `small-icu` is supported.
+
### hasIPv6
* return [<Boolean>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Boolean_type)
@@ -322,3 +332,4 @@ implementation with tests from
[W3C Web Platform Tests](https://github.com/w3c/web-platform-tests).
[MDN-Function]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Normal_objects_and_functions
+[internationalization]: https://github.com/nodejs/node/wiki/Intl
diff --git a/test/common/index.js b/test/common/index.js
index 75a1edd447a534..7f00820123711f 100644
--- a/test/common/index.js
+++ b/test/common/index.js
@@ -267,8 +267,9 @@ if (exports.isWindows) {
}
const ifaces = os.networkInterfaces();
+const re = /lo/;
exports.hasIPv6 = Object.keys(ifaces).some(function(name) {
- return /lo/.test(name) && ifaces[name].some(function(info) {
+ return re.test(name) && ifaces[name].some(function(info) {
return info.family === 'IPv6';
});
});
@@ -433,7 +434,7 @@ function leakedGlobals() {
leaked.push(val);
if (global.__coverage__) {
- return leaked.filter((varname) => !/^(cov_|__cov)/.test(varname));
+ return leaked.filter((varname) => !/^(?:cov_|__cov)/.test(varname));
} else {
return leaked;
}
@@ -689,6 +690,12 @@ Object.defineProperty(exports, 'hasIntl', {
}
});
+Object.defineProperty(exports, 'hasSmallICU', {
+ get: function() {
+ return process.binding('config').hasSmallICU;
+ }
+});
+
// Useful for testing expected internal/error objects
exports.expectsError = function expectsError({code, type, message}) {
return function(error) {
diff --git a/test/debugger/helper-debugger-repl.js b/test/debugger/helper-debugger-repl.js
index 234a40102399f3..f11d4d94981e0e 100644
--- a/test/debugger/helper-debugger-repl.js
+++ b/test/debugger/helper-debugger-repl.js
@@ -51,12 +51,12 @@ function startDebugger(scriptToDebug) {
child.stderr.pipe(process.stderr);
child.on('line', function(line) {
- line = line.replace(/^(debug> *)+/, '');
+ line = line.replace(/^(?:debug> *)+/, '');
console.log(line);
assert.ok(expected.length > 0, `Got unexpected line: ${line}`);
const expectedLine = expected[0].lines.shift();
- assert.ok(line.match(expectedLine) !== null, `${line} != ${expectedLine}`);
+ assert.ok(expectedLine.test(line), `${line} != ${expectedLine}`);
if (expected[0].lines.length === 0) {
const callback = expected[0].callback;
diff --git a/test/doctool/test-doctool-html.js b/test/doctool/test-doctool-html.js
index ba3e793e8a5aac..8f78663cbefb75 100644
--- a/test/doctool/test-doctool-html.js
+++ b/test/doctool/test-doctool-html.js
@@ -91,9 +91,11 @@ const testData = [
},
];
+const spaces = /\s/g;
+
testData.forEach((item) => {
// Normalize expected data by stripping whitespace
- const expected = item.html.replace(/\s/g, '');
+ const expected = item.html.replace(spaces, '');
const includeAnalytics = typeof item.analyticsId !== 'undefined';
fs.readFile(item.file, 'utf8', common.mustCall((err, input) => {
@@ -112,7 +114,7 @@ testData.forEach((item) => {
common.mustCall((err, output) => {
assert.ifError(err);
- const actual = output.replace(/\s/g, '');
+ const actual = output.replace(spaces, '');
// Assert that the input stripped of all whitespace contains the
// expected list
assert.notStrictEqual(actual.indexOf(expected), -1);
diff --git a/test/fixtures/stdio-filter.js b/test/fixtures/stdio-filter.js
deleted file mode 100644
index 583e3a3bd1b0db..00000000000000
--- a/test/fixtures/stdio-filter.js
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright Joyent, Inc. and other Node contributors.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to permit
-// persons to whom the Software is furnished to do so, subject to the
-// following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
-// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-// USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-const util = require('util');
-
-var regexIn = process.argv[2];
-var replacement = process.argv[3];
-var re = new RegExp(regexIn, 'g');
-var stdin = process.openStdin();
-
-stdin.on('data', function(data) {
- data = data.toString();
- process.stdout.write(data.replace(re, replacement));
-});
diff --git a/test/inspector/inspector-helper.js b/test/inspector/inspector-helper.js
index faf932f495367a..bc6097436425af 100644
--- a/test/inspector/inspector-helper.js
+++ b/test/inspector/inspector-helper.js
@@ -521,11 +521,11 @@ exports.startNodeForInspectorTest = function(callback,
clearTimeout(timeoutId);
console.log('[err]', text);
if (found) return;
- const match = text.match(/Debugger listening on ws:\/\/(.+):(\d+)\/(.+)/);
+ const match = text.match(/Debugger listening on ws:\/\/.+:(\d+)\/.+/);
found = true;
child.stderr.removeListener('data', dataCallback);
assert.ok(match, text);
- callback(new Harness(match[2], child));
+ callback(new Harness(match[1], child));
});
child.stderr.on('data', dataCallback);
diff --git a/test/inspector/inspector.status b/test/inspector/inspector.status
index 070d817b2c3ab2..ed6a782b9031a7 100644
--- a/test/inspector/inspector.status
+++ b/test/inspector/inspector.status
@@ -5,6 +5,5 @@ prefix inspector
# sample-test : PASS,FLAKY
[true] # This section applies to all platforms
-test-inspector-port-zero-cluster : PASS,FLAKY
[$system==win32]
diff --git a/test/inspector/test-inspector-port-cluster.js b/test/inspector/test-inspector-port-cluster.js
new file mode 100644
index 00000000000000..b2a53f87ea172e
--- /dev/null
+++ b/test/inspector/test-inspector-port-cluster.js
@@ -0,0 +1,129 @@
+'use strict';
+
+const common = require('../common');
+
+common.skipIfInspectorDisabled();
+
+const assert = require('assert');
+const cluster = require('cluster');
+
+const debuggerPort = common.PORT;
+const childProcess = require('child_process');
+
+let offset = 0;
+
+/*
+ * This test suite checks that inspector port in cluster is incremented
+ * for different execArgv combinations
+ */
+
+function testRunnerMain() {
+ spawnMaster({
+ execArgv: ['--inspect'],
+ workers: [{expectedPort: 9230}]
+ });
+
+ let port = debuggerPort + offset++ * 10;
+
+ spawnMaster({
+ execArgv: [`--inspect=${port}`],
+ workers: [
+ {expectedPort: port + 1},
+ {expectedPort: port + 2},
+ {expectedPort: port + 3}
+ ]
+ });
+
+ port = debuggerPort + offset++ * 10;
+
+ spawnMaster({
+ execArgv: ['--inspect', `--inspect-port=${port}`],
+ workers: [{expectedPort: port + 1}]
+ });
+
+ port = debuggerPort + offset++ * 10;
+
+ spawnMaster({
+ execArgv: ['--inspect', `--debug-port=${port}`],
+ workers: [{expectedPort: port + 1}]
+ });
+
+ port = debuggerPort + offset++ * 10;
+
+ spawnMaster({
+ execArgv: [`--inspect=0.0.0.0:${port}`],
+ workers: [{expectedPort: port + 1, expectedHost: '0.0.0.0'}]
+ });
+
+ port = debuggerPort + offset++ * 10;
+
+ spawnMaster({
+ execArgv: [`--inspect=127.0.0.1:${port}`],
+ workers: [{expectedPort: port + 1, expectedHost: '127.0.0.1'}]
+ });
+
+ if (common.hasIPv6) {
+ port = debuggerPort + offset++ * 10;
+
+ spawnMaster({
+ execArgv: [`--inspect=[::]:${port}`],
+ workers: [{expectedPort: port + 1, expectedHost: '::'}]
+ });
+
+ port = debuggerPort + offset++ * 10;
+
+ spawnMaster({
+ execArgv: [`--inspect=[::1]:${port}`],
+ workers: [{expectedPort: port + 1, expectedHost: '::1'}]
+ });
+ }
+}
+
+function masterProcessMain() {
+ const workers = JSON.parse(process.env.workers);
+
+ for (const worker of workers) {
+ cluster.fork({
+ expectedPort: worker.expectedPort,
+ expectedHost: worker.expectedHost
+ }).on('exit', common.mustCall(checkExitCode));
+ }
+}
+
+function workerProcessMain() {
+ const {expectedPort, expectedHost} = process.env;
+
+ assert.strictEqual(process.debugPort, +expectedPort);
+
+ if (expectedHost !== 'undefined') {
+ assert.strictEqual(
+ process.binding('config').debugOptions.host,
+ expectedHost
+ );
+ }
+
+ process.exit();
+}
+
+function spawnMaster({execArgv, workers}) {
+ childProcess.fork(__filename, {
+ env: {
+ workers: JSON.stringify(workers),
+ testProcess: true
+ },
+ execArgv
+ }).on('exit', common.mustCall(checkExitCode));
+}
+
+function checkExitCode(code, signal) {
+ assert.strictEqual(code, 0);
+ assert.strictEqual(signal, null);
+}
+
+if (!process.env.testProcess) {
+ testRunnerMain();
+} else if (cluster.isMaster) {
+ masterProcessMain();
+} else {
+ workerProcessMain();
+}
diff --git a/test/inspector/test-inspector-port-zero-cluster.js b/test/inspector/test-inspector-port-zero-cluster.js
index 4582b4bb38657b..f64e05f314c0c6 100644
--- a/test/inspector/test-inspector-port-zero-cluster.js
+++ b/test/inspector/test-inspector-port-zero-cluster.js
@@ -4,31 +4,48 @@ const common = require('../common');
common.skipIfInspectorDisabled();
+// Assert that even when started with `--inspect=0` workers are assigned
+// consecutive (i.e. deterministically predictable) debug ports
+
const assert = require('assert');
const cluster = require('cluster');
-if (cluster.isMaster) {
- const ports = [];
- for (const worker of [cluster.fork(),
- cluster.fork(),
- cluster.fork()]) {
- worker.on('message', common.mustCall((message) => {
- ports.push(message.debugPort);
- worker.kill();
+function serialFork() {
+ return new Promise((res) => {
+ const worker = cluster.fork();
+ worker.on('exit', common.mustCall((code, signal) => {
+ // code 0 is normal
+ // code 12 can happen if inspector could not bind because of a port clash
+ if (code !== 0 && code !== 12)
+ assert.fail(`code: ${code}, signal: ${signal}`);
+ const port = worker.process.spawnargs
+ .map((a) => (/=(?:.*:)?(\d{2,5})$/.exec(a) || [])[1])
+ .filter((p) => p)
+ .pop();
+ res(Number(port));
}));
- worker.send('debugPort');
- }
- process.on('exit', () => {
- ports.sort();
- assert.strictEqual(ports.length, 3);
- assert(ports.every((port) => port > 0));
- assert(ports.every((port) => port < 65536));
- assert.strictEqual(ports[0] + 1, ports[1]); // Ports should be consecutive.
- assert.strictEqual(ports[1] + 1, ports[2]);
});
+}
+
+if (cluster.isMaster) {
+ Promise.all([serialFork(), serialFork(), serialFork()])
+ .then(common.mustCall((ports) => {
+ ports.push(process.debugPort);
+ ports.sort();
+ // 4 = [master, worker1, worker2, worker3].length()
+ assert.strictEqual(ports.length, 4);
+ assert(ports.every((port) => port > 0));
+ assert(ports.every((port) => port < 65536));
+ // Ports should be consecutive.
+ assert.strictEqual(ports[0] + 1, ports[1]);
+ assert.strictEqual(ports[1] + 1, ports[2]);
+ assert.strictEqual(ports[2] + 1, ports[3]);
+ }))
+ .catch(
+ (err) => {
+ console.error(err);
+ process.exit(1);
+ });
} else {
- process.on('message', (message) => {
- if (message === 'debugPort')
- process.send({ debugPort: process.debugPort });
- });
+ process.exit(0);
}
diff --git a/test/inspector/test-inspector.js b/test/inspector/test-inspector.js
index 19eb3601f0fbc7..313fba9bd91bc1 100644
--- a/test/inspector/test-inspector.js
+++ b/test/inspector/test-inspector.js
@@ -13,8 +13,8 @@ function checkListResponse(err, response) {
assert.strictEqual(1, response.length);
assert.ok(response[0]['devtoolsFrontendUrl']);
assert.ok(
- response[0]['webSocketDebuggerUrl']
- .match(/ws:\/\/127\.0\.0\.1:\d+\/[0-9A-Fa-f]{8}-/));
+ /ws:\/\/127\.0\.0\.1:\d+\/[0-9A-Fa-f]{8}-/
+ .test(response[0]['webSocketDebuggerUrl']));
}
function checkVersion(err, response) {
diff --git a/test/known_issues/test-inspector-cluster-port-clash.js b/test/known_issues/test-inspector-cluster-port-clash.js
new file mode 100644
index 00000000000000..41b00aacc148be
--- /dev/null
+++ b/test/known_issues/test-inspector-cluster-port-clash.js
@@ -0,0 +1,63 @@
+// Flags: --inspect=0
+'use strict';
+const common = require('../common');
+
+// With the current behavior of Node.js (at least as late as 8.1.0), this
+// test fails with the following error:
+// `AssertionError [ERR_ASSERTION]: worker 2 failed to bind port`
+// Ideally, there would be a way for the user to opt out of sequential port
+// assignment.
+//
+// Refs: https://github.com/nodejs/node/issues/13343
+
+common.skipIfInspectorDisabled();
+
+const assert = require('assert');
+const cluster = require('cluster');
+const net = require('net');
+
+const ports = [process.debugPort];
+const clashPort = process.debugPort + 2;
+function serialFork() {
+ return new Promise((res) => {
+ const worker = cluster.fork();
+ worker.on('error', (err) => assert.fail(err));
+ // no common.mustCall since 1 out of 3 should fail
+ worker.on('online', () => {
+ worker.on('message', common.mustCall((message) => {
+ ports.push(message.debugPort);
+ }));
+ });
+ worker.on('exit', common.mustCall((code, signal) => {
+ assert.strictEqual(signal, null);
+ // worker 2 should fail because of port clash with `server`
+ if (code === 12) {
+ return assert.fail(`worker ${worker.id} failed to bind port`);
+ }
+ assert.strictEqual(0, code);
+ }));
+ worker.on('disconnect', common.mustCall(res));
+ });
+}
+
+if (cluster.isMaster) {
+ cluster.on('online', common.mustCall((worker) => worker.send('dbgport'), 2));
+
+ // block one of the ports with a listening socket
+ const server = net.createServer();
+ server.listen(clashPort, common.localhostIPv4, common.mustCall(() => {
+ // try to fork 3 workers No.2 should fail
+ Promise.all([serialFork(), serialFork(), serialFork()])
+ .then(common.mustNotCall())
+ .catch((err) => console.error(err));
+ }));
+ server.unref();
+} else {
+ const sentinel = common.mustCall();
+ process.on('message', (message) => {
+ if (message !== 'dbgport') return;
+ process.send({ debugPort: process.debugPort });
+ sentinel();
+ process.disconnect();
+ });
+}
diff --git a/test/message/throw_in_line_with_tabs.js b/test/message/throw_in_line_with_tabs.js
index fdc36b331ab8a1..87181f02d7e995 100644
--- a/test/message/throw_in_line_with_tabs.js
+++ b/test/message/throw_in_line_with_tabs.js
@@ -19,7 +19,7 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
-/* eslint-disable indent, no-tabs */
+/* eslint-disable indent-legacy, no-tabs */
'use strict';
require('../common');
diff --git a/test/parallel/test-assert-checktag.js b/test/parallel/test-assert-checktag.js
index 027af935600565..c4823243e7d3e9 100644
--- a/test/parallel/test-assert-checktag.js
+++ b/test/parallel/test-assert-checktag.js
@@ -7,10 +7,11 @@ const util = require('util');
// for assert.throws()
function re(literals, ...values) {
let result = literals[0];
+ const escapeRE = /[\\^$.*+?()[\]{}|=!<>:-]/g;
for (const [i, value] of values.entries()) {
const str = util.inspect(value);
// Need to escape special characters.
- result += str.replace(/[\\^$.*+?()[\]{}|=!<>:-]/g, '\\$&');
+ result += str.replace(escapeRE, '\\$&');
result += literals[i + 1];
}
return common.expectsError({
diff --git a/test/parallel/test-assert-deep.js b/test/parallel/test-assert-deep.js
index fecb5c89dbe3e7..9f1c8dadf94325 100644
--- a/test/parallel/test-assert-deep.js
+++ b/test/parallel/test-assert-deep.js
@@ -7,10 +7,11 @@ const util = require('util');
// for assert.throws()
function re(literals, ...values) {
let result = literals[0];
+ const escapeRE = /[\\^$.*+?()[\]{}|=!<>:-]/g;
for (const [i, value] of values.entries()) {
const str = util.inspect(value);
// Need to escape special characters.
- result += str.replace(/[\\^$.*+?()[\]{}|=!<>:-]/g, '\\$&');
+ result += str.replace(escapeRE, '\\$&');
result += literals[i + 1];
}
return common.expectsError({
diff --git a/test/parallel/test-assert.js b/test/parallel/test-assert.js
index 7b492374f0518b..561ce6d79b4af3 100644
--- a/test/parallel/test-assert.js
+++ b/test/parallel/test-assert.js
@@ -722,13 +722,14 @@ assert.throws(() => {
{
// bad args to AssertionError constructor should throw TypeError
const args = [1, true, false, '', null, Infinity, Symbol('test'), undefined];
+ const re = /^The "options" argument must be of type object$/;
args.forEach((input) => {
assert.throws(
() => new assert.AssertionError(input),
common.expectsError({
code: 'ERR_INVALID_ARG_TYPE',
type: TypeError,
- message: /^The "options" argument must be of type object$/
+ message: re
}));
});
}
diff --git a/test/parallel/test-buffer-alloc.js b/test/parallel/test-buffer-alloc.js
index ca68a27a90fe7a..7016d07f7adef5 100644
--- a/test/parallel/test-buffer-alloc.js
+++ b/test/parallel/test-buffer-alloc.js
@@ -468,6 +468,10 @@ assert.strictEqual(Buffer.from('=bad'.repeat(1e4), 'base64').length, 0);
assert.deepStrictEqual(Buffer.from('w0 ', 'base64'),
Buffer.from('w0', 'base64'));
+// Regression test for https://github.com/nodejs/node/issues/13657.
+assert.deepStrictEqual(Buffer.from(' YWJvcnVtLg', 'base64'),
+ Buffer.from('YWJvcnVtLg', 'base64'));
+
{
// Creating buffers larger than pool size.
const l = Buffer.poolSize + 5;
diff --git a/test/parallel/test-buffer-bytelength.js b/test/parallel/test-buffer-bytelength.js
index 09e59743e40208..8077cc7d5e2663 100644
--- a/test/parallel/test-buffer-bytelength.js
+++ b/test/parallel/test-buffer-bytelength.js
@@ -7,14 +7,11 @@ const SlowBuffer = require('buffer').SlowBuffer;
const vm = require('vm');
// coerce values to string
-assert.throws(() => { Buffer.byteLength(32, 'latin1'); },
- /"string" must be a string, Buffer, or ArrayBuffer/);
-assert.throws(() => { Buffer.byteLength(NaN, 'utf8'); },
- /"string" must be a string, Buffer, or ArrayBuffer/);
-assert.throws(() => { Buffer.byteLength({}, 'latin1'); },
- /"string" must be a string, Buffer, or ArrayBuffer/);
-assert.throws(() => { Buffer.byteLength(); },
- /"string" must be a string, Buffer, or ArrayBuffer/);
+const re = /"string" must be a string, Buffer, or ArrayBuffer/;
+assert.throws(() => { Buffer.byteLength(32, 'latin1'); }, re);
+assert.throws(() => { Buffer.byteLength(NaN, 'utf8'); }, re);
+assert.throws(() => { Buffer.byteLength({}, 'latin1'); }, re);
+assert.throws(() => { Buffer.byteLength(); }, re);
assert.strictEqual(Buffer.byteLength('', undefined, true), -1);
diff --git a/test/parallel/test-buffer-prototype-inspect.js b/test/parallel/test-buffer-prototype-inspect.js
index 5f65a9bb288f16..9e6c66dc3da002 100644
--- a/test/parallel/test-buffer-prototype-inspect.js
+++ b/test/parallel/test-buffer-prototype-inspect.js
@@ -19,5 +19,5 @@ const util = require('util');
{
const buf = Buffer.from('x'.repeat(51));
- assert.ok(/^$/.test(util.inspect(buf)));
+ assert.ok(/^$/.test(util.inspect(buf)));
}
diff --git a/test/parallel/test-child-process-constructor.js b/test/parallel/test-child-process-constructor.js
index c495f1895d0002..8e62f5cc238c22 100644
--- a/test/parallel/test-child-process-constructor.js
+++ b/test/parallel/test-child-process-constructor.js
@@ -8,44 +8,48 @@ assert.strictEqual(typeof ChildProcess, 'function');
{
// Verify that invalid options to spawn() throw.
const child = new ChildProcess();
+ const re = /^TypeError: "options" must be an object$/;
[undefined, null, 'foo', 0, 1, NaN, true, false].forEach((options) => {
assert.throws(() => {
child.spawn(options);
- }, /^TypeError: "options" must be an object$/);
+ }, re);
});
}
{
// Verify that spawn throws if file is not a string.
const child = new ChildProcess();
+ const re = /^TypeError: "file" must be a string$/;
[undefined, null, 0, 1, NaN, true, false, {}].forEach((file) => {
assert.throws(() => {
child.spawn({ file });
- }, /^TypeError: "file" must be a string$/);
+ }, re);
});
}
{
// Verify that spawn throws if envPairs is not an array or undefined.
const child = new ChildProcess();
+ const re = /^TypeError: "envPairs" must be an array$/;
[null, 0, 1, NaN, true, false, {}, 'foo'].forEach((envPairs) => {
assert.throws(() => {
child.spawn({ envPairs, stdio: ['ignore', 'ignore', 'ignore', 'ipc'] });
- }, /^TypeError: "envPairs" must be an array$/);
+ }, re);
});
}
{
// Verify that spawn throws if args is not an array or undefined.
const child = new ChildProcess();
+ const re = /^TypeError: "args" must be an array$/;
[null, 0, 1, NaN, true, false, {}, 'foo'].forEach((args) => {
assert.throws(() => {
child.spawn({ file: 'foo', args });
- }, /^TypeError: "args" must be an array$/);
+ }, re);
});
}
diff --git a/test/parallel/test-child-process-stdio-big-write-end.js b/test/parallel/test-child-process-stdio-big-write-end.js
index 6cc3d86644ac39..2ba409b09898e4 100644
--- a/test/parallel/test-child-process-stdio-big-write-end.js
+++ b/test/parallel/test-child-process-stdio-big-write-end.js
@@ -20,9 +20,9 @@
// USE OR OTHER DEALINGS IN THE SOFTWARE.
'use strict';
-require('../common');
+const common = require('../common');
const assert = require('assert');
-const BUFSIZE = 1024;
+let bufsize = 0;
switch (process.argv[2]) {
case undefined:
@@ -43,22 +43,23 @@ function parent() {
child.stdout.on('data', function(c) {
n += c;
});
- child.stdout.on('end', function() {
+ child.stdout.on('end', common.mustCall(function() {
assert.strictEqual(+n, sent);
console.log('ok');
- });
+ }));
// Write until the buffer fills up.
let buf;
do {
- buf = Buffer.alloc(BUFSIZE, '.');
- sent += BUFSIZE;
+ bufsize += 1024;
+ buf = Buffer.alloc(bufsize, '.');
+ sent += bufsize;
} while (child.stdin.write(buf));
// then write a bunch more times.
for (let i = 0; i < 100; i++) {
- const buf = Buffer.alloc(BUFSIZE, '.');
- sent += BUFSIZE;
+ const buf = Buffer.alloc(bufsize, '.');
+ sent += bufsize;
child.stdin.write(buf);
}
diff --git a/test/parallel/test-cli-syntax.js b/test/parallel/test-cli-syntax.js
index eda45701a5fdf7..867f05256d6940 100644
--- a/test/parallel/test-cli-syntax.js
+++ b/test/parallel/test-cli-syntax.js
@@ -13,6 +13,9 @@ const syntaxArgs = [
['--check']
];
+const syntaxErrorRE = /^SyntaxError: Unexpected identifier$/m;
+const notFoundRE = /^Error: Cannot find module/m;
+
// test good syntax with and without shebang
[
'syntax/good_syntax.js',
@@ -56,8 +59,7 @@ const syntaxArgs = [
assert(c.stderr.startsWith(file), "stderr doesn't start with the filename");
// stderr should have a syntax error message
- const match = c.stderr.match(/^SyntaxError: Unexpected identifier$/m);
- assert(match, 'stderr incorrect');
+ assert(syntaxErrorRE.test(c.stderr), 'stderr incorrect');
assert.strictEqual(c.status, 1, `code === ${c.status}`);
});
@@ -79,8 +81,7 @@ const syntaxArgs = [
assert.strictEqual(c.stdout, '', 'stdout produced');
// stderr should have a module not found error message
- const match = c.stderr.match(/^Error: Cannot find module/m);
- assert(match, 'stderr incorrect');
+ assert(notFoundRE.test(c.stderr), 'stderr incorrect');
assert.strictEqual(c.status, 1, `code === ${c.status}`);
});
@@ -112,8 +113,7 @@ syntaxArgs.forEach(function(args) {
assert.strictEqual(c.stdout, '', 'stdout produced');
// stderr should have a syntax error message
- const match = c.stderr.match(/^SyntaxError: Unexpected identifier$/m);
- assert(match, 'stderr incorrect');
+ assert(syntaxErrorRE.test(c.stderr), 'stderr incorrect');
assert.strictEqual(c.status, 1, `code === ${c.status}`);
});
diff --git a/test/parallel/test-cluster-inspector-debug-port.js b/test/parallel/test-cluster-inspector-debug-port.js
deleted file mode 100644
index a049da78be0f70..00000000000000
--- a/test/parallel/test-cluster-inspector-debug-port.js
+++ /dev/null
@@ -1,41 +0,0 @@
-'use strict';
-// Flags: --inspect={PORT}
-const common = require('../common');
-
-common.skipIfInspectorDisabled();
-
-const assert = require('assert');
-const cluster = require('cluster');
-const debuggerPort = common.PORT;
-
-if (cluster.isMaster) {
- function checkExitCode(code, signal) {
- assert.strictEqual(code, 0);
- assert.strictEqual(signal, null);
- }
-
- function fork(offset, execArgv) {
- if (execArgv)
- cluster.setupMaster({execArgv});
-
- const check = common.mustCall(checkExitCode);
- cluster.fork({portSet: debuggerPort + offset}).on('exit', check);
- }
-
- assert.strictEqual(process.debugPort, debuggerPort);
-
- fork(1);
- fork(2, ['--inspect']);
- fork(3, [`--inspect=${debuggerPort}`]);
- fork(4, ['--inspect', `--debug-port=${debuggerPort}`]);
- fork(5, [`--inspect-port=${debuggerPort}`]);
- fork(6, ['--inspect', `--inspect-port=${debuggerPort}`]);
-} else {
- const hasDebugArg = process.execArgv.some(function(arg) {
- return /inspect/.test(arg);
- });
-
- assert.strictEqual(hasDebugArg, true);
- assert.strictEqual(process.debugPort, +process.env.portSet);
- process.exit();
-}
diff --git a/test/parallel/test-cluster-worker-isconnected.js b/test/parallel/test-cluster-worker-isconnected.js
index 8b2ad865899c60..a0ada77bd023b1 100644
--- a/test/parallel/test-cluster-worker-isconnected.js
+++ b/test/parallel/test-cluster-worker-isconnected.js
@@ -1,38 +1,30 @@
'use strict';
-require('../common');
+const common = require('../common');
const cluster = require('cluster');
const assert = require('assert');
if (cluster.isMaster) {
const worker = cluster.fork();
- assert.ok(worker.isConnected(),
- 'isConnected() should return true as soon as the worker has ' +
- 'been created.');
+ assert.strictEqual(worker.isConnected(), true);
- worker.on('disconnect', function() {
- assert.ok(!worker.isConnected(),
- 'After a disconnect event has been emitted, ' +
- 'isConncted should return false');
- });
+ worker.on('disconnect', common.mustCall(() => {
+ assert.strictEqual(worker.isConnected(), false);
+ }));
worker.on('message', function(msg) {
if (msg === 'readyToDisconnect') {
worker.disconnect();
}
});
-
} else {
- assert.ok(cluster.worker.isConnected(),
- 'isConnected() should return true from within a worker at all ' +
- 'times.');
+ function assertNotConnected() {
+ assert.strictEqual(cluster.worker.isConnected(), false);
+ }
- cluster.worker.process.on('disconnect', function() {
- assert.ok(!cluster.worker.isConnected(),
- 'isConnected() should return false from within a worker ' +
- 'after its underlying process has been disconnected from ' +
- 'the master');
- });
+ assert.strictEqual(cluster.worker.isConnected(), true);
+ cluster.worker.on('disconnect', common.mustCall(assertNotConnected));
+ cluster.worker.process.on('disconnect', common.mustCall(assertNotConnected));
process.send('readyToDisconnect');
}
diff --git a/test/parallel/test-crypto-authenticated.js b/test/parallel/test-crypto-authenticated.js
index c1d70efa5f6d1b..2d5370ba3eac2b 100644
--- a/test/parallel/test-crypto-authenticated.js
+++ b/test/parallel/test-crypto-authenticated.js
@@ -328,6 +328,13 @@ const TEST_CASES = [
tag: 'a44a8266ee1c8eb0c8b5d4cf5ae9f19a', tampered: false },
];
+const errMessages = {
+ auth: / auth/,
+ state: / state/,
+ FIPS: /not supported in FIPS mode/,
+ length: /Invalid IV length/,
+};
+
const ciphers = crypto.getCiphers();
for (const i in TEST_CASES) {
@@ -378,14 +385,14 @@ for (const i in TEST_CASES) {
assert.strictEqual(msg, test.plain);
} else {
// assert that final throws if input data could not be verified!
- assert.throws(function() { decrypt.final('ascii'); }, / auth/);
+ assert.throws(function() { decrypt.final('ascii'); }, errMessages.auth);
}
}
if (test.password) {
if (common.hasFipsCrypto) {
assert.throws(() => { crypto.createCipher(test.algo, test.password); },
- /not supported in FIPS mode/);
+ errMessages.FIPS);
} else {
const encrypt = crypto.createCipher(test.algo, test.password);
if (test.aad)
@@ -404,7 +411,7 @@ for (const i in TEST_CASES) {
if (test.password) {
if (common.hasFipsCrypto) {
assert.throws(() => { crypto.createDecipher(test.algo, test.password); },
- /not supported in FIPS mode/);
+ errMessages.FIPS);
} else {
const decrypt = crypto.createDecipher(test.algo, test.password);
decrypt.setAuthTag(Buffer.from(test.tag, 'hex'));
@@ -416,7 +423,7 @@ for (const i in TEST_CASES) {
assert.strictEqual(msg, test.plain);
} else {
// assert that final throws if input data could not be verified!
- assert.throws(function() { decrypt.final('ascii'); }, / auth/);
+ assert.throws(function() { decrypt.final('ascii'); }, errMessages.auth);
}
}
}
@@ -427,7 +434,7 @@ for (const i in TEST_CASES) {
Buffer.from(test.key, 'hex'),
Buffer.from(test.iv, 'hex'));
encrypt.update('blah', 'ascii');
- assert.throws(function() { encrypt.getAuthTag(); }, / state/);
+ assert.throws(function() { encrypt.getAuthTag(); }, errMessages.state);
}
{
@@ -436,7 +443,7 @@ for (const i in TEST_CASES) {
Buffer.from(test.key, 'hex'),
Buffer.from(test.iv, 'hex'));
assert.throws(() => { encrypt.setAuthTag(Buffer.from(test.tag, 'hex')); },
- / state/);
+ errMessages.state);
}
{
@@ -444,7 +451,7 @@ for (const i in TEST_CASES) {
const decrypt = crypto.createDecipheriv(test.algo,
Buffer.from(test.key, 'hex'),
Buffer.from(test.iv, 'hex'));
- assert.throws(function() { decrypt.getAuthTag(); }, / state/);
+ assert.throws(function() { decrypt.getAuthTag(); }, errMessages.state);
}
{
@@ -455,7 +462,7 @@ for (const i in TEST_CASES) {
Buffer.from(test.key, 'hex'),
Buffer.alloc(0)
);
- }, /Invalid IV length/);
+ }, errMessages.length);
}
}
@@ -467,6 +474,7 @@ for (const i in TEST_CASES) {
'6fKjEjR3Vl30EUYC');
encrypt.update('blah', 'ascii');
encrypt.final();
- assert.throws(() => encrypt.getAuthTag(), / state/);
- assert.throws(() => encrypt.setAAD(Buffer.from('123', 'ascii')), / state/);
+ assert.throws(() => encrypt.getAuthTag(), errMessages.state);
+ assert.throws(() => encrypt.setAAD(Buffer.from('123', 'ascii')),
+ errMessages.state);
}
diff --git a/test/parallel/test-crypto-cipheriv-decipheriv.js b/test/parallel/test-crypto-cipheriv-decipheriv.js
index a03a25d511fe16..31a79d8bf175b8 100644
--- a/test/parallel/test-crypto-cipheriv-decipheriv.js
+++ b/test/parallel/test-crypto-cipheriv-decipheriv.js
@@ -66,12 +66,14 @@ testCipher2(Buffer.from('0123456789abcd0123456789'), Buffer.from('12345678'));
// Zero-sized IV should be accepted in ECB mode.
crypto.createCipheriv('aes-128-ecb', Buffer.alloc(16), Buffer.alloc(0));
+const errMessage = /Invalid IV length/;
+
// But non-empty IVs should be rejected.
for (let n = 1; n < 256; n += 1) {
assert.throws(
() => crypto.createCipheriv('aes-128-ecb', Buffer.alloc(16),
Buffer.alloc(n)),
- /Invalid IV length/);
+ errMessage);
}
// Correctly sized IV should be accepted in CBC mode.
@@ -83,14 +85,14 @@ for (let n = 0; n < 256; n += 1) {
assert.throws(
() => crypto.createCipheriv('aes-128-cbc', Buffer.alloc(16),
Buffer.alloc(n)),
- /Invalid IV length/);
+ errMessage);
}
// Zero-sized IV should be rejected in GCM mode.
assert.throws(
() => crypto.createCipheriv('aes-128-gcm', Buffer.alloc(16),
Buffer.alloc(0)),
- /Invalid IV length/);
+ errMessage);
// But all other IV lengths should be accepted.
for (let n = 1; n < 256; n += 1) {
diff --git a/test/parallel/test-crypto-dh.js b/test/parallel/test-crypto-dh.js
index 285f35b830a2f6..91a066d1bd22b1 100644
--- a/test/parallel/test-crypto-dh.js
+++ b/test/parallel/test-crypto-dh.js
@@ -295,14 +295,15 @@ if (availableCurves.has('prime256v1') && availableCurves.has('secp256k1')) {
// rejected.
ecdh5.setPrivateKey(cafebabeKey, 'hex');
- [ // Some invalid private keys for the secp256k1 curve.
- '0000000000000000000000000000000000000000000000000000000000000000',
- 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141',
- 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF',
+ // Some invalid private keys for the secp256k1 curve.
+ const errMessage = /^Error: Private key is not valid for specified curve\.$/;
+ ['0000000000000000000000000000000000000000000000000000000000000000',
+ 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141',
+ 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF',
].forEach((element) => {
assert.throws(() => {
ecdh5.setPrivateKey(element, 'hex');
- }, /^Error: Private key is not valid for specified curve\.$/);
+ }, errMessage);
// Verify object state did not change.
assert.strictEqual(ecdh5.getPrivateKey('hex'), cafebabeKey);
});
diff --git a/test/parallel/test-crypto-random.js b/test/parallel/test-crypto-random.js
index fd9e71bb084dd2..c60e3b2681e118 100644
--- a/test/parallel/test-crypto-random.js
+++ b/test/parallel/test-crypto-random.js
@@ -140,6 +140,14 @@ const expectedErrorRegexp = /^TypeError: size must be a number >= 0$/;
Buffer.alloc(10),
new Uint8Array(new Array(10).fill(0))
];
+ const errMessages = {
+ offsetNotNumber: /offset must be a number/,
+ offsetOutOfRange: /offset out of range/,
+ offsetNotUInt32: /offset must be a uint32/,
+ sizeNotNumber: /size must be a number/,
+ sizeNotUInt32: /size must be a uint32/,
+ bufferTooSmall: /buffer too small/,
+ };
for (const buf of bufs) {
const len = Buffer.byteLength(buf);
@@ -147,108 +155,108 @@ const expectedErrorRegexp = /^TypeError: size must be a number >= 0$/;
assert.throws(() => {
crypto.randomFillSync(buf, 'test');
- }, /offset must be a number/);
+ }, errMessages.offsetNotNumber);
assert.throws(() => {
crypto.randomFillSync(buf, NaN);
- }, /offset must be a number/);
+ }, errMessages.offsetNotNumber);
assert.throws(() => {
crypto.randomFill(buf, 'test', common.mustNotCall());
- }, /offset must be a number/);
+ }, errMessages.offsetNotNumber);
assert.throws(() => {
crypto.randomFill(buf, NaN, common.mustNotCall());
- }, /offset must be a number/);
+ }, errMessages.offsetNotNumber);
const max = require('buffer').kMaxLength + 1;
assert.throws(() => {
crypto.randomFillSync(buf, 11);
- }, /offset out of range/);
+ }, errMessages.offsetOutOfRange);
assert.throws(() => {
crypto.randomFillSync(buf, max);
- }, /offset out of range/);
+ }, errMessages.offsetOutOfRange);
assert.throws(() => {
crypto.randomFill(buf, 11, common.mustNotCall());
- }, /offset out of range/);
+ }, errMessages.offsetOutOfRange);
assert.throws(() => {
crypto.randomFill(buf, max, common.mustNotCall());
- }, /offset out of range/);
+ }, errMessages.offsetOutOfRange);
assert.throws(() => {
crypto.randomFillSync(buf, 0, 'test');
- }, /size must be a number/);
+ }, errMessages.sizeNotNumber);
assert.throws(() => {
crypto.randomFillSync(buf, 0, NaN);
- }, /size must be a number/);
+ }, errMessages.sizeNotNumber);
assert.throws(() => {
crypto.randomFill(buf, 0, 'test', common.mustNotCall());
- }, /size must be a number/);
+ }, errMessages.sizeNotNumber);
assert.throws(() => {
crypto.randomFill(buf, 0, NaN, common.mustNotCall());
- }, /size must be a number/);
+ }, errMessages.sizeNotNumber);
{
const size = (-1 >>> 0) + 1;
assert.throws(() => {
crypto.randomFillSync(buf, 0, -10);
- }, /size must be a uint32/);
+ }, errMessages.sizeNotUInt32);
assert.throws(() => {
crypto.randomFillSync(buf, 0, size);
- }, /size must be a uint32/);
+ }, errMessages.sizeNotUInt32);
assert.throws(() => {
crypto.randomFill(buf, 0, -10, common.mustNotCall());
- }, /size must be a uint32/);
+ }, errMessages.sizeNotUInt32);
assert.throws(() => {
crypto.randomFill(buf, 0, size, common.mustNotCall());
- }, /size must be a uint32/);
+ }, errMessages.sizeNotUInt32);
}
assert.throws(() => {
crypto.randomFillSync(buf, -10);
- }, /offset must be a uint32/);
+ }, errMessages.offsetNotUInt32);
assert.throws(() => {
crypto.randomFill(buf, -10, common.mustNotCall());
- }, /offset must be a uint32/);
+ }, errMessages.offsetNotUInt32);
assert.throws(() => {
crypto.randomFillSync(buf, 1, 10);
- }, /buffer too small/);
+ }, errMessages.bufferTooSmall);
assert.throws(() => {
crypto.randomFill(buf, 1, 10, common.mustNotCall());
- }, /buffer too small/);
+ }, errMessages.bufferTooSmall);
assert.throws(() => {
crypto.randomFillSync(buf, 0, 12);
- }, /buffer too small/);
+ }, errMessages.bufferTooSmall);
assert.throws(() => {
crypto.randomFill(buf, 0, 12, common.mustNotCall());
- }, /buffer too small/);
+ }, errMessages.bufferTooSmall);
{
// Offset is too big
const offset = (-1 >>> 0) + 1;
assert.throws(() => {
crypto.randomFillSync(buf, offset, 10);
- }, /offset must be a uint32/);
+ }, errMessages.offsetNotUInt32);
assert.throws(() => {
crypto.randomFill(buf, offset, 10, common.mustNotCall());
- }, /offset must be a uint32/);
+ }, errMessages.offsetNotUInt32);
}
}
}
diff --git a/test/parallel/test-crypto-sign-verify.js b/test/parallel/test-crypto-sign-verify.js
index 52daf2e6ff834a..2a64b6d072485b 100644
--- a/test/parallel/test-crypto-sign-verify.js
+++ b/test/parallel/test-crypto-sign-verify.js
@@ -105,6 +105,7 @@ const modSize = 1024;
getEffectiveSaltLength(crypto.constants.RSA_PSS_SALTLEN_MAX_SIGN),
0, 16, 32, 64, 128
];
+ const errMessage = /^Error:.*data too large for key size$/;
signSaltLengths.forEach((signSaltLength) => {
if (signSaltLength > max) {
@@ -117,7 +118,7 @@ const modSize = 1024;
padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
saltLength: signSaltLength
});
- }, /^Error:.*data too large for key size$/);
+ }, errMessage);
} else {
// Otherwise, a valid signature should be generated
const s4 = crypto.createSign(algo)
@@ -200,6 +201,9 @@ const modSize = 1024;
// Test exceptions for invalid `padding` and `saltLength` values
{
+ const paddingNotInteger = /^TypeError: padding must be an integer$/;
+ const saltLengthNotInteger = /^TypeError: saltLength must be an integer$/;
+
[null, undefined, NaN, 'boom', {}, [], true, false]
.forEach((invalidValue) => {
assert.throws(() => {
@@ -209,7 +213,7 @@ const modSize = 1024;
key: keyPem,
padding: invalidValue
});
- }, /^TypeError: padding must be an integer$/);
+ }, paddingNotInteger);
assert.throws(() => {
crypto.createSign('RSA-SHA256')
@@ -219,7 +223,7 @@ const modSize = 1024;
padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
saltLength: invalidValue
});
- }, /^TypeError: saltLength must be an integer$/);
+ }, saltLengthNotInteger);
});
assert.throws(() => {
diff --git a/test/parallel/test-crypto.js b/test/parallel/test-crypto.js
index 19fb6f2687e087..a7638d3cd899a1 100644
--- a/test/parallel/test-crypto.js
+++ b/test/parallel/test-crypto.js
@@ -99,7 +99,8 @@ validateList(cryptoCiphers);
const tlsCiphers = tls.getCiphers();
assert(tls.getCiphers().includes('aes256-sha'));
// There should be no capital letters in any element.
-assert(tlsCiphers.every((value) => /^[^A-Z]+$/.test(value)));
+const noCapitals = /^[^A-Z]+$/;
+assert(tlsCiphers.every((value) => noCapitals.test(value)));
validateList(tlsCiphers);
// Assert that we have sha and sha1 but not SHA and SHA1.
diff --git a/test/parallel/test-dgram-createSocket-type.js b/test/parallel/test-dgram-createSocket-type.js
index e6b17251f82060..125a9d0be5cc1c 100644
--- a/test/parallel/test-dgram-createSocket-type.js
+++ b/test/parallel/test-dgram-createSocket-type.js
@@ -19,6 +19,7 @@ const validTypes = [
{ type: 'udp4' },
{ type: 'udp6' }
];
+const errMessage = /^Bad socket type specified\. Valid types are: udp4, udp6$/;
// Error must be thrown with invalid types
invalidTypes.forEach((invalidType) => {
@@ -27,7 +28,7 @@ invalidTypes.forEach((invalidType) => {
}, common.expectsError({
code: 'ERR_SOCKET_BAD_TYPE',
type: Error,
- message: /^Bad socket type specified\. Valid types are: udp4, udp6$/
+ message: errMessage
}));
});
diff --git a/test/parallel/test-dgram-multicast-setTTL.js b/test/parallel/test-dgram-multicast-setTTL.js
index b7d1e01b321ac7..bd04ce4f32bde6 100644
--- a/test/parallel/test-dgram-multicast-setTTL.js
+++ b/test/parallel/test-dgram-multicast-setTTL.js
@@ -40,7 +40,7 @@ socket.on('listening', common.mustCall(() => {
}, common.expectsError({
code: 'ERR_INVALID_ARG_TYPE',
type: TypeError,
- message: /^The "arg" argument must be of type number$/
+ message: 'The "ttl" argument must be of type number. Received type string'
}));
//close the socket
diff --git a/test/parallel/test-dgram-setTTL.js b/test/parallel/test-dgram-setTTL.js
index c061fbc1870d9e..840a3f4d09f43a 100644
--- a/test/parallel/test-dgram-setTTL.js
+++ b/test/parallel/test-dgram-setTTL.js
@@ -14,7 +14,7 @@ socket.on('listening', common.mustCall(() => {
}, common.expectsError({
code: 'ERR_INVALID_ARG_TYPE',
type: TypeError,
- message: /^The "arg" argument must be of type number$/
+ message: 'The "ttl" argument must be of type number. Received type string'
}));
// TTL must be a number from > 0 to < 256
diff --git a/test/parallel/test-error-reporting.js b/test/parallel/test-error-reporting.js
index cdd066f959d231..8a961299793bb8 100644
--- a/test/parallel/test-error-reporting.js
+++ b/test/parallel/test-error-reporting.js
@@ -42,6 +42,8 @@ function errExec(script, callback) {
});
}
+const syntaxErrorMessage = /SyntaxError/;
+
// Simple throw error
errExec('throws_error.js', common.mustCall(function(err, stdout, stderr) {
@@ -51,30 +53,30 @@ errExec('throws_error.js', common.mustCall(function(err, stdout, stderr) {
// Trying to JSON.parse(undefined)
errExec('throws_error2.js', common.mustCall(function(err, stdout, stderr) {
- assert.ok(/SyntaxError/.test(stderr));
+ assert.ok(syntaxErrorMessage.test(stderr));
}));
// Trying to JSON.parse(undefined) in nextTick
errExec('throws_error3.js', common.mustCall(function(err, stdout, stderr) {
- assert.ok(/SyntaxError/.test(stderr));
+ assert.ok(syntaxErrorMessage.test(stderr));
}));
// throw ILLEGAL error
errExec('throws_error4.js', common.mustCall(function(err, stdout, stderr) {
assert.ok(/\/\*\*/.test(stderr));
- assert.ok(/SyntaxError/.test(stderr));
+ assert.ok(syntaxErrorMessage.test(stderr));
}));
// Specific long exception line doesn't result in stack overflow
errExec('throws_error5.js', common.mustCall(function(err, stdout, stderr) {
- assert.ok(/SyntaxError/.test(stderr));
+ assert.ok(syntaxErrorMessage.test(stderr));
}));
// Long exception line with length > errorBuffer doesn't result in assertion
errExec('throws_error6.js', common.mustCall(function(err, stdout, stderr) {
- assert.ok(/SyntaxError/.test(stderr));
+ assert.ok(syntaxErrorMessage.test(stderr));
}));
// Object that throws in toString() doesn't print garbage
diff --git a/test/parallel/test-event-emitter-max-listeners.js b/test/parallel/test-event-emitter-max-listeners.js
index 614801e3977da6..cf8c072271db35 100644
--- a/test/parallel/test-event-emitter-max-listeners.js
+++ b/test/parallel/test-event-emitter-max-listeners.js
@@ -31,12 +31,12 @@ e.on('maxListeners', common.mustCall());
e.setMaxListeners(42);
const throwsObjs = [NaN, -1, 'and even this'];
+const maxError = /^TypeError: "n" argument must be a positive number$/;
+const defError = /^TypeError: "defaultMaxListeners" must be a positive number$/;
for (const obj of throwsObjs) {
- assert.throws(() => e.setMaxListeners(obj),
- /^TypeError: "n" argument must be a positive number$/);
- assert.throws(() => events.defaultMaxListeners = obj,
- /^TypeError: "defaultMaxListeners" must be a positive number$/);
+ assert.throws(() => e.setMaxListeners(obj), maxError);
+ assert.throws(() => events.defaultMaxListeners = obj, defError);
}
e.emit('maxListeners');
diff --git a/test/parallel/test-fs-append-file.js b/test/parallel/test-fs-append-file.js
index 025a0ed034cd66..e3e4c273d3292d 100644
--- a/test/parallel/test-fs-append-file.js
+++ b/test/parallel/test-fs-append-file.js
@@ -144,6 +144,13 @@ fs.open(filename5, 'a+', function(e, fd) {
});
});
+// test that a missing callback emits a warning, even if the last argument is a
+// function.
+const filename6 = join(common.tmpDir, 'append6.txt');
+const warn = 'Calling an asynchronous function without callback is deprecated.';
+common.expectWarning('DeprecationWarning', warn);
+fs.appendFile(filename6, console.log);
+
process.on('exit', function() {
assert.strictEqual(12, ncallbacks);
diff --git a/test/parallel/test-fs-mkdir-rmdir.js b/test/parallel/test-fs-mkdir-rmdir.js
index bac18fc027931d..8c22331e85e3cd 100644
--- a/test/parallel/test-fs-mkdir-rmdir.js
+++ b/test/parallel/test-fs-mkdir-rmdir.js
@@ -24,14 +24,15 @@ fs.rmdirSync(d);
assert(!common.fileExists(d));
// Similarly test the Async version
-fs.mkdir(d, 0o666, function(err) {
+fs.mkdir(d, 0o666, common.mustCall(function(err) {
assert.ifError(err);
- fs.mkdir(d, 0o666, function(err) {
- assert.ok(err.message.match(/^EEXIST/), 'got EEXIST message');
- assert.strictEqual(err.code, 'EEXIST', 'got EEXIST code');
- assert.strictEqual(err.path, d, 'got proper path for EEXIST');
+ fs.mkdir(d, 0o666, common.mustCall(function(err) {
+ assert.ok(err, 'got no error');
+ assert.ok(/^EEXIST/.test(err.message), 'got no EEXIST message');
+ assert.strictEqual(err.code, 'EEXIST', 'got no EEXIST code');
+ assert.strictEqual(err.path, d, 'got no proper path for EEXIST');
fs.rmdir(d, assert.ifError);
- });
-});
+ }));
+}));
diff --git a/test/parallel/test-fs-null-bytes.js b/test/parallel/test-fs-null-bytes.js
index e9f421a6c41ec1..a21fe516a09993 100644
--- a/test/parallel/test-fs-null-bytes.js
+++ b/test/parallel/test-fs-null-bytes.js
@@ -29,7 +29,7 @@ function check(async, sync) {
const expected = /Path must be a string without null bytes/;
const argsSync = Array.prototype.slice.call(arguments, 2);
const argsAsync = argsSync.concat((er) => {
- assert(er && er.message.match(expected));
+ assert(er && expected.test(er.message));
assert.strictEqual(er.code, 'ENOENT');
});
diff --git a/test/parallel/test-fs-read-stream-inherit.js b/test/parallel/test-fs-read-stream-inherit.js
index b0bbde153539cc..8b1ca06950a98a 100644
--- a/test/parallel/test-fs-read-stream-inherit.js
+++ b/test/parallel/test-fs-read-stream-inherit.js
@@ -1,15 +1,16 @@
'use strict';
const common = require('../common');
-const assert = require('assert');
-const path = require('path');
+const assert = require('assert');
const fs = require('fs');
+const path = require('path');
+
const fn = path.join(common.fixturesDir, 'elipses.txt');
const rangeFile = path.join(common.fixturesDir, 'x.txt');
-let paused = false;
-
{
+ let paused = false;
+
const file = fs.ReadStream(fn);
file.on('open', common.mustCall(function(fd) {
@@ -48,11 +49,11 @@ let paused = false;
}
{
- const file3 = fs.createReadStream(fn, Object.create({encoding: 'utf8'}));
- file3.length = 0;
- file3.on('data', function(data) {
+ const file = fs.createReadStream(fn, Object.create({encoding: 'utf8'}));
+ file.length = 0;
+ file.on('data', function(data) {
assert.strictEqual(typeof data, 'string');
- file3.length += data.length;
+ file.length += data.length;
for (let i = 0; i < data.length; i++) {
// http://www.fileformat.info/info/unicode/char/2026/index.htm
@@ -60,49 +61,49 @@ let paused = false;
}
});
- file3.on('close', common.mustCall(function() {
- assert.strictEqual(file3.length, 10000);
+ file.on('close', common.mustCall(function() {
+ assert.strictEqual(file.length, 10000);
}));
}
{
const options = Object.create({bufferSize: 1, start: 1, end: 2});
- const file4 = fs.createReadStream(rangeFile, options);
- assert.strictEqual(file4.start, 1);
- assert.strictEqual(file4.end, 2);
+ const file = fs.createReadStream(rangeFile, options);
+ assert.strictEqual(file.start, 1);
+ assert.strictEqual(file.end, 2);
let contentRead = '';
- file4.on('data', function(data) {
+ file.on('data', function(data) {
contentRead += data.toString('utf-8');
});
- file4.on('end', common.mustCall(function() {
+ file.on('end', common.mustCall(function() {
assert.strictEqual(contentRead, 'yz');
}));
}
{
const options = Object.create({bufferSize: 1, start: 1});
- const file5 = fs.createReadStream(rangeFile, options);
- assert.strictEqual(file5.start, 1);
- file5.data = '';
- file5.on('data', function(data) {
- file5.data += data.toString('utf-8');
+ const file = fs.createReadStream(rangeFile, options);
+ assert.strictEqual(file.start, 1);
+ file.data = '';
+ file.on('data', function(data) {
+ file.data += data.toString('utf-8');
});
- file5.on('end', common.mustCall(function() {
- assert.strictEqual(file5.data, 'yz\n');
+ file.on('end', common.mustCall(function() {
+ assert.strictEqual(file.data, 'yz\n');
}));
}
// https://github.com/joyent/node/issues/2320
{
const options = Object.create({bufferSize: 1.23, start: 1});
- const file6 = fs.createReadStream(rangeFile, options);
- assert.strictEqual(file6.start, 1);
- file6.data = '';
- file6.on('data', function(data) {
- file6.data += data.toString('utf-8');
+ const file = fs.createReadStream(rangeFile, options);
+ assert.strictEqual(file.start, 1);
+ file.data = '';
+ file.on('data', function(data) {
+ file.data += data.toString('utf-8');
});
- file6.on('end', common.mustCall(function() {
- assert.strictEqual(file6.data, 'yz\n');
+ file.on('end', common.mustCall(function() {
+ assert.strictEqual(file.data, 'yz\n');
}));
}
@@ -136,56 +137,58 @@ let paused = false;
}
{
- let file7 =
+ let data = '';
+ let file =
fs.createReadStream(rangeFile, Object.create({autoClose: false }));
- assert.strictEqual(file7.autoClose, false);
- file7.on('data', common.noop);
- file7.on('end', common.mustCall(function() {
+ assert.strictEqual(file.autoClose, false);
+ file.on('data', (chunk) => { data += chunk; });
+ file.on('end', common.mustCall(function() {
process.nextTick(common.mustCall(function() {
- assert(!file7.closed);
- assert(!file7.destroyed);
- file7Next();
+ assert(!file.closed);
+ assert(!file.destroyed);
+ assert.strictEqual(data, 'xyz\n');
+ fileNext();
}));
}));
- function file7Next() {
+ function fileNext() {
// This will tell us if the fd is usable again or not.
- file7 = fs.createReadStream(null, Object.create({fd: file7.fd, start: 0 }));
- file7.data = '';
- file7.on('data', function(data) {
- file7.data += data;
+ file = fs.createReadStream(null, Object.create({fd: file.fd, start: 0 }));
+ file.data = '';
+ file.on('data', function(data) {
+ file.data += data;
});
- file7.on('end', common.mustCall(function() {
- assert.strictEqual(file7.data, 'xyz\n');
+ file.on('end', common.mustCall(function() {
+ assert.strictEqual(file.data, 'xyz\n');
}));
}
process.on('exit', function() {
- assert(file7.closed);
- assert(file7.destroyed);
+ assert(file.closed);
+ assert(file.destroyed);
});
}
// Just to make sure autoClose won't close the stream because of error.
{
const options = Object.create({fd: 13337, autoClose: false});
- const file8 = fs.createReadStream(null, options);
- file8.on('data', common.noop);
- file8.on('error', common.mustCall());
+ const file = fs.createReadStream(null, options);
+ file.on('data', common.mustNotCall());
+ file.on('error', common.mustCall());
process.on('exit', function() {
- assert(!file8.closed);
- assert(!file8.destroyed);
- assert(file8.fd);
+ assert(!file.closed);
+ assert(!file.destroyed);
+ assert(file.fd);
});
}
// Make sure stream is destroyed when file does not exist.
{
- const file9 = fs.createReadStream('/path/to/file/that/does/not/exist');
- file9.on('data', common.noop);
- file9.on('error', common.mustCall());
+ const file = fs.createReadStream('/path/to/file/that/does/not/exist');
+ file.on('data', common.mustNotCall());
+ file.on('error', common.mustCall());
process.on('exit', function() {
- assert(!file9.closed);
- assert(file9.destroyed);
+ assert(!file.closed);
+ assert(file.destroyed);
});
}
diff --git a/test/parallel/test-fs-read-stream-throw-type-error.js b/test/parallel/test-fs-read-stream-throw-type-error.js
index bc1fca3a3c3e6a..6e4f405daa8ff6 100644
--- a/test/parallel/test-fs-read-stream-throw-type-error.js
+++ b/test/parallel/test-fs-read-stream-throw-type-error.js
@@ -19,15 +19,16 @@ assert.doesNotThrow(function() {
fs.createReadStream(example, {encoding: 'utf8'});
});
+const errMessage = /"options" must be a string or an object/;
assert.throws(function() {
fs.createReadStream(example, 123);
-}, /"options" must be a string or an object/);
+}, errMessage);
assert.throws(function() {
fs.createReadStream(example, 0);
-}, /"options" must be a string or an object/);
+}, errMessage);
assert.throws(function() {
fs.createReadStream(example, true);
-}, /"options" must be a string or an object/);
+}, errMessage);
assert.throws(function() {
fs.createReadStream(example, false);
-}, /"options" must be a string or an object/);
+}, errMessage);
diff --git a/test/parallel/test-fs-read-stream.js b/test/parallel/test-fs-read-stream.js
index 6ca1729066d3dd..9ec397c31e5c3b 100644
--- a/test/parallel/test-fs-read-stream.js
+++ b/test/parallel/test-fs-read-stream.js
@@ -21,183 +21,199 @@
'use strict';
const common = require('../common');
-const assert = require('assert');
-const path = require('path');
+const assert = require('assert');
const fs = require('fs');
+const path = require('path');
+
const fn = path.join(common.fixturesDir, 'elipses.txt');
const rangeFile = path.join(common.fixturesDir, 'x.txt');
-const callbacks = { open: 0, end: 0, close: 0 };
+{
+ let paused = false;
+ let bytesRead = 0;
-let paused = false;
-let bytesRead = 0;
+ const file = fs.ReadStream(fn);
+ const fileSize = fs.statSync(fn).size;
-const file = fs.ReadStream(fn);
-const fileSize = fs.statSync(fn).size;
+ assert.strictEqual(file.bytesRead, 0);
-assert.strictEqual(file.bytesRead, 0);
+ file.on('open', common.mustCall(function(fd) {
+ file.length = 0;
+ assert.strictEqual('number', typeof fd);
+ assert.strictEqual(file.bytesRead, 0);
+ assert.ok(file.readable);
-file.on('open', function(fd) {
- file.length = 0;
- callbacks.open++;
- assert.strictEqual('number', typeof fd);
- assert.strictEqual(file.bytesRead, 0);
- assert.ok(file.readable);
+ // GH-535
+ file.pause();
+ file.resume();
+ file.pause();
+ file.resume();
+ }));
- // GH-535
- file.pause();
- file.resume();
- file.pause();
- file.resume();
-});
+ file.on('data', function(data) {
+ assert.ok(data instanceof Buffer);
+ assert.ok(!paused);
+ file.length += data.length;
-file.on('data', function(data) {
- assert.ok(data instanceof Buffer);
- assert.ok(!paused);
- file.length += data.length;
+ bytesRead += data.length;
+ assert.strictEqual(file.bytesRead, bytesRead);
- bytesRead += data.length;
- assert.strictEqual(file.bytesRead, bytesRead);
+ paused = true;
+ file.pause();
- paused = true;
- file.pause();
+ setTimeout(function() {
+ paused = false;
+ file.resume();
+ }, 10);
+ });
- setTimeout(function() {
- paused = false;
- file.resume();
- }, 10);
-});
+ file.on('end', common.mustCall(function(chunk) {
+ assert.strictEqual(bytesRead, fileSize);
+ assert.strictEqual(file.bytesRead, fileSize);
+ }));
-file.on('end', function(chunk) {
- assert.strictEqual(bytesRead, fileSize);
- assert.strictEqual(file.bytesRead, fileSize);
- callbacks.end++;
-});
+ file.on('close', common.mustCall(function() {
+ assert.strictEqual(bytesRead, fileSize);
+ assert.strictEqual(file.bytesRead, fileSize);
+ }));
-file.on('close', function() {
- assert.strictEqual(bytesRead, fileSize);
- assert.strictEqual(file.bytesRead, fileSize);
- callbacks.close++;
+ process.on('exit', function() {
+ assert.strictEqual(file.length, 30000);
+ });
+}
- //assert.strictEqual(fs.readFileSync(fn), fileContent);
-});
+{
+ const file = fs.createReadStream(fn, {encoding: 'utf8'});
+ file.length = 0;
+ file.on('data', function(data) {
+ assert.strictEqual('string', typeof data);
+ file.length += data.length;
+
+ for (let i = 0; i < data.length; i++) {
+ // http://www.fileformat.info/info/unicode/char/2026/index.htm
+ assert.strictEqual('\u2026', data[i]);
+ }
+ });
-const file3 = fs.createReadStream(fn, {encoding: 'utf8'});
-file3.length = 0;
-file3.on('data', function(data) {
- assert.strictEqual('string', typeof data);
- file3.length += data.length;
+ file.on('close', common.mustCall());
- for (let i = 0; i < data.length; i++) {
- // http://www.fileformat.info/info/unicode/char/2026/index.htm
- assert.strictEqual('\u2026', data[i]);
- }
-});
-
-file3.on('close', function() {
- callbacks.close++;
-});
-
-process.on('exit', function() {
- assert.strictEqual(1, callbacks.open);
- assert.strictEqual(1, callbacks.end);
- assert.strictEqual(2, callbacks.close);
- assert.strictEqual(30000, file.length);
- assert.strictEqual(10000, file3.length);
- console.error('ok');
-});
-
-const file4 = fs.createReadStream(rangeFile, {bufferSize: 1, start: 1, end: 2});
-let contentRead = '';
-file4.on('data', function(data) {
- contentRead += data.toString('utf-8');
-});
-file4.on('end', function(data) {
- assert.strictEqual(contentRead, 'yz');
-});
-
-const file5 = fs.createReadStream(rangeFile, {bufferSize: 1, start: 1});
-file5.data = '';
-file5.on('data', function(data) {
- file5.data += data.toString('utf-8');
-});
-file5.on('end', function() {
- assert.strictEqual(file5.data, 'yz\n');
-});
-
-// https://github.com/joyent/node/issues/2320
-const file6 = fs.createReadStream(rangeFile, {bufferSize: 1.23, start: 1});
-file6.data = '';
-file6.on('data', function(data) {
- file6.data += data.toString('utf-8');
-});
-file6.on('end', function() {
- assert.strictEqual(file6.data, 'yz\n');
-});
+ process.on('exit', function() {
+ assert.strictEqual(file.length, 10000);
+ });
+}
+
+{
+ const file =
+ fs.createReadStream(rangeFile, {bufferSize: 1, start: 1, end: 2});
+ let contentRead = '';
+ file.on('data', function(data) {
+ contentRead += data.toString('utf-8');
+ });
+ file.on('end', common.mustCall(function(data) {
+ assert.strictEqual(contentRead, 'yz');
+ }));
+}
+
+{
+ const file = fs.createReadStream(rangeFile, {bufferSize: 1, start: 1});
+ file.data = '';
+ file.on('data', function(data) {
+ file.data += data.toString('utf-8');
+ });
+ file.on('end', common.mustCall(function() {
+ assert.strictEqual(file.data, 'yz\n');
+ }));
+}
+
+{
+ // Ref: https://github.com/nodejs/node-v0.x-archive/issues/2320
+ const file = fs.createReadStream(rangeFile, {bufferSize: 1.23, start: 1});
+ file.data = '';
+ file.on('data', function(data) {
+ file.data += data.toString('utf-8');
+ });
+ file.on('end', common.mustCall(function() {
+ assert.strictEqual(file.data, 'yz\n');
+ }));
+}
assert.throws(function() {
fs.createReadStream(rangeFile, {start: 10, end: 2});
}, /"start" option must be <= "end" option/);
-const stream = fs.createReadStream(rangeFile, { start: 0, end: 0 });
-stream.data = '';
-
-stream.on('data', function(chunk) {
- stream.data += chunk;
-});
-
-stream.on('end', function() {
- assert.strictEqual('x', stream.data);
-});
-
-// pause and then resume immediately.
-const pauseRes = fs.createReadStream(rangeFile);
-pauseRes.pause();
-pauseRes.resume();
-
-let file7 = fs.createReadStream(rangeFile, {autoClose: false });
-file7.on('data', common.noop);
-file7.on('end', function() {
- process.nextTick(function() {
- assert(!file7.closed);
- assert(!file7.destroyed);
- file7Next();
- });
-});
-
-function file7Next() {
- // This will tell us if the fd is usable again or not.
- file7 = fs.createReadStream(null, {fd: file7.fd, start: 0 });
- file7.data = '';
- file7.on('data', function(data) {
- file7.data += data;
- });
- file7.on('end', function(err) {
- assert.strictEqual(file7.data, 'xyz\n');
+{
+ const stream = fs.createReadStream(rangeFile, { start: 0, end: 0 });
+ stream.data = '';
+
+ stream.on('data', function(chunk) {
+ stream.data += chunk;
});
+
+ stream.on('end', common.mustCall(function() {
+ assert.strictEqual('x', stream.data);
+ }));
}
-// Just to make sure autoClose won't close the stream because of error.
-const file8 = fs.createReadStream(null, {fd: 13337, autoClose: false });
-file8.on('data', common.noop);
-file8.on('error', common.mustCall());
+{
+ // pause and then resume immediately.
+ const pauseRes = fs.createReadStream(rangeFile);
+ pauseRes.pause();
+ pauseRes.resume();
+}
-// Make sure stream is destroyed when file does not exist.
-const file9 = fs.createReadStream('/path/to/file/that/does/not/exist');
-file9.on('data', common.noop);
-file9.on('error', common.mustCall());
+{
+ let file = fs.createReadStream(rangeFile, {autoClose: false });
+ let data = '';
+ file.on('data', function(chunk) { data += chunk; });
+ file.on('end', common.mustCall(function() {
+ assert.strictEqual(data, 'xyz\n');
+ process.nextTick(function() {
+ assert(!file.closed);
+ assert(!file.destroyed);
+ fileNext();
+ });
+ }));
+
+ function fileNext() {
+ // This will tell us if the fd is usable again or not.
+ file = fs.createReadStream(null, {fd: file.fd, start: 0 });
+ file.data = '';
+ file.on('data', function(data) {
+ file.data += data;
+ });
+ file.on('end', common.mustCall(function(err) {
+ assert.strictEqual(file.data, 'xyz\n');
+ }));
+ process.on('exit', function() {
+ assert(file.closed);
+ assert(file.destroyed);
+ });
+ }
+}
-process.on('exit', function() {
- assert(file7.closed);
- assert(file7.destroyed);
+{
+ // Just to make sure autoClose won't close the stream because of error.
+ const file = fs.createReadStream(null, {fd: 13337, autoClose: false });
+ file.on('data', common.mustNotCall());
+ file.on('error', common.mustCall());
+ process.on('exit', function() {
+ assert(!file.closed);
+ assert(!file.destroyed);
+ assert(file.fd);
+ });
+}
- assert(!file8.closed);
- assert(!file8.destroyed);
- assert(file8.fd);
+{
+ // Make sure stream is destroyed when file does not exist.
+ const file = fs.createReadStream('/path/to/file/that/does/not/exist');
+ file.on('data', common.mustNotCall());
+ file.on('error', common.mustCall());
- assert(!file9.closed);
- assert(file9.destroyed);
-});
+ process.on('exit', function() {
+ assert(!file.closed);
+ assert(file.destroyed);
+ });
+}
diff --git a/test/parallel/test-fs-watch-stop-async.js b/test/parallel/test-fs-watch-stop-async.js
index 6716f1fcb2f83b..61db2a300f983b 100644
--- a/test/parallel/test-fs-watch-stop-async.js
+++ b/test/parallel/test-fs-watch-stop-async.js
@@ -1,9 +1,10 @@
'use strict';
const common = require('../common');
+
const assert = require('assert');
const fs = require('fs');
-const watch = fs.watchFile(__filename, common.noop);
+const watch = fs.watchFile(__filename, common.mustNotCall());
let triggered;
const listener = common.mustCall(() => {
triggered = true;
diff --git a/test/parallel/test-fs-watch-stop-sync.js b/test/parallel/test-fs-watch-stop-sync.js
index 4655c0ac62943d..7f0882e489f8b3 100644
--- a/test/parallel/test-fs-watch-stop-sync.js
+++ b/test/parallel/test-fs-watch-stop-sync.js
@@ -1,10 +1,21 @@
'use strict';
-
const common = require('../common');
-const assert = require('assert');
+
+// This test checks that the `stop` event is emitted asynchronously.
+//
+// If it isn't asynchronous, then the listener will be called during the
+// execution of `watch.stop()`. That would be a bug.
+//
+// If it is asynchronous, then the listener will be removed before the event is
+// emitted.
+
const fs = require('fs');
-const watch = fs.watchFile(__filename, common.noop);
-watch.once('stop', assert.fail); // Should not trigger.
+const listener = common.mustNotCall(
+ 'listener should have been removed before the event was emitted'
+);
+
+const watch = fs.watchFile(__filename, common.mustNotCall());
+watch.once('stop', listener);
watch.stop();
-watch.removeListener('stop', assert.fail);
+watch.removeListener('stop', listener);
diff --git a/test/parallel/test-global-console-exists.js b/test/parallel/test-global-console-exists.js
index 425eac077aba43..1434b76e12696e 100644
--- a/test/parallel/test-global-console-exists.js
+++ b/test/parallel/test-global-console-exists.js
@@ -1,39 +1,46 @@
/* eslint-disable required-modules */
-// ordinarily test files must require('common') but that action causes
-// the global console to be compiled, defeating the purpose of this test
'use strict';
-const common = require('../common');
+// Ordinarily test files must require('common') but that action causes
+// the global console to be compiled, defeating the purpose of this test.
+
const assert = require('assert');
const EventEmitter = require('events');
const leakWarning = /EventEmitter memory leak detected\. 2 hello listeners/;
-common.hijackStderr(common.mustCall(function(data) {
- if (process.stderr.writeTimes === 0) {
- assert.ok(data.match(leakWarning));
- } else {
- assert.fail('stderr.write should be called only once');
- }
-}));
-
-process.on('warning', function(warning) {
+let writeTimes = 0;
+let warningTimes = 0;
+process.on('warning', () => {
// This will be called after the default internal
// process warning handler is called. The default
// process warning writes to the console, which will
// invoke the monkeypatched process.stderr.write
// below.
- assert.strictEqual(process.stderr.writeTimes, 1);
+ assert.strictEqual(writeTimes, 1);
EventEmitter.defaultMaxListeners = oldDefault;
- // when we get here, we should be done
+ warningTimes++;
+});
+
+process.on('exit', () => {
+ assert.strictEqual(warningTimes, 1);
});
+process.stderr.write = (data) => {
+ if (writeTimes === 0)
+ assert.ok(leakWarning.test(data));
+ else
+ assert.fail('stderr.write should be called only once');
+
+ writeTimes++;
+};
+
const oldDefault = EventEmitter.defaultMaxListeners;
EventEmitter.defaultMaxListeners = 1;
const e = new EventEmitter();
-e.on('hello', common.noop);
-e.on('hello', common.noop);
+e.on('hello', () => {});
+e.on('hello', () => {});
// TODO: Figure out how to validate console. Currently,
// there is no obvious way of validating that console
diff --git a/test/parallel/test-http-client-immediate-error.js b/test/parallel/test-http-client-immediate-error.js
index 9fbe052efd4104..6b9cacb256f927 100644
--- a/test/parallel/test-http-client-immediate-error.js
+++ b/test/parallel/test-http-client-immediate-error.js
@@ -5,8 +5,36 @@
const common = require('../common');
const assert = require('assert');
+const net = require('net');
const http = require('http');
-const req = http.get({ host: '127.0.0.1', port: 1 });
-req.on('error', common.mustCall((err) => {
- assert.strictEqual(err.code, 'ECONNREFUSED');
+const uv = process.binding('uv');
+const { async_id_symbol } = process.binding('async_wrap');
+const { newUid } = require('async_hooks');
+
+const agent = new http.Agent();
+agent.createConnection = common.mustCall((cfg) => {
+ const sock = new net.Socket();
+
+ // Fake the handle so we can enforce returning an immediate error
+ sock._handle = {
+ connect: common.mustCall((req, addr, port) => {
+ return uv.UV_ENETUNREACH;
+ }),
+ readStart() {},
+ close() {}
+ };
+
+ // Simulate just enough socket handle initialization
+ sock[async_id_symbol] = newUid();
+
+ sock.connect(cfg);
+ return sock;
+});
+
+http.get({
+ host: '127.0.0.1',
+ port: 1,
+ agent
+}).on('error', common.mustCall((err) => {
+ assert.strictEqual(err.code, 'ENETUNREACH');
}));
diff --git a/test/parallel/test-http-client-unescaped-path.js b/test/parallel/test-http-client-unescaped-path.js
index d991e9f75e49e2..11faaec41a6035 100644
--- a/test/parallel/test-http-client-unescaped-path.js
+++ b/test/parallel/test-http-client-unescaped-path.js
@@ -24,8 +24,8 @@ const common = require('../common');
const assert = require('assert');
const http = require('http');
+const errMessage = /contains unescaped characters/;
for (let i = 0; i <= 32; i += 1) {
const path = `bad${String.fromCharCode(i)}path`;
- assert.throws(() => http.get({ path }, common.mustNotCall()),
- /contains unescaped characters/);
+ assert.throws(() => http.get({ path }, common.mustNotCall()), errMessage);
}
diff --git a/test/parallel/test-http-eof-on-connect.js b/test/parallel/test-http-eof-on-connect.js
index 87c6aeca5fb480..7e244354c1cb88 100644
--- a/test/parallel/test-http-eof-on-connect.js
+++ b/test/parallel/test-http-eof-on-connect.js
@@ -29,7 +29,7 @@ const http = require('http');
// It is separate from test-http-malformed-request.js because it is only
// reproduceable on the first packet on the first connection to a server.
-const server = http.createServer(common.noop);
+const server = http.createServer(common.mustNotCall());
server.listen(0);
server.on('listening', function() {
diff --git a/test/parallel/test-http-hostname-typechecking.js b/test/parallel/test-http-hostname-typechecking.js
index 5fd776db27f3ef..c3b702896d4e39 100644
--- a/test/parallel/test-http-hostname-typechecking.js
+++ b/test/parallel/test-http-hostname-typechecking.js
@@ -8,14 +8,14 @@ const http = require('http');
// when passed as the value of either options.hostname or options.host
const vals = [{}, [], NaN, Infinity, -Infinity, true, false, 1, 0, new Date()];
-function errCheck(name) {
- return new RegExp(`^TypeError: "options\\.${name}" must either be a ` +
- 'string, undefined or null$');
-}
+const errHostname =
+ /^TypeError: "options\.hostname" must either be a string, undefined or null$/;
+const errHost =
+ /^TypeError: "options\.host" must either be a string, undefined or null$/;
vals.forEach((v) => {
- assert.throws(() => http.request({hostname: v}), errCheck('hostname'));
- assert.throws(() => http.request({host: v}), errCheck('host'));
+ assert.throws(() => http.request({hostname: v}), errHostname);
+ assert.throws(() => http.request({host: v}), errHost);
});
// These values are OK and should not throw synchronously
diff --git a/test/parallel/test-http-server.js b/test/parallel/test-http-server.js
index 701d91f623fff1..85b2be52fef212 100644
--- a/test/parallel/test-http-server.js
+++ b/test/parallel/test-http-server.js
@@ -116,10 +116,10 @@ process.on('exit', function() {
assert.strictEqual(4, requests_sent);
const hello = new RegExp('/hello');
- assert.notStrictEqual(null, hello.exec(server_response));
+ assert.ok(hello.test(server_response));
const quit = new RegExp('/quit');
- assert.notStrictEqual(null, quit.exec(server_response));
+ assert.ok(quit.test(server_response));
assert.strictEqual(true, client_got_eof);
});
diff --git a/test/parallel/test-http-set-timeout-server.js b/test/parallel/test-http-set-timeout-server.js
index b9cba1d192d0f7..b1b9e98ac0baf7 100644
--- a/test/parallel/test-http-set-timeout-server.js
+++ b/test/parallel/test-http-set-timeout-server.js
@@ -21,6 +21,7 @@
'use strict';
const common = require('../common');
+
const assert = require('assert');
const http = require('http');
const net = require('net');
@@ -30,100 +31,72 @@ const tests = [];
function test(fn) {
if (!tests.length)
process.nextTick(run);
- tests.push(fn);
+ tests.push(common.mustCall(fn));
}
function run() {
const fn = tests.shift();
if (fn) {
- console.log('# %s', fn.name);
fn(run);
- } else {
- console.log('ok');
}
}
test(function serverTimeout(cb) {
- let caughtTimeout = false;
- process.on('exit', function() {
- assert(caughtTimeout);
- });
const server = http.createServer(function(req, res) {
// just do nothing, we should get a timeout event.
});
server.listen(common.mustCall(function() {
- http.get({ port: server.address().port }).on('error', common.noop);
+ http.get({ port: server.address().port }).on('error', common.mustCall());
}));
- const s = server.setTimeout(50, function(socket) {
- caughtTimeout = true;
+ const s = server.setTimeout(50, common.mustCall(function(socket) {
socket.destroy();
server.close();
cb();
- });
+ }));
assert.ok(s instanceof http.Server);
});
test(function serverRequestTimeout(cb) {
- let caughtTimeout = false;
- process.on('exit', function() {
- assert(caughtTimeout);
- });
const server = http.createServer(function(req, res) {
// just do nothing, we should get a timeout event.
- const s = req.setTimeout(50, function() {
- caughtTimeout = true;
- req.socket.destroy();
+ const s = req.setTimeout(50, common.mustCall(function(socket) {
+ socket.destroy();
server.close();
cb();
- });
+ }));
assert.ok(s instanceof http.IncomingMessage);
});
server.listen(common.mustCall(function() {
const port = server.address().port;
const req = http.request({ port: port, method: 'POST' });
- req.on('error', common.noop);
+ req.on('error', common.mustCall());
req.write('Hello');
// req is in progress
}));
});
test(function serverResponseTimeout(cb) {
- let caughtTimeout = false;
- process.on('exit', function() {
- assert(caughtTimeout);
- });
const server = http.createServer(function(req, res) {
// just do nothing, we should get a timeout event.
- const s = res.setTimeout(50, function() {
- caughtTimeout = true;
- res.socket.destroy();
+ const s = res.setTimeout(50, common.mustCall(function(socket) {
+ socket.destroy();
server.close();
cb();
- });
+ }));
assert.ok(s instanceof http.OutgoingMessage);
});
server.listen(common.mustCall(function() {
const port = server.address().port;
- http.get({ port: port }).on('error', common.noop);
+ http.get({ port: port }).on('error', common.mustCall());
}));
});
test(function serverRequestNotTimeoutAfterEnd(cb) {
- let caughtTimeoutOnRequest = false;
- let caughtTimeoutOnResponse = false;
- process.on('exit', function() {
- assert(!caughtTimeoutOnRequest);
- assert(caughtTimeoutOnResponse);
- });
const server = http.createServer(function(req, res) {
// just do nothing, we should get a timeout event.
- const s = req.setTimeout(50, function(socket) {
- caughtTimeoutOnRequest = true;
- });
+ const s = req.setTimeout(50, common.mustNotCall());
assert.ok(s instanceof http.IncomingMessage);
- res.on('timeout', function(socket) {
- caughtTimeoutOnResponse = true;
- });
+ res.on('timeout', common.mustCall());
});
server.on('timeout', function(socket) {
socket.destroy();
@@ -132,7 +105,7 @@ test(function serverRequestNotTimeoutAfterEnd(cb) {
});
server.listen(common.mustCall(function() {
const port = server.address().port;
- http.get({ port: port }).on('error', common.noop);
+ http.get({ port: port }).on('error', common.mustCall());
}));
});
@@ -169,29 +142,16 @@ test(function serverResponseTimeoutWithPipeline(cb) {
});
test(function idleTimeout(cb) {
- let caughtTimeoutOnRequest = false;
- let caughtTimeoutOnResponse = false;
- let caughtTimeoutOnServer = false;
- process.on('exit', function() {
- assert(!caughtTimeoutOnRequest);
- assert(!caughtTimeoutOnResponse);
- assert(caughtTimeoutOnServer);
- });
const server = http.createServer(function(req, res) {
- req.on('timeout', function(socket) {
- caughtTimeoutOnRequest = true;
- });
- res.on('timeout', function(socket) {
- caughtTimeoutOnResponse = true;
- });
+ req.on('timeout', common.mustNotCall());
+ res.on('timeout', common.mustNotCall());
res.end();
});
- const s = server.setTimeout(50, function(socket) {
- caughtTimeoutOnServer = true;
+ const s = server.setTimeout(50, common.mustCall(function(socket) {
socket.destroy();
server.close();
cb();
- });
+ }));
assert.ok(s instanceof http.Server);
server.listen(common.mustCall(function() {
const port = server.address().port;
diff --git a/test/parallel/test-icu-data-dir.js b/test/parallel/test-icu-data-dir.js
index 07a4391505b1e2..3882acb92c767c 100644
--- a/test/parallel/test-icu-data-dir.js
+++ b/test/parallel/test-icu-data-dir.js
@@ -1,5 +1,9 @@
'use strict';
-require('../common');
+const common = require('../common');
+if (!(common.hasIntl && common.hasSmallICU)) {
+ common.skip('missing Intl');
+ return;
+}
const assert = require('assert');
const { spawnSync } = require('child_process');
diff --git a/test/parallel/test-icu-punycode.js b/test/parallel/test-icu-punycode.js
index 13db2dd7bacede..9488568267a140 100644
--- a/test/parallel/test-icu-punycode.js
+++ b/test/parallel/test-icu-punycode.js
@@ -24,6 +24,8 @@ const wptToASCIITests = require('../fixtures/url-toascii.js');
}
{
+ const errMessage = /^Error: Cannot convert name to ASCII$/;
+
for (const [i, test] of wptToASCIITests.entries()) {
if (typeof test === 'string')
continue; // skip comments
@@ -33,8 +35,7 @@ const wptToASCIITests = require('../fixtures/url-toascii.js');
caseComment += ` (${comment})`;
if (output === null) {
assert.throws(() => icu.toASCII(input),
- /^Error: Cannot convert name to ASCII$/,
- `ToASCII ${caseComment}`);
+ errMessage, `ToASCII ${caseComment}`);
assert.doesNotThrow(() => icu.toASCII(input, true),
`ToASCII ${caseComment} in lenient mode`);
} else {
diff --git a/test/parallel/test-internal-errors.js b/test/parallel/test-internal-errors.js
index c97b522e4a6abb..8e06bab34944a1 100644
--- a/test/parallel/test-internal-errors.js
+++ b/test/parallel/test-internal-errors.js
@@ -5,6 +5,13 @@ const common = require('../common');
const errors = require('internal/errors');
const assert = require('assert');
+const errMessages = {
+ objectString: /^'object' === 'string'$/,
+ booleanString: /^'boolean' === 'string'$/,
+ numberString: /^'number' === 'string'$/,
+ invalidKey: /^An invalid error message key was used: TEST_FOO_KEY\.$/,
+};
+
errors.E('TEST_ERROR_1', 'Error for testing purposes: %s');
errors.E('TEST_ERROR_2', (a, b) => `${a} ${b}`);
@@ -43,86 +50,86 @@ assert.throws(
() => new errors.Error('TEST_FOO_KEY'),
common.expectsError({
code: 'ERR_ASSERTION',
- message: /^An invalid error message key was used: TEST_FOO_KEY\.$/
+ message: errMessages.invalidKey
}));
// Calling it twice yields same result (using the key does not create it)
assert.throws(
() => new errors.Error('TEST_FOO_KEY'),
common.expectsError({
code: 'ERR_ASSERTION',
- message: /^An invalid error message key was used: TEST_FOO_KEY\.$/
+ message: errMessages.invalidKey
}));
assert.throws(
() => new errors.Error(1),
common.expectsError({
code: 'ERR_ASSERTION',
- message: /^'number' === 'string'$/
+ message: errMessages.numberString
}));
assert.throws(
() => new errors.Error({}),
common.expectsError({
code: 'ERR_ASSERTION',
- message: /^'object' === 'string'$/
+ message: errMessages.objectString
}));
assert.throws(
() => new errors.Error([]),
common.expectsError({
code: 'ERR_ASSERTION',
- message: /^'object' === 'string'$/
+ message: errMessages.objectString
}));
assert.throws(
() => new errors.Error(true),
common.expectsError({
code: 'ERR_ASSERTION',
- message: /^'boolean' === 'string'$/
+ message: errMessages.booleanString
}));
assert.throws(
() => new errors.TypeError(1),
common.expectsError({
code: 'ERR_ASSERTION',
- message: /^'number' === 'string'$/
+ message: errMessages.numberString
}));
assert.throws(
() => new errors.TypeError({}),
common.expectsError({
code: 'ERR_ASSERTION',
- message: /^'object' === 'string'$/
+ message: errMessages.objectString
}));
assert.throws(
() => new errors.TypeError([]),
common.expectsError({
code: 'ERR_ASSERTION',
- message: /^'object' === 'string'$/
+ message: errMessages.objectString
}));
assert.throws(
() => new errors.TypeError(true),
common.expectsError({
code: 'ERR_ASSERTION',
- message: /^'boolean' === 'string'$/
+ message: errMessages.booleanString
}));
assert.throws(
() => new errors.RangeError(1),
common.expectsError({
code: 'ERR_ASSERTION',
- message: /^'number' === 'string'$/
+ message: errMessages.numberString
}));
assert.throws(
() => new errors.RangeError({}),
common.expectsError({
code: 'ERR_ASSERTION',
- message: /^'object' === 'string'$/
+ message: errMessages.objectString
}));
assert.throws(
() => new errors.RangeError([]),
common.expectsError({
code: 'ERR_ASSERTION',
- message: /^'object' === 'string'$/
+ message: errMessages.objectString
}));
assert.throws(
() => new errors.RangeError(true),
common.expectsError({
code: 'ERR_ASSERTION',
- message: /^'boolean' === 'string'$/
+ message: errMessages.booleanString
}));
diff --git a/test/parallel/test-internal-modules-strip-shebang.js b/test/parallel/test-internal-modules-strip-shebang.js
new file mode 100644
index 00000000000000..93be3d41981f50
--- /dev/null
+++ b/test/parallel/test-internal-modules-strip-shebang.js
@@ -0,0 +1,14 @@
+// Flags: --expose-internals
+'use strict';
+require('../common');
+
+const assert = require('assert');
+const stripShebang = require('internal/module').stripShebang;
+
+[
+ ['', ''],
+ ['aa', 'aa'],
+ ['#!', ''],
+ ['#!bin/bash', ''],
+ ['#!bin/bash\naa', '\naa'],
+].forEach((i) => assert.strictEqual(stripShebang(i[0]), i[1]));
diff --git a/test/parallel/test-net-better-error-messages-path.js b/test/parallel/test-net-better-error-messages-path.js
index f4d00c7aebf055..bb2256637a0d30 100644
--- a/test/parallel/test-net-better-error-messages-path.js
+++ b/test/parallel/test-net-better-error-messages-path.js
@@ -2,12 +2,21 @@
const common = require('../common');
const net = require('net');
const assert = require('assert');
-const fp = '/tmp/fadagagsdfgsdf';
-const c = net.connect(fp);
-c.on('connect', common.mustNotCall());
+{
+ const fp = '/tmp/fadagagsdfgsdf';
+ const c = net.connect(fp);
-c.on('error', common.mustCall(function(e) {
- assert.strictEqual(e.code, 'ENOENT');
- assert.strictEqual(e.message, `connect ENOENT ${fp}`);
-}));
+ c.on('connect', common.mustNotCall());
+ c.on('error', common.expectsError({
+ code: 'ENOENT',
+ message: `connect ENOENT ${fp}`
+ }));
+}
+
+{
+ assert.throws(
+ () => net.createConnection({ path: {} }),
+ common.expectsError({ code: 'ERR_INVALID_ARG_TYPE' })
+ );
+}
diff --git a/test/parallel/test-net-connect-options-port.js b/test/parallel/test-net-connect-options-port.js
index b3c370c8d9030e..1a2bd850f3a54d 100644
--- a/test/parallel/test-net-connect-options-port.js
+++ b/test/parallel/test-net-connect-options-port.js
@@ -190,7 +190,7 @@ function canConnect(port) {
function asyncFailToConnect(port) {
const onError = () => common.mustCall(function(err) {
- const regexp = /^Error: connect (E\w+)(.+)$/;
+ const regexp = /^Error: connect E\w+.+$/;
assert(regexp.test(String(err)), String(err));
});
diff --git a/test/parallel/test-net-end-close.js b/test/parallel/test-net-end-close.js
index d9f33fd7d8d1cf..44a539a3e800a6 100644
--- a/test/parallel/test-net-end-close.js
+++ b/test/parallel/test-net-end-close.js
@@ -14,7 +14,7 @@ const s = new net.Socket({
},
writable: false
});
-s.resume();
+assert.strictEqual(s, s.resume());
const events = [];
diff --git a/test/parallel/test-net-server-close.js b/test/parallel/test-net-server-close.js
index bafd1a85e83b40..89bfddd38a70d2 100644
--- a/test/parallel/test-net-server-close.js
+++ b/test/parallel/test-net-server-close.js
@@ -44,7 +44,7 @@ const server = net.createServer(function(c) {
sockets.push(c);
if (sockets.length === 2) {
- server.close();
+ assert.strictEqual(server.close(), server);
sockets.forEach(function(c) { c.destroy(); });
}
});
@@ -53,7 +53,7 @@ server.on('close', function() {
events.push('server');
});
-server.listen(0, function() {
+assert.strictEqual(server, server.listen(0, function() {
net.createConnection(this.address().port);
net.createConnection(this.address().port);
-});
+}));
diff --git a/test/parallel/test-net-socket-local-address.js b/test/parallel/test-net-socket-local-address.js
index e888667eab4c4f..19749bde9552b6 100644
--- a/test/parallel/test-net-socket-local-address.js
+++ b/test/parallel/test-net-socket-local-address.js
@@ -34,7 +34,10 @@ function connect() {
conns++;
client.once('close', connect);
- client.connect(server.address().port, common.localhostIPv4, () => {
- clientLocalPorts.push(client.localPort);
- });
+ assert.strictEqual(
+ client,
+ client.connect(server.address().port, common.localhostIPv4, () => {
+ clientLocalPorts.push(client.localPort);
+ })
+ );
}
diff --git a/test/parallel/test-net-stream.js b/test/parallel/test-net-stream.js
index 15651eff46f950..1eb984936c0199 100644
--- a/test/parallel/test-net-stream.js
+++ b/test/parallel/test-net-stream.js
@@ -61,7 +61,7 @@ const server = net.createServer(function(socket) {
}).listen(0, function() {
const conn = net.connect(this.address().port);
conn.on('data', function(buf) {
- conn.pause();
+ assert.strictEqual(conn, conn.pause());
setTimeout(function() {
conn.destroy();
}, 20);
diff --git a/test/parallel/test-path.js b/test/parallel/test-path.js
index cdf5c4d9f51509..bf2f3ceddf52ea 100644
--- a/test/parallel/test-path.js
+++ b/test/parallel/test-path.js
@@ -28,6 +28,9 @@ const path = require('path');
const f = __filename;
const failures = [];
+const slashRE = /\//g;
+const backslashRE = /\\/g;
+
// path.basename tests
assert.strictEqual(path.basename(f), 'test-path.js');
assert.strictEqual(path.basename(f, '.js'), 'test-path');
@@ -188,7 +191,7 @@ assert.strictEqual(path.win32.dirname('foo'), '.');
let input = test[0];
let os;
if (extname === path.win32.extname) {
- input = input.replace(/\//g, '\\');
+ input = input.replace(slashRE, '\\');
os = 'win32';
} else {
os = 'posix';
@@ -345,7 +348,7 @@ joinTests.forEach((test) => {
let actualAlt;
let os;
if (join === path.win32.join) {
- actualAlt = actual.replace(/\\/g, '/');
+ actualAlt = actual.replace(backslashRE, '/');
os = 'win32';
} else {
os = 'posix';
@@ -451,9 +454,9 @@ resolveTests.forEach((test) => {
let actualAlt;
const os = resolve === path.win32.resolve ? 'win32' : 'posix';
if (resolve === path.win32.resolve && !common.isWindows)
- actualAlt = actual.replace(/\\/g, '/');
+ actualAlt = actual.replace(backslashRE, '/');
else if (resolve !== path.win32.resolve && common.isWindows)
- actualAlt = actual.replace(/\//g, '\\');
+ actualAlt = actual.replace(slashRE, '\\');
const expected = test[1];
const message =
diff --git a/test/parallel/test-process-chdir.js b/test/parallel/test-process-chdir.js
index b137be4611c20d..61707706a322bc 100644
--- a/test/parallel/test-process-chdir.js
+++ b/test/parallel/test-process-chdir.js
@@ -31,9 +31,10 @@ process.chdir('..');
assert.strictEqual(process.cwd().normalize(),
path.resolve(common.tmpDir).normalize());
+const errMessage = /^TypeError: Bad argument\.$/;
assert.throws(function() { process.chdir({}); },
- /^TypeError: Bad argument\.$/, 'Bad argument.');
+ errMessage, 'Bad argument.');
assert.throws(function() { process.chdir(); },
- /^TypeError: Bad argument\.$/, 'Bad argument.');
+ errMessage, 'Bad argument.');
assert.throws(function() { process.chdir('x', 'y'); },
- /^TypeError: Bad argument\.$/, 'Bad argument.');
+ errMessage, 'Bad argument.');
diff --git a/test/parallel/test-process-emitwarning.js b/test/parallel/test-process-emitwarning.js
index 61ca05cfe9a011..d2d090eae339ee 100644
--- a/test/parallel/test-process-emitwarning.js
+++ b/test/parallel/test-process-emitwarning.js
@@ -12,7 +12,7 @@ const testType = 'CustomWarning';
process.on('warning', common.mustCall((warning) => {
assert(warning);
- assert(/^(Warning|CustomWarning)/.test(warning.name));
+ assert(/^(?:Warning|CustomWarning)/.test(warning.name));
assert.strictEqual(warning.message, testMsg);
if (warning.code) assert.strictEqual(warning.code, testCode);
if (warning.detail) assert.strictEqual(warning.detail, testDetail);
diff --git a/test/parallel/test-process-setuid-setgid.js b/test/parallel/test-process-setuid-setgid.js
index 1feb4248d17f7a..e0db8ee00222dd 100644
--- a/test/parallel/test-process-setuid-setgid.js
+++ b/test/parallel/test-process-setuid-setgid.js
@@ -46,12 +46,12 @@ if (process.getuid() !== 0) {
assert.throws(
() => { process.setgid('nobody'); },
- /^Error: (EPERM, .+|setgid group id does not exist)$/
+ /^Error: (?:EPERM, .+|setgid group id does not exist)$/
);
assert.throws(
() => { process.setuid('nobody'); },
- /^Error: (EPERM, .+|setuid user id does not exist)$/
+ /^Error: (?:EPERM, .+|setuid user id does not exist)$/
);
return;
}
diff --git a/test/parallel/test-process-versions.js b/test/parallel/test-process-versions.js
index 4da16379d5b3fe..02eeb93cb1779e 100644
--- a/test/parallel/test-process-versions.js
+++ b/test/parallel/test-process-versions.js
@@ -21,10 +21,13 @@ const actual_keys = Object.keys(process.versions).sort();
assert.deepStrictEqual(actual_keys, expected_keys);
-assert(/^\d+\.\d+\.\d+(-.*)?$/.test(process.versions.ares));
-assert(/^\d+\.\d+\.\d+(-.*)?$/.test(process.versions.http_parser));
-assert(/^\d+\.\d+\.\d+(-.*)?$/.test(process.versions.node));
-assert(/^\d+\.\d+\.\d+(-.*)?$/.test(process.versions.uv));
-assert(/^\d+\.\d+\.\d+(-.*)?$/.test(process.versions.zlib));
-assert(/^\d+\.\d+\.\d+(\.\d+)?( \(candidate\))?$/.test(process.versions.v8));
+const commonTemplate = /^\d+\.\d+\.\d+(?:-.*)?$/;
+
+assert(commonTemplate.test(process.versions.ares));
+assert(commonTemplate.test(process.versions.http_parser));
+assert(commonTemplate.test(process.versions.node));
+assert(commonTemplate.test(process.versions.uv));
+assert(commonTemplate.test(process.versions.zlib));
+
+assert(/^\d+\.\d+\.\d+(?:\.\d+)?(?: \(candidate\))?$/.test(process.versions.v8));
assert(/^\d+$/.test(process.versions.modules));
diff --git a/test/parallel/test-repl.js b/test/parallel/test-repl.js
index 86dd96d55072cb..703300b3334534 100644
--- a/test/parallel/test-repl.js
+++ b/test/parallel/test-repl.js
@@ -95,7 +95,7 @@ function error_test() {
let expect = client_unix.expect;
if (expect === prompt_multiline)
expect = /[.]{3} /;
- assert.ok(read_buffer.match(expect));
+ assert.ok(RegExp(expect).test(read_buffer));
console.error('match');
}
read_buffer = '';
@@ -378,7 +378,7 @@ function error_test() {
expect: /^(?!repl)/ },
// Avoid emitting stack trace
{ client: client_unix, send: 'a = 3.5e',
- expect: /^(?!\s+at\s)/gm },
+ expect: /^(?!\s+at\s)/m },
// https://github.com/nodejs/node/issues/9850
{ client: client_unix, send: 'function* foo() {}; foo().next();',
diff --git a/test/parallel/test-require-json.js b/test/parallel/test-require-json.js
index 2ab86f0fb97c51..45581b186ca311 100644
--- a/test/parallel/test-require-json.js
+++ b/test/parallel/test-require-json.js
@@ -27,7 +27,7 @@ const assert = require('assert');
try {
require(path.join(common.fixturesDir, 'invalid.json'));
} catch (err) {
- const re = /test[/\\]fixtures[/\\]invalid\.json: Unexpected string/;
- const i = err.message.match(re);
- assert.notStrictEqual(null, i, 'require() json error should include path');
+ assert.ok(
+ /test[/\\]fixtures[/\\]invalid\.json: Unexpected string/.test(err.message),
+ 'require() json error should include path');
}
diff --git a/test/parallel/test-socket-address.js b/test/parallel/test-socket-address.js
index 3e05f89f083223..ccffc5300bbe19 100644
--- a/test/parallel/test-socket-address.js
+++ b/test/parallel/test-socket-address.js
@@ -12,6 +12,6 @@ server.listen(0, common.mustCall(function() {
return -1;
};
assert.throws(() => this.address(),
- /^Error: address ([\w|\s-\d])+$/);
+ /^Error: address [\w|\s-\d]+$/);
server.close();
}));
diff --git a/test/parallel/test-stream-objectmode-undefined.js b/test/parallel/test-stream-objectmode-undefined.js
new file mode 100644
index 00000000000000..64b960f92b4995
--- /dev/null
+++ b/test/parallel/test-stream-objectmode-undefined.js
@@ -0,0 +1,44 @@
+'use strict';
+const common = require('../common');
+const assert = require('assert');
+const { Readable, Writable, Transform } = require('stream');
+
+{
+ const stream = new Readable({
+ objectMode: true,
+ read: common.mustCall(() => {
+ stream.push(undefined);
+ stream.push(null);
+ })
+ });
+
+ stream.on('data', common.mustCall((chunk) => {
+ assert.strictEqual(chunk, undefined);
+ }));
+}
+
+{
+ const stream = new Writable({
+ objectMode: true,
+ write: common.mustCall((chunk) => {
+ assert.strictEqual(chunk, undefined);
+ })
+ });
+
+ stream.write(undefined);
+}
+
+{
+ const stream = new Transform({
+ objectMode: true,
+ transform: common.mustCall((chunk) => {
+ stream.push(chunk);
+ })
+ });
+
+ stream.on('data', common.mustCall((chunk) => {
+ assert.strictEqual(chunk, undefined);
+ }));
+
+ stream.write(undefined);
+}
diff --git a/test/parallel/test-stream-pipe-await-drain-push-while-write.js b/test/parallel/test-stream-pipe-await-drain-push-while-write.js
index 67a8f304c31614..adefad70adc20c 100644
--- a/test/parallel/test-stream-pipe-await-drain-push-while-write.js
+++ b/test/parallel/test-stream-pipe-await-drain-push-while-write.js
@@ -17,7 +17,7 @@ const writable = new stream.Writable({
write: common.mustCall(function(chunk, encoding, cb) {
if (chunk.length === 32 * 1024) { // first chunk
const beforePush = readable._readableState.awaitDrain;
- readable.push(new Buffer(34 * 1024)); // above hwm
+ readable.push(Buffer.alloc(34 * 1024)); // above hwm
// We should check if awaitDrain counter is increased.
const afterPush = readable._readableState.awaitDrain;
assert.strictEqual(afterPush - beforePush, 1,
@@ -34,7 +34,7 @@ const writable = new stream.Writable({
});
// A readable stream which produces two buffers.
-const bufs = [new Buffer(32 * 1024), new Buffer(33 * 1024)]; // above hwm
+const bufs = [Buffer.alloc(32 * 1024), Buffer.alloc(33 * 1024)]; // above hwm
const readable = new stream.Readable({
read: function() {
while (bufs.length > 0) {
diff --git a/test/parallel/test-stream-readable-invalid-chunk.js b/test/parallel/test-stream-readable-invalid-chunk.js
index 3db42e18cdc1b6..990154144ab5ed 100644
--- a/test/parallel/test-stream-readable-invalid-chunk.js
+++ b/test/parallel/test-stream-readable-invalid-chunk.js
@@ -8,6 +8,7 @@ const readable = new stream.Readable({
read: common.noop
});
-assert.throws(() => readable.push([]), /Invalid non-string\/buffer chunk/);
-assert.throws(() => readable.push({}), /Invalid non-string\/buffer chunk/);
-assert.throws(() => readable.push(0), /Invalid non-string\/buffer chunk/);
+const errMessage = /Invalid non-string\/buffer chunk/;
+assert.throws(() => readable.push([]), errMessage);
+assert.throws(() => readable.push({}), errMessage);
+assert.throws(() => readable.push(0), errMessage);
diff --git a/test/parallel/test-stream-writable-write-writev-finish.js b/test/parallel/test-stream-writable-write-writev-finish.js
new file mode 100644
index 00000000000000..c4aaa36606c5f4
--- /dev/null
+++ b/test/parallel/test-stream-writable-write-writev-finish.js
@@ -0,0 +1,156 @@
+'use strict';
+
+const common = require('../common');
+const assert = require('assert');
+const stream = require('stream');
+
+// ensure consistency between the finish event when using cork()
+// and writev and when not using them
+
+{
+ const writable = new stream.Writable();
+
+ writable._write = (chunks, encoding, cb) => {
+ cb(new Error('write test error'));
+ };
+
+ let firstError = false;
+ writable.on('finish', common.mustCall(function() {
+ assert.strictEqual(firstError, true);
+ }));
+
+ writable.on('prefinish', common.mustCall());
+
+ writable.on('error', common.mustCall((er) => {
+ assert.strictEqual(er.message, 'write test error');
+ firstError = true;
+ }));
+
+ writable.end('test');
+}
+
+{
+ const writable = new stream.Writable();
+
+ writable._write = (chunks, encoding, cb) => {
+ setImmediate(cb, new Error('write test error'));
+ };
+
+ let firstError = false;
+ writable.on('finish', common.mustCall(function() {
+ assert.strictEqual(firstError, true);
+ }));
+
+ writable.on('prefinish', common.mustCall());
+
+ writable.on('error', common.mustCall((er) => {
+ assert.strictEqual(er.message, 'write test error');
+ firstError = true;
+ }));
+
+ writable.end('test');
+}
+
+{
+ const writable = new stream.Writable();
+
+ writable._write = (chunks, encoding, cb) => {
+ cb(new Error('write test error'));
+ };
+
+ writable._writev = (chunks, cb) => {
+ cb(new Error('writev test error'));
+ };
+
+ let firstError = false;
+ writable.on('finish', common.mustCall(function() {
+ assert.strictEqual(firstError, true);
+ }));
+
+ writable.on('prefinish', common.mustCall());
+
+ writable.on('error', common.mustCall((er) => {
+ assert.strictEqual(er.message, 'writev test error');
+ firstError = true;
+ }));
+
+ writable.cork();
+ writable.write('test');
+
+ setImmediate(function() {
+ writable.end('test');
+ });
+}
+
+{
+ const writable = new stream.Writable();
+
+ writable._write = (chunks, encoding, cb) => {
+ setImmediate(cb, new Error('write test error'));
+ };
+
+ writable._writev = (chunks, cb) => {
+ setImmediate(cb, new Error('writev test error'));
+ };
+
+ let firstError = false;
+ writable.on('finish', common.mustCall(function() {
+ assert.strictEqual(firstError, true);
+ }));
+
+ writable.on('prefinish', common.mustCall());
+
+ writable.on('error', common.mustCall((er) => {
+ assert.strictEqual(er.message, 'writev test error');
+ firstError = true;
+ }));
+
+ writable.cork();
+ writable.write('test');
+
+ setImmediate(function() {
+ writable.end('test');
+ });
+}
+
+// Regression test for
+// https://github.com/nodejs/node/issues/13812
+
+{
+ const rs = new stream.Readable();
+ rs.push('ok');
+ rs.push(null);
+ rs._read = () => {};
+
+ const ws = new stream.Writable();
+ let firstError = false;
+
+ ws.on('finish', common.mustCall(function() {
+ assert.strictEqual(firstError, true);
+ }));
+ ws.on('error', common.mustCall(function() {
+ firstError = true;
+ }));
+
+ ws._write = (chunk, encoding, done) => {
+ setImmediate(done, new Error());
+ };
+ rs.pipe(ws);
+}
+
+{
+ const rs = new stream.Readable();
+ rs.push('ok');
+ rs.push(null);
+ rs._read = () => {};
+
+ const ws = new stream.Writable();
+
+ ws.on('finish', common.mustNotCall());
+ ws.on('error', common.mustCall());
+
+ ws._write = (chunk, encoding, done) => {
+ done(new Error());
+ };
+ rs.pipe(ws);
+}
diff --git a/test/parallel/test-stream-writable-writev-finish.js b/test/parallel/test-stream-writable-writev-finish.js
deleted file mode 100644
index 6f74ca08d2366d..00000000000000
--- a/test/parallel/test-stream-writable-writev-finish.js
+++ /dev/null
@@ -1,53 +0,0 @@
-'use strict';
-
-const common = require('../common');
-const assert = require('assert');
-const stream = require('stream');
-
-// ensure consistency between the finish event when using cork()
-// and writev and when not using them
-
-{
- const writable = new stream.Writable();
-
- writable._write = (chunks, encoding, cb) => {
- cb(new Error('write test error'));
- };
-
- writable.on('finish', common.mustCall());
-
- writable.on('prefinish', common.mustCall());
-
- writable.on('error', common.mustCall((er) => {
- assert.strictEqual(er.message, 'write test error');
- }));
-
- writable.end('test');
-}
-
-{
- const writable = new stream.Writable();
-
- writable._write = (chunks, encoding, cb) => {
- cb(new Error('write test error'));
- };
-
- writable._writev = (chunks, cb) => {
- cb(new Error('writev test error'));
- };
-
- writable.on('finish', common.mustCall());
-
- writable.on('prefinish', common.mustCall());
-
- writable.on('error', common.mustCall((er) => {
- assert.strictEqual(er.message, 'writev test error');
- }));
-
- writable.cork();
- writable.write('test');
-
- setImmediate(function() {
- writable.end('test');
- });
-}
diff --git a/test/parallel/test-stream2-basic.js b/test/parallel/test-stream2-basic.js
index cb017a17065e27..f544321f9b7778 100644
--- a/test/parallel/test-stream2-basic.js
+++ b/test/parallel/test-stream2-basic.js
@@ -87,42 +87,8 @@ TestWriter.prototype.end = function(c) {
this.emit('end', this.received);
};
-////////
-
-// tiny node-tap lookalike.
-const tests = [];
-let count = 0;
-
-function test(name, fn) {
- count++;
- tests.push([name, fn]);
-}
-
-function run() {
- const next = tests.shift();
- if (!next)
- return console.error('ok');
-
- const name = next[0];
- const fn = next[1];
- console.log('# %s', name);
- fn({
- end: function() {
- count--;
- run();
- }
- });
-}
-
-// ensure all tests have run
-process.on('exit', function() {
- assert.strictEqual(count, 0);
-});
-
-process.nextTick(run);
-
-
-test('a most basic test', function(t) {
+{
+ // Test basic functionality
const r = new TestReader(20);
const reads = [];
@@ -143,10 +109,9 @@ test('a most basic test', function(t) {
'xxxxxxxxxxxxxxxxxxxxxxxxx',
'xxxxxxxxxxxxxxxxxxxxx' ];
- r.on('end', function() {
+ r.on('end', common.mustCall(function() {
assert.deepStrictEqual(reads, expect);
- t.end();
- });
+ }));
let readSize = 1;
function flow() {
@@ -158,9 +123,10 @@ test('a most basic test', function(t) {
}
flow();
-});
+}
-test('pipe', function(t) {
+{
+ // Verify pipe
const r = new TestReader(5);
const expect = [ 'xxxxx',
@@ -176,72 +142,64 @@ test('pipe', function(t) {
const w = new TestWriter();
- w.on('end', function(received) {
+ w.on('end', common.mustCall(function(received) {
assert.deepStrictEqual(received, expect);
- t.end();
- });
+ }));
r.pipe(w);
-});
+}
[1, 2, 3, 4, 5, 6, 7, 8, 9].forEach(function(SPLIT) {
- test('unpipe', function(t) {
- const r = new TestReader(5);
+ // Verify unpipe
+ const r = new TestReader(5);
- // unpipe after 3 writes, then write to another stream instead.
- let expect = [ 'xxxxx',
- 'xxxxx',
- 'xxxxx',
- 'xxxxx',
- 'xxxxx',
- 'xxxxx',
- 'xxxxx',
- 'xxxxx',
- 'xxxxx',
- 'xxxxx' ];
- expect = [ expect.slice(0, SPLIT), expect.slice(SPLIT) ];
-
- const w = [ new TestWriter(), new TestWriter() ];
-
- let writes = SPLIT;
- w[0].on('write', function() {
- if (--writes === 0) {
- r.unpipe();
- assert.strictEqual(r._readableState.pipes, null);
- w[0].end();
- r.pipe(w[1]);
- assert.strictEqual(r._readableState.pipes, w[1]);
- }
- });
+ // unpipe after 3 writes, then write to another stream instead.
+ let expect = [ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx' ];
+ expect = [ expect.slice(0, SPLIT), expect.slice(SPLIT) ];
- let ended = 0;
+ const w = [ new TestWriter(), new TestWriter() ];
- let ended0 = false;
- let ended1 = false;
- w[0].on('end', function(results) {
- assert.strictEqual(ended0, false);
- ended0 = true;
- ended++;
- assert.deepStrictEqual(results, expect[0]);
- });
+ let writes = SPLIT;
+ w[0].on('write', function() {
+ if (--writes === 0) {
+ r.unpipe();
+ assert.strictEqual(r._readableState.pipes, null);
+ w[0].end();
+ r.pipe(w[1]);
+ assert.strictEqual(r._readableState.pipes, w[1]);
+ }
+ });
- w[1].on('end', function(results) {
- assert.strictEqual(ended1, false);
- ended1 = true;
- ended++;
- assert.strictEqual(ended, 2);
- assert.deepStrictEqual(results, expect[1]);
- t.end();
- });
+ let ended = 0;
- r.pipe(w[0]);
- });
+ w[0].on('end', common.mustCall(function(results) {
+ ended++;
+ assert.strictEqual(ended, 1);
+ assert.deepStrictEqual(results, expect[0]);
+ }));
+
+ w[1].on('end', common.mustCall(function(results) {
+ ended++;
+ assert.strictEqual(ended, 2);
+ assert.deepStrictEqual(results, expect[1]);
+ }));
+
+ r.pipe(w[0]);
});
-// both writers should get the same exact data.
-test('multipipe', function(t) {
+{
+ // Verify both writers get the same data when piping to destinations
const r = new TestReader(5);
const w = [ new TestWriter(), new TestWriter() ];
@@ -256,69 +214,66 @@ test('multipipe', function(t) {
'xxxxx',
'xxxxx' ];
- let c = 2;
- w[0].on('end', function(received) {
+ w[0].on('end', common.mustCall(function(received) {
assert.deepStrictEqual(received, expect, 'first');
- if (--c === 0) t.end();
- });
- w[1].on('end', function(received) {
+ }));
+ w[1].on('end', common.mustCall(function(received) {
assert.deepStrictEqual(received, expect, 'second');
- if (--c === 0) t.end();
- });
+ }));
r.pipe(w[0]);
r.pipe(w[1]);
-});
+}
[1, 2, 3, 4, 5, 6, 7, 8, 9].forEach(function(SPLIT) {
- test('multi-unpipe', function(t) {
- const r = new TestReader(5);
-
- // unpipe after 3 writes, then write to another stream instead.
- let expect = [ 'xxxxx',
- 'xxxxx',
- 'xxxxx',
- 'xxxxx',
- 'xxxxx',
- 'xxxxx',
- 'xxxxx',
- 'xxxxx',
- 'xxxxx',
- 'xxxxx' ];
- expect = [ expect.slice(0, SPLIT), expect.slice(SPLIT) ];
+ // Verify multi-unpipe
+ const r = new TestReader(5);
- const w = [ new TestWriter(), new TestWriter(), new TestWriter() ];
+ // unpipe after 3 writes, then write to another stream instead.
+ let expect = [ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx',
+ 'xxxxx' ];
+ expect = [ expect.slice(0, SPLIT), expect.slice(SPLIT) ];
+
+ const w = [ new TestWriter(), new TestWriter(), new TestWriter() ];
+
+ let writes = SPLIT;
+ w[0].on('write', function() {
+ if (--writes === 0) {
+ r.unpipe();
+ w[0].end();
+ r.pipe(w[1]);
+ }
+ });
- let writes = SPLIT;
- w[0].on('write', function() {
- if (--writes === 0) {
- r.unpipe();
- w[0].end();
- r.pipe(w[1]);
- }
- });
+ let ended = 0;
- let ended = 0;
+ w[0].on('end', common.mustCall(function(results) {
+ ended++;
+ assert.strictEqual(ended, 1);
+ assert.deepStrictEqual(results, expect[0]);
+ }));
- w[0].on('end', function(results) {
- ended++;
- assert.deepStrictEqual(results, expect[0]);
- });
+ w[1].on('end', common.mustCall(function(results) {
+ ended++;
+ assert.strictEqual(ended, 2);
+ assert.deepStrictEqual(results, expect[1]);
+ }));
- w[1].on('end', function(results) {
- ended++;
- assert.strictEqual(ended, 2);
- assert.deepStrictEqual(results, expect[1]);
- t.end();
- });
-
- r.pipe(w[0]);
- r.pipe(w[2]);
- });
+ r.pipe(w[0]);
+ r.pipe(w[2]);
});
-test('back pressure respected', function(t) {
+{
+ // Verify that back pressure is respected
const r = new R({ objectMode: true });
r._read = common.mustNotCall();
let counter = 0;
@@ -330,7 +285,6 @@ test('back pressure respected', function(t) {
const w1 = new R();
w1.write = function(chunk) {
- console.error('w1.emit("close")');
assert.strictEqual(chunk[0], 'one');
w1.emit('close');
process.nextTick(function() {
@@ -346,7 +300,6 @@ test('back pressure respected', function(t) {
const w2 = new R();
w2.write = function(chunk) {
- console.error('w2 write', chunk, counter);
assert.strictEqual(chunk[0], expected.shift());
assert.strictEqual(counter, 0);
@@ -358,7 +311,6 @@ test('back pressure respected', function(t) {
setTimeout(function() {
counter--;
- console.error('w2 drain');
w2.emit('drain');
}, 10);
@@ -368,7 +320,6 @@ test('back pressure respected', function(t) {
const w3 = new R();
w3.write = function(chunk) {
- console.error('w3 write', chunk, counter);
assert.strictEqual(chunk[0], expected.shift());
assert.strictEqual(counter, 1);
@@ -380,20 +331,19 @@ test('back pressure respected', function(t) {
setTimeout(function() {
counter--;
- console.error('w3 drain');
w3.emit('drain');
}, 50);
return false;
};
- w3.end = function() {
+ w3.end = common.mustCall(function() {
assert.strictEqual(counter, 2);
assert.strictEqual(expected.length, 0);
- t.end();
- };
-});
+ });
+}
-test('read(0) for ended streams', function(t) {
+{
+ // Verify read(0) behavior for ended streams
const r = new R();
let written = false;
let ended = false;
@@ -414,16 +364,16 @@ test('read(0) for ended streams', function(t) {
assert.strictEqual(buffer.toString(), 'foo');
};
- w.end = function() {
+ w.end = common.mustCall(function() {
ended = true;
assert.strictEqual(written, true);
- t.end();
- };
+ });
r.pipe(w);
-});
+}
-test('sync _read ending', function(t) {
+{
+ // Verify synchronous _read ending
const r = new R();
let called = false;
r._read = function(n) {
@@ -431,6 +381,7 @@ test('sync _read ending', function(t) {
};
r.once('end', function() {
+ // Verify that this is called before the next tick
called = true;
});
@@ -438,11 +389,11 @@ test('sync _read ending', function(t) {
process.nextTick(function() {
assert.strictEqual(called, true);
- t.end();
});
-});
+}
-test('adding readable triggers data flow', function(t) {
+{
+ // Verify that adding readable listeners trigger data flow
const r = new R({ highWaterMark: 5 });
let onReadable = false;
let readCalled = 0;
@@ -459,17 +410,16 @@ test('adding readable triggers data flow', function(t) {
r.read();
});
- r.on('end', function() {
+ r.on('end', common.mustCall(function() {
assert.strictEqual(readCalled, 3);
assert.ok(onReadable);
- t.end();
- });
-});
+ }));
+}
-test('chainable', function(t) {
+{
+ // Verify that streams are chainable
const r = new R();
r._read = common.mustCall();
const r2 = r.setEncoding('utf8').pause().resume().pause();
assert.strictEqual(r, r2);
- t.end();
-});
+}
diff --git a/test/parallel/test-stream2-decode-partial.js b/test/parallel/test-stream2-decode-partial.js
index b43101dbc84c3a..9b1baf7fd677f4 100644
--- a/test/parallel/test-stream2-decode-partial.js
+++ b/test/parallel/test-stream2-decode-partial.js
@@ -4,8 +4,8 @@ const Readable = require('_stream_readable');
const assert = require('assert');
let buf = '';
-const euro = new Buffer([0xE2, 0x82, 0xAC]);
-const cent = new Buffer([0xC2, 0xA2]);
+const euro = Buffer.from([0xE2, 0x82, 0xAC]);
+const cent = Buffer.from([0xC2, 0xA2]);
const source = Buffer.concat([euro, cent]);
const readable = Readable({ encoding: 'utf8' });
diff --git a/test/parallel/test-stream2-objects.js b/test/parallel/test-stream2-objects.js
index 6894d4b9171411..901f946a931944 100644
--- a/test/parallel/test-stream2-objects.js
+++ b/test/parallel/test-stream2-objects.js
@@ -26,40 +26,6 @@ const Readable = require('_stream_readable');
const Writable = require('_stream_writable');
const assert = require('assert');
-// tiny node-tap lookalike.
-const tests = [];
-let count = 0;
-
-function test(name, fn) {
- count++;
- tests.push([name, fn]);
-}
-
-function run() {
- const next = tests.shift();
- if (!next)
- return console.error('ok');
-
- const name = next[0];
- const fn = next[1];
- console.log('# %s', name);
- fn({
- same: assert.deepStrictEqual,
- equal: assert.strictEqual,
- end: function() {
- count--;
- run();
- }
- });
-}
-
-// ensure all tests have run
-process.on('exit', function() {
- assert.strictEqual(count, 0);
-});
-
-process.nextTick(run);
-
function toArray(callback) {
const stream = new Writable({ objectMode: true });
const list = [];
@@ -67,9 +33,9 @@ function toArray(callback) {
list.push(chunk);
};
- stream.end = function() {
+ stream.end = common.mustCall(function() {
callback(list);
- };
+ });
return stream;
}
@@ -85,7 +51,8 @@ function fromArray(list) {
return r;
}
-test('can read objects from stream', function(t) {
+{
+ // Verify that objects can be read from the stream
const r = fromArray([{ one: '1'}, { two: '2' }]);
const v1 = r.read();
@@ -95,34 +62,30 @@ test('can read objects from stream', function(t) {
assert.deepStrictEqual(v1, { one: '1' });
assert.deepStrictEqual(v2, { two: '2' });
assert.deepStrictEqual(v3, null);
+}
- t.end();
-});
-
-test('can pipe objects into stream', function(t) {
+{
+ // Verify that objects can be piped into the stream
const r = fromArray([{ one: '1'}, { two: '2' }]);
- r.pipe(toArray(function(list) {
+ r.pipe(toArray(common.mustCall(function(list) {
assert.deepStrictEqual(list, [
{ one: '1' },
{ two: '2' }
]);
+ })));
+}
- t.end();
- }));
-});
-
-test('read(n) is ignored', function(t) {
+{
+ // Verify that read(n) is ignored
const r = fromArray([{ one: '1'}, { two: '2' }]);
-
const value = r.read(2);
assert.deepStrictEqual(value, { one: '1' });
+}
- t.end();
-});
-
-test('can read objects from _read (sync)', function(t) {
+{
+ // Verify that objects can be synchronously read
const r = new Readable({ objectMode: true });
const list = [{ one: '1'}, { two: '2' }];
r._read = function(n) {
@@ -130,17 +93,16 @@ test('can read objects from _read (sync)', function(t) {
r.push(item || null);
};
- r.pipe(toArray(function(list) {
+ r.pipe(toArray(common.mustCall(function(list) {
assert.deepStrictEqual(list, [
{ one: '1' },
{ two: '2' }
]);
+ })));
+}
- t.end();
- }));
-});
-
-test('can read objects from _read (async)', function(t) {
+{
+ // Verify that objects can be asynchronously read
const r = new Readable({ objectMode: true });
const list = [{ one: '1'}, { two: '2' }];
r._read = function(n) {
@@ -150,17 +112,16 @@ test('can read objects from _read (async)', function(t) {
});
};
- r.pipe(toArray(function(list) {
+ r.pipe(toArray(common.mustCall(function(list) {
assert.deepStrictEqual(list, [
{ one: '1' },
{ two: '2' }
]);
+ })));
+}
- t.end();
- }));
-});
-
-test('can read strings as objects', function(t) {
+{
+ // Verify that strings can be read as objects
const r = new Readable({
objectMode: true
});
@@ -171,14 +132,13 @@ test('can read strings as objects', function(t) {
});
r.push(null);
- r.pipe(toArray(function(array) {
+ r.pipe(toArray(common.mustCall(function(array) {
assert.deepStrictEqual(array, list);
+ })));
+}
- t.end();
- }));
-});
-
-test('read(0) for object streams', function(t) {
+{
+ // Verify read(0) behavior for object streams
const r = new Readable({
objectMode: true
});
@@ -187,14 +147,13 @@ test('read(0) for object streams', function(t) {
r.push('foobar');
r.push(null);
- r.pipe(toArray(function(array) {
+ r.pipe(toArray(common.mustCall(function(array) {
assert.deepStrictEqual(array, ['foobar']);
+ })));
+}
- t.end();
- }));
-});
-
-test('falsey values', function(t) {
+{
+ // Verify the behavior of pushing falsey values
const r = new Readable({
objectMode: true
});
@@ -205,14 +164,13 @@ test('falsey values', function(t) {
r.push('');
r.push(null);
- r.pipe(toArray(function(array) {
+ r.pipe(toArray(common.mustCall(function(array) {
assert.deepStrictEqual(array, [false, 0, '']);
+ })));
+}
- t.end();
- }));
-});
-
-test('high watermark _read', function(t) {
+{
+ // Verify high watermark _read() behavior
const r = new Readable({
highWaterMark: 6,
objectMode: true
@@ -240,11 +198,10 @@ test('high watermark _read', function(t) {
assert.strictEqual(v3, '3');
assert.strictEqual(calls, 1);
+}
- t.end();
-});
-
-test('high watermark push', function(t) {
+{
+ // Verify high watermark push behavior
const r = new Readable({
highWaterMark: 6,
objectMode: true
@@ -254,11 +211,10 @@ test('high watermark push', function(t) {
const bool = r.push(i);
assert.strictEqual(bool, i !== 5);
}
+}
- t.end();
-});
-
-test('can write objects to stream', function(t) {
+{
+ // Verify that objects can be written to stream
const w = new Writable({ objectMode: true });
w._write = function(chunk, encoding, cb) {
@@ -266,15 +222,13 @@ test('can write objects to stream', function(t) {
cb();
};
- w.on('finish', function() {
- t.end();
- });
-
+ w.on('finish', common.mustCall());
w.write({ foo: 'bar' });
w.end();
-});
+}
-test('can write multiple objects to stream', function(t) {
+{
+ // Verify that multiple objects can be written to stream
const w = new Writable({ objectMode: true });
const list = [];
@@ -283,11 +237,9 @@ test('can write multiple objects to stream', function(t) {
cb();
};
- w.on('finish', function() {
+ w.on('finish', common.mustCall(function() {
assert.deepStrictEqual(list, [0, 1, 2, 3, 4]);
-
- t.end();
- });
+ }));
w.write(0);
w.write(1);
@@ -295,9 +247,10 @@ test('can write multiple objects to stream', function(t) {
w.write(3);
w.write(4);
w.end();
-});
+}
-test('can write strings as objects', function(t) {
+{
+ // Verify that strings can be written as objects
const w = new Writable({
objectMode: true
});
@@ -308,11 +261,9 @@ test('can write strings as objects', function(t) {
process.nextTick(cb);
};
- w.on('finish', function() {
+ w.on('finish', common.mustCall(function() {
assert.deepStrictEqual(list, ['0', '1', '2', '3', '4']);
-
- t.end();
- });
+ }));
w.write('0');
w.write('1');
@@ -320,9 +271,10 @@ test('can write strings as objects', function(t) {
w.write('3');
w.write('4');
w.end();
-});
+}
-test('buffers finish until cb is called', function(t) {
+{
+ // Verify that stream buffers finish until callback is called
const w = new Writable({
objectMode: true
});
@@ -337,12 +289,10 @@ test('buffers finish until cb is called', function(t) {
});
};
- w.on('finish', function() {
+ w.on('finish', common.mustCall(function() {
assert.strictEqual(called, true);
-
- t.end();
- });
+ }));
w.write('foo');
w.end();
-});
+}
diff --git a/test/parallel/test-stream2-readable-from-list.js b/test/parallel/test-stream2-readable-from-list.js
index 6f677ce8a4155c..965f962638d586 100644
--- a/test/parallel/test-stream2-readable-from-list.js
+++ b/test/parallel/test-stream2-readable-from-list.js
@@ -26,33 +26,6 @@ const assert = require('assert');
const fromList = require('_stream_readable')._fromList;
const BufferList = require('internal/streams/BufferList');
-// tiny node-tap lookalike.
-const tests = [];
-let count = 0;
-
-function test(name, fn) {
- count++;
- tests.push([name, fn]);
-}
-
-function run() {
- const next = tests.shift();
- if (!next)
- return console.error('ok');
-
- const name = next[0];
- const fn = next[1];
- console.log('# %s', name);
- fn({
- same: assert.deepStrictEqual,
- equal: assert.strictEqual,
- end: function() {
- count--;
- run();
- }
- });
-}
-
function bufferListFromArray(arr) {
const bl = new BufferList();
for (let i = 0; i < arr.length; ++i)
@@ -60,15 +33,8 @@ function bufferListFromArray(arr) {
return bl;
}
-// ensure all tests have run
-process.on('exit', function() {
- assert.strictEqual(count, 0);
-});
-
-process.nextTick(run);
-
-
-test('buffers', function(t) {
+{
+ // Verify behavior with buffers
let list = [ Buffer.from('foog'),
Buffer.from('bark'),
Buffer.from('bazy'),
@@ -77,27 +43,26 @@ test('buffers', function(t) {
// read more than the first element.
let ret = fromList(6, { buffer: list, length: 16 });
- t.equal(ret.toString(), 'foogba');
+ assert.strictEqual(ret.toString(), 'foogba');
// read exactly the first element.
ret = fromList(2, { buffer: list, length: 10 });
- t.equal(ret.toString(), 'rk');
+ assert.strictEqual(ret.toString(), 'rk');
// read less than the first element.
ret = fromList(2, { buffer: list, length: 8 });
- t.equal(ret.toString(), 'ba');
+ assert.strictEqual(ret.toString(), 'ba');
// read more than we have.
ret = fromList(100, { buffer: list, length: 6 });
- t.equal(ret.toString(), 'zykuel');
+ assert.strictEqual(ret.toString(), 'zykuel');
// all consumed.
- t.same(list, new BufferList());
-
- t.end();
-});
+ assert.deepStrictEqual(list, new BufferList());
+}
-test('strings', function(t) {
+{
+ // Verify behavior with strings
let list = [ 'foog',
'bark',
'bazy',
@@ -106,22 +71,20 @@ test('strings', function(t) {
// read more than the first element.
let ret = fromList(6, { buffer: list, length: 16, decoder: true });
- t.equal(ret, 'foogba');
+ assert.strictEqual(ret, 'foogba');
// read exactly the first element.
ret = fromList(2, { buffer: list, length: 10, decoder: true });
- t.equal(ret, 'rk');
+ assert.strictEqual(ret, 'rk');
// read less than the first element.
ret = fromList(2, { buffer: list, length: 8, decoder: true });
- t.equal(ret, 'ba');
+ assert.strictEqual(ret, 'ba');
// read more than we have.
ret = fromList(100, { buffer: list, length: 6, decoder: true });
- t.equal(ret, 'zykuel');
+ assert.strictEqual(ret, 'zykuel');
// all consumed.
- t.same(list, new BufferList());
-
- t.end();
-});
+ assert.deepStrictEqual(list, new BufferList());
+}
diff --git a/test/parallel/test-stream2-set-encoding.js b/test/parallel/test-stream2-set-encoding.js
index 08d9298c6d2138..5b2e35fd01f642 100644
--- a/test/parallel/test-stream2-set-encoding.js
+++ b/test/parallel/test-stream2-set-encoding.js
@@ -20,47 +20,11 @@
// USE OR OTHER DEALINGS IN THE SOFTWARE.
'use strict';
-require('../common');
+const common = require('../common');
const assert = require('assert');
const R = require('_stream_readable');
const util = require('util');
-// tiny node-tap lookalike.
-const tests = [];
-let count = 0;
-
-function test(name, fn) {
- count++;
- tests.push([name, fn]);
-}
-
-function run() {
- const next = tests.shift();
- if (!next)
- return console.error('ok');
-
- const name = next[0];
- const fn = next[1];
- console.log('# %s', name);
- fn({
- same: assert.deepStrictEqual,
- equal: assert.strictEqual,
- end: function() {
- count--;
- run();
- }
- });
-}
-
-// ensure all tests have run
-process.on('exit', function() {
- assert.strictEqual(count, 0);
-});
-
-process.nextTick(run);
-
-/////
-
util.inherits(TestReader, R);
function TestReader(n, opts) {
@@ -89,13 +53,12 @@ TestReader.prototype._read = function(n) {
this.pos += n;
const ret = Buffer.alloc(n, 'a');
- console.log('this.push(ret)', ret);
-
return this.push(ret);
}.bind(this), 1);
};
-test('setEncoding utf8', function(t) {
+{
+ // Verify utf8 encoding
const tr = new TestReader(100);
tr.setEncoding('utf8');
const out = [];
@@ -117,14 +80,14 @@ test('setEncoding utf8', function(t) {
out.push(chunk);
});
- tr.on('end', function() {
- t.same(out, expect);
- t.end();
- });
-});
+ tr.on('end', common.mustCall(function() {
+ assert.deepStrictEqual(out, expect);
+ }));
+}
-test('setEncoding hex', function(t) {
+{
+ // Verify hex encoding
const tr = new TestReader(100);
tr.setEncoding('hex');
const out = [];
@@ -156,13 +119,13 @@ test('setEncoding hex', function(t) {
out.push(chunk);
});
- tr.on('end', function() {
- t.same(out, expect);
- t.end();
- });
-});
+ tr.on('end', common.mustCall(function() {
+ assert.deepStrictEqual(out, expect);
+ }));
+}
-test('setEncoding hex with read(13)', function(t) {
+{
+ // Verify hex encoding with read(13)
const tr = new TestReader(100);
tr.setEncoding('hex');
const out = [];
@@ -185,20 +148,18 @@ test('setEncoding hex with read(13)', function(t) {
'16161' ];
tr.on('readable', function flow() {
- console.log('readable once');
let chunk;
while (null !== (chunk = tr.read(13)))
out.push(chunk);
});
- tr.on('end', function() {
- console.log('END');
- t.same(out, expect);
- t.end();
- });
-});
+ tr.on('end', common.mustCall(function() {
+ assert.deepStrictEqual(out, expect);
+ }));
+}
-test('setEncoding base64', function(t) {
+{
+ // Verify base64 encoding
const tr = new TestReader(100);
tr.setEncoding('base64');
const out = [];
@@ -224,13 +185,13 @@ test('setEncoding base64', function(t) {
out.push(chunk);
});
- tr.on('end', function() {
- t.same(out, expect);
- t.end();
- });
-});
+ tr.on('end', common.mustCall(function() {
+ assert.deepStrictEqual(out, expect);
+ }));
+}
-test('encoding: utf8', function(t) {
+{
+ // Verify utf8 encoding
const tr = new TestReader(100, { encoding: 'utf8' });
const out = [];
const expect =
@@ -251,14 +212,14 @@ test('encoding: utf8', function(t) {
out.push(chunk);
});
- tr.on('end', function() {
- t.same(out, expect);
- t.end();
- });
-});
+ tr.on('end', common.mustCall(function() {
+ assert.deepStrictEqual(out, expect);
+ }));
+}
-test('encoding: hex', function(t) {
+{
+ // Verify hex encoding
const tr = new TestReader(100, { encoding: 'hex' });
const out = [];
const expect =
@@ -289,13 +250,13 @@ test('encoding: hex', function(t) {
out.push(chunk);
});
- tr.on('end', function() {
- t.same(out, expect);
- t.end();
- });
-});
+ tr.on('end', common.mustCall(function() {
+ assert.deepStrictEqual(out, expect);
+ }));
+}
-test('encoding: hex with read(13)', function(t) {
+{
+ // Verify hex encoding with read(13)
const tr = new TestReader(100, { encoding: 'hex' });
const out = [];
const expect =
@@ -322,13 +283,13 @@ test('encoding: hex with read(13)', function(t) {
out.push(chunk);
});
- tr.on('end', function() {
- t.same(out, expect);
- t.end();
- });
-});
+ tr.on('end', common.mustCall(function() {
+ assert.deepStrictEqual(out, expect);
+ }));
+}
-test('encoding: base64', function(t) {
+{
+ // Verify base64 encoding
const tr = new TestReader(100, { encoding: 'base64' });
const out = [];
const expect =
@@ -353,14 +314,13 @@ test('encoding: base64', function(t) {
out.push(chunk);
});
- tr.on('end', function() {
- t.same(out, expect);
- t.end();
- });
-});
+ tr.on('end', common.mustCall(function() {
+ assert.deepStrictEqual(out, expect);
+ }));
+}
-test('chainable', function(t) {
+{
+ // Verify chaining behavior
const tr = new TestReader(100);
- t.equal(tr.setEncoding('utf8'), tr);
- t.end();
-});
+ assert.deepStrictEqual(tr.setEncoding('utf8'), tr);
+}
diff --git a/test/parallel/test-stream2-transform.js b/test/parallel/test-stream2-transform.js
index f9cbfa8d26df08..6b5593d93be9ef 100644
--- a/test/parallel/test-stream2-transform.js
+++ b/test/parallel/test-stream2-transform.js
@@ -20,49 +20,13 @@
// USE OR OTHER DEALINGS IN THE SOFTWARE.
'use strict';
-require('../common');
+const common = require('../common');
const assert = require('assert');
const PassThrough = require('_stream_passthrough');
const Transform = require('_stream_transform');
-// tiny node-tap lookalike.
-const tests = [];
-let count = 0;
-
-function test(name, fn) {
- count++;
- tests.push([name, fn]);
-}
-
-function run() {
- const next = tests.shift();
- if (!next)
- return console.error('ok');
-
- const name = next[0];
- const fn = next[1];
- console.log('# %s', name);
- fn({
- same: assert.deepStrictEqual,
- equal: assert.strictEqual,
- ok: assert,
- end: function() {
- count--;
- run();
- }
- });
-}
-
-// ensure all tests have run
-process.on('exit', function() {
- assert.strictEqual(count, 0);
-});
-
-process.nextTick(run);
-
-/////
-
-test('writable side consumption', function(t) {
+{
+ // Verify writable side consumption
const tx = new Transform({
highWaterMark: 10
});
@@ -79,17 +43,16 @@ test('writable side consumption', function(t) {
}
tx.end();
- t.equal(tx._readableState.length, 10);
- t.equal(transformed, 10);
- t.equal(tx._transformState.writechunk.length, 5);
- t.same(tx._writableState.getBuffer().map(function(c) {
+ assert.strictEqual(tx._readableState.length, 10);
+ assert.strictEqual(transformed, 10);
+ assert.strictEqual(tx._transformState.writechunk.length, 5);
+ assert.deepStrictEqual(tx._writableState.getBuffer().map(function(c) {
return c.chunk.length;
}), [6, 7, 8, 9, 10]);
+}
- t.end();
-});
-
-test('passthrough', function(t) {
+{
+ // Verify passthrough behavior
const pt = new PassThrough();
pt.write(Buffer.from('foog'));
@@ -98,14 +61,14 @@ test('passthrough', function(t) {
pt.write(Buffer.from('kuel'));
pt.end();
- t.equal(pt.read(5).toString(), 'foogb');
- t.equal(pt.read(5).toString(), 'arkba');
- t.equal(pt.read(5).toString(), 'zykue');
- t.equal(pt.read(5).toString(), 'l');
- t.end();
-});
+ assert.strictEqual(pt.read(5).toString(), 'foogb');
+ assert.strictEqual(pt.read(5).toString(), 'arkba');
+ assert.strictEqual(pt.read(5).toString(), 'zykue');
+ assert.strictEqual(pt.read(5).toString(), 'l');
+}
-test('object passthrough', function(t) {
+{
+ // Verify object passthrough behavior
const pt = new PassThrough({ objectMode: true });
pt.write(1);
@@ -117,25 +80,24 @@ test('object passthrough', function(t) {
pt.write({ a: 'b'});
pt.end();
- t.equal(pt.read(), 1);
- t.equal(pt.read(), true);
- t.equal(pt.read(), false);
- t.equal(pt.read(), 0);
- t.equal(pt.read(), 'foo');
- t.equal(pt.read(), '');
- t.same(pt.read(), { a: 'b'});
- t.end();
-});
-
-test('passthrough constructor', function(t) {
+ assert.strictEqual(pt.read(), 1);
+ assert.strictEqual(pt.read(), true);
+ assert.strictEqual(pt.read(), false);
+ assert.strictEqual(pt.read(), 0);
+ assert.strictEqual(pt.read(), 'foo');
+ assert.strictEqual(pt.read(), '');
+ assert.deepStrictEqual(pt.read(), { a: 'b'});
+}
+
+{
+ // Verify passthrough constructor behavior
const pt = PassThrough();
assert(pt instanceof PassThrough);
+}
- t.end();
-});
-
-test('simple transform', function(t) {
+{
+ // Perform a simple transform
const pt = new Transform();
pt._transform = function(c, e, cb) {
const ret = Buffer.alloc(c.length, 'x');
@@ -149,14 +111,14 @@ test('simple transform', function(t) {
pt.write(Buffer.from('kuel'));
pt.end();
- t.equal(pt.read(5).toString(), 'xxxxx');
- t.equal(pt.read(5).toString(), 'xxxxx');
- t.equal(pt.read(5).toString(), 'xxxxx');
- t.equal(pt.read(5).toString(), 'x');
- t.end();
-});
+ assert.strictEqual(pt.read(5).toString(), 'xxxxx');
+ assert.strictEqual(pt.read(5).toString(), 'xxxxx');
+ assert.strictEqual(pt.read(5).toString(), 'xxxxx');
+ assert.strictEqual(pt.read(5).toString(), 'x');
+}
-test('simple object transform', function(t) {
+{
+ // Verify simple object transform
const pt = new Transform({ objectMode: true });
pt._transform = function(c, e, cb) {
pt.push(JSON.stringify(c));
@@ -172,17 +134,17 @@ test('simple object transform', function(t) {
pt.write({ a: 'b'});
pt.end();
- t.equal(pt.read(), '1');
- t.equal(pt.read(), 'true');
- t.equal(pt.read(), 'false');
- t.equal(pt.read(), '0');
- t.equal(pt.read(), '"foo"');
- t.equal(pt.read(), '""');
- t.equal(pt.read(), '{"a":"b"}');
- t.end();
-});
-
-test('async passthrough', function(t) {
+ assert.strictEqual(pt.read(), '1');
+ assert.strictEqual(pt.read(), 'true');
+ assert.strictEqual(pt.read(), 'false');
+ assert.strictEqual(pt.read(), '0');
+ assert.strictEqual(pt.read(), '"foo"');
+ assert.strictEqual(pt.read(), '""');
+ assert.strictEqual(pt.read(), '{"a":"b"}');
+}
+
+{
+ // Verify async passthrough
const pt = new Transform();
pt._transform = function(chunk, encoding, cb) {
setTimeout(function() {
@@ -197,16 +159,16 @@ test('async passthrough', function(t) {
pt.write(Buffer.from('kuel'));
pt.end();
- pt.on('finish', function() {
- t.equal(pt.read(5).toString(), 'foogb');
- t.equal(pt.read(5).toString(), 'arkba');
- t.equal(pt.read(5).toString(), 'zykue');
- t.equal(pt.read(5).toString(), 'l');
- t.end();
- });
-});
+ pt.on('finish', common.mustCall(function() {
+ assert.strictEqual(pt.read(5).toString(), 'foogb');
+ assert.strictEqual(pt.read(5).toString(), 'arkba');
+ assert.strictEqual(pt.read(5).toString(), 'zykue');
+ assert.strictEqual(pt.read(5).toString(), 'l');
+ }));
+}
-test('assymetric transform (expand)', function(t) {
+{
+ // Verify assymetric transform (expand)
const pt = new Transform();
// emit each chunk 2 times.
@@ -226,19 +188,19 @@ test('assymetric transform (expand)', function(t) {
pt.write(Buffer.from('kuel'));
pt.end();
- pt.on('finish', function() {
- t.equal(pt.read(5).toString(), 'foogf');
- t.equal(pt.read(5).toString(), 'oogba');
- t.equal(pt.read(5).toString(), 'rkbar');
- t.equal(pt.read(5).toString(), 'kbazy');
- t.equal(pt.read(5).toString(), 'bazyk');
- t.equal(pt.read(5).toString(), 'uelku');
- t.equal(pt.read(5).toString(), 'el');
- t.end();
- });
-});
+ pt.on('finish', common.mustCall(function() {
+ assert.strictEqual(pt.read(5).toString(), 'foogf');
+ assert.strictEqual(pt.read(5).toString(), 'oogba');
+ assert.strictEqual(pt.read(5).toString(), 'rkbar');
+ assert.strictEqual(pt.read(5).toString(), 'kbazy');
+ assert.strictEqual(pt.read(5).toString(), 'bazyk');
+ assert.strictEqual(pt.read(5).toString(), 'uelku');
+ assert.strictEqual(pt.read(5).toString(), 'el');
+ }));
+}
-test('assymetric transform (compress)', function(t) {
+{
+ // Verify assymetric trasform (compress)
const pt = new Transform();
// each output is the first char of 3 consecutive chunks,
@@ -283,17 +245,17 @@ test('assymetric transform (compress)', function(t) {
pt.end();
// 'abcdeabcdeabcd'
- pt.on('finish', function() {
- t.equal(pt.read(5).toString(), 'abcde');
- t.equal(pt.read(5).toString(), 'abcde');
- t.equal(pt.read(5).toString(), 'abcd');
- t.end();
- });
-});
+ pt.on('finish', common.mustCall(function() {
+ assert.strictEqual(pt.read(5).toString(), 'abcde');
+ assert.strictEqual(pt.read(5).toString(), 'abcde');
+ assert.strictEqual(pt.read(5).toString(), 'abcd');
+ }));
+}
// this tests for a stall when data is written to a full stream
// that has empty transforms.
-test('complex transform', function(t) {
+{
+ // Verify compex transform behavior
let count = 0;
let saved = null;
const pt = new Transform({highWaterMark: 3});
@@ -314,118 +276,96 @@ test('complex transform', function(t) {
pt.once('readable', function() {
process.nextTick(function() {
pt.write(Buffer.from('d'));
- pt.write(Buffer.from('ef'), function() {
+ pt.write(Buffer.from('ef'), common.mustCall(function() {
pt.end();
- t.end();
- });
- t.equal(pt.read().toString(), 'abcdef');
- t.equal(pt.read(), null);
+ }));
+ assert.strictEqual(pt.read().toString(), 'abcdef');
+ assert.strictEqual(pt.read(), null);
});
});
pt.write(Buffer.from('abc'));
-});
+}
-test('passthrough event emission', function(t) {
+{
+ // Verify passthrough event emission
const pt = new PassThrough();
let emits = 0;
pt.on('readable', function() {
- console.error('>>> emit readable %d', emits);
emits++;
});
pt.write(Buffer.from('foog'));
-
- console.error('need emit 0');
pt.write(Buffer.from('bark'));
- console.error('should have emitted readable now 1 === %d', emits);
- t.equal(emits, 1);
-
- t.equal(pt.read(5).toString(), 'foogb');
- t.equal(String(pt.read(5)), 'null');
-
- console.error('need emit 1');
+ assert.strictEqual(emits, 1);
+ assert.strictEqual(pt.read(5).toString(), 'foogb');
+ assert.strictEqual(String(pt.read(5)), 'null');
pt.write(Buffer.from('bazy'));
- console.error('should have emitted, but not again');
pt.write(Buffer.from('kuel'));
- console.error('should have emitted readable now 2 === %d', emits);
- t.equal(emits, 2);
-
- t.equal(pt.read(5).toString(), 'arkba');
- t.equal(pt.read(5).toString(), 'zykue');
- t.equal(pt.read(5), null);
-
- console.error('need emit 2');
+ assert.strictEqual(emits, 2);
+ assert.strictEqual(pt.read(5).toString(), 'arkba');
+ assert.strictEqual(pt.read(5).toString(), 'zykue');
+ assert.strictEqual(pt.read(5), null);
pt.end();
- t.equal(emits, 3);
+ assert.strictEqual(emits, 3);
+ assert.strictEqual(pt.read(5).toString(), 'l');
+ assert.strictEqual(pt.read(5), null);
- t.equal(pt.read(5).toString(), 'l');
- t.equal(pt.read(5), null);
-
- console.error('should not have emitted again');
- t.equal(emits, 3);
- t.end();
-});
+ assert.strictEqual(emits, 3);
+}
-test('passthrough event emission reordered', function(t) {
+{
+ // Verify passthrough event emission reordering
const pt = new PassThrough();
let emits = 0;
pt.on('readable', function() {
- console.error('emit readable', emits);
emits++;
});
pt.write(Buffer.from('foog'));
- console.error('need emit 0');
pt.write(Buffer.from('bark'));
- console.error('should have emitted readable now 1 === %d', emits);
- t.equal(emits, 1);
- t.equal(pt.read(5).toString(), 'foogb');
- t.equal(pt.read(5), null);
-
- console.error('need emit 1');
- pt.once('readable', function() {
- t.equal(pt.read(5).toString(), 'arkba');
-
- t.equal(pt.read(5), null);
-
- console.error('need emit 2');
- pt.once('readable', function() {
- t.equal(pt.read(5).toString(), 'zykue');
- t.equal(pt.read(5), null);
- pt.once('readable', function() {
- t.equal(pt.read(5).toString(), 'l');
- t.equal(pt.read(5), null);
- t.equal(emits, 4);
- t.end();
- });
+ assert.strictEqual(emits, 1);
+ assert.strictEqual(pt.read(5).toString(), 'foogb');
+ assert.strictEqual(pt.read(5), null);
+
+ pt.once('readable', common.mustCall(function() {
+ assert.strictEqual(pt.read(5).toString(), 'arkba');
+ assert.strictEqual(pt.read(5), null);
+
+ pt.once('readable', common.mustCall(function() {
+ assert.strictEqual(pt.read(5).toString(), 'zykue');
+ assert.strictEqual(pt.read(5), null);
+ pt.once('readable', common.mustCall(function() {
+ assert.strictEqual(pt.read(5).toString(), 'l');
+ assert.strictEqual(pt.read(5), null);
+ assert.strictEqual(emits, 4);
+ }));
pt.end();
- });
+ }));
pt.write(Buffer.from('kuel'));
- });
+ }));
pt.write(Buffer.from('bazy'));
-});
+}
-test('passthrough facaded', function(t) {
- console.error('passthrough facaded');
+{
+ // Verify passthrough facade
const pt = new PassThrough();
const datas = [];
pt.on('data', function(chunk) {
datas.push(chunk.toString());
});
- pt.on('end', function() {
- t.same(datas, ['foog', 'bark', 'bazy', 'kuel']);
- t.end();
- });
+ pt.on('end', common.mustCall(function() {
+ assert.deepStrictEqual(datas, ['foog', 'bark', 'bazy', 'kuel']);
+ }));
pt.write(Buffer.from('foog'));
setTimeout(function() {
@@ -440,10 +380,10 @@ test('passthrough facaded', function(t) {
}, 10);
}, 10);
}, 10);
-});
+}
-test('object transform (json parse)', function(t) {
- console.error('json parse stream');
+{
+ // Verify object transform (JSON parse)
const jp = new Transform({ objectMode: true });
jp._transform = function(data, encoding, cb) {
try {
@@ -471,21 +411,20 @@ test('object transform (json parse)', function(t) {
objects.forEach(function(obj) {
jp.write(JSON.stringify(obj));
const res = jp.read();
- t.same(res, obj);
+ assert.deepStrictEqual(res, obj);
});
jp.end();
// read one more time to get the 'end' event
jp.read();
- process.nextTick(function() {
- t.ok(ended);
- t.end();
- });
-});
+ process.nextTick(common.mustCall(function() {
+ assert.strictEqual(ended, true);
+ }));
+}
-test('object transform (json stringify)', function(t) {
- console.error('json parse stream');
+{
+ // Verify object transform (JSON stringify)
const js = new Transform({ objectMode: true });
js._transform = function(data, encoding, cb) {
try {
@@ -513,15 +452,14 @@ test('object transform (json stringify)', function(t) {
objects.forEach(function(obj) {
js.write(obj);
const res = js.read();
- t.equal(res, JSON.stringify(obj));
+ assert.strictEqual(res, JSON.stringify(obj));
});
js.end();
// read one more time to get the 'end' event
js.read();
- process.nextTick(function() {
- t.ok(ended);
- t.end();
- });
-});
+ process.nextTick(common.mustCall(function() {
+ assert.strictEqual(ended, true);
+ }));
+}
diff --git a/test/parallel/test-stream2-writable.js b/test/parallel/test-stream2-writable.js
index 8e1ea9a6034cea..2af3f683a23478 100644
--- a/test/parallel/test-stream2-writable.js
+++ b/test/parallel/test-stream2-writable.js
@@ -49,66 +49,32 @@ for (let i = 0; i < chunks.length; i++) {
chunks[i] = 'x'.repeat(i);
}
-// tiny node-tap lookalike.
-const tests = [];
-let count = 0;
-
-function test(name, fn) {
- count++;
- tests.push([name, fn]);
-}
-
-function run() {
- const next = tests.shift();
- if (!next)
- return console.error('ok');
-
- const name = next[0];
- const fn = next[1];
- console.log('# %s', name);
- fn({
- same: assert.deepStrictEqual,
- equal: assert.strictEqual,
- end: function() {
- count--;
- run();
- }
- });
-}
-
-// ensure all tests have run
-process.on('exit', function() {
- assert.strictEqual(count, 0);
-});
-
-process.nextTick(run);
-
-test('write fast', function(t) {
+{
+ // Verify fast writing
const tw = new TestWriter({
highWaterMark: 100
});
- tw.on('finish', function() {
- t.same(tw.buffer, chunks, 'got chunks in the right order');
- t.end();
- });
+ tw.on('finish', common.mustCall(function() {
+ assert.deepStrictEqual(tw.buffer, chunks, 'got chunks in the right order');
+ }));
chunks.forEach(function(chunk) {
- // screw backpressure. Just buffer it all up.
+ // Ignore backpressure. Just buffer it all up.
tw.write(chunk);
});
tw.end();
-});
+}
-test('write slow', function(t) {
+{
+ // Verify slow writing
const tw = new TestWriter({
highWaterMark: 100
});
- tw.on('finish', function() {
- t.same(tw.buffer, chunks, 'got chunks in the right order');
- t.end();
- });
+ tw.on('finish', common.mustCall(function() {
+ assert.deepStrictEqual(tw.buffer, chunks, 'got chunks in the right order');
+ }));
let i = 0;
(function W() {
@@ -118,20 +84,20 @@ test('write slow', function(t) {
else
tw.end();
})();
-});
+}
-test('write backpressure', function(t) {
+{
+ // Verify write backpressure
const tw = new TestWriter({
highWaterMark: 50
});
let drains = 0;
- tw.on('finish', function() {
- t.same(tw.buffer, chunks, 'got chunks in the right order');
- t.equal(drains, 17);
- t.end();
- });
+ tw.on('finish', common.mustCall(function() {
+ assert.deepStrictEqual(tw.buffer, chunks, 'got chunks in the right order');
+ assert.strictEqual(drains, 17);
+ }));
tw.on('drain', function() {
drains++;
@@ -151,9 +117,10 @@ test('write backpressure', function(t) {
tw.end();
}
})();
-});
+}
-test('write bufferize', function(t) {
+{
+ // Verify write buffersize
const tw = new TestWriter({
highWaterMark: 100
});
@@ -173,7 +140,7 @@ test('write bufferize', function(t) {
undefined ];
tw.on('finish', function() {
- t.same(tw.buffer, chunks, 'got the expected chunks');
+ assert.deepStrictEqual(tw.buffer, chunks, 'got the expected chunks');
});
chunks.forEach(function(chunk, i) {
@@ -181,10 +148,10 @@ test('write bufferize', function(t) {
chunk = Buffer.from(chunk);
tw.write(chunk.toString(enc), enc);
});
- t.end();
-});
+}
-test('write no bufferize', function(t) {
+{
+ // Verify write with no buffersize
const tw = new TestWriter({
highWaterMark: 100,
decodeStrings: false
@@ -211,7 +178,7 @@ test('write no bufferize', function(t) {
undefined ];
tw.on('finish', function() {
- t.same(tw.buffer, chunks, 'got the expected chunks');
+ assert.deepStrictEqual(tw.buffer, chunks, 'got the expected chunks');
});
chunks.forEach(function(chunk, i) {
@@ -219,10 +186,10 @@ test('write no bufferize', function(t) {
chunk = Buffer.from(chunk);
tw.write(chunk.toString(enc), enc);
});
- t.end();
-});
+}
-test('write callbacks', function(t) {
+{
+ // Verify write callbacks
const callbacks = chunks.map(function(chunk, i) {
return [i, function() {
callbacks._called[i] = chunk;
@@ -237,118 +204,117 @@ test('write callbacks', function(t) {
highWaterMark: 100
});
- tw.on('finish', function() {
- process.nextTick(function() {
- t.same(tw.buffer, chunks, 'got chunks in the right order');
- t.same(callbacks._called, chunks, 'called all callbacks');
- t.end();
- });
- });
+ tw.on('finish', common.mustCall(function() {
+ process.nextTick(common.mustCall(function() {
+ assert.deepStrictEqual(tw.buffer, chunks,
+ 'got chunks in the right order');
+ assert.deepStrictEqual(callbacks._called, chunks, 'called all callbacks');
+ }));
+ }));
chunks.forEach(function(chunk, i) {
tw.write(chunk, callbacks[`callback-${i}`]);
});
tw.end();
-});
+}
-test('end callback', function(t) {
+{
+ // Verify end() callback
const tw = new TestWriter();
- tw.end(function() {
- t.end();
- });
-});
+ tw.end(common.mustCall());
+}
-test('end callback with chunk', function(t) {
+{
+ // Verify end() callback with chunk
const tw = new TestWriter();
- tw.end(Buffer.from('hello world'), function() {
- t.end();
- });
-});
+ tw.end(Buffer.from('hello world'), common.mustCall());
+}
-test('end callback with chunk and encoding', function(t) {
+{
+ // Verify end() callback with chunk and encoding
const tw = new TestWriter();
- tw.end('hello world', 'ascii', function() {
- t.end();
- });
-});
+ tw.end('hello world', 'ascii', common.mustCall());
+}
-test('end callback after .write() call', function(t) {
+{
+ // Verify end() callback after write() call
const tw = new TestWriter();
tw.write(Buffer.from('hello world'));
- tw.end(function() {
- t.end();
- });
-});
+ tw.end(common.mustCall());
+}
-test('end callback called after write callback', function(t) {
+{
+ // Verify end() callback after write() callback
const tw = new TestWriter();
let writeCalledback = false;
tw.write(Buffer.from('hello world'), function() {
writeCalledback = true;
});
- tw.end(function() {
- t.equal(writeCalledback, true);
- t.end();
- });
-});
+ tw.end(common.mustCall(function() {
+ assert.strictEqual(writeCalledback, true);
+ }));
+}
-test('encoding should be ignored for buffers', function(t) {
+{
+ // Verify encoding is ignored for buffers
const tw = new W();
const hex = '018b5e9a8f6236ffe30e31baf80d2cf6eb';
- tw._write = function(chunk) {
- t.equal(chunk.toString('hex'), hex);
- t.end();
- };
+ tw._write = common.mustCall(function(chunk) {
+ assert.strictEqual(chunk.toString('hex'), hex);
+ });
const buf = Buffer.from(hex, 'hex');
tw.write(buf, 'latin1');
-});
+}
-test('writables are not pipable', function(t) {
+{
+ // Verify writables cannot be piped
const w = new W();
- w._write = common.noop;
+ w._write = common.mustNotCall();
let gotError = false;
w.on('error', function() {
gotError = true;
});
w.pipe(process.stdout);
- assert(gotError);
- t.end();
-});
+ assert.strictEqual(gotError, true);
+}
-test('duplexes are pipable', function(t) {
+{
+ // Verify that duplex streams cannot be piped
const d = new D();
- d._read = common.noop;
- d._write = common.noop;
+ d._read = common.mustCall();
+ d._write = common.mustNotCall();
let gotError = false;
d.on('error', function() {
gotError = true;
});
d.pipe(process.stdout);
- assert(!gotError);
- t.end();
-});
+ assert.strictEqual(gotError, false);
+}
-test('end(chunk) two times is an error', function(t) {
+{
+ // Verify that end(chunk) twice is an error
const w = new W();
- w._write = common.noop;
+ w._write = common.mustCall((msg) => {
+ assert.strictEqual(msg.toString(), 'this is the end');
+ });
let gotError = false;
w.on('error', function(er) {
gotError = true;
- t.equal(er.message, 'write after end');
+ assert.strictEqual(er.message, 'write after end');
});
w.end('this is the end');
w.end('and so is this');
- process.nextTick(function() {
- assert(gotError);
- t.end();
- });
-});
+ process.nextTick(common.mustCall(function() {
+ assert.strictEqual(gotError, true);
+ }));
+}
-test('dont end while writing', function(t) {
+{
+ // Verify stream doesn't end while writing
const w = new W();
let wrote = false;
w._write = function(chunk, e, cb) {
- assert(!this.writing);
+ assert.strictEqual(this.writing, undefined);
wrote = true;
this.writing = true;
setTimeout(function() {
@@ -356,15 +322,15 @@ test('dont end while writing', function(t) {
cb();
}, 1);
};
- w.on('finish', function() {
- assert(wrote);
- t.end();
- });
+ w.on('finish', common.mustCall(function() {
+ assert.strictEqual(wrote, true);
+ }));
w.write(Buffer.alloc(0));
w.end();
-});
+}
-test('finish does not come before write cb', function(t) {
+{
+ // Verify finish does not come before write() callback
const w = new W();
let writeCb = false;
w._write = function(chunk, e, cb) {
@@ -373,43 +339,42 @@ test('finish does not come before write cb', function(t) {
cb();
}, 10);
};
- w.on('finish', function() {
- assert(writeCb);
- t.end();
- });
+ w.on('finish', common.mustCall(function() {
+ assert.strictEqual(writeCb, true);
+ }));
w.write(Buffer.alloc(0));
w.end();
-});
+}
-test('finish does not come before sync _write cb', function(t) {
+{
+ // Verify finish does not come before synchronous _write() callback
const w = new W();
let writeCb = false;
w._write = function(chunk, e, cb) {
cb();
};
- w.on('finish', function() {
- assert(writeCb);
- t.end();
- });
+ w.on('finish', common.mustCall(function() {
+ assert.strictEqual(writeCb, true);
+ }));
w.write(Buffer.alloc(0), function() {
writeCb = true;
});
w.end();
-});
+}
-test('finish is emitted if last chunk is empty', function(t) {
+{
+ // Verify finish is emitted if the last chunk is empty
const w = new W();
w._write = function(chunk, e, cb) {
process.nextTick(cb);
};
- w.on('finish', function() {
- t.end();
- });
+ w.on('finish', common.mustCall());
w.write(Buffer.allocUnsafe(1));
w.end(Buffer.alloc(0));
-});
+}
-test('finish is emitted after shutdown', function(t) {
+{
+ // Verify that finish is emitted after shutdown
const w = new W();
let shutdown = false;
@@ -424,9 +389,8 @@ test('finish is emitted after shutdown', function(t) {
process.nextTick(cb);
};
w.on('finish', common.mustCall(function() {
- assert(shutdown);
- t.end();
+ assert.strictEqual(shutdown, true);
}));
w.write(Buffer.allocUnsafe(1));
w.end(Buffer.allocUnsafe(0));
-});
+}
diff --git a/test/parallel/test-stream3-cork-end.js b/test/parallel/test-stream3-cork-end.js
index 7227f87ada7fa1..85781cdf7187f2 100644
--- a/test/parallel/test-stream3-cork-end.js
+++ b/test/parallel/test-stream3-cork-end.js
@@ -79,7 +79,7 @@ writeChunks(inputChunks, () => {
// there was a chunk
assert.ok(seen);
- const expected = new Buffer(expectedChunks[i]);
+ const expected = Buffer.from(expectedChunks[i]);
// it was what we expected
assert.ok(seen.equals(expected));
}
diff --git a/test/parallel/test-stream3-cork-uncork.js b/test/parallel/test-stream3-cork-uncork.js
index 98f74a45c6624e..2e8e86be1ef058 100644
--- a/test/parallel/test-stream3-cork-uncork.js
+++ b/test/parallel/test-stream3-cork-uncork.js
@@ -74,7 +74,7 @@ writeChunks(inputChunks, () => {
// there was a chunk
assert.ok(seen);
- const expected = new Buffer(expectedChunks[i]);
+ const expected = Buffer.from(expectedChunks[i]);
// it was what we expected
assert.ok(seen.equals(expected));
}
diff --git a/test/parallel/test-string-decoder.js b/test/parallel/test-string-decoder.js
index 8de0f7ba160ac0..87ab5e8d37bd43 100644
--- a/test/parallel/test-string-decoder.js
+++ b/test/parallel/test-string-decoder.js
@@ -144,6 +144,7 @@ function test(encoding, input, expected, singleSequence) {
} else {
sequences = [singleSequence];
}
+ const hexNumberRE = /.{2}/g;
sequences.forEach((sequence) => {
const decoder = new StringDecoder(encoding);
let output = '';
@@ -155,7 +156,7 @@ function test(encoding, input, expected, singleSequence) {
const message =
'Expected "' + unicodeEscape(expected) + '", ' +
'but got "' + unicodeEscape(output) + '"\n' +
- 'input: ' + input.toString('hex').match(/.{2}/g) + '\n' +
+ 'input: ' + input.toString('hex').match(hexNumberRE) + '\n' +
'Write sequence: ' + JSON.stringify(sequence) + '\n' +
'Full Decoder State: ' + inspect(decoder);
assert.fail(output, expected, message);
diff --git a/test/parallel/test-timers-throw-when-cb-not-function.js b/test/parallel/test-timers-throw-when-cb-not-function.js
index 2aff904f06a500..4e866726c19c22 100644
--- a/test/parallel/test-timers-throw-when-cb-not-function.js
+++ b/test/parallel/test-timers-throw-when-cb-not-function.js
@@ -8,18 +8,14 @@ function doSetTimeout(callback, after) {
};
}
-assert.throws(doSetTimeout('foo'),
- /"callback" argument must be a function/);
-assert.throws(doSetTimeout({foo: 'bar'}),
- /"callback" argument must be a function/);
-assert.throws(doSetTimeout(),
- /"callback" argument must be a function/);
-assert.throws(doSetTimeout(undefined, 0),
- /"callback" argument must be a function/);
-assert.throws(doSetTimeout(null, 0),
- /"callback" argument must be a function/);
-assert.throws(doSetTimeout(false, 0),
- /"callback" argument must be a function/);
+const errMessage = /"callback" argument must be a function/;
+
+assert.throws(doSetTimeout('foo'), errMessage);
+assert.throws(doSetTimeout({foo: 'bar'}), errMessage);
+assert.throws(doSetTimeout(), errMessage);
+assert.throws(doSetTimeout(undefined, 0), errMessage);
+assert.throws(doSetTimeout(null, 0), errMessage);
+assert.throws(doSetTimeout(false, 0), errMessage);
function doSetInterval(callback, after) {
@@ -28,18 +24,12 @@ function doSetInterval(callback, after) {
};
}
-assert.throws(doSetInterval('foo'),
- /"callback" argument must be a function/);
-assert.throws(doSetInterval({foo: 'bar'}),
- /"callback" argument must be a function/);
-assert.throws(doSetInterval(),
- /"callback" argument must be a function/);
-assert.throws(doSetInterval(undefined, 0),
- /"callback" argument must be a function/);
-assert.throws(doSetInterval(null, 0),
- /"callback" argument must be a function/);
-assert.throws(doSetInterval(false, 0),
- /"callback" argument must be a function/);
+assert.throws(doSetInterval('foo'), errMessage);
+assert.throws(doSetInterval({foo: 'bar'}), errMessage);
+assert.throws(doSetInterval(), errMessage);
+assert.throws(doSetInterval(undefined, 0), errMessage);
+assert.throws(doSetInterval(null, 0), errMessage);
+assert.throws(doSetInterval(false, 0), errMessage);
function doSetImmediate(callback, after) {
@@ -48,15 +38,9 @@ function doSetImmediate(callback, after) {
};
}
-assert.throws(doSetImmediate('foo'),
- /"callback" argument must be a function/);
-assert.throws(doSetImmediate({foo: 'bar'}),
- /"callback" argument must be a function/);
-assert.throws(doSetImmediate(),
- /"callback" argument must be a function/);
-assert.throws(doSetImmediate(undefined, 0),
- /"callback" argument must be a function/);
-assert.throws(doSetImmediate(null, 0),
- /"callback" argument must be a function/);
-assert.throws(doSetImmediate(false, 0),
- /"callback" argument must be a function/);
+assert.throws(doSetImmediate('foo'), errMessage);
+assert.throws(doSetImmediate({foo: 'bar'}), errMessage);
+assert.throws(doSetImmediate(), errMessage);
+assert.throws(doSetImmediate(undefined, 0), errMessage);
+assert.throws(doSetImmediate(null, 0), errMessage);
+assert.throws(doSetImmediate(false, 0), errMessage);
diff --git a/test/parallel/test-tls-basic-validations.js b/test/parallel/test-tls-basic-validations.js
index 0b5d87ddc88ff2..a6775c06033a2c 100644
--- a/test/parallel/test-tls-basic-validations.js
+++ b/test/parallel/test-tls-basic-validations.js
@@ -33,7 +33,7 @@ assert.throws(() => tls.createServer({sessionTimeout: 'abcd'}),
assert.throws(() => tls.createServer({ticketKeys: 'abcd'}),
/TypeError: Ticket keys must be a buffer/);
-assert.throws(() => tls.createServer({ticketKeys: new Buffer(0)}),
+assert.throws(() => tls.createServer({ticketKeys: Buffer.alloc(0)}),
/TypeError: Ticket keys length must be 48 bytes/);
assert.throws(() => tls.createSecurePair({}),
diff --git a/test/parallel/test-tls-client-mindhsize.js b/test/parallel/test-tls-client-mindhsize.js
index f9bd0efea4234c..10fe196b539647 100644
--- a/test/parallel/test-tls-client-mindhsize.js
+++ b/test/parallel/test-tls-client-mindhsize.js
@@ -78,13 +78,15 @@ testDHE1024();
assert.throws(() => test(512, true, common.mustNotCall()),
/DH parameter is less than 1024 bits/);
+let errMessage = /minDHSize is not a positive number/;
[0, -1, -Infinity, NaN].forEach((minDHSize) => {
assert.throws(() => tls.connect({ minDHSize }),
- /minDHSize is not a positive number/);
+ errMessage);
});
+errMessage = /minDHSize is not a number/;
[true, false, null, undefined, {}, [], '', '1'].forEach((minDHSize) => {
- assert.throws(() => tls.connect({ minDHSize }), /minDHSize is not a number/);
+ assert.throws(() => tls.connect({ minDHSize }), errMessage);
});
process.on('exit', function() {
diff --git a/test/parallel/test-tls-env-bad-extra-ca.js b/test/parallel/test-tls-env-bad-extra-ca.js
index 12e4e3a4d9518b..57e4c1cfaf3af6 100644
--- a/test/parallel/test-tls-env-bad-extra-ca.js
+++ b/test/parallel/test-tls-env-bad-extra-ca.js
@@ -33,9 +33,8 @@ fork(__filename, opts)
assert.strictEqual(status, 0, 'client did not succeed in connecting');
}))
.on('close', common.mustCall(function() {
- assert(stderr.match(
- /Warning: Ignoring extra certs from.*no-such-file-exists.* load failed:.*No such file or directory/
- ), stderr);
+ const re = /Warning: Ignoring extra certs from.*no-such-file-exists.* load failed:.*No such file or directory/;
+ assert(re.test(stderr), stderr);
}))
.stderr.setEncoding('utf8').on('data', function(str) {
stderr += str;
diff --git a/test/parallel/test-tls-no-sslv23.js b/test/parallel/test-tls-no-sslv23.js
index ff1214d167e6a0..564efab26da22c 100644
--- a/test/parallel/test-tls-no-sslv23.js
+++ b/test/parallel/test-tls-no-sslv23.js
@@ -12,29 +12,33 @@ assert.throws(function() {
tls.createSecureContext({ secureProtocol: 'blargh' });
}, /Unknown method/);
+const errMessageSSLv2 = /SSLv2 methods disabled/;
+
assert.throws(function() {
tls.createSecureContext({ secureProtocol: 'SSLv2_method' });
-}, /SSLv2 methods disabled/);
+}, errMessageSSLv2);
assert.throws(function() {
tls.createSecureContext({ secureProtocol: 'SSLv2_client_method' });
-}, /SSLv2 methods disabled/);
+}, errMessageSSLv2);
assert.throws(function() {
tls.createSecureContext({ secureProtocol: 'SSLv2_server_method' });
-}, /SSLv2 methods disabled/);
+}, errMessageSSLv2);
+
+const errMessageSSLv3 = /SSLv3 methods disabled/;
assert.throws(function() {
tls.createSecureContext({ secureProtocol: 'SSLv3_method' });
-}, /SSLv3 methods disabled/);
+}, errMessageSSLv3);
assert.throws(function() {
tls.createSecureContext({ secureProtocol: 'SSLv3_client_method' });
-}, /SSLv3 methods disabled/);
+}, errMessageSSLv3);
assert.throws(function() {
tls.createSecureContext({ secureProtocol: 'SSLv3_server_method' });
-}, /SSLv3 methods disabled/);
+}, errMessageSSLv3);
// Note that SSLv2 and SSLv3 are disallowed but SSLv2_method and friends are
// still accepted. They are OpenSSL's way of saying that all known protocols
diff --git a/test/parallel/test-tls-passphrase.js b/test/parallel/test-tls-passphrase.js
index 48777e1b059a9b..20b5961fb47f66 100644
--- a/test/parallel/test-tls-passphrase.js
+++ b/test/parallel/test-tls-passphrase.js
@@ -225,6 +225,8 @@ server.listen(0, common.mustCall(function() {
}, common.mustCall());
})).unref();
+const errMessagePassword = /bad password read/;
+
// Missing passphrase
assert.throws(function() {
tls.connect({
@@ -233,7 +235,7 @@ assert.throws(function() {
cert: cert,
rejectUnauthorized: false
});
-}, /bad password read/);
+}, errMessagePassword);
assert.throws(function() {
tls.connect({
@@ -242,7 +244,7 @@ assert.throws(function() {
cert: cert,
rejectUnauthorized: false
});
-}, /bad password read/);
+}, errMessagePassword);
assert.throws(function() {
tls.connect({
@@ -251,7 +253,9 @@ assert.throws(function() {
cert: cert,
rejectUnauthorized: false
});
-}, /bad password read/);
+}, errMessagePassword);
+
+const errMessageDecrypt = /bad decrypt/;
// Invalid passphrase
assert.throws(function() {
@@ -262,7 +266,7 @@ assert.throws(function() {
cert: cert,
rejectUnauthorized: false
});
-}, /bad decrypt/);
+}, errMessageDecrypt);
assert.throws(function() {
tls.connect({
@@ -272,7 +276,7 @@ assert.throws(function() {
cert: cert,
rejectUnauthorized: false
});
-}, /bad decrypt/);
+}, errMessageDecrypt);
assert.throws(function() {
tls.connect({
@@ -282,7 +286,7 @@ assert.throws(function() {
cert: cert,
rejectUnauthorized: false
});
-}, /bad decrypt/);
+}, errMessageDecrypt);
assert.throws(function() {
tls.connect({
@@ -292,4 +296,4 @@ assert.throws(function() {
cert: cert,
rejectUnauthorized: false
});
-}, /bad decrypt/);
+}, errMessageDecrypt);
diff --git a/test/parallel/test-tls-server-failed-handshake-emits-clienterror.js b/test/parallel/test-tls-server-failed-handshake-emits-clienterror.js
index 1ff7decf3cf9cc..0290bcc629a3e3 100644
--- a/test/parallel/test-tls-server-failed-handshake-emits-clienterror.js
+++ b/test/parallel/test-tls-server-failed-handshake-emits-clienterror.js
@@ -21,9 +21,9 @@ const server = tls.createServer({})
}).on('tlsClientError', common.mustCall(function(e) {
assert.ok(e instanceof Error,
'Instance of Error should be passed to error handler');
- assert.ok(e.message.match(
- /SSL routines:SSL23_GET_CLIENT_HELLO:unknown protocol/),
- 'Expecting SSL unknown protocol');
+ assert.ok(
+ /SSL routines:SSL23_GET_CLIENT_HELLO:unknown protocol/.test(e.message),
+ 'Expecting SSL unknown protocol');
server.close();
}));
diff --git a/test/parallel/test-tls-socket-failed-handshake-emits-error.js b/test/parallel/test-tls-socket-failed-handshake-emits-error.js
index ffeb42c8ebd8da..106a14a7df8ec6 100644
--- a/test/parallel/test-tls-socket-failed-handshake-emits-error.js
+++ b/test/parallel/test-tls-socket-failed-handshake-emits-error.js
@@ -21,9 +21,9 @@ const server = net.createServer(function(c) {
s.on('error', common.mustCall(function(e) {
assert.ok(e instanceof Error,
'Instance of Error should be passed to error handler');
- assert.ok(e.message.match(
- /SSL routines:SSL23_GET_CLIENT_HELLO:unknown protocol/),
- 'Expecting SSL unknown protocol');
+ assert.ok(
+ /SSL routines:SSL23_GET_CLIENT_HELLO:unknown protocol/.test(e.message),
+ 'Expecting SSL unknown protocol');
}));
s.on('close', function() {
diff --git a/test/parallel/test-url-domain-ascii-unicode.js b/test/parallel/test-url-domain-ascii-unicode.js
index 9c288cb6e29c38..2be8ac7f5fec8b 100644
--- a/test/parallel/test-url-domain-ascii-unicode.js
+++ b/test/parallel/test-url-domain-ascii-unicode.js
@@ -1,6 +1,10 @@
'use strict';
-require('../common');
+const common = require('../common');
+if (!common.hasIntl) {
+ common.skip('missing Intl');
+ return;
+}
const strictEqual = require('assert').strictEqual;
const url = require('url');
diff --git a/test/parallel/test-url-format-whatwg.js b/test/parallel/test-url-format-whatwg.js
index f9e5691ae5cc04..f7363fdbb998b0 100644
--- a/test/parallel/test-url-format-whatwg.js
+++ b/test/parallel/test-url-format-whatwg.js
@@ -1,6 +1,10 @@
'use strict';
const common = require('../common');
+if (!common.hasIntl) {
+ common.skip('missing Intl');
+ return;
+}
const assert = require('assert');
const url = require('url');
const URL = url.URL;
diff --git a/test/parallel/test-url-parse-invalid-input.js b/test/parallel/test-url-parse-invalid-input.js
index a6de25e10c1501..a2591123324301 100644
--- a/test/parallel/test-url-parse-invalid-input.js
+++ b/test/parallel/test-url-parse-invalid-input.js
@@ -4,6 +4,7 @@ const assert = require('assert');
const url = require('url');
// https://github.com/joyent/node/issues/568
+const errMessage = /^TypeError: Parameter "url" must be a string, not (?:undefined|boolean|number|object|function|symbol)$/;
[
undefined,
null,
@@ -16,8 +17,7 @@ const url = require('url');
() => {},
Symbol('foo')
].forEach((val) => {
- assert.throws(() => { url.parse(val); },
- /^TypeError: Parameter "url" must be a string, not (undefined|boolean|number|object|function|symbol)$/);
+ assert.throws(() => { url.parse(val); }, errMessage);
});
assert.throws(() => { url.parse('http://%E0%A4%A@fail'); },
diff --git a/test/parallel/test-util-format.js b/test/parallel/test-util-format.js
index 93998c598a0e1f..084e6f73b90ddf 100644
--- a/test/parallel/test-util-format.js
+++ b/test/parallel/test-util-format.js
@@ -126,6 +126,12 @@ assert.strictEqual(util.format('o: %j, a: %j', {}, []), 'o: {}, a: []');
assert.strictEqual(util.format('o: %j, a: %j', {}), 'o: {}, a: %j');
assert.strictEqual(util.format('o: %j, a: %j'), 'o: %j, a: %j');
+// Invalid format specifiers
+assert.strictEqual(util.format('a% b', 'x'), 'a% b x');
+assert.strictEqual(util.format('percent: %d%, fraction: %d', 10, 0.1),
+ 'percent: 10%, fraction: 0.1');
+assert.strictEqual(util.format('abc%', 1), 'abc% 1');
+
{
const o = {};
o.o = o;
diff --git a/test/parallel/test-util-inspect.js b/test/parallel/test-util-inspect.js
index c8ee5f72edbe50..19424f6b0be21e 100644
--- a/test/parallel/test-util-inspect.js
+++ b/test/parallel/test-util-inspect.js
@@ -837,9 +837,10 @@ if (typeof Symbol !== 'undefined') {
{
function checkAlignment(container) {
const lines = util.inspect(container).split('\n');
+ const numRE = /\d/;
let pos;
lines.forEach((line) => {
- const npos = line.search(/\d/);
+ const npos = line.search(numRE);
if (npos !== -1) {
if (pos !== undefined) {
assert.strictEqual(pos, npos, 'container items not aligned');
diff --git a/test/parallel/test-util-internal.js b/test/parallel/test-util-internal.js
index 5131353abbef9b..9c016f3c3e1793 100644
--- a/test/parallel/test-util-internal.js
+++ b/test/parallel/test-util-internal.js
@@ -20,26 +20,29 @@ function setHiddenValue(obj, index, val) {
};
}
-assert.throws(getHiddenValue(), /obj must be an object/);
-assert.throws(getHiddenValue(null, 'foo'), /obj must be an object/);
-assert.throws(getHiddenValue(undefined, 'foo'), /obj must be an object/);
-assert.throws(getHiddenValue('bar', 'foo'), /obj must be an object/);
-assert.throws(getHiddenValue(85, 'foo'), /obj must be an object/);
-assert.throws(getHiddenValue({}), /index must be an uint32/);
-assert.throws(getHiddenValue({}, null), /index must be an uint32/);
-assert.throws(getHiddenValue({}, []), /index must be an uint32/);
+const errMessageObj = /obj must be an object/;
+const errMessageIndex = /index must be an uint32/;
+
+assert.throws(getHiddenValue(), errMessageObj);
+assert.throws(getHiddenValue(null, 'foo'), errMessageObj);
+assert.throws(getHiddenValue(undefined, 'foo'), errMessageObj);
+assert.throws(getHiddenValue('bar', 'foo'), errMessageObj);
+assert.throws(getHiddenValue(85, 'foo'), errMessageObj);
+assert.throws(getHiddenValue({}), errMessageIndex);
+assert.throws(getHiddenValue({}, null), errMessageIndex);
+assert.throws(getHiddenValue({}, []), errMessageIndex);
assert.deepStrictEqual(
binding.getHiddenValue({}, kArrowMessagePrivateSymbolIndex),
undefined);
-assert.throws(setHiddenValue(), /obj must be an object/);
-assert.throws(setHiddenValue(null, 'foo'), /obj must be an object/);
-assert.throws(setHiddenValue(undefined, 'foo'), /obj must be an object/);
-assert.throws(setHiddenValue('bar', 'foo'), /obj must be an object/);
-assert.throws(setHiddenValue(85, 'foo'), /obj must be an object/);
-assert.throws(setHiddenValue({}), /index must be an uint32/);
-assert.throws(setHiddenValue({}, null), /index must be an uint32/);
-assert.throws(setHiddenValue({}, []), /index must be an uint32/);
+assert.throws(setHiddenValue(), errMessageObj);
+assert.throws(setHiddenValue(null, 'foo'), errMessageObj);
+assert.throws(setHiddenValue(undefined, 'foo'), errMessageObj);
+assert.throws(setHiddenValue('bar', 'foo'), errMessageObj);
+assert.throws(setHiddenValue(85, 'foo'), errMessageObj);
+assert.throws(setHiddenValue({}), errMessageIndex);
+assert.throws(setHiddenValue({}, null), errMessageIndex);
+assert.throws(setHiddenValue({}, []), errMessageIndex);
const obj = {};
assert.strictEqual(
binding.setHiddenValue(obj, kArrowMessagePrivateSymbolIndex, 'bar'),
diff --git a/test/parallel/test-util-log.js b/test/parallel/test-util-log.js
index 24e84e1be9247b..d660106e1705af 100644
--- a/test/parallel/test-util-log.js
+++ b/test/parallel/test-util-log.js
@@ -46,10 +46,10 @@ const tests = [
];
// test util.log()
+const re = /[0-9]{1,2} [A-Z][a-z]{2} [0-9]{2}:[0-9]{2}:[0-9]{2} - (.+)$/;
tests.forEach(function(test) {
util.log(test.input);
const result = strings.shift().trim();
- const re = (/[0-9]{1,2} [A-Z][a-z]{2} [0-9]{2}:[0-9]{2}:[0-9]{2} - (.+)$/);
const match = re.exec(result);
assert.ok(match);
assert.strictEqual(match[1], test.output);
diff --git a/test/parallel/test-zlib-bytes-read.js b/test/parallel/test-zlib-bytes-read.js
index 701d286817a267..6262c2514954d0 100644
--- a/test/parallel/test-zlib-bytes-read.js
+++ b/test/parallel/test-zlib-bytes-read.js
@@ -28,7 +28,7 @@ for (const method of [
['createDeflateRaw', 'createInflateRaw', true]
]) {
let compWriter;
- let compData = new Buffer(0);
+ let compData = Buffer.alloc(0);
const comp = zlib[method[0]]();
comp.on('data', function(d) {
@@ -44,7 +44,7 @@ for (const method of [
{
let decompWriter;
- let decompData = new Buffer(0);
+ let decompData = Buffer.alloc(0);
const decomp = zlib[method[1]]();
decomp.on('data', function(d) {
@@ -66,10 +66,10 @@ for (const method of [
// Some methods should allow extra data after the compressed data
if (method[2]) {
- const compDataExtra = Buffer.concat([compData, new Buffer('extra')]);
+ const compDataExtra = Buffer.concat([compData, Buffer.from('extra')]);
let decompWriter;
- let decompData = new Buffer(0);
+ let decompData = Buffer.alloc(0);
const decomp = zlib[method[1]]();
decomp.on('data', function(d) {
diff --git a/test/parallel/test-zlib-failed-init.js b/test/parallel/test-zlib-failed-init.js
index 3b6da1d4fb840f..4f224ecd616ec7 100644
--- a/test/parallel/test-zlib-failed-init.js
+++ b/test/parallel/test-zlib-failed-init.js
@@ -6,11 +6,15 @@ const assert = require('assert');
const zlib = require('zlib');
// For raw deflate encoding, requests for 256-byte windows are rejected as
-// invalid by zlib.
-// (http://zlib.net/manual.html#Advanced)
-assert.throws(() => {
- zlib.createDeflateRaw({ windowBits: 8 });
-}, /^Error: Init error$/);
+// invalid by zlib (http://zlib.net/manual.html#Advanced).
+// This check was introduced in version 1.2.9 and prior to that there was
+// no such rejection which is the reason for the version check below
+// (http://zlib.net/ChangeLog.txt).
+if (!/^1\.2\.[0-8]$/.test(process.versions.zlib)) {
+ assert.throws(() => {
+ zlib.createDeflateRaw({ windowBits: 8 });
+ }, /^Error: Init error$/);
+}
// Regression tests for bugs in the validation logic.
diff --git a/test/parallel/test-zlib-from-gzip-with-trailing-garbage.js b/test/parallel/test-zlib-from-gzip-with-trailing-garbage.js
index 872c2581c53b90..0cc4953d41c514 100644
--- a/test/parallel/test-zlib-from-gzip-with-trailing-garbage.js
+++ b/test/parallel/test-zlib-from-gzip-with-trailing-garbage.js
@@ -9,7 +9,7 @@ const zlib = require('zlib');
let data = Buffer.concat([
zlib.gzipSync('abc'),
zlib.gzipSync('def'),
- Buffer(10).fill(0)
+ Buffer.alloc(10)
]);
assert.strictEqual(zlib.gunzipSync(data).toString(), 'abcdef');
@@ -28,8 +28,8 @@ zlib.gunzip(data, common.mustCall((err, result) => {
data = Buffer.concat([
zlib.gzipSync('abc'),
zlib.gzipSync('def'),
- Buffer([0x1f, 0x8b, 0xff, 0xff]),
- Buffer(10).fill(0)
+ Buffer.from([0x1f, 0x8b, 0xff, 0xff]),
+ Buffer.alloc(10)
]);
assert.throws(
@@ -49,7 +49,7 @@ zlib.gunzip(data, common.mustCall((err, result) => {
data = Buffer.concat([
zlib.gzipSync('abc'),
zlib.gzipSync('def'),
- Buffer([0x1f, 0x8b, 0xff, 0xff])
+ Buffer.from([0x1f, 0x8b, 0xff, 0xff])
]);
assert.throws(
diff --git a/test/parallel/test-zlib-sync-no-event.js b/test/parallel/test-zlib-sync-no-event.js
index d6eb1f3c9df6a3..c6584b43d9ba1c 100644
--- a/test/parallel/test-zlib-sync-no-event.js
+++ b/test/parallel/test-zlib-sync-no-event.js
@@ -10,7 +10,7 @@ const message = 'Come on, Fhqwhgads.';
const zipper = new zlib.Gzip();
zipper.on('close', shouldNotBeCalled);
-const buffer = new Buffer(message);
+const buffer = Buffer.from(message);
const zipped = zipper._processChunk(buffer, zlib.constants.Z_FINISH);
const unzipper = new zlib.Gunzip();
diff --git a/test/parallel/test-zlib-truncated.js b/test/parallel/test-zlib-truncated.js
index c7b84c0d703711..678bfedd41c154 100644
--- a/test/parallel/test-zlib-truncated.js
+++ b/test/parallel/test-zlib-truncated.js
@@ -15,6 +15,8 @@ const inputString = 'ΩΩLorem ipsum dolor sit amet, consectetur adipiscing eli'
'm arcu mi, sodales non suscipit id, ultrices ut massa. S' +
'ed ac sem sit amet arcu malesuada fermentum. Nunc sed. ';
+const errMessage = /unexpected end of file/;
+
[
{ comp: 'gzip', decomp: 'gunzip', decompSync: 'gunzipSync' },
{ comp: 'gzip', decomp: 'unzip', decompSync: 'unzipSync' },
@@ -41,11 +43,11 @@ const inputString = 'ΩΩLorem ipsum dolor sit amet, consectetur adipiscing eli'
// sync truncated input test
assert.throws(function() {
zlib[methods.decompSync](truncated);
- }, /unexpected end of file/);
+ }, errMessage);
// async truncated input test
zlib[methods.decomp](truncated, function(err, result) {
- assert(/unexpected end of file/.test(err.message));
+ assert(errMessage.test(err.message));
});
const syncFlushOpt = { finishFlush: zlib.constants.Z_SYNC_FLUSH };
diff --git a/test/pummel/test-net-pingpong.js b/test/pummel/test-net-pingpong.js
index d88b4f638a8ba4..4db843afd3efc8 100644
--- a/test/pummel/test-net-pingpong.js
+++ b/test/pummel/test-net-pingpong.js
@@ -52,7 +52,7 @@ function pingPongTest(port, host, on_complete) {
console.log(`server got: ${JSON.stringify(data)}`);
assert.strictEqual('open', socket.readyState);
assert.strictEqual(true, count <= N);
- if (/PING/.exec(data)) {
+ if (/PING/.test(data)) {
socket.write('PONG');
}
});
diff --git a/test/sequential/test-fs-watch.js b/test/sequential/test-fs-watch.js
index ed0ff3d9227064..70c165ea7992be 100644
--- a/test/sequential/test-fs-watch.js
+++ b/test/sequential/test-fs-watch.js
@@ -130,7 +130,7 @@ fs.watch(__filename, {persistent: false}, function() {
// https://github.com/joyent/node/issues/6690
let oldhandle;
assert.throws(function() {
- const w = fs.watch(__filename, common.noop);
+ const w = fs.watch(__filename, common.mustNotCall());
oldhandle = w._handle;
w._handle = { close: w._handle.close };
w.close();
@@ -138,7 +138,7 @@ assert.throws(function() {
oldhandle.close(); // clean up
assert.throws(function() {
- const w = fs.watchFile(__filename, {persistent: false}, common.noop);
+ const w = fs.watchFile(__filename, {persistent: false}, common.mustNotCall());
oldhandle = w._handle;
w._handle = { stop: w._handle.stop };
w.stop();
diff --git a/test/sequential/test-https-set-timeout-server.js b/test/sequential/test-https-set-timeout-server.js
index 100354b54bf074..f6e97ea5981306 100644
--- a/test/sequential/test-https-set-timeout-server.js
+++ b/test/sequential/test-https-set-timeout-server.js
@@ -137,19 +137,24 @@ test(function serverRequestNotTimeoutAfterEnd(cb) {
test(function serverResponseTimeoutWithPipeline(cb) {
let caughtTimeout = '';
+ let secReceived = false;
process.on('exit', function() {
assert.strictEqual(caughtTimeout, '/2');
});
const server = https.createServer(serverOptions, function(req, res) {
+ if (req.url === '/2')
+ secReceived = true;
res.setTimeout(50, function() {
caughtTimeout += req.url;
});
if (req.url === '/1') res.end();
});
server.on('timeout', function(socket) {
- socket.destroy();
- server.close();
- cb();
+ if (secReceived) {
+ socket.destroy();
+ server.close();
+ cb();
+ }
});
server.listen(0, function() {
const options = {
diff --git a/test/sequential/test-module-loading.js b/test/sequential/test-module-loading.js
index c55c03279edde1..8a7bfe15c43338 100644
--- a/test/sequential/test-module-loading.js
+++ b/test/sequential/test-module-loading.js
@@ -25,6 +25,8 @@ const assert = require('assert');
const path = require('path');
const fs = require('fs');
+const backslash = /\\/g;
+
console.error('load test-module-loading.js');
// assert that this is the main module.
@@ -195,7 +197,7 @@ try {
require(`${loadOrder}file3`);
} catch (e) {
// Not a real .node module, but we know we require'd the right thing.
- assert.ok(e.message.replace(/\\/g, '/').match(/file3\.node/));
+ assert.ok(/file3\.node/.test(e.message.replace(backslash, '/')));
}
assert.strictEqual(require(`${loadOrder}file4`).file4, 'file4.reg', msg);
assert.strictEqual(require(`${loadOrder}file5`).file5, 'file5.reg2', msg);
@@ -203,7 +205,7 @@ try {
try {
require(`${loadOrder}file7`);
} catch (e) {
- assert.ok(e.message.replace(/\\/g, '/').match(/file7\/index\.node/));
+ assert.ok(/file7\/index\.node/.test(e.message.replace(backslash, '/')));
}
assert.strictEqual(require(`${loadOrder}file8`).file8, 'file8/index.reg',
msg);
@@ -237,7 +239,7 @@ try {
const children = module.children.reduce(function red(set, child) {
let id = path.relative(path.dirname(__dirname), child.id);
- id = id.replace(/\\/g, '/');
+ id = id.replace(backslash, '/');
set[id] = child.children.reduce(red, {});
return set;
}, {});
diff --git a/test/sequential/test-process-warnings.js b/test/sequential/test-process-warnings.js
index 0ab8652f561ec8..944029d8b3d732 100644
--- a/test/sequential/test-process-warnings.js
+++ b/test/sequential/test-process-warnings.js
@@ -10,24 +10,26 @@ const normal = [warnmod];
const noWarn = ['--no-warnings', warnmod];
const traceWarn = ['--trace-warnings', warnmod];
+const warningMessage = /^\(.+\)\sWarning: a bad practice warning/;
+
execFile(node, normal, function(er, stdout, stderr) {
// Show Process Warnings
assert.strictEqual(er, null);
assert.strictEqual(stdout, '');
- assert(/^\(.+\)\sWarning: a bad practice warning/.test(stderr));
+ assert(warningMessage.test(stderr));
});
execFile(node, noWarn, function(er, stdout, stderr) {
// Hide Process Warnings
assert.strictEqual(er, null);
assert.strictEqual(stdout, '');
- assert(!/^\(.+\)\sWarning: a bad practice warning/.test(stderr));
+ assert(!warningMessage.test(stderr));
});
execFile(node, traceWarn, function(er, stdout, stderr) {
// Show Warning Trace
assert.strictEqual(er, null);
assert.strictEqual(stdout, '');
- assert(/^\(.+\)\sWarning: a bad practice warning/.test(stderr));
+ assert(warningMessage.test(stderr));
assert(/at Object\.\s\(.+warnings\.js:3:9\)/.test(stderr));
});
diff --git a/test/sequential/test-regress-GH-784.js b/test/sequential/test-regress-GH-784.js
index 7abc622dbe4e6a..127d9216269852 100644
--- a/test/sequential/test-regress-GH-784.js
+++ b/test/sequential/test-regress-GH-784.js
@@ -70,28 +70,30 @@ const responses = [];
function afterPing(result) {
responses.push(result);
console.error(`afterPing. responses.length = ${responses.length}`);
+ const ECONNREFUSED_RE = /ECONNREFUSED/;
+ const successRE = /success/;
switch (responses.length) {
case 2:
- assert.ok(/ECONNREFUSED/.test(responses[0]));
- assert.ok(/ECONNREFUSED/.test(responses[1]));
+ assert.ok(ECONNREFUSED_RE.test(responses[0]));
+ assert.ok(ECONNREFUSED_RE.test(responses[1]));
serverOn();
break;
case 4:
- assert.ok(/success/.test(responses[2]));
- assert.ok(/success/.test(responses[3]));
+ assert.ok(successRE.test(responses[2]));
+ assert.ok(successRE.test(responses[3]));
serverOff();
break;
case 6:
- assert.ok(/ECONNREFUSED/.test(responses[4]));
- assert.ok(/ECONNREFUSED/.test(responses[5]));
+ assert.ok(ECONNREFUSED_RE.test(responses[4]));
+ assert.ok(ECONNREFUSED_RE.test(responses[5]));
serverOn();
break;
case 8:
- assert.ok(/success/.test(responses[6]));
- assert.ok(/success/.test(responses[7]));
+ assert.ok(successRE.test(responses[6]));
+ assert.ok(successRE.test(responses[7]));
server.close();
// we should go to process.on('exit') from here.
break;
diff --git a/tools/.eslintrc.yaml b/tools/.eslintrc.yaml
new file mode 100644
index 00000000000000..e1405dd718bf0f
--- /dev/null
+++ b/tools/.eslintrc.yaml
@@ -0,0 +1,12 @@
+## Tools-specific linter rules
+
+rules:
+ # Stylistic Issues
+ # http://eslint.org/docs/rules/#stylistic-issues
+ indent: [2, 2, {ArrayExpression: first,
+ CallExpression: {arguments: first},
+ FunctionDeclaration: {parameters: first},
+ FunctionExpression: {parameters: first},
+ MemberExpression: off,
+ ObjectExpression: first,
+ SwitchCase: 1}]
diff --git a/tools/eslint-rules/required-modules.js b/tools/eslint-rules/required-modules.js
index 3e4a8e8aadfc82..4a444809b7115c 100644
--- a/tools/eslint-rules/required-modules.js
+++ b/tools/eslint-rules/required-modules.js
@@ -75,15 +75,15 @@ module.exports = function(context) {
if (foundModules.length < requiredModules.length) {
var missingModules = requiredModules.filter(
function(module) {
- return foundModules.indexOf(module === -1);
+ return foundModules.indexOf(module) === -1;
}
- );
+ );
missingModules.forEach(function(moduleName) {
context.report(
node,
'Mandatory module "{{moduleName}}" must be loaded.',
{ moduleName: moduleName }
- );
+ );
});
}
}
diff --git a/tools/eslint/CHANGELOG.md b/tools/eslint/CHANGELOG.md
deleted file mode 100644
index 4f4b3bbdb3fbbc..00000000000000
--- a/tools/eslint/CHANGELOG.md
+++ /dev/null
@@ -1,3939 +0,0 @@
-v3.19.0 - March 31, 2017
-
-* e09132f Fix: no-extra-parens false positive with exports and object literals (#8359) (Teddy Katz)
-* 91baed4 Update: allow custom messages in no-restricted-syntax (fixes #8298) (#8357) (Vitor Balocco)
-* 35c93e6 Fix: prevent space-before-function-paren from checking type annotations (#8349) (Teddy Katz)
-* 3342e9f Fix: don't modify operator precedence in operator-assignment autofixer (#8358) (Teddy Katz)
-* f88375f Docs: clarify that no-unsafe-negation is in eslint:recommended (#8371) (Teddy Katz)
-* 02f0d27 Docs: Add soda0289 to Development Team (#8367) (Kai Cataldo)
-* 155424c Fix: ignore empty path in patterns (fixes #8362) (#8364) (alberto)
-* 27616a8 Fix: prefer-const false positive with object spread (fixes #8187) (#8297) (Vitor Balocco)
-* 8569a90 Docs: add note about git's linebreak handling to linebreak-style docs (#8361) (Teddy Katz)
-* 5878593 Chore: fix invalid syntax in no-param-reassign test (#8360) (Teddy Katz)
-* 1b1046b Fix: don't classify plugins that throw errors as "missing" (fixes #6874) (#8323) (Teddy Katz)
-* 29f4ba5 Fix: no-useless-computed-key invalid autofix for getters and setters (#8335) (Teddy Katz)
-* 0541eaf Fix: no-implicit-coercion invalid autofix with consecutive identifiers (#8340) (Teddy Katz)
-* 41b9786 Fix: no-extra-parens false positive with objects following arrows (#8339) (Teddy Katz)
-* 3146167 Fix: `eslint.verify` should not mutate config argument (fixes #8329) (#8334) (alberto)
-* 927de90 Fix: dot-notation autofix produces invalid syntax for integer properties (#8332) (Teddy Katz)
-* a9d1bea Fix: comma-style autofix produces errors on parenthesized elements (#8331) (Teddy Katz)
-* d52173f Fix: don't generate invalid options in config-rule (#8326) (Teddy Katz)
-* 6eda3b5 Fix: no-extra-parens invalid autofix in for-of statements (#8337) (Teddy Katz)
-* 6c819d8 Fix: dot-notation autofix produces errors on parenthesized computed keys (#8330) (Teddy Katz)
-* 2d883d7 Fix: object-shorthand autofix produces errors on parenthesized functions (#8328) (Teddy Katz)
-* cd9b774 Fix: quotes false positive with backtick option in method names (#8327) (Teddy Katz)
-* d064ba2 Fix: no-else-return false positive for ifs in single-statement position (#8338) (Teddy Katz)
-* 6a718ba Chore: enable max-statements-per-line on ESLint codebase (#8321) (Teddy Katz)
-* 614b62e Chore: update sinon calls to deprecated API. (#8310) (alberto)
-* 0491572 Chore: use precalculated counts in codeframe formatter (#8296) (Vitor Balocco)
-* 8733e6a Chore: Fix incorrect error location properties in tests (#8307) (alberto)
-* c4ffb49 Chore: Fix typos in test option assertions (#8305) (Teddy Katz)
-* 79a97cb Upgrade: devDependencies (#8303) (alberto)
-* e4da200 Upgrade: Mocha to 3.2.0 (#8299) (Ilya Volodin)
-* 2f144ca Fix: operator-assignment autofix errors with parentheses (fixes #8293) (#8294) (Teddy Katz)
-* 7521cd5 Chore: update token logic in rules to use ast-utils (#8288) (Teddy Katz)
-* 9b509ce Chore: refactor space-before-function-paren rule (#8284) (Teddy Katz)
-* ddc6350 Fix: no-param-reassign false positive on destructuring (fixes #8279) (#8281) (Teddy Katz)
-* f8176b3 Chore: improve test coverage for node-event-generator (#8287) (Teddy Katz)
-* 602e9c2 Docs: fix incorrect selector examples (#8278) (Teddy Katz)
-
-v3.18.0 - March 17, 2017
-
-* 85f74ca Fix: broken code path of direct nested loops (fixes #8248) (#8274) (Toru Nagashima)
-* a61c359 Fix: Ignore hidden folders when resolving globs (fixes #8259) (#8270) (Ian VanSchooten)
-* 6f05546 Chore: convert StubModuleResolver in config tests to ES6 class (#8265) (Teddy Katz)
-* 0c0fc31 Fix: false positive of no-extra-parens about spread and sequense (#8275) (Toru Nagashima)
-* e104973 Docs: remove self-reference in no-restricted-syntax docs (#8277) (Vitor Balocco)
-* 23eca51 Update: Add allowTaggedTemplates to no-unused-expressions (fixes #7632) (#8253) (Kevin Partington)
-* f9ede3f Upgrade: doctrine to 2.0.0 (#8269) (alberto)
-* 1b678a6 New: allow rules to listen for AST selectors (fixes #5407) (#7833) (Teddy Katz)
-* 63ca0c5 Chore: use precalculated counts in stylish formatter (#8251) (alberto)
-* 47c3171 Fix: typo in console.error (#8258) (Jan Peer Stöcklmair)
-* e74ed6d Chore: convert Traverser to ES6 class (refs #7849) (#8232) (Teddy Katz)
-* 13eead9 Fix: sort-vars crash on mixed destructuring declarations (#8245) (Teddy Katz)
-* 133f489 Fix: func-name-matching crash on destructuring assignment to functions (#8247) (Teddy Katz)
-* a34b9c4 Fix: func-name-matching crash on non-string literal computed keys (#8246) (Teddy Katz)
-* 7276e6d Docs: remove unneeded semicolons in arrow-parens.md (#8249) (Dmitry Gershun)
-* 8c40a25 concat-stream known to be vulnerable prior 1.5.2 (#8228) (Samuel)
-* 149c055 Upgrade: mock-fs to v4.2.0 (fixes #8194) (#8243) (Teddy Katz)
-* a83bff9 Build: remove unneeded json config in demo (fixes #8237) (#8242) (alberto)
-* df12137 Docs: fix typos (#8235) (Gyandeep Singh)
-* b5e9788 Chore: rename no-extra-parens methods (#8225) (Vitor Balocco)
-* 7f8afe6 Update: no-extra-parens overlooked spread and superClass (fixes #8175) (#8209) (Toru Nagashima)
-* ce6ff56 Docs: set recommended true for no-global-assign (fixes #8215) (#8218) (BinYi LIU)
-* 5b5c236 Fix: wrong comment when module not found in config (fixes #8192) (#8196) (alberto)
-
-v3.17.1 - March 6, 2017
-
-* f8c8e6e Build: change mock-fs path without SSH (fixes #8207) (#8208) (Toru Nagashima)
-* f713f11 Fix: nonblock-statement-body-position multiline error (fixes #8202) (#8203) (Teddy Katz)
-* 41e3d9c Fix: `operator-assignment` with parenthesized expression (fixes #8190) (#8197) (alberto)
-* 5e3bca7 Chore: add eslint-plugin-eslint-plugin (#8198) (Teddy Katz)
-* 580da36 Chore: add missing `output` property to tests (#8195) (alberto)
-
-v3.17.0 - March 3, 2017
-
-* 4fdf6d7 Update: deprecate `applyDefaultPatterns` in `line-comment-position` (#8183) (alberto)
-* 25e5817 Fix: Don't autofix `+ +a` to `++a` in space-unary-ops (#8176) (Alan Pierce)
-* a6ce8f9 Build: Sort rules before dumping them to doc files (#8154) (Danny Andrews)
-* 0af9057 Chore: Upgrade to a patched version of mock-fs (fixes #8177) (#8188) (Teddy Katz)
-* bf4d8cf Update: ignore eslint comments in lines-arount-comment (fixes #4345) (#8155) (alberto)
-* dad20ad New: add SourceCode#getLocFromIndex and #getIndexFromLoc (fixes #8073) (#8158) (Teddy Katz)
-* 18a519f Update: let RuleTester cases assert that no autofix occurs (fixes #8157) (#8163) (Teddy Katz)
-* a30eb8d Docs: improve documentation for RuleTester cases (#8162) (Teddy Katz)
-* a78ec9f Chore: upgrade `coveralls` to ^2.11.16 (#8161) (alberto)
-* d02bd11 Fix: padded-blocks autofix problems with comments (#8149) (alberto)
-* 9994889 Docs: Add missing space to `create` in `no-use-before-define` (#8166) (Justin Anastos)
-* 4d542ba Docs: Remove unneeded statement about autofix (#8164) (alberto)
-* 20daea5 New: no-compare-neg-zero rule (#8091) (薛定谔的猫)
-* 4d35a81 Fix: Add a utility to avoid autofix conflicts (fixes #7928, fixes #8026) (#8067) (Alan Pierce)
-* 287e882 New: nonblock-statement-body-position rule (fixes #6067) (#8108) (Teddy Katz)
-* 7f1f4e5 Chore: remove unneeded devDeps `linefix` and `gh-got` (#8160) (alberto)
-* ca1694b Update: ignore negative ranges in fixes (#8133) (alberto)
-* 163d751 Docs: `lines-around-comment` doesn't disallow empty lines (#8151) (alberto)
-* 1c84922 Chore: upgrade eslint-plugin-node (#8156) (alberto)
-* 1ee5c27 Fix: Make RuleTester handle empty-string cases gracefully (fixes #8142) (#8143) (Teddy Katz)
-* 044bc10 Docs: Add details about "--fix" option for "sort-imports" rule (#8077) (Olivier Audard)
-* 3fec54a Add option to ignore property in no-param-reassign (#8087) (Christian Bundy)
-* 4e52cfc Fix: Improve keyword-spacing typescript support (fixes #8110) (#8111) (Reyad Attiyat)
-* 7ff42e8 New: Allow regexes in RuleTester (fixes #7837) (#8115) (Daniel Lo Nigro)
-* cbd7ded Build: display rules’ meta data in their docs (fixes #5774) (#8127) (Wilson Kurniawan)
-* da8e8af Update: include function name in report message if possible (fixes #7260) (#8058) (Dieter Luypaert)
-* 8f91e32 Fix: `ignoreRestSiblings` option didn't cover arguments (fixes #8119) (#8120) (Toru Nagashima)
-
-v3.16.1 - February 22, 2017
-
-* ff8a80c Fix: duplicated autofix output for inverted fix ranges (fixes #8116) (#8117) (Teddy Katz)
-* a421897 Docs: fix typo in arrow-parens.md (#8132) (Will Chen)
-* 22d7fbf Chore: fix invalid redeclared variables in tests (#8130) (Teddy Katz)
-* 8d95598 Chore: fix output assertion typos in rule tests (#8129) (Teddy Katz)
-* 9fa2559 Docs: Add missing quotes in key-spacing rule (#8121) (Glenn Reyes)
-* f3a6ced Build: package.json update for eslint-config-eslint release (ESLint Jenkins)
-
-v3.16.0 - February 20, 2017
-
-* d89d0b4 Update: fix quotes false negative for string literals as template tags (#8107) (Teddy Katz)
-* 21be366 Chore: Ensuring eslint:recommended rules are sorted. (#8106) (Kevin Partington)
-* 360dbe4 Update: Improve error message when extend config missing (fixes #6115) (#8100) (alberto)
-* f62a724 Chore: use updated token iterator methods (#8103) (Kai Cataldo)
-* daf6f26 Fix: check output in RuleTester when errors is a number (fixes #7640) (#8097) (alberto)
-* cfb65c5 Update: make no-lone-blocks report blocks in switch cases (fixes #8047) (#8062) (Teddy Katz)
-* 290fb1f Update: Add includeComments to getTokenByRangeStart (fixes #8068) (#8069) (Kai Cataldo)
-* ff066dc Chore: Incorrect source code test text (#8096) (Jack Ford)
-* 14d146d Docs: Clarify --ext only works with directories (fixes #7939) (#8095) (alberto)
-* 013a454 Docs: Add TSC meeting quorum requirement (#8086) (Kevin Partington)
-* 7516303 Fix: `sourceCode.getTokenAfter` shouldn't skip tokens after comments (#8055) (Toru Nagashima)
-* c53e034 Fix: unicode-bom fixer insert BOM in appropriate location (fixes #8083) (#8084) (pantosha)
-* 55ac302 Chore: fix the timing to define rules for tests (#8082) (Toru Nagashima)
-* c7e64f3 Upgrade: mock-fs (#8070) (Toru Nagashima)
-* acc3301 Update: handle uncommon linebreaks consistently in rules (fixes #7949) (#8049) (Teddy Katz)
-* 591b74a Chore: enable operator-linebreak on ESLint codebase (#8064) (Teddy Katz)
-* 6445d2a Docs: Add documentation for /* exported */ (fixes #7998) (#8065) (Lee Yi Min)
-* fcc38db Chore: simplify and improve performance for autofix (#8035) (Toru Nagashima)
-* b04fde7 Chore: improve performance of SourceCode constructor (#8054) (Teddy Katz)
-* 90fd555 Update: improve null detection in eqeqeq for ES6 regexes (fixes #8020) (#8042) (Teddy Katz)
-* 16248e2 Fix: no-extra-boolean-cast incorrect Boolean() autofixing (fixes #7977) (#8037) (Jonathan Wilsson)
-* 834f45d Update: rewrite TokenStore (fixes #7810) (#7936) (Toru Nagashima)
-* 329dcdc Chore: unify checks for statement list parents (#8048) (Teddy Katz)
-* c596690 Docs: Clarify generator-star-spacing config example (fixes #8027) (#8034) (Hòa Trần)
-* a11d4a6 Docs: fix a typo in shareable configs documentation (#8036) (Dan Homola)
-* 1e3d4c6 Update: add fixer for no-unused-labels (#7841) (Teddy Katz)
-* f47fb98 Update: ensure semi-spacing checks import/export declarations (#8033) (Teddy Katz)
-* e228d56 Update: no-undefined handles properties/classes/modules (fixes #7964) (#7966) (Kevin Partington)
-* 7bc92d9 Chore: fix invalid test cases (#8030) (Toru Nagashima)
-
-v3.15.0 - February 3, 2017
-
-* f2a3580 Fix: `no-extra-parens` incorrect precedence (fixes #7978) (#7999) (alberto)
-* d6b6ba1 Fix: no-var should fix ForStatement.init (#7993) (Toru Nagashima)
-* 99d386d Upgrade: Espree v3.4.0 (#8019) (Kai Cataldo)
-* 42390fd Docs: update README.md for team (#8016) (Toru Nagashima)
-* d7ffd88 Chore: enable template-tag-spacing on ESLint codebase (#8005) (Teddy Katz)
-* f2be7e3 Docs: Fix typo in object-curly-newline.md (#8002) (Danny Andrews)
-* df2351a Docs: Fix misleading section in brace-style documentation (#7996) (Teddy Katz)
-* 5ae6e00 Chore: avoid unnecessary feature detection for Symbol (#7992) (Teddy Katz)
-* 5d57c57 Chore: fix no-else-return lint error (refs #7986) (#7994) (Vitor Balocco)
-* 62fb054 Chore: enable no-else-return on ESLint codebase (#7986) (Teddy Katz)
-* c59a0ba Update: add ignoreRestSiblings option to no-unused-vars (#7968) (Zack Argyle)
-* 5cdfa99 Chore: enable no-unneeded-ternary on ESLint codebase (#7987) (Teddy Katz)
-* fbd7c13 Update: ensure operator-assignment handles exponentiation operators (#7970) (Teddy Katz)
-* c5066ce Update: add "variables" option to no-use-before-define (fixes #7111) (#7948) (Teddy Katz)
-* 09546a4 New: `template-tag-spacing` rule (fixes #7631) (#7913) (Jonathan Wilsson)
-
-v3.14.1 - January 25, 2017
-
-* 791f32b Fix: brace-style false positive for keyword method names (fixes #7974) (#7980) (Teddy Katz)
-* d7a0add Docs: Add ESLint tutorial embed to getting started (#7971) (Jamis Charles)
-* 72d41f0 Fix: no-var autofix syntax error in single-line statements (fixes #7961) (#7962) (Teddy Katz)
-* b9e5b68 Fix: indent rule crash on sparse array with object (fixes #7959) (#7960) (Gyandeep Singh)
-* a7bd66a Chore: Adding assign/redeclare tests to no-undefined (refs #7964) (#7965) (Kevin Partington)
-* 8bcbf5d Docs: typo in prefer-promise-reject-errors (#7958) (Patrick McElhaney)
-
-v3.14.0 - January 20, 2017
-
-* 506324a Fix: `no-var` does not fix if causes ReferenceError (fixes #7950) (#7953) (Toru Nagashima)
-* 05e7432 New: no-chained-assignments rule (fixes #6424) (#7904) (Stewart Rand)
-* 243e47d Update: Add fixer for no-else-return (fixes #7863) (#7864) (Xander Dumaine)
-* f091d95 New: `prefer-promise-reject-errors` rule (fixes #7685) (#7689) (Teddy Katz)
-* ca01e00 Fix: recognize all line terminators in func-call-spacing (fixes #7923) (#7924) (Francesco Trotta)
-* a664e8a Update: add ignoreJSX option to no-extra-parens (Fixes #7444) (#7926) (Robert Rossmann)
-* 8ac3518 Fix: no-useless-computed-key false positive with `__proto__` (#7934) (Teddy Katz)
-* c835e19 Docs: remove reference to deleted rule (#7942) (Alejandro Oviedo)
-* 3c1e63b Docs: Improve examples for no-case-declarations (fixes #6716) (#7920) (Kevin Rangel)
-* 7e04b33 Fix: Ignore inline plugin rule config in autoconfig (fixes #7860) (#7919) (Ian VanSchooten)
-* 6448ba0 Fix: add parentheses in no-extra-boolean-cast autofixer (fixes #7912) (#7914) (Szymon Przybylski)
-* b3f2094 Fix: brace-style crash with lone block statements (fixes #7908) (#7909) (Teddy Katz)
-* 5eb2e88 Docs: Correct typos in configuring.md (#7916) (Gabriel Delépine)
-* bd5e219 Update: ensure brace-style validates class bodies (fixes #7608) (#7871) (Teddy Katz)
-* 427543a Fix: catastrophic backtracking in astUtils linebreak regex (fixes #7893) (#7898) (Teddy Katz)
-* 995554c Fix: Correct typos in no-alert.md and lib/ast-utils.js (#7905) (Stewart Rand)
-* d6150e3 Chore: Enable comma-dangle on ESLint codebase (fixes #7725) (#7906) (Teddy Katz)
-* 075ec25 Chore: update to use ES6 classes (refs #7849) (#7891) (Claire Dranginis)
-* 55f0cb6 Update: refactor brace-style and fix inconsistencies (fixes #7869) (#7870) (Teddy Katz)
-
-v3.13.1 - January 9, 2017
-
-* 3fc4e3f Fix: prefer-destructuring reporting compound assignments (fixes #7881) (#7882) (Teddy Katz)
-* f90462e Fix: no-extra-label autofix should not remove labels used elsewhere (#7885) (Teddy Katz)
-
-v3.13.0 - January 6, 2017
-
-* cd4c025 Update: add fixer for no-extra-label (#7840) (Teddy Katz)
-* aa75c92 Fix: Ensure prefer-const fixes destructuring assignments (fixes #7852) (#7859) (Teddy Katz)
-* 4008022 Chore: Refactor to use ES6 Classes (Part 3)(refs #7849) (#7865) (Gyandeep Singh)
-* c9ba40a Update: add fixer for `no-unneeded-ternary` (#7540) (Teddy Katz)
-* dd56d87 Update: add object-shorthand option for arrow functions (fixes #7564) (#7746) (Teddy Katz)
-* fbafdc0 Docs: `padded-blocks` `never` case (fixes #7868) (#7878) (alberto)
-* ca1f841 Fix: no-useless-return stack overflow on loops after throw (fixes #7855) (#7856) (Teddy Katz)
-* d80d994 Update: add fixer for object-property-newline (fixes #7740) (#7808) (Teddy Katz)
-* bf3ea3a Fix: capitalized-comments: Ignore consec. comments if first is invalid (#7835) (Kevin Partington)
-* 616611a Chore: Refactor to use ES6 Classes (Part 2)(refs #7849) (#7847) (Gyandeep Singh)
-* 856084b Chore: Refactor to use ES6 Classes (Part 1)(refs #7849) (#7846) (Gyandeep Singh)
-* bf45893 Docs: Clarify that we only support Stage 4 proposals (#7845) (Kevin Partington)
-* 0fc24f7 Fix: adapt new-paren rule so it handles TypeScript (fixes #7817) (#7820) (Philipp A)
-* df0b06b Fix: no-multiple-empty-lines perf issue on large files (fixes #7803) (#7843) (Teddy Katz)
-* 18fa521 Chore: use ast-utils helper functions in no-multiple-empty-lines (#7842) (Teddy Katz)
-* 7122205 Docs: Array destructuring example for no-unused-vars (fixes #7838) (#7839) (Remco Haszing)
-* e21b36b Chore: add integration tests for cache files (refs #7748) (#7794) (Teddy Katz)
-* 2322733 Fix: Throw error if ruletester is missing required test scenarios (#7388) (Teddy Katz)
-* 1beecec Update: add fixer for `operator-linebreak` (#7702) (Teddy Katz)
-* c5c3b21 Fix: no-implied-eval false positive on 'setTimeoutFoo' (fixes #7821) (#7836) (Teddy Katz)
-* 00dd96c Chore: enable array-bracket-spacing on ESLint codebase (#7830) (Teddy Katz)
-* ebcae1f Update: no-return-await with with complex `return` argument (fixes #7594) (#7595) (Dalton Santos)
-* fd4cd3b Fix: Disable no-var autofixer in some incorrect cases in loops (#7811) (Alan Pierce)
-* 1f25834 Docs: update outdated info in Architecture page (#7816) (Teddy Katz)
-* f20b9e9 Fix: Relax no-useless-escape's handling of ']' in regexes (fixes #7789) (#7793) (Teddy Katz)
-* 3004c1e Fix: consistent-return shouldn't report class constructors (fixes #7790) (#7797) (Teddy Katz)
-* b938f1f Docs: Add an example for the spread operator to prefer-spread.md (#7802) (#7804) (butlermd)
-* b8ce2dc Docs: Remove .html extensions from links in developer-guide (#7805) (Kevin Partington)
-* aafebb2 Docs: Wrap placeholder sample in {% raw %} (#7798) (Daniel Lo Nigro)
-* bb6b73b Chore: replace unnecessary function callbacks with arrow functions (#7795) (Teddy Katz)
-* 428fbdf Fix: func-call-spacing "never" doesn't fix w/ line breaks (fixes #7787) (#7788) (Kevin Partington)
-* 6e61070 Fix: `semi` false positive before regex/template literals (fixes #7782) (#7783) (Teddy Katz)
-* ff0c050 Fix: remove internal property from config generation (fixes #7758) (#7761) (alberto)
-* 27424cb New: `prefer-destructuring` rule (fixes #6053) (#7741) (Alex LaFroscia)
-* bb648ce Docs: fix unclear example for no-useless-escape (#7781) (Teddy Katz)
-* 8c3a962 Fix: syntax errors from object-shorthand autofix (fixes #7744) (#7745) (Teddy Katz)
-* 8b296a2 Docs: fix in semi.md: correct instead of incorrect (#7779) (German Prostakov)
-* 3493241 Upgrade: strip-json-comments ~v2.0.1 (Janus Troelsen)
-* 75b7ba4 Chore: enable object-curly-spacing on ESLint codebase (refs #7725) (#7770) (Teddy Katz)
-* 7d1dc7e Update: Make default-case comment case-insensitive (fixes #7673) (#7742) (Robert Rossmann)
-* f1bf5ec Chore: convert remaining old-style context.report() calls to the new API (#7763) (Teddy Katz)
-
-v3.12.2 - December 14, 2016
-
-* dec3ec6 Fix: indent bug with AssignmentExpressions (fixes #7747) (#7750) (Teddy Katz)
-* 5344751 Build: Don't create blogpost links from rule names within other words (#7754) (Teddy Katz)
-* 639b798 Docs: Use `Object.prototype` in examples (#7755) (Alex Reardon)
-
-v3.12.1 - December 12, 2016
-
-* 0ad4d33 Fix: `indent` regression with function calls (fixes #7732, fixes #7733) (#7734) (Teddy Katz)
-* ab246dd Docs: Rules restricting globals/properties/syntax are linked together (#7743) (Kevin Partington)
-* df2f115 Docs: Add eslint-config-mdcs to JSCS Migration Guide (#7737) (Joshua Koo)
-* 4b77333 Build: avoid creating broken rule links in the changelog (#7731) (Teddy Katz)
-
-v3.12.0 - December 9, 2016
-
-* e569225 Update: fix false positive/negative of yoda rule (fixes #7676) (#7695) (Toru Nagashima)
-* e95a230 Fix: indent "first" option false positive on nested arrays (fixes #7727) (#7728) (Teddy Katz)
-* 81f9e7d Fix: Allow duplicated let declarations in `prefer-const` (fixes #7712) (#7717) (Teddy Katz)
-* 1d0d61d New: Add no-await-in-loop rule (#7563) (Nat Mote)
-* 2cdfb4e New: Additional APIs (fixes #6256) (#7669) (Ilya Volodin)
-* 4278c42 Update: make no-obj-calls report errors for Reflect (fixes #7700) (#7710) (Tomas Echeverri Valencia)
-* 4742d82 Docs: clarify the default behavior of `operator-linebreak` (fixes #7459) (#7726) (Teddy Katz)
-* a8489e2 Chore: Avoid parserOptions boilerplate in tests for ES6 rules (#7724) (Teddy Katz)
-* b921d1f Update: add `indent` options for array and object literals (fixes #7473) (#7681) (Teddy Katz)
-* 7079c89 Update: Add airbnb-base to init styleguides (fixes #6986) (#7699) (alberto)
-* 63bb3f8 Docs: improve the documentation for the autofix API (#7716) (Teddy Katz)
-* f8786fb Update: add fixer for `capitalized-comments` (#7701) (Teddy Katz)
-* abfd24f Fix: don't validate schemas for disabled rules (fixes #7690) (#7692) (Teddy Katz)
-* 2ac07d8 Upgrade: Update globals dependency to 9.14.0 (#7683) (Aleksandr Oleynikov)
-* 90a5d29 Docs: Remove incorrect info about issue requirements from PR guide (#7691) (Teddy Katz)
-* f80c278 Docs: Add sails-hook-lint to integrations list (#7679) (Anthony M)
-* e96da3f Docs: link first instance of `package.json` (#7684) (Kent C. Dodds)
-* bf20e20 Build: include links to rule pages in release blogpost (#7671) (Teddy Katz)
-* b30116c Docs: Fix code-blocks in spaced-comment docs (#7524) (Michał Gołębiowski)
-* 0a2a7fd Fix: Allow \u2028 and \u2029 as string escapes in no-useless-escape (#7672) (Teddy Katz)
-* 76c33a9 Docs: Change Sails.js integration to active npm package (#7675) (Anthony M)
-
-v3.11.1 - November 28, 2016
-
-* be739d0 Fix: capitalized-comments fatal error fixed (fixes #7663) (#7664) (Rich Trott)
-* cc4cedc Docs: Fix a typo in array-bracket-spacing documentation (#7667) (Alex Guerrero)
-* f8adadc Docs: fix a typo in capitalized-comments documentation (#7666) (Teddy Katz)
-
-v3.11.0 - November 25, 2016
-
-* ad56694 New: capitalized-comments rule (fixes #6055) (#7415) (Kevin Partington)
-* 7185567 Update: add fixer for `operator-assignment` (#7517) (Teddy Katz)
-* faf5f56 Update: fix false negative of `quotes` with \n in template (fixes #7646) (#7647) (Teddy Katz)
-* 474e444 Update: add fixer for `sort-imports` (#7535) (Teddy Katz)
-* f9b70b3 Docs: Enable example highlighting in rules examples (ref #6444) (#7644) (Alex Guerrero)
-* d50f6c1 Fix: incorrect location for `no-useless-escape` errors (fixes #7643) (#7645) (Teddy Katz)
-* 54a993c Docs: Fix a typo in the require-yield.md (#7652) (Vse Mozhet Byt)
-* eadd808 Chore: Fix prefer-arrow-callback lint errors (#7651) (Kevin Partington)
-* 89bd8de New: `require-await` rule (fixes #6820) (#7435) (Toru Nagashima)
-* b7432bd Chore: Ensure JS files are checked out with LF (#7624) (Kevin Partington)
-* 32a3547 Docs: Add absent quotes in rules documentation (#7625) (Denis Sikuler)
-* 5c9a4ad Fix: Prevent `quotes` from fixing templates to directives (fixes #7610) (#7617) (Teddy Katz)
-* d90ca46 Upgrade: Update markdownlint dependency to 0.3.1 (fixes #7589) (#7592) (David Anson)
-* 07124d1 Docs: add missing quote mark (+=" → "+=") (#7613) (Sean Juarez)
-* 8998043 Docs: fix wording in docs for no-extra-parens config (Michael Ficarra)
-
-v3.10.2 - November 15, 2016
-
-* 0643bfe Fix: correctly handle commented code in `indent` autofixer (fixes #7604) (#7606) (Teddy Katz)
-* bd0514c Fix: syntax error after `key-spacing` autofix with comment (fixes #7603) (#7607) (Teddy Katz)
-* f56c1ef Fix: `indent` crash on parenthesized global return values (fixes #7573) (#7596) (Teddy Katz)
-* 100c6e1 Docs: Fix example for curly "multi-or-nest" option (#7597) (Will Chen)
-* 6abb534 Docs: Update code of conduct link (#7599) (Nicholas C. Zakas)
-* 8302cdb Docs: Update no-tabs to match existing standards & improve readbility (#7590) (Matt Stow)
-
-v3.10.1 - November 14, 2016
-
-* 8a0e92a Fix: handle try/catch correctly in `no-return-await` (fixes #7581) (#7582) (Teddy Katz)
-* c4dd015 Fix: no-useless-return stack overflow on unreachable loops (fixes #7583) (#7584) (Teddy Katz)
-
-v3.10.0 - November 11, 2016
-
-* 7ee039b Update: Add comma-style options for calls, fns, imports (fixes #7470) (Max Englander)
-* 670e060 Chore: make the `object-shorthand` tests more readable (#7580) (Teddy Katz)
-* c3f4809 Update: Allow `func-names` to recognize inferred ES6 names (fixes #7235) (#7244) (Logan Smyth)
-* b8d6e48 Fix: syntax errors created by `object-shorthand` autofix (fixes #7574) (#7575) (Teddy Katz)
-* 1b3b65c Chore: ensure that files in tests/conf are linted (#7579) (Teddy Katz)
-* 2bd1dd7 Update: avoid creating extra whitespace in `arrow-body-style` fixer (#7504) (Teddy Katz)
-* 66fe9ff New: `no-return-await` rule. (fixes #7537) (#7547) (Jordan Harband)
-* 759525e Chore: Use process.exitCode instead of process.exit() in bin/eslint.js (#7569) (Teddy Katz)
-* 0d60db7 Fix: Curly rule doesn't account for leading comment (fixes #7538) (#7539) (Will Chen)
-* 5003b1c Update: fix in/instanceof handling with `space-infix-ops` (fixes #7525) (#7552) (Teddy Katz)
-* 3e6131e Docs: explain config option merging (#7499) (Danny Andrews)
-* 1766524 Update: "Error type should be" assertion in rule-tester (fixes 6106) (#7550) (Frans Jaspers)
-* 44eb274 Docs: Missing semicolon report was missing a comma (#7553) (James)
-* 6dbda15 Docs: Document the optional defaults argument for RuleTester (#7548) (Teddy Katz)
-* e117b80 Docs: typo fix (#7546) (oprogramador)
-* 25e5613 Chore: Remove incorrect test from indent.js. (#7531) (Scott Stern)
-* c0f4937 Fix: `arrow-parens` supports type annotations (fixes #7406) (#7436) (Toru Nagashima)
-* a838b8e Docs: `func-name-matching`: update with “always”/“never” option (#7536) (Jordan Harband)
-* 3c379ff Update: `no-restricted-{imports,modules}`: add “patterns” (fixes #6963) (#7433) (Jordan Harband)
-* f5764ee Docs: Update example of results returned from `executeOnFiles` (#7362) (Simen Bekkhus)
-* 4613ba0 Fix: Add support for escape char in JSX. (#7461) (Scott Stern)
-* ea0970d Fix: `curly` false positive with no-semicolon style (#7509) (Teddy Katz)
-* af1fde1 Update: fix `brace-style` false negative on multiline node (fixes #7493) (#7496) (Teddy Katz)
-* 3798aea Update: max-statements to report function name (refs #7260) (#7399) (Nicholas C. Zakas)
-* 0c215fa Update: Add `ArrowFunctionExpression` support to `require-jsdoc` rule (#7518) (Gyandeep Singh)
-* 578c373 Build: handle deprecated rules with no 'replacedBy' (refs #7471) (#7494) (Vitor Balocco)
-* a7f3976 Docs: Specify min ESLint version for new rule format (#7501) (cowchimp)
-* 8a3e717 Update: Fix `lines-around-directive` semicolon handling (fixes #7450) (#7483) (Teddy Katz)
-* e58cead Update: add a fixer for certain statically-verifiable `eqeqeq` cases (#7389) (Teddy Katz)
-* 0dea0ac Chore: Add Node 7 to travis ci build (#7506) (Gyandeep Singh)
-* 36338f0 Update: add fixer for `no-extra-boolean-cast` (#7387) (Teddy Katz)
-* 183def6 Chore: enable `prefer-arrow-callback` on ESLint codebase (fixes #6407) (#7503) (Teddy Katz)
-* 4f1fa67 Docs: Update copyright (#7497) (Nicholas C. Zakas)
-
-v3.9.1 - October 31, 2016
-
-* 2012258 Fix: incorrect `indent` check for array property access (fixes #7484) (#7485) (Teddy Katz)
-* 8a71d4a Fix: `no-useless-return` false positive on conditionals (fixes #7477) (#7482) (Teddy Katz)
-* 56a662b Fix: allow escaped backreferences in `no-useless-escape` (fixes #7472) (#7474) (Teddy Katz)
-* fffdf13 Build: Fix prefer-reflect rule to not crash site gen build (#7471) (Ilya Volodin)
-* 8ba68a3 Docs: Update broken link (#7490) (Devinsuit)
-* 65231d8 Docs: add the "fixable" icon for `no-useless-return` (#7480) (Teddy Katz)
-
-v3.9.0 - October 28, 2016
-
-* d933516 New: `no-useless-return` rule (fixes #7309) (#7441) (Toru Nagashima)
-* 5e7af30 Update: Add `CallExpression` option for `indent` (fixes #5946) (#7189) (Teddy Katz)
-* b200086 Fix: Support type annotations in array-bracket-spacing (#7445) (Jimmy Jia)
-* 5ed8b9b Update: Deprecate prefer-reflect (fixes #7226) (#7464) (Kai Cataldo)
-* 92ad43b Chore: Update deprecated rules in conf/eslint.json (#7467) (Kai Cataldo)
-* e46666b New: Codeframe formatter (fixes #5860) (#7437) (Vitor Balocco)
-* fe0d903 Upgrade: Shelljs to ^0.7.5 (fixes #7316) (#7465) (Gyandeep Singh)
-* 1d5146f Update: fix wrong indentation about `catch`,`finally` (#7371) (Toru Nagashima)
-* 77e3a34 Chore: Pin mock-fs dev dependency (#7466) (Gyandeep Singh)
-* c675d7d Update: Fix `no-useless-escape` false negative in regexes (fixes #7424) (#7425) (Teddy Katz)
-* ee3bcea Update: add fixer for `newline-after-var` (fixes #5959) (#7375) (Teddy Katz)
-* 6e9ff08 Fix: indent.js to support multiline array statements. (#7237) (Scott Stern)
-* f8153ad Build: Ensure absolute links in docs retain .md extensions (fixes #7419) (#7438) (Teddy Katz)
-* 16367a8 Fix: Return statement spacing. Fix for indent rule. (fixes #7164) (#7197) (Imad Elyafi)
-* 3813988 Update: fix false negative of `no-extra-parens` (fixes #7122) (#7432) (Toru Nagashima)
-* 23062e2 Docs: Fix typo in no-unexpected-multiline (fixes #7442) (#7447) (Denis Sikuler)
-* d257428 Update: `func-name-matching`: add “always”/“never” option (fixes #7391) (#7428) (Jordan Harband)
-* c710584 Fix: support for MemberExpression with function body. (#7400) (Scott Stern)
-* 2c8ed2d Build: ensure that all files are linted on bash (fixes #7426) (#7427) (Teddy Katz)
-* 18ff70f Chore: Enable `no-useless-escape` (#7403) (Vitor Balocco)
-* 8dfd802 Fix: avoid `camelcase` false positive with NewExpressions (fixes #7363) (#7409) (Teddy Katz)
-* e8159b4 Docs: Fix typo and explain static func calls for class-methods-use-this (#7421) (Scott O'Hara)
-* 85d7e24 Docs: add additional examples for MemberExpressions in Indent rule. (#7408) (Scott Stern)
-* 2aa1107 Docs: Include note on fatal: true in the node.js api section (#7376) (Simen Bekkhus)
-* e064a25 Update: add fixer for `arrow-body-style` (#7240) (Teddy Katz)
-* e0fe727 Update: add fixer for `brace-style` (fixes #7074) (#7347) (Teddy Katz)
-* cbbe420 New: Support enhanced parsers (fixes #6974) (#6975) (Nicholas C. Zakas)
-* 644d25b Update: Add an ignoreRegExpLiterals option to max-len (fixes #3229) (#7346) (Wilfred Hughes)
-* 6875576 Docs: Remove broken links to jslinterrors.com (fixes #7368) (#7369) (Dannii Willis)
-
-v3.8.1 - October 17, 2016
-
-* 681c78a Fix: `comma-dangle` was confused by type annotations (fixes #7370) (#7372) (Toru Nagashima)
-* 7525042 Fix: Allow useless escapes in tagged template literals (fixes #7383) (#7384) (Teddy Katz)
-* 9106964 Docs: Fix broken link for stylish formatter (#7386) (Vitor Balocco)
-* 49d3c1b Docs: Document the deprecated meta property (#7367) (Randy Coulman)
-* 19d2996 Docs: Relax permission for merging PRs (refs eslint/tsc-meetings#20) (#7360) (Brandon Mills)
-
-v3.8.0 - October 14, 2016
-
-* ee60acf Chore: add integration tests for autofixing (fixes #5909) (#7349) (Teddy Katz)
-* c8796e9 Update: `comma-dangle` supports trailing function commas (refs #7101) (#7181) (Toru Nagashima)
-* c4abaf0 Update: `space-before-function-paren` supports async/await (refs #7101) (#7180) (Toru Nagashima)
-* d0d3b28 Fix: id-length rule incorrectly firing on member access (fixes #6475) (#7365) (Burak Yiğit Kaya)
-* 2729d94 Fix: Don't report setter params in class bodies as unused (fixes #7351) (#7352) (Teddy Katz)
-* 0b85004 Chore: Enable prefer-template (fixes #6407) (#7357) (Kai Cataldo)
-* ca1947b Chore: Update pull request template (refs eslint/tsc-meetings#20) (#7359) (Brandon Mills)
-* d840afe Docs: remove broken link from no-loop-func doc (#7342) (Michael McDermott)
-* 5266793 Update: no-useless-escape checks template literals (fixes #7331) (#7332) (Kai Cataldo)
-* b08fb91 Update: add source property to LintResult object (fixes #7098) (#7304) (Vitor Balocco)
-* 0db4164 Chore: run prefer-template autofixer on test files (refs #6407) (#7354) (Kai Cataldo)
-* c1470b5 Update: Make the `prefer-template` fixer unescape quotes (fixes #7330) (#7334) (Teddy Katz)
-* 5d08c33 Fix: Handle parentheses correctly in `yoda` fixer (fixes #7326) (#7327) (Teddy Katz)
-* cd72bba New: `func-name-matching` rule (fixes #6065) (#7063) (Annie Zhang)
-* 55b5146 Fix: `RuleTester` didn't support `mocha --watch` (#7287) (Toru Nagashima)
-* f8387c1 Update: add fixer for `prefer-spread` (#7283) (Teddy Katz)
-* 52da71e Fix: Don't require commas after rest properties (fixes #7297) (#7298) (Teddy Katz)
-* 3b11d3f Chore: refactor `no-multiple-empty-lines` (#7314) (Teddy Katz)
-* 16d495d Docs: Updating CLI overview with latest changes (#7335) (Kevin Partington)
-* 52dfce5 Update: add fixer for `one-var-declaration-per-line` (#7295) (Teddy Katz)
-* 0e994ae Update: Improve the error messages for `no-unused-vars` (fixes #7282) (#7315) (Teddy Katz)
-* 93214aa Chore: Convert non-lib/test files to template literals (refs #6407) (#7329) (Kai Cataldo)
-* 72f394d Update: Fix false negative of `no-multiple-empty-lines` (fixes #7312) (#7313) (Teddy Katz)
-* 756bc5a Update: Use characters instead of code units for `max-len` (#7299) (Teddy Katz)
-* c9a7ec5 Fix: Improving optionator configuration for --print-config (#7206) (Kevin Partington)
-* 51bfade Fix: avoid `object-shorthand` crash with spread properties (fixes #7305) (#7306) (Teddy Katz)
-* a12d1a9 Update: add fixer for `no-lonely-if` (#7202) (Teddy Katz)
-* 1418384 Fix: Don't require semicolons before `++`/`--` (#7252) (Adrian Heine né Lang)
-* 2ffe516 Update: add fixer for `curly` (#7105) (Teddy Katz)
-* ac3504d Update: add functionPrototypeMethods to wrap-iife (fixes #7212) (#7284) (Eli White)
-* 5e16fb4 Update: add fixer for `no-extra-bind` (#7236) (Teddy Katz)
-
-v3.7.1 - October 3, 2016
-
-* 3dcae13 Fix: Use the correct location for `comma-dangle` errors (fixes #7291) (#7292) (Teddy Katz)
-* cb7ba6d Fix: no-implicit-coercion should not fix ~. (fixes #7272) (#7289) (Eli White)
-* ce590e2 Chore: Add additional tests for bin/eslint.js (#7290) (Teddy Katz)
-* 8ec82ee Docs: change links of templates to raw data (#7288) (Toru Nagashima)
-
-v3.7.0 - September 30, 2016
-
-* 2fee8ad Fix: object-shorthand's consistent-as-needed option (issue #7214) (#7215) (Naomi Jacobs)
-* c05a19c Update: add fixer for `prefer-numeric-literals` (#7205) (Teddy Katz)
-* 2f171f3 Update: add fixer for `no-undef-init` (#7210) (Teddy Katz)
-* 876d747 Docs: Steps for adding new committers/TSCers (#7221) (Nicholas C. Zakas)
-* dffb4fa Fix: `no-unused-vars` false positive (fixes #7250) (#7258) (Toru Nagashima)
-* 4448cec Docs: Adding missing ES8 reference to configuring (#7271) (Kevin Partington)
-* 332d213 Update: Ensure `indent` handles nested functions correctly (fixes #7249) (#7265) (Teddy Katz)
-* c36d842 Update: add fixer for `no-useless-computed-key` (#7207) (Teddy Katz)
-* 18376cf Update: add fixer for `lines-around-directive` (#7217) (Teddy Katz)
-* f8e8fab Update: add fixer for `wrap-iife` (#7196) (Teddy Katz)
-* 558b444 Docs: Add @not-an-aardvark to development team (#7279) (Ilya Volodin)
-* cd1dc57 Update: Add a fixer for `dot-location` (#7186) (Teddy Katz)
-* 89787b2 Update: for `yoda`, add a fixer (#7199) (Teddy Katz)
-* 742ae67 Fix: avoid indent and no-mixed-spaces-and-tabs conflicts (fixes #7248) (#7266) (Teddy Katz)
-* 85b8714 Fix: Use error templates even when reading from stdin (fixes #7213) (#7223) (Teddy Katz)
-* 66adac1 Docs: correction in prefer-reflect docs (fixes #7069) (#7150) (Scott Stern)
-* e3f95de Update: Fix `no-extra-parens` false negative (fixes #7229) (#7231) (Teddy Katz)
-* 2909c19 Docs: Fix typo in object-shorthand docs (#7267) (Brian Donovan)
-* 7bb800d Chore: add internal rule to enforce meta.docs conventions (fixes #6954) (#7155) (Vitor Balocco)
-* 722c68c Docs: add code fences to the issue template (#7254) (Teddy Katz)
-
-v3.6.1 - September 26, 2016
-
-* b467436 Upgrade: Upgrade Espree to 3.3.1 (#7253) (Ilya Volodin)
-* 299a563 Build: Do not strip .md extension from absolute URLs (#7222) (Kai Cataldo)
-* 27042d2 Chore: removed unused code related to scopeMap (#7218) (Yang Su)
-* d154204 Chore: Lint bin/eslint.js (#7243) (Kevin Partington)
-* 87625fa Docs: Improve eol-last examples in docs (#7227) (Chainarong Tangsurakit)
-* de8eaa4 Docs: `class-methods-use-this`: fix option name (#7224) (Jordan Harband)
-* 2355f8d Docs: Add Brunch plugin to integrations (#7225) (Aleksey Shvayka)
-* a5817ae Docs: Default option from `operator-linebreak` is `after`and not always (#7228) (Konstantin Pschera)
-
-v3.6.0 - September 23, 2016
-
-* 1b05d9c Update: add fixer for `strict` (fixes #6668) (#7198) (Teddy Katz)
-* 0a36138 Docs: Update ecmaVersion instructions (#7195) (Nicholas C. Zakas)
-* aaa3779 Update: Allow `space-unary-ops` to handle await expressions (#7174) (Teddy Katz)
-* 91bf477 Update: add fixer for `prefer-template` (fixes #6978) (#7165) (Teddy Katz)
-* 745343f Update: `no-extra-parens` supports async/await (refs #7101) (#7178) (Toru Nagashima)
-* 8e1fee1 Fix: Handle number literals correctly in `no-whitespace-before-property` (#7185) (Teddy Katz)
-* 462a3f7 Update: `keyword-spacing` supports async/await (refs #7101) (#7179) (Toru Nagashima)
-* 709a734 Update: Allow template string in `valid-typeof` comparison (fixes #7166) (#7168) (Teddy Katz)
-* f71937a Fix: Don't report async/generator callbacks in `array-callback-return` (#7172) (Teddy Katz)
-* 461b015 Fix: Handle async functions correctly in `prefer-arrow-callback` fixer (#7173) (Teddy Katz)
-* 7ea3e4b Fix: Handle await expressions correctly in `no-unused-expressions` (#7175) (Teddy Katz)
-* 16bb802 Update: Ensure `arrow-parens` handles async arrow functions correctly (#7176) (Teddy Katz)
-* 2d10657 Chore: add tests for `generator-star-spacing` and async (refs #7101) (#7182) (Toru Nagashima)
-* c118d21 Update: Let `no-restricted-properties` check destructuring (fixes #7147) (#7151) (Teddy Katz)
-* 9e0b068 Fix: valid-jsdoc does not throw on FieldType without value (fixes #7184) (#7187) (Kai Cataldo)
-* 4b5d9b7 Docs: Update process for evaluating proposals (fixes #7156) (#7183) (Kai Cataldo)
-* 95c777a Update: Make `no-restricted-properties` more flexible (fixes #7137) (#7139) (Teddy Katz)
-* 0fdf23c Update: fix `quotes` rule's false negative (fixes #7084) (#7141) (Toru Nagashima)
-* f2a789d Update: fix `no-unused-vars` false negative (fixes #7124) (#7143) (Toru Nagashima)
-* 6148d85 Fix: Report columns for `eol-last` correctly (fixes #7136) (#7149) (kdex)
-* e016384 Update: add fixer for quote-props (fixes #6996) (#7095) (Teddy Katz)
-* 35f7be9 Upgrade: espree to 3.2.0, remove tests with SyntaxErrors (fixes #7169) (#7170) (Teddy Katz)
-* 28ddcf8 Fix: `max-len`: `ignoreTemplateLiterals`: handle 3+ lines (fixes #7125) (#7138) (Jordan Harband)
-* 660e091 Docs: Update rule descriptions (fixes #5912) (#7152) (Kenneth Williams)
-* 8b3fc32 Update: Make `indent` report lines with mixed spaces/tabs (fixes #4274) (#7076) (Teddy Katz)
-* b39ac2c Update: add fixer for `no-regex-spaces` (#7113) (Teddy Katz)
-* cc80467 Docs: Update PR templates for formatting (#7128) (Nicholas C. Zakas)
-* 76acbb5 Fix: include LogicalExpression in indent length calc (fixes #6731) (#7087) (Alec)
-* a876673 Update: no-implicit-coercion checks TemplateLiterals (fixes #7062) (#7121) (Kai Cataldo)
-* 8db4f0c Chore: Enable `typeof` check for `no-undef` rule in eslint-config-eslint (#7103) (Teddy Katz)
-* 7e8316f Docs: Update release process (#7127) (Nicholas C. Zakas)
-* 22edd8a Update: `class-methods-use-this`: `exceptMethods` option (fixes #7085) (#7120) (Jordan Harband)
-* afd132a Fix: line-comment-position "above" string option now works (fixes #7100) (#7102) (Kevin Partington)
-* 1738b2e Chore: fix name of internal-no-invalid-meta test file (#7142) (Vitor Balocco)
-* ac0bb62 Docs: Fixes examples for allowTemplateLiterals (fixes #7115) (#7135) (Zoe Ingram)
-* bcfa3e5 Update: Add `always`/`never` option to `eol-last` (fixes #6938) (#6952) (kdex)
-* 0ca26d9 Docs: Distinguish examples for space-before-blocks (#7132) (Timo Tijhof)
-* 9a2aefb Chore: Don't require an issue reference in check-commit npm script (#7104) (Teddy Katz)
-* c85fd84 Fix: max-statements-per-line rule to force minimum to be 1 (fixes #7051) (#7092) (Scott Stern)
-* e462e47 Docs: updates category of no-restricted-properties (fixes #7112) (#7118) (Alec)
-* 6ae660b Fix: Don't report comparisons of two typeof expressions (fixes #7078) (#7082) (Teddy Katz)
-* 710f205 Docs: Fix typos in Issues section of Maintainer's Guide (#7114) (Kai Cataldo)
-* 546a3ca Docs: Clarify that linter does not process configuration (fixes #7108) (#7110) (Kevin Partington)
-* 0d50943 Docs: Elaborate on `guard-for-in` best practice (fixes #7071) (#7094) (Dallon Feldner)
-* 58e6d76 Docs: Fix examples for no-restricted-properties (#7099) (not-an-aardvark)
-* 6cfe519 Docs: Corrected typo in line-comment-position rule doc (#7097) (Alex Mercier)
-* f02e52a Docs: Add fixable note to no-implicit-coercion docs (#7096) (Brandon Mills)
-
-v3.5.0 - September 9, 2016
-
-* 08fa538 Update: fix false negative of `arrow-spacing` (fixes #7079) (#7080) (Toru Nagashima)
-* cec65e3 Update: add fixer for no-floating-decimal (fixes #7070) (#7081) (not-an-aardvark)
-* 2a3f699 Fix: Column number for no-multiple-empty-lines (fixes #7086) (#7088) (Ian VanSchooten)
-* 6947299 Docs: Add info about closing accepted issues to docs (fixes #6979) (#7089) (Kai Cataldo)
-* d30157a Docs: Add link to awesome-eslint in integrations page (#7090) (Vitor Balocco)
-* 457be1b Docs: Update so issues are not required (fixes #7015) (#7072) (Nicholas C. Zakas)
-* d9513b7 Fix: Allow linting of .hidden files/folders (fixes #4828) (#6844) (Ian VanSchooten)
-* 6d97c18 New: `max-len`: `ignoreStrings`+`ignoreTemplateLiterals` (fixes #5805) (#7049) (Jordan Harband)
-* 538d258 Update: make no-implicit-coercion support autofixing. (fixes #7056) (#7061) (Eli White)
-* 883316d Update: add fixer for prefer-arrow-callback (fixes #7002) (#7004) (not-an-aardvark)
-* 7502eed Update: auto-fix for `comma-style` (fixes #6941) (#6957) (Gyandeep Singh)
-* 645dda5 Update: add fixer for dot-notation (fixes #7014) (#7054) (not-an-aardvark)
-* 2657846 Fix: `no-console` ignores user-defined console (fixes #7010) (#7058) (Toru Nagashima)
-* 656bb6e Update: add fixer for newline-before-return (fixes #5958) (#7050) (Vitor Balocco)
-* 1f995c3 Fix: no-implicit-coercion string concat false positive (fixes #7057) (#7060) (Kai Cataldo)
-* 6718749 Docs: Clarify that `es6` env also sets `ecmaVersion` to 6 (#7067) (Jérémie Astori)
-* e118728 Update: add fixer for wrap-regex (fixes #7013) (#7048) (not-an-aardvark)
-* f4fcd1e Update: add more `indent` options for functions (fixes #6052) (#7043) (not-an-aardvark)
-* 657eee5 Update: add fixer for new-parens (fixes #6994) (#7047) (not-an-aardvark)
-* ff19aa9 Update: improve `max-statements-per-line` message (fixes #6287) (#7044) (Jordan Harband)
-* 3960617 New: `prefer-numeric-literals` rule (fixes #6068) (#7029) (Annie Zhang)
-* fa760f9 Chore: no-regex-spaces uses internal rule message format (fixes #7052) (#7053) (Kevin Partington)
-* 22c7e09 Update: no-magic-numbers false negative on reassigned vars (fixes #4616) (#7028) (not-an-aardvark)
-* be29599 Update: Throw error if whitespace found in plugin name (fixes #6854) (#6960) (Jesse Ostrander)
-* 4063a79 Fix: Rule message placeholders can be inside braces (fixes #6988) (#7041) (Kevin Partington)
-* 52e8d9c Docs: Clean up sort-vars (#7045) (Matthew Dunsdon)
-* 4126f12 Chore: Rule messages use internal rule message format (fixes #6977) (#6989) (Kevin Partington)
-* 46cb690 New: `no-restricted-properties` rule (fixes #3218) (#7017) (Eli White)
-* 00b3042 Update: Pass file path to parse function (fixes #5344) (#7024) (Annie Zhang)
-* 3f13325 Docs: Add kaicataldo and JamesHenry to our teams (#7039) (alberto)
-* 8e77f16 Update: `new-parens` false negative (fixes #6997) (#6999) (Toru Nagashima)
-* 326f457 Docs: Add missing 'to' in no-restricted-modules (#7022) (Oskar Risberg)
-* 8277357 New: `line-comment-position` rule (fixes #6077) (#6953) (alberto)
-* c1f0d76 New: `lines-around-directive` rule (fixes #6069) (#6998) (Kai Cataldo)
-* 61f1de0 Docs: Fix typo in no-debugger (#7019) (Denis Ciccale)
-* 256c4a2 Fix: Allow separate mode option for multiline and align (fixes #6691) (#6991) (Annie Zhang)
-* a989a7c Docs: Declaring dependency on eslint in shared config (fixes #6617) (#6985) (alberto)
-* 6869c60 Docs: Fix minor typo in no-extra-parens doc (#6992) (Jérémie Astori)
-* 28f1619 Docs: Update the example of SwitchCase (#6981) (fish)
-
-v3.4.0 - August 26, 2016
-
-* c210510 Update: add fixer for no-extra-parens (fixes #6944) (#6950) (not-an-aardvark)
-* ca3d448 Fix: `prefer-const` false negative about `eslintUsed` (fixes #5837) (#6971) (Toru Nagashima)
-* 1153955 Docs: Draft of JSCS migration guide (refs #5859) (#6942) (Nicholas C. Zakas)
-* 3e522be Fix: false negative of `indent` with `else if` statements (fixes #6956) (#6965) (not-an-aardvark)
-* 2dfb290 Docs: Distinguish examples in rules under Stylistic Issues part 7 (#6760) (Kenneth Williams)
-* 3c710c9 Fix: rename "AirBnB" => "Airbnb" init choice (fixes #6969) (Harrison Shoff)
-* 7660b39 Fix: `object-curly-spacing` for type annotations (fixes #6940) (#6945) (Toru Nagashima)
-* 21ab784 New: do not remove non visited files from cache. (fixes #6780) (#6921) (Roy Riojas)
-* 3a1763c Fix: enable `@scope/plugin/ruleId`-style specifier (refs #6362) (#6939) (Toru Nagashima)
-* d6fd064 Update: Add never option to multiline-ternary (fixes #6751) (#6905) (Kai Cataldo)
-* 0d268f1 New: `symbol-description` rule (fixes #6778) (#6825) (Jarek Rencz)
-* a063d4e Fix: no-cond-assign within a function expression (fixes #6908) (#6909) (Patrick McElhaney)
-* 16db93a Build: Tag docs, publish release notes (fixes #6892) (#6934) (Nicholas C. Zakas)
-* 0cf1d55 Chore: Fix object-shorthand errors (fixes #6958) (#6959) (Kai Cataldo)
-* 8851ddd Fix: Improve pref of globbing by inheriting glob.GlobSync (fixes #6710) (#6783) (Kael Zhang)
-* cf2242c Update: `requireStringLiterals` option for `valid-typeof` (fixes #6698) (#6923) (not-an-aardvark)
-* 8561389 Fix: `no-trailing-spaces` wrong fixing (fixes #6933) (#6937) (Toru Nagashima)
-* 6a92be5 Docs: Update semantic versioning policy (#6935) (alberto)
-* a5189a6 New: `class-methods-use-this` rule (fixes #5139) (#6881) (Gyandeep Singh)
-* 1563808 Update: add support for ecmaVersion 20xx (fixes #6750) (#6907) (Kai Cataldo)
-* d8b770c Docs: Change rule descriptions for consistent casing (#6915) (Brandon Mills)
-* c676322 Chore: Use object-shorthand batch 3 (refs #6407) (#6914) (Kai Cataldo)
-
-v3.3.1 - August 15, 2016
-
-* a2f06be Build: optimize rule page title for small browser tabs (fixes #6888) (#6904) (Vitor Balocco)
-* 02a00d6 Docs: clarify rule details for no-template-curly-in-string (#6900) (not-an-aardvark)
-* b9b3446 Fix: sort-keys ignores destructuring patterns (fixes #6896) (#6899) (Kai Cataldo)
-* 3fe3a4f Docs: Update options in `object-shorthand` (#6898) (Grant Snodgrass)
-* cd09c96 Chore: Use object-shorthand batch 2 (refs #6407) (#6897) (Kai Cataldo)
-* 2841008 Chore: Use object-shorthand batch 1 (refs #6407) (#6893) (Kai Cataldo)
-
-v3.3.0 - August 12, 2016
-
-* 683ac56 Build: Add CI release scripts (fixes #6884) (#6885) (Nicholas C. Zakas)
-* ebf8441 Update: `prefer-rest-params` relax for member accesses (fixes #5990) (#6871) (Toru Nagashima)
-* df01c4f Update: Add regex support for exceptions (fixes #5187) (#6883) (Annie Zhang)
-* 055742c Fix: `no-dupe-keys` type errors (fixes #6886) (#6889) (Toru Nagashima)
-* e456fd3 New: `sort-keys` rule (fixes #6076) (#6800) (Toru Nagashima)
-* 3e879fc Update: Rule "eqeqeq" to have more specific null handling (fixes #6543) (#6849) (Simon Sturmer)
-* e8cb7f9 Chore: use eslint-plugin-node (refs #6407) (#6862) (Toru Nagashima)
-* e37bbd8 Docs: Remove duplicate statement (#6878) (Richard Käll)
-* 11395ca Fix: `no-dupe-keys` false negative (fixes #6801) (#6863) (Toru Nagashima)
-* 1ecd2a3 Update: improve error message in `no-control-regex` (#6839) (Jordan Harband)
-* d610d6c Update: make `max-lines` report the actual number of lines (fixes #6766) (#6764) (Jarek Rencz)
-* b256c50 Chore: Fix glob for core js files for lint (fixes #6870) (#6872) (Gyandeep Singh)
-* f8ab8f1 New: func-call-spacing rule (fixes #6080) (#6749) (Brandon Mills)
-* be68f0b New: no-template-curly-in-string rule (fixes #6186) (#6767) (Jeroen Engels)
-* 80789ab Chore: don't throw if rule is in old format (fixes #6848) (#6850) (Vitor Balocco)
-* d47c505 Fix: `newline-after-var` false positive (fixes #6834) (#6847) (Toru Nagashima)
-* bf0afcb Update: validate void operator in no-constant-condition (fixes #5726) (#6837) (Vitor Balocco)
-* 5ef839e New: Add consistent and ..-as-needed to object-shorthand (fixes #5438) (#5439) (Martijn de Haan)
-* 7e1bf01 Fix: update peerDependencies of airbnb option for `--init` (fixes #6843) (#6846) (Vitor Balocco)
-* 8581f4f Fix: `no-invalid-this` false positive (fixes #6824) (#6827) (Toru Nagashima)
-* 90f78f4 Update: add `props` option to `no-self-assign` rule (fixes #6718) (#6721) (Toru Nagashima)
-* 30d71d6 Update: 'requireForBlockBody' modifier for 'arrow-parens' (fixes #6557) (#6558) (Nicolas Froidure)
-* cdded07 Chore: use native `Object.assign` (refs #6407) (#6832) (Gyandeep Singh)
-* 579ec49 Chore: Add link to rule change guidelines in "needs info" template (fixes #6829) (#6831) (Kevin Partington)
-* 117e7aa Docs: Remove incorrect "constructor" statement from `no-new-symbol` docs (#6830) (Jarek Rencz)
-* aef18b4 New: `no-unsafe-negation` rule (fixes #2716) (#6789) (Toru Nagashima)
-* d94e945 Docs: Update Getting Started w/ Readme installation instructions (#6823) (Kai Cataldo)
-* dfbc112 Upgrade: proxyquire to 1.7.10 (fixes #6821) (#6822) (alberto)
-* 4c5e911 Chore: enable `prefer-const` and apply it to our codebase (refs #6407) (#6805) (Toru Nagashima)
-* e524d16 Update: camelcase rule fix for import declarations (fixes #6755) (#6784) (Lorenzo Zottar)
-* 8f3509d Update: make `eslint:all` excluding deprecated rules (fixes #6734) (#6756) (Toru Nagashima)
-* 2b17459 New: `no-global-assign` rule (fixes #6586) (#6746) (alberto)
-
-v3.2.2 - August 1, 2016
-
-* 510ce4b Upgrade: file-entry-cache@^1.3.1 (fixes #6816, refs #6780) (#6819) (alberto)
-* 46b14cd Fix: ignore MemberExpression in VariableDeclarators (fixes #6795) (#6815) (Nicholas C. Zakas)
-
-v3.2.1 - August 1, 2016
-
-* 584577a Build: Pin file-entry-cache to avoid licence issue (refs #6816) (#6818) (alberto)
-* 38d0d23 Docs: clarify minor releases and suggest using `~ to version (#6804) (Henry Zhu)
-* 4ca809e Fix: Normalizes messages so all end with a period (fixes #6762) (#6807) (Patrick McElhaney)
-* c7488ac Fix: Make MemberExpression option opt-in (fixes #6797) (#6798) (Rich Trott)
-* 715e8fa Docs: Update issue closing policy (fixes #6765) (#6808) (Nicholas C. Zakas)
-* 288f7bf Build: Fix site generation (fixes #6791) (#6793) (Nicholas C. Zakas)
-* 261a9f3 Docs: Update JSCS status in README (#6802) (alberto)
-* 5ae0887 Docs: Update no-void.md (#6799) (Daniel Hritzkiv)
-
-v3.2.0 - July 29, 2016
-
-* 2438ee2 Upgrade: Update markdownlint dependency to 0.2.0 (fixes #6781) (#6782) (David Anson)
-* 4fc0018 Chore: dogfooding `no-var` rule and remove `var`s (refs #6407) (#6757) (Toru Nagashima)
-* b22eb5c New: `no-tabs` rule (fixes #6079) (#6772) (Gyandeep Singh)
-* ddea63a Chore: Updated no-control-regex tests to cover all cases (fixes #6438) (#6752) (Efe Gürkan YALAMAN)
-* 1025772 Docs: Add plugin example to disabling with comments guide (fixes #6742) (#6747) (Brandon Mills)
-* 628aae4 Docs: fix inconsistent spacing inside block comment (#6768) (Brian Jacobel)
-* 2983c32 Docs: Add options to func-names config comments (#6748) (Brandon Mills)
-* 2f94443 Docs: fix wrong path (#6763) (molee1905)
-* 6f3faa4 Revert "Build: Remove support for Node v5 (fixes #6743)" (#6758) (Nicholas C. Zakas)
-* 99dfd1c Docs: fix grammar issue in rule-changes page (#6761) (Vitor Balocco)
-* e825458 Fix: Rule no-unused-vars had missing period (fixes #6738) (#6739) (Brian Mock)
-* 71ae64c Docs: Clarify cache file deletion (fixes #4943) (#6712) (Nicholas C. Zakas)
-* 26c85dd Update: merge warnings of consecutive unreachable nodes (fixes #6583) (#6729) (Toru Nagashima)
-* 106e40b Fix: Correct grammar in object-curly-newline reports (fixes #6725) (#6728) (Vitor Balocco)
-* e00754c Chore: Dogfooding ES6 rules (refs #6407) (#6735) (alberto)
-* 181b26a Build: Remove support for Node v5 (fixes #6743) (#6744) (alberto)
-* 5320a6c Update: `no-use-before-define` false negative on for-in/of (fixes #6699) (#6719) (Toru Nagashima)
-* a2090cb Fix: space-infix-ops doesn't fail for type annotations(fixes #5211) (#6723) (Nicholas C. Zakas)
-* 9c36ecf Docs: Add @vitorbal and @platinumazure to development team (Ilya Volodin)
-* e09d1b8 Docs: describe all RuleTester options (fixes #4810, fixes #6709) (#6711) (Nicholas C. Zakas)
-* a157f47 Chore: Update CLIEngine option desc (fixes #5179) (#6713) (Nicholas C. Zakas)
-* a0727f9 Chore: fix `.gitignore` for vscode (refs #6383) (#6720) (Toru Nagashima)
-* 75d2d43 Docs: Clarify Closure type hint expectation (fixes #5231) (#6714) (Nicholas C. Zakas)
-* 95ea25a Update: Check indentation of multi-line chained properties (refs #1801) (#5940) (Rich Trott)
-* e7b1e1c Docs: Edit issue/PR waiting period docs (fixes #6009) (#6715) (Nicholas C. Zakas)
-* 053aa0c Update: Added 'allowSuper' option to `no-underscore-dangle` (fixes #6355) (#6662) (peteward44)
-* 8929045 Build: Automatically generate rule index (refs #2860) (#6658) (Ilya Volodin)
-* f916ae5 Docs: Fix multiline-ternary typos (#6704) (Cédric Malard)
-* c64b0c2 Chore: First ES6 refactoring (refs #6407) (#6570) (Nicholas C. Zakas)
-
-v3.1.1 - July 18, 2016
-
-* 565e584 Fix: `eslint:all` causes regression in 3.1.0 (fixes #6687) (#6696) (alberto)
-* cb90359 Fix: Allow named recursive functions (fixes #6616) (#6667) (alberto)
-* 3f206dd Fix: `balanced` false positive in `spaced-comment` (fixes #6689) (#6692) (Grant Snodgrass)
-* 57f1676 Docs: Add missing brackets from code examples (#6700) (Plusb Preco)
-* 124f066 Chore: Remove fixable key from multiline-ternary metadata (fixes #6683) (#6688) (Kai Cataldo)
-* 9f96086 Fix: Escape control characters in XML. (fixes #6673) (#6672) (George Chung)
-
-v3.1.0 - July 15, 2016
-
-* e8f8c6c Fix: incorrect exitCode when eslint is called with --stdin (fixes #6677) (#6682) (Steven Humphrey)
-* 38639bf Update: make `no-var` fixable (fixes #6639) (#6644) (Toru Nagashima)
-* dfc20e9 Fix: `no-unused-vars` false positive in loop (fixes #6646) (#6649) (Toru Nagashima)
-* 2ba75d5 Update: relax outerIIFEBody definition (fixes #6613) (#6653) (Stephen E. Baker)
-* 421e4bf Chore: combine multiple RegEx replaces with one (fixes #6669) (#6661) (Sakthipriyan Vairamani)
-* 089ee2c Docs: fix typos,wrong path,backticks (#6663) (molee1905)
-* ef827d2 Docs: Add another pre-commit hook to integrations (#6666) (David Alan Hjelle)
-* a343b3c Docs: Fix option typo in no-underscore-dangle (Fixes #6674) (#6675) (Luke Page)
-* 5985eb2 Chore: add internal rule that validates meta property (fixes #6383) (#6608) (Vitor Balocco)
-* 4adb15f Update: Add `balanced` option to `spaced-comment` (fixes #4133) (#6575) (Annie Zhang)
-* 1b13c25 Docs: fix incorrect example being mark as correct (#6660) (David Björklund)
-* a8b4e40 Fix: Install required eslint plugin for "standard" guide (fixes #6656) (#6657) (Feross Aboukhadijeh)
-* 720686b New: `endLine` and `endColumn` of the lint result. (refs #3307) (#6640) (Toru Nagashima)
-* 54faa46 Docs: Small tweaks to CLI documentation (fixes #6627) (#6642) (Kevin Partington)
-* e108850 Docs: Added examples and structure to `padded-blocks` (fixes #6628) (#6643) (alberto)
-* 350e1c0 Docs: Typo (#6650) (Peter Rood)
-* b837c92 Docs: Correct a term in max-len.md (fixes #6637) (#6641) (Vse Mozhet Byt)
-* baeb313 Fix: Warning behavior for executeOnText (fixes #6611) (#6632) (Nicholas C. Zakas)
-* e6004be Chore: Enable preferType in valid-jsdoc (refs #5188) (#6634) (Nicholas C. Zakas)
-* ca323cf Fix: Use default assertion messages (fixes #6532) (#6615) (Dmitrii Abramov)
-* 2bdf22c Fix: Do not throw exception if baseConfig is provided (fixes #6605) (#6625) (Kevin Partington)
-* e42cacb Upgrade: mock-fs to 3.10, fixes for Node 6.3 (fixes #6621) (#6624) (Tim Schaub)
-* 8a263ae New: multiline-ternary rule (fixes #6066) (#6590) (Kai Cataldo)
-* e951303 Update: Adding new `key-spacing` option (fixes #5613) (#5907) (Kyle Mendes)
-* 10c3e91 Docs: Remove reference from 3.0.0 migration guide (refs #6605) (#6618) (Kevin Partington)
-* 5010694 Docs: Removed non-existing resource (#6609) (Moritz Kröger)
-* 6d40d85 Docs: Note that PR requires ACCEPTED issue (refs #6568) (#6604) (Patrick McElhaney)
-
-v3.0.1 - July 5, 2016
-
-* 27700cf Fix: `no-unused-vars` false positive around callback (fixes #6576) (#6579) (Toru Nagashima)
-* 124d8a3 Docs: Pull request template (#6568) (Nicholas C. Zakas)
-* e9a2ed9 Docs: Fix rules\id-length exceptions typos (fixes #6397) (#6593) (GramParallelo)
-* a2cfa1b Fix: Make outerIIFEBody work correctly (fixes #6585) (#6596) (Nicholas C. Zakas)
-* 9c451a2 Docs: Use string severity in example (#6601) (Kenneth Williams)
-* 8308c0b Chore: remove path-is-absolute in favor of the built-in (fixes #6598) (#6600) (shinnn)
-* 7a63717 Docs: Add missing pull request step (fixes #6595) (#6597) (Nicholas C. Zakas)
-* de3ed84 Fix: make `no-unused-vars` ignore for-in (fixes #2342) (#6126) (Oleg Gaidarenko)
-* 6ef2cbe Fix: strip Unicode BOM of config files (fixes #6556) (#6580) (Toru Nagashima)
-* ee7fcfa Docs: Correct type of `outerIIFEBody` in `indent` (fixes #6581) (#6584) (alberto)
-* 25fc7b7 Fix: false negative of `max-len` (fixes #6564) (#6565) (not-an-aardvark)
-* f6b8452 Docs: Distinguish examples in rules under Stylistic Issues part 6 (#6567) (Kenneth Williams)
-
-v3.0.0 - July 1, 2016
-
-* 66de9d8 Docs: Update installation instructions on README (#6569) (Nicholas C. Zakas)
-* dc5b78b Breaking: Add `require-yield` rule to `eslint:recommended` (fixes #6550) (#6554) (Gyandeep Singh)
-* 7988427 Fix: lib/config.js tests pass if personal config exists (fixes #6559) (#6566) (Kevin Partington)
-* 4c05967 Docs: Update rule docs for new format (fixes #5417) (#6551) (Nicholas C. Zakas)
-* 70da5a8 Docs: Correct link to rules page (#fixes 6553) (#6561) (alberto)
-* e2b2030 Update: Check RegExp strings for `no-regex-spaces` (fixes #3586) (#6379) (Jackson Ray Hamilton)
-* 397e51b Update: Implement outerIIFEBody for indent rule (fixes #6259) (#6382) (David Shepherd)
-* 666da7c Docs: 3.0.0 migration guide (#6521) (Nicholas C. Zakas)
-* b9bf8fb Docs: Update Governance Policy (fixes #6452) (#6522) (Nicholas C. Zakas)
-* 1290657 Update: `no-unused-vars` ignores read it modifies itself (fixes #6348) (#6535) (Toru Nagashima)
-* d601f6b Fix: Delete cache only when executing on files (fixes #6459) (#6540) (Kai Cataldo)
-* e0d4b19 Breaking: Error thrown/printed if no config found (fixes #5987) (#6538) (Kevin Partington)
-* 18663d4 Fix: false negative of `no-useless-rename` (fixes #6502) (#6506) (Toru Nagashima)
-* 0a7936d Update: Add fixer for prefer-const (fixes #6448) (#6486) (Nick Heiner)
-* c60341f Chore: Update index and `meta` for `"eslint:recommended"` (refs #6403) (#6539) (Mark Pedrotti)
-* 73da28d Better wording for the error reported by the rule "no-else-return" #6411 (#6413) (Olivier Thomann)
-* e06a5b5 Update: Add fixer for arrow-parens (fixes #4766) (#6501) (madmed88)
-* 5f8f3e8 Docs: Remove Box as a sponsor (#6529) (Nicholas C. Zakas)
-* 7dfe0ad Docs: fix max-lines samples (fixes #6516) (#6515) (Dmitriy Shekhovtsov)
-* fa05119 Breaking: Update eslint:recommended (fixes #6403) (#6509) (Nicholas C. Zakas)
-* e96177b Docs: Add "Proposing a Rule Change" link to CONTRIBUTING.md (#6511) (Kevin Partington)
-* bea9096 Docs: Update pull request steps (fixes #6474) (#6510) (Nicholas C. Zakas)
-* 7bcf6e0 Docs: Consistent example headings & text pt3 (refs #5446) (#6492) (Guy Fraser)
-* 1a328d9 Docs: Consistent example headings & text pt4 (refs #5446) (#6493) (Guy Fraser)
-* ff5765e Docs: Consistent example headings & text pt2 (refs #5446)(#6491) (Guy Fraser)
-* 01384fa Docs: Fixing typos (refs #5446)(#6494) (Guy Fraser)
-* 4343ae8 Fix: false negative of `object-shorthand` (fixes #6429) (#6434) (Toru Nagashima)
-* b7d8c7d Docs: more accurate yoda-speak (#6497) (Tony Lukasavage)
-* 3b0ab0d Fix: add warnIgnored flag to CLIEngine.executeOnText (fixes #6302) (#6305) (Robert Levy)
-* c2c6cec Docs: Mark object-shorthand as fixable. (#6485) (Nick Heiner)
-* 5668236 Fix: Allow objectsInObjects exception when destructuring (fixes #6469) (#6470) (Adam Renklint)
-* 17ac0ae Fix: `strict` rule reports a syntax error for ES2016 (fixes #6405) (#6464) (Toru Nagashima)
-* 4545123 Docs: Rephrase documentation for `no-duplicate-imports` (#6463) (Simen Bekkhus)
-* 1b133e3 Docs: improve `no-native-reassign` and specifying globals (fixes #5358) (#6462) (Toru Nagashima)
-* b179373 Chore: Remove dead code in excuteOnFiles (fixes #6467) (#6466) (Andrew Hutchings)
-* 18fbc4b Chore: Simplify eslint process exit code (fixes #6368) (#6371) (alberto)
-* 58542e4 Breaking: Drop support for node < 4 (fixes #4483) (#6401) (alberto)
-* f50657e Breaking: use default for complexity in eslint:recommended (fixes #6021) (#6410) (alberto)
-* 3e690fb Fix: Exit init early if guide is chosen w/ no package.json (fixes #6476) (#6478) (Kai Cataldo)
-
-v2.13.1 - June 20, 2016
-
-* 434de7f Fix: wrong baseDir (fixes #6450) (#6457) (Toru Nagashima)
-* 3c9ce09 Fix: Keep indentation when fixing `padded-blocks` "never" (fixes #6454) (#6456) (Ed Lee)
-* a9d4cb2 Docs: Fix typo in max-params examples (#6471) (J. William Ashton)
-* 1e185b9 Fix: no-multiple-empty-lines errors when no line breaks (fixes #6449) (#6451) (strawbrary)
-
-v2.13.0 - June 17, 2016
-
-* cf223dd Fix: add test for a syntax error (fixes #6013) (#6378) (Toru Nagashima)
-* da30cf9 Update: Add fixer for object-shorthand (fixes #6412) (#6418) (Nick Heiner)
-* 2cd90eb Chore: Fix rule meta description inconsistencies (refs #5417) (#6422) (Mark Pedrotti)
-* d798b2c Added quotes around "classes" option key (#6441) (Guy Fraser)
-* 852b6df Docs: Delete empty table of links from Code Path Analysis (#6423) (Mark Pedrotti)
-* 5e9117e Chore: sort rules in eslint.json (fixes #6425) (#6426) (alberto)
-* c2b5277 Docs: Add gitter chat link to Reporting Bugs (#6430) (Mark Pedrotti)
-* 1316db0 Update: Add `never` option for `func-names` (fixes #6059) (#6392) (alberto)
-* 1c123e2 Update: Add autofix for `padded-blocks` (fixes #6320) (#6393) (alberto)
-* 8ec89c8 Fix: `--print-config` return config inside subdir (fixes #6329) (#6385) (alberto)
-* 4f73240 Fix: `object-curly-newline` multiline with comments (fixes #6381) (#6396) (Toru Nagashima)
-* 77697a7 Chore: Fake config hierarchy fixtures (fixes #6206) (#6402) (Gyandeep Singh)
-* 73a9a6d Docs: Fix links in Configuring ESLint (#6421) (Mark Pedrotti)
-* ed84c4c Fix: improve `newline-per-chained-call` message (fixes #6340) (#6360) (Toru Nagashima)
-* 9ea4e44 Docs: Update parser reference to `espree` instead of `esprima` (#6404) (alberto)
-* 7f57467 Docs: Make `fix` param clearer (fixes #6366) (#6367) (Nick Heiner)
-* fb49c7f Fix: nested `extends` with relative path (fixes #6358) (#6359) (Toru Nagashima)
-* 5122f73 Update: no-multiple-empty-lines fixer (fixes #6225) (#6226) (Ruurd Moelker)
-* 0e7ce72 Docs: Fix rest-spread-spacing's name (#6365) (cody)
-* cfdd524 Fix: allow semi as braceless body of statements (fixes #6386) (#6391) (alberto)
-* 6b08cfc Docs: key-spacing fixable documenation notes (fixes #6375) (#6376) (Ruurd Moelker)
-* 4b4be3b Docs: `max-lines` option: fix `skipComments` typo (#6374) (Jordan Harband)
-* 20ab4f6 Docs: Fix wrong link in object-curly-newline (#6373) (Grant Snodgrass)
-* 412ce8d Docs: Fix broken links in no-mixed-operators (#6372) (Grant Snodgrass)
-
-v2.12.0 - June 10, 2016
-
-* 54c30fb Update: Add explicit default option `always` for `eqeqeq` (refs #6144) (#6342) (alberto)
-* 2d63370 Update: max-len will warn indented comment lines (fixes #6322) (#6324) (Kai Cataldo)
-* dcd4ad7 Docs: clarify usage of inline disable comments (fixes #6335) (#6347) (Kai Cataldo)
-* c03300b Docs: Clarified how plugin rules look in plugin configs (fixes #6346) (#6351) (Kevin Partington)
-* 9c87709 Docs: Add semantic versioning policy (fixes #6244) (#6343) (Nicholas C. Zakas)
-* 5affab1 Docs: Describe values under Extending Configuration Files (refs #6240) (#6336) (Mark Pedrotti)
-* 2520f5a New: `max-lines` rule (fixes #6078) (#6321) (alberto)
-* 9bfbc64 Update: Option for object literals in `arrow-body-style` (fixes #5936) (#6216) (alberto)
-* 977cdd5 Chore: remove unused method from FileFinder (fixes #6344) (#6345) (alberto)
-* 477fbc1 Docs: Add section about customizing RuleTester (fixes #6227) (#6331) (Jeroen Engels)
-* 0e14016 New: `no-mixed-operators` rule (fixes #6023) (#6241) (Toru Nagashima)
-* 6e03c4b Update: Add never option to arrow-body-style (fixes #6317) (#6318) (Andrew Hyndman)
-* f804397 New: Add `eslint:all` option (fixes #6240) (#6248) (Robert Fletcher)
-* dfe05bf Docs: Link JSCS rules to their corresponding page. (#6334) (alberto)
-* 1cc4356 Docs: Remove reference to numeric config (fixes #6309) (#6327) (Kevin Partington)
-* 2d4efbe Docs: Describe options in rule under Strict Mode (#6312) (Mark Pedrotti)
-* c1953fa Docs: Typo fix 'and' -> 'any' (#6326) (Stephen Edgar)
-* d49ab4b Docs: Code conventions improvements (#6313) (Kevin Partington)
-* 316a507 Fix: one-var allows uninitialized vars in ForIn/ForOf (fixes #5744) (#6272) (Kai Cataldo)
-* 6cbee31 Docs: Typo fix 'colum' -> 'column' (#6306) (Andrew Cobby)
-* 2663569 New: `object-curly-newline` (fixes #6072) (#6223) (Toru Nagashima)
-* 72c2ea5 Update: callback-return allows for object methods (fixes #4711) (#6277) (Kai Cataldo)
-* 89580a4 Docs: Distinguish examples in rules under Stylistic Issues part 5 (#6291) (Kenneth Williams)
-* 1313804 New: rest-spread-spacing rule (fixes #5391) (#6278) (Kai Cataldo)
-* 61dfe68 Fix: `no-useless-rename` false positive in babel-eslint (fixes #6266) (#6290) (alberto)
-* c78c8cb Build: Remove commit check from appveyor (fixes #6292) (#6294) (alberto)
-* 3e38fc1 Chore: more tests for comments at the end of blocks (refs #6090) (#6273) (Kai Cataldo)
-* 38dccdd Docs: `--no-ignore` disables all forms of ignore (fixes #6260) (#6304) (alberto)
-* bb69380 Fix: no-useless-rename handles ExperimentalRestProperty (fixes #6284) (#6288) (Kevin Partington)
-* fca0679 Update: Improve perf not traversing default ignored dirs (fixes #5679) (#6276) (alberto)
-* 320e8b0 Docs: Describe options in rules under Possible Errors part 4 (#6270) (Mark Pedrotti)
-* 3e052c1 Docs: Mark no-useless-rename as fixable in rules index (#6297) (Dalton Santos)
-
-v2.11.1 - May 30, 2016
-
-* 64b0d0c Fix: failed to parse `/*eslint` comments by colon (fixes #6224) (#6258) (Toru Nagashima)
-* c8936eb Build: Don't check commit count (fixes #5935) (#6263) (Nicholas C. Zakas)
-* 113c1a8 Fix: `max-statements-per-line` false positive at exports (fixes #6264) (#6268) (Toru Nagashima)
-* 03beb27 Fix: `no-useless-rename` false positives (fixes #6266) (#6267) (alberto)
-* fe89037 Docs: Fix rule name in example (#6279) (Kenneth Williams)
-
-v2.11.0 - May 27, 2016
-
-* 77dd2b4 Fix: On --init, print message when package.json is invalid (fixes #6257) (#6261) (Kai Cataldo)
-* 7f60186 Fix: `--ignore-pattern` can't uningnore files (fixes #6127) (#6253) (alberto)
-* fea8fe6 New: no-useless-rename (fixes #6058) (#6249) (Kai Cataldo)
-* b4cff9d Fix: Incorrect object-property-newline behavior (fixes #6207) (#6213) (Rafał Ruciński)
-* 35b4656 Docs: Edit arrow-parens.md to show correct output value (#6245) (Adam Terlson)
-* ee0cd58 Fix: `newline-before-return` shouldn't disallow newlines (fixes #6176) (#6217) (alberto)
-* d4f5526 Fix: `vars-on-top` crashs at export declarations (fixes #6210) (#6220) (Toru Nagashima)
-* 088bda9 New: `unicode-bom` rule to allow or disallow BOM (fixes #5502) (#6230) (Andrew Johnston)
-* 14bfc03 Fix: `comma-dangle` wrong autofix (fixes #6233) (#6235) (Toru Nagashima)
-* cdd65d7 Docs: added examples for arrow-body-style (refs #5498) (#6242) (Tieme van Veen)
-* c10c07f Fix: lost code in autofixing (refs #6233) (#6234) (Toru Nagashima)
-* e6d5b1f Docs: Add rule deprecation section to user guide (fixes #5845) (#6201) (Kai Cataldo)
-* 777941e Upgrade: doctrine to 1.2.2 (fixes #6121) (#6231) (alberto)
-* 74c458d Update: key-spacing rule whitespace fixer (fixes #6167) (#6169) (Ruurd Moelker)
-* 04bd586 New: Disallow use of Object.prototype methods on objects (fixes #2693) (#6107) (Andrew Levine)
-* 53754ec Update: max in `max-statements-per-line` should be >=0 (fixes #6171) (#6172) (alberto)
-* 54d1201 Update: Add treatUndefinedAsUnspecified option (fixes #6026) (#6194) (Kenneth Williams)
-* 18152dd Update: Add checkLoops option to no-constant-condition (fixes #5477) (#6202) (Kai Cataldo)
-* 7644908 Fix: no-multiple-empty-lines BOF and EOF defaults (fixes #6179) (#6180) (Ruurd Moelker)
-* 72335eb Fix: `max-statements-per-line` false positive (fixes #6173, fixes #6153) (#6192) (Toru Nagashima)
-* 9fce04e Fix: `generator-star-spacing` false positive (fixes #6135) (#6168) (Toru Nagashima)
-
-v2.10.2 - May 16, 2016
-
-* bda5de5 Fix: Remove default parser from CLIEngine options (fixes #6182) (#6183) (alberto)
-* e59e5a0 Docs: Describe options in rules under Possible Errors part 3 (#6105) (Mark Pedrotti)
-* 842ab2e Build: Run phantomjs tests using karma (fixes #6128) (#6178) (alberto)
-
-v2.10.1 - May 14, 2016
-
-* 9397135 Fix: `valid-jsdoc` false positive at default parameters (fixes #6097) (#6170) (Toru Nagashima)
-* 2166ad4 Fix: warning & error count in `CLIEngine.getErrorResults` (fixes #6155) (#6157) (alberto)
-* 1e0a652 Fix: ignore empty statements in max-statements-per-line (fixes #6153) (#6156) (alberto)
-* f9ca0d6 Fix: `no-extra-parens` to check for nulls (fixes #6161) (#6164) (Gyandeep Singh)
-* d095ee3 Fix: Parser merge sequence in config (fixes #6158) (#6160) (Gyandeep Singh)
-* f33e49f Fix: `no-return-assign` to check for null tokens (fixes #6159) (#6162) (Gyandeep Singh)
-
-v2.10.0 - May 13, 2016
-
-* 098cd9c Docs: Distinguish examples in rules under Stylistic Issues part 4 (#6136) (Kenneth Williams)
-* 805742c Docs: Clarify JSX option usage (#6132) (Richard Collins)
-* 10b0933 Fix: Optimize no-irregular-whitespace for the common case (fixes #6116) (#6117) (Andres Suarez)
-* 36bec90 Docs: linkify URLs in development-environment.md (#6150) (chrisjshull)
-* 29c401a Docs: Convert rules in index under Removed from list to table (#6091) (Mark Pedrotti)
-* e13e696 Fix: `_` and `$` in isES5Constructor (fixes #6085) (#6094) (Kevin Locke)
-* 67916b9 Fix: `no-loop-func` crashed (fixes #6130) (#6138) (Toru Nagashima)
-* d311a62 Fix: Sort fixes consistently even if they overlap (fixes #6124) (#6133) (alberto)
-* 6294459 Docs: Correct syntax for default ignores and `.eslintignore` example (#6118) (alberto)
-* 067db14 Fix: Replace `assert.deepEqual` by `lodash.isEqual` (fixes #6111) (#6112) (alberto)
-* 52fdf04 Fix: `no-multiple-empty-lines` duplicate errors at BOF (fixes #6113) (#6114) (alberto)
-* e6f56da Docs: Document `--ignore-pattern` (#6120) (alberto)
-* ef739cd Fix: Merge various command line configs at the same time (fixes #6104) (#6108) (Ed Lee)
-* 767da6f Update: add returnAssign option to no-extra-parens (fixes #6036) (#6095) (Kai Cataldo)
-* 06f6252 Build: Use split instead of slice/indexOf for commit check (fixes #6109) (#6110) (Ed Lee)
-* c4fc39b Docs: Update headings of rules under Removed (refs #5774) (#6102) (Mark Pedrotti)
-* 716345f Build: Match rule id at beginning of heading (refs #5774) (#6089) (Mark Pedrotti)
-* 0734967 Update: Add an option to `prefer-const` (fixes #5692) (#6040) (Toru Nagashima)
-* 7941d5e Update: Add autofix for `lines-around-comment` (fixes #5956) (#6062) (alberto)
-* dc538aa Build: Pin proxyquire to ">=1.0.0 <1.7.5" (fixes #6096) (#6100) (alberto)
-* 04563ca Docs: Describe options in rules under Possible Errors part 2 (#6063) (Mark Pedrotti)
-* 5d390b2 Chore: Replace deprecated calls to context - batch 4 (fixes #6029) (#6087) (alberto)
-* 6df4b23 Fix: `no-return-assign` warning nested expressions (fixes #5913) (#6041) (Toru Nagashima)
-* 16fad58 Merge pull request #6088 from eslint/docs-one-var-per-line (alberto)
-* 0b67170 Docs: Correct default for `one-var-declaration-per-line` (fixes #6017) (#6022) (Ed Lee)
-* d40017f Fix: comma-style accounts for parens in array (fixes #6006) (#6038) (Kai Cataldo)
-* 992d9cf Docs: Fix typography/teriminology in indent doc (fixes #6045) (#6044) (Rich Trott)
-* 4ae39d2 Chore: Replace deprecated calls to context - batch 3 (refs #6029) (#6056) (alberto)
-* 8633e4d Update: multipass should not exit prematurely (fixes #5995) (#6048) (alberto)
-* 3c44c2c Update: Adds an avoidQuotes option for object-shorthand (fixes #3366) (#5870) (Chris Sauvé)
-* a9a4652 Fix: throw when rule uses `fix` but `meta.fixable` not set (fixes #5970) (#6043) (Vitor Balocco)
-* ad10106 Docs: Update comma-style docs (#6039) (Kai Cataldo)
-* 388d6f8 Fix: `no-sequences` false negative at arrow expressions (fixes #6082) (#6083) (Toru Nagashima)
-* 8e96064 Docs: Clarify rule example in README since we allow string error levels (#6061) (Kevin Partington)
-* a66bf19 Fix: `lines-around-comment` multiple errors on same line (fixes #5965) (#5994) (alberto)
-* a2cc54e Docs: Organize meta and describe visitor in Working with Rules (#5967) (Mark Pedrotti)
-* ef8cbff Fix: object-shorthand should only lint computed methods (fixes #6015) (#6024) (Kai Cataldo)
-* cd1b057 Chore: Replace deprecated calls to context - batch 2 (refs #6029) (#6049) (alberto)
-* a3a6e06 Update: no-irregal-whitespace in a regular expression (fixes #5840) (#6018) (Linda_pp)
-* 9b9d76c Chore: Replace deprecated calls to context - batch 1 (refs #6029) (#6034) (alberto)
-* dd8bf93 Fix: blockless else in max-statements-per-line (fixes #5926) (#5993) (Glen Mailer)
-* f84eb80 New: Add new rule `object-property-newline` (fixes #5667) (#5933) (Vitor Balocco)
-* d5f4104 Docs: mention parsing errors in strict mode (fixes #5485) (#5991) (Mark Pedrotti)
-* 249732e Docs: Move docs from eslint.github.io (fixes #5964) (#6012) (Nicholas C. Zakas)
-* 4c2de6c Docs: Add example of diff clarity to comma-dangle rule docs (#6035) (Vitor Balocco)
-* 3db2e89 Fix: Do not swallow exceptions in CLIEngine.getFormatter (fixes #5977) (#5978) (Gustav Nikolaj)
-* eb2fb44 Fix: Always ignore defaults unless explicitly passed (fixes #5547) (#5820) (Ian VanSchooten)
-* ab57e94 Docs: Add example of diff clarity to newline-per-chained-call (#5986) (Vitor Balocco)
-* 88bc014 Docs: Update readme info about jshint (#6027) (alberto)
-* a2c15cc Docs: put config example in code block (#6005) (Amos Wenger)
-* a5011cb Docs: Fix a wrong examples' header of `prefer-arrow-callback`. (#6020) (Toru Nagashima)
-* 1484ede Docs: Typo in nodejs-api (#6025) (alberto)
-* ade6a9b Docs: typo: "eslint-disable-line" not "eslint disable-line" (#6019) (Will Day)
-* 2f15354 Fix: Removed false positives of break and continue (fixes #5972) (#6000) (Onur Temizkan)
-
-v2.9.0 - April 29, 2016
-
-* a8a2cd8 Fix: Avoid autoconfig crashes from inline comments (fixes #5992) (#5999) (Ian VanSchooten)
-* 23b00e0 Upgrade: npm-license to 0.3.2 (fixes #5996) (#5998) (alberto)
-* 377167d Upgrade: ignore to 3.1.2 (fixes #5979) (#5988) (alberto)
-* 141b778 Fix: no-control-regex literal handling fixed. (fixes #5737) (#5943) (Efe Gürkan YALAMAN)
-* 577757d Fix: Clarify color option (fixes #5928) (#5974) (Grant Snodgrass)
-* e7e6581 Docs: Update CLA link (#5980) (Gustav Nikolaj)
-* 0be26bc Build: Add nodejs 6 to travis (fixes #5971) (#5973) (Gyandeep Singh)
-* e606523 New: Rule `no-unsafe-finally` (fixes #5808) (#5932) (Onur Temizkan)
-* 42d1ecc Chore: Add metadata to existing rules - Batch 7 (refs #5417) (#5969) (Vitor Balocco)
-* e2ad1ec Update: object-shorthand lints computed methods (fixes #5871) (#5963) (Chris Sauvé)
-* d24516a Chore: Add metadata to existing rules - Batch 6 (refs #5417) (#5966) (Vitor Balocco)
-* 1e7a3ef Fix: `id-match` false positive in property values (fixes #5885) (#5960) (Mike Sherov)
-* 51ddd4b Update: Use process @abstract when processing @return (fixes #5941) (#5945) (Simon Schick)
-* 52a4bea Update: Add autofix for `no-whitespace-before-property` (fixes #5927) (#5951) (alberto)
-* 46e058d Docs: Correct typo in configuring.md (#5957) (Nick S. Plekhanov)
-* 5f8abab Chore: Add metadata to existing rules - Batch 5 (refs #5417) (#5944) (Vitor Balocco)
-* 0562f77 Chore: Add missing newlines to test cases (fixes #5947) (Rich Trott)
-* fc78e78 Chore: Enable quote-props rule in eslint-config-eslint (refs #5188) (#5938) (Gyandeep Singh)
-* 43f6d05 Docs: Update docs to refer to column (#5937) (Sashko Stubailo)
-* 586478e Update: Add autofix for `comma-dangle` (fixes #3805) (#5925) (alberto)
-* a4f9c5a Docs: Distinguish examples in rules under Stylistic Issues part 3 (Kenneth Williams)
-* e7c0737 Chore: Enable no-console rule in eslint-config-eslint (refs #5188) (Kevin Partington)
-* 0023fe6 Build: Add “chore” to commit tags (fixes #5880) (#5929) (Mike Sherov)
-* 25d626a Upgrade: espree 3.1.4 (fixes #5923, fixes #5756) (Kai Cataldo)
-* a01b412 New: Add `no-useless-computed-key` rule (fixes #5402) (Burak Yigit Kaya)
-* 9afb9cb Chore: Remove workaround for espree and escope bugs (fixes #5852) (alberto)
-* 3ffc582 Chore: Update copyright and license info (alberto)
-* 249eb40 Docs: Clarify init sets up local installation (fixes #5874) (Kai Cataldo)
-* 6cd8c86 Docs: Describe options in rules under Possible Errors part 1 (Mark Pedrotti)
-* f842d18 Fix: `no-this-before-super` crash on unreachable paths (fixes #5894) (Toru Nagashima)
-* a02960b Docs: Fix missing delimiter in README links (Kevin Partington)
-* 3a9e72c Docs: Update developer guide with new standards (Nicholas C. Zakas)
-* cb78585 Update: Add `allowUnboundThis` to `prefer-arrow-callback` (fixes #4668) (Burak Yigit Kaya)
-* 02be29f Chore: Remove CLA check from bot (Nicholas C. Zakas)
-* 220713e Chore: Add metadata to existing rules - Batch 4 (refs #5417) (Vitor Balocco)
-* df53414 Chore: Include jQuery Foundation info (Nicholas C. Zakas)
-* f1b2992 Fix: `no-useless-escape` false positive in JSXAttribute (fixes #5882) (Toru Nagashima)
-* 74674ad Docs: Move `sort-imports` to 'ECMAScript 6' (Kenneth Williams)
-* ae69ddb Docs: Fix severity type in example (Kenneth Williams)
-* 19f6fff Update: Autofixing does multiple passes (refs #5329) (Nicholas C. Zakas)
-* 1e4b0ca Docs: Reduce length of paragraphs in rules index (Mark Pedrotti)
-* 8cfe1eb Docs: Fix a wrong option (Zach Orlovsky)
-* 8f6739f Docs: Add alberto as reviewer (alberto)
-* 2ae4938 Docs: Fix message for `inline-config` option (alberto)
-* 089900b Docs: Fix a wrong rule name in an example (Toru Nagashima)
-* c032b41 Docs: Fix emphasis (Toru Nagashima)
-* ae606f0 Docs: Update JSCS info in README (alberto)
-* a9c5323 Fix: Install ESLint on init if not installed (fixes #5833) (Kai Cataldo)
-* ed38358 Docs: Removed incorrect example (James M. Greene)
-* af3113c Docs: Fix config comments in indent docs (Brandon Mills)
-* 2b39461 Update: `commentPattern` option for `default-case` rule (fixes #5803) (Artyom Lvov)
-
-v2.8.0 - April 15, 2016
-
-* a8821a5 Docs: Distinguish examples in rules under Stylistic Issues part 2 (Kenneth Williams)
-* 76913b6 Update: Add metadata to existing rules - Batch 3 (refs #5417) (Vitor Balocco)
-* 34ad8d2 Fix: Check that module.paths exists (fixes #5791) (Nicholas C. Zakas)
-* 37239b1 Docs: Add new members of the team (Ilya Volodin)
-* fb3c2eb Update: allow template literals (fixes #5234) (Jonathan Haines)
-* 5a4a935 Update: Add metadata to existing rules - Batch 2 (refs #5417) (Vitor Balocco)
-* ea2e625 Fix: newline-before-return handles return as first token (fixes #5816) (Kevin Partington)
-* f8db9c9 Update: add nestedBinaryExpressions to no-extra-parens (fixes #3065) (Ilya Volodin)
-* 0045d57 Update: `allowNamedFunctions` in `prefer-arrow-callback` (fixes #5675) (alberto)
-* 19da72a Update: Add metadata to existing rules - Batch 1 (refs #5417) (Vitor Balocco)
-* cc14e43 Fix: `no-fallthrough` empty case with comment (fixes #5799) (alberto)
-* 13c8b14 Fix: LogicalExpression checks for short circuit (fixes #5693) (Vamshi krishna)
-* 73b225e Fix: Document and fix metadata (refs #5417) (Ilya Volodin)
-* 882d199 Docs: Improve options description in `no-redeclare` (alberto)
-* 6a71ceb Docs: Improve options description in `no-params-reassign` (alberto)
-* 24b6215 Update: Include 'typeof' in rule 'no-constant-condition' (fixes #5228) (Vamshi krishna)
-* a959063 Docs: Remove link to deprecated ESLintTester project (refs #3110) (Trey Thomas)
-* 6fd7d82 Update: Change order in `eslint --init` env options (fixes #5742) (alberto)
-* c59d909 Fix: Extra paren check around object arrow bodies (fixes #5789) (Brandon Mills)
-* 6f88546 Docs: Use double quotes for better Win compatibility (fixes #5796) (alberto)
-* 02743d5 Fix: catch self-assignment operators in `no-magic-number` (fixes #4400) (alberto)
-* c94e74e Docs: Make rule descriptions more consistent (Kenneth Williams)
-* 6028252 Docs: Distinguish examples in rules under Stylistic Issues part 1 (Mark Pedrotti)
-* ccd8ca9 Fix: Added property onlyDeclaration to id-match rule (fixes #3488) (Gajus Kuizinas)
-* 6703c02 Update: no-useless-escape / exact locations of errors (fixes #5751) (Onur Temizkan)
-* 3d84b91 Fix: ignore trailing whitespace in template literal (fixes #5786) (Kai Cataldo)
-* b0e6bc4 Update: add allowEmptyCatch option to no-empty (fixes #5800) (Kai Cataldo)
-* f1f1dd7 Docs: Add @pedrottimark as a committer (Brandon Mills)
-* 228f201 Update: `commentPattern` option for `no-fallthrough` rule (fixes #5757) (Artyom Lvov)
-* 41db670 Docs: Clarify disable inline comments (Kai Cataldo)
-* 9c9a295 Docs: Add note about shell vs node glob parameters in cli (alberto)
-* 5308ff9 Docs: Add code backticks to sentence in fixable rules (Mark Pedrotti)
-* 965ec06 Docs: fix the examples for space-before-function-paren. (Craig Silverstein)
-* 2b202fc Update: Add ignore option to space-before-function-parens (fixes #4127) (Craig Silverstein)
-* 24c12ba Fix: improve `constructor-super` errors for literals (fixes #5449) (Toru Nagashima)
-
-v2.7.0 - April 4, 2016
-
-* 134cb1f Revert "Update: adds nestedBinaryExpressions for no-extra-parens rule (fixes #3065)" (Ilya Volodin)
-* 7e80867 Docs: Update sentence in fixable rules (Mark Pedrotti)
-* 1b6d5a3 Update: adds nestedBinaryExpressions for no-extra-parens (fixes #3065) (Nick Fisher)
-* 4f93c32 Docs: Clarify `array-bracket-spacing` with newlines (fixes #5768) (alberto)
-* 161ddac Fix: remove `console.dir` (fixes #5770) (Toru Nagashima)
-* 0c33f6a Fix: indent rule uses wrong node for class indent level (fixes #5764) (Paul O’Shannessy)
-
-v2.6.0 - April 1, 2016
-
-* ce2accd Fix: vars-on-top now accepts exported variables (fixes #5711) (Olmo Kramer)
-* 7aacba7 Update: Deprecate option `maximum` in favor of `max` (fixes #5685) (Vitor Balocco)
-* 5fe6fca Fix: no-useless-escape \B regex escape (fixes #5750) (Onur Temizkan)
-* 9b73ffd Update: `destructuring` option of `prefer-const` rule (fixes #5594) (Toru Nagashima)
-* 8ac9206 Docs: Typo in `sort-imports` (alberto)
-* 12902c5 Fix: valid-jsdoc crash w/ Field & Array Type (fixes #5745) (fixes #5746) (Burak Yigit Kaya)
-* 2c8b65a Docs: Edit examples for a few rules (Mark Pedrotti)
-* d736bc2 Fix: Treat SwitchCase like a block in lines-around-comment (fixes #5718) (Scott O'Hara)
-* 24a61a4 Update: make `no-useless-escape` allowing line breaks (fixes #5689) (Toru Nagashima)
-* 4ecd45e Fix: Ensure proper lookup of config files (fixes #5175, fixes #5468) (Nicholas C. Zakas)
-* 088e26b Fix: Update doctrine to allow hyphens in JSDoc names (fixes #5612) (Kai Cataldo)
-* 692fd5d Upgrade: Old Chalk.JS deprecated method (fixes #5716) (Morris Singer)
-* f59d91d Update: no-param-reassign error msgs (fixes #5705) (Isaac Levy)
-* c1b16cd Fix: Object spread throws error in key-spacing rule. (fixes #5724) (Ziad El Khoury Hanna)
-* 3091613 Docs: Correct explanation about properties (James Monger)
-* cb0f0be Fix: Lint issue with `valid-jsdoc` rule (refs #5188) (Gyandeep Singh)
-* aba1954 Build: Ignore jsdoc folder internally (fixes #5714) (alberto)
-* a35f127 Fix: Lint for eslint project in regards to vars (refs #5188) (Gyandeep Singh)
-* d9ab4f0 Fix: Windows scoped package configs (fixes #5644) (Nicholas C. Zakas)
-* 8d0cd0d Update: Basic valid-jsdoc default parameter support (fixes #5658) (Tom Andrews)
-
-v2.5.3 - March 28, 2016
-
-* 8749ac5 Build: Disable bundling dependencies (fixes #5687) (Nicholas C. Zakas)
-
-v2.5.2 - March 28, 2016
-
-* 1cc7f8e Docs: Remove mention of minimatch for .eslintignore (Ian VanSchooten)
-* 5bd69a9 Docs: Reorder FAQ in README (alberto)
-* 98e6bd9 Fix: Correct default for indentation in `eslint --init` (fixes #5698) (alberto)
-* 679095e Fix: make the default of `options.cwd` in runtime (fixes #5694) (Toru Nagashima)
-* 4f06f2f Docs: Distinguish examples in rules under Best Practices part 2 (Mark Pedrotti)
-* 013a18e Build: Fix bundling script (fixes #5680) (Nicholas C. Zakas)
-* 8c5d954 Docs: Typo fix (István Donkó)
-* 09659d6 Docs: Use string severity (Kenneth Williams)
-* a4ae769 Docs: Manual changelog update for v2.5.1 (Nicholas C. Zakas)
-* c41fab9 Fix: don't use path.extname with undefined value (fixes #5678) (Myles Borins)
-
-v2.5.1 - March 25, 2016
-
-* Build: No functional changes, just republished with a working package.
-
-v2.5.0 - March 25, 2016
-
-* 7021aa9 Fix: lines-around-comment in ESLint repo, part 2 (refs #5188) (Kevin Partington)
-* 095c435 Docs: Remove ES2016 from experimental section of README (Kevin Partington)
-* 646f863 Build: Bundle dependencies in package.json (fixes #5013) (Nicholas C. Zakas)
-* ea06868 Docs: Clarify --ext does not apply to globs (fixes #5452) (Ian VanSchooten)
-* 569c478 Build: Fix phantomjs CI problems (fixes #5666) (alberto)
-* 6022426 Docs: Add link to chat room in README primary links (alberto)
-* 2fbb530 Docs: Add link to "Proposing a Rule Change" in README (alberto)
-* 25bf491 Upgrade: globals 9.x (fixes #5668) (Toru Nagashima)
-* d6f8409 New: Rule - No useless escape (fixes #5460) (Onur Temizkan)
-* 12a43f1 Docs: remove brace expansion from configuring.md (refs #5314) (Jonathan Haines)
-* 92d1749 New: max-statements-per-line (fixes #5424) (Kenneth Williams)
-* aaf324a Fix: missing support for json sub configs (fixes #5413) (Noam Okman)
-* 48ad5fe Update: Add 'caughtErrors' to rule no-unused-vars (fixes #3837) (vamshi)
-* ad90c2b Fix: incorrect config message (fixes #5653) (s0ph1e)
-* a551831 Docs: Distinguish examples in rules under Node.js and CommonJS (Mark Pedrotti)
-* 83cd651 Upgrade: chai to 3.5.0 (fixes #5647) (alberto)
-* 32748dc Fix: `radix` rule false positive at shadowed variables (fixes #5639) (Toru Nagashima)
-* 66db38d Fix: `--no-ignore` should not un-ignore default ignores (fixes #5547) (alberto)
-* e3e06f3 Docs: Distinguish examples in rules under Best Practices part 4 (Mark Pedrotti)
-* a9f0865 Docs: Update no-sequences rule docs for clarity (fixes #5536) (Kai Cataldo)
-* bae7b30 Docs: Add michaelficarra as committer (alberto)
-* e2990e7 Docs: Consistent wording in rules README (alberto)
-* 49b4d2a Docs: Update team list with new members (Ilya Volodin)
-* d0ae66c Update: Allow autoconfiguration for JSX code (fixes #5511) (Ian VanSchooten)
-* 38a0a64 Docs: Clarify `linebreak-style` docs (fixes #5628) (alberto)
-* 4b7305e Fix: Allow default ignored files to be unignored (fixes #5410) (Ian VanSchooten)
-* 4b05ce6 Update: Enforce repo coding conventions via ESLint (refs #5188) (Kevin Partington)
-* 051b255 Docs: Remove or rewrite references to former ecmaFeatures (Mark Pedrotti)
-* 9a22625 Fix: `prefer-const` false positive at non-blocked if (fixes #5610) (Toru Nagashima)
-* b1fd482 Fix: leading comments added from previous node (fixes #5531) (Kai Cataldo)
-* c335650 Docs: correct the no-confusing-arrow docs (Daniel Norman)
-* e94b77d Fix: Respect 'ignoreTrailingComments' in max-len rule (fixes #5563) (Vamshi Krishna)
-* 9289ef8 Fix: handle personal package.json without config (fixes #5496) (Denny Christochowitz)
-* 87d74b2 Fix: `prefer-const` got to not change scopes (refs #5284) (Toru Nagashima)
-* 5a881e7 Docs: Fix typo in code snippet for no-unmodified-loop-condition rule (Chris Rebert)
-* 03037c2 Update: Overrides for space-unary-ops (fixes #5060) (Afnan Fahim)
-* 24d986a Update: replace MD5 hashing of cache files with MurmurHash (fixes #5522) (Michael Ficarra)
-* f405030 Fix: Ensure allowing `await` as a property name (fixes #5564) (Toru Nagashima)
-* aefc90c Fix: `no-useless-constructor` clash (fixes #5573) (Toru Nagashima)
-* 9eaa20d Docs: Fix typo in CLI help message (ryym)
-* a7c3e67 Docs: Invalid json in `configuring.md` (alberto)
-* 4e50332 Docs: Make `prefer-template` examples consistent. (alberto)
-* cfc14a9 Fix: valid-jsdoc correctly checks type union (fixes #5260) (Kai Cataldo)
-* 689cb7d Fix: `quote-props` false positive on certain keys (fixes #5532) (Burak Yigit Kaya)
-* 167a03a Fix: `brace-style` erroneously ignoring certain errors (fixes #5197) (Burak Yigit Kaya)
-* 3133f28 Fix: object-curly-spacing doesn't know types (fixes #5537) (fixes #5538) (Burak Yigit Kaya)
-* d0ca171 Docs: Separate parser and config questions in issue template (Kevin Partington)
-* bc769ca Fix: Improve file path resolution (fixes #5314) (Ian VanSchooten)
-* 9ca8567 Docs: Distinguish examples in rules under Best Practices part 3 (Mark Pedrotti)
-* b9c69f1 Docs: Distinguish examples in rules under Variables part 2 (Mark Pedrotti)
-* c289414 New: `no-duplicate-imports` rule (fixes #3478) (Simen Bekkhus)
-
-v2.4.0 - March 11, 2016
-
-* 97b2466 Fix: estraverse/escope to work with unknowns (fixes #5476) (Nicholas C. Zakas)
-* 641b3f7 Fix: validate the type of severity level (fixes #5499) (Shinnosuke Watanabe)
-* 9ee8869 Docs: no-unused-expressions - add more edge unusable and usable examples (Brett Zamir)
-* 56bf864 Docs: Create parity between no-sequences examples (Brett Zamir)
-* 13ef1c7 New: add `--parser-options` to CLI (fixes #5495) (Jordan Harband)
-* ae1ee54 Docs: fix func-style arrow exception option (Craig Martin)
-* 91852fd Docs: no-lone-blocks - show non-problematic (and problematic) label (Brett Zamir)
-* b34458f Docs: Rearrange rules for better categories (and improve rule summaries) (Brett Zamir)
-* 1198b26 Docs: Minor README clarifications (Brett Zamir)
-* 03e6869 Fix: newline-before-return: bug with comment (fixes #5480) (mustafa)
-* ad100fd Fix: overindent in VariableDeclarator parens or brackets (fixes #5492) (David Greenspan)
-* 9b8e04b Docs: Replace all node references to Node.js which is the official name (Brett Zamir)
-* cc1f2f0 Docs: Minor fixes in no-new-func (Brett Zamir)
-* 6ab81d4 Docs: Distinguish examples in rules under Best Practices part 1 (Mark Pedrotti)
-* 9c6c70c Update: add `allowParens` option to `no-confusing-arrow` (fixes #5332) (Burak Yigit Kaya)
-* 979c096 Docs: Document linebreak-style as fixable. (Afnan Fahim)
-* 9f18a81 Fix: Ignore destructuring assignment in `object-shorthand` (fixes #5488) (alberto)
-* 5d9a798 Docs: README.md, prefer-const; change modified to reassigned (Michiel de Bruijne)
-* 38eb7f1 Fix: key-spacing checks ObjectExpression is multiline (fixes #5479) (Kevin Partington)
-* 9592c45 Fix: `no-unmodified-loop-condition` false positive (fixes #5445) (Toru Nagashima)
-
-v2.3.0 - March 4, 2016
-
-* 1b2c6e0 Update: Proposed no-magic-numbers option: ignoreJSXNumbers (fixes #5348) (Brandon Beeks)
-* 63c0b7d Docs: Fix incorrect environment ref. in Rules in Plugins. (fixes #5421) (Jesse McCarthy)
-* 124c447 Build: Add additional linebreak to docs (fixes #5464) (Ilya Volodin)
-* 0d3831b Docs: Add RuleTester parserOptions migration steps (Kevin Partington)
-* 50f4d5a Fix: extends chain (fixes #5411) (Toru Nagashima)
-* 0547072 Update: Replace getLast() with lodash.last() (fixes #5456) (Jordan Eldredge)
-* 8c29946 Docs: Distinguish examples in rules under Possible Errors part 1 (Mark Pedrotti)
-* 5319b4a Docs: Distinguish examples in rules under Possible Errors part 2 (Mark Pedrotti)
-* 1da2420 Fix: crash when SourceCode object was reused (fixes #5007) (Toru Nagashima)
-* 9e9daab New: newline-before-return rule (fixes #5009) (Kai Cataldo)
-* e1bbe45 Fix: Check space after anonymous generator star (fixes #5435) (alberto)
-* 119e0ed Docs: Distinguish examples in rules under Variables (Mark Pedrotti)
-* 905c049 Fix: `no-undef` false positive at new.target (fixes #5420) (Toru Nagashima)
-* 4a67b9a Update: Add ES7 support (fixes #5401) (Brandon Mills)
-* 89c757d Docs: Replace ecmaFeatures with parserOptions in working-with-rules (Kevin Partington)
-* 804c08e Docs: Add parserOptions to RuleTester section of working-with-rules (Kevin Partington)
-* 1982c50 Docs: Document string option for `no-unused-vars`. (alberto)
-* 4f82b2b Update: Support classes in `padded-blocks` (fixes #5092) (alberto)
-* ed5564f Docs: Specify results of `no-unused-var` with `args` (fixes #5334) (chinesedfan)
-* de0a4ef Fix: `getFormatter` throws an error when called as static (fixes #5378) (cowchimp)
-* 78f7ca9 Fix: Prevent crash from swallowing console.log (fixes #5381) (Ian VanSchooten)
-* 34b648d Fix: remove tests which have invalid syntax (fixes #5405) (Toru Nagashima)
-* 7de5ae4 Docs: Missing allow option in docs (Scott O'Hara)
-* cf14c71 Fix: `no-useless-constructor` rule crashes sometimes (fixes #5290) (Burak Yigit Kaya)
-* 70e3a02 Update: Allow string severity in config (fixes #3626) (Nicholas C. Zakas)
-* 13c7c19 Update: Exclude ES5 constructors from consistent-return (fixes #5379) (Kevin Locke)
-* 784d3bf Fix: Location info in `dot-notation` rule (fixes #5397) (Gyandeep Singh)
-* 6280b2d Update: Support switch statements in padded-blocks (fixes #5056) (alberto)
-* 25a5b2c Fix: Allow irregular whitespace in comments (fixes #5368) (Christophe Porteneuve)
-* 560c0d9 New: no-restricted-globals rule implementation (fixes #3966) (Benoît Zugmeyer)
-* c5bb478 Fix: `constructor-super` false positive after a loop (fixes #5394) (Toru Nagashima)
-* 6c0c4aa Docs: Add Issue template (fixes #5313) (Kai Cataldo)
-* 1170e67 Fix: indent rule doesn't handle constructor instantiation (fixes #5384) (Nate Cavanaugh)
-* 6bc9932 Fix: Avoid magic numbers in rule options (fixes #4182) (Brandon Beeks)
-* 694e1c1 Fix: Add tests to cover default magic number tests (fixes #5385) (Brandon Beeks)
-* 0b5349d Fix: .eslintignore paths should be absolute (fixes #5362) (alberto)
-* 8f6c2e7 Update: Better error message for plugins (refs #5221) (Nicholas C. Zakas)
-* 972d41b Update: Improve error message for rule-tester (fixes #5369) (Jeroen Engels)
-* fe3f6bd Fix: `no-self-assign` false positive at shorthand (fixes #5371) (Toru Nagashima)
-* 2376291 Docs: Missing space in `no-fallthrough` doc. (alberto)
-* 5aedb87 Docs: Add mysticatea as reviewer (Nicholas C. Zakas)
-* 1f9fd10 Update: no-invalid-regexp allows custom flags (fixes #5249) (Afnan Fahim)
-* f1eab9b Fix: Support for dash and slash in `valid-jsdoc` (fixes #1598) (Gyandeep Singh)
-* cd12a4b Fix:`newline-per-chained-call` should only warn on methods (fixes #5289) (Burak Yigit Kaya)
-* 0d1377d Docs: Add missing `symbol` type into valid list (Plusb Preco)
-* 6aa2380 Update: prefer-const; change modified to reassigned (fixes #5350) (Michiel de Bruijne)
-* d1d62c6 Fix: indent check for else keyword with Stroustrup style (fixes #5218) (Gyandeep Singh)
-* 7932f78 Build: Fix commit message validation (fixes #5340) (Nicholas C. Zakas)
-* 1c347f5 Fix: Cleanup temp files from tests (fixes #5338) (Nick)
-* 2f3e1ae Build: Change rules to warnings in perf test (fixes #5330) (Brandon Mills)
-* 36f40c2 Docs: Achieve consistent order of h2 in rule pages (Mark Pedrotti)
-
-v2.2.0 - February 19, 2016
-
-* 45a22b5 Docs: remove esprima-fb from suggested parsers (Henry Zhu)
-* a4d9cd3 Docs: Fix semi rule typo (Brandon Mills)
-* 9d005c0 Docs: Correct option name in `no-implicit-coercion` rule (Neil Kistner)
-* 2977248 Fix: Do not cache `.eslintrc.js` (fixes #5067) (Nick)
-* 211eb8f Fix: no-multi-spaces conflicts with smart tabs (fixes #2077) (Afnan Fahim)
-* 6dc9483 Fix: Crash in `constructor-super` (fixes #5319) (Burak Yigit Kaya)
-* 3f48875 Docs: Fix yield star spacing examples (Dmitriy Lazarev)
-* 4dab76e Docs: Update `preferType` heading to keep code format (fixes #5307) (chinesedfan)
-* 7020b82 Fix: `sort-imports` warned between default and members (fixes #5305) (Toru Nagashima)
-* 2f4cd1c Fix: `constructor-super` and `no-this-before-super` false (fixes #5261) (Toru Nagashima)
-* 59e9c5b New: eslint-disable-next-line (fixes #5206) (Kai Cataldo)
-* afb6708 Fix: `indent` rule forgot about some CallExpressions (fixes #5295) (Burak Yigit Kaya)
-* d18d406 Docs: Update PR creation bot message (fixes #5268) (Nicholas C. Zakas)
-* 0b1cd19 Fix: Ignore parser option if set to default parser (fixes #5241) (Kai Cataldo)
-
-v2.1.0 - February 15, 2016
-
-* 7981ef5 Build: Fix release script (Nicholas C. Zakas)
-* c9c34ea Fix: Skip computed members in `newline-per-chained-call` (fixes #5245) (Burak Yigit Kaya)
-* b32ddad Build: `npm run perf` command should check the exit code (fixes #5279) (Burak Yigit Kaya)
-* 6580d1c Docs: Fix incorrect `api.verify` JSDoc for `config` param (refs #5104) (Burak Yigit Kaya)
-* 1f47868 Docs: Update yield-star-spacing documentation for 2.0.0 (fixes #5272) (Burak Yigit Kaya)
-* 29da8aa Fix: `newline-after-var` crash on a switch statement (fixes #5277) (Toru Nagashima)
-* 86c5a20 Fix: `func-style` should ignore ExportDefaultDeclarations (fixes #5183) (Burak Yigit Kaya)
-* ba287aa Fix: Consolidate try/catches to top levels (fixes #5243) (Ian VanSchooten)
-* 3ef5da1 Docs: Update no-magic-numbers#ignorearrayindexes. (KazuakiM)
-* 0d6850e Update: Allow var declaration at end of block (fixes #5246) (alberto)
-* c1e3a73 Fix: Popular style init handles missing package.json keys (refs #5243) (Brandon Mills)
-* 68c6e22 Docs: fix default value of `keyword-spacing`'s overrides option. (Toru Nagashima)
-* 00fe46f Upgrade: inquirer (fixes #5265) (Bogdan Chadkin)
-* ef729d7 Docs: Remove option that is not being used in max-len rule (Thanos Lefteris)
-* 4a5ddd5 Docs: Fix rule config above examples for require-jsdoc (Thanos Lefteris)
-* c5cbc1b Docs: Add rule config above each example in jsx-quotes (Thanos Lefteris)
-* f0aceba Docs: Correct alphabetical ordering in rule list (Randy Coulman)
-* 1651ffa Docs: update migrating to 2.0.0 (fixes #5232) (Toru Nagashima)
-* 9078537 Fix: `indent` on variable declaration with separate array (fixes #5237) (Burak Yigit Kaya)
-* f8868b2 Docs: Typo fix in consistent-this rule doc fixes #5240 (Nicolas Froidure)
-* 44f6915 Fix: ESLint Bot mentions the wrong person for extra info (fixes #5229) (Burak Yigit Kaya)
-* c612a8e Fix: `no-empty-function` crash (fixes #5227) (Toru Nagashima)
-* ae663b6 Docs: Add links for issue documentation (Nicholas C. Zakas)
-* 717bede Build: Switch to using eslint-release (fixes #5223) (Nicholas C. Zakas)
-* 980e139 Fix: Combine all answers for processAnswers (fixes #5220) (Ian VanSchooten)
-* 1f2a1d5 Docs: Remove inline errors from doc examples (fixes #4104) (Burak Yigit Kaya)
-
-v2.0.0 - February 12, 2016
-
-* cc3a66b Docs: Issue message when more info is needed (Nicholas C. Zakas)
-* 2bc40fa Docs: Simplify hierarchy of headings in rule pages (Mark Pedrotti)
-* 1666254 Docs: Add note about only-whitespace rule for `--fix` (fixes #4774) (Burak Yigit Kaya)
-* 2fa09d2 Docs: Add `quotes` to related section of `prefer-template` (fixes #5192) (Burak Yigit Kaya)
-* 7b12995 Fix: `key-spacing` not enforcing no-space in minimum mode (fixes #5008) (Burak Yigit Kaya)
-* c1c4f4d Breaking: new `no-empty-function` rule (fixes #5161) (Toru Nagashima)
-
-v2.0.0-rc.1 - February 9, 2016
-
-* 4dad82a Update: Adding shared environment for node and browser (refs #5196) (Eli White)
-* b46c893 Fix: Config file relative paths (fixes #5164, fixes #5160) (Nicholas C. Zakas)
-* aa5b2ac Fix: no-whitespace-before-property fixes (fixes #5167) (Kai Cataldo)
-* 4e99924 Update: Replace several dependencies with lodash (fixes #5012) (Gajus Kuizinas)
-* 718dc68 Docs: Remove periods in rules' README for consistency. (alberto)
-* 7a47085 Docs: Correct `arrow-spacing` overview. (alberto)
-* a4cde1b Docs: Clarify global-require inside try/catch (fixes #3834) (Brandon Mills)
-* fd07925 Docs: Clarify docs for api.verify (fixes #5101, fixes #5104) (Burak Yigit Kaya)
-* 413247f New: Add a --print-config flag (fixes #5099) (Christopher Crouzet)
-* efeef42 Update: Implement auto fix for space-in-parens (fixes #5050) (alberto)
-* e07fdd4 Fix: code path analysis and labels (fixes #5171) (Toru Nagashima)
-* 2417bb2 Fix: `no-unmodified-loop-condition` false positive (fixes #5166) (Toru Nagashima)
-* fae1884 Fix: Allow same-line comments in padded-blocks (fixes #5055) (Brandon Mills)
-* a24d8ad Fix: Improve autoconfig logging (fixes #5119) (Ian VanSchooten)
-* e525923 Docs: Correct obvious inconsistencies in rules h2 elements (Mark Pedrotti)
-* 9675b5e Docs: `avoid-escape` does not allow backticks (fixes #5147) (alberto)
-* a03919a Fix: `no-unexpected-multiline` false positive (fixes #5148) (Feross Aboukhadijeh)
-* 74360d6 Docs: Note no-empty applies to empty block statements (fixes #5105) (alberto)
-* 6eeaa3f Build: Remove pending tests (fixes #5126) (Ian VanSchooten)
-* 02c83df Docs: Update docs/rules/no-plusplus.md (Sheldon Griffin)
-* 0c4de5c New: Added "table" formatter (fixes #4037) (Gajus Kuizinas)
-* 0a59926 Update: 'implied strict mode' ecmaFeature (fixes #4832) (Nick Evans)
-* 53a6eb3 Fix: Handle singular case in rule-tester error message (fixes #5141) (Bryan Smith)
-* 97ac91c Build: Increment eslint-config-eslint (Nicholas C. Zakas)
-
-v2.0.0-rc.0 - February 2, 2016
-
-* 973c499 Fix: `sort-imports` crash (fixes #5130) (Toru Nagashima)
-* e64b2c2 Breaking: remove `no-empty-label` (fixes #5042) (Toru Nagashima)
-* 79ebbc9 Breaking: update `eslint:recommended` (fixes #5103) (Toru Nagashima)
-* e1d7368 New: `no-extra-label` rule (fixes #5059) (Toru Nagashima)
-* c83b48c Fix: find ignore file only in cwd (fixes #5087) (Nicholas C. Zakas)
-* 3a24240 Docs: Fix jsdoc param names to match function param names (Thanos Lefteris)
-* 1d79746 Docs: Replace ecmaFeatures setting with link to config page (Thanos Lefteris)
-* e96ffd2 New: `template-curly-spacing` rule (fixes #5049) (Toru Nagashima)
-* 4b02902 Update: Extended no-console rule (fixes #5095) (EricHenry)
-* 757651e Docs: Remove reference to rules enabled by default (fixes #5100) (Brandon Mills)
-* 0d87f5d Docs: Clarify eslint-disable comments only affect rules (fixes #5005) (Brandon Mills)
-* 1e791a2 New: `no-self-assign` rule (fixes #4729) (Toru Nagashima)
-* c706eb9 Fix: reduced `no-loop-func` false positive (fixes #5044) (Toru Nagashima)
-* 3275e86 Update: Add extra aliases to consistent-this rule (fixes #4492) (Zachary Alexander Belford)
-* a227360 Docs: Replace joyent org with nodejs (Thanos Lefteris)
-* b2aedfe New: Rule to enforce newline after each call in the chain (fixes #4538) (Rajendra Patil)
-* d67bfdd New: `no-unused-labels` rule (fixes #5052) (Toru Nagashima)
-
-v2.0.0-beta.3 - January 29, 2016
-
-* 86a3e3d Update: Remove blank lines at beginning of files (fixes #5045) (Jared Sohn)
-* 4fea752 New: Autoconfiguration from source inspection (fixes #3567) (Ian VanSchooten)
-* 519f39f Breaking: Remove deprecated rules (fixes #5032) (Gyandeep Singh)
-* c75ee4a New: Add support for configs in plugins (fixes #3659) (Ilya Volodin)
-* 361377f Fix: `prefer-const` false positive reading before writing (fixes #5074) (Toru Nagashima)
-* ff2551d Build: Improve `npm run perf` command (fixes #5028) (Toru Nagashima)
-* bcca69b Update: add int32Hint option to `no-bitwise` rule (fixes #4873) (Maga D. Zandaqo)
-* e3f2683 Update: config extends dependency lookup (fixes #5023) (Nicholas C. Zakas)
-* a327a06 Fix: Indent rule for allman brace style scenario (fixes #5064) (Gyandeep Singh)
-* afdff6d Fix: `no-extra-bind` false positive (fixes #5058) (Toru Nagashima)
-* c1fad4f Update: add autofix support for spaced-comment (fixes #4969, fixes #5030) (Maga D. Zandaqo)
-* 889b942 Revert "Docs: Update readme for legend describing rules icons (refs #4355)" (Nicholas C. Zakas)
-* b0f21a0 Fix: `keyword-spacing` false positive in template strings (fixes #5043) (Toru Nagashima)
-* 53fa5d1 Fix: `prefer-const` false positive in a loop condition (fixes #5024) (Toru Nagashima)
-* 385d399 Docs: Update readme for legend describing rules icons (Kai Cataldo)
-* 505f1a6 Update: Allow parser to be relative to config (fixes #4985) (Nicholas C. Zakas)
-* 79e8a0b New: `one-var-declaration-per-line` rule (fixes #1622) (alberto)
-* 654e6e1 Update: Check extra Boolean calls in no-extra-boolean-cast (fixes #3650) (Andrew Sutton)
-
-v2.0.0-beta.2 - January 22, 2016
-
-* 3fa834f Docs: Fix formatter links (fixes #5006) (Gyandeep Singh)
-* 54b1bc8 Docs: Fix link in strict.md (fixes #5026) (Nick Evans)
-* e0c5cf7 Upgrade: Espree to 3.0.0 (fixes #5018) (Ilya Volodin)
-* 69f149d Docs: language tweaks (Andres Kalle)
-* 2b33c74 Update: valid-jsdoc to not require @return in constructors (fixes #4976) (Maga D. Zandaqo)
-* 6ac2e01 Docs: Fix description of exported comment (Mickael Jeanroy)
-* 29392f8 New: allow-multiline option on comma-dangle (fixes #4967) (Alberto Gimeno)
-* 05b8cb3 Update: Module overrides all 'strict' rule options (fixes #4936) (Nick Evans)
-* 8470474 New: Add metadata to few test rules (fixes #4494) (Ilya Volodin)
-* ba11c1b Docs: Add Algolia as sponsor to README (Nicholas C. Zakas)
-* b28a19d Breaking: Plugins envs and config removal (fixes #4782, fixes #4952) (Nicholas C. Zakas)
-* a456077 Docs: newline-after-var doesn't allow invalid options. (alberto)
-* 3e6a24e Breaking: Change `strict` default mode to "safe" (fixes #4961) (alberto)
-* 5b96265 Breaking: Update eslint:recommended (fixes #4953) (alberto)
-* 7457a4e Upgrade: glob to 6.x (fixes #4991) (Gyandeep Singh)
-* d3f4bdd Build: Cleanup for code coverage (fixes #4983) (Gyandeep Singh)
-* b8fbaa0 Fix: multiple message in TAP formatter (fixes #4975) (Simon Degraeve)
-* 990f8da Fix: `getNodeByRangeIndex` performance issue (fixes #4989) (Toru Nagashima)
-* 8ac1dac Build: Update markdownlint dependency to 0.1.0 (fixes #4988) (David Anson)
-* 5cd5429 Fix: function expression doc in call expression (fixes #4964) (Tim Schaub)
-* 4173baa Fix: `no-dupe-class-members` false positive (fixes #4981) (Toru Nagashima)
-* 12fe803 Breaking: Supports Unicode BOM (fixes #4878) (Toru Nagashima)
-* 1fc80e9 Build: Increment eslint-config-eslint (Nicholas C. Zakas)
-* e0a9024 Update: Report newline between template tag and literal (fixes #4210) (Rajendra Patil)
-* da3336c Update: Rules should get `sourceType` from Program node (fixes #4960) (Nick Evans)
-* a2ac359 Update: Make jsx-quotes fixable (refs #4377) (Gabriele Petronella)
-* ee1014d Fix: Incorrect error location for object-curly-spacing (fixes #4957) (alberto)
-* b52ed17 Fix: Incorrect error location for space-in-parens (fixes #4956) (alberto)
-* 9c1bafb Fix: Columns of parse errors are off by 1 (fixes #4896) (alberto)
-* 5e4841e New: 'id-blacklist' rule (fixes #3358) (Keith Cirkel)
-* 700b8bc Update: Add "allow" option to allow specific operators (fixes #3308) (Rajendra Patil)
-* d82eeb1 Update: Add describe around rule tester blocks (fixes #4907) (Ilya Volodin)
-* 2967402 Update: Add minimum value to integer values in schema (fixes #4941) (Ilya Volodin)
-* 7b632f8 Upgrade: Globals to ^8.18.0 (fixes #4728) (Gyandeep Singh)
-* 86e6e57 Fix: Incorrect error at EOF for no-multiple-empty-lines (fixes #4917) (alberto)
-* 7f058f3 Fix: Incorrect location for padded-blocks (fixes #4913) (alberto)
-* b3de8f7 Fix: Do not show ignore messages for default ignored files (fixes #4931) (Gyandeep Singh)
-* b1360da Update: Support multiLine and singleLine options (fixes #4697) (Rajendra Patil)
-* 82fbe09 Docs: Small semantic issue in documentation example (fixes #4937) (Marcelo Zarate)
-* 13a4e30 Docs: Formatting inconsistencies (fixes #4912) (alberto)
-* d487013 Update: Option to allow extra parens for cond assign (fixes #3317) (alberto)
-* 0f469b4 Fix: JSDoc for function expression on object property (fixes #4900) (Tim Schaub)
-* c2dee27 Update: Add module tests to no-extra-semi (fixes #4915) (Nicholas C. Zakas)
-* 5a633bf Update: Add `preferType` option to `valid-jsdoc` rule (fixes #3056) (Gyandeep Singh)
-* ebd01b7 Build: Fix version number on release (fixes #4921) (Nicholas C. Zakas)
-* 2d626a3 Docs: Fix typo in changelog (Nicholas C. Zakas)
-* c4c4139 Fix: global-require no longer warns if require is shadowed (fixes #4812) (Kevin Partington)
-* bbf7f27 New: provide config.parser via `parserName` on RuleContext (fixes #3670) (Ben Mosher)
-
-v2.0.0-beta.1 - January 11, 2016
-
-* 6c70d84 Build: Fix prerelease script (fixes #4919) (Nicholas C. Zakas)
-* d5c9435 New: 'sort-imports' rule (refs #3143) (Christian Schuller)
-* a8cfd56 Fix: remove duplicate of eslint-config-eslint (fixes #4909) (Toru Nagashima)
-* 19a9fbb Breaking: `space-before-blocks` ignores after keywords (fixes #1338) (Toru Nagashima)
-* c275b41 Fix: no-extra-parens ExpressionStatement restricted prods (fixes #4902) (Michael Ficarra)
-* b795850 Breaking: don't load ~/.eslintrc when using --config flag (fixes #4881) (alberto)
-* 3906481 Build: Add AppVeyor CI (fixes #4894) (Gyandeep Singh)
-* 6390862 Docs: Fix missing footnote (Yoshiya Hinosawa)
-* e5e06f8 Fix: Jsdoc comment for multi-line function expressions (fixes #4889) (Gyandeep Singh)
-* 7c9be60 Fix: Fix path errors in windows (fixes #4888) (Gyandeep Singh)
-* a1840e7 Fix: gray text was invisible on Solarized Dark theme (fixes #4886) (Jack Leigh)
-* fc9f528 Docs: Modify unnecessary flag docs in quote-props (Matija Marohnić)
-* 186e8f0 Update: Ignore camelcase in object destructuring (fixes #3185) (alberto)
-* 7c97201 Upgrade: doctrine version to 1.1.0 (fixes #4854) (Tim Schaub)
-* ceaf324 New: Add no-new-symbol rule (fixes #4862) (alberto)
-* e2f2b66 Breaking: Remove defaults from `eslint:recommended` (fixes #4809) (Ian VanSchooten)
-* 0b3c01e Docs: Specify default for func-style (fixes #4834) (Ian VanSchooten)
-* 008ea39 Docs: Document default for operator assignment (fixes #4835) (alberto)
-* b566f56 Docs: no-new-func typo (alberto)
-* 1569695 Update: Adds default 'that' for consistent-this (fixes #4833) (alberto)
-* f7b28b7 Docs: clarify `requireReturn` option for valid-jsdoc rule (fixes #4859) (Tim Schaub)
-* 407f329 Build: Fix prerelease script (Nicholas C. Zakas)
-* 688f277 Fix: Set proper exit code for Node > 0.10 (fixes #4691) (Nicholas C. Zakas)
-* 58715e9 Fix: Use single quotes in context.report messages (fixes #4845) (Joe Lencioni)
-* 5b7586b Fix: do not require a @return tag for @interface (fixes #4860) (Tim Schaub)
-* d43f26c Breaking: migrate from minimatch to node-ignore (fixes #2365) (Stefan Grönke)
-* c07ca39 Breaking: merges keyword spacing rules (fixes #3869) (Toru Nagashima)
-* 871f534 Upgrade: Optionator version to 0.8.1 (fixes #4851) (Eric Johnson)
-* 82d4cd9 Update: Add atomtest env (fixes #4848) (Andres Suarez)
-* 9c9beb5 Update: Add "ignore" override for operator-linebreak (fixes #4294) (Rajendra Patil)
-* 9c03abc Update: Add "allowCall" option (fixes #4011) (Rajendra Patil)
-* 29516f1 Docs: fix migration guide for no-arrow-condition rule (Peter Newnham)
-* 2ef7549 Docs: clarify remedy to some prefer-const errors (Turadg Aleahmad)
-* 1288ba4 Update: Add default limit to `complexity` (fixes #4808) (Ian VanSchooten)
-* d3e8179 Fix: env is rewritten by modules (fixes #4814) (Toru Nagashima)
-* fd72aba Docs: Example fix for `no-extra-parens` rule (fixes #3527) (Gyandeep Singh)
-* 315f272 Fix: Change max-warnings type to Int (fixes #4660) (George Zahariev)
-* 5050768 Update: Ask for `commonjs` under config init (fixes #3553) (Gyandeep Singh)
-* 4665256 New: Add no-whitespace-before-property rule (fixes #1086) (Kai Cataldo)
-* f500d7d Fix: allow extending @scope/eslint/file (fixes #4800) (André Cruz)
-* 5ab564e New: 'ignoreArrayIndexes' option for 'no-magic-numbers' (fixes #4370) (Christian Schuller)
-* 97cdb95 New: Add no-useless-constructor rule (fixes #4785) (alberto)
-* b9bcbaf Fix: Bug in no-extra-bind (fixes #4806) (Andres Kalle)
-* 246a6d2 Docs: Documentation fix (Andres Kalle)
-* 9ea6b36 Update: Ignore case in jsdoc tags (fixes #4576) (alberto)
-* acdda24 Fix: ignore argument parens in no-unexpected-multiline (fixes #4658) (alberto)
-* 4931f56 Update: optionally allow bitwise operators (fixes #4742) (Swaagie)
-
-v2.0.0-alpha-2 - December 23, 2015
-
-* Build: Add prerelease script (Nicholas C. Zakas)
-* Update: Allow to omit semi for one-line blocks (fixes #4385) (alberto)
-* Fix: Handle getters and setters in key-spacing (fixes #4792) (Brandon Mills)
-* Fix: ObjectRestSpread throws error in key-spacing rule (fixes #4763) (Ziad El Khoury Hanna)
-* Docs: Typo in generator-star (alberto)
-* Fix: Backtick behavior in quotes rule (fixes #3090) (Nicholas C. Zakas)
-* Fix: Empty schemas forbid any options (fixes #4789) (Brandon Mills)
-* Fix: Remove `isMarkedAsUsed` function name (fixes #4783) (Gyandeep Singh)
-* Fix: support arrow functions in no-return-assign (fixes #4743) (alberto)
-* Docs: Add license header to Working with Rules guide (Brandon Mills)
-* Fix: RuleTester to show parsing errors (fixes #4779) (Nicholas C. Zakas)
-* Docs: Escape underscores in no-path-concat (alberto)
-* Update: configuration for classes in space-before-blocks (fixes #4089) (alberto)
-* Docs: Typo in no-useless-concat (alberto)
-* Docs: fix typos, suggests (molee1905)
-* Docs: Typos in space-before-keywords and space-unary-ops (fixes #4771) (alberto)
-* Upgrade: beefy to ^2.0.0, fixes installation errors (fixes #4760) (Kai Cataldo)
-* Docs: Typo in no-unexpected-multiline (fixes #4756) (alberto)
-* Update: option to ignore top-level max statements (fixes #4309) (alberto)
-* Update: Implement auto fix for semi-spacing rule (fixes #3829) (alberto)
-* Fix: small typos in code examples (Plusb Preco)
-* Docs: Add section on file extensions to user-guide/configuring (adam)
-* Fix: Comma first issue in `indent` (fixes #4739, fixes #3456) (Gyandeep Singh)
-* Fix: no-constant-condition false positive (fixes #4737) (alberto)
-* Fix: Add source property for fatal errors (fixes #3325) (Gyandeep Singh)
-* New: Add a comment length option to the max-len rule (fixes #4665) (Ian)
-* Docs: RuleTester doesn't require any tests (fixes #4681) (alberto)
-* Fix: Remove path analysis from debug log (fixes #4631) (Ilya Volodin)
-* Fix: Set null to property ruleId when fatal is true (fixes #4722) (Sébastien Règne)
-* New: Visual Studio compatible formatter (fixes #4708) (rhpijnacker)
-* New: Add greasemonkey environment (fixes #4715) (silverwind)
-* Fix: always-multiline for comma-dangle import (fixes #4704) (Nicholas C. Zakas)
-* Fix: Check 1tbs non-block else (fixes #4692) (Nicholas C. Zakas)
-* Fix: Apply environment configs last (fixes #3915) (Nicholas C. Zakas)
-* New: `no-unmodified-loop-condition` rule (fixes #4523) (Toru Nagashima)
-* Breaking: deprecate `no-arrow-condition` rule (fixes #4417) (Luke Karrys)
-* Update: Add cwd option for cli-engine (fixes #4472) (Ilya Volodin)
-* New: Add no-confusing-arrow rule (refs #4417) (Luke Karrys)
-* Fix: ensure `ConfigOps.merge` do a deep copy (fixes #4682) (Toru Nagashima)
-* Fix: `no-invalid-this` allows this in static method (fixes #4669) (Toru Nagashima)
-* Fix: Export class syntax for `require-jsdoc` rule (fixes #4667) (Gyandeep Singh)
-* Update: Add "safe" mode to strict (fixes #3306) (Brandon Mills)
-
-v2.0.0-alpha-1 - December 11, 2015
-
-* Breaking: Correct links between variables and references (fixes #4615) (Toru Nagashima)
-* Fix: Update rule tests for parser options (fixes #4673) (Nicholas C. Zakas)
-* Breaking: Implement parserOptions (fixes #4641) (Nicholas C. Zakas)
-* Fix: max-len rule overestimates the width of some tabs (fixes #4661) (Nick Evans)
-* New: Add no-implicit-globals rule (fixes #4542) (Joshua Peek)
-* Update: `no-use-before-define` checks invalid initializer (fixes #4280) (Toru Nagashima)
-* Fix: Use oneValuePerFlag for --ignore-pattern option (fixes #4507) (George Zahariev)
-* New: `array-callback-return` rule (fixes #1128) (Toru Nagashima)
-* Upgrade: Handlebars to >= 4.0.5 for security reasons (fixes #4642) (Jacques Favreau)
-* Update: Add class body support to `indent` rule (fixes #4372) (Gyandeep Singh)
-* Breaking: Remove space-after-keyword newline check (fixes #4149) (Nicholas C. Zakas)
-* Breaking: Treat package.json like the rest of configs (fixes #4451) (Ilya Volodin)
-* Docs: writing mistake (molee1905)
-* Update: Add 'method' option to no-empty (fixes #4605) (Kai Cataldo)
-* Breaking: Remove autofix from eqeqeq (fixes #4578) (Ilya Volodin)
-* Breaking: Remove ES6 global variables from builtins (fixes #4085) (Brandon Mills)
-* Fix: Handle forbidden LineTerminators in no-extra-parens (fixes #4229) (Brandon Mills)
-* Update: Option to ignore constructor Fns object-shorthand (fixes #4487) (Kai Cataldo)
-* Fix: Check YieldExpression argument in no-extra-parens (fixes #4608) (Brandon Mills)
-* Fix: Do not cache `package.json` (fixes #4611) (Spain)
-* Build: Consume no-underscore-dangle allowAfterThis option (fixes #4599) (Kevin Partington)
-* New: Add no-restricted-imports rule (fixes #3196) (Guy Ellis)
-* Docs: no-extra-semi no longer refers to deprecated rule (fixes #4598) (Kevin Partington)
-* Fix: `consistent-return` checks the last (refs #3530, fixes #3373) (Toru Nagashima)
-* Update: add class option to `no-use-before-define` (fixes #3944) (Toru Nagashima)
-* Breaking: Simplify rule schemas (fixes #3625) (Nicholas C. Zakas)
-* Docs: Update docs/rules/no-plusplus.md (Xiangyun Chi)
-* Breaking: added bower_components to default ignore (fixes #3550) (Julian Laval)
-* Fix: `no-unreachable` with the code path (refs #3530, fixes #3939) (Toru Nagashima)
-* Fix: `no-this-before-super` with the code path analysis (refs #3530) (Toru Nagashima)
-* Fix: `no-fallthrough` with the code path analysis (refs #3530) (Toru Nagashima)
-* Fix: `constructor-super` with the code path analysis (refs #3530) (Toru Nagashima)
-* Breaking: Switch to Espree 3.0.0 (fixes #4334) (Nicholas C. Zakas)
-* Breaking: Freeze context object (fixes #4495) (Nicholas C. Zakas)
-* Docs: Add Code of Conduct (fixes #3095) (Nicholas C. Zakas)
-* Breaking: Remove warnings of readonly from `no-undef` (fixes #4504) (Toru Nagashima)
-* Update: allowAfterThis option in no-underscore-dangle (fixes #3435) (just-boris)
-* Fix: Adding options unit tests for --ignore-pattern (refs #4507) (Kevin Partington)
-* Breaking: Implement yield-star-spacing rule (fixes #4115) (Bryan Smith)
-* New: `prefer-rest-params` rule (fixes #4108) (Toru Nagashima)
-* Update: `prefer-const` begins to cover separating init (fixes #4474) (Toru Nagashima)
-* Fix: `no-eval` come to catch indirect eval (fixes #4399, fixes #4441) (Toru Nagashima)
-* Breaking: Default no-magic-numbers to none. (fixes #4193) (alberto)
-* Breaking: Allow empty arrow body (fixes #4411) (alberto)
-* New: Code Path Analysis (fixes #3530) (Toru Nagashima)
-
-v1.10.3 - December 1, 2015
-
-* Docs: Update strict rule docs (fixes #4583) (Nicholas C. Zakas)
-* Docs: Reference .eslintrc.* in contributing docs (fixes #4532) (Kai Cataldo)
-* Fix: Add for-of to `curly` rule (fixes #4571) (Kai Cataldo)
-* Fix: Ignore space before function in array start (fixes #4569) (alberto)
-
-v1.10.2 - November 27, 2015
-
-* Upgrade: escope@3.3.0 (refs #4485) (Nicholas C. Zakas)
-* Upgrade: Pinned down js-yaml to avoid breaking dep (fixes #4553) (alberto)
-* Fix: lines-around-comment with multiple comments (fixes #3509) (alberto)
-* Upgrade: doctrine@0.7.1 (fixes #4545) (Kevin Partington)
-* Fix: Bugfix for eqeqeq autofix (fixes #4540) (Kevin Partington)
-* Fix: Add for-in to `curly` rule (fixes #4436) (Kai Cataldo)
-* Fix: `valid-jsdoc` unneeded require check fix (fixes #4527) (Gyandeep Singh)
-* Fix: `brace-style` ASI fix for if-else condition (fixes #4520) (Gyandeep Singh)
-* Build: Add branch update during release process (fixes #4491) (Gyandeep Singh)
-* Build: Allow revert commits in commit messages (fixes #4452) (alberto)
-* Fix: Incorrect location in no-fallthrough (fixes #4516) (alberto)
-* Fix: `no-spaced-func` had been crashed (fixes #4508) (Toru Nagashima)
-* Fix: Add a RestProperty test of `no-undef` (fixes #3271) (Toru Nagashima)
-* Docs: Load badge from HTTPS (Brian J Brennan)
-* Build: Update eslint bot messages (fixes #4497) (Nicholas C. Zakas)
-
-v1.10.1 - November 20, 2015
-
-* Fix: Revert freezing context object (refs #4495) (Nicholas C. Zakas)
-* 1.10.0 (Nicholas C. Zakas)
-
-v1.10.0 - November 20, 2015
-
-* Docs: Remove dupes from changelog (Nicholas C. Zakas)
-* Update: --init to create extensioned files (fixes #4476) (Nicholas C. Zakas)
-* Docs: Update description of exported comment (fixes #3916) (Nicholas C. Zakas)
-* Docs: Move legacy rules to stylistic (files #4111) (Nicholas C. Zakas)
-* Docs: Clean up description of recommended rules (fixes #4365) (Nicholas C. Zakas)
-* Docs: Fix home directory config description (fixes #4398) (Nicholas C. Zakas)
-* Update: Add class support to `require-jsdoc` rule (fixes #4268) (Gyandeep Singh)
-* Update: return type error in `valid-jsdoc` rule (fixes #4443) (Gyandeep Singh)
-* Update: Display errors at the place where fix should go (fixes #4470) (nightwing)
-* Docs: Fix typo in default `cacheLocation` value (Andrew Hutchings)
-* Fix: Handle comments in block-spacing (fixes #4387) (alberto)
-* Update: Accept array for `ignorePattern` (fixes #3982) (Jesse McCarthy)
-* Update: replace label and break with IIFE and return (fixes #4459) (Ilya Panasenko)
-* Fix: space-before-keywords false positive (fixes #4449) (alberto)
-* Fix: Improves performance (refs #3530) (Toru Nagashima)
-* Fix: Autofix quotes produces invalid javascript (fixes #4380) (nightwing)
-* Docs: Update indent.md (Nathan Brown)
-* New: Disable comment config option (fixes #3901) (Matthew Riley MacPherson)
-* New: Config files with extensions (fixes #4045, fixes #4263) (Nicholas C. Zakas)
-* Revert "Update: Add JSX exceptions to no-extra-parens (fixes #4229)" (Brandon Mills)
-* Update: Add JSX exceptions to no-extra-parens (fixes #4229) (Brandon Mills)
-* Docs: Replace link to deprecated rule with newer rule (Andrew Marshall)
-* Fix: `no-extend-native` crashed at empty defineProperty (fixes #4438) (Toru Nagashima)
-* Fix: Support empty if blocks in lines-around-comment (fixes #4339) (alberto)
-* Fix: `curly` warns wrong location for `else` (fixes #4362) (Toru Nagashima)
-* Fix: `id-length` properties never option (fixes #4347) (Toru Nagashima)
-* Docs: missing close rbracket in example (@storkme)
-* Revert "Update: Allow empty arrow body (fixes #4411)" (Nicholas C. Zakas)
-* Fix: eqeqeq autofix avoids clashes with space-infix-ops (fixes #4423) (Kevin Partington)
-* Docs: Document semi-spacing behaviour (fixes #4404) (alberto)
-* Update: Allow empty arrow body (fixes #4411) (alberto)
-* Fix: Handle comments in comma-spacing (fixes #4389) (alberto)
-* Update: Refactor eslint.verify args (fixes #4395) (Nicholas C. Zakas)
-* Fix: no-undef-init should ignore const (fixes #4284) (Nicholas C. Zakas)
-* Fix: Add the missing "as-needed" docs to the radix rule (fixes #4364) (Michał Gołębiowski)
-* Fix: Display singular/plural version of "line" in message (fixes #4359) (Marius Schulz)
-* Update: Add Popular Style Guides (fixes #4320) (Jamund Ferguson)
-* Fix: eslint.report can be called w/o node if loc provided (fixes #4220) (Kevin Partington)
-* Update: no-implicit-coercion validate AssignmentExpression (fixes #4348) (Ilya Panasenko)
-
-v1.9.0 - November 6, 2015
-
-* Update: Make radix accept a "as-needed" option (fixes #4048) (Michał Gołębiowski)
-* Fix: Update the message to include number of lines (fixes #4342) (Brian Delahunty)
-* Docs: ASI causes problem whether semicolons are used or not (Thai Pangsakulyanont)
-* Fix: Fixer to not overlap ranges among fix objects (fixes #4321) (Gyandeep Singh)
-* Update: Add default to `max-nested-callbacks` (fixes #4297) (alberto)
-* Fix: Check comments in space-in-parens (fixes #4302) (alberto)
-* Update: Add quotes to error messages to improve clarity (fixes #4313) (alberto)
-* Fix: tests failing due to differences in temporary paths (fixes #4324) (alberto)
-* Fix: Make tests compatible with Windows (fixes #4315) (Ian VanSchooten)
-* Update: Extract glob and filesystem logic from cli-engine (fixes #4305) (Ian VanSchooten)
-* Build: Clarify commit-check messages (fixes #4256) (Ian VanSchooten)
-* Upgrade: Upgrade various dependencies (fixes #4303) (Gyandeep Singh)
-* Build: Add node 5 to travis build (fixes #4310) (Gyandeep Singh)
-* Fix: ensure using correct estraverse (fixes #3951) (Toru Nagashima)
-* Docs: update docs about using gitignore (Mateusz Derks)
-* Update: Detect and fix wrong linebreaks (fixes #3981) (alberto)
-* New: Add no-case-declarations rule (fixes #4278) (Erik Arvidsson)
-
-v1.8.0 - October 30, 2015
-
-* Fix: Check for node property before testing type (fixes #4298) (Ian VanSchooten)
-* Docs: Specify 'double' as default for quotes (fixes #4270) (Ian VanSchooten)
-* Fix: Missing errors in space-in-parens (fixes #4257, fixes #3996) (alberto)
-* Docs: fixed typo (Mathieu M-Gosselin)
-* Fix: `cacheLocation` handles paths in windows style. (fixes #4285) (royriojas)
-* Docs: fixed typo (mpal9000)
-* Update: Add support for class in `valid-jsdoc` rule (fixes #4279) (Gyandeep Singh)
-* Update: cache-file accepts a directory. (fixes #4241) (royriojas)
-* Update: Add `maxEOF` to no-multiple-empty-lines (fixes #4235) (Adrien Vergé)
-* Update: fix option for comma-spacing (fixes #4232) (HIPP Edgar (PRESTA EXT))
-* Docs: Fix use of wrong word in configuration doc (Jérémie Astori)
-* Fix: Prepare config before verifying SourceCode (fixes #4230) (Ian VanSchooten)
-* Update: RuleTester come to check AST was not modified (fixes #4156) (Toru Nagashima)
-* Fix: wrong count for 'no-multiple-empty-lines' on last line (fixes #4228) (alberto)
-* Update: Add `allow` option to `no-shadow` rule (fixes #3035) (Gyandeep Singh)
-* Doc: Correct the spelling of Alberto's surname (alberto)
-* Docs: Add alberto as a committer (Gyandeep Singh)
-* Build: Do not stub console in testing (fixes #1328) (Gyandeep Singh)
-* Fix: Check node exists before checking type (fixes #4231) (Ian VanSchooten)
-* Update: Option to exclude afterthoughts from no-plusplus (fixes #4093) (Brody McKee)
-* New: Add rule no-arrow-condition (fixes #3280) (Luke Karrys)
-* Update: Add linebreak style option to eol-last (fixes #4148) (alberto)
-* New: arrow-body-style rule (fixes #4109) (alberto)
-
-v1.7.3 - October 21, 2015
-
-* Fix: Support comma-first style in key-spacing (fixes #3877) (Brandon Mills)
-* Fix: no-magic-numbers: variable declarations (fixes #4192) (Ilya Panasenko)
-* Fix: Support ES6 shorthand in key-spacing (fixes #3678) (Brandon Mills)
-* Fix: `indent` array with memberExpression (fixes #4203) (Gyandeep Singh)
-* Fix: `indent` param function on sameline (fixes #4174) (Gyandeep Singh)
-* Fix: no-multiple-empty-lines fails when empty line at EOF (fixes #4214) (alberto)
-* Fix: `comma-dangle` false positive (fixes #4200) (Nicholas C. Zakas)
-* Fix: `valid-jsdoc` prefer problem (fixes #4205) (Nicholas C. Zakas)
-* Docs: Add missing single-quote (Kevin Lamping)
-* Fix: correct no-multiple-empty-lines at EOF (fixes #4140) (alberto)
-
-v1.7.2 - October 19, 2015
-
-* Fix: comma-dangle confused by parens (fixes #4195) (Nicholas C. Zakas)
-* Fix: no-mixed-spaces-and-tabs (fixes #4189, fixes #4190) (alberto)
-* Fix: no-extend-native disallow using Object.properties (fixes #4180) (Nathan Woltman)
-* Fix: no-magic-numbers should ignore Number.parseInt (fixes #4167) (Henry Zhu)
-
-v1.7.1 - October 16, 2015
-
-* Fix: id-match schema (fixes #4155) (Nicholas C. Zakas)
-* Fix: no-magic-numbers should ignore parseInt (fixes #4167) (Nicholas C. Zakas)
-* Fix: `indent` param function fix (fixes #4165, fixes #4164) (Gyandeep Singh)
-
-v1.7.0 - October 16, 2015
-
-* Fix: array-bracket-spacing for empty array (fixes #4141) (alberto)
-* Fix: `indent` arrow function check fix (fixes #4142) (Gyandeep Singh)
-* Update: Support .js files for config (fixes #3102) (Gyandeep Singh)
-* Fix: Make eslint-config-eslint work (fixes #4145) (Nicholas C. Zakas)
-* Fix: `prefer-arrow-callback` had been wrong at arguments (fixes #4095) (Toru Nagashima)
-* Docs: Update various rules docs (Nicholas C. Zakas)
-* New: Create eslint-config-eslint (fixes #3525) (Nicholas C. Zakas)
-* Update: RuleTester allows string errors in invalid cases (fixes #4117) (Kevin Partington)
-* Docs: Reference no-unexpected-multiline in semi (fixes #4114) (alberto)
-* Update: added exceptions to `lines-around-comment` rule. (fixes #2965) (Mathieu M-Gosselin)
-* Update: Add `matchDescription` option to `valid-jsdoc` (fixes #2449) (Gyandeep Singh)
-* Fix: check for objects or arrays in array-bracket-spacing (fixes #4083) (alberto)
-* Docs: Alphabetize Rules lists (Kenneth Chung)
-* Fix: message templates fail when no parameters are passed (fixes #4080) (Ilya Volodin)
-* Fix: `indent` multi-line function call (fixes #4073, fixes #4075) (Gyandeep Singh)
-* Docs: Improve comma-dangle documentation (Gilad Peleg)
-* Fix: no-mixed-tabs-and-spaces fails with some comments (fixes #4086) (alberto)
-* Fix: `semi` to check for do-while loops (fixes #4090) (Gyandeep Singh)
-* Build: Fix path related failures on Windows in tests (fixes #4061) (Burak Yigit Kaya)
-* Fix: `no-unused-vars` had been missing some parameters (fixes #4047) (Toru Nagashima)
-* Fix: no-mixed-spaces-and-tabs with comments and templates (fixes #4077) (alberto)
-* Update: Add `allow` option for `no-underscore-dangle` rule (fixes #2135) (Gyandeep Singh)
-* Update: `allowArrowFunctions` option for `func-style` rule (fixes #1897) (Gyandeep Singh)
-* Fix: Ignore template literals in no-mixed-tabs-and-spaces (fixes #4054) (Nicholas C. Zakas)
-* Build: Enable CodeClimate (fixes #4068) (Nicholas C. Zakas)
-* Fix: `no-cond-assign` had needed double parens in `for` (fixes #4023) (Toru Nagashima)
-* Update: Ignore end of function in newline-after-var (fixes #3682) (alberto)
-* Build: Performance perf to not ignore jshint file (refs #3765) (Gyandeep Singh)
-* Fix: id-match bug incorrectly errors on `NewExpression` (fixes #4042) (Burak Yigit Kaya)
-* Fix: `no-trailing-spaces` autofix to handle linebreaks (fixes #4050) (Gyandeep Singh)
-* Fix: renamed no-magic-number to no-magic-numbers (fixes #4053) (Vincent Lemeunier)
-* New: add "consistent" option to the "curly" rule (fixes #2390) (Benoît Zugmeyer)
-* Update: Option to ignore for loops in init-declarations (fixes #3641) (alberto)
-* Update: Add webextensions environment (fixes #4051) (Blake Winton)
-* Fix: no-cond-assign should report assignment location (fixes #4040) (alberto)
-* New: no-empty-pattern rule (fixes #3668) (alberto)
-* Upgrade: Upgrade globals to 8.11.0 (fixes #3599) (Burak Yigit Kaya)
-* Docs: Re-tag JSX code fences (fixes #4020) (Brandon Mills)
-* New: no-magic-number rule (fixes #4027) (Vincent Lemeunier)
-* Docs: Remove list of users from README (fixes #3881) (Brandon Mills)
-* Fix: `no-redeclare` and `no-sahadow` for builtin globals (fixes #3971) (Toru Nagashima)
-* Build: Add `.eslintignore` file for the project (fixes #3765) (Gyandeep Singh)
-
-v1.6.0 - October 2, 2015
-
-* Fix: cache is basically not working (fixes #4008) (Richard Hansen)
-* Fix: a test failure on Windows (fixes #3968) (Toru Nagashima)
-* Fix: `no-invalid-this` had been missing globals in node (fixes #3961) (Toru Nagashima)
-* Fix: `curly` with `multi` had false positive (fixes #3856) (Toru Nagashima)
-* Build: Add load performance check inside perf function (fixes #3994) (Gyandeep Singh)
-* Fix: space-before-keywords fails with super keyword (fixes #3946) (alberto)
-* Fix: CLI should not fail on account of ignored files (fixes #3978) (Dominic Barnes)
-* Fix: brace-style rule incorrectly flagging switch (fixes #4002) (Aparajita Fishman)
-* Update: Implement auto fix for space-unary-ops rule (fixes #3976) (alberto)
-* Update: Implement auto fix for computed-property-spacing (fixes #3975) (alberto)
-* Update: Implement auto fix for no-multi-spaces rule (fixes #3979) (alberto)
-* Fix: Report shorthand method names in complexity rule (fixes #3955) (Tijn Kersjes)
-* Docs: Add note about typeof check for isNaN (fixes #3985) (Daniel Lo Nigro)
-* Update: ESLint reports parsing errors with clear prefix. (fixes #3555) (Kevin Partington)
-* Build: Update markdownlint dependency (fixes #3954) (David Anson)
-* Update: `no-mixed-require` to have non boolean option (fixes #3922) (Gyandeep Singh)
-* Fix: trailing spaces auto fix to check for line breaks (fixes #3940) (Gyandeep Singh)
-* Update: Add `typeof` option to `no-undef` rule (fixes #3684) (Gyandeep Singh)
-* Docs: Fix explanation and typos for accessor-pairs (alberto)
-* Docs: Fix typos for camelcase (alberto)
-* Docs: Fix typos for max-statements (Danny Guo)
-* Update: Implement auto fix for object-curly-spacing (fixes #3857) (alberto)
-* Update: Implement auto fix for array-bracket-spacing rule (fixes #3858) (alberto)
-* Fix: Add schema to `global-require` rule (fixes #3923) (Gyandeep Singh)
-* Update: Apply lazy loading for rules (fixes #3930) (Gyandeep Singh)
-* Docs: Fix typo for arrow-spacing (Danny Guo)
-* Docs: Fix typos for wrap-regex (Danny Guo)
-* Docs: Fix explanation for space-before-keywords (Danny Guo)
-* Docs: Fix typos for operator-linebreak (Danny Guo)
-* Docs: Fix typos for callback-return (Danny Guo)
-* Fix: no-trailing-spaces autofix to account for blank lines (fixes #3912) (Gyandeep Singh)
-* Docs: Fix example in no-negated-condition.md (fixes #3908) (alberto)
-* Update:warn message use @return when prefer.returns=return (fixes #3889) (闲耘™)
-* Update: Implement auto fix for generator-star-spacing rule (fixes #3873) (alberto)
-* Update: Implement auto fix for arrow-spacing rule (fixes #3860) (alberto)
-* Update: Implement auto fix for block-spacing rule (fixes #3859) (alberto)
-* Fix: Support allman style for switch statement (fixes #3903) (Gyandeep Singh)
-* New: no-negated-condition rule (fixes #3740) (alberto)
-* Docs: Fix typo in blog post template (Nicholas C. Zakas)
-* Update: Add env 'nashorn' to support Java 8 Nashorn Engine (fixes #3874) (Benjamin Winterberg)
-* Docs: Prepare for rule doc linting (refs #2271) (Ian VanSchooten)
-
-v1.5.1 - September 22, 2015
-
-* Fix: valid-jsdoc fix for param with properties (fixes #3476) (Gyandeep Singh)
-* Fix: valid-jsdoc error with square braces (fixes #2270) (Gyandeep Singh)
-* Upgrade: `doctrine` to 0.7.0 (fixes #3891) (Gyandeep Singh)
-* Fix: `space-before-keywords` had been wrong on getters (fixes #3854) (Toru Nagashima)
-* Fix: `no-dupe-args` had been wrong for nested destructure (fixes #3867) (Toru Nagashima)
-* Docs: io.js is the new Node.js (thefourtheye)
-* Docs: Fix method signature on working-with-rules docs (fixes #3862) (alberto)
-* Docs: Add related ternary links (refs #3835) (Ian VanSchooten)
-* Fix: don’t ignore config if cwd is the home dir (fixes #3846) (Mathias Schreck)
-* Fix: `func-style` had been warning arrows with `this` (fixes #3819) (Toru Nagashima)
-* Fix: `space-before-keywords`; allow opening curly braces (fixes #3789) (Marko Raatikka)
-* Build: Fix broken .gitattributes generation (fixes #3566) (Nicholas C. Zakas)
-* Build: Fix formatter docs generation (fixes #3847) (Nicholas C. Zakas)
-
-v1.5.0 - September 18, 2015
-
-* Fix: invalidate cache when config changes. (fixes #3770) (royriojas)
-* Fix: function body indent issues (fixes #3614, fixes #3799) (Gyandeep Singh)
-* Update: Add configuration option to `space-before-blocks` (fixes #3758) (Phil Vargas)
-* Fix: space checking between tokens (fixes #2211) (Nicholas C. Zakas)
-* Fix: env-specified ecmaFeatures had been wrong (fixes #3735) (Toru Nagashima)
-* Docs: Change example wording from warnings to problems (fixes #3676) (Ian VanSchooten)
-* Build: Generate formatter example docs (fixes #3560) (Ian VanSchooten)
-* New: Add --debug flag to CLI (fixes #2692) (Nicholas C. Zakas)
-* Docs: Update no-undef-init docs (fixes #3170) (Nicholas C. Zakas)
-* Docs: Update no-unused-expressions docs (fixes #3685) (Nicholas C. Zakas)
-* Docs: Clarify node types in no-multi-spaces (fixes #3781) (Nicholas C. Zakas)
-* Docs: Update new-cap docs (fixes #3798) (Nicholas C. Zakas)
-* Fix: `space-before-blocks` had conflicted `arrow-spacing` (fixes #3769) (Toru Nagashima)
-* Fix: `comma-dangle` had not been checking imports/exports (fixes #3794) (Toru Nagashima)
-* Fix: tests fail due to differences in temporary paths. (fixes #3778) (royriojas)
-* Fix: Directory ignoring should work (fixes #3812) (Nicholas C. Zakas)
-* Fix: Ensure **/node_modules works in ignore files (fixes #3788) (Nicholas C. Zakas)
-* Update: Implement auto fix for `space-infix-ops` rule (fixes #3801) (Gyandeep Singh)
-* Fix: `no-warning-comments` can't be set via config comment (fixes #3619) (Burak Yigit Kaya)
-* Update: `key-spacing` should allow 1+ around colon (fixes #3363) (Burak Yigit Kaya)
-* Fix: false alarm of semi-spacing with semi set to never (fixes #1983) (Chen Yicai)
-* Fix: Ensure ./ works correctly with CLI (fixes #3792) (Nicholas C. Zakas)
-* Docs: add more examples + tests for block-scoped-var (fixes #3791) (JT)
-* Update: Implement auto fix for `indent` rule (fixes #3734) (Gyandeep Singh)
-* Fix: `space-before-keywords` fails to handle some cases (fixes #3756) (Marko Raatikka)
-* Docs: Add if-else example (fixes #3722) (Ian VanSchooten)
-* Fix: jsx-quotes exception for attributes without value (fixes #3793) (Mathias Schreck)
-* Docs: Fix closing code fence on cli docs (Ian VanSchooten)
-* Update: Implement auto fix for `space-before-blocks` rule (fixes #3776) (Gyandeep Singh)
-* Update: Implement auto fix for `space-after-keywords` rule (fixes #3773) (Gyandeep Singh)
-* Fix: `semi-spacing` had conflicted with `block-spacing` (fixes #3721) (Toru Nagashima)
-* Update: Implement auto fix for `space-before-keywords` rule (fixes #3771) (Gyandeep Singh)
-* Update: auto fix for space-before-function-paren rule (fixes #3766) (alberto)
-* Update: Implement auto fix for `no-extra-semi` rule (fixes #3745) (Gyandeep Singh)
-* Update: Refactors the traversing logic (refs #3530) (Toru Nagashima)
-* Update: Implement auto fix for `space-return-throw-case` (fixes #3732) (Gyandeep Singh)
-* Update: Implement auto fix for `no-spaced-func` rule (fixes #3728) (Gyandeep Singh)
-* Update: Implement auto fix for `eol-last` rule (fixes #3725) (Gyandeep Singh)
-* Update: Implement auto fix for `no-trailing-spaces` rule (fixes #3723) (Gyandeep Singh)
-
-v1.4.3 - September 15, 2015
-
-* Fix: Directory ignoring should work (fixes #3812) (Nicholas C. Zakas)
-* Fix: jsx-quotes exception for attributes without value (fixes #3793) (Mathias Schreck)
-
-v1.4.2 - September 15, 2015
-
-* Fix: Ensure **/node_modules works in ignore files (fixes #3788) (Nicholas C. Zakas)
-* Fix: Ensure ./ works correctly with CLI (fixes #3792) (Nicholas C. Zakas)
-
-v1.4.1 - September 11, 2015
-
-* Fix: CLIEngine default cache parameter name (fixes #3755) (Daniel G. Taylor)
-* Fix: Glob pattern from .eslintignore not applied (fixes #3750) (Burak Yigit Kaya)
-* Fix: Skip JSDoc from NewExpression (fixes #3744) (Nicholas C. Zakas)
-* Docs: Shorten and simplify autocomment for new issues (Nicholas C. Zakas)
-
-v1.4.0 - September 11, 2015
-
-* Docs: Add new formatters to API docs (Ian VanSchooten)
-* New: Implement autofixing (fixes #3134) (Nicholas C. Zakas)
-* Fix: Remove temporary `"allow-null"` (fixes #3705) (Toru Nagashima)
-* Fix: `no-unused-vars` had been crashed at `/*global $foo*/` (fixes #3714) (Toru Nagashima)
-* Build: check-commit now checks commit message length. (fixes #3706) (Kevin Partington)
-* Fix: make getScope acquire innermost scope (fixes #3700) (voideanvalue)
-* Docs: Fix spelling mistake (domharrington)
-* Fix: Allow whitespace in rule message parameters. (fixes #3690) (Kevin Partington)
-* Fix: Eqeqeq rule with no option does not warn on 'a == null' (fixes #3699) (fediev)
-* Fix: `no-unused-expressions` with `allowShortCircuit` false positive if left has no effect (fixes #3675) (Toru Nagashima)
-* Update: Add Node 4 to travis builds (fixes #3697) (Ian VanSchooten)
-* Fix: Not check for punctuator if on same line as last var (fixes #3694) (Gyandeep Singh)
-* Docs: Make `quotes` docs clearer (fixes #3646) (Nicholas C. Zakas)
-* Build: Increase mocha timeout (fixes #3692) (Nicholas C. Zakas)
-* Fix: `no-extra-bind` to flag all arrow funcs (fixes #3672) (Nicholas C. Zakas)
-* Docs: Update README with release and sponsor info (Nicholas C. Zakas)
-* Fix: `object-curly-spacing` had been crashing on an empty object pattern (fixes #3658) (Toru Nagashima)
-* Fix: `no-extra-parens` false positive at IIFE with member accessing (fixes #3653) (Toru Nagashima)
-* Fix: `comma-dangle` with `"always"`/`"always-multiline"` false positive after a rest element (fixes #3627) (Toru Nagashima)
-* New: `jsx-quotes` rule (fixes #2011) (Mathias Schreck)
-* Docs: Add linting for second half of rule docs (refs #2271) (Ian VanSchooten)
-* Fix: `no-unused-vars` had not shown correct locations for `/*global` (fixes #3617) (Toru Nagashima)
-* Fix: `space-after-keywords` not working for `catch` (fixes #3654) (Burak Yigit Kaya)
-* Fix: Incorrectly warning about ignored files (fixes #3649) (Burak Yigit Kaya)
-* Fix: Indent rule VariableDeclarator doesn't apply to arrow functions (fixes #3661) (Burak Yigit Kaya)
-* Upgrade: Consuming handlebars@^4.0.0 (fixes #3632) (Kevin Partington)
-* Docs: Fixing typos in plugin processor section. (fixes #3648) (Kevin Partington)
-* Fix: Invalid env keys would cause an unhandled exception.(fixes #3265) (Ray Booysen)
-* Docs: Fixing broken link in documentation (Ilya Volodin)
-* Update: Check for default assignment in no-unneeded-ternary (fixes #3232) (cjihrig)
-* Fix: `consistent-as-needed` mode with `keyword: true` (fixes #3636) (Alex Guerrero)
-* New: Implement cache in order to only operate on changed files since previous run. (fixes #2998) (Roy Riojas)
-* Update: Grouping related CLI options. (fixes #3612) (Kevin Partington)
-* Update: Using @override does not require @param or @returns (fixes #3629) (Whitney Young)
-* Docs: Use eslint-env in no-undef (fixes #3616) (Ian VanSchooten)
-* New: `require-jsdoc` rule (fixes #1842) (Gyandeep Singh)
-* New: Support glob path on command line (fixes #3402) (Burak Yigit Kaya)
-* Update: Short circuit and ternary support in no-unused-expressions (fixes #2733) (David Warkentin)
-* Docs: Replace to npmjs.com (Ryuichi Okumura)
-* Fix: `indent` should only indent chain calls if the first call is single line (fixes #3591) (Burak Yigit Kaya)
-* Fix: `quote-props` should not crash for object rest spread syntax (fixes #3595) (Joakim Carlstein)
-* Update: Use `globals` module for the `commonjs` globals (fixes #3606) (Sindre Sorhus)
-* New: `no-restricted-syntax` rule to forbid certain syntax (fixes #2422) (Burak Yigit Kaya)
-* Fix: `no-useless-concat` false positive at numbers (fixes #3575, fixes #3589) (Toru Nagashima)
-* New: Add --max-warnings flag to CLI (fixes #2769) (Kevin Partington)
-* New: Add `parser` as an option (fixes #3127) (Gyandeep Singh)
-* New: `space-before-keywords` rule (fixes #1631) (Marko Raatikka)
-* Update: Allowing inline comments to disable eslint rules (fixes #3472) (Whitney Young)
-* Docs: Including for(;;) as valid case in no-constant-condition (Kevin Partington)
-* Update: Add quotes around the label in `no-redeclare` error messages (fixes #3583) (Ian VanSchooten)
-* Docs: correct contributing URL (Dieter Luypaert)
-* Fix: line number for duplicate object keys error (fixes #3573) (Elliot Lynde)
-* New: global-require rule (fixes #2318) (Jamund Ferguson)
-
-v1.3.1 - August 29, 2015
-
-* Fix: `indent` to not crash on empty files (fixes #3570) (Gyandeep Singh)
-* Fix: Remove unused config file (fixes #2227) (Gyandeep Singh)
-
-v1.3.0 - August 28, 2015
-
-* Build: Autogenerate release blog post (fixes #3562) (Nicholas C. Zakas)
-* New: `no-useless-concat` rule (fixes #3506) (Henry Zhu)
-* Update: Add `keywords` flag to `consistent-as-needed` mode in `quote-props` (fixes #3532) (Burak Yigit Kaya)
-* Update: adds `numbers` option to quote-props (fixes #2914) (Jose Roberto Vidal)
-* Fix: `quote-props` rule should ignore computed and shorthand properties (fixes #3557) (fixes #3544) (Burak Yigit Kaya)
-* Docs: Add config comments for rule examples 'accessor-pairs' to 'no-extra-semi' (refs #2271) (Ian VanSchooten)
-* Update: Return to accept `undefined` type (fixes #3382) (Gyandeep Singh)
-* New: Added HTML formatter (fixes #3505) (Julian Laval)
-* Fix: check space after yield keyword in space-unary-ops (fixes #2707) (Mathias Schreck)
-* Docs: (curly) Fix broken code in example (Kent C. Dodds)
-* Update: Quote var name in `no-unused-vars` error messages (refs #3526) (Burak Yigit Kaya)
-* Update: Move methods to SourceCode (fixes #3516) (Nicholas C. Zakas)
-* Fix: Don't try too hard to find fault in `no-implicit-coercion` (refs #3402) (Burak Yigit Kaya)
-* Fix: Detect ternary operator in operator-linebreak rule (fixes #3274) (Burak Yigit Kaya)
-* Docs: Clearer plugin rule configuration (fixes #2022) (Nicholas C. Zakas)
-* Update: Add quotes around the label in `no-empty-label` error reports (fixes #3526) (Burak Yigit Kaya)
-* Docs: Turn off Liquid in example (Nicholas C. Zakas)
-* Docs: Mention CommonJS along with Node.js (fixes #3388) (Nicholas C. Zakas)
-* Docs: Make it clear which rules are recommended (fixes #3398) (Nicholas C. Zakas)
-* Docs: Add links to JSON Schema resources (fixes #3411) (Nicholas C. Zakas)
-* Docs: Add more info to migration guide (fixes #3439) (Nicholas C. Zakas)
-* Fix: ASI indentation issue (fixes #3514) (Burak Yigit Kaya)
-* Fix: Make `no-implicit-coercion` smarter about numerical expressions (fixes #3510) (Burak Yigit Kaya)
-* Fix: `prefer-template` had not been handling TemplateLiteral as literal node (fixes #3507) (Toru Nagashima)
-* Update: `newline-after-var` Allow comment + blank after var (fixes #2852) (Ian VanSchooten)
-* Update: Add `unnecessary` option to `quote-props` (fixes #3381) (Burak Yigit Kaya)
-* Fix: `indent` shouldn't check the last line unless it is a punctuator (fixes #3498) (Burak Yigit Kaya)
-* Fix: `indent` rule does not indent when doing multi-line chain calls (fixes #3279) (Burak Yigit Kaya)
-* Fix: sort-vars rule fails when memo is undefined (fixes #3474) (Burak Yigit Kaya)
-* Fix: `brace-style` doesn't report some closing brace errors (fixes #3486) (Burak Yigit Kaya)
-* Update: separate options for block and line comments in `spaced-comment` rule (fixes #2897) (Burak Yigit Kaya)
-* Fix: `indent` does not check FunctionDeclaration nodes properly (fixes #3173) (Burak Yigit Kaya)
-* Update: Added "properties" option to `id-length` rule to ignore property names. (fixes #3450) (Mathieu M-Gosselin)
-* Update: add new ignore pattern options to no-unused-vars (fixes #2321) (Mathias Schreck)
-* New: Protractor environment (fixes #3457) (James Whitney)
-* Docs: Added section to shareable config (Gregory Waxman)
-* Update: Allow pre-parsed code (fixes #1025, fixes #948) (Nicholas C. Zakas)
-
-v1.2.1 - August 20, 2015
-
-* Fix: "key-spacing" crashes eslint on object literal shorthand properties (fixes #3463) (Burak Yigit Kaya)
-* Fix: ignore leading space check for `null` elements in comma-spacing (fixes #3392) (Mathias Schreck)
-* Fix: `prefer-arrow-callback` false positive at recursive functions (fixes #3454) (Toru Nagashima)
-* Fix: one-var rule doesn’t have default options (fixes #3449) (Burak Yigit Kaya)
-* Fix: Refactor `no-duplicate-case` to be simpler and more efficient (fixes #3440) (Burak Yigit Kaya)
-* Docs: Fix trailing spaces in README (Nicholas C. Zakas)
-* Docs: Update gyandeeps and add byk (Nicholas C. Zakas)
-* Docs: Update plugins documentation for 1.0.0 (Nicholas C. Zakas)
-* Docs: `object-curly-spacing` doc is inaccurate about exceptions (Burak Yigit Kaya)
-* Fix: `object-curly-spacing` shows the incorrect column for opening brace (fixes #3438) (Burak Yigit Kaya)
-
-v1.2.0 - August 18, 2015
-
-* Update: add support for semicolon in comma-first setup in indent rule (fixes #3423) (Burak Yigit Kaya)
-* Docs: better JSDoc for indent rule (Burak Yigit Kaya)
-* Docs: Document the second argument of `CLIEngine.executeOnText()` (Sindre Sorhus)
-* New: `no-dupe-class-members` rule (fixes #3294) (Toru Nagashima)
-* Fix: exclude `AssignmentExpression` and `Property` nodes from extra indentation on first line (fixes #3391) (Burak Yigit Kaya)
-* Update: Separate indent options for var, let and const (fixes #3339) (Burak Yigit Kaya)
-* Fix: Add AssignmentPattern to space-infix-ops (fixes #3380) (Burak Yigit Kaya)
-* Docs: Fix typo: exception label (tienslebien)
-* Update: Clean up tests for CLI config support (refs #2543) (Gyandeep Singh)
-* New: `block-spacing` rule (fixes #3303) (Toru Nagashima)
-* Docs: Update docs for no-iterator (fixes #3405) (Nicholas C. Zakas)
-* Upgrade: bump `espree` dependency to `2.2.4` (fixes #3403) (Burak Yigit Kaya)
-* Fix: false positive on switch 'no duplicate case', (fixes #3408) (Cristian Carlesso)
-* Fix: `valid-jsdoc` test does not recognize aliases for `@param` (fixes #3399) (Burak Yigit Kaya)
-* New: enable `-c` flag to accept a shareable config (fixes #2543) (Shinnosuke Watanabe)
-* Fix: Apply plugin given in CLI (fixes #3383) (Ian VanSchooten)
-* New: Add commonjs environment (fixes #3377) (Nicholas C. Zakas)
-* Docs: Update no-unused-var docs (Nicholas C. Zakas)
-* Fix: trailing commas in object-curly-spacing for import/export (fixes #3324) (Henry Zhu)
-* Update: Make `baseConfig` to behave as other config options (fixes #3371) (Gyandeep Singh)
-* Docs: Add "Compatibility" section to linebreak-style (Vitor Balocco)
-* New: `prefer-arrow-callback` rule (fixes #3140) (Toru Nagashima)
-* Docs: Clarify what an unused var is (fixes #2342) (Nicholas C. Zakas)
-* Docs: Mention double-byte character limitation in max-len (fixes #2370) (Nicholas C. Zakas)
-* Fix: object curly spacing incorrectly warning for import with default and multiple named specifiers (fixes #3370) (Luke Karrys)
-* Fix: Indent rule errors with array of objects (fixes #3329) (Burak Yigit Kaya)
-* Update: Make it clear that `space-infix-ops` support `const` (fixes #3299) (Burak Yigit Kaya)
-* New: `prefer-template` rule (fixes #3014) (Toru Nagashima)
-* Docs: Clarify `no-process-env` docs (fixes #3318) (Nicholas C. Zakas)
-* Docs: Fix arrow name typo (fixes #3309) (Nicholas C. Zakas)
-* Update: Improve error message for `indent` rule violation (fixes #3340) (Burak Yigit Kaya)
-* Fix: radix rule does not apply for Number.parseInt (ES6) (fixes #3364) (Burak Yigit Kaya)
-* Fix: `key-spacing.align` doesn't pay attention to non-whitespace before key (fixes #3267) (Burak Yigit Kaya)
-* Fix: arrow-parens & destructuring/default params (fixes #3353) (Jamund Ferguson)
-* Update: Add support for Allman to brace-style rule, brackets on newline (fixes #3347) (Burak Yigit Kaya)
-* Fix: Regression no-catch-shadow (1.1.0) (fixes #3322) (Burak Yigit Kaya)
-* Docs: remove note outdated in 1.0.0 (Denis Sokolov)
-* Build: automatically convert line endings in release script (fixes #2642) (Burak Yigit Kaya)
-* Update: allow disabling new-cap on object methods (fixes #3172) (Burak Yigit Kaya)
-* Update: Improve checkstyle format (fixes #3183) (Burak Yigit Kaya)
-* Fix: Indent rule errors if an array literal starts a new statement (fixes #3328) (Burak Yigit Kaya)
-* Update: Improve validation error messages (fixes #3193) (Burak Yigit Kaya)
-* Docs: fix syntax error in space-before-function-paren (Fabrício Matté)
-* Fix: `indent` rule to check for last line correctly (fixes #3327) (Gyandeep Singh)
-* Fix: Inconsistent off-by-one errors with column numbers (fixes #3231) (Burak Yigit Kaya)
-* Fix: Keyword "else" must not be followed by a newline (fixes #3226) (Burak Yigit Kaya)
-* Fix: `id-length` does not work for most of the new ES6 patterns (fixes #3286) (Burak Yigit Kaya)
-* Fix: Spaced Comment Exceptions Not Working (fixes #3276) (Jamund Ferguson)
-
-v1.1.0 - August 7, 2015
-
-* Update: Added as-needed option to arrow-parens (fixes #3277) (Jamund Ferguson)
-* Fix: curly-spacing missing import case (fixes #3302) (Jamund Ferguson)
-* Fix: `eslint-env` in comments had not been setting `ecmaFeatures` (fixes #2134) (Toru Nagashima)
-* Fix: `es6` env had been missing `spread` and `newTarget` (fixes #3281) (Toru Nagashima)
-* Fix: Report no-spaced-func on last token before paren (fixes #3289) (Benjamin Woodruff)
-* Fix: Check for null elements in indent rule (fixes #3272) (Gyandeep Singh)
-* Docs: Use backticks for option heading (Gyandeep Singh)
-* Fix: `no-invalid-this` had been missing jsdoc comment (fixes #3287) (Toru Nagashima)
-* Fix: `indent` rule for multi-line objects and arrays (fixes #3236) (Gyandeep Singh)
-* Update: add new `multi-or-nest` option for the `curly` rule (fixes #1806) (Ivan Nikulin)
-* Fix: `no-cond-assign` had been missing simplest pattern (fixes #3249) (Toru Nagashima)
-* Fix: id-length rule doesn't catch violations in arrow function parameters (fixes #3275) (Burak Yigit Kaya)
-* New: Added grep-style formatter (fixes #2991) (Nobody Really)
-* Update: Split out generic AST methods into utility (fixes #962) (Gyandeep Singh)
-* Fix: `accessor-pairs` false positive (fixes #3262) (Toru Nagashima)
-* Fix: `context.getScope()` returns correct scope in blockBindings (fixes #3254) (Toru Nagashima)
-* Update: Expose `getErrorResults` as a static method on `CLIEngine` (fixes #3242) (Gyandeep Singh)
-* Update: Expose `getFormatter` as a static method on `CLIEngine` (fixes #3239) (Gyandeep Singh)
-* Docs: use correct encoding for id-match.md (fixes #3246) (Matthieu Larcher)
-* Docs: place id-match rule at correct place in README.md (fixes #3245) (Matthieu Larcher)
-* Docs: Update no-proto.md (Joe Zimmerman)
-* Docs: Fix typo in object-shorthand docs (Gunnar Lium)
-* Upgrade: inquirer dependency (fixes #3241) (Gyandeep Singh)
-* Fix: `indent` rule for objects and nested one line blocks (fixes #3238, fixes #3237) (Gyandeep Singh)
-* Docs: Fix wrong options in examples of key-spacing (keik)
-* Docs: Adds missing "not" to semi.md (Marius Schulz)
-* Docs: Update no-multi-spaces.md (Kenneth Powers)
-* Fix: `indent` to not error on same line nodes (fixes #3228) (Gyandeep Singh)
-* New: Jest environment (fixes #3212) (Darshak Parikh)
-
-v1.0.0 - July 31, 2015
-
-* Update: merge `no-reserved-keys` into `quote-props` (fixes #1539) (Jose Roberto Vidal)
-* Fix: `indent` error message (fixes #3220) (Gyandeep Singh)
-* Update: Add embertest env (fixes #3205) (ismay)
-* Docs: Correct documentation errors for `id-length` rule. (Jess Telford)
-* Breaking: `indent` rule to have node specific options (fixes #3210) (Gyandeep Singh)
-* Fix: space-after-keyword shouldn't allow newlines (fixes #3198) (Brandon Mills)
-* New: Add JSON formatter (fixes #3036) (Burak Yigit Kaya)
-* Breaking: Switch to RuleTester (fixes #3186) (Nicholas C. Zakas)
-* Breaking: remove duplicate warnings of `no-undef` from `block-scoped-var` (fixes #3201) (Toru Nagashima)
-* Fix: `init-declarations` ignores in for-in/of (fixes #3202) (Toru Nagashima)
-* Fix: `quotes` with `"backtick"` ignores ModuleSpecifier and LiteralPropertyName (fixes #3181) (Toru Nagashima)
-* Fix: space-in-parens in Template Strings (fixes #3182) (Ian VanSchooten)
-* Fix: Check for concatenation in no-throw-literal (fixes #3099, fixes #3101) (Ian VanSchooten)
-* Build: Remove `eslint-tester` from devDependencies (fixes #3189) (Gyandeep Singh)
-* Fix: Use new ESLintTester (fixes #3187) (Nicholas C. Zakas)
-* Update: `new-cap` supports fullnames (fixes #2584) (Toru Nagashima)
-* Fix: Non object rule options merge (fixes #3179) (Gyandeep Singh)
-* New: add id-match rule (fixes #2829) (Matthieu Larcher)
-* Fix: Rule options merge (fixes #3175) (Gyandeep Singh)
-* Fix: `spaced-comment` allows a mix of markers and exceptions (fixes #2895) (Toru Nagashima)
-* Fix: `block-scoped-var` issues (fixes #2253, fixes #2747, fixes #2967) (Toru Nagashima)
-* New: Add id-length rule (fixes #2784) (Burak Yigit Kaya)
-* Update: New parameters for quote-props rule (fixes #1283, fixes #1658) (Tomasz Olędzki)
-
-v1.0.0-rc-3 - July 24, 2015
-
-* Fix: Make Chai and Mocha as a dependency (fixes #3156) (Gyandeep Singh)
-* Fix: traverse `ExperimentalSpread/RestProperty.argument` (fixes #3157) (Toru Nagashima)
-* Fix: Check shareable config package prefix correctly (fixes #3146) (Gyandeep Singh)
-* Update: move redeclaration checking for builtins (fixes #3070) (Toru Nagashima)
-* Fix: `quotes` with `"backtick"` allows directive prologues (fixes #3132) (Toru Nagashima)
-* Fix: `ESLintTester` path in exposed API (fixes #3149) (Gyandeep Singh)
-* Docs: Remove AppVeyor badge (Gyandeep Singh)
-* Fix: Check no-new-func on CallExpressions (fixes #3145) (Benjamin Woodruff)
-
-v1.0.0-rc-2 - July 23, 2015
-
-* Docs: Mention eslint-tester in migration guide (Nicholas C. Zakas)
-* Docs: Mention variables defined in a global comment (fixes #3137) (William Becker)
-* Docs: add documentation about custom-formatters. (fixes #1260) (royriojas)
-* Fix: Multi-line variable declarations indent (fixes #3139) (Gyandeep Singh)
-* Fix: handles blocks in no-use-before-define (fixes #2960) (Jose Roberto Vidal)
-* Update: `props` option of `no-param-reassign` (fixes #1600) (Toru Nagashima)
-* New: Support shared configs named `@scope/eslint-config`, with shortcuts of `@scope` and `@scope/` (fixes #3123) (Jordan Harband)
-* New: Add ignorePattern, ignoreComments, and ignoreUrls options to max-len (fixes #2934, fixes #2221, fixes #1661) (Benjamin Woodruff)
-* Build: Increase Windows Mocha timeout (fixes #3133) (Ian VanSchooten)
-* Docs: incorrect syntax in the example for rule «one-var» (Alexander Burtsev)
-* Build: Check commit message format at end of tests (fixes #3058) (Ian VanSchooten)
-* Update: Move eslint-tester into repo (fixes #3110) (Nicholas C. Zakas)
-* Fix: Not load configs outside config with `root: true` (fixes #3109) (Gyandeep Singh)
-* Docs: Add config information to README (fixes #3074) (Nicholas C. Zakas)
-* Docs: Add mysticatea as committer (Nicholas C. Zakas)
-* Docs: Grammar fixes in rule descriptions (refs #3038) (Greg Cochard)
-* Fix: Update sort-vars to ignore Array and ObjectPattern (fixes #2954) (Harry Ho)
-* Fix: block-scoped-var rule incorrectly flagging break/continue with label (fixes #3082) (Aparajita Fishman)
-* Fix: spaces trigger wrong in `no-useless-call` and `prefer-spread` (fixes #3054) (Toru Nagashima)
-* Fix: `arrow-spacing` allow multi-spaces and line-endings (fixes #3079) (Toru Nagashima)
-* Fix: add missing loop scopes to one-var (fixes #3073) (Jose Roberto Vidal)
-* New: the `no-invalid-this` rule (fixes #2815) (Toru Nagashima)
-* Fix: allow empty loop body in no-extra-semi (fixes #3075) (Mathias Schreck)
-* Update: Add qunit to environments (fixes #2870) (Nicholas C. Zakas)
-* Fix: `space-before-blocks` to consider classes (fixes #3062) (Gyandeep Singh)
-* Fix: Include phantomjs globals (fixes #3064) (Linus Unnebäck)
-* Fix: no-else-return handles multiple else-if blocks (fixes #3015) (Jose Roberto Vidal)
-* Fix: `no-*-assgin` rules support destructuring (fixes #3029) (Toru Nagashima)
-* New: the `no-implicit-coercion` rule (fixes #1621) (Toru Nagashima)
-* Fix: Make no-implied-eval match more types of strings (fixes #2898) (Benjamin Woodruff)
-* Docs: Clarify that bot message is automatic (Ian VanSchooten)
-* Fix: Skip rest properties in no-dupe-keys (fixes 3042) (Nicholas C. Zakas)
-* Docs: New issue template (fixes #3048) (Nicholas C. Zakas)
-* Fix: strict rule supports classes (fixes #2977) (Toru Nagashima)
-* New: the `prefer-reflect` rule (fixes #2939) (Keith Cirkel)
-* Docs: make grammar consistent in rules index (Greg Cochard)
-* Docs: Fix unmatched paren in rule description (Greg Cochard)
-* Docs: Small typo fix in no-useless-call documentation (Paul O’Shannessy)
-* Build: readd phantomjs dependency with locked down version (fixes #3026) (Mathias Schreck)
-* Docs: Add IanVS as committer (Nicholas C. Zakas)
-* docs: additional computed-property-spacing documentation (fixes #2941) (Jamund Ferguson)
-* Docs: Add let and const examples for newline-after-var (fixes #3020) (James Whitney)
-* Build: Remove unnecessary phantomjs devDependency (fixes #3021) (Gyandeep Singh)
-* Update: added shared builtins list (fixes #2972) (Jose Roberto Vidal)
-
-v1.0.0-rc-1 - July 15, 2015
-
-* Upgrade: Espree to 2.2.0 (fixes #3011) (Nicholas C. Zakas)
-* Docs: fix a typo (bartmichu)
-* Fix: indent rule should recognize single line statements with ASI (fixes #3001, fixes #3000) (Mathias Schreck)
-* Update: Handle CRLF line endings in spaced-comment rule - 2 (fixes #3005) (Burak Yigit Kaya)
-* Fix: Indent rule error on empty block body (fixes #2999) (Gyandeep Singh)
-* New: the `no-class-assign` rule (fixes #2718) (Toru Nagashima)
-* New: the `no-const-assign` rule (fixes #2719) (Toru Nagashima)
-* Docs: Add 1.0.0 migration guide (fixes #2994) (Nicholas C. Zakas)
-* Docs: Update changelog for 0.24.1 (fixes #2976) (Nicholas C. Zakas)
-* Breaking: Remove deprecated rules (fixes #1898) (Ian VanSchooten)
-* Fix: multi-line + fat arrow indent (fixes #2239) (Gyandeep Singh)
-* Breaking: Create eslint:recommended and add to --init (fixes #2713) (Greg Cochard)
-* Fix: Indent rule (fixes #1797, fixes #1799, fixes #2248, fixes #2343, fixes #2278, fixes #1800) (Gyandeep Singh)
-* New: `context.getDeclaredVariables(node)` (fixes #2801) (Toru Nagashima)
-* New: the `no-useless-call` rule (fixes #1925) (Toru Nagashima)
-* New: the `prefer-spread` rule (fixes #2946) (Toru Nagashima)
-* Fix: `valid-jsdoc` counts `return` for arrow expressions (fixes #2952) (Toru Nagashima)
-* New: Add exported comment option (fixes #1200) (Jamund Ferguson)
-* Breaking: Default to --reset behavior (fixes #2100) (Brandon Mills)
-* New: Add arrow-parens and arrow-spacing rule (fixes #2628) (Jxck)
-* Fix: Shallow cloning issues in eslint config (fixes #2961) (Gyandeep Singh)
-* Add: Warn on missing rule definition or deprecation (fixes #1549) (Ian VanSchooten)
-* Update: adding some tests for no-redeclare to test named functions (fixes #2953) (Dominic Barnes)
-* New: Add support for root: true in config files (fixes #2736) (Ian VanSchooten)
-* Fix: workaround for leading and trailing comments in padded-block (fixes #2336 and fixes #2788) (Mathias Schreck)
-* Fix: object-shorthand computed props (fixes #2937) (Jamund Ferguson)
-* Fix: Remove invalid check inside `getJSDocComment` function (fixes #2938) (Gyandeep Singh)
-* Docs: Clarify when not to use space-before-blocks (Ian VanSchooten)
-* Update: `no-loop-func` allows block-scoped variables (fixes #2517) (Toru Nagashima)
-* Docs: remove mistaken "off by default" (Jan Schär)
-* Build: Add appveyor CI system (fixes #2923) (Gyandeep Singh)
-* Docs: Fix typo in the shareable configs doc (Siddharth Kannan)
-* Fix: max-len to report correct column number (fixes #2926) (Mathias Schreck)
-* Fix: add destructuring support to comma-dangle rule (fixes #2911) (Mathias Schreck)
-* Docs: clarification in no-unused-vars (Jan Schär)
-* Fix: `no-redeclare` checks module scopes (fixes #2903) (Toru Nagashima)
-* Docs: missing quotes in JSON (Jan Schär)
-* Breaking: Switch to 1-based columns (fixes #2284) (Nicholas C. Zakas)
-* Docs: array-bracket-spacing examples used space-in-brackets (Brandon Mills)
-* Docs: Add spaced-line-comment deprecation notice (Brandon Mills)
-* Docs: Add space-in-brackets deprecation notice (Brandon Mills)
-* Fix: Include execScript in no-implied-eval rule (fixes #2873) (Frederik Braun)
-* Fix: Support class syntax for line-around-comment rule (fixes #2894) (Gyandeep Singh)
-* Fix: lines-around-comment was crashing in some cases due to a missing check (fixes #2892) (Mathieu M-Gosselin)
-* New: Add init-declarations rule (fixes #2606) (cjihrig)
-* Docs: Fix typo in array-bracket-spacing rule (zallek)
-* Fix: Added missing export syntax support to the block-scoped-var rule. (fixes #2887) (Mathieu M-Gosselin)
-* Build: gensite target supports rule removal (refs #1898) (Brandon Mills)
-* Update: Handle CRLF line endings in spaced-comment rule (fixes #2884) (David Anson)
-* Update: Attach parent in getNodeByRangeIndex (fixes #2863) (Brandon Mills)
-* Docs: Fix typo (Bryan Smith)
-* New: Add serviceworker environment (fixes #2557) (Gyandeep Singh)
-* Fix: Yoda should ignore comparisons where both sides are constants (fixes #2867) (cjihrig)
-* Update: Loosens regex rules around intentional fall through comments (Fixes #2811) (greg5green)
-* Update: Add missing schema to rules (fixes #2858) (Ilya Volodin)
-* New: `require-yield` rule (fixes #2822) (Toru Nagashima)
-* New: add callback-return rule (fixes #994) (Jamund Ferguson)
-
-v0.24.1 - July 10, 2015
-
-* Docs: Clarify when not to use space-before-blocks (Ian VanSchooten)
-* Docs: remove mistaken "off by default" (Jan Schär)
-* Docs: remove mistaken "off by default" (Jan Schär)
-* Docs: Fix typo in the shareable configs doc (Siddharth Kannan)
-* Docs: clarification in no-unused-vars (Jan Schär)
-* Docs: missing quotes in JSON (Jan Schär)
-* Fix: Revert 1-based column changes in tests for patch (refs #2284) (Nicholas C. Zakas)
-* Fix: Shallow cloning issues in eslint config (fixes #2961) (Gyandeep Singh)
-* Fix: object-shorthand computed props (fixes #2937) (Jamund Ferguson)
-* Fix: Remove invalid check inside `getJSDocComment` function (fixes #2938) (Gyandeep Singh)
-* Fix: max-len to report correct column number (fixes #2926) (Mathias Schreck)
-* Fix: add destructuring support to comma-dangle rule (fixes #2911) (Mathias Schreck)
-* Fix: `no-redeclare` checks module scopes (fixes #2903) (Toru Nagashima)
-* Fix: Include execScript in no-implied-eval rule (fixes #2873) (Frederik Braun)
-* Fix: Support class syntax for line-around-comment rule (fixes #2894) (Gyandeep Singh)
-* Fix: lines-around-comment was crashing in some cases due to a missing check (fixes #2892) (Mathieu M-Gosselin)
-* Fix: Added missing export syntax support to the block-scoped-var rule. (fixes #2887) (Mathieu M-Gosselin)
-* Fix: Yoda should ignore comparisons where both sides are constants (fixes #2867) (cjihrig)
-* Docs: array-bracket-spacing examples used space-in-brackets (Brandon Mills)
-* Docs: Add spaced-line-comment deprecation notice (Brandon Mills)
-* Docs: Add space-in-brackets deprecation notice (Brandon Mills)
-
-v0.24.0 - June 26, 2015
-
-* Upgrade: eslint-tester to 0.8.1 (Nicholas C. Zakas)
-* Fix: no-dupe-args sparse array crash (fixes #2848) (Chris Walker)
-* Fix: space-after-keywords should ignore extra parens (fixes #2847) (Mathias Schreck)
-* New: add no-unexpected-multiline rule (fixes #746) (Glen Mailer)
-* Update: refactor handle-callback-err to improve performance (fixes #2841) (Mathias Schreck)
-* Fix: Add --init to the CLI options (fixes #2817) (Gyandeep Singh)
-* Update: Add `except-parens` option to `no-return-assign` rule (fixes #2809) (Toru Nagashima)
-* Fix: handle-callback-err missing arrow functions (fixes #2823) (Jamund Ferguson)
-* Fix: `no-extra-semi` in class bodies (fixes #2794) (Toru Nagashima)
-* Fix: Check type to be file when looking for config files (fixes #2790) (Gyandeep Singh)
-* Fix: valid-jsdoc to work for object getters (fixes #2407) (Gyandeep Singh)
-* Update: Add an option as an object to `generator-star-spacing` rule (fixes #2787) (Toru Nagashima)
-* Build: Update markdownlint dependency (David Anson)
-* Fix: context report message to handle more scenarios (fixes #2746) (Gyandeep Singh)
-* Update: Ignore JsDoc comments by default for `spaced-comment` (fixes #2766) (Gyandeep Singh)
-* Fix: one-var 'never' option for mixed initialization (Fixes #2786) (Ian VanSchooten)
-* Docs: Fix a minor typo in a prefer-const example (jviide)
-* Fix: comma-dangle always-multiline: no comma right before the last brace (fixes #2091) (Benoît Zugmeyer)
-* Fix: Allow blocked comments with markers and new-line (fixes #2777) (Gyandeep Singh)
-* Docs: small fix in quote-props examples (Jose Roberto Vidal)
-* Fix: object-shorthand rule should not warn for NFEs (fixes #2748) (Michael Ficarra)
-* Fix: arraysInObjects for object-curly-spacing (fixes #2752) (Jamund Ferguson)
-* Docs: Clarify --rule description (fixes #2773) (Nicholas C. Zakas)
-* Fix: object literals in arrow function bodies (fixes #2702) (Jose Roberto Vidal)
-* New: `constructor-super` rule (fixes #2720) (Toru Nagashima)
-* New: `no-this-before-super` rule (fixes #2721) (Toru Nagashima)
-* Fix: space-unary-ops flags expressions starting w/ keyword (fixes #2764) (Michael Ficarra)
-* Update: Add block options to `lines-around-comment` rule (fixes #2667) (Gyandeep Singh)
-* New: array-bracket-spacing (fixes #2226) (Jamund Ferguson)
-* Fix: No-shadow rule duplicating error messages (fixes #2706) (Aliaksei Shytkin)
-
-v0.23.0 - June 14, 2015
-
-* Build: Comment out auto publishing of release notes (refs #2640) (Ilya Volodin)
-* Fix: "extends" within package.json (fixes #2754) (Gyandeep Singh)
-* Upgrade: globals@8.0.0 (fixes #2759) (silverwind)
-* Docs: eol-last docs fix (fixes #2755) (Gyandeep Singh)
-* Docs: btmills is a reviewer (Nicholas C. Zakas)
-* Build: Revert lock io.js to v2.1.0 (refs #2745) (Brandon Mills)
-* New: computed-property-spacing (refs #2226) (Jamund Ferguson)
-* Build: Pin Sinon version (fixes #2742) (Ilya Volodin)
-* Fix: `prefer-const` treats `for-in`/`for-of` with the same way (Fixes #2739) (Toru Nagashima)
-* Docs: Add links to team members profile (Gyandeep Singh)
-* Docs: add team and ES7 info to readme (Nicholas C. Zakas)
-* Fix: don't try to strip "line:" prefix from parser errors with no such prefix (fixes #2698) (Tim Cuthbertson)
-* Fix: never ignore config comment options (fixes #2725) (Brandon Mills)
-* Update: Add clarification to spaced-comment (refs #2588) (Greg Cochard)
-* Update: Add markers to spaced-comment (fixes #2588) (Greg Cochard)
-* Fix: no-trailing-spaces now handles skipBlankLines (fixes #2575) (Greg Cochard)
-* Docs: Mark global-strict on by default (fixes #2629) (Ilya Volodin)
-* New: Allow extends to be an array (fixes #2699) (Justin Morris)
-* New: globals@7.1.0 (fixes #2682) (silverwind)
-* New: `prefer-const` rule (fixes #2333) (Toru Nagashima)
-* Fix: remove hard-coded list of unary keywords in space-unary-ops rule (fixes #2696) (Tim Cuthbertson)
-* Breaking: Automatically validate rule options (fixes #2595) (Brandon Mills)
-* Update: no-lone-blocks does not report block-level scopes (fixes #2119) (Jose Roberto Vidal)
-* Update: yoda onlyEquality option (fixes #2638) (Denis Sokolov)
-* Docs: update comment to align with source code it's referencing (Michael Ficarra)
-* Fix: Misconfigured default option for lines-around-comment rule (fixes #2677) (Gyandeep Singh)
-* Fix: `no-shadow` allows shadowing in the TDZ (fixes #2568) (Toru Nagashima)
-* New: spaced-comment rule (fixes #1088) (Gyandeep Singh)
-* Fix: Check unused vars in exported functions (fixes #2678) (Gyandeep Singh)
-* Build: Stringify payload of release notes (fixes #2640) (Greg Cochard)
-* Fix: Allowing u flag in regex to properly lint no-empty-character-class (fixes #2679) (Dominic Barnes)
-* Docs: deprecate no-wrap-func (fixes #2644) (Jose Roberto Vidal)
-* Docs: Fixing grammar: then -> than (E)
-* Fix: trailing commas in object-curly-spacing (fixes #2647) (Jamund Ferguson)
-* Docs: be consistent about deprecation status (Matthew Dapena-Tretter)
-* Docs: Fix mistakes in object-curly-spacing docs (Matthew Dapena-Tretter)
-* New: run processors when calling executeOnText (fixes #2331) (Mordy Tikotzky)
-* Update: move executeOnText() tests to the correct describe block (fixes #2648) (Mordy Tikotzky)
-* Update: add tests to assert that the preprocessor is running (fixes #2651) (Mordy Tikotzky)
-* Build: Lock io.js to v2.1.0 (fixes #2653) (Ilya Volodin)
-
-v0.22.1 - May 30, 2015
-
-* Build: Remove release notes auto-publish (refs #2640) (Ilya Volodin)
-
-v0.22.0 - May 30, 2015
-
-* Upgrade: escope 3.1.0 (fixes #2310, #2405) (Toru Nagashima)
-* Fix: “consistent-this” incorrectly flagging destructuring of `this` (fixes #2633) (David Aurelio)
-* Upgrade: eslint-tester to 0.7.0 (Ilya Volodin)
-* Update: allow shadowed references in no-alert (fixes #1105) (Mathias Schreck)
-* Fix: no-multiple-empty-lines and template strings (fixes #2605) (Jamund Ferguson)
-* New: object-curly-spacing (fixes #2225) (Jamund Ferguson)
-* Docs: minor fix for one-var rule (Jamund Ferguson)
-* Fix: Shared config being clobbered by other config (fixes #2592) (Dominic Barnes)
-* Update: adds "functions" option to no-extra-parens (fixes #2477) (Jose Roberto Vidal)
-* Docs: Fix json formatting for lines-around-comments rule (Gyandeep Singh)
-* Fix: Improve around function/class names of `no-shadow` (fixes #2556, #2552) (Toru Nagashima)
-* Fix: Improve code coverage (fixes #2590) (Ilya Volodin)
-* Fix: Allow scoped configs to have sub-configs (fixes #2594) (Greg Cochard)
-* Build: Add auto-update of release tag on github (fixes #2566) (Greg Cochard)
-* New: lines-around-comment (fixes #1344) (Jamund Ferguson)
-* Build: Unblock build by increasing code coverage (Ilya Volodin)
-* New: accessor-pairs rule to object initializations (fixes #1638) (Gyandeep Singh)
-* Fix: counting of variables statements in one-var (fixes #2570) (Mathias Schreck)
-* Build: Add sudo:false for Travis (fixes #2582) (Ilya Volodin)
-* New: Add rule schemas (refs #2179) (Brandon Mills)
-* Docs: Fix typo in shareable-configs example (fixes #2571) (Ted Piotrowski)
-* Build: Relax markdownlint rules by disabling style-only items (David Anson)
-* Fix: Object shorthand rule incorrectly flagging getters/setters (fixes #2563) (Brad Dougherty)
-* New: Add config validator (refs #2179) (Brandon Mills)
-* New: Add worker environment (fixes #2442) (Ilya Volodin)
-* New no-empty-character class (fixes #2508) (Jamund Ferguson)
-* New: Adds --ignore-pattern option. (fixes #1742) (Patrick McElhaney)
-
-v0.21.2 - May 18, 2015
-
-* 0.21.2 (Nicholas C. Zakas)
-* Fix: one-var exception for ForStatement.init (fixes #2505) (Brandon Mills)
-* Fix: Don't throw spurious shadow errors for classes (fixes #2545) (Jimmy Jia)
-* Fix: valid-jsdoc rule to support exported functions (fixes #2522) (Gyandeep Singh)
-* Fix: Allow scoped packages in configuration extends (fixes #2544) (Eric Isakson)
-* Docs: Add chatroom to FAQ (Nicholas C. Zakas)
-* Docs: Move Gitter badge (Nicholas C. Zakas)
-
-v0.21.1 - May 15, 2015
-
-* 0.21.1 (Nicholas C. Zakas)
-* Fix: loc obj in report fn expects column (fixes #2481) (Varun Verma)
-* Build: Make sure that all md files end with empty line (fixes #2520) (Ilya Volodin)
-* Added Gitter badge (The Gitter Badger)
-* Fix: forced no-shadow to check all scopes (fixes #2294) (Jose Roberto Vidal)
-* Fix: --init indent setting (fixes #2493) (Nicholas C. Zakas)
-* Docs: Mention bundling multiple shareable configs (Nicholas C. Zakas)
-* Fix: Not to override the required extended config object directly (fixes #2487) (Gyandeep Singh)
-* Build: Update markdownlint dependency (David Anson)
-* Docs: added recursive function example to no-unused-vars (Jose Roberto Vidal)
-* Docs: Fix typo (then -> than) (Vladimir Agafonkin)
-* Revert "Fix: sanitise Jekyll interpolation during site generation (fixes #2297)" (Nicholas C. Zakas)
-* Fix: dot-location should use correct dot token (fixes #2504) (Mathias Schreck)
-* Fix: Stop linebreak-style from crashing (fixes #2490) (James Whitney)
-* Fix: rule no-duplicate-case problem with CallExpressions. (fixes #2499) (Matthias Osswald)
-* Fix: Enable full support for eslint-env comments (refs #2134) (Ilya Volodin)
-* Build: Speed up site generation (fixes #2475) (Ilya Volodin)
-* Docs: Fixing trailing spaces (Fixes #2478) (Ilya Volodin)
-* Docs: Update README FAQs (Nicholas C. Zakas)
-* Fix: Allow comment before comma for comma-spacing rule (fixes #2408) (Gyandeep Singh)
-
-v0.21.0 - May 9, 2015
-
-* 0.21.0 (Nicholas C. Zakas)
-* New: Shareable configs (fixes #2415) (Nicholas C. Zakas)
-* Fix: Edge cases for no-wrap-func (fixes #2466) (Nicholas C. Zakas)
-* Docs: Update ecmaFeatures description (Nicholas C. Zakas)
-* New: Add dot-location rule. (fixes #1884) (Greg Cochard)
-* New: Add addPlugin method to CLI-engine (Fixes #1971) (Ilya Volodin)
-* Breaking: Do not check unset declaration types (Fixes #2448) (Ilya Volodin)
-* Fix: no-redeclare switch scoping (fixes #2337) (Nicholas C. Zakas)
-* Fix: Check extra scope in no-use-before-define (fixes #2372) (Nicholas C. Zakas)
-* Fix: Ensure baseConfig isn't changed (fixes #2380) (Nicholas C. Zakas)
-* Fix: Don't warn for member expression functions (fixes #2402) (Nicholas C. Zakas)
-* New: Adds skipBlankLines option to the no-trailing-spaces rule (fixes #2303) (Andrew Vaughan)
-* Fix: Adding exception for last line (Refs #2423) (Greg Cochard)
-* Fix: crash on 0 max (fixes #2423) (gcochard)
-* Fix object-shorthand arrow functions (fixes #2414) (Jamund Ferguson)
-* Fix: Improves detection of self-referential functions (fixes #2363) (Jose Roberto Vidal)
-* Update: key-spacing groups must be consecutive lines (fixes #1728) (Brandon Mills)
-* Docs: grammar fix in no-sync (Tony Lukasavage)
-* Docs: Update configuring.md to fix incorrect link. (Ans)
-* New: Check --stdin-filename by ignore settings (fixes #2432) (Aliaksei Shytkin)
-* Fix: `no-loop-func` rule allows functions at init part (fixes #2427) (Toru Nagashima)
-* New: Add init command (fixes #2302) (Ilya Volodin)
-* Fix: no-irregular-whitespace should work with irregular line breaks (fixes #2316) (Mathias Schreck)
-* Fix: generator-star-spacing with class methods (fixes #2351) (Brandon Mills)
-* New: no-unneeded-ternary rule to disallow boolean literals in conditional expressions (fixes #2391) (Gyandeep Singh)
-* Docs: Add `restParams` to `ecmaFeatures` options list (refs: #2346) (Bogdan Savluk)
-* Fix: space-in-brackets Cannot read property 'range' (fixes #2392) (Gyandeep Singh)
-* Docs: Sort the rules (Lukas Böcker)
-* Add: Exception option for `no-extend-native` and `no-native-reassign` (fixes #2355) (Gyandeep Singh)
-* Fix: space-in-brackets import declaration (fixes #2378) (Gyandeep Singh)
-* Update: Add uninitialized and initialized options (fixes #2206) (Ian VanSchooten)
-* Fix: brace-style to not warn about curly mix ifStatements (fixes #1739) (Gyandeep Singh)
-* Fix: npm run profile script should use espree (fixes #2150) (Mathias Schreck)
-* New: Add support for extending configurations (fixes #1637) (Espen Hovlandsdal)
-* Fix: Include string literal keys in object-shorthand (Fixes #2374) (Jamund Ferguson)
-* Docs: Specify language for all code fences, enable corresponding markdownlint rule. (David Anson)
-* New: linebreak-style rule (fixes #1255) (Erik Müller)
-* Update: Add "none" option to operator-linebreak rule (fixes #2295) (Casey Visco)
-* Fix: sanitise Jekyll interpolation during site generation (fixes #2297) (Michael Ficarra)
-
-v0.20.0 - April 24, 2015
-
-* 0.20.0 (Nicholas C. Zakas)
-* Fix: support arrow functions in no-extra-parens (fixes #2367) (Michael Ficarra)
-* Fix: Column position in space-infix-ops rule (fixes #2354) (Gyandeep Singh)
-* Fix: allow plugins to be namespaced (fixes #2360) (Seth Pollack)
-* Update: one-var: enable let & const (fixes #2301) (Joey Baker)
-* Docs: Add meteor to avaiable environments list (bartmichu)
-* Update: Use `Object.assign()` polyfill for all object merging (fixes #2348) (Sindre Sorhus)
-* Docs: Update markdownlint dependency, resolve/suppress new issues. (David Anson)
-* Fix: newline-after-var declare and export (fixes #2325) (Gyandeep Singh)
-* Docs: Some typos and grammar. (AlexKVal)
-* Fix: newline-after-var to ignore declare in for specifiers (fixes #2317) (Gyandeep Singh)
-* New: add --stdin-filename option (fixes #1950) (Mordy Tikotzky)
-* Fix: Load .eslintrc in $HOME only if no other .eslintrc is found (fixes #2279) (Jasper Woudenberg)
-* Fix: Add `v8` module to no-mixed-requires rule (fixes #2320) (Gyandeep Singh)
-* Fix: key-spacing with single properties (fixes #2311) (Brandon Mills)
-* Docs: `no-invalid-regexp`: add `ecmaFeatures` flags for `u`/`y` (Jordan Harband)
-* New: object-shorthand rule (refs: #1617) (Jamund Ferguson)
-* Update: backticks support for quotes rule (fixes #2153) (borislavjivkov)
-* Fix: space-in-brackets to work with modules (fixes #2216) (Nicholas C. Zakas)
-
-v0.19.0 - April 11, 2015
-
-* 0.19.0 (Nicholas C. Zakas)
-* Upgrade: Espree to 2.0.1 (Nicholas C. Zakas)
-* Docs: Update one-var documentation (fixes #2210) (Nicholas C. Zakas)
-* Update: Add test for no-undef (fixes #2214) (Nicholas C. Zakas)
-* Fix: Report better location for padded-blocks error (fixes #2224) (Nicholas C. Zakas)
-* Fix: Don't check concise methods in quote-props (fixes #2251) (Nicholas C. Zakas)
-* Fix: Consider tabs for space-in-parens rule (fixes #2191) (Josh Quintana)
-* Fix: block-scoped-var to work with classes (fixes #2280) (Nicholas C. Zakas)
-* Docs: Remove trailing spaces, enable corresponding markdownlint rule. (David Anson)
-* Fix: padded-blocks with ASI (fixes #2273) (Brandon Mills)
-* Fix: Handle comment lines in newline-after-var (fixed #2237) (Casey Visco)
-* Docs: Standardize on '*' for unordered lists, enable corresponding markdownlint rule. (David Anson)
-* Fix: no-undef and no-underscore-dangle to use double quotes (fixes #2258) (Gyandeep Singh)
-* Docs: Improve grammar and style in comma-dangle.md (Nate Eagleson)
-* Docs: Improve grammar and style in padded-blocks.md (Nate Eagleson)
-* Docs: Update URL in no-wrap-func.md to resolve 404 (Nate Eagleson)
-* Docs: Fix typo in command-line-interface.md (Nate Eagleson)
-* Docs: Fix typo in working-with-rules.md (Nate Eagleson)
-* Docs: Remove hard tabs from *.md, enable corresponding markdownlint rule. (David Anson)
-* Fix: Function id missing in parent scope when using ecmaFeature `modules` for rule block-scoped-var (fixes #2242) (Michael Ferris)
-* Fix: Ignore single lines for vertical alignment (fixes #2018) (Ian VanSchooten)
-* Fix: Allow inline comments in newline-after-var rule (fixes #2229) (Casey Visco)
-* Upgrade: Espree 2.0.0 and escope 3.0.0 (fixes #2234, fixes #2201, fixes (Nicholas C. Zakas)
-* Docs: Update --no-ignore warning (Brandon Mills)
-* Build: Remove jshint files (fixes #2222) (Jeff Tan)
-* Docs: no-empty fix comment change (refs #2188) (Gyandeep Singh)
-* Fix: duplicate semi and no-extra-semi errors (fixes #2207) (Brandon Mills)
-* Docs: Update processors description (Nicholas C. Zakas)
-* Fix: semi error on export declaration (fixes #2194) (Brandon Mills)
-* New: operator-linebreak rule (fixes #1405) (Benoît Zugmeyer)
-* Docs: Fixing broken links in documentation (Ilya Volodin)
-* Upgrade: Espree to 0.12.3 (fixes #2195) (Gyandeep Singh)
-* Fix: camelcase rule with {properties: never} shouldn't check assignment (fixes #2189) (Gyandeep Singh)
-* New: Allow modifying base config (fixes #2143) (Meo)
-* New: no-continue rule (fixes #1945) (borislavjivkov)
-* Fix: `no-empty` rule should allow any comments (fixes #2188) (Gyandeep Singh)
-* Docs: Fix spell in camelcase doc (fixes #2190) (Gyandeep Singh)
-* Fix: Require semicolon after import/export statements (fixes #2174) (Gyandeep Singh)
-* Build: Add linting of Markdown files to "npm test" script (fixes #2182) (David Anson)
-* Build: Fixing site generation (Ilya Volodin)
-* Build: Fix gensite task to work even if files are missing (Nicholas C. Zakas)
-
-v0.18.0 - March 28, 2015
-
-* 0.18.0 (Nicholas C. Zakas)
-* Fix: Mark variables as used in module scope (fixes #2137) (Nicholas C. Zakas)
-* Fix: arrow functions need wrapping (fixes #2113) (Nicholas C. Zakas)
-* Fix: Don't crash on empty array pattern item (fixes #2111) (Nicholas C. Zakas)
-* Fix: Don't error on destructured params (fixes #2051) (Nicholas C. Zakas)
-* Docs: Fixing broken links (Ilya Volodin)
-* Fix: no-constant-condition should not flag += (fixes #2155) (Nicholas C. Zakas)
-* Fix: Ensure piped in code will trigger correct errors (fixes #2154) (Nicholas C. Zakas)
-* Fix: block-scoped-var to handle imports (fixes #2087) (Nicholas C. Zakas)
-* Fix: no-dupe-args to work with destructuring (fixes #2148) (Nicholas C. Zakas)
-* Fix: key-spacing crash on computed properties (fixes #2120) (Brandon Mills)
-* Fix: indent crash on caseless switch (fixes #2144) (Brandon Mills)
-* Fix: Don't warn about destructured catch params (fixes #2125) (Nicholas C. Zakas)
-* Update: Omit setter param from no-unused-vars (fixes #2133) (Nicholas C. Zakas)
-* Docs: Cleaning dead links (Ilya Volodin)
-* Docs: Moving documentation out of the repository and modifying build scripts (Ilya Volodin)
-* Docs: Update link to Documentation (Kate Lizogubova)
-* Docs: Adding back deprecated space-unary-word-ops documentation (Ilya Volodin)
-* Fix: Unused recursive functions should be flagged (issue2095) (Nicholas C. Zakas)
-* Breaking: Remove JSX support from no-undef (fixes #2093) (Nicholas C. Zakas)
-* Fix: markVariableAsUsed() should work in Node.js env (fixes #2089) (Nicholas C. Zakas)
-* New: Add "always" and "never" options to "one-var" rule. (fixes #1619) (Danny Fritz)
-* New: newline-after-var rule (fixes #2057) (Gopal Venkatesan)
-* Fix: func-names with ES6 classes (fixes #2103) (Marsup)
-* Fix: Add "Error" to the "new-cap" rule exceptions (fixes #2098) (Mickaël Tricot)
-* Fix: vars-on-top conflict with ES6 import (fixes #2099) (Gyandeep Singh)
-* Docs: Fixed JSON syntax (Sajin)
-* New: space-before-function-paren rule (fixes #2028) (Brandon Mills)
-* Breaking: rule no-empty also checking for empty catch blocks. (fixes #1841) (Dieter Oberkofler)
-* Update: rule camelcase to allow snake_case in object literals. (fixes #1919) (Dieter Oberkofler)
-* New: Added option int32Hint for space-infix-ops (fixes #1295) (Kirill Efimov)
-* New: no-param-reassign rule (fixes #1599) (Nat Burns)
-
-v0.17.1 - March 17, 2015
-
-* 0.17.1 (Nicholas C. Zakas)
-* Fix: no-func-assign should not fail on import declarations (fixes #2060) (Igor Zalutsky)
-* Fix: block-scoped-var to work with destructuring (fixes #2059) (Nicholas C. Zakas)
-* Fix: no-redeclare should check Node.js scope (fixes #2064) (Nicholas C. Zakas)
-* Fix: space-before-function-parentheses generator methods (fixes #2082) (Brandon Mills)
-* Fix: Method name resolution in complexity rule (fixes #2049) (Nicholas C. Zakas)
-* Fix: no-unused-vars crash from escope workaround (fixes #2042) (Brandon Mills)
-* Fix: restrict dot-notation keywords to actual ES3 keywords (fixes #2075) (Michael Ficarra)
-* Fix: block-scoped-var to work with classes (fixes #2048) (Nicholas C. Zakas)
-* Docs: Update no-new documentation (fixes #2044) (Nicholas C. Zakas)
-* Fix: yoda range exceptions with this (fixes #2063) (Brandon Mills)
-* Docs: Fix documentation on configuring eslint with comments (Miguel Ping)
-* Fix: rule no-duplicate-case problem with MemberExpressions. (fixes #2038) (Dieter Oberkofler)
-* Fix: Exempt \0 from no-octal-escape (fixes #1923) (Michael Ficarra)
-
-v0.17.0 - March 14, 2015
-
-* 0.17.0 (Nicholas C. Zakas)
-* Fix: module import specifiers should be defined (refs #1978) (Nicholas C. Zakas)
-* Fix: Ignore super in no-undef (refs #1968) (Nicholas C. Zakas)
-* Upgrade: Espree to v0.12.0 (refs #1968) (Nicholas C. Zakas)
-* Fix: destructured arguments should work in block-scoped-var (fixes #1996) (Nicholas C. Zakas)
-* Fix: Line breaking with just carriage return (fixes #2005) (Nicholas C. Zakas)
-* Fix: location of new-cap error messages (fixes #2025) (Mathias Schreck)
-* Breaking: Stop checking JSX variable use, expose API instead (fixes #1911) (Glen Mailer)
-* Fix: Check spacing of class methods (fixes #1989) (Nicholas C. Zakas)
-* New: no-duplicate-case rule to disallow a duplicate case label (fixes #2015) (Dieter Oberkofler)
-* Clarify issue requirement for doc pull requests (Ian)
-* Add quotes around object key (Ian)
-* Fix: Add comma-dangle allow-multiline (fixes #1984) (Keith Cirkel)
-* Fix: Don't explode on default export function (fixes #1985) (Nicholas C. Zakas)
-* Update: Add AST node exceptions to comma-style. (fixes #1932) (Evan Simmons)
-* Docs: Add spread operator to available language options (Nicholas C. Zakas)
-* New: generator-star-spacing rule (fixes #1680, fixes #1949) (Brandon Mills)
-
-v0.16.2 - March 10, 2015
-
-* 0.16.2 (Nicholas C. Zakas)
-* Fix: Ensure globalReturn isn't on when node:false (fixes #1995) (Nicholas C. Zakas)
-* Downgrade: escope pegged to 2.0.6 (refs #2001) (Nicholas C. Zakas)
-* Upgrade: escope to 2.0.7 (fixes #1978) (Nicholas C. Zakas)
-* Docs: Update descriptive text for --no-ignore option. (David Anson)
-* Upgrade: estraverse to latest for ESTree support (fixes #1986) (Nicholas C. Zakas)
-* Fix: Global block-scope-var check should work (fixes #1980) (Nicholas C. Zakas)
-* Fix: Don't warn about parens around yield (fixes #1981) (Nicholas C. Zakas)
-
-v0.16.1 - March 8, 2015
-
-* 0.16.1 (Nicholas C. Zakas)
-* Fix: Node.js scoping in block-scoped-var (fixes #1969) (Nicholas C. Zakas)
-* Update: Enable ES6 scoping for more options (Nicholas C. Zakas)
-* Fix: Ensure all export nodes are traversable (fixes #1965) (Nicholas C. Zakas)
-* Fix: Ensure class names are marked as used (fixes #1967) (Nicholas C. Zakas)
-* Fix: remove typo that caused a crash (fixes #1963) (Fabricio C Zuardi)
-* Docs: Added missing "are" (Sean Wilkinson)
-
-v0.16.0 - March 7, 2015
-
-* 0.16.0 (Nicholas C. Zakas)
-* Fix: Pass correct sourceType to escope (fixes #1959) (Nicholas C. Zakas)
-* Fix: Scoping for Node.js (fixes #892) (Nicholas C. Zakas)
-* Fix: strict rule should honor module code (fixes #1956) (Nicholas C. Zakas)
-* New: Add es6 environment (fixes #1864, fixes #1944) (Nicholas C. Zakas)
-* Docs: Update ecmaFeatures list (fixes #1942) (Nicholas C. Zakas)
-* Fix: Make no-unused-vars ignore exports (fixes #1903) (Nicholas C. Zakas)
-* Upgrade: Espree to v1.11.0 (Nicholas C. Zakas)
-* Fix: Comment configuration of rule doesn't work (fixes #1792) (Jary)
-* Fix: Rest args should work in no-undef and block-scoped-var (fixes #1543) (Nicholas C. Zakas)
-* Breaking: change no-comma-dangle to comma-dangle (fixes #1350) (Mathias Schreck)
-* Update: space-before-function-parentheses to support generators (fixes #1929) (Brandon Mills)
-* New: Adding support for "// eslint-disable-line rule" style comments (Billy Matthews)
-* Fix: Use unversioned sinon file in browser test (fixes #1947) (Nicholas C. Zakas)
-* Docs: Add mention of compatible parsers (Nicholas C. Zakas)
-* Fix: Better error when given null as rule config (fixes #1760) (Glen Mailer)
-* Update: no-empty to check TryStatement.handler (fixes #1930) (Brandon Mills)
-* Fix: space-before-function-parentheses and object methods (fixes #1920) (Brandon Mills)
-* New: no-dupe-args rule (fixes #1880) (Jamund Ferguson)
-* Fix: comma-spacing should ignore JSX text (fixes #1916) (Brandon Mills)
-* Breaking: made eol-last less strict (fixes #1460) (Glen Mailer)
-* New: generator-star middle option (fixes #1808) (Jamund Ferguson)
-* Upgrade: Espree to 1.10.0 for classes support (Nicholas C. Zakas)
-* Docs: no-plusplus.md - auto semicolon insertion (Miroslav Obradović)
-* Docs: Use union types in TokenStore JSDoc (refs #1878) (Brandon Mills)
-* Fix: block-scoped-var to work with destructuring (fixes #1863) (Nicholas C. Zakas)
-* Docs: Update docs for token-related methods (fixes #1878) (Nicholas C. Zakas)
-* Update: Remove preferGlobal from package.json (fixes #1877) (Nicholas C. Zakas)
-* Fix: allow block bindings in no-inner-declarations (fixes #1893) (Roberto Vidal)
-* Fix: getScope and no-use-before-define for arrow functions (fixes #1895) (Brandon Mills)
-* Fix: Make no-inner-declarations look for arrow functions (fixes #1892) (Brandon Mills)
-* Breaking: Change no-space-before-semi to semi-spacing and add "after" option (fixes #1671) (Mathias Schreck)
-* Update: Add support for custom preprocessors (fixes #1817) (Ilya Volodin)
-
-v0.15.1 - February 26, 2015
-
-* 0.15.1 (Nicholas C. Zakas)
-* Build: Fix release task (Nicholas C. Zakas)
-* Fix: check all semicolons in no-space-before-semi (fixes #1885) (Mathias Schreck)
-* Fix: Refactor comma-spacing (fixes #1587, fixes #1845) (Roberto Vidal)
-* Fix: Allow globalReturn in consistent-return (fixes #1868) (Brandon Mills)
-* Fix: semi rule should check throw statements (fixes #1873) (Mathias Schreck)
-* Docs: Added HolidayCheck AG as user (0xPIT)
-* Upgrade: `chalk` to 1.0.0 (Sindre Sorhus)
-* Docs: Add CustomInk to the list of companies (Derek Lindahl)
-* Docs: Alphabetize project & company usage list (Derek Lindahl)
-* Docs: fix typo (Henry Zhu)
-* Docs: Fix typo (Brenard Cubacub)
-
-v0.15.0 - February 21, 2015
-
-* 0.15.0 (Nicholas C. Zakas)
-* Upgrade: Espree to 1.9.1 (fixes #1816, fixes #1805) (Nicholas C. Zakas)
-* Fix: make rules work with for-of statements (fixes #1859) (Mathias Schreck)
-* Fix: Enable globalReturn for Node.js environment (fixes #1158) (Nicholas C. Zakas)
-* Fix: Location of extra paren message (fixes #1814) (Nicholas C. Zakas)
-* Fix: Remove unnecessary file exists check (fixes #1831) (Nicholas C. Zakas)
-* Fix: Don't count else-if in max-depth (fixes #1835) (Nicholas C. Zakas)
-* Fix: Don't flag for-of statement (fixes #1852) (Nicholas C. Zakas)
-* Build: Test using io.js as well (Nicholas C. Zakas)
-* Change customformat value to path (suisho)
-* Docs: Add a missing word in the Contributing doc (Ben Linskey)
-* Docs: Fix typo in wrap-iife rule doc title (Ben Linskey)
-* Docs: Update pages to fix rendering of lists (David Anson)
-* Fix: new-cap should allow defining exceptions (fixes #1424) (Brian Di Palma)
-* Update: Add requireReturnDescription for valid-jsdoc (fixes #1833) (Brian Di Palma)
-* New: rule no-throw-literal added (fixes #1791) (Dieter Oberkofler)
-* New: multi-line option for the curly rule (fixes #1812) (Hugo Wood)
-* Docs: fix typo in configuring docs (mendenhallmagic)
-* Update: Backslashes in path (fixes #1818) (Jan Schär)
-* Docs: Update pages to fix rendering of lists and fenced code blocks (David Anson)
-* Docs: add webpack loader to the docs/integrations page (Maxime Thirouin)
-* Breaking: space-before-function-parentheses replaces space-after-function-name and checkFunctionKeyword (fixes #1618) (Mathias Schreck)
-
-v0.14.1 - February 8, 2015
-
-* 0.14.1 (Nicholas C. Zakas)
-* Fix: Exit code should be 1 for any number of errors (fixes #1795) (Nicholas C. Zakas)
-* Fix: Check indentation of first line (fixes #1796) (Nicholas C. Zakas)
-* Fix: strict rules shouldn't throw on arrow functions (fixes #1789) (Nicholas C. Zakas)
-
-v0.14.0 - February 7, 2015
-
-* 0.14.0 (Nicholas C. Zakas)
-* Update: Fix indentation of comment (Nicholas C. Zakas)
-* Fix: comma-spacing for template literals (fixes #1736) (Nicholas C. Zakas)
-* Build: Add Node.js 0.12 testing (Nicholas C. Zakas)
-* Breaking: Remove node from results (fixes #957) (Nicholas C. Zakas)
-* Breaking: Exit code is now error count (Nicholas C. Zakas)
-* Docs: Correct getFormatter() documentation (refs #1723) (Nicholas C. Zakas)
-* Update: Make rules work with arrow functions (fixes #1508, fixes #1509, fixes #1493) (Nicholas C. Zakas)
-* Fix: Ensure template string references count (fixes #1542) (Nicholas C. Zakas)
-* Fix: no-undef to work with arrow functions (fixes #1604) (Nicholas C. Zakas)
-* Upgrade: Espree to version 1.8.0 (Nicholas C. Zakas)
-* Fix: Don't throw error for arguments (fixes #1759) (Nicholas C. Zakas)
-* Fix: Don't warn on computed nonliteral properties (fixes #1762) (Nicholas C. Zakas)
-* New: Allow parser to be configured (fixes #1624) (Nicholas C. Zakas)
-* Docs: Added double quotes for JSON keys for comma-spacing and key-spacing rule (Dmitry Polovka)
-* New: Rule indent (fixes #1022) (Dmitriy Shekhovtsov)
-* Revert "New: Rule indent (fixes #1022)" (Nicholas C. Zakas)
-* Update: fix eslint indentations (fixes #1770) (Dmitriy Shekhovtsov)
-* Fix: Scoping issues for no-unused-vars (fixes #1741) (Nicholas C. Zakas)
-* Docs: Added `eslint-enable` inline (Ivan Fraixedes)
-* New: Add predefined Meteor globals (fixes #1763) (Johan Brook)
-* New: Rule indent (fixes #1022) (Dmitriy Shekhovtsov)
-* Update: Check all assignments for consistent-this (fixes #1513) (Timothy Jones)
-* Fix: Support exceptions in no-multi-spaces (fixes #1755) (Brandon Mills)
-* Docs: Forgotten parentheses in code snippet (Ivan Fraixedes)
-* Update: CLIEngine results include warning and error count (fixes #1732) (gyandeeps)
-* Fix: Scoping issues for no-unused-vars (fixes #1733) (Nicholas C. Zakas)
-* Update: Add getNodeByRangeIndex method (refs #1755) (Brandon Mills)
-* Update: Replace getTokenByRange(Index->Start) (refs #1721) (Brandon Mills)
-* Update: Fast-path for empty input (fixes #546) (Nicholas C. Zakas)
-* Fix: Allow single line else-if (fixes #1739) (Nicholas C. Zakas)
-* Fix: Don't crash when $HOME isn't set (fixes #1465) (Nicholas C. Zakas)
-* Fix: Make no-multi-spaces work for every case (fixes #1603, fixes #1659) (Nicholas C. Zakas)
-* Breaking: Show error and warning counts in stylish summary (fixes #1746) (Brandon Mills)
-* Docs: fixed typo in no-lone-blocks docs (Vitor Balocco)
-* Docs: fixed typo in consistent-return docs (Vitor Balocco)
-* Breaking: remove implied eval check from no-eval (fixes #1202) (Mathias Schreck)
-* Update: Improve CLIEngine.getFormatter() (refs #1723) (Nicholas C. Zakas)
-* Docs: Add Backbone plugin link (Ilya Volodin)
-* Docs: use npm's keyword route (Tom Vincent)
-* Build: Update sitegen script (Closes #1725) (Ilya Volodin)
-
-v0.13.0 - January 24, 2015
-
-* 0.13.0 (Nicholas C. Zakas)
-* Update: The rule spaced-line-comment now also allows tabs and not only spaces as whitespace. (fixes #1713) (Dieter Oberkofler)
-* Docs: add Jasmine rules and eslintplugin npm links (Tom Vincent)
-* Fix: Make no-redeclare work with let (fixes #917) (Nicholas C. Zakas)
-* Update: Add CLIEngine.getFormatter() (fixes #1653) (Nicholas C. Zakas)
-* Breaking: Update escope (fixes #1642) (Nicholas C. Zakas)
-* Update: Switch to using estraverse-fb (fixes #1712) (Nicholas C. Zakas)
-* Docs: Update README FAQ (Nicholas C. Zakas)
-* Update: no-warning-comments matches on whole word only (fixes #1709) (Nick Fisher)
-* Build: Add JSDoc generation (fixes #1363) (Nicholas C. Zakas)
-* Docs: Add more info about context (fixes #1330) (Nicholas C. Zakas)
-* Upgrade: Espree to 1.7.1 (fixes #1706) (Nicholas C. Zakas)
-* Docs: Make CLA notice more prominent (Nicholas C. Zakas)
-* Update: Added globals for: phantom,jquery, prototypejs, shelljs (fixes #1704) (Dmitriy Shekhovtsov)
-* Docs: Fixed example for the space-return-throw-case rule (mpal9000)
-* Fix: Except object literal methods from func-names (fixes #1699) (Brandon Mills)
-* Update: use global strict mode everywhere (fixes #1691) (Brandon Mills)
-* Update: Add allowPattern option for dot-notation rule (fixes #1679) (Tim Schaub)
-* Fix: Missing undeclared variables in JSX (fixes #1676) (Yannick Croissant)
-* Fix: no-unused-expressions rule incorrectly flagging yield (fixes #1672) (Rémi Gérard-Marchant)
-* Update: Combine strict mode rules (fixes #1246) (Brandon Mills)
-* Fix: disregards leading './' in ignore pattern or file name (fixes #1685) (Chris Montrois)
-* Upgrade: globals module to latest (fixes #1670) (Nicholas C. Zakas)
-* Fix: generator-star should allow params (fixes #1677) (Brandon Mills)
-* Fix: no-unused-vars for JSX (fixes #1673 and fixes #1534) (Yannick Croissant)
-* Docs: Add angularjs-eslint link into the integration doc (Emmanuel DEMEY)
-
-v0.12.0 - January 17, 2015
-
-* 0.12.0 (Nicholas C. Zakas)
-* Fix: Track JSX global variable correctly (fixes #1534) (Nicholas C. Zakas)
-* Fix: Property regex flag checking (fixes #1537) (Nicholas C. Zakas)
-* Docs: Add angularjs-eslint link into the integration doc (Emmanuel DEMEY)
-* Update: Expose ecmaFeatures on context (fixes #1648) (Nicholas C. Zakas)
-* Docs: Added Fitbit to the list of companies (Igor Zalutsky)
-* New: gen-star rule (refs #1617) (Jamund Ferguson)
-* New: no-var rule (refs #1617) (Jamund Ferguson)
-* Fix: Support JSX spread operator (fixes #1634) (Nicholas C. Zakas)
-* Docs: Document ecmaFeatures (Nicholas C. Zakas)
-* Upgrade: several dependencies (fixes #1377) (Nicholas C. Zakas)
-* Fix: Broken JSX test (Nicholas C. Zakas)
-* Fix: no-bitwise reports on bitwise assignment expressions (fixes #1643) (Mathias Schreck)
-* Fix: Find JSXIdentifier refs in no-unused-vars (fixes #1534) (Nicholas C. Zakas)
-* Update: Add a couple JSX tests (Nicholas C. Zakas)
-* Fix: quotes rule ignores JSX literals (fixes #1477) (Nicholas C. Zakas)
-* Fix: Don't warn on JSX literals with newlines (fixes #1533) (Nicholas C. Zakas)
-* Update: Fully enable JSX support (fixes #1640) (Nicholas C. Zakas)
-* Breaking: Allow parser feature flips (fixes #1602) (Nicholas C. Zakas)
-* Fix: Allow comments in key-spacing groups (fixes #1632) (Brandon Mills)
-* Fix: block-scoped-var reports labels (fixes #1630) (Michael Ficarra)
-* Docs: add newline to no-process-env (fixes #1627) (Tom Vincent)
-* Fix: Update optionator, --no in help (fixes #1134) (George Zahariev)
-* Fix: Allow individual newlines in space-in-brackets (fixes #1614) (Brandon Mills)
-* Docs: Correct alignment in example project tree (Tim Schaub)
-* Docs: Remove references to Esprima (Nicholas C. Zakas)
-* Docs: Remove illegal code fence (Nicholas C. Zakas)
-
-v0.11.0 - December 30, 2014
-
-* 0.11.0 (Nicholas C. Zakas)
-* Fix: Adding regexp literal exception (fixes #1589) (Greg Cochard)
-* Fix: padded-blocks incorrectly complained on comments (fixes #1416) (Mathias Schreck)
-* Fix: column location of key-spacing with additional tokens (fixes #1458) (Mathias Schreck)
-* Build: tag correct commit (refs #1606) (Mathias Schreck)
-* Upgrade: Updat Espree to 1.3.1 (Nicholas C. Zakas)
-* Fix: add es3 config option to dot-notation rule (fixes #1484) (Michael Ficarra)
-* Fix: valid-jsdoc should recognize @class (fixes #1585) (Nicholas C. Zakas)
-* Update: Switch to use Espree (fixes #1595) (Nicholas C. Zakas)
-* Fix: brace-style stroustrup should report on cuddled elseif (fixes #1583) (Ian Christian Myers)
-* New: Configuration via package.json (fixes #698) (Michael Mclaughlin)
-* Update: Set environments w/ globals (fixes #1577) (Elan Shanker)
-* Fix: yoda treats negative numbers as literals (fixes #1571) (Brandon Mills)
-* Fix: function arguments now count towards no-shadow check (fixes #1584) (Glen Mailer)
-* Fix: check if next statement is on newline when warning against extra semicolons. (fixes #1580) (Evan You)
-* Update: add yoda exception for range tests (fixes #1561) (Brandon Mills)
-* New: space-after-function-name (fixes #1340) (Roberto Vidal)
-
-v0.10.2 - December 12, 2014
-
-* 0.10.2 (Nicholas C. Zakas)
-* Fix: detect for...in in no-loop-func (fixes #1573) (Greg Cochard)
-* Update: simplify comma-spacing logic (fixes #1562) (Brandon Mills)
-* Fix: operator-assignment addition is non-commutative (fixes#1556) (Brandon Mills)
-* 0.10.1 (Nicholas C. Zakas)
-* Update: Add new-cap exception configurations. (Fixes #1487) - `newCapsAllowed` - `nonNewCapsAllowed` (Jordan Harband)
-
-v0.10.1 - December 6, 2014
-
-* 0.10.1 (Nicholas C. Zakas)
-* Docs: Fix v0.10.0 changelog (Nicholas C. Zakas)
-* Build: Ensure changelog works with large semver versions (Nicholas C. Zakas)
-* Fix: comma-spacing and comma-style to work with array literals (fixes #1492) (Nicholas C. Zakas)
-* Update: better operator regex in use-isnan rule (fixes #1551) (Michael Ficarra)
-* Fix: wrong op index in no-multi-spaces (fixes #1547) (Brandon Mills)
-* Fix: Restrict use-isnan violations to comparison operators. (Fixes #1535) (Jordan Harband)
-* Fix: comma-spacing has false positives when parenthesis are used (fixes #1457) (Jamund Ferguson)
-* Docs: alphabetize the "Stylistic Issues" section (Jeff Williams)
-* Build: make the "gensite" target work when DOCS_DIR does not exist (fixes #1530) (Jeff Williams)
-* Docs: badges should only refer to master branch (Mathias Schreck)
-* Fix: prevent crash on empty blocks in no-else-return (fixes #1527) (Mathias Schreck)
-* Build: Fix md to html conversion regex (fixes #1525) (Brandon Mills)
-* 0.10.0 (Nicholas C. Zakas)
-
-v0.10.0 - November 27, 2014
-
-* 0.10.0 (Nicholas C. Zakas)
-* Fix: Add Object and Function as exceptions in new-cap (refs #1487) (Nicholas C. Zakas)
-* Breaking: Allow extensionless files to be passed on CLI (fixes #1131) (Nicholas C. Zakas)
-* Fix: typo: iffe to iife, none to non (Michael Ficarra)
-* Update: refactor tokens API (refs #1212) (Brandon Mills)
-* New: Allow other file extensions (fixes #801) (Nicholas C. Zakas)
-* Update: Add Event to browser globals (fixes #1474) (Nicholas C. Zakas)
-* Fix: check function call arguments in comma-spacing (fixes #1515) (Mathias Schreck)
-* Update: Add no-cond-assign option to disallow nested assignments in conditionals (fixes #1444) (Jeff Williams)
-* Fix: crash in no-multi-spaces on empty array elements (fixes #1418) (Brandon Mills)
-* Fix: Don't explode on directory traversal (fixes #1452) (Nicholas C. Zakas)
-* Fix: no-fallthrough should work when semis are missing (fixes #1447) (Nicholas C. Zakas)
-* Fix: JSDoc parsing by updating doctrine (fixes #1442) (Nicholas C. Zakas)
-* Update: restore the "runs" global present in Jasmine 1.3 (fixes #1498) (Michał Gołębiowski)
-* Fix: ignore undefined identifiers in typeof (fixes #1482) (Mathias Schreck)
-* Fix: Ignoring empty comments. (fixes #1488) (Greg Cochard)
-* New: Add space-unary-ops rules (#1346) (Marcin Kumorek)
-* Update: Remove shebang workaround in spaced-line-comment (fixes #1433) (Michael Ficarra)
-* Docs: change 'and' to 'an' in docs/rules/valid-jsdoc.md (fixes #1441) (Michael Ficarra)
-* Update: Add `beforeAll` and `afterAll` to the Jasmine globals (fixes #1478) (Gyandeep Singh)
-* Update: Add exception options to space-in-parens (fixes #1368) (David Clark)
-* Build: Add check for license issues (fixes #782) (Brandon Mills)
-* Docs: update badges (Yoshua Wuyts)
-* Docs: Update pages to fix rendering of lists and fenced code blocks (David Anson)
-* Fix: env rules merging for command line config (fixes #1271) (Roberto Vidal)
-* Fix: Collect variables declare in switch-case.(fixes #1453) (chris)
-* Fix: remove extra capture group (Nate-Wilkins)
-* Update: allow distinct alignment groups in key-spacing (fixes #1439) (Brandon Mills)
-* Fix: message for numeric property names in quote-props (fixes #1459) (Brandon Mills)
-* Docs: Remove assumption about the rule config (Alexander Schmidt)
-* New: Add ability to time individual rules (fixes #1437) (Brandon Mills)
-* Fix: single quotes (Nate-Wilkins)
-* Docs: Fix broken code fences in key-spacing docs (Brandon Mills)
-* Docs: Explain .eslintignore features (fixes #1094) (Brandon Mills)
-* Breaking: ignore node_modules by default (fixes #1163) (Brandon Mills)
-* Fix: Adds clamping to getSource beforeCount (fixes #1427) (Greg Gianforcaro)
-* New: add no-inline-comment rule (fixes #1366) (Greg Cochard)
-* Fix: '.md' to '.html' with anchors (fixes #1415) (Nate-Wilkins)
-* Build: Filter and sort versions in gensite (fixes #1430) (Brandon Mills)
-* Build: Escape period in regex (fixes #1428) (Brandon Mills)
-* Revert "Fix: '.md' to '.html' with anchors (fixes #1415)" (Nicholas C. Zakas)
-* 0.9.2 (Nicholas C. Zakas)
-* New: Add operator-assignment rule (fixes #1420) (Brandon Mills)
-
-v0.9.2 - November 1, 2014
-
-* 0.9.2 (Nicholas C. Zakas)
-* Fix: '.md' to '.html' with anchors (fixes #1415) (Nate-Wilkins)
-* Fix: Allow line breaks in key-spacing rule (fixes #1407) (Brandon Mills)
-* Build: add coveralls integration (fixes #1411) (Mathias Schreck)
-* Fix: add severity flag for ignored file warning (fixes #1401) (Mathias Schreck)
-* Fix: Keep sinon at ~1.10.3 (fixes #1406) (Brandon Mills)
-* Fix: ! negates .eslintignore patterns (fixes #1093) (Brandon Mills)
-* Fix: let fs.stat throw if a file does not exist (fixes #1296) (Mathias Schreck)
-* Fix: check switch statements in space-before-blocks (fixes #1397) (Mathias Schreck)
-* Docs: fix rule name in example configuration (Mathias Schreck)
-* Fix: disable colors during test run (fixes #1395) (Mathias Schreck)
-* New: add isPathIgnored method to CLIEngine (fixes #1392) (Mathias Schreck)
-* Docs: changing eslint to ESLint and add missing backtick (Mathias Schreck)
-* Docs: Documents the functionality to load a custom formatter from a file (Adam Baldwin)
-* 0.9.1 (Nicholas C. Zakas)
-* Update: Option type for mixed tabs and spaces (fixes #1374) (Max Nordlund)
-* Fix: Nested occurrences of no-else-return now show multiple reports (fixes #1369) (Jordan Hawker)
-
-v0.9.1 - October 25, 2014
-
-* 0.9.1 (Nicholas C. Zakas)
-* Docs: fix link on governance model (azu)
-* Fix: plugins without rulesConfig causes crash (fixes #1388) (Mathias Schreck)
-* 0.9.0 (Nicholas C. Zakas)
-
-v0.9.0 - October 24, 2014
-
-* 0.9.0 (Nicholas C. Zakas)
-* New: Allow reading from STDIN (fixes #368) (Nicholas C. Zakas)
-* New: add --quiet option (fixes #905) (Mathias Schreck)
-* Update: Add support for plugin default configuration (fixes #1358) (Ilya Volodin)
-* Fix: Make sure shebang comment node is removed (fixes #1352) (Nicholas C. Zakas)
-* New: Adding in rule for irregular whitespace checking. (fixes #1024) (Jonathan Kingston)
-* Fix: space-in-parens should not throw for multiline statements (fixes #1351) (Jary)
-* Docs: Explain global vs. local plugins (fixes #1238) (Nicholas C. Zakas)
-* Docs: Add docs on Node.js API (fixes #1247) (Nicholas C. Zakas)
-* Docs: Add recommended keywords for plugins (fixes #1248) (Nicholas C. Zakas)
-* Update: Add CLIEngine#getConfigForFile (fixes #1309) (Nicholas C. Zakas)
-* Update: turn on comma-style for project (fixes #1316) (Nicholas C. Zakas)
-* Fix: Ensure messages are sorted by line (fixes #1343) (Nicholas C. Zakas)
-* Update: Added arraysInObjects and objectsInObjects options to space-in-brackets rule (fixes #1265, fixes #1302) (vegetableman)
-* Breaking: Removed comma spacing check from space-infix-ops (fixes #1361) (vegetableman)
-* Fix: addressed linting errors (Nicholas C. Zakas)
-* Docs: Add Contributor Model (fixes #1341) (Nicholas C. Zakas)
-* Docs: Add reference to CLA (Nicholas C. Zakas)
-* Build: add version numbers to docs (fixes #1170) (Mathias Schreck)
-* Fix: no-fallthrough incorrectly flagged falls through annotations (fixes #1353) (Mathias Schreck)
-* Build: separate site publishing form generation (fixes #1356) (Mathias Schreck)
-* New: Add key-spacing rule (fixes #1280) (Brandon Mills)
-* New: add spaced-line-comment rule (fixes #1345) (Greg Cochard)
-* Docs: added more Related Rules sections (fixes #1347) (Delapouite)
-* Fix: resolve linting issue in (fixes #1339) (Nicholas C. Zakas)
-* New: add space-before-blocks rule (fixes #1277) (Mathias Schreck)
-* Docs: Remove moot integration plugins (Sindre Sorhus)
-* New: add rule for multiple empty lines (fixes #1254) (Greg Cochard)
-* Fix: no-shadow rule should consider function expressions (fixes #1322) (Mathias Schreck)
-* Update: remove globals present only in Jasmine plugins (fixes #1326) (Michał Gołębiowski)
-* New: added no-multi-spaces rule (fixes #630) (vegetableman)
-* New: Added comma-spacing rule (Fixes #628, Fixes #1319) (vegetableman)
-* New: add rule for padded blocks (fixes #1278) (Mathias Schreck)
-* Docs: fix eqeqeq isNullCheck comment (Denis Sokolov)
-* Fix: no-comma-dangle violation in unit test and Makefile.js/lint not checking return codes (fixes #1306) (David Anson)
-* Fix: allow comma-last with object properties having line breaks (fixes #1314) (vegetableman)
-* New: Added comma-style rule (fixes #1282) (vegetableman)
-* Update: add space after function keyword check (fixes #1276) (Mathias Schreck)
-* Update: Add missing environments and fix sorting/grouping of rules (fixes #1307, fixes #1308) (David Anson)
-* Docs: Fix sorting of rules within each section (David Anson)
-* Docs: Correct a few misspelled words (David Anson)
-* Docs: Update multiple pages to fix rendering of fenced code blocks (David Anson)
-* New: Added no-process-env rule (fixes #657) (vegetableman)
-* Fix: add rule ensuring #1258 is fixed by recent rewrite (fixes #1258) (Michael Ficarra)
-* Update: split propertyName from singleValue in space-in-brackets (fixes #1253) (Michael Ficarra)
-* Update: add "as-needed" option to quote-props rule (fixes #1279) (Michael Ficarra)
-* Docs: fixed broken link and changed warning level to error level (vegetableman)
-* Docs: Added "the native web" to the list of companies that use ESLint. (Golo Roden)
-* Docs: Add BountySource badge to README (Nicholas C. Zakas)
-* 0.8.2 (Nicholas C. Zakas)
-
-v0.8.2 - September 20, 2014
-
-* 0.8.2 (Nicholas C. Zakas)
-* Docs: Updated contribution guidelines to add accepted/bounty issues descriptions (Nicholas C. Zakas)
-* Docs: Update README with links and FAQs (Nicholas C. Zakas)
-* Docs: add finally to space-after-keywords documentation (Mathias Schreck)
-* New: add ignoreCase option to sort-vars (fixes #1272) (Mathias Schreck)
-* Docs: fix typo (Barry Handelman)
-* Docs: Fix broken Markdown on configuration page (Nicholas C. Zakas)
-* Docs: Fix reference to wrong rule name (Harry Wolff)
-* Upgrade: Most dev dependencies (Nicholas C. Zakas)
-* Upgrade: shelljs to 0.3.0 (Nicholas C. Zakas)
-* Upgrade: doctrine to 0.5.2 (Nicholas C. Zakas)
-* Upgrade: esprima to 1.2.2 (Nicholas C. Zakas)
-* Upgrade: eslint-tester to latest (Nicholas C. Zakas)
-* Fix: Load .eslintrc in directory with $HOME as an ancestor (fixes #1266) (Beau Gunderson)
-* Fix: load .eslintrc from HOME (fixes #1262) (Beau Gunderson)
-* New: Add sharable rule settings (fixes #1233) (Ilya Volodin)
-* Upgrade: upgrade outdated dependencies (fixes #1251) (Mathias Schreck)
-* Docs: fix typo in no-ex-assign documentation (Michael Ficarra)
-* Docs: add intellij plugin to integrations (ido)
-* Docs: Changing NPM to npm (Peter deHaan)
-* Fix: strict should check function expressions (fixes #1244) (Brandon Mills)
-* Docs: fix vars-on-top documentation (fixes #1234) (Mathias Schreck)
-* 0.8.1 (Nicholas C. Zakas)
-* Docs: Fixed a typo in brace-style.md (Anton Antonov)
-
-v0.8.1 - September 9, 2014
-
-* 0.8.1 (Nicholas C. Zakas)
-* Fix: Ensure exit code is 1 when there's a syntax error (fixes #1239) (Nicholas C. Zakas)
-* Docs: fix up vars-on-top documentation (fixes #1234) (Michael Ficarra)
-* Fix: vars-on-top directive support (fixes #1235) (Michael Ficarra)
-* Fix: Avoid mutating node.range in max-len (fixes #1224) (Brandon Mills)
-* Docs: Typo, add missing quotation mark (Ádám Lippai)
-* Update: space-in-brackets to allow exceptions (fixes #1142) (Brandyn Bennett)
-* 0.8.0 (Nicholas C. Zakas)
-
-v0.8.0 - September 5, 2014
-
-* 0.8.0 (Nicholas C. Zakas)
-* Perf-related revert "Fix: Speed up tokens API (refs #1212)" (Nicholas C. Zakas)
-* Fix: no-fallthrough: continue affects control flow, too (fixes #1220) (Michael Ficarra)
-* Fix: rewrite no-unused-vars rule (refs #1212) (Michael Ficarra)
-* Fix: Error when there's a \r in .eslintrc (#1172) (Gyandeep Singh)
-* Added rule disallowing reserved words being used as keys (fixes #1144) (Emil Bay)
-* Fix: rewrite no-spaced-func rule (refs #1212) (Michael Ficarra)
-* Fix: Speed up getScope() (refs #1212) (Brandon Mills)
-* Fix: no-extra-strict behavior for named function expressions (fixes #1209) (Mathias Schreck)
-* Add Date.UTC to allowed capitalized functions (David Brockman Smoliansky)
-* New: Adding 'vars-on-top' rule (fixes #1148) (Gyandeep Singh)
-* Fix: Speed up tokens API (refs #1212) (Brandon Mills)
-* Docs: document plugin usage (fixes #1117) (Mathias Schreck)
-* New: accept plugins from cli (fixes #1113) (Mathias Schreck)
-* Docs: fix some typos. (Mathias Schreck)
-* New: Load plugins from configs (fixes #1115). (Mathias Schreck)
-* Fix: no-unused-expressions better directive detection (fixes #1195) (Michael Ficarra)
-* Fix: no-unused-expressions directive support (fixes #1185) (Michael Ficarra)
-* Update: Add 'allowSingleLine' option to brace-style (fixes #1089) (John Gozde)
-* Docs: Spell checking and one extra closing curly in code example (Juga Paazmaya)
-* Fix: mergeConfigs ensures the plugins property exists (fixes #1191). (Mathias Schreck)
-* Update: Declare ES6 collections (Map, Set, WeakMap, WeakSet) as built-in globals (fixes #1189) (Michał Gołębiowski)
-* New: Adding 'plugin' CLI option (fixes #1112) (Greg)
-* Fix: Correct a typo in the error message in tests (Michał Gołębiowski)
-* New: Add no-extra-bind rule to flag unnecessary bind calls (fixes #982) (Bence Dányi)
-* Fix: Useless bind call in cli-engine (fixes #1181) (Bence Dányi)
-* Docs: Updates `amd` description (fixes #1175) (James Whitney)
-* New: Adds support for the `jasmine` env (fixes #1176) (James Whitney)
-* Fix: for-in support to no-empty-label rule (fixes #1161) (Marc Harter)
-* docs: Update link (Mathias Bynens)
-* Fix: crash when loading empty eslintrc file (fixes #1164) (Michael Ficarra)
-* Fix: no-unused-var should respect compound assignments (fixes #1166) (Michael Ficarra)
-* Update: ES3 `ReservedWord`s (fixes #1151) Adds ES3 `ReservedWord`s to the list of keywords in the `dot-notation` rule (fixes #1151) (Emil Bay)
-* Update: Update comment parser to read rule slashes (fixes #1116) (Jary)
-* New: add no-void rule (fixes #1017). (Mike Sidorov)
-* New: Add rules.import() (fixes #1114) (Mathias Schreck)
-* New: Make mergeConfigs() merge plugin entries (fixes #1111) (Mathias Schreck)
-* Breaking: Change no-global-strict to global-strict and add "always" option (fixes #989) (Brandon Mills)
-* Fix: no-unreachable should check top-level statements (fixes #1138) (Brandon Mills)
-* Fix: Speed up no-unreachable (fixes #1135) (Brandon Mills)
-* New: advanced handle-callback-err configuration (fixes #1124) (Mathias Schreck)
-* New: Expose CLIEngine (fixes #1083) (Gyandeep Singh)
-* Docs: Add link to new Atom linter (fixes #1125) (Gil Pedersen)
-* Fix: space-after-keywords checks finally of TryStatement (fixes #1122) (Michael Ficarra)
-* Fix: space-after-keywords checks while of DoWhileStatement (fixes #1120) (Michael Ficarra)
-* Fix: space-after-keywords w/ "never" should allow else-if (fixes #1118) (Michael Ficarra)
-* Fix: dot-notation rule flags non-keyword reserved words (fixes #1102) (Michael Ficarra)
-* Update: Use xml-escape instead of inline helper (Ref #848) (jrajav)
-* Update: Added comments support to .eslintignore (fixes #1084) (Vitaly Puzrin)
-* Update: enabled 'no-trailing-spaces' rule by default (fixes #1051) (Vitaly Puzrin)
-* Breaking: Ignore children of all patterns by adding "/**" (Fixes #1069) (jrajav)
-* Fix: skip dot files and ignored dirs on traverse (fixes #1077, related to #814) (Vitaly Puzrin)
-* Docs: Added Gruntjs plugin on integrations page (Gyandeep Singh)
-* Fix: don't break node offsets if hasbang present (fixes #1078) (Vitaly Puzrin)
-* Build: Exclude readme/index from rules Resources generation (Fixes #1072) (jrajav)
-* Docs: Change eol-last examples to `` (Fixes #1068) (jrajav)
-* 0.7.4 (Nicholas C. Zakas)
-* New: space-in-parens rule (Closes #627) (jrajav)
-
-v0.7.4 - July 10, 2014
-
-* 0.7.4 (Nicholas C. Zakas)
-* Docs: Fix 'lintinging' typo and ref links (Tom Vincent)
-* Fix: Transform envs option to object in Config (Fixes #1064) (jrajav)
-* 0.7.3 (Nicholas C. Zakas)
-
-v0.7.3 - July 9, 2014
-
-* 0.7.3 (Nicholas C. Zakas)
-* Update: Address code review comment for strict rule (refs #1011) (Nicholas C. Zakas)
-* Docs: Update copyright policy (Nicholas C. Zakas)
-* Docs: Update documentation for max-len to include description of second option (fixes #1006) (Nicholas C. Zakas)
-* Fix: Avoid double warnings for strict rule (fixes #1011) (Nicholas C. Zakas)
-* Fix: Check envs for true/false (Fixes #1059) (jrajav)
-* 0.7.2 (Nicholas C. Zakas)
-
-v0.7.2 - July 8, 2014
-
-* 0.7.2 (Nicholas C. Zakas)
-* Fix: no-mixed-spaces-and-tabs incorrectly flagging multiline comments (fixes #1055) (Nicholas C. Zakas)
-* Fix: new-cap error that throws on non-string member (fixes #1056) (Nicholas C. Zakas)
-* Fix: Always make globals an object (Fixes #1049) (jrajav)
-* 0.7.1 (Nicholas C. Zakas)
-
-v0.7.1 - July 7, 2014
-
-* 0.7.1 (Nicholas C. Zakas)
-* Docs: Add Related Rules sections (Fixes #990) (jrajav)
-* Fix: Check output file isn't dir, fix tests (Fixes #1034) (jrajav)
-* Docs: Updated documentation for several rules (Nicholas C. Zakas)
-* Docs: Updated contributor guide and dev env setup guide (Nicholas C. Zakas)
-* Breaking: Implement configuration hierarchy (fixes #963) (Nicholas C. Zakas)
-* Update: greatly simplify eqeqeq's operator finding logic (fixes #1037) (Michael Ficarra)
-* New: Add getSourceLines() to core and rule context (fixed #1005) (Jary)
-* Build + Docs: Adding generated resource links to rule docs (Fixes #1021) (jrajav)
-* Fix: Ignore unused params for args: 'none' (Fixes #1026) (jrajav)
-* Fix: Point eqeqeq error at operator (Fixes #1029) (jrajav)
-* New: report output to a file (fixes #1027) (Gyandeep Singh)
-* Breaking: CLIEngine abstraction for CLI operations; formatters no longer are passed configs (fixes #935) (Nicholas C. Zakas)
-* Fix: Allow stdout to drain before exiting (fixes #317) (Nicholas C. Zakas)
-* New: add no-undefined rule (fixes #1020) (Michael Ficarra)
-* New: Added no-mixed-spaces-and-tabs rule (fixes #1003) (Jary)
-* New: Added no-trailing-spaces rule (fixes #995) (Vitaly Puzrin)
-* Update: Factor ignores out of Config (fixes #958) (jrajav)
-* Fix: rewrite eol-last rule (fixes #1007) (fixes #1008) (Michael Ficarra)
-* Fix: add additional IIFE exception in no-extra-parens (fixes #1004) (Michael Ficarra)
-* Docs: Removed reference to brace-style Stroustrup default (fixes #1000) (Caleb Troughton)
-* New: Added eol-last rule (Fixes #996) (Vitaly Puzrin)
-* Fix: Put rule severity in messages (Fixes #984); deprecates passing full config to Formatters (jrajav)
-* Fix: no-unused-vars to check only file globals (fixes #975) (Aliaksei Shytkin)
-* Build: Makefile - Check for rule ids in docs titles (Fixes #969) (Delapouite)
-* Docs: guard-for-in - added missing id in title (Fixes #969) (Delapouite)
-* Breaking: Change 'no-yoda' rule to 'yoda' and add "always" option (Fixes #959) (jrajav)
-* Fix: Fixes no-unused-vars to check /*globals*/ (Fixes #955) (jrajav)
-* Update: no-eval to also warn on setTimeout and setInterval (fixes #721) (Nicholas C. Zakas)
-* Remove: experimental match() method (Nicholas C. Zakas)
-* Update: space-in-brackets now always allows empty object and array literals to have no spaces (fixes #797) (Nicholas C. Zakas)
-* New: Allow the cli parameter "color" and "no-color" (fixes #954) (Tom Gallacher)
-* Fix: valid-jsdoc no more warning for multi-level params (Fixes #925) (Delapouite)
-* Update: Search parent directories for .eslintignore (Fixes #933) (jrajav)
-* Fix: Correct order of arguments passed to assert.equal (fixes #945) (Michał Gołębiowski)
-* Update: Write the summary in stylish formatter in yellow if no errors (fixes #906); test coloring of messages (Michał Gołębiowski)
-* Fix: Corrects configs merging into base config (Fixes #838) (jrajav)
-* Fix: Adding check if char is non-alphabetic to new-cap (Fixes #940) (jrajav)
-* Docs: Update about page description (fixes #936) (Nicholas C. Zakas)
-* Docs: Add '/', forgotten in first commit (Fixes #931) (jrajav)
-* Update: Rule `new-cap` checks capitalized functions (fixes #904) (Aliaksei Shytkin)
-* Docs: Mention allowed semicolons in "never" mode for 'semi' rule (fixes #931) (jrajav)
-* Docs: Mention Yeoman generator in dev setup (fixes #914) (Nicholas C. Zakas)
-* Build: Remove flaky perf test from Travis (Nicholas C. Zakas)
-* Breaking: Refactor .eslintignore functionality (refs #928, fixes #901, fixes #837, fixes #853) (Nicholas C. Zakas)
-* 0.6.2 (Nicholas C. Zakas)
-* Breaking: Remove JSON support for .eslintignore (fixes #883) (icebox)
-
-v0.6.2 - May 23, 2014
-
-* 0.6.2 (Nicholas C. Zakas)
-* Fix: Adding per-environment rule configs to docs and doc validation (Fixes #918) (jrajav)
-* Docs: Updated contribution guidelines (Nicholas C. Zakas)
-* Docs: Update description of eqeqeq to mention special cases (fixes #924) (Nicholas C. Zakas)
-* Fix: block-scoped-var CatchClause handling (fixes #922) (Michael Ficarra)
-* Fix: block-scoped-var respects decls in for and for-in (fixes #919) (Michael Ficarra)
-* Update: Implement eqeqeq option "allow-null" (fixes #910) (Michał Gołębiowski)
-* Fix: new-cap should allow non-alpha characters (fixes #897) (Michael Ficarra)
-* Update: Refactor ESLintTester to fix dependency hell (fixes #602) (Nicholas C. Zakas)
-* Fix: Merge configs with ancestors (Fixes #820) (jrajav)
-* Fix: no-fallthrough should respect block statements in case statements (fixes #893) (Nicholas C. Zakas)
-* Docs: Fix layout issue in configuration docs (fixes #889) (Nicholas C. Zakas)
-* Build: Enable default-case rule (fixes #881) (icebox)
-* Build: Enable space-after-keywords (fixes #884) (icebox)
-* Fix api double emit on comment nodes (fixes #876) (Aliaksei Shytkin)
-* 0.6.1 (Nicholas C. Zakas)
-
-v0.6.1 - May 17, 2014
-
-* 0.6.1 (Nicholas C. Zakas)
-* Upgrade: Optionator to 0.4.0 (fixes #885) (Nicholas C. Zakas)
-* 0.6.0 (Nicholas C. Zakas)
-
-v0.6.0 - May 17, 2014
-
-* 0.6.0 (Nicholas C. Zakas)
-* Fix: Remove -r alias for --rule (fixes #882) (Nicholas C. Zakas)
-* Docs: Update dev setup, contributing, default-case descriptions (Nicholas C. Zakas)
-* Update: valid-jsdoc now allows you to optionally turn off parameter description checks (fixes #822) (Nicholas C. Zakas)
-* Breaking: brace-style now disallows block statements where curlies are on the same line (fixes #758) (Nicholas C. Zakas)
-* Add linting Makefile.js (fixes #870) (icebox)
-* add rule flag, closes #692 (George Zahariev)
-* Add check between rules doc and index (fixes #865) (icebox)
-* Add Build Next mention in integrations README. (icebox)
-* document new IIFE exception for no-extra parens added as part of #655 (Michael Ficarra)
-* (fixes #622) Add rule ID on documentation pages (Delapouite)
-* fixes #655: add IIFE exception to no-extra-parens (Michael Ficarra)
-* add new rule "no-new-require" (Wil Moore III)
-* exit with non-zero status when tests fail (fixes #858) (Márton Salomváry)
-* removed unicode zero width space character from messages (fixes #857) (Márton Salomváry)
-* Change: --rulesdir now can be specified multiple times (fixes #830) (Nicholas C. Zakas)
-* Update: Node 0.8 no longer supported (fixes #734) (Nicholas C. Zakas)
-* Update: Add typed arrays into builtin environment globals (fixes #846) (Nicholas C. Zakas)
-* Fix: Add prototype methods to global scope (fixes #700) (Nicholas C. Zakas)
-* Rule: no-restricted-modules (fixes #791) (Christian)
-* Upgrade: Esprima to 1.2 (fixes #842) (Nicholas C. Zakas)
-* Docs: reporting level 2 is an error (fixes #843) (Brandon Mills)
-* Upgrade: Esprima to 1.2, switch to using Esprima comment attachment (fixes #730) (Nicholas C. Zakas)
-* Fix: Semi rule incorrectly flagging extra semicolon (fixes #840) (Nicholas C. Zakas)
-* Build: Update Travis to only test Node 0.10 (refs #734) (Nicholas C. Zakas)
-* Add "nofunc" option (fixes #829) (Conrad Zimmerman)
-* Rule: no-inner-declarations (fixes #587) (Brandon Mills)
-* Rule 'block-scoped-var': correct scope for functions, arguments (fixes #832) (Aliaksei Shytkin)
-* Rule: default-case (fixes #787) (Aliaksei Shytkin)
-* Ignored files are excluded unless --force is passed on the CLI (Nick Fisher)
-* Fixes a typo and a broken link in the documentation (Nick Fisher)
-* Replaces .some() with .indexOf() where appropriate (Nick Fisher)
-* Fix correct config merge for array values (fixes #819) (Aliaksei Shytkin)
-* Remove warning about ESLint being in Alpha (Nick Fisher)
-* Adds `space-after-keywords` rule (fixes #807) (Nick Fisher)
-* Rule: no-lonely-if (fixes #790) (Brandon Mills)
-* Add ignore comments in file (fixes #305) (Aliaksei Shytkin)
-* 0.5.1 (Nicholas C. Zakas)
-* Change: no-unused-vars default to 'all' (fixes #760) (Nicholas C. Zakas)
-
-v0.5.1 - April 17, 2014
-
-* 0.5.1 (Nicholas C. Zakas)
-* Fix general config not to be modified by comment config in files (fixes #806) (Aliaksei Shytkin)
-* SVG badges (Ryuichi Okumura)
-* fixes #804: clean up implementation of #803 (which fixed #781) (Michael Ficarra)
-* Build: Fix perf test to take median of three runs (fixes #781) (Nicholas C. Zakas)
-* Fix: --reset will now properly ignore default rules in environments.json (fixes #800) (Nicholas C. Zakas)
-* Docs: Updated contributor guidelines (Nicholas C. Zakas)
-* Added Mocha global variables for TDD style. Fixes #793. (Golo Roden)
-* Rule: no-sequences (fixes #561) (Brandon Mills)
-* Change .eslintingore to plain text (fixes #761) (Brandon Mills)
-* Change 'no-spaced-func' message (fixes #762) (Aliaksei Shytkin)
-* Rule 'block-scoped-var' works correct when object inits (fixes #783) (Aliaksei Shytkin)
-* Build: Always build docs site on top of origin/master (Nicholas C. Zakas)
-* 0.5.0 (Nicholas C. Zakas)
-
-v0.5.0 - April 10, 2014
-
-* 0.5.0 (Nicholas C. Zakas)
-* Build: Bump perf limit so Travis won't fail every time (fixes #780) (Nicholas C. Zakas)
-* Add tests to cover 100% of eslint.js (Aliaksei Shytkin)
-* Fix: Make sure no-path-concat doesn't flag non-concat operations (fixes #776) (Nicholas C. Zakas)
-* Rule 'no-unused-var' in functional expression with identifier (fixes #775) (Aliaksei Shytkin)
-* Rule: valid-typeof (Ian Christian Myers)
-* Add global cli flag (ref #692) (Brandon Mills)
-* update to latest Optionator (George Zahariev)
-* Add options for rule 'no-unused-vars' to check all arguments in functions (fixes #728) (Aliaksei Shytkin)
-* Fix: Cleanup package.json (Nicholas C. Zakas)
-* New: Experimental support for CSS Auron (fixes #765) (Nicholas C. Zakas)
-* Lint tests on build (fixes #764) (Aliaksei Shytkin)
-* Rule block-scoped-var works correct with object properties (fixes #755) (Aliaksei Shytkin)
-* Breaking: implement eslint-env and remove jshint/jslint environment comment support (fixes #759) (Aliaksei Shytkin)
-* readme: npm i -> npm install (Linus Unnebäck)
-* Add env flag to cli options summary (fixes #752) (Brandon Mills)
-* Fix: Give the perf test a better calculated budget (fixes #749) (Nicholas C. Zakas)
-* give the `env` flag type `[String]`, improve code (fixes #748) (George Zahariev)
-* fixes #735: add new, more efficient getTokens interfaces (Michael Ficarra)
-* Add --env cli flag (ref #692) (Brandon Mills)
-* Fixes #740 - Make sure callbacks exist before marking them as 'handled'. (mstuart)
-* fixes #743: wrap-regex rule warns on regex used in dynamic member access (Michael Ficarra)
-* replace tab indents with 4 spaces in lib/rules/handle-callback-err.js (Michael Ficarra)
-* Adding homepage and bugs links to package.json (Peter deHaan)
-* JSDoc for rules (Anton Rudeshko)
-* 0.4.5 (Nicholas C. Zakas)
-
-v0.4.5 - March 29, 2014
-
-* 0.4.5 (Nicholas C. Zakas)
-* Build: Add perf check into Travis build to better monitor performance regressions (fixes #732) (Nicholas C. Zakas)
-* Fix: Make sure semi reports correct location of missing semicolon (fixes #726) (Nicholas C. Zakas)
-* Add --no-eslintrc cli flag (ref #717) (Brandon Mills)
-* Fix #716 crash with reset flag (Brandon Mills)
-* Fixed JSON formatting and highlighting (Anton Rudeshko (Tesla))
-* fixes #723: block-scoped-var throws on unnamed function expression (Michael Ficarra)
-* Fix: Make stroustrup brace-style closing message make sense (fixes #719) (Nicholas C. Zakas)
-* no-comma-dangle reports correct line number (Andrey Popp)
-* Upgrade: Esprima to 1.1.1 and EScope to 1.0.1 (fixes #718) (Nicholas C. Zakas)
-* Add reset cli flag (refs #692) (Brandon Mills)
-* Relax eqeqeq null check (fixes #669) (Brandon Mills)
-* 0.4.4 (Nicholas C. Zakas)
-* New Rule: handle-callback-err (fixes #567) (Jamund Ferguson)
-
-v0.4.4 - March 25, 2014
-
-* 0.4.4 (Nicholas C. Zakas)
-* Fix no-used-vars to report FunctionExpression params (fixes #697). (Andrey Popp)
-* fixes #711: eslint reports wrong line number for files with shebang (Michael Ficarra)
-* Fix for no-unused-vars and MemberExpression (Andrey Popp)
-* added no-warning-comments rule (Alexander Schmidt)
-* fixes #699: brace-style does not check function expressions (Michael Ficarra)
-* rewrite block-scoped-var (Michael Ficarra)
-* recommend using hasOwnProperty from Object.prototype in guard-for-in docs (Michael Ficarra)
-* change conf/environments.json spacing to be simpler and more consistent (Michael Ficarra)
-* Update API to use context.getFilename() instead of .filename. (Loren Segal)
-* Small changes, JSDoc is clarified (Aliaksei Shytkin)
-* Move FileFinder to separate file (Aliaksei Shytkin)
-* Cache if file is not found (Aliaksei Shytkin)
-* Use cache on config files seach (Aliaksei Shytkin)
-* Added .eslintignore to load from parents folders (fixes #681) (Aliaksei Shytkin)
-* fix 'node-modules' typo in docs (Fred K. Schott)
-* Upgrade to the latest version of doctrine. (Brian Di Palma)
-* Document optional filename and default it to `input`. (Loren Segal)
-* Fix: Compatibility for Node 0.8 (Nicholas C. Zakas)
-* Update: Makefile.js now uses shelljs-nodecli (Nicholas C. Zakas)
-* #681 apply all .eslintignore exclusions (Aliaksei Shytkin)
-* Add RuleContext.filename property (for eslint/eslint#468). (Loren Segal)
-* 0.4.3 (Nicholas C. Zakas)
-
-v0.4.3 - March 18, 2014
-
-* 0.4.3 (Nicholas C. Zakas)
-* fixes #682: rewrite no-constant-condition rule (Michael Ficarra)
-* Fixes #673 allow configuration of @return errors via requireReturn - (fixes #673) (Brian Di Palma)
-* Tweaking inline code formatting for "if, while, dowhile" (Peter deHaan)
-* Fixes #677 getJSDocComment() should not search beyond FunctionExpression or FunctionDeclaration parent nodes. (Brian Di Palma)
-* Relaxed enforcement of camelcase rule (Ian Christian Myers)
-* Fixing issue #675. Incorrect triggering of no-else-return rule. (Brian Di Palma)
-* Added style option for wrap-iife (Mathias Schreck)
-* Fix: Issues with named function expressions in no-unused-vars and no-shadow (fixes #662) (Nicholas C. Zakas)
-* Update: camelcase rule now doesn't flag function calls (fixes #656) (Nicholas C. Zakas)
-* Updating documentation description for: no-space-before-semi rule, changing rules to exempt strings with semicolons and test for that condition. Fixes #629. (Jonathan Kingston)
-* Adding in rule no-space-before-semi to prevent spaces before semicolons. fixes #629 (Jonathan Kingston)
-* show NPM version (Paul Verest)
-* adapt code formatting (Mathias Schreck)
-* Added a TextMate 2 integration to the docs (Nate Silva)
-* 0.4.2 (Nicholas C. Zakas)
-
-v0.4.2 - March 3, 2014
-
-* 0.4.2 (Nicholas C. Zakas)
-* fixes #651: disable no-catch-shadow rule in node environment (Michael Ficarra)
-* Fixed context.report message parsing (Ian Christian Myers)
-* fixe #648: wrap-iife rule should actually check that IIFEs are wrapped (Michael Ficarra)
-* Added "stroustrup" option for brace-style (Ian Christian Myers)
-* 0.4.1 (Nicholas C. Zakas)
-
-v0.4.1 - February 27, 2014
-
-* 0.4.1 (Nicholas C. Zakas)
-* Created space-in-brackets rule (Ian Christian Myers)
-* Update: Allow valid-jsdoc to specify replacement tags (fixes #637) (Nicholas C. Zakas)
-* Fix: Ensure getJSDocComment() works for all function declarations (fixes #638) (Nicholas C. Zakas)
-* Added broccoli-eslint to integration docs (Christian)
-* fixes #634: getters/setters shouldn't trigger no-dupe-keys (Michael Ficarra)
-* Update: semi to also enforce not using semicolons (fixes #618) (Nicholas C. Zakas)
-* New Rule: no-constant-condition - removed SwitchStatement discriminant check - removed AssignmentExpression with right Identifier - fixed copy paste error - added DoWhileStatement, ForStatement based on discussion: https://github.com/eslint/eslint/pull/624 (fixes #621) (Christian)
-* New Rule: no-constant-condition (fixes #621) (Christian)
-* Adding mimosa-eslint to Build System list (dbashford)
-* Fix: Make sure semi flags return statements without a semicolon (fixes #616) (Nicholas C. Zakas)
-* Fix: stylish formatter blue text -> white text (fixes #607) (Nicholas C. Zakas)
-* Fix: radix rule should warn (not throw error) when parseInt() is called without arguments (fixes #611) (Nicholas C. Zakas)
-* Update README.md (Dmitry)
-* Adding JSDoc comments for TAP format helper functions (Jonathan Kingston)
-* Updating documentation to include TAP format option (Jonathan Kingston)
-* Fixing validation issues to TAP formatter (Jonathan Kingston)
-* Adding TAP formatter and basic tests (Jonathan Kingston)
-* Docs: Updated integrations page (Nicholas C. Zakas)
-* 0.4.0 (Nicholas C. Zakas)
-
-v0.4.0 - February 12, 2014
-
-* 0.4.0 (Nicholas C. Zakas)
-* Change: Switch :after to :exit (fixes #605) (Nicholas C. Zakas)
-* Fix: Make sure no-unused-vars doesn't get confused by nested functions (fixes #584) (Nicholas C. Zakas)
-* Update: .eslintrc to check more things (Nicholas C. Zakas)
-* Fix: Make sure JSDoc parser accepts JSDoc3-style optional parameters (Nicholas C. Zakas)
-* Docs: Update documentation with linking instructions for ESLintTester (Nicholas C. Zakas)
-* New Rule: valid-jsdoc (fixes #536) (Nicholas C. Zakas)
-* #595 improved func-names documentation (Kyle Nunery)
-* #595 added more func-names tests (Kyle Nunery)
-* #595 fix rule message and add more tests (Kyle Nunery)
-* use optionator for option parsing, not optimist (George Zahariev)
-* Include instructions for working with ESLintTester (Nicholas C. Zakas)
-* #595 remove needless 'function Foo() {}' in tests (Kyle Nunery)
-* #595 fix whitespace (Kyle Nunery)
-* #595 fix markdown for js code blocks (Kyle Nunery)
-* Adding information about Yeomen generator (Ilya Volodin)
-* #595 add docs for rule func-names (Kyle Nunery)
-* #595 add func-names rule (Kyle Nunery)
-* migrate variables array to map (Brandon Mills)
-* Perf: Move try-catch out of verify() function to allow V8 optimization (refs #574) (Nicholas C. Zakas)
-* Docs: Added instructions for running npm run profile (Nicholas C. Zakas)
-* refactor variable name lookup into a separate function (Brandon Mills)
-* optimize findVariable() in no-unused-vars (Brandon Mills)
-* move to tests/bench (Chris Dickinson)
-* add `npm run profile`. (Chris Dickinson)
-* #586 refactor based on https://github.com/eslint/eslint/pull/590#discussion_r9476367 (Christian)
-* #586 added no-unreachable jsdoc, documentation note on hoisting case (Christian)
-* #586 add hoisting check to no-unreachable (Christian)
-* readme: Remove stray asterisk (Timo Tijhof)
-* #580 Remove eslint.getAllComments(), related docs, related tests (Christian)
-* Added test for bug fix #582. Test Passes (Shmueli Englard)
-* Added curly braces to if statment (Shmueli Englard)
-* Added new test for fix to #582 (fixes 582) (Shmueli Englard)
-* Bug #582: Added check if node.value isn't a string just exit (Shmueli Englard)
-* Update Rule: implement curly options for single-statement bodies (fixes #511) (Nicholas C. Zakas)
-* New Rule: no-extra-boolean-cast (fixes #557) (Brandon Mills)
-* New Rule: no-sparse-arrays (fixes #499) (Nicholas C. Zakas)
-* Fix: no-spaced-func is now an error (Nicholas C. Zakas)
-* New Rule: no-process-exit (fixes #568) (Nicholas C. Zakas)
-* New Rule: no-labels (fixes #550) (Nicholas C. Zakas)
-* New Rule: no-lone-blocks (fixes #512) (Brandon Mills)
-* Added Emacs/Flycheck integration (Nikolai Prokoschenko)
-* Build: Add perf test (Nicholas C. Zakas)
-* Fix: no-cond-assign shouldn't throw error when there's a for loop with an empty conditional (fixes #53) (Nicholas C. Zakas)
-* Docs: Add docs for no-regex-spaces and all doc errors now break build (closes #562) (Nicholas C. Zakas)
-* Rename: regex-spaces to no-regex-spaces (Nicholas C. Zakas)
-* Docs: Add docs for no-underscore-dangle (refs #562) (Nicholas C. Zakas)
-* Docs: Add docs for no-undef-init (refs #562) (Nicholas C. Zakas)
-* Docs: Add docs for no-return-assign (refs #562) (Nicholas C. Zakas)
-* Fix: Misspelling in no-return-assign message (Nicholas C. Zakas)
-* Docs: Add docs for no-new-wrappers (refs #562) (Nicholas C. Zakas)
-* Docs: Add docs for no-new-object (refs #562) (Nicholas C. Zakas)
-* Docs: Add docs for no-implied-eval (refs #562) (Nicholas C. Zakas)
-* Docs: Updated documentation for developing rules (Nicholas C. Zakas)
-* Testing: Move ESLintTester to be external dependency (fixes #480) (Nicholas C. Zakas)
-* Docs: Add list of known integrations (Nicholas C. Zakas)
-* Fix #570 (dmp42)
-* document no-array-constructor rule (Michael Ficarra)
-* fixes #500: no-array-constructor should not flag 1-argument construction (Michael Ficarra)
-* fixes #501: no-array-constructor recognises CallExpression form (Michael Ficarra)
-* rename no-new-array rule to no-array-constructor; ref #501 (Michael Ficarra)
-* Fix: Make radix rule warn on invalid second parameter (fixes #563) (Nicholas C. Zakas)
-* Docs: Added no-floating-decimal docs (refs #562) (Nicholas C. Zakas)
-* New Rule: no-path-concat (fixes #540) (Nicholas C. Zakas)
-* Docs: Add some missing rule docs (refs #562) (Nicholas C. Zakas)
-* Fix: CLI should not output anything when there are no warnings (fixes #558) (Nicholas C. Zakas)
-* New Rule: no-yoda (fixes #504) (Nicholas C. Zakas)
-* New Rule: consistent-return (fixes #481) (Nicholas C. Zakas)
-* Rewrite configuration documentation to include information about globals (fixes #555) (Nicholas C. Zakas)
-* Allow YAML configuration files (fixes #491) (Nicholas C. Zakas)
-* 0.3.0 (Nicholas C. Zakas)
-
-v0.3.0 - January 20, 2014
-
-* 0.3.0 (Nicholas C. Zakas)
-* Config: Allow comments in JSON configuration files (fixes #492) (Nicholas C. Zakas)
-* Bug: max-len fix to report correct line number (fixes #552) (Nicholas C. Zakas)
-* Build: Use browserify to create browser-ready ESLint (fixes #119) (Nicholas C. Zakas)
-* Docs: Ensure all rules have entry on top-level rules index page (Nicholas C. Zakas)
-* Docs: Add docs for no-fallthrough rule (Nicholas C. Zakas)
-* Update README.md (Peter deHaan)
-* Update README.md (Peter deHaan)
-* Update package.json (Peter deHaan)
-* Docs: Added documentation for semi rule (Nicholas C. Zakas)
-* Build: Reset branch coverage target (Nicholas C. Zakas)
-* Update build system to generate eslint.org during release (Nicholas C. Zakas)
-* Updated setup doc (Nicholas C. Zakas)
-* Fix #525 & #528 (Mangled Deutz)
-* Improve no-negated-in-lhs description (David Bruant)
-* Fixing typo (David Bruant)
-* Update no-new.md (Tamas Fodor)
-* Update no-extra-semi.md (Tamas Fodor)
-* Fixing broken links in documentation (Ilya Volodin)
-* Update about page (Nicholas C. Zakas)
-* Site generation build step and documentation updates to support it (fixes #478) (Nicholas C. Zakas)
-* Change message for brace-style rule (fixes #490) (Nicholas C. Zakas)
-* Add question about ES6 support to FAQ (fixes #530) (Nicholas C. Zakas)
-* Set unlimited number of listeners for event emitter (fixes #524) (Nicholas C. Zakas)
-* Add support for comment events (fixes #531) Add :after events for comments (Nicholas C. Zakas)
-* Add :after events for comments (Nicholas C. Zakas)
-* Allow config files to have any name (fixes #486). (Aparajita Fishman)
-* List available formatters (fixes #533). (Aparajita Fishman)
-* Add support for comment events (fixes #531) (Nicholas C. Zakas)
-* Add Stylish formatter and make it default. Fixes #517 (Sindre Sorhus)
-* Fix missing code exit (Mangled Deutz)
-* Added unit test for calling Config.getConfig with no arguments. (Aparajita Fishman)
-* Typo (Mangled Deutz)
-* Fixed docs typo (Nicholas C. Zakas)
-* Mark functions as used when any method is called on them (Nicholas C. Zakas)
-* Fixed: Config.getConfig is called either with a file path or with no args (fixes #520) (Aparajita Fishman)
-* Fix minor bug in no-empty rule (Nicholas C. Zakas)
-* add more info for failure messages (Nicholas C. Zakas)
-* Add ruleId to all formatters output (fixes #472) (Nicholas C. Zakas)
-* Remove unused code (Nicholas C. Zakas)
-* Correctly handle case with both finally and catch in no-empty (Nicholas C. Zakas)
-* Update documentation for no-unused-vars (Nicholas C. Zakas)
-* Ensure that bound function expressions are reported as being used (fixes #510) (Nicholas C. Zakas)
-* Allow empty catch/finally blocks (fixes #514) and update documentation (fixes #513) (Nicholas C. Zakas)
-* Updated contribution guidelines (Nicholas C. Zakas)
-* Add default setting for no-cond-assign (Nicholas C. Zakas)
-* Add build step to check rule consistency (Nicholas C. Zakas)
-* update docs: explicit cli args are exempt from eslintignore exclusions (Michael Ficarra)
-* fixes #505: no-cond-assign should ignore doubly parenthesised tests (Michael Ficarra)
-* Renamed unnecessary-strict to no-extra-strict (Nicholas C. Zakas)
-* Fixed missing documentation links (Nicholas C. Zakas)
-* Add build task to check for missing docs and tests for rules (Nicholas C. Zakas)
-* Slight reorganization of rule groups (Nicholas C. Zakas)
-* Added one-var and sorted some rules (Nicholas C. Zakas)
-* Updated Travis badge for new location (Nicholas C. Zakas)
-* fixes #494: allow shebangs in processed JS files (Michael Ficarra)
-* fixes #496: lint ignored files when explicitly specified via the CLI (Michael Ficarra)
-* More tests (Ilya Volodin)
-* Upgrade Istanbul (Ilya Volodin)
-* fixes #495: holey arrays cause no-comma-dangle rule to throw (Michael Ficarra)
-* Documentation and minor changes (Ilya Volodin)
-* Adding missing package registration (Ilya Volodin)
-* Adding support for .eslintignore and .jshintignore (Closes #484) (Ilya Volodin)
-* fixes #482: brace-style bug with multiline conditions (Michael Ficarra)
-* Switching Travis to use ESLint (Closes #462) (Ilya Volodin)
-* 0.2.0 (Nicholas C. Zakas)
-
-v0.2.0 - January 1, 2014
-
-* 0.2.0 (Nicholas C. Zakas)
-* Bump code coverage checks (Nicholas C. Zakas)
-* Take care of unreachable code in case statement (Nicholas C. Zakas)
-* Updated rule messaging and added extra tests (Nicholas C. Zakas)
-* Fixing eslint errors and unittests (Ilya Volodin)
-* Rule: max-nested-callbacks (Ian Christian Myers)
-* Fix fall-through rule with nested switch statements (fixes #430) (Nicholas C. Zakas)
-* Fixed trailing comma (Nicholas C. Zakas)
-* Added more tests for func-style (Nicholas C. Zakas)
-* Fixed documentation for func-style (Nicholas C. Zakas)
-* Fixed linting error (Nicholas C. Zakas)
-* Rule to enforce function style (fixes #460) (Nicholas C. Zakas)
-* Rule is off by default. Updated documentation (Ilya Volodin)
-* Rule: sort variables. Closes #457 (Ilya Volodin)
-* Update architecture.md (Nicholas C. Zakas)
-* Change quotes option to avoid-escapes and update docs (fixes #199) (Brandon Payton)
-* Add allow-avoiding-escaped-quotes option to quotes rule (fixes #199) (Brandon Payton)
-* Update no-empty-class.md (Nicholas C. Zakas)
-* Updated titles on all rule documentation (fixes #348) (Nicholas C. Zakas)
-* Fixing eslint errors in codebase (Ilya Volodin)
-* fixes #464: space-infix-ops checks for VariableDeclarator init spacing (Michael Ficarra)
-* Add options to no-unused-vars. Fixes #367 (Ilya Volodin)
-* rename escape function to xmlEscape in checkstyle formatter (Michael Ficarra)
-* The semi rule now reports correct line number (Ian Christian Myers)
-* context.report now takes optional location (Ian Christian Myers)
-* fixes #454: escape values for XML in checkstyle formatter (Michael Ficarra)
-* Add color to Mocha test reporting (Ian Christian Myers)
-* Rule no-nested-ternary (Ian Christian Myers)
-* Fixing no-unused-var and no-redeclare (Ilya Volodin)
-* fixes #449: no-mixed-requires throws TypeError when grouping is enabled (Michael Ficarra)
-* Fixed reported line number for trailing comma error (Ian Christian Myers)
-* Update doc title for quote (Matthew DuVall)
-* fixes #446: join paths without additional delimiters (Michael Ficarra)
-* docs: add documentation for quotes rule (Matthew DuVall)
-* minor style changes to lib/rules/space-infix-ops.js as requested in #444 (Michael Ficarra)
-* remove "function invalid(){ return D }" from some tests (Michael Ficarra)
-* fixes #429: require spaces around infix operators; enabled by default (Michael Ficarra)
-* simplify fix for #442 (Michael Ficarra)
-* Fix broken test, ensure tests get run before a release is pushed (Nicholas C. Zakas)
-* 0.1.4 (Nicholas C. Zakas)
-
-v0.1.4 - December 5, 2013
-
-* 0.1.4 (Nicholas C. Zakas)
-* Add release scripts to package.json (Nicholas C. Zakas)
-* Fixed release error in Makefile (Nicholas C. Zakas)
-* Fix JSHint warnings (Nicholas C. Zakas)
-* Make sure 'default' isn't flagged by no-space-returns-throw rule (fixes #442) (Nicholas C. Zakas)
-* Fixing documentation (Ilya Volodin)
-* Fixing disabling rules with invalid comments Closes #435 (Ilya Volodin)
-* improve assertion on wrong number of errors (Christoph Neuroth)
-* fixes #431: no-unused-expressions should not flag statement level void (Michael Ficarra)
-* fixes #437: fragile no-extend-native rule (Michael Ficarra)
-* change space-* rule documentation headers to be more descriptive (Michael Ficarra)
-* Moved to tabs, added comments, a few more tests (Jamund Ferguson)
-* split GH-332 rule into space-unary-word-ops and space-return-throw-case (Michael Ficarra)
-* fixes #346: validate strings passed to the RegExp constructor (Michael Ficarra)
-* change some documentation extensions from js to md (Michael Ficarra)
-* fixes #332: unary word operators must be followed by whitespace (Michael Ficarra)
-* Add some docs (Jamund Ferguson)
-* DRYing cli tests and improving code coverage (Ilya Volodin)
-* fixes #371: add no-shadow-restricted-names rule (Michael Ficarra)
-* Added Support for Object.defineProperty() checking (Jamund Ferguson)
-* fixes #333: add rule to disallow gratuitously parenthesised expressions (Michael Ficarra)
-* improve rule test coverage (Michael Ficarra)
-* No Extend Native (Jamund Ferguson)
-* change getTokens 2nd/3rd arguments to count tokens, not characters (Michael Ficarra)
-* fixes #416: no-fallthrough flagging last case + reporting wrong line num (Michael Ficarra)
-* fixes #415: fix unnecessary-strict rule false positives (Michael Ficarra)
-* Add missing dependency (Nicholas C. Zakas)
-* Update docs related to running unit tests (Nicholas C. Zakas)
-* Add JSHint as missing dependency (Nicholas C. Zakas)
-* Switch to using ShellJS makefile (fixes #418) (Nicholas C. Zakas)
-* Updated documentation to reflect test changes (refs #417) (Nicholas C. Zakas)
-* Change to eslintTester.addRuleTest (fixes #417) (Nicholas C. Zakas)
-* Fix false positives for no-script-url (fixes #400) (Nicholas C. Zakas)
-* Fix lint warning (Nicholas C. Zakas)
-* Fixing ESLint warnings, introducing Makefile.js (not yet wired in) (Nicholas C. Zakas)
-* fixes #384: include builtin module list to avoid repl dependency (Michael Ficarra)
-* 0.1.3 (Nicholas C. Zakas)
-
-v0.1.3 - November 25, 2013
-
-* 0.1.3 (Nicholas C. Zakas)
-* Updated changelog (Nicholas C. Zakas)
-* Vows is gone. Mocha is now default (Ilya Volodin)
-* fixes #412: remove last remaining false positives in no-spaced-func (Michael Ficarra)
-* fixes #407: no-spaced-func rule flagging non-argument-list spaced parens (Michael Ficarra)
-* Add no-extra-semi to configuration (fixes #386) (Nicholas C. Zakas)
-* Converting formatter tests and core (Ilya Volodin)
-* Don't output anything when there are no errors in compact formatter (fixes #408) (Nicholas C. Zakas)
-* Removing Node 0.11 test - it fails all the time (Nicholas C. Zakas)
-* Completing conversion of rule's tests to mocha (Ilya Volodin)
-* added mocha conversion tests for strict, quote-props and one-var; enhanced one of the invalid one-var tests that was expecting two messages (Michael Paulukonis)
-
-
-v0.1.2 - November 23, 2013
-
-* 0.1.2 (Nicholas C. Zakas)
-* added mocha tests for radix and quotes; fixed some of the internals on quotes from vows annotations (Michael Paulukonis)
-* added tests for regex-spaces, strict, unnecessary-strict; fixed some types in overview/author notes in other tests. (Michael Paulukonis)
-* Converting unittests to mocha (Ilya Volodin)
-* mocha conversions of tests for 'use-isnan' and 'wrap-iife' (Michael Paulukonis)
-* added mocha tests semi.js and wrap-regex.js (Michael Paulukonis)
-* Converting more tests to mocha (Ilya Volodin)
-* Update CONTRIBUTING.md (Nicholas C. Zakas)
-* Cleaning up eslintTester (Ilya Volodin)
-* DRYing unittests and converting them to mocha (Ilya Volodin)
-* Reformatted Gruntfile (Nicholas C. Zakas)
-* Add tests to config load order: base, env, user. (icebox)
-* Fixing indent in gruntfile (Ilya Volodin)
-* Removing jake, adding Grunt, Travis now runs grunt (Ilya Volodin)
-* Add rules per environments to config. (icebox)
-* Add globals property to the environments. (icebox)
-* Fix error about IIFE if the function is in a new (Marsup)
-* Fix a broken link in the docs (Brian J Brennan)
-* Add test coverage for additional cases, fix open paren at beginning of expr (Matthew DuVall)
-* Fixing no-undef for eval use case (Ilya Volodin)
-* fixes #372: disallow negated left operand in `in` operator (Michael Ficarra)
-* Fixing no-self-compare rule to check for operator (Ilya Volodin)
-* bug: open parens in args causes no-spaced-func to trigger (Matthew DuVall)
-* fixes #369: restrict UnaryExpressions to delete in no-unused-expressions (Michael Ficarra)
-* Make sure delete operator isn't flagged as unused expression (fixes #364) (Nicholas C. Zakas)
-* Don't flag ++ or -- as unused expressions (fixes #366) (Nicholas C. Zakas)
-* Ensure that 'use strict' isn't flagged as an unused expression (fixes #361) (Nicholas C. Zakas)
-* Increase test coverage for strict-related rules (refs #361) (Nicholas C. Zakas)
-* Up code coverage numbers (Nicholas C. Zakas)
-* Fixes error in new-cap rule when 'new' is used without a constructor (fixes #360) (Nicholas C. Zakas)
-* added files array in package json (Christian)
-* removed unused jshint dependency (Christian)
-* Add test coverage for new Foo constructor usage (Matt DuVall)
-* Pull code coverage up by removing unused method (Matt DuVall)
-* recognise CallExpression variant of RegExp ctor in no-control-regex rule (Michael Ficarra)
-* Merge smart-eqeqeq into eqeqeq (Matt DuVall)
-* Catch additional cases for a.b, new F, iife (Matt DuVall)
-* 0.2.0-dev (Nicholas C. Zakas)
-* Version 0.1.0 (Nicholas C. Zakas)
-* rule: no-spaced-func disallow spaces between function identifier and application (Matt DuVall)
-
-v0.1.1 - November 09, 2013
-
-* Ensure mergeConfigs() doesn't thrown an error when keys are missing in base config (fixes #358) (Nicholas C. Zakas)
-
-v0.1.0 - November 03, 2013
-
-* Version 0.1.0 (Nicholas C. Zakas)
-* Updated Readme for v0.1.0 (Nicholas C. Zakas)
-* Bump code coverage verification to 95% across the board (Nicholas C. Zakas)
-* Fixed broken links (Nicholas C. Zakas)
-* Added information about runtime rules (Nicholas C. Zakas)
-* Added documentation about configuration files (Nicholas C. Zakas)
-* Added description of -v option (Nicholas C. Zakas)
-* Updated architecture documentation (Nicholas C. Zakas)
-* Fix bug in no-control-regex (fixes #347) (Nicholas C. Zakas)
-* Fix link to architecture doc in readme (azu)
-* Rule: No control characters in regular expressions (fixes #338) (Nicholas C. Zakas)
-* Add escaping \= test (Matt DuVall)
-* Add docs for rule (Matt DuVall)
-* rule: no-div-regex for catching ambiguous division operators in regexes (Matt DuVall)
-* Change context-var to block-scoped-var (Matt DuVall)
-* Implement config.globals (Oleg Grenrus)
-* Add 'config-declared global' test (Oleg Grenrus)
-* Adding ability to separate rules with comma (Ilya Volodin)
-* Added rule for missing 'use strict' (fixes #321) (Nicholas C. Zakas)
-* Fixing unittests and finishing code (Ilya Volodin)
-* Disabling/enabling rules through comments (Ilya Volodin)
-* Rename rule to context-var and add documentation (Matt DuVall)
-* Added link to no-global-strict doc in readme (Nicholas C. Zakas)
-* Add try-catch scoping with tests (Matt DuVall)
-* Fix linting error (Matt DuVall)
-* Store FunctionDeclarations in scope as they can be used as literals (Matt DuVall)
-* Fix to use getTokens and add test for MemberExpression usage (Matt DuVall)
-* rule: block-scope-var to check for variables declared in block-scope (Matt DuVall)
-* no-unused-expressions rule: add test and doc mention for `a && b()` (Michael Ficarra)
-* rule: wrap-regex for parens around regular expression literals (Matt DuVall)
-* fixes #308: implement no-unused-expressions rule; ref. jshint rule W030 (Michael Ficarra)
-* Updated change log script to filter out merge messages (Nicholas C. Zakas)
-* Updated changelog (Nicholas C. Zakas)
-* 0.1.0-dev (Nicholas C. Zakas)
-
-v0.0.9 - October 5, 2013
-
-* Version 0.0.9 release (Nicholas C. Zakas)
-* Added rule for no global strict mode (fixes #322) (Nicholas C. Zakas)
-* Change default on to be errors instead of warnings (fixes #326) (Nicholas C. Zakas)
-* Fixed bug where JSHint was using the wrong file in lint task (Nicholas C. Zakas)
-* Updated docs for no-unused vars rule. (Andrew de Andrade)
-* Removed console.log in tests. (Andrew de Andrade)
-* Added link to roadmap and JSHint feature parity list. (Andrew de Andrade)
-* Fixed warning when unused var declared as param in FunctionExpression/Declaration can be ignored because later param is used (Andrew de Andrade)
-* Rename test for smartereqeqeq.js to smarter-eqeqeq.js (Andrew de Andrade)
-* Keep test filename inline with rule name (Andrew de Andrade)
-* Added further instructions for multiline test cases. (Andrew de Andrade)
-* Protecting private method (Seth McLaughlin)
-* Updating look up algorithm for local config files (Seth McLaughlin)
-* Fixing ESLint errors (Ilya Volodin)
-* Implemented local default config file (Seth McLaughlin)
-* Upgrading escope version and fixing related bugs (Ilya Volodin)
-* Fixing assignment during initialization issue (Ilya Volodin)
-* add plain-English regexp description to no-empty-class rule (Michael Ficarra)
-* fixes #289: no-empty-class flags regexps with... flags (Michael Ficarra)
-* Rule: no-catch-shadow (Ian Christian Myers)
-* Update no-empty for compatibility with esprima@1.0.4 (fixes #290) (Mark Macdonald)
-* Fixing bug with _ in MemberExpression (Ilya Volodin)
-* Rule: no-func-assign (Ian Christian Myers)
-* Fix false warning from no-undef rule (fixes #283) (Mark Macdonald)
-* Adding eslint to jake (Ilya Volodin)
-* Rule no redeclare (Ilya Volodin)
-* Fixing no use before define issues (Ilya Volodin)
-* Rule: no-octal-escape (Ian Christian Myers)
-* Fix for `no-proto` and `no-iterator` false positive (Ian Christian Myers)
-* Rule: no-iterator (Ian Christian Myers)
-* Fixing type in guard-for-in documentation (Ilya Volodin)
-* Rule No use before define (Ilya Volodin)
-* Added documentation for the `no-new` rule (Ian Christian Myers)
-* Added documentation for the `no-eval` rule (Ian Christian Myers)
-* Added documentation for the `no-caller` rule (Ian Christian Myers)
-* Added documentation for the `no-bitwise` rule (Ian Christian Myers)
-* simplify no-empty-class rule (Michael Ficarra)
-* Fix `no-empty-class` false negatives (Ian Christian Myers)
-* Added documentation for the `no-alert` rule (Ian Christian Myers)
-* Added documentation for the `new-parens` rule (Ian Christian Myers)
-* Added documentation for the `max-params` rule (Ian Christian Myers)
-* Added documentation for `max-len` rule (Ian Christian Myers)
-* Created link from rules README.md to no-plusplus.md documentation (Ian Christian Myers)
-* Added documentation for `guard-for-in` rule (Ian Christian Myers)
-* Added documentation for `dot-notation` rule (Ian Christian Myers)
-* Added documentation for `curly` rule (Ian Christian Myers)
-* Updated `camelcase` rule documentation (Ian Christian Myers)
-* Added documentation for `complexity` rule (Ian Christian Myers)
-* Changed `no-dangle` documentation to `no-comma-dangle` (Ian Christian Myers)
-* Rule: no-empty-class (Ian Christian Myers)
-* Increased test coverage for max-depth (Ian Christian Myers)
-* Increased test coverage for no-shadow (Ian Christian Myers)
-* Increased test coverage on no-mixed-requires (Ian Christian Myers)
-* Added docs for eqeqeq and no-with (fixes #262) (Raphael Pigulla)
-* Create camelcase.md (Micah Eschbacher)
-* Fix issues with function in no-unused-vars (Ilya Volodin)
-* Rule: No shadow (Ilya Volodin)
-* fixes #252: semi rule errors on VariableDeclarations in ForInStatements (Michael Ficarra)
-* rule: max-len to lint maximum length of a line (Matt DuVall)
-* Fixes #249 (Raphael Pigulla)
-* Merge branch 'master' of https://github.com/beardtwizzle/eslint (Jonathan Mahoney)
-* Re-add lines that were accidentally deleted from config (Jonathan Mahoney)
-* Add support for pre-defined environment globals (re: #228) (Jonathan Mahoney)
-* Rule: no-else-return (Ian Christian Myers)
-* Re-add lines that were accidentally deleted from config (Jonathan Mahoney)
-* Add support for pre-defined environment globals (re: #228) (Jonathan Mahoney)
-* Fix no-unused-vars to report correct line numbers (Ilya Volodin)
-* Rule: no proto (Ilya Volodin)
-* Rule: No Script URL (Ilya Volodin)
-* Rule: max-depth (Ian Christian Myers)
-* Fix: Error severity for rules with options. (Ian Christian Myers)
-* Rule: No wrap func (Ilya Volodin)
-* bug: Fixes semi rule for VariableDeclaration in ForStatement (Matt DuVall)
-* Individual perf tests for rules (Ilya Volodin)
-* Fix loading rules from a rules directory (Ian Christian Myers)
-* Rule no-mixed-requires (fixes #221) (Raphael Pigulla)
-* bug: Add ForStatement for no-cond-assign check (Matthew DuVall)
-* JSLint XML formatter now escapes special characters in the evidence and reason attributes. (Ian Christian Myers)
-* Formatter: JSLint XML (Ian Christian Myers)
-* Refactored `max-statements` rule. (Ian Christian Myers)
-* Fix tests broken due to new rule message text (James Allardice)
-* Merge branch 'master' into match-jshint-messages (James Allardice)
-* Refactored `one-var` rule. (Ian Christian Myers)
-* split eslint.define into eslint.defineRule and eslint.defineRules (Michael Ficarra)
-* Removed unnecessary rules.js test. (Ian Christian Myers)
-* Rule: one-var (Ian Christian Myers)
-* Rule: No unused variables (Ilya Volodin)
-* expose interface for defining new rules at runtime without fs access (Michael Ficarra)
-* disallow 00 in no-octal rule (Michael Ficarra)
-* Increased test coverage for `lib/cli.js`. (Ian Christian Myers)
-* Increased test coverage for `lib/rules.js` (Ian Christian Myers)
-* Increased test coverage for jUnit formatter. (Ian Christian Myers)
-* scripts/bundle: output bundle+map to /build directory (Michael Ficarra)
-* add test for 0X... hex literals in no-octal tests (Michael Ficarra)
-* fixes #200: no-octals should not see leading-0 floats as violations (Michael Ficarra)
-* add back tests for loading rules from a directory (Michael Ficarra)
-* add back in ability to load rules from a directory (Michael Ficarra)
-* Increased test coverage for `complexity` rule. (Ian Christian Myers)
-* Increased test coverage for `max-params` rule. (Ian Christian Myers)
-* also output source map when generating bundle (Michael Ficarra)
-* Rule: unnecessary-strict (Ian Christian Myers)
-* Improve performance of getTokens (Ilya Volodin)
-* Performance jake task (Ilya Volodin)
-* don't force explicit listing of rules; generate listing for bundle (Michael Ficarra)
-* Rule: no-dupe-keys (Ian Christian Myers)
-* fixes #145: create a browser bundle (Michael Ficarra)
-* Fixing no-caller bug (Ilya Volodin)
-* Check for use of underscore library as an exception for var declarations (Matthew DuVall)
-* Merge branch 'master' of https://github.com/nzakas/eslint into no-underscore-dangle (Matthew DuVall)
-* Fixing spelling (Ilya Volodin)
-* Rule: no-empty-label (Ilya Volodin)
-* Add builtin globals to the global scope (fixes #185) (Mark Macdonald)
-* Rule: no-loop-func (Ilya Volodin)
-* Merge branch 'master' of https://github.com/nzakas/eslint into no-underscore-dangle (Matt DuVall)
-* Use proper node declarations and __proto__ exception (Matt DuVall)
-* Updating no-undef patch (see pull request #164) - Simplify parseBoolean() - Make knowledge of```/*jshint*/``` and ```/*global */``` internal to eslint object - Put user-declared globals in Program scope (Mark Macdonald)
-* Rule: no-eq-null (Ian Christian Myers)
-* fixed broken merge (Raphael Pigulla)
-* fixes #143 (Raphael Pigulla)
-* added consistent-this rule (Raphael Pigulla)
-* Rule: no-sync to encourage async usage (Matt DuVall)
-* Update eslint.json with no-underscore-dangle rule (Matt DuVall)
-* Rule: no-underscore-dangle for func/var declarations (Matt DuVall)
-* Warn on finding the bitwise NOT operator (James Allardice)
-* Updating no-undef patch (see pull request #164) 3. Move parsing of ```/*global */``` and ```/*jshint */``` to eslint.js (Mark Macdonald)
-* Warn on finding a bitwise shift operator (fixes #170) (James Allardice)
-* Fix broken test (James Allardice)
-* Add support for the do-while statement to the curly rule (closes #167) (James Allardice)
-* Removing nasty leading underscores (Patrick Brosset)
-* Added tests and test cases for a few files (Patrick Brosset)
-* CLI: -f now accepts a file path (Ian Christian Myers)
-* Updating no-undef patch (see pull request #164) 1. Move predefined globals to ```conf/environments.json``` 2. Move mixin() to ```lib/util.js``` (Mark Macdonald)
-* Match messages to JS[LH]int where appropriate, and ensure consistent message formatting (closes #163) (James Allardice)
-* Add support for the do-while statement to the curly rule (closes #167) (James Allardice)
-* Removing nasty leading underscores (Patrick Brosset)
-* Added tests and test cases for a few files (Patrick Brosset)
-* Merge branch 'master' of github.com:nzakas/jscheck (Nicholas C. Zakas)
-* Added acceptance criteria for rules to docs (Nicholas C. Zakas)
-* Add no-undef (fixes #6) (Mark Macdonald)
-* Fixing no-self-compare (Ilya Volodin)
-* Rule: No multiline strings (Ilya Volodin)
-* CLI refactor to remove process.exit(), file not found now a regular error message, updated formatters to handle this case (Nicholas C. Zakas)
-* Rule: no-self-compare (Ilya Volodin)
-* Rule: No unnecessary semicolons (fixes #158) (Nicholas C. Zakas)
-* Fixed error in no-ex-assign when return statement as found in catch clause (Nicholas C. Zakas)
-* Rename no-exc-assign to no-ex-assign and add to config (Nicholas C. Zakas)
-* Renamed count-spaces to regex-spaces (Nicholas C. Zakas)
-* Documentation updates (Nicholas C. Zakas)
-* Put all rules into strict mode and update docs accordingly (Nicholas C. Zakas)
-* Merge branch 'master' of github.com:nzakas/jscheck (Nicholas C. Zakas)
-* Ensure getScope() works properly when called from Program node (fixes #148) (Nicholas C. Zakas)
-* Rule: wrap-iife (Ilya Volodin)
-* add additional test for no-cond-assign rule (Stephen Murray)
-* Merge branch 'master' of github.com:nzakas/jscheck (Nicholas C. Zakas)
-* Experimental support for Jake as a build system (fixes #151) (Nicholas C. Zakas)
-* fixes #152 (Stephen Murray)
-* add docs for no-exc-assign (Stephen Murray)
-* Merge branch 'master' of https://github.com/nzakas/eslint into no-new-object-array-literals (Matt DuVall)
-* Merge branch 'master' of https://github.com/nzakas/eslint into count-spaces (Matt DuVall)
-* Added a test for getting global scope from Program node (refs #148) (Nicholas C. Zakas)
-* Add positive test case for `object.Array` (Matthew DuVall)
-* Only support space characters for repetitions (Matthew DuVall)
-* fix line length per code conventions (Stephen Murray)
-* fix indentation per code conventions (Stephen Murray)
-* fixes #149 (Stephen Murray)
-* Rule: no-ternary (Ian Christian Myers)
-* Check that the return statement has an argument before checking its type (James Allardice)
-* Rule: count-spaces for multiple spaces in regular expressions (Matt DuVall)
-* Update eslint.json configuration file for literal rules (Matt DuVall)
-* Created no-label-var rule. (Ian Christian Myers)
-* Rule: no-new-array and no-new-object (Matt DuVall)
-* Added ability to retrieve scope using escope. (Ian Christian Myers)
-* Corrected unused arguments (Patrick Brosset)
-* Reporting function complexity on function:after and using array push/pop to handle nesting (Patrick Brosset)
-* Fixing style issues discovered while npm testing (Patrick Brosset)
-* First draft proposal for a cyclomatic complexity ESLint rule (Patrick Brosset)
-* Corrected file extension on no-plusplus rule documentation. (Ian Christian Myers)
-* Documentation for no-delete-var rule. Closes #129 (Ilya Volodin)
-* Rule: max-statements (Ian Christian Myers)
-* Better documentation for the `no-plusplus` rule. (Ian Christian Myers)
-* Rule: no-plusplus (Ian Christian Myers)
-* Rule: no assignment in return statement (Ilya Volodin)
-* Updating max-params rule name (Ilya Volodin)
-* Rule: Function has too many parameters (Ilya Volodin)
-* Removing merge originals (Ilya Volodin)
-* Rebasing on master (Ilya Volodin)
-* Rule: Variables should not be deleted (Ilya Volodin)
-* Fixes incorrect reporting of missing semicolon (Ian Christian Myers)
-* Rebase against master branch (Mathias Bynens)
-* Rule to warn on use of Math and JSON as functions (James Allardice)
-* Formatter: Checkstyle (Ian Christian Myers)
-* docs: Clean up structure (Mathias Bynens)
-* Merging no-native-reassign and no-redefine (Ilya Volodin)
-* Rule: no native reassignment (Ilya Volodin)
-* 0.0.8-dev (Nicholas C. Zakas)
-* v0.0.7 released (Nicholas C. Zakas)
-* Updated Tests, etc. (Jamund Ferguson)
-* Added jUnit Support (Fixes #16) (Jamund Ferguson)
-
-v0.0.7 - July 22, 2013
-
-* 0.0.7 (Nicholas C. Zakas)
-* Add code coverage checks to npm test and update rule tests to have better coverage (Nicholas C. Zakas)
-* Fixed CLI output on serial programatic executions (Ian Christian Myers)
-* Removes line length from code style convention docs (Josh Perez)
-* Adds escapeRegExp and fixes documentation (Josh Perez)
-* Add quotes rule and test coverage for configuration options (Matt DuVall)
-* Adds templating for lint messages and refactors rules to use it (Josh Perez)
-* Fixes lint rules for unchecked test file (Josh Perez)
-* Changes dotnotation rule to match JSHint style (Josh Perez)
-* Change configInfo to options and add test coverage (Matt DuVall)
-* Merge branch 'master' of https://github.com/nzakas/eslint into optional-args-for-rule (Matt DuVall)
-* Adds dot notation lint rule (Josh Perez)
-* Strip trailing underscores in camelcase rule - Fixes #94 (Patrick Brosset)
-* add mailing list link (Douglas Campos)
-* Strip leading underscores in camelcase rule - Fixes #94 (Patrick Brosset)
-* Created no-dangle rule. (Ian Christian Myers)
-* Fixed rule name (James Allardice)
-* Make sure the callee type is Identifier (James Allardice)
-* Add rule for implied eval via setTimeout/Interval (James Allardice)
-* Fix rule name in config (James Allardice)
-* Fixes #90 -- updates docstrings (Stephen Murray)
-* Fixes issue with fs.existsSync on NodeJS 0.6 (Ian Christian Myers)
-* Fixing -c config option. (Ian Christian Myers)
-* Allow arrays to be passed as multiple args to rule (Matt DuVall)
-* Test to make sure empty case with one line break is safe (Matt DuVall)
-* Rule: The Function constructor is eval (Ilya Volodin)
-* Enabled require("eslint") and exposed out CLI. (Ian Christian Myers)
-* Adds test and fix for issue #82 (Mark Macdonald)
-* Merge branch 'master' of https://github.com/nzakas/eslint into ok (Yusuke Suzuki)
-* Created brace-style rule. (Ian Christian Myers)
-* Formatters can now process multiple files at once (Jamund Ferguson)
-* Rule: Do not use 'new' for side effects (Ilya Volodin)
-* Adds smarter-eqeqeq rule (Josh Perez)
-* Add EditorConfig file for consistent editor/IDE behavior (Jed Hunsaker)
-* Fix the positive case for no-unreachable where there is no return statement at all, or if the return is at the end. Those cases should not return any errors. The error condition was not be checked before throwing the rule error. (Joel Feenstra)
-* Adds test and fix for no-octal on 0 literal (Mark Macdonald)
-* Don't report no-empty warnings when a parent is FunctionExpression / FunctionDeclaration (Yusuke Suzuki)
-* Add api.getAncestors (Yusuke Suzuki)
-* Ensure estraverse version 1.2.0 or later (Yusuke Suzuki)
-* Fixes no-alert lint rule for non identifier calls (Josh Perez)
-* Fixes exception when init is null (Josh Perez)
-* Fixes no-octal check to only check for numbers (Josh Perez)
-* 0.0.7-dev (Nicholas C. Zakas)
-* 0.0.6 (Nicholas C. Zakas)
-* Follow the rule naming conventions (James Allardice)
-* Add rule for missing radix argument to parseInt (James Allardice)
-* Allow return, falls-through comment, and throw for falls-through (Matt DuVall)
-* Merge branch 'master' of https://github.com/nzakas/eslint into rule-fall-through (Matt DuVall)
-* Globals are not good, declare len (Matt DuVall)
-* Rule to add no-fall-through (Matt DuVall)
-
-v0.0.6 - July 16, 2013
-
-* 0.0.6 (Nicholas C. Zakas)
-* Changed semi rule to use tokens instead of source (Nicholas C. Zakas)
-* Renaming new-parens rule (Ilya Volodin)
-* Renaming no-new-wrappers rule and adding tests (Ilya Volodin)
-* Add license URL (Nick Schonning)
-* Remove unused sinon requires (Nick Schonning)
-* Remove redundant JSHint directives (Nick Schonning)
-* Rule: Do not use constructor for wrapper objects (Ilya Volodin)
-* Test node 0.11 unstable but allow it to fail (Nick Schonning)
-* Rule: Constructor should use parentheses (Ilya Volodin)
-* Fix reference to "CSS Lint" in Contributing documentation (Brian McKenna)
-* Add git attributes file for line endings (Andy Hu)
-* Rename to create an 'index' file in GH web view (Evan Goer)
-* Avoid accidentally creating a markdown link (Evan Goer)
-* Add headings and correct internal links (Evan Goer)
-* Add wiki files to docs directory (Evan Goer)
-* Add rules for leading/trailing decimal points (James Allardice)
-* Add rule to prevent comparisons with value NaN (James Allardice)
-* Fixing jshint error (Ilya Volodin)
-* Rule: no octal literals (Ilya Volodin)
-* Rule: no undefined when initializing variables (Ilya Volodin)
-* Updated CONTRIBUTING.md (Nicholas C. Zakas)
-* Make sure namespaces are honored in new-cap (Nicholas C. Zakas)
-* Make sure no-empty also checks for ';;' (Nicholas C. Zakas)
-* Add CLI option to output version (Nicholas C. Zakas)
-* Updated contribution guidelines (Nicholas C. Zakas)
-* Fixing jshint complaints. (Joel Feenstra)
-* Converting to a switch statement and declaring variables. (Joel Feenstra)
-* Added .jshintrc file (until ESLint can lint itself) and cleaned up JSHint warnings (Nicholas C. Zakas)
-* Merge branch 'master' of github.com:nzakas/jscheck (Nicholas C. Zakas)
-* A bit of cleanup (Nicholas C. Zakas)
-* Add unreachable code detection for switch cases and after continue/break. (Joel Feenstra)
-* Add support for detecting unreachable code after a throw or return statement. (Joel Feenstra)
-* Fix curly brace check when an if statement is the alternate. (Joel Feenstra)
-* Check for empty switch statements with no cases. (Matt DuVall)
-* Added CONTRIBUTING.md (Nicholas C. Zakas)
-* Added rule to check for missing semicolons (fixes #9) (Nicholas C. Zakas)
-* Verify that file paths exist before reading the file (Matt DuVall)
-* Added guard-for-in rule (fixes #1) (Nicholas C. Zakas)
-* Run linting with npm test as well (Nicholas C. Zakas)
-* Removed foo.txt (Nicholas C. Zakas)
-* Updated config file with new no-caller ID (Nicholas C. Zakas)
-* Changed name of no-arg to no-caller (Nicholas C. Zakas)
-* Increased test coverage (Nicholas C. Zakas)
-* Got npm test to work with istanbul, huzzah\! (Nicholas C. Zakas)
-* Moved /config to /conf (Nicholas C. Zakas)
-* Added script to auto-generate changelog (Nicholas C. Zakas)
-* Add `quote-props` rule (Mathias Bynens)
-* Cleaned up relationship between bin/eslint, lib/cli.js, and lib/eslint.js (Nicholas C. Zakas)
-* Add problem count to compact formatter (Nicholas C. Zakas)
-* Fix merge conflict (Nicholas C. Zakas)
-* Change reporters to formatters, add format command line option. Also added tests for compact format. (Nicholas C. Zakas)
-* Change reporters to formatters, add format command line option (Nicholas C. Zakas)
-* Start development of 0.0.6-dev (Nicholas C. Zakas)
diff --git a/tools/eslint/LICENSE b/tools/eslint/LICENSE
index 777939e8fc1a7f..7fe552a8661505 100644
--- a/tools/eslint/LICENSE
+++ b/tools/eslint/LICENSE
@@ -1,4 +1,3 @@
-ESLint
Copyright JS Foundation and other contributors, https://js.foundation
Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/tools/eslint/README.md b/tools/eslint/README.md
index 1ccdbb9bfd4262..7fb4fa343af06e 100644
--- a/tools/eslint/README.md
+++ b/tools/eslint/README.md
@@ -5,6 +5,7 @@
[![Downloads][downloads-image]][downloads-url]
[](https://www.bountysource.com/trackers/282608-eslint?utm_source=282608&utm_medium=shield&utm_campaign=TRACKER_BADGE)
[](https://gitter.im/eslint/eslint?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+[](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Feslint%2Feslint?ref=badge_shield)
# ESLint
@@ -13,7 +14,7 @@
[Rules](http://eslint.org/docs/rules/) |
[Contributing](http://eslint.org/docs/developer-guide/contributing) |
[Reporting Bugs](http://eslint.org/docs/developer-guide/contributing/reporting-bugs) |
-[Code of Conduct](https://js.foundation/conduct/) |
+[Code of Conduct](https://js.foundation/community/code-of-conduct) |
[Twitter](https://twitter.com/geteslint) |
[Mailing List](https://groups.google.com/group/eslint) |
[Chat Room](https://gitter.im/eslint/eslint)
@@ -123,7 +124,7 @@ These folks keep the project moving and are resources for help.
* Michael Ficarra ([@michaelficarra](https://github.com/michaelficarra))
* Mark Pedrotti ([@pedrottimark](https://github.com/pedrottimark))
* Oleg Gaidarenko ([@markelog](https://github.com/markelog))
-* Mike Sherov [@mikesherov](https://github.com/mikesherov))
+* Mike Sherov ([@mikesherov](https://github.com/mikesherov))
* Henry Zhu ([@hzoo](https://github.com/hzoo))
* Marat Dulin ([@mdevils](https://github.com/mdevils))
* Alexej Yaroshevich ([@zxqfox](https://github.com/zxqfox))
@@ -172,6 +173,10 @@ ESLint follows [semantic versioning](http://semver.org). However, due to the nat
According to our policy, any minor update may report more errors than the previous release (ex: from a bug fix). As such, we recommend using the tilde (`~`) in `package.json` e.g. `"eslint": "~3.1.0"` to guarantee the results of your builds.
+## License
+
+[](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Feslint%2Feslint?ref=badge_large)
+
## Frequently Asked Questions
### How is ESLint different from JSHint?
@@ -205,7 +210,7 @@ Yes, ESLint natively supports parsing JSX syntax (this must be enabled in [confi
### What about ECMAScript 6 support?
-ESLint has full support for ECMAScript 6. By default, this support is off. You can enable ECMAScript 6 support through [configuration](http://eslint.org/docs/user-guide/configuring).
+ESLint has full support for ECMAScript 6. By default, this support is off. You can enable ECMAScript 6 syntax and global variables through [configuration](http://eslint.org/docs/user-guide/configuring).
### What about experimental features?
diff --git a/tools/eslint/bin/eslint.js b/tools/eslint/bin/eslint.js
index bf534971f24d9b..2b5d4e7fe89944 100755
--- a/tools/eslint/bin/eslint.js
+++ b/tools/eslint/bin/eslint.js
@@ -61,14 +61,12 @@ if (useStdIn) {
} else if (init) {
const configInit = require("../lib/config/config-initializer");
- configInit.initializeConfig(err => {
- if (err) {
- process.exitCode = 1;
- console.error(err.message);
- console.error(err.stack);
- } else {
- process.exitCode = 0;
- }
+ configInit.initializeConfig().then(() => {
+ process.exitCode = 0;
+ }).catch(err => {
+ process.exitCode = 1;
+ console.error(err.message);
+ console.error(err.stack);
});
} else {
process.exitCode = cli.execute(process.argv);
diff --git a/tools/eslint/conf/config-schema.json b/tools/eslint/conf/config-schema.json
new file mode 100644
index 00000000000000..c3676bde92523b
--- /dev/null
+++ b/tools/eslint/conf/config-schema.json
@@ -0,0 +1,15 @@
+{
+ "type": "object",
+ "properties": {
+ "root": { "type": "boolean" },
+ "globals": { "type": ["object"] },
+ "parser": { "type": ["string", "null"] },
+ "env": { "type": "object" },
+ "plugins": { "type": ["array"] },
+ "settings": { "type": "object" },
+ "extends": { "type": ["string", "array"] },
+ "rules": { "type": "object" },
+ "parserOptions": { "type": "object" }
+ },
+ "additionalProperties": false
+}
diff --git a/tools/eslint/conf/cli-options.js b/tools/eslint/conf/default-cli-options.js
similarity index 91%
rename from tools/eslint/conf/cli-options.js
rename to tools/eslint/conf/default-cli-options.js
index b377f3da7f391e..6dfdb54421a393 100644
--- a/tools/eslint/conf/cli-options.js
+++ b/tools/eslint/conf/default-cli-options.js
@@ -12,11 +12,9 @@ module.exports = {
useEslintrc: true,
envs: [],
globals: [],
- rules: {},
extensions: [".js"],
ignore: true,
ignorePath: null,
- parser: "", // must be empty
cache: false,
// in order to honor the cacheFile option if specified
diff --git a/tools/eslint/conf/default-config-options.js b/tools/eslint/conf/default-config-options.js
new file mode 100644
index 00000000000000..63d28c48b66d0b
--- /dev/null
+++ b/tools/eslint/conf/default-config-options.js
@@ -0,0 +1,33 @@
+/**
+ * @fileoverview Default config options
+ * @author Teddy Katz
+ */
+
+"use strict";
+
+/**
+ * Freezes an object and all its nested properties
+ * @param {Object} obj The object to deeply freeze
+ * @returns {Object} `obj` after freezing it
+ */
+function deepFreeze(obj) {
+ if (obj === null || typeof obj !== "object") {
+ return obj;
+ }
+
+ Object.keys(obj).map(key => obj[key]).forEach(deepFreeze);
+ return Object.freeze(obj);
+}
+
+module.exports = deepFreeze({
+ env: {},
+ globals: {},
+ rules: {},
+ settings: {},
+ parser: "espree",
+ parserOptions: {
+ ecmaVersion: 5,
+ sourceType: "script",
+ ecmaFeatures: {}
+ }
+});
diff --git a/tools/eslint/conf/eslint-all.js b/tools/eslint/conf/eslint-all.js
index 28d745a9210c7b..43db54fb718723 100644
--- a/tools/eslint/conf/eslint-all.js
+++ b/tools/eslint/conf/eslint-all.js
@@ -10,7 +10,8 @@
//------------------------------------------------------------------------------
const load = require("../lib/load-rules"),
- rules = require("../lib/rules");
+ Rules = require("../lib/rules");
+const rules = new Rules();
//------------------------------------------------------------------------------
// Helpers
diff --git a/tools/eslint/conf/eslint-recommended.js b/tools/eslint/conf/eslint-recommended.js
index 63c2fc770d214a..0d8d19e447d42c 100755
--- a/tools/eslint/conf/eslint-recommended.js
+++ b/tools/eslint/conf/eslint-recommended.js
@@ -10,15 +10,14 @@
/* eslint-disable sort-keys */
module.exports = {
- parser: "espree",
- ecmaFeatures: {},
-
rules: {
/* eslint-enable sort-keys */
"accessor-pairs": "off",
+ "array-bracket-newline": "off",
"array-bracket-spacing": "off",
"array-callback-return": "off",
+ "array-element-newline": "off",
"arrow-body-style": "off",
"arrow-parens": "off",
"arrow-spacing": "off",
@@ -43,6 +42,7 @@ module.exports = {
"dot-notation": "off",
"eol-last": "off",
"eqeqeq": "off",
+ "for-direction": "off",
"func-call-spacing": "off",
"func-name-matching": "off",
"func-names": "off",
@@ -55,6 +55,7 @@ module.exports = {
"id-length": "off",
"id-match": "off",
"indent": "off",
+ "indent-legacy": "off",
"init-declarations": "off",
"jsx-quotes": "off",
"key-spacing": "off",
@@ -80,11 +81,12 @@ module.exports = {
"no-array-constructor": "off",
"no-await-in-loop": "off",
"no-bitwise": "off",
+ "no-buffer-constructor": "off",
"no-caller": "off",
"no-case-declarations": "error",
"no-catch-shadow": "off",
"no-class-assign": "error",
- "no-compare-neg-zero": "off",
+ "no-compare-neg-zero": "error",
"no-cond-assign": "error",
"no-confusing-arrow": "off",
"no-console": "error",
@@ -202,7 +204,7 @@ module.exports = {
"no-useless-computed-key": "off",
"no-useless-concat": "off",
"no-useless-constructor": "off",
- "no-useless-escape": "off",
+ "no-useless-escape": "error",
"no-useless-rename": "off",
"no-useless-return": "off",
"no-var": "off",
@@ -212,7 +214,7 @@ module.exports = {
"no-with": "off",
"nonblock-statement-body-position": "off",
"object-curly-newline": "off",
- "object-curly-spacing": ["off", "never"],
+ "object-curly-spacing": "off",
"object-property-newline": "off",
"object-shorthand": "off",
"one-var": "off",
@@ -220,6 +222,7 @@ module.exports = {
"operator-assignment": "off",
"operator-linebreak": "off",
"padded-blocks": "off",
+ "padding-line-between-statements": "off",
"prefer-arrow-callback": "off",
"prefer-const": "off",
"prefer-destructuring": "off",
@@ -238,6 +241,7 @@ module.exports = {
"rest-spread-spacing": "off",
"semi": "off",
"semi-spacing": "off",
+ "semi-style": "off",
"sort-imports": "off",
"sort-keys": "off",
"sort-vars": "off",
@@ -248,6 +252,7 @@ module.exports = {
"space-unary-ops": "off",
"spaced-comment": "off",
"strict": "off",
+ "switch-colon-spacing": "off",
"symbol-description": "off",
"template-curly-spacing": "off",
"template-tag-spacing": "off",
diff --git a/tools/eslint/lib/api.js b/tools/eslint/lib/api.js
index 664e9a5b40ee95..0a0832a47645d3 100644
--- a/tools/eslint/lib/api.js
+++ b/tools/eslint/lib/api.js
@@ -5,8 +5,11 @@
"use strict";
+const Linter = require("./linter");
+
module.exports = {
- linter: require("./eslint"),
+ linter: new Linter(),
+ Linter,
CLIEngine: require("./cli-engine"),
RuleTester: require("./testers/rule-tester"),
SourceCode: require("./util/source-code")
diff --git a/tools/eslint/lib/ast-utils.js b/tools/eslint/lib/ast-utils.js
index 0f2f3d6af539e3..98775f5ef0c274 100644
--- a/tools/eslint/lib/ast-utils.js
+++ b/tools/eslint/lib/ast-utils.js
@@ -10,6 +10,7 @@
//------------------------------------------------------------------------------
const esutils = require("esutils");
+const espree = require("espree");
//------------------------------------------------------------------------------
// Helpers
@@ -27,6 +28,7 @@ const thisTagPattern = /^[\s*]*@this/m;
const COMMENTS_IGNORE_PATTERN = /^\s*(?:eslint|jshint\s+|jslint\s+|istanbul\s+|globals?\s+|exported\s+|jscs)/;
const LINEBREAKS = new Set(["\r\n", "\r", "\n", "\u2028", "\u2029"]);
const LINEBREAK_MATCHER = /\r\n|[\r\n\u2028\u2029]/;
+const SHEBANG_MATCHER = /^#!([^\r\n]+)/;
// A set of node types that can contain a list of statements
const STATEMENT_LIST_PARENTS = new Set(["Program", "BlockStatement", "SwitchCase"]);
@@ -243,7 +245,7 @@ function hasJSDocThisTag(node, sourceCode) {
// because callbacks don't have its JSDoc comment.
// e.g.
// sinon.test(/* @this sinon.Sandbox */function() { this.spy(); });
- return sourceCode.getComments(node).leading.some(comment => thisTagPattern.test(comment.value));
+ return sourceCode.getCommentsBefore(node).some(comment => thisTagPattern.test(comment.value));
}
/**
@@ -412,6 +414,7 @@ module.exports = {
COMMENTS_IGNORE_PATTERN,
LINEBREAKS,
LINEBREAK_MATCHER,
+ SHEBANG_MATCHER,
STATEMENT_LIST_PARENTS,
/**
@@ -524,7 +527,7 @@ module.exports = {
/**
* Returns whether the provided node is an ESLint directive comment or not
- * @param {LineComment|BlockComment} node The node to be checked
+ * @param {Line|Block} node The comment token to be checked
* @returns {boolean} `true` if the node is an ESLint directive comment
*/
isDirectiveComment(node) {
@@ -556,9 +559,9 @@ module.exports = {
/**
* Finds the variable by a given name in a given scope and its upper scopes.
*
- * @param {escope.Scope} initScope - A scope to start find.
+ * @param {eslint-scope.Scope} initScope - A scope to start find.
* @param {string} name - A variable name to find.
- * @returns {escope.Variable|null} A found variable or `null`.
+ * @returns {eslint-scope.Variable|null} A found variable or `null`.
*/
getVariableByName(initScope, name) {
let scope = initScope;
@@ -1252,5 +1255,52 @@ module.exports = {
* `node.regex` instead. Also see: https://github.com/eslint/eslint/issues/8020
*/
return node.type === "Literal" && node.value === null && !node.regex;
+ },
+
+ /**
+ * Determines whether two tokens can safely be placed next to each other without merging into a single token
+ * @param {Token|string} leftValue The left token. If this is a string, it will be tokenized and the last token will be used.
+ * @param {Token|string} rightValue The right token. If this is a string, it will be tokenized and the first token will be used.
+ * @returns {boolean} If the tokens cannot be safely placed next to each other, returns `false`. If the tokens can be placed
+ * next to each other, behavior is undefined (although it should return `true` in most cases).
+ */
+ canTokensBeAdjacent(leftValue, rightValue) {
+ let leftToken;
+
+ if (typeof leftValue === "string") {
+ const leftTokens = espree.tokenize(leftValue, { ecmaVersion: 2015 });
+
+ leftToken = leftTokens[leftTokens.length - 1];
+ } else {
+ leftToken = leftValue;
+ }
+
+ const rightToken = typeof rightValue === "string" ? espree.tokenize(rightValue, { ecmaVersion: 2015 })[0] : rightValue;
+
+ if (leftToken.type === "Punctuator" || rightToken.type === "Punctuator") {
+ if (leftToken.type === "Punctuator" && rightToken.type === "Punctuator") {
+ const PLUS_TOKENS = new Set(["+", "++"]);
+ const MINUS_TOKENS = new Set(["-", "--"]);
+
+ return !(
+ PLUS_TOKENS.has(leftToken.value) && PLUS_TOKENS.has(rightToken.value) ||
+ MINUS_TOKENS.has(leftToken.value) && MINUS_TOKENS.has(rightToken.value)
+ );
+ }
+ return true;
+ }
+
+ if (
+ leftToken.type === "String" || rightToken.type === "String" ||
+ leftToken.type === "Template" || rightToken.type === "Template"
+ ) {
+ return true;
+ }
+
+ if (leftToken.type !== "Numeric" && rightToken.type === "Numeric" && rightToken.value.startsWith(".")) {
+ return true;
+ }
+
+ return false;
}
};
diff --git a/tools/eslint/lib/cli-engine.js b/tools/eslint/lib/cli-engine.js
index de875a4d352926..d0abc0a550ebf7 100644
--- a/tools/eslint/lib/cli-engine.js
+++ b/tools/eslint/lib/cli-engine.js
@@ -17,12 +17,10 @@
const fs = require("fs"),
path = require("path"),
- rules = require("./rules"),
- eslint = require("./eslint"),
- defaultOptions = require("../conf/cli-options"),
+ defaultOptions = require("../conf/default-cli-options"),
+ Linter = require("./linter"),
IgnoredPaths = require("./ignored-paths"),
Config = require("./config"),
- Plugins = require("./config/plugins"),
fileEntryCache = require("file-entry-cache"),
globUtil = require("./util/glob-util"),
SourceCodeFixer = require("./util/source-code-fixer"),
@@ -73,8 +71,10 @@ const debug = require("debug")("eslint:cli-engine");
* @typedef {Object} LintResult
* @property {string} filePath The path to the file that was linted.
* @property {LintMessage[]} messages All of the messages for the result.
- * @property {number} errorCount Number or errors for the result.
- * @property {number} warningCount Number or warnings for the result.
+ * @property {number} errorCount Number of errors for the result.
+ * @property {number} warningCount Number of warnings for the result.
+ * @property {number} fixableErrorCount Number of fixable errors for the result.
+ * @property {number} fixableWarningCount Number of fixable warnings for the result.
* @property {string=} [source] The source code of the file that was linted.
* @property {string=} [output] The source code of the file that was linted, with as many fixes applied as possible.
*/
@@ -93,13 +93,21 @@ function calculateStatsPerFile(messages) {
return messages.reduce((stat, message) => {
if (message.fatal || message.severity === 2) {
stat.errorCount++;
+ if (message.fix) {
+ stat.fixableErrorCount++;
+ }
} else {
stat.warningCount++;
+ if (message.fix) {
+ stat.fixableWarningCount++;
+ }
}
return stat;
}, {
errorCount: 0,
- warningCount: 0
+ warningCount: 0,
+ fixableErrorCount: 0,
+ fixableWarningCount: 0
});
}
@@ -113,10 +121,14 @@ function calculateStatsPerRun(results) {
return results.reduce((stat, result) => {
stat.errorCount += result.errorCount;
stat.warningCount += result.warningCount;
+ stat.fixableErrorCount += result.fixableErrorCount;
+ stat.fixableWarningCount += result.fixableWarningCount;
return stat;
}, {
errorCount: 0,
- warningCount: 0
+ warningCount: 0,
+ fixableErrorCount: 0,
+ fixableWarningCount: 0
});
}
@@ -129,11 +141,12 @@ function calculateStatsPerRun(results) {
* @param {string} options.filename The filename from which the text was read.
* @param {boolean} options.allowInlineConfig Flag indicating if inline comments
* should be allowed.
+ * @param {Linter} linter Linter context
* @returns {Object} The result of the fix operation as returned from the
* SourceCodeFixer.
* @private
*/
-function multipassFix(text, config, options) {
+function multipassFix(text, config, options, linter) {
const MAX_PASSES = 10;
let messages = [],
fixedResult,
@@ -153,10 +166,10 @@ function multipassFix(text, config, options) {
passNumber++;
debug(`Linting code for ${options.filename} (pass ${passNumber})`);
- messages = eslint.verify(text, config, options);
+ messages = linter.verify(text, config, options);
debug(`Generating fixed text for ${options.filename} (pass ${passNumber})`);
- fixedResult = SourceCodeFixer.applyFixes(eslint.getSourceCode(), messages);
+ fixedResult = SourceCodeFixer.applyFixes(linter.getSourceCode(), messages);
// stop if there are any syntax errors.
// 'fixedResult.output' is a empty string.
@@ -181,7 +194,7 @@ function multipassFix(text, config, options) {
* the most up-to-date information.
*/
if (fixedResult.fixed) {
- fixedResult.messages = eslint.verify(text, config, options);
+ fixedResult.messages = linter.verify(text, config, options);
}
@@ -200,13 +213,14 @@ function multipassFix(text, config, options) {
* @param {string} filename An optional string representing the texts filename.
* @param {boolean} fix Indicates if fixes should be processed.
* @param {boolean} allowInlineConfig Allow/ignore comments that change config.
+ * @param {Linter} linter Linter context
* @returns {LintResult} The results for linting on this text.
* @private
*/
-function processText(text, configHelper, filename, fix, allowInlineConfig) {
+function processText(text, configHelper, filename, fix, allowInlineConfig, linter) {
// clear all existing settings for a new file
- eslint.reset();
+ linter.reset();
let filePath,
messages,
@@ -224,10 +238,10 @@ function processText(text, configHelper, filename, fix, allowInlineConfig) {
const config = configHelper.getConfig(filePath);
if (config.plugins) {
- Plugins.loadAll(config.plugins);
+ configHelper.plugins.loadAll(config.plugins);
}
- const loadedPlugins = Plugins.getAll();
+ const loadedPlugins = configHelper.plugins.getAll();
for (const plugin in loadedPlugins) {
if (loadedPlugins[plugin].processors && Object.keys(loadedPlugins[plugin].processors).indexOf(fileExtension) >= 0) {
@@ -242,7 +256,7 @@ function processText(text, configHelper, filename, fix, allowInlineConfig) {
const unprocessedMessages = [];
parsedBlocks.forEach(block => {
- unprocessedMessages.push(eslint.verify(block, config, {
+ unprocessedMessages.push(linter.verify(block, config, {
filename,
allowInlineConfig
}));
@@ -258,10 +272,10 @@ function processText(text, configHelper, filename, fix, allowInlineConfig) {
fixedResult = multipassFix(text, config, {
filename,
allowInlineConfig
- });
+ }, linter);
messages = fixedResult.messages;
} else {
- messages = eslint.verify(text, config, {
+ messages = linter.verify(text, config, {
filename,
allowInlineConfig
});
@@ -274,7 +288,9 @@ function processText(text, configHelper, filename, fix, allowInlineConfig) {
filePath: filename,
messages,
errorCount: stats.errorCount,
- warningCount: stats.warningCount
+ warningCount: stats.warningCount,
+ fixableErrorCount: stats.fixableErrorCount,
+ fixableWarningCount: stats.fixableWarningCount
};
if (fixedResult && fixedResult.fixed) {
@@ -294,13 +310,14 @@ function processText(text, configHelper, filename, fix, allowInlineConfig) {
* @param {string} filename The filename of the file being checked.
* @param {Object} configHelper The configuration options for ESLint.
* @param {Object} options The CLIEngine options object.
+ * @param {Linter} linter Linter context
* @returns {LintResult} The results for linting on this file.
* @private
*/
-function processFile(filename, configHelper, options) {
+function processFile(filename, configHelper, options, linter) {
const text = fs.readFileSync(path.resolve(filename), "utf8"),
- result = processText(text, configHelper, filename, options.fix, options.allowInlineConfig);
+ result = processText(text, configHelper, filename, options.fix, options.allowInlineConfig, linter);
return result;
@@ -339,7 +356,9 @@ function createIgnoreResult(filePath, baseDir) {
}
],
errorCount: 0,
- warningCount: 1
+ warningCount: 1,
+ fixableErrorCount: 0,
+ fixableWarningCount: 0
};
}
@@ -432,141 +451,104 @@ function getCacheFile(cacheFile, cwd) {
// Public Interface
//------------------------------------------------------------------------------
-/**
- * Creates a new instance of the core CLI engine.
- * @param {CLIEngineOptions} options The options for this instance.
- * @constructor
- */
-function CLIEngine(options) {
-
- options = Object.assign(
- Object.create(null),
- defaultOptions,
- { cwd: process.cwd() },
- options
- );
-
- /**
- * Stored options for this instance
- * @type {Object}
- */
- this.options = options;
-
- const cacheFile = getCacheFile(this.options.cacheLocation || this.options.cacheFile, this.options.cwd);
+class CLIEngine {
/**
- * Cache used to avoid operating on files that haven't changed since the
- * last successful execution (e.g., file passed linting with no errors and
- * no warnings).
- * @type {Object}
+ * Creates a new instance of the core CLI engine.
+ * @param {CLIEngineOptions} options The options for this instance.
+ * @constructor
*/
- this._fileCache = fileEntryCache.create(cacheFile);
-
- // load in additional rules
- if (this.options.rulePaths) {
- const cwd = this.options.cwd;
-
- this.options.rulePaths.forEach(rulesdir => {
- debug(`Loading rules from ${rulesdir}`);
- rules.load(rulesdir, cwd);
- });
- }
-
- Object.keys(this.options.rules || {}).forEach(name => {
- validator.validateRuleOptions(name, this.options.rules[name], "CLI");
- });
-}
+ constructor(options) {
-/**
- * Returns the formatter representing the given format or null if no formatter
- * with the given name can be found.
- * @param {string} [format] The name of the format to load or the path to a
- * custom formatter.
- * @returns {Function} The formatter function or null if not found.
- */
-CLIEngine.getFormatter = function(format) {
-
- let formatterPath;
+ options = Object.assign(
+ Object.create(null),
+ defaultOptions,
+ { cwd: process.cwd() },
+ options
+ );
- // default is stylish
- format = format || "stylish";
+ /**
+ * Stored options for this instance
+ * @type {Object}
+ */
+ this.options = options;
+ this.linter = new Linter();
- // only strings are valid formatters
- if (typeof format === "string") {
+ const cacheFile = getCacheFile(this.options.cacheLocation || this.options.cacheFile, this.options.cwd);
- // replace \ with / for Windows compatibility
- format = format.replace(/\\/g, "/");
+ /**
+ * Cache used to avoid operating on files that haven't changed since the
+ * last successful execution (e.g., file passed linting with no errors and
+ * no warnings).
+ * @type {Object}
+ */
+ this._fileCache = fileEntryCache.create(cacheFile);
- // if there's a slash, then it's a file
- if (format.indexOf("/") > -1) {
- const cwd = this.options ? this.options.cwd : process.cwd();
+ // load in additional rules
+ if (this.options.rulePaths) {
+ const cwd = this.options.cwd;
- formatterPath = path.resolve(cwd, format);
- } else {
- formatterPath = `./formatters/${format}`;
+ this.options.rulePaths.forEach(rulesdir => {
+ debug(`Loading rules from ${rulesdir}`);
+ this.linter.rules.load(rulesdir, cwd);
+ });
}
- try {
- return require(formatterPath);
- } catch (ex) {
- ex.message = `There was a problem loading formatter: ${formatterPath}\nError: ${ex.message}`;
- throw ex;
- }
+ Object.keys(this.options.rules || {}).forEach(name => {
+ validator.validateRuleOptions(name, this.options.rules[name], "CLI", this.linter.rules);
+ });
- } else {
- return null;
+ this.config = new Config(this.options, this.linter);
}
-};
-/**
- * Returns results that only contains errors.
- * @param {LintResult[]} results The results to filter.
- * @returns {LintResult[]} The filtered results.
- */
-CLIEngine.getErrorResults = function(results) {
- const filtered = [];
-
- results.forEach(result => {
- const filteredMessages = result.messages.filter(isErrorMessage);
-
- if (filteredMessages.length > 0) {
- filtered.push(
- Object.assign(result, {
- messages: filteredMessages,
- errorCount: filteredMessages.length,
- warningCount: 0
- })
- );
- }
- });
-
- return filtered;
-};
+ /**
+ * Returns results that only contains errors.
+ * @param {LintResult[]} results The results to filter.
+ * @returns {LintResult[]} The filtered results.
+ */
+ static getErrorResults(results) {
+ const filtered = [];
+
+ results.forEach(result => {
+ const filteredMessages = result.messages.filter(isErrorMessage);
+
+ if (filteredMessages.length > 0) {
+ filtered.push(
+ Object.assign(result, {
+ messages: filteredMessages,
+ errorCount: filteredMessages.length,
+ warningCount: 0,
+ fixableErrorCount: result.fixableErrorCount,
+ fixableWarningCount: 0
+ })
+ );
+ }
+ });
-/**
- * Outputs fixes from the given results to files.
- * @param {Object} report The report object created by CLIEngine.
- * @returns {void}
- */
-CLIEngine.outputFixes = function(report) {
- report.results.filter(result => result.hasOwnProperty("output")).forEach(result => {
- fs.writeFileSync(result.filePath, result.output);
- });
-};
+ return filtered;
+ }
-CLIEngine.prototype = {
+ /**
+ * Outputs fixes from the given results to files.
+ * @param {Object} report The report object created by CLIEngine.
+ * @returns {void}
+ */
+ static outputFixes(report) {
+ report.results.filter(result => result.hasOwnProperty("output")).forEach(result => {
+ fs.writeFileSync(result.filePath, result.output);
+ });
+ }
- constructor: CLIEngine,
/**
- * Add a plugin by passing it's configuration
+ * Add a plugin by passing its configuration
* @param {string} name Name of the plugin.
* @param {Object} pluginobject Plugin configuration object.
* @returns {void}
*/
addPlugin(name, pluginobject) {
- Plugins.define(name, pluginobject);
- },
+ this.config.plugins.define(name, pluginobject);
+ }
/**
* Resolves the patterns passed into executeOnFiles() into glob-based patterns
@@ -576,7 +558,7 @@ CLIEngine.prototype = {
*/
resolveFileGlobPatterns(patterns) {
return globUtil.resolveFileGlobPatterns(patterns, this.options);
- },
+ }
/**
* Executes the current configuration on an array of file and directory names.
@@ -587,7 +569,7 @@ CLIEngine.prototype = {
const results = [],
options = this.options,
fileCache = this._fileCache,
- configHelper = new Config(options);
+ configHelper = this.config;
let prevConfig; // the previous configuration used
/**
@@ -624,9 +606,10 @@ CLIEngine.prototype = {
* unsupported file extensions and any files that are already linted.
* @param {string} filename The resolved filename of the file to be linted
* @param {boolean} warnIgnored always warn when a file is ignored
+ * @param {Linter} linter Linter context
* @returns {void}
*/
- function executeOnFile(filename, warnIgnored) {
+ function executeOnFile(filename, warnIgnored, linter) {
let hashOfConfig,
descriptor;
@@ -669,7 +652,7 @@ CLIEngine.prototype = {
debug(`Processing ${filename}`);
- const res = processFile(filename, configHelper, options);
+ const res = processFile(filename, configHelper, options, linter);
if (options.cache) {
@@ -702,12 +685,11 @@ CLIEngine.prototype = {
const startTime = Date.now();
-
patterns = this.resolveFileGlobPatterns(patterns);
const fileList = globUtil.listFilesToProcess(patterns, options);
fileList.forEach(fileInfo => {
- executeOnFile(fileInfo.filename, fileInfo.ignored);
+ executeOnFile(fileInfo.filename, fileInfo.ignored, this.linter);
});
const stats = calculateStatsPerRun(results);
@@ -723,9 +705,11 @@ CLIEngine.prototype = {
return {
results,
errorCount: stats.errorCount,
- warningCount: stats.warningCount
+ warningCount: stats.warningCount,
+ fixableErrorCount: stats.fixableErrorCount,
+ fixableWarningCount: stats.fixableWarningCount
};
- },
+ }
/**
* Executes the current configuration on text.
@@ -738,7 +722,7 @@ CLIEngine.prototype = {
const results = [],
options = this.options,
- configHelper = new Config(options),
+ configHelper = this.config,
ignoredPaths = new IgnoredPaths(options);
// resolve filename based on options.cwd (for reporting, ignoredPaths also resolves)
@@ -751,7 +735,7 @@ CLIEngine.prototype = {
results.push(createIgnoreResult(filename, options.cwd));
}
} else {
- results.push(processText(text, configHelper, filename, options.fix, options.allowInlineConfig));
+ results.push(processText(text, configHelper, filename, options.fix, options.allowInlineConfig, this.linter));
}
const stats = calculateStatsPerRun(results);
@@ -759,9 +743,11 @@ CLIEngine.prototype = {
return {
results,
errorCount: stats.errorCount,
- warningCount: stats.warningCount
+ warningCount: stats.warningCount,
+ fixableErrorCount: stats.fixableErrorCount,
+ fixableWarningCount: stats.fixableWarningCount
};
- },
+ }
/**
* Returns a configuration object for the given file based on the CLI options.
@@ -771,10 +757,10 @@ CLIEngine.prototype = {
* @returns {Object} A configuration object for the file.
*/
getConfigForFile(filePath) {
- const configHelper = new Config(this.options);
+ const configHelper = this.config;
return configHelper.getConfig(filePath);
- },
+ }
/**
* Checks if a given path is ignored by ESLint.
@@ -786,12 +772,51 @@ CLIEngine.prototype = {
const ignoredPaths = new IgnoredPaths(this.options);
return ignoredPaths.contains(resolvedPath);
- },
+ }
+
+ /**
+ * Returns the formatter representing the given format or null if no formatter
+ * with the given name can be found.
+ * @param {string} [format] The name of the format to load or the path to a
+ * custom formatter.
+ * @returns {Function} The formatter function or null if not found.
+ */
+ getFormatter(format) {
+
+ let formatterPath;
- getFormatter: CLIEngine.getFormatter
+ // default is stylish
+ format = format || "stylish";
-};
+ // only strings are valid formatters
+ if (typeof format === "string") {
+
+ // replace \ with / for Windows compatibility
+ format = format.replace(/\\/g, "/");
+
+ // if there's a slash, then it's a file
+ if (format.indexOf("/") > -1) {
+ const cwd = this.options ? this.options.cwd : process.cwd();
+
+ formatterPath = path.resolve(cwd, format);
+ } else {
+ formatterPath = `./formatters/${format}`;
+ }
+
+ try {
+ return require(formatterPath);
+ } catch (ex) {
+ ex.message = `There was a problem loading formatter: ${formatterPath}\nError: ${ex.message}`;
+ throw ex;
+ }
+
+ } else {
+ return null;
+ }
+ }
+}
CLIEngine.version = pkg.version;
+CLIEngine.getFormatter = CLIEngine.prototype.getFormatter;
module.exports = CLIEngine;
diff --git a/tools/eslint/lib/cli.js b/tools/eslint/lib/cli.js
index 640bd81baba6ea..530bfbc423d00e 100644
--- a/tools/eslint/lib/cli.js
+++ b/tools/eslint/lib/cli.js
@@ -17,7 +17,6 @@
const fs = require("fs"),
path = require("path"),
- shell = require("shelljs"),
options = require("./options"),
CLIEngine = require("./cli-engine"),
mkdirp = require("mkdirp"),
@@ -83,7 +82,7 @@ function printResults(engine, results, format, outputFile) {
if (outputFile) {
const filePath = path.resolve(process.cwd(), outputFile);
- if (shell.test("-d", filePath)) {
+ if (fs.existsSync(filePath) && fs.statSync(filePath).isDirectory()) {
log.error("Cannot write to output file path, it is a directory: %s", outputFile);
return false;
}
diff --git a/tools/eslint/lib/code-path-analysis/code-path-state.js b/tools/eslint/lib/code-path-analysis/code-path-state.js
index 3faff3ebb85970..a5adb554ff95ea 100644
--- a/tools/eslint/lib/code-path-analysis/code-path-state.js
+++ b/tools/eslint/lib/code-path-analysis/code-path-state.js
@@ -988,7 +988,7 @@ class CodePathState {
switch (context.type) {
case "WhileStatement":
case "ForStatement":
- choiceContext = this.popChoiceContext();
+ this.popChoiceContext();
makeLooped(
this,
forkContext.head,
diff --git a/tools/eslint/lib/config.js b/tools/eslint/lib/config.js
index 03fda87c973c3b..5407134d6f24e5 100644
--- a/tools/eslint/lib/config.js
+++ b/tools/eslint/lib/config.js
@@ -10,13 +10,12 @@
//------------------------------------------------------------------------------
const path = require("path"),
+ os = require("os"),
ConfigOps = require("./config/config-ops"),
ConfigFile = require("./config/config-file"),
Plugins = require("./config/plugins"),
FileFinder = require("./file-finder"),
- userHome = require("user-home"),
- isResolvable = require("is-resolvable"),
- pathIsInside = require("path-is-inside");
+ isResolvable = require("is-resolvable");
const debug = require("debug")("eslint:config");
@@ -24,7 +23,7 @@ const debug = require("debug")("eslint:config");
// Constants
//------------------------------------------------------------------------------
-const PERSONAL_CONFIG_DIR = userHome || null;
+const PERSONAL_CONFIG_DIR = os.homedir() || null;
//------------------------------------------------------------------------------
// Helpers
@@ -43,10 +42,11 @@ function isObject(item) {
/**
* Load and parse a JSON config object from a file.
* @param {string|Object} configToLoad the path to the JSON config file or the config object itself.
+ * @param {Config} configContext config instance object
* @returns {Object} the parsed config object (empty object if there was a parse error)
* @private
*/
-function loadConfig(configToLoad) {
+function loadConfig(configToLoad, configContext) {
let config = {},
filePath = "";
@@ -56,32 +56,33 @@ function loadConfig(configToLoad) {
config = configToLoad;
if (config.extends) {
- config = ConfigFile.applyExtends(config, filePath);
+ config = ConfigFile.applyExtends(config, configContext, filePath);
}
} else {
filePath = configToLoad;
- config = ConfigFile.load(filePath);
+ config = ConfigFile.load(filePath, configContext);
}
}
-
return config;
}
/**
* Get personal config object from ~/.eslintrc.
+ * @param {Config} configContext Plugin context for the config instance
* @returns {Object} the personal config object (null if there is no personal config)
* @private
*/
-function getPersonalConfig() {
+function getPersonalConfig(configContext) {
let config;
if (PERSONAL_CONFIG_DIR) {
+
const filename = ConfigFile.getFilenameForDirectory(PERSONAL_CONFIG_DIR);
if (filename) {
debug("Using personal config");
- config = loadConfig(filename);
+ config = loadConfig(filename, configContext);
}
}
@@ -99,21 +100,18 @@ function hasRules(options) {
/**
* Get a local config object.
- * @param {Object} thisConfig A Config object.
+ * @param {Config} thisConfig A Config object.
* @param {string} directory The directory to start looking in for a local config file.
* @returns {Object} The local config object, or an empty object if there is no local config.
*/
function getLocalConfig(thisConfig, directory) {
- const localConfigFiles = thisConfig.findLocalConfigFiles(directory),
- numFiles = localConfigFiles.length,
- projectConfigPath = ConfigFile.getFilenameForDirectory(thisConfig.options.cwd);
- let found,
- config = {},
- rootPath;
- for (let i = 0; i < numFiles; i++) {
+ const projectConfigPath = ConfigFile.getFilenameForDirectory(thisConfig.options.cwd);
+ const localConfigFiles = thisConfig.findLocalConfigFiles(directory);
+ let found,
+ config = {};
- const localConfigFile = localConfigFiles[i];
+ for (const localConfigFile of localConfigFiles) {
// Don't consider the personal config file in the home directory,
// except if the home directory is the same as the current working directory
@@ -121,27 +119,22 @@ function getLocalConfig(thisConfig, directory) {
continue;
}
- // If root flag is set, don't consider file if it is above root
- if (rootPath && !pathIsInside(path.dirname(localConfigFile), rootPath)) {
- continue;
- }
-
debug(`Loading ${localConfigFile}`);
- const localConfig = loadConfig(localConfigFile);
+ const localConfig = loadConfig(localConfigFile, thisConfig);
// Don't consider a local config file found if the config is null
if (!localConfig) {
continue;
}
- // Check for root flag
- if (localConfig.root === true) {
- rootPath = path.dirname(localConfigFile);
- }
-
found = true;
debug(`Using ${localConfigFile}`);
config = ConfigOps.merge(localConfig, config);
+
+ // Check for root flag
+ if (localConfig.root === true) {
+ break;
+ }
}
if (!found && !thisConfig.useSpecificConfig) {
@@ -152,7 +145,7 @@ function getLocalConfig(thisConfig, directory) {
* - Otherwise, if no rules were manually passed in, throw and error.
* - Note: This function is not called if useEslintrc is false.
*/
- const personalConfig = getPersonalConfig();
+ const personalConfig = getPersonalConfig(thisConfig);
if (personalConfig) {
config = ConfigOps.merge(config, personalConfig);
@@ -186,17 +179,21 @@ class Config {
/**
* Config options
* @param {Object} options Options to be passed in
+ * @param {Linter} linterContext Linter instance object
*/
- constructor(options) {
+ constructor(options, linterContext) {
options = options || {};
+ this.linterContext = linterContext;
+ this.plugins = new Plugins(linterContext.environments, linterContext.rules);
+
this.ignore = options.ignore;
this.ignorePath = options.ignorePath;
this.cache = {};
this.parser = options.parser;
this.parserOptions = options.parserOptions || {};
- this.baseConfig = options.baseConfig ? loadConfig(options.baseConfig) : { rules: {} };
+ this.baseConfig = options.baseConfig ? loadConfig(options.baseConfig, this) : { rules: {} };
this.useEslintrc = (options.useEslintrc !== false);
@@ -219,16 +216,22 @@ class Config {
return globals;
}, {});
- const useConfig = options.configFile;
-
this.options = options;
+ this.loadConfigFile(options.configFile);
+ }
- if (useConfig) {
- debug(`Using command line config ${useConfig}`);
- if (isResolvable(useConfig) || isResolvable(`eslint-config-${useConfig}`) || useConfig.charAt(0) === "@") {
- this.useSpecificConfig = loadConfig(useConfig);
+ /**
+ * Loads the config from the configuration file
+ * @param {string} configFile - patch to the config file
+ * @returns {undefined}
+ */
+ loadConfigFile(configFile) {
+ if (configFile) {
+ debug(`Using command line config ${configFile}`);
+ if (isResolvable(configFile) || isResolvable(`eslint-config-${configFile}`) || configFile.charAt(0) === "@") {
+ this.useSpecificConfig = loadConfig(configFile, this);
} else {
- this.useSpecificConfig = loadConfig(path.resolve(this.options.cwd, useConfig));
+ this.useSpecificConfig = loadConfig(path.resolve(this.options.cwd, configFile), this);
}
}
}
@@ -248,7 +251,6 @@ class Config {
debug(`Constructing config for ${filePath ? filePath : "text"}`);
config = this.cache[directory];
-
if (config) {
debug("Using config from cache");
return config;
@@ -306,13 +308,13 @@ class Config {
// Step 8: Merge in command line plugins
if (this.options.plugins) {
debug("Merging command line plugins");
- Plugins.loadAll(this.options.plugins);
+ this.plugins.loadAll(this.options.plugins);
config = ConfigOps.merge(config, { plugins: this.options.plugins });
}
// Step 9: Apply environments to the config if present
if (config.env) {
- config = ConfigOps.applyEnvironments(config);
+ config = ConfigOps.applyEnvironments(config, this.linterContext.environments);
}
this.cache[directory] = config;
@@ -323,7 +325,7 @@ class Config {
/**
* Find local config files from directory and parent directories.
* @param {string} directory The directory to start searching from.
- * @returns {string[]} The paths of local config files found.
+ * @returns {GeneratorFunction} The paths of local config files found.
*/
findLocalConfigFiles(directory) {
diff --git a/tools/eslint/lib/config/autoconfig.js b/tools/eslint/lib/config/autoconfig.js
index 4a50ce25cdd248..88204a7a45f192 100644
--- a/tools/eslint/lib/config/autoconfig.js
+++ b/tools/eslint/lib/config/autoconfig.js
@@ -10,12 +10,13 @@
//------------------------------------------------------------------------------
const lodash = require("lodash"),
- eslint = require("../eslint"),
+ Linter = require("../linter"),
configRule = require("./config-rule"),
ConfigOps = require("./config-ops"),
recConfig = require("../../conf/eslint-recommended");
const debug = require("debug")("eslint:autoconfig");
+const linter = new Linter();
//------------------------------------------------------------------------------
// Data
@@ -37,11 +38,11 @@ const MAX_CONFIG_COMBINATIONS = 17, // 16 combinations + 1 for severity only
* @param {number} errorCount The number of errors encountered when linting with the config
*/
- /**
- * This callback is used to measure execution status in a progress bar
- * @callback progressCallback
- * @param {number} The total number of times the callback will be called.
- */
+/**
+ * This callback is used to measure execution status in a progress bar
+ * @callback progressCallback
+ * @param {number} The total number of times the callback will be called.
+ */
/**
* Create registryItems for rules
@@ -290,7 +291,7 @@ class Registry {
ruleSets.forEach(ruleSet => {
const lintConfig = Object.assign({}, config, { rules: ruleSet });
- const lintResults = eslint.verify(sourceCodes[filename], lintConfig);
+ const lintResults = linter.verify(sourceCodes[filename], lintConfig);
lintResults.forEach(result => {
@@ -310,7 +311,7 @@ class Registry {
ruleSetIdx += 1;
if (cb) {
- cb(totalFilesLinting); // eslint-disable-line callback-return
+ cb(totalFilesLinting); // eslint-disable-line callback-return
}
});
diff --git a/tools/eslint/lib/config/config-file.js b/tools/eslint/lib/config/config-file.js
index 4e886b8af27b67..c9fcc9dff803ae 100644
--- a/tools/eslint/lib/config/config-file.js
+++ b/tools/eslint/lib/config/config-file.js
@@ -13,17 +13,13 @@
const fs = require("fs"),
path = require("path"),
- shell = require("shelljs"),
ConfigOps = require("./config-ops"),
validator = require("./config-validator"),
- Plugins = require("./plugins"),
pathUtil = require("../util/path-util"),
ModuleResolver = require("../util/module-resolver"),
pathIsInside = require("path-is-inside"),
- stripBom = require("strip-bom"),
stripComments = require("strip-json-comments"),
stringify = require("json-stable-stringify"),
- defaultOptions = require("../../conf/eslint-recommended"),
requireUncached = require("require-uncached");
const debug = require("debug")("eslint:config-file");
@@ -63,11 +59,11 @@ const resolver = new ModuleResolver();
/**
* Convenience wrapper for synchronously reading file contents.
* @param {string} filePath The filename to read.
- * @returns {string} The file contents.
+ * @returns {string} The file contents, with the BOM removed.
* @private
*/
function readFile(filePath) {
- return stripBom(fs.readFileSync(filePath, "utf8"));
+ return fs.readFileSync(filePath, "utf8").replace(/^\ufeff/, "");
}
/**
@@ -368,18 +364,18 @@ function getLookupPath(configFilePath) {
function getEslintCoreConfigPath(name) {
if (name === "eslint:recommended") {
- /*
- * Add an explicit substitution for eslint:recommended to
- * conf/eslint-recommended.js.
- */
+ /*
+ * Add an explicit substitution for eslint:recommended to
+ * conf/eslint-recommended.js.
+ */
return path.resolve(__dirname, "../../conf/eslint-recommended.js");
}
if (name === "eslint:all") {
- /*
- * Add an explicit substitution for eslint:all to conf/eslint-all.js
- */
+ /*
+ * Add an explicit substitution for eslint:all to conf/eslint-all.js
+ */
return path.resolve(__dirname, "../../conf/eslint-all.js");
}
@@ -389,6 +385,7 @@ function getEslintCoreConfigPath(name) {
/**
* Applies values from the "extends" field in a configuration file.
* @param {Object} config The configuration information.
+ * @param {Config} configContext Plugin context for the config instance
* @param {string} filePath The file path from which the configuration information
* was loaded.
* @param {string} [relativeTo] The path to resolve relative to.
@@ -396,7 +393,7 @@ function getEslintCoreConfigPath(name) {
* loaded and merged.
* @private
*/
-function applyExtends(config, filePath, relativeTo) {
+function applyExtends(config, configContext, filePath, relativeTo) {
let configExtends = config.extends;
// normalize into an array for easier handling
@@ -421,7 +418,7 @@ function applyExtends(config, filePath, relativeTo) {
);
}
debug(`Loading ${parentPath}`);
- return ConfigOps.merge(load(parentPath, false, relativeTo), previousValue);
+ return ConfigOps.merge(load(parentPath, configContext, false, relativeTo), previousValue);
} catch (e) {
/*
@@ -516,19 +513,18 @@ function resolve(filePath, relativeTo) {
return { filePath };
-
}
/**
* Loads a configuration file from the given file path.
* @param {string} filePath The filename or package name to load the configuration
* information from.
+ * @param {Config} configContext Plugins context
* @param {boolean} [applyEnvironments=false] Set to true to merge in environment settings.
* @param {string} [relativeTo] The path to resolve relative to.
* @returns {Object} The configuration information.
- * @private
*/
-function load(filePath, applyEnvironments, relativeTo) {
+function load(filePath, configContext, applyEnvironments, relativeTo) {
const resolvedPath = resolve(filePath, relativeTo),
dirname = path.dirname(resolvedPath.filePath),
lookupPath = getLookupPath(dirname);
@@ -538,12 +534,7 @@ function load(filePath, applyEnvironments, relativeTo) {
// ensure plugins are properly loaded first
if (config.plugins) {
- Plugins.loadAll(config.plugins);
- }
-
- // remove parser from config if it is the default parser
- if (config.parser === defaultOptions.parser) {
- config.parser = null;
+ configContext.plugins.loadAll(config.plugins);
}
// include full path of parser if present
@@ -556,20 +547,20 @@ function load(filePath, applyEnvironments, relativeTo) {
}
// validate the configuration before continuing
- validator.validate(config, filePath);
+ validator.validate(config, filePath, configContext.linterContext.rules, configContext.linterContext.environments);
/*
* If an `extends` property is defined, it represents a configuration file to use as
* a "parent". Load the referenced file and merge the configuration recursively.
*/
if (config.extends) {
- config = applyExtends(config, filePath, dirname);
+ config = applyExtends(config, configContext, filePath, dirname);
}
if (config.env && applyEnvironments) {
// Merge in environment-specific globals and parserOptions.
- config = ConfigOps.applyEnvironments(config);
+ config = ConfigOps.applyEnvironments(config, configContext.linterContext.environments);
}
}
@@ -603,7 +594,7 @@ module.exports = {
for (let i = 0, len = CONFIG_FILES.length; i < len; i++) {
const filename = path.join(directory, CONFIG_FILES[i]);
- if (shell.test("-f", filename)) {
+ if (fs.existsSync(filename) && fs.statSync(filename).isFile()) {
return filename;
}
}
diff --git a/tools/eslint/lib/config/config-initializer.js b/tools/eslint/lib/config/config-initializer.js
index 0062a46504fdf5..ed4bde8757e4e4 100644
--- a/tools/eslint/lib/config/config-initializer.js
+++ b/tools/eslint/lib/config/config-initializer.js
@@ -282,13 +282,12 @@ function getConfigForStyleGuide(guide) {
/* istanbul ignore next: no need to test inquirer*/
/**
* Ask use a few questions on command prompt
- * @param {Function} callback callback function when file has been written
- * @returns {void}
+ * @returns {Promise} The promise with the result of the prompt
*/
-function promptUser(callback) {
+function promptUser() {
let config;
- inquirer.prompt([
+ return inquirer.prompt([
{
type: "list",
name: "source",
@@ -343,29 +342,26 @@ function promptUser(callback) {
return ((answers.source === "guide" && answers.packageJsonExists) || answers.source === "auto");
}
}
- ], earlyAnswers => {
+ ]).then(earlyAnswers => {
// early exit if you are using a style guide
if (earlyAnswers.source === "guide") {
if (!earlyAnswers.packageJsonExists) {
log.info("A package.json is necessary to install plugins such as style guides. Run `npm init` to create a package.json file and try again.");
- return;
+ return void 0;
}
if (earlyAnswers.styleguide === "airbnb" && !earlyAnswers.airbnbReact) {
earlyAnswers.styleguide = "airbnb-base";
}
- try {
- config = getConfigForStyleGuide(earlyAnswers.styleguide);
- writeFile(config, earlyAnswers.format);
- } catch (err) {
- callback(err);
- return;
- }
- return;
+
+ config = getConfigForStyleGuide(earlyAnswers.styleguide);
+ writeFile(config, earlyAnswers.format);
+
+ return void 0;
}
// continue with the questions otherwise...
- inquirer.prompt([
+ return inquirer.prompt([
{
type: "confirm",
name: "es6",
@@ -412,25 +408,21 @@ function promptUser(callback) {
return answers.jsx;
}
}
- ], secondAnswers => {
+ ]).then(secondAnswers => {
// early exit if you are using automatic style generation
if (earlyAnswers.source === "auto") {
- try {
- const combinedAnswers = Object.assign({}, earlyAnswers, secondAnswers);
-
- config = processAnswers(combinedAnswers);
- installModules(config);
- writeFile(config, earlyAnswers.format);
- } catch (err) {
- callback(err);
- return;
- }
- return;
+ const combinedAnswers = Object.assign({}, earlyAnswers, secondAnswers);
+
+ config = processAnswers(combinedAnswers);
+ installModules(config);
+ writeFile(config, earlyAnswers.format);
+
+ return void 0;
}
// continue with the style questions otherwise...
- inquirer.prompt([
+ return inquirer.prompt([
{
type: "list",
name: "indent",
@@ -465,16 +457,12 @@ function promptUser(callback) {
default: "JavaScript",
choices: ["JavaScript", "YAML", "JSON"]
}
- ], answers => {
- try {
- const totalAnswers = Object.assign({}, earlyAnswers, secondAnswers, answers);
-
- config = processAnswers(totalAnswers);
- installModules(config);
- writeFile(config, answers.format);
- } catch (err) {
- callback(err); // eslint-disable-line callback-return
- }
+ ]).then(answers => {
+ const totalAnswers = Object.assign({}, earlyAnswers, secondAnswers, answers);
+
+ config = processAnswers(totalAnswers);
+ installModules(config);
+ writeFile(config, answers.format);
});
});
});
@@ -487,8 +475,8 @@ function promptUser(callback) {
const init = {
getConfigForStyleGuide,
processAnswers,
- /* istanbul ignore next */initializeConfig(callback) {
- promptUser(callback);
+ /* istanbul ignore next */initializeConfig() {
+ return promptUser();
}
};
diff --git a/tools/eslint/lib/config/config-ops.js b/tools/eslint/lib/config/config-ops.js
index 52dea1a106df79..e1d9a90135716d 100644
--- a/tools/eslint/lib/config/config-ops.js
+++ b/tools/eslint/lib/config/config-ops.js
@@ -9,8 +9,6 @@
// Requirements
//------------------------------------------------------------------------------
-const Environments = require("./environments");
-
const debug = require("debug")("eslint:config-ops");
//------------------------------------------------------------------------------
@@ -46,10 +44,11 @@ module.exports = {
/**
* Creates an environment config based on the specified environments.
* @param {Object} env The environment settings.
+ * @param {Environments} envContext The environment context.
* @returns {Object} A configuration object with the appropriate rules and globals
* set.
*/
- createEnvironmentConfig(env) {
+ createEnvironmentConfig(env, envContext) {
const envConfig = this.createEmptyConfig();
@@ -58,7 +57,7 @@ module.exports = {
envConfig.env = env;
Object.keys(env).filter(name => env[name]).forEach(name => {
- const environment = Environments.get(name);
+ const environment = envContext.get(name);
if (environment) {
debug(`Creating config for environment ${name}`);
@@ -80,12 +79,13 @@ module.exports = {
* Given a config with environment settings, applies the globals and
* ecmaFeatures to the configuration and returns the result.
* @param {Object} config The configuration information.
+ * @param {Environments} envContent env context.
* @returns {Object} The updated configuration information.
*/
- applyEnvironments(config) {
+ applyEnvironments(config, envContent) {
if (config.env && typeof config.env === "object") {
debug("Apply environment settings to config");
- return this.merge(this.createEnvironmentConfig(config.env), config);
+ return this.merge(this.createEnvironmentConfig(config.env, envContent), config);
}
return config;
@@ -175,7 +175,7 @@ module.exports = {
}
Object.keys(src).forEach(key => {
if (Array.isArray(src[key]) || Array.isArray(target[key])) {
- dst[key] = deepmerge(target[key], src[key], key === "plugins", isRule);
+ dst[key] = deepmerge(target[key], src[key], key === "plugins" || key === "extends", isRule);
} else if (typeof src[key] !== "object" || !src[key] || key === "exported" || key === "astGlobals") {
dst[key] = src[key];
} else {
diff --git a/tools/eslint/lib/config/config-rule.js b/tools/eslint/lib/config/config-rule.js
index a8a073caa3707d..174b34a47d6bb0 100644
--- a/tools/eslint/lib/config/config-rule.js
+++ b/tools/eslint/lib/config/config-rule.js
@@ -9,9 +9,10 @@
// Requirements
//------------------------------------------------------------------------------
-const rules = require("../rules"),
+const Rules = require("../rules"),
loadRules = require("../load-rules");
+const rules = new Rules();
//------------------------------------------------------------------------------
// Helpers
@@ -168,16 +169,16 @@ function combinePropertyObjects(objArr1, objArr2) {
return res;
}
- /**
- * Creates a new instance of a rule configuration set
- *
- * A rule configuration set is an array of configurations that are valid for a
- * given rule. For example, the configuration set for the "semi" rule could be:
- *
- * ruleConfigSet.ruleConfigs // -> [[2], [2, "always"], [2, "never"]]
- *
- * Rule configuration set class
- */
+/**
+ * Creates a new instance of a rule configuration set
+ *
+ * A rule configuration set is an array of configurations that are valid for a
+ * given rule. For example, the configuration set for the "semi" rule could be:
+ *
+ * ruleConfigSet.ruleConfigs // -> [[2], [2, "always"], [2, "never"]]
+ *
+ * Rule configuration set class
+ */
class RuleConfigSet {
/**
diff --git a/tools/eslint/lib/config/config-validator.js b/tools/eslint/lib/config/config-validator.js
index 36e0e9fddb32ae..329a5087df9e41 100644
--- a/tools/eslint/lib/config/config-validator.js
+++ b/tools/eslint/lib/config/config-validator.js
@@ -9,9 +9,8 @@
// Requirements
//------------------------------------------------------------------------------
-const rules = require("../rules"),
- Environments = require("./environments"),
- schemaValidator = require("is-my-json-valid"),
+const schemaValidator = require("is-my-json-valid"),
+ configSchema = require("../../conf/config-schema.json"),
util = require("util");
const validators = {
@@ -25,10 +24,11 @@ const validators = {
/**
* Gets a complete options schema for a rule.
* @param {string} id The rule's unique name.
+ * @param {Rules} rulesContext Rule context
* @returns {Object} JSON Schema for the rule's options.
*/
-function getRuleOptionsSchema(id) {
- const rule = rules.get(id),
+function getRuleOptionsSchema(id, rulesContext) {
+ const rule = rulesContext.get(id),
schema = rule && rule.schema || rule && rule.meta && rule.meta.schema;
// Given a tuple of schemas, insert warning level at the beginning
@@ -72,10 +72,11 @@ function validateRuleSeverity(options) {
* Validates the non-severity options passed to a rule, based on its schema.
* @param {string} id The rule's unique name
* @param {array} localOptions The options for the rule, excluding severity
+* @param {Rules} rulesContext Rule context
* @returns {void}
*/
-function validateRuleSchema(id, localOptions) {
- const schema = getRuleOptionsSchema(id);
+function validateRuleSchema(id, localOptions, rulesContext) {
+ const schema = getRuleOptionsSchema(id, rulesContext);
if (!validators.rules[id] && schema) {
validators.rules[id] = schemaValidator(schema, { verbose: true });
@@ -95,15 +96,16 @@ function validateRuleSchema(id, localOptions) {
* Validates a rule's options against its schema.
* @param {string} id The rule's unique name.
* @param {array|number} options The given options for the rule.
- * @param {string} source The name of the configuration source.
+ * @param {string} source The name of the configuration source to report in any errors.
+ * @param {Rules} rulesContext Rule context
* @returns {void}
*/
-function validateRuleOptions(id, options, source) {
+function validateRuleOptions(id, options, source, rulesContext) {
try {
const severity = validateRuleSeverity(options);
if (severity !== 0 && !(typeof severity === "string" && severity.toLowerCase() === "off")) {
- validateRuleSchema(id, Array.isArray(options) ? options.slice(1) : []);
+ validateRuleSchema(id, Array.isArray(options) ? options.slice(1) : [], rulesContext);
}
} catch (err) {
throw new Error(`${source}:\n\tConfiguration for rule "${id}" is invalid:\n${err.message}`);
@@ -113,51 +115,91 @@ function validateRuleOptions(id, options, source) {
/**
* Validates an environment object
* @param {Object} environment The environment config object to validate.
- * @param {string} source The location to report with any errors.
+ * @param {string} source The name of the configuration source to report in any errors.
+ * @param {Environments} envContext Env context
* @returns {void}
*/
-function validateEnvironment(environment, source) {
+function validateEnvironment(environment, source, envContext) {
// not having an environment is ok
if (!environment) {
return;
}
- if (Array.isArray(environment)) {
- throw new Error("Environment must not be an array");
- }
+ Object.keys(environment).forEach(env => {
+ if (!envContext.get(env)) {
+ const message = `${source}:\n\tEnvironment key "${env}" is unknown\n`;
+
+ throw new Error(message);
+ }
+ });
+}
- if (typeof environment === "object") {
- Object.keys(environment).forEach(env => {
- if (!Environments.get(env)) {
- const message = [
- source, ":\n",
- "\tEnvironment key \"", env, "\" is unknown\n"
- ];
-
- throw new Error(message.join(""));
- }
- });
- } else {
- throw new Error("Environment must be an object");
+/**
+ * Validates a rules config object
+ * @param {Object} rulesConfig The rules config object to validate.
+ * @param {string} source The name of the configuration source to report in any errors.
+ * @param {Rules} rulesContext Rule context
+ * @returns {void}
+ */
+function validateRules(rulesConfig, source, rulesContext) {
+ if (!rulesConfig) {
+ return;
}
+
+ Object.keys(rulesConfig).forEach(id => {
+ validateRuleOptions(id, rulesConfig[id], source, rulesContext);
+ });
}
/**
- * Validates an entire config object.
+ * Formats an array of schema validation errors.
+ * @param {Array} errors An array of error messages to format.
+ * @returns {string} Formatted error message
+ */
+function formatErrors(errors) {
+
+ return errors.map(error => {
+ if (error.message === "has additional properties") {
+ return `Unexpected top-level property "${error.value.replace(/^data\./, "")}"`;
+ }
+ if (error.message === "is the wrong type") {
+ const formattedField = error.field.replace(/^data\./, "");
+ const formattedExpectedType = typeof error.type === "string" ? error.type : error.type.join("/");
+ const formattedValue = JSON.stringify(error.value);
+
+ return `Property "${formattedField}" is the wrong type (expected ${formattedExpectedType} but got \`${formattedValue}\`)`;
+ }
+ return `"${error.field.replace(/^(data\.)/, "")}" ${error.message}. Value: ${error.value}`;
+ }).map(message => `\t- ${message}.\n`).join("");
+}
+
+/**
+ * Validates the top level properties of the config object.
* @param {Object} config The config object to validate.
- * @param {string} source The location to report with any errors.
+ * @param {string} source The name of the configuration source to report in any errors.
* @returns {void}
*/
-function validate(config, source) {
+function validateConfigSchema(config, source) {
+ const validator = schemaValidator(configSchema, { verbose: true });
- if (typeof config.rules === "object") {
- Object.keys(config.rules).forEach(id => {
- validateRuleOptions(id, config.rules[id], source);
- });
+ if (!validator(config)) {
+ throw new Error(`${source}:\n\tESLint configuration is invalid:\n${formatErrors(validator.errors)}`);
}
+}
- validateEnvironment(config.env, source);
+/**
+ * Validates an entire config object.
+ * @param {Object} config The config object to validate.
+ * @param {string} source The name of the configuration source to report in any errors.
+ * @param {Rules} rulesContext The rules context
+ * @param {Environments} envContext The env context
+ * @returns {void}
+ */
+function validate(config, source, rulesContext, envContext) {
+ validateConfigSchema(config, source);
+ validateRules(config.rules, source, rulesContext);
+ validateEnvironment(config.env, source, envContext);
}
//------------------------------------------------------------------------------
diff --git a/tools/eslint/lib/config/environments.js b/tools/eslint/lib/config/environments.js
index 5c34da9328a4da..1ec9438af5de2a 100644
--- a/tools/eslint/lib/config/environments.js
+++ b/tools/eslint/lib/config/environments.js
@@ -11,32 +11,30 @@
const envs = require("../../conf/environments");
//------------------------------------------------------------------------------
-// Private
+// Public Interface
//------------------------------------------------------------------------------
-let environments = new Map();
+class Environments {
-/**
- * Loads the default environments.
- * @returns {void}
- * @private
- */
-function load() {
- Object.keys(envs).forEach(envName => {
- environments.set(envName, envs[envName]);
- });
-}
-
-// always load default environments upfront
-load();
-
-//------------------------------------------------------------------------------
-// Public Interface
-//------------------------------------------------------------------------------
+ /**
+ * create env context
+ */
+ constructor() {
+ this._environments = new Map();
-module.exports = {
+ this.load();
+ }
- load,
+ /**
+ * Loads the default environments.
+ * @returns {void}
+ * @private
+ */
+ load() {
+ Object.keys(envs).forEach(envName => {
+ this._environments.set(envName, envs[envName]);
+ });
+ }
/**
* Gets the environment with the given name.
@@ -44,8 +42,19 @@ module.exports = {
* @returns {Object?} The environment object or null if not found.
*/
get(name) {
- return environments.get(name) || null;
- },
+ return this._environments.get(name) || null;
+ }
+
+ /**
+ * Gets all the environment present
+ * @returns {Object} The environment object for each env name
+ */
+ getAll() {
+ return Array.from(this._environments).reduce((coll, env) => {
+ coll[env[0]] = env[1];
+ return coll;
+ }, {});
+ }
/**
* Defines an environment.
@@ -54,8 +63,8 @@ module.exports = {
* @returns {void}
*/
define(name, env) {
- environments.set(name, env);
- },
+ this._environments.set(name, env);
+ }
/**
* Imports all environments from a plugin.
@@ -69,14 +78,7 @@ module.exports = {
this.define(`${pluginName}/${envName}`, plugin.environments[envName]);
});
}
- },
-
- /**
- * Resets all environments. Only use for tests!
- * @returns {void}
- */
- testReset() {
- environments = new Map();
- load();
}
-};
+}
+
+module.exports = Environments;
diff --git a/tools/eslint/lib/config/plugins.js b/tools/eslint/lib/config/plugins.js
index e28a77929c0b5f..11852df5c968fa 100644
--- a/tools/eslint/lib/config/plugins.js
+++ b/tools/eslint/lib/config/plugins.js
@@ -8,56 +8,61 @@
// Requirements
//------------------------------------------------------------------------------
-const Environments = require("./environments"),
- Rules = require("../rules");
-
const debug = require("debug")("eslint:plugins");
//------------------------------------------------------------------------------
// Private
//------------------------------------------------------------------------------
-let plugins = Object.create(null);
-
const PLUGIN_NAME_PREFIX = "eslint-plugin-",
NAMESPACE_REGEX = /^@.*\//i;
-/**
- * Removes the prefix `eslint-plugin-` from a plugin name.
- * @param {string} pluginName The name of the plugin which may have the prefix.
- * @returns {string} The name of the plugin without prefix.
- */
-function removePrefix(pluginName) {
- return pluginName.indexOf(PLUGIN_NAME_PREFIX) === 0 ? pluginName.substring(PLUGIN_NAME_PREFIX.length) : pluginName;
-}
+//------------------------------------------------------------------------------
+// Public Interface
+//------------------------------------------------------------------------------
/**
- * Gets the scope (namespace) of a plugin.
- * @param {string} pluginName The name of the plugin which may have the prefix.
- * @returns {string} The name of the plugins namepace if it has one.
+ * Plugin class
*/
-function getNamespace(pluginName) {
- return pluginName.match(NAMESPACE_REGEX) ? pluginName.match(NAMESPACE_REGEX)[0] : "";
-}
+class Plugins {
-/**
- * Removes the namespace from a plugin name.
- * @param {string} pluginName The name of the plugin which may have the prefix.
- * @returns {string} The name of the plugin without the namespace.
- */
-function removeNamespace(pluginName) {
- return pluginName.replace(NAMESPACE_REGEX, "");
-}
+ /**
+ * Creates the plugins context
+ * @param {Environments} envContext - env context
+ * @param {Rules} rulesContext - rules context
+ */
+ constructor(envContext, rulesContext) {
+ this._plugins = Object.create(null);
+ this._environments = envContext;
+ this._rules = rulesContext;
+ }
-//------------------------------------------------------------------------------
-// Public Interface
-//------------------------------------------------------------------------------
+ /**
+ * Removes the prefix `eslint-plugin-` from a plugin name.
+ * @param {string} pluginName The name of the plugin which may have the prefix.
+ * @returns {string} The name of the plugin without prefix.
+ */
+ static removePrefix(pluginName) {
+ return pluginName.startsWith(PLUGIN_NAME_PREFIX) ? pluginName.substring(PLUGIN_NAME_PREFIX.length) : pluginName;
+ }
-module.exports = {
+ /**
+ * Gets the scope (namespace) of a plugin.
+ * @param {string} pluginName The name of the plugin which may have the prefix.
+ * @returns {string} The name of the plugins namepace if it has one.
+ */
+ static getNamespace(pluginName) {
+ return pluginName.match(NAMESPACE_REGEX) ? pluginName.match(NAMESPACE_REGEX)[0] : "";
+ }
- removePrefix,
- getNamespace,
- removeNamespace,
+ /**
+ * Removes the namespace from a plugin name.
+ * @param {string} pluginName The name of the plugin which may have the prefix.
+ * @returns {string} The name of the plugin without the namespace.
+ */
+ static removeNamespace(pluginName) {
+ return pluginName.replace(NAMESPACE_REGEX, "");
+ }
/**
* Defines a plugin with a given name rather than loading from disk.
@@ -66,22 +71,16 @@ module.exports = {
* @returns {void}
*/
define(pluginName, plugin) {
- const pluginNamespace = getNamespace(pluginName),
- pluginNameWithoutNamespace = removeNamespace(pluginName),
- pluginNameWithoutPrefix = removePrefix(pluginNameWithoutNamespace),
+ const pluginNamespace = Plugins.getNamespace(pluginName),
+ pluginNameWithoutNamespace = Plugins.removeNamespace(pluginName),
+ pluginNameWithoutPrefix = Plugins.removePrefix(pluginNameWithoutNamespace),
shortName = pluginNamespace + pluginNameWithoutPrefix;
// load up environments and rules
- plugins[shortName] = plugin;
- Environments.importPlugin(plugin, shortName);
- Rules.importPlugin(plugin, shortName);
-
- // load up environments and rules for the name that '@scope/' was omitted
- // 3 lines below will be removed by 4.0.0
- plugins[pluginNameWithoutPrefix] = plugin;
- Environments.importPlugin(plugin, pluginNameWithoutPrefix);
- Rules.importPlugin(plugin, pluginNameWithoutPrefix);
- },
+ this._plugins[shortName] = plugin;
+ this._environments.importPlugin(plugin, shortName);
+ this._rules.importPlugin(plugin, shortName);
+ }
/**
* Gets a plugin with the given name.
@@ -89,16 +88,16 @@ module.exports = {
* @returns {Object} The plugin or null if not loaded.
*/
get(pluginName) {
- return plugins[pluginName] || null;
- },
+ return this._plugins[pluginName] || null;
+ }
/**
* Returns all plugins that are loaded.
* @returns {Object} The plugins cache.
*/
getAll() {
- return plugins;
- },
+ return this._plugins;
+ }
/**
* Loads a plugin with the given name.
@@ -107,9 +106,9 @@ module.exports = {
* @throws {Error} If the plugin cannot be loaded.
*/
load(pluginName) {
- const pluginNamespace = getNamespace(pluginName),
- pluginNameWithoutNamespace = removeNamespace(pluginName),
- pluginNameWithoutPrefix = removePrefix(pluginNameWithoutNamespace),
+ const pluginNamespace = Plugins.getNamespace(pluginName),
+ pluginNameWithoutNamespace = Plugins.removeNamespace(pluginName),
+ pluginNameWithoutPrefix = Plugins.removePrefix(pluginNameWithoutNamespace),
shortName = pluginNamespace + pluginNameWithoutPrefix,
longName = pluginNamespace + PLUGIN_NAME_PREFIX + pluginNameWithoutPrefix;
let plugin = null;
@@ -124,7 +123,7 @@ module.exports = {
throw whitespaceError;
}
- if (!plugins[shortName]) {
+ if (!this._plugins[shortName]) {
try {
plugin = require(longName);
} catch (pluginLoadErr) {
@@ -150,7 +149,7 @@ module.exports = {
this.define(pluginName, plugin);
}
- },
+ }
/**
* Loads all plugins from an array.
@@ -160,13 +159,7 @@ module.exports = {
*/
loadAll(pluginNames) {
pluginNames.forEach(this.load, this);
- },
-
- /**
- * Resets plugin information. Use for tests only.
- * @returns {void}
- */
- testReset() {
- plugins = Object.create(null);
}
-};
+}
+
+module.exports = Plugins;
diff --git a/tools/eslint/lib/file-finder.js b/tools/eslint/lib/file-finder.js
index acb886c9d1e2c2..3458bbf52a4145 100644
--- a/tools/eslint/lib/file-finder.js
+++ b/tools/eslint/lib/file-finder.js
@@ -25,6 +25,7 @@ const fs = require("fs"),
*/
function getDirectoryEntries(directory) {
try {
+
return fs.readdirSync(directory);
} catch (ex) {
return [];
@@ -79,9 +80,9 @@ class FileFinder {
* Searches for all the file names in this.fileNames.
* Is currently used by lib/config.js to find .eslintrc and package.json files.
* @param {string} directory The directory to start the search from.
- * @returns {string[]} The file paths found.
+ * @returns {GeneratorFunction} to iterate the file paths found
*/
- findAllInDirectoryAndParents(directory) {
+ *findAllInDirectoryAndParents(directory) {
const cache = this.cache;
if (directory) {
@@ -91,7 +92,8 @@ class FileFinder {
}
if (cache.hasOwnProperty(directory)) {
- return cache[directory];
+ yield* cache[directory];
+ return; // to avoid doing the normal loop afterwards
}
const dirs = [];
@@ -114,19 +116,21 @@ class FileFinder {
for (let j = 0; j < searched; j++) {
cache[dirs[j]].push(filePath);
}
-
+ yield filePath;
break;
}
}
}
+
const child = directory;
// Assign parent directory to directory.
directory = path.dirname(directory);
if (directory === child) {
- return cache[dirs[0]];
+ return;
}
+
} while (!cache.hasOwnProperty(directory));
// Add what has been cached previously to the cache of each directory searched.
@@ -134,7 +138,7 @@ class FileFinder {
dirs.push.apply(cache[dirs[i]], cache[directory]);
}
- return cache[dirs[0]];
+ yield* cache[dirs[0]];
}
}
diff --git a/tools/eslint/lib/formatters/codeframe.js b/tools/eslint/lib/formatters/codeframe.js
index 1191ccb8efaae9..ed50ae608d48b0 100644
--- a/tools/eslint/lib/formatters/codeframe.js
+++ b/tools/eslint/lib/formatters/codeframe.js
@@ -74,11 +74,14 @@ function formatMessage(message, parentResult) {
* Gets the formatted output summary for a given number of errors and warnings.
* @param {number} errors The number of errors.
* @param {number} warnings The number of warnings.
+ * @param {number} fixableErrors The number of fixable errors.
+ * @param {number} fixableWarnings The number of fixable warnings.
* @returns {string} The formatted output summary.
*/
-function formatSummary(errors, warnings) {
+function formatSummary(errors, warnings, fixableErrors, fixableWarnings) {
const summaryColor = errors > 0 ? "red" : "yellow";
const summary = [];
+ const fixablesSummary = [];
if (errors > 0) {
summary.push(`${errors} ${pluralize("error", errors)}`);
@@ -88,7 +91,21 @@ function formatSummary(errors, warnings) {
summary.push(`${warnings} ${pluralize("warning", warnings)}`);
}
- return chalk[summaryColor].bold(`${summary.join(" and ")} found.`);
+ if (fixableErrors > 0) {
+ fixablesSummary.push(`${fixableErrors} ${pluralize("error", fixableErrors)}`);
+ }
+
+ if (fixableWarnings > 0) {
+ fixablesSummary.push(`${fixableWarnings} ${pluralize("warning", fixableWarnings)}`);
+ }
+
+ let output = chalk[summaryColor].bold(`${summary.join(" and ")} found.`);
+
+ if (fixableErrors || fixableWarnings) {
+ output += chalk[summaryColor].bold(`\n${fixablesSummary.join(" and ")} potentially fixable with the \`--fix\` option.`);
+ }
+
+ return output;
}
//------------------------------------------------------------------------------
@@ -98,6 +115,9 @@ function formatSummary(errors, warnings) {
module.exports = function(results) {
let errors = 0;
let warnings = 0;
+ let fixableErrors = 0;
+ let fixableWarnings = 0;
+
const resultsWithMessages = results.filter(result => result.messages.length > 0);
let output = resultsWithMessages.reduce((resultsOutput, result) => {
@@ -105,12 +125,14 @@ module.exports = function(results) {
errors += result.errorCount;
warnings += result.warningCount;
+ fixableErrors += result.fixableErrorCount;
+ fixableWarnings += result.fixableWarningCount;
return resultsOutput.concat(messages);
}, []).join("\n");
output += "\n";
- output += formatSummary(errors, warnings);
+ output += formatSummary(errors, warnings, fixableErrors, fixableWarnings);
return (errors + warnings) > 0 ? output : "";
};
diff --git a/tools/eslint/lib/formatters/stylish.js b/tools/eslint/lib/formatters/stylish.js
index c19b95d6e3b7be..4ec97a31af5bac 100644
--- a/tools/eslint/lib/formatters/stylish.js
+++ b/tools/eslint/lib/formatters/stylish.js
@@ -28,8 +28,10 @@ function pluralize(word, count) {
module.exports = function(results) {
let output = "\n",
- errors = 0,
- warnings = 0,
+ errorCount = 0,
+ warningCount = 0,
+ fixableErrorCount = 0,
+ fixableWarningCount = 0,
summaryColor = "yellow";
results.forEach(result => {
@@ -39,8 +41,10 @@ module.exports = function(results) {
return;
}
- errors += result.errorCount;
- warnings += result.warningCount;
+ errorCount += result.errorCount;
+ warningCount += result.warningCount;
+ fixableErrorCount += result.fixableErrorCount;
+ fixableWarningCount += result.fixableWarningCount;
output += `${chalk.underline(result.filePath)}\n`;
@@ -73,14 +77,22 @@ module.exports = function(results) {
).split("\n").map(el => el.replace(/(\d+)\s+(\d+)/, (m, p1, p2) => chalk.dim(`${p1}:${p2}`))).join("\n")}\n\n`;
});
- const total = errors + warnings;
+ const total = errorCount + warningCount;
if (total > 0) {
output += chalk[summaryColor].bold([
"\u2716 ", total, pluralize(" problem", total),
- " (", errors, pluralize(" error", errors), ", ",
- warnings, pluralize(" warning", warnings), ")\n"
+ " (", errorCount, pluralize(" error", errorCount), ", ",
+ warningCount, pluralize(" warning", warningCount), ")\n"
].join(""));
+
+ if (fixableErrorCount > 0 || fixableWarningCount > 0) {
+ output += chalk[summaryColor].bold([
+ " ", fixableErrorCount, pluralize(" error", fixableErrorCount), ", ",
+ fixableWarningCount, pluralize(" warning", fixableWarningCount),
+ " potentially fixable with the `--fix` option.\n"
+ ].join(""));
+ }
}
return total > 0 ? output : "";
diff --git a/tools/eslint/lib/formatters/table.js b/tools/eslint/lib/formatters/table.js
index b4859154ba610d..ebc3314e7ad6d1 100644
--- a/tools/eslint/lib/formatters/table.js
+++ b/tools/eslint/lib/formatters/table.js
@@ -9,7 +9,7 @@
//------------------------------------------------------------------------------
const chalk = require("chalk"),
- table = require("table").default,
+ table = require("table").table,
pluralize = require("pluralize");
//------------------------------------------------------------------------------
diff --git a/tools/eslint/lib/ignored-paths.js b/tools/eslint/lib/ignored-paths.js
index cfca7fa4ff1c3b..0d9152495ecac5 100644
--- a/tools/eslint/lib/ignored-paths.js
+++ b/tools/eslint/lib/ignored-paths.js
@@ -12,7 +12,6 @@
const fs = require("fs"),
path = require("path"),
ignore = require("ignore"),
- shell = require("shelljs"),
pathUtil = require("./util/path-util");
const debug = require("debug")("eslint:ignored-paths");
@@ -54,7 +53,7 @@ function findIgnoreFile(cwd) {
const ignoreFilePath = path.resolve(cwd, ESLINT_IGNORE_FILENAME);
- return shell.test("-f", ignoreFilePath) ? ignoreFilePath : "";
+ return fs.existsSync(ignoreFilePath) && fs.statSync(ignoreFilePath).isFile() ? ignoreFilePath : "";
}
/**
@@ -179,7 +178,7 @@ class IgnoredPaths {
let result = false;
const absolutePath = path.resolve(this.options.cwd, filepath);
- const relativePath = pathUtil.getRelativePath(absolutePath, this.options.cwd);
+ const relativePath = pathUtil.getRelativePath(absolutePath, this.baseDir);
if ((typeof category === "undefined") || (category === "default")) {
result = result || (this.ig.default.filter([relativePath]).length === 0);
@@ -213,15 +212,7 @@ class IgnoredPaths {
const filter = ig.createFilter();
- /**
- * TODO
- * 1.
- * Actually, it should be `this.options.baseDir`, which is the base dir of `ignore-path`,
- * as well as Line 177.
- * But doing this leads to a breaking change and fails tests.
- * Related to #6759
- */
- const base = this.options.cwd;
+ const base = this.baseDir;
return function(absolutePath) {
const relative = pathUtil.getRelativePath(absolutePath, base);
diff --git a/tools/eslint/lib/eslint.js b/tools/eslint/lib/linter.js
similarity index 73%
rename from tools/eslint/lib/eslint.js
rename to tools/eslint/lib/linter.js
index a9066c4c8b6884..25af05223d012f 100755
--- a/tools/eslint/lib/eslint.js
+++ b/tools/eslint/lib/linter.js
@@ -1,6 +1,6 @@
/**
- * @fileoverview Main ESLint object.
- * @author Nicholas C. Zakas
+ * @fileoverview Main Linter Class
+ * @author Gyandeep Singh
*/
"use strict";
@@ -11,22 +11,22 @@
const assert = require("assert"),
EventEmitter = require("events").EventEmitter,
- escope = require("escope"),
+ eslintScope = require("eslint-scope"),
levn = require("levn"),
blankScriptAST = require("../conf/blank-script.json"),
- DEFAULT_PARSER = require("../conf/eslint-recommended").parser,
+ defaultConfig = require("../conf/default-config-options.js"),
replacements = require("../conf/replacements.json"),
CodePathAnalyzer = require("./code-path-analysis/code-path-analyzer"),
ConfigOps = require("./config/config-ops"),
validator = require("./config/config-validator"),
Environments = require("./config/environments"),
- CommentEventGenerator = require("./util/comment-event-generator"),
NodeEventGenerator = require("./util/node-event-generator"),
SourceCode = require("./util/source-code"),
Traverser = require("./util/traverser"),
RuleContext = require("./rule-context"),
- rules = require("./rules"),
+ Rules = require("./rules"),
timing = require("./timing"),
+ astUtils = require("./ast-utils"),
pkg = require("../package.json");
@@ -158,19 +158,20 @@ function parseListConfig(string) {
* @param {ASTNode} program The top node of the AST.
* @param {Scope} globalScope The global scope.
* @param {Object} config The existing configuration data.
+ * @param {Environments} envContext Env context
* @returns {void}
*/
-function addDeclaredGlobals(program, globalScope, config) {
+function addDeclaredGlobals(program, globalScope, config, envContext) {
const declaredGlobals = {},
exportedGlobals = {},
explicitGlobals = {},
- builtin = Environments.get("builtin");
+ builtin = envContext.get("builtin");
Object.assign(declaredGlobals, builtin);
Object.keys(config.env).forEach(name => {
if (config.env[name]) {
- const env = Environments.get(name),
+ const env = envContext.get(name),
environmentGlobals = env && env.globals;
if (environmentGlobals) {
@@ -187,7 +188,7 @@ function addDeclaredGlobals(program, globalScope, config) {
let variable = globalScope.set.get(name);
if (!variable) {
- variable = new escope.Variable(name, globalScope);
+ variable = new eslintScope.Variable(name, globalScope);
variable.eslintExplicitGlobal = false;
globalScope.variables.push(variable);
globalScope.set.set(name, variable);
@@ -199,7 +200,7 @@ function addDeclaredGlobals(program, globalScope, config) {
let variable = globalScope.set.get(name);
if (!variable) {
- variable = new escope.Variable(name, globalScope);
+ variable = new eslintScope.Variable(name, globalScope);
variable.eslintExplicitGlobal = true;
variable.eslintExplicitGlobalComment = explicitGlobals[name].comment;
globalScope.variables.push(variable);
@@ -314,11 +315,10 @@ function enableReporting(reportingConfig, start, rulesToEnable) {
* @param {string} filename The file being checked.
* @param {ASTNode} ast The top node of the AST.
* @param {Object} config The existing configuration data.
- * @param {Object[]} reportingConfig The existing reporting configuration data.
- * @param {Object[]} messages The messages queue.
+ * @param {Linter} linterContext Linter context object
* @returns {Object} Modified config object
*/
-function modifyConfigsFromComments(filename, ast, config, reportingConfig, messages) {
+function modifyConfigsFromComments(filename, ast, config, linterContext) {
let commentConfig = {
exported: {},
@@ -327,6 +327,8 @@ function modifyConfigsFromComments(filename, ast, config, reportingConfig, messa
env: {}
};
const commentRules = {};
+ const messages = linterContext.messages;
+ const reportingConfig = linterContext.reportingConfig;
ast.comments.forEach(comment => {
@@ -365,7 +367,7 @@ function modifyConfigsFromComments(filename, ast, config, reportingConfig, messa
Object.keys(items).forEach(name => {
const ruleValue = items[name];
- validator.validateRuleOptions(name, ruleValue, `${filename} line ${comment.loc.start.line}`);
+ validator.validateRuleOptions(name, ruleValue, `${filename} line ${comment.loc.start.line}`, linterContext.rules);
commentRules[name] = ruleValue;
});
break;
@@ -373,7 +375,7 @@ function modifyConfigsFromComments(filename, ast, config, reportingConfig, messa
// no default
}
- } else { // comment.type === "Line"
+ } else { // comment.type === "Line"
if (match[1] === "eslint-disable-line") {
disableReporting(reportingConfig, { line: comment.loc.start.line, column: 0 }, Object.keys(parseListConfig(value)));
enableReporting(reportingConfig, comment.loc.end, Object.keys(parseListConfig(value)));
@@ -387,7 +389,7 @@ function modifyConfigsFromComments(filename, ast, config, reportingConfig, messa
// apply environment configs
Object.keys(commentConfig.env).forEach(name => {
- const env = Environments.get(name);
+ const env = linterContext.environments.get(name);
if (env) {
commentConfig = ConfigOps.merge(commentConfig, env);
@@ -446,15 +448,13 @@ function normalizeEcmaVersion(ecmaVersion, isModule) {
/**
* Process initial config to make it safe to extend by file comment config
* @param {Object} config Initial config
+ * @param {Environments} envContext Env context
* @returns {Object} Processed config
*/
-function prepareConfig(config) {
-
- config.globals = config.globals || config.global || {};
- delete config.global;
-
- const copiedRules = {};
- let parserOptions = {};
+function prepareConfig(config, envContext) {
+ config.globals = config.globals || {};
+ const copiedRules = Object.assign({}, defaultConfig.rules);
+ let parserOptions = Object.assign({}, defaultConfig.parserOptions);
if (typeof config.rules === "object") {
Object.keys(config.rules).forEach(k => {
@@ -474,7 +474,7 @@ function prepareConfig(config) {
// merge in environment parserOptions
if (typeof config.env === "object") {
Object.keys(config.env).forEach(envName => {
- const env = Environments.get(envName);
+ const env = envContext.get(envName);
if (config.env[envName] && env && env.parserOptions) {
parserOptions = ConfigOps.merge(parserOptions, env.parserOptions);
@@ -484,21 +484,18 @@ function prepareConfig(config) {
const preparedConfig = {
rules: copiedRules,
- parser: config.parser || DEFAULT_PARSER,
- globals: ConfigOps.merge({}, config.globals),
- env: ConfigOps.merge({}, config.env || {}),
- settings: ConfigOps.merge({}, config.settings || {}),
+ parser: config.parser || defaultConfig.parser,
+ globals: ConfigOps.merge(defaultConfig.globals, config.globals),
+ env: ConfigOps.merge(defaultConfig.env, config.env || {}),
+ settings: ConfigOps.merge(defaultConfig.settings, config.settings || {}),
parserOptions: ConfigOps.merge(parserOptions, config.parserOptions || {})
};
const isModule = preparedConfig.parserOptions.sourceType === "module";
if (isModule) {
- if (!preparedConfig.parserOptions.ecmaFeatures) {
- preparedConfig.parserOptions.ecmaFeatures = {};
- }
// can't have global return inside of modules
- preparedConfig.parserOptions.ecmaFeatures.globalReturn = false;
+ preparedConfig.parserOptions.ecmaFeatures = Object.assign({}, preparedConfig.parserOptions.ecmaFeatures, { globalReturn: false });
}
preparedConfig.parserOptions.ecmaVersion = normalizeEcmaVersion(preparedConfig.parserOptions.ecmaVersion, isModule);
@@ -586,150 +583,157 @@ function stripUnicodeBOM(text) {
return text;
}
-//------------------------------------------------------------------------------
-// Public Interface
-//------------------------------------------------------------------------------
-
/**
- * Object that is responsible for verifying JavaScript text
- * @name eslint
+ * Get the severity level of a rule (0 - none, 1 - warning, 2 - error)
+ * Returns 0 if the rule config is not valid (an Array or a number)
+ * @param {Array|number} ruleConfig rule configuration
+ * @returns {number} 0, 1, or 2, indicating rule severity
*/
-module.exports = (function() {
-
- const api = Object.create(new EventEmitter());
- let messages = [],
- currentConfig = null,
- currentScopes = null,
- scopeManager = null,
- currentFilename = null,
- traverser = null,
- reportingConfig = [],
- sourceCode = null;
-
- /**
- * Parses text into an AST. Moved out here because the try-catch prevents
- * optimization of functions, so it's best to keep the try-catch as isolated
- * as possible
- * @param {string} text The text to parse.
- * @param {Object} config The ESLint configuration object.
- * @param {string} filePath The path to the file being parsed.
- * @returns {ASTNode|CustomParseResult} The AST or parse result if successful,
- * or null if not.
- * @private
- */
- function parse(text, config, filePath) {
-
- let parser,
- parserOptions = {
- loc: true,
- range: true,
- raw: true,
- tokens: true,
- comment: true,
- attachComment: true,
- filePath
- };
-
- try {
- parser = require(config.parser);
- } catch (ex) {
- messages.push({
- ruleId: null,
- fatal: true,
- severity: 2,
- source: null,
- message: ex.message,
- line: 0,
- column: 0
- });
-
- return null;
- }
+function getRuleSeverity(ruleConfig) {
+ if (typeof ruleConfig === "number") {
+ return ruleConfig;
+ } else if (Array.isArray(ruleConfig)) {
+ return ruleConfig[0];
+ }
+ return 0;
- // merge in any additional parser options
- if (config.parserOptions) {
- parserOptions = Object.assign({}, config.parserOptions, parserOptions);
- }
+}
- /*
- * Check for parsing errors first. If there's a parsing error, nothing
- * else can happen. However, a parsing error does not throw an error
- * from this method - it's just considered a fatal error message, a
- * problem that ESLint identified just like any other.
- */
- try {
- if (typeof parser.parseForESLint === "function") {
- return parser.parseForESLint(text, parserOptions);
- }
- return parser.parse(text, parserOptions);
+/**
+ * Get the options for a rule (not including severity), if any
+ * @param {Array|number} ruleConfig rule configuration
+ * @returns {Array} of rule options, empty Array if none
+ */
+function getRuleOptions(ruleConfig) {
+ if (Array.isArray(ruleConfig)) {
+ return ruleConfig.slice(1);
+ }
+ return [];
- } catch (ex) {
+}
- // If the message includes a leading line number, strip it:
- const message = ex.message.replace(/^line \d+:/i, "").trim();
- const source = (ex.lineNumber) ? SourceCode.splitLines(text)[ex.lineNumber - 1] : null;
+/**
+ * Parses text into an AST. Moved out here because the try-catch prevents
+ * optimization of functions, so it's best to keep the try-catch as isolated
+ * as possible
+ * @param {string} text The text to parse.
+ * @param {Object} config The ESLint configuration object.
+ * @param {string} filePath The path to the file being parsed.
+ * @returns {ASTNode|CustomParseResult} The AST or parse result if successful,
+ * or null if not.
+ * @param {Array} messages Messages array for the linter object
+ * @returns {*} parsed text if successful otherwise null
+ * @private
+ */
+function parse(text, config, filePath, messages) {
+
+ let parser,
+ parserOptions = {
+ loc: true,
+ range: true,
+ raw: true,
+ tokens: true,
+ comment: true,
+ filePath
+ };
- messages.push({
- ruleId: null,
- fatal: true,
- severity: 2,
- source,
- message: `Parsing error: ${message}`,
+ try {
+ parser = require(config.parser);
+ } catch (ex) {
+ messages.push({
+ ruleId: null,
+ fatal: true,
+ severity: 2,
+ source: null,
+ message: ex.message,
+ line: 0,
+ column: 0
+ });
- line: ex.lineNumber,
- column: ex.column
- });
+ return null;
+ }
- return null;
- }
+ // merge in any additional parser options
+ if (config.parserOptions) {
+ parserOptions = Object.assign({}, config.parserOptions, parserOptions);
}
- /**
- * Get the severity level of a rule (0 - none, 1 - warning, 2 - error)
- * Returns 0 if the rule config is not valid (an Array or a number)
- * @param {Array|number} ruleConfig rule configuration
- * @returns {number} 0, 1, or 2, indicating rule severity
+ /*
+ * Check for parsing errors first. If there's a parsing error, nothing
+ * else can happen. However, a parsing error does not throw an error
+ * from this method - it's just considered a fatal error message, a
+ * problem that ESLint identified just like any other.
*/
- function getRuleSeverity(ruleConfig) {
- if (typeof ruleConfig === "number") {
- return ruleConfig;
- } else if (Array.isArray(ruleConfig)) {
- return ruleConfig[0];
+ try {
+ if (typeof parser.parseForESLint === "function") {
+ return parser.parseForESLint(text, parserOptions);
}
- return 0;
+ return parser.parse(text, parserOptions);
- }
+ } catch (ex) {
- /**
- * Get the options for a rule (not including severity), if any
- * @param {Array|number} ruleConfig rule configuration
- * @returns {Array} of rule options, empty Array if none
- */
- function getRuleOptions(ruleConfig) {
- if (Array.isArray(ruleConfig)) {
- return ruleConfig.slice(1);
- }
- return [];
+ // If the message includes a leading line number, strip it:
+ const message = ex.message.replace(/^line \d+:/i, "").trim();
+ const source = (ex.lineNumber) ? SourceCode.splitLines(text)[ex.lineNumber - 1] : null;
+ messages.push({
+ ruleId: null,
+ fatal: true,
+ severity: 2,
+ source,
+ message: `Parsing error: ${message}`,
+
+ line: ex.lineNumber,
+ column: ex.column
+ });
+
+ return null;
}
+}
- // set unlimited listeners (see https://github.com/eslint/eslint/issues/524)
- api.setMaxListeners(0);
+//------------------------------------------------------------------------------
+// Public Interface
+//------------------------------------------------------------------------------
+
+/**
+ * Object that is responsible for verifying JavaScript text
+ * @name eslint
+ */
+class Linter extends EventEmitter {
+
+ constructor() {
+ super();
+ this.messages = [];
+ this.currentConfig = null;
+ this.currentScopes = null;
+ this.scopeManager = null;
+ this.currentFilename = null;
+ this.traverser = null;
+ this.reportingConfig = [];
+ this.sourceCode = null;
+ this.version = pkg.version;
+
+ this.rules = new Rules();
+ this.environments = new Environments();
+
+ // set unlimited listeners (see https://github.com/eslint/eslint/issues/524)
+ this.setMaxListeners(0);
+ }
/**
* Resets the internal state of the object.
* @returns {void}
*/
- api.reset = function() {
+ reset() {
this.removeAllListeners();
- messages = [];
- currentConfig = null;
- currentScopes = null;
- scopeManager = null;
- traverser = null;
- reportingConfig = [];
- sourceCode = null;
- };
+ this.messages = [];
+ this.currentConfig = null;
+ this.currentScopes = null;
+ this.scopeManager = null;
+ this.traverser = null;
+ this.reportingConfig = [];
+ this.sourceCode = null;
+ }
/**
* Configuration object for the `verify` API. A JS representation of the eslintrc files.
@@ -739,7 +743,7 @@ module.exports = (function() {
* @property {Object} [parserOptions] Options for the parsed used.
* @property {Object} [settings] Global settings passed to each rule.
* @property {Object} [env] The environment to verify in.
- * @property {Object} [globals] Available globalsto the code.
+ * @property {Object} [globals] Available globals to the code.
*/
/**
@@ -755,20 +759,19 @@ module.exports = (function() {
* Useful if you want to validate JS without comments overriding rules.
* @returns {Object[]} The results as an array of messages or null if no messages.
*/
- api.verify = function(textOrSourceCode, config, filenameOrOptions, saveState) {
+ verify(textOrSourceCode, config, filenameOrOptions, saveState) {
const text = (typeof textOrSourceCode === "string") ? textOrSourceCode : null;
let ast,
parseResult,
- shebang,
allowInlineConfig;
// evaluate arguments
if (typeof filenameOrOptions === "object") {
- currentFilename = filenameOrOptions.filename;
+ this.currentFilename = filenameOrOptions.filename;
allowInlineConfig = filenameOrOptions.allowInlineConfig;
saveState = filenameOrOptions.saveState;
} else {
- currentFilename = filenameOrOptions;
+ this.currentFilename = filenameOrOptions;
}
if (!saveState) {
@@ -789,24 +792,22 @@ module.exports = (function() {
}
// process initial config to make it safe to extend
- config = prepareConfig(config);
+ config = prepareConfig(config, this.environments);
// only do this for text
if (text !== null) {
// there's no input, just exit here
if (text.trim().length === 0) {
- sourceCode = new SourceCode(text, blankScriptAST);
- return messages;
+ this.sourceCode = new SourceCode(text, blankScriptAST);
+ return this.messages;
}
parseResult = parse(
- stripUnicodeBOM(text).replace(/^#!([^\r\n]+)/, (match, captured) => {
- shebang = captured;
- return `//${captured}`;
- }),
+ stripUnicodeBOM(text).replace(astUtils.SHEBANG_MATCHER, (match, captured) => `//${captured}`),
config,
- currentFilename
+ this.currentFilename,
+ this.messages
);
// if this result is from a parseForESLint() method, normalize
@@ -818,12 +819,12 @@ module.exports = (function() {
}
if (ast) {
- sourceCode = new SourceCode(text, ast);
+ this.sourceCode = new SourceCode(text, ast);
}
} else {
- sourceCode = textOrSourceCode;
- ast = sourceCode.ast;
+ this.sourceCode = textOrSourceCode;
+ ast = this.sourceCode.ast;
}
// if espree failed to parse the file, there's no sense in setting up rules
@@ -831,7 +832,7 @@ module.exports = (function() {
// parse global comments and modify config
if (allowInlineConfig !== false) {
- config = modifyConfigsFromComments(currentFilename, ast, config, reportingConfig, messages);
+ config = modifyConfigsFromComments(this.currentFilename, ast, config, this);
}
// ensure that severities are normalized in the config
@@ -841,7 +842,7 @@ module.exports = (function() {
Object.keys(config.rules).filter(key => getRuleSeverity(config.rules[key]) > 0).forEach(key => {
let ruleCreator;
- ruleCreator = rules.get(key);
+ ruleCreator = this.rules.get(key);
if (!ruleCreator) {
const replacementMsg = getRuleReplacementMessage(key);
@@ -851,7 +852,7 @@ module.exports = (function() {
} else {
ruleCreator = createStubRule(`Definition for rule '${key}' was not found`);
}
- rules.define(key, ruleCreator);
+ this.rules.define(key, ruleCreator);
}
const severity = getRuleSeverity(config.rules[key]);
@@ -859,7 +860,7 @@ module.exports = (function() {
try {
const ruleContext = new RuleContext(
- key, api, severity, options,
+ key, this, severity, options,
config.settings, config.parserOptions, config.parser,
ruleCreator.meta,
(parseResult && parseResult.services ? parseResult.services : {})
@@ -870,7 +871,7 @@ module.exports = (function() {
// add all the selectors from the rule as listeners
Object.keys(rule).forEach(selector => {
- api.on(selector, timing.enabled
+ this.on(selector, timing.enabled
? timing.time(key, rule[selector])
: rule[selector]
);
@@ -882,40 +883,30 @@ module.exports = (function() {
});
// save config so rules can access as necessary
- currentConfig = config;
- traverser = new Traverser();
+ this.currentConfig = config;
+ this.traverser = new Traverser();
- const ecmaFeatures = currentConfig.parserOptions.ecmaFeatures || {};
- const ecmaVersion = currentConfig.parserOptions.ecmaVersion || 5;
+ const ecmaFeatures = this.currentConfig.parserOptions.ecmaFeatures || {};
+ const ecmaVersion = this.currentConfig.parserOptions.ecmaVersion || 5;
// gather scope data that may be needed by the rules
- scopeManager = escope.analyze(ast, {
+ this.scopeManager = eslintScope.analyze(ast, {
ignoreEval: true,
nodejsScope: ecmaFeatures.globalReturn,
impliedStrict: ecmaFeatures.impliedStrict,
ecmaVersion,
- sourceType: currentConfig.parserOptions.sourceType || "script",
+ sourceType: this.currentConfig.parserOptions.sourceType || "script",
fallback: Traverser.getKeys
});
- currentScopes = scopeManager.scopes;
+ this.currentScopes = this.scopeManager.scopes;
// augment global scope with declared global variables
- addDeclaredGlobals(ast, currentScopes[0], currentConfig);
+ addDeclaredGlobals(ast, this.currentScopes[0], this.currentConfig, this.environments);
- // remove shebang comments
- if (shebang && ast.comments.length && ast.comments[0].value === shebang) {
- ast.comments.splice(0, 1);
-
- if (ast.body.length && ast.body[0].leadingComments && ast.body[0].leadingComments[0].value === shebang) {
- ast.body[0].leadingComments.splice(0, 1);
- }
- }
-
- let eventGenerator = new NodeEventGenerator(api);
+ let eventGenerator = new NodeEventGenerator(this);
eventGenerator = new CodePathAnalyzer(eventGenerator);
- eventGenerator = new CommentEventGenerator(eventGenerator, sourceCode);
/*
* Each node has a type property. Whenever a particular type of
@@ -923,7 +914,7 @@ module.exports = (function() {
* automatically be informed that this type of node has been found
* and react accordingly.
*/
- traverser.traverse(ast, {
+ this.traverser.traverse(ast, {
enter(node, parent) {
node.parent = parent;
eventGenerator.enterNode(node);
@@ -935,7 +926,7 @@ module.exports = (function() {
}
// sort by line and column
- messages.sort((a, b) => {
+ this.messages.sort((a, b) => {
const lineDiff = a.line - b.line;
if (lineDiff === 0) {
@@ -945,8 +936,8 @@ module.exports = (function() {
});
- return messages;
- };
+ return this.messages;
+ }
/**
* Reports a message from one of the rules.
@@ -963,11 +954,13 @@ module.exports = (function() {
* @param {Object} meta Metadata of the rule
* @returns {void}
*/
- api.report = function(ruleId, severity, node, location, message, opts, fix, meta) {
+ report(ruleId, severity, node, location, message, opts, fix, meta) {
if (node) {
assert.strictEqual(typeof node, "object", "Node must be an object");
}
+ let endLocation;
+
if (typeof location === "string") {
assert.ok(node, "Node must be provided when reporting error if location is not provided");
@@ -976,14 +969,14 @@ module.exports = (function() {
opts = message;
message = location;
location = node.loc.start;
+ endLocation = node.loc.end;
+ } else {
+ endLocation = location.end;
}
- // Store end location.
- const endLocation = location.end;
-
location = location.start || location;
- if (isDisabledByReportingConfig(reportingConfig, ruleId, location)) {
+ if (isDisabledByReportingConfig(this.reportingConfig, ruleId, location)) {
return;
}
@@ -1003,15 +996,15 @@ module.exports = (function() {
severity,
message,
line: location.line,
- column: location.column + 1, // switch to 1-base instead of 0-base
+ column: location.column + 1, // switch to 1-base instead of 0-base
nodeType: node && node.type,
- source: sourceCode.lines[location.line - 1] || ""
+ source: this.sourceCode.lines[location.line - 1] || ""
};
// Define endLine and endColumn if exists.
if (endLocation) {
problem.endLine = endLocation.line;
- problem.endColumn = endLocation.column + 1; // switch to 1-base instead of 0-base
+ problem.endColumn = endLocation.column + 1; // switch to 1-base instead of 0-base
}
// ensure there's range and text properties, otherwise it's not a valid fix
@@ -1025,73 +1018,39 @@ module.exports = (function() {
problem.fix = fix;
}
- messages.push(problem);
- };
+ this.messages.push(problem);
+ }
/**
* Gets the SourceCode object representing the parsed source.
* @returns {SourceCode} The SourceCode object.
*/
- api.getSourceCode = function() {
- return sourceCode;
- };
-
- // methods that exist on SourceCode object
- const externalMethods = {
- getSource: "getText",
- getSourceLines: "getLines",
- getAllComments: "getAllComments",
- getNodeByRangeIndex: "getNodeByRangeIndex",
- getComments: "getComments",
- getJSDocComment: "getJSDocComment",
- getFirstToken: "getFirstToken",
- getFirstTokens: "getFirstTokens",
- getLastToken: "getLastToken",
- getLastTokens: "getLastTokens",
- getTokenAfter: "getTokenAfter",
- getTokenBefore: "getTokenBefore",
- getTokenByRangeStart: "getTokenByRangeStart",
- getTokens: "getTokens",
- getTokensAfter: "getTokensAfter",
- getTokensBefore: "getTokensBefore",
- getTokensBetween: "getTokensBetween"
- };
-
- // copy over methods
- Object.keys(externalMethods).forEach(methodName => {
- const exMethodName = externalMethods[methodName];
-
- // All functions expected to have less arguments than 5.
- api[methodName] = function(a, b, c, d, e) {
- if (sourceCode) {
- return sourceCode[exMethodName](a, b, c, d, e);
- }
- return null;
- };
- });
+ getSourceCode() {
+ return this.sourceCode;
+ }
/**
* Gets nodes that are ancestors of current node.
* @returns {ASTNode[]} Array of objects representing ancestors.
*/
- api.getAncestors = function() {
- return traverser.parents();
- };
+ getAncestors() {
+ return this.traverser.parents();
+ }
/**
* Gets the scope for the current node.
* @returns {Object} An object representing the current node's scope.
*/
- api.getScope = function() {
- const parents = traverser.parents();
+ getScope() {
+ const parents = this.traverser.parents();
// Don't do this for Program nodes - they have no parents
if (parents.length) {
// if current node introduces a scope, add it to the list
- const current = traverser.current();
+ const current = this.traverser.current();
- if (currentConfig.parserOptions.ecmaVersion >= 6) {
+ if (this.currentConfig.parserOptions.ecmaVersion >= 6) {
if (["BlockStatement", "SwitchStatement", "CatchClause", "FunctionDeclaration", "FunctionExpression", "ArrowFunctionExpression"].indexOf(current.type) >= 0) {
parents.push(current);
}
@@ -1105,7 +1064,7 @@ module.exports = (function() {
for (let i = parents.length - 1; i >= 0; --i) {
// Get the innermost scope
- const scope = scopeManager.acquire(parents[i], true);
+ const scope = this.scopeManager.acquire(parents[i], true);
if (scope) {
if (scope.type === "function-expression-name") {
@@ -1119,8 +1078,8 @@ module.exports = (function() {
}
- return currentScopes[0];
- };
+ return this.currentScopes[0];
+ }
/**
* Record that a particular variable has been used in code
@@ -1128,9 +1087,9 @@ module.exports = (function() {
* @returns {boolean} True if the variable was found and marked as used,
* false if not.
*/
- api.markVariableAsUsed = function(name) {
- const hasGlobalReturn = currentConfig.parserOptions.ecmaFeatures && currentConfig.parserOptions.ecmaFeatures.globalReturn,
- specialScope = hasGlobalReturn || currentConfig.parserOptions.sourceType === "module";
+ markVariableAsUsed(name) {
+ const hasGlobalReturn = this.currentConfig.parserOptions.ecmaFeatures && this.currentConfig.parserOptions.ecmaFeatures.globalReturn,
+ specialScope = hasGlobalReturn || this.currentConfig.parserOptions.sourceType === "module";
let scope = this.getScope(),
i,
len;
@@ -1152,20 +1111,20 @@ module.exports = (function() {
} while ((scope = scope.upper));
return false;
- };
+ }
/**
* Gets the filename for the currently parsed source.
* @returns {string} The filename associated with the source being parsed.
* Defaults to " " if no filename info is present.
*/
- api.getFilename = function() {
- if (typeof currentFilename === "string") {
- return currentFilename;
+ getFilename() {
+ if (typeof this.currentFilename === "string") {
+ return this.currentFilename;
}
return " ";
- };
+ }
/**
* Defines a new linting rule.
@@ -1173,38 +1132,36 @@ module.exports = (function() {
* @param {Function} ruleModule Function from context to object mapping AST node types to event handlers
* @returns {void}
*/
- const defineRule = api.defineRule = function(ruleId, ruleModule) {
- rules.define(ruleId, ruleModule);
- };
+ defineRule(ruleId, ruleModule) {
+ this.rules.define(ruleId, ruleModule);
+ }
/**
* Defines many new linting rules.
* @param {Object} rulesToDefine map from unique rule identifier to rule
* @returns {void}
*/
- api.defineRules = function(rulesToDefine) {
+ defineRules(rulesToDefine) {
Object.getOwnPropertyNames(rulesToDefine).forEach(ruleId => {
- defineRule(ruleId, rulesToDefine[ruleId]);
+ this.defineRule(ruleId, rulesToDefine[ruleId]);
});
- };
+ }
/**
* Gets the default eslint configuration.
* @returns {Object} Object mapping rule IDs to their default configurations
*/
- api.defaults = function() {
- return require("../conf/eslint-recommended");
- };
+ defaults() { // eslint-disable-line class-methods-use-this
+ return defaultConfig;
+ }
/**
* Gets an object with all loaded rules.
* @returns {Map} All loaded rules
*/
- api.getRules = function() {
- return rules.getAllLoadedRules();
- };
-
- api.version = pkg.version;
+ getRules() {
+ return this.rules.getAllLoadedRules();
+ }
/**
* Gets variables that are declared by a specified node.
@@ -1223,12 +1180,48 @@ module.exports = (function() {
* - others - always an empty array.
*
* @param {ASTNode} node A node to get.
- * @returns {escope.Variable[]} Variables that are declared by the node.
+ * @returns {eslint-scope.Variable[]} Variables that are declared by the node.
*/
- api.getDeclaredVariables = function(node) {
- return (scopeManager && scopeManager.getDeclaredVariables(node)) || [];
- };
+ getDeclaredVariables(node) {
+ return (this.scopeManager && this.scopeManager.getDeclaredVariables(node)) || [];
+ }
+}
- return api;
+// methods that exist on SourceCode object
+const externalMethods = {
+ getSource: "getText",
+ getSourceLines: "getLines",
+ getAllComments: "getAllComments",
+ getNodeByRangeIndex: "getNodeByRangeIndex",
+ getComments: "getComments",
+ getCommentsBefore: "getCommentsBefore",
+ getCommentsAfter: "getCommentsAfter",
+ getCommentsInside: "getCommentsInside",
+ getJSDocComment: "getJSDocComment",
+ getFirstToken: "getFirstToken",
+ getFirstTokens: "getFirstTokens",
+ getLastToken: "getLastToken",
+ getLastTokens: "getLastTokens",
+ getTokenAfter: "getTokenAfter",
+ getTokenBefore: "getTokenBefore",
+ getTokenByRangeStart: "getTokenByRangeStart",
+ getTokens: "getTokens",
+ getTokensAfter: "getTokensAfter",
+ getTokensBefore: "getTokensBefore",
+ getTokensBetween: "getTokensBetween"
+};
+
+// copy over methods
+Object.keys(externalMethods).forEach(methodName => {
+ const exMethodName = externalMethods[methodName];
+
+ // All functions expected to have less arguments than 5.
+ Linter.prototype[methodName] = function(a, b, c, d, e) {
+ if (this.sourceCode) {
+ return this.sourceCode[exMethodName](a, b, c, d, e);
+ }
+ return null;
+ };
+});
-}());
+module.exports = Linter;
diff --git a/tools/eslint/lib/load-rules.js b/tools/eslint/lib/load-rules.js
index 92fb7bf20ada0c..b74905d65a50bc 100644
--- a/tools/eslint/lib/load-rules.js
+++ b/tools/eslint/lib/load-rules.js
@@ -12,6 +12,8 @@
const fs = require("fs"),
path = require("path");
+const rulesDirCache = {};
+
//------------------------------------------------------------------------------
// Public Interface
//------------------------------------------------------------------------------
@@ -29,6 +31,11 @@ module.exports = function(rulesDir, cwd) {
rulesDir = path.resolve(cwd, rulesDir);
}
+ // cache will help performance as IO operation are expensive
+ if (rulesDirCache[rulesDir]) {
+ return rulesDirCache[rulesDir];
+ }
+
const rules = Object.create(null);
fs.readdirSync(rulesDir).forEach(file => {
@@ -37,5 +44,7 @@ module.exports = function(rulesDir, cwd) {
}
rules[file.slice(0, -3)] = path.join(rulesDir, file);
});
+ rulesDirCache[rulesDir] = rules;
+
return rules;
};
diff --git a/tools/eslint/lib/rules.js b/tools/eslint/lib/rules.js
index 9244c96c7a1ab3..893104f650b28f 100644
--- a/tools/eslint/lib/rules.js
+++ b/tools/eslint/lib/rules.js
@@ -11,115 +11,85 @@
const loadRules = require("./load-rules");
-//------------------------------------------------------------------------------
-// Privates
-//------------------------------------------------------------------------------
-
-let rules = Object.create(null);
-
//------------------------------------------------------------------------------
// Public Interface
//------------------------------------------------------------------------------
-/**
- * Registers a rule module for rule id in storage.
- * @param {string} ruleId Rule id (file name).
- * @param {Function} ruleModule Rule handler.
- * @returns {void}
- */
-function define(ruleId, ruleModule) {
- rules[ruleId] = ruleModule;
-}
+class Rules {
+ constructor() {
+ this._rules = Object.create(null);
-/**
- * Loads and registers all rules from passed rules directory.
- * @param {string} [rulesDir] Path to rules directory, may be relative. Defaults to `lib/rules`.
- * @param {string} cwd Current working directory
- * @returns {void}
- */
-function load(rulesDir, cwd) {
- const newRules = loadRules(rulesDir, cwd);
+ this.load();
+ }
- Object.keys(newRules).forEach(ruleId => {
- define(ruleId, newRules[ruleId]);
- });
-}
+ /**
+ * Registers a rule module for rule id in storage.
+ * @param {string} ruleId Rule id (file name).
+ * @param {Function} ruleModule Rule handler.
+ * @returns {void}
+ */
+ define(ruleId, ruleModule) {
+ this._rules[ruleId] = ruleModule;
+ }
-/**
- * Registers all given rules of a plugin.
- * @param {Object} plugin The plugin object to import.
- * @param {string} pluginName The name of the plugin without prefix (`eslint-plugin-`).
- * @returns {void}
- */
-function importPlugin(plugin, pluginName) {
- if (plugin.rules) {
- Object.keys(plugin.rules).forEach(ruleId => {
- const qualifiedRuleId = `${pluginName}/${ruleId}`,
- rule = plugin.rules[ruleId];
+ /**
+ * Loads and registers all rules from passed rules directory.
+ * @param {string} [rulesDir] Path to rules directory, may be relative. Defaults to `lib/rules`.
+ * @param {string} cwd Current working directory
+ * @returns {void}
+ */
+ load(rulesDir, cwd) {
+ const newRules = loadRules(rulesDir, cwd);
- define(qualifiedRuleId, rule);
+ Object.keys(newRules).forEach(ruleId => {
+ this.define(ruleId, newRules[ruleId]);
});
}
-}
-/**
- * Access rule handler by id (file name).
- * @param {string} ruleId Rule id (file name).
- * @returns {Function} Rule handler.
- */
-function getHandler(ruleId) {
- if (typeof rules[ruleId] === "string") {
- return require(rules[ruleId]);
+ /**
+ * Registers all given rules of a plugin.
+ * @param {Object} plugin The plugin object to import.
+ * @param {string} pluginName The name of the plugin without prefix (`eslint-plugin-`).
+ * @returns {void}
+ */
+ importPlugin(plugin, pluginName) {
+ if (plugin.rules) {
+ Object.keys(plugin.rules).forEach(ruleId => {
+ const qualifiedRuleId = `${pluginName}/${ruleId}`,
+ rule = plugin.rules[ruleId];
+
+ this.define(qualifiedRuleId, rule);
+ });
+ }
}
- return rules[ruleId];
-
-}
-
-/**
- * Get an object with all currently loaded rules
- * @returns {Map} All loaded rules
- */
-function getAllLoadedRules() {
- const allRules = new Map();
-
- Object.keys(rules).forEach(name => {
- const rule = getHandler(name);
-
- allRules.set(name, rule);
- });
- return allRules;
-}
-/**
- * Reset rules storage.
- * Should be used only in tests.
- * @returns {void}
- */
-function testClear() {
- rules = Object.create(null);
-}
+ /**
+ * Access rule handler by id (file name).
+ * @param {string} ruleId Rule id (file name).
+ * @returns {Function} Rule handler.
+ */
+ get(ruleId) {
+ if (typeof this._rules[ruleId] === "string") {
+ return require(this._rules[ruleId]);
+ }
+ return this._rules[ruleId];
-module.exports = {
- define,
- load,
- importPlugin,
- get: getHandler,
- getAllLoadedRules,
- testClear,
+ }
/**
- * Resets rules to its starting state. Use for tests only.
- * @returns {void}
+ * Get an object with all currently loaded rules
+ * @returns {Map} All loaded rules
*/
- testReset() {
- testClear();
- load();
- }
-};
+ getAllLoadedRules() {
+ const allRules = new Map();
-//------------------------------------------------------------------------------
-// Initialization
-//------------------------------------------------------------------------------
+ Object.keys(this._rules).forEach(name => {
+ const rule = this.get(name);
+
+ allRules.set(name, rule);
+ });
+ return allRules;
+ }
+}
-// loads built-in rules
-load();
+module.exports = Rules;
diff --git a/tools/eslint/lib/rules/array-bracket-newline.js b/tools/eslint/lib/rules/array-bracket-newline.js
new file mode 100644
index 00000000000000..319ac60f2cdf96
--- /dev/null
+++ b/tools/eslint/lib/rules/array-bracket-newline.js
@@ -0,0 +1,235 @@
+/**
+ * @fileoverview Rule to enforce linebreaks after open and before close array brackets
+ * @author Jan Peer Stöcklmair
+ */
+
+"use strict";
+
+const astUtils = require("../ast-utils");
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = {
+ meta: {
+ docs: {
+ description: "enforce linebreaks after opening and before closing array brackets",
+ category: "Stylistic Issues",
+ recommended: false
+ },
+ fixable: "whitespace",
+ schema: [
+ {
+ oneOf: [
+ {
+ enum: ["always", "never"]
+ },
+ {
+ type: "object",
+ properties: {
+ multiline: {
+ type: "boolean"
+ },
+ minItems: {
+ type: ["integer", "null"],
+ minimum: 0
+ }
+ },
+ additionalProperties: false
+ }
+ ]
+ }
+ ]
+ },
+
+ create(context) {
+ const sourceCode = context.getSourceCode();
+
+
+ //----------------------------------------------------------------------
+ // Helpers
+ //----------------------------------------------------------------------
+
+ /**
+ * Normalizes a given option value.
+ *
+ * @param {string|Object|undefined} option - An option value to parse.
+ * @returns {{multiline: boolean, minItems: number}} Normalized option object.
+ */
+ function normalizeOptionValue(option) {
+ let multiline = false;
+ let minItems = 0;
+
+ if (option) {
+ if (option === "always" || option.minItems === 0) {
+ minItems = 0;
+ } else if (option === "never") {
+ minItems = Number.POSITIVE_INFINITY;
+ } else {
+ multiline = Boolean(option.multiline);
+ minItems = option.minItems || Number.POSITIVE_INFINITY;
+ }
+ } else {
+ multiline = true;
+ minItems = Number.POSITIVE_INFINITY;
+ }
+
+ return { multiline, minItems };
+ }
+
+ /**
+ * Normalizes a given option value.
+ *
+ * @param {string|Object|undefined} options - An option value to parse.
+ * @returns {{ArrayExpression: {multiline: boolean, minItems: number}, ArrayPattern: {multiline: boolean, minItems: number}}} Normalized option object.
+ */
+ function normalizeOptions(options) {
+ const value = normalizeOptionValue(options);
+
+ return { ArrayExpression: value, ArrayPattern: value };
+ }
+
+ /**
+ * Reports that there shouldn't be a linebreak after the first token
+ * @param {ASTNode} node - The node to report in the event of an error.
+ * @param {Token} token - The token to use for the report.
+ * @returns {void}
+ */
+ function reportNoBeginningLinebreak(node, token) {
+ context.report({
+ node,
+ loc: token.loc,
+ message: "There should be no linebreak after '['.",
+ fix(fixer) {
+ const nextToken = sourceCode.getTokenAfter(token, { includeComments: true });
+
+ if (astUtils.isCommentToken(nextToken)) {
+ return null;
+ }
+
+ return fixer.removeRange([token.range[1], nextToken.range[0]]);
+ }
+ });
+ }
+
+ /**
+ * Reports that there shouldn't be a linebreak before the last token
+ * @param {ASTNode} node - The node to report in the event of an error.
+ * @param {Token} token - The token to use for the report.
+ * @returns {void}
+ */
+ function reportNoEndingLinebreak(node, token) {
+ context.report({
+ node,
+ loc: token.loc,
+ message: "There should be no linebreak before ']'.",
+ fix(fixer) {
+ const previousToken = sourceCode.getTokenBefore(token, { includeComments: true });
+
+ if (astUtils.isCommentToken(previousToken)) {
+ return null;
+ }
+
+ return fixer.removeRange([previousToken.range[1], token.range[0]]);
+ }
+ });
+ }
+
+ /**
+ * Reports that there should be a linebreak after the first token
+ * @param {ASTNode} node - The node to report in the event of an error.
+ * @param {Token} token - The token to use for the report.
+ * @returns {void}
+ */
+ function reportRequiredBeginningLinebreak(node, token) {
+ context.report({
+ node,
+ loc: token.loc,
+ message: "A linebreak is required after '['.",
+ fix(fixer) {
+ return fixer.insertTextAfter(token, "\n");
+ }
+ });
+ }
+
+ /**
+ * Reports that there should be a linebreak before the last token
+ * @param {ASTNode} node - The node to report in the event of an error.
+ * @param {Token} token - The token to use for the report.
+ * @returns {void}
+ */
+ function reportRequiredEndingLinebreak(node, token) {
+ context.report({
+ node,
+ loc: token.loc,
+ message: "A linebreak is required before ']'.",
+ fix(fixer) {
+ return fixer.insertTextBefore(token, "\n");
+ }
+ });
+ }
+
+ /**
+ * Reports a given node if it violated this rule.
+ *
+ * @param {ASTNode} node - A node to check. This is an ObjectExpression node or an ObjectPattern node.
+ * @param {{multiline: boolean, minItems: number}} options - An option object.
+ * @returns {void}
+ */
+ function check(node) {
+ const elements = node.elements;
+ const normalizedOptions = normalizeOptions(context.options[0]);
+ const options = normalizedOptions[node.type];
+ const openBracket = sourceCode.getFirstToken(node);
+ const closeBracket = sourceCode.getLastToken(node);
+ const firstIncComment = sourceCode.getTokenAfter(openBracket, { includeComments: true });
+ const lastIncComment = sourceCode.getTokenBefore(closeBracket, { includeComments: true });
+ const first = sourceCode.getTokenAfter(openBracket);
+ const last = sourceCode.getTokenBefore(closeBracket);
+
+ const needsLinebreaks = (
+ elements.length >= options.minItems ||
+ (
+ options.multiline &&
+ elements.length > 0 &&
+ firstIncComment.loc.start.line !== lastIncComment.loc.end.line
+ )
+ );
+
+ /*
+ * Use tokens or comments to check multiline or not.
+ * But use only tokens to check whether linebreaks are needed.
+ * This allows:
+ * var arr = [ // eslint-disable-line foo
+ * 'a'
+ * ]
+ */
+
+ if (needsLinebreaks) {
+ if (astUtils.isTokenOnSameLine(openBracket, first)) {
+ reportRequiredBeginningLinebreak(node, openBracket);
+ }
+ if (astUtils.isTokenOnSameLine(last, closeBracket)) {
+ reportRequiredEndingLinebreak(node, closeBracket);
+ }
+ } else {
+ if (!astUtils.isTokenOnSameLine(openBracket, first)) {
+ reportNoBeginningLinebreak(node, openBracket);
+ }
+ if (!astUtils.isTokenOnSameLine(last, closeBracket)) {
+ reportNoEndingLinebreak(node, closeBracket);
+ }
+ }
+ }
+
+ //----------------------------------------------------------------------
+ // Public
+ //----------------------------------------------------------------------
+
+ return {
+ ArrayPattern: check,
+ ArrayExpression: check
+ };
+ }
+};
diff --git a/tools/eslint/lib/rules/array-element-newline.js b/tools/eslint/lib/rules/array-element-newline.js
new file mode 100644
index 00000000000000..8cccae082e2917
--- /dev/null
+++ b/tools/eslint/lib/rules/array-element-newline.js
@@ -0,0 +1,230 @@
+/**
+ * @fileoverview Rule to enforce line breaks after each array element
+ * @author Jan Peer Stöcklmair
+ */
+
+"use strict";
+
+const astUtils = require("../ast-utils");
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = {
+ meta: {
+ docs: {
+ description: "enforce line breaks after each array element",
+ category: "Stylistic Issues",
+ recommended: false
+ },
+ fixable: "whitespace",
+ schema: [
+ {
+ oneOf: [
+ {
+ enum: ["always", "never"]
+ },
+ {
+ type: "object",
+ properties: {
+ multiline: {
+ type: "boolean"
+ },
+ minItems: {
+ type: ["integer", "null"],
+ minimum: 0
+ }
+ },
+ additionalProperties: false
+ }
+ ]
+ }
+ ]
+ },
+
+ create(context) {
+ const sourceCode = context.getSourceCode();
+
+ //----------------------------------------------------------------------
+ // Helpers
+ //----------------------------------------------------------------------
+
+ /**
+ * Normalizes a given option value.
+ *
+ * @param {string|Object|undefined} option - An option value to parse.
+ * @returns {{multiline: boolean, minItems: number}} Normalized option object.
+ */
+ function normalizeOptionValue(option) {
+ let multiline = false;
+ let minItems;
+
+ option = option || "always";
+
+ if (option === "always" || option.minItems === 0) {
+ minItems = 0;
+ } else if (option === "never") {
+ minItems = Number.POSITIVE_INFINITY;
+ } else {
+ multiline = Boolean(option.multiline);
+ minItems = option.minItems || Number.POSITIVE_INFINITY;
+ }
+
+ return { multiline, minItems };
+ }
+
+ /**
+ * Normalizes a given option value.
+ *
+ * @param {string|Object|undefined} options - An option value to parse.
+ * @returns {{ArrayExpression: {multiline: boolean, minItems: number}, ArrayPattern: {multiline: boolean, minItems: number}}} Normalized option object.
+ */
+ function normalizeOptions(options) {
+ const value = normalizeOptionValue(options);
+
+ return { ArrayExpression: value, ArrayPattern: value };
+ }
+
+ /**
+ * Reports that there shouldn't be a line break after the first token
+ * @param {Token} token - The token to use for the report.
+ * @returns {void}
+ */
+ function reportNoLineBreak(token) {
+ const tokenBefore = sourceCode.getTokenBefore(token, { includeComments: true });
+
+ context.report({
+ loc: {
+ start: tokenBefore.loc.end,
+ end: token.loc.start
+ },
+ message: "There should be no linebreak here.",
+ fix(fixer) {
+ if (astUtils.isCommentToken(tokenBefore)) {
+ return null;
+ }
+
+ if (!astUtils.isTokenOnSameLine(tokenBefore, token)) {
+ return fixer.replaceTextRange([tokenBefore.range[1], token.range[0]], " ");
+ }
+
+ /*
+ * This will check if the comma is on the same line as the next element
+ * Following array:
+ * [
+ * 1
+ * , 2
+ * , 3
+ * ]
+ *
+ * will be fixed to:
+ * [
+ * 1, 2, 3
+ * ]
+ */
+ const twoTokensBefore = sourceCode.getTokenBefore(tokenBefore, { includeComments: true });
+
+ if (astUtils.isCommentToken(twoTokensBefore)) {
+ return null;
+ }
+
+ return fixer.replaceTextRange([twoTokensBefore.range[1], tokenBefore.range[0]], "");
+
+ }
+ });
+ }
+
+ /**
+ * Reports that there should be a line break after the first token
+ * @param {Token} token - The token to use for the report.
+ * @returns {void}
+ */
+ function reportRequiredLineBreak(token) {
+ const tokenBefore = sourceCode.getTokenBefore(token, { includeComments: true });
+
+ context.report({
+ loc: {
+ start: tokenBefore.loc.end,
+ end: token.loc.start
+ },
+ message: "There should be a linebreak after this element.",
+ fix(fixer) {
+ return fixer.replaceTextRange([tokenBefore.range[1], token.range[0]], "\n");
+ }
+ });
+ }
+
+ /**
+ * Reports a given node if it violated this rule.
+ *
+ * @param {ASTNode} node - A node to check. This is an ObjectExpression node or an ObjectPattern node.
+ * @param {{multiline: boolean, minItems: number}} options - An option object.
+ * @returns {void}
+ */
+ function check(node) {
+ const elements = node.elements;
+ const normalizedOptions = normalizeOptions(context.options[0]);
+ const options = normalizedOptions[node.type];
+
+ let elementBreak = false;
+
+ /*
+ * MULTILINE: true
+ * loop through every element and check
+ * if at least one element has linebreaks inside
+ * this ensures that following is not valid (due to elements are on the same line):
+ *
+ * [
+ * 1,
+ * 2,
+ * 3
+ * ]
+ */
+ if (options.multiline) {
+ elementBreak = elements
+ .filter(element => element !== null)
+ .some(element => element.loc.start.line !== element.loc.end.line);
+ }
+
+ const needsLinebreaks = (
+ elements.length >= options.minItems ||
+ (
+ options.multiline &&
+ elementBreak
+ )
+ );
+
+ elements.forEach((element, i) => {
+ const previousElement = elements[i - 1];
+
+ if (i === 0 || element === null || previousElement === null) {
+ return;
+ }
+
+ const commaToken = sourceCode.getFirstTokenBetween(previousElement, element, astUtils.isCommaToken);
+ const lastTokenOfPreviousElement = sourceCode.getTokenBefore(commaToken);
+ const firstTokenOfCurrentElement = sourceCode.getTokenAfter(commaToken);
+
+ if (needsLinebreaks) {
+ if (astUtils.isTokenOnSameLine(lastTokenOfPreviousElement, firstTokenOfCurrentElement)) {
+ reportRequiredLineBreak(firstTokenOfCurrentElement);
+ }
+ } else {
+ if (!astUtils.isTokenOnSameLine(lastTokenOfPreviousElement, firstTokenOfCurrentElement)) {
+ reportNoLineBreak(firstTokenOfCurrentElement);
+ }
+ }
+ });
+ }
+
+ //----------------------------------------------------------------------
+ // Public
+ //----------------------------------------------------------------------
+
+ return {
+ ArrayPattern: check,
+ ArrayExpression: check
+ };
+ }
+};
diff --git a/tools/eslint/lib/rules/arrow-parens.js b/tools/eslint/lib/rules/arrow-parens.js
index c292d1b492979c..60a043bb31bd4e 100644
--- a/tools/eslint/lib/rules/arrow-parens.js
+++ b/tools/eslint/lib/rules/arrow-parens.js
@@ -50,14 +50,31 @@ module.exports = {
const sourceCode = context.getSourceCode();
-
/**
* Determines whether a arrow function argument end with `)`
* @param {ASTNode} node The arrow function node.
* @returns {void}
*/
function parens(node) {
- const token = sourceCode.getFirstToken(node, node.async ? 1 : 0);
+ const isAsync = node.async;
+ const firstTokenOfParam = sourceCode.getFirstToken(node, isAsync ? 1 : 0);
+
+ /**
+ * Remove the parenthesis around a parameter
+ * @param {Fixer} fixer Fixer
+ * @returns {string} fixed parameter
+ */
+ function fixParamsWithParenthesis(fixer) {
+ const paramToken = sourceCode.getTokenAfter(firstTokenOfParam);
+ const closingParenToken = sourceCode.getTokenAfter(paramToken);
+ const asyncToken = isAsync ? sourceCode.getTokenBefore(firstTokenOfParam) : null;
+ const shouldAddSpaceForAsync = asyncToken && (asyncToken.end === firstTokenOfParam.start);
+
+ return fixer.replaceTextRange([
+ firstTokenOfParam.range[0],
+ closingParenToken.range[1]
+ ], `${shouldAddSpaceForAsync ? " " : ""}${paramToken.value}`);
+ }
// "as-needed", { "requireForBlockBody": true }: x => x
if (
@@ -68,19 +85,11 @@ module.exports = {
node.body.type !== "BlockStatement" &&
!node.returnType
) {
- if (astUtils.isOpeningParenToken(token)) {
+ if (astUtils.isOpeningParenToken(firstTokenOfParam)) {
context.report({
node,
message: requireForBlockBodyMessage,
- fix(fixer) {
- const paramToken = context.getTokenAfter(token);
- const closingParenToken = context.getTokenAfter(paramToken);
-
- return fixer.replaceTextRange([
- token.range[0],
- closingParenToken.range[1]
- ], paramToken.value);
- }
+ fix: fixParamsWithParenthesis
});
}
return;
@@ -90,12 +99,12 @@ module.exports = {
requireForBlockBody &&
node.body.type === "BlockStatement"
) {
- if (!astUtils.isOpeningParenToken(token)) {
+ if (!astUtils.isOpeningParenToken(firstTokenOfParam)) {
context.report({
node,
message: requireForBlockBodyNoParensMessage,
fix(fixer) {
- return fixer.replaceText(token, `(${token.value})`);
+ return fixer.replaceText(firstTokenOfParam, `(${firstTokenOfParam.value})`);
}
});
}
@@ -109,26 +118,18 @@ module.exports = {
!node.params[0].typeAnnotation &&
!node.returnType
) {
- if (astUtils.isOpeningParenToken(token)) {
+ if (astUtils.isOpeningParenToken(firstTokenOfParam)) {
context.report({
node,
message: asNeededMessage,
- fix(fixer) {
- const paramToken = context.getTokenAfter(token);
- const closingParenToken = context.getTokenAfter(paramToken);
-
- return fixer.replaceTextRange([
- token.range[0],
- closingParenToken.range[1]
- ], paramToken.value);
- }
+ fix: fixParamsWithParenthesis
});
}
return;
}
- if (token.type === "Identifier") {
- const after = sourceCode.getTokenAfter(token);
+ if (firstTokenOfParam.type === "Identifier") {
+ const after = sourceCode.getTokenAfter(firstTokenOfParam);
// (x) => x
if (after.value !== ")") {
@@ -136,7 +137,7 @@ module.exports = {
node,
message,
fix(fixer) {
- return fixer.replaceText(token, `(${token.value})`);
+ return fixer.replaceText(firstTokenOfParam, `(${firstTokenOfParam.value})`);
}
});
}
diff --git a/tools/eslint/lib/rules/block-scoped-var.js b/tools/eslint/lib/rules/block-scoped-var.js
index bb0931a3ceb63f..0b4d855fae5024 100644
--- a/tools/eslint/lib/rules/block-scoped-var.js
+++ b/tools/eslint/lib/rules/block-scoped-var.js
@@ -41,7 +41,7 @@ module.exports = {
/**
* Reports a given reference.
- * @param {escope.Reference} reference - A reference to report.
+ * @param {eslint-scope.Reference} reference - A reference to report.
* @returns {void}
*/
function report(reference) {
diff --git a/tools/eslint/lib/rules/brace-style.js b/tools/eslint/lib/rules/brace-style.js
index bb4433cc45cc36..44bd6d2c80b6f2 100644
--- a/tools/eslint/lib/rules/brace-style.js
+++ b/tools/eslint/lib/rules/brace-style.js
@@ -62,10 +62,12 @@ module.exports = {
function removeNewlineBetween(firstToken, secondToken) {
const textRange = [firstToken.range[1], secondToken.range[0]];
const textBetween = sourceCode.text.slice(textRange[0], textRange[1]);
- const NEWLINE_REGEX = astUtils.createGlobalLinebreakMatcher();
// Don't do a fix if there is a comment between the tokens
- return fixer => fixer.replaceTextRange(textRange, textBetween.trim() ? null : textBetween.replace(NEWLINE_REGEX, ""));
+ if (textBetween.trim()) {
+ return null;
+ }
+ return fixer => fixer.replaceTextRange(textRange, " ");
}
/**
diff --git a/tools/eslint/lib/rules/capitalized-comments.js b/tools/eslint/lib/rules/capitalized-comments.js
index b8d5b8cd612d1e..bb5e5825a36e2b 100644
--- a/tools/eslint/lib/rules/capitalized-comments.js
+++ b/tools/eslint/lib/rules/capitalized-comments.js
@@ -19,7 +19,7 @@ const ALWAYS_MESSAGE = "Comments should not begin with a lowercase character",
NEVER_MESSAGE = "Comments should not begin with an uppercase character",
DEFAULT_IGNORE_PATTERN = astUtils.COMMENTS_IGNORE_PATTERN,
WHITESPACE = /\s/g,
- MAYBE_URL = /^\s*[^:/?#\s]+:\/\/[^?#]/, // TODO: Combine w/ max-len pattern?
+ MAYBE_URL = /^\s*[^:/?#\s]+:\/\/[^?#]/, // TODO: Combine w/ max-len pattern?
DEFAULTS = {
ignorePattern: null,
ignoreInlineComments: false,
@@ -270,7 +270,7 @@ module.exports = {
: NEVER_MESSAGE;
context.report({
- node: null, // Intentionally using loc instead
+ node: null, // Intentionally using loc instead
loc: comment.loc,
message,
fix(fixer) {
@@ -295,7 +295,7 @@ module.exports = {
Program() {
const comments = sourceCode.getAllComments();
- comments.forEach(processComment);
+ comments.filter(token => token.type !== "Shebang").forEach(processComment);
}
};
}
diff --git a/tools/eslint/lib/rules/comma-spacing.js b/tools/eslint/lib/rules/comma-spacing.js
index bb1dd68f63987e..25a0e7d82c8abe 100644
--- a/tools/eslint/lib/rules/comma-spacing.js
+++ b/tools/eslint/lib/rules/comma-spacing.js
@@ -87,8 +87,8 @@ module.exports = {
},
message: options[dir]
- ? "A space is required {{dir}} ','."
- : "There should be no space {{dir}} ','.",
+ ? "A space is required {{dir}} ','."
+ : "There should be no space {{dir}} ','.",
data: {
dir
}
diff --git a/tools/eslint/lib/rules/comma-style.js b/tools/eslint/lib/rules/comma-style.js
index fcaecc662bce8c..1a9382bea35b9d 100644
--- a/tools/eslint/lib/rules/comma-style.js
+++ b/tools/eslint/lib/rules/comma-style.js
@@ -202,7 +202,7 @@ module.exports = {
*/
if (astUtils.isCommaToken(commaToken)) {
validateCommaItemSpacing(previousItemToken, commaToken,
- currentItemToken, reportItem);
+ currentItemToken, reportItem);
}
if (item) {
diff --git a/tools/eslint/lib/rules/complexity.js b/tools/eslint/lib/rules/complexity.js
index 14617bc3537aef..e0313fa78f17c3 100644
--- a/tools/eslint/lib/rules/complexity.js
+++ b/tools/eslint/lib/rules/complexity.js
@@ -122,7 +122,7 @@ module.exports = {
// Avoiding `default`
if (node.test) {
- increaseComplexity(node);
+ increaseComplexity();
}
}
@@ -136,7 +136,7 @@ module.exports = {
// Avoiding &&
if (node.operator === "||") {
- increaseComplexity(node);
+ increaseComplexity();
}
}
diff --git a/tools/eslint/lib/rules/curly.js b/tools/eslint/lib/rules/curly.js
index cd15b2d93574df..e3cccc1f656fc3 100644
--- a/tools/eslint/lib/rules/curly.js
+++ b/tools/eslint/lib/rules/curly.js
@@ -9,7 +9,6 @@
//------------------------------------------------------------------------------
const astUtils = require("../ast-utils");
-const esUtils = require("esutils");
//------------------------------------------------------------------------------
// Rule Definition
@@ -240,7 +239,7 @@ module.exports = {
// e.g. `do{foo()} while (bar)` should be corrected to `do foo() while (bar)`
const needsPrecedingSpace = node.type === "DoWhileStatement" &&
sourceCode.getTokenBefore(bodyNode).end === bodyNode.start &&
- esUtils.code.isIdentifierPartES6(sourceCode.getText(bodyNode).charCodeAt(1));
+ !astUtils.canTokensBeAdjacent("do", sourceCode.getFirstToken(bodyNode, { skip: 1 }));
const openingBracket = sourceCode.getFirstToken(bodyNode);
const closingBracket = sourceCode.getLastToken(bodyNode);
@@ -294,7 +293,7 @@ module.exports = {
}
} else if (multiOrNest) {
if (hasBlock && body.body.length === 1 && isOneLiner(body.body[0])) {
- const leadingComments = sourceCode.getComments(body.body[0]).leading;
+ const leadingComments = sourceCode.getCommentsBefore(body.body[0]);
expected = leadingComments.length > 0;
} else if (!isOneLiner(body)) {
diff --git a/tools/eslint/lib/rules/default-case.js b/tools/eslint/lib/rules/default-case.js
index 3efcbbced5dcab..32cd8dfe4922d0 100644
--- a/tools/eslint/lib/rules/default-case.js
+++ b/tools/eslint/lib/rules/default-case.js
@@ -74,7 +74,7 @@ module.exports = {
let comment;
const lastCase = last(node.cases);
- const comments = sourceCode.getComments(lastCase).trailing;
+ const comments = sourceCode.getCommentsAfter(lastCase);
if (comments.length) {
comment = last(comments);
diff --git a/tools/eslint/lib/rules/dot-notation.js b/tools/eslint/lib/rules/dot-notation.js
index abb9b4b4881b34..55225b8cc41908 100644
--- a/tools/eslint/lib/rules/dot-notation.js
+++ b/tools/eslint/lib/rules/dot-notation.js
@@ -79,11 +79,17 @@ module.exports = {
return null;
}
+ const tokenAfterProperty = sourceCode.getTokenAfter(rightBracket);
+ const needsSpaceAfterProperty = tokenAfterProperty &&
+ rightBracket.range[1] === tokenAfterProperty.range[0] &&
+ !astUtils.canTokensBeAdjacent(String(node.property.value), tokenAfterProperty);
+
const textBeforeDot = astUtils.isDecimalInteger(node.object) ? " " : "";
+ const textAfterProperty = needsSpaceAfterProperty ? " " : "";
return fixer.replaceTextRange(
[leftBracket.range[0], rightBracket.range[1]],
- `${textBeforeDot}.${node.property.value}`
+ `${textBeforeDot}.${node.property.value}${textAfterProperty}`
);
}
});
diff --git a/tools/eslint/lib/rules/for-direction.js b/tools/eslint/lib/rules/for-direction.js
new file mode 100644
index 00000000000000..7178ced9db0a4b
--- /dev/null
+++ b/tools/eslint/lib/rules/for-direction.js
@@ -0,0 +1,105 @@
+/**
+ * @fileoverview enforce "for" loop update clause moving the counter in the right direction.(for-direction)
+ * @author Aladdin-ADD
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = {
+ meta: {
+ docs: {
+ description: "enforce \"for\" loop update clause moving the counter in the right direction.",
+ category: "Possible Errors",
+ recommended: false
+ },
+ fixable: null,
+ schema: []
+ },
+
+ create(context) {
+
+ /**
+ * report an error.
+ * @param {ASTNode} node the node to report.
+ * @returns {void}
+ */
+ function report(node) {
+ context.report({
+ node,
+ message: "The update clause in this loop moves the variable in the wrong direction."
+ });
+ }
+
+ /**
+ * check UpdateExpression add/sub the counter
+ * @param {ASTNode} update UpdateExpression to check
+ * @param {string} counter variable name to check
+ * @returns {int} if add return 1, if sub return -1, if nochange, return 0
+ */
+ function getUpdateDirection(update, counter) {
+ if (update.argument.type === "Identifier" && update.argument.name === counter) {
+ if (update.operator === "++") {
+ return 1;
+ }
+ if (update.operator === "--") {
+ return -1;
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * check AssignmentExpression add/sub the counter
+ * @param {ASTNode} update AssignmentExpression to check
+ * @param {string} counter variable name to check
+ * @returns {int} if add return 1, if sub return -1, if nochange, return 0
+ */
+ function getAssignmentDirection(update, counter) {
+ if (update.left.name === counter) {
+ if (update.operator === "+=") {
+ return 1;
+ }
+ if (update.operator === "-=") {
+ return -1;
+ }
+ }
+ return 0;
+ }
+ return {
+ ForStatement(node) {
+
+ if (node.test && node.test.type === "BinaryExpression" && node.test.left.type === "Identifier" && node.update) {
+ const counter = node.test.left.name;
+ const operator = node.test.operator;
+ const update = node.update;
+
+ if (operator === "<" || operator === "<=") {
+
+ // report error if update sub the counter (--, -=)
+ if (update.type === "UpdateExpression" && getUpdateDirection(update, counter) < 0) {
+ report(node);
+ }
+
+ if (update.type === "AssignmentExpression" && getAssignmentDirection(update, counter) < 0) {
+ report(node);
+ }
+ } else if (operator === ">" || operator === ">=") {
+
+ // report error if update add the counter (++, +=)
+ if (update.type === "UpdateExpression" && getUpdateDirection(update, counter) > 0) {
+ report(node);
+ }
+
+ if (update.type === "AssignmentExpression" && getAssignmentDirection(update, counter) > 0) {
+ report(node);
+ }
+ }
+ }
+ }
+ };
+ }
+};
diff --git a/tools/eslint/lib/rules/func-names.js b/tools/eslint/lib/rules/func-names.js
index e7f950c9ba593d..848ce9757413ea 100644
--- a/tools/eslint/lib/rules/func-names.js
+++ b/tools/eslint/lib/rules/func-names.js
@@ -13,7 +13,7 @@ const astUtils = require("../ast-utils");
/**
* Checks whether or not a given variable is a function name.
- * @param {escope.Variable} variable - A variable to check.
+ * @param {eslint-scope.Variable} variable - A variable to check.
* @returns {boolean} `true` if the variable is a function name.
*/
function isFunctionName(variable) {
diff --git a/tools/eslint/lib/rules/global-require.js b/tools/eslint/lib/rules/global-require.js
index 367fe590ed2210..beda8d99f1b033 100644
--- a/tools/eslint/lib/rules/global-require.js
+++ b/tools/eslint/lib/rules/global-require.js
@@ -17,7 +17,7 @@ const ACCEPTABLE_PARENTS = [
];
/**
- * Finds the escope reference in the given scope.
+ * Finds the eslint-scope reference in the given scope.
* @param {Object} scope The scope to search.
* @param {ASTNode} node The identifier node.
* @returns {Reference|null} Returns the found reference or null if none were found.
diff --git a/tools/eslint/lib/rules/id-length.js b/tools/eslint/lib/rules/id-length.js
index 341f929cdec27e..dad9c406493399 100644
--- a/tools/eslint/lib/rules/id-length.js
+++ b/tools/eslint/lib/rules/id-length.js
@@ -96,7 +96,7 @@ module.exports = {
const isLong = name.length > maxLength;
if (!(isShort || isLong) || exceptions[name]) {
- return; // Nothing to report
+ return; // Nothing to report
}
const isValidExpression = SUPPORTED_EXPRESSIONS[parent.type];
diff --git a/tools/eslint/lib/rules/indent-legacy.js b/tools/eslint/lib/rules/indent-legacy.js
new file mode 100644
index 00000000000000..f686c18ee3f9e5
--- /dev/null
+++ b/tools/eslint/lib/rules/indent-legacy.js
@@ -0,0 +1,1125 @@
+/**
+ * @fileoverview This option sets a specific tab width for your code
+ *
+ * This rule has been ported and modified from nodeca.
+ * @author Vitaly Puzrin
+ * @author Gyandeep Singh
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const astUtils = require("../ast-utils");
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+/* istanbul ignore next: this rule has known coverage issues, but it's deprecated and shouldn't be updated in the future anyway. */
+module.exports = {
+ meta: {
+ docs: {
+ description: "enforce consistent indentation",
+ category: "Stylistic Issues",
+ recommended: false,
+ replacedBy: ["indent"]
+ },
+
+ deprecated: true,
+
+ fixable: "whitespace",
+
+ schema: [
+ {
+ oneOf: [
+ {
+ enum: ["tab"]
+ },
+ {
+ type: "integer",
+ minimum: 0
+ }
+ ]
+ },
+ {
+ type: "object",
+ properties: {
+ SwitchCase: {
+ type: "integer",
+ minimum: 0
+ },
+ VariableDeclarator: {
+ oneOf: [
+ {
+ type: "integer",
+ minimum: 0
+ },
+ {
+ type: "object",
+ properties: {
+ var: {
+ type: "integer",
+ minimum: 0
+ },
+ let: {
+ type: "integer",
+ minimum: 0
+ },
+ const: {
+ type: "integer",
+ minimum: 0
+ }
+ }
+ }
+ ]
+ },
+ outerIIFEBody: {
+ type: "integer",
+ minimum: 0
+ },
+ MemberExpression: {
+ type: "integer",
+ minimum: 0
+ },
+ FunctionDeclaration: {
+ type: "object",
+ properties: {
+ parameters: {
+ oneOf: [
+ {
+ type: "integer",
+ minimum: 0
+ },
+ {
+ enum: ["first"]
+ }
+ ]
+ },
+ body: {
+ type: "integer",
+ minimum: 0
+ }
+ }
+ },
+ FunctionExpression: {
+ type: "object",
+ properties: {
+ parameters: {
+ oneOf: [
+ {
+ type: "integer",
+ minimum: 0
+ },
+ {
+ enum: ["first"]
+ }
+ ]
+ },
+ body: {
+ type: "integer",
+ minimum: 0
+ }
+ }
+ },
+ CallExpression: {
+ type: "object",
+ properties: {
+ parameters: {
+ oneOf: [
+ {
+ type: "integer",
+ minimum: 0
+ },
+ {
+ enum: ["first"]
+ }
+ ]
+ }
+ }
+ },
+ ArrayExpression: {
+ oneOf: [
+ {
+ type: "integer",
+ minimum: 0
+ },
+ {
+ enum: ["first"]
+ }
+ ]
+ },
+ ObjectExpression: {
+ oneOf: [
+ {
+ type: "integer",
+ minimum: 0
+ },
+ {
+ enum: ["first"]
+ }
+ ]
+ }
+ },
+ additionalProperties: false
+ }
+ ]
+ },
+
+ create(context) {
+ const DEFAULT_VARIABLE_INDENT = 1;
+ const DEFAULT_PARAMETER_INDENT = null; // For backwards compatibility, don't check parameter indentation unless specified in the config
+ const DEFAULT_FUNCTION_BODY_INDENT = 1;
+
+ let indentType = "space";
+ let indentSize = 4;
+ const options = {
+ SwitchCase: 0,
+ VariableDeclarator: {
+ var: DEFAULT_VARIABLE_INDENT,
+ let: DEFAULT_VARIABLE_INDENT,
+ const: DEFAULT_VARIABLE_INDENT
+ },
+ outerIIFEBody: null,
+ FunctionDeclaration: {
+ parameters: DEFAULT_PARAMETER_INDENT,
+ body: DEFAULT_FUNCTION_BODY_INDENT
+ },
+ FunctionExpression: {
+ parameters: DEFAULT_PARAMETER_INDENT,
+ body: DEFAULT_FUNCTION_BODY_INDENT
+ },
+ CallExpression: {
+ arguments: DEFAULT_PARAMETER_INDENT
+ },
+ ArrayExpression: 1,
+ ObjectExpression: 1
+ };
+
+ const sourceCode = context.getSourceCode();
+
+ if (context.options.length) {
+ if (context.options[0] === "tab") {
+ indentSize = 1;
+ indentType = "tab";
+ } else /* istanbul ignore else : this will be caught by options validation */ if (typeof context.options[0] === "number") {
+ indentSize = context.options[0];
+ indentType = "space";
+ }
+
+ if (context.options[1]) {
+ const opts = context.options[1];
+
+ options.SwitchCase = opts.SwitchCase || 0;
+ const variableDeclaratorRules = opts.VariableDeclarator;
+
+ if (typeof variableDeclaratorRules === "number") {
+ options.VariableDeclarator = {
+ var: variableDeclaratorRules,
+ let: variableDeclaratorRules,
+ const: variableDeclaratorRules
+ };
+ } else if (typeof variableDeclaratorRules === "object") {
+ Object.assign(options.VariableDeclarator, variableDeclaratorRules);
+ }
+
+ if (typeof opts.outerIIFEBody === "number") {
+ options.outerIIFEBody = opts.outerIIFEBody;
+ }
+
+ if (typeof opts.MemberExpression === "number") {
+ options.MemberExpression = opts.MemberExpression;
+ }
+
+ if (typeof opts.FunctionDeclaration === "object") {
+ Object.assign(options.FunctionDeclaration, opts.FunctionDeclaration);
+ }
+
+ if (typeof opts.FunctionExpression === "object") {
+ Object.assign(options.FunctionExpression, opts.FunctionExpression);
+ }
+
+ if (typeof opts.CallExpression === "object") {
+ Object.assign(options.CallExpression, opts.CallExpression);
+ }
+
+ if (typeof opts.ArrayExpression === "number" || typeof opts.ArrayExpression === "string") {
+ options.ArrayExpression = opts.ArrayExpression;
+ }
+
+ if (typeof opts.ObjectExpression === "number" || typeof opts.ObjectExpression === "string") {
+ options.ObjectExpression = opts.ObjectExpression;
+ }
+ }
+ }
+
+ const caseIndentStore = {};
+
+ /**
+ * Creates an error message for a line, given the expected/actual indentation.
+ * @param {int} expectedAmount The expected amount of indentation characters for this line
+ * @param {int} actualSpaces The actual number of indentation spaces that were found on this line
+ * @param {int} actualTabs The actual number of indentation tabs that were found on this line
+ * @returns {string} An error message for this line
+ */
+ function createErrorMessage(expectedAmount, actualSpaces, actualTabs) {
+ const expectedStatement = `${expectedAmount} ${indentType}${expectedAmount === 1 ? "" : "s"}`; // e.g. "2 tabs"
+ const foundSpacesWord = `space${actualSpaces === 1 ? "" : "s"}`; // e.g. "space"
+ const foundTabsWord = `tab${actualTabs === 1 ? "" : "s"}`; // e.g. "tabs"
+ let foundStatement;
+
+ if (actualSpaces > 0 && actualTabs > 0) {
+ foundStatement = `${actualSpaces} ${foundSpacesWord} and ${actualTabs} ${foundTabsWord}`; // e.g. "1 space and 2 tabs"
+ } else if (actualSpaces > 0) {
+
+ // Abbreviate the message if the expected indentation is also spaces.
+ // e.g. 'Expected 4 spaces but found 2' rather than 'Expected 4 spaces but found 2 spaces'
+ foundStatement = indentType === "space" ? actualSpaces : `${actualSpaces} ${foundSpacesWord}`;
+ } else if (actualTabs > 0) {
+ foundStatement = indentType === "tab" ? actualTabs : `${actualTabs} ${foundTabsWord}`;
+ } else {
+ foundStatement = "0";
+ }
+
+ return `Expected indentation of ${expectedStatement} but found ${foundStatement}.`;
+ }
+
+ /**
+ * Reports a given indent violation
+ * @param {ASTNode} node Node violating the indent rule
+ * @param {int} needed Expected indentation character count
+ * @param {int} gottenSpaces Indentation space count in the actual node/code
+ * @param {int} gottenTabs Indentation tab count in the actual node/code
+ * @param {Object=} loc Error line and column location
+ * @param {boolean} isLastNodeCheck Is the error for last node check
+ * @param {int} lastNodeCheckEndOffset Number of charecters to skip from the end
+ * @returns {void}
+ */
+ function report(node, needed, gottenSpaces, gottenTabs, loc, isLastNodeCheck) {
+ if (gottenSpaces && gottenTabs) {
+
+ // To avoid conflicts with `no-mixed-spaces-and-tabs`, don't report lines that have both spaces and tabs.
+ return;
+ }
+
+ const desiredIndent = (indentType === "space" ? " " : "\t").repeat(needed);
+
+ const textRange = isLastNodeCheck
+ ? [node.range[1] - node.loc.end.column, node.range[1] - node.loc.end.column + gottenSpaces + gottenTabs]
+ : [node.range[0] - node.loc.start.column, node.range[0] - node.loc.start.column + gottenSpaces + gottenTabs];
+
+ context.report({
+ node,
+ loc,
+ message: createErrorMessage(needed, gottenSpaces, gottenTabs),
+ fix: fixer => fixer.replaceTextRange(textRange, desiredIndent)
+ });
+ }
+
+ /**
+ * Get the actual indent of node
+ * @param {ASTNode|Token} node Node to examine
+ * @param {boolean} [byLastLine=false] get indent of node's last line
+ * @returns {Object} The node's indent. Contains keys `space` and `tab`, representing the indent of each character. Also
+ contains keys `goodChar` and `badChar`, where `goodChar` is the amount of the user's desired indentation character, and
+ `badChar` is the amount of the other indentation character.
+ */
+ function getNodeIndent(node, byLastLine) {
+ const token = byLastLine ? sourceCode.getLastToken(node) : sourceCode.getFirstToken(node);
+ const srcCharsBeforeNode = sourceCode.getText(token, token.loc.start.column).split("");
+ const indentChars = srcCharsBeforeNode.slice(0, srcCharsBeforeNode.findIndex(char => char !== " " && char !== "\t"));
+ const spaces = indentChars.filter(char => char === " ").length;
+ const tabs = indentChars.filter(char => char === "\t").length;
+
+ return {
+ space: spaces,
+ tab: tabs,
+ goodChar: indentType === "space" ? spaces : tabs,
+ badChar: indentType === "space" ? tabs : spaces
+ };
+ }
+
+ /**
+ * Checks node is the first in its own start line. By default it looks by start line.
+ * @param {ASTNode} node The node to check
+ * @param {boolean} [byEndLocation=false] Lookup based on start position or end
+ * @returns {boolean} true if its the first in the its start line
+ */
+ function isNodeFirstInLine(node, byEndLocation) {
+ const firstToken = byEndLocation === true ? sourceCode.getLastToken(node, 1) : sourceCode.getTokenBefore(node),
+ startLine = byEndLocation === true ? node.loc.end.line : node.loc.start.line,
+ endLine = firstToken ? firstToken.loc.end.line : -1;
+
+ return startLine !== endLine;
+ }
+
+ /**
+ * Check indent for node
+ * @param {ASTNode} node Node to check
+ * @param {int} neededIndent needed indent
+ * @param {boolean} [excludeCommas=false] skip comma on start of line
+ * @returns {void}
+ */
+ function checkNodeIndent(node, neededIndent) {
+ const actualIndent = getNodeIndent(node, false);
+
+ if (
+ node.type !== "ArrayExpression" &&
+ node.type !== "ObjectExpression" &&
+ (actualIndent.goodChar !== neededIndent || actualIndent.badChar !== 0) &&
+ isNodeFirstInLine(node)
+ ) {
+ report(node, neededIndent, actualIndent.space, actualIndent.tab);
+ }
+
+ if (node.type === "IfStatement" && node.alternate) {
+ const elseToken = sourceCode.getTokenBefore(node.alternate);
+
+ checkNodeIndent(elseToken, neededIndent);
+
+ if (!isNodeFirstInLine(node.alternate)) {
+ checkNodeIndent(node.alternate, neededIndent);
+ }
+ }
+
+ if (node.type === "TryStatement" && node.handler) {
+ const catchToken = sourceCode.getFirstToken(node.handler);
+
+ checkNodeIndent(catchToken, neededIndent);
+ }
+
+ if (node.type === "TryStatement" && node.finalizer) {
+ const finallyToken = sourceCode.getTokenBefore(node.finalizer);
+
+ checkNodeIndent(finallyToken, neededIndent);
+ }
+
+ if (node.type === "DoWhileStatement") {
+ const whileToken = sourceCode.getTokenAfter(node.body);
+
+ checkNodeIndent(whileToken, neededIndent);
+ }
+ }
+
+ /**
+ * Check indent for nodes list
+ * @param {ASTNode[]} nodes list of node objects
+ * @param {int} indent needed indent
+ * @param {boolean} [excludeCommas=false] skip comma on start of line
+ * @returns {void}
+ */
+ function checkNodesIndent(nodes, indent) {
+ nodes.forEach(node => checkNodeIndent(node, indent));
+ }
+
+ /**
+ * Check last node line indent this detects, that block closed correctly
+ * @param {ASTNode} node Node to examine
+ * @param {int} lastLineIndent needed indent
+ * @returns {void}
+ */
+ function checkLastNodeLineIndent(node, lastLineIndent) {
+ const lastToken = sourceCode.getLastToken(node);
+ const endIndent = getNodeIndent(lastToken, true);
+
+ if ((endIndent.goodChar !== lastLineIndent || endIndent.badChar !== 0) && isNodeFirstInLine(node, true)) {
+ report(
+ node,
+ lastLineIndent,
+ endIndent.space,
+ endIndent.tab,
+ { line: lastToken.loc.start.line, column: lastToken.loc.start.column },
+ true
+ );
+ }
+ }
+
+ /**
+ * Check last node line indent this detects, that block closed correctly
+ * This function for more complicated return statement case, where closing parenthesis may be followed by ';'
+ * @param {ASTNode} node Node to examine
+ * @param {int} firstLineIndent first line needed indent
+ * @returns {void}
+ */
+ function checkLastReturnStatementLineIndent(node, firstLineIndent) {
+
+ // in case if return statement ends with ');' we have traverse back to ')'
+ // otherwise we'll measure indent for ';' and replace ')'
+ const lastToken = sourceCode.getLastToken(node, astUtils.isClosingParenToken);
+ const textBeforeClosingParenthesis = sourceCode.getText(lastToken, lastToken.loc.start.column).slice(0, -1);
+
+ if (textBeforeClosingParenthesis.trim()) {
+
+ // There are tokens before the closing paren, don't report this case
+ return;
+ }
+
+ const endIndent = getNodeIndent(lastToken, true);
+
+ if (endIndent.goodChar !== firstLineIndent) {
+ report(
+ node,
+ firstLineIndent,
+ endIndent.space,
+ endIndent.tab,
+ { line: lastToken.loc.start.line, column: lastToken.loc.start.column },
+ true
+ );
+ }
+ }
+
+ /**
+ * Check first node line indent is correct
+ * @param {ASTNode} node Node to examine
+ * @param {int} firstLineIndent needed indent
+ * @returns {void}
+ */
+ function checkFirstNodeLineIndent(node, firstLineIndent) {
+ const startIndent = getNodeIndent(node, false);
+
+ if ((startIndent.goodChar !== firstLineIndent || startIndent.badChar !== 0) && isNodeFirstInLine(node)) {
+ report(
+ node,
+ firstLineIndent,
+ startIndent.space,
+ startIndent.tab,
+ { line: node.loc.start.line, column: node.loc.start.column }
+ );
+ }
+ }
+
+ /**
+ * Returns a parent node of given node based on a specified type
+ * if not present then return null
+ * @param {ASTNode} node node to examine
+ * @param {string} type type that is being looked for
+ * @param {string} stopAtList end points for the evaluating code
+ * @returns {ASTNode|void} if found then node otherwise null
+ */
+ function getParentNodeByType(node, type, stopAtList) {
+ let parent = node.parent;
+
+ if (!stopAtList) {
+ stopAtList = ["Program"];
+ }
+
+ while (parent.type !== type && stopAtList.indexOf(parent.type) === -1 && parent.type !== "Program") {
+ parent = parent.parent;
+ }
+
+ return parent.type === type ? parent : null;
+ }
+
+ /**
+ * Returns the VariableDeclarator based on the current node
+ * if not present then return null
+ * @param {ASTNode} node node to examine
+ * @returns {ASTNode|void} if found then node otherwise null
+ */
+ function getVariableDeclaratorNode(node) {
+ return getParentNodeByType(node, "VariableDeclarator");
+ }
+
+ /**
+ * Check to see if the node is part of the multi-line variable declaration.
+ * Also if its on the same line as the varNode
+ * @param {ASTNode} node node to check
+ * @param {ASTNode} varNode variable declaration node to check against
+ * @returns {boolean} True if all the above condition satisfy
+ */
+ function isNodeInVarOnTop(node, varNode) {
+ return varNode &&
+ varNode.parent.loc.start.line === node.loc.start.line &&
+ varNode.parent.declarations.length > 1;
+ }
+
+ /**
+ * Check to see if the argument before the callee node is multi-line and
+ * there should only be 1 argument before the callee node
+ * @param {ASTNode} node node to check
+ * @returns {boolean} True if arguments are multi-line
+ */
+ function isArgBeforeCalleeNodeMultiline(node) {
+ const parent = node.parent;
+
+ if (parent.arguments.length >= 2 && parent.arguments[1] === node) {
+ return parent.arguments[0].loc.end.line > parent.arguments[0].loc.start.line;
+ }
+
+ return false;
+ }
+
+ /**
+ * Check to see if the node is a file level IIFE
+ * @param {ASTNode} node The function node to check.
+ * @returns {boolean} True if the node is the outer IIFE
+ */
+ function isOuterIIFE(node) {
+ const parent = node.parent;
+ let stmt = parent.parent;
+
+ /*
+ * Verify that the node is an IIEF
+ */
+ if (
+ parent.type !== "CallExpression" ||
+ parent.callee !== node) {
+
+ return false;
+ }
+
+ /*
+ * Navigate legal ancestors to determine whether this IIEF is outer
+ */
+ while (
+ stmt.type === "UnaryExpression" && (
+ stmt.operator === "!" ||
+ stmt.operator === "~" ||
+ stmt.operator === "+" ||
+ stmt.operator === "-") ||
+ stmt.type === "AssignmentExpression" ||
+ stmt.type === "LogicalExpression" ||
+ stmt.type === "SequenceExpression" ||
+ stmt.type === "VariableDeclarator") {
+
+ stmt = stmt.parent;
+ }
+
+ return ((
+ stmt.type === "ExpressionStatement" ||
+ stmt.type === "VariableDeclaration") &&
+ stmt.parent && stmt.parent.type === "Program"
+ );
+ }
+
+ /**
+ * Check indent for function block content
+ * @param {ASTNode} node A BlockStatement node that is inside of a function.
+ * @returns {void}
+ */
+ function checkIndentInFunctionBlock(node) {
+
+ /*
+ * Search first caller in chain.
+ * Ex.:
+ *
+ * Models <- Identifier
+ * .User
+ * .find()
+ * .exec(function() {
+ * // function body
+ * });
+ *
+ * Looks for 'Models'
+ */
+ const calleeNode = node.parent; // FunctionExpression
+ let indent;
+
+ if (calleeNode.parent &&
+ (calleeNode.parent.type === "Property" ||
+ calleeNode.parent.type === "ArrayExpression")) {
+
+ // If function is part of array or object, comma can be put at left
+ indent = getNodeIndent(calleeNode, false).goodChar;
+ } else {
+
+ // If function is standalone, simple calculate indent
+ indent = getNodeIndent(calleeNode).goodChar;
+ }
+
+ if (calleeNode.parent.type === "CallExpression") {
+ const calleeParent = calleeNode.parent;
+
+ if (calleeNode.type !== "FunctionExpression" && calleeNode.type !== "ArrowFunctionExpression") {
+ if (calleeParent && calleeParent.loc.start.line < node.loc.start.line) {
+ indent = getNodeIndent(calleeParent).goodChar;
+ }
+ } else {
+ if (isArgBeforeCalleeNodeMultiline(calleeNode) &&
+ calleeParent.callee.loc.start.line === calleeParent.callee.loc.end.line &&
+ !isNodeFirstInLine(calleeNode)) {
+ indent = getNodeIndent(calleeParent).goodChar;
+ }
+ }
+ }
+
+ // function body indent should be indent + indent size, unless this
+ // is a FunctionDeclaration, FunctionExpression, or outer IIFE and the corresponding options are enabled.
+ let functionOffset = indentSize;
+
+ if (options.outerIIFEBody !== null && isOuterIIFE(calleeNode)) {
+ functionOffset = options.outerIIFEBody * indentSize;
+ } else if (calleeNode.type === "FunctionExpression") {
+ functionOffset = options.FunctionExpression.body * indentSize;
+ } else if (calleeNode.type === "FunctionDeclaration") {
+ functionOffset = options.FunctionDeclaration.body * indentSize;
+ }
+ indent += functionOffset;
+
+ // check if the node is inside a variable
+ const parentVarNode = getVariableDeclaratorNode(node);
+
+ if (parentVarNode && isNodeInVarOnTop(node, parentVarNode)) {
+ indent += indentSize * options.VariableDeclarator[parentVarNode.parent.kind];
+ }
+
+ if (node.body.length > 0) {
+ checkNodesIndent(node.body, indent);
+ }
+
+ checkLastNodeLineIndent(node, indent - functionOffset);
+ }
+
+
+ /**
+ * Checks if the given node starts and ends on the same line
+ * @param {ASTNode} node The node to check
+ * @returns {boolean} Whether or not the block starts and ends on the same line.
+ */
+ function isSingleLineNode(node) {
+ const lastToken = sourceCode.getLastToken(node),
+ startLine = node.loc.start.line,
+ endLine = lastToken.loc.end.line;
+
+ return startLine === endLine;
+ }
+
+ /**
+ * Check to see if the first element inside an array is an object and on the same line as the node
+ * If the node is not an array then it will return false.
+ * @param {ASTNode} node node to check
+ * @returns {boolean} success/failure
+ */
+ function isFirstArrayElementOnSameLine(node) {
+ if (node.type === "ArrayExpression" && node.elements[0]) {
+ return node.elements[0].loc.start.line === node.loc.start.line && node.elements[0].type === "ObjectExpression";
+ }
+ return false;
+
+ }
+
+ /**
+ * Check indent for array block content or object block content
+ * @param {ASTNode} node node to examine
+ * @returns {void}
+ */
+ function checkIndentInArrayOrObjectBlock(node) {
+
+ // Skip inline
+ if (isSingleLineNode(node)) {
+ return;
+ }
+
+ let elements = (node.type === "ArrayExpression") ? node.elements : node.properties;
+
+ // filter out empty elements example would be [ , 2] so remove first element as espree considers it as null
+ elements = elements.filter(elem => elem !== null);
+
+ let nodeIndent;
+ let elementsIndent;
+ const parentVarNode = getVariableDeclaratorNode(node);
+
+ // TODO - come up with a better strategy in future
+ if (isNodeFirstInLine(node)) {
+ const parent = node.parent;
+
+ nodeIndent = getNodeIndent(parent).goodChar;
+ if (!parentVarNode || parentVarNode.loc.start.line !== node.loc.start.line) {
+ if (parent.type !== "VariableDeclarator" || parentVarNode === parentVarNode.parent.declarations[0]) {
+ if (parent.type === "VariableDeclarator" && parentVarNode.loc.start.line === parent.loc.start.line) {
+ nodeIndent = nodeIndent + (indentSize * options.VariableDeclarator[parentVarNode.parent.kind]);
+ } else if (parent.type === "ObjectExpression" || parent.type === "ArrayExpression") {
+ const parentElements = node.parent.type === "ObjectExpression" ? node.parent.properties : node.parent.elements;
+
+ if (parentElements[0] && parentElements[0].loc.start.line === parent.loc.start.line && parentElements[0].loc.end.line !== parent.loc.start.line) {
+
+ /*
+ * If the first element of the array spans multiple lines, don't increase the expected indentation of the rest.
+ * e.g. [{
+ * foo: 1
+ * },
+ * {
+ * bar: 1
+ * }]
+ * the second object is not indented.
+ */
+ } else if (typeof options[parent.type] === "number") {
+ nodeIndent += options[parent.type] * indentSize;
+ } else {
+ nodeIndent = parentElements[0].loc.start.column;
+ }
+ } else if (parent.type === "CallExpression" || parent.type === "NewExpression") {
+ if (typeof options.CallExpression.arguments === "number") {
+ nodeIndent += options.CallExpression.arguments * indentSize;
+ } else if (options.CallExpression.arguments === "first") {
+ if (parent.arguments.indexOf(node) !== -1) {
+ nodeIndent = parent.arguments[0].loc.start.column;
+ }
+ } else {
+ nodeIndent += indentSize;
+ }
+ } else if (parent.type === "LogicalExpression" || parent.type === "ArrowFunctionExpression") {
+ nodeIndent += indentSize;
+ }
+ }
+ } else if (!parentVarNode && !isFirstArrayElementOnSameLine(parent) && parent.type !== "MemberExpression" && parent.type !== "ExpressionStatement" && parent.type !== "AssignmentExpression" && parent.type !== "Property") {
+ nodeIndent = nodeIndent + indentSize;
+ }
+
+ checkFirstNodeLineIndent(node, nodeIndent);
+ } else {
+ nodeIndent = getNodeIndent(node).goodChar;
+ }
+
+ if (options[node.type] === "first") {
+ elementsIndent = elements.length ? elements[0].loc.start.column : 0; // If there are no elements, elementsIndent doesn't matter.
+ } else {
+ elementsIndent = nodeIndent + indentSize * options[node.type];
+ }
+
+ /*
+ * Check if the node is a multiple variable declaration; if so, then
+ * make sure indentation takes that into account.
+ */
+ if (isNodeInVarOnTop(node, parentVarNode)) {
+ elementsIndent += indentSize * options.VariableDeclarator[parentVarNode.parent.kind];
+ }
+
+ checkNodesIndent(elements, elementsIndent);
+
+ if (elements.length > 0) {
+
+ // Skip last block line check if last item in same line
+ if (elements[elements.length - 1].loc.end.line === node.loc.end.line) {
+ return;
+ }
+ }
+
+ checkLastNodeLineIndent(node, nodeIndent + (isNodeInVarOnTop(node, parentVarNode) ? options.VariableDeclarator[parentVarNode.parent.kind] * indentSize : 0));
+ }
+
+ /**
+ * Check if the node or node body is a BlockStatement or not
+ * @param {ASTNode} node node to test
+ * @returns {boolean} True if it or its body is a block statement
+ */
+ function isNodeBodyBlock(node) {
+ return node.type === "BlockStatement" || node.type === "ClassBody" || (node.body && node.body.type === "BlockStatement") ||
+ (node.consequent && node.consequent.type === "BlockStatement");
+ }
+
+ /**
+ * Check indentation for blocks
+ * @param {ASTNode} node node to check
+ * @returns {void}
+ */
+ function blockIndentationCheck(node) {
+
+ // Skip inline blocks
+ if (isSingleLineNode(node)) {
+ return;
+ }
+
+ if (node.parent && (
+ node.parent.type === "FunctionExpression" ||
+ node.parent.type === "FunctionDeclaration" ||
+ node.parent.type === "ArrowFunctionExpression")
+ ) {
+ checkIndentInFunctionBlock(node);
+ return;
+ }
+
+ let indent;
+ let nodesToCheck = [];
+
+ /*
+ * For this statements we should check indent from statement beginning,
+ * not from the beginning of the block.
+ */
+ const statementsWithProperties = [
+ "IfStatement", "WhileStatement", "ForStatement", "ForInStatement", "ForOfStatement", "DoWhileStatement", "ClassDeclaration", "TryStatement"
+ ];
+
+ if (node.parent && statementsWithProperties.indexOf(node.parent.type) !== -1 && isNodeBodyBlock(node)) {
+ indent = getNodeIndent(node.parent).goodChar;
+ } else if (node.parent && node.parent.type === "CatchClause") {
+ indent = getNodeIndent(node.parent.parent).goodChar;
+ } else {
+ indent = getNodeIndent(node).goodChar;
+ }
+
+ if (node.type === "IfStatement" && node.consequent.type !== "BlockStatement") {
+ nodesToCheck = [node.consequent];
+ } else if (Array.isArray(node.body)) {
+ nodesToCheck = node.body;
+ } else {
+ nodesToCheck = [node.body];
+ }
+
+ if (nodesToCheck.length > 0) {
+ checkNodesIndent(nodesToCheck, indent + indentSize);
+ }
+
+ if (node.type === "BlockStatement") {
+ checkLastNodeLineIndent(node, indent);
+ }
+ }
+
+ /**
+ * Filter out the elements which are on the same line of each other or the node.
+ * basically have only 1 elements from each line except the variable declaration line.
+ * @param {ASTNode} node Variable declaration node
+ * @returns {ASTNode[]} Filtered elements
+ */
+ function filterOutSameLineVars(node) {
+ return node.declarations.reduce((finalCollection, elem) => {
+ const lastElem = finalCollection[finalCollection.length - 1];
+
+ if ((elem.loc.start.line !== node.loc.start.line && !lastElem) ||
+ (lastElem && lastElem.loc.start.line !== elem.loc.start.line)) {
+ finalCollection.push(elem);
+ }
+
+ return finalCollection;
+ }, []);
+ }
+
+ /**
+ * Check indentation for variable declarations
+ * @param {ASTNode} node node to examine
+ * @returns {void}
+ */
+ function checkIndentInVariableDeclarations(node) {
+ const elements = filterOutSameLineVars(node);
+ const nodeIndent = getNodeIndent(node).goodChar;
+ const lastElement = elements[elements.length - 1];
+
+ const elementsIndent = nodeIndent + indentSize * options.VariableDeclarator[node.kind];
+
+ checkNodesIndent(elements, elementsIndent);
+
+ // Only check the last line if there is any token after the last item
+ if (sourceCode.getLastToken(node).loc.end.line <= lastElement.loc.end.line) {
+ return;
+ }
+
+ const tokenBeforeLastElement = sourceCode.getTokenBefore(lastElement);
+
+ if (tokenBeforeLastElement.value === ",") {
+
+ // Special case for comma-first syntax where the semicolon is indented
+ checkLastNodeLineIndent(node, getNodeIndent(tokenBeforeLastElement).goodChar);
+ } else {
+ checkLastNodeLineIndent(node, elementsIndent - indentSize);
+ }
+ }
+
+ /**
+ * Check and decide whether to check for indentation for blockless nodes
+ * Scenarios are for or while statements without braces around them
+ * @param {ASTNode} node node to examine
+ * @returns {void}
+ */
+ function blockLessNodes(node) {
+ if (node.body.type !== "BlockStatement") {
+ blockIndentationCheck(node);
+ }
+ }
+
+ /**
+ * Returns the expected indentation for the case statement
+ * @param {ASTNode} node node to examine
+ * @param {int} [switchIndent] indent for switch statement
+ * @returns {int} indent size
+ */
+ function expectedCaseIndent(node, switchIndent) {
+ const switchNode = (node.type === "SwitchStatement") ? node : node.parent;
+ let caseIndent;
+
+ if (caseIndentStore[switchNode.loc.start.line]) {
+ return caseIndentStore[switchNode.loc.start.line];
+ }
+ if (typeof switchIndent === "undefined") {
+ switchIndent = getNodeIndent(switchNode).goodChar;
+ }
+
+ if (switchNode.cases.length > 0 && options.SwitchCase === 0) {
+ caseIndent = switchIndent;
+ } else {
+ caseIndent = switchIndent + (indentSize * options.SwitchCase);
+ }
+
+ caseIndentStore[switchNode.loc.start.line] = caseIndent;
+ return caseIndent;
+
+ }
+
+ /**
+ * Checks wether a return statement is wrapped in ()
+ * @param {ASTNode} node node to examine
+ * @returns {boolean} the result
+ */
+ function isWrappedInParenthesis(node) {
+ const regex = /^return\s*?\(\s*?\);*?/;
+
+ const statementWithoutArgument = sourceCode.getText(node).replace(
+ sourceCode.getText(node.argument), "");
+
+ return regex.test(statementWithoutArgument);
+ }
+
+ return {
+ Program(node) {
+ if (node.body.length > 0) {
+
+ // Root nodes should have no indent
+ checkNodesIndent(node.body, getNodeIndent(node).goodChar);
+ }
+ },
+
+ ClassBody: blockIndentationCheck,
+
+ BlockStatement: blockIndentationCheck,
+
+ WhileStatement: blockLessNodes,
+
+ ForStatement: blockLessNodes,
+
+ ForInStatement: blockLessNodes,
+
+ ForOfStatement: blockLessNodes,
+
+ DoWhileStatement: blockLessNodes,
+
+ IfStatement(node) {
+ if (node.consequent.type !== "BlockStatement" && node.consequent.loc.start.line > node.loc.start.line) {
+ blockIndentationCheck(node);
+ }
+ },
+
+ VariableDeclaration(node) {
+ if (node.declarations[node.declarations.length - 1].loc.start.line > node.declarations[0].loc.start.line) {
+ checkIndentInVariableDeclarations(node);
+ }
+ },
+
+ ObjectExpression(node) {
+ checkIndentInArrayOrObjectBlock(node);
+ },
+
+ ArrayExpression(node) {
+ checkIndentInArrayOrObjectBlock(node);
+ },
+
+ MemberExpression(node) {
+
+ if (typeof options.MemberExpression === "undefined") {
+ return;
+ }
+
+ if (isSingleLineNode(node)) {
+ return;
+ }
+
+ // The typical layout of variable declarations and assignments
+ // alter the expectation of correct indentation. Skip them.
+ // TODO: Add appropriate configuration options for variable
+ // declarations and assignments.
+ if (getParentNodeByType(node, "VariableDeclarator", ["FunctionExpression", "ArrowFunctionExpression"])) {
+ return;
+ }
+
+ if (getParentNodeByType(node, "AssignmentExpression", ["FunctionExpression"])) {
+ return;
+ }
+
+ const propertyIndent = getNodeIndent(node).goodChar + indentSize * options.MemberExpression;
+
+ const checkNodes = [node.property];
+
+ const dot = context.getTokenBefore(node.property);
+
+ if (dot.type === "Punctuator" && dot.value === ".") {
+ checkNodes.push(dot);
+ }
+
+ checkNodesIndent(checkNodes, propertyIndent);
+ },
+
+ SwitchStatement(node) {
+
+ // Switch is not a 'BlockStatement'
+ const switchIndent = getNodeIndent(node).goodChar;
+ const caseIndent = expectedCaseIndent(node, switchIndent);
+
+ checkNodesIndent(node.cases, caseIndent);
+
+
+ checkLastNodeLineIndent(node, switchIndent);
+ },
+
+ SwitchCase(node) {
+
+ // Skip inline cases
+ if (isSingleLineNode(node)) {
+ return;
+ }
+ const caseIndent = expectedCaseIndent(node);
+
+ checkNodesIndent(node.consequent, caseIndent + indentSize);
+ },
+
+ FunctionDeclaration(node) {
+ if (isSingleLineNode(node)) {
+ return;
+ }
+ if (options.FunctionDeclaration.parameters === "first" && node.params.length) {
+ checkNodesIndent(node.params.slice(1), node.params[0].loc.start.column);
+ } else if (options.FunctionDeclaration.parameters !== null) {
+ checkNodesIndent(node.params, getNodeIndent(node).goodChar + indentSize * options.FunctionDeclaration.parameters);
+ }
+ },
+
+ FunctionExpression(node) {
+ if (isSingleLineNode(node)) {
+ return;
+ }
+ if (options.FunctionExpression.parameters === "first" && node.params.length) {
+ checkNodesIndent(node.params.slice(1), node.params[0].loc.start.column);
+ } else if (options.FunctionExpression.parameters !== null) {
+ checkNodesIndent(node.params, getNodeIndent(node).goodChar + indentSize * options.FunctionExpression.parameters);
+ }
+ },
+
+ ReturnStatement(node) {
+ if (isSingleLineNode(node)) {
+ return;
+ }
+
+ const firstLineIndent = getNodeIndent(node).goodChar;
+
+ // in case if return statement is wrapped in parenthesis
+ if (isWrappedInParenthesis(node)) {
+ checkLastReturnStatementLineIndent(node, firstLineIndent);
+ } else {
+ checkNodeIndent(node, firstLineIndent);
+ }
+ },
+
+ CallExpression(node) {
+ if (isSingleLineNode(node)) {
+ return;
+ }
+ if (options.CallExpression.arguments === "first" && node.arguments.length) {
+ checkNodesIndent(node.arguments.slice(1), node.arguments[0].loc.start.column);
+ } else if (options.CallExpression.arguments !== null) {
+ checkNodesIndent(node.arguments, getNodeIndent(node).goodChar + indentSize * options.CallExpression.arguments);
+ }
+ }
+
+ };
+
+ }
+};
diff --git a/tools/eslint/lib/rules/indent.js b/tools/eslint/lib/rules/indent.js
index bba1b20bcf4407..82268975dfbcaa 100644
--- a/tools/eslint/lib/rules/indent.js
+++ b/tools/eslint/lib/rules/indent.js
@@ -12,12 +12,344 @@
// Requirements
//------------------------------------------------------------------------------
+const lodash = require("lodash");
const astUtils = require("../ast-utils");
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
+const KNOWN_NODES = new Set([
+ "AssignmentExpression",
+ "AssignmentPattern",
+ "ArrayExpression",
+ "ArrayPattern",
+ "ArrowFunctionExpression",
+ "AwaitExpression",
+ "BlockStatement",
+ "BinaryExpression",
+ "BreakStatement",
+ "CallExpression",
+ "CatchClause",
+ "ClassBody",
+ "ClassDeclaration",
+ "ClassExpression",
+ "ConditionalExpression",
+ "ContinueStatement",
+ "DoWhileStatement",
+ "DebuggerStatement",
+ "EmptyStatement",
+ "ExperimentalRestProperty",
+ "ExperimentalSpreadProperty",
+ "ExpressionStatement",
+ "ForStatement",
+ "ForInStatement",
+ "ForOfStatement",
+ "FunctionDeclaration",
+ "FunctionExpression",
+ "Identifier",
+ "IfStatement",
+ "Literal",
+ "LabeledStatement",
+ "LogicalExpression",
+ "MemberExpression",
+ "MetaProperty",
+ "MethodDefinition",
+ "NewExpression",
+ "ObjectExpression",
+ "ObjectPattern",
+ "Program",
+ "Property",
+ "RestElement",
+ "ReturnStatement",
+ "SequenceExpression",
+ "SpreadElement",
+ "Super",
+ "SwitchCase",
+ "SwitchStatement",
+ "TaggedTemplateExpression",
+ "TemplateElement",
+ "TemplateLiteral",
+ "ThisExpression",
+ "ThrowStatement",
+ "TryStatement",
+ "UnaryExpression",
+ "UpdateExpression",
+ "VariableDeclaration",
+ "VariableDeclarator",
+ "WhileStatement",
+ "WithStatement",
+ "YieldExpression",
+ "JSXIdentifier",
+ "JSXNamespacedName",
+ "JSXMemberExpression",
+ "JSXEmptyExpression",
+ "JSXExpressionContainer",
+ "JSXElement",
+ "JSXClosingElement",
+ "JSXOpeningElement",
+ "JSXAttribute",
+ "JSXSpreadAttribute",
+ "JSXText",
+ "ExportDefaultDeclaration",
+ "ExportNamedDeclaration",
+ "ExportAllDeclaration",
+ "ExportSpecifier",
+ "ImportDeclaration",
+ "ImportSpecifier",
+ "ImportDefaultSpecifier",
+ "ImportNamespaceSpecifier"
+]);
+
+/*
+ * General rule strategy:
+ * 1. An OffsetStorage instance stores a map of desired offsets, where each token has a specified offset from another
+ * specified token or to the first column.
+ * 2. As the AST is traversed, modify the desired offsets of tokens accordingly. For example, when entering a
+ * BlockStatement, offset all of the tokens in the BlockStatement by 1 indent level from the opening curly
+ * brace of the BlockStatement.
+ * 3. After traversing the AST, calculate the expected indentation levels of every token according to the
+ * OffsetStorage container.
+ * 4. For each line, compare the expected indentation of the first token to the actual indentation in the file,
+ * and report the token if the two values are not equal.
+ */
+
+/**
+ * A helper class to get token-based info related to indentation
+ */
+class TokenInfo {
+
+ /**
+ * @param {SourceCode} sourceCode A SourceCode object
+ */
+ constructor(sourceCode) {
+ this.sourceCode = sourceCode;
+ this.firstTokensByLineNumber = sourceCode.tokensAndComments.reduce((map, token) => {
+ if (!map.has(token.loc.start.line)) {
+ map.set(token.loc.start.line, token);
+ }
+ if (!map.has(token.loc.end.line) && sourceCode.text.slice(token.range[1] - token.loc.end.column, token.range[1]).trim()) {
+ map.set(token.loc.end.line, token);
+ }
+ return map;
+ }, new Map());
+ }
+
+ /**
+ * Gets all tokens and comments
+ * @returns {Token[]} A list of all tokens and comments
+ */
+ getAllTokens() {
+ return this.sourceCode.tokensAndComments;
+ }
+
+ /**
+ * Gets the first token on a given token's line
+ * @param {Token|ASTNode} token a node or token
+ * @returns {Token} The first token on the given line
+ */
+ getFirstTokenOfLine(token) {
+ return this.firstTokensByLineNumber.get(token.loc.start.line);
+ }
+
+ /**
+ * Determines whether a token is the first token in its line
+ * @param {Token} token The token
+ * @returns {boolean} `true` if the token is the first on its line
+ */
+ isFirstTokenOfLine(token) {
+ return this.getFirstTokenOfLine(token) === token;
+ }
+
+ /**
+ * Get the actual indent of a token
+ * @param {Token} token Token to examine. This should be the first token on its line.
+ * @returns {string} The indentation characters that precede the token
+ */
+ getTokenIndent(token) {
+ return this.sourceCode.text.slice(token.range[0] - token.loc.start.column, token.range[0]);
+ }
+}
+
+/**
+ * A class to store information on desired offsets of tokens from each other
+ */
+class OffsetStorage {
+
+ /**
+ * @param {TokenInfo} tokenInfo a TokenInfo instance
+ * @param {string} indentType The desired type of indentation (either "space" or "tab")
+ * @param {number} indentSize The desired size of each indentation level
+ */
+ constructor(tokenInfo, indentType, indentSize) {
+ this.tokenInfo = tokenInfo;
+ this.indentType = indentType;
+ this.indentSize = indentSize;
+
+ /*
+ * desiredOffsets, lockedFirstTokens, and desiredIndentCache conceptually map tokens to something else.
+ * However, they're implemented as objects with range indices as keys because this improves performance as of Node 7.
+ * This uses the assumption that no two tokens start at the same index in the program.
+ *
+ * The values of the desiredOffsets map are objects with the schema { offset: number, from: Token|null }.
+ * These objects should not be mutated or exposed outside of OffsetStorage.
+ */
+ const NO_OFFSET = { offset: 0, from: null };
+
+ this.desiredOffsets = tokenInfo.getAllTokens().reduce((desiredOffsets, token) => {
+ desiredOffsets[token.range[0]] = NO_OFFSET;
+
+ return desiredOffsets;
+ }, Object.create(null));
+ this.lockedFirstTokens = Object.create(null);
+ this.desiredIndentCache = Object.create(null);
+ this.ignoredTokens = new WeakSet();
+ }
+
+ /**
+ * Sets the indent of one token to match the indent of another.
+ * @param {Token} baseToken The first token
+ * @param {Token} offsetToken The second token, whose indent should be matched to the first token
+ * @returns {void}
+ */
+ matchIndentOf(baseToken, offsetToken) {
+ if (baseToken !== offsetToken) {
+ this.desiredOffsets[offsetToken.range[0]] = { offset: 0, from: baseToken };
+ }
+ }
+
+ /**
+ * Sets the offset column of token B to match the offset column of token A.
+ * This is different from matchIndentOf because it matches a *column*, even if baseToken is not
+ * the first token on its line.
+ * @param {Token} baseToken The first token
+ * @param {Token} offsetToken The second token, whose offset should be matched to the first token
+ * @returns {void}
+ */
+ matchOffsetOf(baseToken, offsetToken) {
+
+ /*
+ * lockedFirstTokens is a map from a token whose indentation is controlled by the "first" option to
+ * the token that it depends on. For example, with the `ArrayExpression: first` option, the first
+ * token of each element in the array after the first will be mapped to the first token of the first
+ * element. The desired indentation of each of these tokens is computed based on the desired indentation
+ * of the "first" element, rather than through the normal offset mechanism.
+ */
+ this.lockedFirstTokens[offsetToken.range[0]] = baseToken;
+ }
+
+ /**
+ * Sets the desired offset of a token
+ * @param {Token} token The token
+ * @param {Token} offsetFrom The token that this is offset from
+ * @param {number} offset The desired indent level
+ * @returns {void}
+ */
+ setDesiredOffset(token, offsetFrom, offset) {
+ if (offsetFrom && token.loc.start.line === offsetFrom.loc.start.line) {
+ this.matchIndentOf(offsetFrom, token);
+ } else {
+ this.desiredOffsets[token.range[0]] = { offset, from: offsetFrom };
+ }
+ }
+
+ /**
+ * Sets the desired offset of multiple tokens
+ * @param {Token[]} tokens A list of tokens. These tokens should be consecutive.
+ * @param {Token} offsetFrom The token that this is offset from
+ * @param {number} offset The desired indent level
+ * @returns {void}
+ */
+ setDesiredOffsets(tokens, offsetFrom, offset) {
+
+ /*
+ * TODO: (not-an-aardvark) This function is the main performance holdup for this rule. It works
+ * by setting the desired offset of each token to the given amount relative to the parent, but it's
+ * frequently called with a large list of tokens, and it takes time to set the offset for each token
+ * individually. Since the tokens are always consecutive, it might be possible to improve performance
+ * here by changing the data structure used to store offsets (e.g. allowing a *range* of tokens to
+ * be offset rather than offsetting each token individually).
+ */
+ tokens.forEach(token => this.setDesiredOffset(token, offsetFrom, offset));
+ }
+
+ /**
+ * Gets the desired indent of a token
+ * @param {Token} token The token
+ * @returns {number} The desired indent of the token
+ */
+ getDesiredIndent(token) {
+ if (!(token.range[0] in this.desiredIndentCache)) {
+
+ if (this.ignoredTokens.has(token)) {
+
+ // If the token is ignored, use the actual indent of the token as the desired indent.
+ // This ensures that no errors are reported for this token.
+ this.desiredIndentCache[token.range[0]] = this.tokenInfo.getTokenIndent(token).length / this.indentSize;
+ } else if (token.range[0] in this.lockedFirstTokens) {
+ const firstToken = this.lockedFirstTokens[token.range[0]];
+
+ this.desiredIndentCache[token.range[0]] =
+
+ // (indentation for the first element's line)
+ this.getDesiredIndent(this.tokenInfo.getFirstTokenOfLine(firstToken)) +
+
+ // (space between the start of the first element's line and the first element)
+ (firstToken.loc.start.column - this.tokenInfo.getFirstTokenOfLine(firstToken).loc.start.column) / this.indentSize;
+ } else {
+ const offsetInfo = this.desiredOffsets[token.range[0]];
+
+ this.desiredIndentCache[token.range[0]] = offsetInfo.offset + (offsetInfo.from ? this.getDesiredIndent(offsetInfo.from) : 0);
+ }
+ }
+ return this.desiredIndentCache[token.range[0]];
+ }
+
+ /**
+ * Ignores a token, preventing it from being reported.
+ * @param {Token} token The token
+ * @returns {void}
+ */
+ ignoreToken(token) {
+ if (this.tokenInfo.isFirstTokenOfLine(token)) {
+ this.ignoredTokens.add(token);
+ }
+ }
+
+ /**
+ * Gets the first token that the given token's indentation is dependent on
+ * @param {Token} token The token
+ * @returns {Token} The token that the given token depends on, or `null` if the given token is at the top level
+ */
+ getFirstDependency(token) {
+ return this.desiredOffsets[token.range[0]].from;
+ }
+
+ /**
+ * Increases the offset for a token from its parent by the given amount
+ * @param {Token} token The token whose offset should be increased
+ * @param {number} amount The number of indent levels that the offset should increase by
+ * @returns {void}
+ */
+ increaseOffset(token, amount) {
+ const currentOffsetInfo = this.desiredOffsets[token.range[0]];
+
+ this.desiredOffsets[token.range[0]] = { offset: currentOffsetInfo.offset + amount, from: currentOffsetInfo.from };
+ }
+}
+
+const ELEMENT_LIST_SCHEMA = {
+ oneOf: [
+ {
+ type: "integer",
+ minimum: 0
+ },
+ {
+ enum: ["first", "off"]
+ }
+ ]
+};
+
module.exports = {
meta: {
docs: {
@@ -68,7 +400,8 @@ module.exports = {
type: "integer",
minimum: 0
}
- }
+ },
+ additionalProperties: false
}
]
},
@@ -77,86 +410,49 @@ module.exports = {
minimum: 0
},
MemberExpression: {
- type: "integer",
- minimum: 0
+ oneOf: [
+ {
+ type: "integer",
+ minimum: 0
+ },
+ {
+ enum: ["off"]
+ }
+ ]
},
FunctionDeclaration: {
type: "object",
properties: {
- parameters: {
- oneOf: [
- {
- type: "integer",
- minimum: 0
- },
- {
- enum: ["first"]
- }
- ]
- },
+ parameters: ELEMENT_LIST_SCHEMA,
body: {
type: "integer",
minimum: 0
}
- }
+ },
+ additionalProperties: false
},
FunctionExpression: {
type: "object",
properties: {
- parameters: {
- oneOf: [
- {
- type: "integer",
- minimum: 0
- },
- {
- enum: ["first"]
- }
- ]
- },
+ parameters: ELEMENT_LIST_SCHEMA,
body: {
type: "integer",
minimum: 0
}
- }
+ },
+ additionalProperties: false
},
CallExpression: {
type: "object",
properties: {
- parameters: {
- oneOf: [
- {
- type: "integer",
- minimum: 0
- },
- {
- enum: ["first"]
- }
- ]
- }
- }
+ arguments: ELEMENT_LIST_SCHEMA
+ },
+ additionalProperties: false
},
- ArrayExpression: {
- oneOf: [
- {
- type: "integer",
- minimum: 0
- },
- {
- enum: ["first"]
- }
- ]
- },
- ObjectExpression: {
- oneOf: [
- {
- type: "integer",
- minimum: 0
- },
- {
- enum: ["first"]
- }
- ]
+ ArrayExpression: ELEMENT_LIST_SCHEMA,
+ ObjectExpression: ELEMENT_LIST_SCHEMA,
+ flatTernaryExpressions: {
+ type: "boolean"
}
},
additionalProperties: false
@@ -166,7 +462,7 @@ module.exports = {
create(context) {
const DEFAULT_VARIABLE_INDENT = 1;
- const DEFAULT_PARAMETER_INDENT = null; // For backwards compatibility, don't check parameter indentation unless specified in the config
+ const DEFAULT_PARAMETER_INDENT = 1;
const DEFAULT_FUNCTION_BODY_INDENT = 1;
let indentType = "space";
@@ -178,7 +474,7 @@ module.exports = {
let: DEFAULT_VARIABLE_INDENT,
const: DEFAULT_VARIABLE_INDENT
},
- outerIIFEBody: null,
+ outerIIFEBody: 1,
FunctionDeclaration: {
parameters: DEFAULT_PARAMETER_INDENT,
body: DEFAULT_FUNCTION_BODY_INDENT
@@ -190,68 +486,40 @@ module.exports = {
CallExpression: {
arguments: DEFAULT_PARAMETER_INDENT
},
+ MemberExpression: 1,
ArrayExpression: 1,
- ObjectExpression: 1
+ ObjectExpression: 1,
+ ArrayPattern: 1,
+ ObjectPattern: 1,
+ flatTernaryExpressions: false
};
- const sourceCode = context.getSourceCode();
-
if (context.options.length) {
if (context.options[0] === "tab") {
indentSize = 1;
indentType = "tab";
- } else /* istanbul ignore else : this will be caught by options validation */ if (typeof context.options[0] === "number") {
+ } else if (typeof context.options[0] === "number") {
indentSize = context.options[0];
indentType = "space";
}
if (context.options[1]) {
- const opts = context.options[1];
-
- options.SwitchCase = opts.SwitchCase || 0;
- const variableDeclaratorRules = opts.VariableDeclarator;
+ lodash.merge(options, context.options[1]);
- if (typeof variableDeclaratorRules === "number") {
+ if (typeof options.VariableDeclarator === "number") {
options.VariableDeclarator = {
- var: variableDeclaratorRules,
- let: variableDeclaratorRules,
- const: variableDeclaratorRules
+ var: options.VariableDeclarator,
+ let: options.VariableDeclarator,
+ const: options.VariableDeclarator
};
- } else if (typeof variableDeclaratorRules === "object") {
- Object.assign(options.VariableDeclarator, variableDeclaratorRules);
- }
-
- if (typeof opts.outerIIFEBody === "number") {
- options.outerIIFEBody = opts.outerIIFEBody;
- }
-
- if (typeof opts.MemberExpression === "number") {
- options.MemberExpression = opts.MemberExpression;
- }
-
- if (typeof opts.FunctionDeclaration === "object") {
- Object.assign(options.FunctionDeclaration, opts.FunctionDeclaration);
- }
-
- if (typeof opts.FunctionExpression === "object") {
- Object.assign(options.FunctionExpression, opts.FunctionExpression);
- }
-
- if (typeof opts.CallExpression === "object") {
- Object.assign(options.CallExpression, opts.CallExpression);
- }
-
- if (typeof opts.ArrayExpression === "number" || typeof opts.ArrayExpression === "string") {
- options.ArrayExpression = opts.ArrayExpression;
- }
-
- if (typeof opts.ObjectExpression === "number" || typeof opts.ObjectExpression === "string") {
- options.ObjectExpression = opts.ObjectExpression;
}
}
}
- const caseIndentStore = {};
+ const sourceCode = context.getSourceCode();
+ const tokenInfo = new TokenInfo(sourceCode);
+ const offsets = new OffsetStorage(tokenInfo, indentType, indentSize);
+ const parameterParens = new WeakSet();
/**
* Creates an error message for a line, given the expected/actual indentation.
@@ -266,9 +534,7 @@ module.exports = {
const foundTabsWord = `tab${actualTabs === 1 ? "" : "s"}`; // e.g. "tabs"
let foundStatement;
- if (actualSpaces > 0 && actualTabs > 0) {
- foundStatement = `${actualSpaces} ${foundSpacesWord} and ${actualTabs} ${foundTabsWord}`; // e.g. "1 space and 2 tabs"
- } else if (actualSpaces > 0) {
+ if (actualSpaces > 0) {
// Abbreviate the message if the expected indentation is also spaces.
// e.g. 'Expected 4 spaces but found 2' rather than 'Expected 4 spaces but found 2 spaces'
@@ -284,836 +550,823 @@ module.exports = {
/**
* Reports a given indent violation
- * @param {ASTNode} node Node violating the indent rule
- * @param {int} needed Expected indentation character count
+ * @param {Token} token Node violating the indent rule
+ * @param {int} neededIndentLevel Expected indentation level
* @param {int} gottenSpaces Indentation space count in the actual node/code
* @param {int} gottenTabs Indentation tab count in the actual node/code
- * @param {Object=} loc Error line and column location
- * @param {boolean} isLastNodeCheck Is the error for last node check
- * @param {int} lastNodeCheckEndOffset Number of charecters to skip from the end
* @returns {void}
*/
- function report(node, needed, gottenSpaces, gottenTabs, loc, isLastNodeCheck) {
- if (gottenSpaces && gottenTabs) {
-
- // To avoid conflicts with `no-mixed-spaces-and-tabs`, don't report lines that have both spaces and tabs.
- return;
- }
-
- const desiredIndent = (indentType === "space" ? " " : "\t").repeat(needed);
-
- const textRange = isLastNodeCheck
- ? [node.range[1] - node.loc.end.column, node.range[1] - node.loc.end.column + gottenSpaces + gottenTabs]
- : [node.range[0] - node.loc.start.column, node.range[0] - node.loc.start.column + gottenSpaces + gottenTabs];
+ function report(token, neededIndentLevel) {
+ const actualIndent = Array.from(tokenInfo.getTokenIndent(token));
+ const numSpaces = actualIndent.filter(char => char === " ").length;
+ const numTabs = actualIndent.filter(char => char === "\t").length;
+ const neededChars = neededIndentLevel * indentSize;
context.report({
- node,
- loc,
- message: createErrorMessage(needed, gottenSpaces, gottenTabs),
- fix: fixer => fixer.replaceTextRange(textRange, desiredIndent)
+ node: token,
+ message: createErrorMessage(neededChars, numSpaces, numTabs),
+ loc: {
+ start: { line: token.loc.start.line, column: 0 },
+ end: { line: token.loc.start.line, column: token.loc.start.column }
+ },
+ fix(fixer) {
+ const range = [token.range[0] - token.loc.start.column, token.range[0]];
+ const newText = (indentType === "space" ? " " : "\t").repeat(neededChars);
+
+ return fixer.replaceTextRange(range, newText);
+ }
});
}
/**
- * Get the actual indent of node
- * @param {ASTNode|Token} node Node to examine
- * @param {boolean} [byLastLine=false] get indent of node's last line
- * @param {boolean} [excludeCommas=false] skip comma on start of line
- * @returns {Object} The node's indent. Contains keys `space` and `tab`, representing the indent of each character. Also
- contains keys `goodChar` and `badChar`, where `goodChar` is the amount of the user's desired indentation character, and
- `badChar` is the amount of the other indentation character.
+ * Checks if a token's indentation is correct
+ * @param {Token} token Token to examine
+ * @param {int} desiredIndentLevel needed indent level
+ * @returns {boolean} `true` if the token's indentation is correct
*/
- function getNodeIndent(node, byLastLine) {
- const token = byLastLine ? sourceCode.getLastToken(node) : sourceCode.getFirstToken(node);
- const srcCharsBeforeNode = sourceCode.getText(token, token.loc.start.column).split("");
- const indentChars = srcCharsBeforeNode.slice(0, srcCharsBeforeNode.findIndex(char => char !== " " && char !== "\t"));
- const spaces = indentChars.filter(char => char === " ").length;
- const tabs = indentChars.filter(char => char === "\t").length;
-
- return {
- space: spaces,
- tab: tabs,
- goodChar: indentType === "space" ? spaces : tabs,
- badChar: indentType === "space" ? tabs : spaces
- };
- }
+ function validateTokenIndent(token, desiredIndentLevel) {
+ const indentation = tokenInfo.getTokenIndent(token);
+ const expectedChar = indentType === "space" ? " " : "\t";
- /**
- * Checks node is the first in its own start line. By default it looks by start line.
- * @param {ASTNode} node The node to check
- * @param {boolean} [byEndLocation=false] Lookup based on start position or end
- * @returns {boolean} true if its the first in the its start line
- */
- function isNodeFirstInLine(node, byEndLocation) {
- const firstToken = byEndLocation === true ? sourceCode.getLastToken(node, 1) : sourceCode.getTokenBefore(node),
- startLine = byEndLocation === true ? node.loc.end.line : node.loc.start.line,
- endLine = firstToken ? firstToken.loc.end.line : -1;
+ return indentation === expectedChar.repeat(desiredIndentLevel * indentSize) ||
- return startLine !== endLine;
+ // To avoid conflicts with no-mixed-spaces-and-tabs, don't report mixed spaces and tabs.
+ indentation.includes(" ") && indentation.includes("\t");
}
/**
- * Check indent for node
- * @param {ASTNode} node Node to check
- * @param {int} neededIndent needed indent
- * @param {boolean} [excludeCommas=false] skip comma on start of line
- * @returns {void}
+ * Check to see if the node is a file level IIFE
+ * @param {ASTNode} node The function node to check.
+ * @returns {boolean} True if the node is the outer IIFE
*/
- function checkNodeIndent(node, neededIndent) {
- const actualIndent = getNodeIndent(node, false);
-
- if (
- node.type !== "ArrayExpression" &&
- node.type !== "ObjectExpression" &&
- (actualIndent.goodChar !== neededIndent || actualIndent.badChar !== 0) &&
- isNodeFirstInLine(node)
- ) {
- report(node, neededIndent, actualIndent.space, actualIndent.tab);
- }
-
- if (node.type === "IfStatement" && node.alternate) {
- const elseToken = sourceCode.getTokenBefore(node.alternate);
-
- checkNodeIndent(elseToken, neededIndent);
-
- if (!isNodeFirstInLine(node.alternate)) {
- checkNodeIndent(node.alternate, neededIndent);
- }
- }
-
- if (node.type === "TryStatement" && node.handler) {
- const catchToken = sourceCode.getFirstToken(node.handler);
-
- checkNodeIndent(catchToken, neededIndent);
- }
-
- if (node.type === "TryStatement" && node.finalizer) {
- const finallyToken = sourceCode.getTokenBefore(node.finalizer);
+ function isOuterIIFE(node) {
- checkNodeIndent(finallyToken, neededIndent);
+ /*
+ * Verify that the node is an IIFE
+ */
+ if (!node.parent || node.parent.type !== "CallExpression" || node.parent.callee !== node) {
+ return false;
}
- if (node.type === "DoWhileStatement") {
- const whileToken = sourceCode.getTokenAfter(node.body);
+ /*
+ * Navigate legal ancestors to determine whether this IIFE is outer.
+ * A "legal ancestor" is an expression or statement that causes the function to get executed immediately.
+ * For example, `!(function(){})()` is an outer IIFE even though it is preceded by a ! operator.
+ */
+ let statement = node.parent && node.parent.parent;
- checkNodeIndent(whileToken, neededIndent);
+ while (
+ statement.type === "UnaryExpression" && ["!", "~", "+", "-"].indexOf(statement.operator) > -1 ||
+ statement.type === "AssignmentExpression" ||
+ statement.type === "LogicalExpression" ||
+ statement.type === "SequenceExpression" ||
+ statement.type === "VariableDeclarator"
+ ) {
+ statement = statement.parent;
}
- }
- /**
- * Check indent for nodes list
- * @param {ASTNode[]} nodes list of node objects
- * @param {int} indent needed indent
- * @param {boolean} [excludeCommas=false] skip comma on start of line
- * @returns {void}
- */
- function checkNodesIndent(nodes, indent) {
- nodes.forEach(node => checkNodeIndent(node, indent));
+ return (statement.type === "ExpressionStatement" || statement.type === "VariableDeclaration") && statement.parent.type === "Program";
}
/**
- * Check last node line indent this detects, that block closed correctly
- * @param {ASTNode} node Node to examine
- * @param {int} lastLineIndent needed indent
- * @returns {void}
- */
- function checkLastNodeLineIndent(node, lastLineIndent) {
- const lastToken = sourceCode.getLastToken(node);
- const endIndent = getNodeIndent(lastToken, true);
-
- if ((endIndent.goodChar !== lastLineIndent || endIndent.badChar !== 0) && isNodeFirstInLine(node, true)) {
- report(
- node,
- lastLineIndent,
- endIndent.space,
- endIndent.tab,
- { line: lastToken.loc.start.line, column: lastToken.loc.start.column },
- true
- );
- }
+ * Gets all tokens and comments for a node
+ * @param {ASTNode} node The node
+ * @returns {Token[]} A list of tokens and comments
+ */
+ function getTokensAndComments(node) {
+ return sourceCode.getTokens(node, { includeComments: true });
}
/**
- * Check last node line indent this detects, that block closed correctly
- * This function for more complicated return statement case, where closing parenthesis may be followed by ';'
- * @param {ASTNode} node Node to examine
- * @param {int} firstLineIndent first line needed indent
- * @returns {void}
- */
- function checkLastReturnStatementLineIndent(node, firstLineIndent) {
+ * Check indentation for lists of elements (arrays, objects, function params)
+ * @param {ASTNode[]} elements List of elements that should be offset
+ * @param {Token} startToken The start token of the list that element should be aligned against, e.g. '['
+ * @param {Token} endToken The end token of the list, e.g. ']'
+ * @param {number|string} offset The amount that the elements should be offset
+ * @returns {void}
+ */
+ function addElementListIndent(elements, startToken, endToken, offset) {
+
+ /**
+ * Gets the first token of a given element, including surrounding parentheses.
+ * @param {ASTNode} element A node in the `elements` list
+ * @returns {Token} The first token of this element
+ */
+ function getFirstToken(element) {
+ let token = sourceCode.getTokenBefore(element);
+
+ while (astUtils.isOpeningParenToken(token) && token !== startToken) {
+ token = sourceCode.getTokenBefore(token);
+ }
- // in case if return statement ends with ');' we have traverse back to ')'
- // otherwise we'll measure indent for ';' and replace ')'
- const lastToken = sourceCode.getLastToken(node, astUtils.isClosingParenToken);
- const textBeforeClosingParenthesis = sourceCode.getText(lastToken, lastToken.loc.start.column).slice(0, -1);
+ return sourceCode.getTokenAfter(token);
+ }
- if (textBeforeClosingParenthesis.trim()) {
+ // Run through all the tokens in the list, and offset them by one indent level (mainly for comments, other things will end up overridden)
+ // FIXME: (not-an-aardvark) This isn't performant at all.
+ offsets.setDesiredOffsets(
+ sourceCode.getTokensBetween(startToken, endToken, { includeComments: true }),
+ startToken,
+ offset === "first" ? 1 : offset
+ );
+ offsets.matchIndentOf(startToken, endToken);
- // There are tokens before the closing paren, don't report this case
+ // If the preference is "first" but there is no first element (e.g. sparse arrays w/ empty first slot), fall back to 1 level.
+ if (offset === "first" && elements.length && !elements[0]) {
return;
}
- const endIndent = getNodeIndent(lastToken, true);
+ elements.forEach((element, index) => {
+ if (offset === "off") {
+ offsets.ignoreToken(getFirstToken(element));
+ }
+ if (index === 0 || !element) {
+ return;
+ }
+ if (offset === "first" && tokenInfo.isFirstTokenOfLine(getFirstToken(element))) {
+ offsets.matchOffsetOf(getFirstToken(elements[0]), getFirstToken(element));
+ } else {
+ const previousElement = elements[index - 1];
+ const firstTokenOfPreviousElement = previousElement && getFirstToken(previousElement);
- if (endIndent.goodChar !== firstLineIndent) {
- report(
- node,
- firstLineIndent,
- endIndent.space,
- endIndent.tab,
- { line: lastToken.loc.start.line, column: lastToken.loc.start.column },
- true
- );
- }
+ if (previousElement && sourceCode.getLastToken(previousElement).loc.start.line > startToken.loc.end.line) {
+ offsets.matchIndentOf(firstTokenOfPreviousElement, getFirstToken(element));
+ }
+ }
+ });
}
/**
- * Check first node line indent is correct
- * @param {ASTNode} node Node to examine
- * @param {int} firstLineIndent needed indent
+ * Check indentation for blocks and class bodies
+ * @param {ASTNode} node The BlockStatement or ClassBody node to indent
* @returns {void}
*/
- function checkFirstNodeLineIndent(node, firstLineIndent) {
- const startIndent = getNodeIndent(node, false);
-
- if ((startIndent.goodChar !== firstLineIndent || startIndent.badChar !== 0) && isNodeFirstInLine(node)) {
- report(
- node,
- firstLineIndent,
- startIndent.space,
- startIndent.tab,
- { line: node.loc.start.line, column: node.loc.start.column }
- );
- }
- }
+ function addBlockIndent(node) {
- /**
- * Returns a parent node of given node based on a specified type
- * if not present then return null
- * @param {ASTNode} node node to examine
- * @param {string} type type that is being looked for
- * @param {string} stopAtList end points for the evaluating code
- * @returns {ASTNode|void} if found then node otherwise null
- */
- function getParentNodeByType(node, type, stopAtList) {
- let parent = node.parent;
+ let blockIndentLevel;
- if (!stopAtList) {
- stopAtList = ["Program"];
+ if (node.parent && isOuterIIFE(node.parent)) {
+ blockIndentLevel = options.outerIIFEBody;
+ } else if (node.parent && (node.parent.type === "FunctionExpression" || node.parent.type === "ArrowFunctionExpression")) {
+ blockIndentLevel = options.FunctionExpression.body;
+ } else if (node.parent && node.parent.type === "FunctionDeclaration") {
+ blockIndentLevel = options.FunctionDeclaration.body;
+ } else {
+ blockIndentLevel = 1;
}
- while (parent.type !== type && stopAtList.indexOf(parent.type) === -1 && parent.type !== "Program") {
- parent = parent.parent;
+ /*
+ * For blocks that aren't lone statements, ensure that the opening curly brace
+ * is aligned with the parent.
+ */
+ if (!astUtils.STATEMENT_LIST_PARENTS.has(node.parent.type)) {
+ offsets.matchIndentOf(sourceCode.getFirstToken(node.parent), sourceCode.getFirstToken(node));
}
-
- return parent.type === type ? parent : null;
+ addElementListIndent(node.body, sourceCode.getFirstToken(node), sourceCode.getLastToken(node), blockIndentLevel);
}
/**
- * Returns the VariableDeclarator based on the current node
- * if not present then return null
+ * Check indent for array block content or object block content
* @param {ASTNode} node node to examine
- * @returns {ASTNode|void} if found then node otherwise null
+ * @returns {void}
*/
- function getVariableDeclaratorNode(node) {
- return getParentNodeByType(node, "VariableDeclarator");
- }
+ function addArrayOrObjectIndent(node) {
+ const tokens = getTokensAndComments(node);
- /**
- * Check to see if the node is part of the multi-line variable declaration.
- * Also if its on the same line as the varNode
- * @param {ASTNode} node node to check
- * @param {ASTNode} varNode variable declaration node to check against
- * @returns {boolean} True if all the above condition satisfy
- */
- function isNodeInVarOnTop(node, varNode) {
- return varNode &&
- varNode.parent.loc.start.line === node.loc.start.line &&
- varNode.parent.declarations.length > 1;
+ addElementListIndent(node.elements || node.properties, tokens[0], tokens[tokens.length - 1], options[node.type]);
}
/**
- * Check to see if the argument before the callee node is multi-line and
- * there should only be 1 argument before the callee node
- * @param {ASTNode} node node to check
- * @returns {boolean} True if arguments are multi-line
+ * Check and decide whether to check for indentation for blockless nodes
+ * Scenarios are for or while statements without braces around them
+ * @param {ASTNode} node node to examine
+ * @returns {void}
*/
- function isArgBeforeCalleeNodeMultiline(node) {
- const parent = node.parent;
+ function addBlocklessNodeIndent(node) {
+ if (node.type !== "BlockStatement") {
+ const lastParentToken = sourceCode.getTokenBefore(node, astUtils.isNotOpeningParenToken);
- if (parent.arguments.length >= 2 && parent.arguments[1] === node) {
- return parent.arguments[0].loc.end.line > parent.arguments[0].loc.start.line;
- }
+ let bodyTokens = getTokensAndComments(node);
- return false;
+ while (
+ astUtils.isOpeningParenToken(sourceCode.getTokenBefore(bodyTokens[0])) &&
+ astUtils.isClosingParenToken(sourceCode.getTokenAfter(bodyTokens[bodyTokens.length - 1]))
+ ) {
+ bodyTokens = [sourceCode.getTokenBefore(bodyTokens[0])].concat(bodyTokens).concat(sourceCode.getTokenAfter(bodyTokens[bodyTokens.length - 1]));
+ }
+
+ offsets.setDesiredOffsets(bodyTokens, lastParentToken, 1);
+
+ /*
+ * For blockless nodes with semicolon-first style, don't indent the semicolon.
+ * e.g.
+ * if (foo) bar()
+ * ; [1, 2, 3].map(foo)
+ */
+ const lastToken = sourceCode.getLastToken(node);
+
+ if (astUtils.isSemicolonToken(lastToken)) {
+ offsets.matchIndentOf(lastParentToken, lastToken);
+ }
+ }
}
/**
- * Check to see if the node is a file level IIFE
- * @param {ASTNode} node The function node to check.
- * @returns {boolean} True if the node is the outer IIFE
- */
- function isOuterIIFE(node) {
- const parent = node.parent;
- let stmt = parent.parent;
+ * Checks the indentation of a function's parameters
+ * @param {ASTNode} node The node
+ * @param {number} paramsIndent The indentation level option for the parameters
+ * @returns {void}
+ */
+ function addFunctionParamsIndent(node, paramsIndent) {
+ const openingParen = node.params.length ? sourceCode.getTokenBefore(node.params[0]) : sourceCode.getTokenBefore(node.body, 1);
- /*
- * Verify that the node is an IIEF
- */
- if (
- parent.type !== "CallExpression" ||
- parent.callee !== node) {
+ if (!openingParen) {
- return false;
+ // If there is no opening paren (e.g. for an arrow function with a single parameter), don't indent anything.
+ return;
}
- /*
- * Navigate legal ancestors to determine whether this IIEF is outer
- */
- while (
- stmt.type === "UnaryExpression" && (
- stmt.operator === "!" ||
- stmt.operator === "~" ||
- stmt.operator === "+" ||
- stmt.operator === "-") ||
- stmt.type === "AssignmentExpression" ||
- stmt.type === "LogicalExpression" ||
- stmt.type === "SequenceExpression" ||
- stmt.type === "VariableDeclarator") {
-
- stmt = stmt.parent;
- }
+ const closingParen = sourceCode.getTokenBefore(node.body);
+ const nodeTokens = getTokensAndComments(node);
+ const openingParenIndex = lodash.sortedIndexBy(nodeTokens, openingParen, token => token.range[0]);
+ const closingParenIndex = lodash.sortedIndexBy(nodeTokens, closingParen, token => token.range[0]);
- return ((
- stmt.type === "ExpressionStatement" ||
- stmt.type === "VariableDeclaration") &&
- stmt.parent && stmt.parent.type === "Program"
- );
+ parameterParens.add(nodeTokens[openingParenIndex]);
+ parameterParens.add(nodeTokens[closingParenIndex]);
+
+ addElementListIndent(node.params, nodeTokens[openingParenIndex], nodeTokens[closingParenIndex], paramsIndent);
}
/**
- * Check indent for function block content
- * @param {ASTNode} node A BlockStatement node that is inside of a function.
- * @returns {void}
- */
- function checkIndentInFunctionBlock(node) {
+ * Adds indentation for the right-hand side of binary/logical expressions.
+ * @param {ASTNode} node A BinaryExpression or LogicalExpression node
+ * @returns {void}
+ */
+ function addBinaryOrLogicalExpressionIndent(node) {
+ const tokens = getTokensAndComments(node);
+ const operator = sourceCode.getFirstTokenBetween(node.left, node.right, token => token.value === node.operator);
+ const firstTokenAfterOperator = sourceCode.getTokenAfter(operator);
+ const tokensAfterOperator = tokens.slice(lodash.sortedIndexBy(tokens, firstTokenAfterOperator, token => token.range[0]));
/*
- * Search first caller in chain.
- * Ex.:
- *
- * Models <- Identifier
- * .User
- * .find()
- * .exec(function() {
- * // function body
- * });
- *
- * Looks for 'Models'
+ * For backwards compatibility, don't check BinaryExpression indents, e.g.
+ * var foo = bar &&
+ * baz;
*/
- const calleeNode = node.parent; // FunctionExpression
- let indent;
- if (calleeNode.parent &&
- (calleeNode.parent.type === "Property" ||
- calleeNode.parent.type === "ArrayExpression")) {
+ offsets.ignoreToken(operator);
+ offsets.ignoreToken(tokensAfterOperator[0]);
+ offsets.setDesiredOffset(tokensAfterOperator[0], sourceCode.getFirstToken(node), 1);
+ offsets.setDesiredOffsets(tokensAfterOperator, tokensAfterOperator[0], 1);
+ }
- // If function is part of array or object, comma can be put at left
- indent = getNodeIndent(calleeNode, false, false).goodChar;
+ /**
+ * Checks the indentation for nodes that are like function calls (`CallExpression` and `NewExpression`)
+ * @param {ASTNode} node A CallExpression or NewExpression node
+ * @returns {void}
+ */
+ function addFunctionCallIndent(node) {
+ let openingParen;
+
+ if (node.arguments.length) {
+ openingParen = sourceCode.getFirstTokenBetween(node.callee, node.arguments[0], astUtils.isOpeningParenToken);
} else {
-
- // If function is standalone, simple calculate indent
- indent = getNodeIndent(calleeNode).goodChar;
+ openingParen = sourceCode.getLastToken(node, 1);
}
+ const closingParen = sourceCode.getLastToken(node);
- if (calleeNode.parent.type === "CallExpression") {
- const calleeParent = calleeNode.parent;
-
- if (calleeNode.type !== "FunctionExpression" && calleeNode.type !== "ArrowFunctionExpression") {
- if (calleeParent && calleeParent.loc.start.line < node.loc.start.line) {
- indent = getNodeIndent(calleeParent).goodChar;
- }
- } else {
- if (isArgBeforeCalleeNodeMultiline(calleeNode) &&
- calleeParent.callee.loc.start.line === calleeParent.callee.loc.end.line &&
- !isNodeFirstInLine(calleeNode)) {
- indent = getNodeIndent(calleeParent).goodChar;
- }
- }
- }
+ parameterParens.add(openingParen);
+ parameterParens.add(closingParen);
+ offsets.matchIndentOf(sourceCode.getLastToken(node.callee), openingParen);
- // function body indent should be indent + indent size, unless this
- // is a FunctionDeclaration, FunctionExpression, or outer IIFE and the corresponding options are enabled.
- let functionOffset = indentSize;
+ addElementListIndent(node.arguments, openingParen, closingParen, options.CallExpression.arguments);
+ }
- if (options.outerIIFEBody !== null && isOuterIIFE(calleeNode)) {
- functionOffset = options.outerIIFEBody * indentSize;
- } else if (calleeNode.type === "FunctionExpression") {
- functionOffset = options.FunctionExpression.body * indentSize;
- } else if (calleeNode.type === "FunctionDeclaration") {
- functionOffset = options.FunctionDeclaration.body * indentSize;
+ /**
+ * Checks the indentation of ClassDeclarations and ClassExpressions
+ * @param {ASTNode} node A ClassDeclaration or ClassExpression node
+ * @returns {void}
+ */
+ function addClassIndent(node) {
+ if (node.superClass) {
+ const classToken = sourceCode.getFirstToken(node);
+ const extendsToken = sourceCode.getTokenBefore(node.superClass, astUtils.isNotOpeningParenToken);
+
+ offsets.setDesiredOffset(extendsToken, classToken, 1);
+ offsets.setDesiredOffsets(sourceCode.getTokensBetween(extendsToken, node.body, { includeComments: true }), classToken, 1);
}
- indent += functionOffset;
+ }
- // check if the node is inside a variable
- const parentVarNode = getVariableDeclaratorNode(node);
+ /**
+ * Checks the indentation of parenthesized values, given a list of tokens in a program
+ * @param {Token[]} tokens A list of tokens
+ * @returns {void}
+ */
+ function addParensIndent(tokens) {
+ const parenStack = [];
+ const parenPairs = [];
+
+ tokens.forEach(nextToken => {
+
+ // Accumulate a list of parenthesis pairs
+ if (astUtils.isOpeningParenToken(nextToken)) {
+ parenStack.push(nextToken);
+ } else if (astUtils.isClosingParenToken(nextToken)) {
+ parenPairs.unshift({ left: parenStack.pop(), right: nextToken });
+ }
+ });
- if (parentVarNode && isNodeInVarOnTop(node, parentVarNode)) {
- indent += indentSize * options.VariableDeclarator[parentVarNode.parent.kind];
- }
+ parenPairs.forEach(pair => {
+ const leftParen = pair.left;
+ const rightParen = pair.right;
- if (node.body.length > 0) {
- checkNodesIndent(node.body, indent);
- }
+ // We only want to handle parens around expressions, so exclude parentheses that are in function parameters and function call arguments.
+ if (!parameterParens.has(leftParen) && !parameterParens.has(rightParen)) {
+ offsets.setDesiredOffset(sourceCode.getTokenAfter(leftParen), leftParen, 1);
+ }
- checkLastNodeLineIndent(node, indent - functionOffset);
+ offsets.matchIndentOf(leftParen, rightParen);
+ });
}
-
/**
- * Checks if the given node starts and ends on the same line
- * @param {ASTNode} node The node to check
- * @returns {boolean} Whether or not the block starts and ends on the same line.
- */
- function isSingleLineNode(node) {
- const lastToken = sourceCode.getLastToken(node),
- startLine = node.loc.start.line,
- endLine = lastToken.loc.end.line;
-
- return startLine === endLine;
+ * Ignore all tokens within an unknown node whose offset do not depend
+ * on another token's offset within the unknown node
+ * @param {ASTNode} node Unknown Node
+ * @returns {void}
+ */
+ function ignoreUnknownNode(node) {
+ const unknownNodeTokens = new Set(getTokensAndComments(node));
+
+ unknownNodeTokens.forEach(token => {
+ if (!unknownNodeTokens.has(offsets.getFirstDependency(token))) {
+ const firstTokenOfLine = tokenInfo.getFirstTokenOfLine(token);
+
+ if (token === firstTokenOfLine) {
+ offsets.ignoreToken(token);
+ } else {
+ offsets.matchIndentOf(firstTokenOfLine, token);
+ }
+ }
+ });
}
/**
- * Check to see if the first element inside an array is an object and on the same line as the node
- * If the node is not an array then it will return false.
- * @param {ASTNode} node node to check
- * @returns {boolean} success/failure
- */
- function isFirstArrayElementOnSameLine(node) {
- if (node.type === "ArrayExpression" && node.elements[0]) {
- return node.elements[0].loc.start.line === node.loc.start.line && node.elements[0].type === "ObjectExpression";
+ * Ignore node if it is unknown
+ * @param {ASTNode} node Node
+ * @returns {void}
+ */
+ function checkForUnknownNode(node) {
+ const isNodeUnknown = !(KNOWN_NODES.has(node.type));
+
+ if (isNodeUnknown) {
+ ignoreUnknownNode(node);
}
- return false;
-
}
/**
- * Check indent for array block content or object block content
- * @param {ASTNode} node node to examine
- * @returns {void}
+ * Check whether the given token is the first token of a statement.
+ * @param {Token} token The token to check.
+ * @param {ASTNode} leafNode The expression node that the token belongs directly.
+ * @returns {boolean} `true` if the token is the first token of a statement.
*/
- function checkIndentInArrayOrObjectBlock(node) {
-
- // Skip inline
- if (isSingleLineNode(node)) {
- return;
- }
-
- let elements = (node.type === "ArrayExpression") ? node.elements : node.properties;
-
- // filter out empty elements example would be [ , 2] so remove first element as espree considers it as null
- elements = elements.filter(elem => elem !== null);
-
- let nodeIndent;
- let elementsIndent;
- const parentVarNode = getVariableDeclaratorNode(node);
-
- // TODO - come up with a better strategy in future
- if (isNodeFirstInLine(node)) {
- const parent = node.parent;
-
- nodeIndent = getNodeIndent(parent).goodChar;
- if (!parentVarNode || parentVarNode.loc.start.line !== node.loc.start.line) {
- if (parent.type !== "VariableDeclarator" || parentVarNode === parentVarNode.parent.declarations[0]) {
- if (parent.type === "VariableDeclarator" && parentVarNode.loc.start.line === parent.loc.start.line) {
- nodeIndent = nodeIndent + (indentSize * options.VariableDeclarator[parentVarNode.parent.kind]);
- } else if (parent.type === "ObjectExpression" || parent.type === "ArrayExpression") {
- const parentElements = node.parent.type === "ObjectExpression" ? node.parent.properties : node.parent.elements;
-
- if (parentElements[0] && parentElements[0].loc.start.line === parent.loc.start.line && parentElements[0].loc.end.line !== parent.loc.start.line) {
-
- /*
- * If the first element of the array spans multiple lines, don't increase the expected indentation of the rest.
- * e.g. [{
- * foo: 1
- * },
- * {
- * bar: 1
- * }]
- * the second object is not indented.
- */
- } else if (typeof options[parent.type] === "number") {
- nodeIndent += options[parent.type] * indentSize;
- } else {
- nodeIndent = parentElements[0].loc.start.column;
- }
- } else if (parent.type === "CallExpression" || parent.type === "NewExpression") {
- if (typeof options.CallExpression.arguments === "number") {
- nodeIndent += options.CallExpression.arguments * indentSize;
- } else if (options.CallExpression.arguments === "first") {
- if (parent.arguments.indexOf(node) !== -1) {
- nodeIndent = parent.arguments[0].loc.start.column;
- }
- } else {
- nodeIndent += indentSize;
- }
- } else if (parent.type === "LogicalExpression" || parent.type === "ArrowFunctionExpression") {
- nodeIndent += indentSize;
- }
- }
- } else if (!parentVarNode && !isFirstArrayElementOnSameLine(parent) && parent.type !== "MemberExpression" && parent.type !== "ExpressionStatement" && parent.type !== "AssignmentExpression" && parent.type !== "Property") {
- nodeIndent = nodeIndent + indentSize;
- }
+ function isFirstTokenOfStatement(token, leafNode) {
+ let node = leafNode;
- checkFirstNodeLineIndent(node, nodeIndent);
- } else {
- nodeIndent = getNodeIndent(node).goodChar;
+ while (node.parent && !node.parent.type.endsWith("Statement") && !node.parent.type.endsWith("Declaration")) {
+ node = node.parent;
}
+ node = node.parent;
- if (options[node.type] === "first") {
- elementsIndent = elements.length ? elements[0].loc.start.column : 0; // If there are no elements, elementsIndent doesn't matter.
- } else {
- elementsIndent = nodeIndent + indentSize * options[node.type];
- }
+ return !node || node.range[0] === token.range[0];
+ }
- /*
- * Check if the node is a multiple variable declaration; if so, then
- * make sure indentation takes that into account.
- */
- if (isNodeInVarOnTop(node, parentVarNode)) {
- elementsIndent += indentSize * options.VariableDeclarator[parentVarNode.parent.kind];
- }
+ return {
+ ArrayExpression: addArrayOrObjectIndent,
+ ArrayPattern: addArrayOrObjectIndent,
- checkNodesIndent(elements, elementsIndent);
+ ArrowFunctionExpression(node) {
+ addFunctionParamsIndent(node, options.FunctionExpression.parameters);
+ addBlocklessNodeIndent(node.body);
- if (elements.length > 0) {
+ let arrowToken;
- // Skip last block line check if last item in same line
- if (elements[elements.length - 1].loc.end.line === node.loc.end.line) {
- return;
+ if (node.params.length) {
+ arrowToken = sourceCode.getTokenAfter(node.params[node.params.length - 1], astUtils.isArrowToken);
+ } else {
+ arrowToken = sourceCode.getFirstToken(node, astUtils.isArrowToken);
}
- }
+ offsets.matchIndentOf(sourceCode.getFirstToken(node), arrowToken);
+ },
- checkLastNodeLineIndent(node, nodeIndent + (isNodeInVarOnTop(node, parentVarNode) ? options.VariableDeclarator[parentVarNode.parent.kind] * indentSize : 0));
- }
+ AssignmentExpression(node) {
+ const operator = sourceCode.getFirstTokenBetween(node.left, node.right, token => token.value === node.operator);
+ const nodeTokens = getTokensAndComments(node);
+ const tokensFromOperator = nodeTokens.slice(lodash.sortedIndexBy(nodeTokens, operator, token => token.range[0]));
- /**
- * Check if the node or node body is a BlockStatement or not
- * @param {ASTNode} node node to test
- * @returns {boolean} True if it or its body is a block statement
- */
- function isNodeBodyBlock(node) {
- return node.type === "BlockStatement" || node.type === "ClassBody" || (node.body && node.body.type === "BlockStatement") ||
- (node.consequent && node.consequent.type === "BlockStatement");
- }
+ offsets.setDesiredOffsets(tokensFromOperator, sourceCode.getFirstToken(node.left), 1);
+ offsets.ignoreToken(tokensFromOperator[0]);
+ offsets.ignoreToken(tokensFromOperator[1]);
+ },
- /**
- * Check indentation for blocks
- * @param {ASTNode} node node to check
- * @returns {void}
- */
- function blockIndentationCheck(node) {
+ BinaryExpression: addBinaryOrLogicalExpressionIndent,
+
+ BlockStatement: addBlockIndent,
+
+ CallExpression: addFunctionCallIndent,
+
+ ClassBody: addBlockIndent,
+
+ ClassDeclaration: addClassIndent,
+
+ ClassExpression: addClassIndent,
+
+ ConditionalExpression(node) {
+ const firstToken = sourceCode.getFirstToken(node);
+
+ // `flatTernaryExpressions` option is for the following style:
+ // var a =
+ // foo > 0 ? bar :
+ // foo < 0 ? baz :
+ // /*else*/ qiz ;
+ if (!options.flatTernaryExpressions ||
+ !astUtils.isTokenOnSameLine(node.test, node.consequent) ||
+ isFirstTokenOfStatement(firstToken, node)
+ ) {
+ const questionMarkToken = sourceCode.getFirstTokenBetween(node.test, node.consequent, token => token.type === "Punctuator" && token.value === "?");
+ const colonToken = sourceCode.getFirstTokenBetween(node.consequent, node.alternate, token => token.type === "Punctuator" && token.value === ":");
+
+ const consequentTokens = sourceCode.getTokensBetween(questionMarkToken, colonToken, { includeComments: true });
+ const alternateTokens = sourceCode.getTokensAfter(colonToken, token => token.range[1] <= node.range[1]);
+
+ offsets.setDesiredOffset(questionMarkToken, firstToken, 1);
+ offsets.setDesiredOffset(colonToken, firstToken, 1);
+
+ offsets.setDesiredOffset(consequentTokens[0], firstToken, 1);
+
+ /*
+ * The alternate and the consequent should usually have the same indentation.
+ * If they share part of a line, align the alternate against the first token of the consequent.
+ * This allows the alternate to be indented correctly in cases like this:
+ * foo ? (
+ * bar
+ * ) : ( // this '(' is aligned with the '(' above, so it's considered to be aligned with `foo`
+ * baz // as a result, `baz` is offset by 1 rather than 2
+ * )
+ */
+ if (consequentTokens[consequentTokens.length - 1].loc.end.line === alternateTokens[0].loc.start.line) {
+ offsets.matchIndentOf(consequentTokens[0], alternateTokens[0]);
+ } else {
+
+ /**
+ * If the alternate and consequent do not share part of a line, offset the alternate from the first
+ * token of the conditional expression. For example:
+ * foo ? bar
+ * : baz
+ *
+ * If `baz` were aligned with `bar` rather than being offset by 1 from `foo`, `baz` would end up
+ * having no expected indentation.
+ */
+ offsets.setDesiredOffset(alternateTokens[0], firstToken, 1);
+ }
- // Skip inline blocks
- if (isSingleLineNode(node)) {
- return;
- }
+ offsets.setDesiredOffsets(consequentTokens, consequentTokens[0], 0);
+ offsets.setDesiredOffsets(alternateTokens, alternateTokens[0], 0);
+ }
+ },
- if (node.parent && (
- node.parent.type === "FunctionExpression" ||
- node.parent.type === "FunctionDeclaration" ||
- node.parent.type === "ArrowFunctionExpression"
- )) {
- checkIndentInFunctionBlock(node);
- return;
- }
+ DoWhileStatement: node => addBlocklessNodeIndent(node.body),
- let indent;
- let nodesToCheck = [];
+ ExportNamedDeclaration(node) {
+ if (node.declaration === null) {
+ const tokensInNode = getTokensAndComments(node);
+ const closingCurly = sourceCode.getLastToken(node, astUtils.isClosingBraceToken);
+ const closingCurlyIndex = lodash.sortedIndexBy(tokensInNode, closingCurly, token => token.range[0]);
- /*
- * For this statements we should check indent from statement beginning,
- * not from the beginning of the block.
- */
- const statementsWithProperties = [
- "IfStatement", "WhileStatement", "ForStatement", "ForInStatement", "ForOfStatement", "DoWhileStatement", "ClassDeclaration", "TryStatement"
- ];
-
- if (node.parent && statementsWithProperties.indexOf(node.parent.type) !== -1 && isNodeBodyBlock(node)) {
- indent = getNodeIndent(node.parent).goodChar;
- } else if (node.parent && node.parent.type === "CatchClause") {
- indent = getNodeIndent(node.parent.parent).goodChar;
- } else {
- indent = getNodeIndent(node).goodChar;
- }
+ // Indent the specifiers in `export {foo, bar, baz}`
+ addElementListIndent(node.specifiers, sourceCode.getFirstToken(node, { skip: 1 }), closingCurly, 1);
- if (node.type === "IfStatement" && node.consequent.type !== "BlockStatement") {
- nodesToCheck = [node.consequent];
- } else if (Array.isArray(node.body)) {
- nodesToCheck = node.body;
- } else {
- nodesToCheck = [node.body];
- }
+ if (node.source) {
- if (nodesToCheck.length > 0) {
- checkNodesIndent(nodesToCheck, indent + indentSize);
- }
+ // Indent everything after and including the `from` token in `export {foo, bar, baz} from 'qux'`
+ offsets.setDesiredOffsets(tokensInNode.slice(closingCurlyIndex + 1), sourceCode.getFirstToken(node), 1);
+ }
+ }
+ },
- if (node.type === "BlockStatement") {
- checkLastNodeLineIndent(node, indent);
- }
- }
+ ForInStatement: node => addBlocklessNodeIndent(node.body),
- /**
- * Filter out the elements which are on the same line of each other or the node.
- * basically have only 1 elements from each line except the variable declaration line.
- * @param {ASTNode} node Variable declaration node
- * @returns {ASTNode[]} Filtered elements
- */
- function filterOutSameLineVars(node) {
- return node.declarations.reduce((finalCollection, elem) => {
- const lastElem = finalCollection[finalCollection.length - 1];
+ ForOfStatement: node => addBlocklessNodeIndent(node.body),
+
+ ForStatement(node) {
+ const forOpeningParen = sourceCode.getFirstToken(node, 1);
- if ((elem.loc.start.line !== node.loc.start.line && !lastElem) ||
- (lastElem && lastElem.loc.start.line !== elem.loc.start.line)) {
- finalCollection.push(elem);
+ if (node.init) {
+ offsets.setDesiredOffsets(getTokensAndComments(node.init), forOpeningParen, 1);
+ }
+ if (node.test) {
+ offsets.setDesiredOffsets(getTokensAndComments(node.test), forOpeningParen, 1);
}
+ if (node.update) {
+ offsets.setDesiredOffsets(getTokensAndComments(node.update), forOpeningParen, 1);
+ }
+ addBlocklessNodeIndent(node.body);
+ },
- return finalCollection;
- }, []);
- }
+ FunctionDeclaration(node) {
+ addFunctionParamsIndent(node, options.FunctionDeclaration.parameters);
+ },
- /**
- * Check indentation for variable declarations
- * @param {ASTNode} node node to examine
- * @returns {void}
- */
- function checkIndentInVariableDeclarations(node) {
- const elements = filterOutSameLineVars(node);
- const nodeIndent = getNodeIndent(node).goodChar;
- const lastElement = elements[elements.length - 1];
+ FunctionExpression(node) {
+ addFunctionParamsIndent(node, options.FunctionExpression.parameters);
+ },
- const elementsIndent = nodeIndent + indentSize * options.VariableDeclarator[node.kind];
+ IfStatement(node) {
+ addBlocklessNodeIndent(node.consequent);
+ if (node.alternate && node.alternate.type !== "IfStatement") {
+ addBlocklessNodeIndent(node.alternate);
+ }
+ },
- checkNodesIndent(elements, elementsIndent);
+ ImportDeclaration(node) {
+ if (node.specifiers.some(specifier => specifier.type === "ImportSpecifier")) {
+ const openingCurly = sourceCode.getFirstToken(node, astUtils.isOpeningBraceToken);
+ const closingCurly = sourceCode.getLastToken(node, astUtils.isClosingBraceToken);
- // Only check the last line if there is any token after the last item
- if (sourceCode.getLastToken(node).loc.end.line <= lastElement.loc.end.line) {
- return;
- }
+ addElementListIndent(node.specifiers.filter(specifier => specifier.type === "ImportSpecifier"), openingCurly, closingCurly, 1);
+ }
- const tokenBeforeLastElement = sourceCode.getTokenBefore(lastElement);
+ const fromToken = sourceCode.getLastToken(node, token => token.type === "Identifier" && token.value === "from");
- if (tokenBeforeLastElement.value === ",") {
+ if (fromToken) {
+ const tokensToOffset = sourceCode.getTokensBetween(fromToken, sourceCode.getLastToken(node), 1);
- // Special case for comma-first syntax where the semicolon is indented
- checkLastNodeLineIndent(node, getNodeIndent(tokenBeforeLastElement).goodChar);
- } else {
- checkLastNodeLineIndent(node, elementsIndent - indentSize);
- }
- }
+ offsets.setDesiredOffsets(tokensToOffset, sourceCode.getFirstToken(node), 1);
+ }
+ },
- /**
- * Check and decide whether to check for indentation for blockless nodes
- * Scenarios are for or while statements without braces around them
- * @param {ASTNode} node node to examine
- * @returns {void}
- */
- function blockLessNodes(node) {
- if (node.body.type !== "BlockStatement") {
- blockIndentationCheck(node);
- }
- }
+ LogicalExpression: addBinaryOrLogicalExpressionIndent,
- /**
- * Returns the expected indentation for the case statement
- * @param {ASTNode} node node to examine
- * @param {int} [switchIndent] indent for switch statement
- * @returns {int} indent size
- */
- function expectedCaseIndent(node, switchIndent) {
- const switchNode = (node.type === "SwitchStatement") ? node : node.parent;
- let caseIndent;
+ "MemberExpression, JSXMemberExpression"(node) {
+ const firstNonObjectToken = sourceCode.getFirstTokenBetween(node.object, node.property, astUtils.isNotClosingParenToken);
+ const secondNonObjectToken = sourceCode.getTokenAfter(firstNonObjectToken);
- if (caseIndentStore[switchNode.loc.start.line]) {
- return caseIndentStore[switchNode.loc.start.line];
- }
- if (typeof switchIndent === "undefined") {
- switchIndent = getNodeIndent(switchNode).goodChar;
- }
+ const tokenBeforeObject = sourceCode.getTokenBefore(node.object, token => astUtils.isNotOpeningParenToken(token) || parameterParens.has(token));
+ const firstObjectToken = tokenBeforeObject ? sourceCode.getTokenAfter(tokenBeforeObject) : sourceCode.ast.tokens[0];
+ const lastObjectToken = sourceCode.getTokenBefore(firstNonObjectToken);
- if (switchNode.cases.length > 0 && options.SwitchCase === 0) {
- caseIndent = switchIndent;
- } else {
- caseIndent = switchIndent + (indentSize * options.SwitchCase);
- }
+ if (node.computed) {
- caseIndentStore[switchNode.loc.start.line] = caseIndent;
- return caseIndent;
+ // For computed MemberExpressions, match the closing bracket with the opening bracket.
+ offsets.matchIndentOf(firstNonObjectToken, sourceCode.getLastToken(node));
+ }
- }
+ if (typeof options.MemberExpression === "number") {
+ const firstPropertyToken = node.computed ? firstNonObjectToken : secondNonObjectToken;
+
+ /*
+ * If the object ends on the same line that the property starts, match against the last token
+ * of the object, to ensure that the MemberExpression is not indented.
+ *
+ * Otherwise, match against the first token of the object, e.g.
+ * foo
+ * .bar
+ * .baz // <-- offset by 1 from `foo`
+ */
+ const offsetBase = lastObjectToken.loc.end.line === firstPropertyToken.loc.start.line
+ ? lastObjectToken
+ : firstObjectToken;
+
+ // Match the dot (for non-computed properties) or the opening bracket (for computed properties) against the object.
+ offsets.setDesiredOffset(firstNonObjectToken, offsetBase, options.MemberExpression);
+
+ /*
+ * For computed MemberExpressions, match the first token of the property against the opening bracket.
+ * Otherwise, match the first token of the property against the object.
+ */
+ offsets.setDesiredOffset(secondNonObjectToken, node.computed ? firstNonObjectToken : offsetBase, options.MemberExpression);
+ } else {
- /**
- * Checks wether a return statement is wrapped in ()
- * @param {ASTNode} node node to examine
- * @returns {boolean} the result
- */
- function isWrappedInParenthesis(node) {
- const regex = /^return\s*?\(\s*?\);*?/;
+ // If the MemberExpression option is off, ignore the dot and the first token of the property.
+ offsets.ignoreToken(firstNonObjectToken);
+ offsets.ignoreToken(secondNonObjectToken);
+ offsets.matchIndentOf(firstNonObjectToken, secondNonObjectToken);
+ }
+ },
- const statementWithoutArgument = sourceCode.getText(node).replace(
- sourceCode.getText(node.argument), "");
+ NewExpression(node) {
- return regex.test(statementWithoutArgument);
- }
+ // Only indent the arguments if the NewExpression has parens (e.g. `new Foo(bar)` or `new Foo()`, but not `new Foo`
+ if (node.arguments.length > 0 || astUtils.isClosingParenToken(sourceCode.getLastToken(node)) && astUtils.isOpeningParenToken(sourceCode.getLastToken(node, 1))) {
+ addFunctionCallIndent(node);
+ }
+ },
- return {
- Program(node) {
- if (node.body.length > 0) {
+ ObjectExpression: addArrayOrObjectIndent,
+ ObjectPattern: addArrayOrObjectIndent,
+
+ Property(node) {
+ if (!node.computed && !node.shorthand && !node.method && node.kind === "init") {
+ const colon = sourceCode.getFirstTokenBetween(node.key, node.value, astUtils.isColonToken);
- // Root nodes should have no indent
- checkNodesIndent(node.body, getNodeIndent(node).goodChar);
+ offsets.ignoreToken(sourceCode.getTokenAfter(colon));
}
},
- ClassBody: blockIndentationCheck,
+ SwitchStatement(node) {
+ const tokens = getTokensAndComments(node);
+ const openingCurlyIndex = tokens.findIndex(token => token.range[0] >= node.discriminant.range[1] && astUtils.isOpeningBraceToken(token));
- BlockStatement: blockIndentationCheck,
+ offsets.setDesiredOffsets(tokens.slice(openingCurlyIndex + 1, -1), tokens[openingCurlyIndex], options.SwitchCase);
- WhileStatement: blockLessNodes,
+ const caseKeywords = new WeakSet(node.cases.map(switchCase => sourceCode.getFirstToken(switchCase)));
+ const lastCaseKeyword = node.cases.length && sourceCode.getFirstToken(node.cases[node.cases.length - 1]);
+ const casesWithBlocks = new WeakSet(
+ node.cases
+ .filter(switchCase => switchCase.consequent.length === 1 && switchCase.consequent[0].type === "BlockStatement")
+ .map(switchCase => sourceCode.getFirstToken(switchCase))
+ );
+ let lastAnchor = tokens[openingCurlyIndex];
+
+ tokens.slice(openingCurlyIndex + 1, -1).forEach(token => {
+ if (caseKeywords.has(token)) {
+ lastAnchor = token;
+ } else if (lastAnchor === lastCaseKeyword && (token.type === "Line" || token.type === "Block")) {
+ offsets.ignoreToken(token);
+ } else if (!casesWithBlocks.has(lastAnchor)) {
+ offsets.setDesiredOffset(token, lastAnchor, 1);
+ }
+ });
+ },
- ForStatement: blockLessNodes,
+ TemplateLiteral(node) {
+ const tokens = getTokensAndComments(node);
- ForInStatement: blockLessNodes,
+ offsets.setDesiredOffsets(getTokensAndComments(node.quasis[0]), tokens[0], 0);
+ node.expressions.forEach((expression, index) => {
+ const previousQuasi = node.quasis[index];
+ const nextQuasi = node.quasis[index + 1];
+ const tokenToAlignFrom = previousQuasi.loc.start.line === previousQuasi.loc.end.line ? sourceCode.getFirstToken(previousQuasi) : null;
- ForOfStatement: blockLessNodes,
+ offsets.setDesiredOffsets(sourceCode.getTokensBetween(previousQuasi, nextQuasi), tokenToAlignFrom, 1);
+ offsets.setDesiredOffset(sourceCode.getFirstToken(nextQuasi), tokenToAlignFrom, 0);
+ });
+ },
+
+ VariableDeclaration(node) {
+ const variableIndent = options.VariableDeclarator.hasOwnProperty(node.kind) ? options.VariableDeclarator[node.kind] : DEFAULT_VARIABLE_INDENT;
- DoWhileStatement: blockLessNodes,
+ offsets.setDesiredOffsets(getTokensAndComments(node), sourceCode.getFirstToken(node), variableIndent);
+ const lastToken = sourceCode.getLastToken(node);
- IfStatement(node) {
- if (node.consequent.type !== "BlockStatement" && node.consequent.loc.start.line > node.loc.start.line) {
- blockIndentationCheck(node);
+ if (astUtils.isSemicolonToken(lastToken)) {
+ offsets.ignoreToken(lastToken);
}
},
- VariableDeclaration(node) {
- if (node.declarations[node.declarations.length - 1].loc.start.line > node.declarations[0].loc.start.line) {
- checkIndentInVariableDeclarations(node);
+ VariableDeclarator(node) {
+ if (node.init) {
+ const equalOperator = sourceCode.getTokenBefore(node.init, astUtils.isNotOpeningParenToken);
+ const tokenAfterOperator = sourceCode.getTokenAfter(equalOperator);
+
+ offsets.ignoreToken(equalOperator);
+ offsets.ignoreToken(tokenAfterOperator);
+ offsets.matchIndentOf(equalOperator, tokenAfterOperator);
}
},
- ObjectExpression(node) {
- checkIndentInArrayOrObjectBlock(node);
+ "VariableDeclarator:exit"(node) {
+
+ /*
+ * VariableDeclarator indentation is a bit different from other forms of indentation, in that the
+ * indentation of an opening bracket sometimes won't match that of a closing bracket. For example,
+ * the following indentations are correct:
+ *
+ * var foo = {
+ * ok: true
+ * };
+ *
+ * var foo = {
+ * ok: true,
+ * },
+ * bar = 1;
+ *
+ * Account for when exiting the AST (after indentations have already been set for the nodes in
+ * the declaration) by manually increasing the indentation level of the tokens in the first declarator if the
+ * parent declaration has more than one declarator.
+ */
+ if (node.parent.declarations.length > 1 && node.parent.declarations[0] === node && node.init) {
+ const valueTokens = new Set(getTokensAndComments(node.init));
+
+ valueTokens.forEach(token => {
+ if (!valueTokens.has(offsets.getFirstDependency(token))) {
+ offsets.increaseOffset(token, options.VariableDeclarator[node.parent.kind]);
+ }
+ });
+ }
},
- ArrayExpression(node) {
- checkIndentInArrayOrObjectBlock(node);
- },
+ WhileStatement: node => addBlocklessNodeIndent(node.body),
- MemberExpression(node) {
+ "*:exit": checkForUnknownNode,
- if (typeof options.MemberExpression === "undefined") {
- return;
- }
+ "JSXAttribute[value]"(node) {
+ const equalsToken = sourceCode.getFirstTokenBetween(node.name, node.value, token => token.type === "Punctuator" && token.value === "=");
+ const firstNameToken = sourceCode.getFirstToken(node.name);
- if (isSingleLineNode(node)) {
- return;
- }
+ offsets.setDesiredOffset(equalsToken, firstNameToken, 1);
+ offsets.setDesiredOffset(sourceCode.getFirstToken(node.value), firstNameToken, 1);
+ },
- // The typical layout of variable declarations and assignments
- // alter the expectation of correct indentation. Skip them.
- // TODO: Add appropriate configuration options for variable
- // declarations and assignments.
- if (getParentNodeByType(node, "VariableDeclarator", ["FunctionExpression", "ArrowFunctionExpression"])) {
- return;
+ JSXElement(node) {
+ if (node.closingElement) {
+ addElementListIndent(node.children, sourceCode.getFirstToken(node.openingElement), sourceCode.getFirstToken(node.closingElement), 1);
}
+ },
- if (getParentNodeByType(node, "AssignmentExpression", ["FunctionExpression"])) {
- return;
+ JSXOpeningElement(node) {
+ const firstToken = sourceCode.getFirstToken(node);
+ let closingToken;
+
+ if (node.selfClosing) {
+ closingToken = sourceCode.getLastToken(node, { skip: 1 });
+ offsets.matchIndentOf(closingToken, sourceCode.getLastToken(node));
+ } else {
+ closingToken = sourceCode.getLastToken(node);
}
+ offsets.setDesiredOffsets(getTokensAndComments(node.name), sourceCode.getFirstToken(node));
+ addElementListIndent(node.attributes, firstToken, closingToken, 1);
+ },
- const propertyIndent = getNodeIndent(node).goodChar + indentSize * options.MemberExpression;
+ JSXClosingElement(node) {
+ const firstToken = sourceCode.getFirstToken(node);
- const checkNodes = [node.property];
+ offsets.setDesiredOffsets(getTokensAndComments(node.name), firstToken, 1);
+ offsets.matchIndentOf(firstToken, sourceCode.getLastToken(node));
+ },
- const dot = context.getTokenBefore(node.property);
+ JSXExpressionContainer(node) {
+ const openingCurly = sourceCode.getFirstToken(node);
+ const firstExpressionToken = sourceCode.getFirstToken(node.expression);
- if (dot.type === "Punctuator" && dot.value === ".") {
- checkNodes.push(dot);
+ if (firstExpressionToken) {
+ offsets.setDesiredOffset(firstExpressionToken, openingCurly, 1);
}
- checkNodesIndent(checkNodes, propertyIndent);
+ offsets.matchIndentOf(openingCurly, sourceCode.getLastToken(node));
},
- SwitchStatement(node) {
-
- // Switch is not a 'BlockStatement'
- const switchIndent = getNodeIndent(node).goodChar;
- const caseIndent = expectedCaseIndent(node, switchIndent);
+ "Program:exit"() {
+ addParensIndent(sourceCode.ast.tokens);
- checkNodesIndent(node.cases, caseIndent);
+ /*
+ * Create a Map from (tokenOrComment) => (precedingToken).
+ * This is necessary because sourceCode.getTokenBefore does not handle a comment as an argument correctly.
+ */
+ const precedingTokens = sourceCode.ast.comments.reduce((commentMap, comment) => {
+ const tokenOrCommentBefore = sourceCode.getTokenBefore(comment, { includeComments: true });
+ return commentMap.set(comment, commentMap.has(tokenOrCommentBefore) ? commentMap.get(tokenOrCommentBefore) : tokenOrCommentBefore);
+ }, new WeakMap());
- checkLastNodeLineIndent(node, switchIndent);
- },
+ sourceCode.lines.forEach((line, lineIndex) => {
+ const lineNumber = lineIndex + 1;
- SwitchCase(node) {
+ if (!tokenInfo.firstTokensByLineNumber.has(lineNumber)) {
- // Skip inline cases
- if (isSingleLineNode(node)) {
- return;
- }
- const caseIndent = expectedCaseIndent(node);
+ // Don't check indentation on blank lines
+ return;
+ }
- checkNodesIndent(node.consequent, caseIndent + indentSize);
- },
+ const firstTokenOfLine = tokenInfo.firstTokensByLineNumber.get(lineNumber);
- FunctionDeclaration(node) {
- if (isSingleLineNode(node)) {
- return;
- }
- if (options.FunctionDeclaration.parameters === "first" && node.params.length) {
- checkNodesIndent(node.params.slice(1), node.params[0].loc.start.column);
- } else if (options.FunctionDeclaration.parameters !== null) {
- checkNodesIndent(node.params, getNodeIndent(node).goodChar + indentSize * options.FunctionDeclaration.parameters);
- }
- },
+ if (firstTokenOfLine.loc.start.line !== lineNumber) {
- FunctionExpression(node) {
- if (isSingleLineNode(node)) {
- return;
- }
- if (options.FunctionExpression.parameters === "first" && node.params.length) {
- checkNodesIndent(node.params.slice(1), node.params[0].loc.start.column);
- } else if (options.FunctionExpression.parameters !== null) {
- checkNodesIndent(node.params, getNodeIndent(node).goodChar + indentSize * options.FunctionExpression.parameters);
- }
- },
+ // Don't check the indentation of multi-line tokens (e.g. template literals or block comments) twice.
+ return;
+ }
- ReturnStatement(node) {
- if (isSingleLineNode(node)) {
- return;
- }
+ // If the token matches the expected expected indentation, don't report it.
+ if (validateTokenIndent(firstTokenOfLine, offsets.getDesiredIndent(firstTokenOfLine))) {
+ return;
+ }
- const firstLineIndent = getNodeIndent(node).goodChar;
+ if (astUtils.isCommentToken(firstTokenOfLine)) {
+ const tokenBefore = precedingTokens.get(firstTokenOfLine);
+ const tokenAfter = tokenBefore ? sourceCode.getTokenAfter(tokenBefore) : sourceCode.ast.tokens[0];
- // in case if return statement is wrapped in parenthesis
- if (isWrappedInParenthesis(node)) {
- checkLastReturnStatementLineIndent(node, firstLineIndent);
- } else {
- checkNodeIndent(node, firstLineIndent);
- }
- },
+ // If a comment matches the expected indentation of the token immediately before or after, don't report it.
+ if (
+ tokenBefore && validateTokenIndent(firstTokenOfLine, offsets.getDesiredIndent(tokenBefore)) ||
+ tokenAfter && validateTokenIndent(firstTokenOfLine, offsets.getDesiredIndent(tokenAfter))
+ ) {
+ return;
+ }
+ }
- CallExpression(node) {
- if (isSingleLineNode(node)) {
- return;
- }
- if (options.CallExpression.arguments === "first" && node.arguments.length) {
- checkNodesIndent(node.arguments.slice(1), node.arguments[0].loc.start.column);
- } else if (options.CallExpression.arguments !== null) {
- checkNodesIndent(node.arguments, getNodeIndent(node).goodChar + indentSize * options.CallExpression.arguments);
- }
+ // Otherwise, report the token/comment.
+ report(firstTokenOfLine, offsets.getDesiredIndent(firstTokenOfLine));
+ });
}
};
diff --git a/tools/eslint/lib/rules/key-spacing.js b/tools/eslint/lib/rules/key-spacing.js
index ce150753b849b6..03f45a6c679624 100644
--- a/tools/eslint/lib/rules/key-spacing.js
+++ b/tools/eslint/lib/rules/key-spacing.js
@@ -33,41 +33,6 @@ function last(arr) {
return arr[arr.length - 1];
}
-/**
- * Checks whether a property is a member of the property group it follows.
- * @param {ASTNode} lastMember The last Property known to be in the group.
- * @param {ASTNode} candidate The next Property that might be in the group.
- * @returns {boolean} True if the candidate property is part of the group.
- */
-function continuesPropertyGroup(lastMember, candidate) {
- const groupEndLine = lastMember.loc.start.line,
- candidateStartLine = candidate.loc.start.line;
-
- if (candidateStartLine - groupEndLine <= 1) {
- return true;
- }
-
- // Check that the first comment is adjacent to the end of the group, the
- // last comment is adjacent to the candidate property, and that successive
- // comments are adjacent to each other.
- const comments = candidate.leadingComments;
-
- if (
- comments &&
- comments[0].loc.start.line - groupEndLine <= 1 &&
- candidateStartLine - last(comments).loc.end.line <= 1
- ) {
- for (let i = 1; i < comments.length; i++) {
- if (comments[i].loc.start.line - comments[i - 1].loc.end.line > 1) {
- return false;
- }
- }
- return true;
- }
-
- return false;
-}
-
/**
* Checks whether a node is contained on a single line.
* @param {ASTNode} node AST Node being evaluated.
@@ -350,6 +315,41 @@ module.exports = {
const sourceCode = context.getSourceCode();
+ /**
+ * Checks whether a property is a member of the property group it follows.
+ * @param {ASTNode} lastMember The last Property known to be in the group.
+ * @param {ASTNode} candidate The next Property that might be in the group.
+ * @returns {boolean} True if the candidate property is part of the group.
+ */
+ function continuesPropertyGroup(lastMember, candidate) {
+ const groupEndLine = lastMember.loc.start.line,
+ candidateStartLine = candidate.loc.start.line;
+
+ if (candidateStartLine - groupEndLine <= 1) {
+ return true;
+ }
+
+ // Check that the first comment is adjacent to the end of the group, the
+ // last comment is adjacent to the candidate property, and that successive
+ // comments are adjacent to each other.
+ const leadingComments = sourceCode.getCommentsBefore(candidate);
+
+ if (
+ leadingComments.length &&
+ leadingComments[0].loc.start.line - groupEndLine <= 1 &&
+ candidateStartLine - last(leadingComments).loc.end.line <= 1
+ ) {
+ for (let i = 1; i < leadingComments.length; i++) {
+ if (leadingComments[i].loc.start.line - leadingComments[i - 1].loc.end.line > 1) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ return false;
+ }
+
/**
* Determines if the given property is key-value property.
* @param {ASTNode} property Property node to check.
@@ -634,6 +634,5 @@ module.exports = {
};
-
}
};
diff --git a/tools/eslint/lib/rules/line-comment-position.js b/tools/eslint/lib/rules/line-comment-position.js
index dd8f2b9ad6aa91..0df806cca8cdeb 100644
--- a/tools/eslint/lib/rules/line-comment-position.js
+++ b/tools/eslint/lib/rules/line-comment-position.js
@@ -78,33 +78,37 @@ module.exports = {
//--------------------------------------------------------------------------
return {
- LineComment(node) {
- if (applyDefaultIgnorePatterns && (defaultIgnoreRegExp.test(node.value) || fallThroughRegExp.test(node.value))) {
- return;
- }
-
- if (ignorePattern && customIgnoreRegExp.test(node.value)) {
- return;
- }
-
- const previous = sourceCode.getTokenBefore(node, { includeComments: true });
- const isOnSameLine = previous && previous.loc.end.line === node.loc.start.line;
-
- if (above) {
- if (isOnSameLine) {
- context.report({
- node,
- message: "Expected comment to be above code."
- });
+ Program() {
+ const comments = sourceCode.getAllComments();
+
+ comments.filter(token => token.type === "Line").forEach(node => {
+ if (applyDefaultIgnorePatterns && (defaultIgnoreRegExp.test(node.value) || fallThroughRegExp.test(node.value))) {
+ return;
+ }
+
+ if (ignorePattern && customIgnoreRegExp.test(node.value)) {
+ return;
}
- } else {
- if (!isOnSameLine) {
- context.report({
- node,
- message: "Expected comment to be beside code."
- });
+
+ const previous = sourceCode.getTokenBefore(node, { includeComments: true });
+ const isOnSameLine = previous && previous.loc.end.line === node.loc.start.line;
+
+ if (above) {
+ if (isOnSameLine) {
+ context.report({
+ node,
+ message: "Expected comment to be above code."
+ });
+ }
+ } else {
+ if (!isOnSameLine) {
+ context.report({
+ node,
+ message: "Expected comment to be beside code."
+ });
+ }
}
- }
+ });
}
};
}
diff --git a/tools/eslint/lib/rules/lines-around-comment.js b/tools/eslint/lib/rules/lines-around-comment.js
index e37dd8611ddc8b..5b4cd8ebe92c05 100644
--- a/tools/eslint/lib/rules/lines-around-comment.js
+++ b/tools/eslint/lib/rules/lines-around-comment.js
@@ -31,7 +31,7 @@ function getEmptyLineNums(lines) {
/**
* Return an array with with any line numbers that contain comments.
- * @param {Array} comments An array of comment nodes.
+ * @param {Array} comments An array of comment tokens.
* @returns {Array} An array of line numbers.
*/
function getCommentLineNums(comments) {
@@ -131,38 +131,28 @@ module.exports = {
emptyLines = getEmptyLineNums(lines),
commentAndEmptyLines = commentLines.concat(emptyLines);
- /**
- * Returns whether or not a token is a comment node type
- * @param {Token} token The token to check
- * @returns {boolean} True if the token is a comment node
- */
- function isCommentNodeType(token) {
- return token && (token.type === "Block" || token.type === "Line");
- }
-
/**
* Returns whether or not comments are on lines starting with or ending with code
- * @param {ASTNode} node The comment node to check.
+ * @param {token} token The comment token to check.
* @returns {boolean} True if the comment is not alone.
*/
- function codeAroundComment(node) {
- let token;
+ function codeAroundComment(token) {
+ let currentToken = token;
- token = node;
do {
- token = sourceCode.getTokenBefore(token, { includeComments: true });
- } while (isCommentNodeType(token));
+ currentToken = sourceCode.getTokenBefore(currentToken, { includeComments: true });
+ } while (currentToken && astUtils.isCommentToken(currentToken));
- if (token && astUtils.isTokenOnSameLine(token, node)) {
+ if (currentToken && astUtils.isTokenOnSameLine(currentToken, token)) {
return true;
}
- token = node;
+ currentToken = token;
do {
- token = sourceCode.getTokenAfter(token, { includeComments: true });
- } while (isCommentNodeType(token));
+ currentToken = sourceCode.getTokenAfter(currentToken, { includeComments: true });
+ } while (currentToken && astUtils.isCommentToken(currentToken));
- if (token && astUtils.isTokenOnSameLine(node, token)) {
+ if (currentToken && astUtils.isTokenOnSameLine(token, currentToken)) {
return true;
}
@@ -171,137 +161,135 @@ module.exports = {
/**
* Returns whether or not comments are inside a node type or not.
- * @param {ASTNode} node The Comment node.
* @param {ASTNode} parent The Comment parent node.
* @param {string} nodeType The parent type to check against.
* @returns {boolean} True if the comment is inside nodeType.
*/
- function isCommentInsideNodeType(node, parent, nodeType) {
+ function isParentNodeType(parent, nodeType) {
return parent.type === nodeType ||
(parent.body && parent.body.type === nodeType) ||
(parent.consequent && parent.consequent.type === nodeType);
}
+ /**
+ * Returns the parent node that contains the given token.
+ * @param {token} token The token to check.
+ * @returns {ASTNode} The parent node that contains the given token.
+ */
+ function getParentNodeOfToken(token) {
+ return sourceCode.getNodeByRangeIndex(token.range[0]);
+ }
+
/**
* Returns whether or not comments are at the parent start or not.
- * @param {ASTNode} node The Comment node.
+ * @param {token} token The Comment token.
* @param {string} nodeType The parent type to check against.
* @returns {boolean} True if the comment is at parent start.
*/
- function isCommentAtParentStart(node, nodeType) {
- const ancestors = context.getAncestors();
- let parent;
+ function isCommentAtParentStart(token, nodeType) {
+ const parent = getParentNodeOfToken(token);
- if (ancestors.length) {
- parent = ancestors.pop();
- }
-
- return parent && isCommentInsideNodeType(node, parent, nodeType) &&
- node.loc.start.line - parent.loc.start.line === 1;
+ return parent && isParentNodeType(parent, nodeType) &&
+ token.loc.start.line - parent.loc.start.line === 1;
}
/**
* Returns whether or not comments are at the parent end or not.
- * @param {ASTNode} node The Comment node.
+ * @param {token} token The Comment token.
* @param {string} nodeType The parent type to check against.
* @returns {boolean} True if the comment is at parent end.
*/
- function isCommentAtParentEnd(node, nodeType) {
- const ancestors = context.getAncestors();
- let parent;
-
- if (ancestors.length) {
- parent = ancestors.pop();
- }
+ function isCommentAtParentEnd(token, nodeType) {
+ const parent = getParentNodeOfToken(token);
- return parent && isCommentInsideNodeType(node, parent, nodeType) &&
- parent.loc.end.line - node.loc.end.line === 1;
+ return parent && isParentNodeType(parent, nodeType) &&
+ parent.loc.end.line - token.loc.end.line === 1;
}
/**
* Returns whether or not comments are at the block start or not.
- * @param {ASTNode} node The Comment node.
+ * @param {token} token The Comment token.
* @returns {boolean} True if the comment is at block start.
*/
- function isCommentAtBlockStart(node) {
- return isCommentAtParentStart(node, "ClassBody") || isCommentAtParentStart(node, "BlockStatement") || isCommentAtParentStart(node, "SwitchCase");
+ function isCommentAtBlockStart(token) {
+ return isCommentAtParentStart(token, "ClassBody") || isCommentAtParentStart(token, "BlockStatement") || isCommentAtParentStart(token, "SwitchCase");
}
/**
* Returns whether or not comments are at the block end or not.
- * @param {ASTNode} node The Comment node.
+ * @param {token} token The Comment token.
* @returns {boolean} True if the comment is at block end.
*/
- function isCommentAtBlockEnd(node) {
- return isCommentAtParentEnd(node, "ClassBody") || isCommentAtParentEnd(node, "BlockStatement") || isCommentAtParentEnd(node, "SwitchCase") || isCommentAtParentEnd(node, "SwitchStatement");
+ function isCommentAtBlockEnd(token) {
+ return isCommentAtParentEnd(token, "ClassBody") || isCommentAtParentEnd(token, "BlockStatement") || isCommentAtParentEnd(token, "SwitchCase") || isCommentAtParentEnd(token, "SwitchStatement");
}
/**
* Returns whether or not comments are at the object start or not.
- * @param {ASTNode} node The Comment node.
+ * @param {token} token The Comment token.
* @returns {boolean} True if the comment is at object start.
*/
- function isCommentAtObjectStart(node) {
- return isCommentAtParentStart(node, "ObjectExpression") || isCommentAtParentStart(node, "ObjectPattern");
+ function isCommentAtObjectStart(token) {
+ return isCommentAtParentStart(token, "ObjectExpression") || isCommentAtParentStart(token, "ObjectPattern");
}
/**
* Returns whether or not comments are at the object end or not.
- * @param {ASTNode} node The Comment node.
+ * @param {token} token The Comment token.
* @returns {boolean} True if the comment is at object end.
*/
- function isCommentAtObjectEnd(node) {
- return isCommentAtParentEnd(node, "ObjectExpression") || isCommentAtParentEnd(node, "ObjectPattern");
+ function isCommentAtObjectEnd(token) {
+ return isCommentAtParentEnd(token, "ObjectExpression") || isCommentAtParentEnd(token, "ObjectPattern");
}
/**
* Returns whether or not comments are at the array start or not.
- * @param {ASTNode} node The Comment node.
+ * @param {token} token The Comment token.
* @returns {boolean} True if the comment is at array start.
*/
- function isCommentAtArrayStart(node) {
- return isCommentAtParentStart(node, "ArrayExpression") || isCommentAtParentStart(node, "ArrayPattern");
+ function isCommentAtArrayStart(token) {
+ return isCommentAtParentStart(token, "ArrayExpression") || isCommentAtParentStart(token, "ArrayPattern");
}
/**
* Returns whether or not comments are at the array end or not.
- * @param {ASTNode} node The Comment node.
+ * @param {token} token The Comment token.
* @returns {boolean} True if the comment is at array end.
*/
- function isCommentAtArrayEnd(node) {
- return isCommentAtParentEnd(node, "ArrayExpression") || isCommentAtParentEnd(node, "ArrayPattern");
+ function isCommentAtArrayEnd(token) {
+ return isCommentAtParentEnd(token, "ArrayExpression") || isCommentAtParentEnd(token, "ArrayPattern");
}
/**
- * Checks if a comment node has lines around it (ignores inline comments)
- * @param {ASTNode} node The Comment node.
+ * Checks if a comment token has lines around it (ignores inline comments)
+ * @param {token} token The Comment token.
* @param {Object} opts Options to determine the newline.
* @param {boolean} opts.after Should have a newline after this line.
* @param {boolean} opts.before Should have a newline before this line.
* @returns {void}
*/
- function checkForEmptyLine(node, opts) {
- if (applyDefaultIgnorePatterns && defaultIgnoreRegExp.test(node.value)) {
+ function checkForEmptyLine(token, opts) {
+ if (applyDefaultIgnorePatterns && defaultIgnoreRegExp.test(token.value)) {
return;
}
- if (ignorePattern && customIgnoreRegExp.test(node.value)) {
+ if (ignorePattern && customIgnoreRegExp.test(token.value)) {
return;
}
let after = opts.after,
before = opts.before;
- const prevLineNum = node.loc.start.line - 1,
- nextLineNum = node.loc.end.line + 1,
- commentIsNotAlone = codeAroundComment(node);
+ const prevLineNum = token.loc.start.line - 1,
+ nextLineNum = token.loc.end.line + 1,
+ commentIsNotAlone = codeAroundComment(token);
- const blockStartAllowed = options.allowBlockStart && isCommentAtBlockStart(node),
- blockEndAllowed = options.allowBlockEnd && isCommentAtBlockEnd(node),
- objectStartAllowed = options.allowObjectStart && isCommentAtObjectStart(node),
- objectEndAllowed = options.allowObjectEnd && isCommentAtObjectEnd(node),
- arrayStartAllowed = options.allowArrayStart && isCommentAtArrayStart(node),
- arrayEndAllowed = options.allowArrayEnd && isCommentAtArrayEnd(node);
+ const blockStartAllowed = options.allowBlockStart && isCommentAtBlockStart(token),
+ blockEndAllowed = options.allowBlockEnd && isCommentAtBlockEnd(token),
+ objectStartAllowed = options.allowObjectStart && isCommentAtObjectStart(token),
+ objectEndAllowed = options.allowObjectEnd && isCommentAtObjectEnd(token),
+ arrayStartAllowed = options.allowArrayStart && isCommentAtArrayStart(token),
+ arrayEndAllowed = options.allowArrayEnd && isCommentAtArrayEnd(token);
const exceptionStartAllowed = blockStartAllowed || objectStartAllowed || arrayStartAllowed;
const exceptionEndAllowed = blockEndAllowed || objectEndAllowed || arrayEndAllowed;
@@ -319,17 +307,17 @@ module.exports = {
return;
}
- const previousTokenOrComment = sourceCode.getTokenBefore(node, { includeComments: true });
- const nextTokenOrComment = sourceCode.getTokenAfter(node, { includeComments: true });
+ const previousTokenOrComment = sourceCode.getTokenBefore(token, { includeComments: true });
+ const nextTokenOrComment = sourceCode.getTokenAfter(token, { includeComments: true });
// check for newline before
if (!exceptionStartAllowed && before && !lodash.includes(commentAndEmptyLines, prevLineNum) &&
- !(isCommentNodeType(previousTokenOrComment) && astUtils.isTokenOnSameLine(previousTokenOrComment, node))) {
- const lineStart = node.range[0] - node.loc.start.column;
+ !(astUtils.isCommentToken(previousTokenOrComment) && astUtils.isTokenOnSameLine(previousTokenOrComment, token))) {
+ const lineStart = token.range[0] - token.loc.start.column;
const range = [lineStart, lineStart];
context.report({
- node,
+ node: token,
message: "Expected line before comment.",
fix(fixer) {
return fixer.insertTextBeforeRange(range, "\n");
@@ -339,12 +327,12 @@ module.exports = {
// check for newline after
if (!exceptionEndAllowed && after && !lodash.includes(commentAndEmptyLines, nextLineNum) &&
- !(isCommentNodeType(nextTokenOrComment) && astUtils.isTokenOnSameLine(node, nextTokenOrComment))) {
+ !(astUtils.isCommentToken(nextTokenOrComment) && astUtils.isTokenOnSameLine(token, nextTokenOrComment))) {
context.report({
- node,
+ node: token,
message: "Expected line after comment.",
fix(fixer) {
- return fixer.insertTextAfter(node, "\n");
+ return fixer.insertTextAfter(token, "\n");
}
});
}
@@ -356,25 +344,25 @@ module.exports = {
//--------------------------------------------------------------------------
return {
-
- LineComment(node) {
- if (options.beforeLineComment || options.afterLineComment) {
- checkForEmptyLine(node, {
- after: options.afterLineComment,
- before: options.beforeLineComment
- });
- }
- },
-
- BlockComment(node) {
- if (options.beforeBlockComment || options.afterBlockComment) {
- checkForEmptyLine(node, {
- after: options.afterBlockComment,
- before: options.beforeBlockComment
- });
- }
+ Program() {
+ comments.forEach(token => {
+ if (token.type === "Line") {
+ if (options.beforeLineComment || options.afterLineComment) {
+ checkForEmptyLine(token, {
+ after: options.afterLineComment,
+ before: options.beforeLineComment
+ });
+ }
+ } else if (token.type === "Block") {
+ if (options.beforeBlockComment || options.afterBlockComment) {
+ checkForEmptyLine(token, {
+ after: options.afterBlockComment,
+ before: options.beforeBlockComment
+ });
+ }
+ }
+ });
}
-
};
}
};
diff --git a/tools/eslint/lib/rules/lines-around-directive.js b/tools/eslint/lib/rules/lines-around-directive.js
index 89dd9c6aeedf40..65b6cd1db59e7d 100644
--- a/tools/eslint/lib/rules/lines-around-directive.js
+++ b/tools/eslint/lib/rules/lines-around-directive.js
@@ -1,6 +1,7 @@
/**
* @fileoverview Require or disallow newlines around directives.
* @author Kai Cataldo
+ * @deprecated
*/
"use strict";
@@ -16,7 +17,8 @@ module.exports = {
docs: {
description: "require or disallow newlines around directives",
category: "Stylistic Issues",
- recommended: false
+ recommended: false,
+ replacedBy: ["padding-line-between-statements"]
},
schema: [{
oneOf: [
@@ -38,7 +40,8 @@ module.exports = {
}
]
}],
- fixable: "whitespace"
+ fixable: "whitespace",
+ deprecated: true
},
create(context) {
@@ -131,17 +134,12 @@ module.exports = {
}
const firstDirective = directives[0];
- const hasTokenOrCommentBefore = !!sourceCode.getTokenBefore(firstDirective, { includeComments: true });
+ const leadingComments = sourceCode.getCommentsBefore(firstDirective);
// Only check before the first directive if it is preceded by a comment or if it is at the top of
// the file and expectLineBefore is set to "never". This is to not force a newline at the top of
// the file if there are no comments as well as for compatibility with padded-blocks.
- if (
- firstDirective.leadingComments && firstDirective.leadingComments.length ||
-
- // Shebangs are not added to leading comments but are accounted for by the following.
- node.type === "Program" && hasTokenOrCommentBefore
- ) {
+ if (leadingComments.length) {
if (expectLineBefore === "always" && !hasNewlineBefore(firstDirective)) {
reportError(firstDirective, "before", true);
}
@@ -152,7 +150,7 @@ module.exports = {
} else if (
node.type === "Program" &&
expectLineBefore === "never" &&
- !hasTokenOrCommentBefore &&
+ !leadingComments.length &&
hasNewlineBefore(firstDirective)
) {
reportError(firstDirective, "before", false);
diff --git a/tools/eslint/lib/rules/max-len.js b/tools/eslint/lib/rules/max-len.js
index dd5a4e1ef62553..b693c8078c620e 100644
--- a/tools/eslint/lib/rules/max-len.js
+++ b/tools/eslint/lib/rules/max-len.js
@@ -108,7 +108,7 @@ module.exports = {
previousTabStopOffset = tabWidth ? totalOffset % tabWidth : 0,
spaceCount = tabWidth - previousTabStopOffset;
- extraCharacterCount += spaceCount - 1; // -1 for the replaced tab
+ extraCharacterCount += spaceCount - 1; // -1 for the replaced tab
});
return Array.from(line).length + extraCharacterCount;
}
@@ -268,13 +268,13 @@ module.exports = {
// we iterate over comments in parallel with the lines
let commentsIndex = 0;
- const strings = getAllStrings(sourceCode);
+ const strings = getAllStrings();
const stringsByLine = strings.reduce(groupByLineNumber, {});
- const templateLiterals = getAllTemplateLiterals(sourceCode);
+ const templateLiterals = getAllTemplateLiterals();
const templateLiteralsByLine = templateLiterals.reduce(groupByLineNumber, {});
- const regExpLiterals = getAllRegExpLiterals(sourceCode);
+ const regExpLiterals = getAllRegExpLiterals();
const regExpLiteralsByLine = regExpLiterals.reduce(groupByLineNumber, {});
lines.forEach((line, i) => {
@@ -321,21 +321,24 @@ module.exports = {
}
const lineLength = computeLineLength(line, tabWidth);
+ const commentLengthApplies = lineIsComment && maxCommentLength;
if (lineIsComment && ignoreComments) {
return;
}
- if (lineIsComment && lineLength > maxCommentLength) {
- context.report({
- node,
- loc: { line: lineNumber, column: 0 },
- message: "Line {{lineNumber}} exceeds the maximum comment line length of {{maxCommentLength}}.",
- data: {
- lineNumber: i + 1,
- maxCommentLength
- }
- });
+ if (commentLengthApplies) {
+ if (lineLength > maxCommentLength) {
+ context.report({
+ node,
+ loc: { line: lineNumber, column: 0 },
+ message: "Line {{lineNumber}} exceeds the maximum comment line length of {{maxCommentLength}}.",
+ data: {
+ lineNumber: i + 1,
+ maxCommentLength
+ }
+ });
+ }
} else if (lineLength > maxLength) {
context.report({
node,
diff --git a/tools/eslint/lib/rules/new-parens.js b/tools/eslint/lib/rules/new-parens.js
index ad37979d54ed91..aa0f7fe931db5f 100644
--- a/tools/eslint/lib/rules/new-parens.js
+++ b/tools/eslint/lib/rules/new-parens.js
@@ -38,7 +38,7 @@ module.exports = {
return {
NewExpression(node) {
if (node.arguments.length !== 0) {
- return; // shortcut: if there are arguments, there have to be parens
+ return; // shortcut: if there are arguments, there have to be parens
}
const lastToken = sourceCode.getLastToken(node);
diff --git a/tools/eslint/lib/rules/newline-after-var.js b/tools/eslint/lib/rules/newline-after-var.js
index 7b8d473d1dda17..744a52a580af53 100644
--- a/tools/eslint/lib/rules/newline-after-var.js
+++ b/tools/eslint/lib/rules/newline-after-var.js
@@ -1,6 +1,7 @@
/**
* @fileoverview Rule to check empty newline after "var" statement
* @author Gopal Venkatesan
+ * @deprecated
*/
"use strict";
@@ -20,7 +21,8 @@ module.exports = {
docs: {
description: "require or disallow an empty line after variable declarations",
category: "Stylistic Issues",
- recommended: false
+ recommended: false,
+ replacedBy: ["padding-line-between-statements"]
},
schema: [
@@ -29,7 +31,9 @@ module.exports = {
}
],
- fixable: "whitespace"
+ fixable: "whitespace",
+
+ deprecated: true
},
create(context) {
diff --git a/tools/eslint/lib/rules/newline-before-return.js b/tools/eslint/lib/rules/newline-before-return.js
index 996039b6929b5e..1b9b0c79392a8b 100644
--- a/tools/eslint/lib/rules/newline-before-return.js
+++ b/tools/eslint/lib/rules/newline-before-return.js
@@ -1,6 +1,7 @@
/**
* @fileoverview Rule to require newlines before `return` statement
* @author Kai Cataldo
+ * @deprecated
*/
"use strict";
@@ -13,10 +14,12 @@ module.exports = {
docs: {
description: "require an empty line before `return` statements",
category: "Stylistic Issues",
- recommended: false
+ recommended: false,
+ replacedBy: ["padding-line-between-statements"]
},
fixable: "whitespace",
- schema: []
+ schema: [],
+ deprecated: true
},
create(context) {
@@ -50,8 +53,8 @@ module.exports = {
if (node.parent.body) {
return Array.isArray(node.parent.body)
- ? node.parent.body[0] === node
- : node.parent.body === node;
+ ? node.parent.body[0] === node
+ : node.parent.body === node;
}
if (parentType === "IfStatement") {
@@ -73,7 +76,7 @@ module.exports = {
* @private
*/
function calcCommentLines(node, lineNumTokenBefore) {
- const comments = sourceCode.getComments(node).leading;
+ const comments = sourceCode.getCommentsBefore(node);
let numLinesComments = 0;
if (!comments.length) {
@@ -121,7 +124,7 @@ module.exports = {
if (tokenBefore) {
lineNumTokenBefore = tokenBefore.loc.end.line;
} else {
- lineNumTokenBefore = 0; // global return at beginning of script
+ lineNumTokenBefore = 0; // global return at beginning of script
}
return lineNumTokenBefore;
@@ -153,7 +156,7 @@ module.exports = {
* @private
*/
function canFix(node) {
- const leadingComments = sourceCode.getComments(node).leading;
+ const leadingComments = sourceCode.getCommentsBefore(node);
const lastLeadingComment = leadingComments[leadingComments.length - 1];
const tokenBefore = sourceCode.getTokenBefore(node);
diff --git a/tools/eslint/lib/rules/no-alert.js b/tools/eslint/lib/rules/no-alert.js
index f2cfc3a87762d2..232fa14449cb67 100644
--- a/tools/eslint/lib/rules/no-alert.js
+++ b/tools/eslint/lib/rules/no-alert.js
@@ -35,7 +35,7 @@ function report(context, node, identifierName) {
}
/**
- * Finds the escope reference in the given scope.
+ * Finds the eslint-scope reference in the given scope.
* @param {Object} scope The scope to search.
* @param {ASTNode} node The identifier node.
* @returns {Reference|null} Returns the found reference or null if none were found.
diff --git a/tools/eslint/lib/rules/no-buffer-constructor.js b/tools/eslint/lib/rules/no-buffer-constructor.js
new file mode 100644
index 00000000000000..1521ff2847e11d
--- /dev/null
+++ b/tools/eslint/lib/rules/no-buffer-constructor.js
@@ -0,0 +1,37 @@
+/**
+ * @fileoverview disallow use of the Buffer() constructor
+ * @author Teddy Katz
+ */
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = {
+ meta: {
+ docs: {
+ description: "disallow use of the Buffer() constructor",
+ category: "Node.js and CommonJS",
+ recommended: false
+ },
+ schema: []
+ },
+
+ create(context) {
+
+ //----------------------------------------------------------------------
+ // Public
+ //----------------------------------------------------------------------
+
+ return {
+ "CallExpression[callee.name='Buffer'], NewExpression[callee.name='Buffer']"(node) {
+ context.report({
+ node,
+ message: "{{example}} is deprecated. Use Buffer.from(), Buffer.alloc(), or Buffer.allocUnsafe() instead.",
+ data: { example: node.type === "CallExpression" ? "Buffer()" : "new Buffer()" }
+ });
+ }
+ };
+ }
+};
diff --git a/tools/eslint/lib/rules/no-compare-neg-zero.js b/tools/eslint/lib/rules/no-compare-neg-zero.js
index d93ade5d307134..604e221919922a 100644
--- a/tools/eslint/lib/rules/no-compare-neg-zero.js
+++ b/tools/eslint/lib/rules/no-compare-neg-zero.js
@@ -13,7 +13,7 @@ module.exports = {
docs: {
description: "disallow comparing against -0",
category: "Possible Errors",
- recommended: false
+ recommended: true
},
fixable: null,
schema: []
diff --git a/tools/eslint/lib/rules/no-confusing-arrow.js b/tools/eslint/lib/rules/no-confusing-arrow.js
index d6edbcc810e4fb..fc69ca39a9eda0 100644
--- a/tools/eslint/lib/rules/no-confusing-arrow.js
+++ b/tools/eslint/lib/rules/no-confusing-arrow.js
@@ -33,6 +33,8 @@ module.exports = {
recommended: false
},
+ fixable: "code",
+
schema: [{
type: "object",
properties: {
@@ -55,7 +57,15 @@ module.exports = {
const body = node.body;
if (isConditional(body) && !(config.allowParens && astUtils.isParenthesised(sourceCode, body))) {
- context.report({ node, message: "Arrow function used ambiguously with a conditional expression." });
+ context.report({
+ node,
+ message: "Arrow function used ambiguously with a conditional expression.",
+ fix(fixer) {
+
+ // if `allowParens` is not set to true dont bother wrapping in parens
+ return config.allowParens && fixer.replaceText(node.body, `(${sourceCode.getText(node.body)})`);
+ }
+ });
}
}
diff --git a/tools/eslint/lib/rules/no-console.js b/tools/eslint/lib/rules/no-console.js
index 9131a49a01ae55..32bdf6d1f4d78f 100644
--- a/tools/eslint/lib/rules/no-console.js
+++ b/tools/eslint/lib/rules/no-console.js
@@ -48,7 +48,7 @@ module.exports = {
/**
* Checks whether the given reference is 'console' or not.
*
- * @param {escope.Reference} reference - The reference to check.
+ * @param {eslint-scope.Reference} reference - The reference to check.
* @returns {boolean} `true` if the reference is 'console'.
*/
function isConsole(reference) {
@@ -74,7 +74,7 @@ module.exports = {
* Checks whether the given reference is a member access which is not
* allowed by options or not.
*
- * @param {escope.Reference} reference - The reference to check.
+ * @param {eslint-scope.Reference} reference - The reference to check.
* @returns {boolean} `true` if the reference is a member access which
* is not allowed by options.
*/
@@ -92,7 +92,7 @@ module.exports = {
/**
* Reports the given reference as a violation.
*
- * @param {escope.Reference} reference - The reference to report.
+ * @param {eslint-scope.Reference} reference - The reference to report.
* @returns {void}
*/
function report(reference) {
diff --git a/tools/eslint/lib/rules/no-debugger.js b/tools/eslint/lib/rules/no-debugger.js
index 897b3dbb6094f9..a158724fef118f 100644
--- a/tools/eslint/lib/rules/no-debugger.js
+++ b/tools/eslint/lib/rules/no-debugger.js
@@ -16,7 +16,7 @@ module.exports = {
category: "Possible Errors",
recommended: true
},
-
+ fixable: "code",
schema: []
},
@@ -24,7 +24,13 @@ module.exports = {
return {
DebuggerStatement(node) {
- context.report({ node, message: "Unexpected 'debugger' statement." });
+ context.report({
+ node,
+ message: "Unexpected 'debugger' statement.",
+ fix(fixer) {
+ return fixer.remove(node);
+ }
+ });
}
};
diff --git a/tools/eslint/lib/rules/no-dupe-args.js b/tools/eslint/lib/rules/no-dupe-args.js
index cdb38035c0a01f..c932be01d7615e 100644
--- a/tools/eslint/lib/rules/no-dupe-args.js
+++ b/tools/eslint/lib/rules/no-dupe-args.js
@@ -28,7 +28,7 @@ module.exports = {
/**
* Checks whether or not a given definition is a parameter's.
- * @param {escope.DefEntry} def - A definition to check.
+ * @param {eslint-scope.DefEntry} def - A definition to check.
* @returns {boolean} `true` if the definition is a parameter's.
*/
function isParameter(def) {
diff --git a/tools/eslint/lib/rules/no-empty-function.js b/tools/eslint/lib/rules/no-empty-function.js
index 115d8698eead71..38c915c33f9730 100644
--- a/tools/eslint/lib/rules/no-empty-function.js
+++ b/tools/eslint/lib/rules/no-empty-function.js
@@ -132,11 +132,15 @@ module.exports = {
function reportIfEmpty(node) {
const kind = getKind(node);
const name = astUtils.getFunctionNameWithKind(node);
+ const innerComments = sourceCode.getTokens(node.body, {
+ includeComments: true,
+ filter: astUtils.isCommentToken
+ });
if (allowed.indexOf(kind) === -1 &&
node.body.type === "BlockStatement" &&
node.body.body.length === 0 &&
- sourceCode.getComments(node.body).trailing.length === 0
+ innerComments.length === 0
) {
context.report({
node,
diff --git a/tools/eslint/lib/rules/no-empty.js b/tools/eslint/lib/rules/no-empty.js
index a9b0776c933b07..b71b8582a37195 100644
--- a/tools/eslint/lib/rules/no-empty.js
+++ b/tools/eslint/lib/rules/no-empty.js
@@ -59,7 +59,7 @@ module.exports = {
}
// any other block is only allowed to be empty, if it contains a comment
- if (sourceCode.getComments(node).trailing.length > 0) {
+ if (sourceCode.getCommentsInside(node).length > 0) {
return;
}
diff --git a/tools/eslint/lib/rules/no-eval.js b/tools/eslint/lib/rules/no-eval.js
index fe1456cba0a431..ee5f577f471ef9 100644
--- a/tools/eslint/lib/rules/no-eval.js
+++ b/tools/eslint/lib/rules/no-eval.js
@@ -166,7 +166,7 @@ module.exports = {
/**
* Reports accesses of `eval` via the global object.
*
- * @param {escope.Scope} globalScope - The global scope.
+ * @param {eslint-scope.Scope} globalScope - The global scope.
* @returns {void}
*/
function reportAccessingEvalViaGlobalObject(globalScope) {
@@ -200,7 +200,7 @@ module.exports = {
/**
* Reports all accesses of `eval` (excludes direct calls to eval).
*
- * @param {escope.Scope} globalScope - The global scope.
+ * @param {eslint-scope.Scope} globalScope - The global scope.
* @returns {void}
*/
function reportAccessingEval(globalScope) {
diff --git a/tools/eslint/lib/rules/no-extend-native.js b/tools/eslint/lib/rules/no-extend-native.js
index 547770d8f7e4af..c550cf5da57a25 100644
--- a/tools/eslint/lib/rules/no-extend-native.js
+++ b/tools/eslint/lib/rules/no-extend-native.js
@@ -9,8 +9,15 @@
// Requirements
//------------------------------------------------------------------------------
+const astUtils = require("../ast-utils");
const globals = require("globals");
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+
+const propertyDefinitionMethods = new Set(["defineProperty", "defineProperties"]);
+
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
@@ -43,73 +50,123 @@ module.exports = {
create(context) {
const config = context.options[0] || {};
- const exceptions = config.exceptions || [];
- let modifiedBuiltins = Object.keys(globals.builtin).filter(builtin => builtin[0].toUpperCase() === builtin[0]);
+ const exceptions = new Set(config.exceptions || []);
+ const modifiedBuiltins = new Set(
+ Object.keys(globals.builtin)
+ .filter(builtin => builtin[0].toUpperCase() === builtin[0])
+ .filter(builtin => !exceptions.has(builtin))
+ );
+
+ /**
+ * Reports a lint error for the given node.
+ * @param {ASTNode} node The node to report.
+ * @param {string} builtin The name of the native builtin being extended.
+ * @returns {void}
+ */
+ function reportNode(node, builtin) {
+ context.report({
+ node,
+ message: "{{builtin}} prototype is read only, properties should not be added.",
+ data: {
+ builtin
+ }
+ });
+ }
- if (exceptions.length) {
- modifiedBuiltins = modifiedBuiltins.filter(builtIn => exceptions.indexOf(builtIn) === -1);
+ /**
+ * Check to see if the `prototype` property of the given object
+ * identifier node is being accessed.
+ * @param {ASTNode} identifierNode The Identifier representing the object
+ * to check.
+ * @returns {boolean} True if the identifier is the object of a
+ * MemberExpression and its `prototype` property is being accessed,
+ * false otherwise.
+ */
+ function isPrototypePropertyAccessed(identifierNode) {
+ return Boolean(
+ identifierNode &&
+ identifierNode.parent &&
+ identifierNode.parent.type === "MemberExpression" &&
+ identifierNode.parent.object === identifierNode &&
+ astUtils.getStaticPropertyName(identifierNode.parent) === "prototype"
+ );
}
- return {
+ /**
+ * Checks that an identifier is an object of a prototype whose member
+ * is being assigned in an AssignmentExpression.
+ * Example: Object.prototype.foo = "bar"
+ * @param {ASTNode} identifierNode The identifier to check.
+ * @returns {boolean} True if the identifier's prototype is modified.
+ */
+ function isInPrototypePropertyAssignment(identifierNode) {
+ return Boolean(
+ isPrototypePropertyAccessed(identifierNode) &&
+ identifierNode.parent.parent.type === "MemberExpression" &&
+ identifierNode.parent.parent.parent.type === "AssignmentExpression" &&
+ identifierNode.parent.parent.parent.left === identifierNode.parent.parent
+ );
+ }
- // handle the Array.prototype.extra style case
- AssignmentExpression(node) {
- const lhs = node.left;
+ /**
+ * Checks that an identifier is an object of a prototype whose member
+ * is being extended via the Object.defineProperty() or
+ * Object.defineProperties() methods.
+ * Example: Object.defineProperty(Array.prototype, "foo", ...)
+ * Example: Object.defineProperties(Array.prototype, ...)
+ * @param {ASTNode} identifierNode The identifier to check.
+ * @returns {boolean} True if the identifier's prototype is modified.
+ */
+ function isInDefinePropertyCall(identifierNode) {
+ return Boolean(
+ isPrototypePropertyAccessed(identifierNode) &&
+ identifierNode.parent.parent.type === "CallExpression" &&
+ identifierNode.parent.parent.arguments[0] === identifierNode.parent &&
+ identifierNode.parent.parent.callee.type === "MemberExpression" &&
+ identifierNode.parent.parent.callee.object.type === "Identifier" &&
+ identifierNode.parent.parent.callee.object.name === "Object" &&
+ identifierNode.parent.parent.callee.property.type === "Identifier" &&
+ propertyDefinitionMethods.has(identifierNode.parent.parent.callee.property.name)
+ );
+ }
- if (lhs.type !== "MemberExpression" || lhs.object.type !== "MemberExpression") {
- return;
- }
+ /**
+ * Check to see if object prototype access is part of a prototype
+ * extension. There are three ways a prototype can be extended:
+ * 1. Assignment to prototype property (Object.prototype.foo = 1)
+ * 2. Object.defineProperty()/Object.defineProperties() on a prototype
+ * If prototype extension is detected, report the AssignmentExpression
+ * or CallExpression node.
+ * @param {ASTNode} identifierNode The Identifier representing the object
+ * which prototype is being accessed and possibly extended.
+ * @returns {void}
+ */
+ function checkAndReportPrototypeExtension(identifierNode) {
+ if (isInPrototypePropertyAssignment(identifierNode)) {
+
+ // Identifier --> MemberExpression --> MemberExpression --> AssignmentExpression
+ reportNode(identifierNode.parent.parent.parent, identifierNode.name);
+ } else if (isInDefinePropertyCall(identifierNode)) {
+
+ // Identifier --> MemberExpression --> CallExpression
+ reportNode(identifierNode.parent.parent, identifierNode.name);
+ }
+ }
- const affectsProto = lhs.object.computed
- ? lhs.object.property.type === "Literal" && lhs.object.property.value === "prototype"
- : lhs.object.property.name === "prototype";
+ return {
- if (!affectsProto) {
- return;
- }
+ "Program:exit"() {
+ const globalScope = context.getScope();
modifiedBuiltins.forEach(builtin => {
- if (lhs.object.object.name === builtin) {
- context.report({
- node,
- message: "{{builtin}} prototype is read only, properties should not be added.",
- data: {
- builtin
- }
- });
+ const builtinVar = globalScope.set.get(builtin);
+
+ if (builtinVar && builtinVar.references) {
+ builtinVar.references
+ .map(ref => ref.identifier)
+ .forEach(checkAndReportPrototypeExtension);
}
});
- },
-
- // handle the Object.definePropert[y|ies](Array.prototype) case
- CallExpression(node) {
-
- const callee = node.callee;
-
- // only worry about Object.definePropert[y|ies]
- if (callee.type === "MemberExpression" &&
- callee.object.name === "Object" &&
- (callee.property.name === "defineProperty" || callee.property.name === "defineProperties")) {
-
- // verify the object being added to is a native prototype
- const subject = node.arguments[0];
- const object = subject && subject.object;
-
- if (object &&
- object.type === "Identifier" &&
- (modifiedBuiltins.indexOf(object.name) > -1) &&
- subject.property.name === "prototype") {
-
- context.report({
- node,
- message: "{{objectName}} prototype is read only, properties should not be added.",
- data: {
- objectName: object.name
- }
- });
- }
- }
-
}
};
diff --git a/tools/eslint/lib/rules/no-extra-parens.js b/tools/eslint/lib/rules/no-extra-parens.js
index bbfae735c2d27f..d0d79c6a3295d8 100644
--- a/tools/eslint/lib/rules/no-extra-parens.js
+++ b/tools/eslint/lib/rules/no-extra-parens.js
@@ -9,7 +9,6 @@
//------------------------------------------------------------------------------
const astUtils = require("../ast-utils.js");
-const esUtils = require("esutils");
module.exports = {
meta: {
@@ -250,28 +249,27 @@ module.exports = {
const tokenBeforeLeftParen = sourceCode.getTokenBefore(node, 1);
const firstToken = sourceCode.getFirstToken(node);
- // If there is already whitespace before the previous token, don't add more.
- if (!tokenBeforeLeftParen || tokenBeforeLeftParen.end !== leftParenToken.start) {
- return false;
- }
-
- // If the parens are preceded by a keyword (e.g. `typeof(0)`), a space should be inserted (`typeof 0`)
- const precededByIdentiferPart = esUtils.code.isIdentifierPartES6(tokenBeforeLeftParen.value.slice(-1).charCodeAt(0));
-
- // However, a space should not be inserted unless the first character of the token is an identifier part
- // e.g. `typeof([])` should be fixed to `typeof[]`
- const startsWithIdentifierPart = esUtils.code.isIdentifierPartES6(firstToken.value.charCodeAt(0));
-
- // If the parens are preceded by and start with a unary plus/minus (e.g. `+(+foo)`), a space should be inserted (`+ +foo`)
- const precededByUnaryPlus = tokenBeforeLeftParen.type === "Punctuator" && tokenBeforeLeftParen.value === "+";
- const precededByUnaryMinus = tokenBeforeLeftParen.type === "Punctuator" && tokenBeforeLeftParen.value === "-";
-
- const startsWithUnaryPlus = firstToken.type === "Punctuator" && firstToken.value === "+";
- const startsWithUnaryMinus = firstToken.type === "Punctuator" && firstToken.value === "-";
+ return tokenBeforeLeftParen &&
+ tokenBeforeLeftParen.range[1] === leftParenToken.range[0] &&
+ leftParenToken.range[1] === firstToken.range[0] &&
+ !astUtils.canTokensBeAdjacent(tokenBeforeLeftParen, firstToken);
+ }
- return (precededByIdentiferPart && startsWithIdentifierPart) ||
- (precededByUnaryPlus && startsWithUnaryPlus) ||
- (precededByUnaryMinus && startsWithUnaryMinus);
+ /**
+ * Determines whether a node should be followed by an additional space when removing parens
+ * @param {ASTNode} node node to evaluate; must be surrounded by parentheses
+ * @returns {boolean} `true` if a space should be inserted after the node
+ * @private
+ */
+ function requiresTrailingSpace(node) {
+ const nextTwoTokens = sourceCode.getTokensAfter(node, { count: 2 });
+ const rightParenToken = nextTwoTokens[0];
+ const tokenAfterRightParen = nextTwoTokens[1];
+ const tokenBeforeRightParen = sourceCode.getLastToken(node);
+
+ return rightParenToken && tokenAfterRightParen &&
+ !sourceCode.isSpaceBetweenTokens(rightParenToken, tokenAfterRightParen) &&
+ !astUtils.canTokensBeAdjacent(tokenBeforeRightParen, tokenAfterRightParen);
}
/**
@@ -298,7 +296,7 @@ module.exports = {
return fixer.replaceTextRange([
leftParenToken.range[0],
rightParenToken.range[1]
- ], (requiresLeadingSpace(node) ? " " : "") + parenthesizedSource);
+ ], (requiresLeadingSpace(node) ? " " : "") + parenthesizedSource + (requiresTrailingSpace(node) ? " " : ""));
}
});
}
@@ -507,12 +505,18 @@ module.exports = {
if (hasExcessParens(node.right)) {
report(node.right);
}
+ if (hasExcessParens(node.left)) {
+ report(node.left);
+ }
},
ForOfStatement(node) {
if (hasExcessParens(node.right)) {
report(node.right);
}
+ if (hasExcessParens(node.left)) {
+ report(node.left);
+ }
},
ForStatement(node) {
diff --git a/tools/eslint/lib/rules/no-fallthrough.js b/tools/eslint/lib/rules/no-fallthrough.js
index 30d13da06ddc8f..082e8431d63dc6 100644
--- a/tools/eslint/lib/rules/no-fallthrough.js
+++ b/tools/eslint/lib/rules/no-fallthrough.js
@@ -25,7 +25,7 @@ const DEFAULT_FALLTHROUGH_COMMENT = /falls?\s?through/i;
*/
function hasFallthroughComment(node, context, fallthroughCommentPattern) {
const sourceCode = context.getSourceCode();
- const comment = lodash.last(sourceCode.getComments(node).leading);
+ const comment = lodash.last(sourceCode.getCommentsBefore(node));
return Boolean(comment && fallthroughCommentPattern.test(comment.value));
}
diff --git a/tools/eslint/lib/rules/no-floating-decimal.js b/tools/eslint/lib/rules/no-floating-decimal.js
index 7e023050294a8b..dfba453a4984d6 100644
--- a/tools/eslint/lib/rules/no-floating-decimal.js
+++ b/tools/eslint/lib/rules/no-floating-decimal.js
@@ -5,6 +5,12 @@
"use strict";
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const astUtils = require("../ast-utils");
+
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
@@ -23,16 +29,24 @@ module.exports = {
},
create(context) {
+ const sourceCode = context.getSourceCode();
return {
Literal(node) {
if (typeof node.value === "number") {
- if (node.raw.indexOf(".") === 0) {
+ if (node.raw.startsWith(".")) {
context.report({
node,
message: "A leading decimal point can be confused with a dot.",
- fix: fixer => fixer.insertTextBefore(node, "0")
+ fix(fixer) {
+ const tokenBefore = sourceCode.getTokenBefore(node);
+ const needsSpaceBefore = tokenBefore &&
+ tokenBefore.range[1] === node.range[0] &&
+ !astUtils.canTokensBeAdjacent(tokenBefore, `0${node.raw}`);
+
+ return fixer.insertTextBefore(node, needsSpaceBefore ? " 0" : "0");
+ }
});
}
if (node.raw.indexOf(".") === node.raw.length - 1) {
diff --git a/tools/eslint/lib/rules/no-implicit-coercion.js b/tools/eslint/lib/rules/no-implicit-coercion.js
index 387b3dae479597..cec411af75daa1 100644
--- a/tools/eslint/lib/rules/no-implicit-coercion.js
+++ b/tools/eslint/lib/rules/no-implicit-coercion.js
@@ -6,7 +6,6 @@
"use strict";
const astUtils = require("../ast-utils");
-const esUtils = require("esutils");
//------------------------------------------------------------------------------
// Helpers
@@ -215,8 +214,7 @@ module.exports = {
if (
tokenBefore &&
tokenBefore.range[1] === node.range[0] &&
- esUtils.code.isIdentifierPartES6(tokenBefore.value.slice(-1).charCodeAt(0)) &&
- esUtils.code.isIdentifierPartES6(recommendation.charCodeAt(0))
+ !astUtils.canTokensBeAdjacent(tokenBefore, recommendation)
) {
return fixer.replaceText(node, ` ${recommendation}`);
}
diff --git a/tools/eslint/lib/rules/no-inline-comments.js b/tools/eslint/lib/rules/no-inline-comments.js
index 46815d15418f6a..42b4753dfdd713 100644
--- a/tools/eslint/lib/rules/no-inline-comments.js
+++ b/tools/eslint/lib/rules/no-inline-comments.js
@@ -55,10 +55,11 @@ module.exports = {
//--------------------------------------------------------------------------
return {
+ Program() {
+ const comments = sourceCode.getAllComments();
- LineComment: testCodeAroundComment,
- BlockComment: testCodeAroundComment
-
+ comments.filter(token => token.type !== "Shebang").forEach(testCodeAroundComment);
+ }
};
}
};
diff --git a/tools/eslint/lib/rules/no-inner-declarations.js b/tools/eslint/lib/rules/no-inner-declarations.js
index 2a378487fd5b6b..e7d1b004e771fd 100644
--- a/tools/eslint/lib/rules/no-inner-declarations.js
+++ b/tools/eslint/lib/rules/no-inner-declarations.js
@@ -58,16 +58,14 @@ module.exports = {
* @returns {void}
*/
function check(node) {
- const body = nearestBody(node),
+ const body = nearestBody(),
valid = ((body.type === "Program" && body.distance === 1) ||
body.distance === 2);
if (!valid) {
context.report({ node, message: "Move {{type}} declaration to {{body}} root.", data: {
- type: (node.type === "FunctionDeclaration"
- ? "function" : "variable"),
- body: (body.type === "Program"
- ? "program" : "function body")
+ type: (node.type === "FunctionDeclaration" ? "function" : "variable"),
+ body: (body.type === "Program" ? "program" : "function body")
} });
}
}
diff --git a/tools/eslint/lib/rules/no-irregular-whitespace.js b/tools/eslint/lib/rules/no-irregular-whitespace.js
index 3882501a8629d3..cfbdfd1a5ef97b 100644
--- a/tools/eslint/lib/rules/no-irregular-whitespace.js
+++ b/tools/eslint/lib/rules/no-irregular-whitespace.js
@@ -16,8 +16,8 @@ const astUtils = require("../ast-utils");
// Constants
//------------------------------------------------------------------------------
-const ALL_IRREGULARS = /[\f\v\u0085\u00A0\ufeff\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u202f\u205f\u3000\u2028\u2029]/;
-const IRREGULAR_WHITESPACE = /[\f\v\u0085\u00A0\ufeff\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u202f\u205f\u3000]+/mg;
+const ALL_IRREGULARS = /[\f\v\u0085\ufeff\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u202f\u205f\u3000\u2028\u2029]/;
+const IRREGULAR_WHITESPACE = /[\f\v\u0085\ufeff\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u202f\u205f\u3000]+/mg;
const IRREGULAR_LINE_TERMINATORS = /[\u2028\u2029]/mg;
const LINE_BREAK = astUtils.createGlobalLinebreakMatcher();
@@ -60,9 +60,6 @@ module.exports = {
// Module store of errors that we have found
let errors = [];
- // Comment nodes. We accumulate these as we go, so we can be sure to trigger them after the whole `Program` entity is parsed, even for top-of-file comments.
- const commentNodes = [];
-
// Lookup the `skipComments` option, which defaults to `false`.
const options = context.options[0] || {};
const skipComments = !!options.skipComments;
@@ -71,6 +68,7 @@ module.exports = {
const skipTemplates = !!options.skipTemplates;
const sourceCode = context.getSourceCode();
+ const commentNodes = sourceCode.getAllComments();
/**
* Removes errors that occur inside a string node
@@ -188,16 +186,6 @@ module.exports = {
}
}
- /**
- * Stores a comment node (`LineComment` or `BlockComment`) for later stripping of errors within; a necessary deferring of processing to deal with top-of-file comments.
- * @param {ASTNode} node The comment node
- * @returns {void}
- * @private
- */
- function rememberCommentNode(node) {
- commentNodes.push(node);
- }
-
/**
* A no-op function to act as placeholder for comment accumulation when the `skipComments` option is `false`.
* @returns {void}
@@ -220,7 +208,6 @@ module.exports = {
* We can later filter the errors when they are found to be not an
* issue in nodes we don't care about.
*/
-
checkForIrregularWhitespace(node);
checkForIrregularLineTerminators(node);
};
@@ -228,13 +215,10 @@ module.exports = {
nodes.Identifier = removeInvalidNodeErrorsInIdentifierOrLiteral;
nodes.Literal = removeInvalidNodeErrorsInIdentifierOrLiteral;
nodes.TemplateElement = skipTemplates ? removeInvalidNodeErrorsInTemplateLiteral : noop;
- nodes.LineComment = skipComments ? rememberCommentNode : noop;
- nodes.BlockComment = skipComments ? rememberCommentNode : noop;
nodes["Program:exit"] = function() {
-
if (skipComments) {
- // First strip errors occurring in comment nodes. We have to do this post-`Program` to deal with top-of-file comments.
+ // First strip errors occurring in comment nodes.
commentNodes.forEach(removeInvalidNodeErrorsInComment);
}
diff --git a/tools/eslint/lib/rules/no-lone-blocks.js b/tools/eslint/lib/rules/no-lone-blocks.js
index 95a5b334c602a8..652812fba7bfa7 100644
--- a/tools/eslint/lib/rules/no-lone-blocks.js
+++ b/tools/eslint/lib/rules/no-lone-blocks.js
@@ -94,13 +94,13 @@ module.exports = {
ruleDef.VariableDeclaration = function(node) {
if (node.kind === "let" || node.kind === "const") {
- markLoneBlock(node);
+ markLoneBlock();
}
};
- ruleDef.FunctionDeclaration = function(node) {
+ ruleDef.FunctionDeclaration = function() {
if (context.getScope().isStrict) {
- markLoneBlock(node);
+ markLoneBlock();
}
};
diff --git a/tools/eslint/lib/rules/no-loop-func.js b/tools/eslint/lib/rules/no-loop-func.js
index b8bed958652e46..df0f1767894f6f 100644
--- a/tools/eslint/lib/rules/no-loop-func.js
+++ b/tools/eslint/lib/rules/no-loop-func.js
@@ -90,7 +90,7 @@ function getTopLoopNode(node, excludedNode) {
*
* @param {ASTNode} funcNode - A target function node.
* @param {ASTNode} loopNode - A containing loop node.
- * @param {escope.Reference} reference - A reference to check.
+ * @param {eslint-scope.Reference} reference - A reference to check.
* @returns {boolean} `true` if the reference is safe or not.
*/
function isSafe(funcNode, loopNode, reference) {
@@ -131,7 +131,7 @@ function isSafe(funcNode, loopNode, reference) {
* - is readonly.
* - doesn't exist inside a local function and after the border.
*
- * @param {escope.Reference} upperRef - A reference to check.
+ * @param {eslint-scope.Reference} upperRef - A reference to check.
* @returns {boolean} `true` if the reference is safe.
*/
function isSafeReference(upperRef) {
diff --git a/tools/eslint/lib/rules/no-multi-spaces.js b/tools/eslint/lib/rules/no-multi-spaces.js
index 41a7f924a5e9de..30d650c3a0c3b0 100644
--- a/tools/eslint/lib/rules/no-multi-spaces.js
+++ b/tools/eslint/lib/rules/no-multi-spaces.js
@@ -33,6 +33,9 @@ module.exports = {
}
},
additionalProperties: false
+ },
+ ignoreEOLComments: {
+ type: "boolean"
}
},
additionalProperties: false
@@ -43,8 +46,10 @@ module.exports = {
create(context) {
// the index of the last comment that was checked
- const exceptions = { Property: true },
- options = context.options[0];
+ const sourceCode = context.getSourceCode(),
+ exceptions = { Property: true },
+ options = context.options[0] || {},
+ ignoreEOLComments = options.ignoreEOLComments;
let hasExceptions = true,
lastCommentIndex = 0;
@@ -59,6 +64,23 @@ module.exports = {
hasExceptions = Object.keys(exceptions).length > 0;
}
+ /**
+ * Checks if a given token is the last token of the line or not.
+ * @param {Token} token The token to check.
+ * @returns {boolean} Whether or not a token is at the end of the line it occurs in.
+ * @private
+ */
+ function isLastTokenOfLine(token) {
+ const nextToken = sourceCode.getTokenAfter(token, { includeComments: true });
+
+ // nextToken is null if the comment is the last token in the program.
+ if (!nextToken) {
+ return true;
+ }
+
+ return !astUtils.isTokenOnSameLine(token, nextToken);
+ }
+
/**
* Determines if a given source index is in a comment or not by checking
* the index against the comment range. Since the check goes straight
@@ -73,7 +95,7 @@ module.exports = {
while (lastCommentIndex < comments.length) {
const comment = comments[lastCommentIndex];
- if (comment.range[0] <= index && index < comment.range[1]) {
+ if (comment.range[0] < index && index < comment.range[1]) {
return true;
} else if (index > comment.range[1]) {
lastCommentIndex++;
@@ -85,6 +107,33 @@ module.exports = {
return false;
}
+ /**
+ * Formats value of given comment token for error message by truncating its length.
+ * @param {Token} token comment token
+ * @returns {string} formatted value
+ * @private
+ */
+ function formatReportedCommentValue(token) {
+ const valueLines = token.value.split("\n");
+ const value = valueLines[0];
+ const formattedValue = `${value.substring(0, 12)}...`;
+
+ return valueLines.length === 1 && value.length <= 12 ? value : formattedValue;
+ }
+
+ /**
+ * Creates a fix function that removes the multiple spaces between the two tokens
+ * @param {Token} leftToken left token
+ * @param {Token} rightToken right token
+ * @returns {Function} fix function
+ * @private
+ */
+ function createFix(leftToken, rightToken) {
+ return function(fixer) {
+ return fixer.replaceTextRange([leftToken.range[1], rightToken.range[0]], " ");
+ };
+ }
+
//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------
@@ -92,47 +141,43 @@ module.exports = {
return {
Program() {
- const sourceCode = context.getSourceCode(),
- source = sourceCode.getText(),
+ const source = sourceCode.getText(),
allComments = sourceCode.getAllComments(),
- JOINED_LINEBEAKS = Array.from(astUtils.LINEBREAKS).join(""),
- pattern = new RegExp(String.raw`[^ \t${JOINED_LINEBEAKS}].? {2,}`, "g"); // note: repeating space
+ pattern = /[^\s].*? {2,}/g;
let parent;
-
- /**
- * Creates a fix function that removes the multiple spaces between the two tokens
- * @param {RuleFixer} leftToken left token
- * @param {RuleFixer} rightToken right token
- * @returns {Function} fix function
- * @private
- */
- function createFix(leftToken, rightToken) {
- return function(fixer) {
- return fixer.replaceTextRange([leftToken.range[1], rightToken.range[0]], " ");
- };
- }
-
while (pattern.test(source)) {
// do not flag anything inside of comments
if (!isIndexInComment(pattern.lastIndex, allComments)) {
- const token = sourceCode.getTokenByRangeStart(pattern.lastIndex);
+ const token = sourceCode.getTokenByRangeStart(pattern.lastIndex, { includeComments: true });
if (token) {
- const previousToken = sourceCode.getTokenBefore(token);
+ if (ignoreEOLComments && astUtils.isCommentToken(token) && isLastTokenOfLine(token)) {
+ return;
+ }
+
+ const previousToken = sourceCode.getTokenBefore(token, { includeComments: true });
if (hasExceptions) {
parent = sourceCode.getNodeByRangeIndex(pattern.lastIndex - 1);
}
if (!parent || !exceptions[parent.type]) {
+ let value = token.value;
+
+ if (token.type === "Block") {
+ value = `/*${formatReportedCommentValue(token)}*/`;
+ } else if (token.type === "Line") {
+ value = `//${formatReportedCommentValue(token)}`;
+ }
+
context.report({
node: token,
loc: token.loc.start,
message: "Multiple spaces found before '{{value}}'.",
- data: { value: token.value },
+ data: { value },
fix: createFix(previousToken, token)
});
}
diff --git a/tools/eslint/lib/rules/no-multiple-empty-lines.js b/tools/eslint/lib/rules/no-multiple-empty-lines.js
index 2063ebd917c79e..9d1067c205dd0a 100644
--- a/tools/eslint/lib/rules/no-multiple-empty-lines.js
+++ b/tools/eslint/lib/rules/no-multiple-empty-lines.js
@@ -111,10 +111,19 @@ module.exports = {
message,
data: { max: maxAllowed, pluralizedLines: maxAllowed === 1 ? "line" : "lines" },
fix(fixer) {
- return fixer.removeRange([
- sourceCode.getIndexFromLoc({ line: lastLineNumber + 1, column: 0 }),
- sourceCode.getIndexFromLoc({ line: lineNumber - maxAllowed, column: 0 })
- ]);
+ const rangeStart = sourceCode.getIndexFromLoc({ line: lastLineNumber + 1, column: 0 });
+
+ /*
+ * The end of the removal range is usually the start index of the next line.
+ * However, at the end of the file there is no next line, so the end of the
+ * range is just the length of the text.
+ */
+ const lineNumberAfterRemovedLines = lineNumber - maxAllowed;
+ const rangeEnd = lineNumberAfterRemovedLines <= allLines.length
+ ? sourceCode.getIndexFromLoc({ line: lineNumberAfterRemovedLines, column: 0 })
+ : sourceCode.text.length;
+
+ return fixer.removeRange([rangeStart, rangeEnd]);
}
});
}
diff --git a/tools/eslint/lib/rules/no-redeclare.js b/tools/eslint/lib/rules/no-redeclare.js
index bfbc09ffb6f324..ccb57003ed628b 100644
--- a/tools/eslint/lib/rules/no-redeclare.js
+++ b/tools/eslint/lib/rules/no-redeclare.js
@@ -35,7 +35,7 @@ module.exports = {
/**
* Find variables in a given scope and flag redeclared ones.
- * @param {Scope} scope - An escope scope object.
+ * @param {Scope} scope - An eslint-scope scope object.
* @returns {void}
* @private
*/
diff --git a/tools/eslint/lib/rules/no-self-compare.js b/tools/eslint/lib/rules/no-self-compare.js
index 54f907f594be06..5beaa181b99022 100644
--- a/tools/eslint/lib/rules/no-self-compare.js
+++ b/tools/eslint/lib/rules/no-self-compare.js
@@ -22,15 +22,28 @@ module.exports = {
},
create(context) {
+ const sourceCode = context.getSourceCode();
+
+ /**
+ * Determines whether two nodes are composed of the same tokens.
+ * @param {ASTNode} nodeA The first node
+ * @param {ASTNode} nodeB The second node
+ * @returns {boolean} true if the nodes have identical token representations
+ */
+ function hasSameTokens(nodeA, nodeB) {
+ const tokensA = sourceCode.getTokens(nodeA);
+ const tokensB = sourceCode.getTokens(nodeB);
+
+ return tokensA.length === tokensB.length &&
+ tokensA.every((token, index) => token.type === tokensB[index].type && token.value === tokensB[index].value);
+ }
return {
BinaryExpression(node) {
- const operators = ["===", "==", "!==", "!=", ">", "<", ">=", "<="];
+ const operators = new Set(["===", "==", "!==", "!=", ">", "<", ">=", "<="]);
- if (operators.indexOf(node.operator) > -1 &&
- (node.left.type === "Identifier" && node.right.type === "Identifier" && node.left.name === node.right.name ||
- node.left.type === "Literal" && node.right.type === "Literal" && node.left.value === node.right.value)) {
+ if (operators.has(node.operator) && hasSameTokens(node.left, node.right)) {
context.report({ node, message: "Comparing to itself is potentially pointless." });
}
}
diff --git a/tools/eslint/lib/rules/no-this-before-super.js b/tools/eslint/lib/rules/no-this-before-super.js
index c8d5dc4698d7b0..2a686ac72e9dd1 100644
--- a/tools/eslint/lib/rules/no-this-before-super.js
+++ b/tools/eslint/lib/rules/no-this-before-super.js
@@ -89,7 +89,7 @@ module.exports = {
*/
function isBeforeCallOfSuper() {
return (
- isInConstructorOfDerivedClass(funcInfo) &&
+ isInConstructorOfDerivedClass() &&
!funcInfo.codePath.currentSegments.every(isCalled)
);
}
@@ -206,7 +206,7 @@ module.exports = {
* @returns {void}
*/
onCodePathSegmentStart(segment) {
- if (!isInConstructorOfDerivedClass(funcInfo)) {
+ if (!isInConstructorOfDerivedClass()) {
return;
}
@@ -230,7 +230,7 @@ module.exports = {
* @returns {void}
*/
onCodePathSegmentLoop(fromSegment, toSegment) {
- if (!isInConstructorOfDerivedClass(funcInfo)) {
+ if (!isInConstructorOfDerivedClass()) {
return;
}
diff --git a/tools/eslint/lib/rules/no-undefined.js b/tools/eslint/lib/rules/no-undefined.js
index d29ac1e720f2c6..7e9f96b921855a 100644
--- a/tools/eslint/lib/rules/no-undefined.js
+++ b/tools/eslint/lib/rules/no-undefined.js
@@ -36,7 +36,7 @@ module.exports = {
/**
* Checks the given scope for references to `undefined` and reports
* all references found.
- * @param {escope.Scope} scope The scope to check.
+ * @param {eslint-scope.Scope} scope The scope to check.
* @returns {void}
*/
function checkScope(scope) {
diff --git a/tools/eslint/lib/rules/no-unexpected-multiline.js b/tools/eslint/lib/rules/no-unexpected-multiline.js
index 6c15f5dd591e31..9398b8a6036bc3 100644
--- a/tools/eslint/lib/rules/no-unexpected-multiline.js
+++ b/tools/eslint/lib/rules/no-unexpected-multiline.js
@@ -30,6 +30,9 @@ module.exports = {
const FUNCTION_MESSAGE = "Unexpected newline between function and ( of function call.";
const PROPERTY_MESSAGE = "Unexpected newline between object and [ of property access.";
const TAGGED_TEMPLATE_MESSAGE = "Unexpected newline between template tag and template literal.";
+ const DIVISION_MESSAGE = "Unexpected newline between numerator and division operator.";
+
+ const REGEX_FLAG_MATCHER = /^[gimuy]+$/;
const sourceCode = context.getSourceCode();
@@ -75,6 +78,19 @@ module.exports = {
return;
}
checkForBreakAfter(node.callee, FUNCTION_MESSAGE);
+ },
+
+ "BinaryExpression[operator='/'] > BinaryExpression[operator='/'].left"(node) {
+ const secondSlash = sourceCode.getTokenAfter(node, token => token.value === "/");
+ const tokenAfterOperator = sourceCode.getTokenAfter(secondSlash);
+
+ if (
+ tokenAfterOperator.type === "Identifier" &&
+ REGEX_FLAG_MATCHER.test(tokenAfterOperator.value) &&
+ secondSlash.range[1] === tokenAfterOperator.range[0]
+ ) {
+ checkForBreakAfter(node.left, DIVISION_MESSAGE);
+ }
}
};
diff --git a/tools/eslint/lib/rules/no-unmodified-loop-condition.js b/tools/eslint/lib/rules/no-unmodified-loop-condition.js
index 8243611913a1e8..dbf35baeddf348 100644
--- a/tools/eslint/lib/rules/no-unmodified-loop-condition.js
+++ b/tools/eslint/lib/rules/no-unmodified-loop-condition.js
@@ -18,14 +18,14 @@ const Traverser = require("../util/traverser"),
const pushAll = Function.apply.bind(Array.prototype.push);
const SENTINEL_PATTERN = /(?:(?:Call|Class|Function|Member|New|Yield)Expression|Statement|Declaration)$/;
-const LOOP_PATTERN = /^(?:DoWhile|For|While)Statement$/; // for-in/of statements don't have `test` property.
+const LOOP_PATTERN = /^(?:DoWhile|For|While)Statement$/; // for-in/of statements don't have `test` property.
const GROUP_PATTERN = /^(?:BinaryExpression|ConditionalExpression)$/;
const SKIP_PATTERN = /^(?:ArrowFunction|Class|Function)Expression$/;
const DYNAMIC_PATTERN = /^(?:Call|Member|New|TaggedTemplate|Yield)Expression$/;
/**
* @typedef {Object} LoopConditionInfo
- * @property {escope.Reference} reference - The reference.
+ * @property {eslint-scope.Reference} reference - The reference.
* @property {ASTNode} group - BinaryExpression or ConditionalExpression nodes
* that the reference is belonging to.
* @property {Function} isInLoop - The predicate which checks a given reference
@@ -37,7 +37,7 @@ const DYNAMIC_PATTERN = /^(?:Call|Member|New|TaggedTemplate|Yield)Expression$/;
/**
* Checks whether or not a given reference is a write reference.
*
- * @param {escope.Reference} reference - A reference to check.
+ * @param {eslint-scope.Reference} reference - A reference to check.
* @returns {boolean} `true` if the reference is a write reference.
*/
function isWriteReference(reference) {
@@ -77,7 +77,7 @@ function isUnmodifiedAndNotBelongToGroup(condition) {
* Checks whether or not a given reference is inside of a given node.
*
* @param {ASTNode} node - A node to check.
- * @param {escope.Reference} reference - A reference to check.
+ * @param {eslint-scope.Reference} reference - A reference to check.
* @returns {boolean} `true` if the reference is inside of the node.
*/
function isInRange(node, reference) {
@@ -91,7 +91,7 @@ function isInRange(node, reference) {
* Checks whether or not a given reference is inside of a loop node's condition.
*
* @param {ASTNode} node - A node to check.
- * @param {escope.Reference} reference - A reference to check.
+ * @param {eslint-scope.Reference} reference - A reference to check.
* @returns {boolean} `true` if the reference is inside of the loop node's
* condition.
*/
@@ -134,7 +134,7 @@ function hasDynamicExpressions(root) {
/**
* Creates the loop condition information from a given reference.
*
- * @param {escope.Reference} reference - A reference to create.
+ * @param {eslint-scope.Reference} reference - A reference to create.
* @returns {LoopConditionInfo|null} Created loop condition info, or null.
*/
function toLoopCondition(reference) {
@@ -188,7 +188,7 @@ function toLoopCondition(reference) {
* Gets the function which encloses a given reference.
* This supports only FunctionDeclaration.
*
- * @param {escope.Reference} reference - A reference to get.
+ * @param {eslint-scope.Reference} reference - A reference to get.
* @returns {ASTNode|null} The function node or null.
*/
function getEncloseFunctionDeclaration(reference) {
@@ -209,7 +209,7 @@ function getEncloseFunctionDeclaration(reference) {
* Updates the "modified" flags of given loop conditions with given modifiers.
*
* @param {LoopConditionInfo[]} conditions - The loop conditions to be updated.
- * @param {escope.Reference[]} modifiers - The references to update.
+ * @param {eslint-scope.Reference[]} modifiers - The references to update.
* @returns {void}
*/
function updateModifiedFlag(conditions, modifiers) {
@@ -311,7 +311,7 @@ module.exports = {
* Finds unmodified references which are inside of a loop condition.
* Then reports the references which are outside of groups.
*
- * @param {escope.Variable} variable - A variable to report.
+ * @param {eslint-scope.Variable} variable - A variable to report.
* @returns {void}
*/
function checkReferences(variable) {
diff --git a/tools/eslint/lib/rules/no-unneeded-ternary.js b/tools/eslint/lib/rules/no-unneeded-ternary.js
index b031927f9248cb..929991f86bb843 100644
--- a/tools/eslint/lib/rules/no-unneeded-ternary.js
+++ b/tools/eslint/lib/rules/no-unneeded-ternary.js
@@ -134,7 +134,17 @@ module.exports = {
node,
loc: node.consequent.loc.start,
message: "Unnecessary use of conditional expression for default assignment.",
- fix: fixer => fixer.replaceText(node, `${astUtils.getParenthesisedText(sourceCode, node.test)} || ${astUtils.getParenthesisedText(sourceCode, node.alternate)}`)
+ fix: fixer => {
+ let nodeAlternate = astUtils.getParenthesisedText(sourceCode, node.alternate);
+
+ if (node.alternate.type === "ConditionalExpression") {
+ const isAlternateParenthesised = astUtils.isParenthesised(sourceCode, node.alternate);
+
+ nodeAlternate = isAlternateParenthesised ? nodeAlternate : `(${nodeAlternate})`;
+ }
+
+ return fixer.replaceText(node, `${astUtils.getParenthesisedText(sourceCode, node.test)} || ${nodeAlternate}`);
+ }
});
}
}
diff --git a/tools/eslint/lib/rules/no-unused-vars.js b/tools/eslint/lib/rules/no-unused-vars.js
index 6f270396739c8a..3ed278d54dcd9e 100644
--- a/tools/eslint/lib/rules/no-unused-vars.js
+++ b/tools/eslint/lib/rules/no-unused-vars.js
@@ -108,7 +108,7 @@ module.exports = {
/**
* Determines if a given variable is being exported from a module.
- * @param {Variable} variable - EScope variable object.
+ * @param {Variable} variable - eslint-scope variable object.
* @returns {boolean} True if the variable is exported, false if not.
* @private
*/
@@ -134,7 +134,7 @@ module.exports = {
/**
* Determines if a variable has a sibling rest property
- * @param {Variable} variable - EScope variable object.
+ * @param {Variable} variable - eslint-scope variable object.
* @returns {boolean} True if the variable is exported, false if not.
* @private
*/
@@ -157,7 +157,7 @@ module.exports = {
/**
* Determines if a reference is a read operation.
- * @param {Reference} ref - An escope Reference
+ * @param {Reference} ref - An eslint-scope Reference
* @returns {boolean} whether the given reference represents a read operation
* @private
*/
@@ -212,7 +212,7 @@ module.exports = {
* - The reference is inside of a function scope which is different from
* the declaration.
*
- * @param {escope.Reference} ref - A reference to check.
+ * @param {eslint-scope.Reference} ref - A reference to check.
* @param {ASTNode} prevRhsNode - The previous RHS node.
* @returns {ASTNode|null} The RHS node or null.
* @private
@@ -322,7 +322,7 @@ module.exports = {
/**
* Checks whether a given reference is a read to update itself or not.
*
- * @param {escope.Reference} ref - A reference to check.
+ * @param {eslint-scope.Reference} ref - A reference to check.
* @param {ASTNode} rhsNode - The RHS node of the previous assignment.
* @returns {boolean} The reference is a read to update itself.
* @private
@@ -422,7 +422,7 @@ module.exports = {
/**
* Checks whether the given variable is the last parameter in the non-ignored parameters.
*
- * @param {escope.Variable} variable - The variable to check.
+ * @param {eslint-scope.Variable} variable - The variable to check.
* @returns {boolean} `true` if the variable is the last.
*/
function isLastInNonIgnoredParameters(variable) {
@@ -448,7 +448,7 @@ module.exports = {
/**
* Gets an array of variables without read references.
- * @param {Scope} scope - an escope Scope object.
+ * @param {Scope} scope - an eslint-scope Scope object.
* @param {Variable[]} unusedVars - an array that saving result.
* @returns {Variable[]} unused variables of the scope and descendant scopes.
* @private
@@ -513,7 +513,7 @@ module.exports = {
}
// if "args" option is "after-used", skip all but the last parameter
- if (config.args === "after-used" && !isLastInNonIgnoredParameters(variable)) {
+ if (config.args === "after-used" && astUtils.isFunction(def.name.parent) && !isLastInNonIgnoredParameters(variable)) {
continue;
}
} else {
@@ -540,7 +540,7 @@ module.exports = {
/**
* Gets the index of a given variable name in a given comment.
- * @param {escope.Variable} variable - A variable to get.
+ * @param {eslint-scope.Variable} variable - A variable to get.
* @param {ASTNode} comment - A comment node which includes the variable name.
* @returns {number} The index of the variable name's location.
* @private
@@ -561,7 +561,7 @@ module.exports = {
* Creates the correct location of a given variables.
* The location is at its name string in a `/*global` comment.
*
- * @param {escope.Variable} variable - A variable to get its location.
+ * @param {eslint-scope.Variable} variable - A variable to get its location.
* @returns {{line: number, column: number}} The location object for the variable.
* @private
*/
diff --git a/tools/eslint/lib/rules/no-use-before-define.js b/tools/eslint/lib/rules/no-use-before-define.js
index 1a779b86f2318e..bdff23934c21fd 100644
--- a/tools/eslint/lib/rules/no-use-before-define.js
+++ b/tools/eslint/lib/rules/no-use-before-define.js
@@ -37,7 +37,7 @@ function parseOptions(options) {
/**
* Checks whether or not a given variable is a function declaration.
*
- * @param {escope.Variable} variable - A variable to check.
+ * @param {eslint-scope.Variable} variable - A variable to check.
* @returns {boolean} `true` if the variable is a function declaration.
*/
function isFunction(variable) {
@@ -47,8 +47,8 @@ function isFunction(variable) {
/**
* Checks whether or not a given variable is a class declaration in an upper function scope.
*
- * @param {escope.Variable} variable - A variable to check.
- * @param {escope.Reference} reference - A reference to check.
+ * @param {eslint-scope.Variable} variable - A variable to check.
+ * @param {eslint-scope.Reference} reference - A reference to check.
* @returns {boolean} `true` if the variable is a class declaration.
*/
function isOuterClass(variable, reference) {
@@ -60,8 +60,8 @@ function isOuterClass(variable, reference) {
/**
* Checks whether or not a given variable is a variable declaration in an upper function scope.
-* @param {escope.Variable} variable - A variable to check.
-* @param {escope.Reference} reference - A reference to check.
+* @param {eslint-scope.Variable} variable - A variable to check.
+* @param {eslint-scope.Reference} reference - A reference to check.
* @returns {boolean} `true` if the variable is a variable declaration.
*/
function isOuterVariable(variable, reference) {
@@ -167,8 +167,8 @@ module.exports = {
/**
* Determines whether a given use-before-define case should be reported according to the options.
- * @param {escope.Variable} variable The variable that gets used before being defined
- * @param {escope.Reference} reference The reference to the variable
+ * @param {eslint-scope.Variable} variable The variable that gets used before being defined
+ * @param {eslint-scope.Reference} reference The reference to the variable
* @returns {boolean} `true` if the usage should be reported
*/
function isForbidden(variable, reference) {
@@ -250,7 +250,7 @@ module.exports = {
ruleDefinition["ArrowFunctionExpression:exit"] = function(node) {
if (node.body.type !== "BlockStatement") {
- findVariables(node);
+ findVariables();
}
};
} else {
diff --git a/tools/eslint/lib/rules/no-useless-computed-key.js b/tools/eslint/lib/rules/no-useless-computed-key.js
index fd5ec2c92b5c5c..23de2f3734a0b7 100644
--- a/tools/eslint/lib/rules/no-useless-computed-key.js
+++ b/tools/eslint/lib/rules/no-useless-computed-key.js
@@ -9,7 +9,6 @@
//------------------------------------------------------------------------------
const astUtils = require("../ast-utils");
-const esUtils = require("esutils");
//------------------------------------------------------------------------------
// Rule Definition
@@ -61,8 +60,7 @@ module.exports = {
// Insert a space before the key to avoid changing identifiers, e.g. ({ get[2]() {} }) to ({ get2() {} })
const needsSpaceBeforeKey = tokenBeforeLeftBracket.range[1] === leftSquareBracket.range[0] &&
- esUtils.code.isIdentifierPartES6(tokenBeforeLeftBracket.value.slice(-1).charCodeAt(0)) &&
- esUtils.code.isIdentifierPartES6(key.raw.charCodeAt(0));
+ !astUtils.canTokensBeAdjacent(tokenBeforeLeftBracket, sourceCode.getFirstToken(key));
const replacementKey = (needsSpaceBeforeKey ? " " : "") + key.raw;
diff --git a/tools/eslint/lib/rules/no-useless-escape.js b/tools/eslint/lib/rules/no-useless-escape.js
index ffe11999707ce2..0212bd60e3bdac 100644
--- a/tools/eslint/lib/rules/no-useless-escape.js
+++ b/tools/eslint/lib/rules/no-useless-escape.js
@@ -75,7 +75,7 @@ module.exports = {
docs: {
description: "disallow unnecessary escape characters",
category: "Best Practices",
- recommended: false
+ recommended: true
},
schema: []
diff --git a/tools/eslint/lib/rules/no-var.js b/tools/eslint/lib/rules/no-var.js
index 86373ad5009eda..c74e0b9ad9f6df 100644
--- a/tools/eslint/lib/rules/no-var.js
+++ b/tools/eslint/lib/rules/no-var.js
@@ -19,8 +19,8 @@ const astUtils = require("../ast-utils");
* Finds the nearest function scope or global scope walking up the scope
* hierarchy.
*
- * @param {escope.Scope} scope - The scope to traverse.
- * @returns {escope.Scope} a function scope or global scope containing the given
+ * @param {eslint-scope.Scope} scope - The scope to traverse.
+ * @returns {eslint-scope.Scope} a function scope or global scope containing the given
* scope.
*/
function getEnclosingFunctionScope(scope) {
@@ -34,7 +34,7 @@ function getEnclosingFunctionScope(scope) {
* Checks whether the given variable has any references from a more specific
* function expression (i.e. a closure).
*
- * @param {escope.Variable} variable - A variable to check.
+ * @param {eslint-scope.Variable} variable - A variable to check.
* @returns {boolean} `true` if the variable is used from a closure.
*/
function isReferencedInClosure(variable) {
@@ -93,7 +93,7 @@ function getScopeNode(node) {
/**
* Checks whether a given variable is redeclared or not.
*
- * @param {escope.Variable} variable - A variable to check.
+ * @param {eslint-scope.Variable} variable - A variable to check.
* @returns {boolean} `true` if the variable is redeclared.
*/
function isRedeclared(variable) {
@@ -112,7 +112,7 @@ function isUsedFromOutsideOf(scopeNode) {
/**
* Checks whether a given reference is inside of the specified scope or not.
*
- * @param {escope.Reference} reference - A reference to check.
+ * @param {eslint-scope.Reference} reference - A reference to check.
* @returns {boolean} `true` if the reference is inside of the specified
* scope.
*/
diff --git a/tools/eslint/lib/rules/no-warning-comments.js b/tools/eslint/lib/rules/no-warning-comments.js
index bda43086865a1c..c0ecaca9e7dff4 100644
--- a/tools/eslint/lib/rules/no-warning-comments.js
+++ b/tools/eslint/lib/rules/no-warning-comments.js
@@ -40,7 +40,8 @@ module.exports = {
create(context) {
- const configuration = context.options[0] || {},
+ const sourceCode = context.getSourceCode(),
+ configuration = context.options[0] || {},
warningTerms = configuration.terms || ["todo", "fixme", "xxx"],
location = configuration.location || "start",
selfConfigRegEx = /\bno-warning-comments\b/;
@@ -128,8 +129,11 @@ module.exports = {
}
return {
- BlockComment: checkComment,
- LineComment: checkComment
+ Program() {
+ const comments = sourceCode.getAllComments();
+
+ comments.filter(token => token.type !== "Shebang").forEach(checkComment);
+ }
};
}
};
diff --git a/tools/eslint/lib/rules/object-curly-newline.js b/tools/eslint/lib/rules/object-curly-newline.js
index a4451154dfb148..b78cb9cfce4979 100644
--- a/tools/eslint/lib/rules/object-curly-newline.js
+++ b/tools/eslint/lib/rules/object-curly-newline.js
@@ -30,6 +30,9 @@ const OPTION_VALUE = {
minProperties: {
type: "integer",
minimum: 0
+ },
+ consistent: {
+ type: "boolean"
}
},
additionalProperties: false,
@@ -42,11 +45,12 @@ const OPTION_VALUE = {
* Normalizes a given option value.
*
* @param {string|Object|undefined} value - An option value to parse.
- * @returns {{multiline: boolean, minProperties: number}} Normalized option object.
+ * @returns {{multiline: boolean, minProperties: number, consistent: boolean}} Normalized option object.
*/
function normalizeOptionValue(value) {
let multiline = false;
let minProperties = Number.POSITIVE_INFINITY;
+ let consistent = false;
if (value) {
if (value === "always") {
@@ -56,12 +60,13 @@ function normalizeOptionValue(value) {
} else {
multiline = Boolean(value.multiline);
minProperties = value.minProperties || Number.POSITIVE_INFINITY;
+ consistent = Boolean(value.consistent);
}
} else {
multiline = true;
}
- return { multiline, minProperties };
+ return { multiline, minProperties, consistent };
}
/**
@@ -172,7 +177,14 @@ module.exports = {
});
}
} else {
- if (!astUtils.isTokenOnSameLine(openBrace, first)) {
+ const consistent = options.consistent;
+ const hasLineBreakBetweenOpenBraceAndFirst = !astUtils.isTokenOnSameLine(openBrace, first);
+ const hasLineBreakBetweenCloseBraceAndLast = !astUtils.isTokenOnSameLine(last, closeBrace);
+
+ if (
+ (!consistent && hasLineBreakBetweenOpenBraceAndFirst) ||
+ (consistent && hasLineBreakBetweenOpenBraceAndFirst && !hasLineBreakBetweenCloseBraceAndLast)
+ ) {
context.report({
message: "Unexpected line break after this opening brace.",
node,
@@ -185,7 +197,10 @@ module.exports = {
}
});
}
- if (!astUtils.isTokenOnSameLine(last, closeBrace)) {
+ if (
+ (!consistent && hasLineBreakBetweenCloseBraceAndLast) ||
+ (consistent && !hasLineBreakBetweenOpenBraceAndFirst && hasLineBreakBetweenCloseBraceAndLast)
+ ) {
context.report({
message: "Unexpected line break before this closing brace.",
node,
diff --git a/tools/eslint/lib/rules/object-shorthand.js b/tools/eslint/lib/rules/object-shorthand.js
index 1d3d9dae195ddb..2f7b0ccf90489f 100644
--- a/tools/eslint/lib/rules/object-shorthand.js
+++ b/tools/eslint/lib/rules/object-shorthand.js
@@ -392,7 +392,7 @@ module.exports = {
});
}
} else if (APPLY_TO_METHODS && !node.value.id && (node.value.type === "FunctionExpression" || node.value.type === "ArrowFunctionExpression")) {
- if (IGNORE_CONSTRUCTORS && isConstructor(node.key.name)) {
+ if (IGNORE_CONSTRUCTORS && node.key.type === "Identifier" && isConstructor(node.key.name)) {
return;
}
if (AVOID_QUOTES && isStringLiteral(node.key)) {
diff --git a/tools/eslint/lib/rules/padded-blocks.js b/tools/eslint/lib/rules/padded-blocks.js
index 36036aec4d95df..a485c1770ddcdb 100644
--- a/tools/eslint/lib/rules/padded-blocks.js
+++ b/tools/eslint/lib/rules/padded-blocks.js
@@ -51,7 +51,11 @@ module.exports = {
const config = context.options[0] || "always";
if (typeof config === "string") {
- options.blocks = config === "always";
+ const shouldHavePadding = config === "always";
+
+ options.blocks = shouldHavePadding;
+ options.switches = shouldHavePadding;
+ options.classes = shouldHavePadding;
} else {
if (config.hasOwnProperty("blocks")) {
options.blocks = config.blocks === "always";
diff --git a/tools/eslint/lib/rules/padding-line-between-statements.js b/tools/eslint/lib/rules/padding-line-between-statements.js
new file mode 100644
index 00000000000000..707cf33d85cff7
--- /dev/null
+++ b/tools/eslint/lib/rules/padding-line-between-statements.js
@@ -0,0 +1,587 @@
+/**
+ * @fileoverview Rule to require or disallow newlines between statements
+ * @author Toru Nagashima
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const astUtils = require("../ast-utils");
+
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+
+const LT = `[${Array.from(astUtils.LINEBREAKS).join("")}]`;
+const PADDING_LINE_SEQUENCE = new RegExp(
+ String.raw`^(\s*?${LT})\s*${LT}(\s*;?)$`
+);
+const CJS_EXPORT = /^(?:module\s*\.\s*)?exports(?:\s*\.|\s*\[|$)/;
+const CJS_IMPORT = /^require\(/;
+
+/**
+ * Creates tester which check if a node starts with specific keyword.
+ *
+ * @param {string} keyword The keyword to test.
+ * @returns {Object} the created tester.
+ * @private
+ */
+function newKeywordTester(keyword) {
+ return {
+ test: (node, sourceCode) =>
+ sourceCode.getFirstToken(node).value === keyword
+ };
+}
+
+/**
+ * Creates tester which check if a node is specific type.
+ *
+ * @param {string} type The node type to test.
+ * @returns {Object} the created tester.
+ * @private
+ */
+function newNodeTypeTester(type) {
+ return {
+ test: node =>
+ node.type === type
+ };
+}
+
+/**
+ * Checks the given node is an expression statement of IIFE.
+ *
+ * @param {ASTNode} node The node to check.
+ * @returns {boolean} `true` if the node is an expression statement of IIFE.
+ * @private
+ */
+function isIIFEStatement(node) {
+ if (node.type === "ExpressionStatement") {
+ let call = node.expression;
+
+ if (call.type === "UnaryExpression") {
+ call = call.argument;
+ }
+ return call.type === "CallExpression" && astUtils.isFunction(call.callee);
+ }
+ return false;
+}
+
+/**
+ * Checks whether the given node is a block-like statement.
+ * This checks the last token of the node is the closing brace of a block.
+ *
+ * @param {SourceCode} sourceCode The source code to get tokens.
+ * @param {ASTNode} node The node to check.
+ * @returns {boolean} `true` if the node is a block-like statement.
+ * @private
+ */
+function isBlockLikeStatement(sourceCode, node) {
+
+ // do-while with a block is a block-like statement.
+ if (node.type === "DoWhileStatement" && node.body.type === "BlockStatement") {
+ return true;
+ }
+
+ // IIFE is a block-like statement specially from
+ // JSCS#disallowPaddingNewLinesAfterBlocks.
+ if (isIIFEStatement(node)) {
+ return true;
+ }
+
+ // Checks the last token is a closing brace of blocks.
+ const lastToken = sourceCode.getLastToken(node, astUtils.isNotSemicolonToken);
+ const belongingNode = astUtils.isClosingBraceToken(lastToken)
+ ? sourceCode.getNodeByRangeIndex(lastToken.range[0])
+ : null;
+
+ return Boolean(belongingNode) && (
+ belongingNode.type === "BlockStatement" ||
+ belongingNode.type === "SwitchStatement"
+ );
+}
+
+/**
+ * Check whether the given node is a directive or not.
+ * @param {ASTNode} node The node to check.
+ * @param {SourceCode} sourceCode The source code object to get tokens.
+ * @returns {boolean} `true` if the node is a directive.
+ */
+function isDirective(node, sourceCode) {
+ return (
+ node.type === "ExpressionStatement" &&
+ (
+ node.parent.type === "Program" ||
+ (
+ node.parent.type === "BlockStatement" &&
+ astUtils.isFunction(node.parent.parent)
+ )
+ ) &&
+ node.expression.type === "Literal" &&
+ typeof node.expression.value === "string" &&
+ !astUtils.isParenthesised(sourceCode, node.expression)
+ );
+}
+
+/**
+ * Check whether the given node is a part of directive prologue or not.
+ * @param {ASTNode} node The node to check.
+ * @param {SourceCode} sourceCode The source code object to get tokens.
+ * @returns {boolean} `true` if the node is a part of directive prologue.
+ */
+function isDirectivePrologue(node, sourceCode) {
+ if (isDirective(node, sourceCode)) {
+ for (const sibling of node.parent.body) {
+ if (sibling === node) {
+ break;
+ }
+ if (!isDirective(sibling, sourceCode)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+/**
+ * Gets the actual last token.
+ *
+ * If a semicolon is semicolon-less style's semicolon, this ignores it.
+ * For example:
+ *
+ * foo()
+ * ;[1, 2, 3].forEach(bar)
+ *
+ * @param {SourceCode} sourceCode The source code to get tokens.
+ * @param {ASTNode} node The node to get.
+ * @returns {Token} The actual last token.
+ * @private
+ */
+function getActualLastToken(sourceCode, node) {
+ const semiToken = sourceCode.getLastToken(node);
+ const prevToken = sourceCode.getTokenBefore(semiToken);
+ const nextToken = sourceCode.getTokenAfter(semiToken);
+ const isSemicolonLessStyle = Boolean(
+ prevToken &&
+ nextToken &&
+ prevToken.range[0] >= node.range[0] &&
+ astUtils.isSemicolonToken(semiToken) &&
+ semiToken.loc.start.line !== prevToken.loc.end.line &&
+ semiToken.loc.end.line === nextToken.loc.start.line
+ );
+
+ return isSemicolonLessStyle ? prevToken : semiToken;
+}
+
+/**
+ * This returns the concatenation of the first 2 captured strings.
+ * @param {string} _ Unused. Whole matched string.
+ * @param {string} trailingSpaces The trailing spaces of the first line.
+ * @param {string} indentSpaces The indentation spaces of the last line.
+ * @returns {string} The concatenation of trailingSpaces and indentSpaces.
+ * @private
+ */
+function replacerToRemovePaddingLines(_, trailingSpaces, indentSpaces) {
+ return trailingSpaces + indentSpaces;
+}
+
+/**
+ * Check and report statements for `any` configuration.
+ * It does nothing.
+ *
+ * @returns {void}
+ * @private
+ */
+function verifyForAny() {
+}
+
+/**
+ * Check and report statements for `never` configuration.
+ * This autofix removes blank lines between the given 2 statements.
+ * However, if comments exist between 2 blank lines, it does not remove those
+ * blank lines automatically.
+ *
+ * @param {RuleContext} context The rule context to report.
+ * @param {ASTNode} prevNode The previous node to check.
+ * @param {ASTNode} nextNode The next node to check.
+ * @param {Array} paddingLines The array of token pairs that blank
+ * lines exist between the pair.
+ * @returns {void}
+ * @private
+ */
+function verifyForNever(context, prevNode, nextNode, paddingLines) {
+ if (paddingLines.length === 0) {
+ return;
+ }
+
+ context.report({
+ node: nextNode,
+ message: "Unexpected blank line before this statement.",
+ fix(fixer) {
+ if (paddingLines.length >= 2) {
+ return null;
+ }
+
+ const prevToken = paddingLines[0][0];
+ const nextToken = paddingLines[0][1];
+ const start = prevToken.range[1];
+ const end = nextToken.range[0];
+ const text = context.getSourceCode().text
+ .slice(start, end)
+ .replace(PADDING_LINE_SEQUENCE, replacerToRemovePaddingLines);
+
+ return fixer.replaceTextRange([start, end], text);
+ }
+ });
+}
+
+/**
+ * Check and report statements for `always` configuration.
+ * This autofix inserts a blank line between the given 2 statements.
+ * If the `prevNode` has trailing comments, it inserts a blank line after the
+ * trailing comments.
+ *
+ * @param {RuleContext} context The rule context to report.
+ * @param {ASTNode} prevNode The previous node to check.
+ * @param {ASTNode} nextNode The next node to check.
+ * @param {Array} paddingLines The array of token pairs that blank
+ * lines exist between the pair.
+ * @returns {void}
+ * @private
+ */
+function verifyForAlways(context, prevNode, nextNode, paddingLines) {
+ if (paddingLines.length > 0) {
+ return;
+ }
+
+ context.report({
+ node: nextNode,
+ message: "Expected blank line before this statement.",
+ fix(fixer) {
+ const sourceCode = context.getSourceCode();
+ let prevToken = getActualLastToken(sourceCode, prevNode);
+ const nextToken = sourceCode.getFirstTokenBetween(
+ prevToken,
+ nextNode,
+ {
+ includeComments: true,
+
+ /**
+ * Skip the trailing comments of the previous node.
+ * This inserts a blank line after the last trailing comment.
+ *
+ * For example:
+ *
+ * foo(); // trailing comment.
+ * // comment.
+ * bar();
+ *
+ * Get fixed to:
+ *
+ * foo(); // trailing comment.
+ *
+ * // comment.
+ * bar();
+ *
+ * @param {Token} token The token to check.
+ * @returns {boolean} `true` if the token is not a trailing comment.
+ * @private
+ */
+ filter(token) {
+ if (astUtils.isTokenOnSameLine(prevToken, token)) {
+ prevToken = token;
+ return false;
+ }
+ return true;
+ }
+ }
+ ) || nextNode;
+ const insertText = astUtils.isTokenOnSameLine(prevToken, nextToken)
+ ? "\n\n"
+ : "\n";
+
+ return fixer.insertTextAfter(prevToken, insertText);
+ }
+ });
+}
+
+/**
+ * Types of blank lines.
+ * `any`, `never`, and `always` are defined.
+ * Those have `verify` method to check and report statements.
+ * @private
+ */
+const PaddingTypes = {
+ any: { verify: verifyForAny },
+ never: { verify: verifyForNever },
+ always: { verify: verifyForAlways }
+};
+
+/**
+ * Types of statements.
+ * Those have `test` method to check it matches to the given statement.
+ * @private
+ */
+const StatementTypes = {
+ "*": { test: () => true },
+ "block-like": {
+ test: (node, sourceCode) => isBlockLikeStatement(sourceCode, node)
+ },
+ "cjs-export": {
+ test: (node, sourceCode) =>
+ node.type === "ExpressionStatement" &&
+ node.expression.type === "AssignmentExpression" &&
+ CJS_EXPORT.test(sourceCode.getText(node.expression.left))
+ },
+ "cjs-import": {
+ test: (node, sourceCode) =>
+ node.type === "VariableDeclaration" &&
+ node.declarations.length > 0 &&
+ Boolean(node.declarations[0].init) &&
+ CJS_IMPORT.test(sourceCode.getText(node.declarations[0].init))
+ },
+ directive: {
+ test: isDirectivePrologue
+ },
+ expression: {
+ test: (node, sourceCode) =>
+ node.type === "ExpressionStatement" &&
+ !isDirectivePrologue(node, sourceCode)
+ },
+ "multiline-block-like": {
+ test: (node, sourceCode) =>
+ node.loc.start.line !== node.loc.end.line &&
+ isBlockLikeStatement(sourceCode, node)
+ },
+
+ block: newNodeTypeTester("BlockStatement"),
+ empty: newNodeTypeTester("EmptyStatement"),
+
+ break: newKeywordTester("break"),
+ case: newKeywordTester("case"),
+ class: newKeywordTester("class"),
+ const: newKeywordTester("const"),
+ continue: newKeywordTester("continue"),
+ debugger: newKeywordTester("debugger"),
+ default: newKeywordTester("default"),
+ do: newKeywordTester("do"),
+ export: newKeywordTester("export"),
+ for: newKeywordTester("for"),
+ function: newKeywordTester("function"),
+ if: newKeywordTester("if"),
+ import: newKeywordTester("import"),
+ let: newKeywordTester("let"),
+ return: newKeywordTester("return"),
+ switch: newKeywordTester("switch"),
+ throw: newKeywordTester("throw"),
+ try: newKeywordTester("try"),
+ var: newKeywordTester("var"),
+ while: newKeywordTester("while"),
+ with: newKeywordTester("with")
+};
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = {
+ meta: {
+ docs: {
+ description: "require or disallow padding lines between statements",
+ category: "Stylistic Issues",
+ recommended: false
+ },
+ fixable: "whitespace",
+ schema: {
+ definitions: {
+ paddingType: {
+ enum: Object.keys(PaddingTypes)
+ },
+ statementType: {
+ anyOf: [
+ { enum: Object.keys(StatementTypes) },
+ {
+ type: "array",
+ items: { enum: Object.keys(StatementTypes) },
+ minItems: 1,
+ uniqueItems: true,
+ additionalItems: false
+ }
+ ]
+ }
+ },
+ type: "array",
+ items: {
+ type: "object",
+ properties: {
+ blankLine: { $ref: "#/definitions/paddingType" },
+ prev: { $ref: "#/definitions/statementType" },
+ next: { $ref: "#/definitions/statementType" }
+ },
+ additionalProperties: false,
+ required: ["blankLine", "prev", "next"]
+ },
+ additionalItems: false
+ }
+ },
+
+ create(context) {
+ const sourceCode = context.getSourceCode();
+ const configureList = context.options || [];
+ let scopeInfo = null;
+
+ /**
+ * Processes to enter to new scope.
+ * This manages the current previous statement.
+ * @returns {void}
+ * @private
+ */
+ function enterScope() {
+ scopeInfo = {
+ upper: scopeInfo,
+ prevNode: null
+ };
+ }
+
+ /**
+ * Processes to exit from the current scope.
+ * @returns {void}
+ * @private
+ */
+ function exitScope() {
+ scopeInfo = scopeInfo.upper;
+ }
+
+ /**
+ * Checks whether the given node matches the given type.
+ *
+ * @param {ASTNode} node The statement node to check.
+ * @param {string|string[]} type The statement type to check.
+ * @returns {boolean} `true` if the statement node matched the type.
+ * @private
+ */
+ function match(node, type) {
+ while (node.type === "LabeledStatement") {
+ node = node.body;
+ }
+ if (Array.isArray(type)) {
+ return type.some(match.bind(null, node));
+ }
+ return StatementTypes[type].test(node, sourceCode);
+ }
+
+ /**
+ * Finds the last matched configure from configureList.
+ *
+ * @param {ASTNode} prevNode The previous statement to match.
+ * @param {ASTNode} nextNode The current statement to match.
+ * @returns {Object} The tester of the last matched configure.
+ * @private
+ */
+ function getPaddingType(prevNode, nextNode) {
+ for (let i = configureList.length - 1; i >= 0; --i) {
+ const configure = configureList[i];
+ const matched =
+ match(prevNode, configure.prev) &&
+ match(nextNode, configure.next);
+
+ if (matched) {
+ return PaddingTypes[configure.blankLine];
+ }
+ }
+ return PaddingTypes.any;
+ }
+
+ /**
+ * Gets padding line sequences between the given 2 statements.
+ * Comments are separators of the padding line sequences.
+ *
+ * @param {ASTNode} prevNode The previous statement to count.
+ * @param {ASTNode} nextNode The current statement to count.
+ * @returns {Array} The array of token pairs.
+ * @private
+ */
+ function getPaddingLineSequences(prevNode, nextNode) {
+ const pairs = [];
+ let prevToken = getActualLastToken(sourceCode, prevNode);
+
+ if (nextNode.loc.start.line - prevToken.loc.end.line >= 2) {
+ do {
+ const token = sourceCode.getTokenAfter(
+ prevToken,
+ { includeComments: true }
+ );
+
+ if (token.loc.start.line - prevToken.loc.end.line >= 2) {
+ pairs.push([prevToken, token]);
+ }
+ prevToken = token;
+
+ } while (prevToken.range[0] < nextNode.range[0]);
+ }
+
+ return pairs;
+ }
+
+ /**
+ * Verify padding lines between the given node and the previous node.
+ *
+ * @param {ASTNode} node The node to verify.
+ * @returns {void}
+ * @private
+ */
+ function verify(node) {
+ const parentType = node.parent.type;
+ const validParent =
+ astUtils.STATEMENT_LIST_PARENTS.has(parentType) ||
+ parentType === "SwitchStatement";
+
+ if (!validParent) {
+ return;
+ }
+
+ // Save this node as the current previous statement.
+ const prevNode = scopeInfo.prevNode;
+
+ // Verify.
+ if (prevNode) {
+ const type = getPaddingType(prevNode, node);
+ const paddingLines = getPaddingLineSequences(prevNode, node);
+
+ type.verify(context, prevNode, node, paddingLines);
+ }
+
+ scopeInfo.prevNode = node;
+ }
+
+ /**
+ * Verify padding lines between the given node and the previous node.
+ * Then process to enter to new scope.
+ *
+ * @param {ASTNode} node The node to verify.
+ * @returns {void}
+ * @private
+ */
+ function verifyThenEnterScope(node) {
+ verify(node);
+ enterScope();
+ }
+
+ return {
+ Program: enterScope,
+ BlockStatement: enterScope,
+ SwitchStatement: enterScope,
+ "Program:exit": exitScope,
+ "BlockStatement:exit": exitScope,
+ "SwitchStatement:exit": exitScope,
+
+ ":statement": verify,
+
+ SwitchCase: verifyThenEnterScope,
+ "SwitchCase:exit": exitScope
+ };
+ }
+};
diff --git a/tools/eslint/lib/rules/prefer-arrow-callback.js b/tools/eslint/lib/rules/prefer-arrow-callback.js
index ee385042f1309e..43a8bb77dec634 100644
--- a/tools/eslint/lib/rules/prefer-arrow-callback.js
+++ b/tools/eslint/lib/rules/prefer-arrow-callback.js
@@ -11,7 +11,7 @@
/**
* Checks whether or not a given variable is a function name.
- * @param {escope.Variable} variable - A variable to check.
+ * @param {eslint-scope.Variable} variable - A variable to check.
* @returns {boolean} `true` if the variable is a function name.
*/
function isFunctionName(variable) {
@@ -31,8 +31,8 @@ function checkMetaProperty(node, metaName, propertyName) {
/**
* Gets the variable object of `arguments` which is defined implicitly.
- * @param {escope.Scope} scope - A scope to get.
- * @returns {escope.Variable} The found variable object.
+ * @param {eslint-scope.Scope} scope - A scope to get.
+ * @returns {eslint-scope.Variable} The found variable object.
*/
function getVariableOfArguments(scope) {
const variables = scope.variables;
@@ -159,7 +159,7 @@ module.exports = {
create(context) {
const options = context.options[0] || {};
- const allowUnboundThis = options.allowUnboundThis !== false; // default to true
+ const allowUnboundThis = options.allowUnboundThis !== false; // default to true
const allowNamedFunctions = options.allowNamedFunctions;
const sourceCode = context.getSourceCode();
@@ -277,15 +277,23 @@ module.exports = {
const paramsRightParen = sourceCode.getTokenBefore(node.body);
const asyncKeyword = node.async ? "async " : "";
const paramsFullText = sourceCode.text.slice(paramsLeftParen.range[0], paramsRightParen.range[1]);
-
- if (callbackInfo.isLexicalThis) {
-
- // If the callback function has `.bind(this)`, replace it with an arrow function and remove the binding.
- return fixer.replaceText(node.parent.parent, `${asyncKeyword}${paramsFullText} => ${sourceCode.getText(node.body)}`);
- }
-
- // Otherwise, only replace the `function` keyword and parameters with the arrow function parameters.
- return fixer.replaceTextRange([node.start, node.body.start], `${asyncKeyword}${paramsFullText} => `);
+ const arrowFunctionText = `${asyncKeyword}${paramsFullText} => ${sourceCode.getText(node.body)}`;
+
+ /*
+ * If the callback function has `.bind(this)`, replace it with an arrow function and remove the binding.
+ * Otherwise, just replace the arrow function itself.
+ */
+ const replacedNode = callbackInfo.isLexicalThis ? node.parent.parent : node;
+
+ /*
+ * If the replaced node is part of a BinaryExpression, LogicalExpression, or MemberExpression, then
+ * the arrow function needs to be parenthesized, because `foo || () => {}` is invalid syntax even
+ * though `foo || function() {}` is valid.
+ */
+ const needsParens = replacedNode.parent.type !== "CallExpression" && replacedNode.parent.type !== "ConditionalExpression";
+ const replacementText = needsParens ? `(${arrowFunctionText})` : arrowFunctionText;
+
+ return fixer.replaceText(replacedNode, replacementText);
}
});
}
diff --git a/tools/eslint/lib/rules/prefer-const.js b/tools/eslint/lib/rules/prefer-const.js
index 53bdc2ab7b0582..1395e0a8a08e92 100644
--- a/tools/eslint/lib/rules/prefer-const.js
+++ b/tools/eslint/lib/rules/prefer-const.js
@@ -73,7 +73,7 @@ function canBecomeVariableDeclaration(identifier) {
* warn such variables because this rule cannot distinguish whether the
* exported variables are reassigned or not.
*
- * @param {escope.Variable} variable - A variable to get.
+ * @param {eslint-scope.Variable} variable - A variable to get.
* @param {boolean} ignoreReadBeforeAssign -
* The value of `ignoreReadBeforeAssign` option.
* @returns {ASTNode|null}
@@ -85,17 +85,6 @@ function getIdentifierIfShouldBeConst(variable, ignoreReadBeforeAssign) {
return null;
}
- /*
- * Due to a bug in acorn, code such as `let foo = 1; let foo = 2;` will not throw a syntax error. As a sanity
- * check, make sure that the variable only has one declaration. After the parsing bug is fixed, this check
- * will no longer be necessary, because variables declared with `let` or `const` should always have exactly one
- * declaration.
- * https://github.com/ternjs/acorn/issues/487
- */
- if (variable.defs.length > 1) {
- return null;
- }
-
// Finds the unique WriteReference.
let writer = null;
let isReadBeforeInit = false;
@@ -146,7 +135,7 @@ function getIdentifierIfShouldBeConst(variable, ignoreReadBeforeAssign) {
* This is used to detect a mix of reassigned and never reassigned in a
* destructuring.
*
- * @param {escope.Reference} reference - A reference to get.
+ * @param {eslint-scope.Reference} reference - A reference to get.
* @returns {ASTNode|null} A VariableDeclarator/AssignmentExpression node or
* null.
*/
@@ -172,7 +161,7 @@ function getDestructuringHost(reference) {
* This is used to detect a mix of reassigned and never reassigned in a
* destructuring.
*
- * @param {escope.Variable[]} variables - Variables to group by destructuring.
+ * @param {eslint-scope.Variable[]} variables - Variables to group by destructuring.
* @param {boolean} ignoreReadBeforeAssign -
* The value of `ignoreReadBeforeAssign` option.
* @returns {Map} Grouped identifier nodes.
@@ -274,7 +263,7 @@ module.exports = {
* the array is 1. In destructuring cases, the length of the array can
* be 2 or more.
*
- * @param {(escope.Reference|null)[]} nodes -
+ * @param {(eslint-scope.Reference|null)[]} nodes -
* References which are grouped by destructuring to report.
* @returns {void}
*/
diff --git a/tools/eslint/lib/rules/prefer-destructuring.js b/tools/eslint/lib/rules/prefer-destructuring.js
index d7fbc3559d7162..7f472b423bc18b 100644
--- a/tools/eslint/lib/rules/prefer-destructuring.js
+++ b/tools/eslint/lib/rules/prefer-destructuring.js
@@ -109,8 +109,10 @@ module.exports = {
return;
}
- if (checkArrays && isArrayIndexAccess(rightNode)) {
- report(reportNode, "array");
+ if (isArrayIndexAccess(rightNode)) {
+ if (checkArrays) {
+ report(reportNode, "array");
+ }
return;
}
diff --git a/tools/eslint/lib/rules/prefer-rest-params.js b/tools/eslint/lib/rules/prefer-rest-params.js
index a9db624dcb64aa..d55d5dad02a09e 100644
--- a/tools/eslint/lib/rules/prefer-rest-params.js
+++ b/tools/eslint/lib/rules/prefer-rest-params.js
@@ -11,8 +11,8 @@
/**
* Gets the variable object of `arguments` which is defined implicitly.
- * @param {escope.Scope} scope - A scope to get.
- * @returns {escope.Variable} The found variable object.
+ * @param {eslint-scope.Scope} scope - A scope to get.
+ * @returns {eslint-scope.Variable} The found variable object.
*/
function getVariableOfArguments(scope) {
const variables = scope.variables;
@@ -40,7 +40,7 @@ function getVariableOfArguments(scope) {
* - arguments[0] .... true // computed member access
* - arguments.length .... false // normal member access
*
- * @param {escope.Reference} reference - The reference to check.
+ * @param {eslint-scope.Reference} reference - The reference to check.
* @returns {boolean} `true` if the reference is not normal member access.
*/
function isNotNormalMemberAccess(reference) {
@@ -74,7 +74,7 @@ module.exports = {
/**
* Reports a given reference.
*
- * @param {escope.Reference} reference - A reference to report.
+ * @param {eslint-scope.Reference} reference - A reference to report.
* @returns {void}
*/
function report(reference) {
diff --git a/tools/eslint/lib/rules/radix.js b/tools/eslint/lib/rules/radix.js
index 0dfa081b6a3e35..0484c3bfb371b5 100644
--- a/tools/eslint/lib/rules/radix.js
+++ b/tools/eslint/lib/rules/radix.js
@@ -21,7 +21,7 @@ const MODE_ALWAYS = "always",
/**
* Checks whether a given variable is shadowed or not.
*
- * @param {escope.Variable} variable - A variable to check.
+ * @param {eslint-scope.Variable} variable - A variable to check.
* @returns {boolean} `true` if the variable is shadowed.
*/
function isShadowed(variable) {
diff --git a/tools/eslint/lib/rules/semi-style.js b/tools/eslint/lib/rules/semi-style.js
new file mode 100644
index 00000000000000..97fcc3ac8209bb
--- /dev/null
+++ b/tools/eslint/lib/rules/semi-style.js
@@ -0,0 +1,118 @@
+/**
+ * @fileoverview Rule to enforce location of semicolons.
+ * @author Toru Nagashima
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const astUtils = require("../ast-utils");
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+const SELECTOR = `:matches(${
+ [
+ "BreakStatement", "ContinueStatement", "DebuggerStatement",
+ "DoWhileStatement", "EmptyStatement", "ExportAllDeclaration",
+ "ExportDefaultDeclaration", "ExportNamedDeclaration",
+ "ExpressionStatement", "ImportDeclaration", "ReturnStatement",
+ "ThrowStatement", "VariableDeclaration"
+ ].join(",")
+})`;
+
+module.exports = {
+ meta: {
+ docs: {
+ description: "enforce location of semicolons",
+ category: "Stylistic Issues",
+ recommended: false
+ },
+ schema: [{ enum: ["last", "first"] }],
+ fixable: "whitespace"
+ },
+
+ create(context) {
+ const sourceCode = context.getSourceCode();
+ const option = context.options[0] || "last";
+
+ /**
+ * Check whether comments exist between the given 2 tokens.
+ * @param {Token} left The left token to check.
+ * @param {Token} right The right token to check.
+ * @returns {boolean} `true` if comments exist between the given 2 tokens.
+ */
+ function commentsExistBetween(left, right) {
+ return sourceCode.getFirstTokenBetween(
+ left,
+ right,
+ {
+ includeComments: true,
+ filter: astUtils.isCommentToken
+ }
+ ) !== null;
+ }
+
+ /**
+ * Check the given semicolon token.
+ * @param {Token} semiToken The semicolon token to check.
+ * @param {"first"|"last"} expected The expected location to check.
+ * @returns {void}
+ */
+ function check(semiToken, expected) {
+ const prevToken = sourceCode.getTokenBefore(semiToken);
+ const nextToken = sourceCode.getTokenAfter(semiToken);
+ const prevIsSameLine = !prevToken || astUtils.isTokenOnSameLine(prevToken, semiToken);
+ const nextIsSameLine = !nextToken || astUtils.isTokenOnSameLine(semiToken, nextToken);
+
+ if ((expected === "last" && !prevIsSameLine) || (expected === "first" && !nextIsSameLine)) {
+ context.report({
+ loc: semiToken.loc,
+ message: "Expected this semicolon to be at {{pos}}.",
+ data: {
+ pos: (expected === "last")
+ ? "the end of the previous line"
+ : "the beginning of the next line"
+ },
+ fix(fixer) {
+ if (prevToken && nextToken && commentsExistBetween(prevToken, nextToken)) {
+ return null;
+ }
+
+ const start = prevToken ? prevToken.range[1] : semiToken.range[0];
+ const end = nextToken ? nextToken.range[0] : semiToken.range[1];
+ const text = (expected === "last") ? ";\n" : "\n;";
+
+ return fixer.replaceTextRange([start, end], text);
+ }
+ });
+ }
+ }
+
+ return {
+ [SELECTOR](node) {
+ const lastToken = sourceCode.getLastToken(node);
+
+ if (astUtils.isSemicolonToken(lastToken)) {
+ check(lastToken, option);
+ }
+ },
+
+ ForStatement(node) {
+ const firstSemi = node.init && sourceCode.getTokenAfter(node.init, astUtils.isSemicolonToken);
+ const secondSemi = node.test && sourceCode.getTokenAfter(node.test, astUtils.isSemicolonToken);
+
+ if (firstSemi) {
+ check(firstSemi, "last");
+ }
+ if (secondSemi) {
+ check(secondSemi, "last");
+ }
+ }
+ };
+ }
+};
diff --git a/tools/eslint/lib/rules/sort-imports.js b/tools/eslint/lib/rules/sort-imports.js
index 2b382545efb3f7..74db02ad3dff74 100644
--- a/tools/eslint/lib/rules/sort-imports.js
+++ b/tools/eslint/lib/rules/sort-imports.js
@@ -149,7 +149,7 @@ module.exports = {
message: "Member '{{memberName}}' of the import declaration should be sorted alphabetically.",
data: { memberName: importSpecifiers[firstUnsortedIndex].local.name },
fix(fixer) {
- if (importSpecifiers.some(specifier => sourceCode.getComments(specifier).leading.length || sourceCode.getComments(specifier).trailing.length)) {
+ if (importSpecifiers.some(specifier => sourceCode.getCommentsBefore(specifier).length || sourceCode.getCommentsAfter(specifier).length)) {
// If there are comments in the ImportSpecifier list, don't rearrange the specifiers.
return null;
diff --git a/tools/eslint/lib/rules/space-before-function-paren.js b/tools/eslint/lib/rules/space-before-function-paren.js
index 53aac71ed6e162..8851c4587ac779 100644
--- a/tools/eslint/lib/rules/space-before-function-paren.js
+++ b/tools/eslint/lib/rules/space-before-function-paren.js
@@ -87,9 +87,7 @@ module.exports = {
// Always ignore non-async functions and arrow functions without parens, e.g. async foo => bar
if (node.async && astUtils.isOpeningParenToken(sourceCode.getFirstToken(node, { skip: 1 }))) {
-
- // For backwards compatibility, the base config does not apply to async arrow functions.
- return overrideConfig.asyncArrow || "ignore";
+ return overrideConfig.asyncArrow || baseConfig;
}
} else if (isNamedFunction(node)) {
return overrideConfig.named || baseConfig;
diff --git a/tools/eslint/lib/rules/space-unary-ops.js b/tools/eslint/lib/rules/space-unary-ops.js
index 5b156fac2292d4..da525ea12c529f 100644
--- a/tools/eslint/lib/rules/space-unary-ops.js
+++ b/tools/eslint/lib/rules/space-unary-ops.js
@@ -4,6 +4,12 @@
*/
"use strict";
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const astUtils = require("../ast-utils");
+
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
@@ -68,21 +74,6 @@ module.exports = {
return node.argument && node.argument.type && node.argument.type === "ObjectExpression";
}
- /**
- * Check if it is safe to remove the spaces between the two tokens in
- * the context of a non-word prefix unary operator. For example, `+ +1`
- * cannot safely be changed to `++1`.
- * @param {Token} firstToken The operator for a non-word prefix unary operator
- * @param {Token} secondToken The first token of its operand
- * @returns {boolean} Whether or not the spacing between the tokens can be removed
- */
- function canRemoveSpacesBetween(firstToken, secondToken) {
- return !(
- (firstToken.value === "+" && secondToken.value[0] === "+") ||
- (firstToken.value === "-" && secondToken.value[0] === "-")
- );
- }
-
/**
* Checks if an override exists for a given operator.
* @param {ASTnode} node AST node
@@ -259,7 +250,7 @@ module.exports = {
operator: firstToken.value
},
fix(fixer) {
- if (canRemoveSpacesBetween(firstToken, secondToken)) {
+ if (astUtils.canTokensBeAdjacent(firstToken, secondToken)) {
return fixer.removeRange([firstToken.range[1], secondToken.range[0]]);
}
return null;
@@ -288,9 +279,11 @@ module.exports = {
* @returns {void}
*/
function checkForSpaces(node) {
- const tokens = sourceCode.getFirstTokens(node, 2),
- firstToken = tokens[0],
- secondToken = tokens[1];
+ const tokens = node.type === "UpdateExpression" && !node.prefix
+ ? sourceCode.getLastTokens(node, 2)
+ : sourceCode.getFirstTokens(node, 2);
+ const firstToken = tokens[0];
+ const secondToken = tokens[1];
if ((node.type === "NewExpression" || node.prefix) && firstToken.type === "Keyword") {
checkUnaryWordOperatorForSpaces(node, firstToken, secondToken);
diff --git a/tools/eslint/lib/rules/spaced-comment.js b/tools/eslint/lib/rules/spaced-comment.js
index 4e418fd19f3a86..b1e35055cecee4 100644
--- a/tools/eslint/lib/rules/spaced-comment.js
+++ b/tools/eslint/lib/rules/spaced-comment.js
@@ -229,6 +229,8 @@ module.exports = {
create(context) {
+ const sourceCode = context.getSourceCode();
+
// Unless the first option is never, require a space
const requireSpace = context.options[0] !== "never";
@@ -363,10 +365,11 @@ module.exports = {
}
return {
+ Program() {
+ const comments = sourceCode.getAllComments();
- LineComment: checkCommentForSpace,
- BlockComment: checkCommentForSpace
-
+ comments.filter(token => token.type !== "Shebang").forEach(checkCommentForSpace);
+ }
};
}
};
diff --git a/tools/eslint/lib/rules/switch-colon-spacing.js b/tools/eslint/lib/rules/switch-colon-spacing.js
new file mode 100644
index 00000000000000..400e850997e54e
--- /dev/null
+++ b/tools/eslint/lib/rules/switch-colon-spacing.js
@@ -0,0 +1,133 @@
+/**
+ * @fileoverview Rule to enforce spacing around colons of switch statements.
+ * @author Toru Nagashima
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const astUtils = require("../ast-utils");
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = {
+ meta: {
+ docs: {
+ description: "enforce spacing around colons of switch statements",
+ category: "Stylistic Issues",
+ recommended: false
+ },
+ schema: [
+ {
+ type: "object",
+ properties: {
+ before: { type: "boolean" },
+ after: { type: "boolean" }
+ },
+ additionalProperties: false
+ }
+ ],
+ fixable: "whitespace"
+ },
+
+ create(context) {
+ const sourceCode = context.getSourceCode();
+ const options = context.options[0] || {};
+ const beforeSpacing = options.before === true; // false by default
+ const afterSpacing = options.after !== false; // true by default
+
+ /**
+ * Get the colon token of the given SwitchCase node.
+ * @param {ASTNode} node The SwitchCase node to get.
+ * @returns {Token} The colon token of the node.
+ */
+ function getColonToken(node) {
+ if (node.test) {
+ return sourceCode.getTokenAfter(node.test, astUtils.isColonToken);
+ }
+ return sourceCode.getFirstToken(node, 1);
+ }
+
+ /**
+ * Check whether the spacing between the given 2 tokens is valid or not.
+ * @param {Token} left The left token to check.
+ * @param {Token} right The right token to check.
+ * @param {boolean} expected The expected spacing to check. `true` if there should be a space.
+ * @returns {boolean} `true` if the spacing between the tokens is valid.
+ */
+ function isValidSpacing(left, right, expected) {
+ return (
+ astUtils.isClosingBraceToken(right) ||
+ !astUtils.isTokenOnSameLine(left, right) ||
+ sourceCode.isSpaceBetweenTokens(left, right) === expected
+ );
+ }
+
+ /**
+ * Check whether comments exist between the given 2 tokens.
+ * @param {Token} left The left token to check.
+ * @param {Token} right The right token to check.
+ * @returns {boolean} `true` if comments exist between the given 2 tokens.
+ */
+ function commentsExistBetween(left, right) {
+ return sourceCode.getFirstTokenBetween(
+ left,
+ right,
+ {
+ includeComments: true,
+ filter: astUtils.isCommentToken
+ }
+ ) !== null;
+ }
+
+ /**
+ * Fix the spacing between the given 2 tokens.
+ * @param {RuleFixer} fixer The fixer to fix.
+ * @param {Token} left The left token of fix range.
+ * @param {Token} right The right token of fix range.
+ * @param {boolean} spacing The spacing style. `true` if there should be a space.
+ * @returns {Fix|null} The fix object.
+ */
+ function fix(fixer, left, right, spacing) {
+ if (commentsExistBetween(left, right)) {
+ return null;
+ }
+ if (spacing) {
+ return fixer.insertTextAfter(left, " ");
+ }
+ return fixer.removeRange([left.range[1], right.range[0]]);
+ }
+
+ return {
+ SwitchCase(node) {
+ const colonToken = getColonToken(node);
+ const beforeToken = sourceCode.getTokenBefore(colonToken);
+ const afterToken = sourceCode.getTokenAfter(colonToken);
+
+ if (!isValidSpacing(beforeToken, colonToken, beforeSpacing)) {
+ context.report({
+ node,
+ loc: colonToken.loc,
+ message: "{{verb}} space(s) before this colon.",
+ data: { verb: beforeSpacing ? "Expected" : "Unexpected" },
+ fix: fixer => fix(fixer, beforeToken, colonToken, beforeSpacing)
+ });
+ }
+ if (!isValidSpacing(colonToken, afterToken, afterSpacing)) {
+ context.report({
+ node,
+ loc: colonToken.loc,
+ message: "{{verb}} space(s) after this colon.",
+ data: { verb: afterSpacing ? "Expected" : "Unexpected" },
+ fix: fixer => fix(fixer, colonToken, afterToken, afterSpacing)
+ });
+ }
+ }
+ };
+ }
+};
diff --git a/tools/eslint/lib/rules/template-tag-spacing.js b/tools/eslint/lib/rules/template-tag-spacing.js
index 808fe443891791..907c537ff30182 100755
--- a/tools/eslint/lib/rules/template-tag-spacing.js
+++ b/tools/eslint/lib/rules/template-tag-spacing.js
@@ -45,7 +45,7 @@ module.exports = {
loc: tagToken.loc.start,
message: "Unexpected space between template tag and template literal.",
fix(fixer) {
- const comments = sourceCode.getComments(node.quasi).leading;
+ const comments = sourceCode.getCommentsBefore(node.quasi);
// Don't fix anything if there's a single line comment after the template tag
if (comments.some(comment => comment.type === "Line")) {
diff --git a/tools/eslint/lib/rules/valid-jsdoc.js b/tools/eslint/lib/rules/valid-jsdoc.js
index 66ad1f8d45de1f..331ed7b69b6561 100644
--- a/tools/eslint/lib/rules/valid-jsdoc.js
+++ b/tools/eslint/lib/rules/valid-jsdoc.js
@@ -180,18 +180,18 @@ module.exports = {
let elements = [];
switch (type.type) {
- case "TypeApplication": // {Array.}
+ case "TypeApplication": // {Array.}
elements = type.applications[0].type === "UnionType" ? type.applications[0].elements : type.applications;
typesToCheck.push(getCurrentExpectedTypes(type));
break;
- case "RecordType": // {{20:String}}
+ case "RecordType": // {{20:String}}
elements = type.fields;
break;
- case "UnionType": // {String|number|Test}
- case "ArrayType": // {[String, number, Test]}
+ case "UnionType": // {String|number|Test}
+ case "ArrayType": // {[String, number, Test]}
elements = type.elements;
break;
- case "FieldType": // Array.<{count: number, votes: number}>
+ case "FieldType": // Array.<{count: number, votes: number}>
if (type.value) {
typesToCheck.push(getCurrentExpectedTypes(type.value));
}
diff --git a/tools/eslint/lib/testers/rule-tester.js b/tools/eslint/lib/testers/rule-tester.js
index 61fbdf597f8730..d66cd175a43e88 100644
--- a/tools/eslint/lib/testers/rule-tester.js
+++ b/tools/eslint/lib/testers/rule-tester.js
@@ -12,12 +12,12 @@
* RuleTester.add("{ruleName}", {
* valid: [
* "{code}",
- * { code: "{code}", options: {options}, global: {globals}, globals: {globals}, parser: "{parser}", settings: {settings} }
+ * { code: "{code}", options: {options}, globals: {globals}, parser: "{parser}", settings: {settings} }
* ],
* invalid: [
* { code: "{code}", errors: {numErrors} },
* { code: "{code}", errors: ["{errorMessage}"] },
- * { code: "{code}", options: {options}, global: {globals}, parser: "{parser}", settings: {settings}, errors: [{ message: "{errorMessage}", type: "{errorNodeType}"}] }
+ * { code: "{code}", options: {options}, globals: {globals}, parser: "{parser}", settings: {settings}, errors: [{ message: "{errorMessage}", type: "{errorNodeType}"}] }
* ]
* });
*
@@ -45,8 +45,8 @@ const lodash = require("lodash"),
util = require("util"),
validator = require("../config/config-validator"),
validate = require("is-my-json-valid"),
- eslint = require("../eslint"),
- rules = require("../rules"),
+ Linter = require("../linter"),
+ Environments = require("../config/environments"),
metaSchema = require("../../conf/json-schema-schema.json"),
SourceCodeFixer = require("../util/source-code-fixer");
@@ -69,8 +69,8 @@ const RuleTesterParameters = [
"code",
"filename",
"options",
- "args",
- "errors"
+ "errors",
+ "output"
];
const validateSchema = validate(metaSchema, { verbose: true });
@@ -129,114 +129,107 @@ function freezeDeeply(x) {
// Public Interface
//------------------------------------------------------------------------------
+// default separators for testing
+const DESCRIBE = Symbol("describe");
+const IT = Symbol("it");
+
/**
- * Creates a new instance of RuleTester.
- * @param {Object} [testerConfig] Optional, extra configuration for the tester
- * @constructor
+ * This is `it` or `describe` if those don't exist.
+ * @this {Mocha}
+ * @param {string} text - The description of the test case.
+ * @param {Function} method - The logic of the test case.
+ * @returns {any} Returned value of `method`.
*/
-function RuleTester(testerConfig) {
+function defaultHandler(text, method) {
+ return method.apply(this);
+}
+
+class RuleTester {
/**
- * The configuration to use for this tester. Combination of the tester
- * configuration and the default configuration.
- * @type {Object}
+ * Creates a new instance of RuleTester.
+ * @param {Object} [testerConfig] Optional, extra configuration for the tester
+ * @constructor
*/
- this.testerConfig = lodash.merge(
+ constructor(testerConfig) {
+
+ /**
+ * The configuration to use for this tester. Combination of the tester
+ * configuration and the default configuration.
+ * @type {Object}
+ */
+ this.testerConfig = lodash.merge(
- // we have to clone because merge uses the first argument for recipient
- lodash.cloneDeep(defaultConfig),
- testerConfig
- );
+ // we have to clone because merge uses the first argument for recipient
+ lodash.cloneDeep(defaultConfig),
+ testerConfig
+ );
+
+ /**
+ * Rule definitions to define before tests.
+ * @type {Object}
+ */
+ this.rules = {};
+ this.linter = new Linter();
+ }
/**
- * Rule definitions to define before tests.
- * @type {Object}
+ * Set the configuration to use for all future tests
+ * @param {Object} config the configuration to use.
+ * @returns {void}
*/
- this.rules = {};
-}
+ static setDefaultConfig(config) {
+ if (typeof config !== "object") {
+ throw new Error("RuleTester.setDefaultConfig: config must be an object");
+ }
+ defaultConfig = config;
-/**
- * Set the configuration to use for all future tests
- * @param {Object} config the configuration to use.
- * @returns {void}
- */
-RuleTester.setDefaultConfig = function(config) {
- if (typeof config !== "object") {
- throw new Error("RuleTester.setDefaultConfig: config must be an object");
+ // Make sure the rules object exists since it is assumed to exist later
+ defaultConfig.rules = defaultConfig.rules || {};
}
- defaultConfig = config;
- // Make sure the rules object exists since it is assumed to exist later
- defaultConfig.rules = defaultConfig.rules || {};
-};
-
-/**
- * Get the current configuration used for all tests
- * @returns {Object} the current configuration
- */
-RuleTester.getDefaultConfig = function() {
- return defaultConfig;
-};
+ /**
+ * Get the current configuration used for all tests
+ * @returns {Object} the current configuration
+ */
+ static getDefaultConfig() {
+ return defaultConfig;
+ }
-/**
- * Reset the configuration to the initial configuration of the tester removing
- * any changes made until now.
- * @returns {void}
- */
-RuleTester.resetDefaultConfig = function() {
- defaultConfig = lodash.cloneDeep(testerDefaultConfig);
-};
+ /**
+ * Reset the configuration to the initial configuration of the tester removing
+ * any changes made until now.
+ * @returns {void}
+ */
+ static resetDefaultConfig() {
+ defaultConfig = lodash.cloneDeep(testerDefaultConfig);
+ }
-// default separators for testing
-const DESCRIBE = Symbol("describe");
-const IT = Symbol("it");
-RuleTester[DESCRIBE] = RuleTester[IT] = null;
+ // If people use `mocha test.js --watch` command, `describe` and `it` function
+ // instances are different for each execution. So `describe` and `it` should get fresh instance
+ // always.
+ static get describe() {
+ return (
+ this[DESCRIBE] ||
+ (typeof describe === "function" ? describe : defaultHandler)
+ );
+ }
-/**
- * This is `it` or `describe` if those don't exist.
- * @this {Mocha}
- * @param {string} text - The description of the test case.
- * @param {Function} method - The logic of the test case.
- * @returns {any} Returned value of `method`.
- */
-function defaultHandler(text, method) {
- return method.apply(this);
-}
+ static set describe(value) {
+ this[DESCRIBE] = value;
+ }
-// If people use `mocha test.js --watch` command, `describe` and `it` function
-// instances are different for each execution. So this should get fresh instance
-// always.
-Object.defineProperties(RuleTester, {
- describe: {
- get() {
- return (
- RuleTester[DESCRIBE] ||
- (typeof describe === "function" ? describe : defaultHandler)
- );
- },
- set(value) {
- RuleTester[DESCRIBE] = value;
- },
- configurable: true,
- enumerable: true
- },
- it: {
- get() {
- return (
- RuleTester[IT] ||
- (typeof it === "function" ? it : defaultHandler)
- );
- },
- set(value) {
- RuleTester[IT] = value;
- },
- configurable: true,
- enumerable: true
+ static get it() {
+ return (
+ this[IT] ||
+ (typeof it === "function" ? it : defaultHandler)
+ );
}
-});
-RuleTester.prototype = {
+ static set it(value) {
+ this[IT] = value;
+ }
/**
* Define a rule for one particular run of tests.
@@ -246,7 +239,7 @@ RuleTester.prototype = {
*/
defineRule(name, rule) {
this.rules[name] = rule;
- },
+ }
/**
* Adds a new rule test to execute.
@@ -260,7 +253,8 @@ RuleTester.prototype = {
const testerConfig = this.testerConfig,
requiredScenarios = ["valid", "invalid"],
scenarioErrors = [],
- result = {};
+ result = {},
+ linter = this.linter;
if (lodash.isNil(test) || typeof test !== "object") {
throw new Error(`Test Scenarios for rule ${ruleName} : Could not find test scenario object`);
@@ -312,18 +306,16 @@ RuleTester.prototype = {
filename = item.filename;
}
- if (item.options) {
- const options = item.options.concat();
-
- options.unshift(1);
- config.rules[ruleName] = options;
+ if (Object.prototype.hasOwnProperty.call(item, "options")) {
+ assert(Array.isArray(item.options), "options must be an array");
+ config.rules[ruleName] = [1].concat(item.options);
} else {
config.rules[ruleName] = 1;
}
- eslint.defineRule(ruleName, rule);
+ linter.defineRule(ruleName, rule);
- const schema = validator.getRuleOptionsSchema(ruleName);
+ const schema = validator.getRuleOptionsSchema(ruleName, linter.rules);
if (schema) {
validateSchema(schema);
@@ -335,29 +327,29 @@ RuleTester.prototype = {
}
}
- validator.validate(config, "rule-tester");
+ validator.validate(config, "rule-tester", linter.rules, new Environments());
/*
* Setup AST getters.
* The goal is to check whether or not AST was modified when
* running the rule under test.
*/
- eslint.reset();
+ linter.reset();
- eslint.on("Program", node => {
+ linter.on("Program", node => {
beforeAST = cloneDeeplyExcludesParent(node);
});
- eslint.on("Program:exit", node => {
+ linter.on("Program:exit", node => {
afterAST = node;
});
// Freezes rule-context properties.
- const originalGet = rules.get;
+ const originalGet = linter.rules.get;
try {
- rules.get = function(ruleId) {
- const rule = originalGet(ruleId);
+ linter.rules.get = function(ruleId) {
+ const rule = originalGet.call(linter.rules, ruleId);
if (typeof rule === "function") {
return function(context) {
@@ -384,12 +376,12 @@ RuleTester.prototype = {
};
return {
- messages: eslint.verify(code, config, filename, true),
+ messages: linter.verify(code, config, filename, true),
beforeAST,
afterAST: cloneDeeplyExcludesParent(afterAST)
};
} finally {
- rules.get = originalGet;
+ linter.rules.get = originalGet;
}
}
@@ -421,7 +413,7 @@ RuleTester.prototype = {
const messages = result.messages;
assert.equal(messages.length, 0, util.format("Should have no errors but had %d: %s",
- messages.length, util.inspect(messages)));
+ messages.length, util.inspect(messages)));
assertASTDidntChange(result.beforeAST, result.afterAST);
}
@@ -464,14 +456,17 @@ RuleTester.prototype = {
const messages = result.messages;
-
if (typeof item.errors === "number") {
assert.equal(messages.length, item.errors, util.format("Should have %d error%s but had %d: %s",
item.errors, item.errors === 1 ? "" : "s", messages.length, util.inspect(messages)));
} else {
- assert.equal(messages.length, item.errors.length,
- util.format("Should have %d error%s but had %d: %s",
- item.errors.length, item.errors.length === 1 ? "" : "s", messages.length, util.inspect(messages)));
+ assert.equal(
+ messages.length, item.errors.length,
+ util.format(
+ "Should have %d error%s but had %d: %s",
+ item.errors.length, item.errors.length === 1 ? "" : "s", messages.length, util.inspect(messages)
+ )
+ );
for (let i = 0, l = item.errors.length; i < l; i++) {
assert.ok(!("fatal" in messages[i]), `A fatal parsing error occurred: ${messages[i].message}`);
@@ -527,7 +522,7 @@ RuleTester.prototype = {
"Expected no autofixes to be suggested"
);
} else {
- const fixResult = SourceCodeFixer.applyFixes(eslint.getSourceCode(), messages);
+ const fixResult = SourceCodeFixer.applyFixes(linter.getSourceCode(), messages);
assert.equal(fixResult.output, item.output, "Output is incorrect.");
}
@@ -544,7 +539,7 @@ RuleTester.prototype = {
RuleTester.describe("valid", () => {
test.valid.forEach(valid => {
RuleTester.it(typeof valid === "object" ? valid.code : valid, () => {
- eslint.defineRules(this.rules);
+ linter.defineRules(this.rules);
testValidTemplate(ruleName, valid);
});
});
@@ -553,7 +548,7 @@ RuleTester.prototype = {
RuleTester.describe("invalid", () => {
test.invalid.forEach(invalid => {
RuleTester.it(invalid.code, () => {
- eslint.defineRules(this.rules);
+ linter.defineRules(this.rules);
testInvalidTemplate(ruleName, invalid);
});
});
@@ -562,7 +557,8 @@ RuleTester.prototype = {
return result.suite;
}
-};
+}
+RuleTester[DESCRIBE] = RuleTester[IT] = null;
module.exports = RuleTester;
diff --git a/tools/eslint/lib/timing.js b/tools/eslint/lib/timing.js
index 20456628640bf6..15c93800f1a698 100644
--- a/tools/eslint/lib/timing.js
+++ b/tools/eslint/lib/timing.js
@@ -98,7 +98,7 @@ function display(data) {
return ALIGN[index](":", w + 1, "-");
}).join("|"));
- console.log(table.join("\n")); // eslint-disable-line no-console
+ console.log(table.join("\n")); // eslint-disable-line no-console
}
/* istanbul ignore next */
diff --git a/tools/eslint/lib/token-store/index.js b/tools/eslint/lib/token-store/index.js
index 86d05cf7b3f834..86510bcb7c2ca9 100644
--- a/tools/eslint/lib/token-store/index.js
+++ b/tools/eslint/lib/token-store/index.js
@@ -12,34 +12,15 @@ const assert = require("assert");
const cursors = require("./cursors");
const ForwardTokenCursor = require("./forward-token-cursor");
const PaddedTokenCursor = require("./padded-token-cursor");
+const astUtils = require("../ast-utils");
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
-const PUBLIC_METHODS = Object.freeze([
- "getTokenByRangeStart",
-
- "getFirstToken",
- "getLastToken",
- "getTokenBefore",
- "getTokenAfter",
- "getFirstTokenBetween",
- "getLastTokenBetween",
-
- "getFirstTokens",
- "getLastTokens",
- "getTokensBefore",
- "getTokensAfter",
- "getFirstTokensBetween",
- "getLastTokensBetween",
-
- "getTokens",
- "getTokensBetween",
-
- "getTokenOrCommentBefore",
- "getTokenOrCommentAfter"
-]);
+const TOKENS = Symbol("tokens");
+const COMMENTS = Symbol("comments");
+const INDEX_MAP = Symbol("indexMap");
/**
* Creates the map from locations to indices in `tokens`.
@@ -192,6 +173,24 @@ function createCursorWithPadding(tokens, comments, indexMap, startLoc, endLoc, b
return createCursorWithCount(cursors.forward, tokens, comments, indexMap, startLoc, endLoc, beforeCount);
}
+/**
+ * Gets comment tokens that are adjacent to the current cursor position.
+ * @param {Cursor} cursor - A cursor instance.
+ * @returns {Array} An array of comment tokens adjacent to the current cursor position.
+ * @private
+ */
+function getAdjacentCommentTokensFromCursor(cursor) {
+ const tokens = [];
+ let currentToken = cursor.getOneToken();
+
+ while (currentToken && astUtils.isCommentToken(currentToken)) {
+ tokens.push(currentToken);
+ currentToken = cursor.getOneToken();
+ }
+
+ return tokens;
+}
+
//------------------------------------------------------------------------------
// Exports
//------------------------------------------------------------------------------
@@ -211,22 +210,13 @@ module.exports = class TokenStore {
/**
* Initializes this token store.
- *
- * ※ `comments` needs to be cloned for backward compatibility.
- * After this initialization, ESLint removes a shebang's comment from `comments`.
- * However, so far we had been concatenating 'tokens' and 'comments' before,
- * so the shebang's comment had remained in the concatenated array.
- * As a result, both the result of `getTokenOrCommentAfter` and `getTokenOrCommentBefore`
- * methods had included the shebang's comment.
- * And some rules depends on this behavior.
- *
* @param {Token[]} tokens - The array of tokens.
* @param {Comment[]} comments - The array of comments.
*/
constructor(tokens, comments) {
- this.tokens = tokens;
- this.comments = comments.slice(0);
- this.indexMap = createIndexMap(tokens, comments);
+ this[TOKENS] = tokens;
+ this[COMMENTS] = comments;
+ this[INDEX_MAP] = createIndexMap(tokens, comments);
}
//--------------------------------------------------------------------------
@@ -243,9 +233,9 @@ module.exports = class TokenStore {
getTokenByRangeStart(offset, options) {
const includeComments = options && options.includeComments;
const token = cursors.forward.createBaseCursor(
- this.tokens,
- this.comments,
- this.indexMap,
+ this[TOKENS],
+ this[COMMENTS],
+ this[INDEX_MAP],
offset,
-1,
includeComments
@@ -269,9 +259,9 @@ module.exports = class TokenStore {
getFirstToken(node, options) {
return createCursorWithSkip(
cursors.forward,
- this.tokens,
- this.comments,
- this.indexMap,
+ this[TOKENS],
+ this[COMMENTS],
+ this[INDEX_MAP],
node.range[0],
node.range[1],
options
@@ -281,18 +271,15 @@ module.exports = class TokenStore {
/**
* Gets the last token of the given node.
* @param {ASTNode} node - The AST node.
- * @param {number|Function|Object} [options=0] - The option object. If this is a number then it's `options.skip`. If this is a function then it's `options.filter`.
- * @param {boolean} [options.includeComments=false] - The flag to iterate comments as well.
- * @param {Function|null} [options.filter=null] - The predicate function to choose tokens.
- * @param {number} [options.skip=0] - The count of tokens the cursor skips.
+ * @param {number|Function|Object} [options=0] - The option object. Same options as getFirstToken()
* @returns {Token|null} An object representing the token.
*/
getLastToken(node, options) {
return createCursorWithSkip(
cursors.backward,
- this.tokens,
- this.comments,
- this.indexMap,
+ this[TOKENS],
+ this[COMMENTS],
+ this[INDEX_MAP],
node.range[0],
node.range[1],
options
@@ -302,18 +289,15 @@ module.exports = class TokenStore {
/**
* Gets the token that precedes a given node or token.
* @param {ASTNode|Token|Comment} node - The AST node or token.
- * @param {number|Function|Object} [options=0] - The option object. If this is a number then it's `options.skip`. If this is a function then it's `options.filter`.
- * @param {boolean} [options.includeComments=false] - The flag to iterate comments as well.
- * @param {Function|null} [options.filter=null] - The predicate function to choose tokens.
- * @param {number} [options.skip=0] - The count of tokens the cursor skips.
+ * @param {number|Function|Object} [options=0] - The option object. Same options as getFirstToken()
* @returns {Token|null} An object representing the token.
*/
getTokenBefore(node, options) {
return createCursorWithSkip(
cursors.backward,
- this.tokens,
- this.comments,
- this.indexMap,
+ this[TOKENS],
+ this[COMMENTS],
+ this[INDEX_MAP],
-1,
node.range[0],
options
@@ -323,18 +307,15 @@ module.exports = class TokenStore {
/**
* Gets the token that follows a given node or token.
* @param {ASTNode|Token|Comment} node - The AST node or token.
- * @param {number|Function|Object} [options=0] - The option object. If this is a number then it's `options.skip`. If this is a function then it's `options.filter`.
- * @param {boolean} [options.includeComments=false] - The flag to iterate comments as well.
- * @param {Function|null} [options.filter=null] - The predicate function to choose tokens.
- * @param {number} [options.skip=0] - The count of tokens the cursor skips.
+ * @param {number|Function|Object} [options=0] - The option object. Same options as getFirstToken()
* @returns {Token|null} An object representing the token.
*/
getTokenAfter(node, options) {
return createCursorWithSkip(
cursors.forward,
- this.tokens,
- this.comments,
- this.indexMap,
+ this[TOKENS],
+ this[COMMENTS],
+ this[INDEX_MAP],
node.range[1],
-1,
options
@@ -345,18 +326,15 @@ module.exports = class TokenStore {
* Gets the first token between two non-overlapping nodes.
* @param {ASTNode|Token|Comment} left - Node before the desired token range.
* @param {ASTNode|Token|Comment} right - Node after the desired token range.
- * @param {number|Function|Object} [options=0] - The option object. If this is a number then it's `options.skip`. If this is a function then it's `options.filter`.
- * @param {boolean} [options.includeComments=false] - The flag to iterate comments as well.
- * @param {Function|null} [options.filter=null] - The predicate function to choose tokens.
- * @param {number} [options.skip=0] - The count of tokens the cursor skips.
+ * @param {number|Function|Object} [options=0] - The option object. Same options as getFirstToken()
* @returns {Token|null} An object representing the token.
*/
getFirstTokenBetween(left, right, options) {
return createCursorWithSkip(
cursors.forward,
- this.tokens,
- this.comments,
- this.indexMap,
+ this[TOKENS],
+ this[COMMENTS],
+ this[INDEX_MAP],
left.range[1],
right.range[0],
options
@@ -367,18 +345,15 @@ module.exports = class TokenStore {
* Gets the last token between two non-overlapping nodes.
* @param {ASTNode|Token|Comment} left Node before the desired token range.
* @param {ASTNode|Token|Comment} right Node after the desired token range.
- * @param {number|Function|Object} [options=0] The option object. If this is a number then it's `options.skip`. If this is a function then it's `options.filter`.
- * @param {boolean} [options.includeComments=false] - The flag to iterate comments as well.
- * @param {Function|null} [options.filter=null] - The predicate function to choose tokens.
- * @param {number} [options.skip=0] - The count of tokens the cursor skips.
- * @returns {Token|null} Tokens between left and right.
+ * @param {number|Function|Object} [options=0] - The option object. Same options as getFirstToken()
+ * @returns {Token|null} An object representing the token.
*/
getLastTokenBetween(left, right, options) {
return createCursorWithSkip(
cursors.backward,
- this.tokens,
- this.comments,
- this.indexMap,
+ this[TOKENS],
+ this[COMMENTS],
+ this[INDEX_MAP],
left.range[1],
right.range[0],
options
@@ -427,9 +402,9 @@ module.exports = class TokenStore {
getFirstTokens(node, options) {
return createCursorWithCount(
cursors.forward,
- this.tokens,
- this.comments,
- this.indexMap,
+ this[TOKENS],
+ this[COMMENTS],
+ this[INDEX_MAP],
node.range[0],
node.range[1],
options
@@ -439,18 +414,15 @@ module.exports = class TokenStore {
/**
* Gets the last `count` tokens of the given node.
* @param {ASTNode} node - The AST node.
- * @param {number|Function|Object} [options=0] - The option object. If this is a number then it's `options.count`. If this is a function then it's `options.filter`.
- * @param {boolean} [options.includeComments=false] - The flag to iterate comments as well.
- * @param {Function|null} [options.filter=null] - The predicate function to choose tokens.
- * @param {number} [options.count=0] - The maximum count of tokens the cursor iterates.
+ * @param {number|Function|Object} [options=0] - The option object. Same options as getFirstTokens()
* @returns {Token[]} Tokens.
*/
getLastTokens(node, options) {
return createCursorWithCount(
cursors.backward,
- this.tokens,
- this.comments,
- this.indexMap,
+ this[TOKENS],
+ this[COMMENTS],
+ this[INDEX_MAP],
node.range[0],
node.range[1],
options
@@ -460,18 +432,15 @@ module.exports = class TokenStore {
/**
* Gets the `count` tokens that precedes a given node or token.
* @param {ASTNode|Token|Comment} node - The AST node or token.
- * @param {number|Function|Object} [options=0] - The option object. If this is a number then it's `options.count`. If this is a function then it's `options.filter`.
- * @param {boolean} [options.includeComments=false] - The flag to iterate comments as well.
- * @param {Function|null} [options.filter=null] - The predicate function to choose tokens.
- * @param {number} [options.count=0] - The maximum count of tokens the cursor iterates.
+ * @param {number|Function|Object} [options=0] - The option object. Same options as getFirstTokens()
* @returns {Token[]} Tokens.
*/
getTokensBefore(node, options) {
return createCursorWithCount(
cursors.backward,
- this.tokens,
- this.comments,
- this.indexMap,
+ this[TOKENS],
+ this[COMMENTS],
+ this[INDEX_MAP],
-1,
node.range[0],
options
@@ -481,18 +450,15 @@ module.exports = class TokenStore {
/**
* Gets the `count` tokens that follows a given node or token.
* @param {ASTNode|Token|Comment} node - The AST node or token.
- * @param {number|Function|Object} [options=0] - The option object. If this is a number then it's `options.count`. If this is a function then it's `options.filter`.
- * @param {boolean} [options.includeComments=false] - The flag to iterate comments as well.
- * @param {Function|null} [options.filter=null] - The predicate function to choose tokens.
- * @param {number} [options.count=0] - The maximum count of tokens the cursor iterates.
+ * @param {number|Function|Object} [options=0] - The option object. Same options as getFirstTokens()
* @returns {Token[]} Tokens.
*/
getTokensAfter(node, options) {
return createCursorWithCount(
cursors.forward,
- this.tokens,
- this.comments,
- this.indexMap,
+ this[TOKENS],
+ this[COMMENTS],
+ this[INDEX_MAP],
node.range[1],
-1,
options
@@ -503,18 +469,15 @@ module.exports = class TokenStore {
* Gets the first `count` tokens between two non-overlapping nodes.
* @param {ASTNode|Token|Comment} left - Node before the desired token range.
* @param {ASTNode|Token|Comment} right - Node after the desired token range.
- * @param {number|Function|Object} [options=0] - The option object. If this is a number then it's `options.count`. If this is a function then it's `options.filter`.
- * @param {boolean} [options.includeComments=false] - The flag to iterate comments as well.
- * @param {Function|null} [options.filter=null] - The predicate function to choose tokens.
- * @param {number} [options.count=0] - The maximum count of tokens the cursor iterates.
+ * @param {number|Function|Object} [options=0] - The option object. Same options as getFirstTokens()
* @returns {Token[]} Tokens between left and right.
*/
getFirstTokensBetween(left, right, options) {
return createCursorWithCount(
cursors.forward,
- this.tokens,
- this.comments,
- this.indexMap,
+ this[TOKENS],
+ this[COMMENTS],
+ this[INDEX_MAP],
left.range[1],
right.range[0],
options
@@ -525,18 +488,15 @@ module.exports = class TokenStore {
* Gets the last `count` tokens between two non-overlapping nodes.
* @param {ASTNode|Token|Comment} left Node before the desired token range.
* @param {ASTNode|Token|Comment} right Node after the desired token range.
- * @param {number|Function|Object} [options=0] The option object. If this is a number then it's `options.count`. If this is a function then it's `options.filter`.
- * @param {boolean} [options.includeComments=false] - The flag to iterate comments as well.
- * @param {Function|null} [options.filter=null] - The predicate function to choose tokens.
- * @param {number} [options.count=0] - The maximum count of tokens the cursor iterates.
+ * @param {number|Function|Object} [options=0] - The option object. Same options as getFirstTokens()
* @returns {Token[]} Tokens between left and right.
*/
getLastTokensBetween(left, right, options) {
return createCursorWithCount(
cursors.backward,
- this.tokens,
- this.comments,
- this.indexMap,
+ this[TOKENS],
+ this[COMMENTS],
+ this[INDEX_MAP],
left.range[1],
right.range[0],
options
@@ -561,9 +521,9 @@ module.exports = class TokenStore {
*/
getTokens(node, beforeCount, afterCount) {
return createCursorWithPadding(
- this.tokens,
- this.comments,
- this.indexMap,
+ this[TOKENS],
+ this[COMMENTS],
+ this[INDEX_MAP],
node.range[0],
node.range[1],
beforeCount,
@@ -590,15 +550,63 @@ module.exports = class TokenStore {
*/
getTokensBetween(left, right, padding) {
return createCursorWithPadding(
- this.tokens,
- this.comments,
- this.indexMap,
+ this[TOKENS],
+ this[COMMENTS],
+ this[INDEX_MAP],
left.range[1],
right.range[0],
padding,
padding
).getAllTokens();
}
-};
-module.exports.PUBLIC_METHODS = PUBLIC_METHODS;
+ /**
+ * Gets all comment tokens directly before the given node or token.
+ * @param {ASTNode|token} nodeOrToken The AST node or token to check for adjacent comment tokens.
+ * @returns {Array} An array of comments in occurrence order.
+ */
+ getCommentsBefore(nodeOrToken) {
+ const cursor = createCursorWithCount(
+ cursors.backward,
+ this[TOKENS],
+ this[COMMENTS],
+ this[INDEX_MAP],
+ -1,
+ nodeOrToken.range[0],
+ { includeComments: true }
+ );
+
+ return getAdjacentCommentTokensFromCursor(cursor).reverse();
+ }
+
+ /**
+ * Gets all comment tokens directly after the given node or token.
+ * @param {ASTNode|token} nodeOrToken The AST node or token to check for adjacent comment tokens.
+ * @returns {Array} An array of comments in occurrence order.
+ */
+ getCommentsAfter(nodeOrToken) {
+ const cursor = createCursorWithCount(
+ cursors.forward,
+ this[TOKENS],
+ this[COMMENTS],
+ this[INDEX_MAP],
+ nodeOrToken.range[1],
+ -1,
+ { includeComments: true }
+ );
+
+ return getAdjacentCommentTokensFromCursor(cursor);
+ }
+
+ /**
+ * Gets all comment tokens inside the given node.
+ * @param {ASTNode} node The AST node to get the comments for.
+ * @returns {Array} An array of comments in occurrence order.
+ */
+ getCommentsInside(node) {
+ return this.getTokens(node, {
+ includeComments: true,
+ filter: astUtils.isCommentToken
+ });
+ }
+};
diff --git a/tools/eslint/lib/util/comment-event-generator.js b/tools/eslint/lib/util/comment-event-generator.js
deleted file mode 100644
index 239a9834d0ed20..00000000000000
--- a/tools/eslint/lib/util/comment-event-generator.js
+++ /dev/null
@@ -1,116 +0,0 @@
-/**
- * @fileoverview The event generator for comments.
- * @author Toru Nagashima
- */
-
-"use strict";
-
-//------------------------------------------------------------------------------
-// Helpers
-//------------------------------------------------------------------------------
-
-/**
- * Check collection of comments to prevent double event for comment as
- * leading and trailing, then emit event if passing
- * @param {ASTNode[]} comments - Collection of comment nodes
- * @param {EventEmitter} emitter - The event emitter which is the destination of events.
- * @param {Object[]} locs - List of locations of previous comment nodes
- * @param {string} eventName - Event name postfix
- * @returns {void}
- */
-function emitComments(comments, emitter, locs, eventName) {
- if (comments.length > 0) {
- comments.forEach(node => {
- const index = locs.indexOf(node.loc);
-
- if (index >= 0) {
- locs.splice(index, 1);
- } else {
- locs.push(node.loc);
- emitter.emit(node.type + eventName, node);
- }
- });
- }
-}
-
-/**
- * Shortcut to check and emit enter of comment nodes
- * @param {CommentEventGenerator} generator - A generator to emit.
- * @param {ASTNode[]} comments - Collection of comment nodes
- * @returns {void}
- */
-function emitCommentsEnter(generator, comments) {
- emitComments(
- comments,
- generator.emitter,
- generator.commentLocsEnter,
- "Comment");
-}
-
-/**
- * Shortcut to check and emit exit of comment nodes
- * @param {CommentEventGenerator} generator - A generator to emit.
- * @param {ASTNode[]} comments Collection of comment nodes
- * @returns {void}
- */
-function emitCommentsExit(generator, comments) {
- emitComments(
- comments,
- generator.emitter,
- generator.commentLocsExit,
- "Comment:exit");
-}
-
-//------------------------------------------------------------------------------
-// Public Interface
-//------------------------------------------------------------------------------
-
-/**
- * The event generator for comments.
- * This is the decorator pattern.
- * This generates events of comments before/after events which are generated the original generator.
- *
- * Comment event generator class
- */
-class CommentEventGenerator {
-
- /**
- * @param {EventGenerator} originalEventGenerator - An event generator which is the decoration target.
- * @param {SourceCode} sourceCode - A source code which has comments.
- */
- constructor(originalEventGenerator, sourceCode) {
- this.original = originalEventGenerator;
- this.emitter = originalEventGenerator.emitter;
- this.sourceCode = sourceCode;
- this.commentLocsEnter = [];
- this.commentLocsExit = [];
- }
-
- /**
- * Emits an event of entering comments.
- * @param {ASTNode} node - A node which was entered.
- * @returns {void}
- */
- enterNode(node) {
- const comments = this.sourceCode.getComments(node);
-
- emitCommentsEnter(this, comments.leading);
- this.original.enterNode(node);
- emitCommentsEnter(this, comments.trailing);
- }
-
- /**
- * Emits an event of leaving comments.
- * @param {ASTNode} node - A node which was left.
- * @returns {void}
- */
- leaveNode(node) {
- const comments = this.sourceCode.getComments(node);
-
- emitCommentsExit(this, comments.trailing);
- this.original.leaveNode(node);
- emitCommentsExit(this, comments.leading);
- }
-}
-
-module.exports = CommentEventGenerator;
diff --git a/tools/eslint/lib/util/glob-util.js b/tools/eslint/lib/util/glob-util.js
index 4c21fc55106d99..6a1f150a599a40 100644
--- a/tools/eslint/lib/util/glob-util.js
+++ b/tools/eslint/lib/util/glob-util.js
@@ -11,7 +11,6 @@
const fs = require("fs"),
path = require("path"),
GlobSync = require("./glob"),
- shell = require("shelljs"),
pathUtil = require("./path-util"),
IgnoredPaths = require("../ignored-paths");
@@ -64,7 +63,7 @@ function processPath(options) {
let newPath = pathname;
const resolvedPath = path.resolve(cwd, pathname);
- if (shell.test("-d", resolvedPath)) {
+ if (fs.existsSync(resolvedPath) && fs.statSync(resolvedPath).isDirectory()) {
newPath = pathname.replace(/[/\\]$/, "") + suffix;
}
@@ -151,10 +150,10 @@ function listFilesToProcess(globPatterns, options) {
globPatterns.forEach(pattern => {
const file = path.resolve(cwd, pattern);
- if (shell.test("-f", file)) {
+ if (fs.existsSync(file) && fs.statSync(file).isFile()) {
const ignoredPaths = new IgnoredPaths(options);
- addFile(fs.realpathSync(file), !shell.test("-d", file), ignoredPaths);
+ addFile(fs.realpathSync(file), true, ignoredPaths);
} else {
// regex to find .hidden or /.hidden patterns, but not ./relative or ../relative
diff --git a/tools/eslint/lib/util/module-resolver.js b/tools/eslint/lib/util/module-resolver.js
index 505c572822699b..470a54f7c45713 100644
--- a/tools/eslint/lib/util/module-resolver.js
+++ b/tools/eslint/lib/util/module-resolver.js
@@ -68,7 +68,7 @@ class ModuleResolver {
* lookup file paths when require() is called. So, we are hooking into the
* exact same logic that Node.js uses.
*/
- const result = Module._findPath(name, lookupPaths); // eslint-disable-line no-underscore-dangle
+ const result = Module._findPath(name, lookupPaths); // eslint-disable-line no-underscore-dangle
if (!result) {
throw new Error(`Cannot find module '${name}'`);
diff --git a/tools/eslint/lib/util/npm-util.js b/tools/eslint/lib/util/npm-util.js
index ef1c0c62936347..4859fabc9565ab 100644
--- a/tools/eslint/lib/util/npm-util.js
+++ b/tools/eslint/lib/util/npm-util.js
@@ -10,8 +10,8 @@
//------------------------------------------------------------------------------
const fs = require("fs"),
+ childProcess = require("child_process"),
path = require("path"),
- shell = require("shelljs"),
log = require("../logging");
//------------------------------------------------------------------------------
@@ -29,13 +29,13 @@ function findPackageJson(startDir) {
let dir = path.resolve(startDir || process.cwd());
do {
- const pkgfile = path.join(dir, "package.json");
+ const pkgFile = path.join(dir, "package.json");
- if (!shell.test("-f", pkgfile)) {
+ if (!fs.existsSync(pkgFile) || !fs.statSync(pkgFile).isFile()) {
dir = path.join(dir, "..");
continue;
}
- return pkgfile;
+ return pkgFile;
} while (dir !== path.resolve(dir, ".."));
return null;
}
@@ -53,7 +53,7 @@ function installSyncSaveDev(packages) {
if (Array.isArray(packages)) {
packages = packages.join(" ");
}
- shell.exec(`npm i --save-dev ${packages}`, { stdio: "inherit" });
+ childProcess.execSync(`npm i --save-dev ${packages}`, { stdio: "inherit", encoding: "utf8" });
}
/**
diff --git a/tools/eslint/lib/util/patterns/letters.js b/tools/eslint/lib/util/patterns/letters.js
index b212cfc9ebd34a..eb255d8f001b70 100644
--- a/tools/eslint/lib/util/patterns/letters.js
+++ b/tools/eslint/lib/util/patterns/letters.js
@@ -34,4 +34,3 @@
"use strict";
module.exports = /[A-Za-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF30-\uDF40\uDF42-\uDF49\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF]|\uD801[\uDC00-\uDC9D\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDE00-\uDE11\uDE13-\uDE2B\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF5D-\uDF61]|\uD805[\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDE00-\uDE2F\uDE44\uDE80-\uDEAA]|\uD806[\uDCA0-\uDCDF\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF98]|[\uD80C\uD840-\uD868\uD86A-\uD86C][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D]|\uD87E[\uDC00-\uDE1D]/;
-
diff --git a/tools/eslint/lib/util/source-code-util.js b/tools/eslint/lib/util/source-code-util.js
index 892c32d22a00e8..6ffd243e2e1c65 100644
--- a/tools/eslint/lib/util/source-code-util.js
+++ b/tools/eslint/lib/util/source-code-util.js
@@ -10,9 +10,8 @@
//------------------------------------------------------------------------------
const CLIEngine = require("../cli-engine"),
- eslint = require("../eslint"),
globUtil = require("./glob-util"),
- baseDefaultOptions = require("../../conf/cli-options");
+ baseDefaultOptions = require("../../conf/default-cli-options");
const debug = require("debug")("eslint:source-code-util");
@@ -38,7 +37,7 @@ function getSourceCodeOfFile(filename, options) {
throw new Error(`(${filename}:${msg.line}:${msg.column}) ${msg.message}`);
}
- const sourceCode = eslint.getSourceCode();
+ const sourceCode = cli.linter.getSourceCode();
return sourceCode;
}
diff --git a/tools/eslint/lib/util/source-code.js b/tools/eslint/lib/util/source-code.js
index 5106c1e61fa98a..af01ff3fafaab3 100644
--- a/tools/eslint/lib/util/source-code.js
+++ b/tools/eslint/lib/util/source-code.js
@@ -101,91 +101,95 @@ function sortedMerge(tokens, comments) {
return result;
}
-
//------------------------------------------------------------------------------
// Public Interface
//------------------------------------------------------------------------------
-/**
- * Represents parsed source code.
- * @param {string} text - The source code text.
- * @param {ASTNode} ast - The Program node of the AST representing the code. This AST should be created from the text that BOM was stripped.
- * @constructor
- */
-function SourceCode(text, ast) {
- validate(ast);
+class SourceCode extends TokenStore {
/**
- * The flag to indicate that the source code has Unicode BOM.
- * @type boolean
+ * Represents parsed source code.
+ * @param {string} text - The source code text.
+ * @param {ASTNode} ast - The Program node of the AST representing the code. This AST should be created from the text that BOM was stripped.
+ * @constructor
*/
- this.hasBOM = (text.charCodeAt(0) === 0xFEFF);
+ constructor(text, ast) {
+ validate(ast);
- /**
- * The original text source code.
- * BOM was stripped from this text.
- * @type string
- */
- this.text = (this.hasBOM ? text.slice(1) : text);
+ super(ast.tokens, ast.comments);
- /**
- * The parsed AST for the source code.
- * @type ASTNode
- */
- this.ast = ast;
+ /**
+ * The flag to indicate that the source code has Unicode BOM.
+ * @type boolean
+ */
+ this.hasBOM = (text.charCodeAt(0) === 0xFEFF);
- /**
- * The source code split into lines according to ECMA-262 specification.
- * This is done to avoid each rule needing to do so separately.
- * @type string[]
- */
- this.lines = [];
- this.lineStartIndices = [0];
-
- const lineEndingPattern = astUtils.createGlobalLinebreakMatcher();
- let match;
-
- /*
- * Previously, this was implemented using a regex that
- * matched a sequence of non-linebreak characters followed by a
- * linebreak, then adding the lengths of the matches. However,
- * this caused a catastrophic backtracking issue when the end
- * of a file contained a large number of non-newline characters.
- * To avoid this, the current implementation just matches newlines
- * and uses match.index to get the correct line start indices.
- */
- while ((match = lineEndingPattern.exec(this.text))) {
- this.lines.push(this.text.slice(this.lineStartIndices[this.lineStartIndices.length - 1], match.index));
- this.lineStartIndices.push(match.index + match[0].length);
- }
- this.lines.push(this.text.slice(this.lineStartIndices[this.lineStartIndices.length - 1]));
+ /**
+ * The original text source code.
+ * BOM was stripped from this text.
+ * @type string
+ */
+ this.text = (this.hasBOM ? text.slice(1) : text);
- this.tokensAndComments = sortedMerge(ast.tokens, ast.comments);
+ /**
+ * The parsed AST for the source code.
+ * @type ASTNode
+ */
+ this.ast = ast;
- // create token store methods
- const tokenStore = new TokenStore(ast.tokens, ast.comments);
+ // Check the source text for the presence of a shebang since it is parsed as a standard line comment.
+ const shebangMatched = this.text.match(astUtils.SHEBANG_MATCHER);
+ const hasShebang = shebangMatched && ast.comments.length && ast.comments[0].value === shebangMatched[1];
- for (const methodName of TokenStore.PUBLIC_METHODS) {
- this[methodName] = tokenStore[methodName].bind(tokenStore);
- }
+ if (hasShebang) {
+ ast.comments[0].type = "Shebang";
+ }
- // don't allow modification of this object
- Object.freeze(this);
- Object.freeze(this.lines);
-}
+ this.tokensAndComments = sortedMerge(ast.tokens, ast.comments);
-/**
- * Split the source code into multiple lines based on the line delimiters
- * @param {string} text Source code as a string
- * @returns {string[]} Array of source code lines
- * @public
- */
-SourceCode.splitLines = function(text) {
- return text.split(astUtils.createGlobalLinebreakMatcher());
-};
+ /**
+ * The source code split into lines according to ECMA-262 specification.
+ * This is done to avoid each rule needing to do so separately.
+ * @type string[]
+ */
+ this.lines = [];
+ this.lineStartIndices = [0];
+
+ const lineEndingPattern = astUtils.createGlobalLinebreakMatcher();
+ let match;
+
+ /*
+ * Previously, this was implemented using a regex that
+ * matched a sequence of non-linebreak characters followed by a
+ * linebreak, then adding the lengths of the matches. However,
+ * this caused a catastrophic backtracking issue when the end
+ * of a file contained a large number of non-newline characters.
+ * To avoid this, the current implementation just matches newlines
+ * and uses match.index to get the correct line start indices.
+ */
+ while ((match = lineEndingPattern.exec(this.text))) {
+ this.lines.push(this.text.slice(this.lineStartIndices[this.lineStartIndices.length - 1], match.index));
+ this.lineStartIndices.push(match.index + match[0].length);
+ }
+ this.lines.push(this.text.slice(this.lineStartIndices[this.lineStartIndices.length - 1]));
-SourceCode.prototype = {
- constructor: SourceCode,
+ // Cache for comments found using getComments().
+ this._commentCache = new WeakMap();
+
+ // don't allow modification of this object
+ Object.freeze(this);
+ Object.freeze(this.lines);
+ }
+
+ /**
+ * Split the source code into multiple lines based on the line delimiters
+ * @param {string} text Source code as a string
+ * @returns {string[]} Array of source code lines
+ * @public
+ */
+ static splitLines(text) {
+ return text.split(astUtils.createGlobalLinebreakMatcher());
+ }
/**
* Gets the source code for the given node.
@@ -200,9 +204,7 @@ SourceCode.prototype = {
node.range[1] + (afterCount || 0));
}
return this.text;
-
-
- },
+ }
/**
* Gets the entire source text split into an array of lines.
@@ -210,7 +212,7 @@ SourceCode.prototype = {
*/
getLines() {
return this.lines;
- },
+ }
/**
* Retrieves an array containing all comments in the source code.
@@ -218,7 +220,7 @@ SourceCode.prototype = {
*/
getAllComments() {
return this.ast.comments;
- },
+ }
/**
* Gets all comments for the given node.
@@ -227,60 +229,111 @@ SourceCode.prototype = {
* @public
*/
getComments(node) {
+ if (this._commentCache.has(node)) {
+ return this._commentCache.get(node);
+ }
- let leadingComments = node.leadingComments || [];
- const trailingComments = node.trailingComments || [];
+ const comments = {
+ leading: [],
+ trailing: []
+ };
/*
- * espree adds a "comments" array on Program nodes rather than
- * leadingComments/trailingComments. Comments are only left in the
- * Program node comments array if there is no executable code.
+ * Return all comments as leading comments of the Program node when
+ * there is no executable code.
*/
if (node.type === "Program") {
if (node.body.length === 0) {
- leadingComments = node.comments;
+ comments.leading = node.comments;
+ }
+ } else {
+
+ /* Return comments as trailing comments of nodes that only contain
+ * comments (to mimic the comment attachment behavior present in Espree).
+ */
+ if ((node.type === "BlockStatement" || node.type === "ClassBody") && node.body.length === 0 ||
+ node.type === "ObjectExpression" && node.properties.length === 0 ||
+ node.type === "ArrayExpression" && node.elements.length === 0 ||
+ node.type === "SwitchStatement" && node.cases.length === 0
+ ) {
+ comments.trailing = this.getTokens(node, {
+ includeComments: true,
+ filter: astUtils.isCommentToken
+ });
+ }
+
+ /*
+ * Iterate over tokens before and after node and collect comment tokens.
+ * Do not include comments that exist outside of the parent node
+ * to avoid duplication.
+ */
+ let currentToken = this.getTokenBefore(node, { includeComments: true });
+
+ while (currentToken && astUtils.isCommentToken(currentToken)) {
+ if (node.parent && (currentToken.start < node.parent.start)) {
+ break;
+ }
+ comments.leading.push(currentToken);
+ currentToken = this.getTokenBefore(currentToken, { includeComments: true });
+ }
+
+ comments.leading.reverse();
+
+ currentToken = this.getTokenAfter(node, { includeComments: true });
+
+ while (currentToken && astUtils.isCommentToken(currentToken)) {
+ if (node.parent && (currentToken.end > node.parent.end)) {
+ break;
+ }
+ comments.trailing.push(currentToken);
+ currentToken = this.getTokenAfter(currentToken, { includeComments: true });
}
}
- return {
- leading: leadingComments,
- trailing: trailingComments
- };
- },
+ this._commentCache.set(node, comments);
+ return comments;
+ }
/**
* Retrieves the JSDoc comment for a given node.
* @param {ASTNode} node The AST node to get the comment for.
- * @returns {ASTNode} The BlockComment node containing the JSDoc for the
+ * @returns {ASTNode} The Block comment node containing the JSDoc for the
* given node or null if not found.
* @public
*/
getJSDocComment(node) {
-
let parent = node.parent;
+ const leadingComments = this.getCommentsBefore(node);
switch (node.type) {
case "ClassDeclaration":
case "FunctionDeclaration":
if (looksLikeExport(parent)) {
- return findJSDocComment(parent.leadingComments, parent.loc.start.line);
+ return findJSDocComment(this.getCommentsBefore(parent), parent.loc.start.line);
}
- return findJSDocComment(node.leadingComments, node.loc.start.line);
+ return findJSDocComment(leadingComments, node.loc.start.line);
case "ClassExpression":
- return findJSDocComment(parent.parent.leadingComments, parent.parent.loc.start.line);
+ return findJSDocComment(this.getCommentsBefore(parent.parent), parent.parent.loc.start.line);
case "ArrowFunctionExpression":
case "FunctionExpression":
-
if (parent.type !== "CallExpression" && parent.type !== "NewExpression") {
- while (parent && !parent.leadingComments && !/Function/.test(parent.type) && parent.type !== "MethodDefinition" && parent.type !== "Property") {
+ let parentLeadingComments = this.getCommentsBefore(parent);
+
+ while (!parentLeadingComments.length && !/Function/.test(parent.type) && parent.type !== "MethodDefinition" && parent.type !== "Property") {
parent = parent.parent;
+
+ if (!parent) {
+ break;
+ }
+
+ parentLeadingComments = this.getCommentsBefore(parent);
}
- return parent && (parent.type !== "FunctionDeclaration") ? findJSDocComment(parent.leadingComments, parent.loc.start.line) : null;
- } else if (node.leadingComments) {
- return findJSDocComment(node.leadingComments, node.loc.start.line);
+ return parent && parent.type !== "FunctionDeclaration" && parent.type !== "Program" ? findJSDocComment(parentLeadingComments, parent.loc.start.line) : null;
+ } else if (leadingComments.length) {
+ return findJSDocComment(leadingComments, node.loc.start.line);
}
// falls through
@@ -288,7 +341,7 @@ SourceCode.prototype = {
default:
return null;
}
- },
+ }
/**
* Gets the deepest node containing a range index.
@@ -317,7 +370,7 @@ SourceCode.prototype = {
});
return result ? Object.assign({ parent: resultParent }, result) : null;
- },
+ }
/**
* Determines if two tokens have at least one whitespace character
@@ -332,7 +385,7 @@ SourceCode.prototype = {
const text = this.text.slice(first.range[1], second.range[0]);
return /\s/.test(text.replace(/\/\*.*?\*\//g, ""));
- },
+ }
/**
* Converts a source text index into a (line, column) pair.
@@ -366,8 +419,7 @@ SourceCode.prototype = {
const lineNumber = lodash.sortedLastIndex(this.lineStartIndices, index);
return { line: lineNumber, column: index - this.lineStartIndices[lineNumber - 1] };
-
- },
+ }
/**
* Converts a (line, column) pair into a range index.
@@ -410,7 +462,6 @@ SourceCode.prototype = {
return positionIndex;
}
-};
-
+}
module.exports = SourceCode;
diff --git a/tools/eslint/node_modules/.bin/remark b/tools/eslint/node_modules/.bin/remark
deleted file mode 100644
index ba550cb8cd2550..00000000000000
--- a/tools/eslint/node_modules/.bin/remark
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh
-basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
-
-case `uname` in
- *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
-esac
-
-if [ -x "$basedir/node" ]; then
- "$basedir/node" "$basedir/../remark/cli.js" "$@"
- ret=$?
-else
- node "$basedir/../remark/cli.js" "$@"
- ret=$?
-fi
-exit $ret
diff --git a/tools/eslint/node_modules/.bin/remark b/tools/eslint/node_modules/.bin/remark
new file mode 120000
index 00000000000000..86e23b4873f46e
--- /dev/null
+++ b/tools/eslint/node_modules/.bin/remark
@@ -0,0 +1 @@
+../remark/cli.js
\ No newline at end of file
diff --git a/tools/eslint/node_modules/.bin/remark.cmd b/tools/eslint/node_modules/.bin/remark.cmd
deleted file mode 100644
index 78192589eb2512..00000000000000
--- a/tools/eslint/node_modules/.bin/remark.cmd
+++ /dev/null
@@ -1,7 +0,0 @@
-@IF EXIST "%~dp0\node.exe" (
- "%~dp0\node.exe" "%~dp0\..\remark\cli.js" %*
-) ELSE (
- @SETLOCAL
- @SET PATHEXT=%PATHEXT:;.JS;=;%
- node "%~dp0\..\remark\cli.js" %*
-)
\ No newline at end of file
diff --git a/tools/eslint/node_modules/.bin/shjs b/tools/eslint/node_modules/.bin/shjs
deleted file mode 120000
index a0449975bf894c..00000000000000
--- a/tools/eslint/node_modules/.bin/shjs
+++ /dev/null
@@ -1 +0,0 @@
-../shelljs/bin/shjs
\ No newline at end of file
diff --git a/tools/eslint/node_modules/acorn/README.md b/tools/eslint/node_modules/acorn/README.md
index 2186c7e70d136e..b7efe2341971aa 100644
--- a/tools/eslint/node_modules/acorn/README.md
+++ b/tools/eslint/node_modules/acorn/README.md
@@ -2,7 +2,7 @@
[](https://travis-ci.org/ternjs/acorn)
[](https://www.npmjs.com/package/acorn)
-[](https://cdnjs.com/libraries/acorn)
+[](https://cdnjs.com/libraries/acorn)
[Author funding status: ](https://marijnhaverbeke.nl/fund/)
A tiny, fast JavaScript parser, written completely in JavaScript.
diff --git a/tools/eslint/node_modules/ajv/README.md b/tools/eslint/node_modules/ajv/README.md
index 984b7ba12d6f9c..9d4fcbb9cb3f58 100644
--- a/tools/eslint/node_modules/ajv/README.md
+++ b/tools/eslint/node_modules/ajv/README.md
@@ -1,3 +1,5 @@
+
+
# Ajv: Another JSON Schema Validator
The fastest JSON Schema validator for node.js and browser. Supports [v5 proposals](https://github.com/json-schema/json-schema/wiki/v5-Proposals).
@@ -11,9 +13,9 @@ The fastest JSON Schema validator for node.js and browser. Supports [v5 proposal
[](https://gitter.im/ajv-validator/ajv)
-__Please note__: You can start using NEW beta version [5.0.3](https://github.com/epoberezkin/ajv/releases/tag/5.0.3-beta.0) (see [migration guide from 4.x.x](https://github.com/epoberezkin/ajv/releases/tag/5.0.1-beta.0)) with the support of JSON-Schema draft-06 (not officially published yet): `npm install ajv@^5.0.3-beta`.
+__Please note__: You can start using NEW beta version [5.0.4](https://github.com/epoberezkin/ajv/releases/tag/5.0.4-beta.3) (see [migration guide from 4.x.x](https://github.com/epoberezkin/ajv/releases/tag/5.0.1-beta.0)) with the support of JSON-Schema draft-06 (not officially published yet): `npm install ajv@^5.0.4-beta`.
-Also see [docs](https://github.com/epoberezkin/ajv/tree/5.0.3-beta.0) for 5.0.3.
+Also see [docs](https://github.com/epoberezkin/ajv/tree/5.0.4-beta.3) for 5.0.4.
## Contents
@@ -94,10 +96,10 @@ Currently Ajv is the only validator that passes all the tests from [JSON Schema
npm install ajv
```
-To install a stable beta version [5.0.3](https://github.com/epoberezkin/ajv/releases/tag/5.0.3-beta.0) (see [migration guide from 4.x.x](https://github.com/epoberezkin/ajv/releases/tag/5.0.1-beta.0)):
+To install a stable beta version [5.0.4](https://github.com/epoberezkin/ajv/releases/tag/5.0.4-beta.3) (see [migration guide from 4.x.x](https://github.com/epoberezkin/ajv/releases/tag/5.0.1-beta.0)):
```
-npm install ajv@^5.0.3-beta
+npm install ajv@^5.0.4-beta
```
@@ -163,7 +165,7 @@ Ajv is tested with these browsers:
[](https://saucelabs.com/u/epoberezkin)
-__Please note__: some frameworks, e.g. Dojo, may redifine global require in such way that is not compatible with CommonJS module format. In such case Ajv bundle has to be loaded before the framework and then you can use global Ajv (see issue [#234](https://github.com/epoberezkin/ajv/issues/234)).
+__Please note__: some frameworks, e.g. Dojo, may redefine global require in such way that is not compatible with CommonJS module format. In such case Ajv bundle has to be loaded before the framework and then you can use global Ajv (see issue [#234](https://github.com/epoberezkin/ajv/issues/234)).
## Command line interface
@@ -600,7 +602,7 @@ If the option were `"failing"` then property `additional1` would have been remov
__Please note__: If you use `removeAdditional` option with `additionalProperties` keyword inside `anyOf`/`oneOf` keywords your validation can fail with this schema, for example:
-```JSON
+```json
{
"type": "object",
"oneOf": [
@@ -628,7 +630,7 @@ With the option `removeAdditional: true` the validation will pass for the object
While this behaviour is unexpected (issues [#129](https://github.com/epoberezkin/ajv/issues/129), [#134](https://github.com/epoberezkin/ajv/issues/134)), it is correct. To have the expected behaviour (both objects are allowed and additional properties are removed) the schema has to be refactored in this way:
-```JSON
+```json
{
"type": "object",
"properties": {
@@ -1167,7 +1169,7 @@ Properties of `params` object in errors depend on the keyword that failed valida
- [chai-ajv-json-schema](https://github.com/peon374/chai-ajv-json-schema) - chai plugin to us JSON-schema with expect in mocha tests
- [grunt-jsonschema-ajv](https://github.com/SignpostMarv/grunt-jsonschema-ajv) - Grunt plugin for validating files against JSON-Schema
- [extract-text-webpack-plugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) - extract text from bundle into a file
-- [electron-builder](https://github.com/electron-userland/electron-builder) - a solution to package and build a ready for distribution Electron app
+- [electron-builder](https://github.com/electron-userland/electron-builder) - a solution to package and build a ready for distribution Electron app
- [addons-linter](https://github.com/mozilla/addons-linter) - Mozilla Add-ons Linter
- [gh-pages-generator](https://github.com/epoberezkin/gh-pages-generator) - multi-page site generator converting markdown files to GitHub pages
diff --git a/tools/eslint/node_modules/ajv/dist/ajv.bundle.js b/tools/eslint/node_modules/ajv/dist/ajv.bundle.js
index 1b76cb9f844092..b624d136778b74 100644
--- a/tools/eslint/node_modules/ajv/dist/ajv.bundle.js
+++ b/tools/eslint/node_modules/ajv/dist/ajv.bundle.js
@@ -331,7 +331,7 @@ var util = require('./util');
var DATE = /^\d\d\d\d-(\d\d)-(\d\d)$/;
var DAYS = [0,31,29,31,30,31,30,31,31,30,31,30,31];
var TIME = /^(\d\d):(\d\d):(\d\d)(\.\d+)?(z|[+-]\d\d:\d\d)?$/i;
-var HOSTNAME = /^[0-9a-z](?:(?:[-0-9a-z]{0,61})?[0-9a-z])?(\.[0-9a-z](?:(?:[-0-9a-z]{0,61})?[0-9a-z])?)*$/i;
+var HOSTNAME = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[-0-9a-z]{0,61}[0-9a-z])?)*$/i;
var URI = /^(?:[a-z][a-z0-9+\-.]*:)?(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)(?:\?(?:[a-z0-9\-._~!$&'()*+,;=:@\/?]|%[0-9a-f]{2})*)?(?:\#(?:[a-z0-9\-._~!$&'()*+,;=:@\/?]|%[0-9a-f]{2})*)?$/i;
var UUID = /^(?:urn\:uuid\:)?[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/i;
var JSON_POINTER = /^(?:\/(?:[^~\/]|~0|~1)*)*$|^\#(?:\/(?:[a-z0-9_\-\.!$&'()*+,;:=@]|%[0-9a-f]{2}|~0|~1)*)*$/i;
@@ -881,7 +881,7 @@ function vars(arr, statement) {
return code;
}
-},{"../async":1,"../dotjs/validate":36,"./equal":4,"./resolve":7,"./util":11,"./validation_error":12,"co":47,"json-stable-stringify":48}],7:[function(require,module,exports){
+},{"../async":1,"../dotjs/validate":36,"./equal":4,"./resolve":7,"./util":11,"./validation_error":12,"co":41,"json-stable-stringify":42}],7:[function(require,module,exports){
'use strict';
var url = require('url')
@@ -1150,7 +1150,7 @@ function resolveIds(schema) {
}
}
-},{"./equal":4,"./schema_obj":9,"./util":11,"url":45}],8:[function(require,module,exports){
+},{"./equal":4,"./schema_obj":9,"./util":11,"url":50}],8:[function(require,module,exports){
'use strict';
var ruleModules = require('./_rules')
@@ -1484,7 +1484,7 @@ function unescapeJsonPointer(str) {
return str.replace(/~1/g, '/').replace(/~0/g, '~');
}
-},{"./ucs2length":10,"json-stable-stringify":48}],12:[function(require,module,exports){
+},{"./ucs2length":10,"json-stable-stringify":42}],12:[function(require,module,exports){
'use strict';
module.exports = ValidationError;
@@ -2098,7 +2098,6 @@ module.exports = function generate_anyOf(it, $keyword) {
var $schemaPath = it.schemaPath + it.util.getProperty($keyword);
var $errSchemaPath = it.errSchemaPath + '/' + $keyword;
var $breakOnError = !it.opts.allErrors;
- var $errorKeyword;
var $data = 'data' + ($dataLvl || '');
var $valid = 'valid' + $lvl;
var $errs = 'errs__' + $lvl;
@@ -2132,7 +2131,7 @@ module.exports = function generate_anyOf(it, $keyword) {
it.compositeRule = $it.compositeRule = $wasComposite;
out += ' ' + ($closingBraces) + ' if (!' + ($valid) + ') { var err = '; /* istanbul ignore else */
if (it.createErrors !== false) {
- out += ' { keyword: \'' + ($errorKeyword || 'anyOf') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} ';
+ out += ' { keyword: \'' + ('anyOf') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} ';
if (it.opts.messages !== false) {
out += ' , message: \'should match some schema in anyOf\' ';
}
@@ -2166,7 +2165,6 @@ module.exports = function generate_constant(it, $keyword) {
var $schemaPath = it.schemaPath + it.util.getProperty($keyword);
var $errSchemaPath = it.errSchemaPath + '/' + $keyword;
var $breakOnError = !it.opts.allErrors;
- var $errorKeyword;
var $data = 'data' + ($dataLvl || '');
var $valid = 'valid' + $lvl;
var $isData = it.opts.v5 && $schema && $schema.$data,
@@ -2185,7 +2183,7 @@ module.exports = function generate_constant(it, $keyword) {
$$outStack.push(out);
out = ''; /* istanbul ignore else */
if (it.createErrors !== false) {
- out += ' { keyword: \'' + ($errorKeyword || 'constant') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} ';
+ out += ' { keyword: \'' + ('constant') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} ';
if (it.opts.messages !== false) {
out += ' , message: \'should be equal to constant\' ';
}
@@ -2235,9 +2233,8 @@ module.exports = function generate_custom(it, $keyword) {
}
var $rule = this,
$definition = 'definition' + $lvl,
- $rDef = $rule.definition,
- $validate = $rDef.validate,
- $compile, $inline, $macro, $ruleValidate, $validateCode;
+ $rDef = $rule.definition;
+ var $compile, $inline, $macro, $ruleValidate, $validateCode;
if ($isData && $rDef.$data) {
$validateCode = 'keywordValidate' + $lvl;
var $validateSchema = $rDef.validateSchema;
@@ -2444,7 +2441,6 @@ module.exports = function generate_dependencies(it, $keyword) {
var $schemaPath = it.schemaPath + it.util.getProperty($keyword);
var $errSchemaPath = it.errSchemaPath + '/' + $keyword;
var $breakOnError = !it.opts.allErrors;
- var $errorKeyword;
var $data = 'data' + ($dataLvl || '');
var $errs = 'errs__' + $lvl;
var $it = it.util.copy(it);
@@ -2489,7 +2485,7 @@ module.exports = function generate_dependencies(it, $keyword) {
$$outStack.push(out);
out = ''; /* istanbul ignore else */
if (it.createErrors !== false) {
- out += ' { keyword: \'' + ($errorKeyword || 'dependencies') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { property: \'' + (it.util.escapeQuotes($property)) + '\', missingProperty: \'' + ($missingProperty) + '\', depsCount: ' + ($deps.length) + ', deps: \'' + (it.util.escapeQuotes($deps.length == 1 ? $deps[0] : $deps.join(", "))) + '\' } ';
+ out += ' { keyword: \'' + ('dependencies') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { property: \'' + (it.util.escapeQuotes($property)) + '\', missingProperty: \'' + ($missingProperty) + '\', depsCount: ' + ($deps.length) + ', deps: \'' + (it.util.escapeQuotes($deps.length == 1 ? $deps[0] : $deps.join(", "))) + '\' } ';
if (it.opts.messages !== false) {
out += ' , message: \'should have ';
if ($deps.length == 1) {
@@ -2532,7 +2528,7 @@ module.exports = function generate_dependencies(it, $keyword) {
}
out += ' if (' + ($data) + ($prop) + ' === undefined) { var err = '; /* istanbul ignore else */
if (it.createErrors !== false) {
- out += ' { keyword: \'' + ($errorKeyword || 'dependencies') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { property: \'' + (it.util.escapeQuotes($property)) + '\', missingProperty: \'' + ($missingProperty) + '\', depsCount: ' + ($deps.length) + ', deps: \'' + (it.util.escapeQuotes($deps.length == 1 ? $deps[0] : $deps.join(", "))) + '\' } ';
+ out += ' { keyword: \'' + ('dependencies') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { property: \'' + (it.util.escapeQuotes($property)) + '\', missingProperty: \'' + ($missingProperty) + '\', depsCount: ' + ($deps.length) + ', deps: \'' + (it.util.escapeQuotes($deps.length == 1 ? $deps[0] : $deps.join(", "))) + '\' } ';
if (it.opts.messages !== false) {
out += ' , message: \'should have ';
if ($deps.length == 1) {
@@ -2594,7 +2590,6 @@ module.exports = function generate_enum(it, $keyword) {
var $schemaPath = it.schemaPath + it.util.getProperty($keyword);
var $errSchemaPath = it.errSchemaPath + '/' + $keyword;
var $breakOnError = !it.opts.allErrors;
- var $errorKeyword;
var $data = 'data' + ($dataLvl || '');
var $valid = 'valid' + $lvl;
var $isData = it.opts.v5 && $schema && $schema.$data,
@@ -2623,7 +2618,7 @@ module.exports = function generate_enum(it, $keyword) {
$$outStack.push(out);
out = ''; /* istanbul ignore else */
if (it.createErrors !== false) {
- out += ' { keyword: \'' + ($errorKeyword || 'enum') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { allowedValues: schema' + ($lvl) + ' } ';
+ out += ' { keyword: \'' + ('enum') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { allowedValues: schema' + ($lvl) + ' } ';
if (it.opts.messages !== false) {
out += ' , message: \'should be equal to one of the allowed values\' ';
}
@@ -2662,7 +2657,6 @@ module.exports = function generate_format(it, $keyword) {
var $schemaPath = it.schemaPath + it.util.getProperty($keyword);
var $errSchemaPath = it.errSchemaPath + '/' + $keyword;
var $breakOnError = !it.opts.allErrors;
- var $errorKeyword;
var $data = 'data' + ($dataLvl || '');
if (it.opts.format === false) {
if ($breakOnError) {
@@ -2746,7 +2740,7 @@ module.exports = function generate_format(it, $keyword) {
$$outStack.push(out);
out = ''; /* istanbul ignore else */
if (it.createErrors !== false) {
- out += ' { keyword: \'' + ($errorKeyword || 'format') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { format: ';
+ out += ' { keyword: \'' + ('format') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { format: ';
if ($isData) {
out += '' + ($schemaValue);
} else {
@@ -2803,7 +2797,6 @@ module.exports = function generate_items(it, $keyword) {
var $schemaPath = it.schemaPath + it.util.getProperty($keyword);
var $errSchemaPath = it.errSchemaPath + '/' + $keyword;
var $breakOnError = !it.opts.allErrors;
- var $errorKeyword;
var $data = 'data' + ($dataLvl || '');
var $valid = 'valid' + $lvl;
var $errs = 'errs__' + $lvl;
@@ -2827,7 +2820,7 @@ module.exports = function generate_items(it, $keyword) {
$$outStack.push(out);
out = ''; /* istanbul ignore else */
if (it.createErrors !== false) {
- out += ' { keyword: \'' + ($errorKeyword || 'additionalItems') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { limit: ' + ($schema.length) + ' } ';
+ out += ' { keyword: \'' + ('additionalItems') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { limit: ' + ($schema.length) + ' } ';
if (it.opts.messages !== false) {
out += ' , message: \'should NOT have more than ' + ($schema.length) + ' items\' ';
}
@@ -2950,7 +2943,6 @@ module.exports = function generate_multipleOf(it, $keyword) {
var $schemaPath = it.schemaPath + it.util.getProperty($keyword);
var $errSchemaPath = it.errSchemaPath + '/' + $keyword;
var $breakOnError = !it.opts.allErrors;
- var $errorKeyword;
var $data = 'data' + ($dataLvl || '');
var $isData = it.opts.v5 && $schema && $schema.$data,
$schemaValue;
@@ -2979,7 +2971,7 @@ module.exports = function generate_multipleOf(it, $keyword) {
$$outStack.push(out);
out = ''; /* istanbul ignore else */
if (it.createErrors !== false) {
- out += ' { keyword: \'' + ($errorKeyword || 'multipleOf') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { multipleOf: ' + ($schemaValue) + ' } ';
+ out += ' { keyword: \'' + ('multipleOf') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { multipleOf: ' + ($schemaValue) + ' } ';
if (it.opts.messages !== false) {
out += ' , message: \'should be multiple of ';
if ($isData) {
@@ -3029,7 +3021,6 @@ module.exports = function generate_not(it, $keyword) {
var $schemaPath = it.schemaPath + it.util.getProperty($keyword);
var $errSchemaPath = it.errSchemaPath + '/' + $keyword;
var $breakOnError = !it.opts.allErrors;
- var $errorKeyword;
var $data = 'data' + ($dataLvl || '');
var $errs = 'errs__' + $lvl;
var $it = it.util.copy(it);
@@ -3057,7 +3048,7 @@ module.exports = function generate_not(it, $keyword) {
$$outStack.push(out);
out = ''; /* istanbul ignore else */
if (it.createErrors !== false) {
- out += ' { keyword: \'' + ($errorKeyword || 'not') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} ';
+ out += ' { keyword: \'' + ('not') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} ';
if (it.opts.messages !== false) {
out += ' , message: \'should NOT be valid\' ';
}
@@ -3086,7 +3077,7 @@ module.exports = function generate_not(it, $keyword) {
} else {
out += ' var err = '; /* istanbul ignore else */
if (it.createErrors !== false) {
- out += ' { keyword: \'' + ($errorKeyword || 'not') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} ';
+ out += ' { keyword: \'' + ('not') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} ';
if (it.opts.messages !== false) {
out += ' , message: \'should NOT be valid\' ';
}
@@ -3115,7 +3106,6 @@ module.exports = function generate_oneOf(it, $keyword) {
var $schemaPath = it.schemaPath + it.util.getProperty($keyword);
var $errSchemaPath = it.errSchemaPath + '/' + $keyword;
var $breakOnError = !it.opts.allErrors;
- var $errorKeyword;
var $data = 'data' + ($dataLvl || '');
var $valid = 'valid' + $lvl;
var $errs = 'errs__' + $lvl;
@@ -3155,7 +3145,7 @@ module.exports = function generate_oneOf(it, $keyword) {
$$outStack.push(out);
out = ''; /* istanbul ignore else */
if (it.createErrors !== false) {
- out += ' { keyword: \'' + ($errorKeyword || 'oneOf') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} ';
+ out += ' { keyword: \'' + ('oneOf') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} ';
if (it.opts.messages !== false) {
out += ' , message: \'should match exactly one schema in oneOf\' ';
}
@@ -3194,7 +3184,6 @@ module.exports = function generate_pattern(it, $keyword) {
var $schemaPath = it.schemaPath + it.util.getProperty($keyword);
var $errSchemaPath = it.errSchemaPath + '/' + $keyword;
var $breakOnError = !it.opts.allErrors;
- var $errorKeyword;
var $data = 'data' + ($dataLvl || '');
var $isData = it.opts.v5 && $schema && $schema.$data,
$schemaValue;
@@ -3214,7 +3203,7 @@ module.exports = function generate_pattern(it, $keyword) {
$$outStack.push(out);
out = ''; /* istanbul ignore else */
if (it.createErrors !== false) {
- out += ' { keyword: \'' + ($errorKeyword || 'pattern') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { pattern: ';
+ out += ' { keyword: \'' + ('pattern') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { pattern: ';
if ($isData) {
out += '' + ($schemaValue);
} else {
@@ -3271,7 +3260,6 @@ module.exports = function generate_patternRequired(it, $keyword) {
var $schemaPath = it.schemaPath + it.util.getProperty($keyword);
var $errSchemaPath = it.errSchemaPath + '/' + $keyword;
var $breakOnError = !it.opts.allErrors;
- var $errorKeyword;
var $data = 'data' + ($dataLvl || '');
var $valid = 'valid' + $lvl;
var $key = 'key' + $lvl,
@@ -3293,7 +3281,7 @@ module.exports = function generate_patternRequired(it, $keyword) {
var $missingPattern = it.util.escapeQuotes($pProperty);
out += ' if (!' + ($matched) + ') { ' + ($valid) + ' = false; var err = '; /* istanbul ignore else */
if (it.createErrors !== false) {
- out += ' { keyword: \'' + ($errorKeyword || 'patternRequired') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingPattern: \'' + ($missingPattern) + '\' } ';
+ out += ' { keyword: \'' + ('patternRequired') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingPattern: \'' + ($missingPattern) + '\' } ';
if (it.opts.messages !== false) {
out += ' , message: \'should have property matching pattern \\\'' + ($missingPattern) + '\\\'\' ';
}
@@ -3325,7 +3313,6 @@ module.exports = function generate_properties(it, $keyword) {
var $schemaPath = it.schemaPath + it.util.getProperty($keyword);
var $errSchemaPath = it.errSchemaPath + '/' + $keyword;
var $breakOnError = !it.opts.allErrors;
- var $errorKeyword;
var $data = 'data' + ($dataLvl || '');
var $valid = 'valid' + $lvl;
var $errs = 'errs__' + $lvl;
@@ -3419,7 +3406,7 @@ module.exports = function generate_properties(it, $keyword) {
$$outStack.push(out);
out = ''; /* istanbul ignore else */
if (it.createErrors !== false) {
- out += ' { keyword: \'' + ($errorKeyword || 'additionalProperties') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { additionalProperty: \'' + ($additionalProperty) + '\' } ';
+ out += ' { keyword: \'' + ('additionalProperties') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { additionalProperty: \'' + ($additionalProperty) + '\' } ';
if (it.opts.messages !== false) {
out += ' , message: \'should NOT have additional properties\' ';
}
@@ -3539,7 +3526,7 @@ module.exports = function generate_properties(it, $keyword) {
$$outStack.push(out);
out = ''; /* istanbul ignore else */
if (it.createErrors !== false) {
- out += ' { keyword: \'' + ($errorKeyword || 'required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingProperty: \'' + ($missingProperty) + '\' } ';
+ out += ' { keyword: \'' + ('required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingProperty: \'' + ($missingProperty) + '\' } ';
if (it.opts.messages !== false) {
out += ' , message: \'';
if (it.opts._errorDataPathProperty) {
@@ -3684,7 +3671,7 @@ module.exports = function generate_properties(it, $keyword) {
$$outStack.push(out);
out = ''; /* istanbul ignore else */
if (it.createErrors !== false) {
- out += ' { keyword: \'' + ($errorKeyword || 'patternGroups') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { reason: \'' + ($reason) + '\', limit: ' + ($limit) + ', pattern: \'' + (it.util.escapeQuotes($pgProperty)) + '\' } ';
+ out += ' { keyword: \'' + ('patternGroups') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { reason: \'' + ($reason) + '\', limit: ' + ($limit) + ', pattern: \'' + (it.util.escapeQuotes($pgProperty)) + '\' } ';
if (it.opts.messages !== false) {
out += ' , message: \'should NOT have ' + ($moreOrLess) + ' than ' + ($limit) + ' properties matching pattern "' + (it.util.escapeQuotes($pgProperty)) + '"\' ';
}
@@ -3722,7 +3709,7 @@ module.exports = function generate_properties(it, $keyword) {
$$outStack.push(out);
out = ''; /* istanbul ignore else */
if (it.createErrors !== false) {
- out += ' { keyword: \'' + ($errorKeyword || 'patternGroups') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { reason: \'' + ($reason) + '\', limit: ' + ($limit) + ', pattern: \'' + (it.util.escapeQuotes($pgProperty)) + '\' } ';
+ out += ' { keyword: \'' + ('patternGroups') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { reason: \'' + ($reason) + '\', limit: ' + ($limit) + ', pattern: \'' + (it.util.escapeQuotes($pgProperty)) + '\' } ';
if (it.opts.messages !== false) {
out += ' , message: \'should NOT have ' + ($moreOrLess) + ' than ' + ($limit) + ' properties matching pattern "' + (it.util.escapeQuotes($pgProperty)) + '"\' ';
}
@@ -3772,7 +3759,6 @@ module.exports = function generate_ref(it, $keyword) {
var $schema = it.schema[$keyword];
var $errSchemaPath = it.errSchemaPath + '/' + $keyword;
var $breakOnError = !it.opts.allErrors;
- var $errorKeyword;
var $data = 'data' + ($dataLvl || '');
var $valid = 'valid' + $lvl;
var $async, $refCode;
@@ -3794,7 +3780,7 @@ module.exports = function generate_ref(it, $keyword) {
$$outStack.push(out);
out = ''; /* istanbul ignore else */
if (it.createErrors !== false) {
- out += ' { keyword: \'' + ($errorKeyword || '$ref') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { ref: \'' + (it.util.escapeQuotes($schema)) + '\' } ';
+ out += ' { keyword: \'' + ('$ref') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { ref: \'' + (it.util.escapeQuotes($schema)) + '\' } ';
if (it.opts.messages !== false) {
out += ' , message: \'can\\\'t resolve reference ' + (it.util.escapeQuotes($schema)) + '\' ';
}
@@ -3895,7 +3881,6 @@ module.exports = function generate_required(it, $keyword) {
var $schemaPath = it.schemaPath + it.util.getProperty($keyword);
var $errSchemaPath = it.errSchemaPath + '/' + $keyword;
var $breakOnError = !it.opts.allErrors;
- var $errorKeyword;
var $data = 'data' + ($dataLvl || '');
var $valid = 'valid' + $lvl;
var $isData = it.opts.v5 && $schema && $schema.$data,
@@ -3954,7 +3939,7 @@ module.exports = function generate_required(it, $keyword) {
$$outStack.push(out);
out = ''; /* istanbul ignore else */
if (it.createErrors !== false) {
- out += ' { keyword: \'' + ($errorKeyword || 'required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingProperty: \'' + ($missingProperty) + '\' } ';
+ out += ' { keyword: \'' + ('required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingProperty: \'' + ($missingProperty) + '\' } ';
if (it.opts.messages !== false) {
out += ' , message: \'';
if (it.opts._errorDataPathProperty) {
@@ -4008,7 +3993,7 @@ module.exports = function generate_required(it, $keyword) {
$$outStack.push(out);
out = ''; /* istanbul ignore else */
if (it.createErrors !== false) {
- out += ' { keyword: \'' + ($errorKeyword || 'required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingProperty: \'' + ($missingProperty) + '\' } ';
+ out += ' { keyword: \'' + ('required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingProperty: \'' + ($missingProperty) + '\' } ';
if (it.opts.messages !== false) {
out += ' , message: \'';
if (it.opts._errorDataPathProperty) {
@@ -4052,7 +4037,7 @@ module.exports = function generate_required(it, $keyword) {
if ($isData) {
out += ' if (' + ($vSchema) + ' && !Array.isArray(' + ($vSchema) + ')) { var err = '; /* istanbul ignore else */
if (it.createErrors !== false) {
- out += ' { keyword: \'' + ($errorKeyword || 'required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingProperty: \'' + ($missingProperty) + '\' } ';
+ out += ' { keyword: \'' + ('required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingProperty: \'' + ($missingProperty) + '\' } ';
if (it.opts.messages !== false) {
out += ' , message: \'';
if (it.opts._errorDataPathProperty) {
@@ -4073,7 +4058,7 @@ module.exports = function generate_required(it, $keyword) {
}
out += ' for (var ' + ($i) + ' = 0; ' + ($i) + ' < ' + ($vSchema) + '.length; ' + ($i) + '++) { if (' + ($data) + '[' + ($vSchema) + '[' + ($i) + ']] === undefined) { var err = '; /* istanbul ignore else */
if (it.createErrors !== false) {
- out += ' { keyword: \'' + ($errorKeyword || 'required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingProperty: \'' + ($missingProperty) + '\' } ';
+ out += ' { keyword: \'' + ('required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingProperty: \'' + ($missingProperty) + '\' } ';
if (it.opts.messages !== false) {
out += ' , message: \'';
if (it.opts._errorDataPathProperty) {
@@ -4108,7 +4093,7 @@ module.exports = function generate_required(it, $keyword) {
}
out += ' if (' + ($data) + ($prop) + ' === undefined) { var err = '; /* istanbul ignore else */
if (it.createErrors !== false) {
- out += ' { keyword: \'' + ($errorKeyword || 'required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingProperty: \'' + ($missingProperty) + '\' } ';
+ out += ' { keyword: \'' + ('required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingProperty: \'' + ($missingProperty) + '\' } ';
if (it.opts.messages !== false) {
out += ' , message: \'';
if (it.opts._errorDataPathProperty) {
@@ -4147,7 +4132,6 @@ module.exports = function generate_switch(it, $keyword) {
var $schemaPath = it.schemaPath + it.util.getProperty($keyword);
var $errSchemaPath = it.errSchemaPath + '/' + $keyword;
var $breakOnError = !it.opts.allErrors;
- var $errorKeyword;
var $data = 'data' + ($dataLvl || '');
var $valid = 'valid' + $lvl;
var $errs = 'errs__' + $lvl;
@@ -4188,7 +4172,7 @@ module.exports = function generate_switch(it, $keyword) {
$$outStack.push(out);
out = ''; /* istanbul ignore else */
if (it.createErrors !== false) {
- out += ' { keyword: \'' + ($errorKeyword || 'switch') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { caseIndex: ' + ($caseIndex) + ' } ';
+ out += ' { keyword: \'' + ('switch') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { caseIndex: ' + ($caseIndex) + ' } ';
if (it.opts.messages !== false) {
out += ' , message: \'should pass "switch" keyword validation\' ';
}
@@ -4228,7 +4212,7 @@ module.exports = function generate_switch(it, $keyword) {
$$outStack.push(out);
out = ''; /* istanbul ignore else */
if (it.createErrors !== false) {
- out += ' { keyword: \'' + ($errorKeyword || 'switch') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { caseIndex: ' + ($caseIndex) + ' } ';
+ out += ' { keyword: \'' + ('switch') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { caseIndex: ' + ($caseIndex) + ' } ';
if (it.opts.messages !== false) {
out += ' , message: \'should pass "switch" keyword validation\' ';
}
@@ -4278,7 +4262,6 @@ module.exports = function generate_uniqueItems(it, $keyword) {
var $schemaPath = it.schemaPath + it.util.getProperty($keyword);
var $errSchemaPath = it.errSchemaPath + '/' + $keyword;
var $breakOnError = !it.opts.allErrors;
- var $errorKeyword;
var $data = 'data' + ($dataLvl || '');
var $valid = 'valid' + $lvl;
var $isData = it.opts.v5 && $schema && $schema.$data,
@@ -4302,7 +4285,7 @@ module.exports = function generate_uniqueItems(it, $keyword) {
$$outStack.push(out);
out = ''; /* istanbul ignore else */
if (it.createErrors !== false) {
- out += ' { keyword: \'' + ($errorKeyword || 'uniqueItems') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { i: i, j: j } ';
+ out += ' { keyword: \'' + ('uniqueItems') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { i: i, j: j } ';
if (it.opts.messages !== false) {
out += ' , message: \'should NOT have duplicate items (items ## \' + j + \' and \' + i + \' are identical)\' ';
}
@@ -4388,8 +4371,7 @@ module.exports = function generate_validate(it, $keyword) {
var $valid = 'valid' + $lvl,
$breakOnError = !it.opts.allErrors,
$closingBraces1 = '',
- $closingBraces2 = '',
- $errorKeyword;
+ $closingBraces2 = '';
var $typeSchema = it.schema.type,
$typeIsArray = Array.isArray($typeSchema);
if ($typeSchema && it.opts.coerceTypes) {
@@ -4442,7 +4424,7 @@ module.exports = function generate_validate(it, $keyword) {
$$outStack.push(out);
out = ''; /* istanbul ignore else */
if (it.createErrors !== false) {
- out += ' { keyword: \'' + ($errorKeyword || 'type') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { type: \'';
+ out += ' { keyword: \'' + ('type') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { type: \'';
if ($typeIsArray) {
out += '' + ($typeSchema.join(","));
} else {
@@ -4584,7 +4566,7 @@ module.exports = function generate_validate(it, $keyword) {
}
if ($rulesGroup.type) {
out += ' } ';
- if ($typeSchema && $typeSchema === $rulesGroup.type) {
+ if ($typeSchema && $typeSchema === $rulesGroup.type && !$coerceToTypes) {
var $typeChecked = true;
out += ' else { ';
var $schemaPath = it.schemaPath + '.type',
@@ -4593,7 +4575,7 @@ module.exports = function generate_validate(it, $keyword) {
$$outStack.push(out);
out = ''; /* istanbul ignore else */
if (it.createErrors !== false) {
- out += ' { keyword: \'' + ($errorKeyword || 'type') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { type: \'';
+ out += ' { keyword: \'' + ('type') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { type: \'';
if ($typeIsArray) {
out += '' + ($typeSchema.join(","));
} else {
@@ -4644,7 +4626,7 @@ module.exports = function generate_validate(it, $keyword) {
}
}
}
- if ($typeSchema && !$typeChecked && !(it.opts.coerceTypes && $coerceToTypes)) {
+ if ($typeSchema && !$typeChecked && !$coerceToTypes) {
var $schemaPath = it.schemaPath + '.type',
$errSchemaPath = it.errSchemaPath + '/type',
$method = $typeIsArray ? 'checkDataTypes' : 'checkDataType';
@@ -4653,7 +4635,7 @@ module.exports = function generate_validate(it, $keyword) {
$$outStack.push(out);
out = ''; /* istanbul ignore else */
if (it.createErrors !== false) {
- out += ' { keyword: \'' + ($errorKeyword || 'type') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { type: \'';
+ out += ' { keyword: \'' + ('type') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { type: \'';
if ($typeIsArray) {
out += '' + ($typeSchema.join(","));
} else {
@@ -5388,2231 +5370,2231 @@ function containsMacro(schema) {
}
},{"./dotjs/_formatLimit":13,"./dotjs/constant":20,"./dotjs/patternRequired":30,"./dotjs/switch":34,"./refs/json-schema-v5.json":39}],41:[function(require,module,exports){
-(function (global){
-/*! https://mths.be/punycode v1.4.1 by @mathias */
-;(function(root) {
- /** Detect free variables */
- var freeExports = typeof exports == 'object' && exports &&
- !exports.nodeType && exports;
- var freeModule = typeof module == 'object' && module &&
- !module.nodeType && module;
- var freeGlobal = typeof global == 'object' && global;
- if (
- freeGlobal.global === freeGlobal ||
- freeGlobal.window === freeGlobal ||
- freeGlobal.self === freeGlobal
- ) {
- root = freeGlobal;
- }
+/**
+ * slice() reference.
+ */
- /**
- * The `punycode` object.
- * @name punycode
- * @type Object
- */
- var punycode,
+var slice = Array.prototype.slice;
- /** Highest positive signed 32-bit float value */
- maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
+/**
+ * Expose `co`.
+ */
- /** Bootstring parameters */
- base = 36,
- tMin = 1,
- tMax = 26,
- skew = 38,
- damp = 700,
- initialBias = 72,
- initialN = 128, // 0x80
- delimiter = '-', // '\x2D'
+module.exports = co['default'] = co.co = co;
- /** Regular expressions */
- regexPunycode = /^xn--/,
- regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars
- regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators
+/**
+ * Wrap the given generator `fn` into a
+ * function that returns a promise.
+ * This is a separate function so that
+ * every `co()` call doesn't create a new,
+ * unnecessary closure.
+ *
+ * @param {GeneratorFunction} fn
+ * @return {Function}
+ * @api public
+ */
- /** Error messages */
- errors = {
- 'overflow': 'Overflow: input needs wider integers to process',
- 'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
- 'invalid-input': 'Invalid input'
- },
+co.wrap = function (fn) {
+ createPromise.__generatorFunction__ = fn;
+ return createPromise;
+ function createPromise() {
+ return co.call(this, fn.apply(this, arguments));
+ }
+};
- /** Convenience shortcuts */
- baseMinusTMin = base - tMin,
- floor = Math.floor,
- stringFromCharCode = String.fromCharCode,
+/**
+ * Execute the generator function or a generator
+ * and return a promise.
+ *
+ * @param {Function} fn
+ * @return {Promise}
+ * @api public
+ */
- /** Temporary variable */
- key;
+function co(gen) {
+ var ctx = this;
+ var args = slice.call(arguments, 1)
- /*--------------------------------------------------------------------------*/
+ // we wrap everything in a promise to avoid promise chaining,
+ // which leads to memory leak errors.
+ // see https://github.com/tj/co/issues/180
+ return new Promise(function(resolve, reject) {
+ if (typeof gen === 'function') gen = gen.apply(ctx, args);
+ if (!gen || typeof gen.next !== 'function') return resolve(gen);
- /**
- * A generic error utility function.
- * @private
- * @param {String} type The error type.
- * @returns {Error} Throws a `RangeError` with the applicable error message.
- */
- function error(type) {
- throw new RangeError(errors[type]);
- }
+ onFulfilled();
- /**
- * A generic `Array#map` utility function.
- * @private
- * @param {Array} array The array to iterate over.
- * @param {Function} callback The function that gets called for every array
- * item.
- * @returns {Array} A new array of values returned by the callback function.
- */
- function map(array, fn) {
- var length = array.length;
- var result = [];
- while (length--) {
- result[length] = fn(array[length]);
- }
- return result;
- }
+ /**
+ * @param {Mixed} res
+ * @return {Promise}
+ * @api private
+ */
- /**
- * A simple `Array#map`-like wrapper to work with domain name strings or email
- * addresses.
- * @private
- * @param {String} domain The domain name or email address.
- * @param {Function} callback The function that gets called for every
- * character.
- * @returns {Array} A new string of characters returned by the callback
- * function.
- */
- function mapDomain(string, fn) {
- var parts = string.split('@');
- var result = '';
- if (parts.length > 1) {
- // In email addresses, only the domain name should be punycoded. Leave
- // the local part (i.e. everything up to `@`) intact.
- result = parts[0] + '@';
- string = parts[1];
- }
- // Avoid `split(regex)` for IE8 compatibility. See #17.
- string = string.replace(regexSeparators, '\x2E');
- var labels = string.split('.');
- var encoded = map(labels, fn).join('.');
- return result + encoded;
- }
+ function onFulfilled(res) {
+ var ret;
+ try {
+ ret = gen.next(res);
+ } catch (e) {
+ return reject(e);
+ }
+ next(ret);
+ }
- /**
- * Creates an array containing the numeric code points of each Unicode
- * character in the string. While JavaScript uses UCS-2 internally,
- * this function will convert a pair of surrogate halves (each of which
- * UCS-2 exposes as separate characters) into a single code point,
- * matching UTF-16.
- * @see `punycode.ucs2.encode`
- * @see
- * @memberOf punycode.ucs2
- * @name decode
- * @param {String} string The Unicode input string (UCS-2).
- * @returns {Array} The new array of code points.
- */
- function ucs2decode(string) {
- var output = [],
- counter = 0,
- length = string.length,
- value,
- extra;
- while (counter < length) {
- value = string.charCodeAt(counter++);
- if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
- // high surrogate, and there is a next character
- extra = string.charCodeAt(counter++);
- if ((extra & 0xFC00) == 0xDC00) { // low surrogate
- output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
- } else {
- // unmatched surrogate; only append this code unit, in case the next
- // code unit is the high surrogate of a surrogate pair
- output.push(value);
- counter--;
- }
- } else {
- output.push(value);
- }
- }
- return output;
- }
+ /**
+ * @param {Error} err
+ * @return {Promise}
+ * @api private
+ */
- /**
- * Creates a string based on an array of numeric code points.
- * @see `punycode.ucs2.decode`
- * @memberOf punycode.ucs2
- * @name encode
- * @param {Array} codePoints The array of numeric code points.
- * @returns {String} The new Unicode string (UCS-2).
- */
- function ucs2encode(array) {
- return map(array, function(value) {
- var output = '';
- if (value > 0xFFFF) {
- value -= 0x10000;
- output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
- value = 0xDC00 | value & 0x3FF;
- }
- output += stringFromCharCode(value);
- return output;
- }).join('');
- }
+ function onRejected(err) {
+ var ret;
+ try {
+ ret = gen.throw(err);
+ } catch (e) {
+ return reject(e);
+ }
+ next(ret);
+ }
- /**
- * Converts a basic code point into a digit/integer.
- * @see `digitToBasic()`
- * @private
- * @param {Number} codePoint The basic numeric code point value.
- * @returns {Number} The numeric value of a basic code point (for use in
- * representing integers) in the range `0` to `base - 1`, or `base` if
- * the code point does not represent a value.
- */
- function basicToDigit(codePoint) {
- if (codePoint - 48 < 10) {
- return codePoint - 22;
- }
- if (codePoint - 65 < 26) {
- return codePoint - 65;
- }
- if (codePoint - 97 < 26) {
- return codePoint - 97;
- }
- return base;
- }
+ /**
+ * Get the next value in the generator,
+ * return a promise.
+ *
+ * @param {Object} ret
+ * @return {Promise}
+ * @api private
+ */
- /**
- * Converts a digit/integer into a basic code point.
- * @see `basicToDigit()`
- * @private
- * @param {Number} digit The numeric value of a basic code point.
- * @returns {Number} The basic code point whose value (when used for
- * representing integers) is `digit`, which needs to be in the range
- * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
- * used; else, the lowercase form is used. The behavior is undefined
- * if `flag` is non-zero and `digit` has no uppercase form.
- */
- function digitToBasic(digit, flag) {
- // 0..25 map to ASCII a..z or A..Z
- // 26..35 map to ASCII 0..9
- return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
- }
+ function next(ret) {
+ if (ret.done) return resolve(ret.value);
+ var value = toPromise.call(ctx, ret.value);
+ if (value && isPromise(value)) return value.then(onFulfilled, onRejected);
+ return onRejected(new TypeError('You may only yield a function, promise, generator, array, or object, '
+ + 'but the following object was passed: "' + String(ret.value) + '"'));
+ }
+ });
+}
- /**
- * Bias adaptation function as per section 3.4 of RFC 3492.
- * https://tools.ietf.org/html/rfc3492#section-3.4
- * @private
- */
- function adapt(delta, numPoints, firstTime) {
- var k = 0;
- delta = firstTime ? floor(delta / damp) : delta >> 1;
- delta += floor(delta / numPoints);
- for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
- delta = floor(delta / baseMinusTMin);
- }
- return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
- }
+/**
+ * Convert a `yield`ed value into a promise.
+ *
+ * @param {Mixed} obj
+ * @return {Promise}
+ * @api private
+ */
- /**
- * Converts a Punycode string of ASCII-only symbols to a string of Unicode
- * symbols.
- * @memberOf punycode
- * @param {String} input The Punycode string of ASCII-only symbols.
- * @returns {String} The resulting string of Unicode symbols.
- */
- function decode(input) {
- // Don't use UCS-2
- var output = [],
- inputLength = input.length,
- out,
- i = 0,
- n = initialN,
- bias = initialBias,
- basic,
- j,
- index,
- oldi,
- w,
- k,
- digit,
- t,
- /** Cached calculation results */
- baseMinusT;
+function toPromise(obj) {
+ if (!obj) return obj;
+ if (isPromise(obj)) return obj;
+ if (isGeneratorFunction(obj) || isGenerator(obj)) return co.call(this, obj);
+ if ('function' == typeof obj) return thunkToPromise.call(this, obj);
+ if (Array.isArray(obj)) return arrayToPromise.call(this, obj);
+ if (isObject(obj)) return objectToPromise.call(this, obj);
+ return obj;
+}
- // Handle the basic code points: let `basic` be the number of input code
- // points before the last delimiter, or `0` if there is none, then copy
- // the first basic code points to the output.
+/**
+ * Convert a thunk to a promise.
+ *
+ * @param {Function}
+ * @return {Promise}
+ * @api private
+ */
- basic = input.lastIndexOf(delimiter);
- if (basic < 0) {
- basic = 0;
- }
+function thunkToPromise(fn) {
+ var ctx = this;
+ return new Promise(function (resolve, reject) {
+ fn.call(ctx, function (err, res) {
+ if (err) return reject(err);
+ if (arguments.length > 2) res = slice.call(arguments, 1);
+ resolve(res);
+ });
+ });
+}
- for (j = 0; j < basic; ++j) {
- // if it's not a basic code point
- if (input.charCodeAt(j) >= 0x80) {
- error('not-basic');
- }
- output.push(input.charCodeAt(j));
- }
+/**
+ * Convert an array of "yieldables" to a promise.
+ * Uses `Promise.all()` internally.
+ *
+ * @param {Array} obj
+ * @return {Promise}
+ * @api private
+ */
- // Main decoding loop: start just after the last delimiter if any basic code
- // points were copied; start at the beginning otherwise.
+function arrayToPromise(obj) {
+ return Promise.all(obj.map(toPromise, this));
+}
- for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
+/**
+ * Convert an object of "yieldables" to a promise.
+ * Uses `Promise.all()` internally.
+ *
+ * @param {Object} obj
+ * @return {Promise}
+ * @api private
+ */
- // `index` is the index of the next character to be consumed.
- // Decode a generalized variable-length integer into `delta`,
- // which gets added to `i`. The overflow checking is easier
- // if we increase `i` as we go, then subtract off its starting
- // value at the end to obtain `delta`.
- for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
+function objectToPromise(obj){
+ var results = new obj.constructor();
+ var keys = Object.keys(obj);
+ var promises = [];
+ for (var i = 0; i < keys.length; i++) {
+ var key = keys[i];
+ var promise = toPromise.call(this, obj[key]);
+ if (promise && isPromise(promise)) defer(promise, key);
+ else results[key] = obj[key];
+ }
+ return Promise.all(promises).then(function () {
+ return results;
+ });
- if (index >= inputLength) {
- error('invalid-input');
- }
+ function defer(promise, key) {
+ // predefine the key in the result
+ results[key] = undefined;
+ promises.push(promise.then(function (res) {
+ results[key] = res;
+ }));
+ }
+}
- digit = basicToDigit(input.charCodeAt(index++));
+/**
+ * Check if `obj` is a promise.
+ *
+ * @param {Object} obj
+ * @return {Boolean}
+ * @api private
+ */
- if (digit >= base || digit > floor((maxInt - i) / w)) {
- error('overflow');
- }
+function isPromise(obj) {
+ return 'function' == typeof obj.then;
+}
- i += digit * w;
- t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
+/**
+ * Check if `obj` is a generator.
+ *
+ * @param {Mixed} obj
+ * @return {Boolean}
+ * @api private
+ */
- if (digit < t) {
- break;
- }
+function isGenerator(obj) {
+ return 'function' == typeof obj.next && 'function' == typeof obj.throw;
+}
- baseMinusT = base - t;
- if (w > floor(maxInt / baseMinusT)) {
- error('overflow');
- }
+/**
+ * Check if `obj` is a generator function.
+ *
+ * @param {Mixed} obj
+ * @return {Boolean}
+ * @api private
+ */
+function isGeneratorFunction(obj) {
+ var constructor = obj.constructor;
+ if (!constructor) return false;
+ if ('GeneratorFunction' === constructor.name || 'GeneratorFunction' === constructor.displayName) return true;
+ return isGenerator(constructor.prototype);
+}
- w *= baseMinusT;
+/**
+ * Check for plain object.
+ *
+ * @param {Mixed} val
+ * @return {Boolean}
+ * @api private
+ */
- }
+function isObject(val) {
+ return Object == val.constructor;
+}
- out = output.length + 1;
- bias = adapt(i - oldi, out, oldi == 0);
+},{}],42:[function(require,module,exports){
+var json = typeof JSON !== 'undefined' ? JSON : require('jsonify');
- // `i` was supposed to wrap around from `out` to `0`,
- // incrementing `n` each time, so we'll fix that now:
- if (floor(i / out) > maxInt - n) {
- error('overflow');
- }
+module.exports = function (obj, opts) {
+ if (!opts) opts = {};
+ if (typeof opts === 'function') opts = { cmp: opts };
+ var space = opts.space || '';
+ if (typeof space === 'number') space = Array(space+1).join(' ');
+ var cycles = (typeof opts.cycles === 'boolean') ? opts.cycles : false;
+ var replacer = opts.replacer || function(key, value) { return value; };
- n += floor(i / out);
- i %= out;
-
- // Insert `n` at position `i` of the output
- output.splice(i++, 0, n);
+ var cmp = opts.cmp && (function (f) {
+ return function (node) {
+ return function (a, b) {
+ var aobj = { key: a, value: node[a] };
+ var bobj = { key: b, value: node[b] };
+ return f(aobj, bobj);
+ };
+ };
+ })(opts.cmp);
- }
+ var seen = [];
+ return (function stringify (parent, key, node, level) {
+ var indent = space ? ('\n' + new Array(level + 1).join(space)) : '';
+ var colonSeparator = space ? ': ' : ':';
- return ucs2encode(output);
- }
+ if (node && node.toJSON && typeof node.toJSON === 'function') {
+ node = node.toJSON();
+ }
- /**
- * Converts a string of Unicode symbols (e.g. a domain name label) to a
- * Punycode string of ASCII-only symbols.
- * @memberOf punycode
- * @param {String} input The string of Unicode symbols.
- * @returns {String} The resulting Punycode string of ASCII-only symbols.
- */
- function encode(input) {
- var n,
- delta,
- handledCPCount,
- basicLength,
- bias,
- j,
- m,
- q,
- k,
- t,
- currentValue,
- output = [],
- /** `inputLength` will hold the number of code points in `input`. */
- inputLength,
- /** Cached calculation results */
- handledCPCountPlusOne,
- baseMinusT,
- qMinusT;
+ node = replacer.call(parent, key, node);
- // Convert the input in UCS-2 to Unicode
- input = ucs2decode(input);
+ if (node === undefined) {
+ return;
+ }
+ if (typeof node !== 'object' || node === null) {
+ return json.stringify(node);
+ }
+ if (isArray(node)) {
+ var out = [];
+ for (var i = 0; i < node.length; i++) {
+ var item = stringify(node, i, node[i], level+1) || json.stringify(null);
+ out.push(indent + space + item);
+ }
+ return '[' + out.join(',') + indent + ']';
+ }
+ else {
+ if (seen.indexOf(node) !== -1) {
+ if (cycles) return json.stringify('__cycle__');
+ throw new TypeError('Converting circular structure to JSON');
+ }
+ else seen.push(node);
- // Cache the length
- inputLength = input.length;
+ var keys = objectKeys(node).sort(cmp && cmp(node));
+ var out = [];
+ for (var i = 0; i < keys.length; i++) {
+ var key = keys[i];
+ var value = stringify(node, key, node[key], level+1);
- // Initialize the state
- n = initialN;
- delta = 0;
- bias = initialBias;
+ if(!value) continue;
- // Handle the basic code points
- for (j = 0; j < inputLength; ++j) {
- currentValue = input[j];
- if (currentValue < 0x80) {
- output.push(stringFromCharCode(currentValue));
- }
- }
+ var keyValue = json.stringify(key)
+ + colonSeparator
+ + value;
+ ;
+ out.push(indent + space + keyValue);
+ }
+ seen.splice(seen.indexOf(node), 1);
+ return '{' + out.join(',') + indent + '}';
+ }
+ })({ '': obj }, '', obj, 0);
+};
- handledCPCount = basicLength = output.length;
+var isArray = Array.isArray || function (x) {
+ return {}.toString.call(x) === '[object Array]';
+};
- // `handledCPCount` is the number of code points that have been handled;
- // `basicLength` is the number of basic code points.
+var objectKeys = Object.keys || function (obj) {
+ var has = Object.prototype.hasOwnProperty || function () { return true };
+ var keys = [];
+ for (var key in obj) {
+ if (has.call(obj, key)) keys.push(key);
+ }
+ return keys;
+};
- // Finish the basic string - if it is not empty - with a delimiter
- if (basicLength) {
- output.push(delimiter);
- }
+},{"jsonify":43}],43:[function(require,module,exports){
+exports.parse = require('./lib/parse');
+exports.stringify = require('./lib/stringify');
- // Main encoding loop:
- while (handledCPCount < inputLength) {
+},{"./lib/parse":44,"./lib/stringify":45}],44:[function(require,module,exports){
+var at, // The index of the current character
+ ch, // The current character
+ escapee = {
+ '"': '"',
+ '\\': '\\',
+ '/': '/',
+ b: '\b',
+ f: '\f',
+ n: '\n',
+ r: '\r',
+ t: '\t'
+ },
+ text,
- // All non-basic code points < n have been handled already. Find the next
- // larger one:
- for (m = maxInt, j = 0; j < inputLength; ++j) {
- currentValue = input[j];
- if (currentValue >= n && currentValue < m) {
- m = currentValue;
- }
- }
+ error = function (m) {
+ // Call error when something is wrong.
+ throw {
+ name: 'SyntaxError',
+ message: m,
+ at: at,
+ text: text
+ };
+ },
+
+ next = function (c) {
+ // If a c parameter is provided, verify that it matches the current character.
+ if (c && c !== ch) {
+ error("Expected '" + c + "' instead of '" + ch + "'");
+ }
+
+ // Get the next character. When there are no more characters,
+ // return the empty string.
+
+ ch = text.charAt(at);
+ at += 1;
+ return ch;
+ },
+
+ number = function () {
+ // Parse a number value.
+ var number,
+ string = '';
+
+ if (ch === '-') {
+ string = '-';
+ next('-');
+ }
+ while (ch >= '0' && ch <= '9') {
+ string += ch;
+ next();
+ }
+ if (ch === '.') {
+ string += '.';
+ while (next() && ch >= '0' && ch <= '9') {
+ string += ch;
+ }
+ }
+ if (ch === 'e' || ch === 'E') {
+ string += ch;
+ next();
+ if (ch === '-' || ch === '+') {
+ string += ch;
+ next();
+ }
+ while (ch >= '0' && ch <= '9') {
+ string += ch;
+ next();
+ }
+ }
+ number = +string;
+ if (!isFinite(number)) {
+ error("Bad number");
+ } else {
+ return number;
+ }
+ },
+
+ string = function () {
+ // Parse a string value.
+ var hex,
+ i,
+ string = '',
+ uffff;
+
+ // When parsing for string values, we must look for " and \ characters.
+ if (ch === '"') {
+ while (next()) {
+ if (ch === '"') {
+ next();
+ return string;
+ } else if (ch === '\\') {
+ next();
+ if (ch === 'u') {
+ uffff = 0;
+ for (i = 0; i < 4; i += 1) {
+ hex = parseInt(next(), 16);
+ if (!isFinite(hex)) {
+ break;
+ }
+ uffff = uffff * 16 + hex;
+ }
+ string += String.fromCharCode(uffff);
+ } else if (typeof escapee[ch] === 'string') {
+ string += escapee[ch];
+ } else {
+ break;
+ }
+ } else {
+ string += ch;
+ }
+ }
+ }
+ error("Bad string");
+ },
- // Increase `delta` enough to advance the decoder's state to ,
- // but guard against overflow
- handledCPCountPlusOne = handledCPCount + 1;
- if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
- error('overflow');
- }
+ white = function () {
- delta += (m - n) * handledCPCountPlusOne;
- n = m;
+// Skip whitespace.
- for (j = 0; j < inputLength; ++j) {
- currentValue = input[j];
+ while (ch && ch <= ' ') {
+ next();
+ }
+ },
- if (currentValue < n && ++delta > maxInt) {
- error('overflow');
- }
+ word = function () {
- if (currentValue == n) {
- // Represent delta as a generalized variable-length integer
- for (q = delta, k = base; /* no condition */; k += base) {
- t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
- if (q < t) {
- break;
- }
- qMinusT = q - t;
- baseMinusT = base - t;
- output.push(
- stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
- );
- q = floor(qMinusT / baseMinusT);
- }
+// true, false, or null.
- output.push(stringFromCharCode(digitToBasic(q, 0)));
- bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
- delta = 0;
- ++handledCPCount;
- }
- }
+ switch (ch) {
+ case 't':
+ next('t');
+ next('r');
+ next('u');
+ next('e');
+ return true;
+ case 'f':
+ next('f');
+ next('a');
+ next('l');
+ next('s');
+ next('e');
+ return false;
+ case 'n':
+ next('n');
+ next('u');
+ next('l');
+ next('l');
+ return null;
+ }
+ error("Unexpected '" + ch + "'");
+ },
- ++delta;
- ++n;
+ value, // Place holder for the value function.
- }
- return output.join('');
- }
+ array = function () {
- /**
- * Converts a Punycode string representing a domain name or an email address
- * to Unicode. Only the Punycoded parts of the input will be converted, i.e.
- * it doesn't matter if you call it on a string that has already been
- * converted to Unicode.
- * @memberOf punycode
- * @param {String} input The Punycoded domain name or email address to
- * convert to Unicode.
- * @returns {String} The Unicode representation of the given Punycode
- * string.
- */
- function toUnicode(input) {
- return mapDomain(input, function(string) {
- return regexPunycode.test(string)
- ? decode(string.slice(4).toLowerCase())
- : string;
- });
- }
+// Parse an array value.
- /**
- * Converts a Unicode string representing a domain name or an email address to
- * Punycode. Only the non-ASCII parts of the domain name will be converted,
- * i.e. it doesn't matter if you call it with a domain that's already in
- * ASCII.
- * @memberOf punycode
- * @param {String} input The domain name or email address to convert, as a
- * Unicode string.
- * @returns {String} The Punycode representation of the given domain name or
- * email address.
- */
- function toASCII(input) {
- return mapDomain(input, function(string) {
- return regexNonASCII.test(string)
- ? 'xn--' + encode(string)
- : string;
- });
- }
+ var array = [];
- /*--------------------------------------------------------------------------*/
+ if (ch === '[') {
+ next('[');
+ white();
+ if (ch === ']') {
+ next(']');
+ return array; // empty array
+ }
+ while (ch) {
+ array.push(value());
+ white();
+ if (ch === ']') {
+ next(']');
+ return array;
+ }
+ next(',');
+ white();
+ }
+ }
+ error("Bad array");
+ },
- /** Define the public API */
- punycode = {
- /**
- * A string representing the current Punycode.js version number.
- * @memberOf punycode
- * @type String
- */
- 'version': '1.4.1',
- /**
- * An object of methods to convert from JavaScript's internal character
- * representation (UCS-2) to Unicode code points, and back.
- * @see
- * @memberOf punycode
- * @type Object
- */
- 'ucs2': {
- 'decode': ucs2decode,
- 'encode': ucs2encode
- },
- 'decode': decode,
- 'encode': encode,
- 'toASCII': toASCII,
- 'toUnicode': toUnicode
- };
+ object = function () {
- /** Expose `punycode` */
- // Some AMD build optimizers, like r.js, check for specific condition patterns
- // like the following:
- if (
- typeof define == 'function' &&
- typeof define.amd == 'object' &&
- define.amd
- ) {
- define('punycode', function() {
- return punycode;
- });
- } else if (freeExports && freeModule) {
- if (module.exports == freeExports) {
- // in Node.js, io.js, or RingoJS v0.8.0+
- freeModule.exports = punycode;
- } else {
- // in Narwhal or RingoJS v0.7.0-
- for (key in punycode) {
- punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
- }
- }
- } else {
- // in Rhino or a web browser
- root.punycode = punycode;
- }
+// Parse an object value.
-}(this));
+ var key,
+ object = {};
-}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{}],42:[function(require,module,exports){
-// Copyright Joyent, Inc. and other Node contributors.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to permit
-// persons to whom the Software is furnished to do so, subject to the
-// following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
-// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-// USE OR OTHER DEALINGS IN THE SOFTWARE.
+ if (ch === '{') {
+ next('{');
+ white();
+ if (ch === '}') {
+ next('}');
+ return object; // empty object
+ }
+ while (ch) {
+ key = string();
+ white();
+ next(':');
+ if (Object.hasOwnProperty.call(object, key)) {
+ error('Duplicate key "' + key + '"');
+ }
+ object[key] = value();
+ white();
+ if (ch === '}') {
+ next('}');
+ return object;
+ }
+ next(',');
+ white();
+ }
+ }
+ error("Bad object");
+ };
-'use strict';
+value = function () {
-// If obj.hasOwnProperty has been overridden, then calling
-// obj.hasOwnProperty(prop) will break.
-// See: https://github.com/joyent/node/issues/1707
-function hasOwnProperty(obj, prop) {
- return Object.prototype.hasOwnProperty.call(obj, prop);
-}
+// Parse a JSON value. It could be an object, an array, a string, a number,
+// or a word.
-module.exports = function(qs, sep, eq, options) {
- sep = sep || '&';
- eq = eq || '=';
- var obj = {};
+ white();
+ switch (ch) {
+ case '{':
+ return object();
+ case '[':
+ return array();
+ case '"':
+ return string();
+ case '-':
+ return number();
+ default:
+ return ch >= '0' && ch <= '9' ? number() : word();
+ }
+};
- if (typeof qs !== 'string' || qs.length === 0) {
- return obj;
- }
+// Return the json_parse function. It will have access to all of the above
+// functions and variables.
- var regexp = /\+/g;
- qs = qs.split(sep);
+module.exports = function (source, reviver) {
+ var result;
+
+ text = source;
+ at = 0;
+ ch = ' ';
+ result = value();
+ white();
+ if (ch) {
+ error("Syntax error");
+ }
- var maxKeys = 1000;
- if (options && typeof options.maxKeys === 'number') {
- maxKeys = options.maxKeys;
- }
+ // If there is a reviver function, we recursively walk the new structure,
+ // passing each name/value pair to the reviver function for possible
+ // transformation, starting with a temporary root object that holds the result
+ // in an empty key. If there is not a reviver function, we simply return the
+ // result.
- var len = qs.length;
- // maxKeys <= 0 means that we should not limit keys count
- if (maxKeys > 0 && len > maxKeys) {
- len = maxKeys;
- }
+ return typeof reviver === 'function' ? (function walk(holder, key) {
+ var k, v, value = holder[key];
+ if (value && typeof value === 'object') {
+ for (k in value) {
+ if (Object.prototype.hasOwnProperty.call(value, k)) {
+ v = walk(value, k);
+ if (v !== undefined) {
+ value[k] = v;
+ } else {
+ delete value[k];
+ }
+ }
+ }
+ }
+ return reviver.call(holder, key, value);
+ }({'': result}, '')) : result;
+};
- for (var i = 0; i < len; ++i) {
- var x = qs[i].replace(regexp, '%20'),
- idx = x.indexOf(eq),
- kstr, vstr, k, v;
+},{}],45:[function(require,module,exports){
+var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+ escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+ gap,
+ indent,
+ meta = { // table of character substitutions
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '"' : '\\"',
+ '\\': '\\\\'
+ },
+ rep;
- if (idx >= 0) {
- kstr = x.substr(0, idx);
- vstr = x.substr(idx + 1);
- } else {
- kstr = x;
- vstr = '';
+function quote(string) {
+ // If the string contains no control characters, no quote characters, and no
+ // backslash characters, then we can safely slap some quotes around it.
+ // Otherwise we must also replace the offending characters with safe escape
+ // sequences.
+
+ escapable.lastIndex = 0;
+ return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
+ var c = meta[a];
+ return typeof c === 'string' ? c :
+ '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+ }) + '"' : '"' + string + '"';
+}
+
+function str(key, holder) {
+ // Produce a string from holder[key].
+ var i, // The loop counter.
+ k, // The member key.
+ v, // The member value.
+ length,
+ mind = gap,
+ partial,
+ value = holder[key];
+
+ // If the value has a toJSON method, call it to obtain a replacement value.
+ if (value && typeof value === 'object' &&
+ typeof value.toJSON === 'function') {
+ value = value.toJSON(key);
+ }
+
+ // If we were called with a replacer function, then call the replacer to
+ // obtain a replacement value.
+ if (typeof rep === 'function') {
+ value = rep.call(holder, key, value);
}
+
+ // What happens next depends on the value's type.
+ switch (typeof value) {
+ case 'string':
+ return quote(value);
+
+ case 'number':
+ // JSON numbers must be finite. Encode non-finite numbers as null.
+ return isFinite(value) ? String(value) : 'null';
+
+ case 'boolean':
+ case 'null':
+ // If the value is a boolean or null, convert it to a string. Note:
+ // typeof null does not produce 'null'. The case is included here in
+ // the remote chance that this gets fixed someday.
+ return String(value);
+
+ case 'object':
+ if (!value) return 'null';
+ gap += indent;
+ partial = [];
+
+ // Array.isArray
+ if (Object.prototype.toString.apply(value) === '[object Array]') {
+ length = value.length;
+ for (i = 0; i < length; i += 1) {
+ partial[i] = str(i, value) || 'null';
+ }
+
+ // Join all of the elements together, separated with commas, and
+ // wrap them in brackets.
+ v = partial.length === 0 ? '[]' : gap ?
+ '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' :
+ '[' + partial.join(',') + ']';
+ gap = mind;
+ return v;
+ }
+
+ // If the replacer is an array, use it to select the members to be
+ // stringified.
+ if (rep && typeof rep === 'object') {
+ length = rep.length;
+ for (i = 0; i < length; i += 1) {
+ k = rep[i];
+ if (typeof k === 'string') {
+ v = str(k, value);
+ if (v) {
+ partial.push(quote(k) + (gap ? ': ' : ':') + v);
+ }
+ }
+ }
+ }
+ else {
+ // Otherwise, iterate through all of the keys in the object.
+ for (k in value) {
+ if (Object.prototype.hasOwnProperty.call(value, k)) {
+ v = str(k, value);
+ if (v) {
+ partial.push(quote(k) + (gap ? ': ' : ':') + v);
+ }
+ }
+ }
+ }
+
+ // Join all of the member texts together, separated with commas,
+ // and wrap them in braces.
- k = decodeURIComponent(kstr);
- v = decodeURIComponent(vstr);
+ v = partial.length === 0 ? '{}' : gap ?
+ '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' :
+ '{' + partial.join(',') + '}';
+ gap = mind;
+ return v;
+ }
+}
- if (!hasOwnProperty(obj, k)) {
- obj[k] = v;
- } else if (isArray(obj[k])) {
- obj[k].push(v);
- } else {
- obj[k] = [obj[k], v];
+module.exports = function (value, replacer, space) {
+ var i;
+ gap = '';
+ indent = '';
+
+ // If the space parameter is a number, make an indent string containing that
+ // many spaces.
+ if (typeof space === 'number') {
+ for (i = 0; i < space; i += 1) {
+ indent += ' ';
+ }
+ }
+ // If the space parameter is a string, it will be used as the indent string.
+ else if (typeof space === 'string') {
+ indent = space;
}
- }
- return obj;
+ // If there is a replacer, it must be a function or an array.
+ // Otherwise, throw an error.
+ rep = replacer;
+ if (replacer && typeof replacer !== 'function'
+ && (typeof replacer !== 'object' || typeof replacer.length !== 'number')) {
+ throw new Error('JSON.stringify');
+ }
+
+ // Make a fake root object containing our value under the key of ''.
+ // Return the result of stringifying the value.
+ return str('', {'': value});
};
-var isArray = Array.isArray || function (xs) {
- return Object.prototype.toString.call(xs) === '[object Array]';
-};
+},{}],46:[function(require,module,exports){
+(function (global){
+/*! https://mths.be/punycode v1.4.1 by @mathias */
+;(function(root) {
-},{}],43:[function(require,module,exports){
-// Copyright Joyent, Inc. and other Node contributors.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to permit
-// persons to whom the Software is furnished to do so, subject to the
-// following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
-// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-// USE OR OTHER DEALINGS IN THE SOFTWARE.
+ /** Detect free variables */
+ var freeExports = typeof exports == 'object' && exports &&
+ !exports.nodeType && exports;
+ var freeModule = typeof module == 'object' && module &&
+ !module.nodeType && module;
+ var freeGlobal = typeof global == 'object' && global;
+ if (
+ freeGlobal.global === freeGlobal ||
+ freeGlobal.window === freeGlobal ||
+ freeGlobal.self === freeGlobal
+ ) {
+ root = freeGlobal;
+ }
-'use strict';
+ /**
+ * The `punycode` object.
+ * @name punycode
+ * @type Object
+ */
+ var punycode,
-var stringifyPrimitive = function(v) {
- switch (typeof v) {
- case 'string':
- return v;
-
- case 'boolean':
- return v ? 'true' : 'false';
-
- case 'number':
- return isFinite(v) ? v : '';
+ /** Highest positive signed 32-bit float value */
+ maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
- default:
- return '';
- }
-};
+ /** Bootstring parameters */
+ base = 36,
+ tMin = 1,
+ tMax = 26,
+ skew = 38,
+ damp = 700,
+ initialBias = 72,
+ initialN = 128, // 0x80
+ delimiter = '-', // '\x2D'
-module.exports = function(obj, sep, eq, name) {
- sep = sep || '&';
- eq = eq || '=';
- if (obj === null) {
- obj = undefined;
- }
+ /** Regular expressions */
+ regexPunycode = /^xn--/,
+ regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars
+ regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators
- if (typeof obj === 'object') {
- return map(objectKeys(obj), function(k) {
- var ks = encodeURIComponent(stringifyPrimitive(k)) + eq;
- if (isArray(obj[k])) {
- return map(obj[k], function(v) {
- return ks + encodeURIComponent(stringifyPrimitive(v));
- }).join(sep);
- } else {
- return ks + encodeURIComponent(stringifyPrimitive(obj[k]));
- }
- }).join(sep);
+ /** Error messages */
+ errors = {
+ 'overflow': 'Overflow: input needs wider integers to process',
+ 'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
+ 'invalid-input': 'Invalid input'
+ },
- }
+ /** Convenience shortcuts */
+ baseMinusTMin = base - tMin,
+ floor = Math.floor,
+ stringFromCharCode = String.fromCharCode,
- if (!name) return '';
- return encodeURIComponent(stringifyPrimitive(name)) + eq +
- encodeURIComponent(stringifyPrimitive(obj));
-};
+ /** Temporary variable */
+ key;
-var isArray = Array.isArray || function (xs) {
- return Object.prototype.toString.call(xs) === '[object Array]';
-};
+ /*--------------------------------------------------------------------------*/
-function map (xs, f) {
- if (xs.map) return xs.map(f);
- var res = [];
- for (var i = 0; i < xs.length; i++) {
- res.push(f(xs[i], i));
- }
- return res;
-}
+ /**
+ * A generic error utility function.
+ * @private
+ * @param {String} type The error type.
+ * @returns {Error} Throws a `RangeError` with the applicable error message.
+ */
+ function error(type) {
+ throw new RangeError(errors[type]);
+ }
-var objectKeys = Object.keys || function (obj) {
- var res = [];
- for (var key in obj) {
- if (Object.prototype.hasOwnProperty.call(obj, key)) res.push(key);
- }
- return res;
-};
+ /**
+ * A generic `Array#map` utility function.
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} callback The function that gets called for every array
+ * item.
+ * @returns {Array} A new array of values returned by the callback function.
+ */
+ function map(array, fn) {
+ var length = array.length;
+ var result = [];
+ while (length--) {
+ result[length] = fn(array[length]);
+ }
+ return result;
+ }
-},{}],44:[function(require,module,exports){
-'use strict';
+ /**
+ * A simple `Array#map`-like wrapper to work with domain name strings or email
+ * addresses.
+ * @private
+ * @param {String} domain The domain name or email address.
+ * @param {Function} callback The function that gets called for every
+ * character.
+ * @returns {Array} A new string of characters returned by the callback
+ * function.
+ */
+ function mapDomain(string, fn) {
+ var parts = string.split('@');
+ var result = '';
+ if (parts.length > 1) {
+ // In email addresses, only the domain name should be punycoded. Leave
+ // the local part (i.e. everything up to `@`) intact.
+ result = parts[0] + '@';
+ string = parts[1];
+ }
+ // Avoid `split(regex)` for IE8 compatibility. See #17.
+ string = string.replace(regexSeparators, '\x2E');
+ var labels = string.split('.');
+ var encoded = map(labels, fn).join('.');
+ return result + encoded;
+ }
-exports.decode = exports.parse = require('./decode');
-exports.encode = exports.stringify = require('./encode');
+ /**
+ * Creates an array containing the numeric code points of each Unicode
+ * character in the string. While JavaScript uses UCS-2 internally,
+ * this function will convert a pair of surrogate halves (each of which
+ * UCS-2 exposes as separate characters) into a single code point,
+ * matching UTF-16.
+ * @see `punycode.ucs2.encode`
+ * @see
+ * @memberOf punycode.ucs2
+ * @name decode
+ * @param {String} string The Unicode input string (UCS-2).
+ * @returns {Array} The new array of code points.
+ */
+ function ucs2decode(string) {
+ var output = [],
+ counter = 0,
+ length = string.length,
+ value,
+ extra;
+ while (counter < length) {
+ value = string.charCodeAt(counter++);
+ if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
+ // high surrogate, and there is a next character
+ extra = string.charCodeAt(counter++);
+ if ((extra & 0xFC00) == 0xDC00) { // low surrogate
+ output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
+ } else {
+ // unmatched surrogate; only append this code unit, in case the next
+ // code unit is the high surrogate of a surrogate pair
+ output.push(value);
+ counter--;
+ }
+ } else {
+ output.push(value);
+ }
+ }
+ return output;
+ }
-},{"./decode":42,"./encode":43}],45:[function(require,module,exports){
-// Copyright Joyent, Inc. and other Node contributors.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to permit
-// persons to whom the Software is furnished to do so, subject to the
-// following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
-// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-// USE OR OTHER DEALINGS IN THE SOFTWARE.
+ /**
+ * Creates a string based on an array of numeric code points.
+ * @see `punycode.ucs2.decode`
+ * @memberOf punycode.ucs2
+ * @name encode
+ * @param {Array} codePoints The array of numeric code points.
+ * @returns {String} The new Unicode string (UCS-2).
+ */
+ function ucs2encode(array) {
+ return map(array, function(value) {
+ var output = '';
+ if (value > 0xFFFF) {
+ value -= 0x10000;
+ output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
+ value = 0xDC00 | value & 0x3FF;
+ }
+ output += stringFromCharCode(value);
+ return output;
+ }).join('');
+ }
-'use strict';
+ /**
+ * Converts a basic code point into a digit/integer.
+ * @see `digitToBasic()`
+ * @private
+ * @param {Number} codePoint The basic numeric code point value.
+ * @returns {Number} The numeric value of a basic code point (for use in
+ * representing integers) in the range `0` to `base - 1`, or `base` if
+ * the code point does not represent a value.
+ */
+ function basicToDigit(codePoint) {
+ if (codePoint - 48 < 10) {
+ return codePoint - 22;
+ }
+ if (codePoint - 65 < 26) {
+ return codePoint - 65;
+ }
+ if (codePoint - 97 < 26) {
+ return codePoint - 97;
+ }
+ return base;
+ }
-var punycode = require('punycode');
-var util = require('./util');
+ /**
+ * Converts a digit/integer into a basic code point.
+ * @see `basicToDigit()`
+ * @private
+ * @param {Number} digit The numeric value of a basic code point.
+ * @returns {Number} The basic code point whose value (when used for
+ * representing integers) is `digit`, which needs to be in the range
+ * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
+ * used; else, the lowercase form is used. The behavior is undefined
+ * if `flag` is non-zero and `digit` has no uppercase form.
+ */
+ function digitToBasic(digit, flag) {
+ // 0..25 map to ASCII a..z or A..Z
+ // 26..35 map to ASCII 0..9
+ return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
+ }
-exports.parse = urlParse;
-exports.resolve = urlResolve;
-exports.resolveObject = urlResolveObject;
-exports.format = urlFormat;
-
-exports.Url = Url;
+ /**
+ * Bias adaptation function as per section 3.4 of RFC 3492.
+ * https://tools.ietf.org/html/rfc3492#section-3.4
+ * @private
+ */
+ function adapt(delta, numPoints, firstTime) {
+ var k = 0;
+ delta = firstTime ? floor(delta / damp) : delta >> 1;
+ delta += floor(delta / numPoints);
+ for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
+ delta = floor(delta / baseMinusTMin);
+ }
+ return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
+ }
-function Url() {
- this.protocol = null;
- this.slashes = null;
- this.auth = null;
- this.host = null;
- this.port = null;
- this.hostname = null;
- this.hash = null;
- this.search = null;
- this.query = null;
- this.pathname = null;
- this.path = null;
- this.href = null;
-}
+ /**
+ * Converts a Punycode string of ASCII-only symbols to a string of Unicode
+ * symbols.
+ * @memberOf punycode
+ * @param {String} input The Punycode string of ASCII-only symbols.
+ * @returns {String} The resulting string of Unicode symbols.
+ */
+ function decode(input) {
+ // Don't use UCS-2
+ var output = [],
+ inputLength = input.length,
+ out,
+ i = 0,
+ n = initialN,
+ bias = initialBias,
+ basic,
+ j,
+ index,
+ oldi,
+ w,
+ k,
+ digit,
+ t,
+ /** Cached calculation results */
+ baseMinusT;
-// Reference: RFC 3986, RFC 1808, RFC 2396
+ // Handle the basic code points: let `basic` be the number of input code
+ // points before the last delimiter, or `0` if there is none, then copy
+ // the first basic code points to the output.
-// define these here so at least they only have to be
-// compiled once on the first module load.
-var protocolPattern = /^([a-z0-9.+-]+:)/i,
- portPattern = /:[0-9]*$/,
+ basic = input.lastIndexOf(delimiter);
+ if (basic < 0) {
+ basic = 0;
+ }
- // Special case for a simple path URL
- simplePathPattern = /^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/,
+ for (j = 0; j < basic; ++j) {
+ // if it's not a basic code point
+ if (input.charCodeAt(j) >= 0x80) {
+ error('not-basic');
+ }
+ output.push(input.charCodeAt(j));
+ }
- // RFC 2396: characters reserved for delimiting URLs.
- // We actually just auto-escape these.
- delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'],
+ // Main decoding loop: start just after the last delimiter if any basic code
+ // points were copied; start at the beginning otherwise.
- // RFC 2396: characters not allowed for various reasons.
- unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims),
+ for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
- // Allowed by RFCs, but cause of XSS attacks. Always escape these.
- autoEscape = ['\''].concat(unwise),
- // Characters that are never ever allowed in a hostname.
- // Note that any invalid chars are also handled, but these
- // are the ones that are *expected* to be seen, so we fast-path
- // them.
- nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape),
- hostEndingChars = ['/', '?', '#'],
- hostnameMaxLen = 255,
- hostnamePartPattern = /^[+a-z0-9A-Z_-]{0,63}$/,
- hostnamePartStart = /^([+a-z0-9A-Z_-]{0,63})(.*)$/,
- // protocols that can allow "unsafe" and "unwise" chars.
- unsafeProtocol = {
- 'javascript': true,
- 'javascript:': true
- },
- // protocols that never have a hostname.
- hostlessProtocol = {
- 'javascript': true,
- 'javascript:': true
- },
- // protocols that always contain a // bit.
- slashedProtocol = {
- 'http': true,
- 'https': true,
- 'ftp': true,
- 'gopher': true,
- 'file': true,
- 'http:': true,
- 'https:': true,
- 'ftp:': true,
- 'gopher:': true,
- 'file:': true
- },
- querystring = require('querystring');
+ // `index` is the index of the next character to be consumed.
+ // Decode a generalized variable-length integer into `delta`,
+ // which gets added to `i`. The overflow checking is easier
+ // if we increase `i` as we go, then subtract off its starting
+ // value at the end to obtain `delta`.
+ for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
-function urlParse(url, parseQueryString, slashesDenoteHost) {
- if (url && util.isObject(url) && url instanceof Url) return url;
+ if (index >= inputLength) {
+ error('invalid-input');
+ }
- var u = new Url;
- u.parse(url, parseQueryString, slashesDenoteHost);
- return u;
-}
+ digit = basicToDigit(input.charCodeAt(index++));
-Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) {
- if (!util.isString(url)) {
- throw new TypeError("Parameter 'url' must be a string, not " + typeof url);
- }
+ if (digit >= base || digit > floor((maxInt - i) / w)) {
+ error('overflow');
+ }
- // Copy chrome, IE, opera backslash-handling behavior.
- // Back slashes before the query string get converted to forward slashes
- // See: https://code.google.com/p/chromium/issues/detail?id=25916
- var queryIndex = url.indexOf('?'),
- splitter =
- (queryIndex !== -1 && queryIndex < url.indexOf('#')) ? '?' : '#',
- uSplit = url.split(splitter),
- slashRegex = /\\/g;
- uSplit[0] = uSplit[0].replace(slashRegex, '/');
- url = uSplit.join(splitter);
+ i += digit * w;
+ t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
- var rest = url;
+ if (digit < t) {
+ break;
+ }
- // trim before proceeding.
- // This is to support parse stuff like " http://foo.com \n"
- rest = rest.trim();
+ baseMinusT = base - t;
+ if (w > floor(maxInt / baseMinusT)) {
+ error('overflow');
+ }
- if (!slashesDenoteHost && url.split('#').length === 1) {
- // Try fast path regexp
- var simplePath = simplePathPattern.exec(rest);
- if (simplePath) {
- this.path = rest;
- this.href = rest;
- this.pathname = simplePath[1];
- if (simplePath[2]) {
- this.search = simplePath[2];
- if (parseQueryString) {
- this.query = querystring.parse(this.search.substr(1));
- } else {
- this.query = this.search.substr(1);
- }
- } else if (parseQueryString) {
- this.search = '';
- this.query = {};
- }
- return this;
- }
- }
+ w *= baseMinusT;
- var proto = protocolPattern.exec(rest);
- if (proto) {
- proto = proto[0];
- var lowerProto = proto.toLowerCase();
- this.protocol = lowerProto;
- rest = rest.substr(proto.length);
- }
+ }
- // figure out if it's got a host
- // user@server is *always* interpreted as a hostname, and url
- // resolution will treat //foo/bar as host=foo,path=bar because that's
- // how the browser resolves relative URLs.
- if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) {
- var slashes = rest.substr(0, 2) === '//';
- if (slashes && !(proto && hostlessProtocol[proto])) {
- rest = rest.substr(2);
- this.slashes = true;
- }
- }
+ out = output.length + 1;
+ bias = adapt(i - oldi, out, oldi == 0);
- if (!hostlessProtocol[proto] &&
- (slashes || (proto && !slashedProtocol[proto]))) {
+ // `i` was supposed to wrap around from `out` to `0`,
+ // incrementing `n` each time, so we'll fix that now:
+ if (floor(i / out) > maxInt - n) {
+ error('overflow');
+ }
- // there's a hostname.
- // the first instance of /, ?, ;, or # ends the host.
- //
- // If there is an @ in the hostname, then non-host chars *are* allowed
- // to the left of the last @ sign, unless some host-ending character
- // comes *before* the @-sign.
- // URLs are obnoxious.
- //
- // ex:
- // http://a@b@c/ => user:a@b host:c
- // http://a@b?@c => user:a host:c path:/?@c
+ n += floor(i / out);
+ i %= out;
- // v0.12 TODO(isaacs): This is not quite how Chrome does things.
- // Review our test case against browsers more comprehensively.
+ // Insert `n` at position `i` of the output
+ output.splice(i++, 0, n);
- // find the first instance of any hostEndingChars
- var hostEnd = -1;
- for (var i = 0; i < hostEndingChars.length; i++) {
- var hec = rest.indexOf(hostEndingChars[i]);
- if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
- hostEnd = hec;
- }
+ }
- // at this point, either we have an explicit point where the
- // auth portion cannot go past, or the last @ char is the decider.
- var auth, atSign;
- if (hostEnd === -1) {
- // atSign can be anywhere.
- atSign = rest.lastIndexOf('@');
- } else {
- // atSign must be in auth portion.
- // http://a@b/c@d => host:b auth:a path:/c@d
- atSign = rest.lastIndexOf('@', hostEnd);
- }
+ return ucs2encode(output);
+ }
- // Now we have a portion which is definitely the auth.
- // Pull that off.
- if (atSign !== -1) {
- auth = rest.slice(0, atSign);
- rest = rest.slice(atSign + 1);
- this.auth = decodeURIComponent(auth);
- }
-
- // the host is the remaining to the left of the first non-host char
- hostEnd = -1;
- for (var i = 0; i < nonHostChars.length; i++) {
- var hec = rest.indexOf(nonHostChars[i]);
- if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
- hostEnd = hec;
- }
- // if we still have not hit it, then the entire thing is a host.
- if (hostEnd === -1)
- hostEnd = rest.length;
+ /**
+ * Converts a string of Unicode symbols (e.g. a domain name label) to a
+ * Punycode string of ASCII-only symbols.
+ * @memberOf punycode
+ * @param {String} input The string of Unicode symbols.
+ * @returns {String} The resulting Punycode string of ASCII-only symbols.
+ */
+ function encode(input) {
+ var n,
+ delta,
+ handledCPCount,
+ basicLength,
+ bias,
+ j,
+ m,
+ q,
+ k,
+ t,
+ currentValue,
+ output = [],
+ /** `inputLength` will hold the number of code points in `input`. */
+ inputLength,
+ /** Cached calculation results */
+ handledCPCountPlusOne,
+ baseMinusT,
+ qMinusT;
- this.host = rest.slice(0, hostEnd);
- rest = rest.slice(hostEnd);
+ // Convert the input in UCS-2 to Unicode
+ input = ucs2decode(input);
- // pull out port.
- this.parseHost();
+ // Cache the length
+ inputLength = input.length;
- // we've indicated that there is a hostname,
- // so even if it's empty, it has to be present.
- this.hostname = this.hostname || '';
+ // Initialize the state
+ n = initialN;
+ delta = 0;
+ bias = initialBias;
- // if hostname begins with [ and ends with ]
- // assume that it's an IPv6 address.
- var ipv6Hostname = this.hostname[0] === '[' &&
- this.hostname[this.hostname.length - 1] === ']';
+ // Handle the basic code points
+ for (j = 0; j < inputLength; ++j) {
+ currentValue = input[j];
+ if (currentValue < 0x80) {
+ output.push(stringFromCharCode(currentValue));
+ }
+ }
- // validate a little.
- if (!ipv6Hostname) {
- var hostparts = this.hostname.split(/\./);
- for (var i = 0, l = hostparts.length; i < l; i++) {
- var part = hostparts[i];
- if (!part) continue;
- if (!part.match(hostnamePartPattern)) {
- var newpart = '';
- for (var j = 0, k = part.length; j < k; j++) {
- if (part.charCodeAt(j) > 127) {
- // we replace non-ASCII char with a temporary placeholder
- // we need this to make sure size of hostname is not
- // broken by replacing non-ASCII by nothing
- newpart += 'x';
- } else {
- newpart += part[j];
- }
- }
- // we test again with ASCII char only
- if (!newpart.match(hostnamePartPattern)) {
- var validParts = hostparts.slice(0, i);
- var notHost = hostparts.slice(i + 1);
- var bit = part.match(hostnamePartStart);
- if (bit) {
- validParts.push(bit[1]);
- notHost.unshift(bit[2]);
- }
- if (notHost.length) {
- rest = '/' + notHost.join('.') + rest;
- }
- this.hostname = validParts.join('.');
- break;
- }
- }
- }
- }
+ handledCPCount = basicLength = output.length;
- if (this.hostname.length > hostnameMaxLen) {
- this.hostname = '';
- } else {
- // hostnames are always lower case.
- this.hostname = this.hostname.toLowerCase();
- }
+ // `handledCPCount` is the number of code points that have been handled;
+ // `basicLength` is the number of basic code points.
- if (!ipv6Hostname) {
- // IDNA Support: Returns a punycoded representation of "domain".
- // It only converts parts of the domain name that
- // have non-ASCII characters, i.e. it doesn't matter if
- // you call it with a domain that already is ASCII-only.
- this.hostname = punycode.toASCII(this.hostname);
- }
+ // Finish the basic string - if it is not empty - with a delimiter
+ if (basicLength) {
+ output.push(delimiter);
+ }
- var p = this.port ? ':' + this.port : '';
- var h = this.hostname || '';
- this.host = h + p;
- this.href += this.host;
+ // Main encoding loop:
+ while (handledCPCount < inputLength) {
- // strip [ and ] from the hostname
- // the host field still retains them, though
- if (ipv6Hostname) {
- this.hostname = this.hostname.substr(1, this.hostname.length - 2);
- if (rest[0] !== '/') {
- rest = '/' + rest;
- }
- }
- }
+ // All non-basic code points < n have been handled already. Find the next
+ // larger one:
+ for (m = maxInt, j = 0; j < inputLength; ++j) {
+ currentValue = input[j];
+ if (currentValue >= n && currentValue < m) {
+ m = currentValue;
+ }
+ }
- // now rest is set to the post-host stuff.
- // chop off any delim chars.
- if (!unsafeProtocol[lowerProto]) {
+ // Increase `delta` enough to advance the decoder's state to ,
+ // but guard against overflow
+ handledCPCountPlusOne = handledCPCount + 1;
+ if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
+ error('overflow');
+ }
- // First, make 100% sure that any "autoEscape" chars get
- // escaped, even if encodeURIComponent doesn't think they
- // need to be.
- for (var i = 0, l = autoEscape.length; i < l; i++) {
- var ae = autoEscape[i];
- if (rest.indexOf(ae) === -1)
- continue;
- var esc = encodeURIComponent(ae);
- if (esc === ae) {
- esc = escape(ae);
- }
- rest = rest.split(ae).join(esc);
- }
- }
+ delta += (m - n) * handledCPCountPlusOne;
+ n = m;
+ for (j = 0; j < inputLength; ++j) {
+ currentValue = input[j];
- // chop off from the tail first.
- var hash = rest.indexOf('#');
- if (hash !== -1) {
- // got a fragment string.
- this.hash = rest.substr(hash);
- rest = rest.slice(0, hash);
- }
- var qm = rest.indexOf('?');
- if (qm !== -1) {
- this.search = rest.substr(qm);
- this.query = rest.substr(qm + 1);
- if (parseQueryString) {
- this.query = querystring.parse(this.query);
- }
- rest = rest.slice(0, qm);
- } else if (parseQueryString) {
- // no query string, but parseQueryString still requested
- this.search = '';
- this.query = {};
- }
- if (rest) this.pathname = rest;
- if (slashedProtocol[lowerProto] &&
- this.hostname && !this.pathname) {
- this.pathname = '/';
- }
+ if (currentValue < n && ++delta > maxInt) {
+ error('overflow');
+ }
- //to support http.request
- if (this.pathname || this.search) {
- var p = this.pathname || '';
- var s = this.search || '';
- this.path = p + s;
- }
+ if (currentValue == n) {
+ // Represent delta as a generalized variable-length integer
+ for (q = delta, k = base; /* no condition */; k += base) {
+ t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
+ if (q < t) {
+ break;
+ }
+ qMinusT = q - t;
+ baseMinusT = base - t;
+ output.push(
+ stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
+ );
+ q = floor(qMinusT / baseMinusT);
+ }
- // finally, reconstruct the href based on what has been validated.
- this.href = this.format();
- return this;
-};
+ output.push(stringFromCharCode(digitToBasic(q, 0)));
+ bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
+ delta = 0;
+ ++handledCPCount;
+ }
+ }
-// format a parsed object into a url string
-function urlFormat(obj) {
- // ensure it's an object, and not a string url.
- // If it's an obj, this is a no-op.
- // this way, you can call url_format() on strings
- // to clean up potentially wonky urls.
- if (util.isString(obj)) obj = urlParse(obj);
- if (!(obj instanceof Url)) return Url.prototype.format.call(obj);
- return obj.format();
-}
+ ++delta;
+ ++n;
-Url.prototype.format = function() {
- var auth = this.auth || '';
- if (auth) {
- auth = encodeURIComponent(auth);
- auth = auth.replace(/%3A/i, ':');
- auth += '@';
- }
+ }
+ return output.join('');
+ }
- var protocol = this.protocol || '',
- pathname = this.pathname || '',
- hash = this.hash || '',
- host = false,
- query = '';
-
- if (this.host) {
- host = auth + this.host;
- } else if (this.hostname) {
- host = auth + (this.hostname.indexOf(':') === -1 ?
- this.hostname :
- '[' + this.hostname + ']');
- if (this.port) {
- host += ':' + this.port;
- }
- }
+ /**
+ * Converts a Punycode string representing a domain name or an email address
+ * to Unicode. Only the Punycoded parts of the input will be converted, i.e.
+ * it doesn't matter if you call it on a string that has already been
+ * converted to Unicode.
+ * @memberOf punycode
+ * @param {String} input The Punycoded domain name or email address to
+ * convert to Unicode.
+ * @returns {String} The Unicode representation of the given Punycode
+ * string.
+ */
+ function toUnicode(input) {
+ return mapDomain(input, function(string) {
+ return regexPunycode.test(string)
+ ? decode(string.slice(4).toLowerCase())
+ : string;
+ });
+ }
- if (this.query &&
- util.isObject(this.query) &&
- Object.keys(this.query).length) {
- query = querystring.stringify(this.query);
- }
+ /**
+ * Converts a Unicode string representing a domain name or an email address to
+ * Punycode. Only the non-ASCII parts of the domain name will be converted,
+ * i.e. it doesn't matter if you call it with a domain that's already in
+ * ASCII.
+ * @memberOf punycode
+ * @param {String} input The domain name or email address to convert, as a
+ * Unicode string.
+ * @returns {String} The Punycode representation of the given domain name or
+ * email address.
+ */
+ function toASCII(input) {
+ return mapDomain(input, function(string) {
+ return regexNonASCII.test(string)
+ ? 'xn--' + encode(string)
+ : string;
+ });
+ }
- var search = this.search || (query && ('?' + query)) || '';
+ /*--------------------------------------------------------------------------*/
- if (protocol && protocol.substr(-1) !== ':') protocol += ':';
+ /** Define the public API */
+ punycode = {
+ /**
+ * A string representing the current Punycode.js version number.
+ * @memberOf punycode
+ * @type String
+ */
+ 'version': '1.4.1',
+ /**
+ * An object of methods to convert from JavaScript's internal character
+ * representation (UCS-2) to Unicode code points, and back.
+ * @see
+ * @memberOf punycode
+ * @type Object
+ */
+ 'ucs2': {
+ 'decode': ucs2decode,
+ 'encode': ucs2encode
+ },
+ 'decode': decode,
+ 'encode': encode,
+ 'toASCII': toASCII,
+ 'toUnicode': toUnicode
+ };
- // only the slashedProtocols get the //. Not mailto:, xmpp:, etc.
- // unless they had them to begin with.
- if (this.slashes ||
- (!protocol || slashedProtocol[protocol]) && host !== false) {
- host = '//' + (host || '');
- if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname;
- } else if (!host) {
- host = '';
- }
+ /** Expose `punycode` */
+ // Some AMD build optimizers, like r.js, check for specific condition patterns
+ // like the following:
+ if (
+ typeof define == 'function' &&
+ typeof define.amd == 'object' &&
+ define.amd
+ ) {
+ define('punycode', function() {
+ return punycode;
+ });
+ } else if (freeExports && freeModule) {
+ if (module.exports == freeExports) {
+ // in Node.js, io.js, or RingoJS v0.8.0+
+ freeModule.exports = punycode;
+ } else {
+ // in Narwhal or RingoJS v0.7.0-
+ for (key in punycode) {
+ punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
+ }
+ }
+ } else {
+ // in Rhino or a web browser
+ root.punycode = punycode;
+ }
- if (hash && hash.charAt(0) !== '#') hash = '#' + hash;
- if (search && search.charAt(0) !== '?') search = '?' + search;
+}(this));
- pathname = pathname.replace(/[?#]/g, function(match) {
- return encodeURIComponent(match);
- });
- search = search.replace('#', '%23');
+}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+},{}],47:[function(require,module,exports){
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
- return protocol + host + pathname + search + hash;
-};
+'use strict';
-function urlResolve(source, relative) {
- return urlParse(source, false, true).resolve(relative);
+// If obj.hasOwnProperty has been overridden, then calling
+// obj.hasOwnProperty(prop) will break.
+// See: https://github.com/joyent/node/issues/1707
+function hasOwnProperty(obj, prop) {
+ return Object.prototype.hasOwnProperty.call(obj, prop);
}
-Url.prototype.resolve = function(relative) {
- return this.resolveObject(urlParse(relative, false, true)).format();
-};
-
-function urlResolveObject(source, relative) {
- if (!source) return relative;
- return urlParse(source, false, true).resolveObject(relative);
-}
+module.exports = function(qs, sep, eq, options) {
+ sep = sep || '&';
+ eq = eq || '=';
+ var obj = {};
-Url.prototype.resolveObject = function(relative) {
- if (util.isString(relative)) {
- var rel = new Url();
- rel.parse(relative, false, true);
- relative = rel;
+ if (typeof qs !== 'string' || qs.length === 0) {
+ return obj;
}
- var result = new Url();
- var tkeys = Object.keys(this);
- for (var tk = 0; tk < tkeys.length; tk++) {
- var tkey = tkeys[tk];
- result[tkey] = this[tkey];
- }
+ var regexp = /\+/g;
+ qs = qs.split(sep);
- // hash is always overridden, no matter what.
- // even href="" will remove it.
- result.hash = relative.hash;
+ var maxKeys = 1000;
+ if (options && typeof options.maxKeys === 'number') {
+ maxKeys = options.maxKeys;
+ }
- // if the relative url is empty, then there's nothing left to do here.
- if (relative.href === '') {
- result.href = result.format();
- return result;
+ var len = qs.length;
+ // maxKeys <= 0 means that we should not limit keys count
+ if (maxKeys > 0 && len > maxKeys) {
+ len = maxKeys;
}
- // hrefs like //foo/bar always cut to the protocol.
- if (relative.slashes && !relative.protocol) {
- // take everything except the protocol from relative
- var rkeys = Object.keys(relative);
- for (var rk = 0; rk < rkeys.length; rk++) {
- var rkey = rkeys[rk];
- if (rkey !== 'protocol')
- result[rkey] = relative[rkey];
- }
+ for (var i = 0; i < len; ++i) {
+ var x = qs[i].replace(regexp, '%20'),
+ idx = x.indexOf(eq),
+ kstr, vstr, k, v;
- //urlParse appends trailing / to urls like http://www.example.com
- if (slashedProtocol[result.protocol] &&
- result.hostname && !result.pathname) {
- result.path = result.pathname = '/';
+ if (idx >= 0) {
+ kstr = x.substr(0, idx);
+ vstr = x.substr(idx + 1);
+ } else {
+ kstr = x;
+ vstr = '';
}
- result.href = result.format();
- return result;
- }
+ k = decodeURIComponent(kstr);
+ v = decodeURIComponent(vstr);
- if (relative.protocol && relative.protocol !== result.protocol) {
- // if it's a known url protocol, then changing
- // the protocol does weird things
- // first, if it's not file:, then we MUST have a host,
- // and if there was a path
- // to begin with, then we MUST have a path.
- // if it is file:, then the host is dropped,
- // because that's known to be hostless.
- // anything else is assumed to be absolute.
- if (!slashedProtocol[relative.protocol]) {
- var keys = Object.keys(relative);
- for (var v = 0; v < keys.length; v++) {
- var k = keys[v];
- result[k] = relative[k];
- }
- result.href = result.format();
- return result;
+ if (!hasOwnProperty(obj, k)) {
+ obj[k] = v;
+ } else if (isArray(obj[k])) {
+ obj[k].push(v);
+ } else {
+ obj[k] = [obj[k], v];
}
+ }
- result.protocol = relative.protocol;
- if (!relative.host && !hostlessProtocol[relative.protocol]) {
- var relPath = (relative.pathname || '').split('/');
- while (relPath.length && !(relative.host = relPath.shift()));
- if (!relative.host) relative.host = '';
- if (!relative.hostname) relative.hostname = '';
- if (relPath[0] !== '') relPath.unshift('');
- if (relPath.length < 2) relPath.unshift('');
- result.pathname = relPath.join('/');
- } else {
- result.pathname = relative.pathname;
- }
- result.search = relative.search;
- result.query = relative.query;
- result.host = relative.host || '';
- result.auth = relative.auth;
- result.hostname = relative.hostname || relative.host;
- result.port = relative.port;
- // to support http.request
- if (result.pathname || result.search) {
- var p = result.pathname || '';
- var s = result.search || '';
- result.path = p + s;
- }
- result.slashes = result.slashes || relative.slashes;
- result.href = result.format();
- return result;
- }
-
- var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'),
- isRelAbs = (
- relative.host ||
- relative.pathname && relative.pathname.charAt(0) === '/'
- ),
- mustEndAbs = (isRelAbs || isSourceAbs ||
- (result.host && relative.pathname)),
- removeAllDots = mustEndAbs,
- srcPath = result.pathname && result.pathname.split('/') || [],
- relPath = relative.pathname && relative.pathname.split('/') || [],
- psychotic = result.protocol && !slashedProtocol[result.protocol];
+ return obj;
+};
- // if the url is a non-slashed url, then relative
- // links like ../.. should be able
- // to crawl up to the hostname, as well. This is strange.
- // result.protocol has already been set by now.
- // Later on, put the first path part into the host field.
- if (psychotic) {
- result.hostname = '';
- result.port = null;
- if (result.host) {
- if (srcPath[0] === '') srcPath[0] = result.host;
- else srcPath.unshift(result.host);
- }
- result.host = '';
- if (relative.protocol) {
- relative.hostname = null;
- relative.port = null;
- if (relative.host) {
- if (relPath[0] === '') relPath[0] = relative.host;
- else relPath.unshift(relative.host);
- }
- relative.host = null;
- }
- mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === '');
- }
+var isArray = Array.isArray || function (xs) {
+ return Object.prototype.toString.call(xs) === '[object Array]';
+};
- if (isRelAbs) {
- // it's absolute.
- result.host = (relative.host || relative.host === '') ?
- relative.host : result.host;
- result.hostname = (relative.hostname || relative.hostname === '') ?
- relative.hostname : result.hostname;
- result.search = relative.search;
- result.query = relative.query;
- srcPath = relPath;
- // fall through to the dot-handling below.
- } else if (relPath.length) {
- // it's relative
- // throw away the existing file, and take the new path instead.
- if (!srcPath) srcPath = [];
- srcPath.pop();
- srcPath = srcPath.concat(relPath);
- result.search = relative.search;
- result.query = relative.query;
- } else if (!util.isNullOrUndefined(relative.search)) {
- // just pull out the search.
- // like href='?foo'.
- // Put this after the other two cases because it simplifies the booleans
- if (psychotic) {
- result.hostname = result.host = srcPath.shift();
- //occationaly the auth can get stuck only in host
- //this especially happens in cases like
- //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
- var authInHost = result.host && result.host.indexOf('@') > 0 ?
- result.host.split('@') : false;
- if (authInHost) {
- result.auth = authInHost.shift();
- result.host = result.hostname = authInHost.shift();
- }
- }
- result.search = relative.search;
- result.query = relative.query;
- //to support http.request
- if (!util.isNull(result.pathname) || !util.isNull(result.search)) {
- result.path = (result.pathname ? result.pathname : '') +
- (result.search ? result.search : '');
- }
- result.href = result.format();
- return result;
- }
+},{}],48:[function(require,module,exports){
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
- if (!srcPath.length) {
- // no path at all. easy.
- // we've already handled the other stuff above.
- result.pathname = null;
- //to support http.request
- if (result.search) {
- result.path = '/' + result.search;
- } else {
- result.path = null;
- }
- result.href = result.format();
- return result;
- }
+'use strict';
- // if a url ENDs in . or .., then it must get a trailing slash.
- // however, if it ends in anything else non-slashy,
- // then it must NOT get a trailing slash.
- var last = srcPath.slice(-1)[0];
- var hasTrailingSlash = (
- (result.host || relative.host || srcPath.length > 1) &&
- (last === '.' || last === '..') || last === '');
+var stringifyPrimitive = function(v) {
+ switch (typeof v) {
+ case 'string':
+ return v;
- // strip single dots, resolve double dots to parent dir
- // if the path tries to go above the root, `up` ends up > 0
- var up = 0;
- for (var i = srcPath.length; i >= 0; i--) {
- last = srcPath[i];
- if (last === '.') {
- srcPath.splice(i, 1);
- } else if (last === '..') {
- srcPath.splice(i, 1);
- up++;
- } else if (up) {
- srcPath.splice(i, 1);
- up--;
- }
- }
+ case 'boolean':
+ return v ? 'true' : 'false';
- // if the path is allowed to go above the root, restore leading ..s
- if (!mustEndAbs && !removeAllDots) {
- for (; up--; up) {
- srcPath.unshift('..');
- }
- }
+ case 'number':
+ return isFinite(v) ? v : '';
- if (mustEndAbs && srcPath[0] !== '' &&
- (!srcPath[0] || srcPath[0].charAt(0) !== '/')) {
- srcPath.unshift('');
+ default:
+ return '';
}
+};
- if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) {
- srcPath.push('');
+module.exports = function(obj, sep, eq, name) {
+ sep = sep || '&';
+ eq = eq || '=';
+ if (obj === null) {
+ obj = undefined;
}
- var isAbsolute = srcPath[0] === '' ||
- (srcPath[0] && srcPath[0].charAt(0) === '/');
+ if (typeof obj === 'object') {
+ return map(objectKeys(obj), function(k) {
+ var ks = encodeURIComponent(stringifyPrimitive(k)) + eq;
+ if (isArray(obj[k])) {
+ return map(obj[k], function(v) {
+ return ks + encodeURIComponent(stringifyPrimitive(v));
+ }).join(sep);
+ } else {
+ return ks + encodeURIComponent(stringifyPrimitive(obj[k]));
+ }
+ }).join(sep);
- // put the host back
- if (psychotic) {
- result.hostname = result.host = isAbsolute ? '' :
- srcPath.length ? srcPath.shift() : '';
- //occationaly the auth can get stuck only in host
- //this especially happens in cases like
- //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
- var authInHost = result.host && result.host.indexOf('@') > 0 ?
- result.host.split('@') : false;
- if (authInHost) {
- result.auth = authInHost.shift();
- result.host = result.hostname = authInHost.shift();
- }
}
- mustEndAbs = mustEndAbs || (result.host && srcPath.length);
+ if (!name) return '';
+ return encodeURIComponent(stringifyPrimitive(name)) + eq +
+ encodeURIComponent(stringifyPrimitive(obj));
+};
- if (mustEndAbs && !isAbsolute) {
- srcPath.unshift('');
- }
+var isArray = Array.isArray || function (xs) {
+ return Object.prototype.toString.call(xs) === '[object Array]';
+};
- if (!srcPath.length) {
- result.pathname = null;
- result.path = null;
- } else {
- result.pathname = srcPath.join('/');
+function map (xs, f) {
+ if (xs.map) return xs.map(f);
+ var res = [];
+ for (var i = 0; i < xs.length; i++) {
+ res.push(f(xs[i], i));
}
+ return res;
+}
- //to support request.http
- if (!util.isNull(result.pathname) || !util.isNull(result.search)) {
- result.path = (result.pathname ? result.pathname : '') +
- (result.search ? result.search : '');
+var objectKeys = Object.keys || function (obj) {
+ var res = [];
+ for (var key in obj) {
+ if (Object.prototype.hasOwnProperty.call(obj, key)) res.push(key);
}
- result.auth = relative.auth || result.auth;
- result.slashes = result.slashes || relative.slashes;
- result.href = result.format();
- return result;
+ return res;
};
-Url.prototype.parseHost = function() {
- var host = this.host;
- var port = portPattern.exec(host);
- if (port) {
- port = port[0];
- if (port !== ':') {
- this.port = port.substr(1);
- }
- host = host.substr(0, host.length - port.length);
- }
- if (host) this.hostname = host;
-};
+},{}],49:[function(require,module,exports){
+'use strict';
+
+exports.decode = exports.parse = require('./decode');
+exports.encode = exports.stringify = require('./encode');
+
+},{"./decode":47,"./encode":48}],50:[function(require,module,exports){
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
-},{"./util":46,"punycode":41,"querystring":44}],46:[function(require,module,exports){
'use strict';
-module.exports = {
- isString: function(arg) {
- return typeof(arg) === 'string';
- },
- isObject: function(arg) {
- return typeof(arg) === 'object' && arg !== null;
- },
- isNull: function(arg) {
- return arg === null;
- },
- isNullOrUndefined: function(arg) {
- return arg == null;
- }
-};
+var punycode = require('punycode');
+var util = require('./util');
-},{}],47:[function(require,module,exports){
+exports.parse = urlParse;
+exports.resolve = urlResolve;
+exports.resolveObject = urlResolveObject;
+exports.format = urlFormat;
-/**
- * slice() reference.
- */
+exports.Url = Url;
-var slice = Array.prototype.slice;
+function Url() {
+ this.protocol = null;
+ this.slashes = null;
+ this.auth = null;
+ this.host = null;
+ this.port = null;
+ this.hostname = null;
+ this.hash = null;
+ this.search = null;
+ this.query = null;
+ this.pathname = null;
+ this.path = null;
+ this.href = null;
+}
-/**
- * Expose `co`.
- */
+// Reference: RFC 3986, RFC 1808, RFC 2396
-module.exports = co['default'] = co.co = co;
+// define these here so at least they only have to be
+// compiled once on the first module load.
+var protocolPattern = /^([a-z0-9.+-]+:)/i,
+ portPattern = /:[0-9]*$/,
-/**
- * Wrap the given generator `fn` into a
- * function that returns a promise.
- * This is a separate function so that
- * every `co()` call doesn't create a new,
- * unnecessary closure.
- *
- * @param {GeneratorFunction} fn
- * @return {Function}
- * @api public
- */
+ // Special case for a simple path URL
+ simplePathPattern = /^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/,
-co.wrap = function (fn) {
- createPromise.__generatorFunction__ = fn;
- return createPromise;
- function createPromise() {
- return co.call(this, fn.apply(this, arguments));
- }
-};
+ // RFC 2396: characters reserved for delimiting URLs.
+ // We actually just auto-escape these.
+ delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'],
-/**
- * Execute the generator function or a generator
- * and return a promise.
- *
- * @param {Function} fn
- * @return {Promise}
- * @api public
- */
+ // RFC 2396: characters not allowed for various reasons.
+ unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims),
-function co(gen) {
- var ctx = this;
- var args = slice.call(arguments, 1)
+ // Allowed by RFCs, but cause of XSS attacks. Always escape these.
+ autoEscape = ['\''].concat(unwise),
+ // Characters that are never ever allowed in a hostname.
+ // Note that any invalid chars are also handled, but these
+ // are the ones that are *expected* to be seen, so we fast-path
+ // them.
+ nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape),
+ hostEndingChars = ['/', '?', '#'],
+ hostnameMaxLen = 255,
+ hostnamePartPattern = /^[+a-z0-9A-Z_-]{0,63}$/,
+ hostnamePartStart = /^([+a-z0-9A-Z_-]{0,63})(.*)$/,
+ // protocols that can allow "unsafe" and "unwise" chars.
+ unsafeProtocol = {
+ 'javascript': true,
+ 'javascript:': true
+ },
+ // protocols that never have a hostname.
+ hostlessProtocol = {
+ 'javascript': true,
+ 'javascript:': true
+ },
+ // protocols that always contain a // bit.
+ slashedProtocol = {
+ 'http': true,
+ 'https': true,
+ 'ftp': true,
+ 'gopher': true,
+ 'file': true,
+ 'http:': true,
+ 'https:': true,
+ 'ftp:': true,
+ 'gopher:': true,
+ 'file:': true
+ },
+ querystring = require('querystring');
- // we wrap everything in a promise to avoid promise chaining,
- // which leads to memory leak errors.
- // see https://github.com/tj/co/issues/180
- return new Promise(function(resolve, reject) {
- if (typeof gen === 'function') gen = gen.apply(ctx, args);
- if (!gen || typeof gen.next !== 'function') return resolve(gen);
+function urlParse(url, parseQueryString, slashesDenoteHost) {
+ if (url && util.isObject(url) && url instanceof Url) return url;
- onFulfilled();
+ var u = new Url;
+ u.parse(url, parseQueryString, slashesDenoteHost);
+ return u;
+}
- /**
- * @param {Mixed} res
- * @return {Promise}
- * @api private
- */
+Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) {
+ if (!util.isString(url)) {
+ throw new TypeError("Parameter 'url' must be a string, not " + typeof url);
+ }
- function onFulfilled(res) {
- var ret;
- try {
- ret = gen.next(res);
- } catch (e) {
- return reject(e);
- }
- next(ret);
- }
+ // Copy chrome, IE, opera backslash-handling behavior.
+ // Back slashes before the query string get converted to forward slashes
+ // See: https://code.google.com/p/chromium/issues/detail?id=25916
+ var queryIndex = url.indexOf('?'),
+ splitter =
+ (queryIndex !== -1 && queryIndex < url.indexOf('#')) ? '?' : '#',
+ uSplit = url.split(splitter),
+ slashRegex = /\\/g;
+ uSplit[0] = uSplit[0].replace(slashRegex, '/');
+ url = uSplit.join(splitter);
- /**
- * @param {Error} err
- * @return {Promise}
- * @api private
- */
+ var rest = url;
- function onRejected(err) {
- var ret;
- try {
- ret = gen.throw(err);
- } catch (e) {
- return reject(e);
+ // trim before proceeding.
+ // This is to support parse stuff like " http://foo.com \n"
+ rest = rest.trim();
+
+ if (!slashesDenoteHost && url.split('#').length === 1) {
+ // Try fast path regexp
+ var simplePath = simplePathPattern.exec(rest);
+ if (simplePath) {
+ this.path = rest;
+ this.href = rest;
+ this.pathname = simplePath[1];
+ if (simplePath[2]) {
+ this.search = simplePath[2];
+ if (parseQueryString) {
+ this.query = querystring.parse(this.search.substr(1));
+ } else {
+ this.query = this.search.substr(1);
+ }
+ } else if (parseQueryString) {
+ this.search = '';
+ this.query = {};
}
- next(ret);
+ return this;
}
+ }
- /**
- * Get the next value in the generator,
- * return a promise.
- *
- * @param {Object} ret
- * @return {Promise}
- * @api private
- */
-
- function next(ret) {
- if (ret.done) return resolve(ret.value);
- var value = toPromise.call(ctx, ret.value);
- if (value && isPromise(value)) return value.then(onFulfilled, onRejected);
- return onRejected(new TypeError('You may only yield a function, promise, generator, array, or object, '
- + 'but the following object was passed: "' + String(ret.value) + '"'));
- }
- });
-}
+ var proto = protocolPattern.exec(rest);
+ if (proto) {
+ proto = proto[0];
+ var lowerProto = proto.toLowerCase();
+ this.protocol = lowerProto;
+ rest = rest.substr(proto.length);
+ }
-/**
- * Convert a `yield`ed value into a promise.
- *
- * @param {Mixed} obj
- * @return {Promise}
- * @api private
- */
+ // figure out if it's got a host
+ // user@server is *always* interpreted as a hostname, and url
+ // resolution will treat //foo/bar as host=foo,path=bar because that's
+ // how the browser resolves relative URLs.
+ if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) {
+ var slashes = rest.substr(0, 2) === '//';
+ if (slashes && !(proto && hostlessProtocol[proto])) {
+ rest = rest.substr(2);
+ this.slashes = true;
+ }
+ }
-function toPromise(obj) {
- if (!obj) return obj;
- if (isPromise(obj)) return obj;
- if (isGeneratorFunction(obj) || isGenerator(obj)) return co.call(this, obj);
- if ('function' == typeof obj) return thunkToPromise.call(this, obj);
- if (Array.isArray(obj)) return arrayToPromise.call(this, obj);
- if (isObject(obj)) return objectToPromise.call(this, obj);
- return obj;
-}
+ if (!hostlessProtocol[proto] &&
+ (slashes || (proto && !slashedProtocol[proto]))) {
-/**
- * Convert a thunk to a promise.
- *
- * @param {Function}
- * @return {Promise}
- * @api private
- */
+ // there's a hostname.
+ // the first instance of /, ?, ;, or # ends the host.
+ //
+ // If there is an @ in the hostname, then non-host chars *are* allowed
+ // to the left of the last @ sign, unless some host-ending character
+ // comes *before* the @-sign.
+ // URLs are obnoxious.
+ //
+ // ex:
+ // http://a@b@c/ => user:a@b host:c
+ // http://a@b?@c => user:a host:c path:/?@c
-function thunkToPromise(fn) {
- var ctx = this;
- return new Promise(function (resolve, reject) {
- fn.call(ctx, function (err, res) {
- if (err) return reject(err);
- if (arguments.length > 2) res = slice.call(arguments, 1);
- resolve(res);
- });
- });
-}
+ // v0.12 TODO(isaacs): This is not quite how Chrome does things.
+ // Review our test case against browsers more comprehensively.
-/**
- * Convert an array of "yieldables" to a promise.
- * Uses `Promise.all()` internally.
- *
- * @param {Array} obj
- * @return {Promise}
- * @api private
- */
+ // find the first instance of any hostEndingChars
+ var hostEnd = -1;
+ for (var i = 0; i < hostEndingChars.length; i++) {
+ var hec = rest.indexOf(hostEndingChars[i]);
+ if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
+ hostEnd = hec;
+ }
-function arrayToPromise(obj) {
- return Promise.all(obj.map(toPromise, this));
-}
+ // at this point, either we have an explicit point where the
+ // auth portion cannot go past, or the last @ char is the decider.
+ var auth, atSign;
+ if (hostEnd === -1) {
+ // atSign can be anywhere.
+ atSign = rest.lastIndexOf('@');
+ } else {
+ // atSign must be in auth portion.
+ // http://a@b/c@d => host:b auth:a path:/c@d
+ atSign = rest.lastIndexOf('@', hostEnd);
+ }
-/**
- * Convert an object of "yieldables" to a promise.
- * Uses `Promise.all()` internally.
- *
- * @param {Object} obj
- * @return {Promise}
- * @api private
- */
+ // Now we have a portion which is definitely the auth.
+ // Pull that off.
+ if (atSign !== -1) {
+ auth = rest.slice(0, atSign);
+ rest = rest.slice(atSign + 1);
+ this.auth = decodeURIComponent(auth);
+ }
-function objectToPromise(obj){
- var results = new obj.constructor();
- var keys = Object.keys(obj);
- var promises = [];
- for (var i = 0; i < keys.length; i++) {
- var key = keys[i];
- var promise = toPromise.call(this, obj[key]);
- if (promise && isPromise(promise)) defer(promise, key);
- else results[key] = obj[key];
- }
- return Promise.all(promises).then(function () {
- return results;
- });
+ // the host is the remaining to the left of the first non-host char
+ hostEnd = -1;
+ for (var i = 0; i < nonHostChars.length; i++) {
+ var hec = rest.indexOf(nonHostChars[i]);
+ if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
+ hostEnd = hec;
+ }
+ // if we still have not hit it, then the entire thing is a host.
+ if (hostEnd === -1)
+ hostEnd = rest.length;
- function defer(promise, key) {
- // predefine the key in the result
- results[key] = undefined;
- promises.push(promise.then(function (res) {
- results[key] = res;
- }));
- }
-}
+ this.host = rest.slice(0, hostEnd);
+ rest = rest.slice(hostEnd);
-/**
- * Check if `obj` is a promise.
- *
- * @param {Object} obj
- * @return {Boolean}
- * @api private
- */
+ // pull out port.
+ this.parseHost();
-function isPromise(obj) {
- return 'function' == typeof obj.then;
-}
+ // we've indicated that there is a hostname,
+ // so even if it's empty, it has to be present.
+ this.hostname = this.hostname || '';
-/**
- * Check if `obj` is a generator.
- *
- * @param {Mixed} obj
- * @return {Boolean}
- * @api private
- */
+ // if hostname begins with [ and ends with ]
+ // assume that it's an IPv6 address.
+ var ipv6Hostname = this.hostname[0] === '[' &&
+ this.hostname[this.hostname.length - 1] === ']';
-function isGenerator(obj) {
- return 'function' == typeof obj.next && 'function' == typeof obj.throw;
-}
+ // validate a little.
+ if (!ipv6Hostname) {
+ var hostparts = this.hostname.split(/\./);
+ for (var i = 0, l = hostparts.length; i < l; i++) {
+ var part = hostparts[i];
+ if (!part) continue;
+ if (!part.match(hostnamePartPattern)) {
+ var newpart = '';
+ for (var j = 0, k = part.length; j < k; j++) {
+ if (part.charCodeAt(j) > 127) {
+ // we replace non-ASCII char with a temporary placeholder
+ // we need this to make sure size of hostname is not
+ // broken by replacing non-ASCII by nothing
+ newpart += 'x';
+ } else {
+ newpart += part[j];
+ }
+ }
+ // we test again with ASCII char only
+ if (!newpart.match(hostnamePartPattern)) {
+ var validParts = hostparts.slice(0, i);
+ var notHost = hostparts.slice(i + 1);
+ var bit = part.match(hostnamePartStart);
+ if (bit) {
+ validParts.push(bit[1]);
+ notHost.unshift(bit[2]);
+ }
+ if (notHost.length) {
+ rest = '/' + notHost.join('.') + rest;
+ }
+ this.hostname = validParts.join('.');
+ break;
+ }
+ }
+ }
+ }
-/**
- * Check if `obj` is a generator function.
- *
- * @param {Mixed} obj
- * @return {Boolean}
- * @api private
- */
-function isGeneratorFunction(obj) {
- var constructor = obj.constructor;
- if (!constructor) return false;
- if ('GeneratorFunction' === constructor.name || 'GeneratorFunction' === constructor.displayName) return true;
- return isGenerator(constructor.prototype);
-}
+ if (this.hostname.length > hostnameMaxLen) {
+ this.hostname = '';
+ } else {
+ // hostnames are always lower case.
+ this.hostname = this.hostname.toLowerCase();
+ }
-/**
- * Check for plain object.
- *
- * @param {Mixed} val
- * @return {Boolean}
- * @api private
- */
+ if (!ipv6Hostname) {
+ // IDNA Support: Returns a punycoded representation of "domain".
+ // It only converts parts of the domain name that
+ // have non-ASCII characters, i.e. it doesn't matter if
+ // you call it with a domain that already is ASCII-only.
+ this.hostname = punycode.toASCII(this.hostname);
+ }
-function isObject(val) {
- return Object == val.constructor;
-}
+ var p = this.port ? ':' + this.port : '';
+ var h = this.hostname || '';
+ this.host = h + p;
+ this.href += this.host;
-},{}],48:[function(require,module,exports){
-var json = typeof JSON !== 'undefined' ? JSON : require('jsonify');
+ // strip [ and ] from the hostname
+ // the host field still retains them, though
+ if (ipv6Hostname) {
+ this.hostname = this.hostname.substr(1, this.hostname.length - 2);
+ if (rest[0] !== '/') {
+ rest = '/' + rest;
+ }
+ }
+ }
-module.exports = function (obj, opts) {
- if (!opts) opts = {};
- if (typeof opts === 'function') opts = { cmp: opts };
- var space = opts.space || '';
- if (typeof space === 'number') space = Array(space+1).join(' ');
- var cycles = (typeof opts.cycles === 'boolean') ? opts.cycles : false;
- var replacer = opts.replacer || function(key, value) { return value; };
+ // now rest is set to the post-host stuff.
+ // chop off any delim chars.
+ if (!unsafeProtocol[lowerProto]) {
- var cmp = opts.cmp && (function (f) {
- return function (node) {
- return function (a, b) {
- var aobj = { key: a, value: node[a] };
- var bobj = { key: b, value: node[b] };
- return f(aobj, bobj);
- };
- };
- })(opts.cmp);
+ // First, make 100% sure that any "autoEscape" chars get
+ // escaped, even if encodeURIComponent doesn't think they
+ // need to be.
+ for (var i = 0, l = autoEscape.length; i < l; i++) {
+ var ae = autoEscape[i];
+ if (rest.indexOf(ae) === -1)
+ continue;
+ var esc = encodeURIComponent(ae);
+ if (esc === ae) {
+ esc = escape(ae);
+ }
+ rest = rest.split(ae).join(esc);
+ }
+ }
- var seen = [];
- return (function stringify (parent, key, node, level) {
- var indent = space ? ('\n' + new Array(level + 1).join(space)) : '';
- var colonSeparator = space ? ': ' : ':';
- if (node && node.toJSON && typeof node.toJSON === 'function') {
- node = node.toJSON();
- }
+ // chop off from the tail first.
+ var hash = rest.indexOf('#');
+ if (hash !== -1) {
+ // got a fragment string.
+ this.hash = rest.substr(hash);
+ rest = rest.slice(0, hash);
+ }
+ var qm = rest.indexOf('?');
+ if (qm !== -1) {
+ this.search = rest.substr(qm);
+ this.query = rest.substr(qm + 1);
+ if (parseQueryString) {
+ this.query = querystring.parse(this.query);
+ }
+ rest = rest.slice(0, qm);
+ } else if (parseQueryString) {
+ // no query string, but parseQueryString still requested
+ this.search = '';
+ this.query = {};
+ }
+ if (rest) this.pathname = rest;
+ if (slashedProtocol[lowerProto] &&
+ this.hostname && !this.pathname) {
+ this.pathname = '/';
+ }
- node = replacer.call(parent, key, node);
+ //to support http.request
+ if (this.pathname || this.search) {
+ var p = this.pathname || '';
+ var s = this.search || '';
+ this.path = p + s;
+ }
- if (node === undefined) {
- return;
- }
- if (typeof node !== 'object' || node === null) {
- return json.stringify(node);
- }
- if (isArray(node)) {
- var out = [];
- for (var i = 0; i < node.length; i++) {
- var item = stringify(node, i, node[i], level+1) || json.stringify(null);
- out.push(indent + space + item);
- }
- return '[' + out.join(',') + indent + ']';
- }
- else {
- if (seen.indexOf(node) !== -1) {
- if (cycles) return json.stringify('__cycle__');
- throw new TypeError('Converting circular structure to JSON');
- }
- else seen.push(node);
+ // finally, reconstruct the href based on what has been validated.
+ this.href = this.format();
+ return this;
+};
- var keys = objectKeys(node).sort(cmp && cmp(node));
- var out = [];
- for (var i = 0; i < keys.length; i++) {
- var key = keys[i];
- var value = stringify(node, key, node[key], level+1);
+// format a parsed object into a url string
+function urlFormat(obj) {
+ // ensure it's an object, and not a string url.
+ // If it's an obj, this is a no-op.
+ // this way, you can call url_format() on strings
+ // to clean up potentially wonky urls.
+ if (util.isString(obj)) obj = urlParse(obj);
+ if (!(obj instanceof Url)) return Url.prototype.format.call(obj);
+ return obj.format();
+}
- if(!value) continue;
+Url.prototype.format = function() {
+ var auth = this.auth || '';
+ if (auth) {
+ auth = encodeURIComponent(auth);
+ auth = auth.replace(/%3A/i, ':');
+ auth += '@';
+ }
- var keyValue = json.stringify(key)
- + colonSeparator
- + value;
- ;
- out.push(indent + space + keyValue);
- }
- seen.splice(seen.indexOf(node), 1);
- return '{' + out.join(',') + indent + '}';
- }
- })({ '': obj }, '', obj, 0);
+ var protocol = this.protocol || '',
+ pathname = this.pathname || '',
+ hash = this.hash || '',
+ host = false,
+ query = '';
+
+ if (this.host) {
+ host = auth + this.host;
+ } else if (this.hostname) {
+ host = auth + (this.hostname.indexOf(':') === -1 ?
+ this.hostname :
+ '[' + this.hostname + ']');
+ if (this.port) {
+ host += ':' + this.port;
+ }
+ }
+
+ if (this.query &&
+ util.isObject(this.query) &&
+ Object.keys(this.query).length) {
+ query = querystring.stringify(this.query);
+ }
+
+ var search = this.search || (query && ('?' + query)) || '';
+
+ if (protocol && protocol.substr(-1) !== ':') protocol += ':';
+
+ // only the slashedProtocols get the //. Not mailto:, xmpp:, etc.
+ // unless they had them to begin with.
+ if (this.slashes ||
+ (!protocol || slashedProtocol[protocol]) && host !== false) {
+ host = '//' + (host || '');
+ if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname;
+ } else if (!host) {
+ host = '';
+ }
+
+ if (hash && hash.charAt(0) !== '#') hash = '#' + hash;
+ if (search && search.charAt(0) !== '?') search = '?' + search;
+
+ pathname = pathname.replace(/[?#]/g, function(match) {
+ return encodeURIComponent(match);
+ });
+ search = search.replace('#', '%23');
+
+ return protocol + host + pathname + search + hash;
};
-var isArray = Array.isArray || function (x) {
- return {}.toString.call(x) === '[object Array]';
+function urlResolve(source, relative) {
+ return urlParse(source, false, true).resolve(relative);
+}
+
+Url.prototype.resolve = function(relative) {
+ return this.resolveObject(urlParse(relative, false, true)).format();
};
-var objectKeys = Object.keys || function (obj) {
- var has = Object.prototype.hasOwnProperty || function () { return true };
- var keys = [];
- for (var key in obj) {
- if (has.call(obj, key)) keys.push(key);
+function urlResolveObject(source, relative) {
+ if (!source) return relative;
+ return urlParse(source, false, true).resolveObject(relative);
+}
+
+Url.prototype.resolveObject = function(relative) {
+ if (util.isString(relative)) {
+ var rel = new Url();
+ rel.parse(relative, false, true);
+ relative = rel;
+ }
+
+ var result = new Url();
+ var tkeys = Object.keys(this);
+ for (var tk = 0; tk < tkeys.length; tk++) {
+ var tkey = tkeys[tk];
+ result[tkey] = this[tkey];
+ }
+
+ // hash is always overridden, no matter what.
+ // even href="" will remove it.
+ result.hash = relative.hash;
+
+ // if the relative url is empty, then there's nothing left to do here.
+ if (relative.href === '') {
+ result.href = result.format();
+ return result;
+ }
+
+ // hrefs like //foo/bar always cut to the protocol.
+ if (relative.slashes && !relative.protocol) {
+ // take everything except the protocol from relative
+ var rkeys = Object.keys(relative);
+ for (var rk = 0; rk < rkeys.length; rk++) {
+ var rkey = rkeys[rk];
+ if (rkey !== 'protocol')
+ result[rkey] = relative[rkey];
}
- return keys;
-};
-},{"jsonify":49}],49:[function(require,module,exports){
-exports.parse = require('./lib/parse');
-exports.stringify = require('./lib/stringify');
+ //urlParse appends trailing / to urls like http://www.example.com
+ if (slashedProtocol[result.protocol] &&
+ result.hostname && !result.pathname) {
+ result.path = result.pathname = '/';
+ }
-},{"./lib/parse":50,"./lib/stringify":51}],50:[function(require,module,exports){
-var at, // The index of the current character
- ch, // The current character
- escapee = {
- '"': '"',
- '\\': '\\',
- '/': '/',
- b: '\b',
- f: '\f',
- n: '\n',
- r: '\r',
- t: '\t'
- },
- text,
+ result.href = result.format();
+ return result;
+ }
- error = function (m) {
- // Call error when something is wrong.
- throw {
- name: 'SyntaxError',
- message: m,
- at: at,
- text: text
- };
- },
-
- next = function (c) {
- // If a c parameter is provided, verify that it matches the current character.
- if (c && c !== ch) {
- error("Expected '" + c + "' instead of '" + ch + "'");
- }
-
- // Get the next character. When there are no more characters,
- // return the empty string.
-
- ch = text.charAt(at);
- at += 1;
- return ch;
- },
-
- number = function () {
- // Parse a number value.
- var number,
- string = '';
-
- if (ch === '-') {
- string = '-';
- next('-');
- }
- while (ch >= '0' && ch <= '9') {
- string += ch;
- next();
- }
- if (ch === '.') {
- string += '.';
- while (next() && ch >= '0' && ch <= '9') {
- string += ch;
- }
- }
- if (ch === 'e' || ch === 'E') {
- string += ch;
- next();
- if (ch === '-' || ch === '+') {
- string += ch;
- next();
- }
- while (ch >= '0' && ch <= '9') {
- string += ch;
- next();
- }
- }
- number = +string;
- if (!isFinite(number)) {
- error("Bad number");
- } else {
- return number;
- }
- },
-
- string = function () {
- // Parse a string value.
- var hex,
- i,
- string = '',
- uffff;
-
- // When parsing for string values, we must look for " and \ characters.
- if (ch === '"') {
- while (next()) {
- if (ch === '"') {
- next();
- return string;
- } else if (ch === '\\') {
- next();
- if (ch === 'u') {
- uffff = 0;
- for (i = 0; i < 4; i += 1) {
- hex = parseInt(next(), 16);
- if (!isFinite(hex)) {
- break;
- }
- uffff = uffff * 16 + hex;
- }
- string += String.fromCharCode(uffff);
- } else if (typeof escapee[ch] === 'string') {
- string += escapee[ch];
- } else {
- break;
- }
- } else {
- string += ch;
- }
- }
- }
- error("Bad string");
- },
-
- white = function () {
-
-// Skip whitespace.
-
- while (ch && ch <= ' ') {
- next();
- }
- },
-
- word = function () {
-
-// true, false, or null.
-
- switch (ch) {
- case 't':
- next('t');
- next('r');
- next('u');
- next('e');
- return true;
- case 'f':
- next('f');
- next('a');
- next('l');
- next('s');
- next('e');
- return false;
- case 'n':
- next('n');
- next('u');
- next('l');
- next('l');
- return null;
- }
- error("Unexpected '" + ch + "'");
- },
-
- value, // Place holder for the value function.
-
- array = function () {
-
-// Parse an array value.
-
- var array = [];
+ if (relative.protocol && relative.protocol !== result.protocol) {
+ // if it's a known url protocol, then changing
+ // the protocol does weird things
+ // first, if it's not file:, then we MUST have a host,
+ // and if there was a path
+ // to begin with, then we MUST have a path.
+ // if it is file:, then the host is dropped,
+ // because that's known to be hostless.
+ // anything else is assumed to be absolute.
+ if (!slashedProtocol[relative.protocol]) {
+ var keys = Object.keys(relative);
+ for (var v = 0; v < keys.length; v++) {
+ var k = keys[v];
+ result[k] = relative[k];
+ }
+ result.href = result.format();
+ return result;
+ }
- if (ch === '[') {
- next('[');
- white();
- if (ch === ']') {
- next(']');
- return array; // empty array
- }
- while (ch) {
- array.push(value());
- white();
- if (ch === ']') {
- next(']');
- return array;
- }
- next(',');
- white();
- }
- }
- error("Bad array");
- },
+ result.protocol = relative.protocol;
+ if (!relative.host && !hostlessProtocol[relative.protocol]) {
+ var relPath = (relative.pathname || '').split('/');
+ while (relPath.length && !(relative.host = relPath.shift()));
+ if (!relative.host) relative.host = '';
+ if (!relative.hostname) relative.hostname = '';
+ if (relPath[0] !== '') relPath.unshift('');
+ if (relPath.length < 2) relPath.unshift('');
+ result.pathname = relPath.join('/');
+ } else {
+ result.pathname = relative.pathname;
+ }
+ result.search = relative.search;
+ result.query = relative.query;
+ result.host = relative.host || '';
+ result.auth = relative.auth;
+ result.hostname = relative.hostname || relative.host;
+ result.port = relative.port;
+ // to support http.request
+ if (result.pathname || result.search) {
+ var p = result.pathname || '';
+ var s = result.search || '';
+ result.path = p + s;
+ }
+ result.slashes = result.slashes || relative.slashes;
+ result.href = result.format();
+ return result;
+ }
- object = function () {
+ var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'),
+ isRelAbs = (
+ relative.host ||
+ relative.pathname && relative.pathname.charAt(0) === '/'
+ ),
+ mustEndAbs = (isRelAbs || isSourceAbs ||
+ (result.host && relative.pathname)),
+ removeAllDots = mustEndAbs,
+ srcPath = result.pathname && result.pathname.split('/') || [],
+ relPath = relative.pathname && relative.pathname.split('/') || [],
+ psychotic = result.protocol && !slashedProtocol[result.protocol];
-// Parse an object value.
+ // if the url is a non-slashed url, then relative
+ // links like ../.. should be able
+ // to crawl up to the hostname, as well. This is strange.
+ // result.protocol has already been set by now.
+ // Later on, put the first path part into the host field.
+ if (psychotic) {
+ result.hostname = '';
+ result.port = null;
+ if (result.host) {
+ if (srcPath[0] === '') srcPath[0] = result.host;
+ else srcPath.unshift(result.host);
+ }
+ result.host = '';
+ if (relative.protocol) {
+ relative.hostname = null;
+ relative.port = null;
+ if (relative.host) {
+ if (relPath[0] === '') relPath[0] = relative.host;
+ else relPath.unshift(relative.host);
+ }
+ relative.host = null;
+ }
+ mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === '');
+ }
- var key,
- object = {};
+ if (isRelAbs) {
+ // it's absolute.
+ result.host = (relative.host || relative.host === '') ?
+ relative.host : result.host;
+ result.hostname = (relative.hostname || relative.hostname === '') ?
+ relative.hostname : result.hostname;
+ result.search = relative.search;
+ result.query = relative.query;
+ srcPath = relPath;
+ // fall through to the dot-handling below.
+ } else if (relPath.length) {
+ // it's relative
+ // throw away the existing file, and take the new path instead.
+ if (!srcPath) srcPath = [];
+ srcPath.pop();
+ srcPath = srcPath.concat(relPath);
+ result.search = relative.search;
+ result.query = relative.query;
+ } else if (!util.isNullOrUndefined(relative.search)) {
+ // just pull out the search.
+ // like href='?foo'.
+ // Put this after the other two cases because it simplifies the booleans
+ if (psychotic) {
+ result.hostname = result.host = srcPath.shift();
+ //occationaly the auth can get stuck only in host
+ //this especially happens in cases like
+ //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
+ var authInHost = result.host && result.host.indexOf('@') > 0 ?
+ result.host.split('@') : false;
+ if (authInHost) {
+ result.auth = authInHost.shift();
+ result.host = result.hostname = authInHost.shift();
+ }
+ }
+ result.search = relative.search;
+ result.query = relative.query;
+ //to support http.request
+ if (!util.isNull(result.pathname) || !util.isNull(result.search)) {
+ result.path = (result.pathname ? result.pathname : '') +
+ (result.search ? result.search : '');
+ }
+ result.href = result.format();
+ return result;
+ }
- if (ch === '{') {
- next('{');
- white();
- if (ch === '}') {
- next('}');
- return object; // empty object
- }
- while (ch) {
- key = string();
- white();
- next(':');
- if (Object.hasOwnProperty.call(object, key)) {
- error('Duplicate key "' + key + '"');
- }
- object[key] = value();
- white();
- if (ch === '}') {
- next('}');
- return object;
- }
- next(',');
- white();
- }
- }
- error("Bad object");
- };
+ if (!srcPath.length) {
+ // no path at all. easy.
+ // we've already handled the other stuff above.
+ result.pathname = null;
+ //to support http.request
+ if (result.search) {
+ result.path = '/' + result.search;
+ } else {
+ result.path = null;
+ }
+ result.href = result.format();
+ return result;
+ }
-value = function () {
+ // if a url ENDs in . or .., then it must get a trailing slash.
+ // however, if it ends in anything else non-slashy,
+ // then it must NOT get a trailing slash.
+ var last = srcPath.slice(-1)[0];
+ var hasTrailingSlash = (
+ (result.host || relative.host || srcPath.length > 1) &&
+ (last === '.' || last === '..') || last === '');
-// Parse a JSON value. It could be an object, an array, a string, a number,
-// or a word.
+ // strip single dots, resolve double dots to parent dir
+ // if the path tries to go above the root, `up` ends up > 0
+ var up = 0;
+ for (var i = srcPath.length; i >= 0; i--) {
+ last = srcPath[i];
+ if (last === '.') {
+ srcPath.splice(i, 1);
+ } else if (last === '..') {
+ srcPath.splice(i, 1);
+ up++;
+ } else if (up) {
+ srcPath.splice(i, 1);
+ up--;
+ }
+ }
- white();
- switch (ch) {
- case '{':
- return object();
- case '[':
- return array();
- case '"':
- return string();
- case '-':
- return number();
- default:
- return ch >= '0' && ch <= '9' ? number() : word();
+ // if the path is allowed to go above the root, restore leading ..s
+ if (!mustEndAbs && !removeAllDots) {
+ for (; up--; up) {
+ srcPath.unshift('..');
}
-};
+ }
-// Return the json_parse function. It will have access to all of the above
-// functions and variables.
+ if (mustEndAbs && srcPath[0] !== '' &&
+ (!srcPath[0] || srcPath[0].charAt(0) !== '/')) {
+ srcPath.unshift('');
+ }
-module.exports = function (source, reviver) {
- var result;
-
- text = source;
- at = 0;
- ch = ' ';
- result = value();
- white();
- if (ch) {
- error("Syntax error");
- }
+ if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) {
+ srcPath.push('');
+ }
- // If there is a reviver function, we recursively walk the new structure,
- // passing each name/value pair to the reviver function for possible
- // transformation, starting with a temporary root object that holds the result
- // in an empty key. If there is not a reviver function, we simply return the
- // result.
+ var isAbsolute = srcPath[0] === '' ||
+ (srcPath[0] && srcPath[0].charAt(0) === '/');
- return typeof reviver === 'function' ? (function walk(holder, key) {
- var k, v, value = holder[key];
- if (value && typeof value === 'object') {
- for (k in value) {
- if (Object.prototype.hasOwnProperty.call(value, k)) {
- v = walk(value, k);
- if (v !== undefined) {
- value[k] = v;
- } else {
- delete value[k];
- }
- }
- }
- }
- return reviver.call(holder, key, value);
- }({'': result}, '')) : result;
-};
+ // put the host back
+ if (psychotic) {
+ result.hostname = result.host = isAbsolute ? '' :
+ srcPath.length ? srcPath.shift() : '';
+ //occationaly the auth can get stuck only in host
+ //this especially happens in cases like
+ //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
+ var authInHost = result.host && result.host.indexOf('@') > 0 ?
+ result.host.split('@') : false;
+ if (authInHost) {
+ result.auth = authInHost.shift();
+ result.host = result.hostname = authInHost.shift();
+ }
+ }
-},{}],51:[function(require,module,exports){
-var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
- escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
- gap,
- indent,
- meta = { // table of character substitutions
- '\b': '\\b',
- '\t': '\\t',
- '\n': '\\n',
- '\f': '\\f',
- '\r': '\\r',
- '"' : '\\"',
- '\\': '\\\\'
- },
- rep;
+ mustEndAbs = mustEndAbs || (result.host && srcPath.length);
-function quote(string) {
- // If the string contains no control characters, no quote characters, and no
- // backslash characters, then we can safely slap some quotes around it.
- // Otherwise we must also replace the offending characters with safe escape
- // sequences.
-
- escapable.lastIndex = 0;
- return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
- var c = meta[a];
- return typeof c === 'string' ? c :
- '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
- }) + '"' : '"' + string + '"';
-}
+ if (mustEndAbs && !isAbsolute) {
+ srcPath.unshift('');
+ }
-function str(key, holder) {
- // Produce a string from holder[key].
- var i, // The loop counter.
- k, // The member key.
- v, // The member value.
- length,
- mind = gap,
- partial,
- value = holder[key];
-
- // If the value has a toJSON method, call it to obtain a replacement value.
- if (value && typeof value === 'object' &&
- typeof value.toJSON === 'function') {
- value = value.toJSON(key);
- }
-
- // If we were called with a replacer function, then call the replacer to
- // obtain a replacement value.
- if (typeof rep === 'function') {
- value = rep.call(holder, key, value);
- }
-
- // What happens next depends on the value's type.
- switch (typeof value) {
- case 'string':
- return quote(value);
-
- case 'number':
- // JSON numbers must be finite. Encode non-finite numbers as null.
- return isFinite(value) ? String(value) : 'null';
-
- case 'boolean':
- case 'null':
- // If the value is a boolean or null, convert it to a string. Note:
- // typeof null does not produce 'null'. The case is included here in
- // the remote chance that this gets fixed someday.
- return String(value);
-
- case 'object':
- if (!value) return 'null';
- gap += indent;
- partial = [];
-
- // Array.isArray
- if (Object.prototype.toString.apply(value) === '[object Array]') {
- length = value.length;
- for (i = 0; i < length; i += 1) {
- partial[i] = str(i, value) || 'null';
- }
-
- // Join all of the elements together, separated with commas, and
- // wrap them in brackets.
- v = partial.length === 0 ? '[]' : gap ?
- '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' :
- '[' + partial.join(',') + ']';
- gap = mind;
- return v;
- }
-
- // If the replacer is an array, use it to select the members to be
- // stringified.
- if (rep && typeof rep === 'object') {
- length = rep.length;
- for (i = 0; i < length; i += 1) {
- k = rep[i];
- if (typeof k === 'string') {
- v = str(k, value);
- if (v) {
- partial.push(quote(k) + (gap ? ': ' : ':') + v);
- }
- }
- }
- }
- else {
- // Otherwise, iterate through all of the keys in the object.
- for (k in value) {
- if (Object.prototype.hasOwnProperty.call(value, k)) {
- v = str(k, value);
- if (v) {
- partial.push(quote(k) + (gap ? ': ' : ':') + v);
- }
- }
- }
- }
-
- // Join all of the member texts together, separated with commas,
- // and wrap them in braces.
+ if (!srcPath.length) {
+ result.pathname = null;
+ result.path = null;
+ } else {
+ result.pathname = srcPath.join('/');
+ }
- v = partial.length === 0 ? '{}' : gap ?
- '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' :
- '{' + partial.join(',') + '}';
- gap = mind;
- return v;
- }
-}
+ //to support request.http
+ if (!util.isNull(result.pathname) || !util.isNull(result.search)) {
+ result.path = (result.pathname ? result.pathname : '') +
+ (result.search ? result.search : '');
+ }
+ result.auth = relative.auth || result.auth;
+ result.slashes = result.slashes || relative.slashes;
+ result.href = result.format();
+ return result;
+};
-module.exports = function (value, replacer, space) {
- var i;
- gap = '';
- indent = '';
-
- // If the space parameter is a number, make an indent string containing that
- // many spaces.
- if (typeof space === 'number') {
- for (i = 0; i < space; i += 1) {
- indent += ' ';
- }
- }
- // If the space parameter is a string, it will be used as the indent string.
- else if (typeof space === 'string') {
- indent = space;
+Url.prototype.parseHost = function() {
+ var host = this.host;
+ var port = portPattern.exec(host);
+ if (port) {
+ port = port[0];
+ if (port !== ':') {
+ this.port = port.substr(1);
}
+ host = host.substr(0, host.length - port.length);
+ }
+ if (host) this.hostname = host;
+};
- // If there is a replacer, it must be a function or an array.
- // Otherwise, throw an error.
- rep = replacer;
- if (replacer && typeof replacer !== 'function'
- && (typeof replacer !== 'object' || typeof replacer.length !== 'number')) {
- throw new Error('JSON.stringify');
- }
-
- // Make a fake root object containing our value under the key of ''.
- // Return the result of stringifying the value.
- return str('', {'': value});
+},{"./util":51,"punycode":46,"querystring":49}],51:[function(require,module,exports){
+'use strict';
+
+module.exports = {
+ isString: function(arg) {
+ return typeof(arg) === 'string';
+ },
+ isObject: function(arg) {
+ return typeof(arg) === 'object' && arg !== null;
+ },
+ isNull: function(arg) {
+ return arg === null;
+ },
+ isNullOrUndefined: function(arg) {
+ return arg == null;
+ }
};
},{}],"ajv":[function(require,module,exports){
@@ -8037,5 +8019,5 @@ function Ajv(opts) {
}
}
-},{"./async":1,"./cache":2,"./compile":6,"./compile/formats":5,"./compile/resolve":7,"./compile/rules":8,"./compile/schema_obj":9,"./compile/util":11,"./compile/validation_error":12,"./keyword":37,"./refs/json-schema-draft-04.json":38,"./v5":40,"co":47,"json-stable-stringify":48}]},{},[])("ajv")
+},{"./async":1,"./cache":2,"./compile":6,"./compile/formats":5,"./compile/resolve":7,"./compile/rules":8,"./compile/schema_obj":9,"./compile/util":11,"./compile/validation_error":12,"./keyword":37,"./refs/json-schema-draft-04.json":38,"./v5":40,"co":41,"json-stable-stringify":42}]},{},[])("ajv")
});
\ No newline at end of file
diff --git a/tools/eslint/node_modules/ajv/dist/ajv.min.js b/tools/eslint/node_modules/ajv/dist/ajv.min.js
index c48e7e06b51190..cee0fee6c4b832 100644
--- a/tools/eslint/node_modules/ajv/dist/ajv.min.js
+++ b/tools/eslint/node_modules/ajv/dist/ajv.min.js
@@ -1,6 +1,6 @@
-/* ajv 4.11.5: Another JSON Schema Validator */
-!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var r;r="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,r.Ajv=e()}}(function(){var e;return function e(r,t,a){function s(i,n){if(!t[i]){if(!r[i]){var l="function"==typeof require&&require;if(!n&&l)return l(i,!0);if(o)return o(i,!0);var c=new Error("Cannot find module '"+i+"'");throw c.code="MODULE_NOT_FOUND",c}var h=t[i]={exports:{}};r[i][0].call(h.exports,function(e){var t=r[i][1][e];return s(t?t:e)},h,h.exports,e,r,t,a)}return t[i].exports}for(var o="function"==typeof require&&require,i=0;i=1&&t<=12&&a>=1&&a<=m[t]}function o(e,r){var t=e.match(v);if(!t)return!1;var a=t[1],s=t[2],o=t[3],i=t[5];return a<=23&&s<=59&&o<=59&&(!r||i)}function i(e){var r=e.split(w);return 2==r.length&&s(r[0])&&o(r[1],!0)}function n(e){return e.length<=255&&y.test(e)}function l(e){return j.test(e)&&g.test(e)}function c(e){try{return new RegExp(e),!0}catch(e){return!1}}function h(e,r){if(e&&r)return e>r?1:er?1:e=0?{index:a,compiling:!0}:(a=this._compilations.length,this._compilations[a]={schema:e,root:r,baseId:t},{index:a,compiling:!1})}function i(e,r,t){var a=n.call(this,e,r,t);a>=0&&this._compilations.splice(a,1)}function n(e,r,t){for(var a=0;a=55296&&r<=56319&&s=r)throw new Error("Cannot access property/index "+a+" levels up, current level is "+r);return t[r-a]}if(a>r)throw new Error("Cannot access data "+a+" levels up, current level is "+r);if(o="data"+(r-a||""),!s)return o}for(var n=o,c=s.split("/"),h=0;h",S="result"+s,$=e.opts.v5&&i&&i.$data;if($?(a+=" var schema"+s+" = "+e.util.getData(i.$data,o,e.dataPathArr)+"; ",g="schema"+s):g=i,w){var x=e.util.getData(b.$data,o,e.dataPathArr),_="exclusive"+s,O="op"+s,R="' + "+O+" + '";a+=" var schemaExcl"+s+" = "+x+"; ",x="schemaExcl"+s,a+=" if (typeof "+x+" != 'boolean' && "+x+" !== undefined) { "+u+" = false; ";var t=E,I=I||[];I.push(a),a="",e.createErrors!==!1?(a+=" { keyword: '"+(t||"_formatExclusiveLimit")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(l)+" , params: {} ",e.opts.messages!==!1&&(a+=" , message: '"+E+" should be boolean' "),e.opts.verbose&&(a+=" , schema: validate.schema"+n+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),a+=" } "):a+=" {} ";var A=a;a=I.pop(),a+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+A+"]); ":" validate.errors = ["+A+"]; return false; ":" var err = "+A+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",a+=" } ",c&&(p+="}",a+=" else { "),$&&(a+=" if ("+g+" === undefined) "+u+" = true; else if (typeof "+g+" != 'string') "+u+" = false; else { ",p+="}"),d&&(a+=" if (!"+y+") "+u+" = true; else { ",p+="}"),a+=" var "+S+" = "+y+"("+h+", ",a+=$?""+g:""+e.util.toQuotedString(i),a+=" ); if ("+S+" === undefined) "+u+" = false; var "+_+" = "+x+" === true; if ("+u+" === undefined) { "+u+" = "+_+" ? "+S+" "+j+" 0 : "+S+" "+j+"= 0; } if (!"+u+") var op"+s+" = "+_+" ? '"+j+"' : '"+j+"=';"}else{var _=b===!0,R=j;_||(R+="=");var O="'"+R+"'";$&&(a+=" if ("+g+" === undefined) "+u+" = true; else if (typeof "+g+" != 'string') "+u+" = false; else { ",p+="}"),d&&(a+=" if (!"+y+") "+u+" = true; else { ",p+="}"),a+=" var "+S+" = "+y+"("+h+", ",a+=$?""+g:""+e.util.toQuotedString(i),a+=" ); if ("+S+" === undefined) "+u+" = false; if ("+u+" === undefined) "+u+" = "+S+" "+j,_||(a+="="),a+=" 0;"}a+=""+p+"if (!"+u+") { ";var t=r,I=I||[];I.push(a),a="",e.createErrors!==!1?(a+=" { keyword: '"+(t||"_formatLimit")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(l)+" , params: { comparison: "+O+", limit: ",a+=$?""+g:""+e.util.toQuotedString(i),a+=" , exclusive: "+_+" } ",e.opts.messages!==!1&&(a+=" , message: 'should be "+R+' "',a+=$?"' + "+g+" + '":""+e.util.escapeQuotes(i),a+="\"' "),e.opts.verbose&&(a+=" , schema: ",a+=$?"validate.schema"+n:""+e.util.toQuotedString(i),a+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),a+=" } "):a+=" {} ";var A=a;return a=I.pop(),a+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+A+"]); ":" validate.errors = ["+A+"]; return false; ":" var err = "+A+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",a+="}"}},{}],14:[function(e,r,t){"use strict";r.exports=function(e,r){var t,a,s=" ",o=e.level,i=e.dataLevel,n=e.schema[r],l=e.schemaPath+e.util.getProperty(r),c=e.errSchemaPath+"/"+r,h=!e.opts.allErrors,u="data"+(i||""),f=e.opts.v5&&n&&n.$data;f?(s+=" var schema"+o+" = "+e.util.getData(n.$data,i,e.dataPathArr)+"; ",a="schema"+o):a=n;var d="maximum"==r,p=d?"exclusiveMaximum":"exclusiveMinimum",m=e.schema[p],v=e.opts.v5&&m&&m.$data,y=d?"<":">",g=d?">":"<";if(v){var P=e.util.getData(m.$data,i,e.dataPathArr),E="exclusive"+o,b="op"+o,w="' + "+b+" + '";s+=" var schemaExcl"+o+" = "+P+"; ",P="schemaExcl"+o,s+=" var exclusive"+o+"; if (typeof "+P+" != 'boolean' && typeof "+P+" != 'undefined') { ";var t=p,j=j||[];j.push(s),s="",e.createErrors!==!1?(s+=" { keyword: '"+(t||"_exclusiveLimit")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(c)+" , params: {} ",e.opts.messages!==!1&&(s+=" , message: '"+p+" should be boolean' "),e.opts.verbose&&(s+=" , schema: validate.schema"+l+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+u+" "),s+=" } "):s+=" {} ";var S=s;s=j.pop(),s+=!e.compositeRule&&h?e.async?" throw new ValidationError(["+S+"]); ":" validate.errors = ["+S+"]; return false; ":" var err = "+S+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",s+=" } else if( ",f&&(s+=" ("+a+" !== undefined && typeof "+a+" != 'number') || "),s+=" ((exclusive"+o+" = "+P+" === true) ? "+u+" "+g+"= "+a+" : "+u+" "+g+" "+a+") || "+u+" !== "+u+") { var op"+o+" = exclusive"+o+" ? '"+y+"' : '"+y+"=';"}else{var E=m===!0,w=y;E||(w+="=");var b="'"+w+"'";s+=" if ( ",f&&(s+=" ("+a+" !== undefined && typeof "+a+" != 'number') || "),s+=" "+u+" "+g,E&&(s+="="),s+=" "+a+" || "+u+" !== "+u+") {"}var t=r,j=j||[];j.push(s),s="",e.createErrors!==!1?(s+=" { keyword: '"+(t||"_limit")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(c)+" , params: { comparison: "+b+", limit: "+a+", exclusive: "+E+" } ",e.opts.messages!==!1&&(s+=" , message: 'should be "+w+" ",s+=f?"' + "+a:""+n+"'"),e.opts.verbose&&(s+=" , schema: ",s+=f?"validate.schema"+l:""+n,s+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+u+" "),s+=" } "):s+=" {} ";var S=s;return s=j.pop(),s+=!e.compositeRule&&h?e.async?" throw new ValidationError(["+S+"]); ":" validate.errors = ["+S+"]; return false; ":" var err = "+S+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",s+=" } ",h&&(s+=" else { "),s}},{}],15:[function(e,r,t){"use strict";r.exports=function(e,r){var t,a,s=" ",o=e.level,i=e.dataLevel,n=e.schema[r],l=e.schemaPath+e.util.getProperty(r),c=e.errSchemaPath+"/"+r,h=!e.opts.allErrors,u="data"+(i||""),f=e.opts.v5&&n&&n.$data;f?(s+=" var schema"+o+" = "+e.util.getData(n.$data,i,e.dataPathArr)+"; ",a="schema"+o):a=n;var d="maxItems"==r?">":"<";s+="if ( ",f&&(s+=" ("+a+" !== undefined && typeof "+a+" != 'number') || "),s+=" "+u+".length "+d+" "+a+") { ";var t=r,p=p||[];p.push(s),s="",e.createErrors!==!1?(s+=" { keyword: '"+(t||"_limitItems")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(c)+" , params: { limit: "+a+" } ",e.opts.messages!==!1&&(s+=" , message: 'should NOT have ",s+="maxItems"==r?"more":"less",s+=" than ",s+=f?"' + "+a+" + '":""+n,s+=" items' "),e.opts.verbose&&(s+=" , schema: ",s+=f?"validate.schema"+l:""+n,s+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+u+" "),s+=" } "):s+=" {} ";var m=s;return s=p.pop(),s+=!e.compositeRule&&h?e.async?" throw new ValidationError(["+m+"]); ":" validate.errors = ["+m+"]; return false; ":" var err = "+m+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",s+="} ",h&&(s+=" else { "),s}},{}],16:[function(e,r,t){"use strict";r.exports=function(e,r){var t,a,s=" ",o=e.level,i=e.dataLevel,n=e.schema[r],l=e.schemaPath+e.util.getProperty(r),c=e.errSchemaPath+"/"+r,h=!e.opts.allErrors,u="data"+(i||""),f=e.opts.v5&&n&&n.$data;f?(s+=" var schema"+o+" = "+e.util.getData(n.$data,i,e.dataPathArr)+"; ",a="schema"+o):a=n;var d="maxLength"==r?">":"<";s+="if ( ",f&&(s+=" ("+a+" !== undefined && typeof "+a+" != 'number') || "),s+=e.opts.unicode===!1?" "+u+".length ":" ucs2length("+u+") ",s+=" "+d+" "+a+") { ";var t=r,p=p||[];p.push(s),s="",e.createErrors!==!1?(s+=" { keyword: '"+(t||"_limitLength")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(c)+" , params: { limit: "+a+" } ",e.opts.messages!==!1&&(s+=" , message: 'should NOT be ",s+="maxLength"==r?"longer":"shorter",s+=" than ",s+=f?"' + "+a+" + '":""+n,s+=" characters' "),e.opts.verbose&&(s+=" , schema: ",s+=f?"validate.schema"+l:""+n,
-s+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+u+" "),s+=" } "):s+=" {} ";var m=s;return s=p.pop(),s+=!e.compositeRule&&h?e.async?" throw new ValidationError(["+m+"]); ":" validate.errors = ["+m+"]; return false; ":" var err = "+m+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",s+="} ",h&&(s+=" else { "),s}},{}],17:[function(e,r,t){"use strict";r.exports=function(e,r){var t,a,s=" ",o=e.level,i=e.dataLevel,n=e.schema[r],l=e.schemaPath+e.util.getProperty(r),c=e.errSchemaPath+"/"+r,h=!e.opts.allErrors,u="data"+(i||""),f=e.opts.v5&&n&&n.$data;f?(s+=" var schema"+o+" = "+e.util.getData(n.$data,i,e.dataPathArr)+"; ",a="schema"+o):a=n;var d="maxProperties"==r?">":"<";s+="if ( ",f&&(s+=" ("+a+" !== undefined && typeof "+a+" != 'number') || "),s+=" Object.keys("+u+").length "+d+" "+a+") { ";var t=r,p=p||[];p.push(s),s="",e.createErrors!==!1?(s+=" { keyword: '"+(t||"_limitProperties")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(c)+" , params: { limit: "+a+" } ",e.opts.messages!==!1&&(s+=" , message: 'should NOT have ",s+="maxProperties"==r?"more":"less",s+=" than ",s+=f?"' + "+a+" + '":""+n,s+=" properties' "),e.opts.verbose&&(s+=" , schema: ",s+=f?"validate.schema"+l:""+n,s+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+u+" "),s+=" } "):s+=" {} ";var m=s;return s=p.pop(),s+=!e.compositeRule&&h?e.async?" throw new ValidationError(["+m+"]); ":" validate.errors = ["+m+"]; return false; ":" var err = "+m+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",s+="} ",h&&(s+=" else { "),s}},{}],18:[function(e,r,t){"use strict";r.exports=function(e,r){var t=" ",a=e.schema[r],s=e.schemaPath+e.util.getProperty(r),o=e.errSchemaPath+"/"+r,i=!e.opts.allErrors,n=e.util.copy(e),l="";n.level++;var c="valid"+n.level,h=n.baseId,u=!0,f=a;if(f)for(var d,p=-1,m=f.length-1;p "+x+") { ";var O=h+"["+x+"]";d.schema=$,d.schemaPath=n+"["+x+"]",d.errSchemaPath=l+"/"+x,d.errorPath=e.util.getPathExpr(e.errorPath,x,e.opts.jsonPointers,!0),d.dataPathArr[y]=x;var R=e.validate(d);d.baseId=P,a+=e.util.varOccurences(R,g)<2?" "+e.util.varReplace(R,g,O)+" ":" var "+g+" = "+O+"; "+R+" ",a+=" } ",c&&(a+=" if ("+m+") { ",p+="}")}if("object"==typeof E&&e.util.schemaHasRules(E,e.RULES.all)){d.schema=E,d.schemaPath=e.schemaPath+".additionalItems",d.errSchemaPath=e.errSchemaPath+"/additionalItems",a+=" "+m+" = true; if ("+h+".length > "+i.length+") { for (var "+v+" = "+i.length+"; "+v+" < "+h+".length; "+v+"++) { ",d.errorPath=e.util.getPathExpr(e.errorPath,v,e.opts.jsonPointers,!0);var O=h+"["+v+"]";d.dataPathArr[y]=v;var R=e.validate(d);d.baseId=P,a+=e.util.varOccurences(R,g)<2?" "+e.util.varReplace(R,g,O)+" ":" var "+g+" = "+O+"; "+R+" ",c&&(a+=" if (!"+m+") break; "),a+=" } } ",c&&(a+=" if ("+m+") { ",p+="}")}}else if(e.util.schemaHasRules(i,e.RULES.all)){d.schema=i,d.schemaPath=n,d.errSchemaPath=l,a+=" for (var "+v+" = 0; "+v+" < "+h+".length; "+v+"++) { ",d.errorPath=e.util.getPathExpr(e.errorPath,v,e.opts.jsonPointers,!0);var O=h+"["+v+"]";d.dataPathArr[y]=v;var R=e.validate(d);d.baseId=P,a+=e.util.varOccurences(R,g)<2?" "+e.util.varReplace(R,g,O)+" ":" var "+g+" = "+O+"; "+R+" ",c&&(a+=" if (!"+m+") break; "),a+=" } ",c&&(a+=" if ("+m+") { ",p+="}")}return c&&(a+=" "+p+" if ("+f+" == errors) {"),a=e.util.cleanUpCode(a)}},{}],26:[function(e,r,t){"use strict";r.exports=function(e,r){var t,a,s=" ",o=e.level,i=e.dataLevel,n=e.schema[r],l=e.schemaPath+e.util.getProperty(r),c=e.errSchemaPath+"/"+r,h=!e.opts.allErrors,u="data"+(i||""),f=e.opts.v5&&n&&n.$data;f?(s+=" var schema"+o+" = "+e.util.getData(n.$data,i,e.dataPathArr)+"; ",a="schema"+o):a=n,s+="var division"+o+";if (",f&&(s+=" "+a+" !== undefined && ( typeof "+a+" != 'number' || "),s+=" (division"+o+" = "+u+" / "+a+", ",s+=e.opts.multipleOfPrecision?" Math.abs(Math.round(division"+o+") - division"+o+") > 1e-"+e.opts.multipleOfPrecision+" ":" division"+o+" !== parseInt(division"+o+") ",s+=" ) ",f&&(s+=" ) "),s+=" ) { ";var d=d||[];d.push(s),s="",e.createErrors!==!1?(s+=" { keyword: '"+(t||"multipleOf")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(c)+" , params: { multipleOf: "+a+" } ",e.opts.messages!==!1&&(s+=" , message: 'should be multiple of ",s+=f?"' + "+a:""+n+"'"),e.opts.verbose&&(s+=" , schema: ",s+=f?"validate.schema"+l:""+n,s+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+u+" "),s+=" } "):s+=" {} ";var p=s;return s=d.pop(),s+=!e.compositeRule&&h?e.async?" throw new ValidationError(["+p+"]); ":" validate.errors = ["+p+"]; return false; ":" var err = "+p+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",s+="} ",h&&(s+=" else { "),s}},{}],27:[function(e,r,t){"use strict";r.exports=function(e,r){var t,a=" ",s=e.level,o=e.dataLevel,i=e.schema[r],n=e.schemaPath+e.util.getProperty(r),l=e.errSchemaPath+"/"+r,c=!e.opts.allErrors,h="data"+(o||""),u="errs__"+s,f=e.util.copy(e);f.level++;var d="valid"+f.level;if(e.util.schemaHasRules(i,e.RULES.all)){f.schema=i,f.schemaPath=n,f.errSchemaPath=l,a+=" var "+u+" = errors; ";var p=e.compositeRule;e.compositeRule=f.compositeRule=!0,f.createErrors=!1;var m;f.opts.allErrors&&(m=f.opts.allErrors,f.opts.allErrors=!1),a+=" "+e.validate(f)+" ",f.createErrors=!0,m&&(f.opts.allErrors=m),e.compositeRule=f.compositeRule=p,a+=" if ("+d+") { ";var v=v||[];v.push(a),a="",e.createErrors!==!1?(a+=" { keyword: '"+(t||"not")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(l)+" , params: {} ",e.opts.messages!==!1&&(a+=" , message: 'should NOT be valid' "),e.opts.verbose&&(a+=" , schema: validate.schema"+n+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),a+=" } "):a+=" {} ";var y=a;a=v.pop(),a+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+y+"]); ":" validate.errors = ["+y+"]; return false; ":" var err = "+y+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",a+=" } else { errors = "+u+"; if (vErrors !== null) { if ("+u+") vErrors.length = "+u+"; else vErrors = null; } ",e.opts.allErrors&&(a+=" } ")}else a+=" var err = ",e.createErrors!==!1?(a+=" { keyword: '"+(t||"not")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(l)+" , params: {} ",e.opts.messages!==!1&&(a+=" , message: 'should NOT be valid' "),e.opts.verbose&&(a+=" , schema: validate.schema"+n+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),a+=" } "):a+=" {} ",a+="; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",c&&(a+=" if (false) { ");return a}},{}],28:[function(e,r,t){"use strict";r.exports=function(e,r){var t,a=" ",s=e.level,o=e.dataLevel,i=e.schema[r],n=e.schemaPath+e.util.getProperty(r),l=e.errSchemaPath+"/"+r,c=!e.opts.allErrors,h="data"+(o||""),u="valid"+s,f="errs__"+s,d=e.util.copy(e),p="";d.level++;var m="valid"+d.level;a+="var "+f+" = errors;var prevValid"+s+" = false;var "+u+" = false;";var v=d.baseId,y=e.compositeRule;e.compositeRule=d.compositeRule=!0;var g=i;if(g)for(var P,E=-1,b=g.length-1;E5)a+=" || validate.schema"+n+"["+v+"] ";else{var D=P;if(D)for(var L,Q=-1,C=D.length-1;Q= "+me+"; ",l=e.errSchemaPath+"/patternGroups/minimum",a+=" if (!"+u+") { ";var K=K||[];K.push(a),a="",e.createErrors!==!1?(a+=" { keyword: '"+(t||"patternGroups")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(l)+" , params: { reason: '"+ge+"', limit: "+ye+", pattern: '"+e.util.escapeQuotes(N)+"' } ",e.opts.messages!==!1&&(a+=" , message: 'should NOT have "+Pe+" than "+ye+' properties matching pattern "'+e.util.escapeQuotes(N)+"\"' "),e.opts.verbose&&(a+=" , schema: validate.schema"+n+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),a+=" } "):a+=" {} ";var B=a;a=K.pop(),a+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+B+"]); ":" validate.errors = ["+B+"]; return false; ":" var err = "+B+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",a+=" } ",void 0!==ve&&(a+=" else ")}if(void 0!==ve){var ye=ve,ge="maximum",Pe="more";a+=" "+u+" = pgPropCount"+s+" <= "+ve+"; ",l=e.errSchemaPath+"/patternGroups/maximum",a+=" if (!"+u+") { ";var K=K||[];K.push(a),a="",e.createErrors!==!1?(a+=" { keyword: '"+(t||"patternGroups")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(l)+" , params: { reason: '"+ge+"', limit: "+ye+", pattern: '"+e.util.escapeQuotes(N)+"' } ",e.opts.messages!==!1&&(a+=" , message: 'should NOT have "+Pe+" than "+ye+' properties matching pattern "'+e.util.escapeQuotes(N)+"\"' "),e.opts.verbose&&(a+=" , schema: validate.schema"+n+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),a+=" } "):a+=" {} ";var B=a;a=K.pop(),a+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+B+"]); ":" validate.errors = ["+B+"]; return false; ":" var err = "+B+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",a+=" } "}l=G,c&&(a+=" if ("+u+") { ",p+="}")}}}}return c&&(a+=" "+p+" if ("+f+" == errors) {"),a=e.util.cleanUpCode(a)}},{}],32:[function(e,r,t){"use strict";r.exports=function(e,r){var t,a,s,o=" ",i=e.level,n=e.dataLevel,l=e.schema[r],c=e.errSchemaPath+"/"+r,h=!e.opts.allErrors,u="data"+(n||""),f="valid"+i;if("#"==l||"#/"==l)e.isRoot?(a=e.async,s="validate"):(a=e.root.schema.$async===!0,s="root.refVal[0]");else{var d=e.resolveRef(e.baseId,l,e.isRoot);if(void 0===d){var p="can't resolve reference "+l+" from id "+e.baseId;if("fail"==e.opts.missingRefs){console.log(p);var m=m||[];m.push(o),o="",e.createErrors!==!1?(o+=" { keyword: '"+(t||"$ref")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(c)+" , params: { ref: '"+e.util.escapeQuotes(l)+"' } ",e.opts.messages!==!1&&(o+=" , message: 'can\\'t resolve reference "+e.util.escapeQuotes(l)+"' "),e.opts.verbose&&(o+=" , schema: "+e.util.toQuotedString(l)+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+u+" "),o+=" } "):o+=" {} ";var v=o;o=m.pop(),o+=!e.compositeRule&&h?e.async?" throw new ValidationError(["+v+"]); ":" validate.errors = ["+v+"]; return false; ":" var err = "+v+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",h&&(o+=" if (false) { ")}else{if("ignore"!=e.opts.missingRefs){var y=new Error(p);throw y.missingRef=e.resolve.url(e.baseId,l),y.missingSchema=e.resolve.normalizeId(e.resolve.fullPath(y.missingRef)),y}console.log(p),h&&(o+=" if (true) { ")}}else if(d.inline){var g=e.util.copy(e);g.level++;var P="valid"+g.level;g.schema=d.schema,g.schemaPath="",g.errSchemaPath=l;var E=e.validate(g).replace(/validate\.schema/g,d.code);o+=" "+E+" ",h&&(o+=" if ("+P+") { ")}else a=d.$async===!0,s=d.code}if(s){var m=m||[];m.push(o),o="",o+=e.opts.passContext?" "+s+".call(this, ":" "+s+"( ",o+=" "+u+", (dataPath || '')",'""'!=e.errorPath&&(o+=" + "+e.errorPath);o+=" , "+(n?"data"+(n-1||""):"parentData")+" , "+(n?e.dataPathArr[n]:"parentDataProperty")+", rootData) ";var b=o;if(o=m.pop(),a){if(!e.async)throw new Error("async schema referenced by sync schema");o+=" try { ",h&&(o+="var "+f+" ="),o+=" "+e.yieldAwait+" "+b+"; } catch (e) { if (!(e instanceof ValidationError)) throw e; if (vErrors === null) vErrors = e.errors; else vErrors = vErrors.concat(e.errors); errors = vErrors.length; } ",h&&(o+=" if ("+f+") { ")}else o+=" if (!"+b+") { if (vErrors === null) vErrors = "+s+".errors; else vErrors = vErrors.concat("+s+".errors); errors = vErrors.length; } ",h&&(o+=" else { ")}return o}},{}],33:[function(e,r,t){"use strict";r.exports=function(e,r){var t,a=" ",s=e.level,o=e.dataLevel,i=e.schema[r],n=e.schemaPath+e.util.getProperty(r),l=e.errSchemaPath+"/"+r,c=!e.opts.allErrors,h="data"+(o||""),u="valid"+s,f=e.opts.v5&&i&&i.$data;f&&(a+=" var schema"+s+" = "+e.util.getData(i.$data,o,e.dataPathArr)+"; ");var d="schema"+s;if(!f)if(i.length=e.opts.loopRequired;if(c)if(a+=" var missing"+s+"; ",b){f||(a+=" var "+d+" = validate.schema"+n+"; ");var w="i"+s,j="schema"+s+"["+w+"]",S="' + "+j+" + '";e.opts._errorDataPathProperty&&(e.errorPath=e.util.getPathExpr(E,j,e.opts.jsonPointers)),a+=" var "+u+" = true; ",f&&(a+=" if (schema"+s+" === undefined) "+u+" = true; else if (!Array.isArray(schema"+s+")) "+u+" = false; else {"),a+=" for (var "+w+" = 0; "+w+" < "+d+".length; "+w+"++) { "+u+" = "+h+"["+d+"["+w+"]] !== undefined; if (!"+u+") break; } ",f&&(a+=" } "),a+=" if (!"+u+") { ";var $=$||[];$.push(a),a="",e.createErrors!==!1?(a+=" { keyword: '"+(t||"required")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(l)+" , params: { missingProperty: '"+S+"' } ",e.opts.messages!==!1&&(a+=" , message: '",a+=e.opts._errorDataPathProperty?"is a required property":"should have required property \\'"+S+"\\'",a+="' "),e.opts.verbose&&(a+=" , schema: validate.schema"+n+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),a+=" } "):a+=" {} ";var x=a;a=$.pop(),a+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+x+"]); ":" validate.errors = ["+x+"]; return false; ":" var err = "+x+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",a+=" } else { "}else{a+=" if ( ";var _=p;if(_)for(var O,w=-1,R=_.length-1;w 1) { var i = "+u+".length, j; outer: for (;i--;) { for (j = i; j--;) { if (equal("+u+"[i], "+u+"[j])) { "+f+" = false; break outer; } } } } ",d&&(s+=" } "),s+=" if (!"+f+") { ";var p=p||[];p.push(s),s="",e.createErrors!==!1?(s+=" { keyword: '"+(t||"uniqueItems")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(c)+" , params: { i: i, j: j } ",e.opts.messages!==!1&&(s+=" , message: 'should NOT have duplicate items (items ## ' + j + ' and ' + i + ' are identical)' "),e.opts.verbose&&(s+=" , schema: ",s+=d?"validate.schema"+l:""+n,s+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+u+" "),s+=" } "):s+=" {} ";var m=s;s=p.pop(),s+=!e.compositeRule&&h?e.async?" throw new ValidationError(["+m+"]); ":" validate.errors = ["+m+"]; return false; ":" var err = "+m+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",s+=" } ",h&&(s+=" else { ")}else h&&(s+=" if (true) { ");return s}},{}],36:[function(e,r,t){"use strict";r.exports=function(e,r){function t(e){for(var r=0;r1&&(a=t[0]+"@",e=t[1]),e=e.replace(q,"."),a+i(e.split("."),r).join(".")}function l(e){for(var r,t,a=[],s=0,o=e.length;s=55296&&r<=56319&&s65535&&(e-=65536,r+=C(e>>>10&1023|55296),e=56320|1023&e),r+=C(e)}).join("")}function h(e){return e-48<10?e-22:e-65<26?e-65:e-97<26?e-97:j}function u(e,r){return e+22+75*(e<26)-((0!=r)<<5)}function f(e,r,t){var a=0;for(e=t?Q(e/_):e>>1,e+=Q(e/r);e>L*$>>1;a+=j)e=Q(e/L);return Q(a+(L+1)*e/(e+x))}function d(e){var r,t,a,s,i,n,l,u,d,p,m=[],v=e.length,y=0,g=R,P=O;for(t=e.lastIndexOf(I),t<0&&(t=0),a=0;a=128&&o("not-basic"),m.push(e.charCodeAt(a));for(s=t>0?t+1:0;s=v&&o("invalid-input"),u=h(e.charCodeAt(s++)),(u>=j||u>Q((w-y)/n))&&o("overflow"),y+=u*n,d=l<=P?S:l>=P+$?$:l-P,!(uQ(w/p)&&o("overflow"),n*=p;r=m.length+1,P=f(y-i,r,0==i),Q(y/r)>w-g&&o("overflow"),g+=Q(y/r),y%=r,m.splice(y++,0,g)}return c(m)}function p(e){var r,t,a,s,i,n,c,h,d,p,m,v,y,g,P,E=[];for(e=l(e),v=e.length,r=R,t=0,i=O,n=0;n=r&&mQ((w-t)/y)&&o("overflow"),t+=(c-r)*y,r=c,n=0;nw&&o("overflow"),m==r){for(h=t,d=j;p=d<=i?S:d>=i+$?$:d-i,!(h= 0x80 (not a basic code point)","invalid-input":"Invalid input"},L=j-S,Q=Math.floor,C=String.fromCharCode;if(E={version:"1.4.1",ucs2:{decode:l,encode:c},decode:d,encode:p,toASCII:v,toUnicode:m},"function"==typeof e&&"object"==typeof e.amd&&e.amd)e("punycode",function(){return E});else if(y&&g)if(t.exports==y)g.exports=E;else for(b in E)E.hasOwnProperty(b)&&(y[b]=E[b]);else s.punycode=E}(this)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],42:[function(e,r,t){"use strict";function a(e,r){return Object.prototype.hasOwnProperty.call(e,r)}r.exports=function(e,r,t,o){r=r||"&",t=t||"=";var i={};if("string"!=typeof e||0===e.length)return i;var n=/\+/g;e=e.split(r);var l=1e3;o&&"number"==typeof o.maxKeys&&(l=o.maxKeys);var c=e.length;l>0&&c>l&&(c=l);for(var h=0;h=0?(u=m.substr(0,v),f=m.substr(v+1)):(u=m,f=""),d=decodeURIComponent(u),p=decodeURIComponent(f),a(i,d)?s(i[d])?i[d].push(p):i[d]=[i[d],p]:i[d]=p}return i};var s=Array.isArray||function(e){return"[object Array]"===Object.prototype.toString.call(e)}},{}],43:[function(e,r,t){"use strict";function a(e,r){if(e.map)return e.map(r);for(var t=[],a=0;a",'"',"`"," ","\r","\n","\t"],p=["{","}","|","\\","^","`"].concat(d),m=["'"].concat(p),v=["%","/","?",";","#"].concat(m),y=["/","?","#"],g=/^[+a-z0-9A-Z_-]{0,63}$/,P=/^([+a-z0-9A-Z_-]{0,63})(.*)$/,E={javascript:!0,"javascript:":!0},b={javascript:!0,"javascript:":!0},w={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,"http:":!0,"https:":!0,"ftp:":!0,"gopher:":!0,"file:":!0},j=e("querystring");a.prototype.parse=function(e,r,t){if(!c.isString(e))throw new TypeError("Parameter 'url' must be a string, not "+typeof e);var a=e.indexOf("?"),s=a!==-1&&a127?"x":k[D];if(!q.match(g)){var Q=I.slice(0,$),C=I.slice($+1),V=k.match(P);V&&(Q.push(V[1]),C.unshift(V[2])),C.length&&(i="/"+C.join(".")+i),this.hostname=Q.join(".");break}}}this.hostname=this.hostname.length>255?"":this.hostname.toLowerCase(),R||(this.hostname=l.toASCII(this.hostname));var z=this.port?":"+this.port:"";this.host=(this.hostname||"")+z,this.href+=this.host,R&&(this.hostname=this.hostname.substr(1,this.hostname.length-2),"/"!==i[0]&&(i="/"+i))}if(!E[d])for(var $=0,A=m.length;$0)&&t.host.split("@");j&&(t.auth=j.shift(),t.host=t.hostname=j.shift())}return t.search=e.search,t.query=e.query,c.isNull(t.pathname)&&c.isNull(t.search)||(t.path=(t.pathname?t.pathname:"")+(t.search?t.search:"")),t.href=t.format(),t}if(!P.length)return t.pathname=null,t.path=t.search?"/"+t.search:null,t.href=t.format(),t;for(var S=P.slice(-1)[0],$=(t.host||e.host||P.length>1)&&("."===S||".."===S)||""===S,x=0,_=P.length;_>=0;_--)S=P[_],"."===S?P.splice(_,1):".."===S?(P.splice(_,1),x++):x&&(P.splice(_,1),x--);if(!y&&!g)for(;x--;x)P.unshift("..");!y||""===P[0]||P[0]&&"/"===P[0].charAt(0)||P.unshift(""),$&&"/"!==P.join("/").substr(-1)&&P.push("");var O=""===P[0]||P[0]&&"/"===P[0].charAt(0);if(E){t.hostname=t.host=O?"":P.length?P.shift():"";var j=!!(t.host&&t.host.indexOf("@")>0)&&t.host.split("@");j&&(t.auth=j.shift(),t.host=t.hostname=j.shift())}return y=y||t.host&&P.length,y&&!O&&P.unshift(""),P.length?t.pathname=P.join("/"):(t.pathname=null,t.path=null),c.isNull(t.pathname)&&c.isNull(t.search)||(t.path=(t.pathname?t.pathname:"")+(t.search?t.search:"")),t.auth=e.auth||t.auth,t.slashes=t.slashes||e.slashes,t.href=t.format(),t},a.prototype.parseHost=function(){var e=this.host,r=u.exec(e);r&&(r=r[0],":"!==r&&(this.port=r.substr(1)),e=e.substr(0,e.length-r.length)),e&&(this.hostname=e)}},{"./util":46,punycode:41,querystring:44}],46:[function(e,r,t){"use strict";r.exports={isString:function(e){return"string"==typeof e},isObject:function(e){return"object"==typeof e&&null!==e},isNull:function(e){return null===e},isNullOrUndefined:function(e){return null==e}}},{}],47:[function(e,r,t){function a(e){var r=this,t=f.call(arguments,1);return new Promise(function(a,o){function i(r){var t;try{t=e.next(r)}catch(e){return o(e)}c(t)}function n(r){var t;try{t=e.throw(r)}catch(e){return o(e)}c(t)}function c(e){if(e.done)return a(e.value);var t=s.call(r,e.value);return t&&l(t)?t.then(i,n):n(new TypeError('You may only yield a function, promise, generator, array, or object, but the following object was passed: "'+String(e.value)+'"'))}if("function"==typeof e&&(e=e.apply(r,t)),!e||"function"!=typeof e.next)return a(e);i()})}function s(e){return e?l(e)?e:h(e)||c(e)?a.call(this,e):"function"==typeof e?o.call(this,e):Array.isArray(e)?i.call(this,e):u(e)?n.call(this,e):e:e}function o(e){var r=this;return new Promise(function(t,a){e.call(r,function(e,r){if(e)return a(e);arguments.length>2&&(r=f.call(arguments,1)),t(r)})})}function i(e){return Promise.all(e.map(s,this))}function n(e){function r(e,r){t[r]=void 0,o.push(e.then(function(e){t[r]=e}))}for(var t=new e.constructor,a=Object.keys(e),o=[],i=0;i ="0"&&s<="9";)r+=s,c();if("."===s)for(r+=".";c()&&s>="0"&&s<="9";)r+=s;if("e"===s||"E"===s)for(r+=s,c(),"-"!==s&&"+"!==s||(r+=s,c());s>="0"&&s<="9";)r+=s,c();if(e=+r,isFinite(e))return e;l("Bad number")},u=function(){var e,r,t,a="";if('"'===s)for(;c();){if('"'===s)return c(),a;if("\\"===s)if(c(),"u"===s){for(t=0,r=0;r<4&&(e=parseInt(c(),16),isFinite(e));r+=1)t=16*t+e;a+=String.fromCharCode(t)}else{if("string"!=typeof n[s])break;a+=n[s]}else a+=s}l("Bad string")},f=function(){for(;s&&s<=" ";)c()},d=function(){switch(s){case"t":return c("t"),c("r"),c("u"),c("e"),!0;case"f":return c("f"),c("a"),c("l"),c("s"),c("e"),!1;case"n":return c("n"),c("u"),c("l"),c("l"),null}l("Unexpected '"+s+"'")},p=function(){var e=[];if("["===s){if(c("["),f(),"]"===s)return c("]"),e;for(;s;){if(e.push(i()),f(),"]"===s)return c("]"),e;c(","),f()}}l("Bad array")},m=function(){var e,r={};if("{"===s){if(c("{"),f(),"}"===s)return c("}"),r;for(;s;){if(e=u(),f(),c(":"),Object.hasOwnProperty.call(r,e)&&l('Duplicate key "'+e+'"'),r[e]=i(),f(),"}"===s)return c("}"),r;c(","),f()}}l("Bad object")};i=function(){switch(f(),s){case"{":return m();case"[":return p();case'"':return u();case"-":return h();default:return s>="0"&&s<="9"?h():d()}},r.exports=function(e,r){var t;return o=e,a=0,s=" ",t=i(),f(),s&&l("Syntax error"),"function"==typeof r?function e(t,a){var s,o,i=t[a];if(i&&"object"==typeof i)for(s in i)Object.prototype.hasOwnProperty.call(i,s)&&(o=e(i,s),void 0!==o?i[s]=o:delete i[s]);return r.call(t,a,i)}({"":t},""):t}},{}],51:[function(e,r,t){function a(e){return l.lastIndex=0,l.test(e)?'"'+e.replace(l,function(e){var r=c[e];return"string"==typeof r?r:"\\u"+("0000"+e.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+e+'"'}function s(e,r){var t,l,c,h,u,f=o,d=r[e];switch(d&&"object"==typeof d&&"function"==typeof d.toJSON&&(d=d.toJSON(e)),"function"==typeof n&&(d=n.call(r,e,d)),typeof d){case"string":return a(d);case"number":return isFinite(d)?String(d):"null";case"boolean":case"null":return String(d);case"object":if(!d)return"null";if(o+=i,u=[],"[object Array]"===Object.prototype.toString.apply(d)){for(h=d.length,t=0;t=1&&t<=12&&a>=1&&a<=m[t]}function o(e,r){var t=e.match(v);if(!t)return!1;var a=t[1],s=t[2],o=t[3],i=t[5];return a<=23&&s<=59&&o<=59&&(!r||i)}function i(e){var r=e.split(b);return 2==r.length&&s(r[0])&&o(r[1],!0)}function n(e){return e.length<=255&&y.test(e)}function l(e){return w.test(e)&&g.test(e)}function c(e){try{return new RegExp(e),!0}catch(e){return!1}}function h(e,r){if(e&&r)return e>r?1:er?1:e=0?{index:a,compiling:!0}:(a=this._compilations.length,this._compilations[a]={schema:e,root:r,baseId:t},{index:a,compiling:!1})}function i(e,r,t){var a=n.call(this,e,r,t);a>=0&&this._compilations.splice(a,1)}function n(e,r,t){for(var a=0;a=55296&&r<=56319&&s=r)throw new Error("Cannot access property/index "+a+" levels up, current level is "+r);return t[r-a]}if(a>r)throw new Error("Cannot access data "+a+" levels up, current level is "+r);if(o="data"+(r-a||""),!s)return o}for(var n=o,c=s.split("/"),h=0;h",S="result"+s,$=e.opts.v5&&i&&i.$data;if($?(a+=" var schema"+s+" = "+e.util.getData(i.$data,o,e.dataPathArr)+"; ",g="schema"+s):g=i,w){var x=e.util.getData(b.$data,o,e.dataPathArr),_="exclusive"+s,O="op"+s,R="' + "+O+" + '";a+=" var schemaExcl"+s+" = "+x+"; ",x="schemaExcl"+s,a+=" if (typeof "+x+" != 'boolean' && "+x+" !== undefined) { "+u+" = false; ";var t=E,I=I||[];I.push(a),a="",!1!==e.createErrors?(a+=" { keyword: '"+(t||"_formatExclusiveLimit")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(l)+" , params: {} ",!1!==e.opts.messages&&(a+=" , message: '"+E+" should be boolean' "),e.opts.verbose&&(a+=" , schema: validate.schema"+n+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),a+=" } "):a+=" {} ";var A=a;a=I.pop(),a+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+A+"]); ":" validate.errors = ["+A+"]; return false; ":" var err = "+A+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",a+=" } ",c&&(p+="}",a+=" else { "),$&&(a+=" if ("+g+" === undefined) "+u+" = true; else if (typeof "+g+" != 'string') "+u+" = false; else { ",p+="}"),d&&(a+=" if (!"+y+") "+u+" = true; else { ",p+="}"),a+=" var "+S+" = "+y+"("+h+", ",a+=$?""+g:""+e.util.toQuotedString(i),a+=" ); if ("+S+" === undefined) "+u+" = false; var "+_+" = "+x+" === true; if ("+u+" === undefined) { "+u+" = "+_+" ? "+S+" "+j+" 0 : "+S+" "+j+"= 0; } if (!"+u+") var op"+s+" = "+_+" ? '"+j+"' : '"+j+"=';"}else{var _=!0===b,R=j;_||(R+="=");var O="'"+R+"'";$&&(a+=" if ("+g+" === undefined) "+u+" = true; else if (typeof "+g+" != 'string') "+u+" = false; else { ",p+="}"),d&&(a+=" if (!"+y+") "+u+" = true; else { ",p+="}"),a+=" var "+S+" = "+y+"("+h+", ",a+=$?""+g:""+e.util.toQuotedString(i),a+=" ); if ("+S+" === undefined) "+u+" = false; if ("+u+" === undefined) "+u+" = "+S+" "+j,_||(a+="="),a+=" 0;"}a+=p+"if (!"+u+") { ";var t=r,I=I||[];I.push(a),a="",!1!==e.createErrors?(a+=" { keyword: '"+(t||"_formatLimit")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(l)+" , params: { comparison: "+O+", limit: ",a+=$?""+g:""+e.util.toQuotedString(i),a+=" , exclusive: "+_+" } ",!1!==e.opts.messages&&(a+=" , message: 'should be "+R+' "',a+=$?"' + "+g+" + '":""+e.util.escapeQuotes(i),a+="\"' "),e.opts.verbose&&(a+=" , schema: ",a+=$?"validate.schema"+n:""+e.util.toQuotedString(i),a+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),a+=" } "):a+=" {} ";var A=a;return a=I.pop(),a+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+A+"]); ":" validate.errors = ["+A+"]; return false; ":" var err = "+A+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",a+="}"}},{}],14:[function(e,r,t){"use strict";r.exports=function(e,r){var t,a,s=" ",o=e.level,i=e.dataLevel,n=e.schema[r],l=e.schemaPath+e.util.getProperty(r),c=e.errSchemaPath+"/"+r,h=!e.opts.allErrors,u="data"+(i||""),f=e.opts.v5&&n&&n.$data;f?(s+=" var schema"+o+" = "+e.util.getData(n.$data,i,e.dataPathArr)+"; ",a="schema"+o):a=n;var d="maximum"==r,p=d?"exclusiveMaximum":"exclusiveMinimum",m=e.schema[p],v=e.opts.v5&&m&&m.$data,y=d?"<":">",g=d?">":"<";if(v){var P=e.util.getData(m.$data,i,e.dataPathArr),E="exclusive"+o,b="op"+o,w="' + "+b+" + '";s+=" var schemaExcl"+o+" = "+P+"; ",P="schemaExcl"+o,s+=" var exclusive"+o+"; if (typeof "+P+" != 'boolean' && typeof "+P+" != 'undefined') { ";var t=p,j=j||[];j.push(s),s="",!1!==e.createErrors?(s+=" { keyword: '"+(t||"_exclusiveLimit")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(c)+" , params: {} ",!1!==e.opts.messages&&(s+=" , message: '"+p+" should be boolean' "),e.opts.verbose&&(s+=" , schema: validate.schema"+l+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+u+" "),s+=" } "):s+=" {} ";var S=s;s=j.pop(),s+=!e.compositeRule&&h?e.async?" throw new ValidationError(["+S+"]); ":" validate.errors = ["+S+"]; return false; ":" var err = "+S+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",s+=" } else if( ",f&&(s+=" ("+a+" !== undefined && typeof "+a+" != 'number') || "),s+=" ((exclusive"+o+" = "+P+" === true) ? "+u+" "+g+"= "+a+" : "+u+" "+g+" "+a+") || "+u+" !== "+u+") { var op"+o+" = exclusive"+o+" ? '"+y+"' : '"+y+"=';"}else{var E=!0===m,w=y;E||(w+="=");var b="'"+w+"'";s+=" if ( ",f&&(s+=" ("+a+" !== undefined && typeof "+a+" != 'number') || "),s+=" "+u+" "+g,E&&(s+="="),s+=" "+a+" || "+u+" !== "+u+") {"}var t=r,j=j||[];j.push(s),s="",!1!==e.createErrors?(s+=" { keyword: '"+(t||"_limit")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(c)+" , params: { comparison: "+b+", limit: "+a+", exclusive: "+E+" } ",!1!==e.opts.messages&&(s+=" , message: 'should be "+w+" ",s+=f?"' + "+a:n+"'"),e.opts.verbose&&(s+=" , schema: ",s+=f?"validate.schema"+l:""+n,s+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+u+" "),s+=" } "):s+=" {} ";var S=s;return s=j.pop(),s+=!e.compositeRule&&h?e.async?" throw new ValidationError(["+S+"]); ":" validate.errors = ["+S+"]; return false; ":" var err = "+S+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",s+=" } ",h&&(s+=" else { "),s}},{}],15:[function(e,r,t){"use strict";r.exports=function(e,r){var t,a,s=" ",o=e.level,i=e.dataLevel,n=e.schema[r],l=e.schemaPath+e.util.getProperty(r),c=e.errSchemaPath+"/"+r,h=!e.opts.allErrors,u="data"+(i||""),f=e.opts.v5&&n&&n.$data;f?(s+=" var schema"+o+" = "+e.util.getData(n.$data,i,e.dataPathArr)+"; ",a="schema"+o):a=n;var d="maxItems"==r?">":"<";s+="if ( ",f&&(s+=" ("+a+" !== undefined && typeof "+a+" != 'number') || "),s+=" "+u+".length "+d+" "+a+") { ";var t=r,p=p||[];p.push(s),s="",!1!==e.createErrors?(s+=" { keyword: '"+(t||"_limitItems")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(c)+" , params: { limit: "+a+" } ",!1!==e.opts.messages&&(s+=" , message: 'should NOT have ",s+="maxItems"==r?"more":"less",s+=" than ",s+=f?"' + "+a+" + '":""+n,s+=" items' "),e.opts.verbose&&(s+=" , schema: ",s+=f?"validate.schema"+l:""+n,s+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+u+" "),s+=" } "):s+=" {} ";var m=s;return s=p.pop(),s+=!e.compositeRule&&h?e.async?" throw new ValidationError(["+m+"]); ":" validate.errors = ["+m+"]; return false; ":" var err = "+m+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",s+="} ",h&&(s+=" else { "),s}},{}],16:[function(e,r,t){"use strict";r.exports=function(e,r){var t,a,s=" ",o=e.level,i=e.dataLevel,n=e.schema[r],l=e.schemaPath+e.util.getProperty(r),c=e.errSchemaPath+"/"+r,h=!e.opts.allErrors,u="data"+(i||""),f=e.opts.v5&&n&&n.$data;f?(s+=" var schema"+o+" = "+e.util.getData(n.$data,i,e.dataPathArr)+"; ",a="schema"+o):a=n;var d="maxLength"==r?">":"<";s+="if ( ",f&&(s+=" ("+a+" !== undefined && typeof "+a+" != 'number') || "),s+=!1===e.opts.unicode?" "+u+".length ":" ucs2length("+u+") ",s+=" "+d+" "+a+") { ";var t=r,p=p||[];p.push(s),s="",!1!==e.createErrors?(s+=" { keyword: '"+(t||"_limitLength")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(c)+" , params: { limit: "+a+" } ",!1!==e.opts.messages&&(s+=" , message: 'should NOT be ",s+="maxLength"==r?"longer":"shorter",s+=" than ",s+=f?"' + "+a+" + '":""+n,s+=" characters' "),e.opts.verbose&&(s+=" , schema: ",s+=f?"validate.schema"+l:""+n,
+s+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+u+" "),s+=" } "):s+=" {} ";var m=s;return s=p.pop(),s+=!e.compositeRule&&h?e.async?" throw new ValidationError(["+m+"]); ":" validate.errors = ["+m+"]; return false; ":" var err = "+m+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",s+="} ",h&&(s+=" else { "),s}},{}],17:[function(e,r,t){"use strict";r.exports=function(e,r){var t,a,s=" ",o=e.level,i=e.dataLevel,n=e.schema[r],l=e.schemaPath+e.util.getProperty(r),c=e.errSchemaPath+"/"+r,h=!e.opts.allErrors,u="data"+(i||""),f=e.opts.v5&&n&&n.$data;f?(s+=" var schema"+o+" = "+e.util.getData(n.$data,i,e.dataPathArr)+"; ",a="schema"+o):a=n;var d="maxProperties"==r?">":"<";s+="if ( ",f&&(s+=" ("+a+" !== undefined && typeof "+a+" != 'number') || "),s+=" Object.keys("+u+").length "+d+" "+a+") { ";var t=r,p=p||[];p.push(s),s="",!1!==e.createErrors?(s+=" { keyword: '"+(t||"_limitProperties")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(c)+" , params: { limit: "+a+" } ",!1!==e.opts.messages&&(s+=" , message: 'should NOT have ",s+="maxProperties"==r?"more":"less",s+=" than ",s+=f?"' + "+a+" + '":""+n,s+=" properties' "),e.opts.verbose&&(s+=" , schema: ",s+=f?"validate.schema"+l:""+n,s+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+u+" "),s+=" } "):s+=" {} ";var m=s;return s=p.pop(),s+=!e.compositeRule&&h?e.async?" throw new ValidationError(["+m+"]); ":" validate.errors = ["+m+"]; return false; ":" var err = "+m+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",s+="} ",h&&(s+=" else { "),s}},{}],18:[function(e,r,t){"use strict";r.exports=function(e,r){var t=" ",a=e.schema[r],s=e.schemaPath+e.util.getProperty(r),o=e.errSchemaPath+"/"+r,i=!e.opts.allErrors,n=e.util.copy(e),l="";n.level++;var c="valid"+n.level,h=n.baseId,u=!0,f=a;if(f)for(var d,p=-1,m=f.length-1;p "+$+") { ";var _=c+"["+$+"]";f.schema=S,f.schemaPath=i+"["+$+"]",f.errSchemaPath=n+"/"+$,f.errorPath=e.util.getPathExpr(e.errorPath,$,e.opts.jsonPointers,!0),f.dataPathArr[v]=$;var O=e.validate(f);f.baseId=g,e.util.varOccurences(O,y)<2?t+=" "+e.util.varReplace(O,y,_)+" ":t+=" var "+y+" = "+_+"; "+O+" ",t+=" } ",l&&(t+=" if ("+p+") { ",d+="}")}if("object"==typeof P&&e.util.schemaHasRules(P,e.RULES.all)){f.schema=P,f.schemaPath=e.schemaPath+".additionalItems",f.errSchemaPath=e.errSchemaPath+"/additionalItems",t+=" "+p+" = true; if ("+c+".length > "+o.length+") { for (var "+m+" = "+o.length+"; "+m+" < "+c+".length; "+m+"++) { ",f.errorPath=e.util.getPathExpr(e.errorPath,m,e.opts.jsonPointers,!0);var _=c+"["+m+"]";f.dataPathArr[v]=m;var O=e.validate(f);f.baseId=g,e.util.varOccurences(O,y)<2?t+=" "+e.util.varReplace(O,y,_)+" ":t+=" var "+y+" = "+_+"; "+O+" ",l&&(t+=" if (!"+p+") break; "),t+=" } } ",l&&(t+=" if ("+p+") { ",d+="}")}}else if(e.util.schemaHasRules(o,e.RULES.all)){f.schema=o,f.schemaPath=i,f.errSchemaPath=n,t+=" for (var "+m+" = 0; "+m+" < "+c+".length; "+m+"++) { ",f.errorPath=e.util.getPathExpr(e.errorPath,m,e.opts.jsonPointers,!0);var _=c+"["+m+"]";f.dataPathArr[v]=m;var O=e.validate(f);f.baseId=g,e.util.varOccurences(O,y)<2?t+=" "+e.util.varReplace(O,y,_)+" ":t+=" var "+y+" = "+_+"; "+O+" ",l&&(t+=" if (!"+p+") break; "),t+=" } ",l&&(t+=" if ("+p+") { ",d+="}")}return l&&(t+=" "+d+" if ("+u+" == errors) {"),t=e.util.cleanUpCode(t)}},{}],26:[function(e,r,t){"use strict";r.exports=function(e,r){var t,a=" ",s=e.level,o=e.dataLevel,i=e.schema[r],n=e.schemaPath+e.util.getProperty(r),l=e.errSchemaPath+"/"+r,c=!e.opts.allErrors,h="data"+(o||""),u=e.opts.v5&&i&&i.$data;u?(a+=" var schema"+s+" = "+e.util.getData(i.$data,o,e.dataPathArr)+"; ",t="schema"+s):t=i,a+="var division"+s+";if (",u&&(a+=" "+t+" !== undefined && ( typeof "+t+" != 'number' || "),a+=" (division"+s+" = "+h+" / "+t+", ",a+=e.opts.multipleOfPrecision?" Math.abs(Math.round(division"+s+") - division"+s+") > 1e-"+e.opts.multipleOfPrecision+" ":" division"+s+" !== parseInt(division"+s+") ",a+=" ) ",u&&(a+=" ) "),a+=" ) { ";var f=f||[];f.push(a),a="",!1!==e.createErrors?(a+=" { keyword: 'multipleOf' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(l)+" , params: { multipleOf: "+t+" } ",!1!==e.opts.messages&&(a+=" , message: 'should be multiple of ",a+=u?"' + "+t:i+"'"),e.opts.verbose&&(a+=" , schema: ",a+=u?"validate.schema"+n:""+i,a+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),a+=" } "):a+=" {} ";var d=a;return a=f.pop(),a+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+d+"]); ":" validate.errors = ["+d+"]; return false; ":" var err = "+d+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",a+="} ",c&&(a+=" else { "),a}},{}],27:[function(e,r,t){"use strict";r.exports=function(e,r){var t=" ",a=e.level,s=e.dataLevel,o=e.schema[r],i=e.schemaPath+e.util.getProperty(r),n=e.errSchemaPath+"/"+r,l=!e.opts.allErrors,c="data"+(s||""),h="errs__"+a,u=e.util.copy(e);u.level++;var f="valid"+u.level;if(e.util.schemaHasRules(o,e.RULES.all)){u.schema=o,u.schemaPath=i,u.errSchemaPath=n,t+=" var "+h+" = errors; ";var d=e.compositeRule;e.compositeRule=u.compositeRule=!0,u.createErrors=!1;var p;u.opts.allErrors&&(p=u.opts.allErrors,u.opts.allErrors=!1),t+=" "+e.validate(u)+" ",u.createErrors=!0,p&&(u.opts.allErrors=p),e.compositeRule=u.compositeRule=d,t+=" if ("+f+") { ";var m=m||[];m.push(t),t="",!1!==e.createErrors?(t+=" { keyword: 'not' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(n)+" , params: {} ",!1!==e.opts.messages&&(t+=" , message: 'should NOT be valid' "),e.opts.verbose&&(t+=" , schema: validate.schema"+i+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+c+" "),t+=" } "):t+=" {} ";var v=t;t=m.pop(),t+=!e.compositeRule&&l?e.async?" throw new ValidationError(["+v+"]); ":" validate.errors = ["+v+"]; return false; ":" var err = "+v+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",t+=" } else { errors = "+h+"; if (vErrors !== null) { if ("+h+") vErrors.length = "+h+"; else vErrors = null; } ",e.opts.allErrors&&(t+=" } ")}else t+=" var err = ",!1!==e.createErrors?(t+=" { keyword: 'not' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(n)+" , params: {} ",!1!==e.opts.messages&&(t+=" , message: 'should NOT be valid' "),e.opts.verbose&&(t+=" , schema: validate.schema"+i+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+c+" "),t+=" } "):t+=" {} ",t+="; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",l&&(t+=" if (false) { ");return t}},{}],28:[function(e,r,t){"use strict";r.exports=function(e,r){var t=" ",a=e.level,s=e.dataLevel,o=e.schema[r],i=e.schemaPath+e.util.getProperty(r),n=e.errSchemaPath+"/"+r,l=!e.opts.allErrors,c="data"+(s||""),h="valid"+a,u="errs__"+a,f=e.util.copy(e),d="";f.level++;var p="valid"+f.level;t+="var "+u+" = errors;var prevValid"+a+" = false;var "+h+" = false;";var m=f.baseId,v=e.compositeRule;e.compositeRule=f.compositeRule=!0;var y=o;if(y)for(var g,P=-1,E=y.length-1;P5)t+=" || validate.schema"+i+"["+m+"] ";else{var q=g;if(q)for(var D,L=-1,Q=q.length-1;L= "+pe+"; ",n=e.errSchemaPath+"/patternGroups/minimum",t+=" if (!"+h+") { ";var G=G||[];G.push(t),t="",!1!==e.createErrors?(t+=" { keyword: 'patternGroups' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(n)+" , params: { reason: '"+ye+"', limit: "+ve+", pattern: '"+e.util.escapeQuotes(M)+"' } ",!1!==e.opts.messages&&(t+=" , message: 'should NOT have "+ge+" than "+ve+' properties matching pattern "'+e.util.escapeQuotes(M)+"\"' "),e.opts.verbose&&(t+=" , schema: validate.schema"+i+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+c+" "),t+=" } "):t+=" {} ";var K=t;t=G.pop(),t+=!e.compositeRule&&l?e.async?" throw new ValidationError(["+K+"]); ":" validate.errors = ["+K+"]; return false; ":" var err = "+K+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",t+=" } ",void 0!==me&&(t+=" else ")}if(void 0!==me){var ve=me,ye="maximum",ge="more";t+=" "+h+" = pgPropCount"+a+" <= "+me+"; ",n=e.errSchemaPath+"/patternGroups/maximum",t+=" if (!"+h+") { ";var G=G||[];G.push(t),t="",!1!==e.createErrors?(t+=" { keyword: 'patternGroups' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(n)+" , params: { reason: '"+ye+"', limit: "+ve+", pattern: '"+e.util.escapeQuotes(M)+"' } ",!1!==e.opts.messages&&(t+=" , message: 'should NOT have "+ge+" than "+ve+' properties matching pattern "'+e.util.escapeQuotes(M)+"\"' "),e.opts.verbose&&(t+=" , schema: validate.schema"+i+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+c+" "),t+=" } "):t+=" {} ";var K=t;t=G.pop(),t+=!e.compositeRule&&l?e.async?" throw new ValidationError(["+K+"]); ":" validate.errors = ["+K+"]; return false; ":" var err = "+K+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",t+=" } "}n=J,l&&(t+=" if ("+h+") { ",d+="}")}}}}return l&&(t+=" "+d+" if ("+u+" == errors) {"),t=e.util.cleanUpCode(t)}},{}],32:[function(e,r,t){"use strict";r.exports=function(e,r){var t,a,s=" ",o=e.level,i=e.dataLevel,n=e.schema[r],l=e.errSchemaPath+"/"+r,c=!e.opts.allErrors,h="data"+(i||""),u="valid"+o;if("#"==n||"#/"==n)e.isRoot?(t=e.async,a="validate"):(t=!0===e.root.schema.$async,a="root.refVal[0]");else{var f=e.resolveRef(e.baseId,n,e.isRoot);if(void 0===f){var d="can't resolve reference "+n+" from id "+e.baseId;if("fail"==e.opts.missingRefs){console.log(d);var p=p||[];p.push(s),s="",!1!==e.createErrors?(s+=" { keyword: '$ref' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(l)+" , params: { ref: '"+e.util.escapeQuotes(n)+"' } ",!1!==e.opts.messages&&(s+=" , message: 'can\\'t resolve reference "+e.util.escapeQuotes(n)+"' "),e.opts.verbose&&(s+=" , schema: "+e.util.toQuotedString(n)+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),s+=" } "):s+=" {} ";var m=s;s=p.pop(),s+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+m+"]); ":" validate.errors = ["+m+"]; return false; ":" var err = "+m+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",c&&(s+=" if (false) { ")}else{if("ignore"!=e.opts.missingRefs){var v=new Error(d);throw v.missingRef=e.resolve.url(e.baseId,n),v.missingSchema=e.resolve.normalizeId(e.resolve.fullPath(v.missingRef)),v}console.log(d),c&&(s+=" if (true) { ")}}else if(f.inline){var y=e.util.copy(e);y.level++;var g="valid"+y.level;y.schema=f.schema,y.schemaPath="",y.errSchemaPath=n;var P=e.validate(y).replace(/validate\.schema/g,f.code);s+=" "+P+" ",c&&(s+=" if ("+g+") { ")}else t=!0===f.$async,a=f.code}if(a){var p=p||[];p.push(s),s="",s+=e.opts.passContext?" "+a+".call(this, ":" "+a+"( ",s+=" "+h+", (dataPath || '')",'""'!=e.errorPath&&(s+=" + "+e.errorPath);s+=" , "+(i?"data"+(i-1||""):"parentData")+" , "+(i?e.dataPathArr[i]:"parentDataProperty")+", rootData) ";var E=s;if(s=p.pop(),t){if(!e.async)throw new Error("async schema referenced by sync schema");s+=" try { ",c&&(s+="var "+u+" ="),s+=" "+e.yieldAwait+" "+E+"; } catch (e) { if (!(e instanceof ValidationError)) throw e; if (vErrors === null) vErrors = e.errors; else vErrors = vErrors.concat(e.errors); errors = vErrors.length; } ",c&&(s+=" if ("+u+") { ")}else s+=" if (!"+E+") { if (vErrors === null) vErrors = "+a+".errors; else vErrors = vErrors.concat("+a+".errors); errors = vErrors.length; } ",c&&(s+=" else { ")}return s}},{}],33:[function(e,r,t){"use strict";r.exports=function(e,r){var t=" ",a=e.level,s=e.dataLevel,o=e.schema[r],i=e.schemaPath+e.util.getProperty(r),n=e.errSchemaPath+"/"+r,l=!e.opts.allErrors,c="data"+(s||""),h="valid"+a,u=e.opts.v5&&o&&o.$data;u&&(t+=" var schema"+a+" = "+e.util.getData(o.$data,s,e.dataPathArr)+"; ");var f="schema"+a;if(!u)if(o.length=e.opts.loopRequired;if(l)if(t+=" var missing"+a+"; ",E){u||(t+=" var "+f+" = validate.schema"+i+"; ");var b="i"+a,w="schema"+a+"["+b+"]",j="' + "+w+" + '";e.opts._errorDataPathProperty&&(e.errorPath=e.util.getPathExpr(P,w,e.opts.jsonPointers)),t+=" var "+h+" = true; ",u&&(t+=" if (schema"+a+" === undefined) "+h+" = true; else if (!Array.isArray(schema"+a+")) "+h+" = false; else {"),t+=" for (var "+b+" = 0; "+b+" < "+f+".length; "+b+"++) { "+h+" = "+c+"["+f+"["+b+"]] !== undefined; if (!"+h+") break; } ",u&&(t+=" } "),t+=" if (!"+h+") { ";var S=S||[];S.push(t),t="",!1!==e.createErrors?(t+=" { keyword: 'required' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(n)+" , params: { missingProperty: '"+j+"' } ",!1!==e.opts.messages&&(t+=" , message: '",t+=e.opts._errorDataPathProperty?"is a required property":"should have required property \\'"+j+"\\'",t+="' "),e.opts.verbose&&(t+=" , schema: validate.schema"+i+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+c+" "),t+=" } "):t+=" {} ";var $=t;t=S.pop(),t+=!e.compositeRule&&l?e.async?" throw new ValidationError(["+$+"]); ":" validate.errors = ["+$+"]; return false; ":" var err = "+$+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",t+=" } else { "}else{t+=" if ( ";var x=d;if(x)for(var _,b=-1,O=x.length-1;b 1) { var i = "+h+".length, j; outer: for (;i--;) { for (j = i; j--;) { if (equal("+h+"[i], "+h+"[j])) { "+u+" = false; break outer; } } } } ",f&&(a+=" } "),a+=" if (!"+u+") { ";var d=d||[];d.push(a),a="",!1!==e.createErrors?(a+=" { keyword: 'uniqueItems' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(l)+" , params: { i: i, j: j } ",!1!==e.opts.messages&&(a+=" , message: 'should NOT have duplicate items (items ## ' + j + ' and ' + i + ' are identical)' "),e.opts.verbose&&(a+=" , schema: ",a+=f?"validate.schema"+n:""+i,a+=" , parentSchema: validate.schema"+e.schemaPath+" , data: "+h+" "),a+=" } "):a+=" {} ";var p=a;a=d.pop(),a+=!e.compositeRule&&c?e.async?" throw new ValidationError(["+p+"]); ":" validate.errors = ["+p+"]; return false; ":" var err = "+p+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",a+=" } ",c&&(a+=" else { ")}else c&&(a+=" if (true) { ");return a}},{}],36:[function(e,r,t){"use strict";r.exports=function(e,r){function t(r){return void 0!==e.schema[r.keyword]||"properties"==r.keyword&&(!1===e.schema.additionalProperties||"object"==typeof e.schema.additionalProperties||e.schema.patternProperties&&Object.keys(e.schema.patternProperties).length||e.opts.v5&&e.schema.patternGroups&&Object.keys(e.schema.patternGroups).length)}var a="",s=!0===e.schema.$async;if(e.isTop){var o=e.isTop,i=e.level=0,n=e.dataLevel=0,l="data";if(e.rootId=e.resolve.fullPath(e.root.schema.id),e.baseId=e.baseId||e.rootId,s){e.async=!0;var c="es7"==e.opts.async;e.yieldAwait=c?"await":"yield"}delete e.isTop,e.dataPathArr=[void 0],a+=" var validate = ",s?c?a+=" (async function ":("co*"==e.opts.async&&(a+="co.wrap"),a+="(function* "):a+=" (function ",a+=" (data, dataPath, parentData, parentDataProperty, rootData) { 'use strict'; var vErrors = null; ",a+=" var errors = 0; ",a+=" if (rootData === undefined) rootData = data;"}else{var i=e.level,n=e.dataLevel,l="data"+(n||"");if(e.schema.id&&(e.baseId=e.resolve.url(e.baseId,e.schema.id)),s&&!e.async)throw new Error("async schema in sync schema");a+=" var errs_"+i+" = errors;"}var h="valid"+i,u=!e.opts.allErrors,f="",d="",p=e.schema.type,m=Array.isArray(p);if(p&&e.opts.coerceTypes){var v=e.util.coerceToTypes(e.opts.coerceTypes,p);if(v){var y=e.schemaPath+".type",g=e.errSchemaPath+"/type",P=m?"checkDataTypes":"checkDataType";a+=" if ("+e.util[P](p,l,!0)+") { ";var E="dataType"+i,b="coerced"+i;a+=" var "+E+" = typeof "+l+"; ","array"==e.opts.coerceTypes&&(a+=" if ("+E+" == 'object' && Array.isArray("+l+")) "+E+" = 'array'; "),a+=" var "+b+" = undefined; ";var w="",j=v;if(j)for(var S,$=-1,x=j.length-1;$2&&(r=f.call(arguments,1)),t(r)})})}function i(e){return Promise.all(e.map(s,this))}function n(e){for(var r=new e.constructor,t=Object.keys(e),a=[],o=0;o="0"&&s<="9";)r+=s,c();if("."===s)for(r+=".";c()&&s>="0"&&s<="9";)r+=s;if("e"===s||"E"===s)for(r+=s,c(),"-"!==s&&"+"!==s||(r+=s,c());s>="0"&&s<="9";)r+=s,c();if(e=+r,isFinite(e))return e;l("Bad number")},u=function(){var e,r,t,a="";if('"'===s)for(;c();){if('"'===s)return c(),a;if("\\"===s)if(c(),"u"===s){for(t=0,r=0;r<4&&(e=parseInt(c(),16),isFinite(e));r+=1)t=16*t+e;a+=String.fromCharCode(t)}else{if("string"!=typeof n[s])break;a+=n[s]}else a+=s}l("Bad string")},f=function(){for(;s&&s<=" ";)c()},d=function(){switch(s){case"t":return c("t"),c("r"),c("u"),c("e"),!0;case"f":return c("f"),c("a"),c("l"),c("s"),c("e"),!1;case"n":return c("n"),c("u"),c("l"),c("l"),null}l("Unexpected '"+s+"'")},p=function(){var e=[];if("["===s){if(c("["),f(),"]"===s)return c("]"),e;for(;s;){if(e.push(i()),f(),"]"===s)return c("]"),e;c(","),f()}}l("Bad array")},m=function(){var e,r={};if("{"===s){if(c("{"),f(),"}"===s)return c("}"),r;for(;s;){if(e=u(),f(),c(":"),Object.hasOwnProperty.call(r,e)&&l('Duplicate key "'+e+'"'),r[e]=i(),f(),"}"===s)return c("}"),r;c(","),f()}}l("Bad object")};i=function(){switch(f(),s){case"{":return m();case"[":return p();case'"':return u();case"-":return h();default:return s>="0"&&s<="9"?h():d()}},r.exports=function(e,r){var t;return o=e,a=0,s=" ",t=i(),f(),s&&l("Syntax error"),"function"==typeof r?function e(t,a){var s,o,i=t[a];if(i&&"object"==typeof i)for(s in i)Object.prototype.hasOwnProperty.call(i,s)&&(o=e(i,s),void 0!==o?i[s]=o:delete i[s]);return r.call(t,a,i)}({"":t},""):t}},{}],45:[function(e,r,t){function a(e){return l.lastIndex=0,l.test(e)?'"'+e.replace(l,function(e){var r=c[e];return"string"==typeof r?r:"\\u"+("0000"+e.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+e+'"'}function s(e,r){var t,l,c,h,u,f=o,d=r[e];switch(d&&"object"==typeof d&&"function"==typeof d.toJSON&&(d=d.toJSON(e)),"function"==typeof n&&(d=n.call(r,e,d)),typeof d){case"string":return a(d);case"number":return isFinite(d)?String(d):"null";case"boolean":case"null":return String(d);case"object":if(!d)return"null";if(o+=i,u=[],"[object Array]"===Object.prototype.toString.apply(d)){for(h=d.length,t=0;t1&&(a=t[0]+"@",e=t[1]),e=e.replace(q,"."),a+i(e.split("."),r).join(".")}function l(e){for(var r,t,a=[],s=0,o=e.length;s=55296&&r<=56319&&s65535&&(e-=65536,r+=C(e>>>10&1023|55296),e=56320|1023&e),r+=C(e)}).join("")}function h(e){return e-48<10?e-22:e-65<26?e-65:e-97<26?e-97:j}function u(e,r){return e+22+75*(e<26)-((0!=r)<<5)}function f(e,r,t){var a=0;for(e=t?Q(e/_):e>>1,e+=Q(e/r);e>L*$>>1;a+=j)e=Q(e/L);return Q(a+(L+1)*e/(e+x))}function d(e){var r,t,a,s,i,n,l,u,d,p,m=[],v=e.length,y=0,g=R,P=O;for(t=e.lastIndexOf(I),t<0&&(t=0),a=0;a=128&&o("not-basic"),m.push(e.charCodeAt(a));for(s=t>0?t+1:0;s=v&&o("invalid-input"),u=h(e.charCodeAt(s++)),(u>=j||u>Q((w-y)/n))&&o("overflow"),y+=u*n,d=l<=P?S:l>=P+$?$:l-P,!(uQ(w/p)&&o("overflow"),n*=p;r=m.length+1,P=f(y-i,r,0==i),Q(y/r)>w-g&&o("overflow"),g+=Q(y/r),y%=r,m.splice(y++,0,g)}return c(m)}function p(e){var r,t,a,s,i,n,c,h,d,p,m,v,y,g,P,E=[];for(e=l(e),v=e.length,r=R,t=0,i=O,n=0;n=r&&mQ((w-t)/y)&&o("overflow"),t+=(c-r)*y,r=c,n=0;nw&&o("overflow"),m==r){for(h=t,d=j;p=d<=i?S:d>=i+$?$:d-i,!(h= 0x80 (not a basic code point)","invalid-input":"Invalid input"},L=j-S,Q=Math.floor,C=String.fromCharCode;if(E={version:"1.4.1",ucs2:{decode:l,encode:c},decode:d,encode:p,toASCII:v,toUnicode:m},"function"==typeof e&&"object"==typeof e.amd&&e.amd)e("punycode",function(){return E});else if(y&&g)if(t.exports==y)g.exports=E;else for(b in E)E.hasOwnProperty(b)&&(y[b]=E[b]);else s.punycode=E}(this)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],47:[function(e,r,t){"use strict";function a(e,r){return Object.prototype.hasOwnProperty.call(e,r)}r.exports=function(e,r,t,o){r=r||"&",t=t||"=";var i={};if("string"!=typeof e||0===e.length)return i;e=e.split(r);var n=1e3;o&&"number"==typeof o.maxKeys&&(n=o.maxKeys);var l=e.length;n>0&&l>n&&(l=n);for(var c=0;c=0?(h=p.substr(0,m),u=p.substr(m+1)):(h=p,u=""),f=decodeURIComponent(h),d=decodeURIComponent(u),a(i,f)?s(i[f])?i[f].push(d):i[f]=[i[f],d]:i[f]=d}return i};var s=Array.isArray||function(e){return"[object Array]"===Object.prototype.toString.call(e)}},{}],48:[function(e,r,t){"use strict";function a(e,r){if(e.map)return e.map(r);for(var t=[],a=0;a",'"',"`"," ","\r","\n","\t"],p=["{","}","|","\\","^","`"].concat(d),m=["'"].concat(p),v=["%","/","?",";","#"].concat(m),y=["/","?","#"],g={javascript:!0,"javascript:":!0},P={javascript:!0,"javascript:":!0},E={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,"http:":!0,"https:":!0,"ftp:":!0,"gopher:":!0,"file:":!0},b=e("querystring");a.prototype.parse=function(e,r,t){if(!c.isString(e))throw new TypeError("Parameter 'url' must be a string, not "+typeof e);var a=e.indexOf("?"),s=-1!==a&&a127?A+="x":A+=I[k];if(!A.match(/^[+a-z0-9A-Z_-]{0,63}$/)){var D=O.slice(0,j),L=O.slice(j+1),Q=I.match(/^([+a-z0-9A-Z_-]{0,63})(.*)$/);Q&&(D.push(Q[1]),L.unshift(Q[2])),L.length&&(i="/"+L.join(".")+i),this.hostname=D.join(".");break}}}this.hostname=this.hostname.length>255?"":this.hostname.toLowerCase(),_||(this.hostname=l.toASCII(this.hostname));var C=this.port?":"+this.port:"";this.host=(this.hostname||"")+C,this.href+=this.host,_&&(this.hostname=this.hostname.substr(1,this.hostname.length-2),"/"!==i[0]&&(i="/"+i))}if(!g[d])for(var j=0,R=m.length;j0)&&t.host.split("@");j&&(t.auth=j.shift(),t.host=t.hostname=j.shift())}return t.search=e.search,t.query=e.query,c.isNull(t.pathname)&&c.isNull(t.search)||(t.path=(t.pathname?t.pathname:"")+(t.search?t.search:"")),t.href=t.format(),t}if(!b.length)return t.pathname=null,t.path=t.search?"/"+t.search:null,t.href=t.format(),t;for(var S=b.slice(-1)[0],$=(t.host||e.host||b.length>1)&&("."===S||".."===S)||""===S,x=0,_=b.length;_>=0;_--)S=b[_],"."===S?b.splice(_,1):".."===S?(b.splice(_,1),x++):x&&(b.splice(_,1),x--);if(!y&&!g)for(;x--;x)b.unshift("..");!y||""===b[0]||b[0]&&"/"===b[0].charAt(0)||b.unshift(""),$&&"/"!==b.join("/").substr(-1)&&b.push("");var O=""===b[0]||b[0]&&"/"===b[0].charAt(0);if(w){t.hostname=t.host=O?"":b.length?b.shift():"";var j=!!(t.host&&t.host.indexOf("@")>0)&&t.host.split("@");j&&(t.auth=j.shift(),t.host=t.hostname=j.shift())}return y=y||t.host&&b.length,y&&!O&&b.unshift(""),b.length?t.pathname=b.join("/"):(t.pathname=null,t.path=null),c.isNull(t.pathname)&&c.isNull(t.search)||(t.path=(t.pathname?t.pathname:"")+(t.search?t.search:"")),t.auth=e.auth||t.auth,t.slashes=t.slashes||e.slashes,t.href=t.format(),t},a.prototype.parseHost=function(){var e=this.host,r=u.exec(e);r&&(r=r[0],":"!==r&&(this.port=r.substr(1)),e=e.substr(0,e.length-r.length)),e&&(this.hostname=e)}},{"./util":51,punycode:46,querystring:49}],51:[function(e,r,t){"use strict";r.exports={isString:function(e){return"string"==typeof e},isObject:function(e){return"object"==typeof e&&null!==e},isNull:function(e){return null===e},isNullOrUndefined:function(e){return null==e}}},{}],ajv:[function(e,r,t){"use strict";function a(e){return g.test(e)}function s(r){function t(e,r){var t;if("string"==typeof e){if(!(t=S(e)))throw new Error('no schema with key or ref "'+e+'"')}else{var a=R(e);t=a.validate||I(a)}var s=t(r);return!0===t.$async?"*"==D._opts.async?m(s):s:(D.errors=t.errors,s)}function v(e,r){var t=R(e,void 0,r);return t.validate||I(t)}function E(e,r,t,a){if(Array.isArray(e))for(var s=0;s=i())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+i().toString(16)+" bytes");return 0|e}function m(e){return+e!=e&&(e=0),o.alloc(+e)}function g(e,t){if(o.isBuffer(e))return e.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(e)||e instanceof ArrayBuffer))return e.byteLength;"string"!=typeof e&&(e=""+e);var n=e.length;if(0===n)return 0;for(var r=!1;;)switch(t){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":case void 0:return z(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*n;case"hex":return n>>>1;case"base64":return J(e).length;default:if(r)return z(e).length;t=(""+t).toLowerCase(),r=!0}}function v(e,t,n){var r=!1;if((void 0===t||t<0)&&(t=0),t>this.length)return"";if((void 0===n||n>this.length)&&(n=this.length),n<=0)return"";if(n>>>=0,t>>>=0,n<=t)return"";for(e||(e="utf8");;)switch(e){case"hex":return F(this,t,n);case"utf8":case"utf-8":return P(this,t,n);case"ascii":return R(this,t,n);case"latin1":case"binary":return O(this,t,n);case"base64":return L(this,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return N(this,t,n);default:if(r)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),r=!0}}function b(e,t,n){var r=e[t];e[t]=e[n],e[n]=r}function x(e,t,n,r,i){if(0===e.length)return-1;if("string"==typeof n?(r=n,n=0):n>2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),n=+n,isNaN(n)&&(n=i?0:e.length-1),n<0&&(n=e.length+n),n>=e.length){if(i)return-1;n=e.length-1}else if(n<0){if(!i)return-1;n=0}if("string"==typeof t&&(t=o.from(t,r)),o.isBuffer(t))return 0===t.length?-1:w(e,t,n,r,i);if("number"==typeof t)return t&=255,o.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?i?Uint8Array.prototype.indexOf.call(e,t,n):Uint8Array.prototype.lastIndexOf.call(e,t,n):w(e,[t],n,r,i);throw new TypeError("val must be string, number or Buffer")}function w(e,t,n,r,i){function s(e,t){return 1===o?e[t]:e.readUInt16BE(t*o)}var o=1,a=e.length,u=t.length;if(void 0!==r&&(r=String(r).toLowerCase(),"ucs2"===r||"ucs-2"===r||"utf16le"===r||"utf-16le"===r)){if(e.length<2||t.length<2)return-1;o=2,a/=2,u/=2,n/=2}var c;if(i){var l=-1;for(c=n;ca&&(n=a-u),c=n;c>=0;c--){for(var p=!0,h=0;hi&&(r=i)):r=i;var s=t.length;if(s%2!==0)throw new TypeError("Invalid hex string");r>s/2&&(r=s/2);for(var o=0;o239?4:s>223?3:s>191?2:1;if(i+a<=n){var u,c,l,p;switch(a){case 1:s<128&&(o=s);break;case 2:u=e[i+1],128===(192&u)&&(p=(31&s)<<6|63&u,p>127&&(o=p));break;case 3:u=e[i+1],c=e[i+2],128===(192&u)&&128===(192&c)&&(p=(15&s)<<12|(63&u)<<6|63&c,p>2047&&(p<55296||p>57343)&&(o=p));break;case 4:u=e[i+1],c=e[i+2],l=e[i+3],128===(192&u)&&128===(192&c)&&128===(192&l)&&(p=(15&s)<<18|(63&u)<<12|(63&c)<<6|63&l,p>65535&&p<1114112&&(o=p))}}null===o?(o=65533,a=1):o>65535&&(o-=65536,r.push(o>>>10&1023|55296),o=56320|1023&o),r.push(o),i+=a}return T(r)}function T(e){var t=e.length;if(t<=ee)return String.fromCharCode.apply(String,e);for(var n="",r=0;rr)&&(n=r);for(var i="",s=t;sn)throw new RangeError("Trying to access beyond buffer length")}function B(e,t,n,r,i,s){if(!o.isBuffer(e))throw new TypeError('"buffer" argument must be a Buffer instance');if(t>i||te.length)throw new RangeError("Index out of range")}function I(e,t,n,r){t<0&&(t=65535+t+1);for(var i=0,s=Math.min(e.length-n,2);i>>8*(r?i:1-i)}function j(e,t,n,r){t<0&&(t=4294967295+t+1);for(var i=0,s=Math.min(e.length-n,4);i>>8*(r?i:3-i)&255}function M(e,t,n,r,i,s){if(n+r>e.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("Index out of range")}function D(e,t,n,r,i){return i||M(e,t,n,4,3.4028234663852886e38,-3.4028234663852886e38),Z.write(e,t,n,r,23,4),n+4}function V(e,t,n,r,i){return i||M(e,t,n,8,1.7976931348623157e308,-1.7976931348623157e308),Z.write(e,t,n,r,52,8),n+8}function U(e){if(e=q(e).replace(te,""),e.length<2)return"";for(;e.length%4!==0;)e+="=";return e}function q(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}function W(e){return e<16?"0"+e.toString(16):e.toString(16)}function z(e,t){t=t||1/0;for(var n,r=e.length,i=null,s=[],o=0;o55295&&n<57344){if(!i){if(n>56319){(t-=3)>-1&&s.push(239,191,189);continue}if(o+1===r){(t-=3)>-1&&s.push(239,191,189);continue}i=n;continue}if(n<56320){(t-=3)>-1&&s.push(239,191,189),i=n;continue}n=(i-55296<<10|n-56320)+65536}else i&&(t-=3)>-1&&s.push(239,191,189);if(i=null,n<128){if((t-=1)<0)break;s.push(n)}else if(n<2048){if((t-=2)<0)break;s.push(n>>6|192,63&n|128)}else if(n<65536){if((t-=3)<0)break;s.push(n>>12|224,n>>6&63|128,63&n|128)}else{if(!(n<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;s.push(n>>18|240,n>>12&63|128,n>>6&63|128,63&n|128)}}return s}function Y(e){for(var t=[],n=0;n>8,i=n%256,s.push(i),s.push(r);return s}function J(e){return X.toByteArray(U(e))}function H(e,t,n,r){for(var i=0;i=t.length||i>=e.length);++i)t[i+n]=e[i];return i}function Q(e){return e!==e}var X=e("base64-js"),Z=e("ieee754"),K=e("isarray");n.Buffer=o,n.SlowBuffer=m,n.INSPECT_MAX_BYTES=50,o.TYPED_ARRAY_SUPPORT=void 0!==t.TYPED_ARRAY_SUPPORT?t.TYPED_ARRAY_SUPPORT:r(),n.kMaxLength=i(),o.poolSize=8192,o._augment=function(e){return e.__proto__=o.prototype,e},o.from=function(e,t,n){return a(null,e,t,n)},o.TYPED_ARRAY_SUPPORT&&(o.prototype.__proto__=Uint8Array.prototype,o.__proto__=Uint8Array,"undefined"!=typeof Symbol&&Symbol.species&&o[Symbol.species]===o&&Object.defineProperty(o,Symbol.species,{value:null,configurable:!0})),o.alloc=function(e,t,n){return c(null,e,t,n)},o.allocUnsafe=function(e){return l(null,e)},o.allocUnsafeSlow=function(e){return l(null,e)},o.isBuffer=function(e){return!(null==e||!e._isBuffer)},o.compare=function(e,t){if(!o.isBuffer(e)||!o.isBuffer(t))throw new TypeError("Arguments must be Buffers");if(e===t)return 0;for(var n=e.length,r=t.length,i=0,s=Math.min(n,r);i0&&(e=this.toString("hex",0,t).match(/.{2}/g).join(" "),this.length>t&&(e+=" ... ")),""},o.prototype.compare=function(e,t,n,r,i){if(!o.isBuffer(e))throw new TypeError("Argument must be a Buffer");if(void 0===t&&(t=0),void 0===n&&(n=e?e.length:0),void 0===r&&(r=0),void 0===i&&(i=this.length),t<0||n>e.length||r<0||i>this.length)throw new RangeError("out of range index");if(r>=i&&t>=n)return 0;if(r>=i)return-1;if(t>=n)return 1;if(t>>>=0,n>>>=0,r>>>=0,i>>>=0,this===e)return 0;for(var s=i-r,a=n-t,u=Math.min(s,a),c=this.slice(r,i),l=e.slice(t,n),p=0;pi)&&(n=i),e.length>0&&(n<0||t<0)||t>this.length)throw new RangeError("Attempt to write outside buffer bounds");r||(r="utf8");for(var s=!1;;)switch(r){case"hex":return E(this,e,t,n);case"utf8":case"utf-8":return S(this,e,t,n);case"ascii":return k(this,e,t,n);case"latin1":case"binary":return A(this,e,t,n);case"base64":return _(this,e,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return C(this,e,t,n);default:if(s)throw new TypeError("Unknown encoding: "+r);r=(""+r).toLowerCase(),s=!0}},o.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var ee=4096;o.prototype.slice=function(e,t){var n=this.length;e=~~e,t=void 0===t?n:~~t,e<0?(e+=n,e<0&&(e=0)):e>n&&(e=n),t<0?(t+=n,t<0&&(t=0)):t>n&&(t=n),t0&&(i*=256);)r+=this[e+--t]*i;return r},o.prototype.readUInt8=function(e,t){return t||$(e,1,this.length),this[e]},o.prototype.readUInt16LE=function(e,t){return t||$(e,2,this.length),this[e]|this[e+1]<<8},o.prototype.readUInt16BE=function(e,t){return t||$(e,2,this.length),this[e]<<8|this[e+1]},o.prototype.readUInt32LE=function(e,t){return t||$(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},o.prototype.readUInt32BE=function(e,t){return t||$(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},o.prototype.readIntLE=function(e,t,n){e|=0,t|=0,n||$(e,t,this.length);for(var r=this[e],i=1,s=0;++s=i&&(r-=Math.pow(2,8*t)),r},o.prototype.readIntBE=function(e,t,n){e|=0,t|=0,n||$(e,t,this.length);for(var r=t,i=1,s=this[e+--r];r>0&&(i*=256);)s+=this[e+--r]*i;return i*=128,s>=i&&(s-=Math.pow(2,8*t)),s},o.prototype.readInt8=function(e,t){return t||$(e,1,this.length),128&this[e]?(255-this[e]+1)*-1:this[e]},o.prototype.readInt16LE=function(e,t){t||$(e,2,this.length);var n=this[e]|this[e+1]<<8;return 32768&n?4294901760|n:n},o.prototype.readInt16BE=function(e,t){t||$(e,2,this.length);var n=this[e+1]|this[e]<<8;return 32768&n?4294901760|n:n},o.prototype.readInt32LE=function(e,t){return t||$(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},o.prototype.readInt32BE=function(e,t){return t||$(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},o.prototype.readFloatLE=function(e,t){return t||$(e,4,this.length),Z.read(this,e,!0,23,4)},o.prototype.readFloatBE=function(e,t){return t||$(e,4,this.length),Z.read(this,e,!1,23,4)},o.prototype.readDoubleLE=function(e,t){return t||$(e,8,this.length),Z.read(this,e,!0,52,8)},o.prototype.readDoubleBE=function(e,t){return t||$(e,8,this.length),Z.read(this,e,!1,52,8)},o.prototype.writeUIntLE=function(e,t,n,r){if(e=+e,t|=0,n|=0,!r){B(this,e,t,n,Math.pow(2,8*n)-1,0)}var i=1,s=0;for(this[t]=255&e;++s=0&&(s*=256);)this[t+i]=e/s&255;return t+n},o.prototype.writeUInt8=function(e,t,n){return e=+e,t|=0,n||B(this,e,t,1,255,0),o.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),this[t]=255&e,t+1},o.prototype.writeUInt16LE=function(e,t,n){return e=+e,t|=0,n||B(this,e,t,2,65535,0),o.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):I(this,e,t,!0),t+2},o.prototype.writeUInt16BE=function(e,t,n){return e=+e,t|=0,n||B(this,e,t,2,65535,0),o.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):I(this,e,t,!1),t+2},o.prototype.writeUInt32LE=function(e,t,n){return e=+e,t|=0,n||B(this,e,t,4,4294967295,0),o.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e):j(this,e,t,!0),t+4},o.prototype.writeUInt32BE=function(e,t,n){return e=+e,t|=0,n||B(this,e,t,4,4294967295,0),o.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):j(this,e,t,!1),t+4},o.prototype.writeIntLE=function(e,t,n,r){if(e=+e,t|=0,!r){var i=Math.pow(2,8*n-1);B(this,e,t,n,i-1,-i)}var s=0,o=1,a=0;for(this[t]=255&e;++s>0)-a&255;return t+n},o.prototype.writeIntBE=function(e,t,n,r){if(e=+e,t|=0,!r){var i=Math.pow(2,8*n-1);B(this,e,t,n,i-1,-i)}var s=n-1,o=1,a=0;for(this[t+s]=255&e;--s>=0&&(o*=256);)e<0&&0===a&&0!==this[t+s+1]&&(a=1),this[t+s]=(e/o>>0)-a&255;return t+n},o.prototype.writeInt8=function(e,t,n){return e=+e,t|=0,n||B(this,e,t,1,127,-128),o.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),e<0&&(e=255+e+1),this[t]=255&e,t+1},o.prototype.writeInt16LE=function(e,t,n){return e=+e,t|=0,n||B(this,e,t,2,32767,-32768),o.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):I(this,e,t,!0),t+2},o.prototype.writeInt16BE=function(e,t,n){return e=+e,t|=0,n||B(this,e,t,2,32767,-32768),o.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):I(this,e,t,!1),t+2},o.prototype.writeInt32LE=function(e,t,n){return e=+e,t|=0,n||B(this,e,t,4,2147483647,-2147483648),o.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):j(this,e,t,!0),t+4},o.prototype.writeInt32BE=function(e,t,n){return e=+e,t|=0,n||B(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),o.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):j(this,e,t,!1),t+4},o.prototype.writeFloatLE=function(e,t,n){return D(this,e,t,!0,n)},o.prototype.writeFloatBE=function(e,t,n){return D(this,e,t,!1,n)},o.prototype.writeDoubleLE=function(e,t,n){return V(this,e,t,!0,n)},o.prototype.writeDoubleBE=function(e,t,n){return V(this,e,t,!1,n)},o.prototype.copy=function(e,t,n,r){if(n||(n=0),r||0===r||(r=this.length),t>=e.length&&(t=e.length),t||(t=0),r>0&&r=this.length)throw new RangeError("sourceStart out of bounds");if(r<0)throw new RangeError("sourceEnd out of bounds");r>this.length&&(r=this.length),e.length-t=0;--i)e[i+t]=this[i+n];else if(s<1e3||!o.TYPED_ARRAY_SUPPORT)for(i=0;i>>=0,n=void 0===n?this.length:n>>>0,e||(e=0);var s;if("number"==typeof e)for(s=t;s0)throw new Error("Invalid string. Length must be a multiple of 4");return"="===e[t-2]?2:"="===e[t-1]?1:0}function i(e){return 3*e.length/4-r(e)}function s(e){var t,n,i,s,o,a,u=e.length;o=r(e),a=new p(3*u/4-o),i=o>0?u-4:u;var c=0;for(t=0,n=0;t>16&255,a[c++]=s>>8&255,a[c++]=255&s;return 2===o?(s=l[e.charCodeAt(t)]<<2|l[e.charCodeAt(t+1)]>>4,a[c++]=255&s):1===o&&(s=l[e.charCodeAt(t)]<<10|l[e.charCodeAt(t+1)]<<4|l[e.charCodeAt(t+2)]>>2,a[c++]=s>>8&255,a[c++]=255&s),a}function o(e){return c[e>>18&63]+c[e>>12&63]+c[e>>6&63]+c[63&e]}function a(e,t,n){for(var r,i=[],s=t;sl?l:u+o));return 1===r?(t=e[n-1],i+=c[t>>2],i+=c[t<<4&63],i+="=="):2===r&&(t=(e[n-2]<<8)+e[n-1],i+=c[t>>10],i+=c[t>>4&63],i+=c[t<<2&63],i+="="),s.push(i),s.join("")}n.byteLength=i,n.toByteArray=s,n.fromByteArray=u;for(var c=[],l=[],p="undefined"!=typeof Uint8Array?Uint8Array:Array,h="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",f=0,d=h.length;f>1,l=-7,p=n?i-1:0,h=n?-1:1,f=e[t+p];for(p+=h,s=f&(1<<-l)-1,f>>=-l,l+=a;l>0;s=256*s+e[t+p],p+=h,l-=8);for(o=s&(1<<-l)-1,s>>=-l,l+=r;l>0;o=256*o+e[t+p],p+=h,l-=8);if(0===s)s=1-c;else{if(s===u)return o?NaN:(f?-1:1)*(1/0);o+=Math.pow(2,r),s-=c}return(f?-1:1)*o*Math.pow(2,s-r)},n.write=function(e,t,n,r,i,s){var o,a,u,c=8*s-i-1,l=(1<>1,h=23===i?Math.pow(2,-24)-Math.pow(2,-77):0,f=r?0:s-1,d=r?1:-1,y=t<0||0===t&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(a=isNaN(t)?1:0,o=l):(o=Math.floor(Math.log(t)/Math.LN2),t*(u=Math.pow(2,-o))<1&&(o--,u*=2),t+=o+p>=1?h/u:h*Math.pow(2,1-p),t*u>=2&&(o++,u/=2),o+p>=l?(a=0,o=l):o+p>=1?(a=(t*u-1)*Math.pow(2,i),o+=p):(a=t*Math.pow(2,p-1)*Math.pow(2,i),o=0));i>=8;e[n+f]=255&a,f+=d,a/=256,i-=8);for(o=o<0;e[n+f]=255&o,f+=d,o/=256,c-=8);e[n+f-d]|=128*y}},{}],5:[function(e,t,n){var r={}.toString;t.exports=Array.isArray||function(e){return"[object Array]"==r.call(e)}},{}],6:[function(e,t,n){(function(e){function t(e,t){for(var n=0,r=e.length-1;r>=0;r--){var i=e[r];"."===i?e.splice(r,1):".."===i?(e.splice(r,1),n++):n&&(e.splice(r,1),n--)}if(t)for(;n--;n)e.unshift("..");return e}function r(e,t){if(e.filter)return e.filter(t);for(var n=[],r=0;r=-1&&!i;s--){var o=s>=0?arguments[s]:e.cwd();if("string"!=typeof o)throw new TypeError("Arguments to path.resolve must be strings");o&&(n=o+"/"+n,i="/"===o.charAt(0))}return n=t(r(n.split("/"),function(e){return!!e}),!i).join("/"),(i?"/":"")+n||"."},n.normalize=function(e){var i=n.isAbsolute(e),s="/"===o(e,-1);return e=t(r(e.split("/"),function(e){return!!e}),!i).join("/"),e||i||(e="."),e&&s&&(e+="/"),(i?"/":"")+e},n.isAbsolute=function(e){return"/"===e.charAt(0)},n.join=function(){var e=Array.prototype.slice.call(arguments,0);return n.normalize(r(e,function(e,t){if("string"!=typeof e)throw new TypeError("Arguments to path.join must be strings");return e}).join("/"))},n.relative=function(e,t){function r(e){for(var t=0;t=0&&""===e[n];n--);return t>n?[]:e.slice(t,n-t+1)}e=n.resolve(e).substr(1),t=n.resolve(t).substr(1);for(var i=r(e.split("/")),s=r(t.split("/")),o=Math.min(i.length,s.length),a=o,u=0;u1)for(var n=1;n]*>)(.*)/i,/(.*)(<\/script>)(.*)/i],o=0,a=!0;t=t.split("\n");for(var u=0;u0){if(!a(e).isAsync)return t(e);delete e.async}return e.type="ReturnStatement",e.$mapped=!0,void(e.argument={type:"CallExpression",callee:_(i,[n]).$error,arguments:[e.argument]})}return a(e).isFunction?(r++,t(e),void r--):void t(e)}if(r>0){if(!a(e).isAsync)return t(e);delete e.async}
-return e.$mapped=!0,void(a(e.argument).isUnaryExpression&&"void"===e.argument.operator?e.argument=e.argument.argument:e.argument={type:"CallExpression",callee:_(i,[n]).$return,arguments:e.argument?[e.argument]:[]})},t)}function N(e,t){return Array.isArray(e)?e.map(function(e){return N(e,t)}):(m.treeWalker(e,function(e,t,n){if(t(),"ConditionalExpression"===e.type&&(c(e.alternate)||c(e.consequent))){f(S("condOp"));s(e,P(m.part("if ($0) return $1 ; return $2",[e.test,e.consequent,e.alternate]).body))}},t),e)}function $(e,t){return Array.isArray(e)?e.map(function(e){return $(e,t)}):(m.treeWalker(e,function(e,t,n){if(t(),"LogicalExpression"===e.type&&c(e.right)){var r,i=f(S("logical"+("&&"===e.operator?"And":"Or")));if("||"===e.operator)r="var $0; if (!($0 = $1)) {$0 = $2} return $0";else{if("&&"!==e.operator)throw new Error(b(e)+"Illegal logical operator: "+e.operator);r="var $0; if ($0 = $1) {$0 = $2} return $0"}s(e,P(m.part(r,[i,e.left,e.right]).body))}},t),e)}function B(e,t,n){if("SwitchCase"!==e.type&&a(e).isBlockStatement)for(var r=0;r0&&a(e).isAsync)return delete e.async,e.argument={type:"CallExpression",callee:"ThrowStatement"===e.type?ge.error:ge.return,arguments:e.argument?[e.argument]:[]},void(e.type="ReturnStatement");n(e)})}function ee(e,t){if(n.noRuntime)throw new Error("Nodent: 'noRuntime' option only compatible with -promise and -engine modes");return m.part("{ return (function*($return,$error){ $:body }).$asyncspawn(Promise,this) }",{return:ge.return,error:ge.error,asyncspawn:ge.asyncspawn,body:K(e).concat(t?[{type:"ReturnStatement",argument:ge.return}]:[])}).body[0]}function te(e){e.$asyncgetwarninig||(e.$asyncgetwarninig=!0,y(b(e)+"'async get "+r(e)+"(){...}' is non-standard. See https://github.com/MatAtBread/nodent#differences-from-the-es7-specification"))}function ne(e,t){function r(e,t){m.treeWalker(e,function(n,r,i){n!==e&&a(n).isFunction||(a(n).isAwait?t?(n.$hidden=!0,r()):(delete n.operator,n.delegate=!1,n.type="YieldExpression",r()):r())})}function o(e){var t=n.promises;n.promises=!0,C(e,!0),n.promises=t}function u(e){return"BlockStatement"!==e.body.type&&(e.body={type:"BlockStatement",body:[{type:"ReturnStatement",argument:e.body}]}),e}function c(e,n){n.$asyncexitwarninig||(n.$asyncexitwarninig=!0,y(b(e)+"'async "+{ReturnStatement:"return",ThrowStatement:"throw"}[e.type]+"' not possible in "+(t?"engine":"generator")+" mode. Using Promises for function at "+b(n)))}m.treeWalker(e,function(e,n,i){n();var l,p,h;if(a(e).isAsync&&a(e).isFunction){var f;(f=w(i[0].parent))&&a(f).isAsync&&"get"===i[0].parent.kind&&te(i[0].parent.key),(p=Q(e.body))?(c(p,e.body),o(e)):t?"get"!==i[0].parent.kind&&r(e,!0):(l=e,delete l.async,h=E(l),r(l,!1),l=u(l),l.body=ee(l.body.body,p),h&&V(l.body.body,[ve]),l.id&&"ExpressionStatement"===i[0].parent.type?(l.type="FunctionDeclaration",i[1].replace(l)):i[0].replace(l))}else(l=w(e))&&a(l).isAsync&&((p=Q(l))?(c(p,l),o(e)):t&&"get"!==e.kind||(t?o(e):(e.async=!1,h=E(l),r(l,!1),s(l,u(l)),l.body=ee(l.body.body,p)),h&&V(l.body.body,[ve])))});var l=i(n);return n.engine=!1,n.generators=!1,le(e),ae(e),D(e,l.engine),$(e),N(e),W(e,[q,J,I,j,B]),z(e,"warn"),n.engine=l.engine,n.generators=l.generators,e}function re(e,t,n){var r=[];return m.treeWalker(e,function(i,s,o){return i===e?s():t(i,o)?void r.push([].concat(o)):void(n||a(i).isScope||s())}),r}function ie(e,t){var n=[],r={};if(e=e.filter(function(e){return"ExportNamedDeclaration"!==e[0].parent.type}),e.length){var s={};e.forEach(function(e){function t(e){e in s?r[e]=o.declarations[u]:s[e]=o.declarations[u]}for(var n=e[0],o=n.self,a=(o.kind,[]),u=0;u1?{type:"SequenceExpression",expressions:a}:a[0];"For"!==n.parent.type.slice(0,3)&&(p={type:"ExpressionStatement",expression:p}),n.replace(p)}});var o=Object.keys(s);o.length&&(o=o.map(function(e){return{type:"VariableDeclarator",id:f(e),loc:s[e].loc,start:s[e].start,end:s[e].end}}),n[0]&&"VariableDeclaration"===n[0].type?n[0].declarations=n[0].declarations.concat(o):n.unshift({type:"VariableDeclaration",kind:t,declarations:o}))}return{decls:n,duplicates:r}}function se(e){if(!e)return[];if(Array.isArray(e))return e.reduce(function(e,t){return e.concat(se(t.id))},[]);switch(e.type){case"Identifier":return[e.name];case"ArrayPattern":return e.elements.reduce(function(e,t){return e.concat(se(t))},[]);case"ObjectPattern":return e.properties.reduce(function(e,t){return e.concat(se(t))},[]);case"ObjectProperty":case"Property":return se(e.value);case"RestElement":case"RestProperty":return se(e.argument)}}function oe(e){function t(e){y(b(e)+"Possible assignment to 'const "+r(e)+"'")}function n(e){switch(e.type){case"Identifier":"const"===i[e.name]&&t(e);break;case"ArrayPattern":e.elements.forEach(function(e){"const"===i[e.name]&&t(e)});break;case"ObjectPattern":e.properties.forEach(function(e){"const"===i[e.key.name]&&t(e)})}}var i={};m.treeWalker(e,function(e,t,r){var s=a(e).isBlockStatement;if(s){i=Object.create(i);for(var o=0;o=0){var r=n[0];return("left"!=r.field||"ForInStatement"!==r.parent.type&&"ForOfStatement"!==r.parent.type)&&("init"!=r.field||"ForStatement"!==r.parent.type||"const"!==t.kind&&"let"!==t.kind)}}}function n(e,t){return!("FunctionDeclaration"!==e.type||!e.id)&&(a(e).isAsync||!e.$continuation)}oe(e);var i=!1;return m.treeWalker(e,function(e,s,o){var u=i;if(i=i||he(e),a(e).isBlockStatement){if(c(e)){var l,p,h,d,m,g=!o[0].parent||a(o[0].parent).isScope;if(g){p=re(e,t(["const"]),!1);var v={},x={};p.forEach(function(e){e[0].self.declarations.forEach(function(e){se(e.id).forEach(function(t){v[t]||x[t]?(delete v[t],x[t]=e):v[t]=e})})}),p.forEach(function(e){for(var t=0;t=0&&"ReturnStatement"===r[1].self.type){var s=e.$thisCallName,o=i(ye[s].def.body.body);ye[s].$inlined=!0,a(r[1].self).isJump||o.push({type:"ReturnStatement"}),r[1].replace(o)}});var n=Object.keys(ye).map(function(e){return ye[e].$inlined&&ye[e].def});m.treeWalker(e,function(e,t,r){t(),n.indexOf(e)>=0&&r[0].remove()})}if("Program"!==e.type&&"module"!==e.sourceType||!u(e,function(e){return a(e).isES6},!0)){var r=he(e);!function(e){m.treeWalker(e,function(e,t,n){if("Program"===e.type||"FunctionDeclaration"===e.type||"FunctionExpression"===e.type){var i=r;if(r=r||he(e)){t();var s="Program"===e.type?e:e.body,o=re(s,function(e,t){if("FunctionDeclaration"===e.type)return t[0].parent!==s});o=o.map(function(e){return e[0].remove()}),[].push.apply(s.body,o)}else t();r=i}else t()})}(e)}return m.treeWalker(e,function(e,t,n){t(),Object.keys(e).filter(function(e){return"$"===e[0]}).forEach(function(t){delete e[t]})}),e}var ye={},me=1,ge={};Object.keys(n).filter(function(e){return"$"===e[0]}).forEach(function(e){ge[e.slice(1)]=f(n[e])});var ve=m.part("var $0 = arguments",[ge.arguments]).body[0];return n.engine?(e.ast=ce(e.ast,!0),e.ast=ne(e.ast,n.engine),e.ast=pe(e.ast),de(e.ast)):n.generators?(e.ast=ce(e.ast),e.ast=ne(e.ast),e.ast=pe(e.ast),de(e.ast)):(e.ast=ce(e.ast),C(e.ast)),n.babelTree&&m.treeWalker(e.ast,function(e,t,n){t(),"Literal"===e.type&&s(e,x(e.value))}),e}var m=e("./parser"),g=e("./output"),v={start:!0,end:!0,loc:!0,range:!0},b={getScope:function(){return"FunctionDeclaration"===this.node.type||"FunctionExpression"===this.node.type||"Function"===this.node.type||"ObjectMethod"===this.node.type||"ClassMethod"===this.node.type||"ArrowFunctionExpression"===this.node.type&&"BlockStatement"===this.node.body.type?this.node.body.body:"Program"===this.node.type?this.node.body:null},isScope:function(){return"FunctionDeclaration"===this.node.type||"FunctionExpression"===this.node.type||"Function"===this.node.type||"Program"===this.node.type||"ObjectMethod"===this.node.type||"ClassMethod"===this.node.type||"ArrowFunctionExpression"===this.node.type&&"BlockStatement"===this.node.body.type},isFunction:function(){return"FunctionDeclaration"===this.node.type||"FunctionExpression"===this.node.type||"Function"===this.node.type||"ObjectMethod"===this.node.type||"ClassMethod"===this.node.type||"ArrowFunctionExpression"===this.node.type},isClass:function(){return"ClassDeclaration"===this.node.type||"ClassExpression"===this.node.type},isBlockStatement:function(){return"ClassBody"===this.node.type||"Program"===this.node.type||"BlockStatement"===this.node.type?this.node.body:"SwitchCase"===this.node.type&&this.node.consequent},isExpressionStatement:function(){return"ExpressionStatement"===this.node.type},isLiteral:function(){return"Literal"===this.node.type||"BooleanLiteral"===this.node.type||"RegExpLiteral"===this.node.type||"NumericLiteral"===this.node.type||"StringLiteral"===this.node.type||"NullLiteral"===this.node.type},isDirective:function(){return"ExpressionStatement"===this.node.type&&("StringLiteral"===this.node.expression.type||"Literal"===this.node.expression.type&&"string"==typeof this.node.expression.value)},isUnaryExpression:function(){return"UnaryExpression"===this.node.type},isAwait:function(){return"AwaitExpression"===this.node.type&&!this.node.$hidden},isAsync:function(){return this.node.async},isStatement:function(){return null!==this.node.type.match(/[a-zA-Z]+Declaration/)||null!==this.node.type.match(/[a-zA-Z]+Statement/)},isExpression:function(){return null!==this.node.type.match(/[a-zA-Z]+Expression/)},isLoop:function(){return"ForStatement"===this.node.type||"WhileStatement"===this.node.type||"DoWhileStatement"===this.node.type},isJump:function(){return"ReturnStatement"===this.node.type||"ThrowStatement"===this.node.type||"BreakStatement"===this.node.type||"ContinueStatement"===this.node.type},isES6:function(){switch(this.node.type){case"ExportNamedDeclaration":case"ExportSpecifier":case"ExportDefaultDeclaration":case"ExportAllDeclaration":case"ImportDeclaration":case"ImportSpecifier":case"ImportDefaultSpecifier":case"ImportNamespaceSpecifier":case"ArrowFunctionExpression":case"ForOfStatement":case"YieldExpression":case"Super":case"RestElement":case"RestProperty":case"SpreadElement":case"TemplateLiteral":case"ClassDeclaration":case"ClassExpression":return!0;case"VariableDeclaration":return this.node.kind&&"var"!==this.node.kind;case"FunctionDeclaration":case"FunctionExpression":return!!this.node.generator}}},x={};Object.keys(b).forEach(function(e){Object.defineProperty(x,e,{get:b[e]})}),t.exports={printNode:r,babelLiteralNode:h,asynchronize:function(e,t,n,r){try{return y(e,t,n,r)}catch(t){if(t instanceof SyntaxError){var i=e.origCode.substr(t.pos-t.loc.column);i=i.split("\n")[0],t.message+=" (nodent)\n"+i+"\n"+i.replace(/[\S ]/g,"-").substring(0,t.loc.column)+"^",t.stack=""}throw t}}}},{"./output":10,"./parser":11}],10:[function(e,t,n){"use strict";function r(e){var t=y[e.type]||y[e.type+e.operator]||y[e.type+e.operator+(e.prefix?"prefix":"")];return void 0!==t?t:20}
-function i(e,t,n){var r=this[n||e.type];r?r.call(this,e,t):t.write(e,"/*"+e.type+"?*/ "+t.sourceAt(e.start,e.end))}function s(e,t,n,i){2===i||r(n)0){this.out(e[0],t,e[0].type);for(var r=1,i=e.length;r>":13,"BinaryExpression>>>":13,"BinaryExpression<":12,"BinaryExpression<=":12,"BinaryExpression>":12,"BinaryExpression>=":12,BinaryExpressionin:12,BinaryExpressioninstanceof:12,"BinaryExpression==":11,"BinaryExpression===":11,"BinaryExpression!=":11,"BinaryExpression!==":11,"BinaryExpression&":10,"BinaryExpression^":9,"BinaryExpression|":8,"LogicalExpression&&":7,"LogicalExpression||":6,ConditionalExpression:5,AssignmentPattern:4,AssignmentExpression:4,yield:3,YieldExpression:3,SpreadElement:2,"comma-separated-list":1.5,SequenceExpression:1},m={type:"comma-separated-list"},g={out:i,expr:s,formatParameters:o,Program:function(e,t){var n,r,i=h(t.indent,t.indentLevel),s=t.lineEnd;n=e.body;for(var o=0,a=n.length;o0){t.write(null,s);for(var a=0,u=n.length;a0){this.out(n[0],t,"VariableDeclarator");for(var i=1;i0){for(var n=0;n0)for(var r=0;r "),"ObjectExpression"===e.body.type||"SequenceExpression"===e.body.type?(t.write(null,"("),this.out(e.body,t,e.body.type),t.write(null,")")):this.out(e.body,t,e.body.type)},ThisExpression:function(e,t){t.write(e,"this")},Super:function(e,t){t.write(e,"super")},RestElement:u=function(e,t){t.write(e,"..."),this.out(e.argument,t,e.argument.type)},SpreadElement:u,YieldExpression:function(e,t){t.write(e,e.delegate?"yield*":"yield"),e.argument&&(t.write(null," "),this.expr(t,e,e.argument))},AwaitExpression:function(e,t){t.write(e,"await "),this.expr(t,e,e.argument)},TemplateLiteral:function(e,t){var n,r=e.quasis,i=e.expressions;t.write(e,"`");for(var s=0,o=i.length;s0)for(var n=e.elements,r=n.length,i=0;;){var s=n[i];if(s&&this.expr(t,m,s),i+=1,(i=r)break;t.lineLength()>t.wrapColumn&&t.write(null,t.lineEnd,h(t.indent,t.indentLevel+1))}t.write(null,"]")},ArrayPattern:l,ObjectExpression:function(e,t){var n,r=h(t.indent,t.indentLevel++),i=t.lineEnd,s=r+t.indent;if(t.write(e,"{"),e.properties.length>0){t.write(null,i);for(var o=e.properties,a=o.length,u=0;n=o[u],t.write(null,s),this.out(n,t,"Property"),++ut.wrapColumn&&t.write(null,t.lineEnd,h(t.indent,t.indentLevel+1));t.write(null,i,r,"}")}else t.write(null,"}");t.indentLevel--},Property:function(e,t){e.method||"get"===e.kind||"set"===e.kind?this.MethodDefinition(e,t):(e.shorthand||(e.computed?(t.write(null,"["),this.out(e.key,t,e.key.type),t.write(null,"]")):this.out(e.key,t,e.key.type),t.write(null,": ")),this.expr(t,m,e.value))},ObjectPattern:function(e,t){if(t.write(e,"{"),e.properties.length>0)for(var n=e.properties,r=n.length,i=0;this.out(n[i],t,"Property"),++i0)for(var i=r.length,s=0;s1&&t.write(e," "),this.expr(t,e,e.argument,!0)):(this.expr(t,e,e.argument),t.write(e,e.operator))},UpdateExpression:function(e,t){e.prefix?(t.write(e,e.operator),this.out(e.argument,t,e.argument.type)):(this.out(e.argument,t,e.argument.type),t.write(e,e.operator))},BinaryExpression:c=function(e,t){var n=e.operator;"in"===n&&t.inForInit&&t.write(null,"("),this.expr(t,e,e.left),t.write(e," ",n," "),this.expr(t,e,e.right,"ArrowFunctionExpression"===e.right.type?2:0),"in"===n&&t.inForInit&&t.write(null,")")},LogicalExpression:c,AssignmentExpression:function(e,t){"ObjectPattern"===e.left.type&&t.write(null,"("),this.BinaryExpression(e,t),"ObjectPattern"===e.left.type&&t.write(null,")")},AssignmentPattern:function(e,t){this.expr(t,e,e.left),t.write(e," = "),this.expr(t,e,e.right)},ConditionalExpression:function(e,t){this.expr(t,e,e.test,!0),t.write(e," ? "),this.expr(t,e,e.consequent),t.write(null," : "),this.expr(t,e,e.alternate)},NewExpression:function(e,t){t.write(e,"new "),this.out(e,t,"CallExpression")},CallExpression:function(e,t){this.expr(t,e,e.callee,"ObjectExpression"===e.callee.type?2:0),t.write(e,"(");var n=e.arguments;if(n.length>0)for(var r=n.length,i=0;i=0&&r({self:i,parent:e,field:a[u],index:!0}):c instanceof Object&&i===c&&r({self:i,parent:e,field:a[u]})}})}return n||(n=[{self:e}],n.replace=function(e,t){n[e].replace(t)}),t(e,s,n),e}function s(e,t){var n=[],r={plugins:{asyncawait:{asyncExits:!0,awaitAnywhere:!0}},ecmaVersion:8,allowHashBang:!0,allowReturnOutsideFunction:!0,allowImportExportEverywhere:!0,locations:!0,onComment:n};if(t)for(var s in t)r[s]=t[s];var o=a.parse(e,r);return i(o,function(e,t,r){for(t();n.length&&e.loc&&e.loc.start.line>=n[0].loc.start.line&&e.loc.end.line>=n[0].loc.end.line;)e.$comments=e.$comments||[],e.$comments.push(n.shift())}),o}function o(e,t){function n(e,r){if(Array.isArray(r)&&!Array.isArray(e))throw new Error("Can't substitute an array for a node");return r=r||{},Object.keys(e).forEach(function(i){function s(e){return"function"==typeof e&&(e=e()),r=r.concat(e)}function o(e){return"function"==typeof e&&(e=e()),r[i]=e,r}if(!(e[i]instanceof Object))return r[i]=e[i];if(Array.isArray(e[i]))return r[i]=n(e[i],[]);var a;if(a=Array.isArray(r)?s:o,"Identifier"===e[i].type&&"$"===e[i].name[0])return a(t[e[i].name.slice(1)]);if("LabeledStatement"===e[i].type&&"$"===e[i].label.name){var u=e[i].body.expression;return a(t[u.name||u.value])}return a("LabeledStatement"===e[i].type&&"$$"===e[i].label.name.slice(0,2)?t[e[i].label.name.slice(2)](n(e[i]).body):n(e[i]))}),r}h[e]||(h[e]=s(e,{locations:!1,ranges:!1,onComment:null}));var r=n(h[e]);return{body:r.body,expr:"ExpressionStatement"===r.body[0].type?r.body[0].expression:null}}var a=e("acorn"),u=e("acorn/dist/walk"),c={AwaitExpression:function(e,t,n){n(e.argument,t,"Expression")},SwitchStatement:function(e,t,n){n(e.discriminant,t,"Expression");for(var r=0;r=t}function i(e,t,n){var r=t.input.slice(t.start);return n&&(r=r.replace(p,"$1 $3")),e.test(r)}function s(e,t,n,r){var i=new e.constructor(e.options,e.input,t);if(n)for(var s in n)i[s]=n[s];var o=e,a=i;return["inFunction","inAsyncFunction","inAsync","inGenerator","inModule"].forEach(function(e){e in o&&(a[e]=o[e])}),r&&(i.options.preserveParens=!0),i.nextToken(),i}function o(e,t){var n=function(){};e.extend("initialContext",function(r){return function(){return this.options.ecmaVersion<7&&(n=function(t){e.raise(t.start,"async/await keywords only available when ecmaVersion>=7")}),this.reservedWords=new RegExp(this.reservedWords.toString().replace(/await|async/g,"").replace("|/","/").replace("/|","/").replace("||","|")),this.reservedWordsStrict=new RegExp(this.reservedWordsStrict.toString().replace(/await|async/g,"").replace("|/","/").replace("/|","/").replace("||","|")),this.reservedWordsStrictBind=new RegExp(this.reservedWordsStrictBind.toString().replace(/await|async/g,"").replace("|/","/").replace("/|","/").replace("||","|")),this.inAsyncFunction=t.inAsyncFunction,t.awaitAnywhere&&t.inAsyncFunction&&e.raise(node.start,"The options awaitAnywhere and inAsyncFunction are mutually exclusive"),r.apply(this,arguments)}}),e.extend("shouldParseExportStatement",function(e){return function(){return!("name"!==this.type.label||"async"!==this.value||!i(c,this))||e.apply(this,arguments)}}),e.extend("parseStatement",function(e){return function(n,r){var s=this.start,o=this.startLoc;if("name"===this.type.label)if(i(c,this,!0)){var a=this.inAsyncFunction;try{this.inAsyncFunction=!0,this.next();var l=this.parseStatement(n,r);return l.async=!0,l.start=s,l.loc&&(l.loc.start=o),l.range&&(l.range[0]=s),l}finally{this.inAsyncFunction=a}}else if("object"==typeof t&&t.asyncExits&&i(u,this)){this.next();var l=this.parseStatement(n,r);return l.async=!0,l.start=s,l.loc&&(l.loc.start=o),l.range&&(l.range[0]=s),l}return e.apply(this,arguments)}}),e.extend("parseIdent",function(e){return function(t){var n=e.apply(this,arguments);return this.inAsyncFunction&&"await"===n.name&&0===arguments.length&&this.raise(n.start,"'await' is reserved within async functions"),n}}),e.extend("parseExprAtom",function(e){return function(i){var o,u=this.start,c=this.startLoc,p=e.apply(this,arguments);if("Identifier"===p.type)if("async"!==p.name||r(this,p.end)){if("await"===p.name){var h=this.startNodeAt(p.start,p.loc&&p.loc.start);if(this.inAsyncFunction)return o=this.parseExprSubscripts(),h.operator="await",h.argument=o,h=this.finishNodeAt(h,"AwaitExpression",o.end,o.loc&&o.loc.end),n(h),h;if(this.input.slice(p.end).match(l))return t.awaitAnywhere||"module"!==this.options.sourceType?p:this.raise(p.start,"'await' is reserved within modules");if("object"==typeof t&&t.awaitAnywhere&&(u=this.start,o=s(this,u-4).parseExprSubscripts(),o.end<=u))return o=s(this,u).parseExprSubscripts(),h.operator="await",h.argument=o,h=this.finishNodeAt(h,"AwaitExpression",o.end,o.loc&&o.loc.end),this.pos=o.end,this.end=o.end,this.endLoc=o.endLoc,this.next(),n(h),h;if(!t.awaitAnywhere&&"module"===this.options.sourceType)return this.raise(p.start,"'await' is reserved within modules")}}else{var f=this.inAsyncFunction;try{this.inAsyncFunction=!0;var d=this,y=!1,m={parseFunctionBody:function(e,t){try{var n=y;return y=!0,d.parseFunctionBody.apply(this,arguments)}finally{y=n}},raise:function(){try{return d.raise.apply(this,arguments)}catch(e){throw y?e:a}}};if(o=s(this,this.start,m,!0).parseExpression(),"SequenceExpression"===o.type&&(o=o.expressions[0]),"FunctionExpression"===o.type||"FunctionDeclaration"===o.type||"ArrowFunctionExpression"===o.type)return o=s(this,this.start,m).parseExpression(),"SequenceExpression"===o.type&&(o=o.expressions[0]),o.async=!0,o.start=u,o.loc&&(o.loc.start=c),o.range&&(o.range[0]=u),this.pos=o.end,this.end=o.end,this.endLoc=o.endLoc,this.next(),n(o),o}catch(e){if(e!==a)throw e}finally{this.inAsyncFunction=f}}return p}}),e.extend("finishNodeAt",function(e){return function(t,n,r,i){return t.__asyncValue&&(delete t.__asyncValue,t.value.async=!0),e.apply(this,arguments)}}),e.extend("finishNode",function(e){return function(t,n){return t.__asyncValue&&(delete t.__asyncValue,t.value.async=!0),e.apply(this,arguments)}});e.extend("parsePropertyName",function(e){return function(t){var i=(t.key&&t.key.name,e.apply(this,arguments));return"Identifier"!==i.type||"async"!==i.name||r(this,i.end)||this.input.slice(i.end).match(l)||(h.test(this.input.slice(i.end))?(i=e.apply(this,arguments),t.__asyncValue=!0):(n(t),"set"===t.kind&&this.raise(i.start,"'set (value)' cannot be be async"),i=e.apply(this,arguments),"Identifier"===i.type&&"set"===i.name&&this.raise(i.start,"'set (value)' cannot be be async"),t.__asyncValue=!0)),i}}),e.extend("parseClassMethod",function(e){return function(t,n,r){var i;n.__asyncValue&&("constructor"===n.kind&&this.raise(n.start,"class constructor() cannot be be async"),i=this.inAsyncFunction,this.inAsyncFunction=!0);var s=e.apply(this,arguments);return this.inAsyncFunction=i,s}}),e.extend("parseMethod",function(e){return function(t){var n;this.__currentProperty&&this.__currentProperty.__asyncValue&&(n=this.inAsyncFunction,this.inAsyncFunction=!0);var r=e.apply(this,arguments);return this.inAsyncFunction=n,r}}),e.extend("parsePropertyValue",function(e){return function(t,n,r,i,s,o){var a=this.__currentProperty;this.__currentProperty=t;var u;t.__asyncValue&&(u=this.inAsyncFunction,this.inAsyncFunction=!0);var c=e.apply(this,arguments);return this.inAsyncFunction=u,this.__currentProperty=a,c}})}var a={},u=/^async[\t ]+(return|throw)/,c=/^async[\t ]+function/,l=/^\s*[():;]/,p=/([^\n])\/\*(\*(?!\/)|[^\n*])*\*\/([^\n])/g,h=/\s*(get|set)\s*\(/;t.exports=o},{}],14:[function(e,t,n){function r(e,t){return e.lineStart>=t}function i(e,t,n){var r=t.input.slice(t.start);return n&&(r=r.replace(c,"$1 $3")),e.test(r)}function s(e,t,n){var r=new e.constructor(e.options,e.input,t);if(n)for(var i in n)r[i]=n[i];var s=e,o=r;return["inFunction","inAsync","inGenerator","inModule"].forEach(function(e){e in s&&(o[e]=s[e])}),r.nextToken(),r}function o(e,t){t&&"object"==typeof t||(t={}),e.extend("parse",function(n){return function(){return this.inAsync=t.inAsyncFunction,t.awaitAnywhere&&t.inAsyncFunction&&e.raise(node.start,"The options awaitAnywhere and inAsyncFunction are mutually exclusive"),n.apply(this,arguments)}}),e.extend("parseStatement",function(e){return function(n,r){var s=this.start,o=this.startLoc;if("name"===this.type.label&&t.asyncExits&&i(a,this)){this.next();var u=this.parseStatement(n,r);return u.async=!0,u.start=s,u.loc&&(u.loc.start=o),u.range&&(u.range[0]=s),u}return e.apply(this,arguments)}}),e.extend("parseIdent",function(e){return function(n){return"module"===this.options.sourceType&&this.options.ecmaVersion>=8&&t.awaitAnywhere?e.call(this,!0):e.apply(this,arguments)}}),e.extend("parseExprAtom",function(e){var n={};return function(r){var i,o=this.start,a=(this.startLoc,e.apply(this,arguments));if("Identifier"===a.type&&"await"===a.name&&!this.inAsync&&t.awaitAnywhere){var u=this.startNodeAt(a.start,a.loc&&a.loc.start);o=this.start;var c={raise:function(){try{return pp.raise.apply(this,arguments)}catch(e){throw n}}};try{if(i=s(this,o-4,c).parseExprSubscripts(),i.end<=o)return i=s(this,o,c).parseExprSubscripts(),u.argument=i,u=this.finishNodeAt(u,"AwaitExpression",i.end,i.loc&&i.loc.end),this.pos=i.end,this.end=i.end,this.endLoc=i.endLoc,this.next(),u}catch(e){if(e===n)return a;throw e}}return a}});var n={undefined:!0,get:!0,set:!0,static:!0,async:!0,constructor:!0};e.extend("parsePropertyName",function(e){return function(t){var i=t.key&&t.key.name,s=e.apply(this,arguments);return"get"===this.value&&(t.__maybeStaticAsyncGetter=!0),n[this.value]?s:("Identifier"!==s.type||"async"!==s.name&&"async"!==i||r(this,s.end)||this.input.slice(s.end).match(u)?delete t.__maybeStaticAsyncGetter:"set"===t.kind||"set"===s.name?this.raise(s.start,"'set (value)' cannot be be async"):(this.__isAsyncProp=!0,s=e.apply(this,arguments),"Identifier"===s.type&&"set"===s.name&&this.raise(s.start,"'set (value)' cannot be be async")),s)}}),e.extend("parseClassMethod",function(e){return function(t,n,r){var i=e.apply(this,arguments);return n.__maybeStaticAsyncGetter&&(delete n.__maybeStaticAsyncGetter,n.kind="get"),i}}),e.extend("parseFunctionBody",function(e){return function(t,n){var r=this.inAsync;this.__isAsyncProp&&(t.async=!0,this.inAsync=!0,delete this.__isAsyncProp);var i=e.apply(this,arguments);return this.inAsync=r,i}})}var a=/^async[\t ]+(return|throw)/,u=/^\s*[):;]/,c=/([^\n])\/\*(\*(?!\/)|[^\n*])*\*\/([^\n])/g;t.exports=o},{}],15:[function(e,t,n){!function(e,r){"object"==typeof n&&void 0!==t?r(n):"function"==typeof define&&define.amd?define(["exports"],r):r(e.acorn=e.acorn||{})}(this,function(e){"use strict";function t(e,t){for(var n=65536,r=0;re)return!1;if(n+=t[r+1],n>=e)return!0}}function n(e,n){return e<65?36===e:e<91||(e<97?95===e:e<123||(e<=65535?e>=170&&A.test(String.fromCharCode(e)):n!==!1&&t(e,C)))}function r(e,n){return e<48?36===e:e<58||!(e<65)&&(e<91||(e<97?95===e:e<123||(e<=65535?e>=170&&_.test(String.fromCharCode(e)):n!==!1&&(t(e,C)||t(e,L)))))}function i(e,t){return new P(e,{beforeExpr:!0,binop:t})}function s(e,t){return void 0===t&&(t={}),t.keyword=e,O[e]=new P(e,t)}function o(e){return 10===e||13===e||8232===e||8233===e}function a(e){return"[object Array]"===Object.prototype.toString.call(e)}function u(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function c(e,t){for(var n=1,r=0;;){$.lastIndex=r;var i=$.exec(e);if(!(i&&i.index=2015&&(t.ecmaVersion-=2009),null==t.allowReserved&&(t.allowReserved=t.ecmaVersion<5),a(t.onToken)){var r=t.onToken;t.onToken=function(e){return r.push(e)}}return a(t.onComment)&&(t.onComment=p(t,t.onComment)),t}function p(e,t){return function(n,r,i,s,o,a){var u={type:n?"Block":"Line",value:r,start:i,end:s};e.locations&&(u.loc=new M(this,o,a)),e.ranges&&(u.range=[i,s]),t.push(u)}}function h(e){return new RegExp("^("+e.replace(/ /g,"|")+")$")}function f(e,t,n,r){return e.type=t,e.end=n,this.options.locations&&(e.loc.end=r),this.options.ranges&&(e.range[1]=n),e}function d(e,t,n,r){try{return new RegExp(e,t)}catch(e){if(void 0!==n)throw e instanceof SyntaxError&&r.raise(n,"Error parsing regular expression: "+e.message),e}}function y(e){return e<=65535?String.fromCharCode(e):(e-=65536,String.fromCharCode((e>>10)+55296,(1023&e)+56320))}function m(e,t){return new U(t,e).parse()}function g(e,t,n){var r=new U(n,e,t);return r.nextToken(),r.parseExpression()}function v(e,t){return new U(t,e)}function b(t,n,r){e.parse_dammit=t,e.LooseParser=n,e.pluginsLoose=r}var x={3:"abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile",5:"class enum extends super const export import",6:"enum",strict:"implements interface let package private protected public static yield",strictBind:"eval arguments"},w="break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this",E={5:w,6:w+" const class extends export import super"
-},S="ªµºÀ-ÖØ-öø-ˁˆ-ˑˠ-ˤˬˮͰ-ʹͶͷͺ-ͽͿΆΈ-ΊΌΎ-ΡΣ-ϵϷ-ҁҊ-ԯԱ-Ֆՙա-ևא-תװ-ײؠ-يٮٯٱ-ۓەۥۦۮۯۺ-ۼۿܐܒ-ܯݍ-ޥޱߊ-ߪߴߵߺࠀ-ࠕࠚࠤࠨࡀ-ࡘࢠ-ࢴࢶ-ࢽऄ-हऽॐक़-ॡॱ-ঀঅ-ঌএঐও-নপ-রলশ-হঽৎড়ঢ়য়-ৡৰৱਅ-ਊਏਐਓ-ਨਪ-ਰਲਲ਼ਵਸ਼ਸਹਖ਼-ੜਫ਼ੲ-ੴઅ-ઍએ-ઑઓ-નપ-રલળવ-હઽૐૠૡૹଅ-ଌଏଐଓ-ନପ-ରଲଳଵ-ହଽଡ଼ଢ଼ୟ-ୡୱஃஅ-ஊஎ-ஐஒ-கஙசஜஞடணதந-பம-ஹௐఅ-ఌఎ-ఐఒ-నప-హఽౘ-ౚౠౡಀಅ-ಌಎ-ಐಒ-ನಪ-ಳವ-ಹಽೞೠೡೱೲഅ-ഌഎ-ഐഒ-ഺഽൎൔ-ൖൟ-ൡൺ-ൿඅ-ඖක-නඳ-රලව-ෆก-ะาำเ-ๆກຂຄງຈຊຍດ-ທນ-ຟມ-ຣລວສຫອ-ະາຳຽເ-ໄໆໜ-ໟༀཀ-ཇཉ-ཬྈ-ྌက-ဪဿၐ-ၕၚ-ၝၡၥၦၮ-ၰၵ-ႁႎႠ-ჅჇჍა-ჺჼ-ቈቊ-ቍቐ-ቖቘቚ-ቝበ-ኈኊ-ኍነ-ኰኲ-ኵኸ-ኾዀዂ-ዅወ-ዖዘ-ጐጒ-ጕጘ-ፚᎀ-ᎏᎠ-Ᏽᏸ-ᏽᐁ-ᙬᙯ-ᙿᚁ-ᚚᚠ-ᛪᛮ-ᛸᜀ-ᜌᜎ-ᜑᜠ-ᜱᝀ-ᝑᝠ-ᝬᝮ-ᝰក-ឳៗៜᠠ-ᡷᢀ-ᢨᢪᢰ-ᣵᤀ-ᤞᥐ-ᥭᥰ-ᥴᦀ-ᦫᦰ-ᧉᨀ-ᨖᨠ-ᩔᪧᬅ-ᬳᭅ-ᭋᮃ-ᮠᮮᮯᮺ-ᯥᰀ-ᰣᱍ-ᱏᱚ-ᱽᲀ-ᲈᳩ-ᳬᳮ-ᳱᳵᳶᴀ-ᶿḀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙὛὝὟ-ώᾀ-ᾴᾶ-ᾼιῂ-ῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲ-ῴῶ-ῼⁱⁿₐ-ₜℂℇℊ-ℓℕ℘-ℝℤΩℨK-ℹℼ-ℿⅅ-ⅉⅎⅠ-ↈⰀ-Ⱞⰰ-ⱞⱠ-ⳤⳫ-ⳮⳲⳳⴀ-ⴥⴧⴭⴰ-ⵧⵯⶀ-ⶖⶠ-ⶦⶨ-ⶮⶰ-ⶶⶸ-ⶾⷀ-ⷆⷈ-ⷎⷐ-ⷖⷘ-ⷞ々-〇〡-〩〱-〵〸-〼ぁ-ゖ゛-ゟァ-ヺー-ヿㄅ-ㄭㄱ-ㆎㆠ-ㆺㇰ-ㇿ㐀-䶵一-鿕ꀀ-ꒌꓐ-ꓽꔀ-ꘌꘐ-ꘟꘪꘫꙀ-ꙮꙿ-ꚝꚠ-ꛯꜗ-ꜟꜢ-ꞈꞋ-ꞮꞰ-ꞷꟷ-ꠁꠃ-ꠅꠇ-ꠊꠌ-ꠢꡀ-ꡳꢂ-ꢳꣲ-ꣷꣻꣽꤊ-ꤥꤰ-ꥆꥠ-ꥼꦄ-ꦲꧏꧠ-ꧤꧦ-ꧯꧺ-ꧾꨀ-ꨨꩀ-ꩂꩄ-ꩋꩠ-ꩶꩺꩾ-ꪯꪱꪵꪶꪹ-ꪽꫀꫂꫛ-ꫝꫠ-ꫪꫲ-ꫴꬁ-ꬆꬉ-ꬎꬑ-ꬖꬠ-ꬦꬨ-ꬮꬰ-ꭚꭜ-ꭥꭰ-ꯢ가-힣ힰ-ퟆퟋ-ퟻ豈-舘並-龎ff-stﬓ-ﬗיִײַ-ﬨשׁ-זּטּ-לּמּנּסּףּפּצּ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷻﹰ-ﹴﹶ-ﻼA-Za-zヲ-하-ᅦᅧ-ᅬᅭ-ᅲᅳ-ᅵ",k="·̀-ͯ·҃-֑҇-ׇֽֿׁׂׅׄؐ-ًؚ-٩ٰۖ-ۜ۟-۪ۤۧۨ-ۭ۰-۹ܑܰ-݊ަ-ް߀-߉߫-߳ࠖ-࠙ࠛ-ࠣࠥ-ࠧࠩ-࡙࠭-࡛ࣔ-ࣣ࣡-ःऺ-़ा-ॏ॑-ॗॢॣ०-९ঁ-ঃ়া-ৄেৈো-্ৗৢৣ০-৯ਁ-ਃ਼ਾ-ੂੇੈੋ-੍ੑ੦-ੱੵઁ-ઃ઼ા-ૅે-ૉો-્ૢૣ૦-૯ଁ-ଃ଼ା-ୄେୈୋ-୍ୖୗୢୣ୦-୯ஂா-ூெ-ைொ-்ௗ௦-௯ఀ-ఃా-ౄె-ైొ-్ౕౖౢౣ౦-౯ಁ-ಃ಼ಾ-ೄೆ-ೈೊ-್ೕೖೢೣ೦-೯ഁ-ഃാ-ൄെ-ൈൊ-്ൗൢൣ൦-൯ංඃ්ා-ුූෘ-ෟ෦-෯ෲෳัิ-ฺ็-๎๐-๙ັິ-ູົຼ່-ໍ໐-໙༘༙༠-༩༹༵༷༾༿ཱ-྄྆྇ྍ-ྗྙ-ྼ࿆ါ-ှ၀-၉ၖ-ၙၞ-ၠၢ-ၤၧ-ၭၱ-ၴႂ-ႍႏ-ႝ፝-፟፩-፱ᜒ-᜔ᜲ-᜴ᝒᝓᝲᝳ឴-៓៝០-៩᠋-᠍᠐-᠙ᢩᤠ-ᤫᤰ-᤻᥆-᥏᧐-᧚ᨗ-ᨛᩕ-ᩞ᩠-᩿᩼-᪉᪐-᪙᪰-᪽ᬀ-ᬄ᬴-᭄᭐-᭙᭫-᭳ᮀ-ᮂᮡ-ᮭ᮰-᮹᯦-᯳ᰤ-᰷᱀-᱉᱐-᱙᳐-᳔᳒-᳨᳭ᳲ-᳴᳸᳹᷀-᷵᷻-᷿‿⁀⁔⃐-⃥⃜⃡-⃰⳯-⵿⳱ⷠ-〪ⷿ-゙゚〯꘠-꘩꙯ꙴ-꙽ꚞꚟ꛰꛱ꠂ꠆ꠋꠣ-ꠧꢀꢁꢴ-ꣅ꣐-꣙꣠-꣱꤀-꤉ꤦ-꤭ꥇ-꥓ꦀ-ꦃ꦳-꧀꧐-꧙ꧥ꧰-꧹ꨩ-ꨶꩃꩌꩍ꩐-꩙ꩻ-ꩽꪰꪲ-ꪴꪷꪸꪾ꪿꫁ꫫ-ꫯꫵ꫶ꯣ-ꯪ꯬꯭꯰-꯹ﬞ︀-️︠-︯︳︴﹍-﹏0-9_",A=new RegExp("["+S+"]"),_=new RegExp("["+S+k+"]");S=k=null;var C=[0,11,2,25,2,18,2,1,2,14,3,13,35,122,70,52,268,28,4,48,48,31,17,26,6,37,11,29,3,35,5,7,2,4,43,157,19,35,5,35,5,39,9,51,157,310,10,21,11,7,153,5,3,0,2,43,2,1,4,0,3,22,11,22,10,30,66,18,2,1,11,21,11,25,71,55,7,1,65,0,16,3,2,2,2,26,45,28,4,28,36,7,2,27,28,53,11,21,11,18,14,17,111,72,56,50,14,50,785,52,76,44,33,24,27,35,42,34,4,0,13,47,15,3,22,0,2,0,36,17,2,24,85,6,2,0,2,3,2,14,2,9,8,46,39,7,3,1,3,21,2,6,2,1,2,4,4,0,19,0,13,4,159,52,19,3,54,47,21,1,2,0,185,46,42,3,37,47,21,0,60,42,86,25,391,63,32,0,449,56,264,8,2,36,18,0,50,29,881,921,103,110,18,195,2749,1070,4050,582,8634,568,8,30,114,29,19,47,17,3,32,20,6,18,881,68,12,0,67,12,65,0,32,6124,20,754,9486,1,3071,106,6,12,4,8,8,9,5991,84,2,70,2,1,3,0,3,1,3,3,2,11,2,0,2,6,2,64,2,3,3,7,2,6,2,27,2,3,2,4,2,0,4,6,2,339,3,24,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,7,4149,196,60,67,1213,3,2,26,2,1,2,0,3,0,2,9,2,3,2,0,2,0,7,0,5,0,2,0,2,0,2,2,2,1,2,0,3,0,2,0,2,0,2,0,2,0,2,1,2,0,3,3,2,6,2,3,2,3,2,0,2,9,2,16,6,2,2,4,2,16,4421,42710,42,4148,12,221,3,5761,10591,541],L=[509,0,227,0,150,4,294,9,1368,2,2,1,6,3,41,2,5,0,166,1,1306,2,54,14,32,9,16,3,46,10,54,9,7,2,37,13,2,9,52,0,13,2,49,13,10,2,4,9,83,11,7,0,161,11,6,9,7,3,57,0,2,6,3,1,3,2,10,0,11,1,3,6,4,4,193,17,10,9,87,19,13,9,214,6,3,8,28,1,83,16,16,9,82,12,9,9,84,14,5,9,423,9,838,7,2,7,17,9,57,21,2,13,19882,9,135,4,60,6,26,9,1016,45,17,3,19723,1,5319,4,4,5,9,7,3,6,31,3,149,2,1418,49,513,54,5,49,9,0,15,0,23,4,2,14,1361,6,2,16,3,6,2,1,2,4,2214,6,110,6,6,9,792487,239],P=function(e,t){void 0===t&&(t={}),this.label=e,this.keyword=t.keyword,this.beforeExpr=!!t.beforeExpr,this.startsExpr=!!t.startsExpr,this.isLoop=!!t.isLoop,this.isAssign=!!t.isAssign,this.prefix=!!t.prefix,this.postfix=!!t.postfix,this.binop=t.binop||null,this.updateContext=null},T={beforeExpr:!0},R={startsExpr:!0},O={},F={num:new P("num",R),regexp:new P("regexp",R),string:new P("string",R),name:new P("name",R),eof:new P("eof"),bracketL:new P("[",{beforeExpr:!0,startsExpr:!0}),bracketR:new P("]"),braceL:new P("{",{beforeExpr:!0,startsExpr:!0}),braceR:new P("}"),parenL:new P("(",{beforeExpr:!0,startsExpr:!0}),parenR:new P(")"),comma:new P(",",T),semi:new P(";",T),colon:new P(":",T),dot:new P("."),question:new P("?",T),arrow:new P("=>",T),template:new P("template"),ellipsis:new P("...",T),backQuote:new P("`",R),dollarBraceL:new P("${",{beforeExpr:!0,startsExpr:!0}),eq:new P("=",{beforeExpr:!0,isAssign:!0}),assign:new P("_=",{beforeExpr:!0,isAssign:!0}),incDec:new P("++/--",{prefix:!0,postfix:!0,startsExpr:!0}),prefix:new P("prefix",{beforeExpr:!0,prefix:!0,startsExpr:!0}),logicalOR:i("||",1),logicalAND:i("&&",2),bitwiseOR:i("|",3),bitwiseXOR:i("^",4),bitwiseAND:i("&",5),equality:i("==/!=",6),relational:i(">",7),bitShift:i("<>>",8),plusMin:new P("+/-",{beforeExpr:!0,binop:9,prefix:!0,startsExpr:!0}),modulo:i("%",10),star:i("*",10),slash:i("/",10),starstar:new P("**",{beforeExpr:!0}),_break:s("break"),_case:s("case",T),_catch:s("catch"),_continue:s("continue"),_debugger:s("debugger"),_default:s("default",T),_do:s("do",{isLoop:!0,beforeExpr:!0}),_else:s("else",T),_finally:s("finally"),_for:s("for",{isLoop:!0}),_function:s("function",R),_if:s("if"),_return:s("return",T),_switch:s("switch"),_throw:s("throw",T),_try:s("try"),_var:s("var"),_const:s("const"),_while:s("while",{isLoop:!0}),_with:s("with"),_new:s("new",{beforeExpr:!0,startsExpr:!0}),_this:s("this",R),_super:s("super",R),_class:s("class"),_extends:s("extends",T),_export:s("export"),_import:s("import"),_null:s("null",R),_true:s("true",R),_false:s("false",R),_in:s("in",{beforeExpr:!0,binop:7}),_instanceof:s("instanceof",{beforeExpr:!0,binop:7}),_typeof:s("typeof",{beforeExpr:!0,prefix:!0,startsExpr:!0}),_void:s("void",{beforeExpr:!0,prefix:!0,startsExpr:!0}),_delete:s("delete",{beforeExpr:!0,prefix:!0,startsExpr:!0})},N=/\r\n?|\n|\u2028|\u2029/,$=new RegExp(N.source,"g"),B=/[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/,I=/(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g,j=function(e,t){this.line=e,this.column=t};j.prototype.offset=function(e){return new j(this.line,this.column+e)};var M=function(e,t,n){this.start=t,this.end=n,null!==e.sourceFile&&(this.source=e.sourceFile)},D={ecmaVersion:7,sourceType:"script",onInsertedSemicolon:null,onTrailingComma:null,allowReserved:null,allowReturnOutsideFunction:!1,allowImportExportEverywhere:!1,allowHashBang:!1,locations:!1,onToken:null,onComment:null,ranges:!1,program:null,sourceFile:null,directSourceFile:null,preserveParens:!1,plugins:{}},V={},U=function(e,t,n){this.options=e=l(e),this.sourceFile=e.sourceFile,this.keywords=h(E[e.ecmaVersion>=6?6:5]);var r="";if(!e.allowReserved){for(var i=e.ecmaVersion;!(r=x[i]);i--);"module"==e.sourceType&&(r+=" await")}this.reservedWords=h(r);var s=(r?r+" ":"")+x.strict;this.reservedWordsStrict=h(s),this.reservedWordsStrictBind=h(s+" "+x.strictBind),this.input=String(t),this.containsEsc=!1,this.loadPlugins(e.plugins),n?(this.pos=n,this.lineStart=this.input.lastIndexOf("\n",n-1)+1,this.curLine=this.input.slice(0,this.lineStart).split(N).length):(this.pos=this.lineStart=0,this.curLine=1),this.type=F.eof,this.value=null,this.start=this.end=this.pos,this.startLoc=this.endLoc=this.curPosition(),this.lastTokEndLoc=this.lastTokStartLoc=null,this.lastTokStart=this.lastTokEnd=this.pos,this.context=this.initialContext(),this.exprAllowed=!0,this.strict=this.inModule="module"===e.sourceType,this.potentialArrowAt=-1,this.inFunction=this.inGenerator=this.inAsync=!1,this.yieldPos=this.awaitPos=0,this.labels=[],0===this.pos&&e.allowHashBang&&"#!"===this.input.slice(0,2)&&this.skipLineComment(2)};U.prototype.isKeyword=function(e){return this.keywords.test(e)},U.prototype.isReservedWord=function(e){return this.reservedWords.test(e)},U.prototype.extend=function(e,t){this[e]=t(this[e])},U.prototype.loadPlugins=function(e){var t=this;for(var n in e){var r=V[n];if(!r)throw new Error("Plugin '"+n+"' not found");r(t,e[n])}},U.prototype.parse=function(){var e=this.options.program||this.startNode();return this.nextToken(),this.parseTopLevel(e)};var q=U.prototype;q.isUseStrict=function(e){return this.options.ecmaVersion>=5&&"ExpressionStatement"===e.type&&"Literal"===e.expression.type&&"use strict"===e.expression.raw.slice(1,-1)},q.eat=function(e){return this.type===e&&(this.next(),!0)},q.isContextual=function(e){return this.type===F.name&&this.value===e},q.eatContextual=function(e){return this.value===e&&this.eat(F.name)},q.expectContextual=function(e){this.eatContextual(e)||this.unexpected()},q.canInsertSemicolon=function(){return this.type===F.eof||this.type===F.braceR||N.test(this.input.slice(this.lastTokEnd,this.start))},q.insertSemicolon=function(){if(this.canInsertSemicolon())return this.options.onInsertedSemicolon&&this.options.onInsertedSemicolon(this.lastTokEnd,this.lastTokEndLoc),!0},q.semicolon=function(){this.eat(F.semi)||this.insertSemicolon()||this.unexpected()},q.afterTrailingComma=function(e,t){if(this.type==e)return this.options.onTrailingComma&&this.options.onTrailingComma(this.lastTokStart,this.lastTokStartLoc),t||this.next(),!0},q.expect=function(e){this.eat(e)||this.unexpected()},q.unexpected=function(e){this.raise(null!=e?e:this.start,"Unexpected token")};var W=function(){this.shorthandAssign=0,this.trailingComma=0};q.checkPatternErrors=function(e,t){var n=e&&e.trailingComma;if(!t)return!!n;n&&this.raise(n,"Comma is not permitted after the rest element")},q.checkExpressionErrors=function(e,t){var n=e&&e.shorthandAssign;if(!t)return!!n;n&&this.raise(n,"Shorthand property assignments are valid only in destructuring patterns")},q.checkYieldAwaitInDefaultParams=function(){this.yieldPos&&(!this.awaitPos||this.yieldPos=6&&(e.sourceType=this.options.sourceType),this.finishNode(e,"Program")};var Y={kind:"loop"},G={kind:"switch"};z.isLet=function(){if(this.type!==F.name||this.options.ecmaVersion<6||"let"!=this.value)return!1;I.lastIndex=this.pos;var e=I.exec(this.input),t=this.pos+e[0].length,i=this.input.charCodeAt(t);if(91===i||123==i)return!0;if(n(i,!0)){for(var s=t+1;r(this.input.charCodeAt(s),!0);++s);var o=this.input.slice(t,s);if(!this.isKeyword(o))return!0}return!1},z.isAsyncFunction=function(){if(this.type!==F.name||this.options.ecmaVersion<8||"async"!=this.value)return!1;I.lastIndex=this.pos;var e=I.exec(this.input),t=this.pos+e[0].length;return!(N.test(this.input.slice(this.pos,t))||"function"!==this.input.slice(t,t+8)||t+8!=this.input.length&&r(this.input.charAt(t+8)))},z.parseStatement=function(e,t,n){var r,i=this.type,s=this.startNode();switch(this.isLet()&&(i=F._var,r="let"),i){case F._break:case F._continue:return this.parseBreakContinueStatement(s,i.keyword);case F._debugger:return this.parseDebuggerStatement(s);case F._do:return this.parseDoStatement(s);case F._for:return this.parseForStatement(s);case F._function:return!e&&this.options.ecmaVersion>=6&&this.unexpected(),this.parseFunctionStatement(s,!1);case F._class:return e||this.unexpected(),this.parseClass(s,!0);case F._if:return this.parseIfStatement(s);case F._return:return this.parseReturnStatement(s);case F._switch:return this.parseSwitchStatement(s);case F._throw:return this.parseThrowStatement(s);case F._try:return this.parseTryStatement(s);case F._const:case F._var:return r=r||this.value,e||"var"==r||this.unexpected(),this.parseVarStatement(s,r);case F._while:return this.parseWhileStatement(s);case F._with:return this.parseWithStatement(s);case F.braceL:return this.parseBlock();case F.semi:return this.parseEmptyStatement(s);case F._export:case F._import:return this.options.allowImportExportEverywhere||(t||this.raise(this.start,"'import' and 'export' may only appear at the top level"),this.inModule||this.raise(this.start,"'import' and 'export' may appear only with 'sourceType: module'")),i===F._import?this.parseImport(s):this.parseExport(s,n);default:if(this.isAsyncFunction()&&e)return this.next(),this.parseFunctionStatement(s,!0);var o=this.value,a=this.parseExpression();return i===F.name&&"Identifier"===a.type&&this.eat(F.colon)?this.parseLabeledStatement(s,o,a):this.parseExpressionStatement(s,a)}},z.parseBreakContinueStatement=function(e,t){var n=this,r="break"==t;this.next(),this.eat(F.semi)||this.insertSemicolon()?e.label=null:this.type!==F.name?this.unexpected():(e.label=this.parseIdent(),this.semicolon());for(var i=0;i=6?this.eat(F.semi):this.semicolon(),this.finishNode(e,"DoWhileStatement")},z.parseForStatement=function(e){if(this.next(),this.labels.push(Y),this.expect(F.parenL),this.type===F.semi)return this.parseFor(e,null);var t=this.isLet();if(this.type===F._var||this.type===F._const||t){var n=this.startNode(),r=t?"let":this.value;return this.next(),this.parseVar(n,!0,r),this.finishNode(n,"VariableDeclaration"),!(this.type===F._in||this.options.ecmaVersion>=6&&this.isContextual("of"))||1!==n.declarations.length||"var"!==r&&n.declarations[0].init?this.parseFor(e,n):this.parseForIn(e,n)}var i=new W,s=this.parseExpression(!0,i);return this.type===F._in||this.options.ecmaVersion>=6&&this.isContextual("of")?(this.checkPatternErrors(i,!0),this.toAssignable(s),this.checkLVal(s),this.parseForIn(e,s)):(this.checkExpressionErrors(i,!0),this.parseFor(e,s))},z.parseFunctionStatement=function(e,t){return this.next(),this.parseFunction(e,!0,!1,t)},z.isFunction=function(){return this.type===F._function||this.isAsyncFunction()},z.parseIfStatement=function(e){return this.next(),e.test=this.parseParenExpression(),e.consequent=this.parseStatement(!this.strict&&this.isFunction()),e.alternate=this.eat(F._else)?this.parseStatement(!this.strict&&this.isFunction()):null,this.finishNode(e,"IfStatement")},z.parseReturnStatement=function(e){return this.inFunction||this.options.allowReturnOutsideFunction||this.raise(this.start,"'return' outside of function"),this.next(),this.eat(F.semi)||this.insertSemicolon()?e.argument=null:(e.argument=this.parseExpression(),this.semicolon()),this.finishNode(e,"ReturnStatement")},z.parseSwitchStatement=function(e){var t=this;this.next(),e.discriminant=this.parseParenExpression(),e.cases=[],this.expect(F.braceL),this.labels.push(G);for(var n,r=!1;this.type!=F.braceR;)if(t.type===F._case||t.type===F._default){var i=t.type===F._case;n&&t.finishNode(n,"SwitchCase"),e.cases.push(n=t.startNode()),n.consequent=[],t.next(),i?n.test=t.parseExpression():(r&&t.raiseRecoverable(t.lastTokStart,"Multiple default clauses"),r=!0,n.test=null),t.expect(F.colon)}else n||t.unexpected(),n.consequent.push(t.parseStatement(!0));return n&&this.finishNode(n,"SwitchCase"),this.next(),this.labels.pop(),this.finishNode(e,"SwitchStatement")},z.parseThrowStatement=function(e){return this.next(),N.test(this.input.slice(this.lastTokEnd,this.start))&&this.raise(this.lastTokEnd,"Illegal newline after throw"),e.argument=this.parseExpression(),this.semicolon(),this.finishNode(e,"ThrowStatement")};var J=[];z.parseTryStatement=function(e){if(this.next(),e.block=this.parseBlock(),e.handler=null,this.type===F._catch){var t=this.startNode();this.next(),this.expect(F.parenL),t.param=this.parseBindingAtom(),this.checkLVal(t.param,!0),this.expect(F.parenR),t.body=this.parseBlock(),e.handler=this.finishNode(t,"CatchClause")}return e.finalizer=this.eat(F._finally)?this.parseBlock():null,e.handler||e.finalizer||this.raise(e.start,"Missing catch or finally clause"),this.finishNode(e,"TryStatement")},z.parseVarStatement=function(e,t){return this.next(),this.parseVar(e,!1,t),this.semicolon(),this.finishNode(e,"VariableDeclaration")},z.parseWhileStatement=function(e){return this.next(),e.test=this.parseParenExpression(),this.labels.push(Y),e.body=this.parseStatement(!1),this.labels.pop(),this.finishNode(e,"WhileStatement")},z.parseWithStatement=function(e){return this.strict&&this.raise(this.start,"'with' in strict mode"),this.next(),e.object=this.parseParenExpression(),e.body=this.parseStatement(!1),this.finishNode(e,"WithStatement")},z.parseEmptyStatement=function(e){return this.next(),this.finishNode(e,"EmptyStatement")},z.parseLabeledStatement=function(e,t,n){for(var r=this,i=0;i=0;o--){var a=r.labels[o];if(a.statementStart!=e.start)break;a.statementStart=r.start,a.kind=s}return this.labels.push({name:t,kind:s,statementStart:this.start}),e.body=this.parseStatement(!0),this.labels.pop(),e.label=n,this.finishNode(e,"LabeledStatement")},z.parseExpressionStatement=function(e,t){return e.expression=t,this.semicolon(),this.finishNode(e,"ExpressionStatement")},z.parseBlock=function(e){var t,n=this,r=this.startNode(),i=!0;for(r.body=[],this.expect(F.braceL);!this.eat(F.braceR);){var s=n.parseStatement(!0);r.body.push(s),i&&e&&n.isUseStrict(s)&&(t=n.strict,n.setStrict(n.strict=!0)),i=!1}return t===!1&&this.setStrict(!1),this.finishNode(r,"BlockStatement")},z.parseFor=function(e,t){return e.init=t,this.expect(F.semi),e.test=this.type===F.semi?null:this.parseExpression(),this.expect(F.semi),e.update=this.type===F.parenR?null:this.parseExpression(),this.expect(F.parenR),e.body=this.parseStatement(!1),this.labels.pop(),this.finishNode(e,"ForStatement")},z.parseForIn=function(e,t){var n=this.type===F._in?"ForInStatement":"ForOfStatement";return this.next(),e.left=t,e.right=this.parseExpression(),this.expect(F.parenR),e.body=this.parseStatement(!1),this.labels.pop(),this.finishNode(e,n)},z.parseVar=function(e,t,n){var r=this;for(e.declarations=[],e.kind=n;;){var i=r.startNode();if(r.parseVarId(i),r.eat(F.eq)?i.init=r.parseMaybeAssign(t):"const"!==n||r.type===F._in||r.options.ecmaVersion>=6&&r.isContextual("of")?"Identifier"==i.id.type||t&&(r.type===F._in||r.isContextual("of"))?i.init=null:r.raise(r.lastTokEnd,"Complex binding patterns require an initialization value"):r.unexpected(),e.declarations.push(r.finishNode(i,"VariableDeclarator")),!r.eat(F.comma))break}return e},z.parseVarId=function(e){e.id=this.parseBindingAtom(),this.checkLVal(e.id,!0)},z.parseFunction=function(e,t,n,r){this.initFunction(e),this.options.ecmaVersion>=6&&!r&&(e.generator=this.eat(F.star)),this.options.ecmaVersion>=8&&(e.async=!!r),t&&(e.id=this.parseIdent());var i=this.inGenerator,s=this.inAsync,o=this.yieldPos,a=this.awaitPos;return this.inGenerator=e.generator,this.inAsync=e.async,this.yieldPos=0,this.awaitPos=0,t||this.type!==F.name||(e.id=this.parseIdent()),this.parseFunctionParams(e),this.parseFunctionBody(e,n),this.inGenerator=i,this.inAsync=s,this.yieldPos=o,this.awaitPos=a,this.finishNode(e,t?"FunctionDeclaration":"FunctionExpression")},z.parseFunctionParams=function(e){this.expect(F.parenL),e.params=this.parseBindingList(F.parenR,!1,this.options.ecmaVersion>=8,!0),this.checkYieldAwaitInDefaultParams()},z.parseClass=function(e,t){var n=this;this.next(),this.parseClassId(e,t),this.parseClassSuper(e);var r=this.startNode(),i=!1;for(r.body=[],this.expect(F.braceL);!this.eat(F.braceR);)if(!n.eat(F.semi)){var s=n.startNode(),o=n.eat(F.star),a=!1,u=n.type===F.name&&"static"===n.value;n.parsePropertyName(s),s.static=u&&n.type!==F.parenL,s.static&&(o&&n.unexpected(),o=n.eat(F.star),n.parsePropertyName(s)),n.options.ecmaVersion>=8&&!o&&!s.computed&&"Identifier"===s.key.type&&"async"===s.key.name&&n.type!==F.parenL&&!n.canInsertSemicolon()&&(a=!0,n.parsePropertyName(s)),s.kind="method";var c=!1;if(!s.computed){var l=s.key;o||a||"Identifier"!==l.type||n.type===F.parenL||"get"!==l.name&&"set"!==l.name||(c=!0,s.kind=l.name,l=n.parsePropertyName(s)),!s.static&&("Identifier"===l.type&&"constructor"===l.name||"Literal"===l.type&&"constructor"===l.value)&&(i&&n.raise(l.start,"Duplicate constructor in the same class"),c&&n.raise(l.start,"Constructor can't have get/set modifier"),o&&n.raise(l.start,"Constructor can't be a generator"),a&&n.raise(l.start,"Constructor can't be an async method"),s.kind="constructor",i=!0)}if(n.parseClassMethod(r,s,o,a),c){var p="get"===s.kind?0:1;if(s.value.params.length!==p){var h=s.value.start;"get"===s.kind?n.raiseRecoverable(h,"getter should have no params"):n.raiseRecoverable(h,"setter should have exactly one param")}else"set"===s.kind&&"RestElement"===s.value.params[0].type&&n.raiseRecoverable(s.value.params[0].start,"Setter cannot use rest params")}}return e.body=this.finishNode(r,"ClassBody"),this.finishNode(e,t?"ClassDeclaration":"ClassExpression")},z.parseClassMethod=function(e,t,n,r){t.value=this.parseMethod(n,r),e.body.push(this.finishNode(t,"MethodDefinition"))},z.parseClassId=function(e,t){e.id=this.type===F.name?this.parseIdent():t?this.unexpected():null},z.parseClassSuper=function(e){e.superClass=this.eat(F._extends)?this.parseExprSubscripts():null},z.parseExport=function(e,t){var n=this;if(this.next(),this.eat(F.star))return this.expectContextual("from"),e.source=this.type===F.string?this.parseExprAtom():this.unexpected(),this.semicolon(),this.finishNode(e,"ExportAllDeclaration");if(this.eat(F._default)){this.checkExport(t,"default",this.lastTokStart);var r=this.type==F.parenL,i=this.parseMaybeAssign(),s=!0;return r||"FunctionExpression"!=i.type&&"ClassExpression"!=i.type||(s=!1,i.id&&(i.type="FunctionExpression"==i.type?"FunctionDeclaration":"ClassDeclaration")),e.declaration=i,s&&this.semicolon(),this.finishNode(e,"ExportDefaultDeclaration")}if(this.shouldParseExportStatement())e.declaration=this.parseStatement(!0),"VariableDeclaration"===e.declaration.type?this.checkVariableExport(t,e.declaration.declarations):this.checkExport(t,e.declaration.id.name,e.declaration.id.start),e.specifiers=[],e.source=null;else{if(e.declaration=null,e.specifiers=this.parseExportSpecifiers(t),this.eatContextual("from"))e.source=this.type===F.string?this.parseExprAtom():this.unexpected();else{for(var o=0;o=6&&e)switch(e.type){case"Identifier":this.inAsync&&"await"===e.name&&this.raise(e.start,"Can not use 'await' as identifier inside an async function");break;case"ObjectPattern":case"ArrayPattern":break;case"ObjectExpression":e.type="ObjectPattern";for(var r=0;r=6&&(e.computed||e.method||e.shorthand))){var n,r=e.key;switch(r.type){case"Identifier":n=r.name;break;case"Literal":n=String(r.value);break;default:return}var i=e.kind;if(this.options.ecmaVersion>=6)return void("__proto__"===n&&"init"===i&&(t.proto&&this.raiseRecoverable(r.start,"Redefinition of __proto__ property"),t.proto=!0));n="$"+n;var s=t[n];if(s){var o="init"!==i;(!this.strict&&!o||!s[i])&&o^s.init||this.raiseRecoverable(r.start,"Redefinition of property")}else s=t[n]={init:!1,get:!1,set:!1};s[i]=!0}},Q.parseExpression=function(e,t){var n=this,r=this.start,i=this.startLoc,s=this.parseMaybeAssign(e,t);if(this.type===F.comma){var o=this.startNodeAt(r,i);for(o.expressions=[s];this.eat(F.comma);)o.expressions.push(n.parseMaybeAssign(e,t));return this.finishNode(o,"SequenceExpression")}return s},Q.parseMaybeAssign=function(e,t,n){if(this.inGenerator&&this.isContextual("yield"))return this.parseYield();var r=!1;t||(t=new W,r=!0);var i=this.start,s=this.startLoc;this.type!=F.parenL&&this.type!=F.name||(this.potentialArrowAt=this.start);var o=this.parseMaybeConditional(e,t);if(n&&(o=n.call(this,o,i,s)),this.type.isAssign){this.checkPatternErrors(t,!0),r||W.call(t);var a=this.startNodeAt(i,s);return a.operator=this.value,a.left=this.type===F.eq?this.toAssignable(o):o,t.shorthandAssign=0,this.checkLVal(o),this.next(),a.right=this.parseMaybeAssign(e),this.finishNode(a,"AssignmentExpression")}return r&&this.checkExpressionErrors(t,!0),o},Q.parseMaybeConditional=function(e,t){var n=this.start,r=this.startLoc,i=this.parseExprOps(e,t);if(this.checkExpressionErrors(t))return i;if(this.eat(F.question)){var s=this.startNodeAt(n,r);return s.test=i,s.consequent=this.parseMaybeAssign(),this.expect(F.colon),s.alternate=this.parseMaybeAssign(e),this.finishNode(s,"ConditionalExpression")}return i},Q.parseExprOps=function(e,t){var n=this.start,r=this.startLoc,i=this.parseMaybeUnary(t,!1);return this.checkExpressionErrors(t)?i:this.parseExprOp(i,n,r,-1,e)},Q.parseExprOp=function(e,t,n,r,i){var s=this.type.binop;if(null!=s&&(!i||this.type!==F._in)&&s>r){var o=this.type===F.logicalOR||this.type===F.logicalAND,a=this.value;this.next();var u=this.start,c=this.startLoc,l=this.parseExprOp(this.parseMaybeUnary(null,!1),u,c,s,i),p=this.buildBinary(t,n,e,l,a,o);return this.parseExprOp(p,t,n,r,i)}return e},Q.buildBinary=function(e,t,n,r,i,s){var o=this.startNodeAt(e,t);return o.left=n,o.operator=i,o.right=r,this.finishNode(o,s?"LogicalExpression":"BinaryExpression")},Q.parseMaybeUnary=function(e,t){var n,r=this,i=this.start,s=this.startLoc;if(this.inAsync&&this.isContextual("await"))n=this.parseAwait(e),t=!0;else if(this.type.prefix){var o=this.startNode(),a=this.type===F.incDec;o.operator=this.value,o.prefix=!0,this.next(),o.argument=this.parseMaybeUnary(null,!0),this.checkExpressionErrors(e,!0),a?this.checkLVal(o.argument):this.strict&&"delete"===o.operator&&"Identifier"===o.argument.type?this.raiseRecoverable(o.start,"Deleting local variable in strict mode"):t=!0,
-n=this.finishNode(o,a?"UpdateExpression":"UnaryExpression")}else{if(n=this.parseExprSubscripts(e),this.checkExpressionErrors(e))return n;for(;this.type.postfix&&!this.canInsertSemicolon();){var u=r.startNodeAt(i,s);u.operator=r.value,u.prefix=!1,u.argument=n,r.checkLVal(n),r.next(),n=r.finishNode(u,"UpdateExpression")}}return!t&&this.eat(F.starstar)?this.buildBinary(i,s,n,this.parseMaybeUnary(null,!1),"**",!1):n},Q.parseExprSubscripts=function(e){var t=this.start,n=this.startLoc,r=this.parseExprAtom(e),i="ArrowFunctionExpression"===r.type&&")"!==this.input.slice(this.lastTokStart,this.lastTokEnd);return this.checkExpressionErrors(e)||i?r:this.parseSubscripts(r,t,n)},Q.parseSubscripts=function(e,t,n,r){for(var i=this;;){var s=i.options.ecmaVersion>=8&&"Identifier"===e.type&&"async"===e.name&&!i.canInsertSemicolon();if(i.eat(F.dot)){var o=i.startNodeAt(t,n);o.object=e,o.property=i.parseIdent(!0),o.computed=!1,e=i.finishNode(o,"MemberExpression")}else if(i.eat(F.bracketL)){var a=i.startNodeAt(t,n);a.object=e,a.property=i.parseExpression(),a.computed=!0,i.expect(F.bracketR),e=i.finishNode(a,"MemberExpression")}else if(!r&&i.eat(F.parenL)){var u=new W,c=i.yieldPos,l=i.awaitPos;i.yieldPos=0,i.awaitPos=0;var p=i.parseExprList(F.parenR,i.options.ecmaVersion>=8,!1,u);if(s&&!i.canInsertSemicolon()&&i.eat(F.arrow))return i.checkPatternErrors(u,!0),i.checkYieldAwaitInDefaultParams(),i.yieldPos=c,i.awaitPos=l,i.parseArrowExpression(i.startNodeAt(t,n),p,!0);i.checkExpressionErrors(u,!0),i.yieldPos=c||i.yieldPos,i.awaitPos=l||i.awaitPos;var h=i.startNodeAt(t,n);h.callee=e,h.arguments=p,e=i.finishNode(h,"CallExpression")}else{if(i.type!==F.backQuote)return e;var f=i.startNodeAt(t,n);f.tag=e,f.quasi=i.parseTemplate(),e=i.finishNode(f,"TaggedTemplateExpression")}}},Q.parseExprAtom=function(e){var t,n=this.potentialArrowAt==this.start;switch(this.type){case F._super:this.inFunction||this.raise(this.start,"'super' outside of function or class");case F._this:var r=this.type===F._this?"ThisExpression":"Super";return t=this.startNode(),this.next(),this.finishNode(t,r);case F.name:var i=this.start,s=this.startLoc,o=this.parseIdent(this.type!==F.name);if(this.options.ecmaVersion>=8&&"async"===o.name&&!this.canInsertSemicolon()&&this.eat(F._function))return this.parseFunction(this.startNodeAt(i,s),!1,!1,!0);if(n&&!this.canInsertSemicolon()){if(this.eat(F.arrow))return this.parseArrowExpression(this.startNodeAt(i,s),[o],!1);if(this.options.ecmaVersion>=8&&"async"===o.name&&this.type===F.name)return o=this.parseIdent(),!this.canInsertSemicolon()&&this.eat(F.arrow)||this.unexpected(),this.parseArrowExpression(this.startNodeAt(i,s),[o],!0)}return o;case F.regexp:var a=this.value;return t=this.parseLiteral(a.value),t.regex={pattern:a.pattern,flags:a.flags},t;case F.num:case F.string:return this.parseLiteral(this.value);case F._null:case F._true:case F._false:return t=this.startNode(),t.value=this.type===F._null?null:this.type===F._true,t.raw=this.type.keyword,this.next(),this.finishNode(t,"Literal");case F.parenL:return this.parseParenAndDistinguishExpression(n);case F.bracketL:return t=this.startNode(),this.next(),t.elements=this.parseExprList(F.bracketR,!0,!0,e),this.finishNode(t,"ArrayExpression");case F.braceL:return this.parseObj(!1,e);case F._function:return t=this.startNode(),this.next(),this.parseFunction(t,!1);case F._class:return this.parseClass(this.startNode(),!1);case F._new:return this.parseNew();case F.backQuote:return this.parseTemplate();default:this.unexpected()}},Q.parseLiteral=function(e){var t=this.startNode();return t.value=e,t.raw=this.input.slice(this.start,this.end),this.next(),this.finishNode(t,"Literal")},Q.parseParenExpression=function(){this.expect(F.parenL);var e=this.parseExpression();return this.expect(F.parenR),e},Q.parseParenAndDistinguishExpression=function(e){var t,n=this,r=this.start,i=this.startLoc,s=this.options.ecmaVersion>=8;if(this.options.ecmaVersion>=6){this.next();var o,a,u=this.start,c=this.startLoc,l=[],p=!0,h=!1,f=new W,d=this.yieldPos,y=this.awaitPos;for(this.yieldPos=0,this.awaitPos=0;this.type!==F.parenR;){if(p?p=!1:n.expect(F.comma),s&&n.afterTrailingComma(F.parenR,!0)){h=!0;break}if(n.type===F.ellipsis){o=n.start,l.push(n.parseParenItem(n.parseRest())),n.type===F.comma&&n.raise(n.start,"Comma is not permitted after the rest element");break}n.type!==F.parenL||a||(a=n.start),l.push(n.parseMaybeAssign(!1,f,n.parseParenItem))}var m=this.start,g=this.startLoc;if(this.expect(F.parenR),e&&!this.canInsertSemicolon()&&this.eat(F.arrow))return this.checkPatternErrors(f,!0),this.checkYieldAwaitInDefaultParams(),a&&this.unexpected(a),this.yieldPos=d,this.awaitPos=y,this.parseParenArrowList(r,i,l);l.length&&!h||this.unexpected(this.lastTokStart),o&&this.unexpected(o),this.checkExpressionErrors(f,!0),this.yieldPos=d||this.yieldPos,this.awaitPos=y||this.awaitPos,l.length>1?(t=this.startNodeAt(u,c),t.expressions=l,this.finishNodeAt(t,"SequenceExpression",m,g)):t=l[0]}else t=this.parseParenExpression();if(this.options.preserveParens){var v=this.startNodeAt(r,i);return v.expression=t,this.finishNode(v,"ParenthesizedExpression")}return t},Q.parseParenItem=function(e){return e},Q.parseParenArrowList=function(e,t,n){return this.parseArrowExpression(this.startNodeAt(e,t),n)};var X=[];Q.parseNew=function(){var e=this.startNode(),t=this.parseIdent(!0);if(this.options.ecmaVersion>=6&&this.eat(F.dot))return e.meta=t,e.property=this.parseIdent(!0),"target"!==e.property.name&&this.raiseRecoverable(e.property.start,"The only valid meta property for new is new.target"),this.inFunction||this.raiseRecoverable(e.start,"new.target can only be used in functions"),this.finishNode(e,"MetaProperty");var n=this.start,r=this.startLoc;return e.callee=this.parseSubscripts(this.parseExprAtom(),n,r,!0),this.eat(F.parenL)?e.arguments=this.parseExprList(F.parenR,this.options.ecmaVersion>=8,!1):e.arguments=X,this.finishNode(e,"NewExpression")},Q.parseTemplateElement=function(){var e=this.startNode();return e.value={raw:this.input.slice(this.start,this.end).replace(/\r\n?/g,"\n"),cooked:this.value},this.next(),e.tail=this.type===F.backQuote,this.finishNode(e,"TemplateElement")},Q.parseTemplate=function(){var e=this,t=this.startNode();this.next(),t.expressions=[];var n=this.parseTemplateElement();for(t.quasis=[n];!n.tail;)e.expect(F.dollarBraceL),t.expressions.push(e.parseExpression()),e.expect(F.braceR),t.quasis.push(n=e.parseTemplateElement());return this.next(),this.finishNode(t,"TemplateLiteral")},Q.parseObj=function(e,t){var n=this,r=this.startNode(),i=!0,s={};for(r.properties=[],this.next();!this.eat(F.braceR);){if(i)i=!1;else if(n.expect(F.comma),n.afterTrailingComma(F.braceR))break;var o,a,u,c,l=n.startNode();n.options.ecmaVersion>=6&&(l.method=!1,l.shorthand=!1,(e||t)&&(u=n.start,c=n.startLoc),e||(o=n.eat(F.star))),n.parsePropertyName(l),e||!(n.options.ecmaVersion>=8)||o||l.computed||"Identifier"!==l.key.type||"async"!==l.key.name||n.type===F.parenL||n.type===F.colon||n.canInsertSemicolon()?a=!1:(a=!0,n.parsePropertyName(l,t)),n.parsePropertyValue(l,e,o,a,u,c,t),n.checkPropClash(l,s),r.properties.push(n.finishNode(l,"Property"))}return this.finishNode(r,e?"ObjectPattern":"ObjectExpression")},Q.parsePropertyValue=function(e,t,n,r,i,s,o){if((n||r)&&this.type===F.colon&&this.unexpected(),this.eat(F.colon))e.value=t?this.parseMaybeDefault(this.start,this.startLoc):this.parseMaybeAssign(!1,o),e.kind="init";else if(this.options.ecmaVersion>=6&&this.type===F.parenL)t&&this.unexpected(),e.kind="init",e.method=!0,e.value=this.parseMethod(n,r);else if(this.options.ecmaVersion>=5&&!e.computed&&"Identifier"===e.key.type&&("get"===e.key.name||"set"===e.key.name)&&this.type!=F.comma&&this.type!=F.braceR){(n||r||t)&&this.unexpected(),e.kind=e.key.name,this.parsePropertyName(e),e.value=this.parseMethod(!1);var a="get"===e.kind?0:1;if(e.value.params.length!==a){var u=e.value.start;"get"===e.kind?this.raiseRecoverable(u,"getter should have no params"):this.raiseRecoverable(u,"setter should have exactly one param")}else"set"===e.kind&&"RestElement"===e.value.params[0].type&&this.raiseRecoverable(e.value.params[0].start,"Setter cannot use rest params")}else this.options.ecmaVersion>=6&&!e.computed&&"Identifier"===e.key.type?((this.keywords.test(e.key.name)||(this.strict?this.reservedWordsStrict:this.reservedWords).test(e.key.name)||this.inGenerator&&"yield"==e.key.name||this.inAsync&&"await"==e.key.name)&&this.raiseRecoverable(e.key.start,"'"+e.key.name+"' can not be used as shorthand property"),e.kind="init",t?e.value=this.parseMaybeDefault(i,s,e.key):this.type===F.eq&&o?(o.shorthandAssign||(o.shorthandAssign=this.start),e.value=this.parseMaybeDefault(i,s,e.key)):e.value=e.key,e.shorthand=!0):this.unexpected()},Q.parsePropertyName=function(e){if(this.options.ecmaVersion>=6){if(this.eat(F.bracketL))return e.computed=!0,e.key=this.parseMaybeAssign(),this.expect(F.bracketR),e.key;e.computed=!1}return e.key=this.type===F.num||this.type===F.string?this.parseExprAtom():this.parseIdent(!0)},Q.initFunction=function(e){e.id=null,this.options.ecmaVersion>=6&&(e.generator=!1,e.expression=!1),this.options.ecmaVersion>=8&&(e.async=!1)},Q.parseMethod=function(e,t){var n=this.startNode(),r=this.inGenerator,i=this.inAsync,s=this.yieldPos,o=this.awaitPos;return this.initFunction(n),this.options.ecmaVersion>=6&&(n.generator=e),this.options.ecmaVersion>=8&&(n.async=!!t),this.inGenerator=n.generator,this.inAsync=n.async,this.yieldPos=0,this.awaitPos=0,this.expect(F.parenL),n.params=this.parseBindingList(F.parenR,!1,this.options.ecmaVersion>=8),this.checkYieldAwaitInDefaultParams(),this.parseFunctionBody(n,!1),this.inGenerator=r,this.inAsync=i,this.yieldPos=s,this.awaitPos=o,this.finishNode(n,"FunctionExpression")},Q.parseArrowExpression=function(e,t,n){var r=this.inGenerator,i=this.inAsync,s=this.yieldPos,o=this.awaitPos;return this.initFunction(e),this.options.ecmaVersion>=8&&(e.async=!!n),this.inGenerator=!1,this.inAsync=e.async,this.yieldPos=0,this.awaitPos=0,e.params=this.toAssignableList(t,!0),this.parseFunctionBody(e,!0),this.inGenerator=r,this.inAsync=i,this.yieldPos=s,this.awaitPos=o,this.finishNode(e,"ArrowFunctionExpression")},Q.parseFunctionBody=function(e,t){var n=t&&this.type!==F.braceL;if(n)e.body=this.parseMaybeAssign(),e.expression=!0;else{var r=this.inFunction,i=this.labels;this.inFunction=!0,this.labels=[],e.body=this.parseBlock(!0),e.expression=!1,this.inFunction=r,this.labels=i}var s=!n&&e.body.body.length&&this.isUseStrict(e.body.body[0])?e.body.body[0]:null;if(s&&this.options.ecmaVersion>=7&&!this.isSimpleParamList(e.params)&&this.raiseRecoverable(s.start,"Illegal 'use strict' directive in function with non-simple parameter list"),this.strict||s){var o=this.strict;this.strict=!0,e.id&&this.checkLVal(e.id,!0),this.checkParams(e),this.strict=o}else!t&&this.isSimpleParamList(e.params)||this.checkParams(e)},Q.isSimpleParamList=function(e){for(var t=0;t=6||this.input.slice(this.start,this.end).indexOf("\\")==-1)&&this.raiseRecoverable(this.start,"The keyword '"+this.value+"' is reserved"),this.inGenerator&&"yield"===this.value&&this.raiseRecoverable(this.start,"Can not use 'yield' as identifier inside a generator"),this.inAsync&&"await"===this.value&&this.raiseRecoverable(this.start,"Can not use 'await' as identifier inside an async function"),t.name=this.value):e&&this.type.keyword?t.name=this.type.keyword:this.unexpected(),this.next(),this.finishNode(t,"Identifier")},Q.parseYield=function(){this.yieldPos||(this.yieldPos=this.start);var e=this.startNode();return this.next(),this.type==F.semi||this.canInsertSemicolon()||this.type!=F.star&&!this.type.startsExpr?(e.delegate=!1,e.argument=null):(e.delegate=this.eat(F.star),e.argument=this.parseMaybeAssign()),this.finishNode(e,"YieldExpression")},Q.parseAwait=function(){this.awaitPos||(this.awaitPos=this.start);var e=this.startNode();return this.next(),e.argument=this.parseMaybeUnary(null,!0),this.finishNode(e,"AwaitExpression")};var Z=U.prototype;Z.raise=function(e,t){var n=c(this.input,e);t+=" ("+n.line+":"+n.column+")";var r=new SyntaxError(t);throw r.pos=e,r.loc=n,r.raisedAt=this.pos,r},Z.raiseRecoverable=Z.raise,Z.curPosition=function(){if(this.options.locations)return new j(this.curLine,this.pos-this.lineStart)};var K=function(e,t,n){this.type="",this.start=t,this.end=0,e.options.locations&&(this.loc=new M(e,n)),e.options.directSourceFile&&(this.sourceFile=e.options.directSourceFile),e.options.ranges&&(this.range=[t,0])},ee=U.prototype;ee.startNode=function(){return new K(this,this.start,this.startLoc)},ee.startNodeAt=function(e,t){return new K(this,e,t)},ee.finishNode=function(e,t){return f.call(this,e,t,this.lastTokEnd,this.lastTokEndLoc)},ee.finishNodeAt=function(e,t,n,r){return f.call(this,e,t,n,r)};var te=function(e,t,n,r){this.token=e,this.isExpr=!!t,this.preserveSpace=!!n,this.override=r},ne={b_stat:new te("{",!1),b_expr:new te("{",!0),b_tmpl:new te("${",!0),p_stat:new te("(",!1),p_expr:new te("(",!0),q_tmpl:new te("`",!0,!0,function(e){return e.readTmplToken()}),f_expr:new te("function",!0)},re=U.prototype;re.initialContext=function(){return[ne.b_stat]},re.braceIsBlock=function(e){if(e===F.colon){var t=this.curContext();if(t===ne.b_stat||t===ne.b_expr)return!t.isExpr}return e===F._return?N.test(this.input.slice(this.lastTokEnd,this.start)):e===F._else||e===F.semi||e===F.eof||e===F.parenR||(e==F.braceL?this.curContext()===ne.b_stat:!this.exprAllowed)},re.updateContext=function(e){var t,n=this.type;n.keyword&&e==F.dot?this.exprAllowed=!1:(t=n.updateContext)?t.call(this,e):this.exprAllowed=n.beforeExpr},F.parenR.updateContext=F.braceR.updateContext=function(){if(1==this.context.length)return void(this.exprAllowed=!0);var e=this.context.pop();e===ne.b_stat&&this.curContext()===ne.f_expr?(this.context.pop(),this.exprAllowed=!1):e===ne.b_tmpl?this.exprAllowed=!0:this.exprAllowed=!e.isExpr},F.braceL.updateContext=function(e){this.context.push(this.braceIsBlock(e)?ne.b_stat:ne.b_expr),this.exprAllowed=!0},F.dollarBraceL.updateContext=function(){this.context.push(ne.b_tmpl),this.exprAllowed=!0},F.parenL.updateContext=function(e){var t=e===F._if||e===F._for||e===F._with||e===F._while;this.context.push(t?ne.p_stat:ne.p_expr),this.exprAllowed=!0},F.incDec.updateContext=function(){},F._function.updateContext=function(e){e.beforeExpr&&e!==F.semi&&e!==F._else&&(e!==F.colon&&e!==F.braceL||this.curContext()!==ne.b_stat)&&this.context.push(ne.f_expr),this.exprAllowed=!1},F.backQuote.updateContext=function(){this.curContext()===ne.q_tmpl?this.context.pop():this.context.push(ne.q_tmpl),this.exprAllowed=!1};var ie=function(e){this.type=e.type,this.value=e.value,this.start=e.start,this.end=e.end,e.options.locations&&(this.loc=new M(e,e.startLoc,e.endLoc)),e.options.ranges&&(this.range=[e.start,e.end])},se=U.prototype,oe="object"==typeof Packages&&"[object JavaPackage]"==Object.prototype.toString.call(Packages);se.next=function(){this.options.onToken&&this.options.onToken(new ie(this)),this.lastTokEnd=this.end,this.lastTokStart=this.start,this.lastTokEndLoc=this.endLoc,this.lastTokStartLoc=this.startLoc,this.nextToken()},se.getToken=function(){return this.next(),new ie(this)},"undefined"!=typeof Symbol&&(se[Symbol.iterator]=function(){var e=this;return{next:function(){var t=e.getToken();return{done:t.type===F.eof,value:t}}}}),se.setStrict=function(e){var t=this;if(this.strict=e,this.type===F.num||this.type===F.string){if(this.pos=this.start,this.options.locations)for(;this.pos=this.input.length?this.finishToken(F.eof):e.override?e.override(this):void this.readToken(this.fullCharCodeAtPos())},se.readToken=function(e){return n(e,this.options.ecmaVersion>=6)||92===e?this.readWord():this.getTokenFromCode(e)},se.fullCharCodeAtPos=function(){var e=this.input.charCodeAt(this.pos);return e<=55295||e>=57344?e:(e<<10)+this.input.charCodeAt(this.pos+1)-56613888},se.skipBlockComment=function(){var e=this,t=this.options.onComment&&this.curPosition(),n=this.pos,r=this.input.indexOf("*/",this.pos+=2);if(r===-1&&this.raise(this.pos-2,"Unterminated comment"),this.pos=r+2,this.options.locations){$.lastIndex=n;for(var i;(i=$.exec(this.input))&&i.index8&&t<14||t>=5760&&B.test(String.fromCharCode(t))))break e;++e.pos}}},se.finishToken=function(e,t){this.end=this.pos,this.options.locations&&(this.endLoc=this.curPosition());var n=this.type;this.type=e,this.value=t,this.updateContext(n)},se.readToken_dot=function(){var e=this.input.charCodeAt(this.pos+1);if(e>=48&&e<=57)return this.readNumber(!0);var t=this.input.charCodeAt(this.pos+2);return this.options.ecmaVersion>=6&&46===e&&46===t?(this.pos+=3,this.finishToken(F.ellipsis)):(++this.pos,this.finishToken(F.dot))},se.readToken_slash=function(){var e=this.input.charCodeAt(this.pos+1);return this.exprAllowed?(++this.pos,this.readRegexp()):61===e?this.finishOp(F.assign,2):this.finishOp(F.slash,1)},se.readToken_mult_modulo_exp=function(e){var t=this.input.charCodeAt(this.pos+1),n=1,r=42===e?F.star:F.modulo;return this.options.ecmaVersion>=7&&42===t&&(++n,r=F.starstar,t=this.input.charCodeAt(this.pos+2)),61===t?this.finishOp(F.assign,n+1):this.finishOp(r,n)},se.readToken_pipe_amp=function(e){var t=this.input.charCodeAt(this.pos+1);return t===e?this.finishOp(124===e?F.logicalOR:F.logicalAND,2):61===t?this.finishOp(F.assign,2):this.finishOp(124===e?F.bitwiseOR:F.bitwiseAND,1)},se.readToken_caret=function(){return 61===this.input.charCodeAt(this.pos+1)?this.finishOp(F.assign,2):this.finishOp(F.bitwiseXOR,1)},se.readToken_plus_min=function(e){var t=this.input.charCodeAt(this.pos+1);return t===e?45==t&&62==this.input.charCodeAt(this.pos+2)&&N.test(this.input.slice(this.lastTokEnd,this.pos))?(this.skipLineComment(3),this.skipSpace(),this.nextToken()):this.finishOp(F.incDec,2):61===t?this.finishOp(F.assign,2):this.finishOp(F.plusMin,1)},se.readToken_lt_gt=function(e){var t=this.input.charCodeAt(this.pos+1),n=1;return t===e?(n=62===e&&62===this.input.charCodeAt(this.pos+2)?3:2,61===this.input.charCodeAt(this.pos+n)?this.finishOp(F.assign,n+1):this.finishOp(F.bitShift,n)):33==t&&60==e&&45==this.input.charCodeAt(this.pos+2)&&45==this.input.charCodeAt(this.pos+3)?(this.inModule&&this.unexpected(),this.skipLineComment(4),this.skipSpace(),this.nextToken()):(61===t&&(n=2),this.finishOp(F.relational,n))},se.readToken_eq_excl=function(e){var t=this.input.charCodeAt(this.pos+1);return 61===t?this.finishOp(F.equality,61===this.input.charCodeAt(this.pos+2)?3:2):61===e&&62===t&&this.options.ecmaVersion>=6?(this.pos+=2,this.finishToken(F.arrow)):this.finishOp(61===e?F.eq:F.prefix,1)},se.getTokenFromCode=function(e){switch(e){case 46:return this.readToken_dot();case 40:return++this.pos,this.finishToken(F.parenL);case 41:return++this.pos,this.finishToken(F.parenR);case 59:return++this.pos,this.finishToken(F.semi);case 44:return++this.pos,this.finishToken(F.comma);case 91:return++this.pos,this.finishToken(F.bracketL);case 93:return++this.pos,this.finishToken(F.bracketR);case 123:return++this.pos,this.finishToken(F.braceL);case 125:return++this.pos,this.finishToken(F.braceR);case 58:return++this.pos,this.finishToken(F.colon);case 63:return++this.pos,this.finishToken(F.question);case 96:if(this.options.ecmaVersion<6)break;return++this.pos,this.finishToken(F.backQuote);case 48:var t=this.input.charCodeAt(this.pos+1);if(120===t||88===t)return this.readRadixNumber(16);if(this.options.ecmaVersion>=6){if(111===t||79===t)return this.readRadixNumber(8);if(98===t||66===t)return this.readRadixNumber(2)}case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:return this.readNumber(!1);case 34:case 39:return this.readString(e);case 47:return this.readToken_slash();case 37:case 42:return this.readToken_mult_modulo_exp(e);case 124:case 38:return this.readToken_pipe_amp(e);case 94:return this.readToken_caret();case 43:case 45:return this.readToken_plus_min(e);case 60:case 62:return this.readToken_lt_gt(e);case 61:case 33:return this.readToken_eq_excl(e);case 126:return this.finishOp(F.prefix,1)}this.raise(this.pos,"Unexpected character '"+y(e)+"'")},se.finishOp=function(e,t){var n=this.input.slice(this.pos,this.pos+t);return this.pos+=t,this.finishToken(e,n)};var ae=!!d("","u");se.readRegexp=function(){for(var e,t,n=this,r=this.pos;;){n.pos>=n.input.length&&n.raise(r,"Unterminated regular expression");var i=n.input.charAt(n.pos);if(N.test(i)&&n.raise(r,"Unterminated regular expression"),e)e=!1;else{if("["===i)t=!0;else if("]"===i&&t)t=!1;else if("/"===i&&!t)break;e="\\"===i}++n.pos}var s=this.input.slice(r,this.pos);++this.pos;var o=this.readWord1(),a=s,u="";if(o){var c=/^[gim]*$/;this.options.ecmaVersion>=6&&(c=/^[gimuy]*$/),c.test(o)||this.raise(r,"Invalid regular expression flag"),o.indexOf("u")>=0&&(ae?u="u":(a=a.replace(/\\u\{([0-9a-fA-F]+)\}/g,function(e,t,i){return t=Number("0x"+t),t>1114111&&n.raise(r+i+3,"Code point out of bounds"),"x"}),a=a.replace(/\\u([a-fA-F0-9]{4})|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,"x"),u=u.replace("u","")))}var l=null;return oe||(d(a,u,r,this),l=d(s,o)),this.finishToken(F.regexp,{pattern:s,flags:o,value:l})},se.readInt=function(e,t){for(var n=this,r=this.pos,i=0,s=0,o=null==t?1/0:t;s=97?u-97+10:u>=65?u-65+10:u>=48&&u<=57?u-48:1/0,a>=e)break;++n.pos,i=i*e+a}return this.pos===r||null!=t&&this.pos-r!==t?null:i},se.readRadixNumber=function(e){this.pos+=2;var t=this.readInt(e);return null==t&&this.raise(this.start+2,"Expected number in radix "+e),n(this.fullCharCodeAtPos())&&this.raise(this.pos,"Identifier directly after number"),this.finishToken(F.num,t)},se.readNumber=function(e){var t=this.pos,r=!1,i=48===this.input.charCodeAt(this.pos);e||null!==this.readInt(10)||this.raise(t,"Invalid number"),i&&this.pos==t+1&&(i=!1);var s=this.input.charCodeAt(this.pos);46!==s||i||(++this.pos,this.readInt(10),r=!0,s=this.input.charCodeAt(this.pos)),69!==s&&101!==s||i||(s=this.input.charCodeAt(++this.pos),43!==s&&45!==s||++this.pos,null===this.readInt(10)&&this.raise(t,"Invalid number"),r=!0),n(this.fullCharCodeAtPos())&&this.raise(this.pos,"Identifier directly after number");var o,a=this.input.slice(t,this.pos);return r?o=parseFloat(a):i&&1!==a.length?/[89]/.test(a)||this.strict?this.raise(t,"Invalid number"):o=parseInt(a,8):o=parseInt(a,10),this.finishToken(F.num,o)},se.readCodePoint=function(){var e,t=this.input.charCodeAt(this.pos);if(123===t){this.options.ecmaVersion<6&&this.unexpected();var n=++this.pos;e=this.readHexChar(this.input.indexOf("}",this.pos)-this.pos),++this.pos,e>1114111&&this.raise(n,"Code point out of bounds")}else e=this.readHexChar(4);return e},se.readString=function(e){for(var t=this,n="",r=++this.pos;;){t.pos>=t.input.length&&t.raise(t.start,"Unterminated string constant");var i=t.input.charCodeAt(t.pos);if(i===e)break;92===i?(n+=t.input.slice(r,t.pos),n+=t.readEscapedChar(!1),r=t.pos):(o(i)&&t.raise(t.start,"Unterminated string constant"),++t.pos)}return n+=this.input.slice(r,this.pos++),this.finishToken(F.string,n)},se.readTmplToken=function(){for(var e=this,t="",n=this.pos;;){e.pos>=e.input.length&&e.raise(e.start,"Unterminated template");var r=e.input.charCodeAt(e.pos);if(96===r||36===r&&123===e.input.charCodeAt(e.pos+1))return e.pos===e.start&&e.type===F.template?36===r?(e.pos+=2,e.finishToken(F.dollarBraceL)):(++e.pos,e.finishToken(F.backQuote)):(t+=e.input.slice(n,e.pos),e.finishToken(F.template,t));if(92===r)t+=e.input.slice(n,e.pos),t+=e.readEscapedChar(!0),n=e.pos;else if(o(r)){switch(t+=e.input.slice(n,e.pos),++e.pos,r){case 13:10===e.input.charCodeAt(e.pos)&&++e.pos;case 10:t+="\n";break;default:t+=String.fromCharCode(r)}e.options.locations&&(++e.curLine,e.lineStart=e.pos),n=e.pos}else++e.pos}},se.readEscapedChar=function(e){var t=this.input.charCodeAt(++this.pos);switch(++this.pos,t){case 110:return"\n";case 114:return"\r";case 120:return String.fromCharCode(this.readHexChar(2));case 117:return y(this.readCodePoint());case 116:return"\t";case 98:return"\b";case 118:return"\v";case 102:return"\f";case 13:10===this.input.charCodeAt(this.pos)&&++this.pos;case 10:return this.options.locations&&(this.lineStart=this.pos,++this.curLine),"";default:if(t>=48&&t<=55){var n=this.input.substr(this.pos-1,3).match(/^[0-7]+/)[0],r=parseInt(n,8);return r>255&&(n=n.slice(0,-1),r=parseInt(n,8)),"0"!==n&&(this.strict||e)&&this.raise(this.pos-2,"Octal literal in strict mode"),this.pos+=n.length-1,String.fromCharCode(r)}return String.fromCharCode(t)}},se.readHexChar=function(e){var t=this.pos,n=this.readInt(16,e);return null===n&&this.raise(t,"Bad character escape sequence"),n},se.readWord1=function(){var e=this;this.containsEsc=!1;for(var t="",i=!0,s=this.pos,o=this.options.ecmaVersion>=6;this.pos=6||!this.containsEsc)&&this.keywords.test(e)&&(t=O[e]),this.finishToken(t,e)},e.version="4.0.4",e.parse=m,e.parseExpressionAt=g,e.tokenizer=v,e.addLooseExports=b,e.Parser=U,e.plugins=V,e.defaultOptions=D,e.Position=j,e.SourceLocation=M,e.getLineInfo=c,e.Node=K,e.TokenType=P,e.tokTypes=F,e.TokContext=te,e.tokContexts=ne,e.isIdentifierChar=r,e.isIdentifierStart=n,e.Token=ie,e.isNewLine=o,e.lineBreak=N,e.lineBreakG=$,Object.defineProperty(e,"__esModule",{value:!0})})},{}],16:[function(e,t,n){!function(e,r){"object"==typeof n&&void 0!==t?r(n):"function"==typeof define&&define.amd?define(["exports"],r):r((e.acorn=e.acorn||{},e.acorn.walk=e.acorn.walk||{}))}(this,function(e){"use strict";function t(t,n,r,i,s){r||(r=e.base),function e(t,i,s){var o=s||t.type,a=n[o];r[o](t,i,e),a&&a(t,i)}(t,i,s)}function n(t,n,r,i){r||(r=e.base);var s=[];!function e(t,i,o){var a=o||t.type,u=n[a],c=t!=s[s.length-1];c&&s.push(t),r[a](t,i,e),u&&u(t,i||s,s),c&&s.pop()}(t,i)}function r(t,n,r,i,s){var o=r?e.make(r,i):i;!function e(t,n,r){o[r||t.type](t,n,e)}(t,n,s)}function i(e){return"string"==typeof e?function(t){return t==e}:e?e:function(){return!0}}function s(t,n,r,s,o,a){s=i(s),o||(o=e.base);try{!function e(t,i,a){var u=a||t.type;if((null==n||t.start<=n)&&(null==r||t.end>=r)&&o[u](t,i,e),(null==n||t.start==n)&&(null==r||t.end==r)&&s(u,t))throw new h(t,i)}(t,a)}catch(e){if(e instanceof h)return e;throw e}}function o(t,n,r,s,o){r=i(r),s||(s=e.base);try{!function e(t,i,o){var a=o||t.type;if(!(t.start>n||t.end=n&&r(a,t))throw new h(t,i);s[a](t,i,e)}}(t,o)}catch(e){if(e instanceof h)return e;throw e}}function u(t,n,r,s,o){r=i(r),s||(s=e.base);var a;return function e(t,i,o){if(!(t.start>n)){var u=o||t.type;t.end<=n&&(!a||a.node.end=(t[n]||0))return!0;return!1}var i=n.versions.node.split("."),s=e("./core.json"),o={};for(var a in s)if(Object.prototype.hasOwnProperty.call(s,a)&&r(a))for(var u=0;u=0;c--)i.indexOf(a[c])===-1&&(u=u.concat(i.map(function(e){return s+r.join(r.join.apply(r,a.slice(0,c+1)),e)})));return"win32"===n.platform&&(u[u.length-1]=u[u.length-1].replace(":",":\\")),u.concat(t.paths)}}).call(this,e("_process"))},{_process:7,path:6}],26:[function(e,t,n){var r=e("./core"),i=e("fs"),s=e("path"),o=e("./caller.js"),a=e("./node-modules-paths.js");t.exports=function(e,t){function n(e){if(l(e))return e;for(var t=0;t=0&&e>1;return t?-n:n}var s=e("./base64"),o=5,a=1<>>=o,i>0&&(t|=c),n+=s.encode(t);while(i>0);return n},n.decode=function(e,t,n){var r,a,l=e.length,p=0,h=0;do{if(t>=l)throw new Error("Expected more digits in base 64 VLQ value.");if(a=s.decode(e.charCodeAt(t++)),a===-1)throw new Error("Invalid base64 digit: "+e.charAt(t-1));r=!!(a&c),a&=u,p+=a<0?t-u>1?r(u,t,i,s,o,a):a==n.LEAST_UPPER_BOUND?t1?r(e,u,i,s,o,a):a==n.LEAST_UPPER_BOUND?u:e<0?-1:e}n.GREATEST_LOWER_BOUND=1,n.LEAST_UPPER_BOUND=2,n.search=function(e,t,i,s){if(0===t.length)return-1;var o=r(-1,t.length,e,t,i,s||n.GREATEST_LOWER_BOUND);if(o<0)return-1;for(;o-1>=0&&0===i(t[o],t[o-1],!0);)--o;return o}},{}],31:[function(e,t,n){function r(e,t){var n=e.generatedLine,r=t.generatedLine,i=e.generatedColumn,o=t.generatedColumn;return r>n||r==n&&o>=i||s.compareByGeneratedPositionsInflated(e,t)<=0}function i(){this._array=[],this._sorted=!0,this._last={generatedLine:-1,generatedColumn:0}}var s=e("./util");i.prototype.unsortedForEach=function(e,t){this._array.forEach(e,t)},i.prototype.add=function(e){r(this._last,e)?(this._last=e,this._array.push(e)):(this._sorted=!1,this._array.push(e))},i.prototype.toArray=function(){return this._sorted||(this._array.sort(s.compareByGeneratedPositionsInflated),this._sorted=!0),this._array},n.MappingList=i},{"./util":36}],32:[function(e,t,n){function r(e,t,n){var r=e[t];e[t]=e[n],e[n]=r}function i(e,t){return Math.round(e+Math.random()*(t-e))}function s(e,t,n,o){if(n=0){var s=this._originalMappings[i];if(void 0===e.column)for(var o=s.originalLine;s&&s.originalLine===o;)r.push({line:a.getArg(s,"generatedLine",null),column:a.getArg(s,"generatedColumn",null),lastColumn:a.getArg(s,"lastGeneratedColumn",null)}),s=this._originalMappings[++i];else for(var c=s.originalColumn;s&&s.originalLine===t&&s.originalColumn==c;)r.push({line:a.getArg(s,"generatedLine",null),column:a.getArg(s,"generatedColumn",null),lastColumn:a.getArg(s,"lastGeneratedColumn",null)}),s=this._originalMappings[++i]}return r},n.SourceMapConsumer=r,i.prototype=Object.create(r.prototype),i.prototype.consumer=r,i.fromSourceMap=function(e){var t=Object.create(i.prototype),n=t._names=c.fromArray(e._names.toArray(),!0),r=t._sources=c.fromArray(e._sources.toArray(),!0);t.sourceRoot=e._sourceRoot,t.sourcesContent=e._generateSourcesContent(t._sources.toArray(),t.sourceRoot),t.file=e._file;for(var o=e._mappings.toArray().slice(),u=t.__generatedMappings=[],l=t.__originalMappings=[],h=0,f=o.length;h1&&(n.source=y+i[1],y+=i[1],n.originalLine=f+i[2],f=n.originalLine,n.originalLine+=1,n.originalColumn=d+i[3],d=n.originalColumn,i.length>4&&(n.name=m+i[4],m+=i[4])),E.push(n),"number"==typeof n.originalLine&&w.push(n)}p(E,a.compareByGeneratedPositionsDeflated),this.__generatedMappings=E,p(w,a.compareByOriginalPositions),this.__originalMappings=w},i.prototype._findMapping=function(e,t,n,r,i,s){if(e[n]<=0)throw new TypeError("Line must be greater than or equal to 1, got "+e[n]);if(e[r]<0)throw new TypeError("Column must be greater than or equal to 0, got "+e[r]);return u.search(e,t,i,s)},i.prototype.computeColumnSpans=function(){for(var e=0;e=0){var i=this._generatedMappings[n];if(i.generatedLine===t.generatedLine){var s=a.getArg(i,"source",null);null!==s&&(s=this._sources.at(s),null!=this.sourceRoot&&(s=a.join(this.sourceRoot,s)));var o=a.getArg(i,"name",null);return null!==o&&(o=this._names.at(o)),{source:s,line:a.getArg(i,"originalLine",null),column:a.getArg(i,"originalColumn",null),name:o}}}return{source:null,line:null,column:null,name:null}},i.prototype.hasContentsOfAllSources=function(){return!!this.sourcesContent&&(this.sourcesContent.length>=this._sources.size()&&!this.sourcesContent.some(function(e){return null==e}))},i.prototype.sourceContentFor=function(e,t){if(!this.sourcesContent)return null;if(null!=this.sourceRoot&&(e=a.relative(this.sourceRoot,e)),this._sources.has(e))return this.sourcesContent[this._sources.indexOf(e)];var n;if(null!=this.sourceRoot&&(n=a.urlParse(this.sourceRoot))){var r=e.replace(/^file:\/\//,"");if("file"==n.scheme&&this._sources.has(r))return this.sourcesContent[this._sources.indexOf(r)];if((!n.path||"/"==n.path)&&this._sources.has("/"+e))return this.sourcesContent[this._sources.indexOf("/"+e)]}if(t)return null;throw new Error('"'+e+'" is not in the SourceMap.')},i.prototype.generatedPositionFor=function(e){var t=a.getArg(e,"source");if(null!=this.sourceRoot&&(t=a.relative(this.sourceRoot,t)),!this._sources.has(t))return{line:null,column:null,lastColumn:null};t=this._sources.indexOf(t);var n={source:t,originalLine:a.getArg(e,"line"),originalColumn:a.getArg(e,"column")},i=this._findMapping(n,this._originalMappings,"originalLine","originalColumn",a.compareByOriginalPositions,a.getArg(e,"bias",r.GREATEST_LOWER_BOUND));if(i>=0){var s=this._originalMappings[i];if(s.source===n.source)return{line:a.getArg(s,"generatedLine",null),column:a.getArg(s,"generatedColumn",null),lastColumn:a.getArg(s,"lastGeneratedColumn",null)}}return{line:null,column:null,lastColumn:null}},n.BasicSourceMapConsumer=i,o.prototype=Object.create(r.prototype),o.prototype.constructor=r,o.prototype._version=3,Object.defineProperty(o.prototype,"sources",{get:function(){for(var e=[],t=0;t0&&e.column>=0)||t||n||r)&&!(e&&"line"in e&&"column"in e&&t&&"line"in t&&"column"in t&&e.line>0&&e.column>=0&&t.line>0&&t.column>=0&&n))throw new Error("Invalid mapping: "+JSON.stringify({generated:e,source:n,original:t,name:r}))},r.prototype._serializeMappings=function(){for(var e,t,n,r,o=0,a=1,u=0,c=0,l=0,p=0,h="",f=this._mappings.toArray(),d=0,y=f.length;d0){if(!s.compareByGeneratedPositionsInflated(t,f[d-1]))continue;e+=","}e+=i.encode(t.generatedColumn-o),o=t.generatedColumn,null!=t.source&&(r=this._sources.indexOf(t.source),e+=i.encode(r-p),p=r,e+=i.encode(t.originalLine-1-c),c=t.originalLine-1,e+=i.encode(t.originalColumn-u),u=t.originalColumn,null!=t.name&&(n=this._names.indexOf(t.name),e+=i.encode(n-l),l=n)),h+=e}return h},r.prototype._generateSourcesContent=function(e,t){return e.map(function(e){if(!this._sourcesContents)return null;null!=t&&(e=s.relative(t,e));var n=s.toSetString(e);return Object.prototype.hasOwnProperty.call(this._sourcesContents,n)?this._sourcesContents[n]:null},this)},r.prototype.toJSON=function(){var e={version:this._version,sources:this._sources.toArray(),names:this._names.toArray(),mappings:this._serializeMappings()};return null!=this._file&&(e.file=this._file),null!=this._sourceRoot&&(e.sourceRoot=this._sourceRoot),this._sourcesContents&&(e.sourcesContent=this._generateSourcesContent(e.sources,e.sourceRoot)),e},r.prototype.toString=function(){return JSON.stringify(this.toJSON())},n.SourceMapGenerator=r},{"./array-set":27,"./base64-vlq":28,"./mapping-list":31,"./util":36}],35:[function(e,t,n){function r(e,t,n,r,i){this.children=[],this.sourceContents={},this.line=null==e?null:e,this.column=null==t?null:t,this.source=null==n?null:n,this.name=null==i?null:i,this[a]=!0,null!=r&&this.add(r)}var i=e("./source-map-generator").SourceMapGenerator,s=e("./util"),o=/(\r?\n)/,a="$$$isSourceNode$$$";r.fromStringWithSourceMap=function(e,t,n){function i(e,t){if(null===e||void 0===e.source)a.add(t);else{var i=n?s.join(n,e.source):e.source;a.add(new r(e.originalLine,e.originalColumn,i,t,e.name))}}var a=new r,u=e.split(o),c=function(){return u.shift()+(u.shift()||"")},l=1,p=0,h=null;return t.eachMapping(function(e){if(null!==h){if(!(l0&&(h&&i(h,c()),a.add(u.join(""))),t.sources.forEach(function(e){var r=t.sourceContentFor(e);null!=r&&(null!=n&&(e=s.join(n,e)),a.setSourceContent(e,r))}),a},r.prototype.add=function(e){if(Array.isArray(e))e.forEach(function(e){this.add(e)},this);else{if(!e[a]&&"string"!=typeof e)throw new TypeError("Expected a SourceNode, string, or an array of SourceNodes and strings. Got "+e);e&&this.children.push(e)}return this},r.prototype.prepend=function(e){if(Array.isArray(e))for(var t=e.length-1;t>=0;t--)this.prepend(e[t]);else{if(!e[a]&&"string"!=typeof e)throw new TypeError("Expected a SourceNode, string, or an array of SourceNodes and strings. Got "+e);this.children.unshift(e)}return this},r.prototype.walk=function(e){for(var t,n=0,r=this.children.length;n0){for(t=[],n=0;n=0;l--)o=u[l],"."===o?u.splice(l,1):".."===o?c++:c>0&&(""===o?(u.splice(l+1,c),c=0):(u.splice(l,2),c--));return t=u.join("/"),""===t&&(t=a?"/":"."),r?(r.path=t,s(r)):t}function a(e,t){""===e&&(e="."),""===t&&(t=".");var n=i(t),r=i(e);if(r&&(e=r.path||"/"),n&&!n.scheme)return r&&(n.scheme=r.scheme),s(n);if(n||t.match(v))return t;if(r&&!r.host&&!r.path)return r.host=t,s(r);var a="/"===t.charAt(0)?t:o(e.replace(/\/+$/,"")+"/"+t);return r?(r.path=a,s(r)):a}function u(e,t){""===e&&(e="."),e=e.replace(/\/$/,"");for(var n=0;0!==t.indexOf(e+"/");){var r=e.lastIndexOf("/");if(r<0)return t;if(e=e.slice(0,r),e.match(/^([^\/]+:\/)?\/*$/))return t;++n}return Array(n+1).join("../")+t.substr(e.length+1)}function c(e){return e}function l(e){return h(e)?"$"+e:e}function p(e){return h(e)?e.slice(1):e}function h(e){if(!e)return!1;var t=e.length;if(t<9)return!1;if(95!==e.charCodeAt(t-1)||95!==e.charCodeAt(t-2)||111!==e.charCodeAt(t-3)||116!==e.charCodeAt(t-4)||111!==e.charCodeAt(t-5)||114!==e.charCodeAt(t-6)||112!==e.charCodeAt(t-7)||95!==e.charCodeAt(t-8)||95!==e.charCodeAt(t-9))return!1;for(var n=t-10;n>=0;n--)if(36!==e.charCodeAt(n))return!1;return!0}function f(e,t,n){var r=e.source-t.source;return 0!==r?r:(r=e.originalLine-t.originalLine,0!==r?r:(r=e.originalColumn-t.originalColumn,0!==r||n?r:(r=e.generatedColumn-t.generatedColumn,0!==r?r:(r=e.generatedLine-t.generatedLine,0!==r?r:e.name-t.name))))}function d(e,t,n){var r=e.generatedLine-t.generatedLine;return 0!==r?r:(r=e.generatedColumn-t.generatedColumn,0!==r||n?r:(r=e.source-t.source,0!==r?r:(r=e.originalLine-t.originalLine,0!==r?r:(r=e.originalColumn-t.originalColumn,0!==r?r:e.name-t.name))))}function y(e,t){return e===t?0:e>t?1:-1}function m(e,t){var n=e.generatedLine-t.generatedLine;return 0!==n?n:(n=e.generatedColumn-t.generatedColumn,0!==n?n:(n=y(e.source,t.source),0!==n?n:(n=e.originalLine-t.originalLine,0!==n?n:(n=e.originalColumn-t.originalColumn,0!==n?n:y(e.name,t.name)))))}n.getArg=r;var g=/^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.]*)(?::(\d+))?(\S*)$/,v=/^data:.+\,.+$/;n.urlParse=i,n.urlGenerate=s,n.normalize=o,n.join=a,n.isAbsolute=function(e){return"/"===e.charAt(0)||!!e.match(g)},n.relative=u;var b=function(){return!("__proto__"in Object.create(null))}();n.toSetString=b?c:l,n.fromSetString=b?c:p,n.compareByOriginalPositions=f,n.compareByGeneratedPositionsDeflated=d,n.compareByGeneratedPositionsInflated=m},{}],37:[function(e,t,n){n.SourceMapGenerator=e("./lib/source-map-generator").SourceMapGenerator,n.SourceMapConsumer=e("./lib/source-map-consumer").SourceMapConsumer,n.SourceNode=e("./lib/source-node").SourceNode},{"./lib/source-map-consumer":33,"./lib/source-map-generator":34,"./lib/source-node":35}],38:[function(e,t,n){t.exports={name:"nodent",version:"3.0.7",description:"NoDent - Asynchronous Javascript language extensions",main:"nodent.js",scripts:{cover:"istanbul cover ./nodent.js tests -- --quick --syntax --forceStrict ; open ./coverage/lcov-report/index.html",test:"cd tests && npm i --prod && cd .. && node --expose-gc ./nodent.js tests --syntax --quick","test-loader":"cd tests/loader/app && npm test && cd ../../..",start:"./nodent.js"},bin:{nodentjs:"./nodent.js"},dependencies:{acorn:">=2.5.2","acorn-es7-plugin":"^1.1.3","nodent-runtime":"^3.0.3",resolve:"^1.1.7","source-map":"0.5.6"},repository:{type:"git",url:"git+https://github.com/MatAtBread/nodent.git"},engines:"node >= 0.10.0",keywords:["Javascript","ES7","async","await","language","extensions","Node","callback","generator","Promise","asynchronous"],author:{name:"Mat At Bread",email:"nodent@mailed.me.uk"},license:"BSD-2-Clause",bugs:{url:"https://github.com/MatAtBread/nodent/issues"},gitHead:"8ea9feab498470d7a2c3c09326a1c17e8eeb332a",homepage:"https://github.com/MatAtBread/nodent#readme",_id:"nodent@3.0.7",_shasum:"08dd540baf834c136648aeaa9ae8ecd4bf92aa52",_from:"nodent@>=3.0.2 <4.0.0",_npmVersion:"3.10.3",_nodeVersion:"6.7.0",_npmUser:{name:"matatbread",email:"npm@mailed.me.uk"},maintainers:[{name:"matatbread",email:"npm@mailed.me.uk"}],dist:{shasum:"08dd540baf834c136648aeaa9ae8ecd4bf92aa52",tarball:"https://registry.npmjs.org/nodent/-/nodent-3.0.7.tgz"},_npmOperationalInternal:{host:"packages-18-east.internal.npmjs.com",tmp:"tmp/nodent-3.0.7.tgz_1477471431033_0.10623699799180031"},directories:{},_resolved:"https://registry.npmjs.org/nodent/-/nodent-3.0.7.tgz",readme:"ERROR: No README data found!"}},{}],nodent:[function(e,t,n){(function(n,r,i,s,o,a,u,c){"use strict";function l(e){var t={};return e.forEach(function(e){if(e&&"object"==typeof e)for(var n in e)t[n]=e[n]}),t}function p(e){throw e}function h(){}function f(e){return"ExpressionStatement"===e.type&&("StringLiteral"===e.expression.type||"Literal"===e.expression.type&&"string"==typeof e.expression.value)}function d(t,n,r){n||(n=console.warn.bind(console));var i,s,o={};if("string"==typeof t)(i=t.match(M))&&(s=i[1]||"default");else for(var a=0;a"))}return o.promises||o.es7||o.generators||o.engine?((o.promises||o.es7)&&o.generators&&(n("No valid 'use nodent' directive, assumed -es7 mode"),o=j.es7),(o.generators||o.engine)&&(o.promises=!0),o.promises&&(o.es7=!0),o):null}function y(e){return 65279===e.charCodeAt(0)&&(e=e.slice(1)),"#!"===e.substring(0,2)&&(e="//"+e),e}function m(e){var t;return t=e instanceof i?e:new i(e.toString(),"binary"),t.toString("base64")}function g(e,t){return t=t||e.log,function(n,r,i){var s=y(R.readFileSync(r,"utf8")),o=e.parse(s,r,i);i=i||d(o.ast,t,r),e.asynchronize(o,void 0,i,t),e.prettyPrint(o,i),n._compile(o.code,o.filename)}}function v(e){return e=e||q,function(t,n,r){if(Array.isArray(n)){var i=n;n=function(e,t){return i.indexOf(e)>=0}}else n=n||function(e,t){return!(e.match(/Sync$/)&&e.replace(/Sync$/,"")in t)};r||(r="");var s=Object.create(t);for(var o in s)!function(){var i=o;try{"function"!=typeof t[i]||s[i+r]&&s[i+r].isAsync||!n(i,s)||(s[i+r]=function(){var n=Array.prototype.slice.call(arguments);return new e(function(e,r){var s=function(t,n){if(t)return r(t);switch(arguments.length){case 0:return e();case 2:return e(n);default:return e(Array.prototype.slice.call(arguments,1))}};n.length>t[i].length?n.push(s):n[t[i].length-1]=s;t[i].apply(t,n)})},s[i+r].isAsync=!0)}catch(e){}}();return s.super=t,s}}function b(t,n){var r=t.filename.split("/"),i=r.pop(),s=O(t.ast,n&&n.sourcemap?{map:{startLine:n.mapStartLine||0,file:i+"(original)",sourceMapRoot:r.join("/"),sourceContent:t.origCode}}:null,t.origCode);if(n&&n.sourcemap)try{var o="",a=s.map.toJSON();if(a){var u=e("source-map").SourceMapConsumer;t.sourcemap=a,T[t.filename]={map:a,smc:new u(a)},o="\n\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,"+m(JSON.stringify(a))+"\n"}t.code=s.code+o}catch(e){t.code=s}else t.code=s;return t}function x(e,t,n,r){"object"==typeof n&&void 0===r&&(r=n);var i={origCode:e.toString(),filename:t};try{return i.ast=F.parse(i.origCode,r&&r.parser),r.babelTree&&F.treeWalker(i.ast,function(e,t,n){"Literal"===e.type?n[0].replace(N.babelLiteralNode(e.value)):"Property"===e.type&&("ClassBody"===n[0].parent.type?e.type="ClassProperty":e.type="ObjectProperty"),t()}),i}catch(e){if(e instanceof SyntaxError){var s=i.origCode.substr(e.pos-e.loc.column);s=s.split("\n")[0],e.message+=" "+t+" (nodent)\n"+s+"\n"+s.replace(/[\S ]/g,"-").substring(0,e.loc.column)+"^",e.stack=""}throw e}}function w(t,n){n=n||{};var r=t+"|"+Object.keys(n).sort().reduce(function(e,t){return e+t+JSON.stringify(n[t])},"");return this.covers[r]||(t.indexOf("/")>=0?this.covers[r]=e(t):this.covers[r]=e(c+"/covers/"+t)),this.covers[r](this,n)}function E(e,t,n,r){"object"==typeof n&&void 0===r&&(r=n),r=r||{};for(var i in I)i in r||(r[i]=I[i]);var s=this.parse(e,t,null,r);return this.asynchronize(s,null,r,this.log||h),this.prettyPrint(s,r),s}function S(t,n,r){var i={},s=this;n||(n=/\.njs$/),r?r.compiler||(r.compiler={}):r={compiler:{}};var o=l([B,r.compiler]);return function(a,u,c){function l(e){u.statusCode=500,u.write(e.toString()),u.end()}if(i[a.url])return u.setHeader("Content-Type",i[a.url].contentType),r.setHeaders&&r.setHeaders(u),u.write(i[a.url].output),void u.end();if(!(a.url.match(n)||r.htmlScriptRegex&&a.url.match(r.htmlScriptRegex)))return c&&c();var p=t+a.url;if(r.extensions&&!R.existsSync(p))for(var h=0;h …"+n.source+":"+n.line+":"+n.column+(e.getFunctionName()?")":"")}}return"\n at "+e}return e+t.map(n).join("")}function _(e){var t={};t[I.$asyncbind]={value:V,writable:!0,enumerable:!1,configurable:!0},t[I.$asyncspawn]={value:U,writable:!0,enumerable:!1,configurable:!0};try{Object.defineProperties(Function.prototype,t)}catch(t){e.log("Function prototypes already assigned: ",t.messsage)}I[I.$error]in r||(r[I[I.$error]]=p),e.augmentObject&&Object.defineProperties(Object.prototype,{asyncify:{value:function(e,t,n){return v(e)(this,t,n)},writable:!0,configurable:!0},isThenable:{value:function(){return q.isThenable(this)},writable:!0,configurable:!0}}),Object[I.$makeThenable]=q.resolve}function C(t){function n(e,t){e=e.split("."),t=t.split(".");for(var n=0;n<3;n++){if(e[n]t[n])return 1}return 0}function r(i,s){if(!s.match(/nodent\/nodent\.js$/)){if(s.match(/node_modules\/nodent\/.*\.js$/))return P(i,s);for(var u=0;u=3&&L()}).call(this,e("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},e("buffer").Buffer,arguments[3],arguments[4],arguments[5],arguments[6],"/node_modules/nodent")},{"./htmlScriptParser":8,"./lib/arboriculture":9,"./lib/output":10,"./lib/parser":11,"./package.json":38,_process:7,buffer:2,fs:1,"nodent-runtime":17,path:6,resolve:20,"source-map":37}]},{},[]);
\ No newline at end of file
+/* nodent 3.0.17: NoDent - Asynchronous Javascript language extensions */
+require=function e(t,n,r){function i(o,a){if(!n[o]){if(!t[o]){var u="function"==typeof require&&require;if(!a&&u)return u(o,!0);if(s)return s(o,!0);var c=new Error("Cannot find module '"+o+"'");throw c.code="MODULE_NOT_FOUND",c}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return i(n||e)},l,l.exports,e,t,n,r)}return n[o].exports}for(var s="function"==typeof require&&require,o=0;o=t}function i(e,t,n){var r=t.input.slice(t.start);return n&&(r=r.replace(p,"$1 $3")),e.test(r)}function s(e,t,n,r){var i=new e.constructor(e.options,e.input,t);if(n)for(var s in n)i[s]=n[s];var o=e,a=i;return["inFunction","inAsyncFunction","inAsync","inGenerator","inModule"].forEach(function(e){e in o&&(a[e]=o[e])}),r&&(i.options.preserveParens=!0),i.nextToken(),i}function o(e,t){var n=function(){};e.extend("initialContext",function(r){return function(){return this.options.ecmaVersion<7&&(n=function(t){e.raise(t.start,"async/await keywords only available when ecmaVersion>=7")}),this.reservedWords=new RegExp(this.reservedWords.toString().replace(/await|async/g,"").replace("|/","/").replace("/|","/").replace("||","|")),this.reservedWordsStrict=new RegExp(this.reservedWordsStrict.toString().replace(/await|async/g,"").replace("|/","/").replace("/|","/").replace("||","|")),this.reservedWordsStrictBind=new RegExp(this.reservedWordsStrictBind.toString().replace(/await|async/g,"").replace("|/","/").replace("/|","/").replace("||","|")),this.inAsyncFunction=t.inAsyncFunction,t.awaitAnywhere&&t.inAsyncFunction&&e.raise(node.start,"The options awaitAnywhere and inAsyncFunction are mutually exclusive"),r.apply(this,arguments)}}),e.extend("shouldParseExportStatement",function(e){return function(){return!("name"!==this.type.label||"async"!==this.value||!i(c,this))||e.apply(this,arguments)}}),e.extend("parseStatement",function(e){return function(n,r){var s=this.start,o=this.startLoc;if("name"===this.type.label)if(i(c,this,!0)){var a=this.inAsyncFunction;try{this.inAsyncFunction=!0,this.next();var l=this.parseStatement(n,r);return l.async=!0,l.start=s,l.loc&&(l.loc.start=o),l.range&&(l.range[0]=s),l}finally{this.inAsyncFunction=a}}else if("object"==typeof t&&t.asyncExits&&i(u,this)){this.next();var l=this.parseStatement(n,r);return l.async=!0,l.start=s,l.loc&&(l.loc.start=o),l.range&&(l.range[0]=s),l}return e.apply(this,arguments)}}),e.extend("parseIdent",function(e){return function(t){var n=e.apply(this,arguments);return this.inAsyncFunction&&"await"===n.name&&0===arguments.length&&this.raise(n.start,"'await' is reserved within async functions"),n}}),e.extend("parseExprAtom",function(e){return function(i){var o,u=this.start,c=this.startLoc,p=e.apply(this,arguments);if("Identifier"===p.type)if("async"!==p.name||r(this,p.end)){if("await"===p.name){var h=this.startNodeAt(p.start,p.loc&&p.loc.start);if(this.inAsyncFunction)return o=this.parseExprSubscripts(),h.operator="await",h.argument=o,h=this.finishNodeAt(h,"AwaitExpression",o.end,o.loc&&o.loc.end),n(h),h;if(this.input.slice(p.end).match(l))return t.awaitAnywhere||"module"!==this.options.sourceType?p:this.raise(p.start,"'await' is reserved within modules");if("object"==typeof t&&t.awaitAnywhere&&(u=this.start,o=s(this,u-4).parseExprSubscripts(),o.end<=u))return o=s(this,u).parseExprSubscripts(),h.operator="await",h.argument=o,h=this.finishNodeAt(h,"AwaitExpression",o.end,o.loc&&o.loc.end),this.pos=o.end,this.end=o.end,this.endLoc=o.endLoc,this.next(),n(h),h;if(!t.awaitAnywhere&&"module"===this.options.sourceType)return this.raise(p.start,"'await' is reserved within modules")}}else{var f=this.inAsyncFunction;try{this.inAsyncFunction=!0;var d=this,y=!1,m={parseFunctionBody:function(e,t){try{var n=y;return y=!0,d.parseFunctionBody.apply(this,arguments)}finally{y=n}},raise:function(){try{return d.raise.apply(this,arguments)}catch(e){throw y?e:a}}};if(o=s(this,this.start,m,!0).parseExpression(),"SequenceExpression"===o.type&&(o=o.expressions[0]),"CallExpression"===o.type&&(o=o.callee),"FunctionExpression"===o.type||"FunctionDeclaration"===o.type||"ArrowFunctionExpression"===o.type)return o=s(this,this.start,m).parseExpression(),"SequenceExpression"===o.type&&(o=o.expressions[0]),"CallExpression"===o.type&&(o=o.callee),o.async=!0,o.start=u,o.loc&&(o.loc.start=c),o.range&&(o.range[0]=u),this.pos=o.end,this.end=o.end,this.endLoc=o.endLoc,this.next(),n(o),o}catch(e){if(e!==a)throw e}finally{this.inAsyncFunction=f}}return p}}),e.extend("finishNodeAt",function(e){return function(t,n,r,i){return t.__asyncValue&&(delete t.__asyncValue,t.value.async=!0),e.apply(this,arguments)}}),e.extend("finishNode",function(e){return function(t,n){return t.__asyncValue&&(delete t.__asyncValue,t.value.async=!0),e.apply(this,arguments)}});e.extend("parsePropertyName",function(e){return function(t){var i=(t.key&&t.key.name,e.apply(this,arguments));return"Identifier"!==i.type||"async"!==i.name||r(this,i.end)||this.input.slice(i.end).match(l)||(h.test(this.input.slice(i.end))?(i=e.apply(this,arguments),t.__asyncValue=!0):(n(t),"set"===t.kind&&this.raise(i.start,"'set (value)' cannot be be async"),i=e.apply(this,arguments),"Identifier"===i.type&&"set"===i.name&&this.raise(i.start,"'set (value)' cannot be be async"),t.__asyncValue=!0)),i}}),e.extend("parseClassMethod",function(e){return function(t,n,r){var i;n.__asyncValue&&("constructor"===n.kind&&this.raise(n.start,"class constructor() cannot be be async"),i=this.inAsyncFunction,this.inAsyncFunction=!0);var s=e.apply(this,arguments);return this.inAsyncFunction=i,s}}),e.extend("parseMethod",function(e){return function(t){var n;this.__currentProperty&&this.__currentProperty.__asyncValue&&(n=this.inAsyncFunction,this.inAsyncFunction=!0);var r=e.apply(this,arguments);return this.inAsyncFunction=n,r}}),e.extend("parsePropertyValue",function(e){return function(t,n,r,i,s,o){var a=this.__currentProperty;this.__currentProperty=t;var u;t.__asyncValue&&(u=this.inAsyncFunction,this.inAsyncFunction=!0);var c=e.apply(this,arguments);return this.inAsyncFunction=u,this.__currentProperty=a,c}})}var a={},u=/^async[\t ]+(return|throw)/,c=/^async[\t ]+function/,l=/^\s*[():;]/,p=/([^\n])\/\*(\*(?!\/)|[^\n*])*\*\/([^\n])/g,h=/\s*(get|set)\s*\(/;t.exports=o},{}],3:[function(e,t,n){function r(e,t){return e.lineStart>=t}function i(e,t,n){var r=t.input.slice(t.start);return n&&(r=r.replace(c,"$1 $3")),e.test(r)}function s(e,t,n){var r=new e.constructor(e.options,e.input,t);if(n)for(var i in n)r[i]=n[i];var s=e,o=r;return["inFunction","inAsync","inGenerator","inModule"].forEach(function(e){e in s&&(o[e]=s[e])}),r.nextToken(),r}function o(e,t){t&&"object"==typeof t||(t={}),e.extend("parse",function(n){return function(){return this.inAsync=t.inAsyncFunction,t.awaitAnywhere&&t.inAsyncFunction&&e.raise(node.start,"The options awaitAnywhere and inAsyncFunction are mutually exclusive"),n.apply(this,arguments)}}),e.extend("parseStatement",function(e){return function(n,r){var s=this.start,o=this.startLoc;if("name"===this.type.label&&t.asyncExits&&i(a,this)){this.next();var u=this.parseStatement(n,r);return u.async=!0,u.start=s,u.loc&&(u.loc.start=o),u.range&&(u.range[0]=s),u}return e.apply(this,arguments)}}),e.extend("parseIdent",function(e){return function(n){return"module"===this.options.sourceType&&this.options.ecmaVersion>=8&&t.awaitAnywhere?e.call(this,!0):e.apply(this,arguments)}}),e.extend("parseExprAtom",function(e){var n={};return function(r){var i,o=this.start,a=(this.startLoc,e.apply(this,arguments));if("Identifier"===a.type&&"await"===a.name&&!this.inAsync&&t.awaitAnywhere){var u=this.startNodeAt(a.start,a.loc&&a.loc.start);o=this.start;var c={raise:function(){try{return pp.raise.apply(this,arguments)}catch(e){throw n}}};try{if(i=s(this,o-4,c).parseExprSubscripts(),i.end<=o)return i=s(this,o,c).parseExprSubscripts(),u.argument=i,u=this.finishNodeAt(u,"AwaitExpression",i.end,i.loc&&i.loc.end),this.pos=i.end,this.end=i.end,this.endLoc=i.endLoc,this.next(),u}catch(e){if(e===n)return a;throw e}}return a}});var n={undefined:!0,get:!0,set:!0,static:!0,async:!0,constructor:!0};e.extend("parsePropertyName",function(e){return function(t){var i=t.key&&t.key.name,s=e.apply(this,arguments);"get"===this.value&&(t.__maybeStaticAsyncGetter=!0);return n[this.value]?s:("Identifier"!==s.type||"async"!==s.name&&"async"!==i||r(this,s.end)||this.input.slice(s.end).match(u)?delete t.__maybeStaticAsyncGetter:"set"===t.kind||"set"===s.name?this.raise(s.start,"'set (value)' cannot be be async"):(this.__isAsyncProp=!0,s=e.apply(this,arguments),"Identifier"===s.type&&"set"===s.name&&this.raise(s.start,"'set (value)' cannot be be async")),s)}}),e.extend("parseClassMethod",function(e){return function(t,n,r){var i=e.apply(this,arguments);return n.__maybeStaticAsyncGetter&&(delete n.__maybeStaticAsyncGetter,"get"!==n.key.name&&(n.kind="get")),i}}),e.extend("parseFunctionBody",function(e){return function(t,n){var r=this.inAsync;this.__isAsyncProp&&(t.async=!0,this.inAsync=!0,delete this.__isAsyncProp);var i=e.apply(this,arguments);return this.inAsync=r,i}})}var a=/^async[\t ]+(return|throw)/,u=/^\s*[):;]/,c=/([^\n])\/\*(\*(?!\/)|[^\n*])*\*\/([^\n])/g;t.exports=o},{}],4:[function(e,t,n){"use strict";function r(e){var t=e.length;if(t%4>0)throw new Error("Invalid string. Length must be a multiple of 4");return"="===e[t-2]?2:"="===e[t-1]?1:0}function i(e){return 3*e.length/4-r(e)}function s(e){var t,n,i,s,o,a,u=e.length;o=r(e),a=new p(3*u/4-o),i=o>0?u-4:u;var c=0;for(t=0,n=0;t>16&255,a[c++]=s>>8&255,a[c++]=255&s;return 2===o?(s=l[e.charCodeAt(t)]<<2|l[e.charCodeAt(t+1)]>>4,a[c++]=255&s):1===o&&(s=l[e.charCodeAt(t)]<<10|l[e.charCodeAt(t+1)]<<4|l[e.charCodeAt(t+2)]>>2,a[c++]=s>>8&255,a[c++]=255&s),a}function o(e){return c[e>>18&63]+c[e>>12&63]+c[e>>6&63]+c[63&e]}function a(e,t,n){for(var r,i=[],s=t;su?u:o+16383));return 1===r?(t=e[n-1],i+=c[t>>2],i+=c[t<<4&63],i+="=="):2===r&&(t=(e[n-2]<<8)+e[n-1],i+=c[t>>10],i+=c[t>>4&63],i+=c[t<<2&63],i+="="),s.push(i),s.join("")}n.byteLength=i,n.toByteArray=s,n.fromByteArray=u;for(var c=[],l=[],p="undefined"!=typeof Uint8Array?Uint8Array:Array,h="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",f=0,d=h.length;fH)throw new RangeError("Invalid typed array length");var t=new Uint8Array(e);return t.__proto__=i.prototype,t}function i(e,t,n){if("number"==typeof e){if("string"==typeof t)throw new Error("If encoding is specified then the first argument must be a string");return u(e)}return s(e,t,n)}function s(e,t,n){if("number"==typeof e)throw new TypeError('"value" argument must not be a number');return e instanceof ArrayBuffer?p(e,t,n):"string"==typeof e?c(e,t):h(e)}function o(e){if("number"!=typeof e)throw new TypeError('"size" argument must be a number');if(e<0)throw new RangeError('"size" argument must not be negative')}function a(e,t,n){return o(e),e<=0?r(e):void 0!==t?"string"==typeof n?r(e).fill(t,n):r(e).fill(t):r(e)}function u(e){return o(e),r(e<0?0:0|f(e))}function c(e,t){if("string"==typeof t&&""!==t||(t="utf8"),!i.isEncoding(t))throw new TypeError('"encoding" must be a valid string encoding');var n=0|y(e,t),s=r(n),o=s.write(e,t);return o!==n&&(s=s.slice(0,o)),s}function l(e){for(var t=e.length<0?0:0|f(e.length),n=r(t),i=0;i=H)throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+H.toString(16)+" bytes");return 0|e}function d(e){return+e!=e&&(e=0),i.alloc(+e)}function y(e,t){if(i.isBuffer(e))return e.length;if(ArrayBuffer.isView(e)||e instanceof ArrayBuffer)return e.byteLength;"string"!=typeof e&&(e=""+e);var n=e.length;if(0===n)return 0;for(var r=!1;;)switch(t){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":case void 0:return V(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*n;case"hex":return n>>>1;case"base64":return z(e).length;default:if(r)return V(e).length;t=(""+t).toLowerCase(),r=!0}}function m(e,t,n){var r=!1;if((void 0===t||t<0)&&(t=0),t>this.length)return"";if((void 0===n||n>this.length)&&(n=this.length),n<=0)return"";if(n>>>=0,t>>>=0,n<=t)return"";for(e||(e="utf8");;)switch(e){case"hex":return T(this,t,n);case"utf8":case"utf-8":return C(this,t,n);case"ascii":return P(this,t,n);case"latin1":case"binary":return N(this,t,n);case"base64":return _(this,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return F(this,t,n);default:if(r)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),r=!0}}function g(e,t,n){var r=e[t];e[t]=e[n],e[n]=r}function v(e,t,n,r,s){if(0===e.length)return-1;if("string"==typeof n?(r=n,n=0):n>2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),n=+n,isNaN(n)&&(n=s?0:e.length-1),n<0&&(n=e.length+n),n>=e.length){if(s)return-1;n=e.length-1}else if(n<0){if(!s)return-1;n=0}if("string"==typeof t&&(t=i.from(t,r)),i.isBuffer(t))return 0===t.length?-1:b(e,t,n,r,s);if("number"==typeof t)return t&=255,"function"==typeof Uint8Array.prototype.indexOf?s?Uint8Array.prototype.indexOf.call(e,t,n):Uint8Array.prototype.lastIndexOf.call(e,t,n):b(e,[t],n,r,s);throw new TypeError("val must be string, number or Buffer")}function b(e,t,n,r,i){function s(e,t){return 1===o?e[t]:e.readUInt16BE(t*o)}var o=1,a=e.length,u=t.length;if(void 0!==r&&("ucs2"===(r=String(r).toLowerCase())||"ucs-2"===r||"utf16le"===r||"utf-16le"===r)){if(e.length<2||t.length<2)return-1;o=2,a/=2,u/=2,n/=2}var c;if(i){var l=-1;for(c=n;ca&&(n=a-u),c=n;c>=0;c--){for(var p=!0,h=0;hi&&(r=i):r=i;var s=t.length;if(s%2!=0)throw new TypeError("Invalid hex string");r>s/2&&(r=s/2);for(var o=0;o239?4:s>223?3:s>191?2:1;if(i+a<=n){var u,c,l,p;switch(a){case 1:s<128&&(o=s);break;case 2:u=e[i+1],128==(192&u)&&(p=(31&s)<<6|63&u)>127&&(o=p);break;case 3:u=e[i+1],c=e[i+2],128==(192&u)&&128==(192&c)&&(p=(15&s)<<12|(63&u)<<6|63&c)>2047&&(p<55296||p>57343)&&(o=p);break;case 4:u=e[i+1],c=e[i+2],l=e[i+3],128==(192&u)&&128==(192&c)&&128==(192&l)&&(p=(15&s)<<18|(63&u)<<12|(63&c)<<6|63&l)>65535&&p<1114112&&(o=p)}}null===o?(o=65533,a=1):o>65535&&(o-=65536,r.push(o>>>10&1023|55296),o=56320|1023&o),r.push(o),i+=a}return L(r)}function L(e){var t=e.length;if(t<=Z)return String.fromCharCode.apply(String,e);for(var n="",r=0;rr)&&(n=r);for(var i="",s=t;sn)throw new RangeError("Trying to access beyond buffer length")}function O(e,t,n,r,s,o){if(!i.isBuffer(e))throw new TypeError('"buffer" argument must be a Buffer instance');if(t>s||te.length)throw new RangeError("Index out of range")}function B(e,t,n,r,i,s){if(n+r>e.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("Index out of range")}function R(e,t,n,r,i){return t=+t,n>>>=0,i||B(e,t,n,4,3.4028234663852886e38,-3.4028234663852886e38),Y.write(e,t,n,r,23,4),n+4}function I(e,t,n,r,i){return t=+t,n>>>=0,i||B(e,t,n,8,1.7976931348623157e308,-1.7976931348623157e308),Y.write(e,t,n,r,52,8),n+8}function j(e){if(e=M(e).replace(Q,""),e.length<2)return"";for(;e.length%4!=0;)e+="=";return e}function M(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}function D(e){return e<16?"0"+e.toString(16):e.toString(16)}function V(e,t){t=t||1/0;for(var n,r=e.length,i=null,s=[],o=0;o55295&&n<57344){if(!i){if(n>56319){(t-=3)>-1&&s.push(239,191,189);continue}if(o+1===r){(t-=3)>-1&&s.push(239,191,189);continue}i=n;continue}if(n<56320){(t-=3)>-1&&s.push(239,191,189),i=n;continue}n=65536+(i-55296<<10|n-56320)}else i&&(t-=3)>-1&&s.push(239,191,189);if(i=null,n<128){if((t-=1)<0)break;s.push(n)}else if(n<2048){if((t-=2)<0)break;s.push(n>>6|192,63&n|128)}else if(n<65536){if((t-=3)<0)break;s.push(n>>12|224,n>>6&63|128,63&n|128)}else{if(!(n<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;s.push(n>>18|240,n>>12&63|128,n>>6&63|128,63&n|128)}}return s}function q(e){for(var t=[],n=0;n>8,i=n%256,s.push(i),s.push(r);return s}function z(e){return J.toByteArray(j(e))}function W(e,t,n,r){for(var i=0;i=t.length||i>=e.length);++i)t[i+n]=e[i];return i}function G(e){return e!==e}var J=e("base64-js"),Y=e("ieee754");n.Buffer=i,n.SlowBuffer=d,n.INSPECT_MAX_BYTES=50;var H=2147483647;n.kMaxLength=H,i.TYPED_ARRAY_SUPPORT=function(){try{var e=new Uint8Array(1);return e.__proto__={__proto__:Uint8Array.prototype,foo:function(){return 42}},42===e.foo()}catch(e){return!1}}(),i.TYPED_ARRAY_SUPPORT||"undefined"==typeof console||"function"!=typeof console.error||console.error("This browser lacks typed array (Uint8Array) support which is required by `buffer` v5.x. Use `buffer` v4.x if you require old browser support."),"undefined"!=typeof Symbol&&Symbol.species&&i[Symbol.species]===i&&Object.defineProperty(i,Symbol.species,{value:null,configurable:!0,enumerable:!1,writable:!1}),i.poolSize=8192,i.from=function(e,t,n){return s(e,t,n)},i.prototype.__proto__=Uint8Array.prototype,i.__proto__=Uint8Array,i.alloc=function(e,t,n){return a(e,t,n)},i.allocUnsafe=function(e){return u(e)},i.allocUnsafeSlow=function(e){return u(e)},i.isBuffer=function(e){return null!=e&&!0===e._isBuffer},i.compare=function(e,t){if(!i.isBuffer(e)||!i.isBuffer(t))throw new TypeError("Arguments must be Buffers");if(e===t)return 0;for(var n=e.length,r=t.length,s=0,o=Math.min(n,r);s0&&(e=this.toString("hex",0,t).match(/.{2}/g).join(" "),this.length>t&&(e+=" ... ")),""},i.prototype.compare=function(e,t,n,r,s){if(!i.isBuffer(e))throw new TypeError("Argument must be a Buffer");if(void 0===t&&(t=0),void 0===n&&(n=e?e.length:0),void 0===r&&(r=0),void 0===s&&(s=this.length),t<0||n>e.length||r<0||s>this.length)throw new RangeError("out of range index");if(r>=s&&t>=n)return 0;if(r>=s)return-1;if(t>=n)return 1;if(t>>>=0,n>>>=0,r>>>=0,s>>>=0,this===e)return 0;for(var o=s-r,a=n-t,u=Math.min(o,a),c=this.slice(r,s),l=e.slice(t,n),p=0;p>>=0,isFinite(n)?(n>>>=0,void 0===r&&(r="utf8")):(r=n,n=void 0)}var i=this.length-t;if((void 0===n||n>i)&&(n=i),e.length>0&&(n<0||t<0)||t>this.length)throw new RangeError("Attempt to write outside buffer bounds");r||(r="utf8");for(var s=!1;;)switch(r){case"hex":return x(this,e,t,n);case"utf8":case"utf-8":return w(this,e,t,n);case"ascii":return E(this,e,t,n);case"latin1":case"binary":return S(this,e,t,n);case"base64":return k(this,e,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return A(this,e,t,n);default:if(s)throw new TypeError("Unknown encoding: "+r);r=(""+r).toLowerCase(),s=!0}},i.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var Z=4096;i.prototype.slice=function(e,t){var n=this.length;e=~~e,t=void 0===t?n:~~t,e<0?(e+=n)<0&&(e=0):e>n&&(e=n),t<0?(t+=n)<0&&(t=0):t>n&&(t=n),t>>=0,t>>>=0,n||$(e,t,this.length);for(var r=this[e],i=1,s=0;++s>>=0,t>>>=0,n||$(e,t,this.length);for(var r=this[e+--t],i=1;t>0&&(i*=256);)r+=this[e+--t]*i;return r},i.prototype.readUInt8=function(e,t){return e>>>=0,t||$(e,1,this.length),this[e]},i.prototype.readUInt16LE=function(e,t){return e>>>=0,t||$(e,2,this.length),this[e]|this[e+1]<<8},i.prototype.readUInt16BE=function(e,t){return e>>>=0,t||$(e,2,this.length),this[e]<<8|this[e+1]},i.prototype.readUInt32LE=function(e,t){return e>>>=0,t||$(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},i.prototype.readUInt32BE=function(e,t){return e>>>=0,t||$(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},i.prototype.readIntLE=function(e,t,n){e>>>=0,t>>>=0,n||$(e,t,this.length);for(var r=this[e],i=1,s=0;++s=i&&(r-=Math.pow(2,8*t)),r},i.prototype.readIntBE=function(e,t,n){e>>>=0,t>>>=0,n||$(e,t,this.length);for(var r=t,i=1,s=this[e+--r];r>0&&(i*=256);)s+=this[e+--r]*i;return i*=128,s>=i&&(s-=Math.pow(2,8*t)),s},i.prototype.readInt8=function(e,t){return e>>>=0,t||$(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},i.prototype.readInt16LE=function(e,t){e>>>=0,t||$(e,2,this.length);var n=this[e]|this[e+1]<<8;return 32768&n?4294901760|n:n},i.prototype.readInt16BE=function(e,t){e>>>=0,t||$(e,2,this.length);var n=this[e+1]|this[e]<<8;return 32768&n?4294901760|n:n},i.prototype.readInt32LE=function(e,t){return e>>>=0,t||$(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},i.prototype.readInt32BE=function(e,t){return e>>>=0,t||$(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},i.prototype.readFloatLE=function(e,t){return e>>>=0,t||$(e,4,this.length),Y.read(this,e,!0,23,4)},i.prototype.readFloatBE=function(e,t){return e>>>=0,t||$(e,4,this.length),Y.read(this,e,!1,23,4)},i.prototype.readDoubleLE=function(e,t){return e>>>=0,t||$(e,8,this.length),Y.read(this,e,!0,52,8)},i.prototype.readDoubleBE=function(e,t){return e>>>=0,t||$(e,8,this.length),Y.read(this,e,!1,52,8)},i.prototype.writeUIntLE=function(e,t,n,r){if(e=+e,t>>>=0,n>>>=0,!r){O(this,e,t,n,Math.pow(2,8*n)-1,0)}var i=1,s=0;for(this[t]=255&e;++s>>=0,n>>>=0,!r){O(this,e,t,n,Math.pow(2,8*n)-1,0)}var i=n-1,s=1;for(this[t+i]=255&e;--i>=0&&(s*=256);)this[t+i]=e/s&255;return t+n},i.prototype.writeUInt8=function(e,t,n){return e=+e,t>>>=0,n||O(this,e,t,1,255,0),this[t]=255&e,t+1},i.prototype.writeUInt16LE=function(e,t,n){return e=+e,t>>>=0,n||O(this,e,t,2,65535,0),this[t]=255&e,this[t+1]=e>>>8,t+2},i.prototype.writeUInt16BE=function(e,t,n){return e=+e,t>>>=0,n||O(this,e,t,2,65535,0),this[t]=e>>>8,this[t+1]=255&e,t+2},i.prototype.writeUInt32LE=function(e,t,n){return e=+e,t>>>=0,n||O(this,e,t,4,4294967295,0),this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e,t+4},i.prototype.writeUInt32BE=function(e,t,n){return e=+e,t>>>=0,n||O(this,e,t,4,4294967295,0),this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e,t+4},i.prototype.writeIntLE=function(e,t,n,r){if(e=+e,t>>>=0,!r){var i=Math.pow(2,8*n-1);O(this,e,t,n,i-1,-i)}var s=0,o=1,a=0;for(this[t]=255&e;++s>0)-a&255;return t+n},i.prototype.writeIntBE=function(e,t,n,r){if(e=+e,t>>>=0,!r){var i=Math.pow(2,8*n-1);O(this,e,t,n,i-1,-i)}var s=n-1,o=1,a=0;for(this[t+s]=255&e;--s>=0&&(o*=256);)e<0&&0===a&&0!==this[t+s+1]&&(a=1),this[t+s]=(e/o>>0)-a&255;return t+n},i.prototype.writeInt8=function(e,t,n){return e=+e,t>>>=0,n||O(this,e,t,1,127,-128),e<0&&(e=255+e+1),this[t]=255&e,t+1},i.prototype.writeInt16LE=function(e,t,n){return e=+e,t>>>=0,n||O(this,e,t,2,32767,-32768),this[t]=255&e,this[t+1]=e>>>8,t+2},i.prototype.writeInt16BE=function(e,t,n){return e=+e,t>>>=0,n||O(this,e,t,2,32767,-32768),this[t]=e>>>8,this[t+1]=255&e,t+2},i.prototype.writeInt32LE=function(e,t,n){return e=+e,t>>>=0,n||O(this,e,t,4,2147483647,-2147483648),this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24,t+4},i.prototype.writeInt32BE=function(e,t,n){return e=+e,t>>>=0,n||O(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e,t+4},i.prototype.writeFloatLE=function(e,t,n){return R(this,e,t,!0,n)},i.prototype.writeFloatBE=function(e,t,n){return R(this,e,t,!1,n)},i.prototype.writeDoubleLE=function(e,t,n){return I(this,e,t,!0,n)},i.prototype.writeDoubleBE=function(e,t,n){return I(this,e,t,!1,n)},i.prototype.copy=function(e,t,n,r){if(n||(n=0),r||0===r||(r=this.length),t>=e.length&&(t=e.length),t||(t=0),r>0&&r=this.length)throw new RangeError("sourceStart out of bounds");if(r<0)throw new RangeError("sourceEnd out of bounds");r>this.length&&(r=this.length),e.length-t=0;--i)e[i+t]=this[i+n];else if(s<1e3)for(i=0;i>>=0,n=void 0===n?this.length:n>>>0,e||(e=0);var o;if("number"==typeof e)for(o=t;o>1,l=-7,p=n?i-1:0,h=n?-1:1,f=e[t+p];for(p+=h,s=f&(1<<-l)-1,f>>=-l,l+=a;l>0;s=256*s+e[t+p],p+=h,l-=8);for(o=s&(1<<-l)-1,s>>=-l,l+=r;l>0;o=256*o+e[t+p],p+=h,l-=8);if(0===s)s=1-c;else{if(s===u)return o?NaN:1/0*(f?-1:1);o+=Math.pow(2,r),s-=c}return(f?-1:1)*o*Math.pow(2,s-r)},n.write=function(e,t,n,r,i,s){var o,a,u,c=8*s-i-1,l=(1<>1,h=23===i?Math.pow(2,-24)-Math.pow(2,-77):0,f=r?0:s-1,d=r?1:-1,y=t<0||0===t&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(a=isNaN(t)?1:0,o=l):(o=Math.floor(Math.log(t)/Math.LN2),t*(u=Math.pow(2,-o))<1&&(o--,u*=2),t+=o+p>=1?h/u:h*Math.pow(2,1-p),t*u>=2&&(o++,u/=2),o+p>=l?(a=0,o=l):o+p>=1?(a=(t*u-1)*Math.pow(2,i),o+=p):(a=t*Math.pow(2,p-1)*Math.pow(2,i),o=0));i>=8;e[n+f]=255&a,f+=d,a/=256,i-=8);for(o=o<0;e[n+f]=255&o,f+=d,o/=256,c-=8);e[n+f-d]|=128*y}},{}],8:[function(e,t,n){"use strict";function r(e,t){if(Function.prototype.$asyncspawn||Object.defineProperty(Function.prototype,"$asyncspawn",{value:r,enumerable:!1,configurable:!0,writable:!0}),this instanceof Function){var n=this;return new e(function(e,r){function i(t,n){var o;try{if(o=t.call(s,n),o.done){if(o.value!==e){if(o.value&&o.value===o.value.then)return o.value(e,r);e&&e(o.value),e=null}return}o.value.then?o.value.then(function(e){i(s.next,e)},function(e){i(s.throw,e)}):i(s.next,o.value)}catch(e){return r&&r(e),void(r=null)}}var s=n.call(t,e,r);i(s.next)})}}var i=function(e,t){for(var n=t.toString(),r="return "+n,i=n.match(/.*\(([^)]*)\)/)[1],s=/['"]!!!([^'"]*)['"]/g,o=[];;){var a=s.exec(r);if(!a)break;o.push(a)}return o.reverse().forEach(function(t){r=r.slice(0,t.index)+e[t[1]]+r.substr(t.index+t[0].length)}),r=r.replace(/\/\*[^*]*\*\//g," ").replace(/\s+/g," "),new Function(i,r)()}({zousan:e("./zousan").toString(),thenable:e("./thenableFactory").toString()},function e(t,n){function r(){return i.apply(t,arguments)}Function.prototype.$asyncbind||Object.defineProperty(Function.prototype,"$asyncbind",{value:e,enumerable:!1,configurable:!0,writable:!0}),e.trampoline||(e.trampoline=function(e,t,n,r,i){return function s(o){for(;o;){if(o.then)return o=o.then(s,r),i?void 0:o;try{
+if(o.pop){if(o.length)return o.pop()?t.call(e):o;o=n}else o=o.call(e)}catch(e){return r(e)}}}}),e.LazyThenable||(e.LazyThenable="!!!thenable"(),e.EagerThenable=e.Thenable=(e.EagerThenableFactory="!!!zousan")());var i=this;switch(n){case!0:return new e.Thenable(r);case 0:return new e.LazyThenable(r);case void 0:return r.then=r,r;default:return function(){try{return i.apply(t,arguments)}catch(e){return n(e)}}}});i(),r(),t.exports={$asyncbind:i,$asyncspawn:r}},{"./thenableFactory":9,"./zousan":10}],9:[function(e,t,n){t.exports=function(){function e(e){return e&&e instanceof Object&&"function"==typeof e.then}function t(n,r,i){try{var s=i?i(r):r;if(n===s)return n.reject(new TypeError("Promise resolution loop"));e(s)?s.then(function(e){t(n,e)},function(e){n.reject(e)}):n.resolve(s)}catch(e){n.reject(e)}}function n(){}function r(e){}function i(e,t){this.resolve=e,this.reject=t}function s(r,i){var s=new n;try{this._resolver(function(n){return e(n)?n.then(r,i):t(s,n,r)},function(e){t(s,e,i)})}catch(e){t(s,e,i)}return s}function o(e){this._resolver=e,this.then=s}return n.prototype={resolve:r,reject:r,then:i},o.resolve=function(e){return o.isThenable(e)?e:{then:function(t){return t(e)}}},o.isThenable=e,o}},{}],10:[function(e,t,n){(function(e){"use strict";t.exports=function(t){function n(e){if(e){var t=this;e(function(e){t.resolve(e)},function(e){t.reject(e)})}}function r(e,t){if("function"==typeof e.y)try{var n=e.y.call(void 0,t);e.p.resolve(n)}catch(t){e.p.reject(t)}else e.p.resolve(t)}function i(e,t){if("function"==typeof e.n)try{var n=e.n.call(void 0,t);e.p.resolve(n)}catch(t){e.p.reject(t)}else e.p.reject(t)}t=t||"object"==typeof e&&e.nextTick||"function"==typeof setImmediate&&setImmediate||function(e){setTimeout(e,0)};var s=function(){function e(){for(;n.length-r;){try{n[r]()}catch(e){}n[r++]=void 0,r===i&&(n.splice(0,i),r=0)}}var n=[],r=0,i=1024;return function(i){n.push(i),n.length-r==1&&t(e)}}();return n.prototype={resolve:function(e){if(void 0===this.state){if(e===this)return this.reject(new TypeError("Attempt to resolve promise with self"));var t=this;if(e&&("function"==typeof e||"object"==typeof e))try{var n=0,i=e.then;if("function"==typeof i)return void i.call(e,function(e){n++||t.resolve(e)},function(e){n++||t.reject(e)})}catch(e){return void(n||this.reject(e))}this.state=r,this.v=e,t.c&&s(function(){for(var n=0,i=t.c.length;n]*>)(.*)/i,/(.*)(<\/script>)(.*)/i],o=0,a=!0;t=t.split("\n");for(var u=0;u0){if(!a)return t(e);delete e.async}return void(!a&&i?t():(e.type="ReturnStatement",e.$mapped=!0,e.argument={type:"CallExpression",callee:A(s,[n]).$error,arguments:[e.argument]}))}return"TryStatement"===e.type?(i++,t(e),void i--):o(e).isFunction?(r++,t(e),void r--):void t(e)}if(r>0){if(!o(e).isAsync)return t(e);delete e.async}return e.$mapped=!0,void(o(e.argument).isUnaryExpression&&"void"===e.argument.operator?e.argument=e.argument.argument:e.argument={type:"CallExpression",callee:A(s,[n]).$return,arguments:e.argument?[e.argument]:[]})},t)}function $(e,t){return Array.isArray(e)?e.map(function(e){return $(e,t)}):(y.treeWalker(e,function(e,t,n){if(t(),"ConditionalExpression"===e.type&&(u(e.alternate)||u(e.consequent))){h(E("condOp"));i(e,L(y.part("if ($0) return $1 ; return $2",[e.test,e.consequent,e.alternate]).body))}},t),e)}function O(e,t){return Array.isArray(e)?e.map(function(e){return O(e,t)}):(y.treeWalker(e,function(e,t,n){if(t(),"LogicalExpression"===e.type&&u(e.right)){var r,s=h(E("logical"+("&&"===e.operator?"And":"Or")));if("||"===e.operator)r="var $0; if (!($0 = $1)) {$0 = $2} return $0";else{if("&&"!==e.operator)throw new Error(v(e)+"Illegal logical operator: "+e.operator);r="var $0; if ($0 = $1) {$0 = $2} return $0"}i(e,L(y.part(r,[s,e.left,e.right]).body))}},t),e)}function B(e,t,n){if("SwitchCase"!==e.type&&o(e).isBlockStatement)for(var r=0;r { $$setMapped: while (q) { if (q.then) "+(1===s?" return void q.then($idTrampoline, $exit); ":" return q.then($idTrampoline, $exit); ")+" try { if (q.pop) if (q.length) return q.pop() ? $idContinuation.call(this) : q; else q = $idStep; else q = q.call(this) } catch (_exception) { return $exit(_exception); } } }))($idIter)":"($idTrampoline = (function (q) { $$setMapped: while (q) { if (q.then) "+(1===s?" return void q.then($idTrampoline, $exit); ":" return q.then($idTrampoline, $exit); ")+" try { if (q.pop) if (q.length) return q.pop() ? $idContinuation.call(this) : q; else q = $idStep; else q = q.call(this) } catch (_exception) { return $exit(_exception); } } }).bind(this))($idIter)",{setMapped:function(e){return e.$mapped=!0,e},idTrampoline:E,exit:$,idIter:S,idContinuation:_,idStep:k}).expr:y.part("(Function.$0.trampoline(this,$1,$2,$3,$5)($4))",[me.asyncbind,_,k,$,S,b(1===s)]).expr,l.push({type:"ReturnStatement",argument:F}),l.push({$label:e.$label,type:"FunctionDeclaration",id:S,params:[],body:{type:"BlockStatement",body:m}}),d&&l.push({type:"FunctionDeclaration",id:k,params:[],body:{type:"BlockStatement",body:[d,P]}}),!p||"VariableDeclaration"!==p.type||"let"!==p.kind&&"const"!==p.kind?(l.push(x),t[0].replace(l.map(r))):("const"===p.kind&&(p.kind="let"),t[0].replace([{type:"BlockStatement",body:l.map(r)},r(x)]))}}function Y(e,t){return y.treeWalker(e,function(e,t,s){function a(e){return{type:"ReturnStatement",argument:{type:"UnaryExpression",operator:"void",prefix:!0,argument:P(e||S)}}}function c(e,t){if("BreakStatement"===e.type)i(e,r(A(e.label&&n.generatedSymbolPrefix+"Loop_"+e.label.name+"_exit")));else if("ContinueStatement"===e.type)i(e,r(a(e.label&&n.generatedSymbolPrefix+"Loop_"+e.label.name+"_next")));else if(o(e).isFunction)return!0;t()}"ForInStatement"===e.type&&u(e)?W(e,s):"ForOfStatement"===e.type&&u(e)&&G(e,s),t();var p;if(o(e).isLoop&&u(e)){var f=e.init,d=e.test||b(!0),g=e.update,v=e.body,x=l(v);f&&(o(f).isStatement||(f={type:"ExpressionStatement",expression:f})),g=g&&{type:"ExpressionStatement",expression:g},v=o(v).isBlockStatement?r(v).body:[r(v)];var w=e.$label&&e.$label.name;w="Loop_"+(w||ye++);var E=n.generatedSymbolPrefix+(w+"_exit"),S=n.generatedSymbolPrefix+(w+"_next"),k=h(n.generatedSymbolPrefix+w),A=function(e){return{type:"ReturnStatement",argument:{type:"UnaryExpression",operator:"void",prefix:!0,argument:{type:"CallExpression",callee:h(e||E),arguments:[]}}}},_=C(S,[{type:"ReturnStatement",argument:{type:"CallExpression",callee:x?m(k):k,arguments:[h(E),me.error]}}]);g&&_.body.body.unshift(g);for(var L=0;L0&&o(e).isAsync)return delete e.async,e.argument={type:"CallExpression",callee:"ThrowStatement"===e.type?me.error:me.return,arguments:e.argument?[e.argument]:[]},void(e.type="ReturnStatement");n(e)})}function K(e,t){if(n.noRuntime)throw new Error("Nodent: 'noRuntime' option only compatible with -promise and -engine modes");return y.part("{ return (function*($return,$error){ $:body }).$asyncspawn(Promise,this) }",{return:me.return,error:me.error,asyncspawn:me.asyncspawn,body:X(e).concat(t?[{type:"ReturnStatement",argument:me.return}]:[])}).body[0]}function ee(e){e.$asyncgetwarninig||(e.$asyncgetwarninig=!0,d(v(e)+"'async get "+printNode(e)+"(){...}' is non-standard. See https://github.com/MatAtBread/nodent#differences-from-the-es7-specification"))}function te(e,t){function s(e,t){y.treeWalker(e,function(n,r,i){n!==e&&o(n).isFunction||(o(n).isAwait?t?(n.$hidden=!0,r()):(delete n.operator,n.delegate=!1,n.type="YieldExpression",r()):r())})}function a(e){var t=n.promises;n.promises=!0,_(e,!0),n.promises=t}function u(e){return"BlockStatement"!==e.body.type&&(e.body={type:"BlockStatement",body:[{type:"ReturnStatement",argument:e.body}]}),e}function c(e,n){n.$asyncexitwarninig||(n.$asyncexitwarninig=!0,d(v(e)+"'async "+{ReturnStatement:"return",ThrowStatement:"throw"}[e.type]+"' not possible in "+(t?"engine":"generator")+" mode. Using Promises for function at "+v(n)))}y.treeWalker(e,function(e,n,r){n();var l,p,h;if(o(e).isAsync&&o(e).isFunction){var f;(f=x(r[0].parent))&&o(f).isAsync&&"get"===r[0].parent.kind&&ee(r[0].parent.key),(p=H(e))?(c(p,e.body),a(e)):t?"get"!==r[0].parent.kind&&s(e,!0):(l=e,delete l.async,h=w(l),s(l,!1),l=u(l),l.body=K(l.body.body,p),h&&D(l.body.body,[ge]),l.id&&"ExpressionStatement"===r[0].parent.type?(l.type="FunctionDeclaration",r[1].replace(l)):r[0].replace(l))}else(l=x(e))&&o(l).isAsync&&((p=H(l))?(c(p,l),a(e)):t&&"get"!==e.kind||(t?a(e):(e.async=!1,h=w(l),s(l,!1),i(l,u(l)),l.body=K(l.body.body,p)),h&&D(l.body.body,[ge])))});var l=r(n);return n.engine=!1,n.generators=!1,ce(e),oe(e),M(e,l.engine),O(e),$(e),U(e,[q,J,R,I,B]),z(e,"warn"),n.engine=l.engine,n.generators=l.generators,e}function ne(e,t,n){var r=[];return y.treeWalker(e,function(i,s,a){return i===e?s():t(i,a)?void r.push([].concat(a)):void(n||o(i).isScope||s())}),r}function re(e,t){var n=[],i={};if(e=e.filter(function(e){return"ExportNamedDeclaration"!==e[0].parent.type}),e.length){var s={};e.forEach(function(e){function t(e){e in s?i[e]=o.declarations[u]:s[e]=o.declarations[u]}for(var n=e[0],o=n.self,a=(o.kind,[]),u=0;u1?{type:"SequenceExpression",expressions:a}:a[0];"For"!==n.parent.type.slice(0,3)&&(p={type:"ExpressionStatement",expression:p}),n.replace(p)}});var o=Object.keys(s);o.length&&(o=o.map(function(e){return{type:"VariableDeclarator",id:h(e),loc:s[e].loc,start:s[e].start,end:s[e].end}}),n[0]&&"VariableDeclaration"===n[0].type?n[0].declarations=n[0].declarations.concat(o):n.unshift({type:"VariableDeclaration",kind:t,declarations:o}))}return{decls:n,duplicates:i}}function ie(e){if(!e)return[];if(Array.isArray(e))return e.reduce(function(e,t){return e.concat(ie(t.id))},[]);switch(e.type){case"Identifier":return[e.name];case"AssignmentPattern":return ie(e.left);case"ArrayPattern":return e.elements.reduce(function(e,t){return e.concat(ie(t))},[]);case"ObjectPattern":return e.properties.reduce(function(e,t){return e.concat(ie(t))},[]);case"ObjectProperty":case"Property":return ie(e.value);case"RestElement":case"RestProperty":return ie(e.argument)}}function se(e){function t(e){d(v(e)+"Possible assignment to 'const "+printNode(e)+"'")}function n(e){switch(e.type){case"Identifier":"const"===r[e.name]&&t(e);break;case"ArrayPattern":e.elements.forEach(function(e){"const"===r[e.name]&&t(e)});break;case"ObjectPattern":e.properties.forEach(function(e){"const"===r[e.key.name]&&t(e)})}}var r={};y.treeWalker(e,function(e,t,i){var s=o(e).isBlockStatement;if(s){r=Object.create(r);for(var a=0;a=0){var r=n[0];return("left"!=r.field||"ForInStatement"!==r.parent.type&&"ForOfStatement"!==r.parent.type)&&("init"!=r.field||"ForStatement"!==r.parent.type||"const"!==t.kind&&"let"!==t.kind)}}}function s(e,t){return!("FunctionDeclaration"!==e.type||!e.id)&&(o(e).isAsync||!e.$continuation)}var c={TemplateLiteral:function(e){return e.expressions},NewExpression:function(e){return e.arguments},CallExpression:function(e){return e.arguments},SequenceExpression:function(e){return e.expressions},ArrayExpression:function(e){return e.elements},ObjectExpression:function(e){return e.properties.map(function(e){return e.value})}};y.treeWalker(e,function(e,n,s){var a;if(n(),e.type in c&&!e.$hoisted){var s,l=c[e.type](e),p=[];for(a=0;a0;a--)if(e.declarations[a]&&e.declarations[a].init&&u(e.declarations[a].init)){var h={type:"VariableDeclaration",kind:e.kind,declarations:e.declarations.splice(a)},f=s[0];if(!("index"in f))throw new Error("VariableDeclaration not in a block");f.parent[f.field].splice(f.index+1,0,h)}}),se(e);var l=!1;return y.treeWalker(e,function(e,t,r){var i=l;if(l=l||pe(e),o(e).isBlockStatement){if(u(e)){var a,c,p,f,y,m=!r[0].parent||o(r[0].parent).isScope;if(m){c=ne(e,n(["const"]),!1);var g={},b={};c.forEach(function(e){e[0].self.declarations.forEach(function(e){ie(e.id).forEach(function(t){g[t]||b[t]?(delete g[t],b[t]=e):g[t]=e})})}),c.forEach(function(e){for(var t=0;t=0&&"ReturnStatement"===i[1].self.type){var s=e.$thisCallName,a=r(de[s].def.body.body);de[s].$inlined=!0,o(i[1].self).isJump||a.push({type:"ReturnStatement"}),i[1].replace(a)}});var n=Object.keys(de).map(function(e){return de[e].$inlined&&de[e].def});y.treeWalker(e,function(e,t,r){t(),n.indexOf(e)>=0&&r[0].remove()})}if(!("Program"===e.type&&"module"===e.sourceType||a(e,function(e){return o(e).isES6},!0))){var i=pe(e);!function(e){y.treeWalker(e,function(e,t,n){if("Program"===e.type||"FunctionDeclaration"===e.type||"FunctionExpression"===e.type){var r=i;if(i=i||pe(e)){t();var s="Program"===e.type?e:e.body,o=ne(s,function(e,t){if("FunctionDeclaration"===e.type)return t[0].parent!==s});o=o.map(function(e){return e[0].remove()}),[].push.apply(s.body,o)}else t();i=r}else t()})}(e)}return y.treeWalker(e,function(e,t,n){t(),Object.keys(e).filter(function(e){return"$"===e[0]}).forEach(function(t){delete e[t]})}),e}var de={},ye=1,me={};Object.keys(n).filter(function(e){return"$"===e[0]}).forEach(function(e){me[e.slice(1)]=h(n[e])});var ge=y.part("var $0 = arguments",[me.arguments]).body[0];return n.engine?(e.ast=ue(e.ast,!0),e.ast=te(e.ast,n.engine),e.ast=le(e.ast),fe(e.ast)):n.generators?(e.ast=ue(e.ast),e.ast=te(e.ast),e.ast=le(e.ast),fe(e.ast)):(e.ast=ue(e.ast),_(e.ast)),n.babelTree&&y.treeWalker(e.ast,function(e,t,n){t(),"Literal"===e.type&&i(e,b(e.value))}),e}var y=e("./parser"),m=e("./output");n.printNode=function e(t){if(!t)return"";if(Array.isArray(t))return t.map(e).join("|\n");try{return m(t)}catch(e){return e.message+": "+(t&&t.type)}};var g={start:!0,end:!0,loc:!0,range:!0},v={getScope:function(){return"FunctionDeclaration"===this.node.type||"FunctionExpression"===this.node.type||"Function"===this.node.type||"ObjectMethod"===this.node.type||"ClassMethod"===this.node.type||"ArrowFunctionExpression"===this.node.type&&"BlockStatement"===this.node.body.type?this.node.body.body:"Program"===this.node.type?this.node.body:null},isScope:function(){return"FunctionDeclaration"===this.node.type||"FunctionExpression"===this.node.type||"Function"===this.node.type||"Program"===this.node.type||"ObjectMethod"===this.node.type||"ClassMethod"===this.node.type||"ArrowFunctionExpression"===this.node.type&&"BlockStatement"===this.node.body.type},isFunction:function(){return"FunctionDeclaration"===this.node.type||"FunctionExpression"===this.node.type||"Function"===this.node.type||"ObjectMethod"===this.node.type||"ClassMethod"===this.node.type||"ArrowFunctionExpression"===this.node.type},isClass:function(){return"ClassDeclaration"===this.node.type||"ClassExpression"===this.node.type},isBlockStatement:function(){return"ClassBody"===this.node.type||"Program"===this.node.type||"BlockStatement"===this.node.type?this.node.body:"SwitchCase"===this.node.type&&this.node.consequent},isExpressionStatement:function(){return"ExpressionStatement"===this.node.type},isLiteral:function(){return"Literal"===this.node.type||"BooleanLiteral"===this.node.type||"RegExpLiteral"===this.node.type||"NumericLiteral"===this.node.type||"StringLiteral"===this.node.type||"NullLiteral"===this.node.type},isDirective:function(){return"ExpressionStatement"===this.node.type&&("StringLiteral"===this.node.expression.type||"Literal"===this.node.expression.type&&"string"==typeof this.node.expression.value)},isUnaryExpression:function(){return"UnaryExpression"===this.node.type},isAwait:function(){return"AwaitExpression"===this.node.type&&!this.node.$hidden},isAsync:function(){return this.node.async},isStatement:function(){return null!==this.node.type.match(/[a-zA-Z]+Declaration/)||null!==this.node.type.match(/[a-zA-Z]+Statement/)},isExpression:function(){return null!==this.node.type.match(/[a-zA-Z]+Expression/)},isLoop:function(){return"ForStatement"===this.node.type||"WhileStatement"===this.node.type||"DoWhileStatement"===this.node.type},isJump:function(){return"ReturnStatement"===this.node.type||"ThrowStatement"===this.node.type||"BreakStatement"===this.node.type||"ContinueStatement"===this.node.type},isES6:function(){switch(this.node.type){case"ExportNamedDeclaration":case"ExportSpecifier":case"ExportDefaultDeclaration":case"ExportAllDeclaration":case"ImportDeclaration":case"ImportSpecifier":case"ImportDefaultSpecifier":case"ImportNamespaceSpecifier":case"ArrowFunctionExpression":case"ForOfStatement":case"YieldExpression":case"Super":case"RestElement":case"RestProperty":case"SpreadElement":case"TemplateLiteral":case"ClassDeclaration":case"ClassExpression":return!0;case"VariableDeclaration":return this.node.kind&&"var"!==this.node.kind;case"FunctionDeclaration":case"FunctionExpression":return!!this.node.generator}}},b={};Object.keys(v).forEach(function(e){Object.defineProperty(b,e,{get:v[e]})}),t.exports={printNode:printNode,babelLiteralNode:p,asynchronize:function(e,t,n,r){try{return d(e,t,n,r)}catch(t){if(t instanceof SyntaxError){var i=e.origCode.substr(t.pos-t.loc.column);i=i.split("\n")[0],t.message+=" (nodent)\n"+i+"\n"+i.replace(/[\S ]/g,"-").substring(0,t.loc.column)+"^",t.stack=""}throw t}}}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./output":13,"./parser":14}],13:[function(e,t,n){"use strict";function r(e){var t=y[e.type]||y[e.type+e.operator]||y[e.type+e.operator+(e.prefix?"prefix":"")];return void 0!==t?t:20}function i(e,t,n){var r=this[n||e.type];r?r.call(this,e,t):t.write(e,"/*"+e.type+"?*/ "+t.sourceAt(e.start,e.end))}function s(e,t,n,i){2===i||r(n)0){this.out(e[0],t,e[0].type);for(var r=1,i=e.length;r>":13,"BinaryExpression>>>":13,"BinaryExpression<":12,"BinaryExpression<=":12,"BinaryExpression>":12,"BinaryExpression>=":12,BinaryExpressionin:12,BinaryExpressioninstanceof:12,"BinaryExpression==":11,"BinaryExpression===":11,"BinaryExpression!=":11,"BinaryExpression!==":11,"BinaryExpression&":10,"BinaryExpression^":9,"BinaryExpression|":8,"LogicalExpression&&":7,"LogicalExpression||":6,ConditionalExpression:5,AssignmentPattern:4,AssignmentExpression:4,yield:3,YieldExpression:3,SpreadElement:2,"comma-separated-list":1.5,SequenceExpression:1},m={type:"comma-separated-list"},g={out:i,expr:s,formatParameters:o,Program:function(e,t){var n,r,i=h(t.indent,t.indentLevel),s=t.lineEnd;n=e.body;for(var o=0,a=n.length;o0){t.write(null,s);for(var a=0,u=n.length;a0){this.out(n[0],t,"VariableDeclarator");for(var i=1;i0){for(var n=0;n0)for(var r=0;r ")):(this.formatParameters(e.params,t),t.write(e,"=> ")),"ObjectExpression"===e.body.type||"SequenceExpression"===e.body.type?(t.write(null,"("),this.out(e.body,t,e.body.type),t.write(null,")")):this.out(e.body,t,e.body.type)},ThisExpression:function(e,t){t.write(e,"this")},Super:function(e,t){t.write(e,"super")},RestElement:u=function(e,t){t.write(e,"..."),this.out(e.argument,t,e.argument.type)},SpreadElement:u,YieldExpression:function(e,t){t.write(e,e.delegate?"yield*":"yield"),e.argument&&(t.write(null," "),this.expr(t,e,e.argument))},AwaitExpression:function(e,t){t.write(e,"await "),this.expr(t,e,e.argument)},TemplateLiteral:function(e,t){var n,r=e.quasis,i=e.expressions;t.write(e,"`");for(var s=0,o=i.length;s0)for(var n=e.elements,r=n.length,i=0;;){var s=n[i];if(s&&this.expr(t,m,s),i+=1,(i=r)break;t.lineLength()>t.wrapColumn&&t.write(null,t.lineEnd,h(t.indent,t.indentLevel+1))}t.write(null,"]")},ArrayPattern:l,ObjectExpression:function(e,t){var n,r=h(t.indent,t.indentLevel++),i=t.lineEnd,s=r+t.indent;if(t.write(e,"{"),e.properties.length>0){t.write(null,i);for(var o=e.properties,a=o.length,u=0;n=o[u],t.write(null,s),this.out(n,t,"Property"),++ut.wrapColumn&&t.write(null,t.lineEnd,h(t.indent,t.indentLevel+1));t.write(null,i,r,"}")}else t.write(null,"}");t.indentLevel--},Property:function(e,t){e.method||"get"===e.kind||"set"===e.kind?this.MethodDefinition(e,t):(e.shorthand||(e.computed?(t.write(null,"["),this.out(e.key,t,e.key.type),t.write(null,"]")):this.out(e.key,t,e.key.type),t.write(null,": ")),this.expr(t,m,e.value))},ObjectPattern:function(e,t){if(t.write(e,"{"),e.properties.length>0)for(var n=e.properties,r=n.length,i=0;this.out(n[i],t,"Property"),++i0)for(var i=r.length,s=0;s1&&t.write(e," "),this.expr(t,e,e.argument,!0)):(this.expr(t,e,e.argument),t.write(e,e.operator))},UpdateExpression:function(e,t){e.prefix?(t.write(e,e.operator),this.out(e.argument,t,e.argument.type)):(this.out(e.argument,t,e.argument.type),t.write(e,e.operator))},BinaryExpression:c=function(e,t){var n=e.operator;"in"===n&&t.inForInit&&t.write(null,"("),this.expr(t,e,e.left),t.write(e," ",n," "),this.expr(t,e,e.right,"ArrowFunctionExpression"===e.right.type?2:0),"in"===n&&t.inForInit&&t.write(null,")")},LogicalExpression:c,AssignmentExpression:function(e,t){"ObjectPattern"===e.left.type&&t.write(null,"("),this.BinaryExpression(e,t),"ObjectPattern"===e.left.type&&t.write(null,")")},AssignmentPattern:function(e,t){this.expr(t,e,e.left),t.write(e," = "),this.expr(t,e,e.right)},ConditionalExpression:function(e,t){this.expr(t,e,e.test,!0),t.write(e," ? "),this.expr(t,e,e.consequent),t.write(null," : "),this.expr(t,e,e.alternate)},NewExpression:function(e,t){t.write(e,"new "),this.out(e,t,"CallExpression")},CallExpression:function(e,t){this.expr(t,e,e.callee,"ObjectExpression"===e.callee.type?2:0),t.write(e,"(");var n=e.arguments;if(n.length>0)for(var r=n.length,i=0;i=0&&r({self:i,parent:e,field:a[u],index:!0}):c instanceof Object&&i===c&&r({self:i,parent:e,field:a[u]})}})}return n||(n=[{self:e}],n.replace=function(e,t){n[e].replace(t)}),t(e,s,n),e}function s(t,n){var r=[],s={ecmaVersion:8,allowHashBang:!0,allowReturnOutsideFunction:!0,allowImportExportEverywhere:!0,locations:!0,onComment:r};if((!n||!n.noNodentExtensions||parseInt(a.version)<4)&&(h||(parseInt(a.version)<4&&console.warn("Nodent: Warning - noNodentExtensions option requires acorn >=v4.x. Extensions installed."),e("acorn-es7-plugin")(a),h=!0),s.plugins=s.plugins||{},s.plugins.asyncawait={asyncExits:!0,awaitAnywhere:!0}),n)for(var o in n)"noNodentExtensions"!==o&&(s[o]=n[o]);var u=a.parse(t,s);return i(u,function(e,t,n){for(t();r.length&&e.loc&&e.loc.start.line>=r[0].loc.start.line&&e.loc.end.line>=r[0].loc.end.line;)e.$comments=e.$comments||[],e.$comments.push(r.shift())}),u}function o(e,t){function n(e,r){if(Array.isArray(r)&&!Array.isArray(e))throw new Error("Can't substitute an array for a node");return r=r||{},Object.keys(e).forEach(function(i){function s(e){return"function"==typeof e&&(e=e()),r=r.concat(e)}function o(e){return"function"==typeof e&&(e=e()),r[i]=e,r}if(!(e[i]instanceof Object))return r[i]=e[i];if(Array.isArray(e[i]))return r[i]=n(e[i],[]);var a;if(a=Array.isArray(r)?s:o,"Identifier"===e[i].type&&"$"===e[i].name[0])return a(t[e[i].name.slice(1)]);if("LabeledStatement"===e[i].type&&"$"===e[i].label.name){var u=e[i].body.expression;return a(t[u.name||u.value])}return a("LabeledStatement"===e[i].type&&"$$"===e[i].label.name.slice(0,2)?t[e[i].label.name.slice(2)](n(e[i]).body):n(e[i]))}),r}f[e]||(f[e]=s(e,{noNodentExtensions:!0,locations:!1,ranges:!1,onComment:null}));var r=n(f[e]);return{body:r.body,expr:"ExpressionStatement"===r.body[0].type?r.body[0].expression:null}}var a=e("acorn"),u=e("acorn/dist/walk"),c={AwaitExpression:function(e,t,n){n(e.argument,t,"Expression")},SwitchStatement:function(e,t,n){n(e.discriminant,t,"Expression");for(var r=0;re)return!1;if((n+=t[r+1])>=e)return!0}}function n(e,n){return e<65?36===e:e<91||(e<97?95===e:e<123||(e<=65535?e>=170&&k.test(String.fromCharCode(e)):!1!==n&&t(e,_)))}function r(e,n){return e<48?36===e:e<58||!(e<65)&&(e<91||(e<97?95===e:e<123||(e<=65535?e>=170&&A.test(String.fromCharCode(e)):!1!==n&&(t(e,_)||t(e,C)))))}function i(e,t){
+return new L(e,{beforeExpr:!0,binop:t})}function s(e,t){return void 0===t&&(t={}),t.keyword=e,T[e]=new L(e,t)}function o(e){return 10===e||13===e||8232===e||8233===e}function a(e,t){return j.call(e,t)}function u(e,t){for(var n=1,r=0;;){O.lastIndex=r;var i=O.exec(e);if(!(i&&i.index=2015&&(t.ecmaVersion-=2009),null==t.allowReserved&&(t.allowReserved=t.ecmaVersion<5),D(t.onToken)){var r=t.onToken;t.onToken=function(e){return r.push(e)}}return D(t.onComment)&&(t.onComment=l(t,t.onComment)),t}function l(e,t){return function(n,r,i,s,o,a){var u={type:n?"Block":"Line",value:r,start:i,end:s};e.locations&&(u.loc=new q(this,o,a)),e.ranges&&(u.range=[i,s]),t.push(u)}}function p(e){return new RegExp("^("+e.replace(/ /g,"|")+")$")}function h(e,t,n,r){return e.type=t,e.end=n,this.options.locations&&(e.loc.end=r),this.options.ranges&&(e.range[1]=n),e}function f(e,t,n,r){try{return new RegExp(e,t)}catch(e){if(void 0!==n)throw e instanceof SyntaxError&&r.raise(n,"Error parsing regular expression: "+e.message),e}}function d(e){return e<=65535?String.fromCharCode(e):(e-=65536,String.fromCharCode(55296+(e>>10),56320+(1023&e)))}function y(e,t){return new W(t,e).parse()}function m(e,t,n){var r=new W(n,e,t);return r.nextToken(),r.parseExpression()}function g(e,t){return new W(t,e)}function v(t,n,r){e.parse_dammit=t,e.LooseParser=n,e.pluginsLoose=r}var b={3:"abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile",5:"class enum extends super const export import",6:"enum",strict:"implements interface let package private protected public static yield",strictBind:"eval arguments"},x="break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this",w={5:x,6:x+" const class extends export import super"},E="ªµºÀ-ÖØ-öø-ˁˆ-ˑˠ-ˤˬˮͰ-ʹͶͷͺ-ͽͿΆΈ-ΊΌΎ-ΡΣ-ϵϷ-ҁҊ-ԯԱ-Ֆՙա-ևא-תװ-ײؠ-يٮٯٱ-ۓەۥۦۮۯۺ-ۼۿܐܒ-ܯݍ-ޥޱߊ-ߪߴߵߺࠀ-ࠕࠚࠤࠨࡀ-ࡘࢠ-ࢴࢶ-ࢽऄ-हऽॐक़-ॡॱ-ঀঅ-ঌএঐও-নপ-রলশ-হঽৎড়ঢ়য়-ৡৰৱਅ-ਊਏਐਓ-ਨਪ-ਰਲਲ਼ਵਸ਼ਸਹਖ਼-ੜਫ਼ੲ-ੴઅ-ઍએ-ઑઓ-નપ-રલળવ-હઽૐૠૡૹଅ-ଌଏଐଓ-ନପ-ରଲଳଵ-ହଽଡ଼ଢ଼ୟ-ୡୱஃஅ-ஊஎ-ஐஒ-கஙசஜஞடணதந-பம-ஹௐఅ-ఌఎ-ఐఒ-నప-హఽౘ-ౚౠౡಀಅ-ಌಎ-ಐಒ-ನಪ-ಳವ-ಹಽೞೠೡೱೲഅ-ഌഎ-ഐഒ-ഺഽൎൔ-ൖൟ-ൡൺ-ൿඅ-ඖක-නඳ-රලව-ෆก-ะาำเ-ๆກຂຄງຈຊຍດ-ທນ-ຟມ-ຣລວສຫອ-ະາຳຽເ-ໄໆໜ-ໟༀཀ-ཇཉ-ཬྈ-ྌက-ဪဿၐ-ၕၚ-ၝၡၥၦၮ-ၰၵ-ႁႎႠ-ჅჇჍა-ჺჼ-ቈቊ-ቍቐ-ቖቘቚ-ቝበ-ኈኊ-ኍነ-ኰኲ-ኵኸ-ኾዀዂ-ዅወ-ዖዘ-ጐጒ-ጕጘ-ፚᎀ-ᎏᎠ-Ᏽᏸ-ᏽᐁ-ᙬᙯ-ᙿᚁ-ᚚᚠ-ᛪᛮ-ᛸᜀ-ᜌᜎ-ᜑᜠ-ᜱᝀ-ᝑᝠ-ᝬᝮ-ᝰក-ឳៗៜᠠ-ᡷᢀ-ᢨᢪᢰ-ᣵᤀ-ᤞᥐ-ᥭᥰ-ᥴᦀ-ᦫᦰ-ᧉᨀ-ᨖᨠ-ᩔᪧᬅ-ᬳᭅ-ᭋᮃ-ᮠᮮᮯᮺ-ᯥᰀ-ᰣᱍ-ᱏᱚ-ᱽᲀ-ᲈᳩ-ᳬᳮ-ᳱᳵᳶᴀ-ᶿḀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙὛὝὟ-ώᾀ-ᾴᾶ-ᾼιῂ-ῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲ-ῴῶ-ῼⁱⁿₐ-ₜℂℇℊ-ℓℕ℘-ℝℤΩℨK-ℹℼ-ℿⅅ-ⅉⅎⅠ-ↈⰀ-Ⱞⰰ-ⱞⱠ-ⳤⳫ-ⳮⳲⳳⴀ-ⴥⴧⴭⴰ-ⵧⵯⶀ-ⶖⶠ-ⶦⶨ-ⶮⶰ-ⶶⶸ-ⶾⷀ-ⷆⷈ-ⷎⷐ-ⷖⷘ-ⷞ々-〇〡-〩〱-〵〸-〼ぁ-ゖ゛-ゟァ-ヺー-ヿㄅ-ㄭㄱ-ㆎㆠ-ㆺㇰ-ㇿ㐀-䶵一-鿕ꀀ-ꒌꓐ-ꓽꔀ-ꘌꘐ-ꘟꘪꘫꙀ-ꙮꙿ-ꚝꚠ-ꛯꜗ-ꜟꜢ-ꞈꞋ-ꞮꞰ-ꞷꟷ-ꠁꠃ-ꠅꠇ-ꠊꠌ-ꠢꡀ-ꡳꢂ-ꢳꣲ-ꣷꣻꣽꤊ-ꤥꤰ-ꥆꥠ-ꥼꦄ-ꦲꧏꧠ-ꧤꧦ-ꧯꧺ-ꧾꨀ-ꨨꩀ-ꩂꩄ-ꩋꩠ-ꩶꩺꩾ-ꪯꪱꪵꪶꪹ-ꪽꫀꫂꫛ-ꫝꫠ-ꫪꫲ-ꫴꬁ-ꬆꬉ-ꬎꬑ-ꬖꬠ-ꬦꬨ-ꬮꬰ-ꭚꭜ-ꭥꭰ-ꯢ가-힣ힰ-ퟆퟋ-ퟻ豈-舘並-龎ff-stﬓ-ﬗיִײַ-ﬨשׁ-זּטּ-לּמּנּסּףּפּצּ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷻﹰ-ﹴﹶ-ﻼA-Za-zヲ-하-ᅦᅧ-ᅬᅭ-ᅲᅳ-ᅵ",S="·̀-ͯ·҃-֑҇-ׇֽֿׁׂׅׄؐ-ًؚ-٩ٰۖ-ۜ۟-۪ۤۧۨ-ۭ۰-۹ܑܰ-݊ަ-ް߀-߉߫-߳ࠖ-࠙ࠛ-ࠣࠥ-ࠧࠩ-࡙࠭-࡛ࣔ-ࣣ࣡-ःऺ-़ा-ॏ॑-ॗॢॣ०-९ঁ-ঃ়া-ৄেৈো-্ৗৢৣ০-৯ਁ-ਃ਼ਾ-ੂੇੈੋ-੍ੑ੦-ੱੵઁ-ઃ઼ા-ૅે-ૉો-્ૢૣ૦-૯ଁ-ଃ଼ା-ୄେୈୋ-୍ୖୗୢୣ୦-୯ஂா-ூெ-ைொ-்ௗ௦-௯ఀ-ఃా-ౄె-ైొ-్ౕౖౢౣ౦-౯ಁ-ಃ಼ಾ-ೄೆ-ೈೊ-್ೕೖೢೣ೦-೯ഁ-ഃാ-ൄെ-ൈൊ-്ൗൢൣ൦-൯ංඃ්ා-ුූෘ-ෟ෦-෯ෲෳัิ-ฺ็-๎๐-๙ັິ-ູົຼ່-ໍ໐-໙༘༙༠-༩༹༵༷༾༿ཱ-྄྆྇ྍ-ྗྙ-ྼ࿆ါ-ှ၀-၉ၖ-ၙၞ-ၠၢ-ၤၧ-ၭၱ-ၴႂ-ႍႏ-ႝ፝-፟፩-፱ᜒ-᜔ᜲ-᜴ᝒᝓᝲᝳ឴-៓៝០-៩᠋-᠍᠐-᠙ᢩᤠ-ᤫᤰ-᤻᥆-᥏᧐-᧚ᨗ-ᨛᩕ-ᩞ᩠-᩿᩼-᪉᪐-᪙᪰-᪽ᬀ-ᬄ᬴-᭄᭐-᭙᭫-᭳ᮀ-ᮂᮡ-ᮭ᮰-᮹᯦-᯳ᰤ-᰷᱀-᱉᱐-᱙᳐-᳔᳒-᳨᳭ᳲ-᳴᳸᳹᷀-᷵᷻-᷿‿⁀⁔⃐-⃥⃜⃡-⃰⳯-⵿⳱ⷠ-〪ⷿ-゙゚〯꘠-꘩꙯ꙴ-꙽ꚞꚟ꛰꛱ꠂ꠆ꠋꠣ-ꠧꢀꢁꢴ-ꣅ꣐-꣙꣠-꣱꤀-꤉ꤦ-꤭ꥇ-꥓ꦀ-ꦃ꦳-꧀꧐-꧙ꧥ꧰-꧹ꨩ-ꨶꩃꩌꩍ꩐-꩙ꩻ-ꩽꪰꪲ-ꪴꪷꪸꪾ꪿꫁ꫫ-ꫯꫵ꫶ꯣ-ꯪ꯬꯭꯰-꯹ﬞ︀-️︠-︯︳︴﹍-﹏0-9_",k=new RegExp("["+E+"]"),A=new RegExp("["+E+S+"]");E=S=null;var _=[0,11,2,25,2,18,2,1,2,14,3,13,35,122,70,52,268,28,4,48,48,31,17,26,6,37,11,29,3,35,5,7,2,4,43,157,19,35,5,35,5,39,9,51,157,310,10,21,11,7,153,5,3,0,2,43,2,1,4,0,3,22,11,22,10,30,66,18,2,1,11,21,11,25,71,55,7,1,65,0,16,3,2,2,2,26,45,28,4,28,36,7,2,27,28,53,11,21,11,18,14,17,111,72,56,50,14,50,785,52,76,44,33,24,27,35,42,34,4,0,13,47,15,3,22,0,2,0,36,17,2,24,85,6,2,0,2,3,2,14,2,9,8,46,39,7,3,1,3,21,2,6,2,1,2,4,4,0,19,0,13,4,159,52,19,3,54,47,21,1,2,0,185,46,42,3,37,47,21,0,60,42,86,25,391,63,32,0,449,56,264,8,2,36,18,0,50,29,881,921,103,110,18,195,2749,1070,4050,582,8634,568,8,30,114,29,19,47,17,3,32,20,6,18,881,68,12,0,67,12,65,0,32,6124,20,754,9486,1,3071,106,6,12,4,8,8,9,5991,84,2,70,2,1,3,0,3,1,3,3,2,11,2,0,2,6,2,64,2,3,3,7,2,6,2,27,2,3,2,4,2,0,4,6,2,339,3,24,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,7,4149,196,60,67,1213,3,2,26,2,1,2,0,3,0,2,9,2,3,2,0,2,0,7,0,5,0,2,0,2,0,2,2,2,1,2,0,3,0,2,0,2,0,2,0,2,0,2,1,2,0,3,3,2,6,2,3,2,3,2,0,2,9,2,16,6,2,2,4,2,16,4421,42710,42,4148,12,221,3,5761,10591,541],C=[509,0,227,0,150,4,294,9,1368,2,2,1,6,3,41,2,5,0,166,1,1306,2,54,14,32,9,16,3,46,10,54,9,7,2,37,13,2,9,52,0,13,2,49,13,10,2,4,9,83,11,7,0,161,11,6,9,7,3,57,0,2,6,3,1,3,2,10,0,11,1,3,6,4,4,193,17,10,9,87,19,13,9,214,6,3,8,28,1,83,16,16,9,82,12,9,9,84,14,5,9,423,9,838,7,2,7,17,9,57,21,2,13,19882,9,135,4,60,6,26,9,1016,45,17,3,19723,1,5319,4,4,5,9,7,3,6,31,3,149,2,1418,49,513,54,5,49,9,0,15,0,23,4,2,14,1361,6,2,16,3,6,2,1,2,4,2214,6,110,6,6,9,792487,239],L=function(e,t){void 0===t&&(t={}),this.label=e,this.keyword=t.keyword,this.beforeExpr=!!t.beforeExpr,this.startsExpr=!!t.startsExpr,this.isLoop=!!t.isLoop,this.isAssign=!!t.isAssign,this.prefix=!!t.prefix,this.postfix=!!t.postfix,this.binop=t.binop||null,this.updateContext=null},P={beforeExpr:!0},N={startsExpr:!0},T={},F={num:new L("num",N),regexp:new L("regexp",N),string:new L("string",N),name:new L("name",N),eof:new L("eof"),bracketL:new L("[",{beforeExpr:!0,startsExpr:!0}),bracketR:new L("]"),braceL:new L("{",{beforeExpr:!0,startsExpr:!0}),braceR:new L("}"),parenL:new L("(",{beforeExpr:!0,startsExpr:!0}),parenR:new L(")"),comma:new L(",",P),semi:new L(";",P),colon:new L(":",P),dot:new L("."),question:new L("?",P),arrow:new L("=>",P),template:new L("template"),ellipsis:new L("...",P),backQuote:new L("`",N),dollarBraceL:new L("${",{beforeExpr:!0,startsExpr:!0}),eq:new L("=",{beforeExpr:!0,isAssign:!0}),assign:new L("_=",{beforeExpr:!0,isAssign:!0}),incDec:new L("++/--",{prefix:!0,postfix:!0,startsExpr:!0}),prefix:new L("prefix",{beforeExpr:!0,prefix:!0,startsExpr:!0}),logicalOR:i("||",1),logicalAND:i("&&",2),bitwiseOR:i("|",3),bitwiseXOR:i("^",4),bitwiseAND:i("&",5),equality:i("==/!=",6),relational:i(">",7),bitShift:i("<>>",8),plusMin:new L("+/-",{beforeExpr:!0,binop:9,prefix:!0,startsExpr:!0}),modulo:i("%",10),star:i("*",10),slash:i("/",10),starstar:new L("**",{beforeExpr:!0}),_break:s("break"),_case:s("case",P),_catch:s("catch"),_continue:s("continue"),_debugger:s("debugger"),_default:s("default",P),_do:s("do",{isLoop:!0,beforeExpr:!0}),_else:s("else",P),_finally:s("finally"),_for:s("for",{isLoop:!0}),_function:s("function",N),_if:s("if"),_return:s("return",P),_switch:s("switch"),_throw:s("throw",P),_try:s("try"),_var:s("var"),_const:s("const"),_while:s("while",{isLoop:!0}),_with:s("with"),_new:s("new",{beforeExpr:!0,startsExpr:!0}),_this:s("this",N),_super:s("super",N),_class:s("class"),_extends:s("extends",P),_export:s("export"),_import:s("import"),_null:s("null",N),_true:s("true",N),_false:s("false",N),_in:s("in",{beforeExpr:!0,binop:7}),_instanceof:s("instanceof",{beforeExpr:!0,binop:7}),_typeof:s("typeof",{beforeExpr:!0,prefix:!0,startsExpr:!0}),_void:s("void",{beforeExpr:!0,prefix:!0,startsExpr:!0}),_delete:s("delete",{beforeExpr:!0,prefix:!0,startsExpr:!0})},$=/\r\n?|\n|\u2028|\u2029/,O=new RegExp($.source,"g"),B=/[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/,R=/(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g,I=Object.prototype,j=I.hasOwnProperty,M=I.toString,D=Array.isArray||function(e){return"[object Array]"===M.call(e)},V=function(e,t){this.line=e,this.column=t};V.prototype.offset=function(e){return new V(this.line,this.column+e)};var q=function(e,t,n){this.start=t,this.end=n,null!==e.sourceFile&&(this.source=e.sourceFile)},U={ecmaVersion:7,sourceType:"script",onInsertedSemicolon:null,onTrailingComma:null,allowReserved:null,allowReturnOutsideFunction:!1,allowImportExportEverywhere:!1,allowHashBang:!1,locations:!1,onToken:null,onComment:null,ranges:!1,program:null,sourceFile:null,directSourceFile:null,preserveParens:!1,plugins:{}},z={},W=function(e,t,n){this.options=e=c(e),this.sourceFile=e.sourceFile,this.keywords=p(w[e.ecmaVersion>=6?6:5]);var r="";if(!e.allowReserved){for(var i=e.ecmaVersion;!(r=b[i]);i--);"module"==e.sourceType&&(r+=" await")}this.reservedWords=p(r);var s=(r?r+" ":"")+b.strict;this.reservedWordsStrict=p(s),this.reservedWordsStrictBind=p(s+" "+b.strictBind),this.input=String(t),this.containsEsc=!1,this.loadPlugins(e.plugins),n?(this.pos=n,this.lineStart=this.input.lastIndexOf("\n",n-1)+1,this.curLine=this.input.slice(0,this.lineStart).split($).length):(this.pos=this.lineStart=0,this.curLine=1),this.type=F.eof,this.value=null,this.start=this.end=this.pos,this.startLoc=this.endLoc=this.curPosition(),this.lastTokEndLoc=this.lastTokStartLoc=null,this.lastTokStart=this.lastTokEnd=this.pos,this.context=this.initialContext(),this.exprAllowed=!0,this.inModule="module"===e.sourceType,this.strict=this.inModule||this.strictDirective(this.pos),this.potentialArrowAt=-1,this.inFunction=this.inGenerator=this.inAsync=!1,this.yieldPos=this.awaitPos=0,this.labels=[],0===this.pos&&e.allowHashBang&&"#!"===this.input.slice(0,2)&&this.skipLineComment(2),this.scopeStack=[],this.enterFunctionScope()};W.prototype.isKeyword=function(e){return this.keywords.test(e)},W.prototype.isReservedWord=function(e){return this.reservedWords.test(e)},W.prototype.extend=function(e,t){this[e]=t(this[e])},W.prototype.loadPlugins=function(e){var t=this;for(var n in e){var r=z[n];if(!r)throw new Error("Plugin '"+n+"' not found");r(t,e[n])}},W.prototype.parse=function(){var e=this.options.program||this.startNode();return this.nextToken(),this.parseTopLevel(e)};var G=W.prototype,J=/^(?:'((?:[^']|\.)*)'|"((?:[^"]|\.)*)"|;)/;G.strictDirective=function(e){for(var t=this;;){R.lastIndex=e,e+=R.exec(t.input)[0].length;var n=J.exec(t.input.slice(e));if(!n)return!1;if("use strict"==(n[1]||n[2]))return!0;e+=n[0].length}},G.eat=function(e){return this.type===e&&(this.next(),!0)},G.isContextual=function(e){return this.type===F.name&&this.value===e},G.eatContextual=function(e){return this.value===e&&this.eat(F.name)},G.expectContextual=function(e){this.eatContextual(e)||this.unexpected()},G.canInsertSemicolon=function(){return this.type===F.eof||this.type===F.braceR||$.test(this.input.slice(this.lastTokEnd,this.start))},G.insertSemicolon=function(){if(this.canInsertSemicolon())return this.options.onInsertedSemicolon&&this.options.onInsertedSemicolon(this.lastTokEnd,this.lastTokEndLoc),!0},G.semicolon=function(){this.eat(F.semi)||this.insertSemicolon()||this.unexpected()},G.afterTrailingComma=function(e,t){if(this.type==e)return this.options.onTrailingComma&&this.options.onTrailingComma(this.lastTokStart,this.lastTokStartLoc),t||this.next(),!0},G.expect=function(e){this.eat(e)||this.unexpected()},G.unexpected=function(e){this.raise(null!=e?e:this.start,"Unexpected token")};var Y=function(){this.shorthandAssign=this.trailingComma=this.parenthesizedAssign=this.parenthesizedBind=-1};G.checkPatternErrors=function(e,t){if(e){e.trailingComma>-1&&this.raiseRecoverable(e.trailingComma,"Comma is not permitted after the rest element");var n=t?e.parenthesizedAssign:e.parenthesizedBind;n>-1&&this.raiseRecoverable(n,"Parenthesized pattern")}},G.checkExpressionErrors=function(e,t){var n=e?e.shorthandAssign:-1;if(!t)return n>=0;n>-1&&this.raise(n,"Shorthand property assignments are valid only in destructuring patterns")},G.checkYieldAwaitInDefaultParams=function(){this.yieldPos&&(!this.awaitPos||this.yieldPos=6&&(e.sourceType=this.options.sourceType),this.finishNode(e,"Program")};var Z={kind:"loop"},Q={kind:"switch"};H.isLet=function(){if(this.type!==F.name||this.options.ecmaVersion<6||"let"!=this.value)return!1;R.lastIndex=this.pos;var e=R.exec(this.input),t=this.pos+e[0].length,i=this.input.charCodeAt(t);if(91===i||123==i)return!0;if(n(i,!0)){for(var s=t+1;r(this.input.charCodeAt(s),!0);)++s;var o=this.input.slice(t,s);if(!this.isKeyword(o))return!0}return!1},H.isAsyncFunction=function(){if(this.type!==F.name||this.options.ecmaVersion<8||"async"!=this.value)return!1;R.lastIndex=this.pos;var e=R.exec(this.input),t=this.pos+e[0].length;return!($.test(this.input.slice(this.pos,t))||"function"!==this.input.slice(t,t+8)||t+8!=this.input.length&&r(this.input.charAt(t+8)))},H.parseStatement=function(e,t,n){var r,i=this.type,s=this.startNode();switch(this.isLet()&&(i=F._var,r="let"),i){case F._break:case F._continue:return this.parseBreakContinueStatement(s,i.keyword);case F._debugger:return this.parseDebuggerStatement(s);case F._do:return this.parseDoStatement(s);case F._for:return this.parseForStatement(s);case F._function:return!e&&this.options.ecmaVersion>=6&&this.unexpected(),this.parseFunctionStatement(s,!1);case F._class:return e||this.unexpected(),this.parseClass(s,!0);case F._if:return this.parseIfStatement(s);case F._return:return this.parseReturnStatement(s);case F._switch:return this.parseSwitchStatement(s);case F._throw:return this.parseThrowStatement(s);case F._try:return this.parseTryStatement(s);case F._const:case F._var:return r=r||this.value,e||"var"==r||this.unexpected(),this.parseVarStatement(s,r);case F._while:return this.parseWhileStatement(s);case F._with:return this.parseWithStatement(s);case F.braceL:return this.parseBlock();case F.semi:return this.parseEmptyStatement(s);case F._export:case F._import:return this.options.allowImportExportEverywhere||(t||this.raise(this.start,"'import' and 'export' may only appear at the top level"),this.inModule||this.raise(this.start,"'import' and 'export' may appear only with 'sourceType: module'")),i===F._import?this.parseImport(s):this.parseExport(s,n);default:if(this.isAsyncFunction()&&e)return this.next(),this.parseFunctionStatement(s,!0);var o=this.value,a=this.parseExpression();return i===F.name&&"Identifier"===a.type&&this.eat(F.colon)?this.parseLabeledStatement(s,o,a):this.parseExpressionStatement(s,a)}},H.parseBreakContinueStatement=function(e,t){var n=this,r="break"==t;this.next(),this.eat(F.semi)||this.insertSemicolon()?e.label=null:this.type!==F.name?this.unexpected():(e.label=this.parseIdent(),this.semicolon());for(var i=0;i=6?this.eat(F.semi):this.semicolon(),this.finishNode(e,"DoWhileStatement")},H.parseForStatement=function(e){if(this.next(),this.labels.push(Z),this.enterLexicalScope(),this.expect(F.parenL),this.type===F.semi)return this.parseFor(e,null);var t=this.isLet();if(this.type===F._var||this.type===F._const||t){var n=this.startNode(),r=t?"let":this.value;return this.next(),this.parseVar(n,!0,r),this.finishNode(n,"VariableDeclaration"),!(this.type===F._in||this.options.ecmaVersion>=6&&this.isContextual("of"))||1!==n.declarations.length||"var"!==r&&n.declarations[0].init?this.parseFor(e,n):this.parseForIn(e,n)}var i=new Y,s=this.parseExpression(!0,i);return this.type===F._in||this.options.ecmaVersion>=6&&this.isContextual("of")?(this.toAssignable(s),this.checkLVal(s),this.checkPatternErrors(i,!0),this.parseForIn(e,s)):(this.checkExpressionErrors(i,!0),this.parseFor(e,s))},H.parseFunctionStatement=function(e,t){return this.next(),this.parseFunction(e,!0,!1,t)},H.isFunction=function(){return this.type===F._function||this.isAsyncFunction()},H.parseIfStatement=function(e){return this.next(),e.test=this.parseParenExpression(),e.consequent=this.parseStatement(!this.strict&&this.isFunction()),e.alternate=this.eat(F._else)?this.parseStatement(!this.strict&&this.isFunction()):null,this.finishNode(e,"IfStatement")},H.parseReturnStatement=function(e){return this.inFunction||this.options.allowReturnOutsideFunction||this.raise(this.start,"'return' outside of function"),this.next(),this.eat(F.semi)||this.insertSemicolon()?e.argument=null:(e.argument=this.parseExpression(),this.semicolon()),this.finishNode(e,"ReturnStatement")},H.parseSwitchStatement=function(e){var t=this;this.next(),e.discriminant=this.parseParenExpression(),e.cases=[],this.expect(F.braceL),this.labels.push(Q),this.enterLexicalScope();for(var n,r=!1;this.type!=F.braceR;)if(t.type===F._case||t.type===F._default){var i=t.type===F._case;n&&t.finishNode(n,"SwitchCase"),e.cases.push(n=t.startNode()),n.consequent=[],t.next(),i?n.test=t.parseExpression():(r&&t.raiseRecoverable(t.lastTokStart,"Multiple default clauses"),r=!0,n.test=null),t.expect(F.colon)}else n||t.unexpected(),n.consequent.push(t.parseStatement(!0));return this.exitLexicalScope(),n&&this.finishNode(n,"SwitchCase"),this.next(),this.labels.pop(),this.finishNode(e,"SwitchStatement")},H.parseThrowStatement=function(e){return this.next(),$.test(this.input.slice(this.lastTokEnd,this.start))&&this.raise(this.lastTokEnd,"Illegal newline after throw"),e.argument=this.parseExpression(),this.semicolon(),this.finishNode(e,"ThrowStatement")};var X=[];H.parseTryStatement=function(e){if(this.next(),e.block=this.parseBlock(),e.handler=null,this.type===F._catch){var t=this.startNode();this.next(),this.expect(F.parenL),t.param=this.parseBindingAtom(),this.enterLexicalScope(),this.checkLVal(t.param,"let"),this.expect(F.parenR),t.body=this.parseBlock(!1),this.exitLexicalScope(),e.handler=this.finishNode(t,"CatchClause")}return e.finalizer=this.eat(F._finally)?this.parseBlock():null,e.handler||e.finalizer||this.raise(e.start,"Missing catch or finally clause"),this.finishNode(e,"TryStatement")},H.parseVarStatement=function(e,t){return this.next(),this.parseVar(e,!1,t),this.semicolon(),this.finishNode(e,"VariableDeclaration")},H.parseWhileStatement=function(e){return this.next(),e.test=this.parseParenExpression(),this.labels.push(Z),e.body=this.parseStatement(!1),this.labels.pop(),this.finishNode(e,"WhileStatement")},H.parseWithStatement=function(e){return this.strict&&this.raise(this.start,"'with' in strict mode"),this.next(),e.object=this.parseParenExpression(),e.body=this.parseStatement(!1),this.finishNode(e,"WithStatement")},H.parseEmptyStatement=function(e){return this.next(),this.finishNode(e,"EmptyStatement")},H.parseLabeledStatement=function(e,t,n){for(var r=this,i=0;i=0;o--){var a=r.labels[o];if(a.statementStart!=e.start)break;a.statementStart=r.start,a.kind=s}return this.labels.push({name:t,kind:s,statementStart:this.start}),e.body=this.parseStatement(!0),("ClassDeclaration"==e.body.type||"VariableDeclaration"==e.body.type&&"var"!=e.body.kind||"FunctionDeclaration"==e.body.type&&(this.strict||e.body.generator))&&this.raiseRecoverable(e.body.start,"Invalid labeled declaration"),this.labels.pop(),e.label=n,this.finishNode(e,"LabeledStatement")},H.parseExpressionStatement=function(e,t){return e.expression=t,this.semicolon(),this.finishNode(e,"ExpressionStatement")},H.parseBlock=function(e){var t=this;void 0===e&&(e=!0);var n=this.startNode();for(n.body=[],this.expect(F.braceL),e&&this.enterLexicalScope();!this.eat(F.braceR);){var r=t.parseStatement(!0);n.body.push(r)}return e&&this.exitLexicalScope(),this.finishNode(n,"BlockStatement")},H.parseFor=function(e,t){return e.init=t,this.expect(F.semi),e.test=this.type===F.semi?null:this.parseExpression(),this.expect(F.semi),e.update=this.type===F.parenR?null:this.parseExpression(),this.expect(F.parenR),this.exitLexicalScope(),e.body=this.parseStatement(!1),this.labels.pop(),this.finishNode(e,"ForStatement")},H.parseForIn=function(e,t){var n=this.type===F._in?"ForInStatement":"ForOfStatement";return this.next(),e.left=t,e.right=this.parseExpression(),this.expect(F.parenR),this.exitLexicalScope(),e.body=this.parseStatement(!1),this.labels.pop(),this.finishNode(e,n)},H.parseVar=function(e,t,n){var r=this;for(e.declarations=[],e.kind=n;;){var i=r.startNode();if(r.parseVarId(i,n),r.eat(F.eq)?i.init=r.parseMaybeAssign(t):"const"!==n||r.type===F._in||r.options.ecmaVersion>=6&&r.isContextual("of")?"Identifier"==i.id.type||t&&(r.type===F._in||r.isContextual("of"))?i.init=null:r.raise(r.lastTokEnd,"Complex binding patterns require an initialization value"):r.unexpected(),e.declarations.push(r.finishNode(i,"VariableDeclarator")),!r.eat(F.comma))break}return e},H.parseVarId=function(e,t){e.id=this.parseBindingAtom(t),this.checkLVal(e.id,t,!1)},H.parseFunction=function(e,t,n,r){this.initFunction(e),this.options.ecmaVersion>=6&&!r&&(e.generator=this.eat(F.star)),this.options.ecmaVersion>=8&&(e.async=!!r),t&&(e.id="nullableID"===t&&this.type!=F.name?null:this.parseIdent(),e.id&&this.checkLVal(e.id,"var"));var i=this.inGenerator,s=this.inAsync,o=this.yieldPos,a=this.awaitPos,u=this.inFunction;return this.inGenerator=e.generator,this.inAsync=e.async,this.yieldPos=0,this.awaitPos=0,this.inFunction=!0,this.enterFunctionScope(),t||(e.id=this.type==F.name?this.parseIdent():null),this.parseFunctionParams(e),this.parseFunctionBody(e,n),this.inGenerator=i,this.inAsync=s,this.yieldPos=o,this.awaitPos=a,this.inFunction=u,this.finishNode(e,t?"FunctionDeclaration":"FunctionExpression")},H.parseFunctionParams=function(e){this.expect(F.parenL),e.params=this.parseBindingList(F.parenR,!1,this.options.ecmaVersion>=8,!0),this.checkYieldAwaitInDefaultParams()},H.parseClass=function(e,t){var n=this;this.next(),this.parseClassId(e,t),this.parseClassSuper(e);var r=this.startNode(),i=!1;for(r.body=[],this.expect(F.braceL);!this.eat(F.braceR);)if(!n.eat(F.semi)){var s=n.startNode(),o=n.eat(F.star),a=!1,u=n.type===F.name&&"static"===n.value;n.parsePropertyName(s),s.static=u&&n.type!==F.parenL,s.static&&(o&&n.unexpected(),o=n.eat(F.star),n.parsePropertyName(s)),n.options.ecmaVersion>=8&&!o&&!s.computed&&"Identifier"===s.key.type&&"async"===s.key.name&&n.type!==F.parenL&&!n.canInsertSemicolon()&&(a=!0,n.parsePropertyName(s)),s.kind="method";var c=!1;if(!s.computed){var l=s.key;o||a||"Identifier"!==l.type||n.type===F.parenL||"get"!==l.name&&"set"!==l.name||(c=!0,s.kind=l.name,l=n.parsePropertyName(s)),!s.static&&("Identifier"===l.type&&"constructor"===l.name||"Literal"===l.type&&"constructor"===l.value)&&(i&&n.raise(l.start,"Duplicate constructor in the same class"),c&&n.raise(l.start,"Constructor can't have get/set modifier"),o&&n.raise(l.start,"Constructor can't be a generator"),a&&n.raise(l.start,"Constructor can't be an async method"),s.kind="constructor",i=!0)}if(n.parseClassMethod(r,s,o,a),c){var p="get"===s.kind?0:1;if(s.value.params.length!==p){var h=s.value.start;"get"===s.kind?n.raiseRecoverable(h,"getter should have no params"):n.raiseRecoverable(h,"setter should have exactly one param")}else"set"===s.kind&&"RestElement"===s.value.params[0].type&&n.raiseRecoverable(s.value.params[0].start,"Setter cannot use rest params")}}return e.body=this.finishNode(r,"ClassBody"),this.finishNode(e,t?"ClassDeclaration":"ClassExpression")},H.parseClassMethod=function(e,t,n,r){t.value=this.parseMethod(n,r),e.body.push(this.finishNode(t,"MethodDefinition"))},H.parseClassId=function(e,t){e.id=this.type===F.name?this.parseIdent():!0===t?this.unexpected():null},H.parseClassSuper=function(e){e.superClass=this.eat(F._extends)?this.parseExprSubscripts():null},H.parseExport=function(e,t){var n=this;if(this.next(),this.eat(F.star))return this.expectContextual("from"),e.source=this.type===F.string?this.parseExprAtom():this.unexpected(),this.semicolon(),this.finishNode(e,"ExportAllDeclaration");if(this.eat(F._default)){this.checkExport(t,"default",this.lastTokStart);var r;if(this.type===F._function||(r=this.isAsyncFunction())){var i=this.startNode();this.next(),r&&this.next(),e.declaration=this.parseFunction(i,"nullableID",!1,r)}else if(this.type===F._class){var s=this.startNode();e.declaration=this.parseClass(s,"nullableID")}else e.declaration=this.parseMaybeAssign(),this.semicolon();return this.finishNode(e,"ExportDefaultDeclaration")}if(this.shouldParseExportStatement())e.declaration=this.parseStatement(!0),"VariableDeclaration"===e.declaration.type?this.checkVariableExport(t,e.declaration.declarations):this.checkExport(t,e.declaration.id.name,e.declaration.id.start),e.specifiers=[],e.source=null;else{if(e.declaration=null,e.specifiers=this.parseExportSpecifiers(t),this.eatContextual("from"))e.source=this.type===F.string?this.parseExprAtom():this.unexpected();else{for(var o=0;o=6&&e)switch(e.type){case"Identifier":this.inAsync&&"await"===e.name&&this.raise(e.start,"Can not use 'await' as identifier inside an async function");break;case"ObjectPattern":case"ArrayPattern":break;case"ObjectExpression":e.type="ObjectPattern";for(var r=0;r=6&&(e.computed||e.method||e.shorthand))){var n,r=e.key;switch(r.type){case"Identifier":n=r.name;break;case"Literal":n=String(r.value);break;default:return}var i=e.kind;if(this.options.ecmaVersion>=6)return void("__proto__"===n&&"init"===i&&(t.proto&&this.raiseRecoverable(r.start,"Redefinition of __proto__ property"),t.proto=!0));n="$"+n;var s=t[n];if(s){var o;o="init"===i?this.strict&&s.init||s.get||s.set:s.init||s[i],o&&this.raiseRecoverable(r.start,"Redefinition of property")}else s=t[n]={init:!1,get:!1,set:!1};s[i]=!0}},ee.parseExpression=function(e,t){var n=this,r=this.start,i=this.startLoc,s=this.parseMaybeAssign(e,t);if(this.type===F.comma){var o=this.startNodeAt(r,i);for(o.expressions=[s];this.eat(F.comma);)o.expressions.push(n.parseMaybeAssign(e,t));return this.finishNode(o,"SequenceExpression")}return s},ee.parseMaybeAssign=function(e,t,n){if(this.inGenerator&&this.isContextual("yield"))return this.parseYield();var r=!1,i=-1,s=-1;t?(i=t.parenthesizedAssign,s=t.trailingComma,t.parenthesizedAssign=t.trailingComma=-1):(t=new Y,r=!0);var o=this.start,a=this.startLoc;this.type!=F.parenL&&this.type!=F.name||(this.potentialArrowAt=this.start);var u=this.parseMaybeConditional(e,t);if(n&&(u=n.call(this,u,o,a)),this.type.isAssign){this.checkPatternErrors(t,!0),r||Y.call(t);var c=this.startNodeAt(o,a);return c.operator=this.value,c.left=this.type===F.eq?this.toAssignable(u):u,t.shorthandAssign=-1,this.checkLVal(u),this.next(),c.right=this.parseMaybeAssign(e),this.finishNode(c,"AssignmentExpression")}return r&&this.checkExpressionErrors(t,!0),i>-1&&(t.parenthesizedAssign=i),s>-1&&(t.trailingComma=s),u},ee.parseMaybeConditional=function(e,t){var n=this.start,r=this.startLoc,i=this.parseExprOps(e,t);if(this.checkExpressionErrors(t))return i;if(this.eat(F.question)){var s=this.startNodeAt(n,r);return s.test=i,s.consequent=this.parseMaybeAssign(),this.expect(F.colon),s.alternate=this.parseMaybeAssign(e),this.finishNode(s,"ConditionalExpression")}return i},ee.parseExprOps=function(e,t){var n=this.start,r=this.startLoc,i=this.parseMaybeUnary(t,!1);return this.checkExpressionErrors(t)?i:i.start==n&&"ArrowFunctionExpression"===i.type?i:this.parseExprOp(i,n,r,-1,e)},ee.parseExprOp=function(e,t,n,r,i){var s=this.type.binop;if(null!=s&&(!i||this.type!==F._in)&&s>r){var o=this.type===F.logicalOR||this.type===F.logicalAND,a=this.value;this.next();var u=this.start,c=this.startLoc,l=this.parseExprOp(this.parseMaybeUnary(null,!1),u,c,s,i),p=this.buildBinary(t,n,e,l,a,o);return this.parseExprOp(p,t,n,r,i)}return e},ee.buildBinary=function(e,t,n,r,i,s){var o=this.startNodeAt(e,t);return o.left=n,o.operator=i,o.right=r,this.finishNode(o,s?"LogicalExpression":"BinaryExpression")},ee.parseMaybeUnary=function(e,t){var n,r=this,i=this.start,s=this.startLoc;if(this.inAsync&&this.isContextual("await"))n=this.parseAwait(e),t=!0;else if(this.type.prefix){var o=this.startNode(),a=this.type===F.incDec;o.operator=this.value,o.prefix=!0,this.next(),o.argument=this.parseMaybeUnary(null,!0),this.checkExpressionErrors(e,!0),a?this.checkLVal(o.argument):this.strict&&"delete"===o.operator&&"Identifier"===o.argument.type?this.raiseRecoverable(o.start,"Deleting local variable in strict mode"):t=!0,n=this.finishNode(o,a?"UpdateExpression":"UnaryExpression")}else{if(n=this.parseExprSubscripts(e),this.checkExpressionErrors(e))return n;for(;this.type.postfix&&!this.canInsertSemicolon();){var u=r.startNodeAt(i,s);u.operator=r.value,u.prefix=!1,u.argument=n,r.checkLVal(n),r.next(),n=r.finishNode(u,"UpdateExpression")}}return!t&&this.eat(F.starstar)?this.buildBinary(i,s,n,this.parseMaybeUnary(null,!1),"**",!1):n},ee.parseExprSubscripts=function(e){var t=this.start,n=this.startLoc,r=this.parseExprAtom(e),i="ArrowFunctionExpression"===r.type&&")"!==this.input.slice(this.lastTokStart,this.lastTokEnd);if(this.checkExpressionErrors(e)||i)return r;var s=this.parseSubscripts(r,t,n);return e&&"MemberExpression"===s.type&&(e.parenthesizedAssign>=s.start&&(e.parenthesizedAssign=-1),e.parenthesizedBind>=s.start&&(e.parenthesizedBind=-1)),s},ee.parseSubscripts=function(e,t,n,r){for(var i,s=this,o=this.options.ecmaVersion>=8&&"Identifier"===e.type&&"async"===e.name&&this.lastTokEnd==e.end&&!this.canInsertSemicolon();;)if((i=s.eat(F.bracketL))||s.eat(F.dot)){var a=s.startNodeAt(t,n);a.object=e,a.property=i?s.parseExpression():s.parseIdent(!0),a.computed=!!i,i&&s.expect(F.bracketR),e=s.finishNode(a,"MemberExpression")}else if(!r&&s.eat(F.parenL)){var u=new Y,c=s.yieldPos,l=s.awaitPos;s.yieldPos=0,s.awaitPos=0;var p=s.parseExprList(F.parenR,s.options.ecmaVersion>=8,!1,u);if(o&&!s.canInsertSemicolon()&&s.eat(F.arrow))return s.checkPatternErrors(u,!1),s.checkYieldAwaitInDefaultParams(),s.yieldPos=c,s.awaitPos=l,s.parseArrowExpression(s.startNodeAt(t,n),p,!0);s.checkExpressionErrors(u,!0),s.yieldPos=c||s.yieldPos,s.awaitPos=l||s.awaitPos;var h=s.startNodeAt(t,n);h.callee=e,h.arguments=p,e=s.finishNode(h,"CallExpression")}else{if(s.type!==F.backQuote)return e;var f=s.startNodeAt(t,n);f.tag=e,f.quasi=s.parseTemplate(),e=s.finishNode(f,"TaggedTemplateExpression")}},ee.parseExprAtom=function(e){var t,n=this.potentialArrowAt==this.start;switch(this.type){case F._super:this.inFunction||this.raise(this.start,"'super' outside of function or class");case F._this:var r=this.type===F._this?"ThisExpression":"Super";return t=this.startNode(),this.next(),this.finishNode(t,r);case F.name:var i=this.start,s=this.startLoc,o=this.parseIdent(this.type!==F.name);if(this.options.ecmaVersion>=8&&"async"===o.name&&!this.canInsertSemicolon()&&this.eat(F._function))return this.parseFunction(this.startNodeAt(i,s),!1,!1,!0);if(n&&!this.canInsertSemicolon()){if(this.eat(F.arrow))return this.parseArrowExpression(this.startNodeAt(i,s),[o],!1);if(this.options.ecmaVersion>=8&&"async"===o.name&&this.type===F.name)return o=this.parseIdent(),!this.canInsertSemicolon()&&this.eat(F.arrow)||this.unexpected(),this.parseArrowExpression(this.startNodeAt(i,s),[o],!0)}return o;case F.regexp:var a=this.value;return t=this.parseLiteral(a.value),t.regex={pattern:a.pattern,flags:a.flags},t;case F.num:case F.string:return this.parseLiteral(this.value);case F._null:case F._true:case F._false:return t=this.startNode(),t.value=this.type===F._null?null:this.type===F._true,t.raw=this.type.keyword,this.next(),this.finishNode(t,"Literal");case F.parenL:var u=this.start,c=this.parseParenAndDistinguishExpression(n);return e&&(e.parenthesizedAssign<0&&!this.isSimpleAssignTarget(c)&&(e.parenthesizedAssign=u),e.parenthesizedBind<0&&(e.parenthesizedBind=u)),c;case F.bracketL:return t=this.startNode(),this.next(),t.elements=this.parseExprList(F.bracketR,!0,!0,e),this.finishNode(t,"ArrayExpression");case F.braceL:return this.parseObj(!1,e);case F._function:return t=this.startNode(),this.next(),this.parseFunction(t,!1);case F._class:return this.parseClass(this.startNode(),!1);case F._new:return this.parseNew();case F.backQuote:return this.parseTemplate();default:this.unexpected()}},ee.parseLiteral=function(e){var t=this.startNode();return t.value=e,t.raw=this.input.slice(this.start,this.end),this.next(),this.finishNode(t,"Literal")},ee.parseParenExpression=function(){this.expect(F.parenL);var e=this.parseExpression();return this.expect(F.parenR),e},ee.parseParenAndDistinguishExpression=function(e){var t,n=this,r=this.start,i=this.startLoc,s=this.options.ecmaVersion>=8;if(this.options.ecmaVersion>=6){this.next();var o,a,u=this.start,c=this.startLoc,l=[],p=!0,h=!1,f=new Y,d=this.yieldPos,y=this.awaitPos;for(this.yieldPos=0,this.awaitPos=0;this.type!==F.parenR;){if(p?p=!1:n.expect(F.comma),s&&n.afterTrailingComma(F.parenR,!0)){h=!0;break}if(n.type===F.ellipsis){o=n.start,l.push(n.parseParenItem(n.parseRest())),n.type===F.comma&&n.raise(n.start,"Comma is not permitted after the rest element");break}n.type!==F.parenL||a||(a=n.start),l.push(n.parseMaybeAssign(!1,f,n.parseParenItem))}var m=this.start,g=this.startLoc;if(this.expect(F.parenR),e&&!this.canInsertSemicolon()&&this.eat(F.arrow))return this.checkPatternErrors(f,!1),this.checkYieldAwaitInDefaultParams(),a&&this.unexpected(a),this.yieldPos=d,this.awaitPos=y,this.parseParenArrowList(r,i,l);l.length&&!h||this.unexpected(this.lastTokStart),o&&this.unexpected(o),this.checkExpressionErrors(f,!0),this.yieldPos=d||this.yieldPos,this.awaitPos=y||this.awaitPos,l.length>1?(t=this.startNodeAt(u,c),t.expressions=l,this.finishNodeAt(t,"SequenceExpression",m,g)):t=l[0]}else t=this.parseParenExpression();if(this.options.preserveParens){var v=this.startNodeAt(r,i);return v.expression=t,this.finishNode(v,"ParenthesizedExpression")}return t},ee.parseParenItem=function(e){return e},ee.parseParenArrowList=function(e,t,n){return this.parseArrowExpression(this.startNodeAt(e,t),n)};var te=[];ee.parseNew=function(){var e=this.startNode(),t=this.parseIdent(!0);if(this.options.ecmaVersion>=6&&this.eat(F.dot))return e.meta=t,e.property=this.parseIdent(!0),"target"!==e.property.name&&this.raiseRecoverable(e.property.start,"The only valid meta property for new is new.target"),this.inFunction||this.raiseRecoverable(e.start,"new.target can only be used in functions"),this.finishNode(e,"MetaProperty");var n=this.start,r=this.startLoc;return e.callee=this.parseSubscripts(this.parseExprAtom(),n,r,!0),this.eat(F.parenL)?e.arguments=this.parseExprList(F.parenR,this.options.ecmaVersion>=8,!1):e.arguments=te,this.finishNode(e,"NewExpression")},ee.parseTemplateElement=function(){var e=this.startNode();return e.value={raw:this.input.slice(this.start,this.end).replace(/\r\n?/g,"\n"),cooked:this.value},this.next(),e.tail=this.type===F.backQuote,this.finishNode(e,"TemplateElement")},ee.parseTemplate=function(){var e=this,t=this.startNode();this.next(),t.expressions=[];var n=this.parseTemplateElement();for(t.quasis=[n];!n.tail;)e.expect(F.dollarBraceL),t.expressions.push(e.parseExpression()),e.expect(F.braceR),t.quasis.push(n=e.parseTemplateElement());return this.next(),this.finishNode(t,"TemplateLiteral")},ee.parseObj=function(e,t){var n=this,r=this.startNode(),i=!0,s={};for(r.properties=[],this.next();!this.eat(F.braceR);){if(i)i=!1;else if(n.expect(F.comma),n.afterTrailingComma(F.braceR))break;var o,a,u,c,l=n.startNode();n.options.ecmaVersion>=6&&(l.method=!1,l.shorthand=!1,(e||t)&&(u=n.start,c=n.startLoc),e||(o=n.eat(F.star))),n.parsePropertyName(l),e||!(n.options.ecmaVersion>=8)||o||l.computed||"Identifier"!==l.key.type||"async"!==l.key.name||n.type===F.parenL||n.type===F.colon||n.canInsertSemicolon()?a=!1:(a=!0,n.parsePropertyName(l,t)),n.parsePropertyValue(l,e,o,a,u,c,t),n.checkPropClash(l,s),r.properties.push(n.finishNode(l,"Property"))}return this.finishNode(r,e?"ObjectPattern":"ObjectExpression")},ee.parsePropertyValue=function(e,t,n,r,i,s,o){if((n||r)&&this.type===F.colon&&this.unexpected(),this.eat(F.colon))e.value=t?this.parseMaybeDefault(this.start,this.startLoc):this.parseMaybeAssign(!1,o),e.kind="init";else if(this.options.ecmaVersion>=6&&this.type===F.parenL)t&&this.unexpected(),e.kind="init",e.method=!0,e.value=this.parseMethod(n,r);else if(this.options.ecmaVersion>=5&&!e.computed&&"Identifier"===e.key.type&&("get"===e.key.name||"set"===e.key.name)&&this.type!=F.comma&&this.type!=F.braceR){(n||r||t)&&this.unexpected(),e.kind=e.key.name,this.parsePropertyName(e),e.value=this.parseMethod(!1);var a="get"===e.kind?0:1;if(e.value.params.length!==a){var u=e.value.start;"get"===e.kind?this.raiseRecoverable(u,"getter should have no params"):this.raiseRecoverable(u,"setter should have exactly one param")}else"set"===e.kind&&"RestElement"===e.value.params[0].type&&this.raiseRecoverable(e.value.params[0].start,"Setter cannot use rest params")}else this.options.ecmaVersion>=6&&!e.computed&&"Identifier"===e.key.type?((this.keywords.test(e.key.name)||(this.strict?this.reservedWordsStrict:this.reservedWords).test(e.key.name)||this.inGenerator&&"yield"==e.key.name||this.inAsync&&"await"==e.key.name)&&this.raiseRecoverable(e.key.start,"'"+e.key.name+"' can not be used as shorthand property"),e.kind="init",t?e.value=this.parseMaybeDefault(i,s,e.key):this.type===F.eq&&o?(o.shorthandAssign<0&&(o.shorthandAssign=this.start),e.value=this.parseMaybeDefault(i,s,e.key)):e.value=e.key,e.shorthand=!0):this.unexpected()},ee.parsePropertyName=function(e){if(this.options.ecmaVersion>=6){if(this.eat(F.bracketL))return e.computed=!0,e.key=this.parseMaybeAssign(),this.expect(F.bracketR),e.key;e.computed=!1}return e.key=this.type===F.num||this.type===F.string?this.parseExprAtom():this.parseIdent(!0)},ee.initFunction=function(e){e.id=null,this.options.ecmaVersion>=6&&(e.generator=!1,e.expression=!1),this.options.ecmaVersion>=8&&(e.async=!1)},ee.parseMethod=function(e,t){var n=this.startNode(),r=this.inGenerator,i=this.inAsync,s=this.yieldPos,o=this.awaitPos,a=this.inFunction;return this.initFunction(n),this.options.ecmaVersion>=6&&(n.generator=e),this.options.ecmaVersion>=8&&(n.async=!!t),this.inGenerator=n.generator,this.inAsync=n.async,this.yieldPos=0,this.awaitPos=0,this.inFunction=!0,this.enterFunctionScope(),this.expect(F.parenL),n.params=this.parseBindingList(F.parenR,!1,this.options.ecmaVersion>=8),this.checkYieldAwaitInDefaultParams(),this.parseFunctionBody(n,!1),this.inGenerator=r,this.inAsync=i,this.yieldPos=s,this.awaitPos=o,this.inFunction=a,this.finishNode(n,"FunctionExpression")},ee.parseArrowExpression=function(e,t,n){var r=this.inGenerator,i=this.inAsync,s=this.yieldPos,o=this.awaitPos,a=this.inFunction;return this.enterFunctionScope(),this.initFunction(e),this.options.ecmaVersion>=8&&(e.async=!!n),this.inGenerator=!1,this.inAsync=e.async,this.yieldPos=0,this.awaitPos=0,this.inFunction=!0,e.params=this.toAssignableList(t,!0),this.parseFunctionBody(e,!0),this.inGenerator=r,this.inAsync=i,this.yieldPos=s,this.awaitPos=o,this.inFunction=a,this.finishNode(e,"ArrowFunctionExpression")},ee.parseFunctionBody=function(e,t){var n=t&&this.type!==F.braceL,r=this.strict,i=!1;if(n)e.body=this.parseMaybeAssign(),e.expression=!0,this.checkParams(e,!1);else{var s=this.options.ecmaVersion>=7&&!this.isSimpleParamList(e.params);r&&!s||(i=this.strictDirective(this.end))&&s&&this.raiseRecoverable(e.start,"Illegal 'use strict' directive in function with non-simple parameter list");var o=this.labels;this.labels=[],i&&(this.strict=!0),this.checkParams(e,!r&&!i&&!t&&this.isSimpleParamList(e.params)),e.body=this.parseBlock(!1),e.expression=!1,this.labels=o}this.exitFunctionScope(),this.strict&&e.id&&this.checkLVal(e.id,"none"),this.strict=r},ee.isSimpleParamList=function(e){for(var t=0;t