diff --git a/.eslintrc.yaml b/.eslintrc.yaml index ba6334b0346985..1362c9cb29e387 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -97,7 +97,7 @@ rules: key-spacing: [2, {mode: minimum}] keyword-spacing: 2 linebreak-style: [2, unix] - max-len: [2, 80, 2] + max-len: [2, {code: 80, ignoreUrls: true, tabWidth: 2}] new-parens: 2 no-mixed-spaces-and-tabs: 2 no-multiple-empty-lines: [2, {max: 2, maxEOF: 0, maxBOF: 0}] diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 24b66f8b2f8b4d..8b133a64e09d68 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -13,9 +13,7 @@ Contributors guide: https://github.com/nodejs/node/blob/master/CONTRIBUTING.md - [ ] `make -j4 test` (UNIX), or `vcbuild test nosign` (Windows) passes - [ ] tests and/or benchmarks are included - [ ] documentation is changed or added -- [ ] commit message follows [commit guidelines][] +- [ ] commit message follows [commit guidelines](https://github.com/nodejs/node/blob/master/CONTRIBUTING.md#commit-guidelines) ##### Affected core subsystem(s) - -[commit guidelines]: https://github.com/nodejs/node/blob/master/CONTRIBUTING.md#commit-guidelines diff --git a/.gitignore b/.gitignore index 4f129c4581ba8f..f8f99f5f839389 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,7 @@ !tools/doc/node_modules/**/.* !.editorconfig !.eslintignore -!.eslintrc +!.eslintrc.yaml !.gitattributes !.github !.gitignore diff --git a/CHANGELOG.md b/CHANGELOG.md index ff24baf55faa72..3bf1747aa7b37c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,7 +28,8 @@ release.
+ +
+ Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and @@ -16,6 +20,23 @@ policies, and releases are managed under an If you need help using or installing Node.js, please use the [nodejs/help](https://github.com/nodejs/help) issue tracker. + +# Table of Contents + +* [Resources for Newcomers](#resources-for-newcomers) +* [Release Types](#release-types) + * [Download](#download) + * [Current and LTS Releases](#current-and-lts-releases) + * [Nightly Releases](#nightly-releases) + * [API Documentation](#api-documentation) + * [Verifying Binaries](#verifying-binaries) +* [Building Node.js](#building-nodejs) + * [Security](#security) + * [Current Project Team Members](#current-project-team-members) + * [CTC (Core Technical Committee)](#ctc-core-technical-committee) + * [Collaborators](#collaborators) + * [Release Team](#release-team) + ## Resources for Newcomers ### Official Resources @@ -69,6 +90,7 @@ The Node.js project maintains multiple types of releases: Binaries, installers, and source tarballs are available at` (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/README.md b/tools/eslint/README.md index dcd42cff46685a..1ccdbb9bfd4262 100644 --- a/tools/eslint/README.md +++ b/tools/eslint/README.md @@ -112,6 +112,7 @@ These folks keep the project moving and are resources for help. * Toru Nagashima ([@mysticatea](https://github.com/mysticatea)) * Alberto Rodríguez ([@alberto](https://github.com/alberto)) * Kai Cataldo ([@kaicataldo](https://github.com/kaicataldo)) +* Teddy Katz ([@not-an-aardvark](https://github.com/not-an-aardvark)) ### Development Team @@ -129,7 +130,7 @@ These folks keep the project moving and are resources for help. * Kevin Partington ([@platinumazure](https://github.com/platinumazure)) * Vitor Balocco ([@vitorbal](https://github.com/vitorbal)) * James Henry ([@JamesHenry](https://github.com/JamesHenry)) -* Teddy Katz ([@not-an-aardvark](https://github.com/not-an-aardvark)) +* Reyad Attiyat ([@soda0289](https://github.com/soda0289)) ## Releases diff --git a/tools/eslint/conf/eslint.json b/tools/eslint/conf/eslint-recommended.js similarity index 93% rename from tools/eslint/conf/eslint.json rename to tools/eslint/conf/eslint-recommended.js index 81f5bb8aa5ee82..63c2fc770d214a 100755 --- a/tools/eslint/conf/eslint.json +++ b/tools/eslint/conf/eslint-recommended.js @@ -1,7 +1,81 @@ -{ - "parser": "espree", - "ecmaFeatures": {}, - "rules": { +/** + * @fileoverview Configuration applied when a user configuration extends from + * eslint:recommended. + * @author Nicholas C. Zakas + */ + +"use strict"; + +/* eslint sort-keys: ["error", "asc"], quote-props: ["error", "consistent"] */ +/* eslint-disable sort-keys */ + +module.exports = { + parser: "espree", + ecmaFeatures: {}, + + rules: { + + /* eslint-enable sort-keys */ + "accessor-pairs": "off", + "array-bracket-spacing": "off", + "array-callback-return": "off", + "arrow-body-style": "off", + "arrow-parens": "off", + "arrow-spacing": "off", + "block-scoped-var": "off", + "block-spacing": "off", + "brace-style": "off", + "callback-return": "off", + "camelcase": "off", + "capitalized-comments": "off", + "class-methods-use-this": "off", + "comma-dangle": "off", + "comma-spacing": "off", + "comma-style": "off", + "complexity": "off", + "computed-property-spacing": "off", + "consistent-return": "off", + "consistent-this": "off", + "constructor-super": "error", + "curly": "off", + "default-case": "off", + "dot-location": "off", + "dot-notation": "off", + "eol-last": "off", + "eqeqeq": "off", + "func-call-spacing": "off", + "func-name-matching": "off", + "func-names": "off", + "func-style": "off", + "generator-star-spacing": "off", + "global-require": "off", + "guard-for-in": "off", + "handle-callback-err": "off", + "id-blacklist": "off", + "id-length": "off", + "id-match": "off", + "indent": "off", + "init-declarations": "off", + "jsx-quotes": "off", + "key-spacing": "off", + "keyword-spacing": "off", + "line-comment-position": "off", + "linebreak-style": "off", + "lines-around-comment": "off", + "lines-around-directive": "off", + "max-depth": "off", + "max-len": "off", + "max-lines": "off", + "max-nested-callbacks": "off", + "max-params": "off", + "max-statements": "off", + "max-statements-per-line": "off", + "multiline-ternary": "off", + "new-cap": "off", + "new-parens": "off", + "newline-after-var": "off", + "newline-before-return": "off", + "newline-per-chained-call": "off", "no-alert": "off", "no-array-constructor": "off", "no-await-in-loop": "off", @@ -10,6 +84,7 @@ "no-case-declarations": "error", "no-catch-shadow": "off", "no-class-assign": "error", + "no-compare-neg-zero": "off", "no-cond-assign": "error", "no-confusing-arrow": "off", "no-console": "error", @@ -61,6 +136,7 @@ "no-mixed-operators": "off", "no-mixed-requires": "off", "no-mixed-spaces-and-tabs": "error", + "no-multi-assign": "off", "no-multi-spaces": "off", "no-multi-str": "off", "no-multiple-empty-lines": "off", @@ -99,20 +175,20 @@ "no-sequences": "off", "no-shadow": "off", "no-shadow-restricted-names": "off", - "no-whitespace-before-property": "off", "no-spaced-func": "off", "no-sparse-arrays": "error", "no-sync": "off", "no-tabs": "off", + "no-template-curly-in-string": "off", "no-ternary": "off", - "no-trailing-spaces": "off", "no-this-before-super": "error", "no-throw-literal": "off", + "no-trailing-spaces": "off", "no-undef": "error", "no-undef-init": "off", "no-undefined": "off", - "no-unexpected-multiline": "error", "no-underscore-dangle": "off", + "no-unexpected-multiline": "error", "no-unmodified-loop-condition": "off", "no-unneeded-ternary": "off", "no-unreachable": "error", @@ -129,70 +205,12 @@ "no-useless-escape": "off", "no-useless-rename": "off", "no-useless-return": "off", - "no-void": "off", "no-var": "off", + "no-void": "off", "no-warning-comments": "off", + "no-whitespace-before-property": "off", "no-with": "off", - "array-bracket-spacing": "off", - "array-callback-return": "off", - "arrow-body-style": "off", - "arrow-parens": "off", - "arrow-spacing": "off", - "accessor-pairs": "off", - "block-scoped-var": "off", - "block-spacing": "off", - "brace-style": "off", - "callback-return": "off", - "camelcase": "off", - "capitalized-comments": "off", - "class-methods-use-this": "off", - "comma-dangle": "off", - "comma-spacing": "off", - "comma-style": "off", - "complexity": "off", - "computed-property-spacing": "off", - "consistent-return": "off", - "consistent-this": "off", - "constructor-super": "error", - "curly": "off", - "default-case": "off", - "dot-location": "off", - "dot-notation": "off", - "eol-last": "off", - "eqeqeq": "off", - "func-call-spacing": "off", - "func-names": "off", - "func-name-matching": "off", - "func-style": "off", - "generator-star-spacing": "off", - "global-require": "off", - "guard-for-in": "off", - "handle-callback-err": "off", - "id-blacklist": "off", - "id-length": "off", - "id-match": "off", - "indent": "off", - "init-declarations": "off", - "jsx-quotes": "off", - "key-spacing": "off", - "keyword-spacing": "off", - "linebreak-style": "off", - "line-comment-position": "off", - "lines-around-comment": "off", - "lines-around-directive": "off", - "max-depth": "off", - "max-len": "off", - "max-lines": "off", - "max-nested-callbacks": "off", - "max-params": "off", - "max-statements": "off", - "max-statements-per-line": "off", - "multiline-ternary": "off", - "new-cap": "off", - "new-parens": "off", - "newline-after-var": "off", - "newline-before-return": "off", - "newline-per-chained-call": "off", + "nonblock-statement-body-position": "off", "object-curly-newline": "off", "object-curly-spacing": ["off", "never"], "object-property-newline": "off", @@ -206,6 +224,7 @@ "prefer-const": "off", "prefer-destructuring": "off", "prefer-numeric-literals": "off", + "prefer-promise-reject-errors": "off", "prefer-reflect": "off", "prefer-rest-params": "off", "prefer-spread": "off", @@ -219,8 +238,8 @@ "rest-spread-spacing": "off", "semi": "off", "semi-spacing": "off", - "sort-keys": "off", "sort-imports": "off", + "sort-keys": "off", "sort-vars": "off", "space-before-blocks": "off", "space-before-function-paren": "off", @@ -231,6 +250,7 @@ "strict": "off", "symbol-description": "off", "template-curly-spacing": "off", + "template-tag-spacing": "off", "unicode-bom": "off", "use-isnan": "error", "valid-jsdoc": "off", @@ -238,8 +258,7 @@ "vars-on-top": "off", "wrap-iife": "off", "wrap-regex": "off", - "no-template-curly-in-string": "off", "yield-star-spacing": "off", "yoda": "off" } -} +}; diff --git a/tools/eslint/lib/ast-utils.js b/tools/eslint/lib/ast-utils.js index 46dfebe101caa2..0f2f3d6af539e3 100644 --- a/tools/eslint/lib/ast-utils.js +++ b/tools/eslint/lib/ast-utils.js @@ -10,7 +10,6 @@ //------------------------------------------------------------------------------ const esutils = require("esutils"); -const lodash = require("lodash"); //------------------------------------------------------------------------------ // Helpers @@ -24,6 +23,14 @@ const bindOrCallOrApplyPattern = /^(?:bind|call|apply)$/; const breakableTypePattern = /^(?:(?:Do)?While|For(?:In|Of)?|Switch)Statement$/; 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]/; + +// A set of node types that can contain a list of statements +const STATEMENT_LIST_PARENTS = new Set(["Program", "BlockStatement", "SwitchCase"]); + /** * Checks reference if is non initializer and writable. * @param {Reference} reference - A reference to check. @@ -142,7 +149,7 @@ function isInLoop(node) { */ function isNullOrUndefined(node) { return ( - (node.type === "Literal" && node.value === null) || + module.exports.isNullLiteral(node) || (node.type === "Identifier" && node.name === "undefined") || (node.type === "UnaryExpression" && node.operator === "void") ); @@ -158,9 +165,9 @@ function isCallee(node) { } /** - * Checks whether or not a node is `Reclect.apply`. + * Checks whether or not a node is `Reflect.apply`. * @param {ASTNode} node - A node to check. - * @returns {boolean} Whether or not the node is a `Reclect.apply`. + * @returns {boolean} Whether or not the node is a `Reflect.apply`. */ function isReflectApply(node) { return ( @@ -210,6 +217,15 @@ function isMethodWhichHasThisArg(node) { return false; } +/** + * Creates the negate function of the given function. + * @param {Function} f - The function to negate. + * @returns {Function} Negated function. + */ +function negate(f) { + return token => !f(token); +} + /** * Checks whether or not a node has a `@this` tag in its comments. * @param {ASTNode} node - A node to check. @@ -247,56 +263,145 @@ function isParenthesised(sourceCode, node) { } /** - * Gets the `=>` token of the given arrow function node. + * Checks if the given token is an arrow token or not. * - * @param {ASTNode} node - The arrow function node to get. - * @param {SourceCode} sourceCode - The source code object to get tokens. - * @returns {Token} `=>` token. + * @param {Token} token - The token to check. + * @returns {boolean} `true` if the token is an arrow token. */ -function getArrowToken(node, sourceCode) { - let token = sourceCode.getTokenBefore(node.body); +function isArrowToken(token) { + return token.value === "=>" && token.type === "Punctuator"; +} - while (token.value !== "=>") { - token = sourceCode.getTokenBefore(token); - } +/** + * Checks if the given token is a comma token or not. + * + * @param {Token} token - The token to check. + * @returns {boolean} `true` if the token is a comma token. + */ +function isCommaToken(token) { + return token.value === "," && token.type === "Punctuator"; +} - return token; +/** + * Checks if the given token is a semicolon token or not. + * + * @param {Token} token - The token to check. + * @returns {boolean} `true` if the token is a semicolon token. + */ +function isSemicolonToken(token) { + return token.value === ";" && token.type === "Punctuator"; } /** - * Gets the `(` token of the given function node. + * Checks if the given token is a colon token or not. * - * @param {ASTNode} node - The function node to get. - * @param {SourceCode} sourceCode - The source code object to get tokens. - * @returns {Token} `(` token. + * @param {Token} token - The token to check. + * @returns {boolean} `true` if the token is a colon token. */ -function getOpeningParenOfParams(node, sourceCode) { - let token = node.id ? sourceCode.getTokenAfter(node.id) : sourceCode.getFirstToken(node); +function isColonToken(token) { + return token.value === ":" && token.type === "Punctuator"; +} - while (token.value !== "(") { - token = sourceCode.getTokenAfter(token); - } +/** + * Checks if the given token is an opening parenthesis token or not. + * + * @param {Token} token - The token to check. + * @returns {boolean} `true` if the token is an opening parenthesis token. + */ +function isOpeningParenToken(token) { + return token.value === "(" && token.type === "Punctuator"; +} + +/** + * Checks if the given token is a closing parenthesis token or not. + * + * @param {Token} token - The token to check. + * @returns {boolean} `true` if the token is a closing parenthesis token. + */ +function isClosingParenToken(token) { + return token.value === ")" && token.type === "Punctuator"; +} - return token; +/** + * Checks if the given token is an opening square bracket token or not. + * + * @param {Token} token - The token to check. + * @returns {boolean} `true` if the token is an opening square bracket token. + */ +function isOpeningBracketToken(token) { + return token.value === "[" && token.type === "Punctuator"; } -const lineIndexCache = new WeakMap(); +/** + * Checks if the given token is a closing square bracket token or not. + * + * @param {Token} token - The token to check. + * @returns {boolean} `true` if the token is a closing square bracket token. + */ +function isClosingBracketToken(token) { + return token.value === "]" && token.type === "Punctuator"; +} /** - * Gets the range index for the first character in each of the lines of `sourceCode`. - * @param {SourceCode} sourceCode A sourceCode object - * @returns {number[]} The indices of the first characters in the each of the lines of the code + * Checks if the given token is an opening brace token or not. + * + * @param {Token} token - The token to check. + * @returns {boolean} `true` if the token is an opening brace token. */ -function getLineIndices(sourceCode) { +function isOpeningBraceToken(token) { + return token.value === "{" && token.type === "Punctuator"; +} - if (!lineIndexCache.has(sourceCode)) { - const lineIndices = (sourceCode.text.match(/[^\r\n\u2028\u2029]*(\r\n|\r|\n|\u2028|\u2029)/g) || []) - .reduce((indices, line) => indices.concat(indices[indices.length - 1] + line.length), [0]); +/** + * Checks if the given token is a closing brace token or not. + * + * @param {Token} token - The token to check. + * @returns {boolean} `true` if the token is a closing brace token. + */ +function isClosingBraceToken(token) { + return token.value === "}" && token.type === "Punctuator"; +} - // Store the sourceCode object in a WeakMap to avoid iterating over all of the lines every time a sourceCode object is passed in. - lineIndexCache.set(sourceCode, lineIndices); - } - return lineIndexCache.get(sourceCode); +/** + * Checks if the given token is a comment token or not. + * + * @param {Token} token - The token to check. + * @returns {boolean} `true` if the token is a comment token. + */ +function isCommentToken(token) { + return token.type === "Line" || token.type === "Block" || token.type === "Shebang"; +} + +/** + * Checks if the given token is a keyword token or not. + * + * @param {Token} token - The token to check. + * @returns {boolean} `true` if the token is a keyword token. + */ +function isKeywordToken(token) { + return token.type === "Keyword"; +} + +/** + * Gets the `(` token of the given function node. + * + * @param {ASTNode} node - The function node to get. + * @param {SourceCode} sourceCode - The source code object to get tokens. + * @returns {Token} `(` token. + */ +function getOpeningParenOfParams(node, sourceCode) { + return node.id + ? sourceCode.getTokenAfter(node.id, isOpeningParenToken) + : sourceCode.getFirstToken(node, isOpeningParenToken); +} + +/** + * Creates a version of the LINEBREAK_MATCHER regex with the global flag. + * Global regexes are mutable, so this needs to be a function instead of a constant. + * @returns {RegExp} A global regular expression that matches line terminators + */ +function createGlobalLinebreakMatcher() { + return new RegExp(LINEBREAK_MATCHER.source, "g"); } //------------------------------------------------------------------------------ @@ -304,6 +409,10 @@ function getLineIndices(sourceCode) { //------------------------------------------------------------------------------ module.exports = { + COMMENTS_IGNORE_PATTERN, + LINEBREAKS, + LINEBREAK_MATCHER, + STATEMENT_LIST_PARENTS, /** * Determines whether two adjacent tokens are on the same line. @@ -325,6 +434,29 @@ module.exports = { isInLoop, isArrayFromMethod, isParenthesised, + createGlobalLinebreakMatcher, + + isArrowToken, + isClosingBraceToken, + isClosingBracketToken, + isClosingParenToken, + isColonToken, + isCommaToken, + isCommentToken, + isKeywordToken, + isNotClosingBraceToken: negate(isClosingBraceToken), + isNotClosingBracketToken: negate(isClosingBracketToken), + isNotClosingParenToken: negate(isClosingParenToken), + isNotColonToken: negate(isColonToken), + isNotCommaToken: negate(isCommaToken), + isNotOpeningBraceToken: negate(isOpeningBraceToken), + isNotOpeningBracketToken: negate(isOpeningBracketToken), + isNotOpeningParenToken: negate(isOpeningParenToken), + isNotSemicolonToken: negate(isSemicolonToken), + isOpeningBraceToken, + isOpeningBracketToken, + isOpeningParenToken, + isSemicolonToken, /** * Checks whether or not a given node is a string literal. @@ -658,6 +790,8 @@ module.exports = { case "/": case "%": return 13; + case "**": + return 15; // no default } @@ -666,10 +800,10 @@ module.exports = { case "UnaryExpression": case "AwaitExpression": - return 14; + return 16; case "UpdateExpression": - return 15; + return 17; case "CallExpression": @@ -677,14 +811,14 @@ module.exports = { if (node.callee.type === "FunctionExpression") { return -1; } - return 16; + return 18; case "NewExpression": - return 17; + return 19; // no default } - return 18; + return 20; }, /** @@ -1023,7 +1157,7 @@ module.exports = { let end = null; if (node.type === "ArrowFunctionExpression") { - const arrowToken = getArrowToken(node, sourceCode); + const arrowToken = sourceCode.getTokenBefore(node.body, isArrowToken); start = arrowToken.loc.start; end = arrowToken.loc.end; @@ -1037,42 +1171,10 @@ module.exports = { return { start: Object.assign({}, start), - end: Object.assign({}, end), + end: Object.assign({}, end) }; }, - /* - * Converts a range index into a (line, column) pair. - * @param {SourceCode} sourceCode A SourceCode object - * @param {number} rangeIndex The range index of a character in a file - * @returns {Object} A {line, column} location object with a 0-indexed column - */ - getLocationFromRangeIndex(sourceCode, rangeIndex) { - const lineIndices = getLineIndices(sourceCode); - - /* - * lineIndices is a sorted list of indices of the first character of each line. - * To figure out which line rangeIndex is on, determine the last index at which rangeIndex could - * be inserted into lineIndices to keep the list sorted. - */ - const lineNumber = lodash.sortedLastIndex(lineIndices, rangeIndex); - - return { line: lineNumber, column: rangeIndex - lineIndices[lineNumber - 1] }; - - }, - - /** - * Converts a (line, column) pair into a range index. - * @param {SourceCode} sourceCode A SourceCode object - * @param {Object} loc A line/column location - * @param {number} loc.line The line number of the location (1-indexed) - * @param {number} loc.column The column number of the location (0-indexed) - * @returns {number} The range index of the location in the file. - */ - getRangeIndexFromLocation(sourceCode, loc) { - return getLineIndices(sourceCode)[loc.line - 1] + loc.column; - }, - /** * Gets the parenthesized text of a node. This is similar to sourceCode.getText(node), but it also includes any parentheses * surrounding the node. @@ -1097,5 +1199,58 @@ module.exports = { } return sourceCode.getText().slice(leftToken.range[0], rightToken.range[1]); + }, + + /* + * Determine if a node has a possiblity to be an Error object + * @param {ASTNode} node ASTNode to check + * @returns {boolean} True if there is a chance it contains an Error obj + */ + couldBeError(node) { + switch (node.type) { + case "Identifier": + case "CallExpression": + case "NewExpression": + case "MemberExpression": + case "TaggedTemplateExpression": + case "YieldExpression": + case "AwaitExpression": + return true; // possibly an error object. + + case "AssignmentExpression": + return module.exports.couldBeError(node.right); + + case "SequenceExpression": { + const exprs = node.expressions; + + return exprs.length !== 0 && module.exports.couldBeError(exprs[exprs.length - 1]); + } + + case "LogicalExpression": + return module.exports.couldBeError(node.left) || module.exports.couldBeError(node.right); + + case "ConditionalExpression": + return module.exports.couldBeError(node.consequent) || module.exports.couldBeError(node.alternate); + + default: + return false; + } + }, + + /** + * Determines whether the given node is a `null` literal. + * @param {ASTNode} node The node to check + * @returns {boolean} `true` if the node is a `null` literal + */ + isNullLiteral(node) { + + /* + * Checking `node.value === null` does not guarantee that a literal is a null literal. + * When parsing values that cannot be represented in the current environment (e.g. unicode + * regexes in Node 4), `node.value` is set to `null` because it wouldn't be possible to + * set `node.value` to a unicode regex. To make sure a literal is actually `null`, check + * `node.regex` instead. Also see: https://github.com/eslint/eslint/issues/8020 + */ + return node.type === "Literal" && node.value === null && !node.regex; } }; diff --git a/tools/eslint/lib/cli.js b/tools/eslint/lib/cli.js index 9fdcfc701e7167..640bd81baba6ea 100644 --- a/tools/eslint/lib/cli.js +++ b/tools/eslint/lib/cli.js @@ -188,9 +188,9 @@ const cli = { } return (report.errorCount || tooManyWarnings) ? 1 : 0; - } else { - return 1; } + return 1; + } diff --git a/tools/eslint/lib/code-path-analysis/code-path-analyzer.js b/tools/eslint/lib/code-path-analysis/code-path-analyzer.js index cb8b1e1bf8ce8c..539b5e18b3cff7 100644 --- a/tools/eslint/lib/code-path-analysis/code-path-analyzer.js +++ b/tools/eslint/lib/code-path-analysis/code-path-analyzer.js @@ -512,13 +512,8 @@ function processCodePathToExit(analyzer, node) { break; } - /* - * Skip updating the current segment to avoid creating useless segments if - * the node type is the same as the parent node type. - */ - if (!dontForward && (!node.parent || node.type !== node.parent.type)) { - - // Emits onCodePathSegmentStart events if updated. + // Emits onCodePathSegmentStart events if updated. + if (!dontForward) { forwardCurrentToHead(analyzer, node); } debug.dumpState(node, state, true); 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 64779c0d3c8b12..3faff3ebb85970 100644 --- a/tools/eslint/lib/code-path-analysis/code-path-state.js +++ b/tools/eslint/lib/code-path-analysis/code-path-state.js @@ -467,8 +467,8 @@ class CodePathState { * Creates the next path from own true/false fork context. */ const prevForkContext = - context.kind === "&&" ? context.trueForkContext : - /* kind === "||" */ context.falseForkContext; + context.kind === "&&" ? context.trueForkContext + /* kind === "||" */ : context.falseForkContext; forkContext.replaceHead(prevForkContext.makeNext(0, -1)); prevForkContext.clear(); diff --git a/tools/eslint/lib/code-path-analysis/debug-helpers.js b/tools/eslint/lib/code-path-analysis/debug-helpers.js index 622bd6081fa546..9af985ce85f56e 100644 --- a/tools/eslint/lib/code-path-analysis/debug-helpers.js +++ b/tools/eslint/lib/code-path-analysis/debug-helpers.js @@ -107,22 +107,23 @@ module.exports = { text += "style=\"rounded,dashed,filled\",fillcolor=\"#FF9800\",label=\"<>\\n"; } - if (segment.internal.nodes.length > 0) { - text += segment.internal.nodes.map(node => { - switch (node.type) { - case "Identifier": return `${node.type} (${node.name})`; - case "Literal": return `${node.type} (${node.value})`; - default: return node.type; - } - }).join("\\n"); - } else if (segment.internal.exitNodes.length > 0) { - text += segment.internal.exitNodes.map(node => { - switch (node.type) { - case "Identifier": return `${node.type}:exit (${node.name})`; - case "Literal": return `${node.type}:exit (${node.value})`; - default: return `${node.type}:exit`; - } - }).join("\\n"); + if (segment.internal.nodes.length > 0 || segment.internal.exitNodes.length > 0) { + text += [].concat( + segment.internal.nodes.map(node => { + switch (node.type) { + case "Identifier": return `${node.type} (${node.name})`; + case "Literal": return `${node.type} (${node.value})`; + default: return node.type; + } + }), + segment.internal.exitNodes.map(node => { + switch (node.type) { + case "Identifier": return `${node.type}:exit (${node.name})`; + case "Literal": return `${node.type}:exit (${node.value})`; + default: return `${node.type}:exit`; + } + }) + ).join("\\n"); } else { text += "????"; } diff --git a/tools/eslint/lib/config.js b/tools/eslint/lib/config.js index 9c56e7ad988e28..03fda87c973c3b 100644 --- a/tools/eslint/lib/config.js +++ b/tools/eslint/lib/config.js @@ -234,8 +234,9 @@ class Config { } /** - * Build a config object merging the base config (conf/eslint.json), the - * environments config (conf/environments.js) and eventually the user config. + * Build a config object merging the base config (conf/eslint-recommended), + * the environments config (conf/environments.js) and eventually the user + * config. * @param {string} filePath a file in whose directory we start looking for a local config * @returns {Object} config object */ diff --git a/tools/eslint/lib/config/autoconfig.js b/tools/eslint/lib/config/autoconfig.js index 23fdbe69803afc..4a50ce25cdd248 100644 --- a/tools/eslint/lib/config/autoconfig.js +++ b/tools/eslint/lib/config/autoconfig.js @@ -13,7 +13,7 @@ const lodash = require("lodash"), eslint = require("../eslint"), configRule = require("./config-rule"), ConfigOps = require("./config-ops"), - recConfig = require("../../conf/eslint.json"); + recConfig = require("../../conf/eslint-recommended"); const debug = require("debug")("eslint:autoconfig"); @@ -65,17 +65,16 @@ function makeRegistryItems(rulesConfig) { * Unless a rulesConfig is provided at construction, the registry will not contain * any rules, only methods. This will be useful for building up registries manually. * -* @constructor -* @class Registry -* @param {rulesConfig} [rulesConfig] Hash of rule names and arrays of possible configurations +* Registry class */ -function Registry(rulesConfig) { - this.rules = (rulesConfig) ? makeRegistryItems(rulesConfig) : {}; -} - -Registry.prototype = { +class Registry { - constructor: Registry, + /** + * @param {rulesConfig} [rulesConfig] Hash of rule names and arrays of possible configurations + */ + constructor(rulesConfig) { + this.rules = (rulesConfig) ? makeRegistryItems(rulesConfig) : {}; + } /** * Populate the registry with core rule configs. @@ -89,7 +88,7 @@ Registry.prototype = { const rulesConfig = configRule.createCoreRuleConfigs(); this.rules = makeRegistryItems(rulesConfig); - }, + } /** * Creates sets of rule configurations which can be used for linting @@ -156,7 +155,7 @@ Registry.prototype = { } return ruleSets; - }, + } /** * Remove all items from the registry with a non-zero number of errors @@ -182,7 +181,7 @@ Registry.prototype = { }); return newRegistry; - }, + } /** * Removes rule configurations which were not included in a ruleSet @@ -199,7 +198,7 @@ Registry.prototype = { }); return newRegistry; - }, + } /** * Creates a registry of rules which had no error-free configs. @@ -221,7 +220,7 @@ Registry.prototype = { }); return failingRegistry; - }, + } /** * Create an eslint config for any rules which only have one configuration @@ -240,7 +239,7 @@ Registry.prototype = { }); return config; - }, + } /** * Return a cloned registry containing only configs with a desired specificity @@ -258,7 +257,7 @@ Registry.prototype = { }); return newRegistry; - }, + } /** * Lint SourceCodes against all configurations in the registry, and record results @@ -297,8 +296,13 @@ Registry.prototype = { // It is possible that the error is from a configuration comment // in a linted file, in which case there may not be a config - // set in this ruleSetIdx. (https://github.com/eslint/eslint/issues/5992) - if (lintedRegistry.rules[result.ruleId][ruleSetIdx]) { + // set in this ruleSetIdx. + // (https://github.com/eslint/eslint/issues/5992) + // (https://github.com/eslint/eslint/issues/7860) + if ( + lintedRegistry.rules[result.ruleId] && + lintedRegistry.rules[result.ruleId][ruleSetIdx] + ) { lintedRegistry.rules[result.ruleId][ruleSetIdx].errorCount += 1; } }); @@ -316,7 +320,7 @@ Registry.prototype = { return lintedRegistry; } -}; +} /** * Extract rule configuration into eslint:recommended where possible. diff --git a/tools/eslint/lib/config/config-file.js b/tools/eslint/lib/config/config-file.js index 90015097a3db97..4e886b8af27b67 100644 --- a/tools/eslint/lib/config/config-file.js +++ b/tools/eslint/lib/config/config-file.js @@ -23,7 +23,7 @@ const fs = require("fs"), stripBom = require("strip-bom"), stripComments = require("strip-json-comments"), stringify = require("json-stable-stringify"), - defaultOptions = require("../../conf/eslint.json"), + defaultOptions = require("../../conf/eslint-recommended"), requireUncached = require("require-uncached"); const debug = require("debug")("eslint:config-file"); @@ -183,6 +183,22 @@ function loadPackageJSONConfigFile(filePath) { } } +/** + * Creates an error to notify about a missing config to extend from. + * @param {string} configName The name of the missing config. + * @returns {Error} The error object to throw + * @private + */ +function configMissingError(configName) { + const error = new Error(`Failed to load config "${configName}" to extend from.`); + + error.messageTemplate = "extend-config-missing"; + error.messageData = { + configName + }; + return error; +} + /** * Loads a configuration file regardless of the source. Inspects the file path * to determine the correctly way to load the config file. @@ -199,6 +215,9 @@ function loadConfigFile(file) { config = loadJSConfigFile(filePath); if (file.configName) { config = config.configs[file.configName]; + if (!config) { + throw configMissingError(file.configFullName); + } } break; @@ -340,6 +359,33 @@ function getLookupPath(configFilePath) { return path.join(basedir, "node_modules"); } +/** + * Resolves a eslint core config path + * @param {string} name The eslint config name. + * @returns {string} The resolved path of the config. + * @private + */ +function getEslintCoreConfigPath(name) { + if (name === "eslint:recommended") { + + /* + * 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 + */ + return path.resolve(__dirname, "../../conf/eslint-all.js"); + } + + throw configMissingError(name); +} + /** * Applies values from the "extends" field in a configuration file. * @param {Object} config The configuration information. @@ -360,33 +406,20 @@ function applyExtends(config, filePath, relativeTo) { // Make the last element in an array take the highest precedence config = configExtends.reduceRight((previousValue, parentPath) => { - - if (parentPath === "eslint:recommended") { - - /* - * Add an explicit substitution for eslint:recommended to conf/eslint.json - * this lets us use the eslint.json file as the recommended rules - */ - parentPath = path.resolve(__dirname, "../../conf/eslint.json"); - } else if (parentPath === "eslint:all") { - - /* - * Add an explicit substitution for eslint:all to conf/eslint-all.js - */ - parentPath = path.resolve(__dirname, "../../conf/eslint-all.js"); - } else if (isFilePath(parentPath)) { - - /* - * If the `extends` path is relative, use the directory of the current configuration - * file as the reference point. Otherwise, use as-is. - */ - parentPath = (!path.isAbsolute(parentPath) ? - path.join(relativeTo || path.dirname(filePath), parentPath) : - parentPath - ); - } - try { + if (parentPath.startsWith("eslint:")) { + parentPath = getEslintCoreConfigPath(parentPath); + } else if (isFilePath(parentPath)) { + + /* + * If the `extends` path is relative, use the directory of the current configuration + * file as the reference point. Otherwise, use as-is. + */ + parentPath = (path.isAbsolute(parentPath) + ? parentPath + : path.join(relativeTo || path.dirname(filePath), parentPath) + ); + } debug(`Loading ${parentPath}`); return ConfigOps.merge(load(parentPath, false, relativeTo), previousValue); } catch (e) { @@ -455,30 +488,34 @@ function normalizePackageName(name, prefix) { * or package name. * @param {string} filePath The filepath to resolve. * @param {string} [relativeTo] The path to resolve relative to. - * @returns {Object} A path that can be used directly to load the configuration. + * @returns {Object} An object containing 3 properties: + * - 'filePath' (required) the resolved path that can be used directly to load the configuration. + * - 'configName' the name of the configuration inside the plugin. + * - 'configFullName' the name of the configuration as used in the eslint config (e.g. 'plugin:node/recommended'). * @private */ function resolve(filePath, relativeTo) { if (isFilePath(filePath)) { return { filePath: path.resolve(relativeTo || "", filePath) }; - } else { - let normalizedPackageName; - - if (filePath.indexOf("plugin:") === 0) { - const packagePath = filePath.substr(7, filePath.lastIndexOf("/") - 7); - const configName = filePath.substr(filePath.lastIndexOf("/") + 1, filePath.length - filePath.lastIndexOf("/") - 1); - - normalizedPackageName = normalizePackageName(packagePath, "eslint-plugin"); - debug(`Attempting to resolve ${normalizedPackageName}`); - filePath = resolver.resolve(normalizedPackageName, getLookupPath(relativeTo)); - return { filePath, configName }; - } else { - normalizedPackageName = normalizePackageName(filePath, "eslint-config"); - debug(`Attempting to resolve ${normalizedPackageName}`); - filePath = resolver.resolve(normalizedPackageName, getLookupPath(relativeTo)); - return { filePath }; - } } + let normalizedPackageName; + + if (filePath.startsWith("plugin:")) { + const configFullName = filePath; + const pluginName = filePath.substr(7, filePath.lastIndexOf("/") - 7); + const configName = filePath.substr(filePath.lastIndexOf("/") + 1, filePath.length - filePath.lastIndexOf("/") - 1); + + normalizedPackageName = normalizePackageName(pluginName, "eslint-plugin"); + debug(`Attempting to resolve ${normalizedPackageName}`); + filePath = resolver.resolve(normalizedPackageName, getLookupPath(relativeTo)); + return { filePath, configName, configFullName }; + } + normalizedPackageName = normalizePackageName(filePath, "eslint-config"); + debug(`Attempting to resolve ${normalizedPackageName}`); + filePath = resolver.resolve(normalizedPackageName, getLookupPath(relativeTo)); + return { filePath }; + + } diff --git a/tools/eslint/lib/config/config-initializer.js b/tools/eslint/lib/config/config-initializer.js index 502a73bd6c3ed1..0062a46504fdf5 100644 --- a/tools/eslint/lib/config/config-initializer.js +++ b/tools/eslint/lib/config/config-initializer.js @@ -17,7 +17,7 @@ const util = require("util"), ConfigOps = require("./config-ops"), getSourceCodeOfFiles = require("../util/source-code-util").getSourceCodeOfFiles, npmUtil = require("../util/npm-util"), - recConfig = require("../../conf/eslint.json"), + recConfig = require("../../conf/eslint-recommended"), log = require("../logging"); const debug = require("debug")("eslint:config-initializer"); @@ -317,7 +317,7 @@ function promptUser(callback) { default: false, when(answers) { return answers.styleguide === "airbnb"; - }, + } }, { type: "input", diff --git a/tools/eslint/lib/config/config-rule.js b/tools/eslint/lib/config/config-rule.js index d495198aed454b..a8a073caa3707d 100644 --- a/tools/eslint/lib/config/config-rule.js +++ b/tools/eslint/lib/config/config-rule.js @@ -176,22 +176,21 @@ function combinePropertyObjects(objArr1, objArr2) { * * ruleConfigSet.ruleConfigs // -> [[2], [2, "always"], [2, "never"]] * - * @param {ruleConfig[]} configs Valid rule configurations - * @constructor + * Rule configuration set class */ -function RuleConfigSet(configs) { +class RuleConfigSet { /** - * Stored valid rule configurations for this instance - * @type {array} - */ - this.ruleConfigs = configs || []; - -} - -RuleConfigSet.prototype = { - - constructor: RuleConfigSet, + * @param {ruleConfig[]} configs Valid rule configurations + */ + constructor(configs) { + + /** + * Stored valid rule configurations for this instance + * @type {array} + */ + this.ruleConfigs = configs || []; + } /** * Add a severity level to the front of all configs in the instance. @@ -210,7 +209,7 @@ RuleConfigSet.prototype = { // Add a single config at the beginning consisting of only the severity this.ruleConfigs.unshift(severity); - }, + } /** * Add rule configs from an array of strings (schema enums) @@ -219,12 +218,12 @@ RuleConfigSet.prototype = { */ addEnums(enums) { this.ruleConfigs = this.ruleConfigs.concat(combineArrays(this.ruleConfigs, enums)); - }, + } /** * Add rule configurations from a schema object * @param {Object} obj Schema item with type === "object" - * @returns {void} + * @returns {boolean} true if at least one schema for the object could be generated, false otherwise */ addObject(obj) { const objectConfigSet = { @@ -259,9 +258,12 @@ RuleConfigSet.prototype = { if (objectConfigSet.objectConfigs.length > 0) { this.ruleConfigs = this.ruleConfigs.concat(combineArrays(this.ruleConfigs, objectConfigSet.objectConfigs)); + return true; } + + return false; } -}; +} /** * Generate valid rule configurations based on a schema object @@ -272,20 +274,21 @@ function generateConfigsFromSchema(schema) { const configSet = new RuleConfigSet(); if (Array.isArray(schema)) { - schema.forEach(opt => { + for (const opt of schema) { if (opt.enum) { configSet.addEnums(opt.enum); - } - - if (opt.type && opt.type === "object") { - configSet.addObject(opt); - } + } else if (opt.type && opt.type === "object") { + if (!configSet.addObject(opt)) { + break; + } - if (opt.oneOf) { + // TODO (IanVS): support oneOf + } else { - // TODO (IanVS): not yet implemented + // If we don't know how to fill in this option, don't fill in any of the following options. + break; } - }); + } } configSet.addErrorSeverity(); return configSet.ruleConfigs; diff --git a/tools/eslint/lib/config/config-validator.js b/tools/eslint/lib/config/config-validator.js index c5268169b92356..36e0e9fddb32ae 100644 --- a/tools/eslint/lib/config/config-validator.js +++ b/tools/eslint/lib/config/config-validator.js @@ -40,13 +40,13 @@ function getRuleOptionsSchema(id) { minItems: 0, maxItems: schema.length }; - } else { - return { - type: "array", - minItems: 0, - maxItems: 0 - }; } + return { + type: "array", + minItems: 0, + maxItems: 0 + }; + } // Given a full schema, leave it alone diff --git a/tools/eslint/lib/config/plugins.js b/tools/eslint/lib/config/plugins.js index 5073d564a04e79..e28a77929c0b5f 100644 --- a/tools/eslint/lib/config/plugins.js +++ b/tools/eslint/lib/config/plugins.js @@ -127,14 +127,25 @@ module.exports = { if (!plugins[shortName]) { try { plugin = require(longName); - } catch (err) { - debug(`Failed to load plugin ${longName}.`); - err.message = `Failed to load plugin ${pluginName}: ${err.message}`; - err.messageTemplate = "plugin-missing"; - err.messageData = { - pluginName: longName - }; - throw err; + } catch (pluginLoadErr) { + try { + + // Check whether the plugin exists + require.resolve(longName); + } catch (missingPluginErr) { + + // If the plugin can't be resolved, display the missing plugin error (usually a config or install error) + debug(`Failed to load plugin ${longName}.`); + missingPluginErr.message = `Failed to load plugin ${pluginName}: ${missingPluginErr.message}`; + missingPluginErr.messageTemplate = "plugin-missing"; + missingPluginErr.messageData = { + pluginName: longName + }; + throw missingPluginErr; + } + + // Otherwise, the plugin exists and is throwing on module load for some reason, so print the stack trace. + throw pluginLoadErr; } this.define(pluginName, plugin); diff --git a/tools/eslint/lib/eslint.js b/tools/eslint/lib/eslint.js index 3ae7cfe9c68103..a9066c4c8b6884 100755 --- a/tools/eslint/lib/eslint.js +++ b/tools/eslint/lib/eslint.js @@ -14,7 +14,7 @@ const assert = require("assert"), escope = require("escope"), levn = require("levn"), blankScriptAST = require("../conf/blank-script.json"), - DEFAULT_PARSER = require("../conf/eslint.json").parser, + DEFAULT_PARSER = require("../conf/eslint-recommended").parser, replacements = require("../conf/replacements.json"), CodePathAnalyzer = require("./code-path-analysis/code-path-analyzer"), ConfigOps = require("./config/config-ops"), @@ -528,9 +528,9 @@ function createStubRule(message) { if (message) { return createRuleModule; - } else { - throw new Error("No message passed to stub rule"); } + throw new Error("No message passed to stub rule"); + } /** @@ -660,9 +660,9 @@ module.exports = (function() { try { if (typeof parser.parseForESLint === "function") { return parser.parseForESLint(text, parserOptions); - } else { - return parser.parse(text, parserOptions); } + return parser.parse(text, parserOptions); + } catch (ex) { // If the message includes a leading line number, strip it: @@ -695,9 +695,9 @@ module.exports = (function() { return ruleConfig; } else if (Array.isArray(ruleConfig)) { return ruleConfig[0]; - } else { - return 0; } + return 0; + } /** @@ -708,9 +708,9 @@ module.exports = (function() { function getRuleOptions(ruleConfig) { if (Array.isArray(ruleConfig)) { return ruleConfig.slice(1); - } else { - return []; } + return []; + } // set unlimited listeners (see https://github.com/eslint/eslint/issues/524) @@ -778,17 +778,18 @@ module.exports = (function() { // search and apply "eslint-env *". const envInFile = findEslintEnv(text || textOrSourceCode.text); + config = Object.assign({}, config); + if (envInFile) { - if (!config || !config.env) { - config = Object.assign({}, config || {}, { env: envInFile }); - } else { - config = Object.assign({}, config); + if (config.env) { config.env = Object.assign({}, config.env, envInFile); + } else { + config.env = envInFile; } } // process initial config to make it safe to extend - config = prepareConfig(config || {}); + config = prepareConfig(config); // only do this for text if (text !== null) { @@ -864,14 +865,14 @@ module.exports = (function() { (parseResult && parseResult.services ? parseResult.services : {}) ); - const rule = ruleCreator.create ? ruleCreator.create(ruleContext) : - ruleCreator(ruleContext); + const rule = ruleCreator.create ? ruleCreator.create(ruleContext) + : ruleCreator(ruleContext); - // add all the node types as listeners - Object.keys(rule).forEach(nodeType => { - api.on(nodeType, timing.enabled - ? timing.time(key, rule[nodeType]) - : rule[nodeType] + // add all the selectors from the rule as listeners + Object.keys(rule).forEach(selector => { + api.on(selector, timing.enabled + ? timing.time(key, rule[selector]) + : rule[selector] ); }); } catch (ex) { @@ -939,9 +940,9 @@ module.exports = (function() { if (lineDiff === 0) { return a.column - b.column; - } else { - return lineDiff; } + return lineDiff; + }); return messages; @@ -1109,9 +1110,9 @@ module.exports = (function() { if (scope) { if (scope.type === "function-expression-name") { return scope.childScopes[0]; - } else { - return scope; } + return scope; + } } @@ -1161,9 +1162,9 @@ module.exports = (function() { api.getFilename = function() { if (typeof currentFilename === "string") { return currentFilename; - } else { - return ""; } + return ""; + }; /** @@ -1192,7 +1193,7 @@ module.exports = (function() { * @returns {Object} Object mapping rule IDs to their default configurations */ api.defaults = function() { - return require("../conf/eslint.json"); + return require("../conf/eslint-recommended"); }; /** diff --git a/tools/eslint/lib/formatters/checkstyle.js b/tools/eslint/lib/formatters/checkstyle.js index 5985ad0eff5752..c807871930bdec 100644 --- a/tools/eslint/lib/formatters/checkstyle.js +++ b/tools/eslint/lib/formatters/checkstyle.js @@ -19,9 +19,9 @@ const xmlEscape = require("../util/xml-escape"); function getMessageType(message) { if (message.fatal || message.severity === 2) { return "error"; - } else { - return "warning"; } + return "warning"; + } //------------------------------------------------------------------------------ diff --git a/tools/eslint/lib/formatters/codeframe.js b/tools/eslint/lib/formatters/codeframe.js index e8cd59bb94b3a8..1191ccb8efaae9 100644 --- a/tools/eslint/lib/formatters/codeframe.js +++ b/tools/eslint/lib/formatters/codeframe.js @@ -56,7 +56,7 @@ function formatMessage(message, parentResult) { `${type}:`, `${msg}`, ruleId ? `${ruleId}` : "", - sourceCode ? `at ${filePath}:` : `at ${filePath}`, + sourceCode ? `at ${filePath}:` : `at ${filePath}` ].filter(String).join(" "); const result = [firstLine]; @@ -101,15 +101,10 @@ module.exports = function(results) { const resultsWithMessages = results.filter(result => result.messages.length > 0); let output = resultsWithMessages.reduce((resultsOutput, result) => { - const messages = result.messages.map(message => { - if (message.fatal || message.severity === 2) { - errors++; - } else { - warnings++; - } - - return `${formatMessage(message, result)}\n\n`; - }); + const messages = result.messages.map(message => `${formatMessage(message, result)}\n\n`); + + errors += result.errorCount; + warnings += result.warningCount; return resultsOutput.concat(messages); }, []).join("\n"); diff --git a/tools/eslint/lib/formatters/compact.js b/tools/eslint/lib/formatters/compact.js index c641039ff284c6..2b540bde2361c1 100644 --- a/tools/eslint/lib/formatters/compact.js +++ b/tools/eslint/lib/formatters/compact.js @@ -17,9 +17,9 @@ function getMessageType(message) { if (message.fatal || message.severity === 2) { return "Error"; - } else { - return "Warning"; } + return "Warning"; + } diff --git a/tools/eslint/lib/formatters/junit.js b/tools/eslint/lib/formatters/junit.js index 35b03bf9ffc139..c41a2a4dd8b962 100644 --- a/tools/eslint/lib/formatters/junit.js +++ b/tools/eslint/lib/formatters/junit.js @@ -19,9 +19,9 @@ const xmlEscape = require("../util/xml-escape"); function getMessageType(message) { if (message.fatal || message.severity === 2) { return "Error"; - } else { - return "Warning"; } + return "Warning"; + } //------------------------------------------------------------------------------ diff --git a/tools/eslint/lib/formatters/stylish.js b/tools/eslint/lib/formatters/stylish.js index a176d03ab83e0b..c19b95d6e3b7be 100644 --- a/tools/eslint/lib/formatters/stylish.js +++ b/tools/eslint/lib/formatters/stylish.js @@ -28,7 +28,6 @@ function pluralize(word, count) { module.exports = function(results) { let output = "\n", - total = 0, errors = 0, warnings = 0, summaryColor = "yellow"; @@ -40,7 +39,9 @@ module.exports = function(results) { return; } - total += messages.length; + errors += result.errorCount; + warnings += result.warningCount; + output += `${chalk.underline(result.filePath)}\n`; output += `${table( @@ -50,10 +51,8 @@ module.exports = function(results) { if (message.fatal || message.severity === 2) { messageType = chalk.red("error"); summaryColor = "red"; - errors++; } else { messageType = chalk.yellow("warning"); - warnings++; } return [ @@ -74,6 +73,8 @@ 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; + if (total > 0) { output += chalk[summaryColor].bold([ "\u2716 ", total, pluralize(" problem", total), diff --git a/tools/eslint/lib/formatters/tap.js b/tools/eslint/lib/formatters/tap.js index 27825d0ba996e7..06699257b583c3 100644 --- a/tools/eslint/lib/formatters/tap.js +++ b/tools/eslint/lib/formatters/tap.js @@ -18,9 +18,9 @@ const yaml = require("js-yaml"); function getMessageType(message) { if (message.fatal || message.severity === 2) { return "error"; - } else { - return "warning"; } + return "warning"; + } /** diff --git a/tools/eslint/lib/formatters/unix.js b/tools/eslint/lib/formatters/unix.js index a5635278bc3fa9..c6c4ebbdb9f4cc 100644 --- a/tools/eslint/lib/formatters/unix.js +++ b/tools/eslint/lib/formatters/unix.js @@ -16,9 +16,9 @@ function getMessageType(message) { if (message.fatal || message.severity === 2) { return "Error"; - } else { - return "Warning"; } + return "Warning"; + } diff --git a/tools/eslint/lib/formatters/visualstudio.js b/tools/eslint/lib/formatters/visualstudio.js index feb7fb4bef382b..0d49431db87926 100644 --- a/tools/eslint/lib/formatters/visualstudio.js +++ b/tools/eslint/lib/formatters/visualstudio.js @@ -18,9 +18,9 @@ function getMessageType(message) { if (message.fatal || message.severity === 2) { return "error"; - } else { - return "warning"; } + return "warning"; + } diff --git a/tools/eslint/lib/ignored-paths.js b/tools/eslint/lib/ignored-paths.js index bace73db6a394b..cfca7fa4ff1c3b 100644 --- a/tools/eslint/lib/ignored-paths.js +++ b/tools/eslint/lib/ignored-paths.js @@ -201,6 +201,12 @@ class IgnoredPaths { const ig = ignore().add(DEFAULT_IGNORE_DIRS); + if (this.options.dotfiles !== true) { + + // Ignore hidden folders. (This cannot be ".*", or else it's not possible to unignore hidden files) + ig.add([".*/*", "!../"]); + } + if (this.options.ignore) { ig.add(this.ig.custom); } diff --git a/tools/eslint/lib/internal-rules/internal-consistent-docs-description.js b/tools/eslint/lib/internal-rules/internal-consistent-docs-description.js index a4a5dca03fbbf2..55e2a6c7645a21 100644 --- a/tools/eslint/lib/internal-rules/internal-consistent-docs-description.js +++ b/tools/eslint/lib/internal-rules/internal-consistent-docs-description.js @@ -71,7 +71,7 @@ function checkMetaDocsDescription(context, exportsNode) { if (description === "") { context.report({ node: metaDocsDescription.value, - message: "`meta.docs.description` should not be empty.", + message: "`meta.docs.description` should not be empty." }); return; } diff --git a/tools/eslint/lib/internal-rules/internal-no-invalid-meta.js b/tools/eslint/lib/internal-rules/internal-no-invalid-meta.js index d1c78efa61e557..d13df358bfeb94 100644 --- a/tools/eslint/lib/internal-rules/internal-no-invalid-meta.js +++ b/tools/eslint/lib/internal-rules/internal-no-invalid-meta.js @@ -94,16 +94,6 @@ function hasMetaSchema(metaPropertyNode) { return getPropertyFromObject("schema", metaPropertyNode.value); } -/** - * Whether this `meta` ObjectExpression has a `fixable` property defined or not. - * - * @param {ASTNode} metaPropertyNode The `meta` ObjectExpression for this rule. - * @returns {boolean} `true` if a `fixable` property exists. - */ -function hasMetaFixable(metaPropertyNode) { - return getPropertyFromObject("fixable", metaPropertyNode.value); -} - /** * Checks the validity of the meta definition of this rule and reports any errors found. * @@ -112,7 +102,7 @@ function hasMetaFixable(metaPropertyNode) { * @param {boolean} ruleIsFixable whether the rule is fixable or not. * @returns {void} */ -function checkMetaValidity(context, exportsNode, ruleIsFixable) { +function checkMetaValidity(context, exportsNode) { const metaProperty = getMetaPropertyFromExportsNode(exportsNode); if (!metaProperty) { @@ -142,11 +132,6 @@ function checkMetaValidity(context, exportsNode, ruleIsFixable) { if (!hasMetaSchema(metaProperty)) { context.report(metaProperty, "Rule is missing a meta.schema property."); - return; - } - - if (ruleIsFixable && !hasMetaFixable(metaProperty)) { - context.report(metaProperty, "Rule is fixable, but is missing a meta.fixable property."); } } @@ -177,7 +162,6 @@ module.exports = { create(context) { let exportsNode; - let ruleIsFixable = false; return { AssignmentExpression(node) { @@ -191,35 +175,13 @@ module.exports = { } }, - CallExpression(node) { - - // If the rule has a call for `context.report` and a property `fix` - // is being passed in, then we consider that the rule is fixable. - // - // Note that we only look for context.report() calls in the new - // style (with single MessageDescriptor argument), because only - // calls in the new style can specify a fix. - if (node.callee.type === "MemberExpression" && - node.callee.object.type === "Identifier" && - node.callee.object.name === "context" && - node.callee.property.type === "Identifier" && - node.callee.property.name === "report" && - node.arguments.length === 1 && - node.arguments[0].type === "ObjectExpression") { - - if (getPropertyFromObject("fix", node.arguments[0])) { - ruleIsFixable = true; - } - } - }, - "Program:exit"() { if (!isCorrectExportsFormat(exportsNode)) { context.report({ node: exportsNode, message: "Rule does not export an Object. Make sure the rule follows the new rule format." }); return; } - checkMetaValidity(context, exportsNode, ruleIsFixable); + checkMetaValidity(context, exportsNode); } }; } diff --git a/tools/eslint/lib/rule-context.js b/tools/eslint/lib/rule-context.js index 9c80d2e1a31cc6..99221666af8847 100644 --- a/tools/eslint/lib/rule-context.js +++ b/tools/eslint/lib/rule-context.js @@ -8,7 +8,7 @@ // Requirements //------------------------------------------------------------------------------ -const RuleFixer = require("./util/rule-fixer"); +const ruleFixer = require("./util/rule-fixer"); //------------------------------------------------------------------------------ // Constants @@ -124,7 +124,7 @@ class RuleContext { // if there's a fix specified, get it if (typeof descriptor.fix === "function") { - fix = descriptor.fix(new RuleFixer()); + fix = descriptor.fix(ruleFixer); } this.eslint.report( diff --git a/tools/eslint/lib/rules.js b/tools/eslint/lib/rules.js index 80f83882d331cb..9244c96c7a1ab3 100644 --- a/tools/eslint/lib/rules.js +++ b/tools/eslint/lib/rules.js @@ -70,9 +70,9 @@ function importPlugin(plugin, pluginName) { function getHandler(ruleId) { if (typeof rules[ruleId] === "string") { return require(rules[ruleId]); - } else { - return rules[ruleId]; } + return rules[ruleId]; + } /** diff --git a/tools/eslint/lib/rules/array-callback-return.js b/tools/eslint/lib/rules/array-callback-return.js index 1713125a7a722d..cf64a98e327e7e 100644 --- a/tools/eslint/lib/rules/array-callback-return.js +++ b/tools/eslint/lib/rules/array-callback-return.js @@ -9,6 +9,8 @@ // Requirements //------------------------------------------------------------------------------ +const lodash = require("lodash"); + const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ @@ -147,7 +149,8 @@ module.exports = { upper: null, codePath: null, hasReturn: false, - shouldCheck: false + shouldCheck: false, + node: null }; /** @@ -168,8 +171,11 @@ module.exports = { node, loc: getLocation(node, context.getSourceCode()).loc.start, message: funcInfo.hasReturn - ? "Expected to return a value at the end of this function." - : "Expected to return a value in this function." + ? "Expected to return a value at the end of {{name}}." + : "Expected to return a value in {{name}}.", + data: { + name: astUtils.getFunctionNameWithKind(funcInfo.node) + } }); } } @@ -187,7 +193,8 @@ module.exports = { node.body.type === "BlockStatement" && isCallbackOfArrayMethod(node) && !node.async && - !node.generator + !node.generator, + node }; }, @@ -204,7 +211,10 @@ module.exports = { if (!node.argument) { context.report({ node, - message: "Expected a return value." + message: "{{name}} expected a return value.", + data: { + name: lodash.upperFirst(astUtils.getFunctionNameWithKind(funcInfo.node)) + } }); } } diff --git a/tools/eslint/lib/rules/arrow-body-style.js b/tools/eslint/lib/rules/arrow-body-style.js index 9778a6776f5e1f..f2f14245be97dc 100644 --- a/tools/eslint/lib/rules/arrow-body-style.js +++ b/tools/eslint/lib/rules/arrow-body-style.js @@ -4,6 +4,12 @@ */ "use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("../ast-utils"); + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -94,7 +100,7 @@ module.exports = { const firstValueToken = sourceCode.getTokenAfter(returnKeyword); let lastValueToken = sourceCode.getLastToken(blockBody[0]); - if (lastValueToken.type === "Punctuator" && lastValueToken.value === ";") { + if (astUtils.isSemicolonToken(lastValueToken)) { /* The last token of the returned value is the last token of the ReturnExpression (if * the ReturnExpression has no semicolon), or the second-to-last token (if the ReturnExpression @@ -114,7 +120,7 @@ module.exports = { const textBeforeReturn = sourceText.slice(arrowBody.range[0] + 1, returnKeyword.range[0]); const textBetweenReturnAndValue = sourceText.slice(returnKeyword.range[1], firstValueToken.range[0]); const rawReturnValueText = sourceText.slice(firstValueToken.range[0], lastValueToken.range[1]); - const returnValueText = firstValueToken.value === "{" ? `(${rawReturnValueText})` : rawReturnValueText; + const returnValueText = astUtils.isOpeningBraceToken(firstValueToken) ? `(${rawReturnValueText})` : rawReturnValueText; const textAfterValue = sourceText.slice(lastValueToken.range[1], blockBody[0].range[1] - 1); const textAfterReturnStatement = sourceText.slice(blockBody[0].range[1], arrowBody.range[1] - 1); @@ -136,10 +142,7 @@ module.exports = { loc: arrowBody.loc.start, message: "Expected block statement surrounding arrow body.", fix(fixer) { - const lastTokenBeforeBody = sourceCode.getTokensBetween(sourceCode.getFirstToken(node), arrowBody) - .reverse() - .find(token => token.value !== "("); - + const lastTokenBeforeBody = sourceCode.getLastTokenBetween(sourceCode.getFirstToken(node), arrowBody, astUtils.isNotOpeningParenToken); const firstBodyToken = sourceCode.getTokenAfter(lastTokenBeforeBody); return fixer.replaceTextRange( diff --git a/tools/eslint/lib/rules/arrow-parens.js b/tools/eslint/lib/rules/arrow-parens.js index e069e307eb2040..c292d1b492979c 100644 --- a/tools/eslint/lib/rules/arrow-parens.js +++ b/tools/eslint/lib/rules/arrow-parens.js @@ -4,6 +4,12 @@ */ "use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("../ast-utils"); + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -62,7 +68,7 @@ module.exports = { node.body.type !== "BlockStatement" && !node.returnType ) { - if (token.type === "Punctuator" && token.value === "(") { + if (astUtils.isOpeningParenToken(token)) { context.report({ node, message: requireForBlockBodyMessage, @@ -84,7 +90,7 @@ module.exports = { requireForBlockBody && node.body.type === "BlockStatement" ) { - if (token.type !== "Punctuator" || token.value !== "(") { + if (!astUtils.isOpeningParenToken(token)) { context.report({ node, message: requireForBlockBodyNoParensMessage, @@ -103,7 +109,7 @@ module.exports = { !node.params[0].typeAnnotation && !node.returnType ) { - if (token.type === "Punctuator" && token.value === "(") { + if (astUtils.isOpeningParenToken(token)) { context.report({ node, message: asNeededMessage, diff --git a/tools/eslint/lib/rules/arrow-spacing.js b/tools/eslint/lib/rules/arrow-spacing.js index 3bc9017630ba72..37e03907cb9f27 100644 --- a/tools/eslint/lib/rules/arrow-spacing.js +++ b/tools/eslint/lib/rules/arrow-spacing.js @@ -4,6 +4,12 @@ */ "use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("../ast-utils"); + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -51,12 +57,7 @@ module.exports = { * @returns {Object} Tokens of arrow and before/after arrow. */ function getTokens(node) { - let arrow = sourceCode.getTokenBefore(node.body); - - // skip '(' tokens. - while (arrow.value !== "=>") { - arrow = sourceCode.getTokenBefore(arrow); - } + const arrow = sourceCode.getTokenBefore(node.body, astUtils.isArrowToken); return { before: sourceCode.getTokenBefore(arrow), diff --git a/tools/eslint/lib/rules/block-spacing.js b/tools/eslint/lib/rules/block-spacing.js index 9c0a7f388ba3bb..f18381a31034c3 100644 --- a/tools/eslint/lib/rules/block-spacing.js +++ b/tools/eslint/lib/rules/block-spacing.js @@ -74,8 +74,8 @@ module.exports = { // Gets braces and the first/last token of content. const openBrace = getOpenBrace(node); const closeBrace = sourceCode.getLastToken(node); - const firstToken = sourceCode.getTokenOrCommentAfter(openBrace); - const lastToken = sourceCode.getTokenOrCommentBefore(closeBrace); + const firstToken = sourceCode.getTokenAfter(openBrace, { includeComments: true }); + const lastToken = sourceCode.getTokenBefore(closeBrace, { includeComments: true }); // Skip if the node is invalid or empty. if (openBrace.type !== "Punctuator" || diff --git a/tools/eslint/lib/rules/brace-style.js b/tools/eslint/lib/rules/brace-style.js index 197767b07c19a5..bb4433cc45cc36 100644 --- a/tools/eslint/lib/rules/brace-style.js +++ b/tools/eslint/lib/rules/brace-style.js @@ -5,6 +5,8 @@ "use strict"; +const astUtils = require("../ast-utils"); + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -52,215 +54,86 @@ module.exports = { //-------------------------------------------------------------------------- /** - * Determines if a given node is a block statement. - * @param {ASTNode} node The node to check. - * @returns {boolean} True if the node is a block statement, false if not. - * @private - */ - function isBlock(node) { - return node && node.type === "BlockStatement"; - } - - /** - * Check if the token is an punctuator with a value of curly brace - * @param {Object} token - Token to check - * @returns {boolean} true if its a curly punctuator - * @private - */ - function isCurlyPunctuator(token) { - return token.value === "{" || token.value === "}"; - } - - /** - * Reports a place where a newline unexpectedly appears - * @param {ASTNode} node The node to report - * @param {string} message The message to report + * Fixes a place where a newline unexpectedly appears * @param {Token} firstToken The token before the unexpected newline - * @returns {void} + * @param {Token} secondToken The token after the unexpected newline + * @returns {Function} A fixer function to remove the newlines between the tokens */ - function reportExtraNewline(node, message, firstToken) { - context.report({ - node, - message, - fix(fixer) { - const secondToken = sourceCode.getTokenAfter(firstToken); - const textBetween = sourceCode.getText().slice(firstToken.range[1], secondToken.range[0]); - const NEWLINE_REGEX = /\r\n|\r|\n|\u2028|\u2029/g; + 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 textBetween.trim() ? null : fixer.replaceTextRange([firstToken.range[1], secondToken.range[0]], textBetween.replace(NEWLINE_REGEX, "")); - } - }); + // 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, "")); } /** - * Binds a list of properties to a function that verifies that the opening - * curly brace is on the same line as its controlling statement of a given - * node. - * @param {...string} The properties to check on the node. - * @returns {Function} A function that will perform the check on a node - * @private - */ - function checkBlock() { - const blockProperties = arguments; - - return function(node) { - Array.prototype.forEach.call(blockProperties, blockProp => { - const block = node[blockProp]; - - if (!isBlock(block)) { - return; - } - - const previousToken = sourceCode.getTokenBefore(block); - const curlyToken = sourceCode.getFirstToken(block); - const curlyTokenEnd = sourceCode.getLastToken(block); - const allOnSameLine = previousToken.loc.start.line === curlyTokenEnd.loc.start.line; - - if (allOnSameLine && params.allowSingleLine) { - return; - } - - if (style !== "allman" && previousToken.loc.start.line !== curlyToken.loc.start.line) { - reportExtraNewline(node, OPEN_MESSAGE, previousToken); - } else if (style === "allman" && previousToken.loc.start.line === curlyToken.loc.start.line) { - context.report({ - node, - message: OPEN_MESSAGE_ALLMAN, - fix: fixer => fixer.insertTextBefore(curlyToken, "\n") - }); - } - - if (!block.body.length) { - return; - } - - if (curlyToken.loc.start.line === block.body[0].loc.start.line) { - context.report({ - node: block.body[0], - message: BODY_MESSAGE, - fix: fixer => fixer.insertTextAfter(curlyToken, "\n") - }); - } + * Validates a pair of curly brackets based on the user's config + * @param {Token} openingCurly The opening curly bracket + * @param {Token} closingCurly The closing curly bracket + * @returns {void} + */ + function validateCurlyPair(openingCurly, closingCurly) { + const tokenBeforeOpeningCurly = sourceCode.getTokenBefore(openingCurly); + const tokenAfterOpeningCurly = sourceCode.getTokenAfter(openingCurly); + const tokenBeforeClosingCurly = sourceCode.getTokenBefore(closingCurly); + const singleLineException = params.allowSingleLine && astUtils.isTokenOnSameLine(openingCurly, closingCurly); - if (curlyTokenEnd.loc.start.line === block.body[block.body.length - 1].loc.end.line) { - context.report({ - node: block.body[block.body.length - 1], - message: CLOSE_MESSAGE_SINGLE, - fix: fixer => fixer.insertTextBefore(curlyTokenEnd, "\n") - }); - } + if (style !== "allman" && !astUtils.isTokenOnSameLine(tokenBeforeOpeningCurly, openingCurly)) { + context.report({ + node: openingCurly, + message: OPEN_MESSAGE, + fix: removeNewlineBetween(tokenBeforeOpeningCurly, openingCurly) }); - }; - } - - /** - * Enforces the configured brace style on IfStatements - * @param {ASTNode} node An IfStatement node. - * @returns {void} - * @private - */ - function checkIfStatement(node) { - checkBlock("consequent", "alternate")(node); - - if (node.alternate) { - - const tokens = sourceCode.getTokensBefore(node.alternate, 2); - - if (style === "1tbs") { - if (tokens[0].loc.start.line !== tokens[1].loc.start.line && - node.consequent.type === "BlockStatement" && - isCurlyPunctuator(tokens[0])) { - reportExtraNewline(node.alternate, CLOSE_MESSAGE, tokens[0]); - } - } else if (tokens[0].loc.start.line === tokens[1].loc.start.line) { - context.report({ - node: node.alternate, - message: CLOSE_MESSAGE_STROUSTRUP_ALLMAN, - fix: fixer => fixer.insertTextAfter(tokens[0], "\n") - }); - } - } - } - - /** - * Enforces the configured brace style on TryStatements - * @param {ASTNode} node A TryStatement node. - * @returns {void} - * @private - */ - function checkTryStatement(node) { - checkBlock("block", "finalizer")(node); - if (isBlock(node.finalizer)) { - const tokens = sourceCode.getTokensBefore(node.finalizer, 2); - - if (style === "1tbs") { - if (tokens[0].loc.start.line !== tokens[1].loc.start.line) { - reportExtraNewline(node.finalizer, CLOSE_MESSAGE, tokens[0]); - } - } else if (tokens[0].loc.start.line === tokens[1].loc.start.line) { - context.report({ - node: node.finalizer, - message: CLOSE_MESSAGE_STROUSTRUP_ALLMAN, - fix: fixer => fixer.insertTextAfter(tokens[0], "\n") - }); - } + if (style === "allman" && astUtils.isTokenOnSameLine(tokenBeforeOpeningCurly, openingCurly) && !singleLineException) { + context.report({ + node: openingCurly, + message: OPEN_MESSAGE_ALLMAN, + fix: fixer => fixer.insertTextBefore(openingCurly, "\n") + }); } - } - - /** - * Enforces the configured brace style on CatchClauses - * @param {ASTNode} node A CatchClause node. - * @returns {void} - * @private - */ - function checkCatchClause(node) { - const previousToken = sourceCode.getTokenBefore(node), - firstToken = sourceCode.getFirstToken(node); - checkBlock("body")(node); + if (astUtils.isTokenOnSameLine(openingCurly, tokenAfterOpeningCurly) && tokenAfterOpeningCurly !== closingCurly && !singleLineException) { + context.report({ + node: openingCurly, + message: BODY_MESSAGE, + fix: fixer => fixer.insertTextAfter(openingCurly, "\n") + }); + } - if (isBlock(node.body)) { - if (style === "1tbs") { - if (previousToken.loc.start.line !== firstToken.loc.start.line) { - reportExtraNewline(node, CLOSE_MESSAGE, previousToken); - } - } else { - if (previousToken.loc.start.line === firstToken.loc.start.line) { - context.report({ - node, - message: CLOSE_MESSAGE_STROUSTRUP_ALLMAN, - fix: fixer => fixer.insertTextAfter(previousToken, "\n") - }); - } - } + if (tokenBeforeClosingCurly !== openingCurly && !singleLineException && astUtils.isTokenOnSameLine(tokenBeforeClosingCurly, closingCurly)) { + context.report({ + node: closingCurly, + message: CLOSE_MESSAGE_SINGLE, + fix: fixer => fixer.insertTextBefore(closingCurly, "\n") + }); } } /** - * Enforces the configured brace style on SwitchStatements - * @param {ASTNode} node A SwitchStatement node. - * @returns {void} - * @private - */ - function checkSwitchStatement(node) { - let tokens; + * Validates the location of a token that appears before a keyword (e.g. a newline before `else`) + * @param {Token} curlyToken The closing curly token. This is assumed to precede a keyword token (such as `else` or `finally`). + * @returns {void} + */ + function validateCurlyBeforeKeyword(curlyToken) { + const keywordToken = sourceCode.getTokenAfter(curlyToken); - if (node.cases && node.cases.length) { - tokens = sourceCode.getTokensBefore(node.cases[0], 2); - } else { - tokens = sourceCode.getLastTokens(node, 3); + if (style === "1tbs" && !astUtils.isTokenOnSameLine(curlyToken, keywordToken)) { + context.report({ + node: curlyToken, + message: CLOSE_MESSAGE, + fix: removeNewlineBetween(curlyToken, keywordToken) + }); } - if (style !== "allman" && tokens[0].loc.start.line !== tokens[1].loc.start.line) { - reportExtraNewline(node, OPEN_MESSAGE, tokens[0]); - } else if (style === "allman" && tokens[0].loc.start.line === tokens[1].loc.start.line) { + if (style !== "1tbs" && astUtils.isTokenOnSameLine(curlyToken, keywordToken)) { context.report({ - node, - message: OPEN_MESSAGE_ALLMAN, - fix: fixer => fixer.insertTextBefore(tokens[1], "\n") + node: curlyToken, + message: CLOSE_MESSAGE_STROUSTRUP_ALLMAN, + fix: fixer => fixer.insertTextAfter(curlyToken, "\n") }); } } @@ -270,20 +143,38 @@ module.exports = { //-------------------------------------------------------------------------- return { - FunctionDeclaration: checkBlock("body"), - FunctionExpression: checkBlock("body"), - ArrowFunctionExpression: checkBlock("body"), - IfStatement: checkIfStatement, - TryStatement: checkTryStatement, - CatchClause: checkCatchClause, - DoWhileStatement: checkBlock("body"), - WhileStatement: checkBlock("body"), - WithStatement: checkBlock("body"), - ForStatement: checkBlock("body"), - ForInStatement: checkBlock("body"), - ForOfStatement: checkBlock("body"), - SwitchStatement: checkSwitchStatement - }; + BlockStatement(node) { + if (!astUtils.STATEMENT_LIST_PARENTS.has(node.parent.type)) { + validateCurlyPair(sourceCode.getFirstToken(node), sourceCode.getLastToken(node)); + } + }, + ClassBody(node) { + validateCurlyPair(sourceCode.getFirstToken(node), sourceCode.getLastToken(node)); + }, + SwitchStatement(node) { + const closingCurly = sourceCode.getLastToken(node); + const openingCurly = sourceCode.getTokenBefore(node.cases.length ? node.cases[0] : closingCurly); + + validateCurlyPair(openingCurly, closingCurly); + }, + IfStatement(node) { + if (node.consequent.type === "BlockStatement" && node.alternate) { + + // Handle the keyword after the `if` block (before `else`) + validateCurlyBeforeKeyword(sourceCode.getLastToken(node.consequent)); + } + }, + TryStatement(node) { + + // Handle the keyword after the `try` block (before `catch` or `finally`) + validateCurlyBeforeKeyword(sourceCode.getLastToken(node.block)); + if (node.handler && node.finalizer) { + + // Handle the keyword after the `catch` block (before `finally`) + validateCurlyBeforeKeyword(sourceCode.getLastToken(node.handler.body)); + } + } + }; } }; diff --git a/tools/eslint/lib/rules/capitalized-comments.js b/tools/eslint/lib/rules/capitalized-comments.js index 29cff4450b535a..b8d5b8cd612d1e 100644 --- a/tools/eslint/lib/rules/capitalized-comments.js +++ b/tools/eslint/lib/rules/capitalized-comments.js @@ -9,6 +9,7 @@ //------------------------------------------------------------------------------ const LETTER_PATTERN = require("../util/patterns/letters"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -16,7 +17,7 @@ const LETTER_PATTERN = require("../util/patterns/letters"); const ALWAYS_MESSAGE = "Comments should not begin with a lowercase character", NEVER_MESSAGE = "Comments should not begin with an uppercase character", - DEFAULT_IGNORE_PATTERN = /^\s*(?:eslint|istanbul|jscs|jshint|globals?|exported)\b/, + DEFAULT_IGNORE_PATTERN = astUtils.COMMENTS_IGNORE_PATTERN, WHITESPACE = /\s/g, MAYBE_URL = /^\s*[^:/?#\s]+:\/\/[^?#]/, // TODO: Combine w/ max-len pattern? DEFAULTS = { @@ -163,8 +164,8 @@ module.exports = { * otherwise. */ function isInlineComment(comment) { - const previousToken = sourceCode.getTokenOrCommentBefore(comment), - nextToken = sourceCode.getTokenOrCommentAfter(comment); + const previousToken = sourceCode.getTokenBefore(comment, { includeComments: true }), + nextToken = sourceCode.getTokenAfter(comment, { includeComments: true }); return Boolean( previousToken && @@ -181,7 +182,7 @@ module.exports = { * @returns {boolean} True if the comment follows a valid comment. */ function isConsecutiveComment(comment) { - const previousTokenOrComment = sourceCode.getTokenOrCommentBefore(comment); + const previousTokenOrComment = sourceCode.getTokenBefore(comment, { includeComments: true }); return Boolean( previousTokenOrComment && @@ -264,9 +265,9 @@ module.exports = { commentValid = isCommentValid(comment, options); if (!commentValid) { - const message = capitalize === "always" ? - ALWAYS_MESSAGE : - NEVER_MESSAGE; + const message = capitalize === "always" + ? ALWAYS_MESSAGE + : NEVER_MESSAGE; context.report({ node: null, // Intentionally using loc instead diff --git a/tools/eslint/lib/rules/comma-dangle.js b/tools/eslint/lib/rules/comma-dangle.js index af7ab2767f5566..17066d94791c6a 100644 --- a/tools/eslint/lib/rules/comma-dangle.js +++ b/tools/eslint/lib/rules/comma-dangle.js @@ -10,6 +10,7 @@ //------------------------------------------------------------------------------ const lodash = require("lodash"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -20,7 +21,7 @@ const DEFAULT_OPTIONS = Object.freeze({ objects: "never", imports: "never", exports: "never", - functions: "ignore", + functions: "ignore" }); /** @@ -53,7 +54,7 @@ function normalizeOptions(optionValue) { exports: optionValue, // For backward compatibility, always ignore functions. - functions: "ignore", + functions: "ignore" }; } if (typeof optionValue === "object" && optionValue !== null) { @@ -62,7 +63,7 @@ function normalizeOptions(optionValue) { objects: optionValue.objects || DEFAULT_OPTIONS.objects, imports: optionValue.imports || DEFAULT_OPTIONS.imports, exports: optionValue.exports || DEFAULT_OPTIONS.exports, - functions: optionValue.functions || DEFAULT_OPTIONS.functions, + functions: optionValue.functions || DEFAULT_OPTIONS.functions }; } @@ -121,7 +122,7 @@ module.exports = { additionalProperties: false } ] - }, + } ] }, @@ -178,7 +179,7 @@ module.exports = { default: { const nextToken = sourceCode.getTokenAfter(lastItem); - if (nextToken.value === ",") { + if (astUtils.isCommaToken(nextToken)) { return nextToken; } return sourceCode.getLastToken(lastItem); @@ -224,7 +225,7 @@ module.exports = { const trailingToken = getTrailingToken(node, lastItem); - if (trailingToken.value === ",") { + if (astUtils.isCommaToken(trailingToken)) { context.report({ node: lastItem, loc: trailingToken.loc.start, @@ -312,7 +313,7 @@ module.exports = { "always-multiline": forceTrailingCommaIfMultiline, "only-multiline": allowTrailingCommaIfMultiline, never: forbidTrailingComma, - ignore: lodash.noop, + ignore: lodash.noop }; return { @@ -330,7 +331,7 @@ module.exports = { FunctionExpression: predicate[options.functions], ArrowFunctionExpression: predicate[options.functions], CallExpression: predicate[options.functions], - NewExpression: predicate[options.functions], + NewExpression: predicate[options.functions] }; } }; diff --git a/tools/eslint/lib/rules/comma-spacing.js b/tools/eslint/lib/rules/comma-spacing.js index f571cfa199675a..bb1dd68f63987e 100644 --- a/tools/eslint/lib/rules/comma-spacing.js +++ b/tools/eslint/lib/rules/comma-spacing.js @@ -53,16 +53,6 @@ module.exports = { // list of comma tokens to ignore for the check of leading whitespace const commaTokensToIgnore = []; - /** - * Determines if a given token is a comma operator. - * @param {ASTNode} token The token to check. - * @returns {boolean} True if the token is a comma, false if not. - * @private - */ - function isComma(token) { - return !!token && (token.type === "Punctuator") && (token.value === ","); - } - /** * Reports a spacing error with an appropriate message. * @param {ASTNode} node The binary expression node to report. @@ -78,27 +68,27 @@ module.exports = { if (options[dir]) { if (dir === "before") { return fixer.insertTextBefore(node, " "); - } else { - return fixer.insertTextAfter(node, " "); } - } else { - let start, end; - const newText = ""; + return fixer.insertTextAfter(node, " "); - if (dir === "before") { - start = otherNode.range[1]; - end = node.range[0]; - } else { - start = node.range[1]; - end = otherNode.range[0]; - } + } + let start, end; + const newText = ""; - return fixer.replaceTextRange([start, end], newText); + if (dir === "before") { + start = otherNode.range[1]; + end = node.range[0]; + } else { + start = node.range[1]; + end = otherNode.range[0]; } + + return fixer.replaceTextRange([start, end], newText); + }, - message: options[dir] ? - "A space is required {{dir}} ','." : - "There should be no space {{dir}} ','.", + message: options[dir] + ? "A space is required {{dir}} ','." + : "There should be no space {{dir}} ','.", data: { dir } @@ -147,7 +137,7 @@ module.exports = { if (element === null) { token = sourceCode.getTokenAfter(previousToken); - if (isComma(token)) { + if (astUtils.isCommaToken(token)) { commaTokensToIgnore.push(token); } } else { @@ -166,7 +156,7 @@ module.exports = { "Program:exit"() { tokensAndComments.forEach((token, i) => { - if (!isComma(token)) { + if (!astUtils.isCommaToken(token)) { return; } @@ -179,8 +169,8 @@ module.exports = { validateCommaItemSpacing({ comma: token, - left: isComma(previousToken) || commaTokensToIgnore.indexOf(token) > -1 ? null : previousToken, - right: isComma(nextToken) ? null : nextToken + left: astUtils.isCommaToken(previousToken) || commaTokensToIgnore.indexOf(token) > -1 ? null : previousToken, + right: astUtils.isCommaToken(nextToken) ? null : nextToken }, token); }); }, diff --git a/tools/eslint/lib/rules/comma-style.js b/tools/eslint/lib/rules/comma-style.js index bb290f90b980d1..fcaecc662bce8c 100644 --- a/tools/eslint/lib/rules/comma-style.js +++ b/tools/eslint/lib/rules/comma-style.js @@ -48,7 +48,7 @@ module.exports = { FunctionDeclaration: true, FunctionExpression: true, ImportDeclaration: true, - ObjectPattern: true, + ObjectPattern: true }; if (context.options.length === 2 && context.options[1].hasOwnProperty("exceptions")) { @@ -63,16 +63,6 @@ module.exports = { // Helpers //-------------------------------------------------------------------------- - /** - * Determines if a given token is a comma operator. - * @param {ASTNode} token The token to check. - * @returns {boolean} True if the token is a comma, false if not. - * @private - */ - function isComma(token) { - return !!token && (token.type === "Punctuator") && (token.value === ","); - } - /** * Modified text based on the style * @param {string} styleType Style type @@ -192,7 +182,7 @@ module.exports = { tokenBeforeComma = sourceCode.getTokenBefore(commaToken); // Check if previous token is wrapped in parentheses - if (tokenBeforeComma && tokenBeforeComma.value === ")") { + if (tokenBeforeComma && astUtils.isClosingParenToken(tokenBeforeComma)) { previousItemToken = tokenBeforeComma; } @@ -210,12 +200,16 @@ module.exports = { * All comparisons are done based on these tokens directly, so * they are always valid regardless of an undefined item. */ - if (isComma(commaToken)) { + if (astUtils.isCommaToken(commaToken)) { validateCommaItemSpacing(previousItemToken, commaToken, currentItemToken, reportItem); } - previousItemToken = item ? sourceCode.getLastToken(item) : previousItemToken; + if (item) { + const tokenAfterItem = sourceCode.getTokenAfter(item, astUtils.isNotClosingParenToken); + + previousItemToken = tokenAfterItem ? sourceCode.getTokenBefore(tokenAfterItem) : sourceCode.ast.tokens[sourceCode.ast.tokens.length - 1]; + } }); /* @@ -229,7 +223,7 @@ module.exports = { const lastToken = sourceCode.getLastToken(node), nextToLastToken = sourceCode.getTokenBefore(lastToken); - if (isComma(nextToLastToken)) { + if (astUtils.isCommaToken(nextToLastToken)) { validateCommaItemSpacing( sourceCode.getTokenBefore(nextToLastToken), nextToLastToken, diff --git a/tools/eslint/lib/rules/complexity.js b/tools/eslint/lib/rules/complexity.js index 2f3e4040799872..14617bc3537aef 100644 --- a/tools/eslint/lib/rules/complexity.js +++ b/tools/eslint/lib/rules/complexity.js @@ -6,6 +6,14 @@ "use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const lodash = require("lodash"); + +const astUtils = require("../ast-utils"); + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -81,17 +89,15 @@ module.exports = { * @private */ function endFunction(node) { + const name = lodash.upperFirst(astUtils.getFunctionNameWithKind(node)); const complexity = fns.pop(); - let name = "anonymous"; - - if (node.id) { - name = node.id.name; - } else if (node.parent.type === "MethodDefinition" || node.parent.type === "Property") { - name = node.parent.key.name; - } if (complexity > THRESHOLD) { - context.report({ node, message: "Function '{{name}}' has a complexity of {{complexity}}.", data: { name, complexity } }); + context.report({ + node, + message: "{{name}} has a complexity of {{complexity}}.", + data: { name, complexity } + }); } } diff --git a/tools/eslint/lib/rules/consistent-return.js b/tools/eslint/lib/rules/consistent-return.js index 0c1a6a7493f663..20469772a91121 100644 --- a/tools/eslint/lib/rules/consistent-return.js +++ b/tools/eslint/lib/rules/consistent-return.js @@ -8,6 +8,8 @@ // Requirements //------------------------------------------------------------------------------ +const lodash = require("lodash"); + const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ @@ -81,7 +83,7 @@ module.exports = { * @returns {void} */ function checkLastSegment(node) { - let loc, type; + let loc, name; /* * Skip if it expected no return value or unreachable. @@ -100,12 +102,11 @@ module.exports = { // The head of program. loc = { line: 1, column: 0 }; - type = "program"; + name = "program"; } else if (node.type === "ArrowFunctionExpression") { // `=>` token - loc = context.getSourceCode().getTokenBefore(node.body).loc.start; - type = "function"; + loc = context.getSourceCode().getTokenBefore(node.body, astUtils.isArrowToken).loc.start; } else if ( node.parent.type === "MethodDefinition" || (node.parent.type === "Property" && node.parent.method) @@ -113,33 +114,36 @@ module.exports = { // Method name. loc = node.parent.key.loc.start; - type = "method"; } else { // Function name or `function` keyword. loc = (node.id || node).loc.start; - type = "function"; + } + + if (!name) { + name = astUtils.getFunctionNameWithKind(node); } // Reports. context.report({ node, loc, - message: "Expected to return a value at the end of this {{type}}.", - data: { type } + message: "Expected to return a value at the end of {{name}}.", + data: { name } }); } return { // Initializes/Disposes state of each code path. - onCodePathStart(codePath) { + onCodePathStart(codePath, node) { funcInfo = { upper: funcInfo, codePath, hasReturn: false, hasReturnValue: false, - message: "" + message: "", + node }; }, onCodePathEnd() { @@ -158,8 +162,11 @@ module.exports = { if (!funcInfo.hasReturn) { funcInfo.hasReturn = true; funcInfo.hasReturnValue = hasReturnValue; - funcInfo.message = "Expected {{which}} return value."; + funcInfo.message = "{{name}} expected {{which}} return value."; funcInfo.data = { + name: funcInfo.node.type === "Program" + ? "Program" + : lodash.upperFirst(astUtils.getFunctionNameWithKind(funcInfo.node)), which: hasReturnValue ? "a" : "no" }; } else if (funcInfo.hasReturnValue !== hasReturnValue) { diff --git a/tools/eslint/lib/rules/constructor-super.js b/tools/eslint/lib/rules/constructor-super.js index e84df7e81da025..d0a238df8edbd3 100644 --- a/tools/eslint/lib/rules/constructor-super.js +++ b/tools/eslint/lib/rules/constructor-super.js @@ -209,9 +209,9 @@ module.exports = { if (!calledInEveryPaths) { context.report({ - message: calledInSomePaths ? - "Lacked a call of 'super()' in some code paths." : - "Expected to call 'super()'.", + message: calledInSomePaths + ? "Lacked a call of 'super()' in some code paths." + : "Expected to call 'super()'.", node: node.parent }); } diff --git a/tools/eslint/lib/rules/curly.js b/tools/eslint/lib/rules/curly.js index 801552d69e151b..cd15b2d93574df 100644 --- a/tools/eslint/lib/rules/curly.js +++ b/tools/eslint/lib/rules/curly.js @@ -76,7 +76,7 @@ module.exports = { function isCollapsedOneLiner(node) { const before = sourceCode.getTokenBefore(node); const last = sourceCode.getLastToken(node); - const lastExcludingSemicolon = last.type === "Punctuator" && last.value === ";" ? sourceCode.getTokenBefore(last) : last; + const lastExcludingSemicolon = astUtils.isSemicolonToken(last) ? sourceCode.getTokenBefore(last) : last; return before.loc.start.line === lastExcludingSemicolon.loc.end.line; } @@ -94,19 +94,23 @@ module.exports = { return first.loc.start.line === last.loc.end.line; } + /** + * Checks if the given token is an `else` token or not. + * + * @param {Token} token - The token to check. + * @returns {boolean} `true` if the token is an `else` token. + */ + function isElseKeywordToken(token) { + return token.value === "else" && token.type === "Keyword"; + } + /** * Gets the `else` keyword token of a given `IfStatement` node. * @param {ASTNode} node - A `IfStatement` node to get. * @returns {Token} The `else` keyword token. */ function getElseKeyword(node) { - let token = sourceCode.getTokenAfter(node.consequent); - - while (token.type !== "Keyword" || token.value !== "else") { - token = sourceCode.getTokenAfter(token); - } - - return token; + return node.alternate && sourceCode.getFirstTokenBetween(node.consequent, node.alternate, isElseKeywordToken); } /** @@ -170,7 +174,7 @@ module.exports = { const tokenAfter = sourceCode.getTokenAfter(closingBracket); const lastBlockNode = sourceCode.getNodeByRangeIndex(tokenBefore.range[0]); - if (tokenBefore.value === ";") { + if (astUtils.isSemicolonToken(tokenBefore)) { // If the last statement already has a semicolon, don't add another one. return false; diff --git a/tools/eslint/lib/rules/default-case.js b/tools/eslint/lib/rules/default-case.js index 070ff3c7a9666b..3efcbbced5dcab 100644 --- a/tools/eslint/lib/rules/default-case.js +++ b/tools/eslint/lib/rules/default-case.js @@ -31,9 +31,9 @@ module.exports = { create(context) { const options = context.options[0] || {}; - const commentPattern = options.commentPattern ? - new RegExp(options.commentPattern) : - DEFAULT_COMMENT_PATTERN; + const commentPattern = options.commentPattern + ? new RegExp(options.commentPattern) + : DEFAULT_COMMENT_PATTERN; const sourceCode = context.getSourceCode(); diff --git a/tools/eslint/lib/rules/dot-notation.js b/tools/eslint/lib/rules/dot-notation.js index d55b098b25b9b3..abb9b4b4881b34 100644 --- a/tools/eslint/lib/rules/dot-notation.js +++ b/tools/eslint/lib/rules/dot-notation.js @@ -4,6 +4,12 @@ */ "use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("../ast-utils"); + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -64,20 +70,20 @@ module.exports = { propertyValue: JSON.stringify(node.property.value) }, fix(fixer) { - const leftBracket = sourceCode.getTokenBefore(node.property); - const rightBracket = sourceCode.getTokenAfter(node.property); - const textBeforeProperty = sourceCode.text.slice(leftBracket.range[1], node.property.range[0]); - const textAfterProperty = sourceCode.text.slice(node.property.range[1], rightBracket.range[0]); + const leftBracket = sourceCode.getTokenAfter(node.object, astUtils.isOpeningBracketToken); + const rightBracket = sourceCode.getLastToken(node); - if (textBeforeProperty.trim() || textAfterProperty.trim()) { + if (sourceCode.getFirstTokenBetween(leftBracket, rightBracket, { includeComments: true, filter: astUtils.isCommentToken })) { // Don't perform any fixes if there are comments inside the brackets. return null; } + const textBeforeDot = astUtils.isDecimalInteger(node.object) ? " " : ""; + return fixer.replaceTextRange( [leftBracket.range[0], rightBracket.range[1]], - `.${node.property.value}` + `${textBeforeDot}.${node.property.value}` ); } }); diff --git a/tools/eslint/lib/rules/eqeqeq.js b/tools/eslint/lib/rules/eqeqeq.js index d77607afb5f2aa..8801102e649aa4 100644 --- a/tools/eslint/lib/rules/eqeqeq.js +++ b/tools/eslint/lib/rules/eqeqeq.js @@ -5,6 +5,12 @@ "use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("../ast-utils"); + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -57,9 +63,9 @@ module.exports = { const options = context.options[1] || {}; const sourceCode = context.getSourceCode(); - const nullOption = (config === "always") ? - options.null || "always" : - "ignore"; + const nullOption = (config === "always") + ? options.null || "always" + : "ignore"; const enforceRuleForNull = (nullOption === "always"); const enforceInverseRuleForNull = (nullOption === "never"); @@ -100,8 +106,7 @@ module.exports = { * @private */ function isNullCheck(node) { - return (node.right.type === "Literal" && node.right.value === null) || - (node.left.type === "Literal" && node.left.value === null); + return astUtils.isNullLiteral(node.right) || astUtils.isNullLiteral(node.left); } /** @@ -134,7 +139,11 @@ module.exports = { // If the comparison is a `typeof` comparison or both sides are literals with the same type, then it's safe to fix. if (isTypeOfBinary(node) || areLiteralsAndSameType(node)) { - const operatorToken = sourceCode.getTokensBetween(node.left, node.right).find(token => token.value === node.operator); + const operatorToken = sourceCode.getFirstTokenBetween( + node.left, + node.right, + token => token.value === node.operator + ); return fixer.replaceText(operatorToken, expectedOperator); } diff --git a/tools/eslint/lib/rules/func-call-spacing.js b/tools/eslint/lib/rules/func-call-spacing.js index 5c416f0373fcac..4fd78c864b3890 100644 --- a/tools/eslint/lib/rules/func-call-spacing.js +++ b/tools/eslint/lib/rules/func-call-spacing.js @@ -5,6 +5,12 @@ "use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("../ast-utils"); + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -67,28 +73,19 @@ module.exports = { * @private */ function checkSpacing(node) { + const lastToken = sourceCode.getLastToken(node); const lastCalleeToken = sourceCode.getLastToken(node.callee); - let prevToken = lastCalleeToken; - let parenToken = sourceCode.getTokenAfter(lastCalleeToken); - - // advances to an open parenthesis. - while ( - parenToken && - parenToken.range[1] < node.range[1] && - parenToken.value !== "(" - ) { - prevToken = parenToken; - parenToken = sourceCode.getTokenAfter(parenToken); - } + const parenToken = sourceCode.getFirstTokenBetween(lastCalleeToken, lastToken, astUtils.isOpeningParenToken); + const prevToken = parenToken && sourceCode.getTokenBefore(parenToken); // Parens in NewExpression are optional if (!(parenToken && parenToken.range[1] < node.range[1])) { return; } - const hasWhitespace = sourceCode.isSpaceBetweenTokens(prevToken, parenToken); - const hasNewline = hasWhitespace && - /\n/.test(text.slice(prevToken.range[1], parenToken.range[0]).replace(/\/\*.*?\*\//g, "")); + const textBetweenTokens = text.slice(prevToken.range[1], parenToken.range[0]).replace(/\/\*.*?\*\//g, ""); + const hasWhitespace = /\s/.test(textBetweenTokens); + const hasNewline = hasWhitespace && astUtils.LINEBREAK_MATCHER.test(textBetweenTokens); /* * never allowNewlines hasWhitespace hasNewline message diff --git a/tools/eslint/lib/rules/func-name-matching.js b/tools/eslint/lib/rules/func-name-matching.js index 4eed7a68ea2b51..db06d5d468d774 100644 --- a/tools/eslint/lib/rules/func-name-matching.js +++ b/tools/eslint/lib/rules/func-name-matching.js @@ -132,6 +132,15 @@ module.exports = { }); } + /** + * Determines whether a given node is a string literal + * @param {ASTNode} node The node to check + * @returns {boolean} `true` if the node is a string literal + */ + function isStringLiteral(node) { + return node.type === "Literal" && typeof node.value === "string"; + } + //-------------------------------------------------------------------------- // Public //-------------------------------------------------------------------------- @@ -139,7 +148,7 @@ module.exports = { return { VariableDeclarator(node) { - if (!node.init || node.init.type !== "FunctionExpression") { + if (!node.init || node.init.type !== "FunctionExpression" || node.id.type !== "Identifier") { return; } if (node.init.id && shouldWarn(node.id.name, node.init.id.name)) { @@ -148,14 +157,16 @@ module.exports = { }, AssignmentExpression(node) { - if (node.right.type !== "FunctionExpression" || - (node.left.computed && node.left.property.type !== "Literal") || - (!includeModuleExports && isModuleExports(node.left)) - ) { + if ( + node.right.type !== "FunctionExpression" || + (node.left.computed && node.left.property.type !== "Literal") || + (!includeModuleExports && isModuleExports(node.left)) || + (node.left.type !== "Identifier" && node.left.type !== "MemberExpression") + ) { return; } - const isProp = node.left.type === "MemberExpression" ? true : false; + const isProp = node.left.type === "MemberExpression"; const name = isProp ? astUtils.getStaticPropertyName(node.left) : node.left.name; if (node.right.id && isIdentifier(name) && shouldWarn(name, node.right.id.name)) { @@ -164,13 +175,13 @@ module.exports = { }, Property(node) { - if (node.value.type !== "FunctionExpression" || !node.value.id || node.computed && node.key.type !== "Literal") { + if (node.value.type !== "FunctionExpression" || !node.value.id || node.computed && !isStringLiteral(node.key)) { return; } if (node.key.type === "Identifier" && shouldWarn(node.key.name, node.value.id.name)) { report(node, node.key.name, node.value.id.name, true); } else if ( - node.key.type === "Literal" && + isStringLiteral(node.key) && isIdentifier(node.key.value, ecmaVersion) && shouldWarn(node.key.value, node.value.id.name) ) { diff --git a/tools/eslint/lib/rules/func-names.js b/tools/eslint/lib/rules/func-names.js index 0d8567149493dc..e7f950c9ba593d 100644 --- a/tools/eslint/lib/rules/func-names.js +++ b/tools/eslint/lib/rules/func-names.js @@ -5,6 +5,12 @@ "use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("../ast-utils"); + /** * Checks whether or not a given variable is a function name. * @param {escope.Variable} variable - A variable to check. @@ -82,15 +88,24 @@ module.exports = { return; } - const name = node.id && node.id.name; + const hasName = Boolean(node.id && node.id.name); + const name = astUtils.getFunctionNameWithKind(node); if (never) { - if (name) { - context.report({ node, message: "Unexpected function expression name." }); + if (hasName) { + context.report({ + node, + message: "Unexpected named {{name}}.", + data: { name } + }); } } else { - if (!name && (asNeeded ? !hasInferredName(node) : !isObjectOrClassMethod(node))) { - context.report({ node, message: "Missing function expression name." }); + if (!hasName && (asNeeded ? !hasInferredName(node) : !isObjectOrClassMethod(node))) { + context.report({ + node, + message: "Unexpected unnamed {{name}}.", + data: { name } + }); } } } diff --git a/tools/eslint/lib/rules/generator-star-spacing.js b/tools/eslint/lib/rules/generator-star-spacing.js index fc676d0cbbb85f..9836e4ead9767f 100644 --- a/tools/eslint/lib/rules/generator-star-spacing.js +++ b/tools/eslint/lib/rules/generator-star-spacing.js @@ -55,21 +55,26 @@ module.exports = { const sourceCode = context.getSourceCode(); /** - * Gets `*` token from a given node. + * Checks if the given token is a star token or not. * - * @param {ASTNode} node - A node to get `*` token. This is one of - * FunctionDeclaration, FunctionExpression, Property, and - * MethodDefinition. - * @returns {Token} `*` token. + * @param {Token} token - The token to check. + * @returns {boolean} `true` if the token is a star token. */ - function getStarToken(node) { - let token = sourceCode.getFirstToken(node); - - while (token.value !== "*") { - token = sourceCode.getTokenAfter(token); - } + function isStarToken(token) { + return token.value === "*" && token.type === "Punctuator"; + } - return token; + /** + * Gets the generator star token of the given function node. + * + * @param {ASTNode} node - The function node to get. + * @returns {Token} Found star token. + */ + function getStarToken(node) { + return sourceCode.getFirstToken( + (node.parent.method || node.parent.type === "MethodDefinition") ? node.parent : node, + isStarToken + ); } /** @@ -116,17 +121,11 @@ module.exports = { * @returns {void} */ function checkFunction(node) { - let starToken; - if (!node.generator) { return; } - if (node.parent.method || node.parent.type === "MethodDefinition") { - starToken = getStarToken(node.parent); - } else { - starToken = getStarToken(node); - } + const starToken = getStarToken(node); // Only check before when preceded by `function`|`static` keyword const prevToken = sourceCode.getTokenBefore(starToken); diff --git a/tools/eslint/lib/rules/global-require.js b/tools/eslint/lib/rules/global-require.js index bfd01433957e3e..367fe590ed2210 100644 --- a/tools/eslint/lib/rules/global-require.js +++ b/tools/eslint/lib/rules/global-require.js @@ -29,9 +29,9 @@ function findReference(scope, node) { /* istanbul ignore else: correctly returns null */ if (references.length === 1) { return references[0]; - } else { - return null; } + return null; + } /** diff --git a/tools/eslint/lib/rules/id-blacklist.js b/tools/eslint/lib/rules/id-blacklist.js index f94f6d0a4684d4..d03ee1ec233d07 100644 --- a/tools/eslint/lib/rules/id-blacklist.js +++ b/tools/eslint/lib/rules/id-blacklist.js @@ -55,8 +55,8 @@ module.exports = { * @returns {boolean} whether an error should be reported or not */ function shouldReport(effectiveParent, name) { - return effectiveParent.type !== "CallExpression" - && effectiveParent.type !== "NewExpression" && + return effectiveParent.type !== "CallExpression" && + effectiveParent.type !== "NewExpression" && isInvalid(name); } diff --git a/tools/eslint/lib/rules/id-length.js b/tools/eslint/lib/rules/id-length.js index 6a6c69d1017e8c..341f929cdec27e 100644 --- a/tools/eslint/lib/rules/id-length.js +++ b/tools/eslint/lib/rules/id-length.js @@ -104,9 +104,9 @@ module.exports = { if (isValidExpression && (isValidExpression === true || isValidExpression(parent, node))) { context.report({ node, - message: isShort ? - "Identifier name '{{name}}' is too short (< {{min}})." : - "Identifier name '{{name}}' is too long (> {{max}}).", + message: isShort + ? "Identifier name '{{name}}' is too short (< {{min}})." + : "Identifier name '{{name}}' is too long (> {{max}}).", data: { name, min: minLength, max: maxLength } }); } diff --git a/tools/eslint/lib/rules/id-match.js b/tools/eslint/lib/rules/id-match.js index 29d06c36024c57..7536e07b10945a 100644 --- a/tools/eslint/lib/rules/id-match.js +++ b/tools/eslint/lib/rules/id-match.js @@ -63,8 +63,8 @@ module.exports = { * @returns {boolean} whether an error should be reported or not */ function shouldReport(effectiveParent, name) { - return effectiveParent.type !== "CallExpression" - && effectiveParent.type !== "NewExpression" && + return effectiveParent.type !== "CallExpression" && + effectiveParent.type !== "NewExpression" && isInvalid(name); } diff --git a/tools/eslint/lib/rules/indent.js b/tools/eslint/lib/rules/indent.js index 6c3c27c8e1941a..bba1b20bcf4407 100644 --- a/tools/eslint/lib/rules/indent.js +++ b/tools/eslint/lib/rules/indent.js @@ -8,6 +8,12 @@ "use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("../ast-utils"); + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -435,15 +441,10 @@ module.exports = { * @returns {void} */ function checkLastReturnStatementLineIndent(node, firstLineIndent) { - const nodeLastToken = sourceCode.getLastToken(node); - let lastToken = nodeLastToken; // in case if return statement ends with ');' we have traverse back to ')' // otherwise we'll measure indent for ';' and replace ')' - while (lastToken.value !== ")") { - lastToken = sourceCode.getTokenBefore(lastToken); - } - + const lastToken = sourceCode.getLastToken(node, astUtils.isClosingParenToken); const textBeforeClosingParenthesis = sourceCode.getText(lastToken, lastToken.loc.start.column).slice(0, -1); if (textBeforeClosingParenthesis.trim()) { @@ -691,9 +692,9 @@ module.exports = { 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"; - } else { - return false; } + return false; + } /** @@ -729,7 +730,7 @@ module.exports = { } else if (parent.type === "ObjectExpression" || parent.type === "ArrayExpression") { const parentElements = node.parent.type === "ObjectExpression" ? node.parent.properties : node.parent.elements; - if (parentElements[0].loc.start.line === parent.loc.start.line && parentElements[0].loc.end.line !== parent.loc.start.line) { + 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. @@ -936,20 +937,20 @@ module.exports = { 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 { - if (typeof switchIndent === "undefined") { - switchIndent = getNodeIndent(switchNode).goodChar; - } + caseIndent = switchIndent + (indentSize * options.SwitchCase); + } - if (switchNode.cases.length > 0 && options.SwitchCase === 0) { - caseIndent = switchIndent; - } else { - caseIndent = switchIndent + (indentSize * options.SwitchCase); - } + caseIndentStore[switchNode.loc.start.line] = caseIndent; + return caseIndent; - caseIndentStore[switchNode.loc.start.line] = caseIndent; - return caseIndent; - } } /** diff --git a/tools/eslint/lib/rules/key-spacing.js b/tools/eslint/lib/rules/key-spacing.js index 8d7564a5bbf246..ce150753b849b6 100644 --- a/tools/eslint/lib/rules/key-spacing.js +++ b/tools/eslint/lib/rules/key-spacing.js @@ -4,6 +4,12 @@ */ "use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("../ast-utils"); + //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ @@ -15,7 +21,7 @@ * @returns {boolean} True if str contains a line terminator. */ function containsLineTerminator(str) { - return /[\n\r\u2028\u2029]/.test(str); + return astUtils.LINEBREAK_MATCHER.test(str); } /** @@ -364,14 +370,9 @@ module.exports = { * @returns {ASTNode} The last token before a colon punctuator. */ function getLastTokenBeforeColon(node) { - let prevNode; + const colonToken = sourceCode.getTokenAfter(node, astUtils.isColonToken); - while (node && (node.type !== "Punctuator" || node.value !== ":")) { - prevNode = node; - node = sourceCode.getTokenAfter(node); - } - - return prevNode; + return sourceCode.getTokenBefore(colonToken); } /** @@ -381,12 +382,7 @@ module.exports = { * @returns {ASTNode} The colon punctuator. */ function getNextColon(node) { - - while (node && (node.type !== "Punctuator" || node.value !== ":")) { - node = sourceCode.getTokenAfter(node); - } - - return node; + return sourceCode.getTokenAfter(node, astUtils.isColonToken); } /** @@ -417,8 +413,8 @@ module.exports = { function report(property, side, whitespace, expected, mode) { const diff = whitespace.length - expected, nextColon = getNextColon(property.key), - tokenBeforeColon = sourceCode.getTokenOrCommentBefore(nextColon), - tokenAfterColon = sourceCode.getTokenOrCommentAfter(nextColon), + tokenBeforeColon = sourceCode.getTokenBefore(nextColon, { includeComments: true }), + tokenAfterColon = sourceCode.getTokenAfter(nextColon, { includeComments: true }), isKeySide = side === "key", locStart = isKeySide ? tokenBeforeColon.loc.start : tokenAfterColon.loc.start, isExtra = diff > 0, @@ -628,15 +624,16 @@ module.exports = { } }; - } else { // Obey beforeColon and afterColon in each property as configured + } + + // Obey beforeColon and afterColon in each property as configured + return { + Property(node) { + verifySpacing(node, isSingleLine(node.parent) ? singleLineOptions : multiLineOptions); + } + }; - return { - Property(node) { - verifySpacing(node, isSingleLine(node.parent) ? singleLineOptions : multiLineOptions); - } - }; - } } }; diff --git a/tools/eslint/lib/rules/keyword-spacing.js b/tools/eslint/lib/rules/keyword-spacing.js index 1dfc291f6e827b..218cfd02be68b9 100644 --- a/tools/eslint/lib/rules/keyword-spacing.js +++ b/tools/eslint/lib/rules/keyword-spacing.js @@ -342,11 +342,7 @@ module.exports = { */ function checkSpacingAroundTokenBefore(node) { if (node) { - let token = sourceCode.getTokenBefore(node); - - while (token.type !== "Keyword") { - token = sourceCode.getTokenBefore(token); - } + const token = sourceCode.getTokenBefore(node, astUtils.isKeywordToken); checkSpacingAround(token); } @@ -363,7 +359,8 @@ module.exports = { const firstToken = node && sourceCode.getFirstToken(node); if (firstToken && - (firstToken.type === "Keyword" || firstToken.value === "async") + ((firstToken.type === "Keyword" && firstToken.value === "function") || + firstToken.value === "async") ) { checkSpacingBefore(firstToken); } @@ -439,14 +436,7 @@ module.exports = { */ function checkSpacingForForOfStatement(node) { checkSpacingAroundFirstToken(node); - - // `of` is not a keyword token. - let token = sourceCode.getTokenBefore(node.right); - - while (token.value !== "of") { - token = sourceCode.getTokenBefore(token); - } - checkSpacingAround(token); + checkSpacingAround(sourceCode.getTokenBefore(node.right, astUtils.isNotOpeningParenToken)); } /** @@ -506,11 +496,25 @@ module.exports = { node.value.async ) ) { - const token = sourceCode.getFirstToken( - node, - node.static ? 1 : 0 + const token = sourceCode.getTokenBefore( + node.key, + tok => { + switch (tok.value) { + case "get": + case "set": + case "async": + return true; + default: + return false; + } + } ); + if (!token) { + throw new Error("Failed to find token get, set, or async beside method name"); + } + + checkSpacingAround(token); } } diff --git a/tools/eslint/lib/rules/line-comment-position.js b/tools/eslint/lib/rules/line-comment-position.js index fa2384e88a8583..dd8f2b9ad6aa91 100644 --- a/tools/eslint/lib/rules/line-comment-position.js +++ b/tools/eslint/lib/rules/line-comment-position.js @@ -4,6 +4,8 @@ */ "use strict"; +const astUtils = require("../ast-utils"); + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -33,6 +35,9 @@ module.exports = { }, applyDefaultPatterns: { type: "boolean" + }, + applyDefaultIgnorePatterns: { + type: "boolean" } }, additionalProperties: false @@ -43,12 +48,11 @@ module.exports = { }, create(context) { - const DEFAULT_IGNORE_PATTERN = "^\\s*(?:eslint|jshint\\s+|jslint\\s+|istanbul\\s+|globals?\\s+|exported\\s+|jscs|falls?\\s?through)"; const options = context.options[0]; let above, ignorePattern, - applyDefaultPatterns = true; + applyDefaultIgnorePatterns = true; if (!options || typeof options === "string") { above = !options || options === "above"; @@ -56,10 +60,16 @@ module.exports = { } else { above = options.position === "above"; ignorePattern = options.ignorePattern; - applyDefaultPatterns = options.applyDefaultPatterns !== false; + + if (options.hasOwnProperty("applyDefaultIgnorePatterns")) { + applyDefaultIgnorePatterns = options.applyDefaultIgnorePatterns !== false; + } else { + applyDefaultIgnorePatterns = options.applyDefaultPatterns !== false; + } } - const defaultIgnoreRegExp = new RegExp(DEFAULT_IGNORE_PATTERN); + const defaultIgnoreRegExp = astUtils.COMMENTS_IGNORE_PATTERN; + const fallThroughRegExp = /^\s*falls?\s?through/; const customIgnoreRegExp = new RegExp(ignorePattern); const sourceCode = context.getSourceCode(); @@ -69,7 +79,7 @@ module.exports = { return { LineComment(node) { - if (applyDefaultPatterns && defaultIgnoreRegExp.test(node.value)) { + if (applyDefaultIgnorePatterns && (defaultIgnoreRegExp.test(node.value) || fallThroughRegExp.test(node.value))) { return; } @@ -77,7 +87,7 @@ module.exports = { return; } - const previous = sourceCode.getTokenOrCommentBefore(node); + const previous = sourceCode.getTokenBefore(node, { includeComments: true }); const isOnSameLine = previous && previous.loc.end.line === node.loc.start.line; if (above) { diff --git a/tools/eslint/lib/rules/linebreak-style.js b/tools/eslint/lib/rules/linebreak-style.js index 6f1a451cdb47bb..907bc02ec4c6b1 100644 --- a/tools/eslint/lib/rules/linebreak-style.js +++ b/tools/eslint/lib/rules/linebreak-style.js @@ -5,6 +5,12 @@ "use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("../ast-utils"); + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -60,7 +66,7 @@ module.exports = { expectedLF = linebreakStyle === "unix", expectedLFChars = expectedLF ? "\n" : "\r\n", source = sourceCode.getText(), - pattern = /\r\n|\r|\n|\u2028|\u2029/g; + pattern = astUtils.createGlobalLinebreakMatcher(); let match; let i = 0; diff --git a/tools/eslint/lib/rules/lines-around-comment.js b/tools/eslint/lib/rules/lines-around-comment.js index 83751cd6a50ad6..e37dd8611ddc8b 100644 --- a/tools/eslint/lib/rules/lines-around-comment.js +++ b/tools/eslint/lib/rules/lines-around-comment.js @@ -93,6 +93,12 @@ module.exports = { }, allowArrayEnd: { type: "boolean" + }, + ignorePattern: { + type: "string" + }, + applyDefaultIgnorePatterns: { + type: "boolean" } }, additionalProperties: false @@ -103,6 +109,11 @@ module.exports = { create(context) { const options = context.options[0] ? Object.assign({}, context.options[0]) : {}; + const ignorePattern = options.ignorePattern; + const defaultIgnoreRegExp = astUtils.COMMENTS_IGNORE_PATTERN; + const customIgnoreRegExp = new RegExp(ignorePattern); + const applyDefaultIgnorePatterns = options.applyDefaultIgnorePatterns !== false; + options.beforeLineComment = options.beforeLineComment || false; options.afterLineComment = options.afterLineComment || false; @@ -139,7 +150,7 @@ module.exports = { token = node; do { - token = sourceCode.getTokenOrCommentBefore(token); + token = sourceCode.getTokenBefore(token, { includeComments: true }); } while (isCommentNodeType(token)); if (token && astUtils.isTokenOnSameLine(token, node)) { @@ -148,7 +159,7 @@ module.exports = { token = node; do { - token = sourceCode.getTokenOrCommentAfter(token); + token = sourceCode.getTokenAfter(token, { includeComments: true }); } while (isCommentNodeType(token)); if (token && astUtils.isTokenOnSameLine(node, token)) { @@ -270,6 +281,14 @@ module.exports = { * @returns {void} */ function checkForEmptyLine(node, opts) { + if (applyDefaultIgnorePatterns && defaultIgnoreRegExp.test(node.value)) { + return; + } + + if (ignorePattern && customIgnoreRegExp.test(node.value)) { + return; + } + let after = opts.after, before = opts.before; @@ -300,8 +319,8 @@ module.exports = { return; } - const previousTokenOrComment = sourceCode.getTokenOrCommentBefore(node); - const nextTokenOrComment = sourceCode.getTokenOrCommentAfter(node); + const previousTokenOrComment = sourceCode.getTokenBefore(node, { includeComments: true }); + const nextTokenOrComment = sourceCode.getTokenAfter(node, { includeComments: true }); // check for newline before if (!exceptionStartAllowed && before && !lodash.includes(commentAndEmptyLines, prevLineNum) && diff --git a/tools/eslint/lib/rules/lines-around-directive.js b/tools/eslint/lib/rules/lines-around-directive.js index b1e54e940b8f64..89dd9c6aeedf40 100644 --- a/tools/eslint/lib/rules/lines-around-directive.js +++ b/tools/eslint/lib/rules/lines-around-directive.js @@ -31,7 +31,7 @@ module.exports = { }, after: { enum: ["always", "never"] - }, + } }, additionalProperties: false, minProperties: 2 @@ -57,7 +57,7 @@ module.exports = { * @returns {boolean} Whether or not the passed in node is preceded by a blank newline. */ function hasNewlineBefore(node) { - const tokenBefore = sourceCode.getTokenOrCommentBefore(node); + const tokenBefore = sourceCode.getTokenBefore(node, { includeComments: true }); const tokenLineBefore = tokenBefore ? tokenBefore.loc.end.line : 0; return node.loc.start.line - tokenLineBefore >= 2; @@ -74,7 +74,7 @@ module.exports = { const lastToken = sourceCode.getLastToken(node); const secondToLastToken = sourceCode.getTokenBefore(lastToken); - return lastToken.type === "Punctuator" && lastToken.value === ";" && lastToken.loc.start.line > secondToLastToken.loc.end.line + return astUtils.isSemicolonToken(lastToken) && lastToken.loc.start.line > secondToLastToken.loc.end.line ? secondToLastToken : lastToken; } @@ -86,7 +86,7 @@ module.exports = { */ function hasNewlineAfter(node) { const lastToken = getLastTokenOnLine(node); - const tokenAfter = sourceCode.getTokenOrCommentAfter(lastToken); + const tokenAfter = sourceCode.getTokenAfter(lastToken, { includeComments: true }); return tokenAfter.loc.start.line - lastToken.loc.end.line >= 2; } @@ -131,7 +131,7 @@ module.exports = { } const firstDirective = directives[0]; - const hasTokenOrCommentBefore = !!sourceCode.getTokenOrCommentBefore(firstDirective); + const hasTokenOrCommentBefore = !!sourceCode.getTokenBefore(firstDirective, { includeComments: true }); // 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 diff --git a/tools/eslint/lib/rules/max-lines.js b/tools/eslint/lib/rules/max-lines.js index 08cf9f6084b2a1..297c75dc138ad6 100644 --- a/tools/eslint/lib/rules/max-lines.js +++ b/tools/eslint/lib/rules/max-lines.js @@ -90,7 +90,7 @@ module.exports = { token = comment; do { - token = sourceCode.getTokenOrCommentBefore(token); + token = sourceCode.getTokenBefore(token, { includeComments: true }); } while (isCommentNodeType(token)); if (token && astUtils.isTokenOnSameLine(token, comment)) { @@ -99,7 +99,7 @@ module.exports = { token = comment; do { - token = sourceCode.getTokenOrCommentAfter(token); + token = sourceCode.getTokenAfter(token, { includeComments: true }); } while (isCommentNodeType(token)); if (token && astUtils.isTokenOnSameLine(comment, token)) { @@ -134,7 +134,7 @@ module.exports = { message: "File must be at most {{max}} lines long. It's {{actual}} lines long.", data: { max, - actual: lines.length, + actual: lines.length } }); } diff --git a/tools/eslint/lib/rules/max-params.js b/tools/eslint/lib/rules/max-params.js index bbf087092e5057..85838adaccb846 100644 --- a/tools/eslint/lib/rules/max-params.js +++ b/tools/eslint/lib/rules/max-params.js @@ -5,6 +5,14 @@ "use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const lodash = require("lodash"); + +const astUtils = require("../ast-utils"); + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -66,10 +74,15 @@ module.exports = { */ function checkFunction(node) { if (node.params.length > numParams) { - context.report({ node, message: "This function has too many parameters ({{count}}). Maximum allowed is {{max}}.", data: { - count: node.params.length, - max: numParams - } }); + context.report({ + node, + message: "{{name}} has too many parameters ({{count}}). Maximum allowed is {{max}}.", + data: { + name: lodash.upperFirst(astUtils.getFunctionNameWithKind(node)), + count: node.params.length, + max: numParams + } + }); } } diff --git a/tools/eslint/lib/rules/max-statements-per-line.js b/tools/eslint/lib/rules/max-statements-per-line.js index 888ec37eda0fb9..3bf370efd8805c 100644 --- a/tools/eslint/lib/rules/max-statements-per-line.js +++ b/tools/eslint/lib/rules/max-statements-per-line.js @@ -4,6 +4,12 @@ */ "use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("../ast-utils"); + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -60,7 +66,7 @@ module.exports = { data: { numberOfStatementsOnThisLine, maxStatementsPerLine, - statements: numberOfStatementsOnThisLine === 1 ? "statement" : "statements", + statements: numberOfStatementsOnThisLine === 1 ? "statement" : "statements" } }); } @@ -74,12 +80,7 @@ module.exports = { * @returns {Token} The actual last token. */ function getActualLastToken(node) { - let lastToken = sourceCode.getLastToken(node); - - if (lastToken.value === ";") { - lastToken = sourceCode.getTokenBefore(lastToken); - } - return lastToken; + return sourceCode.getLastToken(node, astUtils.isNotSemicolonToken); } /** diff --git a/tools/eslint/lib/rules/max-statements.js b/tools/eslint/lib/rules/max-statements.js index 63d51fa571b7b0..f98aa3a21d9f66 100644 --- a/tools/eslint/lib/rules/max-statements.js +++ b/tools/eslint/lib/rules/max-statements.js @@ -5,6 +5,14 @@ "use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const lodash = require("lodash"); + +const astUtils = require("../ast-utils"); + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -84,19 +92,12 @@ module.exports = { */ function reportIfTooManyStatements(node, count, max) { if (count > max) { - const messageEnd = " has too many statements ({{count}}). Maximum allowed is {{max}}."; - let name = "This function"; - - if (node.id) { - name = `Function '${node.id.name}'`; - } else if (node.parent.type === "MethodDefinition" || node.parent.type === "Property") { - name = `Function '${context.getSource(node.parent.key)}'`; - } + const name = lodash.upperFirst(astUtils.getFunctionNameWithKind(node)); context.report({ node, - message: name + messageEnd, - data: { count, max } + message: "{{name}} has too many statements ({{count}}). Maximum allowed is {{max}}.", + data: { name, count, max } }); } } diff --git a/tools/eslint/lib/rules/new-cap.js b/tools/eslint/lib/rules/new-cap.js index e7f7f1ab893396..2f02c0924bb2dc 100644 --- a/tools/eslint/lib/rules/new-cap.js +++ b/tools/eslint/lib/rules/new-cap.js @@ -180,9 +180,9 @@ module.exports = { return "non-alpha"; } else if (firstChar === firstCharLower) { return "lower"; - } else { - return "upper"; } + return "upper"; + } /** diff --git a/tools/eslint/lib/rules/new-parens.js b/tools/eslint/lib/rules/new-parens.js index b0fc5ba97950b7..ad37979d54ed91 100644 --- a/tools/eslint/lib/rules/new-parens.js +++ b/tools/eslint/lib/rules/new-parens.js @@ -6,28 +6,14 @@ "use strict"; //------------------------------------------------------------------------------ -// Helpers +// Requirements //------------------------------------------------------------------------------ -/** - * Checks whether the given token is an opening parenthesis or not. - * - * @param {Token} token - The token to check. - * @returns {boolean} `true` if the token is an opening parenthesis. - */ -function isOpeningParen(token) { - return token.type === "Punctuator" && token.value === "("; -} +const astUtils = require("../ast-utils"); -/** - * Checks whether the given token is an closing parenthesis or not. - * - * @param {Token} token - The token to check. - * @returns {boolean} `true` if the token is an closing parenthesis. - */ -function isClosingParen(token) { - return token.type === "Punctuator" && token.value === ")"; -} +//------------------------------------------------------------------------------ +// Helpers +//------------------------------------------------------------------------------ //------------------------------------------------------------------------------ // Rule Definition @@ -56,8 +42,8 @@ module.exports = { } const lastToken = sourceCode.getLastToken(node); - const hasLastParen = lastToken && isClosingParen(lastToken); - const hasParens = hasLastParen && isOpeningParen(sourceCode.getTokenBefore(lastToken)); + const hasLastParen = lastToken && astUtils.isClosingParenToken(lastToken); + const hasParens = hasLastParen && astUtils.isOpeningParenToken(sourceCode.getTokenBefore(lastToken)); if (!hasParens) { context.report({ diff --git a/tools/eslint/lib/rules/newline-after-var.js b/tools/eslint/lib/rules/newline-after-var.js index 51130e23db9ffe..7b8d473d1dda17 100644 --- a/tools/eslint/lib/rules/newline-after-var.js +++ b/tools/eslint/lib/rules/newline-after-var.js @@ -5,6 +5,12 @@ "use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("../ast-utils"); + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -201,8 +207,7 @@ module.exports = { message: NEVER_MESSAGE, data: { identifier: node.name }, fix(fixer) { - const NEWLINE_REGEX = /\r\n|\r|\n|\u2028|\u2029/; - const linesBetween = sourceCode.getText().slice(lastToken.range[1], nextToken.range[0]).split(NEWLINE_REGEX); + const linesBetween = sourceCode.getText().slice(lastToken.range[1], nextToken.range[0]).split(astUtils.LINEBREAK_MATCHER); return fixer.replaceTextRange([lastToken.range[1], nextToken.range[0]], `${linesBetween.slice(0, -1).join("")}\n${linesBetween[linesBetween.length - 1]}`); } diff --git a/tools/eslint/lib/rules/newline-before-return.js b/tools/eslint/lib/rules/newline-before-return.js index e8cd74b2c7b728..996039b6929b5e 100644 --- a/tools/eslint/lib/rules/newline-before-return.js +++ b/tools/eslint/lib/rules/newline-before-return.js @@ -60,9 +60,9 @@ module.exports = { return isPrecededByTokens(node, ["do"]); } else if (parentType === "SwitchCase") { return isPrecededByTokens(node, [":"]); - } else { - return isPrecededByTokens(node, [")"]); } + return isPrecededByTokens(node, [")"]); + } /** diff --git a/tools/eslint/lib/rules/newline-per-chained-call.js b/tools/eslint/lib/rules/newline-per-chained-call.js index a60c750923cbaa..613429d13f0d19 100644 --- a/tools/eslint/lib/rules/newline-per-chained-call.js +++ b/tools/eslint/lib/rules/newline-per-chained-call.js @@ -6,6 +6,8 @@ "use strict"; +const astUtils = require("../ast-utils"); + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -47,7 +49,7 @@ module.exports = { */ function getPropertyText(node) { const prefix = node.computed ? "[" : "."; - const lines = sourceCode.getText(node.property).split(/\r\n|\r|\n/g); + const lines = sourceCode.getText(node.property).split(astUtils.LINEBREAK_MATCHER); const suffix = node.computed && lines.length === 1 ? "]" : ""; return prefix + lines[0] + suffix; diff --git a/tools/eslint/lib/rules/no-await-in-loop.js b/tools/eslint/lib/rules/no-await-in-loop.js index a75f7f2934bc23..97fff7f18e0f1c 100644 --- a/tools/eslint/lib/rules/no-await-in-loop.js +++ b/tools/eslint/lib/rules/no-await-in-loop.js @@ -10,7 +10,7 @@ const loopTypes = new Set([ "ForOfStatement", "ForInStatement", "WhileStatement", - "DoWhileStatement", + "DoWhileStatement" ]); // Node types at which we should stop looking for loops. For example, it is fine to declare an async @@ -18,7 +18,7 @@ const loopTypes = new Set([ const boundaryTypes = new Set([ "FunctionDeclaration", "FunctionExpression", - "ArrowFunctionExpression", + "ArrowFunctionExpression" ]); module.exports = { @@ -26,9 +26,9 @@ module.exports = { docs: { description: "disallow `await` inside of loops", category: "Possible Errors", - recommended: false, + recommended: false }, - schema: [], + schema: [] }, create(context) { return { @@ -69,7 +69,7 @@ module.exports = { } } } - }, + } }; } }; diff --git a/tools/eslint/lib/rules/no-compare-neg-zero.js b/tools/eslint/lib/rules/no-compare-neg-zero.js new file mode 100644 index 00000000000000..d93ade5d307134 --- /dev/null +++ b/tools/eslint/lib/rules/no-compare-neg-zero.js @@ -0,0 +1,53 @@ +/** + * @fileoverview The rule should warn against code that tries to compare against -0. + * @author Aladdin-ADD + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = { + meta: { + docs: { + description: "disallow comparing against -0", + category: "Possible Errors", + recommended: false + }, + fixable: null, + schema: [] + }, + + create(context) { + + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- + + /** + * Checks a given node is -0 + * + * @param {ASTNode} node - A node to check. + * @returns {boolean} `true` if the node is -0. + */ + function isNegZero(node) { + return node.type === "UnaryExpression" && node.operator === "-" && node.argument.type === "Literal" && node.argument.value === 0; + } + const OPERATORS_TO_CHECK = new Set([">", ">=", "<", "<=", "==", "===", "!=", "!=="]); + + return { + BinaryExpression(node) { + if (OPERATORS_TO_CHECK.has(node.operator)) { + if (isNegZero(node.left) || isNegZero(node.right)) { + context.report({ + node, + message: "Do not use the '{{operator}}' operator to compare against -0.", + data: { operator: node.operator } + }); + } + } + } + }; + } +}; diff --git a/tools/eslint/lib/rules/no-cond-assign.js b/tools/eslint/lib/rules/no-cond-assign.js index 3e94d12a539942..61e5751e4ed07e 100644 --- a/tools/eslint/lib/rules/no-cond-assign.js +++ b/tools/eslint/lib/rules/no-cond-assign.js @@ -66,19 +66,6 @@ module.exports = { return null; } - /** - * Check whether the code represented by an AST node is enclosed in parentheses. - * @param {!Object} node The node to test. - * @returns {boolean} `true` if the code is enclosed in parentheses; otherwise, `false`. - */ - function isParenthesised(node) { - const previousToken = sourceCode.getTokenBefore(node), - nextToken = sourceCode.getTokenAfter(node); - - return previousToken.value === "(" && previousToken.range[1] <= node.range[0] && - nextToken.value === ")" && nextToken.range[0] >= node.range[1]; - } - /** * Check whether the code represented by an AST node is enclosed in two sets of parentheses. * @param {!Object} node The node to test. @@ -88,9 +75,9 @@ module.exports = { const previousToken = sourceCode.getTokenBefore(node, 1), nextToken = sourceCode.getTokenAfter(node, 1); - return isParenthesised(node) && - previousToken.value === "(" && previousToken.range[1] <= node.range[0] && - nextToken.value === ")" && nextToken.range[0] >= node.range[1]; + return astUtils.isParenthesised(sourceCode, node) && + astUtils.isOpeningParenToken(previousToken) && previousToken.range[1] <= node.range[0] && + astUtils.isClosingParenToken(nextToken) && nextToken.range[0] >= node.range[1]; } /** @@ -101,9 +88,9 @@ module.exports = { function testForAssign(node) { if (node.test && (node.test.type === "AssignmentExpression") && - (node.type === "ForStatement" ? - !isParenthesised(node.test) : - !isParenthesisedTwice(node.test) + (node.type === "ForStatement" + ? !astUtils.isParenthesised(sourceCode, node.test) + : !isParenthesisedTwice(node.test) ) ) { diff --git a/tools/eslint/lib/rules/no-dupe-keys.js b/tools/eslint/lib/rules/no-dupe-keys.js index f056b1fcbeb43e..0120d0b38cfffc 100644 --- a/tools/eslint/lib/rules/no-dupe-keys.js +++ b/tools/eslint/lib/rules/no-dupe-keys.js @@ -123,7 +123,7 @@ module.exports = { node: info.node, loc: node.key.loc, message: "Duplicate key '{{name}}'.", - data: { name }, + data: { name } }); } diff --git a/tools/eslint/lib/rules/no-else-return.js b/tools/eslint/lib/rules/no-else-return.js index 43564346b043e2..68ab4c7608f135 100644 --- a/tools/eslint/lib/rules/no-else-return.js +++ b/tools/eslint/lib/rules/no-else-return.js @@ -5,6 +5,13 @@ "use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("../ast-utils"); +const FixTracker = require("../util/fix-tracker"); + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -17,7 +24,9 @@ module.exports = { recommended: false }, - schema: [] + schema: [], + + fixable: "code" }, create(context) { @@ -33,7 +42,66 @@ module.exports = { * @returns {void} */ function displayReport(node) { - context.report({ node, message: "Unnecessary 'else' after 'return'." }); + context.report({ + node, + message: "Unnecessary 'else' after 'return'.", + fix: fixer => { + const sourceCode = context.getSourceCode(); + const startToken = sourceCode.getFirstToken(node); + const elseToken = sourceCode.getTokenBefore(startToken); + const source = sourceCode.getText(node); + const lastIfToken = sourceCode.getTokenBefore(elseToken); + let fixedSource, firstTokenOfElseBlock; + + if (startToken.type === "Punctuator" && startToken.value === "{") { + firstTokenOfElseBlock = sourceCode.getTokenAfter(startToken); + } else { + firstTokenOfElseBlock = startToken; + } + + // If the if block does not have curly braces and does not end in a semicolon + // and the else block starts with (, [, /, +, ` or -, then it is not + // safe to remove the else keyword, because ASI will not add a semicolon + // after the if block + const ifBlockMaybeUnsafe = node.parent.consequent.type !== "BlockStatement" && lastIfToken.value !== ";"; + const elseBlockUnsafe = /^[([/+`-]/.test(firstTokenOfElseBlock.value); + + if (ifBlockMaybeUnsafe && elseBlockUnsafe) { + return null; + } + + const endToken = sourceCode.getLastToken(node); + const lastTokenOfElseBlock = sourceCode.getTokenBefore(endToken); + + if (lastTokenOfElseBlock.value !== ";") { + const nextToken = sourceCode.getTokenAfter(endToken); + + const nextTokenUnsafe = nextToken && /^[([/+`-]/.test(nextToken.value); + const nextTokenOnSameLine = nextToken && nextToken.loc.start.line === lastTokenOfElseBlock.loc.start.line; + + // If the else block contents does not end in a semicolon, + // and the else block starts with (, [, /, +, ` or -, then it is not + // safe to remove the else block, because ASI will not add a semicolon + // after the remaining else block contents + if (nextTokenUnsafe || (nextTokenOnSameLine && nextToken.value !== "}")) { + return null; + } + } + + if (startToken.type === "Punctuator" && startToken.value === "{") { + fixedSource = source.slice(1, -1); + } else { + fixedSource = source; + } + + // Extend the replacement range to include the entire + // function to avoid conflicting with no-useless-return. + // https://github.com/eslint/eslint/issues/8026 + return new FixTracker(fixer, sourceCode) + .retainEnclosingFunction(node) + .replaceTextRange([elseToken.start, node.end], fixedSource); + } + }); } /** @@ -121,35 +189,45 @@ module.exports = { return checkForReturnOrIf(node); } - //-------------------------------------------------------------------------- - // Public API - //-------------------------------------------------------------------------- - - return { + /** + * Check the if statement + * @returns {void} + * @param {Node} node The node for the if statement to check + * @private + */ + function IfStatement(node) { + const parent = context.getAncestors().pop(); + let consequents, + alternate; - IfStatement(node) { - const parent = context.getAncestors().pop(); - let consequents, - alternate; + /* + * Fixing this would require splitting one statement into two, so no error should + * be reported if this node is in a position where only one statement is allowed. + */ + if (!astUtils.STATEMENT_LIST_PARENTS.has(parent.type)) { + return; + } - // Only "top-level" if statements are checked, meaning the first `if` - // in a `if-else-if-...` chain. - if (parent.type === "IfStatement" && parent.alternate === node) { + for (consequents = []; node.type === "IfStatement"; node = node.alternate) { + if (!node.alternate) { return; } + consequents.push(node.consequent); + alternate = node.alternate; + } - for (consequents = []; node.type === "IfStatement"; node = node.alternate) { - if (!node.alternate) { - return; - } - consequents.push(node.consequent); - alternate = node.alternate; - } - - if (consequents.every(alwaysReturns)) { - displayReport(alternate); - } + if (consequents.every(alwaysReturns)) { + displayReport(alternate); } + } + + //-------------------------------------------------------------------------- + // Public API + //-------------------------------------------------------------------------- + + return { + + "IfStatement:exit": IfStatement }; diff --git a/tools/eslint/lib/rules/no-empty-function.js b/tools/eslint/lib/rules/no-empty-function.js index 65f9c9e1515342..115d8698eead71 100644 --- a/tools/eslint/lib/rules/no-empty-function.js +++ b/tools/eslint/lib/rules/no-empty-function.js @@ -5,6 +5,12 @@ "use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("../ast-utils"); + //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ @@ -19,18 +25,6 @@ const ALLOW_OPTIONS = Object.freeze([ "setters", "constructors" ]); -const SHOW_KIND = Object.freeze({ - functions: "function", - arrowFunctions: "arrow function", - generatorFunctions: "generator function", - asyncFunctions: "async function", - methods: "method", - generatorMethods: "generator method", - asyncMethods: "async method", - getters: "getter", - setters: "setter", - constructors: "constructor" -}); /** * Gets the kind of a given function node. @@ -137,6 +131,7 @@ module.exports = { */ function reportIfEmpty(node) { const kind = getKind(node); + const name = astUtils.getFunctionNameWithKind(node); if (allowed.indexOf(kind) === -1 && node.body.type === "BlockStatement" && @@ -146,10 +141,8 @@ module.exports = { context.report({ node, loc: node.body.loc.start, - message: "Unexpected empty {{kind}}.", - data: { - kind: SHOW_KIND[kind] - } + message: "Unexpected empty {{name}}.", + data: { name } }); } } diff --git a/tools/eslint/lib/rules/no-extend-native.js b/tools/eslint/lib/rules/no-extend-native.js index c44a2e894699e9..547770d8f7e4af 100644 --- a/tools/eslint/lib/rules/no-extend-native.js +++ b/tools/eslint/lib/rules/no-extend-native.js @@ -60,9 +60,9 @@ module.exports = { return; } - const affectsProto = lhs.object.computed ? - lhs.object.property.type === "Literal" && lhs.object.property.value === "prototype" : - lhs.object.property.name === "prototype"; + const affectsProto = lhs.object.computed + ? lhs.object.property.type === "Literal" && lhs.object.property.value === "prototype" + : lhs.object.property.name === "prototype"; if (!affectsProto) { return; diff --git a/tools/eslint/lib/rules/no-extra-bind.js b/tools/eslint/lib/rules/no-extra-bind.js index c2795998c66e48..2d22eff2459b5d 100644 --- a/tools/eslint/lib/rules/no-extra-bind.js +++ b/tools/eslint/lib/rules/no-extra-bind.js @@ -8,7 +8,7 @@ // Requirements //------------------------------------------------------------------------------ -const getPropertyName = require("../ast-utils").getStaticPropertyName; +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -44,8 +44,7 @@ module.exports = { loc: node.parent.property.loc.start, fix(fixer) { const firstTokenToRemove = context.getSourceCode() - .getTokensBetween(node.parent.object, node.parent.property) - .find(token => token.value !== ")"); + .getFirstTokenBetween(node.parent.object, node.parent.property, astUtils.isNotClosingParenToken); return fixer.removeRange([firstTokenToRemove.range[0], node.parent.parent.range[1]]); } @@ -73,7 +72,7 @@ module.exports = { grandparent.arguments.length === 1 && parent.type === "MemberExpression" && parent.object === node && - getPropertyName(parent) === "bind" + astUtils.getStaticPropertyName(parent) === "bind" ); } diff --git a/tools/eslint/lib/rules/no-extra-boolean-cast.js b/tools/eslint/lib/rules/no-extra-boolean-cast.js index 123a7cacc5256a..47ca7e22feabda 100644 --- a/tools/eslint/lib/rules/no-extra-boolean-cast.js +++ b/tools/eslint/lib/rules/no-extra-boolean-cast.js @@ -5,6 +5,12 @@ "use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("../ast-utils"); + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -91,7 +97,22 @@ module.exports = { context.report({ node, message: "Redundant Boolean call.", - fix: fixer => fixer.replaceText(node, sourceCode.getText(node.arguments[0])) + fix: fixer => { + if (!node.arguments.length) { + return fixer.replaceText(parent, "true"); + } + + if (node.arguments.length > 1 || node.arguments[0].type === "SpreadElement") { + return null; + } + + const argument = node.arguments[0]; + + if (astUtils.getPrecedence(argument) < astUtils.getPrecedence(node.parent)) { + return fixer.replaceText(node, `(${sourceCode.getText(argument)})`); + } + return fixer.replaceText(node, sourceCode.getText(argument)); + } }); } } diff --git a/tools/eslint/lib/rules/no-extra-label.js b/tools/eslint/lib/rules/no-extra-label.js index 22afbf405b7ea9..b89267de93d7b3 100644 --- a/tools/eslint/lib/rules/no-extra-label.js +++ b/tools/eslint/lib/rules/no-extra-label.js @@ -110,12 +110,7 @@ module.exports = { node: labelNode, message: "This label '{{name}}' is unnecessary.", data: labelNode, - fix(fixer) { - return fixer.replaceTextRange( - [info.label.range[0], labelNode.range[1]], - sourceCode.text.slice(info.label.parent.body.range[0], sourceCode.getFirstToken(node).range[1]) - ); - } + fix: fixer => fixer.removeRange([sourceCode.getFirstToken(node).range[1], labelNode.range[1]]) }); } return; diff --git a/tools/eslint/lib/rules/no-extra-parens.js b/tools/eslint/lib/rules/no-extra-parens.js index 004d431701a574..bbfae735c2d27f 100644 --- a/tools/eslint/lib/rules/no-extra-parens.js +++ b/tools/eslint/lib/rules/no-extra-parens.js @@ -44,7 +44,8 @@ module.exports = { properties: { conditionalAssign: { type: "boolean" }, nestedBinaryExpressions: { type: "boolean" }, - returnAssign: { type: "boolean" } + returnAssign: { type: "boolean" }, + ignoreJSX: { enum: ["none", "all", "single-line", "multi-line"] } }, additionalProperties: false } @@ -59,12 +60,16 @@ module.exports = { create(context) { const sourceCode = context.getSourceCode(); + const tokensToIgnore = new WeakSet(); const isParenthesised = astUtils.isParenthesised.bind(astUtils, sourceCode); const precedence = astUtils.getPrecedence; const ALL_NODES = context.options[0] !== "functions"; const EXCEPT_COND_ASSIGN = ALL_NODES && context.options[1] && context.options[1].conditionalAssign === false; const NESTED_BINARY = ALL_NODES && context.options[1] && context.options[1].nestedBinaryExpressions === false; const EXCEPT_RETURN_ASSIGN = ALL_NODES && context.options[1] && context.options[1].returnAssign === false; + const IGNORE_JSX = ALL_NODES && context.options[1] && context.options[1].ignoreJSX; + const PRECEDENCE_OF_ASSIGNMENT_EXPR = precedence({ type: "AssignmentExpression" }); + const PRECEDENCE_OF_UPDATE_EXPR = precedence({ type: "UpdateExpression" }); /** * Determines if this rule should be enforced for a node given the current configuration. @@ -73,6 +78,31 @@ module.exports = { * @private */ function ruleApplies(node) { + if (node.type === "JSXElement") { + const isSingleLine = node.loc.start.line === node.loc.end.line; + + switch (IGNORE_JSX) { + + // Exclude this JSX element from linting + case "all": + return false; + + // Exclude this JSX element if it is multi-line element + case "multi-line": + return isSingleLine; + + // Exclude this JSX element if it is single-line element + case "single-line": + return !isSingleLine; + + // Nothing special to be done for JSX elements + case "none": + break; + + // no default + } + } + return ALL_NODES || node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression"; } @@ -87,8 +117,8 @@ module.exports = { nextToken = sourceCode.getTokenAfter(node, 1); return isParenthesised(node) && previousToken && nextToken && - previousToken.value === "(" && previousToken.range[1] <= node.range[0] && - nextToken.value === ")" && nextToken.range[0] >= node.range[1]; + astUtils.isOpeningParenToken(previousToken) && previousToken.range[1] <= node.range[0] && + astUtils.isClosingParenToken(nextToken) && nextToken.range[0] >= node.range[1]; } /** @@ -140,6 +170,19 @@ module.exports = { return false; } + /** + * Determines if a constructor function is newed-up with parens + * @param {ASTNode} newExpression - The NewExpression node to be checked. + * @returns {boolean} True if the constructor is called with parens. + * @private + */ + function isNewExpressionWithParens(newExpression) { + const lastToken = sourceCode.getLastToken(newExpression); + const penultimateToken = sourceCode.getTokenBefore(lastToken); + + return newExpression.arguments.length > 0 || astUtils.isOpeningParenToken(penultimateToken) && astUtils.isClosingParenToken(lastToken); + } + /** * Determines if a node is or contains an assignment expression * @param {ASTNode} node - The node to be checked. @@ -175,9 +218,9 @@ module.exports = { return node.argument && containsAssignment(node.argument); } else if (node.type === "ArrowFunctionExpression" && node.body.type !== "BlockStatement") { return containsAssignment(node.body); - } else { - return containsAssignment(node); } + return containsAssignment(node); + } /** @@ -196,69 +239,6 @@ module.exports = { return hasDoubleExcessParens(node); } - /** - * Checks whether or not a given node is located at the head of ExpressionStatement. - * @param {ASTNode} node - A node to check. - * @returns {boolean} `true` if the node is located at the head of ExpressionStatement. - */ - function isHeadOfExpressionStatement(node) { - let parent = node.parent; - - while (parent) { - switch (parent.type) { - case "SequenceExpression": - if (parent.expressions[0] !== node || isParenthesised(node)) { - return false; - } - break; - - case "UnaryExpression": - case "UpdateExpression": - if (parent.prefix || isParenthesised(node)) { - return false; - } - break; - - case "BinaryExpression": - case "LogicalExpression": - if (parent.left !== node || isParenthesised(node)) { - return false; - } - break; - - case "ConditionalExpression": - if (parent.test !== node || isParenthesised(node)) { - return false; - } - break; - - case "CallExpression": - if (parent.callee !== node || isParenthesised(node)) { - return false; - } - break; - - case "MemberExpression": - if (parent.object !== node || isParenthesised(node)) { - return false; - } - break; - - case "ExpressionStatement": - return true; - - default: - return false; - } - - node = parent; - parent = parent.parent; - } - - /* istanbul ignore next */ - throw new Error("unreachable"); - } - /** * Determines whether a node should be preceded by an additional space when removing parens * @param {ASTNode} node node to evaluate; must be surrounded by parentheses @@ -276,7 +256,7 @@ module.exports = { } // If the parens are preceded by a keyword (e.g. `typeof(0)`), a space should be inserted (`typeof 0`) - const precededByKeyword = tokenBeforeLeftParen.type === "Keyword"; + 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[]` @@ -289,7 +269,7 @@ module.exports = { const startsWithUnaryPlus = firstToken.type === "Punctuator" && firstToken.value === "+"; const startsWithUnaryMinus = firstToken.type === "Punctuator" && firstToken.value === "-"; - return (precededByKeyword && startsWithIdentifierPart) || + return (precededByIdentiferPart && startsWithIdentifierPart) || (precededByUnaryPlus && startsWithUnaryPlus) || (precededByUnaryMinus && startsWithUnaryMinus); } @@ -304,6 +284,10 @@ module.exports = { const leftParenToken = sourceCode.getTokenBefore(node); const rightParenToken = sourceCode.getTokenAfter(node); + if (tokensToIgnore.has(sourceCode.getFirstToken(node)) && !isParenthesisedTwice(node)) { + return; + } + context.report({ node, loc: leftParenToken.loc.start, @@ -325,7 +309,11 @@ module.exports = { * @returns {void} * @private */ - function dryUnaryUpdate(node) { + function checkUnaryUpdate(node) { + if (node.type === "UnaryExpression" && node.argument.type === "BinaryExpression" && node.argument.operator === "**") { + return; + } + if (hasExcessParens(node.argument) && precedence(node.argument) >= precedence(node)) { report(node.argument); } @@ -337,10 +325,11 @@ module.exports = { * @returns {void} * @private */ - function dryCallNew(node) { + function checkCallNew(node) { if (hasExcessParens(node.callee) && precedence(node.callee) >= precedence(node) && !( node.type === "CallExpression" && - node.callee.type === "FunctionExpression" && + (node.callee.type === "FunctionExpression" || + node.callee.type === "NewExpression" && !isNewExpressionWithParens(node.callee)) && // One set of parentheses are allowed for a function expression !hasDoubleExcessParens(node.callee) @@ -348,12 +337,12 @@ module.exports = { report(node.callee); } if (node.arguments.length === 1) { - if (hasDoubleExcessParens(node.arguments[0]) && precedence(node.arguments[0]) >= precedence({ type: "AssignmentExpression" })) { + if (hasDoubleExcessParens(node.arguments[0]) && precedence(node.arguments[0]) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) { report(node.arguments[0]); } } else { [].forEach.call(node.arguments, arg => { - if (hasExcessParens(arg) && precedence(arg) >= precedence({ type: "AssignmentExpression" })) { + if (hasExcessParens(arg) && precedence(arg) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) { report(arg); } }); @@ -366,23 +355,91 @@ module.exports = { * @returns {void} * @private */ - function dryBinaryLogical(node) { + function checkBinaryLogical(node) { const prec = precedence(node); - const shouldSkipLeft = NESTED_BINARY && (node.left.type === "BinaryExpression" || node.left.type === "LogicalExpression"); + const leftPrecedence = precedence(node.left); + const rightPrecedence = precedence(node.right); + const isExponentiation = node.operator === "**"; + const shouldSkipLeft = (NESTED_BINARY && (node.left.type === "BinaryExpression" || node.left.type === "LogicalExpression")) || + node.left.type === "UnaryExpression" && isExponentiation; const shouldSkipRight = NESTED_BINARY && (node.right.type === "BinaryExpression" || node.right.type === "LogicalExpression"); - if (!shouldSkipLeft && hasExcessParens(node.left) && precedence(node.left) >= prec) { + if (!shouldSkipLeft && hasExcessParens(node.left) && (leftPrecedence > prec || (leftPrecedence === prec && !isExponentiation))) { report(node.left); } - if (!shouldSkipRight && hasExcessParens(node.right) && precedence(node.right) > prec) { + if (!shouldSkipRight && hasExcessParens(node.right) && (rightPrecedence > prec || (rightPrecedence === prec && isExponentiation))) { report(node.right); } } + /** + * Check the parentheses around the super class of the given class definition. + * @param {ASTNode} node The node of class declarations to check. + * @returns {void} + */ + function checkClass(node) { + if (!node.superClass) { + return; + } + + // If `node.superClass` is a LeftHandSideExpression, parentheses are extra. + // Otherwise, parentheses are needed. + const hasExtraParens = precedence(node.superClass) > PRECEDENCE_OF_UPDATE_EXPR + ? hasExcessParens(node.superClass) + : hasDoubleExcessParens(node.superClass); + + if (hasExtraParens) { + report(node.superClass); + } + } + + /** + * Check the parentheses around the argument of the given spread operator. + * @param {ASTNode} node The node of spread elements/properties to check. + * @returns {void} + */ + function checkSpreadOperator(node) { + const hasExtraParens = precedence(node.argument) >= PRECEDENCE_OF_ASSIGNMENT_EXPR + ? hasExcessParens(node.argument) + : hasDoubleExcessParens(node.argument); + + if (hasExtraParens) { + report(node.argument); + } + } + + /** + * Checks the parentheses for an ExpressionStatement or ExportDefaultDeclaration + * @param {ASTNode} node The ExpressionStatement.expression or ExportDefaultDeclaration.declaration node + * @returns {void} + */ + function checkExpressionOrExportStatement(node) { + const firstToken = isParenthesised(node) ? sourceCode.getTokenBefore(node) : sourceCode.getFirstToken(node); + const secondToken = sourceCode.getTokenAfter(firstToken, astUtils.isNotOpeningParenToken); + + if ( + astUtils.isOpeningParenToken(firstToken) && + ( + astUtils.isOpeningBraceToken(secondToken) || + secondToken.type === "Keyword" && ( + secondToken.value === "function" || + secondToken.value === "class" || + secondToken.value === "let" && astUtils.isOpeningBracketToken(sourceCode.getTokenAfter(secondToken)) + ) + ) + ) { + tokensToIgnore.add(secondToken); + } + + if (hasExcessParens(node)) { + report(node); + } + } + return { ArrayExpression(node) { [].forEach.call(node.elements, e => { - if (e && hasExcessParens(e) && precedence(e) >= precedence({ type: "AssignmentExpression" })) { + if (e && hasExcessParens(e) && precedence(e) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) { report(e); } }); @@ -394,13 +451,13 @@ module.exports = { } if (node.body.type !== "BlockStatement") { - if (sourceCode.getFirstToken(node.body).value !== "{" && hasExcessParens(node.body) && precedence(node.body) >= precedence({ type: "AssignmentExpression" })) { - report(node.body); - return; - } + const firstBodyToken = sourceCode.getFirstToken(node.body, astUtils.isNotOpeningParenToken); + const tokenBeforeFirst = sourceCode.getTokenBefore(firstBodyToken); - // Object literals *must* be parenthesised - if (node.body.type === "ObjectExpression" && hasDoubleExcessParens(node.body)) { + if (astUtils.isOpeningParenToken(tokenBeforeFirst) && astUtils.isOpeningBraceToken(firstBodyToken)) { + tokensToIgnore.add(firstBodyToken); + } + if (hasExcessParens(node.body) && precedence(node.body) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) { report(node.body); } } @@ -416,8 +473,8 @@ module.exports = { } }, - BinaryExpression: dryBinaryLogical, - CallExpression: dryCallNew, + BinaryExpression: checkBinaryLogical, + CallExpression: checkCallNew, ConditionalExpression(node) { if (isReturnAssignException(node)) { @@ -428,11 +485,11 @@ module.exports = { report(node.test); } - if (hasExcessParens(node.consequent) && precedence(node.consequent) >= precedence({ type: "AssignmentExpression" })) { + if (hasExcessParens(node.consequent) && precedence(node.consequent) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) { report(node.consequent); } - if (hasExcessParens(node.alternate) && precedence(node.alternate) >= precedence({ type: "AssignmentExpression" })) { + if (hasExcessParens(node.alternate) && precedence(node.alternate) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) { report(node.alternate); } }, @@ -443,27 +500,8 @@ module.exports = { } }, - ExpressionStatement(node) { - if (hasExcessParens(node.expression)) { - const firstTokens = sourceCode.getFirstTokens(node.expression, 2); - const firstToken = firstTokens[0]; - const secondToken = firstTokens[1]; - - if ( - !firstToken || - firstToken.value !== "{" && - firstToken.value !== "function" && - firstToken.value !== "class" && - ( - firstToken.value !== "let" || - !secondToken || - secondToken.value !== "[" - ) - ) { - report(node.expression); - } - } - }, + ExportDefaultDeclaration: node => checkExpressionOrExportStatement(node.declaration), + ExpressionStatement: node => checkExpressionOrExportStatement(node.expression), ForInStatement(node) { if (hasExcessParens(node.right)) { @@ -497,7 +535,7 @@ module.exports = { } }, - LogicalExpression: dryBinaryLogical, + LogicalExpression: checkBinaryLogical, MemberExpression(node) { if ( @@ -506,19 +544,11 @@ module.exports = { ( node.computed || !( - (node.object.type === "Literal" && - typeof node.object.value === "number" && - astUtils.isDecimalInteger(node.object)) - || + astUtils.isDecimalInteger(node.object) || // RegExp literal is allowed to have parens (#1589) (node.object.type === "Literal" && node.object.regex) ) - ) && - !( - (node.object.type === "FunctionExpression" || node.object.type === "ClassExpression") && - isHeadOfExpressionStatement(node) && - !hasDoubleExcessParens(node.object) ) ) { report(node.object); @@ -528,13 +558,13 @@ module.exports = { } }, - NewExpression: dryCallNew, + NewExpression: checkCallNew, ObjectExpression(node) { [].forEach.call(node.properties, e => { const v = e.value; - if (v && hasExcessParens(v) && precedence(v) >= precedence({ type: "AssignmentExpression" })) { + if (v && hasExcessParens(v) && precedence(v) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) { report(v); } }); @@ -584,13 +614,13 @@ module.exports = { } }, - UnaryExpression: dryUnaryUpdate, - UpdateExpression: dryUnaryUpdate, - AwaitExpression: dryUnaryUpdate, + UnaryExpression: checkUnaryUpdate, + UpdateExpression: checkUnaryUpdate, + AwaitExpression: checkUnaryUpdate, VariableDeclarator(node) { if (node.init && hasExcessParens(node.init) && - precedence(node.init) >= precedence({ type: "AssignmentExpression" }) && + precedence(node.init) >= PRECEDENCE_OF_ASSIGNMENT_EXPR && // RegExp literal is allowed to have parens (#1589) !(node.init.type === "Literal" && node.init.regex)) { @@ -620,7 +650,14 @@ module.exports = { report(node.argument); } } - } + }, + + ClassDeclaration: checkClass, + ClassExpression: checkClass, + + SpreadElement: checkSpreadOperator, + SpreadProperty: checkSpreadOperator, + ExperimentalSpreadProperty: checkSpreadOperator }; } diff --git a/tools/eslint/lib/rules/no-extra-semi.js b/tools/eslint/lib/rules/no-extra-semi.js index f51f16ee6af3f1..0ec914989d4246 100644 --- a/tools/eslint/lib/rules/no-extra-semi.js +++ b/tools/eslint/lib/rules/no-extra-semi.js @@ -5,6 +5,13 @@ "use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const FixTracker = require("../util/fix-tracker"); +const astUtils = require("../ast-utils"); + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -34,7 +41,13 @@ module.exports = { node: nodeOrToken, message: "Unnecessary semicolon.", fix(fixer) { - return fixer.remove(nodeOrToken); + + // Expand the replacement range to include the surrounding + // tokens to avoid conflicting with semi. + // https://github.com/eslint/eslint/issues/7928 + return new FixTracker(fixer, context.getSourceCode()) + .retainSurroundingTokens(nodeOrToken) + .remove(nodeOrToken); } }); } @@ -48,10 +61,10 @@ module.exports = { */ function checkForPartOfClassBody(firstToken) { for (let token = firstToken; - token.type === "Punctuator" && token.value !== "}"; + token.type === "Punctuator" && !astUtils.isClosingBraceToken(token); token = sourceCode.getTokenAfter(token) ) { - if (token.value === ";") { + if (astUtils.isSemicolonToken(token)) { report(token); } } diff --git a/tools/eslint/lib/rules/no-global-assign.js b/tools/eslint/lib/rules/no-global-assign.js index caf2500231e14a..5a1cc64aeb2069 100644 --- a/tools/eslint/lib/rules/no-global-assign.js +++ b/tools/eslint/lib/rules/no-global-assign.js @@ -14,7 +14,7 @@ module.exports = { docs: { description: "disallow assignments to native objects or read-only global variables", category: "Best Practices", - recommended: false + recommended: true }, schema: [ diff --git a/tools/eslint/lib/rules/no-implicit-coercion.js b/tools/eslint/lib/rules/no-implicit-coercion.js index 8e8db9879ba38c..387b3dae479597 100644 --- a/tools/eslint/lib/rules/no-implicit-coercion.js +++ b/tools/eslint/lib/rules/no-implicit-coercion.js @@ -6,6 +6,7 @@ "use strict"; const astUtils = require("../ast-utils"); +const esUtils = require("esutils"); //------------------------------------------------------------------------------ // Helpers @@ -197,19 +198,31 @@ module.exports = { */ function report(node, recommendation, shouldFix) { shouldFix = typeof shouldFix === "undefined" ? true : shouldFix; - const reportObj = { + + context.report({ node, message: "use `{{recommendation}}` instead.", data: { recommendation + }, + fix(fixer) { + if (!shouldFix) { + return null; + } + + const tokenBefore = sourceCode.getTokenBefore(node); + + if ( + tokenBefore && + tokenBefore.range[1] === node.range[0] && + esUtils.code.isIdentifierPartES6(tokenBefore.value.slice(-1).charCodeAt(0)) && + esUtils.code.isIdentifierPartES6(recommendation.charCodeAt(0)) + ) { + return fixer.replaceText(node, ` ${recommendation}`); + } + return fixer.replaceText(node, recommendation); } - }; - - if (shouldFix) { - reportObj.fix = fixer => fixer.replaceText(node, recommendation); - } - - context.report(reportObj); + }); } return { diff --git a/tools/eslint/lib/rules/no-inner-declarations.js b/tools/eslint/lib/rules/no-inner-declarations.js index 01cc67863ffff5..2a378487fd5b6b 100644 --- a/tools/eslint/lib/rules/no-inner-declarations.js +++ b/tools/eslint/lib/rules/no-inner-declarations.js @@ -64,10 +64,10 @@ module.exports = { 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-invalid-regexp.js b/tools/eslint/lib/rules/no-invalid-regexp.js index dcde234c6f6aa2..45596f7ee876a1 100644 --- a/tools/eslint/lib/rules/no-invalid-regexp.js +++ b/tools/eslint/lib/rules/no-invalid-regexp.js @@ -74,7 +74,8 @@ module.exports = { } catch (e) { context.report({ node, - message: `${e.message}.` + message: "{{message}}.", + data: e }); } diff --git a/tools/eslint/lib/rules/no-irregular-whitespace.js b/tools/eslint/lib/rules/no-irregular-whitespace.js index b1949fbc735479..3882501a8629d3 100644 --- a/tools/eslint/lib/rules/no-irregular-whitespace.js +++ b/tools/eslint/lib/rules/no-irregular-whitespace.js @@ -6,6 +6,12 @@ "use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("../ast-utils"); + //------------------------------------------------------------------------------ // Constants //------------------------------------------------------------------------------ @@ -13,7 +19,7 @@ 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 IRREGULAR_LINE_TERMINATORS = /[\u2028\u2029]/mg; -const LINE_BREAK = /\r\n|\r|\n|\u2028|\u2029/g; +const LINE_BREAK = astUtils.createGlobalLinebreakMatcher(); //------------------------------------------------------------------------------ // Rule Definition diff --git a/tools/eslint/lib/rules/no-lone-blocks.js b/tools/eslint/lib/rules/no-lone-blocks.js index 9528421ca5bd39..95a5b334c602a8 100644 --- a/tools/eslint/lib/rules/no-lone-blocks.js +++ b/tools/eslint/lib/rules/no-lone-blocks.js @@ -32,22 +32,22 @@ module.exports = { * @returns {void} */ function report(node) { - const parent = context.getAncestors().pop(); + const message = node.parent.type === "BlockStatement" ? "Nested block is redundant." : "Block is redundant."; - context.report({ node, message: parent.type === "Program" ? - "Block is redundant." : - "Nested block is redundant." - }); + context.report({ node, message }); } /** - * Checks for any ocurrence of BlockStatement > BlockStatement or Program > BlockStatement - * @returns {boolean} True if the current node is a lone block. + * Checks for any ocurrence of a BlockStatement in a place where lists of statements can appear + * @param {ASTNode} node The node to check + * @returns {boolean} True if the node is a lone block. */ - function isLoneBlock() { - const parent = context.getAncestors().pop(); + function isLoneBlock(node) { + return node.parent.type === "BlockStatement" || + node.parent.type === "Program" || - return parent.type === "BlockStatement" || parent.type === "Program"; + // Don't report blocks in switch cases if the block is the only statement of the case. + node.parent.type === "SwitchCase" && !(node.parent.consequent[0] === node && node.parent.consequent.length === 1); } /** diff --git a/tools/eslint/lib/rules/no-mixed-operators.js b/tools/eslint/lib/rules/no-mixed-operators.js index b066d74a0c40e0..9f1fbc9a6d41b6 100644 --- a/tools/eslint/lib/rules/no-mixed-operators.js +++ b/tools/eslint/lib/rules/no-mixed-operators.js @@ -148,13 +148,7 @@ module.exports = { * @returns {Token} The operator token of the node. */ function getOperatorToken(node) { - let token = sourceCode.getTokenAfter(node.left); - - while (token.value === ")") { - token = sourceCode.getTokenAfter(token); - } - - return token; + return sourceCode.getTokenAfter(node.left, astUtils.isNotClosingParenToken); } /** diff --git a/tools/eslint/lib/rules/no-mixed-requires.js b/tools/eslint/lib/rules/no-mixed-requires.js index 4d51d3ab3a07a4..55ad1e73e07628 100644 --- a/tools/eslint/lib/rules/no-mixed-requires.js +++ b/tools/eslint/lib/rules/no-mixed-requires.js @@ -153,11 +153,11 @@ module.exports = { // "var utils = require('./utils');" return REQ_FILE; - } else { - - // "var async = require('async');" - return REQ_MODULE; } + + // "var async = require('async');" + return REQ_MODULE; + } /** diff --git a/tools/eslint/lib/rules/no-multi-assign.js b/tools/eslint/lib/rules/no-multi-assign.js new file mode 100644 index 00000000000000..164869f6ddc1d9 --- /dev/null +++ b/tools/eslint/lib/rules/no-multi-assign.js @@ -0,0 +1,41 @@ +/** + * @fileoverview Rule to check use of chained assignment expressions + * @author Stewart Rand + */ + +"use strict"; + + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = { + meta: { + docs: { + description: "disallow use of chained assignment expressions", + category: "Stylistic Issues", + recommended: false + }, + schema: [] + }, + + create(context) { + + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + return { + AssignmentExpression(node) { + if (["AssignmentExpression", "VariableDeclarator"].indexOf(node.parent.type) !== -1) { + context.report({ + node, + message: "Unexpected chained assignment." + }); + } + } + }; + + } +}; diff --git a/tools/eslint/lib/rules/no-multi-spaces.js b/tools/eslint/lib/rules/no-multi-spaces.js index 64eeebec55a383..41a7f924a5e9de 100644 --- a/tools/eslint/lib/rules/no-multi-spaces.js +++ b/tools/eslint/lib/rules/no-multi-spaces.js @@ -5,6 +5,8 @@ "use strict"; +const astUtils = require("../ast-utils"); + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -93,7 +95,8 @@ module.exports = { const sourceCode = context.getSourceCode(), source = sourceCode.getText(), allComments = sourceCode.getAllComments(), - pattern = /[^\n\r\u2028\u2029\t ].? {2,}/g; // note: repeating space + JOINED_LINEBEAKS = Array.from(astUtils.LINEBREAKS).join(""), + pattern = new RegExp(String.raw`[^ \t${JOINED_LINEBEAKS}].? {2,}`, "g"); // note: repeating space let parent; diff --git a/tools/eslint/lib/rules/no-multi-str.js b/tools/eslint/lib/rules/no-multi-str.js index 6cf5840e30264b..76f29cbb5a9f6b 100644 --- a/tools/eslint/lib/rules/no-multi-str.js +++ b/tools/eslint/lib/rules/no-multi-str.js @@ -5,6 +5,12 @@ "use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("../ast-utils"); + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -39,9 +45,7 @@ module.exports = { return { Literal(node) { - const lineBreak = /\n/; - - if (lineBreak.test(node.raw) && !isJSXElement(node.parent)) { + if (astUtils.LINEBREAK_MATCHER.test(node.raw) && !isJSXElement(node.parent)) { context.report({ node, message: "Multiline support is limited to browsers supporting ES5 only." }); } } diff --git a/tools/eslint/lib/rules/no-multiple-empty-lines.js b/tools/eslint/lib/rules/no-multiple-empty-lines.js index c45c7aa1678927..2063ebd917c79e 100644 --- a/tools/eslint/lib/rules/no-multiple-empty-lines.js +++ b/tools/eslint/lib/rules/no-multiple-empty-lines.js @@ -5,8 +5,6 @@ */ "use strict"; -const astUtils = require("../ast-utils"); - //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -114,8 +112,8 @@ module.exports = { data: { max: maxAllowed, pluralizedLines: maxAllowed === 1 ? "line" : "lines" }, fix(fixer) { return fixer.removeRange([ - astUtils.getRangeIndexFromLocation(sourceCode, { line: lastLineNumber + 1, column: 0 }), - astUtils.getRangeIndexFromLocation(sourceCode, { line: lineNumber - maxAllowed, column: 0 }) + sourceCode.getIndexFromLoc({ line: lastLineNumber + 1, column: 0 }), + sourceCode.getIndexFromLoc({ line: lineNumber - maxAllowed, column: 0 }) ]); } }); diff --git a/tools/eslint/lib/rules/no-native-reassign.js b/tools/eslint/lib/rules/no-native-reassign.js index f721fc278fe3ec..d3dfefbaf05f0b 100644 --- a/tools/eslint/lib/rules/no-native-reassign.js +++ b/tools/eslint/lib/rules/no-native-reassign.js @@ -15,7 +15,7 @@ module.exports = { docs: { description: "disallow assignments to native objects or read-only global variables", category: "Best Practices", - recommended: true, + recommended: false, replacedBy: ["no-global-assign"] }, diff --git a/tools/eslint/lib/rules/no-negated-in-lhs.js b/tools/eslint/lib/rules/no-negated-in-lhs.js index 143518060b33bd..495cbc160ec7d6 100644 --- a/tools/eslint/lib/rules/no-negated-in-lhs.js +++ b/tools/eslint/lib/rules/no-negated-in-lhs.js @@ -15,7 +15,7 @@ module.exports = { docs: { description: "disallow negating the left operand in `in` expressions", category: "Possible Errors", - recommended: true, + recommended: false, replacedBy: ["no-unsafe-negation"] }, deprecated: true, diff --git a/tools/eslint/lib/rules/no-new-func.js b/tools/eslint/lib/rules/no-new-func.js index 17ca7c9f03d6b3..6abbe8391d5d38 100644 --- a/tools/eslint/lib/rules/no-new-func.js +++ b/tools/eslint/lib/rules/no-new-func.js @@ -27,20 +27,18 @@ module.exports = { //-------------------------------------------------------------------------- /** - * Checks if the callee is the Function constructor, and if so, reports an issue. - * @param {ASTNode} node The node to check and report on + * Reports a node. + * @param {ASTNode} node The node to report * @returns {void} * @private */ - function validateCallee(node) { - if (node.callee.name === "Function") { - context.report({ node, message: "The Function constructor is eval." }); - } + function report(node) { + context.report({ node, message: "The Function constructor is eval." }); } return { - NewExpression: validateCallee, - CallExpression: validateCallee + "NewExpression[callee.name = 'Function']": report, + "CallExpression[callee.name = 'Function']": report }; } diff --git a/tools/eslint/lib/rules/no-new.js b/tools/eslint/lib/rules/no-new.js index e0f45de1bd298b..6e6025aac54304 100644 --- a/tools/eslint/lib/rules/no-new.js +++ b/tools/eslint/lib/rules/no-new.js @@ -24,12 +24,8 @@ module.exports = { create(context) { return { - - ExpressionStatement(node) { - - if (node.expression.type === "NewExpression") { - context.report({ node, message: "Do not use 'new' for side effects." }); - } + "ExpressionStatement > NewExpression"(node) { + context.report({ node: node.parent, message: "Do not use 'new' for side effects." }); } }; diff --git a/tools/eslint/lib/rules/no-param-reassign.js b/tools/eslint/lib/rules/no-param-reassign.js index 31f5be3cb25972..560d1d6b6f2fd6 100644 --- a/tools/eslint/lib/rules/no-param-reassign.js +++ b/tools/eslint/lib/rules/no-param-reassign.js @@ -20,17 +20,40 @@ module.exports = { schema: [ { - type: "object", - properties: { - props: { type: "boolean" } - }, - additionalProperties: false + oneOf: [ + { + type: "object", + properties: { + props: { + enum: [false] + } + }, + additionalProperties: false + }, + { + type: "object", + properties: { + props: { + enum: [true] + }, + ignorePropertyModificationsFor: { + type: "array", + items: { + type: "string" + }, + uniqueItems: true + } + }, + additionalProperties: false + } + ] } ] }, create(context) { const props = context.options[0] && Boolean(context.options[0].props); + const ignoredPropertyAssignmentsFor = context.options[0] && context.options[0].ignorePropertyModificationsFor || []; /** * Checks whether or not the reference modifies properties of its variable. @@ -73,8 +96,15 @@ module.exports = { } break; - default: + // EXCLUDES: e.g. ({ [foo]: a }) = bar; + case "Property": + if (parent.key === node) { + return false; + } + break; + + // no default } node = parent; @@ -103,7 +133,7 @@ module.exports = { ) { if (reference.isWrite()) { context.report({ node: identifier, message: "Assignment to function parameter '{{name}}'.", data: { name: identifier.name } }); - } else if (props && isModifyingProp(reference)) { + } else if (props && isModifyingProp(reference) && ignoredPropertyAssignmentsFor.indexOf(identifier.name) === -1) { context.report({ node: identifier, message: "Assignment to property of function parameter '{{name}}'.", data: { name: identifier.name } }); } } diff --git a/tools/eslint/lib/rules/no-process-exit.js b/tools/eslint/lib/rules/no-process-exit.js index c0c2455545afab..04e423b88ffb99 100644 --- a/tools/eslint/lib/rules/no-process-exit.js +++ b/tools/eslint/lib/rules/no-process-exit.js @@ -26,17 +26,9 @@ module.exports = { //-------------------------------------------------------------------------- return { - - CallExpression(node) { - const callee = node.callee; - - if (callee.type === "MemberExpression" && callee.object.name === "process" && - callee.property.name === "exit" - ) { - context.report({ node, message: "Don't use process.exit(); throw an error instead." }); - } + "CallExpression > MemberExpression.callee[object.name = 'process'][property.name = 'exit']"(node) { + context.report({ node: node.parent, message: "Don't use process.exit(); throw an error instead." }); } - }; } diff --git a/tools/eslint/lib/rules/no-redeclare.js b/tools/eslint/lib/rules/no-redeclare.js index deb896289b76f0..bfbc09ffb6f324 100644 --- a/tools/eslint/lib/rules/no-redeclare.js +++ b/tools/eslint/lib/rules/no-redeclare.js @@ -89,13 +89,13 @@ module.exports = { BlockStatement: checkForBlock, SwitchStatement: checkForBlock }; - } else { - return { - Program: checkForGlobal, - FunctionDeclaration: checkForBlock, - FunctionExpression: checkForBlock, - ArrowFunctionExpression: checkForBlock - }; } + return { + Program: checkForGlobal, + FunctionDeclaration: checkForBlock, + FunctionExpression: checkForBlock, + ArrowFunctionExpression: checkForBlock + }; + } }; diff --git a/tools/eslint/lib/rules/no-restricted-properties.js b/tools/eslint/lib/rules/no-restricted-properties.js index b6c584c57e32e3..e3a3d14e51a22f 100644 --- a/tools/eslint/lib/rules/no-restricted-properties.js +++ b/tools/eslint/lib/rules/no-restricted-properties.js @@ -109,6 +109,7 @@ module.exports = { if (matchedObjectProperty) { const message = matchedObjectProperty.message ? ` ${matchedObjectProperty.message}` : ""; + // eslint-disable-next-line eslint-plugin/report-message-format context.report({ node, message: "'{{objectName}}.{{propertyName}}' is restricted from being used.{{message}}", data: { objectName, propertyName, @@ -117,6 +118,7 @@ module.exports = { } else if (globalMatchedProperty) { const message = globalMatchedProperty.message ? ` ${globalMatchedProperty.message}` : ""; + // eslint-disable-next-line eslint-plugin/report-message-format context.report({ node, message: "'{{propertyName}}' is restricted from being used.{{message}}", data: { propertyName, message diff --git a/tools/eslint/lib/rules/no-restricted-syntax.js b/tools/eslint/lib/rules/no-restricted-syntax.js index 830452d995dab4..1798065ec06cbe 100644 --- a/tools/eslint/lib/rules/no-restricted-syntax.js +++ b/tools/eslint/lib/rules/no-restricted-syntax.js @@ -8,8 +8,6 @@ // Rule Definition //------------------------------------------------------------------------------ -const nodeTypes = require("espree").Syntax; - module.exports = { meta: { docs: { @@ -20,31 +18,44 @@ module.exports = { schema: { type: "array", - items: [ - { - enum: Object.keys(nodeTypes).map(k => nodeTypes[k]) - } - ], + items: [{ + oneOf: [ + { + type: "string" + }, + { + type: "object", + properties: { + selector: { type: "string" }, + message: { type: "string" } + }, + required: ["selector"], + additionalProperties: false + } + ] + }], uniqueItems: true, minItems: 0 } }, create(context) { - - /** - * Generates a warning from the provided node, saying that node type is not allowed. - * @param {ASTNode} node The node to warn on - * @returns {void} - */ - function warn(node) { - context.report({ node, message: "Using '{{type}}' is not allowed.", data: node }); - } - - return context.options.reduce((result, nodeType) => { - result[nodeType] = warn; - - return result; + return context.options.reduce((result, selectorOrObject) => { + const isStringFormat = (typeof selectorOrObject === "string"); + const hasCustomMessage = !isStringFormat && Boolean(selectorOrObject.message); + + const selector = isStringFormat ? selectorOrObject : selectorOrObject.selector; + const message = hasCustomMessage ? selectorOrObject.message : "Using '{{selector}}' is not allowed."; + + return Object.assign(result, { + [selector](node) { + context.report({ + node, + message, + data: hasCustomMessage ? {} : { selector } + }); + } + }); }, {}); } diff --git a/tools/eslint/lib/rules/no-return-assign.js b/tools/eslint/lib/rules/no-return-assign.js index 653d997468ebf8..882f94b7246212 100644 --- a/tools/eslint/lib/rules/no-return-assign.js +++ b/tools/eslint/lib/rules/no-return-assign.js @@ -5,23 +5,16 @@ "use strict"; //------------------------------------------------------------------------------ -// Helpers +// Requirements //------------------------------------------------------------------------------ -const SENTINEL_TYPE = /^(?:[a-zA-Z]+?Statement|ArrowFunctionExpression|FunctionExpression|ClassExpression)$/; +const astUtils = require("../ast-utils"); -/** - * Checks whether or not a node is enclosed in parentheses. - * @param {Node|null} node - A node to check. - * @param {sourceCode} sourceCode - The ESLint SourceCode object. - * @returns {boolean} Whether or not the node is enclosed in parentheses. - */ -function isEnclosedInParens(node, sourceCode) { - const prevToken = sourceCode.getTokenBefore(node); - const nextToken = sourceCode.getTokenAfter(node); +//------------------------------------------------------------------------------ +// Helpers +//------------------------------------------------------------------------------ - return prevToken && prevToken.value === "(" && nextToken && nextToken.value === ")"; -} +const SENTINEL_TYPE = /^(?:[a-zA-Z]+?Statement|ArrowFunctionExpression|FunctionExpression|ClassExpression)$/; //------------------------------------------------------------------------------ // Rule Definition @@ -48,7 +41,7 @@ module.exports = { return { AssignmentExpression(node) { - if (!always && isEnclosedInParens(node, sourceCode)) { + if (!always && astUtils.isParenthesised(sourceCode, node)) { return; } diff --git a/tools/eslint/lib/rules/no-return-await.js b/tools/eslint/lib/rules/no-return-await.js index bc0498cb044d70..a7933460d47624 100644 --- a/tools/eslint/lib/rules/no-return-await.js +++ b/tools/eslint/lib/rules/no-return-await.js @@ -19,7 +19,7 @@ module.exports = { category: "Best Practices", recommended: false // TODO: set to true }, - fixable: false, + fixable: null, schema: [ ] }, @@ -35,7 +35,7 @@ module.exports = { context.report({ node: context.getSourceCode().getFirstToken(node), loc: node.loc, - message, + message }); } @@ -88,7 +88,7 @@ module.exports = { if (isInTailCallPosition(node) && !hasErrorHandler(node)) { reportUnnecessaryAwait(node); } - }, + } }; } }; diff --git a/tools/eslint/lib/rules/no-sequences.js b/tools/eslint/lib/rules/no-sequences.js index 67f9d8212fd4e5..23c1956ebeba07 100644 --- a/tools/eslint/lib/rules/no-sequences.js +++ b/tools/eslint/lib/rules/no-sequences.js @@ -5,6 +5,12 @@ "use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("../ast-utils"); + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -57,12 +63,7 @@ module.exports = { * @returns {boolean} True if the node has a paren on each side. */ function isParenthesised(node) { - const previousToken = sourceCode.getTokenBefore(node), - nextToken = sourceCode.getTokenAfter(node); - - return previousToken && nextToken && - previousToken.value === "(" && previousToken.range[1] <= node.range[0] && - nextToken.value === ")" && nextToken.range[0] >= node.range[1]; + return astUtils.isParenthesised(sourceCode, node); } /** @@ -75,8 +76,8 @@ module.exports = { nextToken = sourceCode.getTokenAfter(node, 1); return isParenthesised(node) && previousToken && nextToken && - previousToken.value === "(" && previousToken.range[1] <= node.range[0] && - nextToken.value === ")" && nextToken.range[0] >= node.range[1]; + astUtils.isOpeningParenToken(previousToken) && previousToken.range[1] <= node.range[0] && + astUtils.isClosingParenToken(nextToken) && nextToken.range[0] >= node.range[1]; } return { diff --git a/tools/eslint/lib/rules/no-sync.js b/tools/eslint/lib/rules/no-sync.js index 90b2be1e9fdf19..885b1eb6289174 100644 --- a/tools/eslint/lib/rules/no-sync.js +++ b/tools/eslint/lib/rules/no-sync.js @@ -26,19 +26,14 @@ module.exports = { return { - MemberExpression(node) { - const propertyName = node.property.name, - syncRegex = /.*Sync$/; - - if (syncRegex.exec(propertyName) !== null) { - context.report({ - node, - message: "Unexpected sync method: '{{propertyName}}'.", - data: { - propertyName - } - }); - } + "MemberExpression[property.name=/.*Sync$/]"(node) { + context.report({ + node, + message: "Unexpected sync method: '{{propertyName}}'.", + data: { + propertyName: node.property.name + } + }); } }; diff --git a/tools/eslint/lib/rules/no-throw-literal.js b/tools/eslint/lib/rules/no-throw-literal.js index 0d1f42985f89ec..5e9054399a28ae 100644 --- a/tools/eslint/lib/rules/no-throw-literal.js +++ b/tools/eslint/lib/rules/no-throw-literal.js @@ -5,44 +5,7 @@ "use strict"; -//------------------------------------------------------------------------------ -// Helpers -//------------------------------------------------------------------------------ - -/** - * Determine if a node has a possiblity to be an Error object - * @param {ASTNode} node ASTNode to check - * @returns {boolean} True if there is a chance it contains an Error obj - */ -function couldBeError(node) { - switch (node.type) { - case "Identifier": - case "CallExpression": - case "NewExpression": - case "MemberExpression": - case "TaggedTemplateExpression": - case "YieldExpression": - return true; // possibly an error object. - - case "AssignmentExpression": - return couldBeError(node.right); - - case "SequenceExpression": { - const exprs = node.expressions; - - return exprs.length !== 0 && couldBeError(exprs[exprs.length - 1]); - } - - case "LogicalExpression": - return couldBeError(node.left) || couldBeError(node.right); - - case "ConditionalExpression": - return couldBeError(node.consequent) || couldBeError(node.alternate); - - default: - return false; - } -} +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -64,7 +27,7 @@ module.exports = { return { ThrowStatement(node) { - if (!couldBeError(node.argument)) { + if (!astUtils.couldBeError(node.argument)) { context.report({ node, message: "Expected an object to be thrown." }); } else if (node.argument.type === "Identifier") { if (node.argument.name === "undefined") { diff --git a/tools/eslint/lib/rules/no-trailing-spaces.js b/tools/eslint/lib/rules/no-trailing-spaces.js index eb1bd2fcdc266f..471381f24618e5 100644 --- a/tools/eslint/lib/rules/no-trailing-spaces.js +++ b/tools/eslint/lib/rules/no-trailing-spaces.js @@ -4,6 +4,12 @@ */ "use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("../ast-utils"); + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -34,7 +40,7 @@ module.exports = { create(context) { const sourceCode = context.getSourceCode(); - const BLANK_CLASS = "[ \t\u00a0\u2000-\u200b\u2028\u2029\u3000]", + const BLANK_CLASS = "[ \t\u00a0\u2000-\u200b\u3000]", SKIP_BLANK = `^${BLANK_CLASS}*$`, NONBLANK = `${BLANK_CLASS}+$`; @@ -81,7 +87,7 @@ module.exports = { const re = new RegExp(NONBLANK), skipMatch = new RegExp(SKIP_BLANK), lines = sourceCode.lines, - linebreaks = sourceCode.getText().match(/\r\n|\r|\n|\u2028|\u2029/g); + linebreaks = sourceCode.getText().match(astUtils.createGlobalLinebreakMatcher()); let totalLength = 0, fixRange = []; diff --git a/tools/eslint/lib/rules/no-undefined.js b/tools/eslint/lib/rules/no-undefined.js index 18e1d98641dc86..d29ac1e720f2c6 100644 --- a/tools/eslint/lib/rules/no-undefined.js +++ b/tools/eslint/lib/rules/no-undefined.js @@ -21,15 +21,54 @@ module.exports = { create(context) { + /** + * Report an invalid "undefined" identifier node. + * @param {ASTNode} node The node to report. + * @returns {void} + */ + function report(node) { + context.report({ + node, + message: "Unexpected use of undefined." + }); + } + + /** + * Checks the given scope for references to `undefined` and reports + * all references found. + * @param {escope.Scope} scope The scope to check. + * @returns {void} + */ + function checkScope(scope) { + const undefinedVar = scope.set.get("undefined"); + + if (!undefinedVar) { + return; + } + + const references = undefinedVar.references; + + const defs = undefinedVar.defs; + + // Report non-initializing references (those are covered in defs below) + references + .filter(ref => !ref.init) + .forEach(ref => report(ref.identifier)); + + defs.forEach(def => report(def.name)); + } + return { + "Program:exit"() { + const globalScope = context.getScope(); + + const stack = [globalScope]; - Identifier(node) { - if (node.name === "undefined") { - const parent = context.getAncestors().pop(); + while (stack.length) { + const scope = stack.pop(); - if (!parent || parent.type !== "MemberExpression" || node !== parent.property || parent.computed) { - context.report({ node, message: "Unexpected use of undefined." }); - } + stack.push.apply(stack, scope.childScopes); + checkScope(scope); } } }; diff --git a/tools/eslint/lib/rules/no-unexpected-multiline.js b/tools/eslint/lib/rules/no-unexpected-multiline.js index bae4833983b14e..6c15f5dd591e31 100644 --- a/tools/eslint/lib/rules/no-unexpected-multiline.js +++ b/tools/eslint/lib/rules/no-unexpected-multiline.js @@ -4,9 +4,16 @@ */ "use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("../ast-utils"); + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ + module.exports = { meta: { docs: { @@ -35,14 +42,8 @@ module.exports = { * @private */ function checkForBreakAfter(node, msg) { - let nodeExpressionEnd = node; - let openParen = sourceCode.getTokenAfter(node); - - // Move along until the end of the wrapped expression - while (openParen.value === ")") { - nodeExpressionEnd = openParen; - openParen = sourceCode.getTokenAfter(nodeExpressionEnd); - } + const openParen = sourceCode.getTokenAfter(node, astUtils.isNotClosingParenToken); + const nodeExpressionEnd = sourceCode.getTokenBefore(openParen); if (openParen.loc.start.line !== nodeExpressionEnd.loc.end.line) { context.report({ node, loc: openParen.loc.start, message: msg, data: { char: openParen.value } }); diff --git a/tools/eslint/lib/rules/no-unneeded-ternary.js b/tools/eslint/lib/rules/no-unneeded-ternary.js index cba83ea48140ec..b031927f9248cb 100644 --- a/tools/eslint/lib/rules/no-unneeded-ternary.js +++ b/tools/eslint/lib/rules/no-unneeded-ternary.js @@ -67,7 +67,11 @@ module.exports = { */ function invertExpression(node) { if (node.type === "BinaryExpression" && Object.prototype.hasOwnProperty.call(OPERATOR_INVERSES, node.operator)) { - const operatorToken = sourceCode.getTokensBetween(node.left, node.right).find(token => token.value === node.operator); + const operatorToken = sourceCode.getFirstTokenBetween( + node.left, + node.right, + token => token.value === node.operator + ); return sourceCode.getText().slice(node.range[0], operatorToken.range[0]) + OPERATOR_INVERSES[node.operator] + sourceCode.getText().slice(operatorToken.range[1], node.range[1]); } diff --git a/tools/eslint/lib/rules/no-unsafe-negation.js b/tools/eslint/lib/rules/no-unsafe-negation.js index 4e2378d4d0f7db..761dc03386e13f 100644 --- a/tools/eslint/lib/rules/no-unsafe-negation.js +++ b/tools/eslint/lib/rules/no-unsafe-negation.js @@ -44,7 +44,7 @@ module.exports = { docs: { description: "disallow negating the left operand of relational operators", category: "Possible Errors", - recommended: false + recommended: true }, schema: [], fixable: "code" diff --git a/tools/eslint/lib/rules/no-unused-expressions.js b/tools/eslint/lib/rules/no-unused-expressions.js index 548e02f463e71a..b4e1074d5498a1 100644 --- a/tools/eslint/lib/rules/no-unused-expressions.js +++ b/tools/eslint/lib/rules/no-unused-expressions.js @@ -25,6 +25,9 @@ module.exports = { }, allowTernary: { type: "boolean" + }, + allowTaggedTemplates: { + type: "boolean" } }, additionalProperties: false @@ -35,7 +38,8 @@ module.exports = { create(context) { const config = context.options[0] || {}, allowShortCircuit = config.allowShortCircuit || false, - allowTernary = config.allowTernary || false; + allowTernary = config.allowTernary || false, + allowTaggedTemplates = config.allowTaggedTemplates || false; /** * @param {ASTNode} node - any node @@ -95,12 +99,17 @@ module.exports = { return isValidExpression(node.consequent) && isValidExpression(node.alternate); } } + if (allowShortCircuit) { if (node.type === "LogicalExpression") { return isValidExpression(node.right); } } + if (allowTaggedTemplates && node.type === "TaggedTemplateExpression") { + return true; + } + return /^(?:Assignment|Call|New|Update|Yield|Await)Expression$/.test(node.type) || (node.type === "UnaryExpression" && ["delete", "void"].indexOf(node.operator) >= 0); } diff --git a/tools/eslint/lib/rules/no-unused-labels.js b/tools/eslint/lib/rules/no-unused-labels.js index 7d3e533c44a566..12f60ca184ea57 100644 --- a/tools/eslint/lib/rules/no-unused-labels.js +++ b/tools/eslint/lib/rules/no-unused-labels.js @@ -17,10 +17,13 @@ module.exports = { recommended: true }, - schema: [] + schema: [], + + fixable: "code" }, create(context) { + const sourceCode = context.getSourceCode(); let scopeInfo = null; /** @@ -49,7 +52,19 @@ module.exports = { context.report({ node: node.label, message: "'{{name}}:' is defined but never used.", - data: node.label + data: node.label, + fix(fixer) { + + /* + * Only perform a fix if there are no comments between the label and the body. This will be the case + * when there is exactly one token/comment (the ":") between the label and the body. + */ + if (sourceCode.getTokenAfter(node.label, { includeComments: true }) === sourceCode.getTokenBefore(node.body, { includeComments: true })) { + return fixer.removeRange([node.range[0], node.body.range[0]]); + } + + return null; + } }); } diff --git a/tools/eslint/lib/rules/no-unused-vars.js b/tools/eslint/lib/rules/no-unused-vars.js index ac8f2ed1c0a20a..6f270396739c8a 100644 --- a/tools/eslint/lib/rules/no-unused-vars.js +++ b/tools/eslint/lib/rules/no-unused-vars.js @@ -42,6 +42,9 @@ module.exports = { args: { enum: ["all", "after-used", "none"] }, + ignoreRestSiblings: { + type: "boolean" + }, argsIgnorePattern: { type: "string" }, @@ -59,13 +62,16 @@ module.exports = { }, create(context) { + const sourceCode = context.getSourceCode(); const DEFINED_MESSAGE = "'{{name}}' is defined but never used."; const ASSIGNED_MESSAGE = "'{{name}}' is assigned a value but never used."; + const REST_PROPERTY_TYPE = /^(?:Experimental)?RestProperty$/; const config = { vars: "all", args: "after-used", + ignoreRestSiblings: false, caughtErrors: "none" }; @@ -77,6 +83,7 @@ module.exports = { } else { config.vars = firstOption.vars || config.vars; config.args = firstOption.args || config.args; + config.ignoreRestSiblings = firstOption.ignoreRestSiblings || config.ignoreRestSiblings; config.caughtErrors = firstOption.caughtErrors || config.caughtErrors; if (firstOption.varsIgnorePattern) { @@ -120,9 +127,32 @@ module.exports = { } return node.parent.type.indexOf("Export") === 0; - } else { - return false; } + return false; + + } + + /** + * Determines if a variable has a sibling rest property + * @param {Variable} variable - EScope variable object. + * @returns {boolean} True if the variable is exported, false if not. + * @private + */ + function hasRestSpreadSibling(variable) { + if (config.ignoreRestSiblings) { + return variable.defs.some(def => { + const propertyNode = def.name.parent; + const patternNode = propertyNode.parent; + + return ( + propertyNode.type === "Property" && + patternNode.type === "ObjectPattern" && + REST_PROPERTY_TYPE.test(patternNode.properties[patternNode.properties.length - 1].type) + ); + }); + } + + return false; } /** @@ -495,7 +525,7 @@ module.exports = { } } - if (!isUsedVariable(variable) && !isExported(variable)) { + if (!isUsedVariable(variable) && !isExported(variable) && !hasRestSpreadSibling(variable)) { unusedVars.push(variable); } } @@ -537,23 +567,8 @@ module.exports = { */ function getLocation(variable) { const comment = variable.eslintExplicitGlobalComment; - const baseLoc = comment.loc.start; - let column = getColumnInComment(variable, comment); - const prefix = comment.value.slice(0, column); - const lineInComment = (prefix.match(/\n/g) || []).length; - - if (lineInComment > 0) { - column -= 1 + prefix.lastIndexOf("\n"); - } else { - - // 2 is for `/*` - column += baseLoc.column + 2; - } - return { - line: baseLoc.line + lineInComment, - column - }; + return sourceCode.getLocFromIndex(comment.range[0] + 2 + getColumnInComment(variable, comment)); } //-------------------------------------------------------------------------- diff --git a/tools/eslint/lib/rules/no-use-before-define.js b/tools/eslint/lib/rules/no-use-before-define.js index ea1cf301f29af4..1a779b86f2318e 100644 --- a/tools/eslint/lib/rules/no-use-before-define.js +++ b/tools/eslint/lib/rules/no-use-before-define.js @@ -21,22 +21,17 @@ const FOR_IN_OF_TYPE = /^For(?:In|Of)Statement$/; function parseOptions(options) { let functions = true; let classes = true; + let variables = true; if (typeof options === "string") { functions = (options !== "nofunc"); } else if (typeof options === "object" && options !== null) { functions = options.functions !== false; classes = options.classes !== false; + variables = options.variables !== false; } - return { functions, classes }; -} - -/** - * @returns {boolean} `false`. - */ -function alwaysFalse() { - return false; + return { functions, classes, variables }; } /** @@ -64,14 +59,16 @@ function isOuterClass(variable, reference) { } /** - * Checks whether or not a given variable is a function declaration or a class declaration in an upper function scope. - * - * @param {escope.Variable} variable - A variable to check. - * @param {escope.Reference} reference - A reference to check. - * @returns {boolean} `true` if the variable is a function declaration or a class declaration. - */ -function isFunctionOrOuterClass(variable, reference) { - return isFunction(variable, reference) || 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. +* @returns {boolean} `true` if the variable is a variable declaration. +*/ +function isOuterVariable(variable, reference) { + return ( + variable.defs[0].type === "Variable" && + variable.scope.variableScope !== reference.from.variableScope + ); } /** @@ -155,7 +152,8 @@ module.exports = { type: "object", properties: { functions: { type: "boolean" }, - classes: { type: "boolean" } + classes: { type: "boolean" }, + variables: { type: "boolean" } }, additionalProperties: false } @@ -167,17 +165,23 @@ module.exports = { create(context) { const options = parseOptions(context.options[0]); - // Defines a function which checks whether or not a reference is allowed according to the option. - let isAllowed; - - if (options.functions && options.classes) { - isAllowed = alwaysFalse; - } else if (options.functions) { - isAllowed = isOuterClass; - } else if (options.classes) { - isAllowed = isFunction; - } else { - isAllowed = isFunctionOrOuterClass; + /** + * 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 + * @returns {boolean} `true` if the usage should be reported + */ + function isForbidden(variable, reference) { + if (isFunction(variable)) { + return options.functions; + } + if (isOuterClass(variable, reference)) { + return options.classes; + } + if (isOuterVariable(variable, reference)) { + return options.variables; + } + return true; } /** @@ -200,7 +204,7 @@ module.exports = { !variable || variable.identifiers.length === 0 || (variable.identifiers[0].range[1] < reference.identifier.range[1] && !isInInitializer(variable, reference)) || - isAllowed(variable, reference) + !isForbidden(variable, reference) ) { return; } diff --git a/tools/eslint/lib/rules/no-useless-computed-key.js b/tools/eslint/lib/rules/no-useless-computed-key.js index c1ab1d9acd5bc2..fd5ec2c92b5c5c 100644 --- a/tools/eslint/lib/rules/no-useless-computed-key.js +++ b/tools/eslint/lib/rules/no-useless-computed-key.js @@ -4,6 +4,13 @@ */ "use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("../ast-utils"); +const esUtils = require("esutils"); + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -34,15 +41,14 @@ module.exports = { const key = node.key, nodeType = typeof key.value; - if (key.type === "Literal" && (nodeType === "string" || nodeType === "number")) { + if (key.type === "Literal" && (nodeType === "string" || nodeType === "number") && key.value !== "__proto__") { context.report({ node, message: MESSAGE_UNNECESSARY_COMPUTED, data: { property: sourceCode.getText(key) }, fix(fixer) { - const leftSquareBracket = sourceCode.getFirstToken(node, node.value.generator || node.value.async ? 1 : 0); - const rightSquareBracket = sourceCode.getTokensBetween(node.key, node.value).find(token => token.value === "]"); - + const leftSquareBracket = sourceCode.getFirstToken(node, astUtils.isOpeningBracketToken); + const rightSquareBracket = sourceCode.getFirstTokenBetween(node.key, node.value, astUtils.isClosingBracketToken); const tokensBetween = sourceCode.getTokensBetween(leftSquareBracket, rightSquareBracket, 1); if (tokensBetween.slice(0, -1).some((token, index) => sourceCode.getText().slice(token.range[1], tokensBetween[index + 1].range[0]).trim())) { @@ -50,7 +56,17 @@ module.exports = { // If there are comments between the brackets and the property name, don't do a fix. return null; } - return fixer.replaceTextRange([leftSquareBracket.range[0], rightSquareBracket.range[1]], key.raw); + + const tokenBeforeLeftBracket = sourceCode.getTokenBefore(leftSquareBracket); + + // 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)); + + const replacementKey = (needsSpaceBeforeKey ? " " : "") + key.raw; + + return fixer.replaceTextRange([leftSquareBracket.range[0], rightSquareBracket.range[1]], replacementKey); } }); } diff --git a/tools/eslint/lib/rules/no-useless-concat.js b/tools/eslint/lib/rules/no-useless-concat.js index ed0ef66a2441e1..e42781fee7da30 100644 --- a/tools/eslint/lib/rules/no-useless-concat.js +++ b/tools/eslint/lib/rules/no-useless-concat.js @@ -23,6 +23,15 @@ function isConcatenation(node) { return node.type === "BinaryExpression" && node.operator === "+"; } +/** + * Checks if the given token is a `+` token or not. + * @param {Token} token - The token to check. + * @returns {boolean} `true` if the token is a `+` token. + */ +function isConcatOperatorToken(token) { + return token.value === "+" && token.type === "Punctuator"; +} + /** * Get's the right most node on the left side of a BinaryExpression with + operator. * @param {ASTNode} node - A BinaryExpression node to check. @@ -85,13 +94,7 @@ module.exports = { astUtils.isStringLiteral(right) && astUtils.isTokenOnSameLine(left, right) ) { - - // move warning location to operator - let operatorToken = sourceCode.getTokenAfter(left); - - while (operatorToken.value !== "+") { - operatorToken = sourceCode.getTokenAfter(operatorToken); - } + const operatorToken = sourceCode.getFirstTokenBetween(left, right, isConcatOperatorToken); context.report({ node, diff --git a/tools/eslint/lib/rules/no-useless-escape.js b/tools/eslint/lib/rules/no-useless-escape.js index b9266bbbafa69a..ffe11999707ce2 100644 --- a/tools/eslint/lib/rules/no-useless-escape.js +++ b/tools/eslint/lib/rules/no-useless-escape.js @@ -24,7 +24,7 @@ function union(setA, setB) { }()); } -const VALID_STRING_ESCAPES = new Set("\\nrvtbfux\n\r\u2028\u2029"); +const VALID_STRING_ESCAPES = union(new Set("\\nrvtbfux"), astUtils.LINEBREAKS); const REGEX_GENERAL_ESCAPES = new Set("\\bcdDfnrsStvwWxu0123456789]"); const REGEX_NON_CHARCLASS_ESCAPES = union(REGEX_GENERAL_ESCAPES, new Set("^/.$*+?[{}|()B")); @@ -94,7 +94,7 @@ module.exports = { function report(node, startOffset, character) { context.report({ node, - loc: astUtils.getLocationFromRangeIndex(sourceCode, astUtils.getRangeIndexFromLocation(sourceCode, node.loc.start) + startOffset), + loc: sourceCode.getLocFromIndex(sourceCode.getIndexFromLoc(node.loc.start) + startOffset), message: "Unnecessary escape character: \\{{character}}.", data: { character } }); @@ -147,7 +147,13 @@ module.exports = { function check(node) { const isTemplateElement = node.type === "TemplateElement"; - if (isTemplateElement && node.parent && node.parent.parent && node.parent.parent.type === "TaggedTemplateExpression") { + if ( + isTemplateElement && + node.parent && + node.parent.parent && + node.parent.parent.type === "TaggedTemplateExpression" && + node.parent === node.parent.parent.quasi + ) { // Don't report tagged template literals, because the backslash character is accessible to the tag function. return; diff --git a/tools/eslint/lib/rules/no-useless-return.js b/tools/eslint/lib/rules/no-useless-return.js index e2a6da03183501..29f644cc43df73 100644 --- a/tools/eslint/lib/rules/no-useless-return.js +++ b/tools/eslint/lib/rules/no-useless-return.js @@ -8,7 +8,8 @@ // Requirements //------------------------------------------------------------------------------ -const astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"), + FixTracker = require("../util/fix-tracker"); //------------------------------------------------------------------------------ // Helpers @@ -45,13 +46,7 @@ function remove(array, element) { * @returns {boolean} `true` if the node is removeable. */ function isRemovable(node) { - const parent = node.parent; - - return ( - parent.type === "Program" || - parent.type === "BlockStatement" || - parent.type === "SwitchCase" - ); + return astUtils.STATEMENT_LIST_PARENTS.has(node.parent.type); } /** @@ -213,7 +208,7 @@ module.exports = { scopeInfo = { upper: scopeInfo, uselessReturns: [], - codePath, + codePath }; }, @@ -225,8 +220,18 @@ module.exports = { loc: node.loc, message: "Unnecessary return statement.", fix(fixer) { - return isRemovable(node) ? fixer.remove(node) : null; - }, + if (isRemovable(node)) { + + // Extend the replacement range to include the + // entire function to avoid conflicting with + // no-else-return. + // https://github.com/eslint/eslint/issues/8026 + return new FixTracker(fixer, context.getSourceCode()) + .retainEnclosingFunction(node) + .remove(node); + } + return null; + } }); } @@ -238,7 +243,7 @@ module.exports = { onCodePathSegmentStart(segment) { const info = { uselessReturns: getUselessReturns([], segment.allPrevSegments), - returned: false, + returned: false }; // Stores the info. @@ -287,7 +292,7 @@ module.exports = { WithStatement: markReturnStatementsOnCurrentSegmentsAsUsed, ExportNamedDeclaration: markReturnStatementsOnCurrentSegmentsAsUsed, ExportDefaultDeclaration: markReturnStatementsOnCurrentSegmentsAsUsed, - ExportAllDeclaration: markReturnStatementsOnCurrentSegmentsAsUsed, + ExportAllDeclaration: markReturnStatementsOnCurrentSegmentsAsUsed }; } }; diff --git a/tools/eslint/lib/rules/no-var.js b/tools/eslint/lib/rules/no-var.js index 3c22f009c63bb6..86373ad5009eda 100644 --- a/tools/eslint/lib/rules/no-var.js +++ b/tools/eslint/lib/rules/no-var.js @@ -128,6 +128,43 @@ function isUsedFromOutsideOf(scopeNode) { }; } +/** + * Creates the predicate function which checks whether a variable has their references in TDZ. + * + * The predicate function would return `true`: + * + * - if a reference is before the declarator. E.g. (var a = b, b = 1;)(var {a = b, b} = {};) + * - if a reference is in the expression of their default value. E.g. (var {a = a} = {};) + * - if a reference is in the expression of their initializer. E.g. (var a = a;) + * + * @param {ASTNode} node - The initializer node of VariableDeclarator. + * @returns {Function} The predicate function. + * @private + */ +function hasReferenceInTDZ(node) { + const initStart = node.range[0]; + const initEnd = node.range[1]; + + return variable => { + const id = variable.defs[0].name; + const idStart = id.range[0]; + const defaultValue = (id.parent.type === "AssignmentPattern" ? id.parent.right : null); + const defaultStart = defaultValue && defaultValue.range[0]; + const defaultEnd = defaultValue && defaultValue.range[1]; + + return variable.references.some(reference => { + const start = reference.identifier.range[0]; + const end = reference.identifier.range[1]; + + return !reference.init && ( + start < idStart || + (defaultValue !== null && start >= defaultStart && end <= defaultEnd) || + (start >= initStart && end <= initEnd) + ); + }); + }; +} + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -147,6 +184,21 @@ module.exports = { create(context) { const sourceCode = context.getSourceCode(); + /** + * Checks whether the variables which are defined by the given declarator node have their references in TDZ. + * + * @param {ASTNode} declarator - The VariableDeclarator node to check. + * @returns {boolean} `true` if one of the variables which are defined by the given declarator node have their references in TDZ. + */ + function hasSelfReferenceInTDZ(declarator) { + if (!declarator.init) { + return false; + } + const variables = context.getDeclaredVariables(declarator); + + return variables.some(hasReferenceInTDZ(declarator.init)); + } + /** * Checks whether it can fix a given variable declaration or not. * It cannot fix if the following cases: @@ -156,6 +208,8 @@ module.exports = { * - A variable is used from outside the scope. * - A variable is used from a closure within a loop. * - A variable might be used before it is assigned within a loop. + * - A variable might be used in TDZ. + * - A variable is declared in statement position (e.g. a single-line `IfStatement`) * * ## A variable is declared on a SwitchCase node. * @@ -201,8 +255,10 @@ module.exports = { const scopeNode = getScopeNode(node); if (node.parent.type === "SwitchCase" || - variables.some(isRedeclared) || - variables.some(isUsedFromOutsideOf(scopeNode))) { + node.declarations.some(hasSelfReferenceInTDZ) || + variables.some(isRedeclared) || + variables.some(isUsedFromOutsideOf(scopeNode)) + ) { return false; } @@ -215,6 +271,16 @@ module.exports = { } } + if ( + !isLoopAssignee(node) && + !(node.parent.type === "ForStatement" && node.parent.init === node) && + !astUtils.STATEMENT_LIST_PARENTS.has(node.parent.type) + ) { + + // If the declaration is not in a block, e.g. `if (foo) var bar = 1;`, then it can't be fixed. + return false; + } + return true; } @@ -241,7 +307,7 @@ module.exports = { } return { - VariableDeclaration(node) { + "VariableDeclaration:exit"(node) { if (node.kind === "var") { report(node); } diff --git a/tools/eslint/lib/rules/no-whitespace-before-property.js b/tools/eslint/lib/rules/no-whitespace-before-property.js index cb9af56579fce3..71db50c4395643 100644 --- a/tools/eslint/lib/rules/no-whitespace-before-property.js +++ b/tools/eslint/lib/rules/no-whitespace-before-property.js @@ -4,6 +4,10 @@ */ "use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ @@ -29,21 +33,6 @@ module.exports = { // Helpers //-------------------------------------------------------------------------- - /** - * Finds opening bracket token of node's computed property - * @param {ASTNode} node - the node to check - * @returns {Token} opening bracket token of node's computed property - * @private - */ - function findOpeningBracket(node) { - let token = sourceCode.getTokenBefore(node.property); - - while (token.value !== "[") { - token = sourceCode.getTokenBefore(token); - } - return token; - } - /** * Reports whitespace before property token * @param {ASTNode} node - the node to report in the event of an error @@ -87,7 +76,7 @@ module.exports = { } if (node.computed) { - rightToken = findOpeningBracket(node); + rightToken = sourceCode.getTokenBefore(node.property, astUtils.isOpeningBracketToken); leftToken = sourceCode.getTokenBefore(rightToken); } else { rightToken = sourceCode.getFirstToken(node.property); diff --git a/tools/eslint/lib/rules/nonblock-statement-body-position.js b/tools/eslint/lib/rules/nonblock-statement-body-position.js new file mode 100644 index 00000000000000..212e36a57c2b57 --- /dev/null +++ b/tools/eslint/lib/rules/nonblock-statement-body-position.js @@ -0,0 +1,114 @@ +/** + * @fileoverview enforce the location of single-line statements + * @author Teddy Katz + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +const POSITION_SCHEMA = { enum: ["beside", "below", "any"] }; + +module.exports = { + meta: { + docs: { + description: "enforce the location of single-line statements", + category: "Stylistic Issues", + recommended: false + }, + fixable: "whitespace", + schema: [ + POSITION_SCHEMA, + { + properties: { + overrides: { + properties: { + if: POSITION_SCHEMA, + else: POSITION_SCHEMA, + while: POSITION_SCHEMA, + do: POSITION_SCHEMA, + for: POSITION_SCHEMA + }, + additionalProperties: false + } + }, + additionalProperties: false + } + ] + }, + + create(context) { + const sourceCode = context.getSourceCode(); + + //---------------------------------------------------------------------- + // Helpers + //---------------------------------------------------------------------- + + /** + * Gets the applicable preference for a particular keyword + * @param {string} keywordName The name of a keyword, e.g. 'if' + * @returns {string} The applicable option for the keyword, e.g. 'beside' + */ + function getOption(keywordName) { + return context.options[1] && context.options[1].overrides && context.options[1].overrides[keywordName] || + context.options[0] || + "beside"; + } + + /** + * Validates the location of a single-line statement + * @param {ASTNode} node The single-line statement + * @param {string} keywordName The applicable keyword name for the single-line statement + * @returns {void} + */ + function validateStatement(node, keywordName) { + const option = getOption(keywordName); + + if (node.type === "BlockStatement" || option === "any") { + return; + } + + const tokenBefore = sourceCode.getTokenBefore(node); + + if (tokenBefore.loc.end.line === node.loc.start.line && option === "below") { + context.report({ + node, + message: "Expected a linebreak before this statement.", + fix: fixer => fixer.insertTextBefore(node, "\n") + }); + } else if (tokenBefore.loc.end.line !== node.loc.start.line && option === "beside") { + context.report({ + node, + message: "Expected no linebreak before this statement.", + fix(fixer) { + if (sourceCode.getText().slice(tokenBefore.range[1], node.range[0]).trim()) { + return null; + } + return fixer.replaceTextRange([tokenBefore.range[1], node.range[0]], " "); + } + }); + } + } + + //---------------------------------------------------------------------- + // Public + //---------------------------------------------------------------------- + + return { + IfStatement(node) { + validateStatement(node.consequent, "if"); + + // Check the `else` node, but don't check 'else if' statements. + if (node.alternate && node.alternate.type !== "IfStatement") { + validateStatement(node.alternate, "else"); + } + }, + WhileStatement: node => validateStatement(node.body, "while"), + DoWhileStatement: node => validateStatement(node.body, "do"), + ForStatement: node => validateStatement(node.body, "for"), + ForInStatement: node => validateStatement(node.body, "for"), + ForOfStatement: node => validateStatement(node.body, "for") + }; + } +}; diff --git a/tools/eslint/lib/rules/object-curly-newline.js b/tools/eslint/lib/rules/object-curly-newline.js index 88fc79463cb6ae..a4451154dfb148 100644 --- a/tools/eslint/lib/rules/object-curly-newline.js +++ b/tools/eslint/lib/rules/object-curly-newline.js @@ -128,8 +128,8 @@ module.exports = { const options = normalizedOptions[node.type]; const openBrace = sourceCode.getFirstToken(node); const closeBrace = sourceCode.getLastToken(node); - let first = sourceCode.getTokenOrCommentAfter(openBrace); - let last = sourceCode.getTokenOrCommentBefore(closeBrace); + let first = sourceCode.getTokenAfter(openBrace, { includeComments: true }); + let last = sourceCode.getTokenBefore(closeBrace, { includeComments: true }); const needsLinebreaks = ( node.properties.length >= options.minProperties || ( diff --git a/tools/eslint/lib/rules/object-curly-spacing.js b/tools/eslint/lib/rules/object-curly-spacing.js index 15e8fb5a342bce..5c885240e2e9f8 100644 --- a/tools/eslint/lib/rules/object-curly-spacing.js +++ b/tools/eslint/lib/rules/object-curly-spacing.js @@ -171,8 +171,8 @@ module.exports = { if (astUtils.isTokenOnSameLine(penultimate, last)) { const shouldCheckPenultimate = ( - options.arraysInObjectsException && penultimate.value === "]" || - options.objectsInObjectsException && penultimate.value === "}" + options.arraysInObjectsException && astUtils.isClosingBracketToken(penultimate) || + options.objectsInObjectsException && astUtils.isClosingBraceToken(penultimate) ); const penultimateType = shouldCheckPenultimate && sourceCode.getNodeByRangeIndex(penultimate.start).type; @@ -206,14 +206,8 @@ module.exports = { */ function getClosingBraceOfObject(node) { const lastProperty = node.properties[node.properties.length - 1]; - let token = sourceCode.getTokenAfter(lastProperty); - // skip ')' and trailing commas. - while (token.type !== "Punctuator" || token.value !== "}") { - token = sourceCode.getTokenAfter(token); - } - - return token; + return sourceCode.getTokenAfter(lastProperty, astUtils.isClosingBraceToken); } /** @@ -254,15 +248,9 @@ module.exports = { firstSpecifier = node.specifiers[1]; } - const first = sourceCode.getTokenBefore(firstSpecifier); - let last = sourceCode.getTokenAfter(lastSpecifier); - - // to support a trailing comma. - if (last.value === ",") { - last = sourceCode.getTokenAfter(last); - } - - const second = sourceCode.getTokenAfter(first), + const first = sourceCode.getTokenBefore(firstSpecifier), + last = sourceCode.getTokenAfter(lastSpecifier, astUtils.isNotCommaToken), + second = sourceCode.getTokenAfter(first), penultimate = sourceCode.getTokenBefore(last); validateBraceSpacing(node, first, second, penultimate, last); @@ -280,15 +268,9 @@ module.exports = { const firstSpecifier = node.specifiers[0], lastSpecifier = node.specifiers[node.specifiers.length - 1], - first = sourceCode.getTokenBefore(firstSpecifier); - let last = sourceCode.getTokenAfter(lastSpecifier); - - // to support a trailing comma. - if (last.value === ",") { - last = sourceCode.getTokenAfter(last); - } - - const second = sourceCode.getTokenAfter(first), + first = sourceCode.getTokenBefore(firstSpecifier), + last = sourceCode.getTokenAfter(lastSpecifier, astUtils.isNotCommaToken), + second = sourceCode.getTokenAfter(first), penultimate = sourceCode.getTokenBefore(last); validateBraceSpacing(node, first, second, penultimate, last); diff --git a/tools/eslint/lib/rules/object-property-newline.js b/tools/eslint/lib/rules/object-property-newline.js index a64420be93a910..0463e389ab9918 100644 --- a/tools/eslint/lib/rules/object-property-newline.js +++ b/tools/eslint/lib/rules/object-property-newline.js @@ -34,9 +34,9 @@ module.exports = { create(context) { const allowSameLine = context.options[0] && Boolean(context.options[0].allowMultiplePropertiesPerLine); - const errorMessage = allowSameLine ? - "Object properties must go on a new line if they aren't all on the same line." : - "Object properties must go on a new line."; + const errorMessage = allowSameLine + ? "Object properties must go on a new line if they aren't all on the same line." + : "Object properties must go on a new line."; const sourceCode = context.getSourceCode(); diff --git a/tools/eslint/lib/rules/object-shorthand.js b/tools/eslint/lib/rules/object-shorthand.js index 43997f90692de5..1d3d9dae195ddb 100644 --- a/tools/eslint/lib/rules/object-shorthand.js +++ b/tools/eslint/lib/rules/object-shorthand.js @@ -215,8 +215,8 @@ module.exports = { * @returns {Object} A fix for this node */ function makeFunctionShorthand(fixer, node) { - const firstKeyToken = node.computed ? sourceCode.getTokens(node).find(token => token.value === "[") : sourceCode.getFirstToken(node.key); - const lastKeyToken = node.computed ? sourceCode.getTokensBetween(node.key, node.value).find(token => token.value === "]") : sourceCode.getLastToken(node.key); + const firstKeyToken = node.computed ? sourceCode.getFirstToken(node, astUtils.isOpeningBracketToken) : sourceCode.getFirstToken(node.key); + const lastKeyToken = node.computed ? sourceCode.getFirstTokenBetween(node.key, node.value, astUtils.isClosingBracketToken) : sourceCode.getLastToken(node.key); const keyText = sourceCode.text.slice(firstKeyToken.range[0], lastKeyToken.range[1]); let keyPrefix = ""; @@ -230,16 +230,22 @@ module.exports = { const functionToken = sourceCode.getTokens(node.value).find(token => token.type === "Keyword" && token.value === "function"); const tokenBeforeParams = node.value.generator ? sourceCode.getTokenAfter(functionToken) : functionToken; - return fixer.replaceTextRange([firstKeyToken.range[0], tokenBeforeParams.range[1]], keyPrefix + keyText); - } else { - const arrowToken = sourceCode.getTokens(node.value).find(token => token.value === "=>"); - const tokenBeforeArrow = sourceCode.getTokenBefore(arrowToken); - const hasParensAroundParameters = tokenBeforeArrow.type === "Punctuator" && tokenBeforeArrow.value === ")"; - const oldParamText = sourceCode.text.slice(sourceCode.getFirstToken(node.value, node.value.async ? 1 : 0).range[0], tokenBeforeArrow.range[1]); - const newParamText = hasParensAroundParameters ? oldParamText : `(${oldParamText})`; - - return fixer.replaceTextRange([firstKeyToken.range[0], arrowToken.range[1]], keyPrefix + keyText + newParamText); + return fixer.replaceTextRange( + [firstKeyToken.range[0], node.range[1]], + keyPrefix + keyText + sourceCode.text.slice(tokenBeforeParams.range[1], node.value.range[1]) + ); } + const arrowToken = sourceCode.getTokens(node.value).find(token => token.value === "=>"); + const tokenBeforeArrow = sourceCode.getTokenBefore(arrowToken); + const hasParensAroundParameters = tokenBeforeArrow.type === "Punctuator" && tokenBeforeArrow.value === ")"; + const oldParamText = sourceCode.text.slice(sourceCode.getFirstToken(node.value, node.value.async ? 1 : 0).range[0], tokenBeforeArrow.range[1]); + const newParamText = hasParensAroundParameters ? oldParamText : `(${oldParamText})`; + + return fixer.replaceTextRange( + [firstKeyToken.range[0], node.range[1]], + keyPrefix + keyText + newParamText + sourceCode.text.slice(arrowToken.range[1], node.value.range[1]) + ); + } /** @@ -368,11 +374,12 @@ module.exports = { // Checks for property/method shorthand. if (isConciseProperty) { if (node.method && (APPLY_NEVER || AVOID_QUOTES && isStringLiteral(node.key))) { + const message = APPLY_NEVER ? "Expected longform method syntax." : "Expected longform method syntax for string literal keys."; // { x() {} } should be written as { x: function() {} } context.report({ node, - message: `Expected longform method syntax${APPLY_NEVER ? "" : " for string literal keys"}.`, + message, fix: fixer => makeFunctionLongform(fixer, node) }); } else if (APPLY_NEVER) { diff --git a/tools/eslint/lib/rules/operator-assignment.js b/tools/eslint/lib/rules/operator-assignment.js index e003478c7bc427..99cca356f275a9 100644 --- a/tools/eslint/lib/rules/operator-assignment.js +++ b/tools/eslint/lib/rules/operator-assignment.js @@ -4,6 +4,12 @@ */ "use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("../ast-utils"); + //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ @@ -27,7 +33,7 @@ function isCommutativeOperatorWithShorthand(operator) { * a shorthand form. */ function isNonCommutativeOperatorWithShorthand(operator) { - return ["+", "-", "/", "%", "<<", ">>", ">>>"].indexOf(operator) >= 0; + return ["+", "-", "/", "%", "<<", ">>", ">>>", "**"].indexOf(operator) >= 0; } //------------------------------------------------------------------------------ @@ -108,7 +114,7 @@ module.exports = { * @returns {Token} The operator token in the node */ function getOperatorToken(node) { - return sourceCode.getTokensBetween(node.left, node.right).find(token => token.value === node.operator); + return sourceCode.getFirstTokenBetween(node.left, node.right, token => token.value === node.operator); } /** @@ -135,7 +141,7 @@ module.exports = { const equalsToken = getOperatorToken(node); const operatorToken = getOperatorToken(expr); const leftText = sourceCode.getText().slice(node.range[0], equalsToken.range[0]); - const rightText = sourceCode.getText().slice(operatorToken.range[1], node.range[1]); + const rightText = sourceCode.getText().slice(operatorToken.range[1], node.right.range[1]); return fixer.replaceText(node, `${leftText}${expr.operator}=${rightText}`); } @@ -171,9 +177,20 @@ module.exports = { if (canBeFixed(node.left)) { const operatorToken = getOperatorToken(node); const leftText = sourceCode.getText().slice(node.range[0], operatorToken.range[0]); - const rightText = sourceCode.getText().slice(operatorToken.range[1], node.range[1]); + const newOperator = node.operator.slice(0, -1); + let rightText; + + // If this change would modify precedence (e.g. `foo *= bar + 1` => `foo = foo * (bar + 1)`), parenthesize the right side. + if ( + astUtils.getPrecedence(node.right) <= astUtils.getPrecedence({ type: "BinaryExpression", operator: newOperator }) && + !astUtils.isParenthesised(sourceCode, node.right) + ) { + rightText = `${sourceCode.text.slice(operatorToken.range[1], node.right.range[0])}(${sourceCode.getText(node.right)})`; + } else { + rightText = sourceCode.text.slice(operatorToken.range[1], node.range[1]); + } - return fixer.replaceText(node, `${leftText}= ${leftText}${node.operator.slice(0, -1)}${rightText}`); + return fixer.replaceText(node, `${leftText}= ${leftText}${newOperator}${rightText}`); } return null; } diff --git a/tools/eslint/lib/rules/operator-linebreak.js b/tools/eslint/lib/rules/operator-linebreak.js index c8f2b2818e23b2..8253094c52e4ff 100644 --- a/tools/eslint/lib/rules/operator-linebreak.js +++ b/tools/eslint/lib/rules/operator-linebreak.js @@ -5,14 +5,16 @@ "use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ -const LINEBREAK_REGEX = /\r\n|\r|\n|\u2028|\u2029/g; - module.exports = { meta: { docs: { @@ -85,7 +87,7 @@ module.exports = { if (hasLinebreakBefore !== hasLinebreakAfter && desiredStyle !== "none") { // If there is a comment before and after the operator, don't do a fix. - if (sourceCode.getTokenOrCommentBefore(operatorToken) !== tokenBefore && sourceCode.getTokenOrCommentAfter(operatorToken) !== tokenAfter) { + if (sourceCode.getTokenBefore(operatorToken, { includeComments: true }) !== tokenBefore && sourceCode.getTokenAfter(operatorToken, { includeComments: true }) !== tokenAfter) { return null; } @@ -100,6 +102,7 @@ module.exports = { newTextBefore = textAfter; newTextAfter = textBefore; } else { + const LINEBREAK_REGEX = astUtils.createGlobalLinebreakMatcher(); // Otherwise, if no linebreak is desired and no comments interfere, replace the linebreaks with empty strings. newTextBefore = desiredStyle === "before" || textBefore.trim() ? textBefore : textBefore.replace(LINEBREAK_REGEX, ""); @@ -129,19 +132,14 @@ module.exports = { * @returns {void} */ function validateNode(node, leftSide) { - let leftToken = sourceCode.getLastToken(leftSide); - let operatorToken = sourceCode.getTokenAfter(leftToken); // When the left part of a binary expression is a single expression wrapped in // parentheses (ex: `(a) + b`), leftToken will be the last token of the expression // and operatorToken will be the closing parenthesis. // The leftToken should be the last closing parenthesis, and the operatorToken // should be the token right after that. - while (operatorToken.value === ")") { - leftToken = operatorToken; - operatorToken = sourceCode.getTokenAfter(operatorToken); - } - + const operatorToken = sourceCode.getTokenAfter(leftSide, astUtils.isNotClosingParenToken); + const leftToken = sourceCode.getTokenBefore(operatorToken); const rightToken = sourceCode.getTokenAfter(operatorToken); const operator = operatorToken.value; const operatorStyleOverride = styleOverrides[operator]; diff --git a/tools/eslint/lib/rules/padded-blocks.js b/tools/eslint/lib/rules/padded-blocks.js index 2b4da39b360214..36036aec4d95df 100644 --- a/tools/eslint/lib/rules/padded-blocks.js +++ b/tools/eslint/lib/rules/padded-blocks.js @@ -90,23 +90,32 @@ module.exports = { return node.type === "Line" || node.type === "Block"; } + /** + * Checks if there is padding between two tokens + * @param {Token} first The first token + * @param {Token} second The second token + * @returns {boolean} True if there is at least a line between the tokens + */ + function isPaddingBetweenTokens(first, second) { + return second.loc.start.line - first.loc.end.line >= 2; + } + + /** * Checks if the given token has a blank line after it. * @param {Token} token The token to check. * @returns {boolean} Whether or not the token is followed by a blank line. */ - function isTokenTopPadded(token) { - const tokenStartLine = token.loc.start.line, - expectedFirstLine = tokenStartLine + 2; - let first = token; + function getFirstBlockToken(token) { + let prev = token, + first = token; do { - first = sourceCode.getTokenOrCommentAfter(first); - } while (isComment(first) && first.loc.start.line === tokenStartLine); - - const firstLine = first.loc.start.line; + prev = first; + first = sourceCode.getTokenAfter(first, { includeComments: true }); + } while (isComment(first) && first.loc.start.line === prev.loc.end.line); - return expectedFirstLine <= firstLine; + return first; } /** @@ -114,18 +123,16 @@ module.exports = { * @param {Token} token The token to check * @returns {boolean} Whether or not the token is preceeded by a blank line */ - function isTokenBottomPadded(token) { - const blockEnd = token.loc.end.line, - expectedLastLine = blockEnd - 2; - let last = token; + function getLastBlockToken(token) { + let last = token, + next = token; do { - last = sourceCode.getTokenOrCommentBefore(last); - } while (isComment(last) && last.loc.end.line === blockEnd); - - const lastLine = last.loc.end.line; + next = last; + last = sourceCode.getTokenBefore(last, { includeComments: true }); + } while (isComment(last) && last.loc.end.line === next.loc.start.line); - return lastLine <= expectedLastLine; + return last; } /** @@ -155,17 +162,21 @@ module.exports = { */ function checkPadding(node) { const openBrace = getOpenBrace(node), + firstBlockToken = getFirstBlockToken(openBrace), + tokenBeforeFirst = sourceCode.getTokenBefore(firstBlockToken, { includeComments: true }), closeBrace = sourceCode.getLastToken(node), - blockHasTopPadding = isTokenTopPadded(openBrace), - blockHasBottomPadding = isTokenBottomPadded(closeBrace); + lastBlockToken = getLastBlockToken(closeBrace), + tokenAfterLast = sourceCode.getTokenAfter(lastBlockToken, { includeComments: true }), + blockHasTopPadding = isPaddingBetweenTokens(tokenBeforeFirst, firstBlockToken), + blockHasBottomPadding = isPaddingBetweenTokens(lastBlockToken, tokenAfterLast); if (requirePaddingFor(node)) { if (!blockHasTopPadding) { context.report({ node, - loc: { line: openBrace.loc.start.line, column: openBrace.loc.start.column }, + loc: { line: tokenBeforeFirst.loc.start.line, column: tokenBeforeFirst.loc.start.column }, fix(fixer) { - return fixer.insertTextAfter(openBrace, "\n"); + return fixer.insertTextAfter(tokenBeforeFirst, "\n"); }, message: ALWAYS_MESSAGE }); @@ -173,36 +184,34 @@ module.exports = { if (!blockHasBottomPadding) { context.report({ node, - loc: { line: closeBrace.loc.end.line, column: closeBrace.loc.end.column - 1 }, + loc: { line: tokenAfterLast.loc.end.line, column: tokenAfterLast.loc.end.column - 1 }, fix(fixer) { - return fixer.insertTextBefore(closeBrace, "\n"); + return fixer.insertTextBefore(tokenAfterLast, "\n"); }, message: ALWAYS_MESSAGE }); } } else { if (blockHasTopPadding) { - const nextToken = sourceCode.getTokenOrCommentAfter(openBrace); context.report({ node, - loc: { line: openBrace.loc.start.line, column: openBrace.loc.start.column }, + loc: { line: tokenBeforeFirst.loc.start.line, column: tokenBeforeFirst.loc.start.column }, fix(fixer) { - return fixer.replaceTextRange([openBrace.end, nextToken.start - nextToken.loc.start.column], "\n"); + return fixer.replaceTextRange([tokenBeforeFirst.end, firstBlockToken.start - firstBlockToken.loc.start.column], "\n"); }, message: NEVER_MESSAGE }); } if (blockHasBottomPadding) { - const previousToken = sourceCode.getTokenOrCommentBefore(closeBrace); context.report({ node, - loc: { line: closeBrace.loc.end.line, column: closeBrace.loc.end.column - 1 }, + loc: { line: tokenAfterLast.loc.end.line, column: tokenAfterLast.loc.end.column - 1 }, message: NEVER_MESSAGE, fix(fixer) { - return fixer.replaceTextRange([previousToken.end, closeBrace.start - closeBrace.loc.start.column], "\n"); + return fixer.replaceTextRange([lastBlockToken.end, tokenAfterLast.start - tokenAfterLast.loc.start.column], "\n"); } }); } diff --git a/tools/eslint/lib/rules/prefer-const.js b/tools/eslint/lib/rules/prefer-const.js index 07d8da82a105c4..53bdc2ab7b0582 100644 --- a/tools/eslint/lib/rules/prefer-const.js +++ b/tools/eslint/lib/rules/prefer-const.js @@ -9,7 +9,7 @@ // Helpers //------------------------------------------------------------------------------ -const PATTERN_TYPE = /^(?:.+?Pattern|RestElement|Property)$/; +const PATTERN_TYPE = /^(?:.+?Pattern|RestElement|SpreadProperty|ExperimentalRestProperty|Property)$/; const DECLARATION_HOST_TYPE = /^(?:Program|BlockStatement|SwitchCase)$/; const DESTRUCTURING_HOST_TYPE = /^(?:VariableDeclarator|AssignmentExpression)$/; diff --git a/tools/eslint/lib/rules/prefer-destructuring.js b/tools/eslint/lib/rules/prefer-destructuring.js index c3fbcaa6310fc8..d7fbc3559d7162 100644 --- a/tools/eslint/lib/rules/prefer-destructuring.js +++ b/tools/eslint/lib/rules/prefer-destructuring.js @@ -89,7 +89,7 @@ module.exports = { * @returns {void} */ function report(reportNode, type) { - context.report({ node: reportNode, message: `Use ${type} destructuring` }); + context.report({ node: reportNode, message: "Use {{type}} destructuring.", data: { type } }); } /** @@ -158,7 +158,9 @@ module.exports = { * @returns {void} */ function checkAssigmentExpression(node) { - performCheck(node.left, node.right, node); + if (node.operator === "=") { + performCheck(node.left, node.right, node); + } } //-------------------------------------------------------------------------- diff --git a/tools/eslint/lib/rules/prefer-promise-reject-errors.js b/tools/eslint/lib/rules/prefer-promise-reject-errors.js new file mode 100644 index 00000000000000..97223a65a822ba --- /dev/null +++ b/tools/eslint/lib/rules/prefer-promise-reject-errors.js @@ -0,0 +1,124 @@ +/** + * @fileoverview restrict values that can be used as Promise rejection reasons + * @author Teddy Katz + */ +"use strict"; + +const astUtils = require("../ast-utils"); + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = { + meta: { + docs: { + description: "require using Error objects as Promise rejection reasons", + category: "Best Practices", + recommended: false + }, + fixable: null, + schema: [ + { + type: "object", + properties: { + allowEmptyReject: { type: "boolean" } + }, + additionalProperties: false + } + ] + }, + + create(context) { + + const ALLOW_EMPTY_REJECT = context.options.length && context.options[0].allowEmptyReject; + + //---------------------------------------------------------------------- + // Helpers + //---------------------------------------------------------------------- + + /** + * Checks the argument of a reject() or Promise.reject() CallExpression, and reports it if it can't be an Error + * @param {ASTNode} callExpression A CallExpression node which is used to reject a Promise + * @returns {void} + */ + function checkRejectCall(callExpression) { + if (!callExpression.arguments.length && ALLOW_EMPTY_REJECT) { + return; + } + if ( + !callExpression.arguments.length || + !astUtils.couldBeError(callExpression.arguments[0]) || + callExpression.arguments[0].type === "Identifier" && callExpression.arguments[0].name === "undefined" + ) { + context.report({ + node: callExpression, + message: "Expected the Promise rejection reason to be an Error." + }); + } + } + + /** + * Determines whether a function call is a Promise.reject() call + * @param {ASTNode} node A CallExpression node + * @returns {boolean} `true` if the call is a Promise.reject() call + */ + function isPromiseRejectCall(node) { + return node.callee.type === "MemberExpression" && + node.callee.object.type === "Identifier" && node.callee.object.name === "Promise" && + node.callee.property.type === "Identifier" && node.callee.property.name === "reject"; + } + + //---------------------------------------------------------------------- + // Public + //---------------------------------------------------------------------- + + return { + + // Check `Promise.reject(value)` calls. + CallExpression(node) { + if (isPromiseRejectCall(node)) { + checkRejectCall(node); + } + }, + + /* + * Check for `new Promise((resolve, reject) => {})`, and check for reject() calls. + * This function is run on "NewExpression:exit" instead of "NewExpression" to ensure that + * the nodes in the expression already have the `parent` property. + */ + "NewExpression:exit"(node) { + if ( + node.callee.type === "Identifier" && node.callee.name === "Promise" && + node.arguments.length && astUtils.isFunction(node.arguments[0]) && + node.arguments[0].params.length > 1 && node.arguments[0].params[1].type === "Identifier" + ) { + context.getDeclaredVariables(node.arguments[0]) + + /* + * Find the first variable that matches the second parameter's name. + * If the first parameter has the same name as the second parameter, then the variable will actually + * be "declared" when the first parameter is evaluated, but then it will be immediately overwritten + * by the second parameter. It's not possible for an expression with the variable to be evaluated before + * the variable is overwritten, because functions with duplicate parameters cannot have destructuring or + * default assignments in their parameter lists. Therefore, it's not necessary to explicitly account for + * this case. + */ + .find(variable => variable.name === node.arguments[0].params[1].name) + + // Get the references to that variable. + .references + + // Only check the references that read the parameter's value. + .filter(ref => ref.isRead()) + + // Only check the references that are used as the callee in a function call, e.g. `reject(foo)`. + .filter(ref => ref.identifier.parent.type === "CallExpression" && ref.identifier === ref.identifier.parent.callee) + + // Check the argument of the function call to determine whether it's an Error. + .forEach(ref => checkRejectCall(ref.identifier.parent)); + } + } + }; + } +}; diff --git a/tools/eslint/lib/rules/prefer-spread.js b/tools/eslint/lib/rules/prefer-spread.js index 158d6777f9cf75..1f578582843030 100644 --- a/tools/eslint/lib/rules/prefer-spread.js +++ b/tools/eslint/lib/rules/prefer-spread.js @@ -108,7 +108,7 @@ module.exports = { return null; } - const propertyDot = sourceCode.getTokensBetween(applied, node.callee.property).find(token => token.value === "."); + const propertyDot = sourceCode.getFirstTokenBetween(applied, node.callee.property, token => token.value === "."); return fixer.replaceTextRange([propertyDot.range[0], node.range[1]], `(...${sourceCode.getText(node.arguments[1])})`); } diff --git a/tools/eslint/lib/rules/prefer-template.js b/tools/eslint/lib/rules/prefer-template.js index 28e69cd3c505af..eb3754529a20c2 100644 --- a/tools/eslint/lib/rules/prefer-template.js +++ b/tools/eslint/lib/rules/prefer-template.js @@ -157,7 +157,7 @@ module.exports = { } if (isConcatenation(currentNode) && hasStringLiteral(currentNode) && hasNonStringLiteral(currentNode)) { - const plusSign = sourceCode.getTokensBetween(currentNode.left, currentNode.right).find(token => token.value === "+"); + const plusSign = sourceCode.getFirstTokenBetween(currentNode.left, currentNode.right, token => token.value === "+"); const textBeforePlus = getTextBetween(currentNode.left, plusSign); const textAfterPlus = getTextBetween(plusSign, currentNode.right); const leftEndsWithCurly = endsWithTemplateCurly(currentNode.left); diff --git a/tools/eslint/lib/rules/quotes.js b/tools/eslint/lib/rules/quotes.js index 5c53c76908c3df..b1117b85fba670 100644 --- a/tools/eslint/lib/rules/quotes.js +++ b/tools/eslint/lib/rules/quotes.js @@ -33,6 +33,9 @@ const QUOTE_SETTINGS = { } }; +// An unescaped newline is a newline preceded by an even number of backslashes. +const UNESCAPED_LINEBREAK_PATTERN = new RegExp(String.raw`(^|[^\\])(\\\\)*[${Array.from(astUtils.LINEBREAKS).join("")}]`); + /** * Switches quoting of javascript string between ' " and ` * escaping and unescaping as necessary. @@ -206,6 +209,7 @@ module.exports = { // LiteralPropertyName. case "Property": + case "MethodDefinition": return parent.key === node && !parent.computed; // ModuleSpecifier. @@ -254,22 +258,23 @@ module.exports = { TemplateLiteral(node) { // If backticks are expected or it's a tagged template, then this shouldn't throw an errors - if (allowTemplateLiterals || quoteOption === "backtick" || node.parent.type === "TaggedTemplateExpression") { + if ( + allowTemplateLiterals || + quoteOption === "backtick" || + node.parent.type === "TaggedTemplateExpression" && node === node.parent.quasi + ) { return; } - /* - * A warning should be produced if the template literal only has one TemplateElement, and has no unescaped newlines. - * An unescaped newline is a newline preceded by an even number of backslashes. - */ - const shouldWarn = node.quasis.length === 1 && !/(^|[^\\])(\\\\)*[\r\n\u2028\u2029]/.test(node.quasis[0].value.raw); + // A warning should be produced if the template literal only has one TemplateElement, and has no unescaped newlines. + const shouldWarn = node.quasis.length === 1 && !UNESCAPED_LINEBREAK_PATTERN.test(node.quasis[0].value.raw); if (shouldWarn) { context.report({ node, message: "Strings must use {{description}}.", data: { - description: settings.description, + description: settings.description }, fix(fixer) { if (isPartOfDirectivePrologue(node)) { diff --git a/tools/eslint/lib/rules/require-await.js b/tools/eslint/lib/rules/require-await.js index 89b24f75b0f951..a5698ae058bdf0 100644 --- a/tools/eslint/lib/rules/require-await.js +++ b/tools/eslint/lib/rules/require-await.js @@ -51,7 +51,7 @@ module.exports = { function enterFunction() { scopeInfo = { upper: scopeInfo, - hasAwait: false, + hasAwait: false }; } diff --git a/tools/eslint/lib/rules/semi-spacing.js b/tools/eslint/lib/rules/semi-spacing.js index 4fe95fbf20cebd..fd300e4a37a782 100644 --- a/tools/eslint/lib/rules/semi-spacing.js +++ b/tools/eslint/lib/rules/semi-spacing.js @@ -105,20 +105,7 @@ module.exports = { function isBeforeClosingParen(token) { const nextToken = sourceCode.getTokenAfter(token); - return ( - nextToken && - nextToken.type === "Punctuator" && - (nextToken.value === "}" || nextToken.value === ")") - ); - } - - /** - * Checks if the given token is a semicolon. - * @param {Token} token The token to check. - * @returns {boolean} Whether or not the given token is a semicolon. - */ - function isSemicolon(token) { - return token.type === "Punctuator" && token.value === ";"; + return (nextToken && astUtils.isClosingBraceToken(nextToken) || astUtils.isClosingParenToken(nextToken)); } /** @@ -128,7 +115,7 @@ module.exports = { * @returns {void} */ function checkSemicolonSpacing(token, node) { - if (isSemicolon(token)) { + if (astUtils.isSemicolonToken(token)) { const location = token.loc.start; if (hasLeadingSpace(token)) { @@ -206,6 +193,10 @@ module.exports = { DebuggerStatement: checkNode, ReturnStatement: checkNode, ThrowStatement: checkNode, + ImportDeclaration: checkNode, + ExportNamedDeclaration: checkNode, + ExportAllDeclaration: checkNode, + ExportDefaultDeclaration: checkNode, ForStatement(node) { if (node.init) { checkSemicolonSpacing(sourceCode.getTokenAfter(node.init), node); diff --git a/tools/eslint/lib/rules/semi.js b/tools/eslint/lib/rules/semi.js index ee37ab018c82fd..0bfdff110f2437 100644 --- a/tools/eslint/lib/rules/semi.js +++ b/tools/eslint/lib/rules/semi.js @@ -4,6 +4,13 @@ */ "use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const FixTracker = require("../util/fix-tracker"); +const astUtils = require("../ast-utils"); + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -85,7 +92,13 @@ module.exports = { message = "Extra semicolon."; loc = loc.start; fix = function(fixer) { - return fixer.remove(lastToken); + + // Expand the replacement range to include the surrounding + // tokens to avoid conflicting with no-extra-semi. + // https://github.com/eslint/eslint/issues/7928 + return new FixTracker(fixer, sourceCode) + .retainSurroundingTokens(lastToken) + .remove(lastToken); }; } @@ -98,15 +111,6 @@ module.exports = { } - /** - * Checks whether a token is a semicolon punctuator. - * @param {Token} token The token. - * @returns {boolean} True if token is a semicolon punctuator. - */ - function isSemicolon(token) { - return (token.type === "Punctuator" && token.value === ";"); - } - /** * Check if a semicolon is unnecessary, only true if: * - next token is on a new line and is not one of the opt-out tokens @@ -115,7 +119,7 @@ module.exports = { * @returns {boolean} whether the semicolon is unnecessary. */ function isUnnecessarySemicolon(lastToken) { - if (!isSemicolon(lastToken)) { + if (!astUtils.isSemicolonToken(lastToken)) { return false; } @@ -128,7 +132,7 @@ module.exports = { const lastTokenLine = lastToken.loc.end.line; const nextTokenLine = nextToken.loc.start.line; const isOptOutToken = OPT_OUT_PATTERN.test(nextToken.value) && nextToken.value !== "++" && nextToken.value !== "--"; - const isDivider = (nextToken.value === "}" || nextToken.value === ";"); + const isDivider = (astUtils.isClosingBraceToken(nextToken) || astUtils.isSemicolonToken(nextToken)); return (lastTokenLine !== nextTokenLine && !isOptOutToken) || isDivider; } @@ -164,7 +168,7 @@ module.exports = { report(node, true); } } else { - if (!isSemicolon(lastToken)) { + if (!astUtils.isSemicolonToken(lastToken)) { if (!exceptOneLine || !isOneLinerBlock(node)) { report(node); } diff --git a/tools/eslint/lib/rules/sort-imports.js b/tools/eslint/lib/rules/sort-imports.js index 83f500990239b2..2b382545efb3f7 100644 --- a/tools/eslint/lib/rules/sort-imports.js +++ b/tools/eslint/lib/rules/sort-imports.js @@ -71,9 +71,9 @@ module.exports = { return "all"; } else if (node.specifiers.length === 1) { return "single"; - } else { - return "multiple"; } + return "multiple"; + } /** @@ -93,9 +93,9 @@ module.exports = { function getFirstLocalMemberName(node) { if (node.specifiers[0]) { return node.specifiers[0].local.name; - } else { - return null; } + return null; + } return { diff --git a/tools/eslint/lib/rules/sort-keys.js b/tools/eslint/lib/rules/sort-keys.js index e42375d6bcc59f..8821f629433d48 100644 --- a/tools/eslint/lib/rules/sort-keys.js +++ b/tools/eslint/lib/rules/sort-keys.js @@ -64,7 +64,7 @@ const isValidOrders = { }, descIN(a, b) { return isValidOrders.ascIN(b, a); - }, + } }; //------------------------------------------------------------------------------ @@ -147,7 +147,7 @@ module.exports = { prevName, order, insensitive: insensitive ? "insensitive " : "", - natual: natual ? "natural " : "", + natual: natual ? "natural " : "" } }); } diff --git a/tools/eslint/lib/rules/sort-vars.js b/tools/eslint/lib/rules/sort-vars.js index e18cc320ef0553..1fdfc9ace68424 100644 --- a/tools/eslint/lib/rules/sort-vars.js +++ b/tools/eslint/lib/rules/sort-vars.js @@ -37,11 +37,9 @@ module.exports = { return { VariableDeclaration(node) { - node.declarations.reduce((memo, decl) => { - if (decl.id.type === "ObjectPattern" || decl.id.type === "ArrayPattern") { - return memo; - } + const idDeclarations = node.declarations.filter(decl => decl.id.type === "Identifier"); + idDeclarations.slice(1).reduce((memo, decl) => { let lastVariableName = memo.id.name, currenVariableName = decl.id.name; @@ -53,10 +51,10 @@ module.exports = { if (currenVariableName < lastVariableName) { context.report({ node: decl, message: "Variables within the same declaration block should be sorted alphabetically." }); return memo; - } else { - return decl; } - }, node.declarations[0]); + return decl; + + }, idDeclarations[0]); } }; } diff --git a/tools/eslint/lib/rules/space-before-function-paren.js b/tools/eslint/lib/rules/space-before-function-paren.js index c62413a37cd829..53aac71ed6e162 100644 --- a/tools/eslint/lib/rules/space-before-function-paren.js +++ b/tools/eslint/lib/rules/space-before-function-paren.js @@ -4,6 +4,12 @@ */ "use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("../ast-utils"); + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -45,31 +51,9 @@ module.exports = { }, create(context) { - - const configuration = context.options[0], - sourceCode = context.getSourceCode(); - let requireAnonymousFunctionSpacing = true, - forbidAnonymousFunctionSpacing = false, - requireNamedFunctionSpacing = true, - forbidNamedFunctionSpacing = false, - requireArrowFunctionSpacing = false, - forbidArrowFunctionSpacing = false; - - if (typeof configuration === "object") { - requireAnonymousFunctionSpacing = ( - !configuration.anonymous || configuration.anonymous === "always"); - forbidAnonymousFunctionSpacing = configuration.anonymous === "never"; - requireNamedFunctionSpacing = ( - !configuration.named || configuration.named === "always"); - forbidNamedFunctionSpacing = configuration.named === "never"; - requireArrowFunctionSpacing = configuration.asyncArrow === "always"; - forbidArrowFunctionSpacing = configuration.asyncArrow === "never"; - } else if (configuration === "never") { - requireAnonymousFunctionSpacing = false; - forbidAnonymousFunctionSpacing = true; - requireNamedFunctionSpacing = false; - forbidNamedFunctionSpacing = true; - } + const sourceCode = context.getSourceCode(); + const baseConfig = typeof context.options[0] === "string" ? context.options[0] : "always"; + const overrideConfig = typeof context.options[0] === "object" ? context.options[0] : {}; /** * Determines whether a function has a name. @@ -94,72 +78,67 @@ module.exports = { } /** - * Validates the spacing before function parentheses. - * @param {ASTNode} node The node to be validated. - * @returns {void} + * Gets the config for a given function + * @param {ASTNode} node The function node + * @returns {string} "always", "never", or "ignore" */ - function validateSpacingBeforeParentheses(node) { - const isArrow = node.type === "ArrowFunctionExpression"; - const isNamed = !isArrow && isNamedFunction(node); - const isAnonymousGenerator = node.generator && !isNamed; - const isNormalArrow = isArrow && !node.async; - const isArrowWithoutParens = isArrow && sourceCode.getFirstToken(node, 1).value !== "("; - let forbidSpacing, requireSpacing, rightToken; - - // isAnonymousGenerator → `generator-star-spacing` should warn it. E.g. `function* () {}` - // isNormalArrow → ignore always. - // isArrowWithoutParens → ignore always. E.g. `async a => a` - if (isAnonymousGenerator || isNormalArrow || isArrowWithoutParens) { - return; - } + function getConfigForFunction(node) { + if (node.type === "ArrowFunctionExpression") { + + // 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"; + } + } else if (isNamedFunction(node)) { + return overrideConfig.named || baseConfig; - if (isArrow) { - forbidSpacing = forbidArrowFunctionSpacing; - requireSpacing = requireArrowFunctionSpacing; - } else if (isNamed) { - forbidSpacing = forbidNamedFunctionSpacing; - requireSpacing = requireNamedFunctionSpacing; - } else { - forbidSpacing = forbidAnonymousFunctionSpacing; - requireSpacing = requireAnonymousFunctionSpacing; + // `generator-star-spacing` should warn anonymous generators. E.g. `function* () {}` + } else if (!node.generator) { + return overrideConfig.anonymous || baseConfig; } - rightToken = sourceCode.getFirstToken(node); - while (rightToken.value !== "(") { - rightToken = sourceCode.getTokenAfter(rightToken); + return "ignore"; + } + + /** + * Checks the parens of a function node + * @param {ASTNode} node A function node + * @returns {void} + */ + function checkFunction(node) { + const functionConfig = getConfigForFunction(node); + + if (functionConfig === "ignore") { + return; } + + const rightToken = sourceCode.getFirstToken(node, astUtils.isOpeningParenToken); const leftToken = sourceCode.getTokenBefore(rightToken); - const location = leftToken.loc.end; - - if (sourceCode.isSpaceBetweenTokens(leftToken, rightToken)) { - if (forbidSpacing) { - context.report({ - node, - loc: location, - message: "Unexpected space before function parentheses.", - fix(fixer) { - return fixer.removeRange([leftToken.range[1], rightToken.range[0]]); - } - }); - } - } else { - if (requireSpacing) { - context.report({ - node, - loc: location, - message: "Missing space before function parentheses.", - fix(fixer) { - return fixer.insertTextAfter(leftToken, " "); - } - }); - } + const hasSpacing = sourceCode.isSpaceBetweenTokens(leftToken, rightToken); + + if (hasSpacing && functionConfig === "never") { + context.report({ + node, + loc: leftToken.loc.end, + message: "Unexpected space before function parentheses.", + fix: fixer => fixer.removeRange([leftToken.range[1], rightToken.range[0]]) + }); + } else if (!hasSpacing && functionConfig === "always") { + context.report({ + node, + loc: leftToken.loc.end, + message: "Missing space before function parentheses.", + fix: fixer => fixer.insertTextAfter(leftToken, " ") + }); } } return { - FunctionDeclaration: validateSpacingBeforeParentheses, - FunctionExpression: validateSpacingBeforeParentheses, - ArrowFunctionExpression: validateSpacingBeforeParentheses, + ArrowFunctionExpression: checkFunction, + FunctionDeclaration: checkFunction, + FunctionExpression: checkFunction }; } }; diff --git a/tools/eslint/lib/rules/space-in-parens.js b/tools/eslint/lib/rules/space-in-parens.js index af838dfa9e8376..95b03c3db50487 100644 --- a/tools/eslint/lib/rules/space-in-parens.js +++ b/tools/eslint/lib/rules/space-in-parens.js @@ -128,13 +128,13 @@ module.exports = { } if (ALWAYS) { - if (right.type === "Punctuator" && right.value === ")") { + if (astUtils.isClosingParenToken(right)) { return false; } return !isOpenerException(right); - } else { - return isOpenerException(right); } + return isOpenerException(right); + } /** @@ -144,7 +144,7 @@ module.exports = { * @returns {boolean} True if the paren should have a space */ function shouldCloserHaveSpace(left, right) { - if (left.type === "Punctuator" && left.value === "(") { + if (astUtils.isOpeningParenToken(left)) { return false; } @@ -154,9 +154,9 @@ module.exports = { if (ALWAYS) { return !isCloserException(left); - } else { - return isCloserException(left); } + return isCloserException(left); + } /** @@ -180,9 +180,9 @@ module.exports = { if (ALWAYS) { return isOpenerException(right); - } else { - return !isOpenerException(right); } + return !isOpenerException(right); + } /** @@ -192,7 +192,7 @@ module.exports = { * @returns {boolean} True if the paren should reject the space */ function shouldCloserRejectSpace(left, right) { - if (left.type === "Punctuator" && left.value === "(") { + if (astUtils.isOpeningParenToken(left)) { return false; } @@ -206,9 +206,9 @@ module.exports = { if (ALWAYS) { return isCloserException(left); - } else { - return !isCloserException(left); } + return !isCloserException(left); + } //-------------------------------------------------------------------------- @@ -224,11 +224,7 @@ module.exports = { const prevToken = tokens[i - 1]; const nextToken = tokens[i + 1]; - if (token.type !== "Punctuator") { - return; - } - - if (token.value !== "(" && token.value !== ")") { + if (!astUtils.isOpeningParenToken(token) && !astUtils.isClosingParenToken(token)) { return; } diff --git a/tools/eslint/lib/rules/space-unary-ops.js b/tools/eslint/lib/rules/space-unary-ops.js index 11c59c8274f358..5b156fac2292d4 100644 --- a/tools/eslint/lib/rules/space-unary-ops.js +++ b/tools/eslint/lib/rules/space-unary-ops.js @@ -68,6 +68,21 @@ 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 @@ -244,7 +259,10 @@ module.exports = { operator: firstToken.value }, fix(fixer) { - return fixer.removeRange([firstToken.range[1], secondToken.range[0]]); + if (canRemoveSpacesBetween(firstToken, secondToken)) { + return fixer.removeRange([firstToken.range[1], secondToken.range[0]]); + } + return null; } }); } diff --git a/tools/eslint/lib/rules/spaced-comment.js b/tools/eslint/lib/rules/spaced-comment.js index 85abd7360e622a..4e418fd19f3a86 100644 --- a/tools/eslint/lib/rules/spaced-comment.js +++ b/tools/eslint/lib/rules/spaced-comment.js @@ -5,6 +5,7 @@ "use strict"; const lodash = require("lodash"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -88,8 +89,7 @@ function createExceptionsPattern(exceptions) { pattern += exceptions.map(escapeAndRepeat).join("|"); pattern += ")"; } - - pattern += "(?:$|[\n\r]))"; + pattern += `(?:$|[${Array.from(astUtils.LINEBREAKS).join("")}]))`; } return pattern; @@ -279,10 +279,10 @@ module.exports = { end += match[0].length; } return fixer.insertTextAfterRange([start, end], " "); - } else { - end += match[0].length; - return fixer.replaceTextRange([start, end], commentIdentifier + (match[1] ? match[1] : "")); } + end += match[0].length; + return fixer.replaceTextRange([start, end], commentIdentifier + (match[1] ? match[1] : "")); + }, message, data: { refChar } @@ -302,12 +302,12 @@ module.exports = { fix(fixer) { if (requireSpace) { return fixer.insertTextAfterRange([node.start, node.end - 2], " "); - } else { - const end = node.end - 2, - start = end - match[0].length; - - return fixer.replaceTextRange([start, end], ""); } + const end = node.end - 2, + start = end - match[0].length; + + return fixer.replaceTextRange([start, end], ""); + }, message }); diff --git a/tools/eslint/lib/rules/strict.js b/tools/eslint/lib/rules/strict.js index 34ed443d92c816..bb926f666141e9 100644 --- a/tools/eslint/lib/rules/strict.js +++ b/tools/eslint/lib/rules/strict.js @@ -9,6 +9,8 @@ // Requirements //------------------------------------------------------------------------------ +const astUtils = require("../ast-utils"); + //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ @@ -23,7 +25,7 @@ const messages = { implied: "'use strict' is unnecessary when implied strict mode is enabled.", unnecessaryInClasses: "'use strict' is unnecessary inside of classes.", nonSimpleParameterList: "'use strict' directive inside a function with non-simple parameter list throws a syntax error since ES2016.", - wrap: "Wrap this function in a function with 'use strict' directive." + wrap: "Wrap {{name}} in a function with 'use strict' directive." }; /** @@ -188,7 +190,11 @@ module.exports = { if (isSimpleParameterList(node.params)) { context.report({ node, message: messages.function }); } else { - context.report({ node, message: messages.wrap }); + context.report({ + node, + message: messages.wrap, + data: { name: astUtils.getFunctionNameWithKind(node) } + }); } } @@ -212,8 +218,8 @@ module.exports = { */ function enterFunction(node) { const isBlock = node.body.type === "BlockStatement", - useStrictDirectives = isBlock ? - getUseStrictDirectives(node.body.body) : []; + useStrictDirectives = isBlock + ? getUseStrictDirectives(node.body.body) : []; if (mode === "function") { enterFunctionInFunctionMode(node, useStrictDirectives); diff --git a/tools/eslint/lib/rules/template-tag-spacing.js b/tools/eslint/lib/rules/template-tag-spacing.js new file mode 100755 index 00000000000000..808fe443891791 --- /dev/null +++ b/tools/eslint/lib/rules/template-tag-spacing.js @@ -0,0 +1,77 @@ +/** + * @fileoverview Rule to check spacing between template tags and their literals + * @author Jonathan Wilsson + */ + +"use strict"; + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = { + meta: { + docs: { + description: "require or disallow spacing between template tags and their literals", + category: "Stylistic Issues", + recommended: false + }, + + fixable: "whitespace", + + schema: [ + { enum: ["always", "never"] } + ] + }, + + create(context) { + const never = context.options[0] !== "always"; + const sourceCode = context.getSourceCode(); + + /** + * Check if a space is present between a template tag and its literal + * @param {ASTNode} node node to evaluate + * @returns {void} + * @private + */ + function checkSpacing(node) { + const tagToken = sourceCode.getTokenBefore(node.quasi); + const literalToken = sourceCode.getFirstToken(node.quasi); + const hasWhitespace = sourceCode.isSpaceBetweenTokens(tagToken, literalToken); + + if (never && hasWhitespace) { + context.report({ + node, + loc: tagToken.loc.start, + message: "Unexpected space between template tag and template literal.", + fix(fixer) { + const comments = sourceCode.getComments(node.quasi).leading; + + // Don't fix anything if there's a single line comment after the template tag + if (comments.some(comment => comment.type === "Line")) { + return null; + } + + return fixer.replaceTextRange( + [tagToken.range[1], literalToken.range[0]], + comments.reduce((text, comment) => text + sourceCode.getText(comment), "") + ); + } + }); + } else if (!never && !hasWhitespace) { + context.report({ + node, + loc: tagToken.loc.start, + message: "Missing space between template tag and template literal.", + fix(fixer) { + return fixer.insertTextAfter(tagToken, " "); + } + }); + } + } + + return { + TaggedTemplateExpression: checkSpacing + }; + } +}; diff --git a/tools/eslint/lib/rules/unicode-bom.js b/tools/eslint/lib/rules/unicode-bom.js index 2f16a258509e8b..7109a49edbb5ed 100644 --- a/tools/eslint/lib/rules/unicode-bom.js +++ b/tools/eslint/lib/rules/unicode-bom.js @@ -45,7 +45,7 @@ module.exports = { loc: location, message: "Expected Unicode BOM (Byte Order Mark).", fix(fixer) { - return fixer.insertTextBefore(node, "\uFEFF"); + return fixer.insertTextBeforeRange([0, 1], "\uFEFF"); } }); } else if (sourceCode.hasBOM && (requireBOM === "never")) { diff --git a/tools/eslint/lib/rules/wrap-iife.js b/tools/eslint/lib/rules/wrap-iife.js index bbbc79ab1fff25..59179eb17ed6a5 100644 --- a/tools/eslint/lib/rules/wrap-iife.js +++ b/tools/eslint/lib/rules/wrap-iife.js @@ -5,6 +5,10 @@ "use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ @@ -51,11 +55,7 @@ module.exports = { * @private */ function wrapped(node) { - const previousToken = sourceCode.getTokenBefore(node), - nextToken = sourceCode.getTokenAfter(node); - - return previousToken && previousToken.value === "(" && - nextToken && nextToken.value === ")"; + return astUtils.isParenthesised(sourceCode, node); } /** diff --git a/tools/eslint/lib/rules/yoda.js b/tools/eslint/lib/rules/yoda.js index ba711c63c2f1ae..bdb7d2a4278ba3 100644 --- a/tools/eslint/lib/rules/yoda.js +++ b/tools/eslint/lib/rules/yoda.js @@ -235,12 +235,7 @@ module.exports = { * paren token. */ function isParenWrapped() { - let tokenBefore, tokenAfter; - - return ((tokenBefore = sourceCode.getTokenBefore(node)) && - tokenBefore.value === "(" && - (tokenAfter = sourceCode.getTokenAfter(node)) && - tokenAfter.value === ")"); + return astUtils.isParenthesised(sourceCode, node); } return (node.type === "LogicalExpression" && @@ -269,11 +264,11 @@ module.exports = { * @returns {string} A string representation of the node with the sides and operator flipped */ function getFlippedString(node) { - const operatorToken = sourceCode.getTokensBetween(node.left, node.right).find(token => token.value === node.operator); + const operatorToken = sourceCode.getFirstTokenBetween(node.left, node.right, token => token.value === node.operator); const textBeforeOperator = sourceCode.getText().slice(sourceCode.getTokenBefore(operatorToken).range[1], operatorToken.range[0]); const textAfterOperator = sourceCode.getText().slice(operatorToken.range[1], sourceCode.getTokenAfter(operatorToken).range[0]); - const leftText = sourceCode.getText().slice(sourceCode.getFirstToken(node).range[0], sourceCode.getTokenBefore(operatorToken).range[1]); - const rightText = sourceCode.getText().slice(sourceCode.getTokenAfter(operatorToken).range[0], sourceCode.getLastToken(node).range[1]); + const leftText = sourceCode.getText().slice(node.range[0], sourceCode.getTokenBefore(operatorToken).range[1]); + const rightText = sourceCode.getText().slice(sourceCode.getTokenAfter(operatorToken).range[0], node.range[1]); return rightText + textBeforeOperator + OPERATOR_FLIP_MAP[operatorToken.value] + textAfterOperator + leftText; } diff --git a/tools/eslint/lib/testers/rule-tester.js b/tools/eslint/lib/testers/rule-tester.js index 5d327ad28b9360..61fbdf597f8730 100644 --- a/tools/eslint/lib/testers/rule-tester.js +++ b/tools/eslint/lib/testers/rule-tester.js @@ -147,6 +147,12 @@ function RuleTester(testerConfig) { lodash.cloneDeep(defaultConfig), testerConfig ); + + /** + * Rule definitions to define before tests. + * @type {Object} + */ + this.rules = {}; } /** @@ -213,7 +219,7 @@ Object.defineProperties(RuleTester, { RuleTester[DESCRIBE] = value; }, configurable: true, - enumerable: true, + enumerable: true }, it: { get() { @@ -226,8 +232,8 @@ Object.defineProperties(RuleTester, { RuleTester[IT] = value; }, configurable: true, - enumerable: true, - }, + enumerable: true + } }); RuleTester.prototype = { @@ -239,7 +245,7 @@ RuleTester.prototype = { * @returns {void} */ defineRule(name, rule) { - eslint.defineRule(name, rule); + this.rules[name] = rule; }, /** @@ -337,12 +343,13 @@ RuleTester.prototype = { * running the rule under test. */ eslint.reset(); + eslint.on("Program", node => { beforeAST = cloneDeeplyExcludesParent(node); + }); - eslint.on("Program:exit", node => { - afterAST = cloneDeeplyExcludesParent(node); - }); + eslint.on("Program:exit", node => { + afterAST = node; }); // Freezes rule-context properties. @@ -361,25 +368,25 @@ RuleTester.prototype = { return rule(context); }; - } else { - return { - meta: rule.meta, - create(context) { - Object.freeze(context); - freezeDeeply(context.options); - freezeDeeply(context.settings); - freezeDeeply(context.parserOptions); - - return rule.create(context); - } - }; } + return { + meta: rule.meta, + create(context) { + Object.freeze(context); + freezeDeeply(context.options); + freezeDeeply(context.settings); + freezeDeeply(context.parserOptions); + + return rule.create(context); + } + }; + }; return { messages: eslint.verify(code, config, filename, true), beforeAST, - afterAST + afterAST: cloneDeeplyExcludesParent(afterAST) }; } finally { rules.get = originalGet; @@ -419,6 +426,28 @@ RuleTester.prototype = { assertASTDidntChange(result.beforeAST, result.afterAST); } + /** + * Asserts that the message matches its expected value. If the expected + * value is a regular expression, it is checked against the actual + * value. + * @param {string} actual Actual value + * @param {string|RegExp} expected Expected value + * @returns {void} + * @private + */ + function assertMessageMatches(actual, expected) { + if (expected instanceof RegExp) { + + // assert.js doesn't have a built-in RegExp match function + assert.ok( + expected.test(actual), + `Expected '${actual}' to match ${expected}` + ); + } else { + assert.equal(actual, expected); + } + } + /** * Check if the template is invalid or not * all invalid cases go through this. @@ -448,10 +477,10 @@ RuleTester.prototype = { assert.ok(!("fatal" in messages[i]), `A fatal parsing error occurred: ${messages[i].message}`); assert.equal(messages[i].ruleId, ruleName, "Error rule name should be the same as the name of the rule being tested"); - if (typeof item.errors[i] === "string") { + if (typeof item.errors[i] === "string" || item.errors[i] instanceof RegExp) { // Just an error message. - assert.equal(messages[i].message, item.errors[i]); + assertMessageMatches(messages[i].message, item.errors[i]); } else if (typeof item.errors[i] === "object") { /* @@ -460,7 +489,7 @@ RuleTester.prototype = { * column. */ if (item.errors[i].message) { - assert.equal(messages[i].message, item.errors[i].message); + assertMessageMatches(messages[i].message, item.errors[i].message); } if (item.errors[i].type) { @@ -484,17 +513,24 @@ RuleTester.prototype = { } } else { - // Only string or object errors are valid. - assert.fail(messages[i], null, "Error should be a string or object."); + // Message was an unexpected type + assert.fail(messages[i], null, "Error should be a string, object, or RegExp."); } } + } - if (item.hasOwnProperty("output")) { + if (item.hasOwnProperty("output")) { + if (item.output === null) { + assert.strictEqual( + messages.filter(message => message.fix).length, + 0, + "Expected no autofixes to be suggested" + ); + } else { const fixResult = SourceCodeFixer.applyFixes(eslint.getSourceCode(), messages); assert.equal(fixResult.output, item.output, "Output is incorrect."); } - } assertASTDidntChange(result.beforeAST, result.afterAST); @@ -507,7 +543,8 @@ RuleTester.prototype = { RuleTester.describe(ruleName, () => { RuleTester.describe("valid", () => { test.valid.forEach(valid => { - RuleTester.it(valid.code || valid, () => { + RuleTester.it(typeof valid === "object" ? valid.code : valid, () => { + eslint.defineRules(this.rules); testValidTemplate(ruleName, valid); }); }); @@ -516,6 +553,7 @@ RuleTester.prototype = { RuleTester.describe("invalid", () => { test.invalid.forEach(invalid => { RuleTester.it(invalid.code, () => { + eslint.defineRules(this.rules); testInvalidTemplate(ruleName, invalid); }); }); diff --git a/tools/eslint/lib/token-store.js b/tools/eslint/lib/token-store.js deleted file mode 100644 index 9cd37cd175bf54..00000000000000 --- a/tools/eslint/lib/token-store.js +++ /dev/null @@ -1,203 +0,0 @@ -/** - * @fileoverview Object to handle access and retrieval of tokens. - * @author Brandon Mills - */ -"use strict"; - -//------------------------------------------------------------------------------ -// Implementation -//------------------------------------------------------------------------------ - -module.exports = function(tokens) { - const api = {}, - starts = Object.create(null), - ends = Object.create(null), - length = tokens.length; - - /** - * Gets tokens in a given interval. - * @param {int} start Inclusive index of the first token. 0 if negative. - * @param {int} end Exclusive index of the last token. - * @returns {Token[]} Tokens in the interval. - */ - function get(start, end) { - const result = []; - - for (let i = Math.max(0, start); i < end && i < length; i++) { - result.push(tokens[i]); - } - - return result; - } - - /** - * Gets the index in the tokens array of the last token belonging to a node. - * Usually a node ends exactly at a token, but due to ASI, sometimes a - * node's range extends beyond its last token. - * @param {ASTNode} node The node for which to find the last token's index. - * @returns {int} Index in the tokens array of the node's last token. - */ - function lastTokenIndex(node) { - const end = node.range[1]; - let cursor = ends[end]; - - // If the node extends beyond its last token, get the token before the - // next token - if (typeof cursor === "undefined") { - cursor = starts[end] - 1; - } - - // If there isn't a next token, the desired token is the last one in the - // array - if (isNaN(cursor)) { - cursor = length - 1; - } - - return cursor; - } - - // Map tokens' start and end range to the index in the tokens array - for (let i = 0; i < length; i++) { - const range = tokens[i].range; - - starts[range[0]] = i; - ends[range[1]] = i; - } - - /** - * Gets a number of tokens that precede a given node or token in the token - * stream. - * @param {(ASTNode|Token)} node The AST node or token. - * @param {int} [beforeCount=0] The number of tokens before the node or - * token to retrieve. - * @returns {Token[]} Array of objects representing tokens. - */ - api.getTokensBefore = function(node, beforeCount) { - const first = starts[node.range[0]]; - - return get(first - (beforeCount || 0), first); - }; - - /** - * Gets the token that precedes a given node or token in the token stream. - * @param {(ASTNode|Token)} node The AST node or token. - * @param {int} [skip=0] A number of tokens to skip before the given node or - * token. - * @returns {Token} An object representing the token. - */ - api.getTokenBefore = function(node, skip) { - return tokens[starts[node.range[0]] - (skip || 0) - 1]; - }; - - /** - * Gets a number of tokens that follow a given node or token in the token - * stream. - * @param {(ASTNode|Token)} node The AST node or token. - * @param {int} [afterCount=0] The number of tokens after the node or token - * to retrieve. - * @returns {Token[]} Array of objects representing tokens. - */ - api.getTokensAfter = function(node, afterCount) { - const start = lastTokenIndex(node) + 1; - - return get(start, start + (afterCount || 0)); - }; - - /** - * Gets the token that follows a given node or token in the token stream. - * @param {(ASTNode|Token)} node The AST node or token. - * @param {int} [skip=0] A number of tokens to skip after the given node or - * token. - * @returns {Token} An object representing the token. - */ - api.getTokenAfter = function(node, skip) { - return tokens[lastTokenIndex(node) + (skip || 0) + 1]; - }; - - /** - * Gets all tokens that are related to the given node. - * @param {ASTNode} node The AST node. - * @param {int} [beforeCount=0] The number of tokens before the node to retrieve. - * @param {int} [afterCount=0] The number of tokens after the node to retrieve. - * @returns {Token[]} Array of objects representing tokens. - */ - api.getTokens = function(node, beforeCount, afterCount) { - return get( - starts[node.range[0]] - (beforeCount || 0), - lastTokenIndex(node) + (afterCount || 0) + 1 - ); - }; - - /** - * Gets the first `count` tokens of the given node's token stream. - * @param {ASTNode} node The AST node. - * @param {int} [count=0] The number of tokens of the node to retrieve. - * @returns {Token[]} Array of objects representing tokens. - */ - api.getFirstTokens = function(node, count) { - const first = starts[node.range[0]]; - - return get( - first, - Math.min(lastTokenIndex(node) + 1, first + (count || 0)) - ); - }; - - /** - * Gets the first token of the given node's token stream. - * @param {ASTNode} node The AST node. - * @param {int} [skip=0] A number of tokens to skip. - * @returns {Token} An object representing the token. - */ - api.getFirstToken = function(node, skip) { - return tokens[starts[node.range[0]] + (skip || 0)]; - }; - - /** - * Gets the last `count` tokens of the given node. - * @param {ASTNode} node The AST node. - * @param {int} [count=0] The number of tokens of the node to retrieve. - * @returns {Token[]} Array of objects representing tokens. - */ - api.getLastTokens = function(node, count) { - const last = lastTokenIndex(node) + 1; - - return get(Math.max(starts[node.range[0]], last - (count || 0)), last); - }; - - /** - * Gets the last token of the given node's token stream. - * @param {ASTNode} node The AST node. - * @param {int} [skip=0] A number of tokens to skip. - * @returns {Token} An object representing the token. - */ - api.getLastToken = function(node, skip) { - return tokens[lastTokenIndex(node) - (skip || 0)]; - }; - - /** - * Gets all of the tokens between two non-overlapping nodes. - * @param {ASTNode} left Node before the desired token range. - * @param {ASTNode} right Node after the desired token range. - * @param {int} [padding=0] Number of extra tokens on either side of center. - * @returns {Token[]} Tokens between left and right plus padding. - */ - api.getTokensBetween = function(left, right, padding) { - padding = padding || 0; - return get( - lastTokenIndex(left) + 1 - padding, - starts[right.range[0]] + padding - ); - }; - - /** - * Gets the token starting at the specified index. - * @param {int} startIndex Index of the start of the token's range. - * @returns {Token} The token starting at index, or null if no such token. - */ - api.getTokenByRangeStart = function(startIndex) { - return (tokens[starts[startIndex]] || null); - }; - - return api; -}; diff --git a/tools/eslint/lib/token-store/backward-token-comment-cursor.js b/tools/eslint/lib/token-store/backward-token-comment-cursor.js new file mode 100644 index 00000000000000..7c2137a176ff21 --- /dev/null +++ b/tools/eslint/lib/token-store/backward-token-comment-cursor.js @@ -0,0 +1,57 @@ +/** + * @fileoverview Define the cursor which iterates tokens and comments in reverse. + * @author Toru Nagashima + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const Cursor = require("./cursor"); +const utils = require("./utils"); + +//------------------------------------------------------------------------------ +// Exports +//------------------------------------------------------------------------------ + +/** + * The cursor which iterates tokens and comments in reverse. + */ +module.exports = class BackwardTokenCommentCursor extends Cursor { + + /** + * Initializes this cursor. + * @param {Token[]} tokens - The array of tokens. + * @param {Comment[]} comments - The array of comments. + * @param {Object} indexMap - The map from locations to indices in `tokens`. + * @param {number} startLoc - The start location of the iteration range. + * @param {number} endLoc - The end location of the iteration range. + */ + constructor(tokens, comments, indexMap, startLoc, endLoc) { + super(); + this.tokens = tokens; + this.comments = comments; + this.tokenIndex = utils.getLastIndex(tokens, indexMap, endLoc); + this.commentIndex = utils.search(comments, endLoc) - 1; + this.border = startLoc; + } + + /** @inheritdoc */ + moveNext() { + const token = (this.tokenIndex >= 0) ? this.tokens[this.tokenIndex] : null; + const comment = (this.commentIndex >= 0) ? this.comments[this.commentIndex] : null; + + if (token && (!comment || token.range[1] > comment.range[1])) { + this.current = token; + this.tokenIndex -= 1; + } else if (comment) { + this.current = comment; + this.commentIndex -= 1; + } else { + this.current = null; + } + + return Boolean(this.current) && (this.border === -1 || this.current.range[0] >= this.border); + } +}; diff --git a/tools/eslint/lib/token-store/backward-token-cursor.js b/tools/eslint/lib/token-store/backward-token-cursor.js new file mode 100644 index 00000000000000..caa117faeac286 --- /dev/null +++ b/tools/eslint/lib/token-store/backward-token-cursor.js @@ -0,0 +1,56 @@ +/** + * @fileoverview Define the cursor which iterates tokens only in reverse. + * @author Toru Nagashima + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const Cursor = require("./cursor"); +const utils = require("./utils"); + +//------------------------------------------------------------------------------ +// Exports +//------------------------------------------------------------------------------ + +/** + * The cursor which iterates tokens only in reverse. + */ +module.exports = class BackwardTokenCursor extends Cursor { + + /** + * Initializes this cursor. + * @param {Token[]} tokens - The array of tokens. + * @param {Comment[]} comments - The array of comments. + * @param {Object} indexMap - The map from locations to indices in `tokens`. + * @param {number} startLoc - The start location of the iteration range. + * @param {number} endLoc - The end location of the iteration range. + */ + constructor(tokens, comments, indexMap, startLoc, endLoc) { + super(); + this.tokens = tokens; + this.index = utils.getLastIndex(tokens, indexMap, endLoc); + this.indexEnd = utils.getFirstIndex(tokens, indexMap, startLoc); + } + + /** @inheritdoc */ + moveNext() { + if (this.index >= this.indexEnd) { + this.current = this.tokens[this.index]; + this.index -= 1; + return true; + } + return false; + } + + // + // Shorthand for performance. + // + + /** @inheritdoc */ + getOneToken() { + return (this.index >= this.indexEnd) ? this.tokens[this.index] : null; + } +}; diff --git a/tools/eslint/lib/token-store/cursor.js b/tools/eslint/lib/token-store/cursor.js new file mode 100644 index 00000000000000..4e1595c6dcb8a3 --- /dev/null +++ b/tools/eslint/lib/token-store/cursor.js @@ -0,0 +1,76 @@ +/** + * @fileoverview Define the abstract class about cursors which iterate tokens. + * @author Toru Nagashima + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Exports +//------------------------------------------------------------------------------ + +/** + * The abstract class about cursors which iterate tokens. + * + * This class has 2 abstract methods. + * + * - `current: Token | Comment | null` ... The current token. + * - `moveNext(): boolean` ... Moves this cursor to the next token. If the next token didn't exist, it returns `false`. + * + * This is similar to ES2015 Iterators. + * However, Iterators were slow (at 2017-01), so I created this class as similar to C# IEnumerable. + * + * There are the following known sub classes. + * + * - ForwardTokenCursor .......... The cursor which iterates tokens only. + * - BackwardTokenCursor ......... The cursor which iterates tokens only in reverse. + * - ForwardTokenCommentCursor ... The cursor which iterates tokens and comments. + * - BackwardTokenCommentCursor .. The cursor which iterates tokens and comments in reverse. + * - DecorativeCursor + * - FilterCursor ............ The cursor which ignores the specified tokens. + * - SkipCursor .............. The cursor which ignores the first few tokens. + * - LimitCursor ............. The cursor which limits the count of tokens. + * + */ +module.exports = class Cursor { + + /** + * Initializes this cursor. + */ + constructor() { + this.current = null; + } + + /** + * Gets the first token. + * This consumes this cursor. + * @returns {Token|Comment} The first token or null. + */ + getOneToken() { + return this.moveNext() ? this.current : null; + } + + /** + * Gets the first tokens. + * This consumes this cursor. + * @returns {(Token|Comment)[]} All tokens. + */ + getAllTokens() { + const tokens = []; + + while (this.moveNext()) { + tokens.push(this.current); + } + + return tokens; + } + + /** + * Moves this cursor to the next token. + * @returns {boolean} `true` if the next token exists. + * @abstract + */ + /* istanbul ignore next */ + moveNext() { // eslint-disable-line class-methods-use-this + throw new Error("Not implemented."); + } +}; diff --git a/tools/eslint/lib/token-store/cursors.js b/tools/eslint/lib/token-store/cursors.js new file mode 100644 index 00000000000000..b315c7e65e1a7c --- /dev/null +++ b/tools/eslint/lib/token-store/cursors.js @@ -0,0 +1,92 @@ +/** + * @fileoverview Define 2 token factories; forward and backward. + * @author Toru Nagashima + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const BackwardTokenCommentCursor = require("./backward-token-comment-cursor"); +const BackwardTokenCursor = require("./backward-token-cursor"); +const FilterCursor = require("./filter-cursor"); +const ForwardTokenCommentCursor = require("./forward-token-comment-cursor"); +const ForwardTokenCursor = require("./forward-token-cursor"); +const LimitCursor = require("./limit-cursor"); +const SkipCursor = require("./skip-cursor"); + +//------------------------------------------------------------------------------ +// Helpers +//------------------------------------------------------------------------------ + +/** + * The cursor factory. + * @private + */ +class CursorFactory { + + /** + * Initializes this cursor. + * @param {Function} TokenCursor - The class of the cursor which iterates tokens only. + * @param {Function} TokenCommentCursor - The class of the cursor which iterates the mix of tokens and comments. + */ + constructor(TokenCursor, TokenCommentCursor) { + this.TokenCursor = TokenCursor; + this.TokenCommentCursor = TokenCommentCursor; + } + + /** + * Creates a base cursor instance that can be decorated by createCursor. + * + * @param {Token[]} tokens - The array of tokens. + * @param {Comment[]} comments - The array of comments. + * @param {Object} indexMap - The map from locations to indices in `tokens`. + * @param {number} startLoc - The start location of the iteration range. + * @param {number} endLoc - The end location of the iteration range. + * @param {boolean} includeComments - The flag to iterate comments as well. + * @returns {Cursor} The created base cursor. + */ + createBaseCursor(tokens, comments, indexMap, startLoc, endLoc, includeComments) { + const Cursor = includeComments ? this.TokenCommentCursor : this.TokenCursor; + + return new Cursor(tokens, comments, indexMap, startLoc, endLoc); + } + + /** + * Creates a cursor that iterates tokens with normalized options. + * + * @param {Token[]} tokens - The array of tokens. + * @param {Comment[]} comments - The array of comments. + * @param {Object} indexMap - The map from locations to indices in `tokens`. + * @param {number} startLoc - The start location of the iteration range. + * @param {number} endLoc - The end location of the iteration range. + * @param {boolean} includeComments - The flag to iterate comments as well. + * @param {Function|null} filter - The predicate function to choose tokens. + * @param {number} skip - The count of tokens the cursor skips. + * @param {number} count - The maximum count of tokens the cursor iterates. Zero is no iteration for backward compatibility. + * @returns {Cursor} The created cursor. + */ + createCursor(tokens, comments, indexMap, startLoc, endLoc, includeComments, filter, skip, count) { + let cursor = this.createBaseCursor(tokens, comments, indexMap, startLoc, endLoc, includeComments); + + if (filter) { + cursor = new FilterCursor(cursor, filter); + } + if (skip >= 1) { + cursor = new SkipCursor(cursor, skip); + } + if (count >= 0) { + cursor = new LimitCursor(cursor, count); + } + + return cursor; + } +} + +//------------------------------------------------------------------------------ +// Exports +//------------------------------------------------------------------------------ + +exports.forward = new CursorFactory(ForwardTokenCursor, ForwardTokenCommentCursor); +exports.backward = new CursorFactory(BackwardTokenCursor, BackwardTokenCommentCursor); diff --git a/tools/eslint/lib/token-store/decorative-cursor.js b/tools/eslint/lib/token-store/decorative-cursor.js new file mode 100644 index 00000000000000..f0bff9c51dba76 --- /dev/null +++ b/tools/eslint/lib/token-store/decorative-cursor.js @@ -0,0 +1,39 @@ +/** + * @fileoverview Define the abstract class about cursors which manipulate another cursor. + * @author Toru Nagashima + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const Cursor = require("./cursor"); + +//------------------------------------------------------------------------------ +// Exports +//------------------------------------------------------------------------------ + +/** + * The abstract class about cursors which manipulate another cursor. + */ +module.exports = class DecorativeCursor extends Cursor { + + /** + * Initializes this cursor. + * @param {Cursor} cursor - The cursor to be decorated. + */ + constructor(cursor) { + super(); + this.cursor = cursor; + } + + /** @inheritdoc */ + moveNext() { + const retv = this.cursor.moveNext(); + + this.current = this.cursor.current; + + return retv; + } +}; diff --git a/tools/eslint/lib/token-store/filter-cursor.js b/tools/eslint/lib/token-store/filter-cursor.js new file mode 100644 index 00000000000000..7133627bd395a1 --- /dev/null +++ b/tools/eslint/lib/token-store/filter-cursor.js @@ -0,0 +1,43 @@ +/** + * @fileoverview Define the cursor which ignores specified tokens. + * @author Toru Nagashima + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const DecorativeCursor = require("./decorative-cursor"); + +//------------------------------------------------------------------------------ +// Exports +//------------------------------------------------------------------------------ + +/** + * The decorative cursor which ignores specified tokens. + */ +module.exports = class FilterCursor extends DecorativeCursor { + + /** + * Initializes this cursor. + * @param {Cursor} cursor - The cursor to be decorated. + * @param {Function} predicate - The predicate function to decide tokens this cursor iterates. + */ + constructor(cursor, predicate) { + super(cursor); + this.predicate = predicate; + } + + /** @inheritdoc */ + moveNext() { + const predicate = this.predicate; + + while (super.moveNext()) { + if (predicate(this.current)) { + return true; + } + } + return false; + } +}; diff --git a/tools/eslint/lib/token-store/forward-token-comment-cursor.js b/tools/eslint/lib/token-store/forward-token-comment-cursor.js new file mode 100644 index 00000000000000..be08552970fcd1 --- /dev/null +++ b/tools/eslint/lib/token-store/forward-token-comment-cursor.js @@ -0,0 +1,57 @@ +/** + * @fileoverview Define the cursor which iterates tokens and comments. + * @author Toru Nagashima + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const Cursor = require("./cursor"); +const utils = require("./utils"); + +//------------------------------------------------------------------------------ +// Exports +//------------------------------------------------------------------------------ + +/** + * The cursor which iterates tokens and comments. + */ +module.exports = class ForwardTokenCommentCursor extends Cursor { + + /** + * Initializes this cursor. + * @param {Token[]} tokens - The array of tokens. + * @param {Comment[]} comments - The array of comments. + * @param {Object} indexMap - The map from locations to indices in `tokens`. + * @param {number} startLoc - The start location of the iteration range. + * @param {number} endLoc - The end location of the iteration range. + */ + constructor(tokens, comments, indexMap, startLoc, endLoc) { + super(); + this.tokens = tokens; + this.comments = comments; + this.tokenIndex = utils.getFirstIndex(tokens, indexMap, startLoc); + this.commentIndex = utils.search(comments, startLoc); + this.border = endLoc; + } + + /** @inheritdoc */ + moveNext() { + const token = (this.tokenIndex < this.tokens.length) ? this.tokens[this.tokenIndex] : null; + const comment = (this.commentIndex < this.comments.length) ? this.comments[this.commentIndex] : null; + + if (token && (!comment || token.range[0] < comment.range[0])) { + this.current = token; + this.tokenIndex += 1; + } else if (comment) { + this.current = comment; + this.commentIndex += 1; + } else { + this.current = null; + } + + return Boolean(this.current) && (this.border === -1 || this.current.range[1] <= this.border); + } +}; diff --git a/tools/eslint/lib/token-store/forward-token-cursor.js b/tools/eslint/lib/token-store/forward-token-cursor.js new file mode 100644 index 00000000000000..5748cb45a62981 --- /dev/null +++ b/tools/eslint/lib/token-store/forward-token-cursor.js @@ -0,0 +1,61 @@ +/** + * @fileoverview Define the cursor which iterates tokens only. + * @author Toru Nagashima + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const Cursor = require("./cursor"); +const utils = require("./utils"); + +//------------------------------------------------------------------------------ +// Exports +//------------------------------------------------------------------------------ + +/** + * The cursor which iterates tokens only. + */ +module.exports = class ForwardTokenCursor extends Cursor { + + /** + * Initializes this cursor. + * @param {Token[]} tokens - The array of tokens. + * @param {Comment[]} comments - The array of comments. + * @param {Object} indexMap - The map from locations to indices in `tokens`. + * @param {number} startLoc - The start location of the iteration range. + * @param {number} endLoc - The end location of the iteration range. + */ + constructor(tokens, comments, indexMap, startLoc, endLoc) { + super(); + this.tokens = tokens; + this.index = utils.getFirstIndex(tokens, indexMap, startLoc); + this.indexEnd = utils.getLastIndex(tokens, indexMap, endLoc); + } + + /** @inheritdoc */ + moveNext() { + if (this.index <= this.indexEnd) { + this.current = this.tokens[this.index]; + this.index += 1; + return true; + } + return false; + } + + // + // Shorthand for performance. + // + + /** @inheritdoc */ + getOneToken() { + return (this.index <= this.indexEnd) ? this.tokens[this.index] : null; + } + + /** @inheritdoc */ + getAllTokens() { + return this.tokens.slice(this.index, this.indexEnd + 1); + } +}; diff --git a/tools/eslint/lib/token-store/index.js b/tools/eslint/lib/token-store/index.js new file mode 100644 index 00000000000000..86d05cf7b3f834 --- /dev/null +++ b/tools/eslint/lib/token-store/index.js @@ -0,0 +1,604 @@ +/** + * @fileoverview Object to handle access and retrieval of tokens. + * @author Brandon Mills + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const assert = require("assert"); +const cursors = require("./cursors"); +const ForwardTokenCursor = require("./forward-token-cursor"); +const PaddedTokenCursor = require("./padded-token-cursor"); + +//------------------------------------------------------------------------------ +// Helpers +//------------------------------------------------------------------------------ + +const PUBLIC_METHODS = Object.freeze([ + "getTokenByRangeStart", + + "getFirstToken", + "getLastToken", + "getTokenBefore", + "getTokenAfter", + "getFirstTokenBetween", + "getLastTokenBetween", + + "getFirstTokens", + "getLastTokens", + "getTokensBefore", + "getTokensAfter", + "getFirstTokensBetween", + "getLastTokensBetween", + + "getTokens", + "getTokensBetween", + + "getTokenOrCommentBefore", + "getTokenOrCommentAfter" +]); + +/** + * Creates the map from locations to indices in `tokens`. + * + * The first/last location of tokens is mapped to the index of the token. + * The first/last location of comments is mapped to the index of the next token of each comment. + * + * @param {Token[]} tokens - The array of tokens. + * @param {Comment[]} comments - The array of comments. + * @returns {Object} The map from locations to indices in `tokens`. + * @private + */ +function createIndexMap(tokens, comments) { + const map = Object.create(null); + let tokenIndex = 0; + let commentIndex = 0; + let nextStart = 0; + let range = null; + + while (tokenIndex < tokens.length || commentIndex < comments.length) { + nextStart = (commentIndex < comments.length) ? comments[commentIndex].range[0] : Number.MAX_SAFE_INTEGER; + while (tokenIndex < tokens.length && (range = tokens[tokenIndex].range)[0] < nextStart) { + map[range[0]] = tokenIndex; + map[range[1] - 1] = tokenIndex; + tokenIndex += 1; + } + + nextStart = (tokenIndex < tokens.length) ? tokens[tokenIndex].range[0] : Number.MAX_SAFE_INTEGER; + while (commentIndex < comments.length && (range = comments[commentIndex].range)[0] < nextStart) { + map[range[0]] = tokenIndex; + map[range[1] - 1] = tokenIndex; + commentIndex += 1; + } + } + + return map; +} + +/** + * Creates the cursor iterates tokens with options. + * + * @param {CursorFactory} factory - The cursor factory to initialize cursor. + * @param {Token[]} tokens - The array of tokens. + * @param {Comment[]} comments - The array of comments. + * @param {Object} indexMap - The map from locations to indices in `tokens`. + * @param {number} startLoc - The start location of the iteration range. + * @param {number} endLoc - The end location of the iteration range. + * @param {number|Function|Object} [opts=0] - The option object. If this is a number then it's `opts.skip`. If this is a function then it's `opts.filter`. + * @param {boolean} [opts.includeComments=false] - The flag to iterate comments as well. + * @param {Function|null} [opts.filter=null] - The predicate function to choose tokens. + * @param {number} [opts.skip=0] - The count of tokens the cursor skips. + * @returns {Cursor} The created cursor. + * @private + */ +function createCursorWithSkip(factory, tokens, comments, indexMap, startLoc, endLoc, opts) { + let includeComments = false; + let skip = 0; + let filter = null; + + if (typeof opts === "number") { + skip = opts | 0; + } else if (typeof opts === "function") { + filter = opts; + } else if (opts) { + includeComments = !!opts.includeComments; + skip = opts.skip | 0; + filter = opts.filter || null; + } + assert(skip >= 0, "options.skip should be zero or a positive integer."); + assert(!filter || typeof filter === "function", "options.filter should be a function."); + + return factory.createCursor(tokens, comments, indexMap, startLoc, endLoc, includeComments, filter, skip, -1); +} + +/** + * Creates the cursor iterates tokens with options. + * + * @param {CursorFactory} factory - The cursor factory to initialize cursor. + * @param {Token[]} tokens - The array of tokens. + * @param {Comment[]} comments - The array of comments. + * @param {Object} indexMap - The map from locations to indices in `tokens`. + * @param {number} startLoc - The start location of the iteration range. + * @param {number} endLoc - The end location of the iteration range. + * @param {number|Function|Object} [opts=0] - The option object. If this is a number then it's `opts.count`. If this is a function then it's `opts.filter`. + * @param {boolean} [opts.includeComments] - The flag to iterate comments as well. + * @param {Function|null} [opts.filter=null] - The predicate function to choose tokens. + * @param {number} [opts.count=0] - The maximum count of tokens the cursor iterates. Zero is no iteration for backward compatibility. + * @returns {Cursor} The created cursor. + * @private + */ +function createCursorWithCount(factory, tokens, comments, indexMap, startLoc, endLoc, opts) { + let includeComments = false; + let count = 0; + let countExists = false; + let filter = null; + + if (typeof opts === "number") { + count = opts | 0; + countExists = true; + } else if (typeof opts === "function") { + filter = opts; + } else if (opts) { + includeComments = !!opts.includeComments; + count = opts.count | 0; + countExists = typeof opts.count === "number"; + filter = opts.filter || null; + } + assert(count >= 0, "options.count should be zero or a positive integer."); + assert(!filter || typeof filter === "function", "options.filter should be a function."); + + return factory.createCursor(tokens, comments, indexMap, startLoc, endLoc, includeComments, filter, 0, countExists ? count : -1); +} + +/** + * Creates the cursor iterates tokens with options. + * This is overload function of the below. + * + * @param {Token[]} tokens - The array of tokens. + * @param {Comment[]} comments - The array of comments. + * @param {Object} indexMap - The map from locations to indices in `tokens`. + * @param {number} startLoc - The start location of the iteration range. + * @param {number} endLoc - The end location of the iteration range. + * @param {Function|Object} opts - The option object. If this is a function then it's `opts.filter`. + * @param {boolean} [opts.includeComments] - The flag to iterate comments as well. + * @param {Function|null} [opts.filter=null] - The predicate function to choose tokens. + * @param {number} [opts.count=0] - The maximum count of tokens the cursor iterates. Zero is no iteration for backward compatibility. + * @returns {Cursor} The created cursor. + * @private + */ +/** + * Creates the cursor iterates tokens with options. + * + * @param {Token[]} tokens - The array of tokens. + * @param {Comment[]} comments - The array of comments. + * @param {Object} indexMap - The map from locations to indices in `tokens`. + * @param {number} startLoc - The start location of the iteration range. + * @param {number} endLoc - The end location of the iteration range. + * @param {number} [beforeCount=0] - The number of tokens before the node to retrieve. + * @param {boolean} [afterCount=0] - The number of tokens after the node to retrieve. + * @returns {Cursor} The created cursor. + * @private + */ +function createCursorWithPadding(tokens, comments, indexMap, startLoc, endLoc, beforeCount, afterCount) { + if (typeof beforeCount === "undefined" && typeof afterCount === "undefined") { + return new ForwardTokenCursor(tokens, comments, indexMap, startLoc, endLoc); + } + if (typeof beforeCount === "number" || typeof beforeCount === "undefined") { + return new PaddedTokenCursor(tokens, comments, indexMap, startLoc, endLoc, beforeCount | 0, afterCount | 0); + } + return createCursorWithCount(cursors.forward, tokens, comments, indexMap, startLoc, endLoc, beforeCount); +} + +//------------------------------------------------------------------------------ +// Exports +//------------------------------------------------------------------------------ + +/** + * The token store. + * + * This class provides methods to get tokens by locations as fast as possible. + * The methods are a part of public API, so we should be careful if it changes this class. + * + * People can get tokens in O(1) by the hash map which is mapping from the location of tokens/comments to tokens. + * Also people can get a mix of tokens and comments in O(log k), the k is the number of comments. + * Assuming that comments to be much fewer than tokens, this does not make hash map from token's locations to comments to reduce memory cost. + * This uses binary-searching instead for comments. + */ +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); + } + + //-------------------------------------------------------------------------- + // Gets single token. + //-------------------------------------------------------------------------- + + /** + * Gets the token starting at the specified index. + * @param {number} offset - Index of the start of the token's range. + * @param {Object} [options=0] - The option object. + * @param {boolean} [options.includeComments=false] - The flag to iterate comments as well. + * @returns {Token|null} The token starting at index, or null if no such token. + */ + getTokenByRangeStart(offset, options) { + const includeComments = options && options.includeComments; + const token = cursors.forward.createBaseCursor( + this.tokens, + this.comments, + this.indexMap, + offset, + -1, + includeComments + ).getOneToken(); + + if (token && token.range[0] === offset) { + return token; + } + return null; + } + + /** + * Gets the first 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. + * @returns {Token|null} An object representing the token. + */ + getFirstToken(node, options) { + return createCursorWithSkip( + cursors.forward, + this.tokens, + this.comments, + this.indexMap, + node.range[0], + node.range[1], + options + ).getOneToken(); + } + + /** + * 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. + * @returns {Token|null} An object representing the token. + */ + getLastToken(node, options) { + return createCursorWithSkip( + cursors.backward, + this.tokens, + this.comments, + this.indexMap, + node.range[0], + node.range[1], + options + ).getOneToken(); + } + + /** + * 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. + * @returns {Token|null} An object representing the token. + */ + getTokenBefore(node, options) { + return createCursorWithSkip( + cursors.backward, + this.tokens, + this.comments, + this.indexMap, + -1, + node.range[0], + options + ).getOneToken(); + } + + /** + * 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. + * @returns {Token|null} An object representing the token. + */ + getTokenAfter(node, options) { + return createCursorWithSkip( + cursors.forward, + this.tokens, + this.comments, + this.indexMap, + node.range[1], + -1, + options + ).getOneToken(); + } + + /** + * 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. + * @returns {Token|null} An object representing the token. + */ + getFirstTokenBetween(left, right, options) { + return createCursorWithSkip( + cursors.forward, + this.tokens, + this.comments, + this.indexMap, + left.range[1], + right.range[0], + options + ).getOneToken(); + } + + /** + * 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. + */ + getLastTokenBetween(left, right, options) { + return createCursorWithSkip( + cursors.backward, + this.tokens, + this.comments, + this.indexMap, + left.range[1], + right.range[0], + options + ).getOneToken(); + } + + /** + * Gets the token that precedes a given node or token in the token stream. + * This is defined for backward compatibility. Use `includeComments` option instead. + * TODO: We have a plan to remove this in a future major version. + * @param {ASTNode|Token|Comment} node The AST node or token. + * @param {number} [skip=0] A number of tokens to skip. + * @returns {Token|null} An object representing the token. + * @deprecated + */ + getTokenOrCommentBefore(node, skip) { + return this.getTokenBefore(node, { includeComments: true, skip }); + } + + /** + * Gets the token that follows a given node or token in the token stream. + * This is defined for backward compatibility. Use `includeComments` option instead. + * TODO: We have a plan to remove this in a future major version. + * @param {ASTNode|Token|Comment} node The AST node or token. + * @param {number} [skip=0] A number of tokens to skip. + * @returns {Token|null} An object representing the token. + * @deprecated + */ + getTokenOrCommentAfter(node, skip) { + return this.getTokenAfter(node, { includeComments: true, skip }); + } + + //-------------------------------------------------------------------------- + // Gets multiple tokens. + //-------------------------------------------------------------------------- + + /** + * Gets the first `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. + * @returns {Token[]} Tokens. + */ + getFirstTokens(node, options) { + return createCursorWithCount( + cursors.forward, + this.tokens, + this.comments, + this.indexMap, + node.range[0], + node.range[1], + options + ).getAllTokens(); + } + + /** + * 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. + * @returns {Token[]} Tokens. + */ + getLastTokens(node, options) { + return createCursorWithCount( + cursors.backward, + this.tokens, + this.comments, + this.indexMap, + node.range[0], + node.range[1], + options + ).getAllTokens().reverse(); + } + + /** + * 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. + * @returns {Token[]} Tokens. + */ + getTokensBefore(node, options) { + return createCursorWithCount( + cursors.backward, + this.tokens, + this.comments, + this.indexMap, + -1, + node.range[0], + options + ).getAllTokens().reverse(); + } + + /** + * 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. + * @returns {Token[]} Tokens. + */ + getTokensAfter(node, options) { + return createCursorWithCount( + cursors.forward, + this.tokens, + this.comments, + this.indexMap, + node.range[1], + -1, + options + ).getAllTokens(); + } + + /** + * 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. + * @returns {Token[]} Tokens between left and right. + */ + getFirstTokensBetween(left, right, options) { + return createCursorWithCount( + cursors.forward, + this.tokens, + this.comments, + this.indexMap, + left.range[1], + right.range[0], + options + ).getAllTokens(); + } + + /** + * 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. + * @returns {Token[]} Tokens between left and right. + */ + getLastTokensBetween(left, right, options) { + return createCursorWithCount( + cursors.backward, + this.tokens, + this.comments, + this.indexMap, + left.range[1], + right.range[0], + options + ).getAllTokens().reverse(); + } + + /** + * Gets all tokens that are related to the given node. + * @param {ASTNode} node - The AST node. + * @param {Function|Object} options The option object. 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. + * @returns {Token[]} Array of objects representing tokens. + */ + /** + * Gets all tokens that are related to the given node. + * @param {ASTNode} node - The AST node. + * @param {int} [beforeCount=0] - The number of tokens before the node to retrieve. + * @param {int} [afterCount=0] - The number of tokens after the node to retrieve. + * @returns {Token[]} Array of objects representing tokens. + */ + getTokens(node, beforeCount, afterCount) { + return createCursorWithPadding( + this.tokens, + this.comments, + this.indexMap, + node.range[0], + node.range[1], + beforeCount, + afterCount + ).getAllTokens(); + } + + /** + * Gets all of the 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 {Function|Object} options The option object. 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. + * @returns {Token[]} Tokens between left and right. + */ + /** + * Gets all of the 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 {int} [padding=0] Number of extra tokens on either side of center. + * @returns {Token[]} Tokens between left and right. + */ + getTokensBetween(left, right, padding) { + return createCursorWithPadding( + this.tokens, + this.comments, + this.indexMap, + left.range[1], + right.range[0], + padding, + padding + ).getAllTokens(); + } +}; + +module.exports.PUBLIC_METHODS = PUBLIC_METHODS; diff --git a/tools/eslint/lib/token-store/limit-cursor.js b/tools/eslint/lib/token-store/limit-cursor.js new file mode 100644 index 00000000000000..efb46cf0e3f40d --- /dev/null +++ b/tools/eslint/lib/token-store/limit-cursor.js @@ -0,0 +1,40 @@ +/** + * @fileoverview Define the cursor which limits the number of tokens. + * @author Toru Nagashima + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const DecorativeCursor = require("./decorative-cursor"); + +//------------------------------------------------------------------------------ +// Exports +//------------------------------------------------------------------------------ + +/** + * The decorative cursor which limits the number of tokens. + */ +module.exports = class LimitCursor extends DecorativeCursor { + + /** + * Initializes this cursor. + * @param {Cursor} cursor - The cursor to be decorated. + * @param {number} count - The count of tokens this cursor iterates. + */ + constructor(cursor, count) { + super(cursor); + this.count = count; + } + + /** @inheritdoc */ + moveNext() { + if (this.count > 0) { + this.count -= 1; + return super.moveNext(); + } + return false; + } +}; diff --git a/tools/eslint/lib/token-store/padded-token-cursor.js b/tools/eslint/lib/token-store/padded-token-cursor.js new file mode 100644 index 00000000000000..c083aed1e9bab9 --- /dev/null +++ b/tools/eslint/lib/token-store/padded-token-cursor.js @@ -0,0 +1,38 @@ +/** + * @fileoverview Define the cursor which iterates tokens only, with inflated range. + * @author Toru Nagashima + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const ForwardTokenCursor = require("./forward-token-cursor"); + +//------------------------------------------------------------------------------ +// Exports +//------------------------------------------------------------------------------ + +/** + * The cursor which iterates tokens only, with inflated range. + * This is for the backward compatibility of padding options. + */ +module.exports = class PaddedTokenCursor extends ForwardTokenCursor { + + /** + * Initializes this cursor. + * @param {Token[]} tokens - The array of tokens. + * @param {Comment[]} comments - The array of comments. + * @param {Object} indexMap - The map from locations to indices in `tokens`. + * @param {number} startLoc - The start location of the iteration range. + * @param {number} endLoc - The end location of the iteration range. + * @param {number} beforeCount - The number of tokens this cursor iterates before start. + * @param {number} afterCount - The number of tokens this cursor iterates after end. + */ + constructor(tokens, comments, indexMap, startLoc, endLoc, beforeCount, afterCount) { + super(tokens, comments, indexMap, startLoc, endLoc); + this.index = Math.max(0, this.index - beforeCount); + this.indexEnd = Math.min(tokens.length - 1, this.indexEnd + afterCount); + } +}; diff --git a/tools/eslint/lib/token-store/skip-cursor.js b/tools/eslint/lib/token-store/skip-cursor.js new file mode 100644 index 00000000000000..ab34dfab0db3c6 --- /dev/null +++ b/tools/eslint/lib/token-store/skip-cursor.js @@ -0,0 +1,42 @@ +/** + * @fileoverview Define the cursor which ignores the first few tokens. + * @author Toru Nagashima + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const DecorativeCursor = require("./decorative-cursor"); + +//------------------------------------------------------------------------------ +// Exports +//------------------------------------------------------------------------------ + +/** + * The decorative cursor which ignores the first few tokens. + */ +module.exports = class SkipCursor extends DecorativeCursor { + + /** + * Initializes this cursor. + * @param {Cursor} cursor - The cursor to be decorated. + * @param {number} count - The count of tokens this cursor skips. + */ + constructor(cursor, count) { + super(cursor); + this.count = count; + } + + /** @inheritdoc */ + moveNext() { + while (this.count > 0) { + this.count -= 1; + if (!super.moveNext()) { + return false; + } + } + return super.moveNext(); + } +}; diff --git a/tools/eslint/lib/token-store/utils.js b/tools/eslint/lib/token-store/utils.js new file mode 100644 index 00000000000000..f83b6cf699999c --- /dev/null +++ b/tools/eslint/lib/token-store/utils.js @@ -0,0 +1,100 @@ +/** + * @fileoverview Define utilify functions for token store. + * @author Toru Nagashima + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const lodash = require("lodash"); + +//------------------------------------------------------------------------------ +// Helpers +//------------------------------------------------------------------------------ + +/** + * Gets `token.range[0]` from the given token. + * + * @param {Node|Token|Comment} token - The token to get. + * @returns {number} The start location. + * @private + */ +function getStartLocation(token) { + return token.range[0]; +} + +//------------------------------------------------------------------------------ +// Exports +//------------------------------------------------------------------------------ + +/** + * Binary-searches the index of the first token which is after the given location. + * If it was not found, this returns `tokens.length`. + * + * @param {(Token|Comment)[]} tokens - It searches the token in this list. + * @param {number} location - The location to search. + * @returns {number} The found index or `tokens.length`. + */ +exports.search = function search(tokens, location) { + return lodash.sortedIndexBy( + tokens, + { range: [location] }, + getStartLocation + ); +}; + +/** + * Gets the index of the `startLoc` in `tokens`. + * `startLoc` can be the value of `node.range[1]`, so this checks about `startLoc - 1` as well. + * + * @param {(Token|Comment)[]} tokens - The tokens to find an index. + * @param {Object} indexMap - The map from locations to indices. + * @param {number} startLoc - The location to get an index. + * @returns {number} The index. + */ +exports.getFirstIndex = function getFirstIndex(tokens, indexMap, startLoc) { + if (startLoc in indexMap) { + return indexMap[startLoc]; + } + if ((startLoc - 1) in indexMap) { + const index = indexMap[startLoc - 1]; + const token = (index >= 0 && index < tokens.length) ? tokens[index] : null; + + // For the map of "comment's location -> token's index", it points the next token of a comment. + // In that case, +1 is unnecessary. + if (token && token.range[0] >= startLoc) { + return index; + } + return index + 1; + } + return 0; +}; + +/** + * Gets the index of the `endLoc` in `tokens`. + * The information of end locations are recorded at `endLoc - 1` in `indexMap`, so this checks about `endLoc - 1` as well. + * + * @param {(Token|Comment)[]} tokens - The tokens to find an index. + * @param {Object} indexMap - The map from locations to indices. + * @param {number} endLoc - The location to get an index. + * @returns {number} The index. + */ +exports.getLastIndex = function getLastIndex(tokens, indexMap, endLoc) { + if (endLoc in indexMap) { + return indexMap[endLoc] - 1; + } + if ((endLoc - 1) in indexMap) { + const index = indexMap[endLoc - 1]; + const token = (index >= 0 && index < tokens.length) ? tokens[index] : null; + + // For the map of "comment's location -> token's index", it points the next token of a comment. + // In that case, -1 is necessary. + if (token && token.range[1] > endLoc) { + return index - 1; + } + return index; + } + return tokens.length - 1; +}; diff --git a/tools/eslint/lib/util/comment-event-generator.js b/tools/eslint/lib/util/comment-event-generator.js index dfa7132ff850ef..239a9834d0ed20 100644 --- a/tools/eslint/lib/util/comment-event-generator.js +++ b/tools/eslint/lib/util/comment-event-generator.js @@ -70,46 +70,47 @@ function emitCommentsExit(generator, comments) { * This is the decorator pattern. * This generates events of comments before/after events which are generated the original generator. * - * @param {EventGenerator} originalEventGenerator - An event generator which is the decoration target. - * @param {SourceCode} sourceCode - A source code which has comments. - * @returns {CommentEventGenerator} new instance. + * Comment event generator class */ -function CommentEventGenerator(originalEventGenerator, sourceCode) { - this.original = originalEventGenerator; - this.emitter = originalEventGenerator.emitter; - this.sourceCode = sourceCode; - this.commentLocsEnter = []; - this.commentLocsExit = []; -} +class CommentEventGenerator { -CommentEventGenerator.prototype = { - constructor: 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: function enterNode(node) { + 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: function leaveNode(node) { + 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/fix-tracker.js b/tools/eslint/lib/util/fix-tracker.js new file mode 100644 index 00000000000000..189072e1abc161 --- /dev/null +++ b/tools/eslint/lib/util/fix-tracker.js @@ -0,0 +1,121 @@ +/** + * @fileoverview Helper class to aid in constructing fix commands. + * @author Alan Pierce + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("../ast-utils"); + +//------------------------------------------------------------------------------ +// Public Interface +//------------------------------------------------------------------------------ + +/** + * A helper class to combine fix options into a fix command. Currently, it + * exposes some "retain" methods that extend the range of the text being + * replaced so that other fixes won't touch that region in the same pass. + */ +class FixTracker { + + /** + * Create a new FixTracker. + * + * @param {ruleFixer} fixer A ruleFixer instance. + * @param {SourceCode} sourceCode A SourceCode object for the current code. + */ + constructor(fixer, sourceCode) { + this.fixer = fixer; + this.sourceCode = sourceCode; + this.retainedRange = null; + } + + /** + * Mark the given range as "retained", meaning that other fixes may not + * may not modify this region in the same pass. + * + * @param {int[]} range The range to retain. + * @returns {FixTracker} The same RuleFixer, for chained calls. + */ + retainRange(range) { + this.retainedRange = range; + return this; + } + + /** + * Given a node, find the function containing it (or the entire program) and + * mark it as retained, meaning that other fixes may not modify it in this + * pass. This is useful for avoiding conflicts in fixes that modify control + * flow. + * + * @param {ASTNode} node The node to use as a starting point. + * @returns {FixTracker} The same RuleFixer, for chained calls. + */ + retainEnclosingFunction(node) { + const functionNode = astUtils.getUpperFunction(node); + + return this.retainRange( + functionNode ? functionNode.range : this.sourceCode.ast.range); + } + + /** + * Given a node or token, find the token before and afterward, and mark that + * range as retained, meaning that other fixes may not modify it in this + * pass. This is useful for avoiding conflicts in fixes that make a small + * change to the code where the AST should not be changed. + * + * @param {ASTNode|Token} nodeOrToken The node or token to use as a starting + * point. The token to the left and right are use in the range. + * @returns {FixTracker} The same RuleFixer, for chained calls. + */ + retainSurroundingTokens(nodeOrToken) { + const tokenBefore = this.sourceCode.getTokenBefore(nodeOrToken) || nodeOrToken; + const tokenAfter = this.sourceCode.getTokenAfter(nodeOrToken) || nodeOrToken; + + return this.retainRange([tokenBefore.range[0], tokenAfter.range[1]]); + } + + /** + * Create a fix command that replaces the given range with the given text, + * accounting for any retained ranges. + * + * @param {int[]} range The range to remove in the fix. + * @param {string} text The text to insert in place of the range. + * @returns {Object} The fix command. + */ + replaceTextRange(range, text) { + let actualRange; + + if (this.retainedRange) { + actualRange = [ + Math.min(this.retainedRange[0], range[0]), + Math.max(this.retainedRange[1], range[1]) + ]; + } else { + actualRange = range; + } + + return this.fixer.replaceTextRange( + actualRange, + this.sourceCode.text.slice(actualRange[0], range[0]) + + text + + this.sourceCode.text.slice(range[1], actualRange[1]) + ); + } + + /** + * Create a fix command that removes the given node or token, accounting for + * any retained ranges. + * + * @param {ASTNode|Token} nodeOrToken The node or token to remove. + * @returns {Object} The fix command. + */ + remove(nodeOrToken) { + return this.replaceTextRange(nodeOrToken.range, ""); + } +} + +module.exports = FixTracker; diff --git a/tools/eslint/lib/util/glob-util.js b/tools/eslint/lib/util/glob-util.js index 198e069e9f0850..4c21fc55106d99 100644 --- a/tools/eslint/lib/util/glob-util.js +++ b/tools/eslint/lib/util/glob-util.js @@ -86,7 +86,7 @@ function resolveFileGlobPatterns(patterns, options) { const processPathExtensions = processPath(options); - return patterns.map(processPathExtensions); + return patterns.filter(p => p.length).map(processPathExtensions); } /** @@ -165,7 +165,7 @@ function listFilesToProcess(globPatterns, options) { const globOptions = { nodir: true, dot: true, - cwd, + cwd }; new GlobSync(pattern, globOptions, shouldIgnore).found.forEach(globMatch => { diff --git a/tools/eslint/lib/util/glob.js b/tools/eslint/lib/util/glob.js index 915dcff08ef186..a231e16f4d0bce 100644 --- a/tools/eslint/lib/util/glob.js +++ b/tools/eslint/lib/util/glob.js @@ -15,7 +15,7 @@ const Sync = require("glob").GlobSync, // Private //------------------------------------------------------------------------------ -const IGNORE = typeof Symbol === "function" ? Symbol("ignore") : "_shouldIgnore"; +const IGNORE = Symbol("ignore"); /** * Subclass of `glob.GlobSync` diff --git a/tools/eslint/lib/util/node-event-generator.js b/tools/eslint/lib/util/node-event-generator.js index 1666ae93f53406..568a3b7fe104be 100644 --- a/tools/eslint/lib/util/node-event-generator.js +++ b/tools/eslint/lib/util/node-event-generator.js @@ -5,6 +5,185 @@ "use strict"; +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const esquery = require("esquery"); +const lodash = require("lodash"); + +//------------------------------------------------------------------------------ +// Typedefs +//------------------------------------------------------------------------------ + +/** + * An object describing an AST selector + * @typedef {Object} ASTSelector + * @property {string} rawSelector The string that was parsed into this selector + * @property {boolean} isExit `true` if this should be emitted when exiting the node rather than when entering + * @property {Object} parsedSelector An object (from esquery) describing the matching behavior of the selector + * @property {string[]|null} listenerTypes A list of node types that could possibly cause the selector to match, + * or `null` if all node types could cause a match + * @property {number} attributeCount The total number of classes, pseudo-classes, and attribute queries in this selector + * @property {number} identifierCount The total number of identifier queries in this selector + */ + +//------------------------------------------------------------------------------ +// Helpers +//------------------------------------------------------------------------------ + +/** +* Gets the possible types of a selector +* @param {Object} parsedSelector An object (from esquery) describing the matching behavior of the selector +* @returns {string[]|null} The node types that could possibly trigger this selector, or `null` if all node types could trigger it +*/ +function getPossibleTypes(parsedSelector) { + switch (parsedSelector.type) { + case "identifier": + return [parsedSelector.value]; + + case "matches": { + const typesForComponents = parsedSelector.selectors.map(getPossibleTypes); + + if (typesForComponents.every(typesForComponent => typesForComponent)) { + return lodash.union.apply(null, typesForComponents); + } + return null; + } + + case "compound": { + const typesForComponents = parsedSelector.selectors.map(getPossibleTypes).filter(typesForComponent => typesForComponent); + + // If all of the components could match any type, then the compound could also match any type. + if (!typesForComponents.length) { + return null; + } + + /* + * If at least one of the components could only match a particular type, the compound could only match + * the intersection of those types. + */ + return lodash.intersection.apply(null, typesForComponents); + } + + case "child": + case "descendant": + case "sibling": + case "adjacent": + return getPossibleTypes(parsedSelector.right); + + default: + return null; + + } +} + +/** + * Counts the number of class, pseudo-class, and attribute queries in this selector + * @param {Object} parsedSelector An object (from esquery) describing the selector's matching behavior + * @returns {number} The number of class, pseudo-class, and attribute queries in this selector + */ +function countClassAttributes(parsedSelector) { + switch (parsedSelector.type) { + case "child": + case "descendant": + case "sibling": + case "adjacent": + return countClassAttributes(parsedSelector.left) + countClassAttributes(parsedSelector.right); + + case "compound": + case "not": + case "matches": + return parsedSelector.selectors.reduce((sum, childSelector) => sum + countClassAttributes(childSelector), 0); + + case "attribute": + case "field": + case "nth-child": + case "nth-last-child": + return 1; + + default: + return 0; + } +} + +/** + * Counts the number of identifier queries in this selector + * @param {Object} parsedSelector An object (from esquery) describing the selector's matching behavior + * @returns {number} The number of identifier queries + */ +function countIdentifiers(parsedSelector) { + switch (parsedSelector.type) { + case "child": + case "descendant": + case "sibling": + case "adjacent": + return countIdentifiers(parsedSelector.left) + countIdentifiers(parsedSelector.right); + + case "compound": + case "not": + case "matches": + return parsedSelector.selectors.reduce((sum, childSelector) => sum + countIdentifiers(childSelector), 0); + + case "identifier": + return 1; + + default: + return 0; + } +} + +/** + * Compares the specificity of two selector objects, with CSS-like rules. + * @param {ASTSelector} selectorA An AST selector descriptor + * @param {ASTSelector} selectorB Another AST selector descriptor + * @returns {number} + * a value less than 0 if selectorA is less specific than selectorB + * a value greater than 0 if selectorA is more specific than selectorB + * a value less than 0 if selectorA and selectorB have the same specificity, and selectorA <= selectorB alphabetically + * a value greater than 0 if selectorA and selectorB have the same specificity, and selectorA > selectorB alphabetically + */ +function compareSpecificity(selectorA, selectorB) { + return selectorA.attributeCount - selectorB.attributeCount || + selectorA.identifierCount - selectorB.identifierCount || + (selectorA.rawSelector <= selectorB.rawSelector ? -1 : 1); +} + +/** + * Parses a raw selector string, and throws a useful error if parsing fails. + * @param {string} rawSelector A raw AST selector + * @returns {Object} An object (from esquery) describing the matching behavior of this selector + * @throws {Error} An error if the selector is invalid + */ +function tryParseSelector(rawSelector) { + try { + return esquery.parse(rawSelector.replace(/:exit$/, "")); + } catch (err) { + if (typeof err.offset === "number") { + throw new Error(`Syntax error in selector "${rawSelector}" at position ${err.offset}: ${err.message}`); + } + throw err; + } +} + +/** + * Parses a raw selector string, and returns the parsed selector along with specificity and type information. + * @param {string} rawSelector A raw AST selector + * @returns {ASTSelector} A selector descriptor + */ +const parseSelector = lodash.memoize(rawSelector => { + const parsedSelector = tryParseSelector(rawSelector); + + return { + rawSelector, + isExit: rawSelector.endsWith(":exit"), + parsedSelector, + listenerTypes: getPossibleTypes(parsedSelector), + attributeCount: countClassAttributes(parsedSelector), + identifierCount: countIdentifiers(parsedSelector) + }; +}); + //------------------------------------------------------------------------------ // Public Interface //------------------------------------------------------------------------------ @@ -24,10 +203,97 @@ class NodeEventGenerator { /** - * @param {EventEmitter} emitter - An event emitter which is the destination of events. - */ + * @param {EventEmitter} emitter - An event emitter which is the destination of events. This emitter must already + * have registered listeners for all of the events that it needs to listen for. + * @returns {NodeEventGenerator} new instance + */ constructor(emitter) { this.emitter = emitter; + this.currentAncestry = []; + this.enterSelectorsByNodeType = new Map(); + this.exitSelectorsByNodeType = new Map(); + this.anyTypeEnterSelectors = []; + this.anyTypeExitSelectors = []; + + const eventNames = typeof emitter.eventNames === "function" + + // Use the built-in eventNames() function if available (Node 6+) + ? emitter.eventNames() + + /* + * Otherwise, use the private _events property. + * Using a private property isn't ideal here, but this seems to + * be the best way to get a list of event names without overriding + * addEventListener, which would hurt performance. This property + * is widely used and unlikely to be removed in a future version + * (see https://github.com/nodejs/node/issues/1817). Also, future + * node versions will have eventNames() anyway. + */ + : Object.keys(emitter._events); // eslint-disable-line no-underscore-dangle + + eventNames.forEach(rawSelector => { + const selector = parseSelector(rawSelector); + + if (selector.listenerTypes) { + selector.listenerTypes.forEach(nodeType => { + const typeMap = selector.isExit ? this.exitSelectorsByNodeType : this.enterSelectorsByNodeType; + + if (!typeMap.has(nodeType)) { + typeMap.set(nodeType, []); + } + typeMap.get(nodeType).push(selector); + }); + } else { + (selector.isExit ? this.anyTypeExitSelectors : this.anyTypeEnterSelectors).push(selector); + } + }); + + this.anyTypeEnterSelectors.sort(compareSpecificity); + this.anyTypeExitSelectors.sort(compareSpecificity); + this.enterSelectorsByNodeType.forEach(selectorList => selectorList.sort(compareSpecificity)); + this.exitSelectorsByNodeType.forEach(selectorList => selectorList.sort(compareSpecificity)); + } + + /** + * Checks a selector against a node, and emits it if it matches + * @param {ASTNode} node The node to check + * @param {ASTSelector} selector An AST selector descriptor + * @returns {void} + */ + applySelector(node, selector) { + if (esquery.matches(node, selector.parsedSelector, this.currentAncestry)) { + this.emitter.emit(selector.rawSelector, node); + } + } + + /** + * Applies all appropriate selectors to a node, in specificity order + * @param {ASTNode} node The node to check + * @param {boolean} isExit `false` if the node is currently being entered, `true` if it's currently being exited + * @returns {void} + */ + applySelectors(node, isExit) { + const selectorsByNodeType = (isExit ? this.exitSelectorsByNodeType : this.enterSelectorsByNodeType).get(node.type) || []; + const anyTypeSelectors = isExit ? this.anyTypeExitSelectors : this.anyTypeEnterSelectors; + + /* + * selectorsByNodeType and anyTypeSelectors were already sorted by specificity in the constructor. + * Iterate through each of them, applying selectors in the right order. + */ + let selectorsByTypeIndex = 0; + let anyTypeSelectorsIndex = 0; + + while (selectorsByTypeIndex < selectorsByNodeType.length || anyTypeSelectorsIndex < anyTypeSelectors.length) { + if ( + selectorsByTypeIndex >= selectorsByNodeType.length || + anyTypeSelectorsIndex < anyTypeSelectors.length && + compareSpecificity(anyTypeSelectors[anyTypeSelectorsIndex], selectorsByNodeType[selectorsByTypeIndex]) < 0 + ) { + this.applySelector(node, anyTypeSelectors[anyTypeSelectorsIndex++]); + } else { + this.applySelector(node, selectorsByNodeType[selectorsByTypeIndex++]); + } + } } /** @@ -36,7 +302,10 @@ class NodeEventGenerator { * @returns {void} */ enterNode(node) { - this.emitter.emit(node.type, node); + if (node.parent) { + this.currentAncestry.unshift(node.parent); + } + this.applySelectors(node, false); } /** @@ -45,7 +314,8 @@ class NodeEventGenerator { * @returns {void} */ leaveNode(node) { - this.emitter.emit(`${node.type}:exit`, node); + this.applySelectors(node, true); + this.currentAncestry.shift(); } } diff --git a/tools/eslint/lib/util/rule-fixer.js b/tools/eslint/lib/util/rule-fixer.js index e6afe85f502f38..bdd80d13b162d4 100644 --- a/tools/eslint/lib/util/rule-fixer.js +++ b/tools/eslint/lib/util/rule-fixer.js @@ -34,14 +34,9 @@ function insertTextAt(index, text) { /** * Creates code fixing commands for rules. - * @constructor */ -function RuleFixer() { - Object.freeze(this); -} -RuleFixer.prototype = { - constructor: RuleFixer, +const ruleFixer = Object.freeze({ /** * Creates a fix command that inserts text after the given node or token. @@ -139,7 +134,7 @@ RuleFixer.prototype = { }; } -}; +}); -module.exports = RuleFixer; +module.exports = ruleFixer; diff --git a/tools/eslint/lib/util/source-code-fixer.js b/tools/eslint/lib/util/source-code-fixer.js index 3b702e509e77a4..6490a467fa725b 100644 --- a/tools/eslint/lib/util/source-code-fixer.js +++ b/tools/eslint/lib/util/source-code-fixer.js @@ -16,6 +16,17 @@ const debug = require("debug")("eslint:text-fixer"); const BOM = "\uFEFF"; +/** + * Compares items in a messages array by range. + * @param {Message} a The first message. + * @param {Message} b The second message. + * @returns {int} -1 if a comes before b, 1 if a comes after b, 0 if equal. + * @private + */ +function compareMessagesByFixRange(a, b) { + return a.fix.range[0] - b.fix.range[0] || a.fix.range[1] - b.fix.range[1]; +} + /** * Compares items in a messages array by line and column. * @param {Message} a The first message. @@ -24,13 +35,7 @@ const BOM = "\uFEFF"; * @private */ function compareMessagesByLocation(a, b) { - const lineDiff = a.line - b.line; - - if (lineDiff === 0) { - return a.column - b.column; - } else { - return lineDiff; - } + return a.line - b.line || a.column - b.column; } //------------------------------------------------------------------------------ @@ -68,9 +73,10 @@ SourceCodeFixer.applyFixes = function(sourceCode, messages) { // clone the array const remainingMessages = [], fixes = [], + bom = (sourceCode.hasBOM ? BOM : ""), text = sourceCode.text; - let lastFixPos = text.length + 1, - prefix = (sourceCode.hasBOM ? BOM : ""); + let lastPos = Number.NEGATIVE_INFINITY, + output = bom; messages.forEach(problem => { if (problem.hasOwnProperty("fix")) { @@ -83,53 +89,43 @@ SourceCodeFixer.applyFixes = function(sourceCode, messages) { if (fixes.length) { debug("Found fixes to apply"); - // sort in reverse order of occurrence - fixes.sort((a, b) => b.fix.range[1] - a.fix.range[1] || b.fix.range[0] - a.fix.range[0]); - - // split into array of characters for easier manipulation - const chars = text.split(""); - - fixes.forEach(problem => { + for (const problem of fixes.sort(compareMessagesByFixRange)) { const fix = problem.fix; - let start = fix.range[0]; + const start = fix.range[0]; const end = fix.range[1]; - let insertionText = fix.text; - - if (end < lastFixPos) { - if (start < 0) { - // Remove BOM. - prefix = ""; - start = 0; - } - - if (start === 0 && insertionText[0] === BOM) { - - // Set BOM. - prefix = BOM; - insertionText = insertionText.slice(1); - } - - chars.splice(start, end - start, insertionText); - lastFixPos = start; - } else { + // Remain it as a problem if it's overlapped or it's a negative range + if (lastPos >= start || start > end) { remainingMessages.push(problem); + continue; } - }); + + // Remove BOM. + if ((start < 0 && end >= 0) || (start === 0 && fix.text.startsWith(BOM))) { + output = ""; + } + + // Make output to this fix. + output += text.slice(Math.max(0, lastPos), Math.max(0, start)); + output += fix.text; + lastPos = end; + } + output += text.slice(Math.max(0, lastPos)); return { fixed: true, messages: remainingMessages.sort(compareMessagesByLocation), - output: prefix + chars.join("") - }; - } else { - debug("No fixes to apply"); - return { - fixed: false, - messages, - output: prefix + text + output }; } + + debug("No fixes to apply"); + return { + fixed: false, + messages, + output: bom + text + }; + }; module.exports = SourceCodeFixer; diff --git a/tools/eslint/lib/util/source-code.js b/tools/eslint/lib/util/source-code.js index 5d073039d81cd7..5106c1e61fa98a 100644 --- a/tools/eslint/lib/util/source-code.js +++ b/tools/eslint/lib/util/source-code.js @@ -8,8 +8,10 @@ // Requirements //------------------------------------------------------------------------------ -const createTokenStore = require("../token-store.js"), - Traverser = require("./traverser"); +const TokenStore = require("../token-store"), + Traverser = require("./traverser"), + astUtils = require("../ast-utils"), + lodash = require("lodash"); //------------------------------------------------------------------------------ // Private @@ -56,9 +58,9 @@ function findJSDocComment(comments, line) { if (line - comments[i].loc.end.line <= 1) { return comments[i]; - } else { - break; } + break; + } } } @@ -77,6 +79,28 @@ function looksLikeExport(astNode) { astNode.type === "ExportAllDeclaration" || astNode.type === "ExportSpecifier"; } +/** + * Merges two sorted lists into a larger sorted list in O(n) time + * @param {Token[]} tokens The list of tokens + * @param {Token[]} comments The list of comments + * @returns {Token[]} A sorted list of tokens and comments + */ +function sortedMerge(tokens, comments) { + const result = []; + let tokenIndex = 0; + let commentIndex = 0; + + while (tokenIndex < tokens.length || commentIndex < comments.length) { + if (commentIndex >= comments.length || tokenIndex < tokens.length && tokens[tokenIndex].range[0] < comments[commentIndex].range[0]) { + result.push(tokens[tokenIndex++]); + } else { + result.push(comments[commentIndex++]); + } + } + + return result; +} + //------------------------------------------------------------------------------ // Public Interface @@ -115,23 +139,35 @@ function SourceCode(text, ast) { * This is done to avoid each rule needing to do so separately. * @type string[] */ - this.lines = SourceCode.splitLines(this.text); + 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])); - this.tokensAndComments = ast.tokens - .concat(ast.comments) - .sort((left, right) => left.range[0] - right.range[0]); + this.tokensAndComments = sortedMerge(ast.tokens, ast.comments); // create token store methods - const tokenStore = createTokenStore(ast.tokens); + const tokenStore = new TokenStore(ast.tokens, ast.comments); - Object.keys(tokenStore).forEach(methodName => { - this[methodName] = tokenStore[methodName]; - }); - - const tokensAndCommentsStore = createTokenStore(this.tokensAndComments); - - this.getTokenOrCommentBefore = tokensAndCommentsStore.getTokenBefore; - this.getTokenOrCommentAfter = tokensAndCommentsStore.getTokenAfter; + for (const methodName of TokenStore.PUBLIC_METHODS) { + this[methodName] = tokenStore[methodName].bind(tokenStore); + } // don't allow modification of this object Object.freeze(this); @@ -145,7 +181,7 @@ function SourceCode(text, ast) { * @public */ SourceCode.splitLines = function(text) { - return text.split(/\r\n|\r|\n|\u2028|\u2029/g); + return text.split(astUtils.createGlobalLinebreakMatcher()); }; SourceCode.prototype = { @@ -162,9 +198,9 @@ SourceCode.prototype = { if (node) { return this.text.slice(Math.max(node.range[0] - (beforeCount || 0), 0), node.range[1] + (afterCount || 0)); - } else { - return this.text; } + return this.text; + }, @@ -296,6 +332,83 @@ 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. + * @param {number} index The index of a character in a file + * @returns {Object} A {line, column} location object with a 0-indexed column + */ + getLocFromIndex(index) { + if (typeof index !== "number") { + throw new TypeError("Expected `index` to be a number."); + } + + if (index < 0 || index > this.text.length) { + throw new RangeError(`Index out of range (requested index ${index}, but source text has length ${this.text.length}).`); + } + + /* + * For an argument of this.text.length, return the location one "spot" past the last character + * of the file. If the last character is a linebreak, the location will be column 0 of the next + * line; otherwise, the location will be in the next column on the same line. + * + * See getIndexFromLoc for the motivation for this special case. + */ + if (index === this.text.length) { + return { line: this.lines.length, column: this.lines[this.lines.length - 1].length }; + } + + /* + * To figure out which line rangeIndex is on, determine the last index at which rangeIndex could + * be inserted into lineIndices to keep the list sorted. + */ + 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. + * @param {Object} loc A line/column location + * @param {number} loc.line The line number of the location (1-indexed) + * @param {number} loc.column The column number of the location (0-indexed) + * @returns {number} The range index of the location in the file. + */ + getIndexFromLoc(loc) { + if (typeof loc !== "object" || typeof loc.line !== "number" || typeof loc.column !== "number") { + throw new TypeError("Expected `loc` to be an object with numeric `line` and `column` properties."); + } + + if (loc.line <= 0) { + throw new RangeError(`Line number out of range (line ${loc.line} requested). Line numbers should be 1-based.`); + } + + if (loc.line > this.lineStartIndices.length) { + throw new RangeError(`Line number out of range (line ${loc.line} requested, but only ${this.lineStartIndices.length} lines present).`); + } + + const lineStartIndex = this.lineStartIndices[loc.line - 1]; + const lineEndIndex = loc.line === this.lineStartIndices.length ? this.text.length : this.lineStartIndices[loc.line]; + const positionIndex = lineStartIndex + loc.column; + + /* + * By design, getIndexFromLoc({ line: lineNum, column: 0 }) should return the start index of + * the given line, provided that the line number is valid element of this.lines. Since the + * last element of this.lines is an empty string for files with trailing newlines, add a + * special case where getting the index for the first location after the end of the file + * will return the length of the file, rather than throwing an error. This allows rules to + * use getIndexFromLoc consistently without worrying about edge cases at the end of a file. + */ + if ( + loc.line === this.lineStartIndices.length && positionIndex > lineEndIndex || + loc.line < this.lineStartIndices.length && positionIndex >= lineEndIndex + ) { + throw new RangeError(`Column number out of range (column ${loc.column} requested, but the length of line ${loc.line} is ${lineEndIndex - lineStartIndex}).`); + } + + return positionIndex; } }; diff --git a/tools/eslint/lib/util/traverser.js b/tools/eslint/lib/util/traverser.js index d5710bb8ac7b2d..fc070186b3b60e 100644 --- a/tools/eslint/lib/util/traverser.js +++ b/tools/eslint/lib/util/traverser.js @@ -14,41 +14,32 @@ const estraverse = require("estraverse"); // Helpers //------------------------------------------------------------------------------ -const KEY_BLACKLIST = [ +const KEY_BLACKLIST = new Set([ "parent", "leadingComments", "trailingComments" -]; +]); /** * Wrapper around an estraverse controller that ensures the correct keys * are visited. * @constructor */ -function Traverser() { - - const controller = Object.create(new estraverse.Controller()), - originalTraverse = controller.traverse; - - // intercept call to traverse() and add the fallback key to the visitor - controller.traverse = function(node, visitor) { +class Traverser extends estraverse.Controller { + traverse(node, visitor) { visitor.fallback = Traverser.getKeys; - return originalTraverse.call(this, node, visitor); - }; - - return controller; + return super.traverse(node, visitor); + } + + /** + * Calculates the keys to use for traversal. + * @param {ASTNode} node The node to read keys from. + * @returns {string[]} An array of keys to visit on the node. + * @private + */ + static getKeys(node) { + return Object.keys(node).filter(key => !KEY_BLACKLIST.has(key)); + } } -/** - * Calculates the keys to use for traversal. - * @param {ASTNode} node The node to read keys from. - * @returns {string[]} An array of keys to visit on the node. - * @private - */ -Traverser.getKeys = function(node) { - return Object.keys(node).filter(key => KEY_BLACKLIST.indexOf(key) === -1); -}; - module.exports = Traverser; - - diff --git a/tools/eslint/messages/extend-config-missing.txt b/tools/eslint/messages/extend-config-missing.txt new file mode 100644 index 00000000000000..38e64581970b0e --- /dev/null +++ b/tools/eslint/messages/extend-config-missing.txt @@ -0,0 +1,3 @@ +ESLint couldn't find the config "<%- configName %>" to extend from. Please check that the name of the config is correct. + +If you still have problems, please stop by https://gitter.im/eslint/eslint to chat with the team. diff --git a/tools/eslint/node_modules/acorn/AUTHORS b/tools/eslint/node_modules/acorn/AUTHORS index 306404542a3b07..1377f6034ed673 100644 --- a/tools/eslint/node_modules/acorn/AUTHORS +++ b/tools/eslint/node_modules/acorn/AUTHORS @@ -23,6 +23,7 @@ Jesse McCarthy Jiaxing Wang Joel Kemp Johannes Herr +John-David Dalton Jordan Klassen Jürg Lehni Kai Cataldo @@ -41,6 +42,7 @@ Max Schaefer Max Zerzouri Mihai Bazon Mike Rennie +naoh Nicholas C. Zakas Nick Fitzgerald Olivier Thomann @@ -55,6 +57,8 @@ Richard Gibson Rich Harris Sebastian McKenzie Simen Bekkhus +Teddy Katz Timothy Gu Toru Nagashima +Wexpo Lyu zsjforcn diff --git a/tools/eslint/node_modules/acorn/README.md b/tools/eslint/node_modules/acorn/README.md index 82dc28717adfe0..2186c7e70d136e 100644 --- a/tools/eslint/node_modules/acorn/README.md +++ b/tools/eslint/node_modules/acorn/README.md @@ -1,7 +1,8 @@ # Acorn [![Build Status](https://travis-ci.org/ternjs/acorn.svg?branch=master)](https://travis-ci.org/ternjs/acorn) -[![NPM version](https://img.shields.io/npm/v/acorn.svg)](https://www.npmjs.com/package/acorn) +[![NPM version](https://img.shields.io/npm/v/acorn.svg)](https://www.npmjs.com/package/acorn) +[![CDNJS](https://img.shields.io/cdnjs/v/acorn.svg)](https://cdnjs.com/libraries/acorn) [Author funding status: ![maintainer happiness](https://marijnhaverbeke.nl/fund/status_s.png?force)](https://marijnhaverbeke.nl/fund/) A tiny, fast JavaScript parser, written completely in JavaScript. diff --git a/tools/eslint/node_modules/acorn/bin/acorn b/tools/eslint/node_modules/acorn/bin/acorn index 78ebd4f0ea2420..41b786f4296169 100755 --- a/tools/eslint/node_modules/acorn/bin/acorn +++ b/tools/eslint/node_modules/acorn/bin/acorn @@ -29,7 +29,7 @@ for (var i = 2; i < process.argv.length; ++i) { else if (arg == "--compact") compact = true else if (arg == "--help") help(0) else if (arg == "--tokenize") tokenize = true - else if (arg == "--module") options.sourceType = 'module' + else if (arg == "--module") options.sourceType = "module" else { var match = arg.match(/^--ecma(\d+)$/) if (match) @@ -41,18 +41,20 @@ for (var i = 2; i < process.argv.length; ++i) { function run(code) { var result - if (!tokenize) { - try { result = acorn.parse(code, options) } - catch(e) { console.error(e.message); process.exit(1) } - } else { - result = [] - var tokenizer = acorn.tokenizer(code, options), token - while (true) { - try { token = tokenizer.getToken() } - catch(e) { console.error(e.message); process.exit(1) } - result.push(token) - if (token.type == acorn.tokTypes.eof) break + try { + if (!tokenize) { + result = acorn.parse(code, options) + } else { + result = [] + var tokenizer = acorn.tokenizer(code, options), token + do { + token = tokenizer.getToken() + result.push(token) + } while (token.type != acorn.tokTypes.eof) } + } catch (e) { + console.error(e.message) + process.exit(1) } if (!silent) console.log(JSON.stringify(result, null, compact ? null : 2)) } diff --git a/tools/eslint/node_modules/acorn/dist/acorn.es.js b/tools/eslint/node_modules/acorn/dist/acorn.es.js index 32dd5954ea0e68..74417b8aa83559 100644 --- a/tools/eslint/node_modules/acorn/dist/acorn.es.js +++ b/tools/eslint/node_modules/acorn/dist/acorn.es.js @@ -38,7 +38,11 @@ nonASCIIidentifierStartChars = nonASCIIidentifierChars = null // offset starts at 0x10000, and each pair of numbers represents an // offset to the next range, and then a size of the range. They were // generated by bin/generate-identifier-regex.js + +// eslint-disable-next-line comma-spacing var astralIdentifierStartCodes = [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] + +// eslint-disable-next-line comma-spacing var astralIdentifierCodes = [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] // This has a complexity linear to the value of the code. The @@ -244,16 +248,20 @@ var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/ var skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g -function isArray(obj) { - return Object.prototype.toString.call(obj) === "[object Array]" -} +var ref = Object.prototype; +var hasOwnProperty = ref.hasOwnProperty; +var toString = ref.toString; // Checks if an object has a property. function has(obj, propName) { - return Object.prototype.hasOwnProperty.call(obj, propName) + return hasOwnProperty.call(obj, propName) } +var isArray = Array.isArray || (function (obj) { return ( + toString.call(obj) === "[object Array]" +); }) + // These are used when `options.locations` is on, for the // `startLoc` and `endLoc` properties. @@ -401,9 +409,9 @@ function getOptions(opts) { } function pushComment(options, array) { - return function (block, text, start, end, startLoc, endLoc) { + return function(block, text, start, end, startLoc, endLoc) { var comment = { - type: block ? 'Block' : 'Line', + type: block ? "Block" : "Line", value: text, start: start, end: end @@ -481,7 +489,8 @@ var Parser = function Parser(options, input, startPos) { this.exprAllowed = true // Figure out if it's a module code. - this.strict = this.inModule = options.sourceType === "module" + this.inModule = options.sourceType === "module" + this.strict = this.inModule || this.strictDirective(this.pos) // Used to signify the start of a potential arrow function this.potentialArrowAt = -1 @@ -494,8 +503,12 @@ var Parser = function Parser(options, input, startPos) { this.labels = [] // If enabled, skip leading hashbang line. - if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === '#!') + if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === "#!") this.skipLineComment(2) + + // Scope tracking for duplicate variable names (see scope.js) + this.scopeStack = [] + this.enterFunctionScope() }; // DEPRECATED Kept for backwards compatibility until 3.0 in case a plugin uses them @@ -526,12 +539,18 @@ var pp = Parser.prototype // ## Parser utilities -// Test whether a statement node is the string literal `"use strict"`. +var literal = /^(?:'((?:[^']|\.)*)'|"((?:[^"]|\.)*)"|;)/ +pp.strictDirective = function(start) { + var this$1 = this; -pp.isUseStrict = function(stmt) { - return this.options.ecmaVersion >= 5 && stmt.type === "ExpressionStatement" && - stmt.expression.type === "Literal" && - stmt.expression.raw.slice(1, -1) === "use strict" + for (;;) { + skipWhiteSpace.lastIndex = start + start += skipWhiteSpace.exec(this$1.input)[0].length + var match = literal.exec(this$1.input.slice(start)) + if (!match) return false + if ((match[1] || match[2]) == "use strict") return true + start += match[0].length + } } // Predicate that tests whether the next token is of the given @@ -611,20 +630,21 @@ pp.unexpected = function(pos) { } var DestructuringErrors = function DestructuringErrors() { - this.shorthandAssign = 0 - this.trailingComma = 0 + this.shorthandAssign = this.trailingComma = this.parenthesizedAssign = this.parenthesizedBind = -1 }; -pp.checkPatternErrors = function(refDestructuringErrors, andThrow) { - var trailing = refDestructuringErrors && refDestructuringErrors.trailingComma - if (!andThrow) return !!trailing - if (trailing) this.raise(trailing, "Comma is not permitted after the rest element") +pp.checkPatternErrors = function(refDestructuringErrors, isAssign) { + if (!refDestructuringErrors) return + if (refDestructuringErrors.trailingComma > -1) + this.raiseRecoverable(refDestructuringErrors.trailingComma, "Comma is not permitted after the rest element") + var parens = isAssign ? refDestructuringErrors.parenthesizedAssign : refDestructuringErrors.parenthesizedBind + if (parens > -1) this.raiseRecoverable(parens, "Parenthesized pattern") } pp.checkExpressionErrors = function(refDestructuringErrors, andThrow) { - var pos = refDestructuringErrors && refDestructuringErrors.shorthandAssign - if (!andThrow) return !!pos - if (pos) this.raise(pos, "Shorthand property assignments are valid only in destructuring patterns") + var pos = refDestructuringErrors ? refDestructuringErrors.shorthandAssign : -1 + if (!andThrow) return pos >= 0 + if (pos > -1) this.raise(pos, "Shorthand property assignments are valid only in destructuring patterns") } pp.checkYieldAwaitInDefaultParams = function() { @@ -634,6 +654,12 @@ pp.checkYieldAwaitInDefaultParams = function() { this.raise(this.awaitPos, "Await expression cannot be a default value") } +pp.isSimpleAssignTarget = function(expr) { + if (expr.type === "ParenthesizedExpression") + return this.isSimpleAssignTarget(expr.expression) + return expr.type === "Identifier" || expr.type === "MemberExpression" +} + var pp$1 = Parser.prototype // ### Statement parsing @@ -646,15 +672,11 @@ var pp$1 = Parser.prototype pp$1.parseTopLevel = function(node) { var this$1 = this; - var first = true, exports = {} + var exports = {} if (!node.body) node.body = [] while (this.type !== tt.eof) { var stmt = this$1.parseStatement(true, true, exports) node.body.push(stmt) - if (first) { - if (this$1.isUseStrict(stmt)) this$1.setStrict(true) - first = false - } } this.next() if (this.options.ecmaVersion >= 6) { @@ -672,7 +694,8 @@ pp$1.isLet = function() { var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next) if (nextCh === 91 || nextCh == 123) return true // '{' and '[' if (isIdentifierStart(nextCh, true)) { - for (var pos = next + 1; isIdentifierChar(this.input.charCodeAt(pos), true); ++pos) {} + var pos = next + 1 + while (isIdentifierChar(this.input.charCodeAt(pos), true)) ++pos var ident = this.input.slice(next, pos) if (!this.isKeyword(ident)) return true } @@ -779,7 +802,8 @@ pp$1.parseBreakContinueStatement = function(node, keyword) { // Verify that there is an actual destination to break or // continue to. - for (var i = 0; i < this.labels.length; ++i) { + var i = 0 + for (; i < this.labels.length; ++i) { var lab = this$1.labels[i] if (node.label == null || lab.name === node.label.name) { if (lab.kind != null && (isBreak || lab.kind === "loop")) break @@ -821,6 +845,7 @@ pp$1.parseDoStatement = function(node) { pp$1.parseForStatement = function(node) { this.next() this.labels.push(loopLabel) + this.enterLexicalScope() this.expect(tt.parenL) if (this.type === tt.semi) return this.parseFor(node, null) var isLet = this.isLet() @@ -837,9 +862,9 @@ pp$1.parseForStatement = function(node) { var refDestructuringErrors = new DestructuringErrors var init = this.parseExpression(true, refDestructuringErrors) if (this.type === tt._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) { - this.checkPatternErrors(refDestructuringErrors, true) this.toAssignable(init) this.checkLVal(init) + this.checkPatternErrors(refDestructuringErrors, true) return this.parseForIn(node, init) } else { this.checkExpressionErrors(refDestructuringErrors, true) @@ -887,12 +912,14 @@ pp$1.parseSwitchStatement = function(node) { node.cases = [] this.expect(tt.braceL) this.labels.push(switchLabel) + this.enterLexicalScope() // Statements under must be grouped (by label) in SwitchCase // nodes. `cur` is used to keep the node that we are currently // adding statements to. - for (var cur, sawDefault = false; this.type != tt.braceR;) { + var cur + for (var sawDefault = false; this.type != tt.braceR;) { if (this$1.type === tt._case || this$1.type === tt._default) { var isCase = this$1.type === tt._case if (cur) this$1.finishNode(cur, "SwitchCase") @@ -912,6 +939,7 @@ pp$1.parseSwitchStatement = function(node) { cur.consequent.push(this$1.parseStatement(true)) } } + this.exitLexicalScope() if (cur) this.finishNode(cur, "SwitchCase") this.next() // Closing brace this.labels.pop() @@ -940,9 +968,11 @@ pp$1.parseTryStatement = function(node) { this.next() this.expect(tt.parenL) clause.param = this.parseBindingAtom() - this.checkLVal(clause.param, true) + this.enterLexicalScope() + this.checkLVal(clause.param, "let") this.expect(tt.parenR) - clause.body = this.parseBlock() + clause.body = this.parseBlock(false) + this.exitLexicalScope() node.handler = this.finishNode(clause, "CatchClause") } node.finalizer = this.eat(tt._finally) ? this.parseBlock() : null @@ -995,6 +1025,10 @@ pp$1.parseLabeledStatement = function(node, maybeName, expr) { } this.labels.push({name: maybeName, kind: kind, statementStart: this.start}) node.body = this.parseStatement(true) + if (node.body.type == "ClassDeclaration" || + node.body.type == "VariableDeclaration" && node.body.kind != "var" || + node.body.type == "FunctionDeclaration" && (this.strict || node.body.generator)) + this.raiseRecoverable(node.body.start, "Invalid labeled declaration") this.labels.pop() node.label = expr return this.finishNode(node, "LabeledStatement") @@ -1010,22 +1044,23 @@ pp$1.parseExpressionStatement = function(node, expr) { // strict"` declarations when `allowStrict` is true (used for // function bodies). -pp$1.parseBlock = function(allowStrict) { +pp$1.parseBlock = function(createNewLexicalScope) { var this$1 = this; + if ( createNewLexicalScope === void 0 ) createNewLexicalScope = true; - var node = this.startNode(), first = true, oldStrict + var node = this.startNode() node.body = [] this.expect(tt.braceL) + if (createNewLexicalScope) { + this.enterLexicalScope() + } while (!this.eat(tt.braceR)) { var stmt = this$1.parseStatement(true) node.body.push(stmt) - if (first && allowStrict && this$1.isUseStrict(stmt)) { - oldStrict = this$1.strict - this$1.setStrict(this$1.strict = true) - } - first = false } - if (oldStrict === false) this.setStrict(false) + if (createNewLexicalScope) { + this.exitLexicalScope() + } return this.finishNode(node, "BlockStatement") } @@ -1040,6 +1075,7 @@ pp$1.parseFor = function(node, init) { this.expect(tt.semi) node.update = this.type === tt.parenR ? null : this.parseExpression() this.expect(tt.parenR) + this.exitLexicalScope() node.body = this.parseStatement(false) this.labels.pop() return this.finishNode(node, "ForStatement") @@ -1054,6 +1090,7 @@ pp$1.parseForIn = function(node, init) { node.left = init node.right = this.parseExpression() this.expect(tt.parenR) + this.exitLexicalScope() node.body = this.parseStatement(false) this.labels.pop() return this.finishNode(node, type) @@ -1068,7 +1105,7 @@ pp$1.parseVar = function(node, isFor, kind) { node.kind = kind for (;;) { var decl = this$1.startNode() - this$1.parseVarId(decl) + this$1.parseVarId(decl, kind) if (this$1.eat(tt.eq)) { decl.init = this$1.parseMaybeAssign(isFor) } else if (kind === "const" && !(this$1.type === tt._in || (this$1.options.ecmaVersion >= 6 && this$1.isContextual("of")))) { @@ -1084,9 +1121,9 @@ pp$1.parseVar = function(node, isFor, kind) { return node } -pp$1.parseVarId = function(decl) { - decl.id = this.parseBindingAtom() - this.checkLVal(decl.id, true) +pp$1.parseVarId = function(decl, kind) { + decl.id = this.parseBindingAtom(kind) + this.checkLVal(decl.id, kind, false) } // Parse a function declaration or literal (depending on the @@ -1099,17 +1136,25 @@ pp$1.parseFunction = function(node, isStatement, allowExpressionBody, isAsync) { if (this.options.ecmaVersion >= 8) node.async = !!isAsync - if (isStatement) - node.id = this.parseIdent() + if (isStatement) { + node.id = isStatement === "nullableID" && this.type != tt.name ? null : this.parseIdent() + if (node.id) { + this.checkLVal(node.id, "var") + } + } - var oldInGen = this.inGenerator, oldInAsync = this.inAsync, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos + var oldInGen = this.inGenerator, oldInAsync = this.inAsync, + oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction this.inGenerator = node.generator this.inAsync = node.async this.yieldPos = 0 this.awaitPos = 0 + this.inFunction = true + this.enterFunctionScope() + + if (!isStatement) + node.id = this.type == tt.name ? this.parseIdent() : null - if (!isStatement && this.type === tt.name) - node.id = this.parseIdent() this.parseFunctionParams(node) this.parseFunctionBody(node, allowExpressionBody) @@ -1117,6 +1162,7 @@ pp$1.parseFunction = function(node, isStatement, allowExpressionBody, isAsync) { this.inAsync = oldInAsync this.yieldPos = oldYieldPos this.awaitPos = oldAwaitPos + this.inFunction = oldInFunc return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression") } @@ -1133,6 +1179,7 @@ pp$1.parseClass = function(node, isStatement) { var this$1 = this; this.next() + this.parseClassId(node, isStatement) this.parseClassSuper(node) var classBody = this.startNode() @@ -1202,7 +1249,7 @@ pp$1.parseClassMethod = function(classBody, method, isGenerator, isAsync) { } pp$1.parseClassId = function(node, isStatement) { - node.id = this.type === tt.name ? this.parseIdent() : isStatement ? this.unexpected() : null + node.id = this.type === tt.name ? this.parseIdent() : isStatement === true ? this.unexpected() : null } pp$1.parseClassSuper = function(node) { @@ -1224,20 +1271,19 @@ pp$1.parseExport = function(node, exports) { } if (this.eat(tt._default)) { // export default ... this.checkExport(exports, "default", this.lastTokStart) - var parens = this.type == tt.parenL - var expr = this.parseMaybeAssign() - var needsSemi = true - if (!parens && (expr.type == "FunctionExpression" || - expr.type == "ClassExpression")) { - needsSemi = false - if (expr.id) { - expr.type = expr.type == "FunctionExpression" - ? "FunctionDeclaration" - : "ClassDeclaration" - } + var isAsync + if (this.type === tt._function || (isAsync = this.isAsyncFunction())) { + var fNode = this.startNode() + this.next() + if (isAsync) this.next() + node.declaration = this.parseFunction(fNode, "nullableID", false, isAsync) + } else if (this.type === tt._class) { + var cNode = this.startNode() + node.declaration = this.parseClass(cNode, "nullableID") + } else { + node.declaration = this.parseMaybeAssign() + this.semicolon() } - node.declaration = expr - if (needsSemi) this.semicolon() return this.finishNode(node, "ExportDefaultDeclaration") } // export var|const|let|function|class ... @@ -1271,7 +1317,7 @@ pp$1.parseExport = function(node, exports) { pp$1.checkExport = function(exports, name, pos) { if (!exports) return - if (Object.prototype.hasOwnProperty.call(exports, name)) + if (has(exports, name)) this.raiseRecoverable(pos, "Duplicate export '" + name + "'") exports[name] = true } @@ -1305,12 +1351,12 @@ pp$1.checkVariableExport = function(exports, decls) { } pp$1.shouldParseExportStatement = function() { - return this.type.keyword === "var" - || this.type.keyword === "const" - || this.type.keyword === "class" - || this.type.keyword === "function" - || this.isLet() - || this.isAsyncFunction() + return this.type.keyword === "var" || + this.type.keyword === "const" || + this.type.keyword === "class" || + this.type.keyword === "function" || + this.isLet() || + this.isAsyncFunction() } // Parses a comma-separated list of module exports. @@ -1328,7 +1374,7 @@ pp$1.parseExportSpecifiers = function(exports) { } else first = false var node = this$1.startNode() - node.local = this$1.parseIdent(this$1.type === tt._default) + node.local = this$1.parseIdent(true) node.exported = this$1.eatContextual("as") ? this$1.parseIdent(true) : node.local this$1.checkExport(exports, node.exported.name, node.exported.start) nodes.push(this$1.finishNode(node, "ExportSpecifier")) @@ -1363,7 +1409,7 @@ pp$1.parseImportSpecifiers = function() { // import defaultObj, { x, y as z } from '...' var node = this.startNode() node.local = this.parseIdent() - this.checkLVal(node.local, true) + this.checkLVal(node.local, "let") nodes.push(this.finishNode(node, "ImportDefaultSpecifier")) if (!this.eat(tt.comma)) return nodes } @@ -1372,7 +1418,7 @@ pp$1.parseImportSpecifiers = function() { this.next() this.expectContextual("as") node$1.local = this.parseIdent() - this.checkLVal(node$1.local, true) + this.checkLVal(node$1.local, "let") nodes.push(this.finishNode(node$1, "ImportNamespaceSpecifier")) return nodes } @@ -1392,7 +1438,7 @@ pp$1.parseImportSpecifiers = function() { if (this$1.isKeyword(node$2.local.name)) this$1.unexpected(node$2.local.start) if (this$1.reservedWordsStrict.test(node$2.local.name)) this$1.raiseRecoverable(node$2.local.start, "The keyword '" + node$2.local.name + "' is reserved") } - this$1.checkLVal(node$2.local, true) + this$1.checkLVal(node$2.local, "let") nodes.push(this$1.finishNode(node$2, "ImportSpecifier")) } return nodes @@ -1408,7 +1454,7 @@ pp$2.toAssignable = function(node, isBinding) { if (this.options.ecmaVersion >= 6 && node) { switch (node.type) { - case "Identifier": + case "Identifier": if (this.inAsync && node.name === "await") this.raise(node.start, "Can not use 'await' as identifier inside an async function") break @@ -1574,51 +1620,68 @@ pp$2.parseMaybeDefault = function(startPos, startLoc, left) { // Verify that a node is an lval — something that can be assigned // to. +// bindingType can be either: +// 'var' indicating that the lval creates a 'var' binding +// 'let' indicating that the lval creates a lexical ('let' or 'const') binding +// 'none' indicating that the binding should be checked for illegal identifiers, but not for duplicate references -pp$2.checkLVal = function(expr, isBinding, checkClashes) { +pp$2.checkLVal = function(expr, bindingType, checkClashes) { var this$1 = this; switch (expr.type) { case "Identifier": if (this.strict && this.reservedWordsStrictBind.test(expr.name)) - this.raiseRecoverable(expr.start, (isBinding ? "Binding " : "Assigning to ") + expr.name + " in strict mode") + this.raiseRecoverable(expr.start, (bindingType ? "Binding " : "Assigning to ") + expr.name + " in strict mode") if (checkClashes) { if (has(checkClashes, expr.name)) this.raiseRecoverable(expr.start, "Argument name clash") checkClashes[expr.name] = true } + if (bindingType && bindingType !== "none") { + if ( + bindingType === "var" && !this.canDeclareVarName(expr.name) || + bindingType !== "var" && !this.canDeclareLexicalName(expr.name) + ) { + this.raiseRecoverable(expr.start, ("Identifier '" + (expr.name) + "' has already been declared")) + } + if (bindingType === "var") { + this.declareVarName(expr.name) + } else { + this.declareLexicalName(expr.name) + } + } break case "MemberExpression": - if (isBinding) this.raiseRecoverable(expr.start, (isBinding ? "Binding" : "Assigning to") + " member expression") + if (bindingType) this.raiseRecoverable(expr.start, (bindingType ? "Binding" : "Assigning to") + " member expression") break case "ObjectPattern": for (var i = 0; i < expr.properties.length; i++) - this$1.checkLVal(expr.properties[i].value, isBinding, checkClashes) + this$1.checkLVal(expr.properties[i].value, bindingType, checkClashes) break case "ArrayPattern": for (var i$1 = 0; i$1 < expr.elements.length; i$1++) { var elem = expr.elements[i$1] - if (elem) this$1.checkLVal(elem, isBinding, checkClashes) + if (elem) this$1.checkLVal(elem, bindingType, checkClashes) } break case "AssignmentPattern": - this.checkLVal(expr.left, isBinding, checkClashes) + this.checkLVal(expr.left, bindingType, checkClashes) break case "RestElement": - this.checkLVal(expr.argument, isBinding, checkClashes) + this.checkLVal(expr.argument, bindingType, checkClashes) break case "ParenthesizedExpression": - this.checkLVal(expr.expression, isBinding, checkClashes) + this.checkLVal(expr.expression, bindingType, checkClashes) break default: - this.raise(expr.start, (isBinding ? "Binding" : "Assigning to") + " rvalue") + this.raise(expr.start, (bindingType ? "Binding" : "Assigning to") + " rvalue") } } @@ -1668,8 +1731,13 @@ pp$3.checkPropClash = function(prop, propHash) { name = "$" + name var other = propHash[name] if (other) { - var isGetSet = kind !== "init" - if ((this.strict || isGetSet) && other[kind] || !(isGetSet ^ other.init)) + var redefinition + if (kind === "init") { + redefinition = this.strict && other.init || other.get || other.set + } else { + redefinition = other.init || other[kind] + } + if (redefinition) this.raiseRecoverable(key.start, "Redefinition of property") } else { other = propHash[name] = { @@ -1716,11 +1784,16 @@ pp$3.parseExpression = function(noIn, refDestructuringErrors) { pp$3.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) { if (this.inGenerator && this.isContextual("yield")) return this.parseYield() - var ownDestructuringErrors = false - if (!refDestructuringErrors) { + var ownDestructuringErrors = false, oldParenAssign = -1, oldTrailingComma = -1 + if (refDestructuringErrors) { + oldParenAssign = refDestructuringErrors.parenthesizedAssign + oldTrailingComma = refDestructuringErrors.trailingComma + refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = -1 + } else { refDestructuringErrors = new DestructuringErrors ownDestructuringErrors = true } + var startPos = this.start, startLoc = this.startLoc if (this.type == tt.parenL || this.type == tt.name) this.potentialArrowAt = this.start @@ -1732,7 +1805,7 @@ pp$3.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) { var node = this.startNodeAt(startPos, startLoc) node.operator = this.value node.left = this.type === tt.eq ? this.toAssignable(left) : left - refDestructuringErrors.shorthandAssign = 0 // reset because shorthand default was used correctly + refDestructuringErrors.shorthandAssign = -1 // reset because shorthand default was used correctly this.checkLVal(left) this.next() node.right = this.parseMaybeAssign(noIn) @@ -1740,6 +1813,8 @@ pp$3.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) { } else { if (ownDestructuringErrors) this.checkExpressionErrors(refDestructuringErrors, true) } + if (oldParenAssign > -1) refDestructuringErrors.parenthesizedAssign = oldParenAssign + if (oldTrailingComma > -1) refDestructuringErrors.trailingComma = oldTrailingComma return left } @@ -1766,7 +1841,7 @@ pp$3.parseExprOps = function(noIn, refDestructuringErrors) { var startPos = this.start, startLoc = this.startLoc var expr = this.parseMaybeUnary(refDestructuringErrors, false) if (this.checkExpressionErrors(refDestructuringErrors)) return expr - return this.parseExprOp(expr, startPos, startLoc, -1, noIn) + return expr.start == startPos && expr.type === "ArrowFunctionExpression" ? expr : this.parseExprOp(expr, startPos, startLoc, -1, noIn) } // Parse binary operators with the operator precedence parsing @@ -1848,34 +1923,34 @@ pp$3.parseExprSubscripts = function(refDestructuringErrors) { var expr = this.parseExprAtom(refDestructuringErrors) var skipArrowSubscripts = expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")" if (this.checkExpressionErrors(refDestructuringErrors) || skipArrowSubscripts) return expr - return this.parseSubscripts(expr, startPos, startLoc) + var result = this.parseSubscripts(expr, startPos, startLoc) + if (refDestructuringErrors && result.type === "MemberExpression") { + if (refDestructuringErrors.parenthesizedAssign >= result.start) refDestructuringErrors.parenthesizedAssign = -1 + if (refDestructuringErrors.parenthesizedBind >= result.start) refDestructuringErrors.parenthesizedBind = -1 + } + return result } pp$3.parseSubscripts = function(base, startPos, startLoc, noCalls) { var this$1 = this; - for (;;) { - var maybeAsyncArrow = this$1.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" && !this$1.canInsertSemicolon() - if (this$1.eat(tt.dot)) { + var maybeAsyncArrow = this.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" && + this.lastTokEnd == base.end && !this.canInsertSemicolon() + for (var computed;;) { + if ((computed = this$1.eat(tt.bracketL)) || this$1.eat(tt.dot)) { var node = this$1.startNodeAt(startPos, startLoc) node.object = base - node.property = this$1.parseIdent(true) - node.computed = false + node.property = computed ? this$1.parseExpression() : this$1.parseIdent(true) + node.computed = !!computed + if (computed) this$1.expect(tt.bracketR) base = this$1.finishNode(node, "MemberExpression") - } else if (this$1.eat(tt.bracketL)) { - var node$1 = this$1.startNodeAt(startPos, startLoc) - node$1.object = base - node$1.property = this$1.parseExpression() - node$1.computed = true - this$1.expect(tt.bracketR) - base = this$1.finishNode(node$1, "MemberExpression") } else if (!noCalls && this$1.eat(tt.parenL)) { var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this$1.yieldPos, oldAwaitPos = this$1.awaitPos this$1.yieldPos = 0 this$1.awaitPos = 0 var exprList = this$1.parseExprList(tt.parenR, this$1.options.ecmaVersion >= 8, false, refDestructuringErrors) if (maybeAsyncArrow && !this$1.canInsertSemicolon() && this$1.eat(tt.arrow)) { - this$1.checkPatternErrors(refDestructuringErrors, true) + this$1.checkPatternErrors(refDestructuringErrors, false) this$1.checkYieldAwaitInDefaultParams() this$1.yieldPos = oldYieldPos this$1.awaitPos = oldAwaitPos @@ -1884,15 +1959,15 @@ pp$3.parseSubscripts = function(base, startPos, startLoc, noCalls) { this$1.checkExpressionErrors(refDestructuringErrors, true) this$1.yieldPos = oldYieldPos || this$1.yieldPos this$1.awaitPos = oldAwaitPos || this$1.awaitPos - var node$2 = this$1.startNodeAt(startPos, startLoc) - node$2.callee = base - node$2.arguments = exprList - base = this$1.finishNode(node$2, "CallExpression") + var node$1 = this$1.startNodeAt(startPos, startLoc) + node$1.callee = base + node$1.arguments = exprList + base = this$1.finishNode(node$1, "CallExpression") } else if (this$1.type === tt.backQuote) { - var node$3 = this$1.startNodeAt(startPos, startLoc) - node$3.tag = base - node$3.quasi = this$1.parseTemplate() - base = this$1.finishNode(node$3, "TaggedTemplateExpression") + var node$2 = this$1.startNodeAt(startPos, startLoc) + node$2.tag = base + node$2.quasi = this$1.parseTemplate() + base = this$1.finishNode(node$2, "TaggedTemplateExpression") } else { return base } @@ -1951,7 +2026,14 @@ pp$3.parseExprAtom = function(refDestructuringErrors) { return this.finishNode(node, "Literal") case tt.parenL: - return this.parseParenAndDistinguishExpression(canBeArrow) + var start = this.start, expr = this.parseParenAndDistinguishExpression(canBeArrow) + if (refDestructuringErrors) { + if (refDestructuringErrors.parenthesizedAssign < 0 && !this.isSimpleAssignTarget(expr)) + refDestructuringErrors.parenthesizedAssign = start + if (refDestructuringErrors.parenthesizedBind < 0) + refDestructuringErrors.parenthesizedBind = start + } + return expr case tt.bracketL: node = this.startNode() @@ -2029,7 +2111,7 @@ pp$3.parseParenAndDistinguishExpression = function(canBeArrow) { this.expect(tt.parenR) if (canBeArrow && !this.canInsertSemicolon() && this.eat(tt.arrow)) { - this.checkPatternErrors(refDestructuringErrors, true) + this.checkPatternErrors(refDestructuringErrors, false) this.checkYieldAwaitInDefaultParams() if (innerParenStart) this.unexpected(innerParenStart) this.yieldPos = oldYieldPos @@ -2103,7 +2185,7 @@ pp$3.parseNew = function() { pp$3.parseTemplateElement = function() { var elem = this.startNode() elem.value = { - raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, '\n'), + raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, "\n"), cooked: this.value } this.next() @@ -2210,7 +2292,7 @@ pp$3.parsePropertyValue = function(prop, isPattern, isGenerator, isAsync, startP if (isPattern) { prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key) } else if (this.type === tt.eq && refDestructuringErrors) { - if (!refDestructuringErrors.shorthandAssign) + if (refDestructuringErrors.shorthandAssign < 0) refDestructuringErrors.shorthandAssign = this.start prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key) } else { @@ -2249,7 +2331,8 @@ pp$3.initFunction = function(node) { // Parse object or class method. pp$3.parseMethod = function(isGenerator, isAsync) { - var node = this.startNode(), oldInGen = this.inGenerator, oldInAsync = this.inAsync, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos + var node = this.startNode(), oldInGen = this.inGenerator, oldInAsync = this.inAsync, + oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction this.initFunction(node) if (this.options.ecmaVersion >= 6) @@ -2261,6 +2344,8 @@ pp$3.parseMethod = function(isGenerator, isAsync) { this.inAsync = node.async this.yieldPos = 0 this.awaitPos = 0 + this.inFunction = true + this.enterFunctionScope() this.expect(tt.parenL) node.params = this.parseBindingList(tt.parenR, false, this.options.ecmaVersion >= 8) @@ -2271,14 +2356,17 @@ pp$3.parseMethod = function(isGenerator, isAsync) { this.inAsync = oldInAsync this.yieldPos = oldYieldPos this.awaitPos = oldAwaitPos + this.inFunction = oldInFunc return this.finishNode(node, "FunctionExpression") } // Parse arrow function expression with given parameters. pp$3.parseArrowExpression = function(node, params, isAsync) { - var oldInGen = this.inGenerator, oldInAsync = this.inAsync, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos + var oldInGen = this.inGenerator, oldInAsync = this.inAsync, + oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction + this.enterFunctionScope() this.initFunction(node) if (this.options.ecmaVersion >= 8) node.async = !!isAsync @@ -2287,6 +2375,7 @@ pp$3.parseArrowExpression = function(node, params, isAsync) { this.inAsync = node.async this.yieldPos = 0 this.awaitPos = 0 + this.inFunction = true node.params = this.toAssignableList(params, true) this.parseFunctionBody(node, true) @@ -2295,6 +2384,7 @@ pp$3.parseArrowExpression = function(node, params, isAsync) { this.inAsync = oldInAsync this.yieldPos = oldYieldPos this.awaitPos = oldAwaitPos + this.inFunction = oldInFunc return this.finishNode(node, "ArrowFunctionExpression") } @@ -2302,37 +2392,42 @@ pp$3.parseArrowExpression = function(node, params, isAsync) { pp$3.parseFunctionBody = function(node, isArrowFunction) { var isExpression = isArrowFunction && this.type !== tt.braceL + var oldStrict = this.strict, useStrict = false if (isExpression) { node.body = this.parseMaybeAssign() node.expression = true + this.checkParams(node, false) } else { + var nonSimple = this.options.ecmaVersion >= 7 && !this.isSimpleParamList(node.params) + if (!oldStrict || nonSimple) { + useStrict = this.strictDirective(this.end) + // If this is a strict mode function, verify that argument names + // are not repeated, and it does not try to bind the words `eval` + // or `arguments`. + if (useStrict && nonSimple) + this.raiseRecoverable(node.start, "Illegal 'use strict' directive in function with non-simple parameter list") + } // Start a new scope with regard to labels and the `inFunction` // flag (restore them to their old value afterwards). - var oldInFunc = this.inFunction, oldLabels = this.labels - this.inFunction = true; this.labels = [] - node.body = this.parseBlock(true) + var oldLabels = this.labels + this.labels = [] + if (useStrict) this.strict = true + + // Add the params to varDeclaredNames to ensure that an error is thrown + // if a let/const declaration in the function clashes with one of the params. + this.checkParams(node, !oldStrict && !useStrict && !isArrowFunction && this.isSimpleParamList(node.params)) + node.body = this.parseBlock(false) node.expression = false - this.inFunction = oldInFunc; this.labels = oldLabels + this.labels = oldLabels } + this.exitFunctionScope() - // If this is a strict mode function, verify that argument names - // are not repeated, and it does not try to bind the words `eval` - // or `arguments`. - var useStrict = (!isExpression && node.body.body.length && this.isUseStrict(node.body.body[0])) ? node.body.body[0] : null - if (useStrict && this.options.ecmaVersion >= 7 && !this.isSimpleParamList(node.params)) - this.raiseRecoverable(useStrict.start, "Illegal 'use strict' directive in function with non-simple parameter list") - - if (this.strict || useStrict) { - var oldStrict = this.strict - this.strict = true - if (node.id) - this.checkLVal(node.id, true) - this.checkParams(node) - this.strict = oldStrict - } else if (isArrowFunction || !this.isSimpleParamList(node.params)) { - this.checkParams(node) + if (this.strict && node.id) { + // Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval' + this.checkLVal(node.id, "none") } + this.strict = oldStrict } pp$3.isSimpleParamList = function(params) { @@ -2344,11 +2439,11 @@ pp$3.isSimpleParamList = function(params) { // Checks function params for various disallowed patterns such as using "eval" // or "arguments" and duplicate parameters. -pp$3.checkParams = function(node) { +pp$3.checkParams = function(node, allowDuplicates) { var this$1 = this; var nameHash = {} - for (var i = 0; i < node.params.length; i++) this$1.checkLVal(node.params[i], true, nameHash) + for (var i = 0; i < node.params.length; i++) this$1.checkLVal(node.params[i], "var", allowDuplicates ? null : nameHash) } // Parses a comma-separated list of expressions, and returns them as @@ -2372,11 +2467,11 @@ pp$3.parseExprList = function(close, allowTrailingComma, allowEmpty, refDestruct elt = null else if (this$1.type === tt.ellipsis) { elt = this$1.parseSpread(refDestructuringErrors) - if (this$1.type === tt.comma && refDestructuringErrors && !refDestructuringErrors.trailingComma) { + if (refDestructuringErrors && this$1.type === tt.comma && refDestructuringErrors.trailingComma < 0) refDestructuringErrors.trailingComma = this$1.start - } - } else + } else { elt = this$1.parseMaybeAssign(false, refDestructuringErrors) + } elts.push(elt) } return elts @@ -2458,6 +2553,82 @@ pp$4.curPosition = function() { } } +var pp$5 = Parser.prototype + +// Object.assign polyfill +var assign = Object.assign || function(target) { + var sources = [], len = arguments.length - 1; + while ( len-- > 0 ) sources[ len ] = arguments[ len + 1 ]; + + for (var i = 0; i < sources.length; i++) { + var source = sources[i] + for (var key in source) { + if (has(source, key)) { + target[key] = source[key] + } + } + } + return target +} + +// The functions in this module keep track of declared variables in the current scope in order to detect duplicate variable names. + +pp$5.enterFunctionScope = function() { + // var: a hash of var-declared names in the current lexical scope + // lexical: a hash of lexically-declared names in the current lexical scope + // childVar: a hash of var-declared names in all child lexical scopes of the current lexical scope (within the current function scope) + // parentLexical: a hash of lexically-declared names in all parent lexical scopes of the current lexical scope (within the current function scope) + this.scopeStack.push({var: {}, lexical: {}, childVar: {}, parentLexical: {}}) +} + +pp$5.exitFunctionScope = function() { + this.scopeStack.pop() +} + +pp$5.enterLexicalScope = function() { + var parentScope = this.scopeStack[this.scopeStack.length - 1] + var childScope = {var: {}, lexical: {}, childVar: {}, parentLexical: {}} + + this.scopeStack.push(childScope) + assign(childScope.parentLexical, parentScope.lexical, parentScope.parentLexical) +} + +pp$5.exitLexicalScope = function() { + var childScope = this.scopeStack.pop() + var parentScope = this.scopeStack[this.scopeStack.length - 1] + + assign(parentScope.childVar, childScope.var, childScope.childVar) +} + +/** + * A name can be declared with `var` if there are no variables with the same name declared with `let`/`const` + * in the current lexical scope or any of the parent lexical scopes in this function. + */ +pp$5.canDeclareVarName = function(name) { + var currentScope = this.scopeStack[this.scopeStack.length - 1] + + return !has(currentScope.lexical, name) && !has(currentScope.parentLexical, name) +} + +/** + * A name can be declared with `let`/`const` if there are no variables with the same name declared with `let`/`const` + * in the current scope, and there are no variables with the same name declared with `var` in the current scope or in + * any child lexical scopes in this function. + */ +pp$5.canDeclareLexicalName = function(name) { + var currentScope = this.scopeStack[this.scopeStack.length - 1] + + return !has(currentScope.lexical, name) && !has(currentScope.var, name) && !has(currentScope.childVar, name) +} + +pp$5.declareVarName = function(name) { + this.scopeStack[this.scopeStack.length - 1].var[name] = true +} + +pp$5.declareLexicalName = function(name) { + this.scopeStack[this.scopeStack.length - 1].lexical[name] = true +} + var Node = function Node(parser, pos, loc) { this.type = "" this.start = pos @@ -2472,13 +2643,13 @@ var Node = function Node(parser, pos, loc) { // Start an AST node, attaching a start offset. -var pp$5 = Parser.prototype +var pp$6 = Parser.prototype -pp$5.startNode = function() { +pp$6.startNode = function() { return new Node(this, this.start, this.startLoc) } -pp$5.startNodeAt = function(pos, loc) { +pp$6.startNodeAt = function(pos, loc) { return new Node(this, pos, loc) } @@ -2494,13 +2665,13 @@ function finishNodeAt(node, type, pos, loc) { return node } -pp$5.finishNode = function(node, type) { +pp$6.finishNode = function(node, type) { return finishNodeAt.call(this, node, type, this.lastTokEnd, this.lastTokEndLoc) } // Finish node at given position -pp$5.finishNodeAt = function(node, type, pos, loc) { +pp$6.finishNodeAt = function(node, type, pos, loc) { return finishNodeAt.call(this, node, type, pos, loc) } @@ -2508,11 +2679,12 @@ pp$5.finishNodeAt = function(node, type, pos, loc) { // given point in the program is loosely based on sweet.js' approach. // See https://github.com/mozilla/sweet.js/wiki/design -var TokContext = function TokContext(token, isExpr, preserveSpace, override) { +var TokContext = function TokContext(token, isExpr, preserveSpace, override, generator) { this.token = token this.isExpr = !!isExpr this.preserveSpace = !!preserveSpace this.override = override + this.generator = !!generator }; var types = { @@ -2522,16 +2694,18 @@ var types = { p_stat: new TokContext("(", false), p_expr: new TokContext("(", true), q_tmpl: new TokContext("`", true, true, function (p) { return p.readTmplToken(); }), - f_expr: new TokContext("function", true) + f_expr: new TokContext("function", true), + f_expr_gen: new TokContext("function", true, false, null, true), + f_gen: new TokContext("function", false, false, null, true) } -var pp$6 = Parser.prototype +var pp$7 = Parser.prototype -pp$6.initialContext = function() { +pp$7.initialContext = function() { return [types.b_stat] } -pp$6.braceIsBlock = function(prevType) { +pp$7.braceIsBlock = function(prevType) { if (prevType === tt.colon) { var parent = this.curContext() if (parent === types.b_stat || parent === types.b_expr) @@ -2539,14 +2713,22 @@ pp$6.braceIsBlock = function(prevType) { } if (prevType === tt._return) return lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) - if (prevType === tt._else || prevType === tt.semi || prevType === tt.eof || prevType === tt.parenR) + if (prevType === tt._else || prevType === tt.semi || prevType === tt.eof || prevType === tt.parenR || prevType == tt.arrow) return true if (prevType == tt.braceL) return this.curContext() === types.b_stat return !this.exprAllowed } -pp$6.updateContext = function(prevType) { +pp$7.inGeneratorContext = function() { + var this$1 = this; + + for (var i = this.context.length - 1; i >= 0; i--) + if (this$1.context[i].generator) return true + return false +} + +pp$7.updateContext = function(prevType) { var update, type = this.type if (type.keyword && prevType == tt.dot) this.exprAllowed = false @@ -2563,8 +2745,8 @@ tt.parenR.updateContext = tt.braceR.updateContext = function() { this.exprAllowed = true return } - var out = this.context.pop() - if (out === types.b_stat && this.curContext() === types.f_expr) { + var out = this.context.pop(), cur + if (out === types.b_stat && (cur = this.curContext()) && cur.token === "function") { this.context.pop() this.exprAllowed = false } else if (out === types.b_tmpl) { @@ -2609,6 +2791,26 @@ tt.backQuote.updateContext = function() { this.exprAllowed = false } +tt.star.updateContext = function(prevType) { + if (prevType == tt._function) { + if (this.curContext() === types.f_expr) + this.context[this.context.length - 1] = types.f_expr_gen + else + this.context.push(types.f_gen) + } + this.exprAllowed = true +} + +tt.name.updateContext = function(prevType) { + var allowed = false + if (this.options.ecmaVersion >= 6) { + if (this.value == "of" && !this.exprAllowed || + this.value == "yield" && this.inGeneratorContext()) + allowed = true + } + this.exprAllowed = allowed +} + // Object type used to represent tokens. Note that normally, tokens // simply exist as properties on the parser object. This is only // used for the onToken callback and the external tokenizer. @@ -2626,14 +2828,14 @@ var Token = function Token(p) { // ## Tokenizer -var pp$7 = Parser.prototype +var pp$8 = Parser.prototype // Are we running under Rhino? var isRhino = typeof Packages == "object" && Object.prototype.toString.call(Packages) == "[object JavaPackage]" // Move to the next token -pp$7.next = function() { +pp$8.next = function() { if (this.options.onToken) this.options.onToken(new Token(this)) @@ -2644,50 +2846,38 @@ pp$7.next = function() { this.nextToken() } -pp$7.getToken = function() { +pp$8.getToken = function() { this.next() return new Token(this) } // If we're in an ES6 environment, make parsers iterable if (typeof Symbol !== "undefined") - pp$7[Symbol.iterator] = function () { - var self = this - return {next: function () { - var token = self.getToken() - return { - done: token.type === tt.eof, - value: token + pp$8[Symbol.iterator] = function() { + var this$1 = this; + + return { + next: function () { + var token = this$1.getToken() + return { + done: token.type === tt.eof, + value: token + } } - }} + } } // Toggle strict mode. Re-reads the next number or string to please // pedantic tests (`"use strict"; 010;` should fail). -pp$7.setStrict = function(strict) { - var this$1 = this; - - this.strict = strict - if (this.type !== tt.num && this.type !== tt.string) return - this.pos = this.start - if (this.options.locations) { - while (this.pos < this.lineStart) { - this$1.lineStart = this$1.input.lastIndexOf("\n", this$1.lineStart - 2) + 1 - --this$1.curLine - } - } - this.nextToken() -} - -pp$7.curContext = function() { +pp$8.curContext = function() { return this.context[this.context.length - 1] } // Read a single token, updating the parser object's token-related // properties. -pp$7.nextToken = function() { +pp$8.nextToken = function() { var curContext = this.curContext() if (!curContext || !curContext.preserveSpace) this.skipSpace() @@ -2699,7 +2889,7 @@ pp$7.nextToken = function() { else this.readToken(this.fullCharCodeAtPos()) } -pp$7.readToken = function(code) { +pp$8.readToken = function(code) { // Identifier or keyword. '\uXXXX' sequences are allowed in // identifiers, so '\' also dispatches to that. if (isIdentifierStart(code, this.options.ecmaVersion >= 6) || code === 92 /* '\' */) @@ -2708,14 +2898,14 @@ pp$7.readToken = function(code) { return this.getTokenFromCode(code) } -pp$7.fullCharCodeAtPos = function() { +pp$8.fullCharCodeAtPos = function() { var code = this.input.charCodeAt(this.pos) if (code <= 0xd7ff || code >= 0xe000) return code var next = this.input.charCodeAt(this.pos + 1) return (code << 10) + next - 0x35fdc00 } -pp$7.skipBlockComment = function() { +pp$8.skipBlockComment = function() { var this$1 = this; var startLoc = this.options.onComment && this.curPosition() @@ -2735,12 +2925,12 @@ pp$7.skipBlockComment = function() { startLoc, this.curPosition()) } -pp$7.skipLineComment = function(startSkip) { +pp$8.skipLineComment = function(startSkip) { var this$1 = this; var start = this.pos var startLoc = this.options.onComment && this.curPosition() - var ch = this.input.charCodeAt(this.pos+=startSkip) + var ch = this.input.charCodeAt(this.pos += startSkip) while (this.pos < this.input.length && ch !== 10 && ch !== 13 && ch !== 8232 && ch !== 8233) { ++this$1.pos ch = this$1.input.charCodeAt(this$1.pos) @@ -2753,44 +2943,44 @@ pp$7.skipLineComment = function(startSkip) { // Called at the start of the parse and after every token. Skips // whitespace and comments, and. -pp$7.skipSpace = function() { +pp$8.skipSpace = function() { var this$1 = this; loop: while (this.pos < this.input.length) { var ch = this$1.input.charCodeAt(this$1.pos) switch (ch) { - case 32: case 160: // ' ' - ++this$1.pos - break - case 13: - if (this$1.input.charCodeAt(this$1.pos + 1) === 10) { - ++this$1.pos - } - case 10: case 8232: case 8233: + case 32: case 160: // ' ' + ++this$1.pos + break + case 13: + if (this$1.input.charCodeAt(this$1.pos + 1) === 10) { ++this$1.pos - if (this$1.options.locations) { - ++this$1.curLine - this$1.lineStart = this$1.pos - } + } + case 10: case 8232: case 8233: + ++this$1.pos + if (this$1.options.locations) { + ++this$1.curLine + this$1.lineStart = this$1.pos + } + break + case 47: // '/' + switch (this$1.input.charCodeAt(this$1.pos + 1)) { + case 42: // '*' + this$1.skipBlockComment() break - case 47: // '/' - switch (this$1.input.charCodeAt(this$1.pos + 1)) { - case 42: // '*' - this$1.skipBlockComment() - break - case 47: - this$1.skipLineComment(2) - break - default: - break loop - } + case 47: + this$1.skipLineComment(2) break default: - if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) { - ++this$1.pos - } else { - break loop - } + break loop + } + break + default: + if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) { + ++this$1.pos + } else { + break loop + } } } } @@ -2800,7 +2990,7 @@ pp$7.skipSpace = function() { // the token, so that the next one's `start` will point at the // right position. -pp$7.finishToken = function(type, val) { +pp$8.finishToken = function(type, val) { this.end = this.pos if (this.options.locations) this.endLoc = this.curPosition() var prevType = this.type @@ -2819,7 +3009,7 @@ pp$7.finishToken = function(type, val) { // // All in the name of speed. // -pp$7.readToken_dot = function() { +pp$8.readToken_dot = function() { var next = this.input.charCodeAt(this.pos + 1) if (next >= 48 && next <= 57) return this.readNumber(true) var next2 = this.input.charCodeAt(this.pos + 2) @@ -2832,14 +3022,14 @@ pp$7.readToken_dot = function() { } } -pp$7.readToken_slash = function() { // '/' +pp$8.readToken_slash = function() { // '/' var next = this.input.charCodeAt(this.pos + 1) - if (this.exprAllowed) {++this.pos; return this.readRegexp()} + if (this.exprAllowed) { ++this.pos; return this.readRegexp() } if (next === 61) return this.finishOp(tt.assign, 2) return this.finishOp(tt.slash, 1) } -pp$7.readToken_mult_modulo_exp = function(code) { // '%*' +pp$8.readToken_mult_modulo_exp = function(code) { // '%*' var next = this.input.charCodeAt(this.pos + 1) var size = 1 var tokentype = code === 42 ? tt.star : tt.modulo @@ -2855,20 +3045,20 @@ pp$7.readToken_mult_modulo_exp = function(code) { // '%*' return this.finishOp(tokentype, size) } -pp$7.readToken_pipe_amp = function(code) { // '|&' +pp$8.readToken_pipe_amp = function(code) { // '|&' var next = this.input.charCodeAt(this.pos + 1) if (next === code) return this.finishOp(code === 124 ? tt.logicalOR : tt.logicalAND, 2) if (next === 61) return this.finishOp(tt.assign, 2) return this.finishOp(code === 124 ? tt.bitwiseOR : tt.bitwiseAND, 1) } -pp$7.readToken_caret = function() { // '^' +pp$8.readToken_caret = function() { // '^' var next = this.input.charCodeAt(this.pos + 1) if (next === 61) return this.finishOp(tt.assign, 2) return this.finishOp(tt.bitwiseXOR, 1) } -pp$7.readToken_plus_min = function(code) { // '+-' +pp$8.readToken_plus_min = function(code) { // '+-' var next = this.input.charCodeAt(this.pos + 1) if (next === code) { if (next == 45 && this.input.charCodeAt(this.pos + 2) == 62 && @@ -2884,7 +3074,7 @@ pp$7.readToken_plus_min = function(code) { // '+-' return this.finishOp(tt.plusMin, 1) } -pp$7.readToken_lt_gt = function(code) { // '<>' +pp$8.readToken_lt_gt = function(code) { // '<>' var next = this.input.charCodeAt(this.pos + 1) var size = 1 if (next === code) { @@ -2904,7 +3094,7 @@ pp$7.readToken_lt_gt = function(code) { // '<>' return this.finishOp(tt.relational, size) } -pp$7.readToken_eq_excl = function(code) { // '=!' +pp$8.readToken_eq_excl = function(code) { // '=!' var next = this.input.charCodeAt(this.pos + 1) if (next === 61) return this.finishOp(tt.equality, this.input.charCodeAt(this.pos + 2) === 61 ? 3 : 2) if (code === 61 && next === 62 && this.options.ecmaVersion >= 6) { // '=>' @@ -2914,7 +3104,7 @@ pp$7.readToken_eq_excl = function(code) { // '=!' return this.finishOp(code === 61 ? tt.eq : tt.prefix, 1) } -pp$7.getTokenFromCode = function(code) { +pp$8.getTokenFromCode = function(code) { switch (code) { // The interpretation of a dot depends on whether it is followed // by a digit or another two dots. @@ -2987,7 +3177,7 @@ pp$7.getTokenFromCode = function(code) { this.raise(this.pos, "Unexpected character '" + codePointToString(code) + "'") } -pp$7.finishOp = function(type, size) { +pp$8.finishOp = function(type, size) { var str = this.input.slice(this.pos, this.pos + size) this.pos += size return this.finishToken(type, str) @@ -3009,7 +3199,7 @@ function tryCreateRegexp(src, flags, throwErrorAt, parser) { var regexpUnicodeSupport = !!tryCreateRegexp("\uffff", "u") -pp$7.readRegexp = function() { +pp$8.readRegexp = function() { var this$1 = this; var escaped, inClass, start = this.pos @@ -3074,7 +3264,7 @@ pp$7.readRegexp = function() { // were read, the integer value otherwise. When `len` is given, this // will return `null` unless the integer has exactly `len` digits. -pp$7.readInt = function(radix, len) { +pp$8.readInt = function(radix, len) { var this$1 = this; var start = this.pos, total = 0 @@ -3093,7 +3283,7 @@ pp$7.readInt = function(radix, len) { return total } -pp$7.readRadixNumber = function(radix) { +pp$8.readRadixNumber = function(radix) { this.pos += 2 // 0x var val = this.readInt(radix) if (val == null) this.raise(this.start + 2, "Expected number in radix " + radix) @@ -3103,7 +3293,7 @@ pp$7.readRadixNumber = function(radix) { // Read an integer, octal integer, or floating-point number. -pp$7.readNumber = function(startsWithDot) { +pp$8.readNumber = function(startsWithDot) { var start = this.pos, isFloat = false, octal = this.input.charCodeAt(this.pos) === 48 if (!startsWithDot && this.readInt(10) === null) this.raise(start, "Invalid number") if (octal && this.pos == start + 1) octal = false @@ -3132,13 +3322,13 @@ pp$7.readNumber = function(startsWithDot) { // Read a string value, interpreting backslash-escapes. -pp$7.readCodePoint = function() { +pp$8.readCodePoint = function() { var ch = this.input.charCodeAt(this.pos), code if (ch === 123) { if (this.options.ecmaVersion < 6) this.unexpected() var codePos = ++this.pos - code = this.readHexChar(this.input.indexOf('}', this.pos) - this.pos) + code = this.readHexChar(this.input.indexOf("}", this.pos) - this.pos) ++this.pos if (code > 0x10FFFF) this.raise(codePos, "Code point out of bounds") } else { @@ -3154,7 +3344,7 @@ function codePointToString(code) { return String.fromCharCode((code >> 10) + 0xD800, (code & 1023) + 0xDC00) } -pp$7.readString = function(quote) { +pp$8.readString = function(quote) { var this$1 = this; var out = "", chunkStart = ++this.pos @@ -3177,7 +3367,7 @@ pp$7.readString = function(quote) { // Reads template string tokens. -pp$7.readTmplToken = function() { +pp$8.readTmplToken = function() { var this$1 = this; var out = "", chunkStart = this.pos @@ -3205,14 +3395,14 @@ pp$7.readTmplToken = function() { out += this$1.input.slice(chunkStart, this$1.pos) ++this$1.pos switch (ch) { - case 13: - if (this$1.input.charCodeAt(this$1.pos) === 10) ++this$1.pos - case 10: - out += "\n" - break - default: - out += String.fromCharCode(ch) - break + case 13: + if (this$1.input.charCodeAt(this$1.pos) === 10) ++this$1.pos + case 10: + out += "\n" + break + default: + out += String.fromCharCode(ch) + break } if (this$1.options.locations) { ++this$1.curLine @@ -3227,7 +3417,7 @@ pp$7.readTmplToken = function() { // Used to read escaped characters -pp$7.readEscapedChar = function(inTemplate) { +pp$8.readEscapedChar = function(inTemplate) { var ch = this.input.charCodeAt(++this.pos) ++this.pos switch (ch) { @@ -3263,7 +3453,7 @@ pp$7.readEscapedChar = function(inTemplate) { // Used to read character escape sequences ('\x', '\u', '\U'). -pp$7.readHexChar = function(len) { +pp$8.readHexChar = function(len) { var codePos = this.pos var n = this.readInt(16, len) if (n === null) this.raise(codePos, "Bad character escape sequence") @@ -3276,7 +3466,7 @@ pp$7.readHexChar = function(len) { // Incrementally adds only escaped chars, adding other chunks as-is // as a micro-optimization. -pp$7.readWord1 = function() { +pp$8.readWord1 = function() { var this$1 = this; this.containsEsc = false @@ -3309,11 +3499,13 @@ pp$7.readWord1 = function() { // Read an identifier or keyword token. Will check for reserved // words when necessary. -pp$7.readWord = function() { +pp$8.readWord = function() { var word = this.readWord1() var type = tt.name - if ((this.options.ecmaVersion >= 6 || !this.containsEsc) && this.keywords.test(word)) + if (this.keywords.test(word)) { + if (this.containsEsc) this.raiseRecoverable(this.start, "Escape sequence in keyword " + word) type = keywordTypes[word] + } return this.finishToken(type, word) } @@ -3338,7 +3530,7 @@ pp$7.readWord = function() { // [dammit]: acorn_loose.js // [walk]: util/walk.js -var version = "4.0.4" +var version = "5.0.3" // The main exported interface (under `self.acorn` when in the // browser) is a `parse` function that takes a code string and @@ -3371,10 +3563,11 @@ function tokenizer(input, options) { // This is a terrible kludge to support the existing, pre-ES6 // interface where the loose parser module retroactively adds exports // to this module. +// eslint-disable-line camelcase function addLooseExports(parse, Parser, plugins) { - parse_dammit = parse + parse_dammit = parse // eslint-disable-line camelcase LooseParser = Parser pluginsLoose = plugins } -export { version, parse, parseExpressionAt, tokenizer, parse_dammit, LooseParser, pluginsLoose, addLooseExports, Parser, plugins, defaultOptions, Position, SourceLocation, getLineInfo, Node, TokenType, tt as tokTypes, TokContext, types as tokContexts, isIdentifierChar, isIdentifierStart, Token, isNewLine, lineBreak, lineBreakG }; \ No newline at end of file +export { version, parse, parseExpressionAt, tokenizer, parse_dammit, LooseParser, pluginsLoose, addLooseExports, Parser, plugins, defaultOptions, Position, SourceLocation, getLineInfo, Node, TokenType, tt as tokTypes, keywordTypes, TokContext, types as tokContexts, isIdentifierChar, isIdentifierStart, Token, isNewLine, lineBreak, lineBreakG, nonASCIIwhitespace }; \ No newline at end of file diff --git a/tools/eslint/node_modules/acorn/dist/acorn.js b/tools/eslint/node_modules/acorn/dist/acorn.js index ea572b3ebd3f4b..ce66e72fea5483 100644 --- a/tools/eslint/node_modules/acorn/dist/acorn.js +++ b/tools/eslint/node_modules/acorn/dist/acorn.js @@ -44,7 +44,11 @@ nonASCIIidentifierStartChars = nonASCIIidentifierChars = null // offset starts at 0x10000, and each pair of numbers represents an // offset to the next range, and then a size of the range. They were // generated by bin/generate-identifier-regex.js + +// eslint-disable-next-line comma-spacing var astralIdentifierStartCodes = [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] + +// eslint-disable-next-line comma-spacing var astralIdentifierCodes = [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] // This has a complexity linear to the value of the code. The @@ -250,16 +254,20 @@ var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/ var skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g -function isArray(obj) { - return Object.prototype.toString.call(obj) === "[object Array]" -} +var ref = Object.prototype; +var hasOwnProperty = ref.hasOwnProperty; +var toString = ref.toString; // Checks if an object has a property. function has(obj, propName) { - return Object.prototype.hasOwnProperty.call(obj, propName) + return hasOwnProperty.call(obj, propName) } +var isArray = Array.isArray || (function (obj) { return ( + toString.call(obj) === "[object Array]" +); }) + // These are used when `options.locations` is on, for the // `startLoc` and `endLoc` properties. @@ -407,9 +415,9 @@ function getOptions(opts) { } function pushComment(options, array) { - return function (block, text, start, end, startLoc, endLoc) { + return function(block, text, start, end, startLoc, endLoc) { var comment = { - type: block ? 'Block' : 'Line', + type: block ? "Block" : "Line", value: text, start: start, end: end @@ -487,7 +495,8 @@ var Parser = function Parser(options, input, startPos) { this.exprAllowed = true // Figure out if it's a module code. - this.strict = this.inModule = options.sourceType === "module" + this.inModule = options.sourceType === "module" + this.strict = this.inModule || this.strictDirective(this.pos) // Used to signify the start of a potential arrow function this.potentialArrowAt = -1 @@ -500,8 +509,12 @@ var Parser = function Parser(options, input, startPos) { this.labels = [] // If enabled, skip leading hashbang line. - if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === '#!') + if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === "#!") this.skipLineComment(2) + + // Scope tracking for duplicate variable names (see scope.js) + this.scopeStack = [] + this.enterFunctionScope() }; // DEPRECATED Kept for backwards compatibility until 3.0 in case a plugin uses them @@ -532,12 +545,18 @@ var pp = Parser.prototype // ## Parser utilities -// Test whether a statement node is the string literal `"use strict"`. +var literal = /^(?:'((?:[^']|\.)*)'|"((?:[^"]|\.)*)"|;)/ +pp.strictDirective = function(start) { + var this$1 = this; -pp.isUseStrict = function(stmt) { - return this.options.ecmaVersion >= 5 && stmt.type === "ExpressionStatement" && - stmt.expression.type === "Literal" && - stmt.expression.raw.slice(1, -1) === "use strict" + for (;;) { + skipWhiteSpace.lastIndex = start + start += skipWhiteSpace.exec(this$1.input)[0].length + var match = literal.exec(this$1.input.slice(start)) + if (!match) return false + if ((match[1] || match[2]) == "use strict") return true + start += match[0].length + } } // Predicate that tests whether the next token is of the given @@ -617,20 +636,21 @@ pp.unexpected = function(pos) { } var DestructuringErrors = function DestructuringErrors() { - this.shorthandAssign = 0 - this.trailingComma = 0 + this.shorthandAssign = this.trailingComma = this.parenthesizedAssign = this.parenthesizedBind = -1 }; -pp.checkPatternErrors = function(refDestructuringErrors, andThrow) { - var trailing = refDestructuringErrors && refDestructuringErrors.trailingComma - if (!andThrow) return !!trailing - if (trailing) this.raise(trailing, "Comma is not permitted after the rest element") +pp.checkPatternErrors = function(refDestructuringErrors, isAssign) { + if (!refDestructuringErrors) return + if (refDestructuringErrors.trailingComma > -1) + this.raiseRecoverable(refDestructuringErrors.trailingComma, "Comma is not permitted after the rest element") + var parens = isAssign ? refDestructuringErrors.parenthesizedAssign : refDestructuringErrors.parenthesizedBind + if (parens > -1) this.raiseRecoverable(parens, "Parenthesized pattern") } pp.checkExpressionErrors = function(refDestructuringErrors, andThrow) { - var pos = refDestructuringErrors && refDestructuringErrors.shorthandAssign - if (!andThrow) return !!pos - if (pos) this.raise(pos, "Shorthand property assignments are valid only in destructuring patterns") + var pos = refDestructuringErrors ? refDestructuringErrors.shorthandAssign : -1 + if (!andThrow) return pos >= 0 + if (pos > -1) this.raise(pos, "Shorthand property assignments are valid only in destructuring patterns") } pp.checkYieldAwaitInDefaultParams = function() { @@ -640,6 +660,12 @@ pp.checkYieldAwaitInDefaultParams = function() { this.raise(this.awaitPos, "Await expression cannot be a default value") } +pp.isSimpleAssignTarget = function(expr) { + if (expr.type === "ParenthesizedExpression") + return this.isSimpleAssignTarget(expr.expression) + return expr.type === "Identifier" || expr.type === "MemberExpression" +} + var pp$1 = Parser.prototype // ### Statement parsing @@ -652,15 +678,11 @@ var pp$1 = Parser.prototype pp$1.parseTopLevel = function(node) { var this$1 = this; - var first = true, exports = {} + var exports = {} if (!node.body) node.body = [] while (this.type !== tt.eof) { var stmt = this$1.parseStatement(true, true, exports) node.body.push(stmt) - if (first) { - if (this$1.isUseStrict(stmt)) this$1.setStrict(true) - first = false - } } this.next() if (this.options.ecmaVersion >= 6) { @@ -678,7 +700,8 @@ pp$1.isLet = function() { var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next) if (nextCh === 91 || nextCh == 123) return true // '{' and '[' if (isIdentifierStart(nextCh, true)) { - for (var pos = next + 1; isIdentifierChar(this.input.charCodeAt(pos), true); ++pos) {} + var pos = next + 1 + while (isIdentifierChar(this.input.charCodeAt(pos), true)) ++pos var ident = this.input.slice(next, pos) if (!this.isKeyword(ident)) return true } @@ -785,7 +808,8 @@ pp$1.parseBreakContinueStatement = function(node, keyword) { // Verify that there is an actual destination to break or // continue to. - for (var i = 0; i < this.labels.length; ++i) { + var i = 0 + for (; i < this.labels.length; ++i) { var lab = this$1.labels[i] if (node.label == null || lab.name === node.label.name) { if (lab.kind != null && (isBreak || lab.kind === "loop")) break @@ -827,6 +851,7 @@ pp$1.parseDoStatement = function(node) { pp$1.parseForStatement = function(node) { this.next() this.labels.push(loopLabel) + this.enterLexicalScope() this.expect(tt.parenL) if (this.type === tt.semi) return this.parseFor(node, null) var isLet = this.isLet() @@ -843,9 +868,9 @@ pp$1.parseForStatement = function(node) { var refDestructuringErrors = new DestructuringErrors var init = this.parseExpression(true, refDestructuringErrors) if (this.type === tt._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) { - this.checkPatternErrors(refDestructuringErrors, true) this.toAssignable(init) this.checkLVal(init) + this.checkPatternErrors(refDestructuringErrors, true) return this.parseForIn(node, init) } else { this.checkExpressionErrors(refDestructuringErrors, true) @@ -893,12 +918,14 @@ pp$1.parseSwitchStatement = function(node) { node.cases = [] this.expect(tt.braceL) this.labels.push(switchLabel) + this.enterLexicalScope() // Statements under must be grouped (by label) in SwitchCase // nodes. `cur` is used to keep the node that we are currently // adding statements to. - for (var cur, sawDefault = false; this.type != tt.braceR;) { + var cur + for (var sawDefault = false; this.type != tt.braceR;) { if (this$1.type === tt._case || this$1.type === tt._default) { var isCase = this$1.type === tt._case if (cur) this$1.finishNode(cur, "SwitchCase") @@ -918,6 +945,7 @@ pp$1.parseSwitchStatement = function(node) { cur.consequent.push(this$1.parseStatement(true)) } } + this.exitLexicalScope() if (cur) this.finishNode(cur, "SwitchCase") this.next() // Closing brace this.labels.pop() @@ -946,9 +974,11 @@ pp$1.parseTryStatement = function(node) { this.next() this.expect(tt.parenL) clause.param = this.parseBindingAtom() - this.checkLVal(clause.param, true) + this.enterLexicalScope() + this.checkLVal(clause.param, "let") this.expect(tt.parenR) - clause.body = this.parseBlock() + clause.body = this.parseBlock(false) + this.exitLexicalScope() node.handler = this.finishNode(clause, "CatchClause") } node.finalizer = this.eat(tt._finally) ? this.parseBlock() : null @@ -1001,6 +1031,10 @@ pp$1.parseLabeledStatement = function(node, maybeName, expr) { } this.labels.push({name: maybeName, kind: kind, statementStart: this.start}) node.body = this.parseStatement(true) + if (node.body.type == "ClassDeclaration" || + node.body.type == "VariableDeclaration" && node.body.kind != "var" || + node.body.type == "FunctionDeclaration" && (this.strict || node.body.generator)) + this.raiseRecoverable(node.body.start, "Invalid labeled declaration") this.labels.pop() node.label = expr return this.finishNode(node, "LabeledStatement") @@ -1016,22 +1050,23 @@ pp$1.parseExpressionStatement = function(node, expr) { // strict"` declarations when `allowStrict` is true (used for // function bodies). -pp$1.parseBlock = function(allowStrict) { +pp$1.parseBlock = function(createNewLexicalScope) { var this$1 = this; + if ( createNewLexicalScope === void 0 ) createNewLexicalScope = true; - var node = this.startNode(), first = true, oldStrict + var node = this.startNode() node.body = [] this.expect(tt.braceL) + if (createNewLexicalScope) { + this.enterLexicalScope() + } while (!this.eat(tt.braceR)) { var stmt = this$1.parseStatement(true) node.body.push(stmt) - if (first && allowStrict && this$1.isUseStrict(stmt)) { - oldStrict = this$1.strict - this$1.setStrict(this$1.strict = true) - } - first = false } - if (oldStrict === false) this.setStrict(false) + if (createNewLexicalScope) { + this.exitLexicalScope() + } return this.finishNode(node, "BlockStatement") } @@ -1046,6 +1081,7 @@ pp$1.parseFor = function(node, init) { this.expect(tt.semi) node.update = this.type === tt.parenR ? null : this.parseExpression() this.expect(tt.parenR) + this.exitLexicalScope() node.body = this.parseStatement(false) this.labels.pop() return this.finishNode(node, "ForStatement") @@ -1060,6 +1096,7 @@ pp$1.parseForIn = function(node, init) { node.left = init node.right = this.parseExpression() this.expect(tt.parenR) + this.exitLexicalScope() node.body = this.parseStatement(false) this.labels.pop() return this.finishNode(node, type) @@ -1074,7 +1111,7 @@ pp$1.parseVar = function(node, isFor, kind) { node.kind = kind for (;;) { var decl = this$1.startNode() - this$1.parseVarId(decl) + this$1.parseVarId(decl, kind) if (this$1.eat(tt.eq)) { decl.init = this$1.parseMaybeAssign(isFor) } else if (kind === "const" && !(this$1.type === tt._in || (this$1.options.ecmaVersion >= 6 && this$1.isContextual("of")))) { @@ -1090,9 +1127,9 @@ pp$1.parseVar = function(node, isFor, kind) { return node } -pp$1.parseVarId = function(decl) { - decl.id = this.parseBindingAtom() - this.checkLVal(decl.id, true) +pp$1.parseVarId = function(decl, kind) { + decl.id = this.parseBindingAtom(kind) + this.checkLVal(decl.id, kind, false) } // Parse a function declaration or literal (depending on the @@ -1105,17 +1142,25 @@ pp$1.parseFunction = function(node, isStatement, allowExpressionBody, isAsync) { if (this.options.ecmaVersion >= 8) node.async = !!isAsync - if (isStatement) - node.id = this.parseIdent() + if (isStatement) { + node.id = isStatement === "nullableID" && this.type != tt.name ? null : this.parseIdent() + if (node.id) { + this.checkLVal(node.id, "var") + } + } - var oldInGen = this.inGenerator, oldInAsync = this.inAsync, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos + var oldInGen = this.inGenerator, oldInAsync = this.inAsync, + oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction this.inGenerator = node.generator this.inAsync = node.async this.yieldPos = 0 this.awaitPos = 0 + this.inFunction = true + this.enterFunctionScope() + + if (!isStatement) + node.id = this.type == tt.name ? this.parseIdent() : null - if (!isStatement && this.type === tt.name) - node.id = this.parseIdent() this.parseFunctionParams(node) this.parseFunctionBody(node, allowExpressionBody) @@ -1123,6 +1168,7 @@ pp$1.parseFunction = function(node, isStatement, allowExpressionBody, isAsync) { this.inAsync = oldInAsync this.yieldPos = oldYieldPos this.awaitPos = oldAwaitPos + this.inFunction = oldInFunc return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression") } @@ -1139,6 +1185,7 @@ pp$1.parseClass = function(node, isStatement) { var this$1 = this; this.next() + this.parseClassId(node, isStatement) this.parseClassSuper(node) var classBody = this.startNode() @@ -1208,7 +1255,7 @@ pp$1.parseClassMethod = function(classBody, method, isGenerator, isAsync) { } pp$1.parseClassId = function(node, isStatement) { - node.id = this.type === tt.name ? this.parseIdent() : isStatement ? this.unexpected() : null + node.id = this.type === tt.name ? this.parseIdent() : isStatement === true ? this.unexpected() : null } pp$1.parseClassSuper = function(node) { @@ -1230,20 +1277,19 @@ pp$1.parseExport = function(node, exports) { } if (this.eat(tt._default)) { // export default ... this.checkExport(exports, "default", this.lastTokStart) - var parens = this.type == tt.parenL - var expr = this.parseMaybeAssign() - var needsSemi = true - if (!parens && (expr.type == "FunctionExpression" || - expr.type == "ClassExpression")) { - needsSemi = false - if (expr.id) { - expr.type = expr.type == "FunctionExpression" - ? "FunctionDeclaration" - : "ClassDeclaration" - } + var isAsync + if (this.type === tt._function || (isAsync = this.isAsyncFunction())) { + var fNode = this.startNode() + this.next() + if (isAsync) this.next() + node.declaration = this.parseFunction(fNode, "nullableID", false, isAsync) + } else if (this.type === tt._class) { + var cNode = this.startNode() + node.declaration = this.parseClass(cNode, "nullableID") + } else { + node.declaration = this.parseMaybeAssign() + this.semicolon() } - node.declaration = expr - if (needsSemi) this.semicolon() return this.finishNode(node, "ExportDefaultDeclaration") } // export var|const|let|function|class ... @@ -1277,7 +1323,7 @@ pp$1.parseExport = function(node, exports) { pp$1.checkExport = function(exports, name, pos) { if (!exports) return - if (Object.prototype.hasOwnProperty.call(exports, name)) + if (has(exports, name)) this.raiseRecoverable(pos, "Duplicate export '" + name + "'") exports[name] = true } @@ -1311,12 +1357,12 @@ pp$1.checkVariableExport = function(exports, decls) { } pp$1.shouldParseExportStatement = function() { - return this.type.keyword === "var" - || this.type.keyword === "const" - || this.type.keyword === "class" - || this.type.keyword === "function" - || this.isLet() - || this.isAsyncFunction() + return this.type.keyword === "var" || + this.type.keyword === "const" || + this.type.keyword === "class" || + this.type.keyword === "function" || + this.isLet() || + this.isAsyncFunction() } // Parses a comma-separated list of module exports. @@ -1334,7 +1380,7 @@ pp$1.parseExportSpecifiers = function(exports) { } else first = false var node = this$1.startNode() - node.local = this$1.parseIdent(this$1.type === tt._default) + node.local = this$1.parseIdent(true) node.exported = this$1.eatContextual("as") ? this$1.parseIdent(true) : node.local this$1.checkExport(exports, node.exported.name, node.exported.start) nodes.push(this$1.finishNode(node, "ExportSpecifier")) @@ -1369,7 +1415,7 @@ pp$1.parseImportSpecifiers = function() { // import defaultObj, { x, y as z } from '...' var node = this.startNode() node.local = this.parseIdent() - this.checkLVal(node.local, true) + this.checkLVal(node.local, "let") nodes.push(this.finishNode(node, "ImportDefaultSpecifier")) if (!this.eat(tt.comma)) return nodes } @@ -1378,7 +1424,7 @@ pp$1.parseImportSpecifiers = function() { this.next() this.expectContextual("as") node$1.local = this.parseIdent() - this.checkLVal(node$1.local, true) + this.checkLVal(node$1.local, "let") nodes.push(this.finishNode(node$1, "ImportNamespaceSpecifier")) return nodes } @@ -1398,7 +1444,7 @@ pp$1.parseImportSpecifiers = function() { if (this$1.isKeyword(node$2.local.name)) this$1.unexpected(node$2.local.start) if (this$1.reservedWordsStrict.test(node$2.local.name)) this$1.raiseRecoverable(node$2.local.start, "The keyword '" + node$2.local.name + "' is reserved") } - this$1.checkLVal(node$2.local, true) + this$1.checkLVal(node$2.local, "let") nodes.push(this$1.finishNode(node$2, "ImportSpecifier")) } return nodes @@ -1414,7 +1460,7 @@ pp$2.toAssignable = function(node, isBinding) { if (this.options.ecmaVersion >= 6 && node) { switch (node.type) { - case "Identifier": + case "Identifier": if (this.inAsync && node.name === "await") this.raise(node.start, "Can not use 'await' as identifier inside an async function") break @@ -1580,51 +1626,68 @@ pp$2.parseMaybeDefault = function(startPos, startLoc, left) { // Verify that a node is an lval — something that can be assigned // to. +// bindingType can be either: +// 'var' indicating that the lval creates a 'var' binding +// 'let' indicating that the lval creates a lexical ('let' or 'const') binding +// 'none' indicating that the binding should be checked for illegal identifiers, but not for duplicate references -pp$2.checkLVal = function(expr, isBinding, checkClashes) { +pp$2.checkLVal = function(expr, bindingType, checkClashes) { var this$1 = this; switch (expr.type) { case "Identifier": if (this.strict && this.reservedWordsStrictBind.test(expr.name)) - this.raiseRecoverable(expr.start, (isBinding ? "Binding " : "Assigning to ") + expr.name + " in strict mode") + this.raiseRecoverable(expr.start, (bindingType ? "Binding " : "Assigning to ") + expr.name + " in strict mode") if (checkClashes) { if (has(checkClashes, expr.name)) this.raiseRecoverable(expr.start, "Argument name clash") checkClashes[expr.name] = true } + if (bindingType && bindingType !== "none") { + if ( + bindingType === "var" && !this.canDeclareVarName(expr.name) || + bindingType !== "var" && !this.canDeclareLexicalName(expr.name) + ) { + this.raiseRecoverable(expr.start, ("Identifier '" + (expr.name) + "' has already been declared")) + } + if (bindingType === "var") { + this.declareVarName(expr.name) + } else { + this.declareLexicalName(expr.name) + } + } break case "MemberExpression": - if (isBinding) this.raiseRecoverable(expr.start, (isBinding ? "Binding" : "Assigning to") + " member expression") + if (bindingType) this.raiseRecoverable(expr.start, (bindingType ? "Binding" : "Assigning to") + " member expression") break case "ObjectPattern": for (var i = 0; i < expr.properties.length; i++) - this$1.checkLVal(expr.properties[i].value, isBinding, checkClashes) + this$1.checkLVal(expr.properties[i].value, bindingType, checkClashes) break case "ArrayPattern": for (var i$1 = 0; i$1 < expr.elements.length; i$1++) { var elem = expr.elements[i$1] - if (elem) this$1.checkLVal(elem, isBinding, checkClashes) + if (elem) this$1.checkLVal(elem, bindingType, checkClashes) } break case "AssignmentPattern": - this.checkLVal(expr.left, isBinding, checkClashes) + this.checkLVal(expr.left, bindingType, checkClashes) break case "RestElement": - this.checkLVal(expr.argument, isBinding, checkClashes) + this.checkLVal(expr.argument, bindingType, checkClashes) break case "ParenthesizedExpression": - this.checkLVal(expr.expression, isBinding, checkClashes) + this.checkLVal(expr.expression, bindingType, checkClashes) break default: - this.raise(expr.start, (isBinding ? "Binding" : "Assigning to") + " rvalue") + this.raise(expr.start, (bindingType ? "Binding" : "Assigning to") + " rvalue") } } @@ -1674,8 +1737,13 @@ pp$3.checkPropClash = function(prop, propHash) { name = "$" + name var other = propHash[name] if (other) { - var isGetSet = kind !== "init" - if ((this.strict || isGetSet) && other[kind] || !(isGetSet ^ other.init)) + var redefinition + if (kind === "init") { + redefinition = this.strict && other.init || other.get || other.set + } else { + redefinition = other.init || other[kind] + } + if (redefinition) this.raiseRecoverable(key.start, "Redefinition of property") } else { other = propHash[name] = { @@ -1722,11 +1790,16 @@ pp$3.parseExpression = function(noIn, refDestructuringErrors) { pp$3.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) { if (this.inGenerator && this.isContextual("yield")) return this.parseYield() - var ownDestructuringErrors = false - if (!refDestructuringErrors) { + var ownDestructuringErrors = false, oldParenAssign = -1, oldTrailingComma = -1 + if (refDestructuringErrors) { + oldParenAssign = refDestructuringErrors.parenthesizedAssign + oldTrailingComma = refDestructuringErrors.trailingComma + refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = -1 + } else { refDestructuringErrors = new DestructuringErrors ownDestructuringErrors = true } + var startPos = this.start, startLoc = this.startLoc if (this.type == tt.parenL || this.type == tt.name) this.potentialArrowAt = this.start @@ -1738,7 +1811,7 @@ pp$3.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) { var node = this.startNodeAt(startPos, startLoc) node.operator = this.value node.left = this.type === tt.eq ? this.toAssignable(left) : left - refDestructuringErrors.shorthandAssign = 0 // reset because shorthand default was used correctly + refDestructuringErrors.shorthandAssign = -1 // reset because shorthand default was used correctly this.checkLVal(left) this.next() node.right = this.parseMaybeAssign(noIn) @@ -1746,6 +1819,8 @@ pp$3.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) { } else { if (ownDestructuringErrors) this.checkExpressionErrors(refDestructuringErrors, true) } + if (oldParenAssign > -1) refDestructuringErrors.parenthesizedAssign = oldParenAssign + if (oldTrailingComma > -1) refDestructuringErrors.trailingComma = oldTrailingComma return left } @@ -1772,7 +1847,7 @@ pp$3.parseExprOps = function(noIn, refDestructuringErrors) { var startPos = this.start, startLoc = this.startLoc var expr = this.parseMaybeUnary(refDestructuringErrors, false) if (this.checkExpressionErrors(refDestructuringErrors)) return expr - return this.parseExprOp(expr, startPos, startLoc, -1, noIn) + return expr.start == startPos && expr.type === "ArrowFunctionExpression" ? expr : this.parseExprOp(expr, startPos, startLoc, -1, noIn) } // Parse binary operators with the operator precedence parsing @@ -1854,34 +1929,34 @@ pp$3.parseExprSubscripts = function(refDestructuringErrors) { var expr = this.parseExprAtom(refDestructuringErrors) var skipArrowSubscripts = expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")" if (this.checkExpressionErrors(refDestructuringErrors) || skipArrowSubscripts) return expr - return this.parseSubscripts(expr, startPos, startLoc) + var result = this.parseSubscripts(expr, startPos, startLoc) + if (refDestructuringErrors && result.type === "MemberExpression") { + if (refDestructuringErrors.parenthesizedAssign >= result.start) refDestructuringErrors.parenthesizedAssign = -1 + if (refDestructuringErrors.parenthesizedBind >= result.start) refDestructuringErrors.parenthesizedBind = -1 + } + return result } pp$3.parseSubscripts = function(base, startPos, startLoc, noCalls) { var this$1 = this; - for (;;) { - var maybeAsyncArrow = this$1.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" && !this$1.canInsertSemicolon() - if (this$1.eat(tt.dot)) { + var maybeAsyncArrow = this.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" && + this.lastTokEnd == base.end && !this.canInsertSemicolon() + for (var computed;;) { + if ((computed = this$1.eat(tt.bracketL)) || this$1.eat(tt.dot)) { var node = this$1.startNodeAt(startPos, startLoc) node.object = base - node.property = this$1.parseIdent(true) - node.computed = false + node.property = computed ? this$1.parseExpression() : this$1.parseIdent(true) + node.computed = !!computed + if (computed) this$1.expect(tt.bracketR) base = this$1.finishNode(node, "MemberExpression") - } else if (this$1.eat(tt.bracketL)) { - var node$1 = this$1.startNodeAt(startPos, startLoc) - node$1.object = base - node$1.property = this$1.parseExpression() - node$1.computed = true - this$1.expect(tt.bracketR) - base = this$1.finishNode(node$1, "MemberExpression") } else if (!noCalls && this$1.eat(tt.parenL)) { var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this$1.yieldPos, oldAwaitPos = this$1.awaitPos this$1.yieldPos = 0 this$1.awaitPos = 0 var exprList = this$1.parseExprList(tt.parenR, this$1.options.ecmaVersion >= 8, false, refDestructuringErrors) if (maybeAsyncArrow && !this$1.canInsertSemicolon() && this$1.eat(tt.arrow)) { - this$1.checkPatternErrors(refDestructuringErrors, true) + this$1.checkPatternErrors(refDestructuringErrors, false) this$1.checkYieldAwaitInDefaultParams() this$1.yieldPos = oldYieldPos this$1.awaitPos = oldAwaitPos @@ -1890,15 +1965,15 @@ pp$3.parseSubscripts = function(base, startPos, startLoc, noCalls) { this$1.checkExpressionErrors(refDestructuringErrors, true) this$1.yieldPos = oldYieldPos || this$1.yieldPos this$1.awaitPos = oldAwaitPos || this$1.awaitPos - var node$2 = this$1.startNodeAt(startPos, startLoc) - node$2.callee = base - node$2.arguments = exprList - base = this$1.finishNode(node$2, "CallExpression") + var node$1 = this$1.startNodeAt(startPos, startLoc) + node$1.callee = base + node$1.arguments = exprList + base = this$1.finishNode(node$1, "CallExpression") } else if (this$1.type === tt.backQuote) { - var node$3 = this$1.startNodeAt(startPos, startLoc) - node$3.tag = base - node$3.quasi = this$1.parseTemplate() - base = this$1.finishNode(node$3, "TaggedTemplateExpression") + var node$2 = this$1.startNodeAt(startPos, startLoc) + node$2.tag = base + node$2.quasi = this$1.parseTemplate() + base = this$1.finishNode(node$2, "TaggedTemplateExpression") } else { return base } @@ -1957,7 +2032,14 @@ pp$3.parseExprAtom = function(refDestructuringErrors) { return this.finishNode(node, "Literal") case tt.parenL: - return this.parseParenAndDistinguishExpression(canBeArrow) + var start = this.start, expr = this.parseParenAndDistinguishExpression(canBeArrow) + if (refDestructuringErrors) { + if (refDestructuringErrors.parenthesizedAssign < 0 && !this.isSimpleAssignTarget(expr)) + refDestructuringErrors.parenthesizedAssign = start + if (refDestructuringErrors.parenthesizedBind < 0) + refDestructuringErrors.parenthesizedBind = start + } + return expr case tt.bracketL: node = this.startNode() @@ -2035,7 +2117,7 @@ pp$3.parseParenAndDistinguishExpression = function(canBeArrow) { this.expect(tt.parenR) if (canBeArrow && !this.canInsertSemicolon() && this.eat(tt.arrow)) { - this.checkPatternErrors(refDestructuringErrors, true) + this.checkPatternErrors(refDestructuringErrors, false) this.checkYieldAwaitInDefaultParams() if (innerParenStart) this.unexpected(innerParenStart) this.yieldPos = oldYieldPos @@ -2109,7 +2191,7 @@ pp$3.parseNew = function() { pp$3.parseTemplateElement = function() { var elem = this.startNode() elem.value = { - raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, '\n'), + raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, "\n"), cooked: this.value } this.next() @@ -2216,7 +2298,7 @@ pp$3.parsePropertyValue = function(prop, isPattern, isGenerator, isAsync, startP if (isPattern) { prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key) } else if (this.type === tt.eq && refDestructuringErrors) { - if (!refDestructuringErrors.shorthandAssign) + if (refDestructuringErrors.shorthandAssign < 0) refDestructuringErrors.shorthandAssign = this.start prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key) } else { @@ -2255,7 +2337,8 @@ pp$3.initFunction = function(node) { // Parse object or class method. pp$3.parseMethod = function(isGenerator, isAsync) { - var node = this.startNode(), oldInGen = this.inGenerator, oldInAsync = this.inAsync, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos + var node = this.startNode(), oldInGen = this.inGenerator, oldInAsync = this.inAsync, + oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction this.initFunction(node) if (this.options.ecmaVersion >= 6) @@ -2267,6 +2350,8 @@ pp$3.parseMethod = function(isGenerator, isAsync) { this.inAsync = node.async this.yieldPos = 0 this.awaitPos = 0 + this.inFunction = true + this.enterFunctionScope() this.expect(tt.parenL) node.params = this.parseBindingList(tt.parenR, false, this.options.ecmaVersion >= 8) @@ -2277,14 +2362,17 @@ pp$3.parseMethod = function(isGenerator, isAsync) { this.inAsync = oldInAsync this.yieldPos = oldYieldPos this.awaitPos = oldAwaitPos + this.inFunction = oldInFunc return this.finishNode(node, "FunctionExpression") } // Parse arrow function expression with given parameters. pp$3.parseArrowExpression = function(node, params, isAsync) { - var oldInGen = this.inGenerator, oldInAsync = this.inAsync, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos + var oldInGen = this.inGenerator, oldInAsync = this.inAsync, + oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction + this.enterFunctionScope() this.initFunction(node) if (this.options.ecmaVersion >= 8) node.async = !!isAsync @@ -2293,6 +2381,7 @@ pp$3.parseArrowExpression = function(node, params, isAsync) { this.inAsync = node.async this.yieldPos = 0 this.awaitPos = 0 + this.inFunction = true node.params = this.toAssignableList(params, true) this.parseFunctionBody(node, true) @@ -2301,6 +2390,7 @@ pp$3.parseArrowExpression = function(node, params, isAsync) { this.inAsync = oldInAsync this.yieldPos = oldYieldPos this.awaitPos = oldAwaitPos + this.inFunction = oldInFunc return this.finishNode(node, "ArrowFunctionExpression") } @@ -2308,37 +2398,42 @@ pp$3.parseArrowExpression = function(node, params, isAsync) { pp$3.parseFunctionBody = function(node, isArrowFunction) { var isExpression = isArrowFunction && this.type !== tt.braceL + var oldStrict = this.strict, useStrict = false if (isExpression) { node.body = this.parseMaybeAssign() node.expression = true + this.checkParams(node, false) } else { + var nonSimple = this.options.ecmaVersion >= 7 && !this.isSimpleParamList(node.params) + if (!oldStrict || nonSimple) { + useStrict = this.strictDirective(this.end) + // If this is a strict mode function, verify that argument names + // are not repeated, and it does not try to bind the words `eval` + // or `arguments`. + if (useStrict && nonSimple) + this.raiseRecoverable(node.start, "Illegal 'use strict' directive in function with non-simple parameter list") + } // Start a new scope with regard to labels and the `inFunction` // flag (restore them to their old value afterwards). - var oldInFunc = this.inFunction, oldLabels = this.labels - this.inFunction = true; this.labels = [] - node.body = this.parseBlock(true) + var oldLabels = this.labels + this.labels = [] + if (useStrict) this.strict = true + + // Add the params to varDeclaredNames to ensure that an error is thrown + // if a let/const declaration in the function clashes with one of the params. + this.checkParams(node, !oldStrict && !useStrict && !isArrowFunction && this.isSimpleParamList(node.params)) + node.body = this.parseBlock(false) node.expression = false - this.inFunction = oldInFunc; this.labels = oldLabels + this.labels = oldLabels } + this.exitFunctionScope() - // If this is a strict mode function, verify that argument names - // are not repeated, and it does not try to bind the words `eval` - // or `arguments`. - var useStrict = (!isExpression && node.body.body.length && this.isUseStrict(node.body.body[0])) ? node.body.body[0] : null - if (useStrict && this.options.ecmaVersion >= 7 && !this.isSimpleParamList(node.params)) - this.raiseRecoverable(useStrict.start, "Illegal 'use strict' directive in function with non-simple parameter list") - - if (this.strict || useStrict) { - var oldStrict = this.strict - this.strict = true - if (node.id) - this.checkLVal(node.id, true) - this.checkParams(node) - this.strict = oldStrict - } else if (isArrowFunction || !this.isSimpleParamList(node.params)) { - this.checkParams(node) + if (this.strict && node.id) { + // Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval' + this.checkLVal(node.id, "none") } + this.strict = oldStrict } pp$3.isSimpleParamList = function(params) { @@ -2350,11 +2445,11 @@ pp$3.isSimpleParamList = function(params) { // Checks function params for various disallowed patterns such as using "eval" // or "arguments" and duplicate parameters. -pp$3.checkParams = function(node) { +pp$3.checkParams = function(node, allowDuplicates) { var this$1 = this; var nameHash = {} - for (var i = 0; i < node.params.length; i++) this$1.checkLVal(node.params[i], true, nameHash) + for (var i = 0; i < node.params.length; i++) this$1.checkLVal(node.params[i], "var", allowDuplicates ? null : nameHash) } // Parses a comma-separated list of expressions, and returns them as @@ -2378,11 +2473,11 @@ pp$3.parseExprList = function(close, allowTrailingComma, allowEmpty, refDestruct elt = null else if (this$1.type === tt.ellipsis) { elt = this$1.parseSpread(refDestructuringErrors) - if (this$1.type === tt.comma && refDestructuringErrors && !refDestructuringErrors.trailingComma) { + if (refDestructuringErrors && this$1.type === tt.comma && refDestructuringErrors.trailingComma < 0) refDestructuringErrors.trailingComma = this$1.start - } - } else + } else { elt = this$1.parseMaybeAssign(false, refDestructuringErrors) + } elts.push(elt) } return elts @@ -2464,6 +2559,82 @@ pp$4.curPosition = function() { } } +var pp$5 = Parser.prototype + +// Object.assign polyfill +var assign = Object.assign || function(target) { + var sources = [], len = arguments.length - 1; + while ( len-- > 0 ) sources[ len ] = arguments[ len + 1 ]; + + for (var i = 0; i < sources.length; i++) { + var source = sources[i] + for (var key in source) { + if (has(source, key)) { + target[key] = source[key] + } + } + } + return target +} + +// The functions in this module keep track of declared variables in the current scope in order to detect duplicate variable names. + +pp$5.enterFunctionScope = function() { + // var: a hash of var-declared names in the current lexical scope + // lexical: a hash of lexically-declared names in the current lexical scope + // childVar: a hash of var-declared names in all child lexical scopes of the current lexical scope (within the current function scope) + // parentLexical: a hash of lexically-declared names in all parent lexical scopes of the current lexical scope (within the current function scope) + this.scopeStack.push({var: {}, lexical: {}, childVar: {}, parentLexical: {}}) +} + +pp$5.exitFunctionScope = function() { + this.scopeStack.pop() +} + +pp$5.enterLexicalScope = function() { + var parentScope = this.scopeStack[this.scopeStack.length - 1] + var childScope = {var: {}, lexical: {}, childVar: {}, parentLexical: {}} + + this.scopeStack.push(childScope) + assign(childScope.parentLexical, parentScope.lexical, parentScope.parentLexical) +} + +pp$5.exitLexicalScope = function() { + var childScope = this.scopeStack.pop() + var parentScope = this.scopeStack[this.scopeStack.length - 1] + + assign(parentScope.childVar, childScope.var, childScope.childVar) +} + +/** + * A name can be declared with `var` if there are no variables with the same name declared with `let`/`const` + * in the current lexical scope or any of the parent lexical scopes in this function. + */ +pp$5.canDeclareVarName = function(name) { + var currentScope = this.scopeStack[this.scopeStack.length - 1] + + return !has(currentScope.lexical, name) && !has(currentScope.parentLexical, name) +} + +/** + * A name can be declared with `let`/`const` if there are no variables with the same name declared with `let`/`const` + * in the current scope, and there are no variables with the same name declared with `var` in the current scope or in + * any child lexical scopes in this function. + */ +pp$5.canDeclareLexicalName = function(name) { + var currentScope = this.scopeStack[this.scopeStack.length - 1] + + return !has(currentScope.lexical, name) && !has(currentScope.var, name) && !has(currentScope.childVar, name) +} + +pp$5.declareVarName = function(name) { + this.scopeStack[this.scopeStack.length - 1].var[name] = true +} + +pp$5.declareLexicalName = function(name) { + this.scopeStack[this.scopeStack.length - 1].lexical[name] = true +} + var Node = function Node(parser, pos, loc) { this.type = "" this.start = pos @@ -2478,13 +2649,13 @@ var Node = function Node(parser, pos, loc) { // Start an AST node, attaching a start offset. -var pp$5 = Parser.prototype +var pp$6 = Parser.prototype -pp$5.startNode = function() { +pp$6.startNode = function() { return new Node(this, this.start, this.startLoc) } -pp$5.startNodeAt = function(pos, loc) { +pp$6.startNodeAt = function(pos, loc) { return new Node(this, pos, loc) } @@ -2500,13 +2671,13 @@ function finishNodeAt(node, type, pos, loc) { return node } -pp$5.finishNode = function(node, type) { +pp$6.finishNode = function(node, type) { return finishNodeAt.call(this, node, type, this.lastTokEnd, this.lastTokEndLoc) } // Finish node at given position -pp$5.finishNodeAt = function(node, type, pos, loc) { +pp$6.finishNodeAt = function(node, type, pos, loc) { return finishNodeAt.call(this, node, type, pos, loc) } @@ -2514,11 +2685,12 @@ pp$5.finishNodeAt = function(node, type, pos, loc) { // given point in the program is loosely based on sweet.js' approach. // See https://github.com/mozilla/sweet.js/wiki/design -var TokContext = function TokContext(token, isExpr, preserveSpace, override) { +var TokContext = function TokContext(token, isExpr, preserveSpace, override, generator) { this.token = token this.isExpr = !!isExpr this.preserveSpace = !!preserveSpace this.override = override + this.generator = !!generator }; var types = { @@ -2528,16 +2700,18 @@ var types = { p_stat: new TokContext("(", false), p_expr: new TokContext("(", true), q_tmpl: new TokContext("`", true, true, function (p) { return p.readTmplToken(); }), - f_expr: new TokContext("function", true) + f_expr: new TokContext("function", true), + f_expr_gen: new TokContext("function", true, false, null, true), + f_gen: new TokContext("function", false, false, null, true) } -var pp$6 = Parser.prototype +var pp$7 = Parser.prototype -pp$6.initialContext = function() { +pp$7.initialContext = function() { return [types.b_stat] } -pp$6.braceIsBlock = function(prevType) { +pp$7.braceIsBlock = function(prevType) { if (prevType === tt.colon) { var parent = this.curContext() if (parent === types.b_stat || parent === types.b_expr) @@ -2545,14 +2719,22 @@ pp$6.braceIsBlock = function(prevType) { } if (prevType === tt._return) return lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) - if (prevType === tt._else || prevType === tt.semi || prevType === tt.eof || prevType === tt.parenR) + if (prevType === tt._else || prevType === tt.semi || prevType === tt.eof || prevType === tt.parenR || prevType == tt.arrow) return true if (prevType == tt.braceL) return this.curContext() === types.b_stat return !this.exprAllowed } -pp$6.updateContext = function(prevType) { +pp$7.inGeneratorContext = function() { + var this$1 = this; + + for (var i = this.context.length - 1; i >= 0; i--) + if (this$1.context[i].generator) return true + return false +} + +pp$7.updateContext = function(prevType) { var update, type = this.type if (type.keyword && prevType == tt.dot) this.exprAllowed = false @@ -2569,8 +2751,8 @@ tt.parenR.updateContext = tt.braceR.updateContext = function() { this.exprAllowed = true return } - var out = this.context.pop() - if (out === types.b_stat && this.curContext() === types.f_expr) { + var out = this.context.pop(), cur + if (out === types.b_stat && (cur = this.curContext()) && cur.token === "function") { this.context.pop() this.exprAllowed = false } else if (out === types.b_tmpl) { @@ -2615,6 +2797,26 @@ tt.backQuote.updateContext = function() { this.exprAllowed = false } +tt.star.updateContext = function(prevType) { + if (prevType == tt._function) { + if (this.curContext() === types.f_expr) + this.context[this.context.length - 1] = types.f_expr_gen + else + this.context.push(types.f_gen) + } + this.exprAllowed = true +} + +tt.name.updateContext = function(prevType) { + var allowed = false + if (this.options.ecmaVersion >= 6) { + if (this.value == "of" && !this.exprAllowed || + this.value == "yield" && this.inGeneratorContext()) + allowed = true + } + this.exprAllowed = allowed +} + // Object type used to represent tokens. Note that normally, tokens // simply exist as properties on the parser object. This is only // used for the onToken callback and the external tokenizer. @@ -2632,14 +2834,14 @@ var Token = function Token(p) { // ## Tokenizer -var pp$7 = Parser.prototype +var pp$8 = Parser.prototype // Are we running under Rhino? var isRhino = typeof Packages == "object" && Object.prototype.toString.call(Packages) == "[object JavaPackage]" // Move to the next token -pp$7.next = function() { +pp$8.next = function() { if (this.options.onToken) this.options.onToken(new Token(this)) @@ -2650,50 +2852,38 @@ pp$7.next = function() { this.nextToken() } -pp$7.getToken = function() { +pp$8.getToken = function() { this.next() return new Token(this) } // If we're in an ES6 environment, make parsers iterable if (typeof Symbol !== "undefined") - pp$7[Symbol.iterator] = function () { - var self = this - return {next: function () { - var token = self.getToken() - return { - done: token.type === tt.eof, - value: token + pp$8[Symbol.iterator] = function() { + var this$1 = this; + + return { + next: function () { + var token = this$1.getToken() + return { + done: token.type === tt.eof, + value: token + } } - }} + } } // Toggle strict mode. Re-reads the next number or string to please // pedantic tests (`"use strict"; 010;` should fail). -pp$7.setStrict = function(strict) { - var this$1 = this; - - this.strict = strict - if (this.type !== tt.num && this.type !== tt.string) return - this.pos = this.start - if (this.options.locations) { - while (this.pos < this.lineStart) { - this$1.lineStart = this$1.input.lastIndexOf("\n", this$1.lineStart - 2) + 1 - --this$1.curLine - } - } - this.nextToken() -} - -pp$7.curContext = function() { +pp$8.curContext = function() { return this.context[this.context.length - 1] } // Read a single token, updating the parser object's token-related // properties. -pp$7.nextToken = function() { +pp$8.nextToken = function() { var curContext = this.curContext() if (!curContext || !curContext.preserveSpace) this.skipSpace() @@ -2705,7 +2895,7 @@ pp$7.nextToken = function() { else this.readToken(this.fullCharCodeAtPos()) } -pp$7.readToken = function(code) { +pp$8.readToken = function(code) { // Identifier or keyword. '\uXXXX' sequences are allowed in // identifiers, so '\' also dispatches to that. if (isIdentifierStart(code, this.options.ecmaVersion >= 6) || code === 92 /* '\' */) @@ -2714,14 +2904,14 @@ pp$7.readToken = function(code) { return this.getTokenFromCode(code) } -pp$7.fullCharCodeAtPos = function() { +pp$8.fullCharCodeAtPos = function() { var code = this.input.charCodeAt(this.pos) if (code <= 0xd7ff || code >= 0xe000) return code var next = this.input.charCodeAt(this.pos + 1) return (code << 10) + next - 0x35fdc00 } -pp$7.skipBlockComment = function() { +pp$8.skipBlockComment = function() { var this$1 = this; var startLoc = this.options.onComment && this.curPosition() @@ -2741,12 +2931,12 @@ pp$7.skipBlockComment = function() { startLoc, this.curPosition()) } -pp$7.skipLineComment = function(startSkip) { +pp$8.skipLineComment = function(startSkip) { var this$1 = this; var start = this.pos var startLoc = this.options.onComment && this.curPosition() - var ch = this.input.charCodeAt(this.pos+=startSkip) + var ch = this.input.charCodeAt(this.pos += startSkip) while (this.pos < this.input.length && ch !== 10 && ch !== 13 && ch !== 8232 && ch !== 8233) { ++this$1.pos ch = this$1.input.charCodeAt(this$1.pos) @@ -2759,44 +2949,44 @@ pp$7.skipLineComment = function(startSkip) { // Called at the start of the parse and after every token. Skips // whitespace and comments, and. -pp$7.skipSpace = function() { +pp$8.skipSpace = function() { var this$1 = this; loop: while (this.pos < this.input.length) { var ch = this$1.input.charCodeAt(this$1.pos) switch (ch) { - case 32: case 160: // ' ' - ++this$1.pos - break - case 13: - if (this$1.input.charCodeAt(this$1.pos + 1) === 10) { - ++this$1.pos - } - case 10: case 8232: case 8233: + case 32: case 160: // ' ' + ++this$1.pos + break + case 13: + if (this$1.input.charCodeAt(this$1.pos + 1) === 10) { ++this$1.pos - if (this$1.options.locations) { - ++this$1.curLine - this$1.lineStart = this$1.pos - } + } + case 10: case 8232: case 8233: + ++this$1.pos + if (this$1.options.locations) { + ++this$1.curLine + this$1.lineStart = this$1.pos + } + break + case 47: // '/' + switch (this$1.input.charCodeAt(this$1.pos + 1)) { + case 42: // '*' + this$1.skipBlockComment() break - case 47: // '/' - switch (this$1.input.charCodeAt(this$1.pos + 1)) { - case 42: // '*' - this$1.skipBlockComment() - break - case 47: - this$1.skipLineComment(2) - break - default: - break loop - } + case 47: + this$1.skipLineComment(2) break default: - if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) { - ++this$1.pos - } else { - break loop - } + break loop + } + break + default: + if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) { + ++this$1.pos + } else { + break loop + } } } } @@ -2806,7 +2996,7 @@ pp$7.skipSpace = function() { // the token, so that the next one's `start` will point at the // right position. -pp$7.finishToken = function(type, val) { +pp$8.finishToken = function(type, val) { this.end = this.pos if (this.options.locations) this.endLoc = this.curPosition() var prevType = this.type @@ -2825,7 +3015,7 @@ pp$7.finishToken = function(type, val) { // // All in the name of speed. // -pp$7.readToken_dot = function() { +pp$8.readToken_dot = function() { var next = this.input.charCodeAt(this.pos + 1) if (next >= 48 && next <= 57) return this.readNumber(true) var next2 = this.input.charCodeAt(this.pos + 2) @@ -2838,14 +3028,14 @@ pp$7.readToken_dot = function() { } } -pp$7.readToken_slash = function() { // '/' +pp$8.readToken_slash = function() { // '/' var next = this.input.charCodeAt(this.pos + 1) - if (this.exprAllowed) {++this.pos; return this.readRegexp()} + if (this.exprAllowed) { ++this.pos; return this.readRegexp() } if (next === 61) return this.finishOp(tt.assign, 2) return this.finishOp(tt.slash, 1) } -pp$7.readToken_mult_modulo_exp = function(code) { // '%*' +pp$8.readToken_mult_modulo_exp = function(code) { // '%*' var next = this.input.charCodeAt(this.pos + 1) var size = 1 var tokentype = code === 42 ? tt.star : tt.modulo @@ -2861,20 +3051,20 @@ pp$7.readToken_mult_modulo_exp = function(code) { // '%*' return this.finishOp(tokentype, size) } -pp$7.readToken_pipe_amp = function(code) { // '|&' +pp$8.readToken_pipe_amp = function(code) { // '|&' var next = this.input.charCodeAt(this.pos + 1) if (next === code) return this.finishOp(code === 124 ? tt.logicalOR : tt.logicalAND, 2) if (next === 61) return this.finishOp(tt.assign, 2) return this.finishOp(code === 124 ? tt.bitwiseOR : tt.bitwiseAND, 1) } -pp$7.readToken_caret = function() { // '^' +pp$8.readToken_caret = function() { // '^' var next = this.input.charCodeAt(this.pos + 1) if (next === 61) return this.finishOp(tt.assign, 2) return this.finishOp(tt.bitwiseXOR, 1) } -pp$7.readToken_plus_min = function(code) { // '+-' +pp$8.readToken_plus_min = function(code) { // '+-' var next = this.input.charCodeAt(this.pos + 1) if (next === code) { if (next == 45 && this.input.charCodeAt(this.pos + 2) == 62 && @@ -2890,7 +3080,7 @@ pp$7.readToken_plus_min = function(code) { // '+-' return this.finishOp(tt.plusMin, 1) } -pp$7.readToken_lt_gt = function(code) { // '<>' +pp$8.readToken_lt_gt = function(code) { // '<>' var next = this.input.charCodeAt(this.pos + 1) var size = 1 if (next === code) { @@ -2910,7 +3100,7 @@ pp$7.readToken_lt_gt = function(code) { // '<>' return this.finishOp(tt.relational, size) } -pp$7.readToken_eq_excl = function(code) { // '=!' +pp$8.readToken_eq_excl = function(code) { // '=!' var next = this.input.charCodeAt(this.pos + 1) if (next === 61) return this.finishOp(tt.equality, this.input.charCodeAt(this.pos + 2) === 61 ? 3 : 2) if (code === 61 && next === 62 && this.options.ecmaVersion >= 6) { // '=>' @@ -2920,7 +3110,7 @@ pp$7.readToken_eq_excl = function(code) { // '=!' return this.finishOp(code === 61 ? tt.eq : tt.prefix, 1) } -pp$7.getTokenFromCode = function(code) { +pp$8.getTokenFromCode = function(code) { switch (code) { // The interpretation of a dot depends on whether it is followed // by a digit or another two dots. @@ -2993,7 +3183,7 @@ pp$7.getTokenFromCode = function(code) { this.raise(this.pos, "Unexpected character '" + codePointToString(code) + "'") } -pp$7.finishOp = function(type, size) { +pp$8.finishOp = function(type, size) { var str = this.input.slice(this.pos, this.pos + size) this.pos += size return this.finishToken(type, str) @@ -3015,7 +3205,7 @@ function tryCreateRegexp(src, flags, throwErrorAt, parser) { var regexpUnicodeSupport = !!tryCreateRegexp("\uffff", "u") -pp$7.readRegexp = function() { +pp$8.readRegexp = function() { var this$1 = this; var escaped, inClass, start = this.pos @@ -3080,7 +3270,7 @@ pp$7.readRegexp = function() { // were read, the integer value otherwise. When `len` is given, this // will return `null` unless the integer has exactly `len` digits. -pp$7.readInt = function(radix, len) { +pp$8.readInt = function(radix, len) { var this$1 = this; var start = this.pos, total = 0 @@ -3099,7 +3289,7 @@ pp$7.readInt = function(radix, len) { return total } -pp$7.readRadixNumber = function(radix) { +pp$8.readRadixNumber = function(radix) { this.pos += 2 // 0x var val = this.readInt(radix) if (val == null) this.raise(this.start + 2, "Expected number in radix " + radix) @@ -3109,7 +3299,7 @@ pp$7.readRadixNumber = function(radix) { // Read an integer, octal integer, or floating-point number. -pp$7.readNumber = function(startsWithDot) { +pp$8.readNumber = function(startsWithDot) { var start = this.pos, isFloat = false, octal = this.input.charCodeAt(this.pos) === 48 if (!startsWithDot && this.readInt(10) === null) this.raise(start, "Invalid number") if (octal && this.pos == start + 1) octal = false @@ -3138,13 +3328,13 @@ pp$7.readNumber = function(startsWithDot) { // Read a string value, interpreting backslash-escapes. -pp$7.readCodePoint = function() { +pp$8.readCodePoint = function() { var ch = this.input.charCodeAt(this.pos), code if (ch === 123) { if (this.options.ecmaVersion < 6) this.unexpected() var codePos = ++this.pos - code = this.readHexChar(this.input.indexOf('}', this.pos) - this.pos) + code = this.readHexChar(this.input.indexOf("}", this.pos) - this.pos) ++this.pos if (code > 0x10FFFF) this.raise(codePos, "Code point out of bounds") } else { @@ -3160,7 +3350,7 @@ function codePointToString(code) { return String.fromCharCode((code >> 10) + 0xD800, (code & 1023) + 0xDC00) } -pp$7.readString = function(quote) { +pp$8.readString = function(quote) { var this$1 = this; var out = "", chunkStart = ++this.pos @@ -3183,7 +3373,7 @@ pp$7.readString = function(quote) { // Reads template string tokens. -pp$7.readTmplToken = function() { +pp$8.readTmplToken = function() { var this$1 = this; var out = "", chunkStart = this.pos @@ -3211,14 +3401,14 @@ pp$7.readTmplToken = function() { out += this$1.input.slice(chunkStart, this$1.pos) ++this$1.pos switch (ch) { - case 13: - if (this$1.input.charCodeAt(this$1.pos) === 10) ++this$1.pos - case 10: - out += "\n" - break - default: - out += String.fromCharCode(ch) - break + case 13: + if (this$1.input.charCodeAt(this$1.pos) === 10) ++this$1.pos + case 10: + out += "\n" + break + default: + out += String.fromCharCode(ch) + break } if (this$1.options.locations) { ++this$1.curLine @@ -3233,7 +3423,7 @@ pp$7.readTmplToken = function() { // Used to read escaped characters -pp$7.readEscapedChar = function(inTemplate) { +pp$8.readEscapedChar = function(inTemplate) { var ch = this.input.charCodeAt(++this.pos) ++this.pos switch (ch) { @@ -3269,7 +3459,7 @@ pp$7.readEscapedChar = function(inTemplate) { // Used to read character escape sequences ('\x', '\u', '\U'). -pp$7.readHexChar = function(len) { +pp$8.readHexChar = function(len) { var codePos = this.pos var n = this.readInt(16, len) if (n === null) this.raise(codePos, "Bad character escape sequence") @@ -3282,7 +3472,7 @@ pp$7.readHexChar = function(len) { // Incrementally adds only escaped chars, adding other chunks as-is // as a micro-optimization. -pp$7.readWord1 = function() { +pp$8.readWord1 = function() { var this$1 = this; this.containsEsc = false @@ -3315,11 +3505,13 @@ pp$7.readWord1 = function() { // Read an identifier or keyword token. Will check for reserved // words when necessary. -pp$7.readWord = function() { +pp$8.readWord = function() { var word = this.readWord1() var type = tt.name - if ((this.options.ecmaVersion >= 6 || !this.containsEsc) && this.keywords.test(word)) + if (this.keywords.test(word)) { + if (this.containsEsc) this.raiseRecoverable(this.start, "Escape sequence in keyword " + word) type = keywordTypes[word] + } return this.finishToken(type, word) } @@ -3344,7 +3536,7 @@ pp$7.readWord = function() { // [dammit]: acorn_loose.js // [walk]: util/walk.js -var version = "4.0.4" +var version = "5.0.3" // The main exported interface (under `self.acorn` when in the // browser) is a `parse` function that takes a code string and @@ -3377,8 +3569,9 @@ function tokenizer(input, options) { // This is a terrible kludge to support the existing, pre-ES6 // interface where the loose parser module retroactively adds exports // to this module. +// eslint-disable-line camelcase function addLooseExports(parse, Parser, plugins) { - exports.parse_dammit = parse + exports.parse_dammit = parse // eslint-disable-line camelcase exports.LooseParser = Parser exports.pluginsLoose = plugins } @@ -3397,6 +3590,7 @@ exports.getLineInfo = getLineInfo; exports.Node = Node; exports.TokenType = TokenType; exports.tokTypes = tt; +exports.keywordTypes = keywordTypes; exports.TokContext = TokContext; exports.tokContexts = types; exports.isIdentifierChar = isIdentifierChar; @@ -3405,6 +3599,7 @@ exports.Token = Token; exports.isNewLine = isNewLine; exports.lineBreak = lineBreak; exports.lineBreakG = lineBreakG; +exports.nonASCIIwhitespace = nonASCIIwhitespace; Object.defineProperty(exports, '__esModule', { value: true }); diff --git a/tools/eslint/node_modules/acorn/dist/acorn_loose.es.js b/tools/eslint/node_modules/acorn/dist/acorn_loose.es.js index 3c9dc412ef1780..11813609a4a426 100644 --- a/tools/eslint/node_modules/acorn/dist/acorn_loose.es.js +++ b/tools/eslint/node_modules/acorn/dist/acorn_loose.es.js @@ -205,7 +205,7 @@ lp.readToken = function() { this$1.toks.type = tokTypes.ellipsis } return new Token(this$1.toks) - } catch(e) { + } catch (e) { if (!(e instanceof SyntaxError)) throw e // Try to skip some text, based on the error message, and then continue @@ -216,12 +216,15 @@ lp.readToken = function() { replace = {start: e.pos, end: pos, type: tokTypes.string, value: this$1.input.slice(e.pos + 1, pos)} } else if (/regular expr/i.test(msg)) { var re = this$1.input.slice(e.pos, pos) - try { re = new RegExp(re) } catch(e) {} + try { re = new RegExp(re) } catch (e) { /* ignore compilation error due to new syntax */ } replace = {start: e.pos, end: pos, type: tokTypes.regexp, value: re} } else if (/template/.test(msg)) { - replace = {start: e.pos, end: pos, - type: tokTypes.template, - value: this$1.input.slice(e.pos, pos)} + replace = { + start: e.pos, + end: pos, + type: tokTypes.template, + value: this$1.input.slice(e.pos, pos) + } } else { replace = false } @@ -259,7 +262,7 @@ lp.resetTo = function(pos) { this.toks.pos = pos var ch = this.input.charAt(pos - 1) - this.toks.exprAllowed = !ch || /[\[\{\(,;:?\/*=+\-~!|&%^<>]/.test(ch) || + this.toks.exprAllowed = !ch || /[[{(,;:?/*=+\-~!|&%^<>]/.test(ch) || /[enwfd]/.test(ch) && /\b(keywords|case|else|return|throw|new|in|(instance|type)of|delete|void)$/.test(this.input.slice(pos - 10, pos)) @@ -544,7 +547,7 @@ lp$1.parseClass = function(isStatement) { var node = this.startNode() this.next() if (this.tok.type === tokTypes.name) node.id = this.parseIdent() - else if (isStatement) node.id = this.dummyIdent() + else if (isStatement === true) node.id = this.dummyIdent() else node.id = null node.superClass = this.eat(tokTypes._extends) ? this.parseExpression() : null node.body = this.startNode() @@ -590,7 +593,7 @@ lp$1.parseClass = function(isStatement) { method.key.type === "Literal" && method.key.value === "constructor")) { method.kind = "constructor" } else { - method.kind = "method" + method.kind = "method" } method.value = this$1.parseMethod(isGenerator, isAsync) } @@ -618,7 +621,7 @@ lp$1.parseFunction = function(node, isStatement, isAsync) { node.async = !!isAsync } if (this.tok.type === tokTypes.name) node.id = this.parseIdent() - else if (isStatement) node.id = this.dummyIdent() + else if (isStatement === true) node.id = this.dummyIdent() this.inAsync = node.async node.params = this.parseFunctionParams() node.body = this.parseBlock() @@ -635,16 +638,18 @@ lp$1.parseExport = function() { } if (this.eat(tokTypes._default)) { // export default (function foo() {}) // This is FunctionExpression. - var isParenL = this.tok.type === tokTypes.parenL - var expr = this.parseMaybeAssign() - if (!isParenL && expr.id) { - switch (expr.type) { - case "FunctionExpression": expr.type = "FunctionDeclaration"; break - case "ClassExpression": expr.type = "ClassDeclaration"; break - } + var isAsync + if (this.tok.type === tokTypes._function || (isAsync = this.toks.isAsyncFunction())) { + var fNode = this.startNode() + this.next() + if (isAsync) this.next() + node.declaration = this.parseFunction(fNode, "nullableID", isAsync) + } else if (this.tok.type === tokTypes._class) { + node.declaration = this.parseClass("nullableID") + } else { + node.declaration = this.parseMaybeAssign() + this.semicolon() } - node.declaration = expr - this.semicolon() return this.finishNode(node, "ExportDefaultDeclaration") } if (this.tok.type.keyword || this.toks.isLet() || this.toks.isAsyncFunction()) { @@ -666,7 +671,7 @@ lp$1.parseImport = function() { if (this.tok.type === tokTypes.string) { node.specifiers = [] node.source = this.parseExprAtom() - node.kind = '' + node.kind = "" } else { var elt if (this.tok.type === tokTypes.name && this.tok.value !== "from") { @@ -1025,7 +1030,7 @@ lp$2.parseExprAtom = function() { return this.parseObj() case tokTypes._class: - return this.parseClass() + return this.parseClass(false) case tokTypes._function: node = this.startNode() @@ -1064,7 +1069,7 @@ lp$2.parseNew = function() { lp$2.parseTemplateElement = function() { var elem = this.startNode() elem.value = { - raw: this.input.slice(this.tok.start, this.tok.end).replace(/\r\n?/g, '\n'), + raw: this.input.slice(this.tok.start, this.tok.end).replace(/\r\n?/g, "\n"), cooked: this.tok.value } this.next() @@ -1087,7 +1092,7 @@ lp$2.parseTemplate = function() { curElt = this$1.parseTemplateElement() } else { curElt = this$1.startNode() - curElt.value = {cooked: '', raw: ''} + curElt.value = {cooked: "", raw: ""} curElt.tail = true this$1.finishNode(curElt, "TemplateElement") } @@ -1349,6 +1354,7 @@ lp$2.parseAwait = function() { defaultOptions.tabSize = 4 +// eslint-disable-next-line camelcase function parse_dammit(input, options) { var p = new LooseParser(input, options) p.next() diff --git a/tools/eslint/node_modules/acorn/dist/acorn_loose.js b/tools/eslint/node_modules/acorn/dist/acorn_loose.js index ca52a7902e9f58..6ad0085da11a26 100644 --- a/tools/eslint/node_modules/acorn/dist/acorn_loose.js +++ b/tools/eslint/node_modules/acorn/dist/acorn_loose.js @@ -209,7 +209,7 @@ lp.readToken = function() { this$1.toks.type = __acorn.tokTypes.ellipsis } return new __acorn.Token(this$1.toks) - } catch(e) { + } catch (e) { if (!(e instanceof SyntaxError)) throw e // Try to skip some text, based on the error message, and then continue @@ -220,12 +220,15 @@ lp.readToken = function() { replace = {start: e.pos, end: pos, type: __acorn.tokTypes.string, value: this$1.input.slice(e.pos + 1, pos)} } else if (/regular expr/i.test(msg)) { var re = this$1.input.slice(e.pos, pos) - try { re = new RegExp(re) } catch(e) {} + try { re = new RegExp(re) } catch (e) { /* ignore compilation error due to new syntax */ } replace = {start: e.pos, end: pos, type: __acorn.tokTypes.regexp, value: re} } else if (/template/.test(msg)) { - replace = {start: e.pos, end: pos, - type: __acorn.tokTypes.template, - value: this$1.input.slice(e.pos, pos)} + replace = { + start: e.pos, + end: pos, + type: __acorn.tokTypes.template, + value: this$1.input.slice(e.pos, pos) + } } else { replace = false } @@ -263,7 +266,7 @@ lp.resetTo = function(pos) { this.toks.pos = pos var ch = this.input.charAt(pos - 1) - this.toks.exprAllowed = !ch || /[\[\{\(,;:?\/*=+\-~!|&%^<>]/.test(ch) || + this.toks.exprAllowed = !ch || /[[{(,;:?/*=+\-~!|&%^<>]/.test(ch) || /[enwfd]/.test(ch) && /\b(keywords|case|else|return|throw|new|in|(instance|type)of|delete|void)$/.test(this.input.slice(pos - 10, pos)) @@ -548,7 +551,7 @@ lp$1.parseClass = function(isStatement) { var node = this.startNode() this.next() if (this.tok.type === __acorn.tokTypes.name) node.id = this.parseIdent() - else if (isStatement) node.id = this.dummyIdent() + else if (isStatement === true) node.id = this.dummyIdent() else node.id = null node.superClass = this.eat(__acorn.tokTypes._extends) ? this.parseExpression() : null node.body = this.startNode() @@ -594,7 +597,7 @@ lp$1.parseClass = function(isStatement) { method.key.type === "Literal" && method.key.value === "constructor")) { method.kind = "constructor" } else { - method.kind = "method" + method.kind = "method" } method.value = this$1.parseMethod(isGenerator, isAsync) } @@ -622,7 +625,7 @@ lp$1.parseFunction = function(node, isStatement, isAsync) { node.async = !!isAsync } if (this.tok.type === __acorn.tokTypes.name) node.id = this.parseIdent() - else if (isStatement) node.id = this.dummyIdent() + else if (isStatement === true) node.id = this.dummyIdent() this.inAsync = node.async node.params = this.parseFunctionParams() node.body = this.parseBlock() @@ -639,16 +642,18 @@ lp$1.parseExport = function() { } if (this.eat(__acorn.tokTypes._default)) { // export default (function foo() {}) // This is FunctionExpression. - var isParenL = this.tok.type === __acorn.tokTypes.parenL - var expr = this.parseMaybeAssign() - if (!isParenL && expr.id) { - switch (expr.type) { - case "FunctionExpression": expr.type = "FunctionDeclaration"; break - case "ClassExpression": expr.type = "ClassDeclaration"; break - } + var isAsync + if (this.tok.type === __acorn.tokTypes._function || (isAsync = this.toks.isAsyncFunction())) { + var fNode = this.startNode() + this.next() + if (isAsync) this.next() + node.declaration = this.parseFunction(fNode, "nullableID", isAsync) + } else if (this.tok.type === __acorn.tokTypes._class) { + node.declaration = this.parseClass("nullableID") + } else { + node.declaration = this.parseMaybeAssign() + this.semicolon() } - node.declaration = expr - this.semicolon() return this.finishNode(node, "ExportDefaultDeclaration") } if (this.tok.type.keyword || this.toks.isLet() || this.toks.isAsyncFunction()) { @@ -670,7 +675,7 @@ lp$1.parseImport = function() { if (this.tok.type === __acorn.tokTypes.string) { node.specifiers = [] node.source = this.parseExprAtom() - node.kind = '' + node.kind = "" } else { var elt if (this.tok.type === __acorn.tokTypes.name && this.tok.value !== "from") { @@ -1029,7 +1034,7 @@ lp$2.parseExprAtom = function() { return this.parseObj() case __acorn.tokTypes._class: - return this.parseClass() + return this.parseClass(false) case __acorn.tokTypes._function: node = this.startNode() @@ -1068,7 +1073,7 @@ lp$2.parseNew = function() { lp$2.parseTemplateElement = function() { var elem = this.startNode() elem.value = { - raw: this.input.slice(this.tok.start, this.tok.end).replace(/\r\n?/g, '\n'), + raw: this.input.slice(this.tok.start, this.tok.end).replace(/\r\n?/g, "\n"), cooked: this.tok.value } this.next() @@ -1091,7 +1096,7 @@ lp$2.parseTemplate = function() { curElt = this$1.parseTemplateElement() } else { curElt = this$1.startNode() - curElt.value = {cooked: '', raw: ''} + curElt.value = {cooked: "", raw: ""} curElt.tail = true this$1.finishNode(curElt, "TemplateElement") } @@ -1353,6 +1358,7 @@ lp$2.parseAwait = function() { __acorn.defaultOptions.tabSize = 4 +// eslint-disable-next-line camelcase function parse_dammit(input, options) { var p = new LooseParser(input, options) p.next() diff --git a/tools/eslint/node_modules/acorn/dist/walk.es.js b/tools/eslint/node_modules/acorn/dist/walk.es.js index b717ed996ec3ad..280b9a0454705b 100644 --- a/tools/eslint/node_modules/acorn/dist/walk.es.js +++ b/tools/eslint/node_modules/acorn/dist/walk.es.js @@ -71,7 +71,7 @@ function findNodeAt(node, start, end, test, base, state) { test = makeTest(test) if (!base) base = exports.base try { - ;(function c(node, st, override) { + (function c(node, st, override) { var type = override || node.type if ((start == null || node.start <= start) && (end == null || node.end >= end)) @@ -93,7 +93,7 @@ function findNodeAround(node, pos, test, base, state) { test = makeTest(test) if (!base) base = exports.base try { - ;(function c(node, st, override) { + (function c(node, st, override) { var type = override || node.type if (node.start > pos || node.end < pos) return base[type](node, st, c) @@ -110,7 +110,7 @@ function findNodeAfter(node, pos, test, base, state) { test = makeTest(test) if (!base) base = exports.base try { - ;(function c(node, st, override) { + (function c(node, st, override) { if (node.end < pos) return var type = override || node.type if (node.start >= pos && test(type, node)) throw new Found(node, st) @@ -255,7 +255,7 @@ base.Pattern = function (node, st, c) { base.VariablePattern = ignore base.MemberPattern = skipThrough base.RestElement = function (node, st, c) { return c(node.argument, st, "Pattern"); } -base.ArrayPattern = function (node, st, c) { +base.ArrayPattern = function (node, st, c) { for (var i = 0; i < node.elements.length; ++i) { var elt = node.elements[i] if (elt) c(elt, st, "Pattern") diff --git a/tools/eslint/node_modules/acorn/dist/walk.js b/tools/eslint/node_modules/acorn/dist/walk.js index 3c9c5948760d9f..29609de0408c55 100644 --- a/tools/eslint/node_modules/acorn/dist/walk.js +++ b/tools/eslint/node_modules/acorn/dist/walk.js @@ -77,7 +77,7 @@ function findNodeAt(node, start, end, test, base, state) { test = makeTest(test) if (!base) base = exports.base try { - ;(function c(node, st, override) { + (function c(node, st, override) { var type = override || node.type if ((start == null || node.start <= start) && (end == null || node.end >= end)) @@ -99,7 +99,7 @@ function findNodeAround(node, pos, test, base, state) { test = makeTest(test) if (!base) base = exports.base try { - ;(function c(node, st, override) { + (function c(node, st, override) { var type = override || node.type if (node.start > pos || node.end < pos) return base[type](node, st, c) @@ -116,7 +116,7 @@ function findNodeAfter(node, pos, test, base, state) { test = makeTest(test) if (!base) base = exports.base try { - ;(function c(node, st, override) { + (function c(node, st, override) { if (node.end < pos) return var type = override || node.type if (node.start >= pos && test(type, node)) throw new Found(node, st) @@ -261,7 +261,7 @@ base.Pattern = function (node, st, c) { base.VariablePattern = ignore base.MemberPattern = skipThrough base.RestElement = function (node, st, c) { return c(node.argument, st, "Pattern"); } -base.ArrayPattern = function (node, st, c) { +base.ArrayPattern = function (node, st, c) { for (var i = 0; i < node.elements.length; ++i) { var elt = node.elements[i] if (elt) c(elt, st, "Pattern") diff --git a/tools/eslint/node_modules/acorn/package.json b/tools/eslint/node_modules/acorn/package.json index 27dfdebdcb4d20..a76980d4a49620 100644 --- a/tools/eslint/node_modules/acorn/package.json +++ b/tools/eslint/node_modules/acorn/package.json @@ -2,25 +2,25 @@ "_args": [ [ { - "raw": "acorn@^4.0.1", + "raw": "acorn@^5.0.1", "scope": null, "escapedName": "acorn", "name": "acorn", - "rawSpec": "^4.0.1", - "spec": ">=4.0.1 <5.0.0", + "rawSpec": "^5.0.1", + "spec": ">=5.0.1 <6.0.0", "type": "range" }, "/Users/trott/io.js/tools/node_modules/espree" ] ], - "_from": "acorn@>=4.0.1 <5.0.0", - "_id": "acorn@4.0.4", + "_from": "acorn@>=5.0.1 <6.0.0", + "_id": "acorn@5.0.3", "_inCache": true, "_location": "/acorn", "_nodeVersion": "6.9.1", "_npmOperationalInternal": { - "host": "packages-12-west.internal.npmjs.com", - "tmp": "tmp/acorn-4.0.4.tgz_1482157987722_0.9571468001231551" + "host": "packages-18-east.internal.npmjs.com", + "tmp": "tmp/acorn-5.0.3.tgz_1491067098969_0.3370379332918674" }, "_npmUser": { "name": "marijn", @@ -29,21 +29,21 @@ "_npmVersion": "3.10.8", "_phantomChildren": {}, "_requested": { - "raw": "acorn@^4.0.1", + "raw": "acorn@^5.0.1", "scope": null, "escapedName": "acorn", "name": "acorn", - "rawSpec": "^4.0.1", - "spec": ">=4.0.1 <5.0.0", + "rawSpec": "^5.0.1", + "spec": ">=5.0.1 <6.0.0", "type": "range" }, "_requiredBy": [ "/espree" ], - "_resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.4.tgz", - "_shasum": "17a8d6a7a6c4ef538b814ec9abac2779293bf30a", + "_resolved": "https://registry.npmjs.org/acorn/-/acorn-5.0.3.tgz", + "_shasum": "c460df08491463f028ccb82eab3730bf01087b3d", "_shrinkwrap": null, - "_spec": "acorn@^4.0.1", + "_spec": "acorn@^5.0.1", "_where": "/Users/trott/io.js/tools/node_modules/espree", "bin": { "acorn": "./bin/acorn" @@ -124,6 +124,9 @@ { "name": "Johannes Herr" }, + { + "name": "John-David Dalton" + }, { "name": "Jordan Klassen" }, @@ -178,6 +181,9 @@ { "name": "Mike Rennie" }, + { + "name": "naoh" + }, { "name": "Nicholas C. Zakas" }, @@ -220,12 +226,18 @@ { "name": "Simen Bekkhus" }, + { + "name": "Teddy Katz" + }, { "name": "Timothy Gu" }, { "name": "Toru Nagashima" }, + { + "name": "Wexpo Lyu" + }, { "name": "zsjforcn" } @@ -233,19 +245,24 @@ "dependencies": {}, "description": "ECMAScript parser", "devDependencies": { + "eslint": "^3.18.0", + "eslint-config-standard": "^7.1.0", + "eslint-plugin-import": "^2.2.0", + "eslint-plugin-promise": "^3.5.0", + "eslint-plugin-standard": "^2.1.1", "rollup": "^0.34.1", "rollup-plugin-buble": "^0.11.0", "unicode-9.0.0": "^0.7.0" }, "directories": {}, "dist": { - "shasum": "17a8d6a7a6c4ef538b814ec9abac2779293bf30a", - "tarball": "https://registry.npmjs.org/acorn/-/acorn-4.0.4.tgz" + "shasum": "c460df08491463f028ccb82eab3730bf01087b3d", + "tarball": "https://registry.npmjs.org/acorn/-/acorn-5.0.3.tgz" }, "engines": { "node": ">=0.4.0" }, - "gitHead": "e7001cad79b4b0d7c4a6cf569ea33bfc808183cd", + "gitHead": "dc2a033831e0813496bdb558c70b9fdf4720f048", "homepage": "https://github.com/ternjs/acorn", "jsnext:main": "dist/acorn.es.js", "license": "MIT", @@ -254,10 +271,6 @@ { "name": "marijn", "email": "marijnh@gmail.com" - }, - { - "name": "rreverser", - "email": "me@rreverser.com" } ], "name": "acorn", @@ -273,9 +286,10 @@ "build:loose": "rollup -c rollup/config.loose.js", "build:main": "rollup -c rollup/config.main.js", "build:walk": "rollup -c rollup/config.walk.js", + "lint": "eslint src/", "prepublish": "npm test", "pretest": "npm run build", - "test": "node test/run.js" + "test": "node test/run.js && node test/lint.js" }, - "version": "4.0.4" + "version": "5.0.3" } diff --git a/tools/eslint/node_modules/acorn/src/.eslintrc b/tools/eslint/node_modules/acorn/src/.eslintrc new file mode 100644 index 00000000000000..5549678a7a8043 --- /dev/null +++ b/tools/eslint/node_modules/acorn/src/.eslintrc @@ -0,0 +1,33 @@ +{ + "extends": [ + "eslint:recommended", + "standard", + "plugin:import/errors", + "plugin:import/warnings" + ], + "rules": { + "curly": "off", + "eqeqeq": "off", + "indent": ["error", 2, { "SwitchCase": 0, "VariableDeclarator": 2 }], + "new-parens": "off", + "no-case-declarations": "off", + "no-cond-assign": "off", + "no-fallthrough": "off", + "no-labels": "off", + "no-mixed-operators": "off", + "no-return-assign": "off", + "no-unused-labels": "error", + "no-var": "error", + "object-curly-spacing": ["error", "never"], + "one-var": "off", + "quotes": ["error", "double"], + "semi-spacing": "off", + "space-before-function-paren": ["error", "never"] + }, + "globals": { + "Packages": false + }, + "plugins": [ + "import" + ] +} \ No newline at end of file diff --git a/tools/eslint/node_modules/acorn/src/bin/.eslintrc b/tools/eslint/node_modules/acorn/src/bin/.eslintrc new file mode 100644 index 00000000000000..2598b25f5f3b14 --- /dev/null +++ b/tools/eslint/node_modules/acorn/src/bin/.eslintrc @@ -0,0 +1,6 @@ +{ + "extends": "../.eslintrc", + "rules": { + "no-console": "off" + } +} \ No newline at end of file diff --git a/tools/eslint/node_modules/acorn/src/bin/acorn.js b/tools/eslint/node_modules/acorn/src/bin/acorn.js index 62e0dad1883664..b9ee5ee9df76e9 100644 --- a/tools/eslint/node_modules/acorn/src/bin/acorn.js +++ b/tools/eslint/node_modules/acorn/src/bin/acorn.js @@ -22,7 +22,7 @@ for (let i = 2; i < process.argv.length; ++i) { else if (arg == "--compact") compact = true else if (arg == "--help") help(0) else if (arg == "--tokenize") tokenize = true - else if (arg == "--module") options.sourceType = 'module' + else if (arg == "--module") options.sourceType = "module" else { let match = arg.match(/^--ecma(\d+)$/) if (match) @@ -34,18 +34,20 @@ for (let i = 2; i < process.argv.length; ++i) { function run(code) { let result - if (!tokenize) { - try { result = acorn.parse(code, options) } - catch(e) { console.error(e.message); process.exit(1) } - } else { - result = [] - let tokenizer = acorn.tokenizer(code, options), token - while (true) { - try { token = tokenizer.getToken() } - catch(e) { console.error(e.message); process.exit(1) } - result.push(token) - if (token.type == acorn.tokTypes.eof) break + try { + if (!tokenize) { + result = acorn.parse(code, options) + } else { + result = [] + let tokenizer = acorn.tokenizer(code, options), token + do { + token = tokenizer.getToken() + result.push(token) + } while (token.type != acorn.tokTypes.eof) } + } catch (e) { + console.error(e.message) + process.exit(1) } if (!silent) console.log(JSON.stringify(result, null, compact ? null : 2)) } diff --git a/tools/eslint/node_modules/acorn/src/expression.js b/tools/eslint/node_modules/acorn/src/expression.js index f8a7e0fff9f60d..47790d2dc0b2c6 100644 --- a/tools/eslint/node_modules/acorn/src/expression.js +++ b/tools/eslint/node_modules/acorn/src/expression.js @@ -47,8 +47,13 @@ pp.checkPropClash = function(prop, propHash) { name = "$" + name let other = propHash[name] if (other) { - let isGetSet = kind !== "init" - if ((this.strict || isGetSet) && other[kind] || !(isGetSet ^ other.init)) + let redefinition + if (kind === "init") { + redefinition = this.strict && other.init || other.get || other.set + } else { + redefinition = other.init || other[kind] + } + if (redefinition) this.raiseRecoverable(key.start, "Redefinition of property") } else { other = propHash[name] = { @@ -93,11 +98,16 @@ pp.parseExpression = function(noIn, refDestructuringErrors) { pp.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) { if (this.inGenerator && this.isContextual("yield")) return this.parseYield() - let ownDestructuringErrors = false - if (!refDestructuringErrors) { + let ownDestructuringErrors = false, oldParenAssign = -1, oldTrailingComma = -1 + if (refDestructuringErrors) { + oldParenAssign = refDestructuringErrors.parenthesizedAssign + oldTrailingComma = refDestructuringErrors.trailingComma + refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = -1 + } else { refDestructuringErrors = new DestructuringErrors ownDestructuringErrors = true } + let startPos = this.start, startLoc = this.startLoc if (this.type == tt.parenL || this.type == tt.name) this.potentialArrowAt = this.start @@ -109,7 +119,7 @@ pp.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) { let node = this.startNodeAt(startPos, startLoc) node.operator = this.value node.left = this.type === tt.eq ? this.toAssignable(left) : left - refDestructuringErrors.shorthandAssign = 0 // reset because shorthand default was used correctly + refDestructuringErrors.shorthandAssign = -1 // reset because shorthand default was used correctly this.checkLVal(left) this.next() node.right = this.parseMaybeAssign(noIn) @@ -117,6 +127,8 @@ pp.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) { } else { if (ownDestructuringErrors) this.checkExpressionErrors(refDestructuringErrors, true) } + if (oldParenAssign > -1) refDestructuringErrors.parenthesizedAssign = oldParenAssign + if (oldTrailingComma > -1) refDestructuringErrors.trailingComma = oldTrailingComma return left } @@ -143,7 +155,7 @@ pp.parseExprOps = function(noIn, refDestructuringErrors) { let startPos = this.start, startLoc = this.startLoc let expr = this.parseMaybeUnary(refDestructuringErrors, false) if (this.checkExpressionErrors(refDestructuringErrors)) return expr - return this.parseExprOp(expr, startPos, startLoc, -1, noIn) + return expr.start == startPos && expr.type === "ArrowFunctionExpression" ? expr : this.parseExprOp(expr, startPos, startLoc, -1, noIn) } // Parse binary operators with the operator precedence parsing @@ -223,24 +235,24 @@ pp.parseExprSubscripts = function(refDestructuringErrors) { let expr = this.parseExprAtom(refDestructuringErrors) let skipArrowSubscripts = expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")" if (this.checkExpressionErrors(refDestructuringErrors) || skipArrowSubscripts) return expr - return this.parseSubscripts(expr, startPos, startLoc) + let result = this.parseSubscripts(expr, startPos, startLoc) + if (refDestructuringErrors && result.type === "MemberExpression") { + if (refDestructuringErrors.parenthesizedAssign >= result.start) refDestructuringErrors.parenthesizedAssign = -1 + if (refDestructuringErrors.parenthesizedBind >= result.start) refDestructuringErrors.parenthesizedBind = -1 + } + return result } pp.parseSubscripts = function(base, startPos, startLoc, noCalls) { - for (;;) { - let maybeAsyncArrow = this.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" && !this.canInsertSemicolon() - if (this.eat(tt.dot)) { + let maybeAsyncArrow = this.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" && + this.lastTokEnd == base.end && !this.canInsertSemicolon() + for (let computed;;) { + if ((computed = this.eat(tt.bracketL)) || this.eat(tt.dot)) { let node = this.startNodeAt(startPos, startLoc) node.object = base - node.property = this.parseIdent(true) - node.computed = false - base = this.finishNode(node, "MemberExpression") - } else if (this.eat(tt.bracketL)) { - let node = this.startNodeAt(startPos, startLoc) - node.object = base - node.property = this.parseExpression() - node.computed = true - this.expect(tt.bracketR) + node.property = computed ? this.parseExpression() : this.parseIdent(true) + node.computed = !!computed + if (computed) this.expect(tt.bracketR) base = this.finishNode(node, "MemberExpression") } else if (!noCalls && this.eat(tt.parenL)) { let refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos @@ -248,7 +260,7 @@ pp.parseSubscripts = function(base, startPos, startLoc, noCalls) { this.awaitPos = 0 let exprList = this.parseExprList(tt.parenR, this.options.ecmaVersion >= 8, false, refDestructuringErrors) if (maybeAsyncArrow && !this.canInsertSemicolon() && this.eat(tt.arrow)) { - this.checkPatternErrors(refDestructuringErrors, true) + this.checkPatternErrors(refDestructuringErrors, false) this.checkYieldAwaitInDefaultParams() this.yieldPos = oldYieldPos this.awaitPos = oldAwaitPos @@ -324,7 +336,14 @@ pp.parseExprAtom = function(refDestructuringErrors) { return this.finishNode(node, "Literal") case tt.parenL: - return this.parseParenAndDistinguishExpression(canBeArrow) + let start = this.start, expr = this.parseParenAndDistinguishExpression(canBeArrow) + if (refDestructuringErrors) { + if (refDestructuringErrors.parenthesizedAssign < 0 && !this.isSimpleAssignTarget(expr)) + refDestructuringErrors.parenthesizedAssign = start + if (refDestructuringErrors.parenthesizedBind < 0) + refDestructuringErrors.parenthesizedBind = start + } + return expr case tt.bracketL: node = this.startNode() @@ -400,7 +419,7 @@ pp.parseParenAndDistinguishExpression = function(canBeArrow) { this.expect(tt.parenR) if (canBeArrow && !this.canInsertSemicolon() && this.eat(tt.arrow)) { - this.checkPatternErrors(refDestructuringErrors, true) + this.checkPatternErrors(refDestructuringErrors, false) this.checkYieldAwaitInDefaultParams() if (innerParenStart) this.unexpected(innerParenStart) this.yieldPos = oldYieldPos @@ -474,7 +493,7 @@ pp.parseNew = function() { pp.parseTemplateElement = function() { let elem = this.startNode() elem.value = { - raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, '\n'), + raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, "\n"), cooked: this.value } this.next() @@ -577,7 +596,7 @@ pp.parsePropertyValue = function(prop, isPattern, isGenerator, isAsync, startPos if (isPattern) { prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key) } else if (this.type === tt.eq && refDestructuringErrors) { - if (!refDestructuringErrors.shorthandAssign) + if (refDestructuringErrors.shorthandAssign < 0) refDestructuringErrors.shorthandAssign = this.start prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key) } else { @@ -616,7 +635,8 @@ pp.initFunction = function(node) { // Parse object or class method. pp.parseMethod = function(isGenerator, isAsync) { - let node = this.startNode(), oldInGen = this.inGenerator, oldInAsync = this.inAsync, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos + let node = this.startNode(), oldInGen = this.inGenerator, oldInAsync = this.inAsync, + oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction this.initFunction(node) if (this.options.ecmaVersion >= 6) @@ -628,6 +648,8 @@ pp.parseMethod = function(isGenerator, isAsync) { this.inAsync = node.async this.yieldPos = 0 this.awaitPos = 0 + this.inFunction = true + this.enterFunctionScope() this.expect(tt.parenL) node.params = this.parseBindingList(tt.parenR, false, this.options.ecmaVersion >= 8) @@ -638,14 +660,17 @@ pp.parseMethod = function(isGenerator, isAsync) { this.inAsync = oldInAsync this.yieldPos = oldYieldPos this.awaitPos = oldAwaitPos + this.inFunction = oldInFunc return this.finishNode(node, "FunctionExpression") } // Parse arrow function expression with given parameters. pp.parseArrowExpression = function(node, params, isAsync) { - let oldInGen = this.inGenerator, oldInAsync = this.inAsync, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos + let oldInGen = this.inGenerator, oldInAsync = this.inAsync, + oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction + this.enterFunctionScope() this.initFunction(node) if (this.options.ecmaVersion >= 8) node.async = !!isAsync @@ -654,6 +679,7 @@ pp.parseArrowExpression = function(node, params, isAsync) { this.inAsync = node.async this.yieldPos = 0 this.awaitPos = 0 + this.inFunction = true node.params = this.toAssignableList(params, true) this.parseFunctionBody(node, true) @@ -662,6 +688,7 @@ pp.parseArrowExpression = function(node, params, isAsync) { this.inAsync = oldInAsync this.yieldPos = oldYieldPos this.awaitPos = oldAwaitPos + this.inFunction = oldInFunc return this.finishNode(node, "ArrowFunctionExpression") } @@ -669,37 +696,42 @@ pp.parseArrowExpression = function(node, params, isAsync) { pp.parseFunctionBody = function(node, isArrowFunction) { let isExpression = isArrowFunction && this.type !== tt.braceL + let oldStrict = this.strict, useStrict = false if (isExpression) { node.body = this.parseMaybeAssign() node.expression = true + this.checkParams(node, false) } else { + let nonSimple = this.options.ecmaVersion >= 7 && !this.isSimpleParamList(node.params) + if (!oldStrict || nonSimple) { + useStrict = this.strictDirective(this.end) + // If this is a strict mode function, verify that argument names + // are not repeated, and it does not try to bind the words `eval` + // or `arguments`. + if (useStrict && nonSimple) + this.raiseRecoverable(node.start, "Illegal 'use strict' directive in function with non-simple parameter list") + } // Start a new scope with regard to labels and the `inFunction` // flag (restore them to their old value afterwards). - let oldInFunc = this.inFunction, oldLabels = this.labels - this.inFunction = true; this.labels = [] - node.body = this.parseBlock(true) + let oldLabels = this.labels + this.labels = [] + if (useStrict) this.strict = true + + // Add the params to varDeclaredNames to ensure that an error is thrown + // if a let/const declaration in the function clashes with one of the params. + this.checkParams(node, !oldStrict && !useStrict && !isArrowFunction && this.isSimpleParamList(node.params)) + node.body = this.parseBlock(false) node.expression = false - this.inFunction = oldInFunc; this.labels = oldLabels + this.labels = oldLabels } + this.exitFunctionScope() - // If this is a strict mode function, verify that argument names - // are not repeated, and it does not try to bind the words `eval` - // or `arguments`. - let useStrict = (!isExpression && node.body.body.length && this.isUseStrict(node.body.body[0])) ? node.body.body[0] : null - if (useStrict && this.options.ecmaVersion >= 7 && !this.isSimpleParamList(node.params)) - this.raiseRecoverable(useStrict.start, "Illegal 'use strict' directive in function with non-simple parameter list") - - if (this.strict || useStrict) { - let oldStrict = this.strict - this.strict = true - if (node.id) - this.checkLVal(node.id, true) - this.checkParams(node) - this.strict = oldStrict - } else if (isArrowFunction || !this.isSimpleParamList(node.params)) { - this.checkParams(node) + if (this.strict && node.id) { + // Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval' + this.checkLVal(node.id, "none") } + this.strict = oldStrict } pp.isSimpleParamList = function(params) { @@ -711,9 +743,9 @@ pp.isSimpleParamList = function(params) { // Checks function params for various disallowed patterns such as using "eval" // or "arguments" and duplicate parameters. -pp.checkParams = function(node) { +pp.checkParams = function(node, allowDuplicates) { let nameHash = {} - for (let i = 0; i < node.params.length; i++) this.checkLVal(node.params[i], true, nameHash) + for (let i = 0; i < node.params.length; i++) this.checkLVal(node.params[i], "var", allowDuplicates ? null : nameHash) } // Parses a comma-separated list of expressions, and returns them as @@ -735,11 +767,11 @@ pp.parseExprList = function(close, allowTrailingComma, allowEmpty, refDestructur elt = null else if (this.type === tt.ellipsis) { elt = this.parseSpread(refDestructuringErrors) - if (this.type === tt.comma && refDestructuringErrors && !refDestructuringErrors.trailingComma) { + if (refDestructuringErrors && this.type === tt.comma && refDestructuringErrors.trailingComma < 0) refDestructuringErrors.trailingComma = this.start - } - } else + } else { elt = this.parseMaybeAssign(false, refDestructuringErrors) + } elts.push(elt) } return elts diff --git a/tools/eslint/node_modules/acorn/src/identifier.js b/tools/eslint/node_modules/acorn/src/identifier.js index c65a24cf5fb410..fa5ded616e6cf7 100644 --- a/tools/eslint/node_modules/acorn/src/identifier.js +++ b/tools/eslint/node_modules/acorn/src/identifier.js @@ -10,7 +10,7 @@ export const reservedWords = { // And the keywords -var ecma5AndLessKeywords = "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" +const ecma5AndLessKeywords = "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" export const keywords = { 5: ecma5AndLessKeywords, @@ -38,7 +38,11 @@ nonASCIIidentifierStartChars = nonASCIIidentifierChars = null // offset starts at 0x10000, and each pair of numbers represents an // offset to the next range, and then a size of the range. They were // generated by bin/generate-identifier-regex.js + +// eslint-disable-next-line comma-spacing const astralIdentifierStartCodes = [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] + +// eslint-disable-next-line comma-spacing const astralIdentifierCodes = [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] // This has a complexity linear to the value of the code. The diff --git a/tools/eslint/node_modules/acorn/src/index.js b/tools/eslint/node_modules/acorn/src/index.js index 9debb0ac7cdedb..9c25d92ee142f5 100644 --- a/tools/eslint/node_modules/acorn/src/index.js +++ b/tools/eslint/node_modules/acorn/src/index.js @@ -25,18 +25,19 @@ import "./statement" import "./lval" import "./expression" import "./location" +import "./scope" export {Parser, plugins} from "./state" export {defaultOptions} from "./options" export {Position, SourceLocation, getLineInfo} from "./locutil" export {Node} from "./node" -export {TokenType, types as tokTypes} from "./tokentype" +export {TokenType, types as tokTypes, keywords as keywordTypes} from "./tokentype" export {TokContext, types as tokContexts} from "./tokencontext" export {isIdentifierChar, isIdentifierStart} from "./identifier" export {Token} from "./tokenize" -export {isNewLine, lineBreak, lineBreakG} from "./whitespace" +export {isNewLine, lineBreak, lineBreakG, nonASCIIwhitespace} from "./whitespace" -export const version = "4.0.4" +export const version = "5.0.3" // The main exported interface (under `self.acorn` when in the // browser) is a `parse` function that takes a code string and @@ -69,9 +70,9 @@ export function tokenizer(input, options) { // This is a terrible kludge to support the existing, pre-ES6 // interface where the loose parser module retroactively adds exports // to this module. -export let parse_dammit, LooseParser, pluginsLoose +export let parse_dammit, LooseParser, pluginsLoose // eslint-disable-line camelcase export function addLooseExports(parse, Parser, plugins) { - parse_dammit = parse + parse_dammit = parse // eslint-disable-line camelcase LooseParser = Parser pluginsLoose = plugins } diff --git a/tools/eslint/node_modules/acorn/src/loose/expression.js b/tools/eslint/node_modules/acorn/src/loose/expression.js index 1ef11b836dbaae..62bd42de3371ab 100644 --- a/tools/eslint/node_modules/acorn/src/loose/expression.js +++ b/tools/eslint/node_modules/acorn/src/loose/expression.js @@ -280,7 +280,7 @@ lp.parseExprAtom = function() { return this.parseObj() case tt._class: - return this.parseClass() + return this.parseClass(false) case tt._function: node = this.startNode() @@ -319,7 +319,7 @@ lp.parseNew = function() { lp.parseTemplateElement = function() { let elem = this.startNode() elem.value = { - raw: this.input.slice(this.tok.start, this.tok.end).replace(/\r\n?/g, '\n'), + raw: this.input.slice(this.tok.start, this.tok.end).replace(/\r\n?/g, "\n"), cooked: this.tok.value } this.next() @@ -340,7 +340,7 @@ lp.parseTemplate = function() { curElt = this.parseTemplateElement() } else { curElt = this.startNode() - curElt.value = {cooked: '', raw: ''} + curElt.value = {cooked: "", raw: ""} curElt.tail = true this.finishNode(curElt, "TemplateElement") } diff --git a/tools/eslint/node_modules/acorn/src/loose/index.js b/tools/eslint/node_modules/acorn/src/loose/index.js index 98bbf4b3bebbab..daf7bf2d792f30 100644 --- a/tools/eslint/node_modules/acorn/src/loose/index.js +++ b/tools/eslint/node_modules/acorn/src/loose/index.js @@ -39,6 +39,7 @@ export {LooseParser, pluginsLoose} from "./state" defaultOptions.tabSize = 4 +// eslint-disable-next-line camelcase export function parse_dammit(input, options) { let p = new LooseParser(input, options) p.next() diff --git a/tools/eslint/node_modules/acorn/src/loose/parseutil.js b/tools/eslint/node_modules/acorn/src/loose/parseutil.js index c5ee096a1dd7a6..b620fdaf0aca58 100644 --- a/tools/eslint/node_modules/acorn/src/loose/parseutil.js +++ b/tools/eslint/node_modules/acorn/src/loose/parseutil.js @@ -1 +1 @@ -export function isDummy(node) { return node.name == "✖" } \ No newline at end of file +export function isDummy(node) { return node.name == "✖" } diff --git a/tools/eslint/node_modules/acorn/src/loose/statement.js b/tools/eslint/node_modules/acorn/src/loose/statement.js index 42eda0597ef8e2..192df43e0f3f23 100644 --- a/tools/eslint/node_modules/acorn/src/loose/statement.js +++ b/tools/eslint/node_modules/acorn/src/loose/statement.js @@ -252,7 +252,7 @@ lp.parseClass = function(isStatement) { let node = this.startNode() this.next() if (this.tok.type === tt.name) node.id = this.parseIdent() - else if (isStatement) node.id = this.dummyIdent() + else if (isStatement === true) node.id = this.dummyIdent() else node.id = null node.superClass = this.eat(tt._extends) ? this.parseExpression() : null node.body = this.startNode() @@ -298,7 +298,7 @@ lp.parseClass = function(isStatement) { method.key.type === "Literal" && method.key.value === "constructor")) { method.kind = "constructor" } else { - method.kind = "method" + method.kind = "method" } method.value = this.parseMethod(isGenerator, isAsync) } @@ -326,7 +326,7 @@ lp.parseFunction = function(node, isStatement, isAsync) { node.async = !!isAsync } if (this.tok.type === tt.name) node.id = this.parseIdent() - else if (isStatement) node.id = this.dummyIdent() + else if (isStatement === true) node.id = this.dummyIdent() this.inAsync = node.async node.params = this.parseFunctionParams() node.body = this.parseBlock() @@ -343,16 +343,18 @@ lp.parseExport = function() { } if (this.eat(tt._default)) { // export default (function foo() {}) // This is FunctionExpression. - let isParenL = this.tok.type === tt.parenL - let expr = this.parseMaybeAssign() - if (!isParenL && expr.id) { - switch (expr.type) { - case "FunctionExpression": expr.type = "FunctionDeclaration"; break - case "ClassExpression": expr.type = "ClassDeclaration"; break - } + let isAsync + if (this.tok.type === tt._function || (isAsync = this.toks.isAsyncFunction())) { + let fNode = this.startNode() + this.next() + if (isAsync) this.next() + node.declaration = this.parseFunction(fNode, "nullableID", isAsync) + } else if (this.tok.type === tt._class) { + node.declaration = this.parseClass("nullableID") + } else { + node.declaration = this.parseMaybeAssign() + this.semicolon() } - node.declaration = expr - this.semicolon() return this.finishNode(node, "ExportDefaultDeclaration") } if (this.tok.type.keyword || this.toks.isLet() || this.toks.isAsyncFunction()) { @@ -374,7 +376,7 @@ lp.parseImport = function() { if (this.tok.type === tt.string) { node.specifiers = [] node.source = this.parseExprAtom() - node.kind = '' + node.kind = "" } else { let elt if (this.tok.type === tt.name && this.tok.value !== "from") { diff --git a/tools/eslint/node_modules/acorn/src/loose/tokenize.js b/tools/eslint/node_modules/acorn/src/loose/tokenize.js index c08be977832a98..2d5130b638e251 100644 --- a/tools/eslint/node_modules/acorn/src/loose/tokenize.js +++ b/tools/eslint/node_modules/acorn/src/loose/tokenize.js @@ -34,7 +34,7 @@ lp.readToken = function() { this.toks.type = tt.ellipsis } return new Token(this.toks) - } catch(e) { + } catch (e) { if (!(e instanceof SyntaxError)) throw e // Try to skip some text, based on the error message, and then continue @@ -45,12 +45,15 @@ lp.readToken = function() { replace = {start: e.pos, end: pos, type: tt.string, value: this.input.slice(e.pos + 1, pos)} } else if (/regular expr/i.test(msg)) { let re = this.input.slice(e.pos, pos) - try { re = new RegExp(re) } catch(e) {} + try { re = new RegExp(re) } catch (e) { /* ignore compilation error due to new syntax */ } replace = {start: e.pos, end: pos, type: tt.regexp, value: re} } else if (/template/.test(msg)) { - replace = {start: e.pos, end: pos, - type: tt.template, - value: this.input.slice(e.pos, pos)} + replace = { + start: e.pos, + end: pos, + type: tt.template, + value: this.input.slice(e.pos, pos) + } } else { replace = false } @@ -86,7 +89,7 @@ lp.readToken = function() { lp.resetTo = function(pos) { this.toks.pos = pos let ch = this.input.charAt(pos - 1) - this.toks.exprAllowed = !ch || /[\[\{\(,;:?\/*=+\-~!|&%^<>]/.test(ch) || + this.toks.exprAllowed = !ch || /[[{(,;:?/*=+\-~!|&%^<>]/.test(ch) || /[enwfd]/.test(ch) && /\b(keywords|case|else|return|throw|new|in|(instance|type)of|delete|void)$/.test(this.input.slice(pos - 10, pos)) diff --git a/tools/eslint/node_modules/acorn/src/lval.js b/tools/eslint/node_modules/acorn/src/lval.js index c88d71938b6310..815d9966a5d180 100644 --- a/tools/eslint/node_modules/acorn/src/lval.js +++ b/tools/eslint/node_modules/acorn/src/lval.js @@ -10,7 +10,7 @@ const pp = Parser.prototype pp.toAssignable = function(node, isBinding) { if (this.options.ecmaVersion >= 6 && node) { switch (node.type) { - case "Identifier": + case "Identifier": if (this.inAsync && node.name === "await") this.raise(node.start, "Can not use 'await' as identifier inside an async function") break @@ -172,48 +172,65 @@ pp.parseMaybeDefault = function(startPos, startLoc, left) { // Verify that a node is an lval — something that can be assigned // to. +// bindingType can be either: +// 'var' indicating that the lval creates a 'var' binding +// 'let' indicating that the lval creates a lexical ('let' or 'const') binding +// 'none' indicating that the binding should be checked for illegal identifiers, but not for duplicate references -pp.checkLVal = function(expr, isBinding, checkClashes) { +pp.checkLVal = function(expr, bindingType, checkClashes) { switch (expr.type) { case "Identifier": if (this.strict && this.reservedWordsStrictBind.test(expr.name)) - this.raiseRecoverable(expr.start, (isBinding ? "Binding " : "Assigning to ") + expr.name + " in strict mode") + this.raiseRecoverable(expr.start, (bindingType ? "Binding " : "Assigning to ") + expr.name + " in strict mode") if (checkClashes) { if (has(checkClashes, expr.name)) this.raiseRecoverable(expr.start, "Argument name clash") checkClashes[expr.name] = true } + if (bindingType && bindingType !== "none") { + if ( + bindingType === "var" && !this.canDeclareVarName(expr.name) || + bindingType !== "var" && !this.canDeclareLexicalName(expr.name) + ) { + this.raiseRecoverable(expr.start, `Identifier '${expr.name}' has already been declared`) + } + if (bindingType === "var") { + this.declareVarName(expr.name) + } else { + this.declareLexicalName(expr.name) + } + } break case "MemberExpression": - if (isBinding) this.raiseRecoverable(expr.start, (isBinding ? "Binding" : "Assigning to") + " member expression") + if (bindingType) this.raiseRecoverable(expr.start, (bindingType ? "Binding" : "Assigning to") + " member expression") break case "ObjectPattern": for (let i = 0; i < expr.properties.length; i++) - this.checkLVal(expr.properties[i].value, isBinding, checkClashes) + this.checkLVal(expr.properties[i].value, bindingType, checkClashes) break case "ArrayPattern": for (let i = 0; i < expr.elements.length; i++) { let elem = expr.elements[i] - if (elem) this.checkLVal(elem, isBinding, checkClashes) + if (elem) this.checkLVal(elem, bindingType, checkClashes) } break case "AssignmentPattern": - this.checkLVal(expr.left, isBinding, checkClashes) + this.checkLVal(expr.left, bindingType, checkClashes) break case "RestElement": - this.checkLVal(expr.argument, isBinding, checkClashes) + this.checkLVal(expr.argument, bindingType, checkClashes) break case "ParenthesizedExpression": - this.checkLVal(expr.expression, isBinding, checkClashes) + this.checkLVal(expr.expression, bindingType, checkClashes) break default: - this.raise(expr.start, (isBinding ? "Binding" : "Assigning to") + " rvalue") + this.raise(expr.start, (bindingType ? "Binding" : "Assigning to") + " rvalue") } } diff --git a/tools/eslint/node_modules/acorn/src/options.js b/tools/eslint/node_modules/acorn/src/options.js index e7b217e8d50967..9dda44ae880588 100644 --- a/tools/eslint/node_modules/acorn/src/options.js +++ b/tools/eslint/node_modules/acorn/src/options.js @@ -111,9 +111,9 @@ export function getOptions(opts) { } function pushComment(options, array) { - return function (block, text, start, end, startLoc, endLoc) { + return function(block, text, start, end, startLoc, endLoc) { let comment = { - type: block ? 'Block' : 'Line', + type: block ? "Block" : "Line", value: text, start: start, end: end @@ -125,4 +125,3 @@ function pushComment(options, array) { array.push(comment) } } - diff --git a/tools/eslint/node_modules/acorn/src/parseutil.js b/tools/eslint/node_modules/acorn/src/parseutil.js index 55d10344a8cdda..ffa00503026cdb 100644 --- a/tools/eslint/node_modules/acorn/src/parseutil.js +++ b/tools/eslint/node_modules/acorn/src/parseutil.js @@ -1,17 +1,21 @@ import {types as tt} from "./tokentype" import {Parser} from "./state" -import {lineBreak} from "./whitespace" +import {lineBreak, skipWhiteSpace} from "./whitespace" const pp = Parser.prototype // ## Parser utilities -// Test whether a statement node is the string literal `"use strict"`. - -pp.isUseStrict = function(stmt) { - return this.options.ecmaVersion >= 5 && stmt.type === "ExpressionStatement" && - stmt.expression.type === "Literal" && - stmt.expression.raw.slice(1, -1) === "use strict" +const literal = /^(?:'((?:[^']|\.)*)'|"((?:[^"]|\.)*)"|;)/ +pp.strictDirective = function(start) { + for (;;) { + skipWhiteSpace.lastIndex = start + start += skipWhiteSpace.exec(this.input)[0].length + let match = literal.exec(this.input.slice(start)) + if (!match) return false + if ((match[1] || match[2]) == "use strict") return true + start += match[0].length + } } // Predicate that tests whether the next token is of the given @@ -92,21 +96,22 @@ pp.unexpected = function(pos) { export class DestructuringErrors { constructor() { - this.shorthandAssign = 0 - this.trailingComma = 0 + this.shorthandAssign = this.trailingComma = this.parenthesizedAssign = this.parenthesizedBind = -1 } } -pp.checkPatternErrors = function(refDestructuringErrors, andThrow) { - let trailing = refDestructuringErrors && refDestructuringErrors.trailingComma - if (!andThrow) return !!trailing - if (trailing) this.raise(trailing, "Comma is not permitted after the rest element") +pp.checkPatternErrors = function(refDestructuringErrors, isAssign) { + if (!refDestructuringErrors) return + if (refDestructuringErrors.trailingComma > -1) + this.raiseRecoverable(refDestructuringErrors.trailingComma, "Comma is not permitted after the rest element") + let parens = isAssign ? refDestructuringErrors.parenthesizedAssign : refDestructuringErrors.parenthesizedBind + if (parens > -1) this.raiseRecoverable(parens, "Parenthesized pattern") } pp.checkExpressionErrors = function(refDestructuringErrors, andThrow) { - let pos = refDestructuringErrors && refDestructuringErrors.shorthandAssign - if (!andThrow) return !!pos - if (pos) this.raise(pos, "Shorthand property assignments are valid only in destructuring patterns") + let pos = refDestructuringErrors ? refDestructuringErrors.shorthandAssign : -1 + if (!andThrow) return pos >= 0 + if (pos > -1) this.raise(pos, "Shorthand property assignments are valid only in destructuring patterns") } pp.checkYieldAwaitInDefaultParams = function() { @@ -115,3 +120,9 @@ pp.checkYieldAwaitInDefaultParams = function() { if (this.awaitPos) this.raise(this.awaitPos, "Await expression cannot be a default value") } + +pp.isSimpleAssignTarget = function(expr) { + if (expr.type === "ParenthesizedExpression") + return this.isSimpleAssignTarget(expr.expression) + return expr.type === "Identifier" || expr.type === "MemberExpression" +} diff --git a/tools/eslint/node_modules/acorn/src/scope.js b/tools/eslint/node_modules/acorn/src/scope.js new file mode 100644 index 00000000000000..2ec0448990b37d --- /dev/null +++ b/tools/eslint/node_modules/acorn/src/scope.js @@ -0,0 +1,75 @@ +import {Parser} from "./state" +import {has} from "./util" + +const pp = Parser.prototype + +// Object.assign polyfill +const assign = Object.assign || function(target, ...sources) { + for (let i = 0; i < sources.length; i++) { + const source = sources[i] + for (const key in source) { + if (has(source, key)) { + target[key] = source[key] + } + } + } + return target +} + +// The functions in this module keep track of declared variables in the current scope in order to detect duplicate variable names. + +pp.enterFunctionScope = function() { + // var: a hash of var-declared names in the current lexical scope + // lexical: a hash of lexically-declared names in the current lexical scope + // childVar: a hash of var-declared names in all child lexical scopes of the current lexical scope (within the current function scope) + // parentLexical: a hash of lexically-declared names in all parent lexical scopes of the current lexical scope (within the current function scope) + this.scopeStack.push({var: {}, lexical: {}, childVar: {}, parentLexical: {}}) +} + +pp.exitFunctionScope = function() { + this.scopeStack.pop() +} + +pp.enterLexicalScope = function() { + const parentScope = this.scopeStack[this.scopeStack.length - 1] + const childScope = {var: {}, lexical: {}, childVar: {}, parentLexical: {}} + + this.scopeStack.push(childScope) + assign(childScope.parentLexical, parentScope.lexical, parentScope.parentLexical) +} + +pp.exitLexicalScope = function() { + const childScope = this.scopeStack.pop() + const parentScope = this.scopeStack[this.scopeStack.length - 1] + + assign(parentScope.childVar, childScope.var, childScope.childVar) +} + +/** + * A name can be declared with `var` if there are no variables with the same name declared with `let`/`const` + * in the current lexical scope or any of the parent lexical scopes in this function. + */ +pp.canDeclareVarName = function(name) { + const currentScope = this.scopeStack[this.scopeStack.length - 1] + + return !has(currentScope.lexical, name) && !has(currentScope.parentLexical, name) +} + +/** + * A name can be declared with `let`/`const` if there are no variables with the same name declared with `let`/`const` + * in the current scope, and there are no variables with the same name declared with `var` in the current scope or in + * any child lexical scopes in this function. + */ +pp.canDeclareLexicalName = function(name) { + const currentScope = this.scopeStack[this.scopeStack.length - 1] + + return !has(currentScope.lexical, name) && !has(currentScope.var, name) && !has(currentScope.childVar, name) +} + +pp.declareVarName = function(name) { + this.scopeStack[this.scopeStack.length - 1].var[name] = true +} + +pp.declareLexicalName = function(name) { + this.scopeStack[this.scopeStack.length - 1].lexical[name] = true +} diff --git a/tools/eslint/node_modules/acorn/src/state.js b/tools/eslint/node_modules/acorn/src/state.js index 1a8e2931726a57..5d9ae7501bd789 100644 --- a/tools/eslint/node_modules/acorn/src/state.js +++ b/tools/eslint/node_modules/acorn/src/state.js @@ -69,7 +69,8 @@ export class Parser { this.exprAllowed = true // Figure out if it's a module code. - this.strict = this.inModule = options.sourceType === "module" + this.inModule = options.sourceType === "module" + this.strict = this.inModule || this.strictDirective(this.pos) // Used to signify the start of a potential arrow function this.potentialArrowAt = -1 @@ -82,8 +83,12 @@ export class Parser { this.labels = [] // If enabled, skip leading hashbang line. - if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === '#!') + if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === "#!") this.skipLineComment(2) + + // Scope tracking for duplicate variable names (see scope.js) + this.scopeStack = [] + this.enterFunctionScope() } // DEPRECATED Kept for backwards compatibility until 3.0 in case a plugin uses them diff --git a/tools/eslint/node_modules/acorn/src/statement.js b/tools/eslint/node_modules/acorn/src/statement.js index 3cd29163d28d1c..eb2f18e8bc4c13 100644 --- a/tools/eslint/node_modules/acorn/src/statement.js +++ b/tools/eslint/node_modules/acorn/src/statement.js @@ -2,6 +2,7 @@ import {types as tt} from "./tokentype" import {Parser} from "./state" import {lineBreak, skipWhiteSpace} from "./whitespace" import {isIdentifierStart, isIdentifierChar} from "./identifier" +import {has} from "./util" import {DestructuringErrors} from "./parseutil" const pp = Parser.prototype @@ -14,15 +15,11 @@ const pp = Parser.prototype // to its body instead of creating a new node. pp.parseTopLevel = function(node) { - let first = true, exports = {} + let exports = {} if (!node.body) node.body = [] while (this.type !== tt.eof) { let stmt = this.parseStatement(true, true, exports) node.body.push(stmt) - if (first) { - if (this.isUseStrict(stmt)) this.setStrict(true) - first = false - } } this.next() if (this.options.ecmaVersion >= 6) { @@ -40,7 +37,8 @@ pp.isLet = function() { let next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next) if (nextCh === 91 || nextCh == 123) return true // '{' and '[' if (isIdentifierStart(nextCh, true)) { - for (var pos = next + 1; isIdentifierChar(this.input.charCodeAt(pos), true); ++pos) {} + let pos = next + 1 + while (isIdentifierChar(this.input.charCodeAt(pos), true)) ++pos let ident = this.input.slice(next, pos) if (!this.isKeyword(ident)) return true } @@ -145,7 +143,8 @@ pp.parseBreakContinueStatement = function(node, keyword) { // Verify that there is an actual destination to break or // continue to. - for (var i = 0; i < this.labels.length; ++i) { + let i = 0 + for (; i < this.labels.length; ++i) { let lab = this.labels[i] if (node.label == null || lab.name === node.label.name) { if (lab.kind != null && (isBreak || lab.kind === "loop")) break @@ -187,6 +186,7 @@ pp.parseDoStatement = function(node) { pp.parseForStatement = function(node) { this.next() this.labels.push(loopLabel) + this.enterLexicalScope() this.expect(tt.parenL) if (this.type === tt.semi) return this.parseFor(node, null) let isLet = this.isLet() @@ -203,9 +203,9 @@ pp.parseForStatement = function(node) { let refDestructuringErrors = new DestructuringErrors let init = this.parseExpression(true, refDestructuringErrors) if (this.type === tt._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) { - this.checkPatternErrors(refDestructuringErrors, true) this.toAssignable(init) this.checkLVal(init) + this.checkPatternErrors(refDestructuringErrors, true) return this.parseForIn(node, init) } else { this.checkExpressionErrors(refDestructuringErrors, true) @@ -251,12 +251,14 @@ pp.parseSwitchStatement = function(node) { node.cases = [] this.expect(tt.braceL) this.labels.push(switchLabel) + this.enterLexicalScope() // Statements under must be grouped (by label) in SwitchCase // nodes. `cur` is used to keep the node that we are currently // adding statements to. - for (var cur, sawDefault = false; this.type != tt.braceR;) { + let cur + for (let sawDefault = false; this.type != tt.braceR;) { if (this.type === tt._case || this.type === tt._default) { let isCase = this.type === tt._case if (cur) this.finishNode(cur, "SwitchCase") @@ -276,6 +278,7 @@ pp.parseSwitchStatement = function(node) { cur.consequent.push(this.parseStatement(true)) } } + this.exitLexicalScope() if (cur) this.finishNode(cur, "SwitchCase") this.next() // Closing brace this.labels.pop() @@ -304,9 +307,11 @@ pp.parseTryStatement = function(node) { this.next() this.expect(tt.parenL) clause.param = this.parseBindingAtom() - this.checkLVal(clause.param, true) + this.enterLexicalScope() + this.checkLVal(clause.param, "let") this.expect(tt.parenR) - clause.body = this.parseBlock() + clause.body = this.parseBlock(false) + this.exitLexicalScope() node.handler = this.finishNode(clause, "CatchClause") } node.finalizer = this.eat(tt._finally) ? this.parseBlock() : null @@ -357,6 +362,10 @@ pp.parseLabeledStatement = function(node, maybeName, expr) { } this.labels.push({name: maybeName, kind: kind, statementStart: this.start}) node.body = this.parseStatement(true) + if (node.body.type == "ClassDeclaration" || + node.body.type == "VariableDeclaration" && node.body.kind != "var" || + node.body.type == "FunctionDeclaration" && (this.strict || node.body.generator)) + this.raiseRecoverable(node.body.start, "Invalid labeled declaration") this.labels.pop() node.label = expr return this.finishNode(node, "LabeledStatement") @@ -372,20 +381,20 @@ pp.parseExpressionStatement = function(node, expr) { // strict"` declarations when `allowStrict` is true (used for // function bodies). -pp.parseBlock = function(allowStrict) { - let node = this.startNode(), first = true, oldStrict +pp.parseBlock = function(createNewLexicalScope = true) { + let node = this.startNode() node.body = [] this.expect(tt.braceL) + if (createNewLexicalScope) { + this.enterLexicalScope() + } while (!this.eat(tt.braceR)) { let stmt = this.parseStatement(true) node.body.push(stmt) - if (first && allowStrict && this.isUseStrict(stmt)) { - oldStrict = this.strict - this.setStrict(this.strict = true) - } - first = false } - if (oldStrict === false) this.setStrict(false) + if (createNewLexicalScope) { + this.exitLexicalScope() + } return this.finishNode(node, "BlockStatement") } @@ -400,6 +409,7 @@ pp.parseFor = function(node, init) { this.expect(tt.semi) node.update = this.type === tt.parenR ? null : this.parseExpression() this.expect(tt.parenR) + this.exitLexicalScope() node.body = this.parseStatement(false) this.labels.pop() return this.finishNode(node, "ForStatement") @@ -414,6 +424,7 @@ pp.parseForIn = function(node, init) { node.left = init node.right = this.parseExpression() this.expect(tt.parenR) + this.exitLexicalScope() node.body = this.parseStatement(false) this.labels.pop() return this.finishNode(node, type) @@ -426,7 +437,7 @@ pp.parseVar = function(node, isFor, kind) { node.kind = kind for (;;) { let decl = this.startNode() - this.parseVarId(decl) + this.parseVarId(decl, kind) if (this.eat(tt.eq)) { decl.init = this.parseMaybeAssign(isFor) } else if (kind === "const" && !(this.type === tt._in || (this.options.ecmaVersion >= 6 && this.isContextual("of")))) { @@ -442,9 +453,9 @@ pp.parseVar = function(node, isFor, kind) { return node } -pp.parseVarId = function(decl) { - decl.id = this.parseBindingAtom() - this.checkLVal(decl.id, true) +pp.parseVarId = function(decl, kind) { + decl.id = this.parseBindingAtom(kind) + this.checkLVal(decl.id, kind, false) } // Parse a function declaration or literal (depending on the @@ -457,17 +468,25 @@ pp.parseFunction = function(node, isStatement, allowExpressionBody, isAsync) { if (this.options.ecmaVersion >= 8) node.async = !!isAsync - if (isStatement) - node.id = this.parseIdent() + if (isStatement) { + node.id = isStatement === "nullableID" && this.type != tt.name ? null : this.parseIdent() + if (node.id) { + this.checkLVal(node.id, "var") + } + } - let oldInGen = this.inGenerator, oldInAsync = this.inAsync, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos + let oldInGen = this.inGenerator, oldInAsync = this.inAsync, + oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction this.inGenerator = node.generator this.inAsync = node.async this.yieldPos = 0 this.awaitPos = 0 + this.inFunction = true + this.enterFunctionScope() + + if (!isStatement) + node.id = this.type == tt.name ? this.parseIdent() : null - if (!isStatement && this.type === tt.name) - node.id = this.parseIdent() this.parseFunctionParams(node) this.parseFunctionBody(node, allowExpressionBody) @@ -475,6 +494,7 @@ pp.parseFunction = function(node, isStatement, allowExpressionBody, isAsync) { this.inAsync = oldInAsync this.yieldPos = oldYieldPos this.awaitPos = oldAwaitPos + this.inFunction = oldInFunc return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression") } @@ -489,6 +509,7 @@ pp.parseFunctionParams = function(node) { pp.parseClass = function(node, isStatement) { this.next() + this.parseClassId(node, isStatement) this.parseClassSuper(node) let classBody = this.startNode() @@ -558,7 +579,7 @@ pp.parseClassMethod = function(classBody, method, isGenerator, isAsync) { } pp.parseClassId = function(node, isStatement) { - node.id = this.type === tt.name ? this.parseIdent() : isStatement ? this.unexpected() : null + node.id = this.type === tt.name ? this.parseIdent() : isStatement === true ? this.unexpected() : null } pp.parseClassSuper = function(node) { @@ -578,20 +599,19 @@ pp.parseExport = function(node, exports) { } if (this.eat(tt._default)) { // export default ... this.checkExport(exports, "default", this.lastTokStart) - let parens = this.type == tt.parenL - let expr = this.parseMaybeAssign() - let needsSemi = true - if (!parens && (expr.type == "FunctionExpression" || - expr.type == "ClassExpression")) { - needsSemi = false - if (expr.id) { - expr.type = expr.type == "FunctionExpression" - ? "FunctionDeclaration" - : "ClassDeclaration" - } + let isAsync + if (this.type === tt._function || (isAsync = this.isAsyncFunction())) { + let fNode = this.startNode() + this.next() + if (isAsync) this.next() + node.declaration = this.parseFunction(fNode, "nullableID", false, isAsync) + } else if (this.type === tt._class) { + let cNode = this.startNode() + node.declaration = this.parseClass(cNode, "nullableID") + } else { + node.declaration = this.parseMaybeAssign() + this.semicolon() } - node.declaration = expr - if (needsSemi) this.semicolon() return this.finishNode(node, "ExportDefaultDeclaration") } // export var|const|let|function|class ... @@ -625,7 +645,7 @@ pp.parseExport = function(node, exports) { pp.checkExport = function(exports, name, pos) { if (!exports) return - if (Object.prototype.hasOwnProperty.call(exports, name)) + if (has(exports, name)) this.raiseRecoverable(pos, "Duplicate export '" + name + "'") exports[name] = true } @@ -655,12 +675,12 @@ pp.checkVariableExport = function(exports, decls) { } pp.shouldParseExportStatement = function() { - return this.type.keyword === "var" - || this.type.keyword === "const" - || this.type.keyword === "class" - || this.type.keyword === "function" - || this.isLet() - || this.isAsyncFunction() + return this.type.keyword === "var" || + this.type.keyword === "const" || + this.type.keyword === "class" || + this.type.keyword === "function" || + this.isLet() || + this.isAsyncFunction() } // Parses a comma-separated list of module exports. @@ -676,7 +696,7 @@ pp.parseExportSpecifiers = function(exports) { } else first = false let node = this.startNode() - node.local = this.parseIdent(this.type === tt._default) + node.local = this.parseIdent(true) node.exported = this.eatContextual("as") ? this.parseIdent(true) : node.local this.checkExport(exports, node.exported.name, node.exported.start) nodes.push(this.finishNode(node, "ExportSpecifier")) @@ -709,7 +729,7 @@ pp.parseImportSpecifiers = function() { // import defaultObj, { x, y as z } from '...' let node = this.startNode() node.local = this.parseIdent() - this.checkLVal(node.local, true) + this.checkLVal(node.local, "let") nodes.push(this.finishNode(node, "ImportDefaultSpecifier")) if (!this.eat(tt.comma)) return nodes } @@ -718,7 +738,7 @@ pp.parseImportSpecifiers = function() { this.next() this.expectContextual("as") node.local = this.parseIdent() - this.checkLVal(node.local, true) + this.checkLVal(node.local, "let") nodes.push(this.finishNode(node, "ImportNamespaceSpecifier")) return nodes } @@ -738,7 +758,7 @@ pp.parseImportSpecifiers = function() { if (this.isKeyword(node.local.name)) this.unexpected(node.local.start) if (this.reservedWordsStrict.test(node.local.name)) this.raiseRecoverable(node.local.start, "The keyword '" + node.local.name + "' is reserved") } - this.checkLVal(node.local, true) + this.checkLVal(node.local, "let") nodes.push(this.finishNode(node, "ImportSpecifier")) } return nodes diff --git a/tools/eslint/node_modules/acorn/src/tokencontext.js b/tools/eslint/node_modules/acorn/src/tokencontext.js index 911a51563d6d24..33e94f4898a464 100644 --- a/tools/eslint/node_modules/acorn/src/tokencontext.js +++ b/tools/eslint/node_modules/acorn/src/tokencontext.js @@ -7,11 +7,12 @@ import {types as tt} from "./tokentype" import {lineBreak} from "./whitespace" export class TokContext { - constructor(token, isExpr, preserveSpace, override) { + constructor(token, isExpr, preserveSpace, override, generator) { this.token = token this.isExpr = !!isExpr this.preserveSpace = !!preserveSpace this.override = override + this.generator = !!generator } } @@ -22,7 +23,9 @@ export const types = { p_stat: new TokContext("(", false), p_expr: new TokContext("(", true), q_tmpl: new TokContext("`", true, true, p => p.readTmplToken()), - f_expr: new TokContext("function", true) + f_expr: new TokContext("function", true), + f_expr_gen: new TokContext("function", true, false, null, true), + f_gen: new TokContext("function", false, false, null, true) } const pp = Parser.prototype @@ -39,13 +42,19 @@ pp.braceIsBlock = function(prevType) { } if (prevType === tt._return) return lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) - if (prevType === tt._else || prevType === tt.semi || prevType === tt.eof || prevType === tt.parenR) + if (prevType === tt._else || prevType === tt.semi || prevType === tt.eof || prevType === tt.parenR || prevType == tt.arrow) return true if (prevType == tt.braceL) return this.curContext() === types.b_stat return !this.exprAllowed } +pp.inGeneratorContext = function() { + for (let i = this.context.length - 1; i >= 0; i--) + if (this.context[i].generator) return true + return false +} + pp.updateContext = function(prevType) { let update, type = this.type if (type.keyword && prevType == tt.dot) @@ -63,8 +72,8 @@ tt.parenR.updateContext = tt.braceR.updateContext = function() { this.exprAllowed = true return } - let out = this.context.pop() - if (out === types.b_stat && this.curContext() === types.f_expr) { + let out = this.context.pop(), cur + if (out === types.b_stat && (cur = this.curContext()) && cur.token === "function") { this.context.pop() this.exprAllowed = false } else if (out === types.b_tmpl) { @@ -108,3 +117,23 @@ tt.backQuote.updateContext = function() { this.context.push(types.q_tmpl) this.exprAllowed = false } + +tt.star.updateContext = function(prevType) { + if (prevType == tt._function) { + if (this.curContext() === types.f_expr) + this.context[this.context.length - 1] = types.f_expr_gen + else + this.context.push(types.f_gen) + } + this.exprAllowed = true +} + +tt.name.updateContext = function(prevType) { + let allowed = false + if (this.options.ecmaVersion >= 6) { + if (this.value == "of" && !this.exprAllowed || + this.value == "yield" && this.inGeneratorContext()) + allowed = true + } + this.exprAllowed = allowed +} diff --git a/tools/eslint/node_modules/acorn/src/tokenize.js b/tools/eslint/node_modules/acorn/src/tokenize.js index 08ea7bf74fb854..917a013b88ab50 100644 --- a/tools/eslint/node_modules/acorn/src/tokenize.js +++ b/tools/eslint/node_modules/acorn/src/tokenize.js @@ -48,33 +48,21 @@ pp.getToken = function() { // If we're in an ES6 environment, make parsers iterable if (typeof Symbol !== "undefined") - pp[Symbol.iterator] = function () { - let self = this - return {next: function () { - let token = self.getToken() - return { - done: token.type === tt.eof, - value: token + pp[Symbol.iterator] = function() { + return { + next: () => { + let token = this.getToken() + return { + done: token.type === tt.eof, + value: token + } } - }} + } } // Toggle strict mode. Re-reads the next number or string to please // pedantic tests (`"use strict"; 010;` should fail). -pp.setStrict = function(strict) { - this.strict = strict - if (this.type !== tt.num && this.type !== tt.string) return - this.pos = this.start - if (this.options.locations) { - while (this.pos < this.lineStart) { - this.lineStart = this.input.lastIndexOf("\n", this.lineStart - 2) + 1 - --this.curLine - } - } - this.nextToken() -} - pp.curContext = function() { return this.context[this.context.length - 1] } @@ -131,7 +119,7 @@ pp.skipBlockComment = function() { pp.skipLineComment = function(startSkip) { let start = this.pos let startLoc = this.options.onComment && this.curPosition() - let ch = this.input.charCodeAt(this.pos+=startSkip) + let ch = this.input.charCodeAt(this.pos += startSkip) while (this.pos < this.input.length && ch !== 10 && ch !== 13 && ch !== 8232 && ch !== 8233) { ++this.pos ch = this.input.charCodeAt(this.pos) @@ -148,38 +136,38 @@ pp.skipSpace = function() { loop: while (this.pos < this.input.length) { let ch = this.input.charCodeAt(this.pos) switch (ch) { - case 32: case 160: // ' ' - ++this.pos - break - case 13: - if (this.input.charCodeAt(this.pos + 1) === 10) { - ++this.pos - } - case 10: case 8232: case 8233: + case 32: case 160: // ' ' + ++this.pos + break + case 13: + if (this.input.charCodeAt(this.pos + 1) === 10) { ++this.pos - if (this.options.locations) { - ++this.curLine - this.lineStart = this.pos - } + } + case 10: case 8232: case 8233: + ++this.pos + if (this.options.locations) { + ++this.curLine + this.lineStart = this.pos + } + break + case 47: // '/' + switch (this.input.charCodeAt(this.pos + 1)) { + case 42: // '*' + this.skipBlockComment() break - case 47: // '/' - switch (this.input.charCodeAt(this.pos + 1)) { - case 42: // '*' - this.skipBlockComment() - break - case 47: - this.skipLineComment(2) - break - default: - break loop - } + case 47: + this.skipLineComment(2) break default: - if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) { - ++this.pos - } else { - break loop - } + break loop + } + break + default: + if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) { + ++this.pos + } else { + break loop + } } } } @@ -223,7 +211,7 @@ pp.readToken_dot = function() { pp.readToken_slash = function() { // '/' let next = this.input.charCodeAt(this.pos + 1) - if (this.exprAllowed) {++this.pos; return this.readRegexp()} + if (this.exprAllowed) { ++this.pos; return this.readRegexp() } if (next === 61) return this.finishOp(tt.assign, 2) return this.finishOp(tt.slash, 1) } @@ -396,7 +384,7 @@ function tryCreateRegexp(src, flags, throwErrorAt, parser) { } } -var regexpUnicodeSupport = !!tryCreateRegexp("\uffff", "u") +const regexpUnicodeSupport = !!tryCreateRegexp("\uffff", "u") pp.readRegexp = function() { let escaped, inClass, start = this.pos @@ -523,7 +511,7 @@ pp.readCodePoint = function() { if (ch === 123) { if (this.options.ecmaVersion < 6) this.unexpected() let codePos = ++this.pos - code = this.readHexChar(this.input.indexOf('}', this.pos) - this.pos) + code = this.readHexChar(this.input.indexOf("}", this.pos) - this.pos) ++this.pos if (code > 0x10FFFF) this.raise(codePos, "Code point out of bounds") } else { @@ -586,14 +574,14 @@ pp.readTmplToken = function() { out += this.input.slice(chunkStart, this.pos) ++this.pos switch (ch) { - case 13: - if (this.input.charCodeAt(this.pos) === 10) ++this.pos - case 10: - out += "\n" - break - default: - out += String.fromCharCode(ch) - break + case 13: + if (this.input.charCodeAt(this.pos) === 10) ++this.pos + case 10: + out += "\n" + break + default: + out += String.fromCharCode(ch) + break } if (this.options.locations) { ++this.curLine @@ -691,7 +679,9 @@ pp.readWord1 = function() { pp.readWord = function() { let word = this.readWord1() let type = tt.name - if ((this.options.ecmaVersion >= 6 || !this.containsEsc) && this.keywords.test(word)) + if (this.keywords.test(word)) { + if (this.containsEsc) this.raiseRecoverable(this.start, "Escape sequence in keyword " + word) type = keywordTypes[word] + } return this.finishToken(type, word) } diff --git a/tools/eslint/node_modules/acorn/src/util.js b/tools/eslint/node_modules/acorn/src/util.js index 3517f8d212a749..9f548a140e59fd 100644 --- a/tools/eslint/node_modules/acorn/src/util.js +++ b/tools/eslint/node_modules/acorn/src/util.js @@ -1,9 +1,11 @@ -export function isArray(obj) { - return Object.prototype.toString.call(obj) === "[object Array]" -} +const {hasOwnProperty, toString} = Object.prototype // Checks if an object has a property. export function has(obj, propName) { - return Object.prototype.hasOwnProperty.call(obj, propName) + return hasOwnProperty.call(obj, propName) } + +export const isArray = Array.isArray || ((obj) => ( + toString.call(obj) === "[object Array]" +)) diff --git a/tools/eslint/node_modules/acorn/src/walk/index.js b/tools/eslint/node_modules/acorn/src/walk/index.js index 0da7e0d86c39b7..e1c6ad40998098 100644 --- a/tools/eslint/node_modules/acorn/src/walk/index.js +++ b/tools/eslint/node_modules/acorn/src/walk/index.js @@ -73,7 +73,7 @@ export function findNodeAt(node, start, end, test, base, state) { test = makeTest(test) if (!base) base = exports.base try { - ;(function c(node, st, override) { + (function c(node, st, override) { let type = override || node.type if ((start == null || node.start <= start) && (end == null || node.end >= end)) @@ -95,7 +95,7 @@ export function findNodeAround(node, pos, test, base, state) { test = makeTest(test) if (!base) base = exports.base try { - ;(function c(node, st, override) { + (function c(node, st, override) { let type = override || node.type if (node.start > pos || node.end < pos) return base[type](node, st, c) @@ -112,7 +112,7 @@ export function findNodeAfter(node, pos, test, base, state) { test = makeTest(test) if (!base) base = exports.base try { - ;(function c(node, st, override) { + (function c(node, st, override) { if (node.end < pos) return let type = override || node.type if (node.start >= pos && test(type, node)) throw new Found(node, st) @@ -151,7 +151,7 @@ const create = Object.create || function(proto) { export function make(funcs, base) { if (!base) base = exports.base let visitor = create(base) - for (var type in funcs) visitor[type] = funcs[type] + for (let type in funcs) visitor[type] = funcs[type] return visitor } @@ -257,7 +257,7 @@ base.Pattern = (node, st, c) => { base.VariablePattern = ignore base.MemberPattern = skipThrough base.RestElement = (node, st, c) => c(node.argument, st, "Pattern") -base.ArrayPattern = (node, st, c) => { +base.ArrayPattern = (node, st, c) => { for (let i = 0; i < node.elements.length; ++i) { let elt = node.elements[i] if (elt) c(elt, st, "Pattern") diff --git a/tools/eslint/node_modules/ajv-keywords/keywords/dotjs/_formatLimit.js b/tools/eslint/node_modules/ajv-keywords/keywords/dotjs/_formatLimit.js index 0f2a5e938030d7..b2c5093df5784b 100644 --- a/tools/eslint/node_modules/ajv-keywords/keywords/dotjs/_formatLimit.js +++ b/tools/eslint/node_modules/ajv-keywords/keywords/dotjs/_formatLimit.js @@ -4,7 +4,7 @@ module.exports = function generate__formatLimit(it, $keyword) { var $lvl = it.level; var $dataLvl = it.dataLevel; var $schema = it.schema[$keyword]; - var $schemaPath = it.schemaPath + '.' + $keyword; + var $schemaPath = it.schemaPath + it.util.getProperty($keyword); var $errSchemaPath = it.errSchemaPath + '/' + $keyword; var $breakOnError = !it.opts.allErrors; var $errorKeyword; @@ -37,7 +37,7 @@ module.exports = function generate__formatLimit(it, $keyword) { $isDataExcl = it.opts.v5 && $schemaExcl && $schemaExcl.$data, $op = $isMax ? '<' : '>', $result = 'result' + $lvl; - var $isData = it.opts.v5 && $schema && $schema.$data, + var $isData = it.opts.$data && $schema && $schema.$data, $schemaValue; if ($isData) { out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; '; diff --git a/tools/eslint/node_modules/ajv-keywords/keywords/dotjs/patternRequired.js b/tools/eslint/node_modules/ajv-keywords/keywords/dotjs/patternRequired.js index 196443aefef459..e20df98ca79182 100644 --- a/tools/eslint/node_modules/ajv-keywords/keywords/dotjs/patternRequired.js +++ b/tools/eslint/node_modules/ajv-keywords/keywords/dotjs/patternRequired.js @@ -4,7 +4,7 @@ module.exports = function generate_patternRequired(it, $keyword) { var $lvl = it.level; var $dataLvl = it.dataLevel; var $schema = it.schema[$keyword]; - var $schemaPath = it.schemaPath + '.' + $keyword; + var $schemaPath = it.schemaPath + it.util.getProperty($keyword); var $errSchemaPath = it.errSchemaPath + '/' + $keyword; var $breakOnError = !it.opts.allErrors; var $errorKeyword; diff --git a/tools/eslint/node_modules/ajv-keywords/keywords/dotjs/switch.js b/tools/eslint/node_modules/ajv-keywords/keywords/dotjs/switch.js index 6bef000ad412ef..f0e843fe0205fc 100644 --- a/tools/eslint/node_modules/ajv-keywords/keywords/dotjs/switch.js +++ b/tools/eslint/node_modules/ajv-keywords/keywords/dotjs/switch.js @@ -4,7 +4,7 @@ module.exports = function generate_switch(it, $keyword) { var $lvl = it.level; var $dataLvl = it.dataLevel; var $schema = it.schema[$keyword]; - var $schemaPath = it.schemaPath + '.' + $keyword; + var $schemaPath = it.schemaPath + it.util.getProperty($keyword); var $errSchemaPath = it.errSchemaPath + '/' + $keyword; var $breakOnError = !it.opts.allErrors; var $errorKeyword; diff --git a/tools/eslint/node_modules/ajv-keywords/package.json b/tools/eslint/node_modules/ajv-keywords/package.json index 8a03a0cf9194ff..2bc14214abb938 100644 --- a/tools/eslint/node_modules/ajv-keywords/package.json +++ b/tools/eslint/node_modules/ajv-keywords/package.json @@ -14,13 +14,13 @@ ] ], "_from": "ajv-keywords@>=1.0.0 <2.0.0", - "_id": "ajv-keywords@1.5.0", + "_id": "ajv-keywords@1.5.1", "_inCache": true, "_location": "/ajv-keywords", "_nodeVersion": "4.6.1", "_npmOperationalInternal": { - "host": "packages-12-west.internal.npmjs.com", - "tmp": "tmp/ajv-keywords-1.5.0.tgz_1482960345081_0.35162315983325243" + "host": "packages-18-east.internal.npmjs.com", + "tmp": "tmp/ajv-keywords-1.5.1.tgz_1485107517951_0.29220994655042887" }, "_npmUser": { "name": "esp", @@ -40,8 +40,8 @@ "_requiredBy": [ "/table" ], - "_resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.0.tgz", - "_shasum": "c11e6859eafff83e0dafc416929472eca946aa2c", + "_resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", + "_shasum": "314dd0a4b3368fad3dfcdc54ede6171b886daf3c", "_shrinkwrap": null, "_spec": "ajv-keywords@^1.0.0", "_where": "/Users/trott/io.js/tools/node_modules/table", @@ -70,14 +70,14 @@ }, "directories": {}, "dist": { - "shasum": "c11e6859eafff83e0dafc416929472eca946aa2c", - "tarball": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.0.tgz" + "shasum": "314dd0a4b3368fad3dfcdc54ede6171b886daf3c", + "tarball": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz" }, "files": [ "index.js", "keywords" ], - "gitHead": "0677af4020d8aee0e322b78932662a2fd59bd93f", + "gitHead": "33c43a2b190c9929fe9e3e9a32a38dace146abf4", "homepage": "https://github.com/epoberezkin/ajv-keywords#readme", "keywords": [ "JSON-Schema", @@ -110,5 +110,5 @@ "test-cov": "istanbul cover -x 'spec/**' node_modules/mocha/bin/_mocha -- spec/*.spec.js -R spec", "test-spec": "mocha spec/*.spec.js -R spec" }, - "version": "1.5.0" + "version": "1.5.1" } diff --git a/tools/eslint/node_modules/ajv/README.md b/tools/eslint/node_modules/ajv/README.md index 2d086258db9d23..984b7ba12d6f9c 100644 --- a/tools/eslint/node_modules/ajv/README.md +++ b/tools/eslint/node_modules/ajv/README.md @@ -11,9 +11,9 @@ The fastest JSON Schema validator for node.js and browser. Supports [v5 proposal [![Gitter](https://img.shields.io/gitter/room/ajv-validator/ajv.svg)](https://gitter.im/ajv-validator/ajv) -__Please note__: You can start using NEW beta version [5.0.1 (change log)](https://github.com/epoberezkin/ajv/releases/tag/5.0.1-beta.0) with the support of draft 6 (not officially published yet): `npm install ajv@^5.0.1-beta`. +__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`. -Also see [docs](https://github.com/epoberezkin/ajv/tree/b82905dc771193112c9c016f08c7fadb6ec3e896) for 5.0.1. +Also see [docs](https://github.com/epoberezkin/ajv/tree/5.0.3-beta.0) for 5.0.3. ## Contents @@ -94,10 +94,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.0](https://github.com/epoberezkin/ajv/releases/tag/5.0.0-beta.1): +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)): ``` -npm install ajv@^5.0.0-beta +npm install ajv@^5.0.3-beta ``` @@ -350,7 +350,9 @@ The advantages of using custom keywords are: - simplify your schemas - help bringing a bigger part of the validation logic to your schemas - make your schemas more expressive, less verbose and closer to your application domain -- implement custom data processors that modify your data and/or create side effects while the data is being validated +- implement custom data processors that modify your data (`modifying` option MUST be used in keyword definition) and/or create side effects while the data is being validated + +If a keyword is used only for side-effects and its validation result is pre-defined, use option `valid: true/false` in keyword definition to simplify both generated code (no error handling in case of `valid: true`) and your keyword functions (no need to return any validation result). The concerns you have to be aware of when extending JSON-schema standard with custom keywords are the portability and understanding of your schemas. You will have to support these custom keywords on other platforms and to properly document these keywords so that everybody can understand them in your schemas. @@ -460,7 +462,7 @@ function checkIdExists(schema, data) { .select('id') .where('id', data) .then(function (rows) { - return !!rows/length; // true if record is found + return !!rows.length; // true if record is found }); } @@ -925,6 +927,8 @@ Keyword definition is an object with the following properties: - _inline_: compiling function that returns code (as string) - _schema_: an optional `false` value used with "validate" keyword to not pass schema - _metaSchema_: an optional meta-schema for keyword schema +- _modifying_: `true` MUST be passed if keyword modifies data +- _valid_: pass `true`/`false` to pre-define validation result, the result returned from validation function will be ignored. This option cannot be used with macro keywords. - _$data_: an optional `true` value to support [$data reference](#data-reference) as the value of custom keyword. The reference will be resolved at validation time. If the keyword has meta-schema it would be extended to allow $data and it will be used to validate the resolved value. Supporting $data reference requires that keyword has validating function (as the only option or in addition to compile, macro or inline function). - _async_: an optional `true` value if the validation function is asynchronous (whether it is compiled or passed in _validate_ property); in this case it should return a promise that resolves with a value `true` or `false`. This option is ignored in case of "macro" and "inline" keywords. - _errors_: an optional boolean indicating whether keyword returns errors. If this property is not set Ajv will determine if the errors were set in case of failed validation. @@ -1146,20 +1150,24 @@ Properties of `params` object in errors depend on the keyword that failed valida ## Some packages using Ajv +- [webpack](https://github.com/webpack/webpack) - a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser - [jsonscript-js](https://github.com/JSONScript/jsonscript-js) - the interpreter for [JSONScript](http://www.jsonscript.org) - scripted processing of existing endpoints and services - [osprey-method-handler](https://github.com/mulesoft-labs/osprey-method-handler) - Express middleware for validating requests and responses based on a RAML method object, used in [osprey](https://github.com/mulesoft/osprey) - validating API proxy generated from a RAML definition -- [jsoneditor](https://github.com/josdejong/jsoneditor) - A web-based tool to view, edit, format, and validate JSON http://jsoneditoronline.org -- [JSON Schema Lint](https://github.com/nickcmaynard/jsonschemalint) - A web tool to validate JSON/YAML document against a single JSON-schema http://jsonschemalint.com +- [har-validator](https://github.com/ahmadnassri/har-validator) - HTTP Archive (HAR) validator +- [jsoneditor](https://github.com/josdejong/jsoneditor) - a web-based tool to view, edit, format, and validate JSON http://jsoneditoronline.org +- [JSON Schema Lint](https://github.com/nickcmaynard/jsonschemalint) - a web tool to validate JSON/YAML document against a single JSON-schema http://jsonschemalint.com - [objection](https://github.com/vincit/objection.js) - SQL-friendly ORM for node.js - [table](https://github.com/gajus/table) - formats data into a string table -- [ripple-lib](https://github.com/ripple/ripple-lib) - A JavaScript API for interacting with [Ripple](https://ripple.com) in Node.js and the browser -- [restbase](https://github.com/wikimedia/restbase) - Distributed storage with REST API & dispatcher for backend services built to provide a low-latency & high-throughput API for Wikipedia / Wikimedia content +- [ripple-lib](https://github.com/ripple/ripple-lib) - a JavaScript API for interacting with [Ripple](https://ripple.com) in Node.js and the browser +- [restbase](https://github.com/wikimedia/restbase) - distributed storage with REST API & dispatcher for backend services built to provide a low-latency & high-throughput API for Wikipedia / Wikimedia content - [hippie-swagger](https://github.com/CacheControl/hippie-swagger) - [Hippie](https://github.com/vesln/hippie) wrapper that provides end to end API testing with swagger validation - [react-form-controlled](https://github.com/seeden/react-form-controlled) - React controlled form components with validation -- [rabbitmq-schema](https://github.com/tjmehta/rabbitmq-schema) - A schema definition module for RabbitMQ graphs and messages +- [rabbitmq-schema](https://github.com/tjmehta/rabbitmq-schema) - a schema definition module for RabbitMQ graphs and messages - [@query/schema](https://www.npmjs.com/package/@query/schema) - stream filtering with a URI-safe query syntax parsing to JSON Schema - [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 - [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 3d1911a2bd1d43..1b76cb9f844092 100644 --- a/tools/eslint/node_modules/ajv/dist/ajv.bundle.js +++ b/tools/eslint/node_modules/ajv/dist/ajv.bundle.js @@ -2223,6 +2223,7 @@ module.exports = function generate_custom(it, $keyword) { var $breakOnError = !it.opts.allErrors; var $errorKeyword; var $data = 'data' + ($dataLvl || ''); + var $valid = 'valid' + $lvl; var $errs = 'errs__' + $lvl; var $isData = it.opts.v5 && $schema && $schema.$data, $schemaValue; @@ -2257,9 +2258,16 @@ module.exports = function generate_custom(it, $keyword) { if (!($inline || $macro)) { out += '' + ($ruleErrs) + ' = null;'; } - out += 'var ' + ($errs) + ' = errors;var valid' + ($lvl) + ';'; - if ($inline && $rDef.statements) { - out += ' ' + ($ruleValidate.validate); + out += 'var ' + ($errs) + ' = errors;var ' + ($valid) + ';'; + if ($validateSchema) { + out += ' ' + ($valid) + ' = ' + ($definition) + '.validateSchema(' + ($schemaValue) + '); if (' + ($valid) + ') {'; + } + if ($inline) { + if ($rDef.statements) { + out += ' ' + ($ruleValidate.validate) + ' '; + } else { + out += ' ' + ($valid) + ' = ' + ($ruleValidate.validate) + '; '; + } } else if ($macro) { var $it = it.util.copy(it); $it.level++; @@ -2271,7 +2279,7 @@ module.exports = function generate_custom(it, $keyword) { var $code = it.validate($it).replace(/validate\.schema/g, $validateCode); it.compositeRule = $it.compositeRule = $wasComposite; out += ' ' + ($code); - } else if (!$inline) { + } else { var $$outStack = $$outStack || []; $$outStack.push(out); out = ''; @@ -2290,102 +2298,56 @@ module.exports = function generate_custom(it, $keyword) { if (it.errorPath != '""') { out += ' + ' + (it.errorPath); } - if ($dataLvl) { - out += ' , data' + (($dataLvl - 1) || '') + ' , ' + (it.dataPathArr[$dataLvl]) + ' '; - } else { - out += ' , parentData , parentDataProperty '; - } - out += ' , rootData ) '; + var $parentData = $dataLvl ? 'data' + (($dataLvl - 1) || '') : 'parentData', + $parentDataProperty = $dataLvl ? it.dataPathArr[$dataLvl] : 'parentDataProperty'; + out += ' , ' + ($parentData) + ' , ' + ($parentDataProperty) + ' , rootData ) '; var def_callRuleValidate = out; out = $$outStack.pop(); - if ($rDef.errors !== false) { + if ($rDef.errors === false) { + out += ' ' + ($valid) + ' = '; + if ($asyncKeyword) { + out += '' + (it.yieldAwait); + } + out += '' + (def_callRuleValidate) + '; '; + } else { if ($asyncKeyword) { $ruleErrs = 'customErrors' + $lvl; - out += ' var ' + ($ruleErrs) + ' = null; try { valid' + ($lvl) + ' = ' + (it.yieldAwait) + (def_callRuleValidate) + '; } catch (e) { valid' + ($lvl) + ' = false; if (e instanceof ValidationError) ' + ($ruleErrs) + ' = e.errors; else throw e; } '; + out += ' var ' + ($ruleErrs) + ' = null; try { ' + ($valid) + ' = ' + (it.yieldAwait) + (def_callRuleValidate) + '; } catch (e) { ' + ($valid) + ' = false; if (e instanceof ValidationError) ' + ($ruleErrs) + ' = e.errors; else throw e; } '; } else { - out += ' ' + ($validateCode) + '.errors = null; '; + out += ' ' + ($ruleErrs) + ' = null; ' + ($valid) + ' = ' + (def_callRuleValidate) + '; '; } } } - out += 'if ('; + if ($rDef.modifying) { + out += ' ' + ($data) + ' = ' + ($parentData) + '[' + ($parentDataProperty) + '];'; + } if ($validateSchema) { - out += ' !' + ($definition) + '.validateSchema(' + ($schemaValue) + ') || '; + out += ' }'; } - out += ' ! '; - if ($inline) { - if ($rDef.statements) { - out += ' valid' + ($lvl) + ' '; - } else { - out += ' (' + ($ruleValidate.validate) + ') '; + if ($rDef.valid) { + if ($breakOnError) { + out += ' if (true) { '; } - } else if ($macro) { - out += ' ' + ($nextValid) + ' '; } else { - if ($asyncKeyword) { - if ($rDef.errors === false) { - out += ' (' + (it.yieldAwait) + (def_callRuleValidate) + ') '; + out += ' if ( '; + if ($rDef.valid === undefined) { + out += ' !'; + if ($macro) { + out += '' + ($nextValid); } else { - out += ' valid' + ($lvl) + ' '; + out += '' + ($valid); } } else { - out += ' ' + (def_callRuleValidate) + ' '; + out += ' ' + (!$rDef.valid) + ' '; } - } - out += ') { '; - $errorKeyword = $rule.keyword; - var $$outStack = $$outStack || []; - $$outStack.push(out); - out = ''; - var $$outStack = $$outStack || []; - $$outStack.push(out); - out = ''; /* istanbul ignore else */ - if (it.createErrors !== false) { - out += ' { keyword: \'' + ($errorKeyword || 'custom') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { keyword: \'' + ($rule.keyword) + '\' } '; - if (it.opts.messages !== false) { - out += ' , message: \'should pass "' + ($rule.keyword) + '" keyword validation\' '; - } - if (it.opts.verbose) { - out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; - } - out += ' } '; - } else { - out += ' {} '; - } - var __err = out; - out = $$outStack.pop(); - if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */ - if (it.async) { - out += ' throw new ValidationError([' + (__err) + ']); '; - } else { - out += ' validate.errors = [' + (__err) + ']; return false; '; - } - } else { - out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; - } - var def_customError = out; - out = $$outStack.pop(); - if ($inline) { - if ($rDef.errors) { - if ($rDef.errors != 'full') { - out += ' for (var ' + ($i) + '=' + ($errs) + '; ' + ($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:e r?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||"")+" , "+e.dataPathArr[n]+" ":" , parentData , parentDataProperty ",o+=", 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=" ",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="valid"+o,d=e.opts.v5&&n&&n.$data;d?(s+=" var schema"+o+" = "+e.util.getData(n.$data,i,e.dataPathArr)+"; ",a="schema"+o):a=n;var p="schema"+o;if(!d)if(n.length =e.opts.loopRequired;if(h)if(s+=" var missing"+o+"; ",w){d||(s+=" var "+p+" = validate.schema"+l+"; ");var j="i"+o,S="schema"+o+"["+j+"]",$="' + "+S+" + '";e.opts._errorDataPathProperty&&(e.errorPath=e.util.getPathExpr(b,S,e.opts.jsonPointers)),s+=" var "+f+" = true; ",d&&(s+=" if (schema"+o+" === undefined) "+f+" = true; else if (!Array.isArray(schema"+o+")) "+f+" = false; else {"),s+=" for (var "+j+" = 0; "+j+" < "+p+".length; "+j+"++) { "+f+" = "+u+"["+p+"["+j+"]] !== undefined; if (!"+f+") break; } ",d&&(s+=" } "),s+=" if (!"+f+") { ";var x=x||[];x.push(s),s="",e.createErrors!==!1?(s+=" { keyword: '"+(t||"required")+"' , dataPath: (dataPath || '') + "+e.errorPath+" , schemaPath: "+e.util.toQuotedString(c)+" , params: { missingProperty: '"+$+"' } ",e.opts.messages!==!1&&(s+=" , message: '",s+=e.opts._errorDataPathProperty?"is a required property":"should have required property \\'"+$+"\\'",s+="' "),e.opts.verbose&&(s+=" , schema: validate.schema"+l+" , parentSchema: validate.schema"+e.schemaPath+" , data: "+u+" "),s+=" } "):s+=" {} ";var _=s;s=x.pop(),s+=!e.compositeRule&&h?e.async?" throw new ValidationError(["+_+"]); ":" validate.errors = ["+_+"]; return false; ":" var err = "+_+"; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ",s+=" } else { "}else{s+=" if ( ";var O=m;if(O)for(var R,j=-1,I=O.length-1;j 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;r 1&&(a=t[0]+"@",e=t[1]),e=e.replace(q,".");var s=e.split("."),o=i(s,r).join(".");return a+o}function l(e){for(var r,t,a=[],s=0,o=e.length;s =55296&&r<=56319&&s 65535&&(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,!(u Q(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&&m Q((w-t)/y)&&o("overflow"),t+=(c-r)*y,r=c,n=0;n w&&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=255,P=/^[+a-z0-9A-Z_-]{0,63}$/,E=/^([+a-z0-9A-Z_-]{0,63})(.*)$/,b={javascript:!0,"javascript:":!0},w={javascript:!0,"javascript:":!0},j={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,"http:":!0,"https:":!0,"ftp:":!0,"gopher:":!0,"file:":!0},S=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&&a 127?"x":D[Q];if(!L.match(P)){var V=k.slice(0,_),z=k.slice(_+1),U=D.match(E);U&&(V.push(U[1]),z.unshift(U[2])),z.length&&(n="/"+z.join(".")+n),this.hostname=V.join(".");break}}}this.hostname=this.hostname.length>g?"":this.hostname.toLowerCase(),A||(this.hostname=l.toASCII(this.hostname));var T=this.port?":"+this.port:"",M=this.hostname||"";this.host=M+T,this.href+=this.host,A&&(this.hostname=this.hostname.substr(1,this.hostname.length-2),"/"!==n[0]&&(n="/"+n))}if(!b[p])for(var _=0,q=m.length;_ 0)&&t.host.split("@");$&&(t.auth=$.shift(),t.host=t.hostname=$.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 x=b.slice(-1)[0],_=(t.host||e.host||b.length>1)&&("."===x||".."===x)||""===x,O=0,R=b.length;R>=0;R--)x=b[R],"."===x?b.splice(R,1):".."===x?(b.splice(R,1),O++):O&&(b.splice(R,1),O--);if(!P&&!E)for(;O--;O)b.unshift("..");!P||""===b[0]||b[0]&&"/"===b[0].charAt(0)||b.unshift(""),_&&"/"!==b.join("/").substr(-1)&&b.push("");var I=""===b[0]||b[0]&&"/"===b[0].charAt(0);if(S){t.hostname=t.host=I?"":b.length?b.shift():"";var $=!!(t.host&&t.host.indexOf("@")>0)&&t.host.split("@");$&&(t.auth=$.shift(),t.host=t.hostname=$.shift())}return P=P||t.host&&b.length,P&&!I&&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":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)+'"'))}return"function"==typeof e&&(e=e.apply(r,t)),e&&"function"==typeof e.next?void i():a(e)})}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){return e?a(e):(arguments.length>2&&(r=f.call(arguments,1)),void 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();return e=+r,isFinite(e)?e:void 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(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:e r?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;r 1&&(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&&s 65535&&(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,!(u Q(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&&m Q((w-t)/y)&&o("overflow"),t+=(c-r)*y,r=c,n=0;n w&&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&&a 127?"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 =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;o 239?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;r r)&&(n=r);for(var i="",s=t;s n)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||t e.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);i 0&&(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),t 0&&(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){var i=Math.pow(2,8*n)-1;B(this,e,t,n,i,0)}var s=1,o=0;for(this[t]=255&e;++o =0&&(o*=256);)this[t+s]=e/o&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;s l?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;u 1)for(var n=1;n ]*>)(.*)/i,/(.*)(<\/script>)(.*)/i],o=0,a=!0;t=t.split("\n");for(var u=0;u 0){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))){var r=(f(S("condOp")),P(m.part("if ($0) return $1 ; return $2",[e.test,e.consequent,e.alternate]).body));s(e,r)}},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;r 0&&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;u 1?{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){var l=c(e);if(l){var p,h,d,m,g,v=!o[0].parent||a(o[0].parent).isScope;if(v){h=re(e,t(["const"]),!1);var x={},w={};h.forEach(function(e){e[0].self.declarations.forEach(function(e){se(e.id).forEach(function(t){x[t]||w[t]?(delete x[t],w[t]=e):x[t]=e})})}),h.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()})}var r="Program"===e.type||"module"===e.sourceType;if(!r||!u(e,function(e){return a(e).isES6},!0)){var s=he(e);!function(e){m.treeWalker(e,function(e,t,n){if("Program"===e.type||"FunctionDeclaration"===e.type||"FunctionExpression"===e.type){var r=s;if(s=s||he(e)){t();var i="Program"===e.type?e:e.body,o=re(i,function(e,t){if("FunctionDeclaration"===e.type)return t[0].parent!==i});o=o.map(function(e){return e[0].remove()}),[].push.apply(i.body,o)}else t();s=r}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;i 0){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;s 0)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"),++i 0)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&&"undefined"!=typeof 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;r e)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;return t?void(n&&this.raise(n,"Comma is not permitted after the rest element")):!!n},q.checkExpressionErrors=function(e,t){var n=e&&e.shorthandAssign;return t?void(n&&this.raise(n,"Shorthand property assignments are valid only in destructuring patterns")):!!n},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);if(e<=55295||e>=57344)return e;var t=this.input.charCodeAt(this.pos+1);return(e<<10)+t-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.index 8&&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(){var e=this.input.charCodeAt(this.pos+1);return 61===e?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)};var ue="4.0.4";e.version=ue,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&&"undefined"!=typeof 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?t 1?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;h 1&&(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;t 0&&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;d 0){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[u]=!0,null!=r&&this.add(r)}var i=e("./source-map-generator").SourceMapGenerator,s=e("./util"),o=/(\r?\n)/,a=10,u="$$$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(){var e=u.shift(),t=u.shift()||"";return e+t},l=1,p=0,h=null;return t.eachMapping(function(e){if(null!==h){if(!(l 0&&(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[u]&&"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[u]&&"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;n 0){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(){var e=Object.create(null);return!("__proto__"in e)}();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),r=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)};return new e(r)},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 +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?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}for(var s="function"==typeof require&&require,o=0;o =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;o 239?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;r r)&&(n=r);for(var i="",s=t;s n)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||t e.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);i 0&&(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),t 0&&(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;s l?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;u 1)for(var n=1;n ]*>)(.*)/i,/(.*)(<\/script>)(.*)/i],o=0,a=!0;t=t.split("\n");for(var u=0;u 0){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;r 0&&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;u 1?{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;i 0){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;s 0)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"),++i 0)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;r e)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.index 8&&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?t 1?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;h 1&&(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;t 0&&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;d 0){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(!(l 0&&(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;n 0){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 diff --git a/tools/eslint/node_modules/ajv/dist/regenerator.min.js b/tools/eslint/node_modules/ajv/dist/regenerator.min.js index 2d0d23621e24f4..83b02b98af34aa 100644 --- a/tools/eslint/node_modules/ajv/dist/regenerator.min.js +++ b/tools/eslint/node_modules/ajv/dist/regenerator.min.js @@ -1,36 +1,36 @@ /* regenerator 0.9.5: Source transformer enabling ECMAScript 6 generator functions (yield) in JavaScript-of-today (ES5) */ -require=function e(t,n,r){function i(s,o){if(!n[s]){if(!t[s]){var u="function"==typeof require&&require;if(!o&&u)return u(s,!0);if(a)return a(s,!0);var l=new Error("Cannot find module '"+s+"'");throw l.code="MODULE_NOT_FOUND",l}var c=n[s]={exports:{}};t[s][0].call(c.exports,function(e){var n=t[s][1][e];return i(n?n:e)},c,c.exports,e,t,n,r)}return n[s].exports}for(var a="function"==typeof require&&require,s=0;s =0;a--)if(s[a]!=o[a])return!1;for(a=s.length-1;a>=0;a--)if(i=s[a],!u(e[i],t[i]))return!1;return!0}function p(e,t){return!(!e||!t)&&("[object RegExp]"==Object.prototype.toString.call(t)?t.test(e):e instanceof t||t.call({},e)===!0)}function f(e,t,n,r){var i;h.isString(n)&&(r=n,n=null);try{t()}catch(e){i=e}if(r=(n&&n.name?" ("+n.name+").":".")+(r?" "+r:"."),e&&!i&&s(i,n,"Missing expected exception"+r),!e&&p(i,n)&&s(i,n,"Got unwanted exception"+r),e&&i&&n&&!p(i,n)||!e&&i)throw i}var h=e("util/"),d=Array.prototype.slice,y=Object.prototype.hasOwnProperty,m=t.exports=o;m.AssertionError=function(e){this.name="AssertionError",this.actual=e.actual,this.expected=e.expected,this.operator=e.operator,e.message?(this.message=e.message,this.generatedMessage=!1):(this.message=a(this),this.generatedMessage=!0);var t=e.stackStartFunction||s;if(Error.captureStackTrace)Error.captureStackTrace(this,t);else{var n=new Error;if(n.stack){var r=n.stack,i=t.name,o=r.indexOf("\n"+i);if(o>=0){var u=r.indexOf("\n",o+1);r=r.substring(u+1)}this.stack=r}}},h.inherits(m.AssertionError,Error),m.fail=s,m.ok=o,m.equal=function(e,t,n){e!=t&&s(e,t,n,"==",m.equal)},m.notEqual=function(e,t,n){e==t&&s(e,t,n,"!=",m.notEqual)},m.deepEqual=function(e,t,n){u(e,t)||s(e,t,n,"deepEqual",m.deepEqual)},m.notDeepEqual=function(e,t,n){u(e,t)&&s(e,t,n,"notDeepEqual",m.notDeepEqual)},m.strictEqual=function(e,t,n){e!==t&&s(e,t,n,"===",m.strictEqual)},m.notStrictEqual=function(e,t,n){e===t&&s(e,t,n,"!==",m.notStrictEqual)},m.throws=function(e,t,n){f.apply(this,[!0].concat(d.call(arguments)))},m.doesNotThrow=function(e,t){f.apply(this,[!1].concat(d.call(arguments)))},m.ifError=function(e){if(e)throw e};var b=Object.keys||function(e){var t=[];for(var n in e)y.call(e,n)&&t.push(n);return t}},{"util/":35}],3:[function(e,t,n){arguments[4][1][0].apply(n,arguments)},{dup:1}],4:[function(e,t,n){(function(t){"use strict";function r(){try{var e=new Uint8Array(1);return e.__proto__={__proto__:Uint8Array.prototype,foo:function(){return 42}},42===e.foo()&&"function"==typeof e.subarray&&0===e.subarray(1,1).byteLength}catch(e){return!1}}function i(){return s.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function a(e,t){if(i() =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),s.alloc(+e)}function b(e,t){if(s.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 X(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 X(e).length;t=(""+t).toLowerCase(),r=!0}}function g(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 B(this,t,n);case"utf8":case"utf-8":return F(this,t,n);case"ascii":return P(this,t,n);case"latin1":case"binary":return j(this,t,n);case"base64":return k(this,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return O(this,t,n);default:if(r)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),r=!0}}function v(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=s.from(t,r)),s.isBuffer(t))return 0===t.length?-1:_(e,t,n,r,i);if("number"==typeof t)return t&=255,s.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?i?Uint8Array.prototype.indexOf.call(e,t,n):Uint8Array.prototype.lastIndexOf.call(e,t,n):_(e,[t],n,r,i);throw new TypeError("val must be string, number or Buffer")}function _(e,t,n,r,i){function a(e,t){return 1===s?e[t]:e.readUInt16BE(t*s)}var s=1,o=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;s=2,o/=2,u/=2,n/=2}var l;if(i){var c=-1;for(l=n;l o&&(n=o-u),l=n;l>=0;l--){for(var p=!0,f=0;fi&&(r=i)):r=i;var a=t.length;if(a%2!==0)throw new TypeError("Invalid hex string");r>a/2&&(r=a/2);for(var s=0;s 239?4:a>223?3:a>191?2:1;if(i+o<=n){var u,l,c,p;switch(o){case 1:a<128&&(s=a);break;case 2:u=e[i+1],128===(192&u)&&(p=(31&a)<<6|63&u,p>127&&(s=p));break;case 3:u=e[i+1],l=e[i+2],128===(192&u)&&128===(192&l)&&(p=(15&a)<<12|(63&u)<<6|63&l,p>2047&&(p<55296||p>57343)&&(s=p));break;case 4:u=e[i+1],l=e[i+2],c=e[i+3],128===(192&u)&&128===(192&l)&&128===(192&c)&&(p=(15&a)<<18|(63&u)<<12|(63&l)<<6|63&c,p>65535&&p<1114112&&(s=p))}}null===s?(s=65533,o=1):s>65535&&(s-=65536,r.push(s>>>10&1023|55296),s=56320|1023&s),r.push(s),i+=o}return T(r)}function T(e){var t=e.length;if(t<=ee)return String.fromCharCode.apply(String,e);for(var n="",r=0;r r)&&(n=r);for(var i="",a=t;a n)throw new RangeError("Trying to access beyond buffer length")}function N(e,t,n,r,i,a){if(!s.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 L(e,t,n,r){t<0&&(t=65535+t+1);for(var i=0,a=Math.min(e.length-n,2);i>>8*(r?i:1-i)}function M(e,t,n,r){t<0&&(t=4294967295+t+1);for(var i=0,a=Math.min(e.length-n,4);i>>8*(r?i:3-i)&255}function R(e,t,n,r,i,a){if(n+r>e.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("Index out of range")}function U(e,t,n,r,i){return i||R(e,t,n,4,3.4028234663852886e38,-3.4028234663852886e38),Q.write(e,t,n,r,23,4),n+4}function V(e,t,n,r,i){return i||R(e,t,n,8,1.7976931348623157e308,-1.7976931348623157e308),Q.write(e,t,n,r,52,8),n+8}function G(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 K(e){return e<16?"0"+e.toString(16):e.toString(16)}function X(e,t){t=t||1/0;for(var n,r=e.length,i=null,a=[],s=0;s 55295&&n<57344){if(!i){if(n>56319){(t-=3)>-1&&a.push(239,191,189);continue}if(s+1===r){(t-=3)>-1&&a.push(239,191,189);continue}i=n;continue}if(n<56320){(t-=3)>-1&&a.push(239,191,189),i=n;continue}n=(i-55296<<10|n-56320)+65536}else i&&(t-=3)>-1&&a.push(239,191,189);if(i=null,n<128){if((t-=1)<0)break;a.push(n)}else if(n<2048){if((t-=2)<0)break;a.push(n>>6|192,63&n|128)}else if(n<65536){if((t-=3)<0)break;a.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;a.push(n>>18|240,n>>12&63|128,n>>6&63|128,63&n|128)}}return a}function J(e){for(var t=[],n=0;n >8,i=n%256,a.push(i),a.push(r);return a}function z(e){return $.toByteArray(G(e))}function Y(e,t,n,r){for(var i=0;i =t.length||i>=e.length);++i)t[i+n]=e[i];return i}function H(e){return e!==e}var $=e("base64-js"),Q=e("ieee754"),Z=e("isarray");n.Buffer=s,n.SlowBuffer=m,n.INSPECT_MAX_BYTES=50,s.TYPED_ARRAY_SUPPORT=void 0!==t.TYPED_ARRAY_SUPPORT?t.TYPED_ARRAY_SUPPORT:r(),n.kMaxLength=i(),s.poolSize=8192,s._augment=function(e){return e.__proto__=s.prototype,e},s.from=function(e,t,n){return o(null,e,t,n)},s.TYPED_ARRAY_SUPPORT&&(s.prototype.__proto__=Uint8Array.prototype,s.__proto__=Uint8Array,"undefined"!=typeof Symbol&&Symbol.species&&s[Symbol.species]===s&&Object.defineProperty(s,Symbol.species,{value:null,configurable:!0})),s.alloc=function(e,t,n){return l(null,e,t,n)},s.allocUnsafe=function(e){return c(null,e)},s.allocUnsafeSlow=function(e){return c(null,e)},s.isBuffer=function(e){return!(null==e||!e._isBuffer)},s.compare=function(e,t){if(!s.isBuffer(e)||!s.isBuffer(t))throw new TypeError("Arguments must be Buffers");if(e===t)return 0;for(var n=e.length,r=t.length,i=0,a=Math.min(n,r);i0&&(e=this.toString("hex",0,t).match(/.{2}/g).join(" "),this.length>t&&(e+=" ... "))," "},s.prototype.compare=function(e,t,n,r,i){if(!s.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 a=i-r,o=n-t,u=Math.min(a,o),l=this.slice(r,i),c=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 a=!1;;)switch(r){case"hex":return E(this,e,t,n);case"utf8":case"utf-8":return A(this,e,t,n);case"ascii":return D(this,e,t,n);case"latin1":case"binary":return C(this,e,t,n);case"base64":return S(this,e,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return w(this,e,t,n);default:if(a)throw new TypeError("Unknown encoding: "+r);r=(""+r).toLowerCase(),a=!0}},s.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var ee=4096;s.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),t 0&&(i*=256);)r+=this[e+--t]*i;return r},s.prototype.readUInt8=function(e,t){return t||I(e,1,this.length),this[e]},s.prototype.readUInt16LE=function(e,t){return t||I(e,2,this.length),this[e]|this[e+1]<<8},s.prototype.readUInt16BE=function(e,t){return t||I(e,2,this.length),this[e]<<8|this[e+1]},s.prototype.readUInt32LE=function(e,t){return t||I(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},s.prototype.readUInt32BE=function(e,t){return t||I(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},s.prototype.readIntLE=function(e,t,n){e|=0,t|=0,n||I(e,t,this.length);for(var r=this[e],i=1,a=0;++a =i&&(r-=Math.pow(2,8*t)),r},s.prototype.readIntBE=function(e,t,n){e|=0,t|=0,n||I(e,t,this.length);for(var r=t,i=1,a=this[e+--r];r>0&&(i*=256);)a+=this[e+--r]*i;return i*=128,a>=i&&(a-=Math.pow(2,8*t)),a},s.prototype.readInt8=function(e,t){return t||I(e,1,this.length),128&this[e]?(255-this[e]+1)*-1:this[e]},s.prototype.readInt16LE=function(e,t){t||I(e,2,this.length);var n=this[e]|this[e+1]<<8;return 32768&n?4294901760|n:n},s.prototype.readInt16BE=function(e,t){t||I(e,2,this.length);var n=this[e+1]|this[e]<<8;return 32768&n?4294901760|n:n},s.prototype.readInt32LE=function(e,t){return t||I(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},s.prototype.readInt32BE=function(e,t){return t||I(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},s.prototype.readFloatLE=function(e,t){return t||I(e,4,this.length),Q.read(this,e,!0,23,4)},s.prototype.readFloatBE=function(e,t){return t||I(e,4,this.length),Q.read(this,e,!1,23,4)},s.prototype.readDoubleLE=function(e,t){return t||I(e,8,this.length),Q.read(this,e,!0,52,8)},s.prototype.readDoubleBE=function(e,t){return t||I(e,8,this.length),Q.read(this,e,!1,52,8)},s.prototype.writeUIntLE=function(e,t,n,r){if(e=+e,t|=0,n|=0,!r){var i=Math.pow(2,8*n)-1;N(this,e,t,n,i,0)}var a=1,s=0;for(this[t]=255&e;++s =0&&(s*=256);)this[t+a]=e/s&255;return t+n},s.prototype.writeUInt8=function(e,t,n){return e=+e,t|=0,n||N(this,e,t,1,255,0),s.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),this[t]=255&e,t+1},s.prototype.writeUInt16LE=function(e,t,n){return e=+e,t|=0,n||N(this,e,t,2,65535,0),s.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):L(this,e,t,!0),t+2},s.prototype.writeUInt16BE=function(e,t,n){return e=+e,t|=0,n||N(this,e,t,2,65535,0),s.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):L(this,e,t,!1),t+2},s.prototype.writeUInt32LE=function(e,t,n){return e=+e,t|=0,n||N(this,e,t,4,4294967295,0),s.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e):M(this,e,t,!0),t+4},s.prototype.writeUInt32BE=function(e,t,n){return e=+e,t|=0,n||N(this,e,t,4,4294967295,0),s.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):M(this,e,t,!1),t+4},s.prototype.writeIntLE=function(e,t,n,r){if(e=+e,t|=0,!r){var i=Math.pow(2,8*n-1);N(this,e,t,n,i-1,-i)}var a=0,s=1,o=0;for(this[t]=255&e;++a >0)-o&255;return t+n},s.prototype.writeIntBE=function(e,t,n,r){if(e=+e,t|=0,!r){var i=Math.pow(2,8*n-1);N(this,e,t,n,i-1,-i)}var a=n-1,s=1,o=0;for(this[t+a]=255&e;--a>=0&&(s*=256);)e<0&&0===o&&0!==this[t+a+1]&&(o=1),this[t+a]=(e/s>>0)-o&255;return t+n},s.prototype.writeInt8=function(e,t,n){return e=+e,t|=0,n||N(this,e,t,1,127,-128),s.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),e<0&&(e=255+e+1),this[t]=255&e,t+1},s.prototype.writeInt16LE=function(e,t,n){return e=+e,t|=0,n||N(this,e,t,2,32767,-32768),s.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):L(this,e,t,!0),t+2},s.prototype.writeInt16BE=function(e,t,n){return e=+e,t|=0,n||N(this,e,t,2,32767,-32768),s.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):L(this,e,t,!1),t+2},s.prototype.writeInt32LE=function(e,t,n){return e=+e,t|=0,n||N(this,e,t,4,2147483647,-2147483648),s.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):M(this,e,t,!0),t+4},s.prototype.writeInt32BE=function(e,t,n){return e=+e,t|=0,n||N(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),s.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):M(this,e,t,!1),t+4},s.prototype.writeFloatLE=function(e,t,n){return U(this,e,t,!0,n)},s.prototype.writeFloatBE=function(e,t,n){return U(this,e,t,!1,n)},s.prototype.writeDoubleLE=function(e,t,n){return V(this,e,t,!0,n)},s.prototype.writeDoubleBE=function(e,t,n){return V(this,e,t,!1,n)},s.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(a<1e3||!s.TYPED_ARRAY_SUPPORT)for(i=0;i>>=0,n=void 0===n?this.length:n>>>0,e||(e=0);var a;if("number"==typeof e)for(a=t;a 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 a(e){var t,n,i,a,s,o,u=e.length;s=r(e),o=new p(3*u/4-s),i=s>0?u-4:u;var l=0;for(t=0,n=0;t>16&255,o[l++]=a>>8&255,o[l++]=255&a;return 2===s?(a=c[e.charCodeAt(t)]<<2|c[e.charCodeAt(t+1)]>>4,o[l++]=255&a):1===s&&(a=c[e.charCodeAt(t)]<<10|c[e.charCodeAt(t+1)]<<4|c[e.charCodeAt(t+2)]>>2,o[l++]=a>>8&255,o[l++]=255&a),o}function s(e){return l[e>>18&63]+l[e>>12&63]+l[e>>6&63]+l[63&e]}function o(e,t,n){for(var r,i=[],a=t;a c?c:u+s));return 1===r?(t=e[n-1],i+=l[t>>2],i+=l[t<<4&63],i+="=="):2===r&&(t=(e[n-2]<<8)+e[n-1],i+=l[t>>10],i+=l[t>>4&63],i+=l[t<<2&63],i+="="),a.push(i),a.join("")}n.byteLength=i,n.toByteArray=a,n.fromByteArray=u;for(var l=[],c=[],p="undefined"!=typeof Uint8Array?Uint8Array:Array,f="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",h=0,d=f.length;h >1,c=-7,p=n?i-1:0,f=n?-1:1,h=e[t+p];for(p+=f,a=h&(1<<-c)-1,h>>=-c,c+=o;c>0;a=256*a+e[t+p],p+=f,c-=8);for(s=a&(1<<-c)-1,a>>=-c,c+=r;c>0;s=256*s+e[t+p],p+=f,c-=8);if(0===a)a=1-l;else{if(a===u)return s?NaN:(h?-1:1)*(1/0);s+=Math.pow(2,r),a-=l}return(h?-1:1)*s*Math.pow(2,a-r)},n.write=function(e,t,n,r,i,a){var s,o,u,l=8*a-i-1,c=(1< >1,f=23===i?Math.pow(2,-24)-Math.pow(2,-77):0,h=r?0:a-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?(o=isNaN(t)?1:0,s=c):(s=Math.floor(Math.log(t)/Math.LN2),t*(u=Math.pow(2,-s))<1&&(s--,u*=2),t+=s+p>=1?f/u:f*Math.pow(2,1-p),t*u>=2&&(s++,u/=2),s+p>=c?(o=0,s=c):s+p>=1?(o=(t*u-1)*Math.pow(2,i),s+=p):(o=t*Math.pow(2,p-1)*Math.pow(2,i),s=0));i>=8;e[n+h]=255&o,h+=d,o/=256,i-=8);for(s=s<