diff --git a/.eslintrc b/.eslintrc index 38d01df0778210..59f9f06e8baa0d 100644 --- a/.eslintrc +++ b/.eslintrc @@ -13,7 +13,7 @@ rules: no-duplicate-case: 2 no-empty-character-class: 2 no-ex-assign: 2 - no-extra-boolean-cast : 2 + no-extra-boolean-cast: 2 no-extra-parens: [2, "functions"] no-extra-semi: 2 no-func-assign: 2 @@ -85,10 +85,11 @@ rules: prefer-const: 2 # Custom rules in tools/eslint-rules + align-function-arguments: 2 + align-multiline-assignment: 2 assert-fail-single-argument: 2 new-with-error: [2, "Error", "RangeError", "TypeError", "SyntaxError", "ReferenceError"] - # Global scoped method and vars globals: DTRACE_HTTP_CLIENT_REQUEST : false diff --git a/.gitignore b/.gitignore index 8f75e34da6fd5a..5eabf17883b951 100644 --- a/.gitignore +++ b/.gitignore @@ -40,6 +40,8 @@ _UpgradeReport_Files/ ipch/ *.sdf *.opensdf +*.VC.opendb +.vs/ /config.mk /config.gypi diff --git a/AUTHORS b/AUTHORS index 5ab61aebf20966..15191f7b31d975 100644 --- a/AUTHORS +++ b/AUTHORS @@ -623,7 +623,7 @@ Steve Sharp Victor Widell Evan Rutledge Borden Johnny Ray -Steve Mao +Steve Mao Stiliyan Lazarov Wang Xinyong Ray Donnelly @@ -831,7 +831,7 @@ Claudio Rodriguez Ido Ben-Yair Kyle Smith Marti Martz -Stefan Budeanu +Stefan Budeanu Emily Aviva Kapor-Mater Sam P Gallagher-Bishop David Woods @@ -868,5 +868,122 @@ Super Zheng Rafał Pocztarski Michael Ruddy Andy Bettisworth +Jörg Krause +Alexander Martin +Prince J Wesley +janriemer +Arthur Gautier +Martin von Gagern +Hideki Yamamura +Lenny Markus +Nelson Pecora +Graham Fairweather +Nicholas Young +chrisjohn404 +Bo Borgerson +Mudit Ameta +Adri Van Houdt +Max Barinov +Damian Schenkelman +iamchenxin +Nik Nyby +Ben Ripkens +Ryan Sobol +jona +Martin Bark +José F. Romaniello +Richard Sun +Sequoia McDowell +zoubin +Robert Jefe Lindstaedt +Saquib +Daniel Sellers +Julien Waechter +Vitor Cortez +Michael Theriot +Peter Geiss +Richard Lau +José Moreira +Tom Atkinson +Glen Arrowsmith +Jeff Harris +Alexander Makarenko +Drew Folta +Myles Borins +Dmitriy Lazarev +Adam Langley +Kári Tristan Helgason +Manuel Valls +Prayag Verma +Gibson Fahnestock +Alan Cohen +Christophe Naud-Dulude +Matthias Bastian +Phillip Kovalev +Rainer Oviir +HUANG Wei +DC +Daniel Turing +Julie Pagano +Ruben Bridgewater +Felix Becker +Igor Klopov +Tsarevich Dmitry +Ojas Shirekar +Noah Rose +Rafael Cepeda +Chinedu Francis Nwafili +Braydon Fuller +Jiho Choi +Dirceu Pereira Tiegs +Marc Cuva +Chris Dew +Tristan Slominski +Hugo Wood +Owen Smith +Anton Andesen +Aayush Naik +Netto Farah +Craig Akimoto +Michael Barrett +Alexander Marchenko +Robert C Jensen +Vaibhav +Stefano Vozza +Daijiro Wachi +Kirill Fomichev +Mithun Patel +Alexander Penev +Andrea Giammarchi +Lance Ball +Jarrett Widman +Florian Margaine +Wolfgang Steiner +Bill Automata +Robert Chiras +Corey Kosak +John Eversole +Gareth Ellis +Eugene Obrezkov +Kyle Simpson +Bogdan Lobor +Daniel Wang +Mihai Potra +Brendon Pierson +Brad Hill +Mike Kaufman +Igor Kalashnikov +Anna Henningsen +Amery +James Reggio +Joran Dirk Greef +Matthew Douglass +William Kapke +Yuta Hiroto +Ilya Shaisultanov +James Lal +Josh Leder +surya panikkal +vsemozhetbyt # Generated by tools/update-authors.sh diff --git a/BUILDING.md b/BUILDING.md index a1cbb1bd7fbf8f..a247a21a0e5f9d 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -9,7 +9,7 @@ If you consistently can reproduce a test failure, search for it in the file a new issue. -### Unix / Macintosh +### Unix / OS X Prerequisites: @@ -17,8 +17,17 @@ Prerequisites: * `clang` and `clang++` 3.4 or newer * Python 2.6 or 2.7 * GNU Make 3.81 or newer + +On OS X, you will also need: +* [Xcode](https://developer.apple.com/xcode/download/) + * You also need to install the `Command Line Tools` via Xcode. You can find + this under the menu `Xcode -> Preferences -> Downloads` + * This step will install `gcc` and the related toolchain containing `make` + +On FreeBSD and OpenBSD, you may also need: * libexecinfo (FreeBSD and OpenBSD only) + ```text $ ./configure $ make @@ -133,7 +142,7 @@ This option will build with "small" (English only) support, but the full `Intl` (ECMA-402) APIs. With `--download=all` it will download the ICU library as needed. -##### Unix / Macintosh: +##### Unix / OS X: ```text $ ./configure --with-intl=small-icu --download=all @@ -156,7 +165,7 @@ data at runtime. With the `--download=all`, this may download ICU if you don't have an ICU in `deps/icu`. -##### Unix / Macintosh: +##### Unix / OS X: ```text $ ./configure --with-intl=full-icu --download=all @@ -173,7 +182,7 @@ $ ./configure --with-intl=full-icu --download=all The `Intl` object will not be available. This is the default at present, so this option is not normally needed. -##### Unix / Macintosh: +##### Unix / OS X: ```text $ ./configure --with-intl=none @@ -185,7 +194,7 @@ $ ./configure --with-intl=none > vcbuild intl-none ``` -#### Use existing installed ICU (Unix / Macintosh only): +#### Use existing installed ICU (Unix / OS X only): ```text $ pkg-config --modversion icu-i18n && ./configure --with-intl=system-icu @@ -201,7 +210,7 @@ You can find other ICU releases at Download the file named something like `icu4c-**##.#**-src.tgz` (or `.zip`). -##### Unix / Macintosh +##### Unix / OS X ```text # from an already-unpacked ICU: diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a1268f6cf337d..a76ff31c02b991 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,119 @@ # Node.js ChangeLog +## 2016-06-28, Version 4.4.7 'Argon' (LTS), @thealphanerd + +This LTS release comes with 89 commits. This includes 46 commits that are docs related, 11 commits that are test related, 8 commits that are build related, and 4 commits that are benchmark related. + +### Notable Changes + +- **debugger**: + - All properties of an array (aside from length) can now be printed in the repl (cjihrig) [#6448](https://github.com/nodejs/node/pull/6448) +- **npm**: + - Upgrade npm to 2.15.8 (Rebecca Turner) [#7412](https://github.com/nodejs/node/pull/7412) +- **stream**: + - Fix for a bug that became more prevalent with the stream changes that landed in v4.4.5. (Anna Henningsen) [#7160](https://github.com/nodejs/node/pull/7160) +- **V8**: + - Fix for a bug in crankshaft that was causing crashes on arm64 (Myles Borins) [#7442](https://github.com/nodejs/node/pull/7442) + - Add missing classes to postmortem info such as JSMap and JSSet (evan.lucas) [#3792](https://github.com/nodejs/node/pull/3792) + +### Commits + +* [[`87cdb83a96`](https://github.com/nodejs/node/commit/87cdb83a96)] - **benchmark**: merge url.js with url-resolve.js (Andreas Madsen) [#5177](https://github.com/nodejs/node/pull/5177) +* [[`921e8568d5`](https://github.com/nodejs/node/commit/921e8568d5)] - **benchmark**: move misc to categorized directories (Andreas Madsen) [#5177](https://github.com/nodejs/node/pull/5177) +* [[`c189eec14e`](https://github.com/nodejs/node/commit/c189eec14e)] - **benchmark**: fix configuation parameters (Andreas Madsen) [#5177](https://github.com/nodejs/node/pull/5177) +* [[`58ad451f0b`](https://github.com/nodejs/node/commit/58ad451f0b)] - **benchmark**: move string-decoder to its own category (Andreas Madsen) [#5177](https://github.com/nodejs/node/pull/5177) +* [[`a01caa3166`](https://github.com/nodejs/node/commit/a01caa3166)] - **build**: don't compile with -B, redux (Ben Noordhuis) [#6650](https://github.com/nodejs/node/pull/6650) +* [[`37606caeaf`](https://github.com/nodejs/node/commit/37606caeaf)] - **build**: don't compile with -B (Ben Noordhuis) [#6393](https://github.com/nodejs/node/pull/6393) +* [[`64fb7a1929`](https://github.com/nodejs/node/commit/64fb7a1929)] - **build**: update android-configure script for npm (Robert Chiras) [#6349](https://github.com/nodejs/node/pull/6349) +* [[`43ce6fc8d2`](https://github.com/nodejs/node/commit/43ce6fc8d2)] - **build**: fix DESTCPU detection for binary target (Richard Lau) [#6310](https://github.com/nodejs/node/pull/6310) +* [[`6dfe7aeed5`](https://github.com/nodejs/node/commit/6dfe7aeed5)] - **cares**: Support malloc(0) scenarios for AIX (Gireesh Punathil) [#6305](https://github.com/nodejs/node/pull/6305) +* [[`2389006720`](https://github.com/nodejs/node/commit/2389006720)] - **debugger**: display array contents in repl (cjihrig) [#6448](https://github.com/nodejs/node/pull/6448) +* [[`1c6809ce75`](https://github.com/nodejs/node/commit/1c6809ce75)] - **debugger**: introduce exec method for debugger (Jackson Tian) +* [[`200b3ca9ed`](https://github.com/nodejs/node/commit/200b3ca9ed)] - **deps**: upgrade npm in LTS to 2.15.8 (Rebecca Turner) [#7412](https://github.com/nodejs/node/pull/7412) +* [[`49921e8819`](https://github.com/nodejs/node/commit/49921e8819)] - **deps**: backport 102e3e87e7 from V8 upstream (Myles Borins) [#7442](https://github.com/nodejs/node/pull/7442) +* [[`de00f91041`](https://github.com/nodejs/node/commit/de00f91041)] - **deps**: backport bc2e393 from v8 upstream (evan.lucas) [#3792](https://github.com/nodejs/node/pull/3792) +* [[`1549899531`](https://github.com/nodejs/node/commit/1549899531)] - **dgram,test**: add addMembership/dropMembership tests (Rich Trott) [#6753](https://github.com/nodejs/node/pull/6753) +* [[`0ba3c2ca66`](https://github.com/nodejs/node/commit/0ba3c2ca66)] - **doc**: fix layout problem in v4 changelog (Myles Borins) [#7394](https://github.com/nodejs/node/pull/7394) +* [[`98469ad84d`](https://github.com/nodejs/node/commit/98469ad84d)] - **doc**: correct args for cluster message event (Colin Ihrig) [#7297](https://github.com/nodejs/node/pull/7297) +* [[`67863f110b`](https://github.com/nodejs/node/commit/67863f110b)] - **doc**: update licenses (Myles Borins) [#7127](https://github.com/nodejs/node/pull/7127) +* [[`c31eaad42d`](https://github.com/nodejs/node/commit/c31eaad42d)] - **doc**: clarify buffer class (Steve Mao) [#6914](https://github.com/nodejs/node/pull/6914) +* [[`e0dd476fe5`](https://github.com/nodejs/node/commit/e0dd476fe5)] - **doc**: fix typos in timers topic to aid readability (Kevin Donahue) [#6916](https://github.com/nodejs/node/pull/6916) +* [[`a8391bc9fc`](https://github.com/nodejs/node/commit/a8391bc9fc)] - **doc**: add jhamhader to collaborators (Yuval Brik) [#6946](https://github.com/nodejs/node/pull/6946) +* [[`22ca7b877b`](https://github.com/nodejs/node/commit/22ca7b877b)] - **doc**: add @othiym23 to list of collaborators (Forrest L Norvell) [#6945](https://github.com/nodejs/node/pull/6945) +* [[`2c3c4e5819`](https://github.com/nodejs/node/commit/2c3c4e5819)] - **doc**: reference list of language-specific globals (Anna Henningsen) [#6900](https://github.com/nodejs/node/pull/6900) +* [[`5a1a0b5ed1`](https://github.com/nodejs/node/commit/5a1a0b5ed1)] - **doc**: make the api doc print-friendly (Marian) [#6748](https://github.com/nodejs/node/pull/6748) +* [[`03db88e012`](https://github.com/nodejs/node/commit/03db88e012)] - **doc**: add bengl to collaborators (Bryan English) [#6921](https://github.com/nodejs/node/pull/6921) +* [[`fbf95dde94`](https://github.com/nodejs/node/commit/fbf95dde94)] - **doc**: Update DCO to v1.1 (William Kapke) [#6353](https://github.com/nodejs/node/pull/6353) +* [[`f23a9c39c0`](https://github.com/nodejs/node/commit/f23a9c39c0)] - **doc**: fix typo in Error.captureStackTrace (Mohsen) [#6811](https://github.com/nodejs/node/pull/6811) +* [[`30ab6a890c`](https://github.com/nodejs/node/commit/30ab6a890c)] - **doc**: fix name to match git log (Robert Jefe Lindstaedt) [#6880](https://github.com/nodejs/node/pull/6880) +* [[`2b0f40ca16`](https://github.com/nodejs/node/commit/2b0f40ca16)] - **doc**: add note for fs.watch virtualized env (Robert Jefe Lindstaedt) [#6809](https://github.com/nodejs/node/pull/6809) +* [[`3b461870be`](https://github.com/nodejs/node/commit/3b461870be)] - **doc**: Backport ee.once doc clarifications to 4.x. (Lance Ball) [#7103](https://github.com/nodejs/node/pull/7103) +* [[`eadb7e5b20`](https://github.com/nodejs/node/commit/eadb7e5b20)] - **doc**: subdivide TOC, add auxiliary links (Jeremiah Senkpiel) [#6167](https://github.com/nodejs/node/pull/6167) +* [[`107839c5dd`](https://github.com/nodejs/node/commit/107839c5dd)] - **doc**: no Node.js(1) (Jeremiah Senkpiel) [#6167](https://github.com/nodejs/node/pull/6167) +* [[`401325f9e2`](https://github.com/nodejs/node/commit/401325f9e2)] - **doc**: better example & synopsis (Jeremiah Senkpiel) [#6167](https://github.com/nodejs/node/pull/6167) +* [[`c654184f28`](https://github.com/nodejs/node/commit/c654184f28)] - **doc**: remove link to Sign in crypto.md (Kirill Fomichev) [#6812](https://github.com/nodejs/node/pull/6812) +* [[`3e9288e466`](https://github.com/nodejs/node/commit/3e9288e466)] - **doc**: fix exec example in child_process (Evan Lucas) [#6660](https://github.com/nodejs/node/pull/6660) +* [[`3d820e45b4`](https://github.com/nodejs/node/commit/3d820e45b4)] - **doc**: "a" -> "an" in api/documentation.md (Anchika Agarwal) [#6689](https://github.com/nodejs/node/pull/6689) +* [[`352496daa2`](https://github.com/nodejs/node/commit/352496daa2)] - **doc**: move the readme newcomers section (Jeremiah Senkpiel) [#6681](https://github.com/nodejs/node/pull/6681) +* [[`ac6b921ce5`](https://github.com/nodejs/node/commit/ac6b921ce5)] - **doc**: mention existence/purpose of module wrapper (Matt Harrison) [#6433](https://github.com/nodejs/node/pull/6433) +* [[`97d1fc0fc6`](https://github.com/nodejs/node/commit/97d1fc0fc6)] - **doc**: improve onboarding-extras.md formatting (Jeremiah Senkpiel) [#6548](https://github.com/nodejs/node/pull/6548) +* [[`c9b144ddd4`](https://github.com/nodejs/node/commit/c9b144ddd4)] - **doc**: linkify remaining references to fs.Stats object (Kevin Donahue) [#6485](https://github.com/nodejs/node/pull/6485) +* [[`d909c25a33`](https://github.com/nodejs/node/commit/d909c25a33)] - **doc**: fix the lint of an example in cluster.md (yorkie) [#6516](https://github.com/nodejs/node/pull/6516) +* [[`21d02f460f`](https://github.com/nodejs/node/commit/21d02f460f)] - **doc**: add missing underscore for markdown italics (Kevin Donahue) [#6529](https://github.com/nodejs/node/pull/6529) +* [[`18ecc779bb`](https://github.com/nodejs/node/commit/18ecc779bb)] - **doc**: ensure consistent grammar in node.1 file (justshiv) [#6426](https://github.com/nodejs/node/pull/6426) +* [[`52d9e7b61d`](https://github.com/nodejs/node/commit/52d9e7b61d)] - **doc**: fix a typo in __dirname section (William Luo) [#6473](https://github.com/nodejs/node/pull/6473) +* [[`de20235235`](https://github.com/nodejs/node/commit/de20235235)] - **doc**: remove all scrollbar styling (Claudio Rodriguez) [#6479](https://github.com/nodejs/node/pull/6479) +* [[`a6f45b4eda`](https://github.com/nodejs/node/commit/a6f45b4eda)] - **doc**: Remove extra space in REPL example (Juan) [#6447](https://github.com/nodejs/node/pull/6447) +* [[`feda15b2b8`](https://github.com/nodejs/node/commit/feda15b2b8)] - **doc**: update build instructions for OS X (Rich Trott) [#6309](https://github.com/nodejs/node/pull/6309) +* [[`3d1a3e4a30`](https://github.com/nodejs/node/commit/3d1a3e4a30)] - **doc**: change references to Stable to Current (Myles Borins) [#6318](https://github.com/nodejs/node/pull/6318) +* [[`e28598b1ef`](https://github.com/nodejs/node/commit/e28598b1ef)] - **doc**: update authors (James M Snell) [#6373](https://github.com/nodejs/node/pull/6373) +* [[`0f3a94acbd`](https://github.com/nodejs/node/commit/0f3a94acbd)] - **doc**: add JacksonTian to collaborators (Jackson Tian) [#6388](https://github.com/nodejs/node/pull/6388) +* [[`d7d54c8fd2`](https://github.com/nodejs/node/commit/d7d54c8fd2)] - **doc**: add Minqi Pan to collaborators (Minqi Pan) [#6387](https://github.com/nodejs/node/pull/6387) +* [[`83721c6fd2`](https://github.com/nodejs/node/commit/83721c6fd2)] - **doc**: add eljefedelrodeodeljefe to collaborators (Robert Jefe Lindstaedt) [#6389](https://github.com/nodejs/node/pull/6389) +* [[`b112fd1b4e`](https://github.com/nodejs/node/commit/b112fd1b4e)] - **doc**: add ronkorving to collaborators (ronkorving) [#6385](https://github.com/nodejs/node/pull/6385) +* [[`ac60d9cc86`](https://github.com/nodejs/node/commit/ac60d9cc86)] - **doc**: add estliberitas to collaborators (Alexander Makarenko) [#6386](https://github.com/nodejs/node/pull/6386) +* [[`435cd56de5`](https://github.com/nodejs/node/commit/435cd56de5)] - **doc**: DCO anchor that doesn't change (William Kapke) [#6257](https://github.com/nodejs/node/pull/6257) +* [[`7d8141dd1b`](https://github.com/nodejs/node/commit/7d8141dd1b)] - **doc**: add stefanmb to collaborators (Stefan Budeanu) [#6227](https://github.com/nodejs/node/pull/6227) +* [[`6dfc96326d`](https://github.com/nodejs/node/commit/6dfc96326d)] - **doc**: add iWuzHere to collaborators (Imran Iqbal) [#6226](https://github.com/nodejs/node/pull/6226) +* [[`3dbcc73159`](https://github.com/nodejs/node/commit/3dbcc73159)] - **doc**: add santigimeno to collaborators (Santiago Gimeno) [#6225](https://github.com/nodejs/node/pull/6225) +* [[`ae3eb24a3d`](https://github.com/nodejs/node/commit/ae3eb24a3d)] - **doc**: add addaleax to collaborators (Anna Henningsen) [#6224](https://github.com/nodejs/node/pull/6224) +* [[`46ee7bb4ba`](https://github.com/nodejs/node/commit/46ee7bb4ba)] - **doc**: fix incorrect references in buffer docs (Amery) [#6194](https://github.com/nodejs/node/pull/6194) +* [[`e3f78eb7c1`](https://github.com/nodejs/node/commit/e3f78eb7c1)] - **doc**: improve rendering of v4.4.5 changelog entry (Myles Borins) [#6958](https://github.com/nodejs/node/pull/6958) +* [[`bac87d01d9`](https://github.com/nodejs/node/commit/bac87d01d9)] - **gitignore**: adding .vs/ directory to .gitignore (Mike Kaufman) [#6070](https://github.com/nodejs/node/pull/6070) +* [[`93f2314dc2`](https://github.com/nodejs/node/commit/93f2314dc2)] - **gitignore**: ignore VS 2015 *.VC.opendb files (Mike Kaufman) [#6070](https://github.com/nodejs/node/pull/6070) +* [[`c98aaf59bf`](https://github.com/nodejs/node/commit/c98aaf59bf)] - **http**: speed up checkIsHttpToken (Jackson Tian) [#4790](https://github.com/nodejs/node/pull/4790) +* [[`552e25cb6b`](https://github.com/nodejs/node/commit/552e25cb6b)] - **lib,test**: update in preparation for linter update (Rich Trott) [#6498](https://github.com/nodejs/node/pull/6498) +* [[`aaeeec4765`](https://github.com/nodejs/node/commit/aaeeec4765)] - **lib,test,tools**: alignment on variable assignments (Rich Trott) [#6869](https://github.com/nodejs/node/pull/6869) +* [[`b3acbc5648`](https://github.com/nodejs/node/commit/b3acbc5648)] - **net**: replace __defineGetter__ with defineProperty (Fedor Indutny) [#6284](https://github.com/nodejs/node/pull/6284) +* [[`4c1eb5bf03`](https://github.com/nodejs/node/commit/4c1eb5bf03)] - **repl**: create history file with mode 0600 (Carl Lei) [#3394](https://github.com/nodejs/node/pull/3394) +* [[`90306bb81d`](https://github.com/nodejs/node/commit/90306bb81d)] - **src**: use size_t for http parser array size fields (Ben Noordhuis) [#5969](https://github.com/nodejs/node/pull/5969) +* [[`af41a63d0f`](https://github.com/nodejs/node/commit/af41a63d0f)] - **src**: replace ARRAY_SIZE with typesafe arraysize (Ben Noordhuis) [#5969](https://github.com/nodejs/node/pull/5969) +* [[`037291e31f`](https://github.com/nodejs/node/commit/037291e31f)] - **src**: make sure Utf8Value always zero-terminates (Anna Henningsen) [#7101](https://github.com/nodejs/node/pull/7101) +* [[`a08a0179e9`](https://github.com/nodejs/node/commit/a08a0179e9)] - **stream**: ensure awaitDrain is increased once (David Halls) [#7292](https://github.com/nodejs/node/pull/7292) +* [[`b73ec46dcb`](https://github.com/nodejs/node/commit/b73ec46dcb)] - **stream**: reset awaitDrain after manual .resume() (Anna Henningsen) [#7160](https://github.com/nodejs/node/pull/7160) +* [[`55319fe798`](https://github.com/nodejs/node/commit/55319fe798)] - **stream_base**: expose `bytesRead` getter (Fedor Indutny) [#6284](https://github.com/nodejs/node/pull/6284) +* [[`0414d882ce`](https://github.com/nodejs/node/commit/0414d882ce)] - **test**: fix test-net-* error code check for getaddrinfo(3) (Natanael Copa) [#5099](https://github.com/nodejs/node/pull/5099) +* [[`be0bb5f5fc`](https://github.com/nodejs/node/commit/be0bb5f5fc)] - **test**: fix unreliable known_issues test (Rich Trott) [#6555](https://github.com/nodejs/node/pull/6555) +* [[`ab50e82f42`](https://github.com/nodejs/node/commit/ab50e82f42)] - **test**: fix test-process-exec-argv flakiness (Santiago Gimeno) [#7128](https://github.com/nodejs/node/pull/7128) +* [[`4e38655d5f`](https://github.com/nodejs/node/commit/4e38655d5f)] - **test**: refactor test-tls-reuse-host-from-socket (Rich Trott) [#6756](https://github.com/nodejs/node/pull/6756) +* [[`1c4549a31e`](https://github.com/nodejs/node/commit/1c4549a31e)] - **test**: fix flaky test-stdout-close-catch (Santiago Gimeno) [#6808](https://github.com/nodejs/node/pull/6808) +* [[`3b94e31245`](https://github.com/nodejs/node/commit/3b94e31245)] - **test**: robust handling of env for npm-test-install (Myles Borins) [#6797](https://github.com/nodejs/node/pull/6797) +* [[`4067cde7ee`](https://github.com/nodejs/node/commit/4067cde7ee)] - **test**: abstract skip functionality to common (Jeremiah Senkpiel) [#7114](https://github.com/nodejs/node/pull/7114) +* [[`8b396e3d71`](https://github.com/nodejs/node/commit/8b396e3d71)] - **test**: fix test-debugger-repl-break-in-module (Rich Trott) [#6686](https://github.com/nodejs/node/pull/6686) +* [[`847b29c050`](https://github.com/nodejs/node/commit/847b29c050)] - **test**: fix test-debugger-repl-term (Rich Trott) [#6682](https://github.com/nodejs/node/pull/6682) +* [[`1d68bdbe3f`](https://github.com/nodejs/node/commit/1d68bdbe3f)] - **test**: fix error message checks in test-module-loading (James M Snell) [#5986](https://github.com/nodejs/node/pull/5986) +* [[`7e739ae159`](https://github.com/nodejs/node/commit/7e739ae159)] - **test,tools**: adjust function argument alignment (Rich Trott) [#7100](https://github.com/nodejs/node/pull/7100) +* [[`216486c2b6`](https://github.com/nodejs/node/commit/216486c2b6)] - **tools**: lint for function argument alignment (Rich Trott) [#7100](https://github.com/nodejs/node/pull/7100) +* [[`6a76485ad7`](https://github.com/nodejs/node/commit/6a76485ad7)] - **tools**: update ESLint to 2.9.0 (Rich Trott) [#6498](https://github.com/nodejs/node/pull/6498) +* [[`a31153c02c`](https://github.com/nodejs/node/commit/a31153c02c)] - **tools**: remove the minifying logic (Sakthipriyan Vairamani) [#6636](https://github.com/nodejs/node/pull/6636) +* [[`10bd1a73fd`](https://github.com/nodejs/node/commit/10bd1a73fd)] - **tools**: fix license-builder.sh again for ICU (Steven R. Loomis) [#6068](https://github.com/nodejs/node/pull/6068) +* [[`0f6146c6c0`](https://github.com/nodejs/node/commit/0f6146c6c0)] - **tools**: add tests for the doctool (Ian Kronquist) [#6031](https://github.com/nodejs/node/pull/6031) +* [[`cc3645cff3`](https://github.com/nodejs/node/commit/cc3645cff3)] - **tools**: lint for alignment of variable assignments (Rich Trott) [#6869](https://github.com/nodejs/node/pull/6869) + ## 2016-06-22, Version 4.4.6 'Argon' (LTS), @thealphanerd +### Notable Changes + This is an important security release. All Node.js users should consult the security release summary at nodejs.org for details on patched vulnerabilities. This release is specifically related to a Buffer overflow vulnerability discovered in v8, more details can be found [in the CVE](https://www.cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-1669) @@ -14,17 +126,14 @@ This release is specifically related to a Buffer overflow vulnerability discover ### Notable Changes -* **buffer**: - * Buffer no longer errors if you call lastIndexOf with a search term longer than the buffer (Anna Henningsen) [#6511](https://github.com/nodejs/node/pull/6511) - -* **contextify**: - * Context objects are now properly garbage collected, this solves a problem some individuals were experiencing with extreme memory growth (Ali Ijaz Sheikh) [#6871](https://github.com/nodejs/node/pull/6871) - -* **deps**: - * update npm to 2.15.5 (Rebecca Turner) [#6663](https://github.com/nodejs/node/pull/6663) - -* **http**: - * Invalid status codes can no longer be sent. Limited to 3 digit numbers between 100 - 999 (Brian White) [#6291](https://github.com/nodejs/node/pull/6291) +- **buffer**: + - Buffer.indexOf now returns correct values for all UTF-16 input (Anna Henningsen) [#6511](https://github.com/nodejs/node/pull/6511) +- **contextify**: + - Context objects are now properly garbage collected, this solves a problem some individuals were experiencing with extreme memory growth (Ali Ijaz Sheikh) [#6871](https://github.com/nodejs/node/pull/6871) +- **deps**: + - update npm to 2.15.5 (Rebecca Turner) [#6663](https://github.com/nodejs/node/pull/6663) +- **http**: + - Invalid status codes can no longer be sent. Limited to 3 digit numbers between 100 - 999 (Brian White) [#6291](https://github.com/nodejs/node/pull/6291) ### Commits diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 87d6d93584c22c..362846556ac52f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -174,6 +174,7 @@ to address, apply your changes in a separate commit and push that to your feature branch. Post a comment in the pull request afterwards; GitHub does not send out notifications when you add commits. + ## Developer's Certificate of Origin 1.1 By making a contribution to this project, I certify that: diff --git a/LICENSE b/LICENSE index e6cd58888640bf..f6e6f5555a8e3b 100644 --- a/LICENSE +++ b/LICENSE @@ -1032,7 +1032,7 @@ The externally maintained libraries used by Node.js are: - ESLint, located at tools/eslint, is licensed as follows: """ ESLint - Copyright (c) 2013 Nicholas C. Zakas. All rights reserved. + Copyright jQuery Foundation and other contributors, https://jquery.org/ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Makefile b/Makefile index 0f8648cc3678ea..4d180501c6d2c3 100644 --- a/Makefile +++ b/Makefile @@ -88,7 +88,7 @@ cctest: all @out/$(BUILDTYPE)/$@ test: | cctest # Depends on 'all'. - $(PYTHON) tools/test.py --mode=release message parallel sequential -J + $(PYTHON) tools/test.py --mode=release doctool message parallel sequential -J $(MAKE) jslint $(MAKE) cpplint @@ -145,7 +145,7 @@ test-all-valgrind: test-build test-ci: | build-addons $(PYTHON) tools/test.py -p tap --logfile test.tap --mode=release --flaky-tests=$(FLAKY_TESTS) \ - $(TEST_CI_ARGS) addons message parallel sequential + $(TEST_CI_ARGS) addons doctool message parallel sequential test-release: test-build $(PYTHON) tools/test.py --mode=release @@ -264,11 +264,40 @@ RELEASE=$(shell sed -ne 's/\#define NODE_VERSION_IS_RELEASE \([01]\)/\1/p' src/n PLATFORM=$(shell uname | tr '[:upper:]' '[:lower:]') NPMVERSION=v$(shell cat deps/npm/package.json | grep '"version"' | sed 's/^[^:]*: "\([^"]*\)",.*/\1/') -ifeq ($(findstring x86_64,$(shell uname -m)),x86_64) +UNAME_M=$(shell uname -m) +ifeq ($(findstring x86_64,$(UNAME_M)),x86_64) DESTCPU ?= x64 else +ifeq ($(findstring ppc64,$(UNAME_M)),ppc64) +DESTCPU ?= ppc64 +else +ifeq ($(findstring ppc,$(UNAME_M)),ppc) +DESTCPU ?= ppc +else +ifeq ($(findstring s390x,$(UNAME_M)),s390x) +DESTCPU ?= s390x +else +ifeq ($(findstring s390,$(UNAME_M)),s390) +DESTCPU ?= s390 +else +ifeq ($(findstring arm,$(UNAME_M)),arm) +DESTCPU ?= arm +else +ifeq ($(findstring aarch64,$(UNAME_M)),aarch64) +DESTCPU ?= aarch64 +else +ifeq ($(findstring powerpc,$(shell uname -p)),powerpc) +DESTCPU ?= ppc64 +else DESTCPU ?= x86 endif +endif +endif +endif +endif +endif +endif +endif ifeq ($(DESTCPU),x64) ARCH=x64 else diff --git a/README.md b/README.md index 20c24dee60beba..8d697ca91778b1 100644 --- a/README.md +++ b/README.md @@ -17,23 +17,30 @@ 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. +## Resources for Newcomers + +* [Website](https://nodejs.org/en/) +* [Contributing to the project](./CONTRIBUTING.md) +* IRC (general questions): [#node.js on chat.freenode.net](https://webchat.freenode.net?channels=node.js&uio=d4) +* IRC (node core development): [#node-dev on chat.reenode.net](https://webchat.freenode.net?channels=node-dev&uio=d4) + ## Release Types The Node.js project maintains multiple types of releases: -* **Stable**: Released from active development branches of this repository, +* **Current**: Released from active development branches of this repository, versioned by [SemVer](http://semver.org/) and signed by a member of the [Release Team](#release-team). - Code for Stable releases is organized in this repository by major version + Code for Current releases is organized in this repository by major version number, For example: [v4.x](https://github.com/nodejs/node/tree/v4.x). - The major version number of Stable releases will increment every 6 months + The major version number of Current releases will increment every 6 months allowing for breaking changes to be introduced. This happens in April and - October every year. Stable release lines beginning in October each year have - a maximum support life of 8 months. Stable release lines beginning in April + October every year. Current release lines beginning in October each year have + a maximum support life of 8 months. Current release lines beginning in April each year will convert to LTS (see below) after 6 months and receive further support for 30 months. * **LTS**: Releases that receive Long-term Support, with a focus on stability - and security. Every second Stable release line (major version) will become an + and security. Every second Current release line (major version) will become an LTS line and receive 18 months of _Active LTS_ support and a further 12 months of _Maintenance_. LTS release lines are given alphabetically ordered codenames, beginning with v4 Argon. LTS releases are less frequent @@ -41,7 +48,7 @@ The Node.js project maintains multiple types of releases: only incrementing patch version numbers. There are no breaking changes or feature additions, except in some special circumstances. More information can be found in the [LTS README](https://github.com/nodejs/LTS/). -* **Nightly**: Versions of code in this repository on the current Stable +* **Nightly**: Versions of code in this repository on the current Current branch, automatically built every 24-hours where changes exist. Use with caution. @@ -50,10 +57,10 @@ The Node.js project maintains multiple types of releases: Binaries, installers, and source tarballs are available at . -**Stable** and **LTS** releases are available at +**Current** and **LTS** releases are available at , listed under their version strings. The [latest](https://nodejs.org/download/release/latest/) directory is an -alias for the latest Stable release. The latest LTS release from an LTS +alias for the latest Current release. The latest LTS release from an LTS line is available in the form: latest-_codename_. For example: @@ -68,7 +75,7 @@ documentation of the latest stable version. ### Verifying Binaries -Stable, LTS and Nightly download directories all contain a *SHASUM256.txt* +Current, LTS and Nightly download directories all contain a *SHASUM256.txt* file that lists the SHA checksums for each file available for download. @@ -88,7 +95,7 @@ $ grep node-vx.y.z.tar.gz SHASUMS256.txt | sha256sum -c - _(Where "node-vx.y.z.tar.gz" is the name of the file you have downloaded)_ -Additionally, Stable and LTS releases (not Nightlies) have GPG signed +Additionally, Current and LTS releases (not Nightlies) have GPG signed copies of SHASUM256.txt files available as SHASUM256.txt.asc. You can use `gpg` to verify that the file has not been tampered with. @@ -116,16 +123,6 @@ the binary verification command above. See [BUILDING.md](BUILDING.md) for instructions on how to build Node.js from source. - -## Resources for Newcomers - -* [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md) -* [CONTRIBUTING.md](./CONTRIBUTING.md) -* [GOVERNANCE.md](./GOVERNANCE.md) -* IRC (general questions): [#node.js on Freenode.net](https://webchat.freenode.net?channels=node.js&uio=d4) -* IRC (node core development): [#node-dev on Freenode.net](https://webchat.freenode.net?channels=node-dev&uio=d4) -* [nodejs/node on Gitter](https://gitter.im/nodejs/node) - ## Security All security bugs in Node.js are taken seriously and should be reported by @@ -167,16 +164,23 @@ information about the governance of the Node.js project, see ### Collaborators +* [addaleax](https://github.com/addaleax) - **Anna Henningsen** <anna@addaleax.net> * [AndreasMadsen](https://github.com/AndreasMadsen) - **Andreas Madsen** <amwebdk@gmail.com> +* [bengl](https://github.com/bengl) - **Bryan English** <bryan@bryanenglish.com> * [benjamingr](https://github.com/benjamingr) - **Benjamin Gruenbaum** <benjamingr@gmail.com> * [brendanashworth](https://github.com/brendanashworth) - **Brendan Ashworth** <brendan.ashworth@me.com> * [calvinmetcalf](https://github.com/calvinmetcalf) - **Calvin Metcalf** <calvin.metcalf@gmail.com> * [claudiorodriguez](https://github.com/claudiorodriguez) - **Claudio Rodriguez** <cjrodr@yahoo.com> * [domenic](https://github.com/domenic) - **Domenic Denicola** <d@domenic.me> +* [eljefedelrodeodeljefe](https://github.com/eljefedelrodeodeljefe) - **Robert Jefe Lindstaedt** <robert.lindstaedt@gmail.com> +* [estliberitas](https://github.com/estliberitas) - **Alexander Makarenko** <estliberitas@gmail.com> * [geek](https://github.com/geek) - **Wyatt Preul** <wpreul@gmail.com> * [iarna](https://github.com/iarna) - **Rebecca Turner** <me@re-becca.org> * [isaacs](https://github.com/isaacs) - **Isaac Z. Schlueter** <i@izs.me> +* [iWuzHere](https://github.com/iWuzHere) - **Imran Iqbal** <imran@imraniqbal.org> +* [JacksonTian](https://github.com/JacksonTian) - **Jackson Tian** <shvyo1987@gmail.com> * [jbergstroem](https://github.com/jbergstroem) - **Johan Bergström** <bugs@bergstroem.nu> +* [jhamhader](https://github.com/jhamhader) - **Yuval Brik** <yuval@brik.org.il> * [joaocgreis](https://github.com/joaocgreis) - **João Reis** <reis@janeasystems.com> * [julianduque](https://github.com/julianduque) - **Julian Duque** <julianduquej@gmail.com> * [JungMinu](https://github.com/JungMinu) - **Minwoo Jung** <jmwsoft@gmail.com> @@ -187,18 +191,23 @@ information about the governance of the Node.js project, see * [mikeal](https://github.com/mikeal) - **Mikeal Rogers** <mikeal.rogers@gmail.com> * [monsanto](https://github.com/monsanto) - **Christopher Monsanto** <chris@monsan.to> * [Olegas](https://github.com/Olegas) - **Oleg Elifantiev** <oleg@elifantiev.ru> +* [othiym23](https://github.com/othiym23) - **Forrest L Norvell** <ogd@aoaioxxysz.net> * [petkaantonov](https://github.com/petkaantonov) - **Petka Antonov** <petka_antonov@hotmail.com> * [phillipj](https://github.com/phillipj) - **Phillip Johnsen** <johphi@gmail.com> +* [pmq20](https://github.com/pmq20) - **Minqi Pan** <pmq2001@gmail.com> * [qard](https://github.com/qard) - **Stephen Belanger** <admin@stephenbelanger.com> * [rlidwka](https://github.com/rlidwka) - **Alex Kocharin** <alex@kocharin.ru> * [rmg](https://github.com/rmg) - **Ryan Graham** <r.m.graham@gmail.com> * [robertkowalski](https://github.com/robertkowalski) - **Robert Kowalski** <rok@kowalski.gd> * [romankl](https://github.com/romankl) - **Roman Klauke** <romaaan.git@gmail.com> +* [ronkorving](https://github.com/ronkorving) - **Ron Korving** <ron@ronkorving.nl> * [saghul](https://github.com/saghul) - **Saúl Ibarra Corretgé** <saghul@gmail.com> * [sam-github](https://github.com/sam-github) - **Sam Roberts** <vieuxtech@gmail.com> +* [santigimeno](https://github.com/santigimeno) - **Santiago Gimeno** <santiago.gimeno@gmail.com> * [seishun](https://github.com/seishun) - **Nikolai Vavilov** <vvnicholas@gmail.com> * [silverwind](https://github.com/silverwind) - **Roman Reiss** <me@silverwind.io> * [srl295](https://github.com/srl295) - **Steven R Loomis** <srloomis@us.ibm.com> +* [stefanmb](https://github.com/stefanmb) - **Stefan Budeanu** <stefan@budeanu.com> * [targos](https://github.com/targos) - **Michaël Zasso** <mic.besace@gmail.com> * [tellnes](https://github.com/tellnes) - **Christian Tellnes** <christian@tellnes.no> * [thealphanerd](https://github.com/thealphanerd) - **Myles Borins** <myles.borins@gmail.com> diff --git a/WORKING_GROUPS.md b/WORKING_GROUPS.md index 94e221ebdb43c5..451251320c1168 100644 --- a/WORKING_GROUPS.md +++ b/WORKING_GROUPS.md @@ -471,21 +471,32 @@ or else the discussion will continue. Simple majority wins. Note that changes to WG membership require unanimous consensus. See "WG Membership" above. -### Developer's Certificate of Origin 1.0 + +## Developer's Certificate of Origin 1.1 By making a contribution to this project, I certify that: * (a) The contribution was created in whole or in part by me and I - have the right to submit it under the open source license indicated - in the file; or + have the right to submit it under the open source license + indicated in the file; or + * (b) The contribution is based upon previous work that, to the best - of my knowledge, is covered under an appropriate open source license - and I have the right under that license to submit that work with - modifications, whether created in whole or in part by me, under the - same open source license (unless I am permitted to submit under a - different license), as indicated in the file; or + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + * (c) The contribution was provided directly to me by some other - person who certified (a), (b) or (c) and I have not modified it. + person who certified (a), (b) or (c) and I have not modified + it. + +* (d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. ### Moderation Policy diff --git a/android-configure b/android-configure index cbf137f47174c7..1dc238ebd0c522 100755 --- a/android-configure +++ b/android-configure @@ -1,5 +1,14 @@ #!/bin/bash +# In order to cross-compile node for Android using NDK, run: +# source android-configure [arch] +# +# By running android-configure with source, will allow environment variables to +# be persistent in current session. This is useful for installing native node +# modules with npm. Also, don't forget to set the arch in npm config using +# 'npm config set arch=' + + if [ -z "$2" ]; then ARCH=arm else @@ -42,8 +51,16 @@ export CC=$TOOLCHAIN/bin/$SUFFIX-gcc export CXX=$TOOLCHAIN/bin/$SUFFIX-g++ export LINK=$TOOLCHAIN/bin/$SUFFIX-g++ -./configure \ - --dest-cpu=$DEST_CPU \ - --dest-os=android \ - --without-snapshot \ - --openssl-no-asm +GYP_DEFINES="target_arch=$ARCH" +GYP_DEFINES+=" v8_target_arch=$ARCH" +GYP_DEFINES+=" android_target_arch=$ARCH" +GYP_DEFINES+=" host_os=linux OS=android" +export GYP_DEFINES + +if [ -f "configure" ]; then + ./configure \ + --dest-cpu=$DEST_CPU \ + --dest-os=android \ + --without-snapshot \ + --openssl-no-asm +fi diff --git a/benchmark/assert/deepequal-prims-and-objs-big-array.js b/benchmark/assert/deepequal-prims-and-objs-big-array.js index d8d2b57331f7ef..dc18d959bbce2b 100644 --- a/benchmark/assert/deepequal-prims-and-objs-big-array.js +++ b/benchmark/assert/deepequal-prims-and-objs-big-array.js @@ -1,22 +1,25 @@ 'use strict'; var common = require('../common.js'); var assert = require('assert'); + +const primValues = { + 'null': null, + 'undefined': undefined, + 'string': 'a', + 'number': 1, + 'boolean': true, + 'object': { 0: 'a' }, + 'array': [1, 2, 3], + 'new-array': new Array([1, 2, 3]) +}; + var bench = common.createBenchmark(main, { - prim: [ - null, - undefined, - 'a', - 1, - true, - {0: 'a'}, - [1, 2, 3], - new Array([1, 2, 3]) - ], + prim: Object.keys(primValues), n: [25] }); function main(conf) { - var prim = conf.prim; + var prim = primValues[conf.prim]; var n = +conf.n; var primArray; var primArrayCompare; diff --git a/benchmark/assert/deepequal-prims-and-objs-big-loop.js b/benchmark/assert/deepequal-prims-and-objs-big-loop.js index 5f0519bb3b45ad..3c76a586f7d5fb 100644 --- a/benchmark/assert/deepequal-prims-and-objs-big-loop.js +++ b/benchmark/assert/deepequal-prims-and-objs-big-loop.js @@ -1,22 +1,25 @@ 'use strict'; var common = require('../common.js'); var assert = require('assert'); + +const primValues = { + 'null': null, + 'undefined': undefined, + 'string': 'a', + 'number': 1, + 'boolean': true, + 'object': { 0: 'a' }, + 'array': [1, 2, 3], + 'new-array': new Array([1, 2, 3]) +}; + var bench = common.createBenchmark(main, { - prim: [ - null, - undefined, - 'a', - 1, - true, - {0: 'a'}, - [1, 2, 3], - new Array([1, 2, 3]) - ], + prim: Object.keys(primValues), n: [1e5] }); function main(conf) { - var prim = conf.prim; + var prim = primValues[conf.prim]; var n = +conf.n; var x; diff --git a/benchmark/buffers/buffer-read.js b/benchmark/buffers/buffer-read.js index 2810aa1b463321..1cdc4bc4697067 100644 --- a/benchmark/buffers/buffer-read.js +++ b/benchmark/buffers/buffer-read.js @@ -2,7 +2,7 @@ var common = require('../common.js'); var bench = common.createBenchmark(main, { - noAssert: [false, true], + noAssert: ['false', 'true'], buffer: ['fast', 'slow'], type: ['UInt8', 'UInt16LE', 'UInt16BE', 'UInt32LE', 'UInt32BE', diff --git a/benchmark/buffers/buffer-tostring.js b/benchmark/buffers/buffer-tostring.js index f71c2b9a2b5127..937a84b267ed19 100644 --- a/benchmark/buffers/buffer-tostring.js +++ b/benchmark/buffers/buffer-tostring.js @@ -3,13 +3,13 @@ const common = require('../common.js'); const bench = common.createBenchmark(main, { - arg: [true, false], + arg: ['true', 'false'], len: [0, 1, 64, 1024], n: [1e7] }); function main(conf) { - const arg = conf.arg; + const arg = conf.arg === 'true'; const len = conf.len | 0; const n = conf.n | 0; const buf = Buffer(len).fill(42); diff --git a/benchmark/buffers/buffer-write.js b/benchmark/buffers/buffer-write.js index 4e07fc511be12a..51f8cd505ec6d9 100644 --- a/benchmark/buffers/buffer-write.js +++ b/benchmark/buffers/buffer-write.js @@ -1,7 +1,7 @@ 'use strict'; var common = require('../common.js'); var bench = common.createBenchmark(main, { - noAssert: [false, true], + noAssert: ['false', 'true'], buffer: ['fast', 'slow'], type: ['UInt8', 'UInt16LE', 'UInt16BE', 'UInt32LE', 'UInt32BE', diff --git a/benchmark/misc/child-process-read.js b/benchmark/child_process/child-process-read.js similarity index 100% rename from benchmark/misc/child-process-read.js rename to benchmark/child_process/child-process-read.js diff --git a/benchmark/misc/spawn-echo.js b/benchmark/child_process/spawn-echo.js similarity index 100% rename from benchmark/misc/spawn-echo.js rename to benchmark/child_process/spawn-echo.js diff --git a/benchmark/common.js b/benchmark/common.js index 69c3d00ee2e1f1..dbf8d1b13b7beb 100644 --- a/benchmark/common.js +++ b/benchmark/common.js @@ -152,6 +152,10 @@ Benchmark.prototype._run = function() { var j = 0; set.forEach(function(s) { vals.forEach(function(val) { + if (typeof val !== 'number' && typeof val !== 'string') { + throw new TypeError(`configuration "${key}" had type ${typeof val}`); + } + newSet[j++] = s.concat(key + '=' + val); }); }); diff --git a/benchmark/misc/domain-fn-args.js b/benchmark/domain/domain-fn-args.js similarity index 100% rename from benchmark/misc/domain-fn-args.js rename to benchmark/domain/domain-fn-args.js diff --git a/benchmark/http/check_is_http_token.js b/benchmark/http/check_is_http_token.js new file mode 100644 index 00000000000000..9e0b8279b58ed0 --- /dev/null +++ b/benchmark/http/check_is_http_token.js @@ -0,0 +1,52 @@ +'use strict'; + +const common = require('../common.js'); +const _checkIsHttpToken = require('_http_common')._checkIsHttpToken; + +const bench = common.createBenchmark(main, { + key: [ + 'TCN', + 'ETag', + 'date', + 'Vary', + 'server', + 'Server', + 'status', + 'version', + 'Expires', + 'alt-svc', + 'location', + 'Connection', + 'Keep-Alive', + 'content-type', + 'Content-Type', + 'Cache-Control', + 'Last-Modified', + 'Accept-Ranges', + 'content-length', + 'x-frame-options', + 'x-xss-protection', + 'Content-Encoding', + 'Content-Location', + 'Transfer-Encoding', + 'alternate-protocol', + ':', // invalid input + '@@', + '中文呢', // unicode + '((((())))', // invalid + ':alternate-protocol', // fast bailout + 'alternate-protocol:' // slow bailout + ], + n: [1e6], +}); + +function main(conf) { + var n = +conf.n; + var key = conf.key; + + bench.start(); + for (var i = 0; i < n; i++) { + _checkIsHttpToken(key); + } + bench.end(n); +} diff --git a/benchmark/misc/module-loader.js b/benchmark/module/module-loader.js similarity index 100% rename from benchmark/misc/module-loader.js rename to benchmark/module/module-loader.js diff --git a/benchmark/misc/next-tick-breadth-args.js b/benchmark/process/next-tick-breadth-args.js similarity index 100% rename from benchmark/misc/next-tick-breadth-args.js rename to benchmark/process/next-tick-breadth-args.js diff --git a/benchmark/misc/next-tick-breadth.js b/benchmark/process/next-tick-breadth.js similarity index 100% rename from benchmark/misc/next-tick-breadth.js rename to benchmark/process/next-tick-breadth.js diff --git a/benchmark/misc/next-tick-depth-args.js b/benchmark/process/next-tick-depth-args.js similarity index 100% rename from benchmark/misc/next-tick-depth-args.js rename to benchmark/process/next-tick-depth-args.js diff --git a/benchmark/misc/next-tick-depth.js b/benchmark/process/next-tick-depth.js similarity index 100% rename from benchmark/misc/next-tick-depth.js rename to benchmark/process/next-tick-depth.js diff --git a/benchmark/misc/string-decoder.js b/benchmark/string_decoder/string-decoder.js similarity index 100% rename from benchmark/misc/string-decoder.js rename to benchmark/string_decoder/string-decoder.js diff --git a/benchmark/misc/timers.js b/benchmark/timers/timers.js similarity index 100% rename from benchmark/misc/timers.js rename to benchmark/timers/timers.js diff --git a/benchmark/url/url-resolve.js b/benchmark/url/url-resolve.js index 18f67e82e30787..8372132e4d269e 100644 --- a/benchmark/url/url-resolve.js +++ b/benchmark/url/url-resolve.js @@ -3,30 +3,43 @@ var common = require('../common.js'); var url = require('url'); var v8 = require('v8'); +var hrefs = [ + 'http://example.com/', + 'http://nodejs.org/docs/latest/api/url.html#url_url_format_urlobj', + 'http://blog.nodejs.org/', + 'https://encrypted.google.com/search?q=url&q=site:npmjs.org&hl=en', + 'javascript:alert("node is awesome");', + 'some.ran/dom/url.thing?oh=yes#whoo' +]; + + +var paths = [ + '../../../../../etc/passwd', + '../foo/bar?baz=boom', + 'foo/bar', + 'http://nodejs.org', + './foo/bar?baz' +]; + var bench = common.createBenchmark(main, { - type: ['one'], - n: [1e5], + href: Object.keys(hrefs), + path: Object.keys(paths), + n: [1e5] }); function main(conf) { - var type = conf.type; var n = conf.n | 0; - - var inputs = { - one: ['http://example.com/', '../../../../../etc/passwd'], - }; - var input = inputs[type] || []; + var href = hrefs[conf.href]; + var path = paths[conf.path]; // Force-optimize url.resolve() so that the benchmark doesn't get // disrupted by the optimizer kicking in halfway through. - for (var name in inputs) - url.resolve(inputs[name][0], inputs[name][1]); - + url.resolve(href, path); v8.setFlagsFromString('--allow_natives_syntax'); eval('%OptimizeFunctionOnNextCall(url.resolve)'); bench.start(); for (var i = 0; i < n; i += 1) - url.resolve(input[0], input[1]); + url.resolve(href, path); bench.end(n); } diff --git a/benchmark/misc/url.js b/benchmark/url/url.js similarity index 100% rename from benchmark/misc/url.js rename to benchmark/url/url.js diff --git a/deps/cares/cares.gyp b/deps/cares/cares.gyp index 8a5239b4129623..745e38e33d2d6b 100644 --- a/deps/cares/cares.gyp +++ b/deps/cares/cares.gyp @@ -12,6 +12,10 @@ [ 'OS=="aix"', { 'include_dirs': [ 'config/aix' ], 'sources': [ 'config/aix/ares_config.h' ], + 'defines': [ + # Support for malloc(0) + '_LINUX_SOURCE_COMPAT=1', + '_ALL_SOURCE=1'], }], ['OS=="solaris"', { 'defines': [ diff --git a/deps/npm/.npmignore b/deps/npm/.npmignore index 6f97b5dc0dcb48..93398c04aa252f 100644 --- a/deps/npm/.npmignore +++ b/deps/npm/.npmignore @@ -28,3 +28,5 @@ html/*.png *.pyc /test/tap/builtin-config + +.nyc_output diff --git a/deps/npm/.travis.yml b/deps/npm/.travis.yml index ec83c64532d80e..38db7ad0b02403 100644 --- a/deps/npm/.travis.yml +++ b/deps/npm/.travis.yml @@ -1,12 +1,17 @@ language: node_js sudo: false node_js: - - "6" + # LTS is our most important target - "4" + # next LTS and master is next most important + - "6" + # still in LTS maintenance until fall 2016 + # (also still in wide use) + - "0.10" + # will be unsupported as soon as 6 becomes LTS and 7 released - "5" + # technically in LTS / distros, unbeloved - "0.12" - - "0.10" - - "0.8" env: - DEPLOY_VERSION=testing before_install: diff --git a/deps/npm/AUTHORS b/deps/npm/AUTHORS index 00c2a1d31f8541..92fa799c099b38 100644 --- a/deps/npm/AUTHORS +++ b/deps/npm/AUTHORS @@ -362,3 +362,9 @@ Paul Irish Paul O'Leary McCann Francis Gulotta Rachel Evans +Michael Jackson +Myles Borins +André Herculano +Wyatt Preul +Gianluca Casati +Tapani Moilanen diff --git a/deps/npm/CHANGELOG.md b/deps/npm/CHANGELOG.md index 2e9d6604322895..5927c19c3b5d5d 100644 --- a/deps/npm/CHANGELOG.md +++ b/deps/npm/CHANGELOG.md @@ -1,3 +1,253 @@ +### v2.15.8 (2016-06-17): + +There's a very important bug fix and a long-awaited (and signifcant!) +deprecation in this hotfix release. [Hold on.](http://butt.holdings/) + +#### *WHOA* + +When Node.js 6.0.0 was released, the CLI team noticed an alarming upsurge in +bugs related to important files (like `README.md`) not being included in +published packages. The new bugs looked much like +[#5082](https://github.com/npm/npm/issues/5082), which had been around in one +form or another since April, 2014. #5082 used to be a very rare (and obnoxious) +bug that the CLI team hadn't had much luck reproducing, and we'd basically +marked it down as a race condition that arose on machines using slow and / or +rotating-media-based hard drives. + +Under 6.0.0, the behavior was reliable enough to be nearly deterministic, and +made it very difficult for publishers using `.npmignore` files in combination +with `"files"` stanzas in `package.json` to get their packages onto the +registry without one or more files missing from the packed tarball. The entire +saga is contained within [the issue](https://github.com/npm/npm/issues/5082), +but the summary is that an improvement to the performance of +[`fs.realpath()`](https://nodejs.org/api/fs.html#fs_fs_realpath_path_options_callback) +made it much more likely that the packing code would lose the race. + +Fixing this has proven to be very difficult, in part because the code used by +npm to produce package tarballs is more complicated than, strictly speaking, it +needs to be. [**@evanlucas**](https://github.com/evanlucas) contributed [a +patch](https://github.com/npm/fstream/pull/50) that passed the tests in a +[special test suite](https://github.com/othiym23/eliminate-5082) that I +([**@othiym23**](https://github.com/othiym23)) created (with help from +[**@addaleax**](https://github.com/addaleax)), but only _after_ we'd released +the fixed version of that package did we learn that it actually made the +problem _worse_ in other situations in npm proper. Eventually, +[**@rvagg**](https://github.com/rvagg) put together a more durable fix that +appears to completely address the errant behavior under Node.js 6.0.0. That's +the patch included in this release. Everybody should chip in for redback +insurance for Rod and his family; he's done the community a huge favor. + +Does this mean the long (2+ year) saga of #5082 is now over? At this point, I'm +going to quote from my latest summary on the issue: + +> The CLI team (mostly me, with input from the rest of the team) has decided that +> the overall complexity of the interaction between `fstream`, `fstream-ignore`, +> `fstream-npm`, and `node-tar` has grown more convoluted than the team is +> comfortable (maybe even capable of) supporting. +> +> - While I believe that @rvagg's (very targeted) fix addresses _this_ issue, I +> would be shocked if there aren't other race conditions in npm's packing +> logic. I've already identified a couple other places in the code that are +> most likely race conditions, even if they're harder to trigger than the +> current one. +> - The way that dependency bundling is integrated leads to a situation in +> which a bunch of logic is duplicated between `fstream-npm` and +> `lib/utils/tar.js` in npm itself, and the way `fstream`'s extension +> mechanism works makes this difficult to clean up. This caused a nasty +> regression ([#13088](https://github.com/npm/fstream/pull/50), see below) as +> of ~`npm@3.8.7` where the dependencies of `bundledDependencies` were no +> longer being included in the built package tarballs. +> - The interaction between `.npmignore`, `.gitignore`, and `files` is hopelessly +> complicated, scattered in many places throughout the code. We've been +> discussing [making the ignores and includes logic clearer and more +> predictable](https://github.com/npm/npm/wiki/Files-and-Ignores), and the +> current code fights our efforts to clean that up. +> +> So, our intention is still to replace `fstream`, `fstream-ignore`, and +> `fstream-npm` with something much simpler and purpose-built. There's no real +> reason to have a stream abstraction here when a simple recursive-descent +> filesystem visitor and a synchronous function that can answer whether a given +> path should be included in the packed tarball would do the job adequately. +> +> What's not yet clear is whether we'll need to replace `node-tar` in the +> process. `node-tar` is a very robust implementation of tar (it handles, like, +> everything), and it also includes some very important tweaks to prevent several +> classes of security exploits involving maliciously crafted packages. However, +> its packing API involves passing in an `fstream` instance, so we'd either need +> to produce something that follows enough of `fstream`'s contract for `node-tar` +> to keep working, or swap `node-tar` out for something like `tar-stream` (and +> then ensuring that our use of `tar-stream` is secure, which could involve +> security patches for either npm or `tar-stream`). + +The testing and review of `fstream@1.0.10` that the team has done leads us to +believe that this bug is fixed, but I'm feeling more than a little paranoid +about fstream now, so it's important that people keep a close eye on their +publishes for a while and let us know immediately if they notice any +irregularities. + +* [`2c49265`](https://github.com/npm/npm/commit/2c49265c6746d29ae0cd5f3532d28c5950f9847e) + [#5082](https://github.com/npm/npm/issues/5082) `fstream@1.0.10`: Ensure that + entries are collected after a paused stream resumes. + ([@rvagg](https://github.com/rvagg)) +* [`92e4344`](https://github.com/npm/npm/commit/92e43444d9204f749f83512aeab5d5e0a2d085a7) + [#5082](https://github.com/npm/npm/issues/5082) Remove the warning introduced + in `npm@3.10.0`, because it should no longer be necessary. + ([@othiym23](https://github.com/othiym23)) + +#### GOODBYE, FAITHFUL FRIEND + +At NodeConf Adventure 2016 (RIP in peace, Mikeal Rogers's NodeConf!), the CLI +team had an opportunity to talk to representatives from some of the larger +companies that we knew were still using Node.js 0.8 in production. After asking +them whether they were still using 0.8, we got back blank stares and questions +like, "0.8? You mean, from four years ago?" After establishing that being able +to run npm in their legacy environments was no longer necessary, the CLI team +made the decision to drop support for 0.8. (Faithful observers of our [team +meetings](https://github.com/npm/npm/issues?utf8=%E2%9C%93&q=is%3Aissue+npm+cli+team+meeting+) +will have known this was the plan for NodeConf since the beginning of 2016.) + +In practice, this means only what's in the commit below: we've removed 0.8 from +our continuous integration test matrix below, and will no longer be habitually +testing changes under Node 0.8. We may also give ourselves permission to use +`setImmediate()` in test code. However, since the project still supports +Node.js 0.10 and 0.12, it's unlikely that patches that rely on ES 2015 +functionality will land anytime soon. + +Looking forward, the team's current plan is to drop support for Node.js 0.10 +when its LTS maintenace window expires in October, 2016, and 0.12 when its +maintenance / LTS window ends at the end of 2016. We will also drop support for +Node.js 5.x when Node.js 6 becomes LTS and Node.js 7 is released, also in the +October-December 2016 timeframe. + +(Confused about Node.js's LTS policy? [Don't +be!](https://github.com/nodejs/LTS) If you look at [this +diagram](https://github.com/nodejs/LTS/blob/ce364a94b0e0619eba570cd57be396573e1ef889/schedule.png), +it should make all of the preceding clear.) + +If, in practice, this doesn't work with distribution packagers or other +community stakeholders responsible for packaging and distributing Node.js and +npm, please reach out to us. Aligning the npm CLI's LTS policy with Node's +helps everybody minimize the amount of work they need to do, and since all of +our teams are small and very busy, this is somewhere between a necessity and +non-negotiable. + +* [`4a1ecc0`](https://github.com/npm/npm/commit/4a1ecc068fb2660bd9bc3e2e2372aa0176d2193b) + Remove 0.8 from the Node.js testing matrix, and reorder to match real-world + priority, with comments. ([@othiym23](https://github.com/othiym23)) + +### v2.15.7 (2016-06-16): + +It pains me greatly that we haven't been able to fix +[#5082](https://github.com/npm/npm/issues/5082) yet, but warning you away from +potentially publishing incomplete packages takes priority over feeling cheesy +about landing a warning to help keep y'all out of trouble, so here you go +(_please read this next bit_ (_please clap_)): + +#### DANGER: PUBLISHING ON NODE 6.0.0 + +Publishing and packing are buggy under Node versions greater than 6.0.0. +Please use Node.js LTS (4.4.x) to publish packages. See +[#5082](https://github.com/npm/npm/issues/5082) for details and current +status. + +* [`dff00ce`](https://github.com/npm/npm/commit/dff00cedd56b9c04370f840299a7e657a7a835c6) + [#13077](https://github.com/npm/npm/pull/13077) + Warn when using Node 6+. + ([@othiym23](https://github.com/othiym23)) + +#### PACKAGING CHANGES + +* [`1877171`](https://github.com/npm/npm/commit/1877171648e20595a82de34073b643f7e01a339f) + [#12873](https://github.com/npm/npm/issues/12873) + Ignore `.nyc_output`. This will help avoid an accidental publish or commit filled with + code coverage data. + ([@TheAlphaNerd](https://github.com/TheAlphaNerd)) + +#### DOCUMENTATION CHANGES + +* [`470ae86`](https://github.com/npm/npm/commit/470ae86e052ae2f29ebec15b7547230b6240042e) + [#12983](https://github.com/npm/npm/pull/12983) + Describe how to run the lifecycle scripts of dependencies. How you do + this changed with `npm` v2. + ([@Tapppi](https://github.com/Tapppi)) +* [`9cedf37`](https://github.com/npm/npm/commit/9cedf37e5a3e26d0ffd6351af8cac974e3e011c2) + [#12776](https://github.com/npm/npm/pull/12776) + Remove mention of `` arg for `run-script`. + ([@fibo](https://github.com/fibo)) +* [`55b8424`](https://github.com/npm/npm/commit/55b8424d7229f2021cac55f0b03de72403e7c0ff) + [#12840](https://github.com/npm/npm/pull/12840) + Remove sexualized language from comment. + ([@geek](https://github.com/geek)) +* [`d6bf0c3`](https://github.com/npm/npm/commit/d6bf0c393788a6398bf80b41c57956f2dbcf3b39) + [#12802](https://github.com/npm/npm/pull/12802) + Small grammar fix in `doc/cli/npm.md`. + ([@andresilveira](https://github.com/andresilveira)) + +#### DEPENDENCY UPDATES + +* [`2c2c568`](https://github.com/npm/npm/commit/2c2c56857ff801d5fe1b6d3157870cd16e65891b) + `readable-stream@2.1.4`: Brought up to date with Node 6.1.0's streams implementation. + ([@calvinmetcalf](https://github.com/calvinmetcalf)) +* [`d682e64`](https://github.com/npm/npm/commit/d682e6445845b0a2584935d5e2942409c43f6916) + [npm/npm-user-validate#8](https://github.com/npm/npm-user-validate/pull/8) + `npm-user-validate@0.1.4`: Add a maximum length limit for usernames based on + the (arbitrary) limit imposed by the primary npm registry. + ([@aredridel](https://github.com/aredridel)) +* [`448b65b`](https://github.com/npm/npm/commit/448b65b48cda3b782b714057fb4b8311cc1fa36a) + `which@1.2.10`: Remove unused dependency `is-absolute`, bug fixes. + ([@isaacs](https://github.com/isaacs)) +* [`7d15434`](https://github.com/npm/npm/commit/7d15434f0b0af8e70b119835b21968217224664f) + `require-inject@1.4.0`: Add `requireInject.withEmptyCache` and + `requireInject.installGlobally.andClearCache` to support loading modules to be + injected with an empty cache. + ([@iarna](https://github.com/iarna)) +* [`31845c0`](https://github.com/npm/npm/commit/31845c081bc6f3f8a2f3d83a3c792dccffbaa2a8) + `init-package-json@1.9.4`: + Replace use of reserved identifier `package` in, uh, the package. + ([@adius](https://github.com/adius)) +* [`d73ef3e`](https://github.com/npm/npm/commit/d73ef3e6b18d4905de668c5115bc6042905a02d9) + `glob@7.0.4`: Use userland `fs.realpath` implementation to get glob working under Node 6. + ([@isaacs](https://github.com/isaacs)) +* [`b47da85`](https://github.com/npm/npm/commit/b47da85cf83b946f2c8d29ab612c92028f31f6b0) + `inflight@1.0.5`: Correct link to package repository, add `"files"` stanza. + ([@iarna](https://github.com/iarna), [@jamestalmage](https://github.com/jamestalmage)) +* [`04815e4`](https://github.com/npm/npm/commit/04815e436035de785279fd000cdbc821cc1f3447) + [npm/npmlog#32](https://github.com/npm/npmlog/pull/32) + `npmlog@2.0.4`: Add `"files"` stanza to `package.json`. + ([@jamestalmage](https://github.com/jamestalmage)) +* [`9e29ad2`](https://github.com/npm/npm/commit/9e29ad227300bb970e7bcd21029944d4733e40db) + `wrappy@1.0.2`: Add `"files"` stanza to `package.json`. + ([@jamestalmage](https://github.com/jamestalmage)) +* [`44af4d4`](https://github.com/npm/npm/commit/44af4d475ac65bdce6d088173273ce4a4f74a49e) + `abbrev@1.0.9` ([@jorrit](https://github.com/jorrit)) +* [`6c977c0`](https://github.com/npm/npm/commit/6c977c0031d074479a26c7bec6ec83fd6c6526b2) + `npm-registry-client@7.1.2`: Add support for newer versions of `npmlog`. + ([@iarna](https://github.com/iarna)) + +### v2.15.6 (2016-05-12): + +I have a couple of doc fixes and a shrinkwrap fix for you all this week. + +#### PEER DEPENDENCIES AND SHRINKWRAPS + +* [`55c998a`](https://github.com/npm/npm/commit/55c998a098a306b90a84beef163a8890f9a616b1) + [#5135](https://github.com/npm/npm/issues/5135) + Fix a bug where peerDependencies & shrinkwraps didn't play nice together. (Where + the peerDependency resolver would end up installing its dep when it wasn't needed.) + ([@majgis](https://github.com/majgis)) + +#### NPM AND `node-gyp` DOCS IMPROVEMENTS + +* [`1826908`](https://github.com/npm/npm/commit/1826908b991510d8fbc71a0d0f2c01ff24fd83c2) + [#12636](https://github.com/npm/npm/pull/12636) + Improve `npm-scripts` documentation regarding when `node-gyp` is used. + ([@reconbot](https://github.com/reconbot)) +* [`f9ff7f3`](https://github.com/npm/npm/commit/f9ff7f36cc2c2c3fbb4f6eef91491b589d049d5f) + [#12586](https://github.com/npm/npm/pull/12586) + Correct `package.json` documentation as to when `node-gyp rebuild` called. + This now matches https://docs.npmjs.com/misc/scripts#default-values + ([@reconbot](https://github.com/reconbot)) + ### v2.15.5 (2016-05-05): This is a minor LTS release, bringing dependencies up to date and updating diff --git a/deps/npm/appveyor.yml b/deps/npm/appveyor.yml new file mode 100644 index 00000000000000..6bec7c49389b91 --- /dev/null +++ b/deps/npm/appveyor.yml @@ -0,0 +1,38 @@ +environment: + matrix: + # LTS is our most important target + - nodejs_version: "4" + # next LTS and master is next most important + - nodejs_version: "6" + # still in LTS maintenance until fall 2016 + # (also still in wide use) + - nodejs_version: "0.10" + # will be unsupported as soon as 6 becomes LTS and 7 released + - nodejs_version: "5" + # technically in LTS / distros, unbeloved + - nodejs_version: "0.12" + COVERALLS_REPO_TOKEN: + secure: XdC0aySefK0HLh1GNk6aKrzZPbCfPQLyA4mYtFGEp4DrTuZA/iuCUS0LDqFYO8JQ +platform: + - x86 + - x64 +install: + - ps: Install-Product node $env:nodejs_version $env:platform + - npm config set spin false + - npm rebuild + - node . install -g . + - set "PATH=%APPDATA%\npm;C:\Program Files\Git\mingw64\libexec;%PATH%" + - npm install --loglevel=http +test_script: + - node --version + - npm --version + - npm test +notifications: +- provider: Slack + incoming_webhook: + secure: vXiG5AgpqxJsXZ0N0CTYDuVrX6RMjBybZKtOx6IbRxCyjgd+DAx6Z9/0XgYQjuof7QFJY3M/U6HxaREQVYbNVHA+C5N5dNALRbKzAC8QNbA= +# GO_FAST +matrix: + fast_finish: true +# we don't need the builds, we just need tests +build: off diff --git a/deps/npm/doc/cli/npm.md b/deps/npm/doc/cli/npm.md index e23354ac86f147..e59b9abeef0e25 100644 --- a/deps/npm/doc/cli/npm.md +++ b/deps/npm/doc/cli/npm.md @@ -41,7 +41,7 @@ requires compiling of C++ Code, npm will use [node-gyp](https://github.com/TooTallNate/node-gyp) for that task. For a Unix system, [node-gyp](https://github.com/TooTallNate/node-gyp) needs Python, make and a buildchain like GCC. On Windows, -Python and Microsoft Visual Studio C++ is needed. Python 3 is +Python and Microsoft Visual Studio C++ are needed. Python 3 is not supported by [node-gyp](https://github.com/TooTallNate/node-gyp). For more information visit [the node-gyp repository](https://github.com/TooTallNate/node-gyp) and diff --git a/deps/npm/doc/files/package.json.md b/deps/npm/doc/files/package.json.md index cb9a341d7770c0..848ad2b3367aed 100644 --- a/deps/npm/doc/files/package.json.md +++ b/deps/npm/doc/files/package.json.md @@ -734,10 +734,10 @@ npm will default some values based on package contents. If there is a `server.js` file in the root of your package, then npm will default the `start` command to `node server.js`. -* `"scripts":{"preinstall": "node-gyp rebuild"}` +* `"scripts":{"install": "node-gyp rebuild"}` - If there is a `binding.gyp` file in the root of your package, npm will - default the `preinstall` command to compile using node-gyp. + If there is a `binding.gyp` file in the root of your package and you have not defined an `install` or `preinstall` script, npm will + default the `install` command to compile using node-gyp. * `"contributors": [...]` diff --git a/deps/npm/doc/misc/npm-scripts.md b/deps/npm/doc/misc/npm-scripts.md index 10d82bec076e87..0dc20f278f7afb 100644 --- a/deps/npm/doc/misc/npm-scripts.md +++ b/deps/npm/doc/misc/npm-scripts.md @@ -34,9 +34,10 @@ following scripts: stop and start scripts if no `restart` script is provided. Additionally, arbitrary scripts can be executed by running `npm -run-script `. *Pre* and *post* commands with matching +run-script `. *Pre* and *post* commands with matching names will be run for those as well (e.g. `premyscript`, `myscript`, -`postmyscript`). +`postmyscript`). Scripts from dependencies can be run with `npm explore + -- npm run `. ## COMMON USES @@ -71,7 +72,8 @@ npm will default some script values based on package contents. * `"install": "node-gyp rebuild"`: - If there is a `bindings.gyp` file in the root of your package, npm will + If there is a `binding.gyp` file in the root of your package and you + haven't defined your own `install` or `preinstall` scripts, npm will default the `install` command to compile using node-gyp. ## USER diff --git a/deps/npm/html/doc/README.html b/deps/npm/html/doc/README.html index 3bfde0a728f07f..85b91c5a60c7c2 100644 --- a/deps/npm/html/doc/README.html +++ b/deps/npm/html/doc/README.html @@ -127,5 +127,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/api/npm-bin.html b/deps/npm/html/doc/api/npm-bin.html index 5e9484bded048b..6ca31ecba63b10 100644 --- a/deps/npm/html/doc/api/npm-bin.html +++ b/deps/npm/html/doc/api/npm-bin.html @@ -28,5 +28,5 @@

SYNOPSIS

       - + diff --git a/deps/npm/html/doc/api/npm-bugs.html b/deps/npm/html/doc/api/npm-bugs.html index ceb7572465e891..b2a6238bc8c967 100644 --- a/deps/npm/html/doc/api/npm-bugs.html +++ b/deps/npm/html/doc/api/npm-bugs.html @@ -33,5 +33,5 @@

SYNOPSIS

       - + diff --git a/deps/npm/html/doc/api/npm-cache.html b/deps/npm/html/doc/api/npm-cache.html index c90381500fd2ed..b8519f628e57d6 100644 --- a/deps/npm/html/doc/api/npm-cache.html +++ b/deps/npm/html/doc/api/npm-cache.html @@ -42,5 +42,5 @@

SYNOPSIS

       - + diff --git a/deps/npm/html/doc/api/npm-commands.html b/deps/npm/html/doc/api/npm-commands.html index eb90c0ccb9adc4..276944b413c481 100644 --- a/deps/npm/html/doc/api/npm-commands.html +++ b/deps/npm/html/doc/api/npm-commands.html @@ -36,5 +36,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/api/npm-config.html b/deps/npm/html/doc/api/npm-config.html index fabdef673d59ba..979e51188e97f3 100644 --- a/deps/npm/html/doc/api/npm-config.html +++ b/deps/npm/html/doc/api/npm-config.html @@ -57,5 +57,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/api/npm-deprecate.html b/deps/npm/html/doc/api/npm-deprecate.html index 339ec069d0f4f7..6c7425aaecae49 100644 --- a/deps/npm/html/doc/api/npm-deprecate.html +++ b/deps/npm/html/doc/api/npm-deprecate.html @@ -47,5 +47,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/api/npm-docs.html b/deps/npm/html/doc/api/npm-docs.html index 778d393fad29bb..5857e19fb4b96e 100644 --- a/deps/npm/html/doc/api/npm-docs.html +++ b/deps/npm/html/doc/api/npm-docs.html @@ -33,5 +33,5 @@

SYNOPSIS

       - + diff --git a/deps/npm/html/doc/api/npm-edit.html b/deps/npm/html/doc/api/npm-edit.html index 482f569b79955d..052792f2988d92 100644 --- a/deps/npm/html/doc/api/npm-edit.html +++ b/deps/npm/html/doc/api/npm-edit.html @@ -36,5 +36,5 @@

SYNOPSIS

       - + diff --git a/deps/npm/html/doc/api/npm-explore.html b/deps/npm/html/doc/api/npm-explore.html index e1bd478647bce7..0a38de88466405 100644 --- a/deps/npm/html/doc/api/npm-explore.html +++ b/deps/npm/html/doc/api/npm-explore.html @@ -31,5 +31,5 @@

SYNOPSIS

       - + diff --git a/deps/npm/html/doc/api/npm-help-search.html b/deps/npm/html/doc/api/npm-help-search.html index 85665599b567c6..dbabcc86ed49d6 100644 --- a/deps/npm/html/doc/api/npm-help-search.html +++ b/deps/npm/html/doc/api/npm-help-search.html @@ -44,5 +44,5 @@

SYNOPSIS

       - + diff --git a/deps/npm/html/doc/api/npm-init.html b/deps/npm/html/doc/api/npm-init.html index c310c8ca6fbaee..df2c0a6d540187 100644 --- a/deps/npm/html/doc/api/npm-init.html +++ b/deps/npm/html/doc/api/npm-init.html @@ -39,5 +39,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/api/npm-install.html b/deps/npm/html/doc/api/npm-install.html index de8ee12446aa10..19f294567fbe35 100644 --- a/deps/npm/html/doc/api/npm-install.html +++ b/deps/npm/html/doc/api/npm-install.html @@ -32,5 +32,5 @@

SYNOPSIS

       - + diff --git a/deps/npm/html/doc/api/npm-link.html b/deps/npm/html/doc/api/npm-link.html index 54f2cabf9a8b5b..77c16cbed33f34 100644 --- a/deps/npm/html/doc/api/npm-link.html +++ b/deps/npm/html/doc/api/npm-link.html @@ -42,5 +42,5 @@

SYNOPSIS

       - + diff --git a/deps/npm/html/doc/api/npm-load.html b/deps/npm/html/doc/api/npm-load.html index f64db440acb7a6..301164b9790250 100644 --- a/deps/npm/html/doc/api/npm-load.html +++ b/deps/npm/html/doc/api/npm-load.html @@ -37,5 +37,5 @@

SYNOPSIS

       - + diff --git a/deps/npm/html/doc/api/npm-ls.html b/deps/npm/html/doc/api/npm-ls.html index bfeed4581fba16..86cd99509a64b9 100644 --- a/deps/npm/html/doc/api/npm-ls.html +++ b/deps/npm/html/doc/api/npm-ls.html @@ -63,5 +63,5 @@

global

       - + diff --git a/deps/npm/html/doc/api/npm-outdated.html b/deps/npm/html/doc/api/npm-outdated.html index 2d5f6aad329703..23e455f021f6b3 100644 --- a/deps/npm/html/doc/api/npm-outdated.html +++ b/deps/npm/html/doc/api/npm-outdated.html @@ -28,5 +28,5 @@

SYNOPSIS

       - + diff --git a/deps/npm/html/doc/api/npm-owner.html b/deps/npm/html/doc/api/npm-owner.html index 36ee9ebba72f7b..d82bb94385167a 100644 --- a/deps/npm/html/doc/api/npm-owner.html +++ b/deps/npm/html/doc/api/npm-owner.html @@ -47,5 +47,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/api/npm-pack.html b/deps/npm/html/doc/api/npm-pack.html index 288386888da17c..21ccba34bf820c 100644 --- a/deps/npm/html/doc/api/npm-pack.html +++ b/deps/npm/html/doc/api/npm-pack.html @@ -33,5 +33,5 @@

SYNOPSIS

       - + diff --git a/deps/npm/html/doc/api/npm-ping.html b/deps/npm/html/doc/api/npm-ping.html index 90eb85a552dfb3..a00f7c8db34201 100644 --- a/deps/npm/html/doc/api/npm-ping.html +++ b/deps/npm/html/doc/api/npm-ping.html @@ -29,4 +29,4 @@

SYNOPSIS

       - + diff --git a/deps/npm/html/doc/api/npm-prefix.html b/deps/npm/html/doc/api/npm-prefix.html index be18dea7f53cc3..0c8a7eecbd5f35 100644 --- a/deps/npm/html/doc/api/npm-prefix.html +++ b/deps/npm/html/doc/api/npm-prefix.html @@ -29,5 +29,5 @@

SYNOPSIS

       - + diff --git a/deps/npm/html/doc/api/npm-prune.html b/deps/npm/html/doc/api/npm-prune.html index 3bbe302223aa8d..73eb52824c7512 100644 --- a/deps/npm/html/doc/api/npm-prune.html +++ b/deps/npm/html/doc/api/npm-prune.html @@ -30,5 +30,5 @@

SYNOPSIS

       - + diff --git a/deps/npm/html/doc/api/npm-publish.html b/deps/npm/html/doc/api/npm-publish.html index 5c353abc099306..2c08e342da751b 100644 --- a/deps/npm/html/doc/api/npm-publish.html +++ b/deps/npm/html/doc/api/npm-publish.html @@ -46,5 +46,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/api/npm-rebuild.html b/deps/npm/html/doc/api/npm-rebuild.html index 884c10ec60c1a2..30c3581fab53cc 100644 --- a/deps/npm/html/doc/api/npm-rebuild.html +++ b/deps/npm/html/doc/api/npm-rebuild.html @@ -30,5 +30,5 @@

CONFIGURATION

       - + diff --git a/deps/npm/html/doc/api/npm-repo.html b/deps/npm/html/doc/api/npm-repo.html index 7fcc7626a51d01..5b57941e831c6a 100644 --- a/deps/npm/html/doc/api/npm-repo.html +++ b/deps/npm/html/doc/api/npm-repo.html @@ -33,5 +33,5 @@

SYNOPSIS

       - + diff --git a/deps/npm/html/doc/api/npm-restart.html b/deps/npm/html/doc/api/npm-restart.html index b07e623adb2ff9..612b3c50deeaa9 100644 --- a/deps/npm/html/doc/api/npm-restart.html +++ b/deps/npm/html/doc/api/npm-restart.html @@ -52,5 +52,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/api/npm-root.html b/deps/npm/html/doc/api/npm-root.html index 8fdd3750988465..9e73077ca6622d 100644 --- a/deps/npm/html/doc/api/npm-root.html +++ b/deps/npm/html/doc/api/npm-root.html @@ -29,5 +29,5 @@

SYNOPSIS

       - + diff --git a/deps/npm/html/doc/api/npm-run-script.html b/deps/npm/html/doc/api/npm-run-script.html index 84e66fad817de1..257c705cc90076 100644 --- a/deps/npm/html/doc/api/npm-run-script.html +++ b/deps/npm/html/doc/api/npm-run-script.html @@ -41,5 +41,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/api/npm-search.html b/deps/npm/html/doc/api/npm-search.html index c0bbc25f201693..26cd8b90d4b5f7 100644 --- a/deps/npm/html/doc/api/npm-search.html +++ b/deps/npm/html/doc/api/npm-search.html @@ -53,5 +53,5 @@

SYNOPSIS

       - + diff --git a/deps/npm/html/doc/api/npm-shrinkwrap.html b/deps/npm/html/doc/api/npm-shrinkwrap.html index dbeaf23889dddd..932571629ea2ee 100644 --- a/deps/npm/html/doc/api/npm-shrinkwrap.html +++ b/deps/npm/html/doc/api/npm-shrinkwrap.html @@ -33,5 +33,5 @@

SYNOPSIS

       - + diff --git a/deps/npm/html/doc/api/npm-start.html b/deps/npm/html/doc/api/npm-start.html index 7bc6170b299683..619dcd3ac60c70 100644 --- a/deps/npm/html/doc/api/npm-start.html +++ b/deps/npm/html/doc/api/npm-start.html @@ -28,5 +28,5 @@

SYNOPSIS

       - + diff --git a/deps/npm/html/doc/api/npm-stop.html b/deps/npm/html/doc/api/npm-stop.html index 68cd39101cc72e..0d922b317479ae 100644 --- a/deps/npm/html/doc/api/npm-stop.html +++ b/deps/npm/html/doc/api/npm-stop.html @@ -28,5 +28,5 @@

SYNOPSIS

       - + diff --git a/deps/npm/html/doc/api/npm-tag.html b/deps/npm/html/doc/api/npm-tag.html index f6f0e0db6d93fc..ad1d1f5f45970e 100644 --- a/deps/npm/html/doc/api/npm-tag.html +++ b/deps/npm/html/doc/api/npm-tag.html @@ -36,5 +36,5 @@

SYNOPSIS

       - + diff --git a/deps/npm/html/doc/api/npm-test.html b/deps/npm/html/doc/api/npm-test.html index 3aabf3f7e14062..0cde42b3a80a4b 100644 --- a/deps/npm/html/doc/api/npm-test.html +++ b/deps/npm/html/doc/api/npm-test.html @@ -30,5 +30,5 @@

SYNOPSIS

       - + diff --git a/deps/npm/html/doc/api/npm-uninstall.html b/deps/npm/html/doc/api/npm-uninstall.html index 9cbb4c391eacb4..1a3d538be003fd 100644 --- a/deps/npm/html/doc/api/npm-uninstall.html +++ b/deps/npm/html/doc/api/npm-uninstall.html @@ -30,5 +30,5 @@

SYNOPSIS

       - + diff --git a/deps/npm/html/doc/api/npm-unpublish.html b/deps/npm/html/doc/api/npm-unpublish.html index c1cf291e09483a..42e37237277352 100644 --- a/deps/npm/html/doc/api/npm-unpublish.html +++ b/deps/npm/html/doc/api/npm-unpublish.html @@ -33,5 +33,5 @@

SYNOPSIS

       - + diff --git a/deps/npm/html/doc/api/npm-update.html b/deps/npm/html/doc/api/npm-update.html index df80fc3a8f9717..261896f04a8bb7 100644 --- a/deps/npm/html/doc/api/npm-update.html +++ b/deps/npm/html/doc/api/npm-update.html @@ -33,5 +33,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/api/npm-version.html b/deps/npm/html/doc/api/npm-version.html index b8fda6c4994f8b..714f00d92c7077 100644 --- a/deps/npm/html/doc/api/npm-version.html +++ b/deps/npm/html/doc/api/npm-version.html @@ -32,5 +32,5 @@

SYNOPSIS

       - + diff --git a/deps/npm/html/doc/api/npm-view.html b/deps/npm/html/doc/api/npm-view.html index f7833d5d166ac1..38369368172b43 100644 --- a/deps/npm/html/doc/api/npm-view.html +++ b/deps/npm/html/doc/api/npm-view.html @@ -81,5 +81,5 @@

RETURN VALUE

       - + diff --git a/deps/npm/html/doc/api/npm-whoami.html b/deps/npm/html/doc/api/npm-whoami.html index 0dcecdc78908ea..0cda3bb2f8fc2f 100644 --- a/deps/npm/html/doc/api/npm-whoami.html +++ b/deps/npm/html/doc/api/npm-whoami.html @@ -29,5 +29,5 @@

SYNOPSIS

       - + diff --git a/deps/npm/html/doc/api/npm.html b/deps/npm/html/doc/api/npm.html index 7c1a288eabf5de..a97c81cd00e29e 100644 --- a/deps/npm/html/doc/api/npm.html +++ b/deps/npm/html/doc/api/npm.html @@ -23,7 +23,7 @@

SYNOPSIS

npm.commands.install(["package"], cb) })

VERSION

-

2.15.5

+

2.15.8

DESCRIPTION

This is the API documentation for npm. To find documentation of the command line @@ -109,5 +109,5 @@

ABBREVS

       - + diff --git a/deps/npm/html/doc/cli/npm-access.html b/deps/npm/html/doc/cli/npm-access.html index 5d0547543dd34c..1f02afc3779664 100644 --- a/deps/npm/html/doc/cli/npm-access.html +++ b/deps/npm/html/doc/cli/npm-access.html @@ -84,5 +84,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-adduser.html b/deps/npm/html/doc/cli/npm-adduser.html index ea15a6163a3054..34f122ae490b9a 100644 --- a/deps/npm/html/doc/cli/npm-adduser.html +++ b/deps/npm/html/doc/cli/npm-adduser.html @@ -72,5 +72,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-bin.html b/deps/npm/html/doc/cli/npm-bin.html index 9f44db69551d69..17c948d5c0ee9a 100644 --- a/deps/npm/html/doc/cli/npm-bin.html +++ b/deps/npm/html/doc/cli/npm-bin.html @@ -35,5 +35,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-bugs.html b/deps/npm/html/doc/cli/npm-bugs.html index aa2592a3922119..9aefe4e90bfb7e 100644 --- a/deps/npm/html/doc/cli/npm-bugs.html +++ b/deps/npm/html/doc/cli/npm-bugs.html @@ -56,5 +56,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-build.html b/deps/npm/html/doc/cli/npm-build.html index af1255c14168b7..b9af10d0e77dab 100644 --- a/deps/npm/html/doc/cli/npm-build.html +++ b/deps/npm/html/doc/cli/npm-build.html @@ -40,5 +40,5 @@

DESCRIPTION

       - + diff --git a/deps/npm/html/doc/cli/npm-bundle.html b/deps/npm/html/doc/cli/npm-bundle.html index 1f50a8b0f4e22a..ef886e36868e7a 100644 --- a/deps/npm/html/doc/cli/npm-bundle.html +++ b/deps/npm/html/doc/cli/npm-bundle.html @@ -31,5 +31,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-cache.html b/deps/npm/html/doc/cli/npm-cache.html index 165a24f9aec527..498e84f3571ef9 100644 --- a/deps/npm/html/doc/cli/npm-cache.html +++ b/deps/npm/html/doc/cli/npm-cache.html @@ -81,5 +81,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-completion.html b/deps/npm/html/doc/cli/npm-completion.html index d48a0721082136..4d1341f1286152 100644 --- a/deps/npm/html/doc/cli/npm-completion.html +++ b/deps/npm/html/doc/cli/npm-completion.html @@ -42,5 +42,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-config.html b/deps/npm/html/doc/cli/npm-config.html index ba0fc7f5aa27dd..2e97f189d5ad4f 100644 --- a/deps/npm/html/doc/cli/npm-config.html +++ b/deps/npm/html/doc/cli/npm-config.html @@ -68,5 +68,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-dedupe.html b/deps/npm/html/doc/cli/npm-dedupe.html index 4c5cebfb449a8f..9837fe5c528d88 100644 --- a/deps/npm/html/doc/cli/npm-dedupe.html +++ b/deps/npm/html/doc/cli/npm-dedupe.html @@ -65,5 +65,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-deprecate.html b/deps/npm/html/doc/cli/npm-deprecate.html index 02ae63d41424ab..a7dc40a17476d0 100644 --- a/deps/npm/html/doc/cli/npm-deprecate.html +++ b/deps/npm/html/doc/cli/npm-deprecate.html @@ -38,5 +38,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-dist-tag.html b/deps/npm/html/doc/cli/npm-dist-tag.html index dfd245fef1b18e..c2df3a675d7e20 100644 --- a/deps/npm/html/doc/cli/npm-dist-tag.html +++ b/deps/npm/html/doc/cli/npm-dist-tag.html @@ -87,5 +87,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-docs.html b/deps/npm/html/doc/cli/npm-docs.html index 1059759b2b1e20..be387900f338e4 100644 --- a/deps/npm/html/doc/cli/npm-docs.html +++ b/deps/npm/html/doc/cli/npm-docs.html @@ -56,5 +56,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-edit.html b/deps/npm/html/doc/cli/npm-edit.html index 3fba9940e0bfa6..fb10654ffdd5b9 100644 --- a/deps/npm/html/doc/cli/npm-edit.html +++ b/deps/npm/html/doc/cli/npm-edit.html @@ -49,5 +49,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-explore.html b/deps/npm/html/doc/cli/npm-explore.html index fef17b26e0ed35..0f0d1aac8a64d5 100644 --- a/deps/npm/html/doc/cli/npm-explore.html +++ b/deps/npm/html/doc/cli/npm-explore.html @@ -49,5 +49,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-help-search.html b/deps/npm/html/doc/cli/npm-help-search.html index d1bf8924b6ba2e..a9a8def91eff03 100644 --- a/deps/npm/html/doc/cli/npm-help-search.html +++ b/deps/npm/html/doc/cli/npm-help-search.html @@ -46,5 +46,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-help.html b/deps/npm/html/doc/cli/npm-help.html index fb288ba13e826d..eb4b31b6b88aec 100644 --- a/deps/npm/html/doc/cli/npm-help.html +++ b/deps/npm/html/doc/cli/npm-help.html @@ -52,5 +52,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-init.html b/deps/npm/html/doc/cli/npm-init.html index 6fbad20eca47b6..b57502cc6f218a 100644 --- a/deps/npm/html/doc/cli/npm-init.html +++ b/deps/npm/html/doc/cli/npm-init.html @@ -48,5 +48,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-install.html b/deps/npm/html/doc/cli/npm-install.html index 20162d1c9f4ba7..641add6d1221df 100644 --- a/deps/npm/html/doc/cli/npm-install.html +++ b/deps/npm/html/doc/cli/npm-install.html @@ -281,5 +281,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-link.html b/deps/npm/html/doc/cli/npm-link.html index a85e3939b8baf8..060c7e42cfc0cb 100644 --- a/deps/npm/html/doc/cli/npm-link.html +++ b/deps/npm/html/doc/cli/npm-link.html @@ -73,5 +73,5 @@

SYNOPSIS

       - + diff --git a/deps/npm/html/doc/cli/npm-logout.html b/deps/npm/html/doc/cli/npm-logout.html index 1601bae0fd15b3..f8efeb5bfe47a0 100644 --- a/deps/npm/html/doc/cli/npm-logout.html +++ b/deps/npm/html/doc/cli/npm-logout.html @@ -51,5 +51,5 @@

scope

       - + diff --git a/deps/npm/html/doc/cli/npm-ls.html b/deps/npm/html/doc/cli/npm-ls.html index 1f2a04c917415d..78d24d8dccdefb 100644 --- a/deps/npm/html/doc/cli/npm-ls.html +++ b/deps/npm/html/doc/cli/npm-ls.html @@ -22,7 +22,7 @@

SYNOPSIS

limit the results to only the paths to the packages named. Note that nested packages will also show the paths to the specified packages. For example, running npm ls promzard in npm's source tree will show:

-
npm@2.15.5 /path/to/npm
+
npm@2.15.8 /path/to/npm
 └─┬ init-package-json@0.0.4
   └── promzard@0.1.5
 

It will print out extraneous, missing, and invalid packages.

@@ -97,5 +97,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-outdated.html b/deps/npm/html/doc/cli/npm-outdated.html index bc1fa06883878e..88eb32213ddf72 100644 --- a/deps/npm/html/doc/cli/npm-outdated.html +++ b/deps/npm/html/doc/cli/npm-outdated.html @@ -116,5 +116,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-owner.html b/deps/npm/html/doc/cli/npm-owner.html index 1aa44ebdd50a0f..acae0f62d25567 100644 --- a/deps/npm/html/doc/cli/npm-owner.html +++ b/deps/npm/html/doc/cli/npm-owner.html @@ -51,5 +51,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-pack.html b/deps/npm/html/doc/cli/npm-pack.html index 6d83ba1de7ede6..e99b0196a84e41 100644 --- a/deps/npm/html/doc/cli/npm-pack.html +++ b/deps/npm/html/doc/cli/npm-pack.html @@ -41,5 +41,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-ping.html b/deps/npm/html/doc/cli/npm-ping.html index 9bf1dcbd5e91b4..a4a0840f5fdbcd 100644 --- a/deps/npm/html/doc/cli/npm-ping.html +++ b/deps/npm/html/doc/cli/npm-ping.html @@ -32,4 +32,4 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-prefix.html b/deps/npm/html/doc/cli/npm-prefix.html index 614d420d4e5e4f..db12f0af4f5975 100644 --- a/deps/npm/html/doc/cli/npm-prefix.html +++ b/deps/npm/html/doc/cli/npm-prefix.html @@ -38,5 +38,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-prune.html b/deps/npm/html/doc/cli/npm-prune.html index 72afc505a3dc7e..76435f80dc8831 100644 --- a/deps/npm/html/doc/cli/npm-prune.html +++ b/deps/npm/html/doc/cli/npm-prune.html @@ -41,5 +41,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-publish.html b/deps/npm/html/doc/cli/npm-publish.html index 6f01fa806d56dd..7e1f12600047b3 100644 --- a/deps/npm/html/doc/cli/npm-publish.html +++ b/deps/npm/html/doc/cli/npm-publish.html @@ -69,5 +69,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-rebuild.html b/deps/npm/html/doc/cli/npm-rebuild.html index 17c5272080e9d3..bc99d2ae77759c 100644 --- a/deps/npm/html/doc/cli/npm-rebuild.html +++ b/deps/npm/html/doc/cli/npm-rebuild.html @@ -38,5 +38,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-repo.html b/deps/npm/html/doc/cli/npm-repo.html index ff48563e4a1d94..2f2f82c4a5c730 100644 --- a/deps/npm/html/doc/cli/npm-repo.html +++ b/deps/npm/html/doc/cli/npm-repo.html @@ -42,5 +42,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-restart.html b/deps/npm/html/doc/cli/npm-restart.html index e74e528c6376c2..333ec35dd57f20 100644 --- a/deps/npm/html/doc/cli/npm-restart.html +++ b/deps/npm/html/doc/cli/npm-restart.html @@ -53,5 +53,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-rm.html b/deps/npm/html/doc/cli/npm-rm.html index a7079518a5551b..c3474fdee2b085 100644 --- a/deps/npm/html/doc/cli/npm-rm.html +++ b/deps/npm/html/doc/cli/npm-rm.html @@ -39,5 +39,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-root.html b/deps/npm/html/doc/cli/npm-root.html index ece73937748763..bf0aebb037c190 100644 --- a/deps/npm/html/doc/cli/npm-root.html +++ b/deps/npm/html/doc/cli/npm-root.html @@ -35,5 +35,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-run-script.html b/deps/npm/html/doc/cli/npm-run-script.html index c8c733e304869f..f1ac515eb7e9a2 100644 --- a/deps/npm/html/doc/cli/npm-run-script.html +++ b/deps/npm/html/doc/cli/npm-run-script.html @@ -57,5 +57,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-search.html b/deps/npm/html/doc/cli/npm-search.html index faa3dfebf2cc04..698a5fb30b32bd 100644 --- a/deps/npm/html/doc/cli/npm-search.html +++ b/deps/npm/html/doc/cli/npm-search.html @@ -57,5 +57,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-shrinkwrap.html b/deps/npm/html/doc/cli/npm-shrinkwrap.html index a26f1c45bc82f1..bb75f581746633 100644 --- a/deps/npm/html/doc/cli/npm-shrinkwrap.html +++ b/deps/npm/html/doc/cli/npm-shrinkwrap.html @@ -168,5 +168,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-star.html b/deps/npm/html/doc/cli/npm-star.html index 4ef8bf2873bd66..0190d53ddbd19a 100644 --- a/deps/npm/html/doc/cli/npm-star.html +++ b/deps/npm/html/doc/cli/npm-star.html @@ -36,5 +36,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-stars.html b/deps/npm/html/doc/cli/npm-stars.html index ba1a995dc8fd99..fa5d37a1c85269 100644 --- a/deps/npm/html/doc/cli/npm-stars.html +++ b/deps/npm/html/doc/cli/npm-stars.html @@ -37,5 +37,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-start.html b/deps/npm/html/doc/cli/npm-start.html index 1edd091dff1043..18cb073c4c5474 100644 --- a/deps/npm/html/doc/cli/npm-start.html +++ b/deps/npm/html/doc/cli/npm-start.html @@ -39,5 +39,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-stop.html b/deps/npm/html/doc/cli/npm-stop.html index 503e36cd578f6a..b3456b9912e5d6 100644 --- a/deps/npm/html/doc/cli/npm-stop.html +++ b/deps/npm/html/doc/cli/npm-stop.html @@ -34,5 +34,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-tag.html b/deps/npm/html/doc/cli/npm-tag.html index 573353ab797763..7bc678f9cc770c 100644 --- a/deps/npm/html/doc/cli/npm-tag.html +++ b/deps/npm/html/doc/cli/npm-tag.html @@ -62,5 +62,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-team.html b/deps/npm/html/doc/cli/npm-team.html index 6b5e185e7346b4..36ad94b5692742 100644 --- a/deps/npm/html/doc/cli/npm-team.html +++ b/deps/npm/html/doc/cli/npm-team.html @@ -67,4 +67,4 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-test.html b/deps/npm/html/doc/cli/npm-test.html index f05d2b309b95a7..2b676a77156f52 100644 --- a/deps/npm/html/doc/cli/npm-test.html +++ b/deps/npm/html/doc/cli/npm-test.html @@ -38,5 +38,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-uninstall.html b/deps/npm/html/doc/cli/npm-uninstall.html index dd919844052161..839a4dbbd414ac 100644 --- a/deps/npm/html/doc/cli/npm-uninstall.html +++ b/deps/npm/html/doc/cli/npm-uninstall.html @@ -57,5 +57,5 @@

SYNOPSIS

       - + diff --git a/deps/npm/html/doc/cli/npm-unpublish.html b/deps/npm/html/doc/cli/npm-unpublish.html index 545729a5e8e1bd..b39f7234c5d8ef 100644 --- a/deps/npm/html/doc/cli/npm-unpublish.html +++ b/deps/npm/html/doc/cli/npm-unpublish.html @@ -47,5 +47,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-update.html b/deps/npm/html/doc/cli/npm-update.html index 6936fd0595c5de..59557db0c67076 100644 --- a/deps/npm/html/doc/cli/npm-update.html +++ b/deps/npm/html/doc/cli/npm-update.html @@ -117,5 +117,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-version.html b/deps/npm/html/doc/cli/npm-version.html index 01220efbe84d69..be8cd7755bfa6b 100644 --- a/deps/npm/html/doc/cli/npm-version.html +++ b/deps/npm/html/doc/cli/npm-version.html @@ -95,5 +95,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-view.html b/deps/npm/html/doc/cli/npm-view.html index afbdb8d1373804..25966cc2335597 100644 --- a/deps/npm/html/doc/cli/npm-view.html +++ b/deps/npm/html/doc/cli/npm-view.html @@ -85,5 +85,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm-whoami.html b/deps/npm/html/doc/cli/npm-whoami.html index 20d9261b22859b..7581c154687af8 100644 --- a/deps/npm/html/doc/cli/npm-whoami.html +++ b/deps/npm/html/doc/cli/npm-whoami.html @@ -33,5 +33,5 @@

SEE ALSO

       - + diff --git a/deps/npm/html/doc/cli/npm.html b/deps/npm/html/doc/cli/npm.html index ac99ada06eacb9..82a95ac453b0da 100644 --- a/deps/npm/html/doc/cli/npm.html +++ b/deps/npm/html/doc/cli/npm.html @@ -13,7 +13,7 @@

npm

javascript package manager

SYNOPSIS

npm <command> [args]
 

VERSION

-

2.15.5

+

2.15.8

DESCRIPTION

npm is the package manager for the Node JavaScript platform. It puts modules in place so that node can find them, and manages dependency @@ -36,7 +36,7 @@

DEPENDENCIES

node-gyp for that task. For a Unix system, node-gyp needs Python, make and a buildchain like GCC. On Windows, -Python and Microsoft Visual Studio C++ is needed. Python 3 is +Python and Microsoft Visual Studio C++ are needed. Python 3 is not supported by node-gyp. For more information visit the node-gyp repository and @@ -126,7 +126,7 @@

AUTHOR

Isaac Z. Schlueter :: isaacs :: @izs :: -i@izs.me

+i@izs.me

SEE ALSO

  • npm-help(1)
  • @@ -152,5 +152,5 @@

    SEE ALSO

           - + diff --git a/deps/npm/html/doc/files/npm-folders.html b/deps/npm/html/doc/files/npm-folders.html index 7682df15417643..f7898a03c3213a 100644 --- a/deps/npm/html/doc/files/npm-folders.html +++ b/deps/npm/html/doc/files/npm-folders.html @@ -183,5 +183,5 @@

    SEE ALSO

           - + diff --git a/deps/npm/html/doc/files/npm-global.html b/deps/npm/html/doc/files/npm-global.html index 7682df15417643..f7898a03c3213a 100644 --- a/deps/npm/html/doc/files/npm-global.html +++ b/deps/npm/html/doc/files/npm-global.html @@ -183,5 +183,5 @@

    SEE ALSO

           - + diff --git a/deps/npm/html/doc/files/npm-json.html b/deps/npm/html/doc/files/npm-json.html index c11cbc5357f680..2ff02b2956d7b3 100644 --- a/deps/npm/html/doc/files/npm-json.html +++ b/deps/npm/html/doc/files/npm-json.html @@ -546,9 +546,9 @@

    DEFAULT VALUES

    If there is a server.js file in the root of your package, then npm will default the start command to node server.js.

    -
  • "scripts":{"preinstall": "node-gyp rebuild"}

    -

    If there is a binding.gyp file in the root of your package, npm will -default the preinstall command to compile using node-gyp.

    +
  • "scripts":{"install": "node-gyp rebuild"}

    +

    If there is a binding.gyp file in the root of your package and you have not defined an install or preinstall script, npm will +default the install command to compile using node-gyp.

  • "contributors": [...]

    If there is an AUTHORS file in the root of your package, npm will @@ -582,5 +582,5 @@

    SEE ALSO

           - + diff --git a/deps/npm/html/doc/files/npmrc.html b/deps/npm/html/doc/files/npmrc.html index 05c3f572a8d146..d587ff0ee10075 100644 --- a/deps/npm/html/doc/files/npmrc.html +++ b/deps/npm/html/doc/files/npmrc.html @@ -83,5 +83,5 @@

    SEE ALSO

           - + diff --git a/deps/npm/html/doc/files/package.json.html b/deps/npm/html/doc/files/package.json.html index c11cbc5357f680..2ff02b2956d7b3 100644 --- a/deps/npm/html/doc/files/package.json.html +++ b/deps/npm/html/doc/files/package.json.html @@ -546,9 +546,9 @@

    DEFAULT VALUES

    If there is a server.js file in the root of your package, then npm will default the start command to node server.js.

  • -
  • "scripts":{"preinstall": "node-gyp rebuild"}

    -

    If there is a binding.gyp file in the root of your package, npm will -default the preinstall command to compile using node-gyp.

    +
  • "scripts":{"install": "node-gyp rebuild"}

    +

    If there is a binding.gyp file in the root of your package and you have not defined an install or preinstall script, npm will +default the install command to compile using node-gyp.

  • "contributors": [...]

    If there is an AUTHORS file in the root of your package, npm will @@ -582,5 +582,5 @@

    SEE ALSO

           - + diff --git a/deps/npm/html/doc/index.html b/deps/npm/html/doc/index.html index 876103b0162d85..229355f496a603 100644 --- a/deps/npm/html/doc/index.html +++ b/deps/npm/html/doc/index.html @@ -242,5 +242,5 @@

    semver(7)

           - + diff --git a/deps/npm/html/doc/misc/npm-coding-style.html b/deps/npm/html/doc/misc/npm-coding-style.html index fb10e35d7a4b62..3b112c6dbdb666 100644 --- a/deps/npm/html/doc/misc/npm-coding-style.html +++ b/deps/npm/html/doc/misc/npm-coding-style.html @@ -147,5 +147,5 @@

    SEE ALSO

           - + diff --git a/deps/npm/html/doc/misc/npm-config.html b/deps/npm/html/doc/misc/npm-config.html index 8adaff16063476..e38ce0e816caf8 100644 --- a/deps/npm/html/doc/misc/npm-config.html +++ b/deps/npm/html/doc/misc/npm-config.html @@ -812,5 +812,5 @@

    SEE ALSO

           - + diff --git a/deps/npm/html/doc/misc/npm-developers.html b/deps/npm/html/doc/misc/npm-developers.html index 82702688a6b102..ce113f31716368 100644 --- a/deps/npm/html/doc/misc/npm-developers.html +++ b/deps/npm/html/doc/misc/npm-developers.html @@ -195,5 +195,5 @@

    SEE ALSO

           - + diff --git a/deps/npm/html/doc/misc/npm-disputes.html b/deps/npm/html/doc/misc/npm-disputes.html index 8d056c3c5384a5..cbb723ea07337d 100644 --- a/deps/npm/html/doc/misc/npm-disputes.html +++ b/deps/npm/html/doc/misc/npm-disputes.html @@ -13,7 +13,7 @@

    npm-disputes

    Handling Module

    SYNOPSIS

    1. Get the author email with npm owner ls <pkgname>
    2. -
    3. Email the author, CC support@npmjs.com
    4. +
    5. Email the author, CC support@npmjs.com
    6. After a few weeks, if there's no resolution, we'll sort it out.

    Don't squat on package names. Publish code or move out of the way.

    @@ -51,12 +51,12 @@

    DESCRIPTION

    owner (Bob).
  • Joe emails Bob, explaining the situation as respectfully as possible, and what he would like to do with the module name. He -adds the npm support staff support@npmjs.com to the CC list of +adds the npm support staff support@npmjs.com to the CC list of the email. Mention in the email that Bob can run npm owner add joe foo to add Joe as an owner of the foo package.
  • After a reasonable amount of time, if Bob has not responded, or if Bob and Joe can't come to any sort of resolution, email support -support@npmjs.com and we'll sort it out. ("Reasonable" is +support@npmjs.com and we'll sort it out. ("Reasonable" is usually at least 4 weeks, but extra time is allowed around common holidays.)
  • @@ -112,5 +112,5 @@

    SEE ALSO

           - + diff --git a/deps/npm/html/doc/misc/npm-orgs.html b/deps/npm/html/doc/misc/npm-orgs.html index b52c3541801af0..4d461db28afd7c 100644 --- a/deps/npm/html/doc/misc/npm-orgs.html +++ b/deps/npm/html/doc/misc/npm-orgs.html @@ -86,4 +86,4 @@

    Team Admins create teams

           - + diff --git a/deps/npm/html/doc/misc/npm-registry.html b/deps/npm/html/doc/misc/npm-registry.html index 36aa364aa32f53..5bb5377166f898 100644 --- a/deps/npm/html/doc/misc/npm-registry.html +++ b/deps/npm/html/doc/misc/npm-registry.html @@ -70,5 +70,5 @@

    SEE ALSO

           - + diff --git a/deps/npm/html/doc/misc/npm-scope.html b/deps/npm/html/doc/misc/npm-scope.html index 1c08416786b552..2b7518026552f3 100644 --- a/deps/npm/html/doc/misc/npm-scope.html +++ b/deps/npm/html/doc/misc/npm-scope.html @@ -92,5 +92,5 @@

    SEE ALSO

           - + diff --git a/deps/npm/html/doc/misc/npm-scripts.html b/deps/npm/html/doc/misc/npm-scripts.html index e15458dc3187a6..5d381414f486fc 100644 --- a/deps/npm/html/doc/misc/npm-scripts.html +++ b/deps/npm/html/doc/misc/npm-scripts.html @@ -42,9 +42,10 @@

    DESCRIPTION

    stop and start scripts if no restart script is provided.

Additionally, arbitrary scripts can be executed by running npm -run-script <pkg> <stage>. Pre and post commands with matching +run-script <stage>. Pre and post commands with matching names will be run for those as well (e.g. premyscript, myscript, -postmyscript).

+postmyscript). Scripts from dependencies can be run with `npm explore

+

-- npm run `.

COMMON USES

If you need to perform operations on your package before it is used, in a way that is not dependent on the operating system or architecture of the @@ -74,7 +75,8 @@

DEFAULT VALUES

will default the start command to node server.js.

  • "install": "node-gyp rebuild":

    -

    If there is a bindings.gyp file in the root of your package, npm will +

    If there is a binding.gyp file in the root of your package and you +haven't defined your own install or preinstall scripts, npm will default the install command to compile using node-gyp.

  • @@ -207,5 +209,5 @@

    SEE ALSO

           - + diff --git a/deps/npm/html/doc/misc/removing-npm.html b/deps/npm/html/doc/misc/removing-npm.html index 41bbbd4e3207da..f0ac708064dbfe 100644 --- a/deps/npm/html/doc/misc/removing-npm.html +++ b/deps/npm/html/doc/misc/removing-npm.html @@ -57,5 +57,5 @@

    SEE ALSO

           - + diff --git a/deps/npm/html/doc/misc/semver.html b/deps/npm/html/doc/misc/semver.html index 9cb0f7e6fd4409..64be384d50f904 100644 --- a/deps/npm/html/doc/misc/semver.html +++ b/deps/npm/html/doc/misc/semver.html @@ -302,5 +302,5 @@

    Ranges

           - + diff --git a/deps/npm/lib/completion.js b/deps/npm/lib/completion.js index c85a42de640194..d218679ba1f22c 100644 --- a/deps/npm/lib/completion.js +++ b/deps/npm/lib/completion.js @@ -159,7 +159,7 @@ function dumpScript (cb) { process.stdout.write(d, function () { cb() }) process.stdout.on("error", function (er) { - // Darwin is a real dick sometimes. + // Darwin is a pain sometimes. // // This is necessary because the "source" or "." program in // bash on OS X closes its file argument before reading diff --git a/deps/npm/lib/install.js b/deps/npm/lib/install.js index 9cc6a46fc0ca06..10166718d2269c 100644 --- a/deps/npm/lib/install.js +++ b/deps/npm/lib/install.js @@ -1182,7 +1182,7 @@ function prepareForInstallMany (packageData, depsKey, bundled, wrap, family) { // prefer to not install things that are satisfied by // something in the "family" list, unless we're installing // from a shrinkwrap. - if (wrap) return wrap + if (depsKey !== "peerDependencies" && wrap) return true if (semver.validRange(family[d], true)) { return !semver.satisfies(family[d], packageData[depsKey][d], true) } diff --git a/deps/npm/man/man1/npm-README.1 b/deps/npm/man/man1/npm-README.1 index 630b82760ccaa0..e46fb969a117d1 100644 --- a/deps/npm/man/man1/npm-README.1 +++ b/deps/npm/man/man1/npm-README.1 @@ -1,4 +1,4 @@ -.TH "NPM" "1" "May 2016" "" "" +.TH "NPM" "1" "June 2016" "" "" .SH "NAME" \fBnpm\fR \- a JavaScript package manager .P diff --git a/deps/npm/man/man1/npm-access.1 b/deps/npm/man/man1/npm-access.1 index 7cc94f62106020..6cddb81db0b400 100644 --- a/deps/npm/man/man1/npm-access.1 +++ b/deps/npm/man/man1/npm-access.1 @@ -1,4 +1,4 @@ -.TH "NPM\-ACCESS" "1" "May 2016" "" "" +.TH "NPM\-ACCESS" "1" "June 2016" "" "" .SH "NAME" \fBnpm-access\fR \- Set access level on published packages .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-adduser.1 b/deps/npm/man/man1/npm-adduser.1 index a2ede7903dbfee..3a22940ba695a6 100644 --- a/deps/npm/man/man1/npm-adduser.1 +++ b/deps/npm/man/man1/npm-adduser.1 @@ -1,4 +1,4 @@ -.TH "NPM\-ADDUSER" "1" "May 2016" "" "" +.TH "NPM\-ADDUSER" "1" "June 2016" "" "" .SH "NAME" \fBnpm-adduser\fR \- Add a registry user account .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-bin.1 b/deps/npm/man/man1/npm-bin.1 index be4d81ebd311ab..6cccb70e5acd90 100644 --- a/deps/npm/man/man1/npm-bin.1 +++ b/deps/npm/man/man1/npm-bin.1 @@ -1,4 +1,4 @@ -.TH "NPM\-BIN" "1" "May 2016" "" "" +.TH "NPM\-BIN" "1" "June 2016" "" "" .SH "NAME" \fBnpm-bin\fR \- Display npm bin folder .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-bugs.1 b/deps/npm/man/man1/npm-bugs.1 index 77cbb3774a38d7..2ee758aa95668f 100644 --- a/deps/npm/man/man1/npm-bugs.1 +++ b/deps/npm/man/man1/npm-bugs.1 @@ -1,4 +1,4 @@ -.TH "NPM\-BUGS" "1" "May 2016" "" "" +.TH "NPM\-BUGS" "1" "June 2016" "" "" .SH "NAME" \fBnpm-bugs\fR \- Bugs for a package in a web browser maybe .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-build.1 b/deps/npm/man/man1/npm-build.1 index 9cd7dfbc15bb02..d4687cd735459d 100644 --- a/deps/npm/man/man1/npm-build.1 +++ b/deps/npm/man/man1/npm-build.1 @@ -1,4 +1,4 @@ -.TH "NPM\-BUILD" "1" "May 2016" "" "" +.TH "NPM\-BUILD" "1" "June 2016" "" "" .SH "NAME" \fBnpm-build\fR \- Build a package .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-bundle.1 b/deps/npm/man/man1/npm-bundle.1 index 561d0f2859405d..098b0d31779233 100644 --- a/deps/npm/man/man1/npm-bundle.1 +++ b/deps/npm/man/man1/npm-bundle.1 @@ -1,4 +1,4 @@ -.TH "NPM\-BUNDLE" "1" "May 2016" "" "" +.TH "NPM\-BUNDLE" "1" "June 2016" "" "" .SH "NAME" \fBnpm-bundle\fR \- REMOVED .SH DESCRIPTION diff --git a/deps/npm/man/man1/npm-cache.1 b/deps/npm/man/man1/npm-cache.1 index d9bfd8fd6adef4..b325ea394907e3 100644 --- a/deps/npm/man/man1/npm-cache.1 +++ b/deps/npm/man/man1/npm-cache.1 @@ -1,4 +1,4 @@ -.TH "NPM\-CACHE" "1" "May 2016" "" "" +.TH "NPM\-CACHE" "1" "June 2016" "" "" .SH "NAME" \fBnpm-cache\fR \- Manipulates packages cache .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-completion.1 b/deps/npm/man/man1/npm-completion.1 index 98b4d14c1494cf..c808bd1a72e721 100644 --- a/deps/npm/man/man1/npm-completion.1 +++ b/deps/npm/man/man1/npm-completion.1 @@ -1,4 +1,4 @@ -.TH "NPM\-COMPLETION" "1" "May 2016" "" "" +.TH "NPM\-COMPLETION" "1" "June 2016" "" "" .SH "NAME" \fBnpm-completion\fR \- Tab Completion for npm .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-config.1 b/deps/npm/man/man1/npm-config.1 index 12776e7a884671..6e57eb23a04ce9 100644 --- a/deps/npm/man/man1/npm-config.1 +++ b/deps/npm/man/man1/npm-config.1 @@ -1,4 +1,4 @@ -.TH "NPM\-CONFIG" "1" "May 2016" "" "" +.TH "NPM\-CONFIG" "1" "June 2016" "" "" .SH "NAME" \fBnpm-config\fR \- Manage the npm configuration files .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-dedupe.1 b/deps/npm/man/man1/npm-dedupe.1 index c7c2be7ed087be..b5970c3b5c6086 100644 --- a/deps/npm/man/man1/npm-dedupe.1 +++ b/deps/npm/man/man1/npm-dedupe.1 @@ -1,4 +1,4 @@ -.TH "NPM\-DEDUPE" "1" "May 2016" "" "" +.TH "NPM\-DEDUPE" "1" "June 2016" "" "" .SH "NAME" \fBnpm-dedupe\fR \- Reduce duplication .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-deprecate.1 b/deps/npm/man/man1/npm-deprecate.1 index babbc0c2078624..26db5fc374d3a1 100644 --- a/deps/npm/man/man1/npm-deprecate.1 +++ b/deps/npm/man/man1/npm-deprecate.1 @@ -1,4 +1,4 @@ -.TH "NPM\-DEPRECATE" "1" "May 2016" "" "" +.TH "NPM\-DEPRECATE" "1" "June 2016" "" "" .SH "NAME" \fBnpm-deprecate\fR \- Deprecate a version of a package .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-dist-tag.1 b/deps/npm/man/man1/npm-dist-tag.1 index b7f026cdc95aa4..7c8fe79e82abcd 100644 --- a/deps/npm/man/man1/npm-dist-tag.1 +++ b/deps/npm/man/man1/npm-dist-tag.1 @@ -1,4 +1,4 @@ -.TH "NPM\-DIST\-TAG" "1" "May 2016" "" "" +.TH "NPM\-DIST\-TAG" "1" "June 2016" "" "" .SH "NAME" \fBnpm-dist-tag\fR \- Modify package distribution tags .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-docs.1 b/deps/npm/man/man1/npm-docs.1 index b1a4c9b70b2772..979df3b857b5a3 100644 --- a/deps/npm/man/man1/npm-docs.1 +++ b/deps/npm/man/man1/npm-docs.1 @@ -1,4 +1,4 @@ -.TH "NPM\-DOCS" "1" "May 2016" "" "" +.TH "NPM\-DOCS" "1" "June 2016" "" "" .SH "NAME" \fBnpm-docs\fR \- Docs for a package in a web browser maybe .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-edit.1 b/deps/npm/man/man1/npm-edit.1 index 95a328b1468aca..823ec61480bc2e 100644 --- a/deps/npm/man/man1/npm-edit.1 +++ b/deps/npm/man/man1/npm-edit.1 @@ -1,4 +1,4 @@ -.TH "NPM\-EDIT" "1" "May 2016" "" "" +.TH "NPM\-EDIT" "1" "June 2016" "" "" .SH "NAME" \fBnpm-edit\fR \- Edit an installed package .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-explore.1 b/deps/npm/man/man1/npm-explore.1 index 98b5be7253e538..68682897f4500f 100644 --- a/deps/npm/man/man1/npm-explore.1 +++ b/deps/npm/man/man1/npm-explore.1 @@ -1,4 +1,4 @@ -.TH "NPM\-EXPLORE" "1" "May 2016" "" "" +.TH "NPM\-EXPLORE" "1" "June 2016" "" "" .SH "NAME" \fBnpm-explore\fR \- Browse an installed package .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-help-search.1 b/deps/npm/man/man1/npm-help-search.1 index 5b4141dafdbb08..24216d771b98fe 100644 --- a/deps/npm/man/man1/npm-help-search.1 +++ b/deps/npm/man/man1/npm-help-search.1 @@ -1,4 +1,4 @@ -.TH "NPM\-HELP\-SEARCH" "1" "May 2016" "" "" +.TH "NPM\-HELP\-SEARCH" "1" "June 2016" "" "" .SH "NAME" \fBnpm-help-search\fR \- Search npm help documentation .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-help.1 b/deps/npm/man/man1/npm-help.1 index a2528aa6bb9a70..12ce7361fa771c 100644 --- a/deps/npm/man/man1/npm-help.1 +++ b/deps/npm/man/man1/npm-help.1 @@ -1,4 +1,4 @@ -.TH "NPM\-HELP" "1" "May 2016" "" "" +.TH "NPM\-HELP" "1" "June 2016" "" "" .SH "NAME" \fBnpm-help\fR \- Get help on npm .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-init.1 b/deps/npm/man/man1/npm-init.1 index 257ed419071f2d..94955f53957327 100644 --- a/deps/npm/man/man1/npm-init.1 +++ b/deps/npm/man/man1/npm-init.1 @@ -1,4 +1,4 @@ -.TH "NPM\-INIT" "1" "May 2016" "" "" +.TH "NPM\-INIT" "1" "June 2016" "" "" .SH "NAME" \fBnpm-init\fR \- Interactively create a package\.json file .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-install.1 b/deps/npm/man/man1/npm-install.1 index a6be8c5b8d709b..4d2ec5b9c8a7a4 100644 --- a/deps/npm/man/man1/npm-install.1 +++ b/deps/npm/man/man1/npm-install.1 @@ -1,4 +1,4 @@ -.TH "NPM\-INSTALL" "1" "May 2016" "" "" +.TH "NPM\-INSTALL" "1" "June 2016" "" "" .SH "NAME" \fBnpm-install\fR \- Install a package .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-link.1 b/deps/npm/man/man1/npm-link.1 index 45897e11199629..913c457424a6c5 100644 --- a/deps/npm/man/man1/npm-link.1 +++ b/deps/npm/man/man1/npm-link.1 @@ -1,4 +1,4 @@ -.TH "NPM\-LINK" "1" "May 2016" "" "" +.TH "NPM\-LINK" "1" "June 2016" "" "" .SH "NAME" \fBnpm-link\fR \- Symlink a package folder .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-logout.1 b/deps/npm/man/man1/npm-logout.1 index 36edae2f21ede0..33fc3551221185 100644 --- a/deps/npm/man/man1/npm-logout.1 +++ b/deps/npm/man/man1/npm-logout.1 @@ -1,4 +1,4 @@ -.TH "NPM\-LOGOUT" "1" "May 2016" "" "" +.TH "NPM\-LOGOUT" "1" "June 2016" "" "" .SH "NAME" \fBnpm-logout\fR \- Log out of the registry .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-ls.1 b/deps/npm/man/man1/npm-ls.1 index a1e11b17e62bdd..3f7fe455a7a747 100644 --- a/deps/npm/man/man1/npm-ls.1 +++ b/deps/npm/man/man1/npm-ls.1 @@ -1,4 +1,4 @@ -.TH "NPM\-LS" "1" "May 2016" "" "" +.TH "NPM\-LS" "1" "June 2016" "" "" .SH "NAME" \fBnpm-ls\fR \- List installed packages .SH SYNOPSIS @@ -23,7 +23,7 @@ For example, running \fBnpm ls promzard\fP in npm's source tree will show: .P .RS 2 .nf -npm@2.15.5 /path/to/npm +npm@2.15.8 /path/to/npm └─┬ init\-package\-json@0\.0\.4 └── promzard@0\.1\.5 .fi diff --git a/deps/npm/man/man1/npm-outdated.1 b/deps/npm/man/man1/npm-outdated.1 index 0e73f444599efb..0fc75e4553770a 100644 --- a/deps/npm/man/man1/npm-outdated.1 +++ b/deps/npm/man/man1/npm-outdated.1 @@ -1,4 +1,4 @@ -.TH "NPM\-OUTDATED" "1" "May 2016" "" "" +.TH "NPM\-OUTDATED" "1" "June 2016" "" "" .SH "NAME" \fBnpm-outdated\fR \- Check for outdated packages .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-owner.1 b/deps/npm/man/man1/npm-owner.1 index f7c93748388886..fee7e8a46ecbf7 100644 --- a/deps/npm/man/man1/npm-owner.1 +++ b/deps/npm/man/man1/npm-owner.1 @@ -1,4 +1,4 @@ -.TH "NPM\-OWNER" "1" "May 2016" "" "" +.TH "NPM\-OWNER" "1" "June 2016" "" "" .SH "NAME" \fBnpm-owner\fR \- Manage package owners .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-pack.1 b/deps/npm/man/man1/npm-pack.1 index 60385abfa78eba..963ca5ee12e5eb 100644 --- a/deps/npm/man/man1/npm-pack.1 +++ b/deps/npm/man/man1/npm-pack.1 @@ -1,4 +1,4 @@ -.TH "NPM\-PACK" "1" "May 2016" "" "" +.TH "NPM\-PACK" "1" "June 2016" "" "" .SH "NAME" \fBnpm-pack\fR \- Create a tarball from a package .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-ping.1 b/deps/npm/man/man1/npm-ping.1 index cefc3f4bf5460b..2d0948ba1ddfbe 100644 --- a/deps/npm/man/man1/npm-ping.1 +++ b/deps/npm/man/man1/npm-ping.1 @@ -1,4 +1,4 @@ -.TH "NPM\-PING" "1" "May 2016" "" "" +.TH "NPM\-PING" "1" "June 2016" "" "" .SH "NAME" \fBnpm-ping\fR \- Ping npm registry .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-prefix.1 b/deps/npm/man/man1/npm-prefix.1 index 2a176a78ab9356..10b3c6ee9f913e 100644 --- a/deps/npm/man/man1/npm-prefix.1 +++ b/deps/npm/man/man1/npm-prefix.1 @@ -1,4 +1,4 @@ -.TH "NPM\-PREFIX" "1" "May 2016" "" "" +.TH "NPM\-PREFIX" "1" "June 2016" "" "" .SH "NAME" \fBnpm-prefix\fR \- Display prefix .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-prune.1 b/deps/npm/man/man1/npm-prune.1 index db1143d0495d6c..7598006fd3fad4 100644 --- a/deps/npm/man/man1/npm-prune.1 +++ b/deps/npm/man/man1/npm-prune.1 @@ -1,4 +1,4 @@ -.TH "NPM\-PRUNE" "1" "May 2016" "" "" +.TH "NPM\-PRUNE" "1" "June 2016" "" "" .SH "NAME" \fBnpm-prune\fR \- Remove extraneous packages .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-publish.1 b/deps/npm/man/man1/npm-publish.1 index 103ca216c568ce..e032222cc45ad8 100644 --- a/deps/npm/man/man1/npm-publish.1 +++ b/deps/npm/man/man1/npm-publish.1 @@ -1,4 +1,4 @@ -.TH "NPM\-PUBLISH" "1" "May 2016" "" "" +.TH "NPM\-PUBLISH" "1" "June 2016" "" "" .SH "NAME" \fBnpm-publish\fR \- Publish a package .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-rebuild.1 b/deps/npm/man/man1/npm-rebuild.1 index e3ca990c869985..cf2cecf63df986 100644 --- a/deps/npm/man/man1/npm-rebuild.1 +++ b/deps/npm/man/man1/npm-rebuild.1 @@ -1,4 +1,4 @@ -.TH "NPM\-REBUILD" "1" "May 2016" "" "" +.TH "NPM\-REBUILD" "1" "June 2016" "" "" .SH "NAME" \fBnpm-rebuild\fR \- Rebuild a package .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-repo.1 b/deps/npm/man/man1/npm-repo.1 index 065069032cf2d9..14c46dfd43d437 100644 --- a/deps/npm/man/man1/npm-repo.1 +++ b/deps/npm/man/man1/npm-repo.1 @@ -1,4 +1,4 @@ -.TH "NPM\-REPO" "1" "May 2016" "" "" +.TH "NPM\-REPO" "1" "June 2016" "" "" .SH "NAME" \fBnpm-repo\fR \- Open package repository page in the browser .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-restart.1 b/deps/npm/man/man1/npm-restart.1 index 80b573e346c88f..10e662a15d337a 100644 --- a/deps/npm/man/man1/npm-restart.1 +++ b/deps/npm/man/man1/npm-restart.1 @@ -1,4 +1,4 @@ -.TH "NPM\-RESTART" "1" "May 2016" "" "" +.TH "NPM\-RESTART" "1" "June 2016" "" "" .SH "NAME" \fBnpm-restart\fR \- Restart a package .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-rm.1 b/deps/npm/man/man1/npm-rm.1 index 3a1c6bd2d314e2..7c81b3ba6984cc 100644 --- a/deps/npm/man/man1/npm-rm.1 +++ b/deps/npm/man/man1/npm-rm.1 @@ -1,4 +1,4 @@ -.TH "NPM\-RM" "1" "May 2016" "" "" +.TH "NPM\-RM" "1" "June 2016" "" "" .SH "NAME" \fBnpm-rm\fR \- Remove a package .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-root.1 b/deps/npm/man/man1/npm-root.1 index c68278048ca13e..fe9b6667c16ec3 100644 --- a/deps/npm/man/man1/npm-root.1 +++ b/deps/npm/man/man1/npm-root.1 @@ -1,4 +1,4 @@ -.TH "NPM\-ROOT" "1" "May 2016" "" "" +.TH "NPM\-ROOT" "1" "June 2016" "" "" .SH "NAME" \fBnpm-root\fR \- Display npm root .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-run-script.1 b/deps/npm/man/man1/npm-run-script.1 index 3d208b53870964..a05dbd7641e2d8 100644 --- a/deps/npm/man/man1/npm-run-script.1 +++ b/deps/npm/man/man1/npm-run-script.1 @@ -1,4 +1,4 @@ -.TH "NPM\-RUN\-SCRIPT" "1" "May 2016" "" "" +.TH "NPM\-RUN\-SCRIPT" "1" "June 2016" "" "" .SH "NAME" \fBnpm-run-script\fR \- Run arbitrary package scripts .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-search.1 b/deps/npm/man/man1/npm-search.1 index 3ffb15c3be46ab..62247cc3f3191c 100644 --- a/deps/npm/man/man1/npm-search.1 +++ b/deps/npm/man/man1/npm-search.1 @@ -1,4 +1,4 @@ -.TH "NPM\-SEARCH" "1" "May 2016" "" "" +.TH "NPM\-SEARCH" "1" "June 2016" "" "" .SH "NAME" \fBnpm-search\fR \- Search for packages .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-shrinkwrap.1 b/deps/npm/man/man1/npm-shrinkwrap.1 index 33b1883998be2a..9c0e12df34e0e7 100644 --- a/deps/npm/man/man1/npm-shrinkwrap.1 +++ b/deps/npm/man/man1/npm-shrinkwrap.1 @@ -1,4 +1,4 @@ -.TH "NPM\-SHRINKWRAP" "1" "May 2016" "" "" +.TH "NPM\-SHRINKWRAP" "1" "June 2016" "" "" .SH "NAME" \fBnpm-shrinkwrap\fR \- Lock down dependency versions .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-star.1 b/deps/npm/man/man1/npm-star.1 index 3b0152fad7122a..4c9294f71ddd04 100644 --- a/deps/npm/man/man1/npm-star.1 +++ b/deps/npm/man/man1/npm-star.1 @@ -1,4 +1,4 @@ -.TH "NPM\-STAR" "1" "May 2016" "" "" +.TH "NPM\-STAR" "1" "June 2016" "" "" .SH "NAME" \fBnpm-star\fR \- Mark your favorite packages .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-stars.1 b/deps/npm/man/man1/npm-stars.1 index 488e4745e8323f..bed2c0f95a9205 100644 --- a/deps/npm/man/man1/npm-stars.1 +++ b/deps/npm/man/man1/npm-stars.1 @@ -1,4 +1,4 @@ -.TH "NPM\-STARS" "1" "May 2016" "" "" +.TH "NPM\-STARS" "1" "June 2016" "" "" .SH "NAME" \fBnpm-stars\fR \- View packages marked as favorites .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-start.1 b/deps/npm/man/man1/npm-start.1 index 33143e4168ef0a..cb09bea2c7e7fb 100644 --- a/deps/npm/man/man1/npm-start.1 +++ b/deps/npm/man/man1/npm-start.1 @@ -1,4 +1,4 @@ -.TH "NPM\-START" "1" "May 2016" "" "" +.TH "NPM\-START" "1" "June 2016" "" "" .SH "NAME" \fBnpm-start\fR \- Start a package .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-stop.1 b/deps/npm/man/man1/npm-stop.1 index 8f1e4be700f7b2..9fa9e8f018154f 100644 --- a/deps/npm/man/man1/npm-stop.1 +++ b/deps/npm/man/man1/npm-stop.1 @@ -1,4 +1,4 @@ -.TH "NPM\-STOP" "1" "May 2016" "" "" +.TH "NPM\-STOP" "1" "June 2016" "" "" .SH "NAME" \fBnpm-stop\fR \- Stop a package .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-tag.1 b/deps/npm/man/man1/npm-tag.1 index f4a027259928d2..63d4534140f050 100644 --- a/deps/npm/man/man1/npm-tag.1 +++ b/deps/npm/man/man1/npm-tag.1 @@ -1,4 +1,4 @@ -.TH "NPM\-TAG" "1" "May 2016" "" "" +.TH "NPM\-TAG" "1" "June 2016" "" "" .SH "NAME" \fBnpm-tag\fR \- Tag a published version .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-team.1 b/deps/npm/man/man1/npm-team.1 index bbcee7a2b6b909..7242d5084546b1 100644 --- a/deps/npm/man/man1/npm-team.1 +++ b/deps/npm/man/man1/npm-team.1 @@ -1,4 +1,4 @@ -.TH "NPM\-TEAM" "1" "May 2016" "" "" +.TH "NPM\-TEAM" "1" "June 2016" "" "" .SH "NAME" \fBnpm-team\fR \- Manage organization teams and team memberships .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-test.1 b/deps/npm/man/man1/npm-test.1 index 30f1b8ea96950b..18407f3fdeb354 100644 --- a/deps/npm/man/man1/npm-test.1 +++ b/deps/npm/man/man1/npm-test.1 @@ -1,4 +1,4 @@ -.TH "NPM\-TEST" "1" "May 2016" "" "" +.TH "NPM\-TEST" "1" "June 2016" "" "" .SH "NAME" \fBnpm-test\fR \- Test a package .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-uninstall.1 b/deps/npm/man/man1/npm-uninstall.1 index c34a58dacd38bc..f56053f9be24e7 100644 --- a/deps/npm/man/man1/npm-uninstall.1 +++ b/deps/npm/man/man1/npm-uninstall.1 @@ -1,4 +1,4 @@ -.TH "NPM\-UNINSTALL" "1" "May 2016" "" "" +.TH "NPM\-UNINSTALL" "1" "June 2016" "" "" .SH "NAME" \fBnpm-uninstall\fR \- Remove a package .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-unpublish.1 b/deps/npm/man/man1/npm-unpublish.1 index 7d5518cd5f8e6b..764fcf047f83b8 100644 --- a/deps/npm/man/man1/npm-unpublish.1 +++ b/deps/npm/man/man1/npm-unpublish.1 @@ -1,4 +1,4 @@ -.TH "NPM\-UNPUBLISH" "1" "May 2016" "" "" +.TH "NPM\-UNPUBLISH" "1" "June 2016" "" "" .SH "NAME" \fBnpm-unpublish\fR \- Remove a package from the registry .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-update.1 b/deps/npm/man/man1/npm-update.1 index 77e2e50fa4c7e8..2e03b3a0f55c85 100644 --- a/deps/npm/man/man1/npm-update.1 +++ b/deps/npm/man/man1/npm-update.1 @@ -1,4 +1,4 @@ -.TH "NPM\-UPDATE" "1" "May 2016" "" "" +.TH "NPM\-UPDATE" "1" "June 2016" "" "" .SH "NAME" \fBnpm-update\fR \- Update a package .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-version.1 b/deps/npm/man/man1/npm-version.1 index f5325cdebb3faa..728bbf97a2e70a 100644 --- a/deps/npm/man/man1/npm-version.1 +++ b/deps/npm/man/man1/npm-version.1 @@ -1,4 +1,4 @@ -.TH "NPM\-VERSION" "1" "May 2016" "" "" +.TH "NPM\-VERSION" "1" "June 2016" "" "" .SH "NAME" \fBnpm-version\fR \- Bump a package version .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-view.1 b/deps/npm/man/man1/npm-view.1 index 2c600a17c8dd1b..4a5cee506c6a24 100644 --- a/deps/npm/man/man1/npm-view.1 +++ b/deps/npm/man/man1/npm-view.1 @@ -1,4 +1,4 @@ -.TH "NPM\-VIEW" "1" "May 2016" "" "" +.TH "NPM\-VIEW" "1" "June 2016" "" "" .SH "NAME" \fBnpm-view\fR \- View registry info .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm-whoami.1 b/deps/npm/man/man1/npm-whoami.1 index 406c8b42a91720..e6ca9addb1a0c2 100644 --- a/deps/npm/man/man1/npm-whoami.1 +++ b/deps/npm/man/man1/npm-whoami.1 @@ -1,4 +1,4 @@ -.TH "NPM\-WHOAMI" "1" "May 2016" "" "" +.TH "NPM\-WHOAMI" "1" "June 2016" "" "" .SH "NAME" \fBnpm-whoami\fR \- Display npm username .SH SYNOPSIS diff --git a/deps/npm/man/man1/npm.1 b/deps/npm/man/man1/npm.1 index a466ba281fea6d..851eaf87ed2523 100644 --- a/deps/npm/man/man1/npm.1 +++ b/deps/npm/man/man1/npm.1 @@ -1,4 +1,4 @@ -.TH "NPM" "1" "May 2016" "" "" +.TH "NPM" "1" "June 2016" "" "" .SH "NAME" \fBnpm\fR \- javascript package manager .SH SYNOPSIS @@ -10,7 +10,7 @@ npm [args] .RE .SH VERSION .P -2.15.5 +2.15.8 .SH DESCRIPTION .P npm is the package manager for the Node JavaScript platform\. It puts @@ -41,7 +41,7 @@ requires compiling of C++ Code, npm will use node\-gyp \fIhttps://github\.com/TooTallNate/node\-gyp\fR for that task\. For a Unix system, node\-gyp \fIhttps://github\.com/TooTallNate/node\-gyp\fR needs Python, make and a buildchain like GCC\. On Windows, -Python and Microsoft Visual Studio C++ is needed\. Python 3 is +Python and Microsoft Visual Studio C++ are needed\. Python 3 is not supported by node\-gyp \fIhttps://github\.com/TooTallNate/node\-gyp\fR\|\. For more information visit the node\-gyp repository \fIhttps://github\.com/TooTallNate/node\-gyp\fR and diff --git a/deps/npm/man/man3/npm-bin.3 b/deps/npm/man/man3/npm-bin.3 index e86afe7d7426a0..3f819825b34249 100644 --- a/deps/npm/man/man3/npm-bin.3 +++ b/deps/npm/man/man3/npm-bin.3 @@ -1,4 +1,4 @@ -.TH "NPM\-BIN" "3" "May 2016" "" "" +.TH "NPM\-BIN" "3" "June 2016" "" "" .SH "NAME" \fBnpm-bin\fR \- Display npm bin folder .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm-bugs.3 b/deps/npm/man/man3/npm-bugs.3 index 6dde2c10f42de5..92878898f7196d 100644 --- a/deps/npm/man/man3/npm-bugs.3 +++ b/deps/npm/man/man3/npm-bugs.3 @@ -1,4 +1,4 @@ -.TH "NPM\-BUGS" "3" "May 2016" "" "" +.TH "NPM\-BUGS" "3" "June 2016" "" "" .SH "NAME" \fBnpm-bugs\fR \- Bugs for a package in a web browser maybe .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm-cache.3 b/deps/npm/man/man3/npm-cache.3 index 30a610071c9564..df17a56e23791a 100644 --- a/deps/npm/man/man3/npm-cache.3 +++ b/deps/npm/man/man3/npm-cache.3 @@ -1,4 +1,4 @@ -.TH "NPM\-CACHE" "3" "May 2016" "" "" +.TH "NPM\-CACHE" "3" "June 2016" "" "" .SH "NAME" \fBnpm-cache\fR \- manage the npm cache programmatically .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm-commands.3 b/deps/npm/man/man3/npm-commands.3 index 327379333e18c6..e781234c7ed40c 100644 --- a/deps/npm/man/man3/npm-commands.3 +++ b/deps/npm/man/man3/npm-commands.3 @@ -1,4 +1,4 @@ -.TH "NPM\-COMMANDS" "3" "May 2016" "" "" +.TH "NPM\-COMMANDS" "3" "June 2016" "" "" .SH "NAME" \fBnpm-commands\fR \- npm commands .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm-config.3 b/deps/npm/man/man3/npm-config.3 index abbb685a5f44b3..0ebada528d5175 100644 --- a/deps/npm/man/man3/npm-config.3 +++ b/deps/npm/man/man3/npm-config.3 @@ -1,4 +1,4 @@ -.TH "NPM\-CONFIG" "3" "May 2016" "" "" +.TH "NPM\-CONFIG" "3" "June 2016" "" "" .SH "NAME" \fBnpm-config\fR \- Manage the npm configuration files .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm-deprecate.3 b/deps/npm/man/man3/npm-deprecate.3 index 048c63dfb085c7..9a9cc0aa0c1edd 100644 --- a/deps/npm/man/man3/npm-deprecate.3 +++ b/deps/npm/man/man3/npm-deprecate.3 @@ -1,4 +1,4 @@ -.TH "NPM\-DEPRECATE" "3" "May 2016" "" "" +.TH "NPM\-DEPRECATE" "3" "June 2016" "" "" .SH "NAME" \fBnpm-deprecate\fR \- Deprecate a version of a package .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm-docs.3 b/deps/npm/man/man3/npm-docs.3 index 03eceac3583d6a..f8ccc15a1ef0c8 100644 --- a/deps/npm/man/man3/npm-docs.3 +++ b/deps/npm/man/man3/npm-docs.3 @@ -1,4 +1,4 @@ -.TH "NPM\-DOCS" "3" "May 2016" "" "" +.TH "NPM\-DOCS" "3" "June 2016" "" "" .SH "NAME" \fBnpm-docs\fR \- Docs for a package in a web browser maybe .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm-edit.3 b/deps/npm/man/man3/npm-edit.3 index 7bc2a591a0b90c..28bc989a4f6956 100644 --- a/deps/npm/man/man3/npm-edit.3 +++ b/deps/npm/man/man3/npm-edit.3 @@ -1,4 +1,4 @@ -.TH "NPM\-EDIT" "3" "May 2016" "" "" +.TH "NPM\-EDIT" "3" "June 2016" "" "" .SH "NAME" \fBnpm-edit\fR \- Edit an installed package .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm-explore.3 b/deps/npm/man/man3/npm-explore.3 index 805d311a29b793..a1be2956ff5d29 100644 --- a/deps/npm/man/man3/npm-explore.3 +++ b/deps/npm/man/man3/npm-explore.3 @@ -1,4 +1,4 @@ -.TH "NPM\-EXPLORE" "3" "May 2016" "" "" +.TH "NPM\-EXPLORE" "3" "June 2016" "" "" .SH "NAME" \fBnpm-explore\fR \- Browse an installed package .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm-help-search.3 b/deps/npm/man/man3/npm-help-search.3 index ffe4001a10982f..b399bd6ae7f6c6 100644 --- a/deps/npm/man/man3/npm-help-search.3 +++ b/deps/npm/man/man3/npm-help-search.3 @@ -1,4 +1,4 @@ -.TH "NPM\-HELP\-SEARCH" "3" "May 2016" "" "" +.TH "NPM\-HELP\-SEARCH" "3" "June 2016" "" "" .SH "NAME" \fBnpm-help-search\fR \- Search the help pages .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm-init.3 b/deps/npm/man/man3/npm-init.3 index 698b0a81cd3e55..abda90991396dd 100644 --- a/deps/npm/man/man3/npm-init.3 +++ b/deps/npm/man/man3/npm-init.3 @@ -1,4 +1,4 @@ -.TH "NPM" "" "May 2016" "" "" +.TH "NPM" "" "June 2016" "" "" .SH "NAME" \fBnpm\fR .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm-install.3 b/deps/npm/man/man3/npm-install.3 index 92de44f766aa71..75942be2a1d364 100644 --- a/deps/npm/man/man3/npm-install.3 +++ b/deps/npm/man/man3/npm-install.3 @@ -1,4 +1,4 @@ -.TH "NPM\-INSTALL" "3" "May 2016" "" "" +.TH "NPM\-INSTALL" "3" "June 2016" "" "" .SH "NAME" \fBnpm-install\fR \- install a package programmatically .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm-link.3 b/deps/npm/man/man3/npm-link.3 index bfaad676ef8437..b4f3d4a89c34e2 100644 --- a/deps/npm/man/man3/npm-link.3 +++ b/deps/npm/man/man3/npm-link.3 @@ -1,4 +1,4 @@ -.TH "NPM\-LINK" "3" "May 2016" "" "" +.TH "NPM\-LINK" "3" "June 2016" "" "" .SH "NAME" \fBnpm-link\fR \- Symlink a package folder .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm-load.3 b/deps/npm/man/man3/npm-load.3 index 858e8361257951..22dda10e42e3da 100644 --- a/deps/npm/man/man3/npm-load.3 +++ b/deps/npm/man/man3/npm-load.3 @@ -1,4 +1,4 @@ -.TH "NPM\-LOAD" "3" "May 2016" "" "" +.TH "NPM\-LOAD" "3" "June 2016" "" "" .SH "NAME" \fBnpm-load\fR \- Load config settings .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm-ls.3 b/deps/npm/man/man3/npm-ls.3 index f458b9ea5dc63a..b6a9a76f2ee8a3 100644 --- a/deps/npm/man/man3/npm-ls.3 +++ b/deps/npm/man/man3/npm-ls.3 @@ -1,4 +1,4 @@ -.TH "NPM\-LS" "3" "May 2016" "" "" +.TH "NPM\-LS" "3" "June 2016" "" "" .SH "NAME" \fBnpm-ls\fR \- List installed packages .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm-outdated.3 b/deps/npm/man/man3/npm-outdated.3 index 901e4e7a89f884..218c080822b3ea 100644 --- a/deps/npm/man/man3/npm-outdated.3 +++ b/deps/npm/man/man3/npm-outdated.3 @@ -1,4 +1,4 @@ -.TH "NPM\-OUTDATED" "3" "May 2016" "" "" +.TH "NPM\-OUTDATED" "3" "June 2016" "" "" .SH "NAME" \fBnpm-outdated\fR \- Check for outdated packages .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm-owner.3 b/deps/npm/man/man3/npm-owner.3 index cc20ca567e70f3..7788fb7d79fa33 100644 --- a/deps/npm/man/man3/npm-owner.3 +++ b/deps/npm/man/man3/npm-owner.3 @@ -1,4 +1,4 @@ -.TH "NPM\-OWNER" "3" "May 2016" "" "" +.TH "NPM\-OWNER" "3" "June 2016" "" "" .SH "NAME" \fBnpm-owner\fR \- Manage package owners .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm-pack.3 b/deps/npm/man/man3/npm-pack.3 index 31008a561d7eb8..849d25a563673c 100644 --- a/deps/npm/man/man3/npm-pack.3 +++ b/deps/npm/man/man3/npm-pack.3 @@ -1,4 +1,4 @@ -.TH "NPM\-PACK" "3" "May 2016" "" "" +.TH "NPM\-PACK" "3" "June 2016" "" "" .SH "NAME" \fBnpm-pack\fR \- Create a tarball from a package .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm-ping.3 b/deps/npm/man/man3/npm-ping.3 index 762d23ac732fff..4826af70ced1ab 100644 --- a/deps/npm/man/man3/npm-ping.3 +++ b/deps/npm/man/man3/npm-ping.3 @@ -1,4 +1,4 @@ -.TH "NPM\-PING" "3" "May 2016" "" "" +.TH "NPM\-PING" "3" "June 2016" "" "" .SH "NAME" \fBnpm-ping\fR \- Ping npm registry .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm-prefix.3 b/deps/npm/man/man3/npm-prefix.3 index 88d23381a07492..6ddb3541ef9b52 100644 --- a/deps/npm/man/man3/npm-prefix.3 +++ b/deps/npm/man/man3/npm-prefix.3 @@ -1,4 +1,4 @@ -.TH "NPM\-PREFIX" "3" "May 2016" "" "" +.TH "NPM\-PREFIX" "3" "June 2016" "" "" .SH "NAME" \fBnpm-prefix\fR \- Display prefix .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm-prune.3 b/deps/npm/man/man3/npm-prune.3 index 5b5532651eb8a2..045a91bee56b27 100644 --- a/deps/npm/man/man3/npm-prune.3 +++ b/deps/npm/man/man3/npm-prune.3 @@ -1,4 +1,4 @@ -.TH "NPM\-PRUNE" "3" "May 2016" "" "" +.TH "NPM\-PRUNE" "3" "June 2016" "" "" .SH "NAME" \fBnpm-prune\fR \- Remove extraneous packages .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm-publish.3 b/deps/npm/man/man3/npm-publish.3 index 3561b1332a4639..aa11a3a1e74a25 100644 --- a/deps/npm/man/man3/npm-publish.3 +++ b/deps/npm/man/man3/npm-publish.3 @@ -1,4 +1,4 @@ -.TH "NPM\-PUBLISH" "3" "May 2016" "" "" +.TH "NPM\-PUBLISH" "3" "June 2016" "" "" .SH "NAME" \fBnpm-publish\fR \- Publish a package .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm-rebuild.3 b/deps/npm/man/man3/npm-rebuild.3 index 80210d78407c1e..1ed8d31d3fdfcf 100644 --- a/deps/npm/man/man3/npm-rebuild.3 +++ b/deps/npm/man/man3/npm-rebuild.3 @@ -1,4 +1,4 @@ -.TH "NPM\-REBUILD" "3" "May 2016" "" "" +.TH "NPM\-REBUILD" "3" "June 2016" "" "" .SH "NAME" \fBnpm-rebuild\fR \- Rebuild a package .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm-repo.3 b/deps/npm/man/man3/npm-repo.3 index fc43f26752d664..baadbf992de4e7 100644 --- a/deps/npm/man/man3/npm-repo.3 +++ b/deps/npm/man/man3/npm-repo.3 @@ -1,4 +1,4 @@ -.TH "NPM\-REPO" "3" "May 2016" "" "" +.TH "NPM\-REPO" "3" "June 2016" "" "" .SH "NAME" \fBnpm-repo\fR \- Open package repository page in the browser .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm-restart.3 b/deps/npm/man/man3/npm-restart.3 index 6558f40a584087..7798d7c3a63bf4 100644 --- a/deps/npm/man/man3/npm-restart.3 +++ b/deps/npm/man/man3/npm-restart.3 @@ -1,4 +1,4 @@ -.TH "NPM\-RESTART" "3" "May 2016" "" "" +.TH "NPM\-RESTART" "3" "June 2016" "" "" .SH "NAME" \fBnpm-restart\fR \- Restart a package .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm-root.3 b/deps/npm/man/man3/npm-root.3 index 74f7e93420d81e..d573a26c9b8fd9 100644 --- a/deps/npm/man/man3/npm-root.3 +++ b/deps/npm/man/man3/npm-root.3 @@ -1,4 +1,4 @@ -.TH "NPM\-ROOT" "3" "May 2016" "" "" +.TH "NPM\-ROOT" "3" "June 2016" "" "" .SH "NAME" \fBnpm-root\fR \- Display npm root .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm-run-script.3 b/deps/npm/man/man3/npm-run-script.3 index 79469339dbb751..081c0959efc057 100644 --- a/deps/npm/man/man3/npm-run-script.3 +++ b/deps/npm/man/man3/npm-run-script.3 @@ -1,4 +1,4 @@ -.TH "NPM\-RUN\-SCRIPT" "3" "May 2016" "" "" +.TH "NPM\-RUN\-SCRIPT" "3" "June 2016" "" "" .SH "NAME" \fBnpm-run-script\fR \- Run arbitrary package scripts .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm-search.3 b/deps/npm/man/man3/npm-search.3 index 6544cbcc85119e..21ecc787ef647e 100644 --- a/deps/npm/man/man3/npm-search.3 +++ b/deps/npm/man/man3/npm-search.3 @@ -1,4 +1,4 @@ -.TH "NPM\-SEARCH" "3" "May 2016" "" "" +.TH "NPM\-SEARCH" "3" "June 2016" "" "" .SH "NAME" \fBnpm-search\fR \- Search for packages .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm-shrinkwrap.3 b/deps/npm/man/man3/npm-shrinkwrap.3 index deb1d79e3fffc8..52d355ce9efbcf 100644 --- a/deps/npm/man/man3/npm-shrinkwrap.3 +++ b/deps/npm/man/man3/npm-shrinkwrap.3 @@ -1,4 +1,4 @@ -.TH "NPM\-SHRINKWRAP" "3" "May 2016" "" "" +.TH "NPM\-SHRINKWRAP" "3" "June 2016" "" "" .SH "NAME" \fBnpm-shrinkwrap\fR \- programmatically generate package shrinkwrap file .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm-start.3 b/deps/npm/man/man3/npm-start.3 index 6217ef634b3181..8e011ff765b0ce 100644 --- a/deps/npm/man/man3/npm-start.3 +++ b/deps/npm/man/man3/npm-start.3 @@ -1,4 +1,4 @@ -.TH "NPM\-START" "3" "May 2016" "" "" +.TH "NPM\-START" "3" "June 2016" "" "" .SH "NAME" \fBnpm-start\fR \- Start a package .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm-stop.3 b/deps/npm/man/man3/npm-stop.3 index 748678020cc857..23b8a57689021c 100644 --- a/deps/npm/man/man3/npm-stop.3 +++ b/deps/npm/man/man3/npm-stop.3 @@ -1,4 +1,4 @@ -.TH "NPM\-STOP" "3" "May 2016" "" "" +.TH "NPM\-STOP" "3" "June 2016" "" "" .SH "NAME" \fBnpm-stop\fR \- Stop a package .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm-tag.3 b/deps/npm/man/man3/npm-tag.3 index f5c548b76b9d45..3ee3f2018505f8 100644 --- a/deps/npm/man/man3/npm-tag.3 +++ b/deps/npm/man/man3/npm-tag.3 @@ -1,4 +1,4 @@ -.TH "NPM\-TAG" "3" "May 2016" "" "" +.TH "NPM\-TAG" "3" "June 2016" "" "" .SH "NAME" \fBnpm-tag\fR \- Tag a published version .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm-test.3 b/deps/npm/man/man3/npm-test.3 index d108f4ce927f10..310c18ec865add 100644 --- a/deps/npm/man/man3/npm-test.3 +++ b/deps/npm/man/man3/npm-test.3 @@ -1,4 +1,4 @@ -.TH "NPM\-TEST" "3" "May 2016" "" "" +.TH "NPM\-TEST" "3" "June 2016" "" "" .SH "NAME" \fBnpm-test\fR \- Test a package .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm-uninstall.3 b/deps/npm/man/man3/npm-uninstall.3 index 56585c1433cd60..cb1d2b78e4d642 100644 --- a/deps/npm/man/man3/npm-uninstall.3 +++ b/deps/npm/man/man3/npm-uninstall.3 @@ -1,4 +1,4 @@ -.TH "NPM\-UNINSTALL" "3" "May 2016" "" "" +.TH "NPM\-UNINSTALL" "3" "June 2016" "" "" .SH "NAME" \fBnpm-uninstall\fR \- uninstall a package programmatically .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm-unpublish.3 b/deps/npm/man/man3/npm-unpublish.3 index 90ef3f17514152..4e31f64c21cdb6 100644 --- a/deps/npm/man/man3/npm-unpublish.3 +++ b/deps/npm/man/man3/npm-unpublish.3 @@ -1,4 +1,4 @@ -.TH "NPM\-UNPUBLISH" "3" "May 2016" "" "" +.TH "NPM\-UNPUBLISH" "3" "June 2016" "" "" .SH "NAME" \fBnpm-unpublish\fR \- Remove a package from the registry .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm-update.3 b/deps/npm/man/man3/npm-update.3 index 6d4fb5d3ac74e2..9adb90c0c3cc9a 100644 --- a/deps/npm/man/man3/npm-update.3 +++ b/deps/npm/man/man3/npm-update.3 @@ -1,4 +1,4 @@ -.TH "NPM\-UPDATE" "3" "May 2016" "" "" +.TH "NPM\-UPDATE" "3" "June 2016" "" "" .SH "NAME" \fBnpm-update\fR \- Update a package .SH SYNOPSIS @@ -8,7 +8,7 @@ npm\.commands\.update(packages, callback) .fi .RE -.TH "DESCRIPTION" "" "May 2016" "" "" +.TH "DESCRIPTION" "" "June 2016" "" "" .SH "NAME" \fBDESCRIPTION\fR .P diff --git a/deps/npm/man/man3/npm-version.3 b/deps/npm/man/man3/npm-version.3 index 7ec65e9056ec74..843ae20614abd1 100644 --- a/deps/npm/man/man3/npm-version.3 +++ b/deps/npm/man/man3/npm-version.3 @@ -1,4 +1,4 @@ -.TH "NPM\-VERSION" "3" "May 2016" "" "" +.TH "NPM\-VERSION" "3" "June 2016" "" "" .SH "NAME" \fBnpm-version\fR \- Bump a package version .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm-view.3 b/deps/npm/man/man3/npm-view.3 index c806d3c6a7ca67..15ecf6cc1eb9bb 100644 --- a/deps/npm/man/man3/npm-view.3 +++ b/deps/npm/man/man3/npm-view.3 @@ -1,4 +1,4 @@ -.TH "NPM\-VIEW" "3" "May 2016" "" "" +.TH "NPM\-VIEW" "3" "June 2016" "" "" .SH "NAME" \fBnpm-view\fR \- View registry info .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm-whoami.3 b/deps/npm/man/man3/npm-whoami.3 index 024e71ba6e3f12..5e4ad95c8041ae 100644 --- a/deps/npm/man/man3/npm-whoami.3 +++ b/deps/npm/man/man3/npm-whoami.3 @@ -1,4 +1,4 @@ -.TH "NPM\-WHOAMI" "3" "May 2016" "" "" +.TH "NPM\-WHOAMI" "3" "June 2016" "" "" .SH "NAME" \fBnpm-whoami\fR \- Display npm username .SH SYNOPSIS diff --git a/deps/npm/man/man3/npm.3 b/deps/npm/man/man3/npm.3 index 4c691a49f7ab10..0a741e57f4cd7c 100644 --- a/deps/npm/man/man3/npm.3 +++ b/deps/npm/man/man3/npm.3 @@ -1,4 +1,4 @@ -.TH "NPM" "3" "May 2016" "" "" +.TH "NPM" "3" "June 2016" "" "" .SH "NAME" \fBnpm\fR \- javascript package manager .SH SYNOPSIS @@ -20,7 +20,7 @@ npm\.load([configObject, ]function (er, npm) { .RE .SH VERSION .P -2.15.5 +2.15.8 .SH DESCRIPTION .P This is the API documentation for npm\. diff --git a/deps/npm/man/man5/npm-folders.5 b/deps/npm/man/man5/npm-folders.5 index 20c2d64716322c..b94aeb863ecc5f 100644 --- a/deps/npm/man/man5/npm-folders.5 +++ b/deps/npm/man/man5/npm-folders.5 @@ -1,4 +1,4 @@ -.TH "NPM\-FOLDERS" "5" "May 2016" "" "" +.TH "NPM\-FOLDERS" "5" "June 2016" "" "" .SH "NAME" \fBnpm-folders\fR \- Folder Structures Used by npm .SH DESCRIPTION diff --git a/deps/npm/man/man5/npm-global.5 b/deps/npm/man/man5/npm-global.5 index 20c2d64716322c..b94aeb863ecc5f 100644 --- a/deps/npm/man/man5/npm-global.5 +++ b/deps/npm/man/man5/npm-global.5 @@ -1,4 +1,4 @@ -.TH "NPM\-FOLDERS" "5" "May 2016" "" "" +.TH "NPM\-FOLDERS" "5" "June 2016" "" "" .SH "NAME" \fBnpm-folders\fR \- Folder Structures Used by npm .SH DESCRIPTION diff --git a/deps/npm/man/man5/npm-json.5 b/deps/npm/man/man5/npm-json.5 index 7cb23623c4a084..0d0f25b74103b3 100644 --- a/deps/npm/man/man5/npm-json.5 +++ b/deps/npm/man/man5/npm-json.5 @@ -1,4 +1,4 @@ -.TH "PACKAGE\.JSON" "5" "May 2016" "" "" +.TH "PACKAGE\.JSON" "5" "June 2016" "" "" .SH "NAME" \fBpackage.json\fR \- Specifics of npm's package\.json handling .SH DESCRIPTION @@ -881,9 +881,9 @@ npm will default some values based on package contents\. If there is a \fBserver\.js\fP file in the root of your package, then npm will default the \fBstart\fP command to \fBnode server\.js\fP\|\. .IP \(bu 2 -\fB"scripts":{"preinstall": "node\-gyp rebuild"}\fP -If there is a \fBbinding\.gyp\fP file in the root of your package, npm will -default the \fBpreinstall\fP command to compile using node\-gyp\. +\fB"scripts":{"install": "node\-gyp rebuild"}\fP +If there is a \fBbinding\.gyp\fP file in the root of your package and you have not defined an \fBinstall\fP or \fBpreinstall\fP script, npm will +default the \fBinstall\fP command to compile using node\-gyp\. .IP \(bu 2 \fB"contributors": [\.\.\.]\fP If there is an \fBAUTHORS\fP file in the root of your package, npm will diff --git a/deps/npm/man/man5/npmrc.5 b/deps/npm/man/man5/npmrc.5 index 8b5d2b2e34ccd3..f70ee7da749a55 100644 --- a/deps/npm/man/man5/npmrc.5 +++ b/deps/npm/man/man5/npmrc.5 @@ -1,4 +1,4 @@ -.TH "NPMRC" "5" "May 2016" "" "" +.TH "NPMRC" "5" "June 2016" "" "" .SH "NAME" \fBnpmrc\fR \- The npm config files .SH DESCRIPTION diff --git a/deps/npm/man/man5/package.json.5 b/deps/npm/man/man5/package.json.5 index 7cb23623c4a084..0d0f25b74103b3 100644 --- a/deps/npm/man/man5/package.json.5 +++ b/deps/npm/man/man5/package.json.5 @@ -1,4 +1,4 @@ -.TH "PACKAGE\.JSON" "5" "May 2016" "" "" +.TH "PACKAGE\.JSON" "5" "June 2016" "" "" .SH "NAME" \fBpackage.json\fR \- Specifics of npm's package\.json handling .SH DESCRIPTION @@ -881,9 +881,9 @@ npm will default some values based on package contents\. If there is a \fBserver\.js\fP file in the root of your package, then npm will default the \fBstart\fP command to \fBnode server\.js\fP\|\. .IP \(bu 2 -\fB"scripts":{"preinstall": "node\-gyp rebuild"}\fP -If there is a \fBbinding\.gyp\fP file in the root of your package, npm will -default the \fBpreinstall\fP command to compile using node\-gyp\. +\fB"scripts":{"install": "node\-gyp rebuild"}\fP +If there is a \fBbinding\.gyp\fP file in the root of your package and you have not defined an \fBinstall\fP or \fBpreinstall\fP script, npm will +default the \fBinstall\fP command to compile using node\-gyp\. .IP \(bu 2 \fB"contributors": [\.\.\.]\fP If there is an \fBAUTHORS\fP file in the root of your package, npm will diff --git a/deps/npm/man/man7/npm-coding-style.7 b/deps/npm/man/man7/npm-coding-style.7 index d15b0a4bac03e6..b1a928170d33fe 100644 --- a/deps/npm/man/man7/npm-coding-style.7 +++ b/deps/npm/man/man7/npm-coding-style.7 @@ -1,4 +1,4 @@ -.TH "NPM\-CODING\-STYLE" "7" "May 2016" "" "" +.TH "NPM\-CODING\-STYLE" "7" "June 2016" "" "" .SH "NAME" \fBnpm-coding-style\fR \- npm's "funny" coding style .SH DESCRIPTION diff --git a/deps/npm/man/man7/npm-config.7 b/deps/npm/man/man7/npm-config.7 index 001bd51c4bcec5..4801da7457cf8b 100644 --- a/deps/npm/man/man7/npm-config.7 +++ b/deps/npm/man/man7/npm-config.7 @@ -1,4 +1,4 @@ -.TH "NPM\-CONFIG" "7" "May 2016" "" "" +.TH "NPM\-CONFIG" "7" "June 2016" "" "" .SH "NAME" \fBnpm-config\fR \- More than you probably want to know about npm configuration .SH DESCRIPTION diff --git a/deps/npm/man/man7/npm-developers.7 b/deps/npm/man/man7/npm-developers.7 index 400522cb08af30..b6236379c6a802 100644 --- a/deps/npm/man/man7/npm-developers.7 +++ b/deps/npm/man/man7/npm-developers.7 @@ -1,4 +1,4 @@ -.TH "NPM\-DEVELOPERS" "7" "May 2016" "" "" +.TH "NPM\-DEVELOPERS" "7" "June 2016" "" "" .SH "NAME" \fBnpm-developers\fR \- Developer Guide .SH DESCRIPTION diff --git a/deps/npm/man/man7/npm-disputes.7 b/deps/npm/man/man7/npm-disputes.7 index db434aa6f9821b..4f6c315be015f6 100644 --- a/deps/npm/man/man7/npm-disputes.7 +++ b/deps/npm/man/man7/npm-disputes.7 @@ -1,4 +1,4 @@ -.TH "NPM\-DISPUTES" "7" "May 2016" "" "" +.TH "NPM\-DISPUTES" "7" "June 2016" "" "" .SH "NAME" \fBnpm-disputes\fR \- Handling Module Name Disputes .SH SYNOPSIS diff --git a/deps/npm/man/man7/npm-index.7 b/deps/npm/man/man7/npm-index.7 index 25460e29f30a5f..a74f8aa6d8c6e5 100644 --- a/deps/npm/man/man7/npm-index.7 +++ b/deps/npm/man/man7/npm-index.7 @@ -1,4 +1,4 @@ -.TH "NPM\-INDEX" "7" "May 2016" "" "" +.TH "NPM\-INDEX" "7" "June 2016" "" "" .SH "NAME" \fBnpm-index\fR \- Index of all npm documentation .SS npm help README diff --git a/deps/npm/man/man7/npm-orgs.7 b/deps/npm/man/man7/npm-orgs.7 index 0eb054f4d066e5..2961014fb88699 100644 --- a/deps/npm/man/man7/npm-orgs.7 +++ b/deps/npm/man/man7/npm-orgs.7 @@ -1,4 +1,4 @@ -.TH "NPM\-ORGS" "7" "May 2016" "" "" +.TH "NPM\-ORGS" "7" "June 2016" "" "" .SH "NAME" \fBnpm-orgs\fR \- Working with Teams & Orgs .SH DESCRIPTION diff --git a/deps/npm/man/man7/npm-registry.7 b/deps/npm/man/man7/npm-registry.7 index 1d07da46ac10df..743710179f6ed4 100644 --- a/deps/npm/man/man7/npm-registry.7 +++ b/deps/npm/man/man7/npm-registry.7 @@ -1,4 +1,4 @@ -.TH "NPM\-REGISTRY" "7" "May 2016" "" "" +.TH "NPM\-REGISTRY" "7" "June 2016" "" "" .SH "NAME" \fBnpm-registry\fR \- The JavaScript Package Registry .SH DESCRIPTION diff --git a/deps/npm/man/man7/npm-scope.7 b/deps/npm/man/man7/npm-scope.7 index 807e2ec4218207..c18eac6540f493 100644 --- a/deps/npm/man/man7/npm-scope.7 +++ b/deps/npm/man/man7/npm-scope.7 @@ -1,4 +1,4 @@ -.TH "NPM\-SCOPE" "7" "May 2016" "" "" +.TH "NPM\-SCOPE" "7" "June 2016" "" "" .SH "NAME" \fBnpm-scope\fR \- Scoped packages .SH DESCRIPTION diff --git a/deps/npm/man/man7/npm-scripts.7 b/deps/npm/man/man7/npm-scripts.7 index a360985c9a5999..641422c45811eb 100644 --- a/deps/npm/man/man7/npm-scripts.7 +++ b/deps/npm/man/man7/npm-scripts.7 @@ -1,4 +1,4 @@ -.TH "NPM\-SCRIPTS" "7" "May 2016" "" "" +.TH "NPM\-SCRIPTS" "7" "June 2016" "" "" .SH "NAME" \fBnpm-scripts\fR \- How npm handles the "scripts" field .SH DESCRIPTION @@ -48,9 +48,11 @@ stop and start scripts if no \fBrestart\fP script is provided\. .RE .P Additionally, arbitrary scripts can be executed by running \fBnpm -run\-script \fP\|\. \fIPre\fR and \fIpost\fR commands with matching +run\-script \fP\|\. \fIPre\fR and \fIpost\fR commands with matching names will be run for those as well (e\.g\. \fBpremyscript\fP, \fBmyscript\fP, -\fBpostmyscript\fP)\. +\fBpostmyscript\fP)\. Scripts from dependencies can be run with `npm explore +.P + \-\- npm run `\. .SH COMMON USES .P If you need to perform operations on your package before it is used, in a way @@ -92,7 +94,8 @@ If there is a \fBserver\.js\fP file in the root of your package, then npm will default the \fBstart\fP command to \fBnode server\.js\fP\|\. .IP \(bu 2 \fB"install": "node\-gyp rebuild"\fP: -If there is a \fBbindings\.gyp\fP file in the root of your package, npm will +If there is a \fBbinding\.gyp\fP file in the root of your package and you +haven't defined your own \fBinstall\fP or \fBpreinstall\fP scripts, npm will default the \fBinstall\fP command to compile using node\-gyp\. .RE diff --git a/deps/npm/man/man7/removing-npm.7 b/deps/npm/man/man7/removing-npm.7 index cbd6ae2346d94e..0df248fbc08320 100644 --- a/deps/npm/man/man7/removing-npm.7 +++ b/deps/npm/man/man7/removing-npm.7 @@ -1,4 +1,4 @@ -.TH "NPM\-REMOVAL" "1" "May 2016" "" "" +.TH "NPM\-REMOVAL" "1" "June 2016" "" "" .SH "NAME" \fBnpm-removal\fR \- Cleaning the Slate .SH SYNOPSIS diff --git a/deps/npm/man/man7/semver.7 b/deps/npm/man/man7/semver.7 index 84b72ecc740ab3..8705628acaa67d 100644 --- a/deps/npm/man/man7/semver.7 +++ b/deps/npm/man/man7/semver.7 @@ -1,4 +1,4 @@ -.TH "SEMVER" "7" "May 2016" "" "" +.TH "SEMVER" "7" "June 2016" "" "" .SH "NAME" \fBsemver\fR \- The semantic versioner for npm .SH Usage diff --git a/deps/npm/node_modules/abbrev/.npmignore b/deps/npm/node_modules/abbrev/.npmignore deleted file mode 100644 index 9d6cd2f025d4a6..00000000000000 --- a/deps/npm/node_modules/abbrev/.npmignore +++ /dev/null @@ -1,4 +0,0 @@ -.nyc_output -nyc_output -node_modules -coverage diff --git a/deps/npm/node_modules/abbrev/.travis.yml b/deps/npm/node_modules/abbrev/.travis.yml deleted file mode 100644 index 991d04b6e2272b..00000000000000 --- a/deps/npm/node_modules/abbrev/.travis.yml +++ /dev/null @@ -1,5 +0,0 @@ -language: node_js -node_js: - - '0.10' - - '0.12' - - 'iojs' diff --git a/deps/npm/node_modules/abbrev/CONTRIBUTING.md b/deps/npm/node_modules/abbrev/CONTRIBUTING.md deleted file mode 100644 index 2f302612f81630..00000000000000 --- a/deps/npm/node_modules/abbrev/CONTRIBUTING.md +++ /dev/null @@ -1,3 +0,0 @@ - To get started, sign the - Contributor License Agreement. diff --git a/deps/npm/node_modules/abbrev/package.json b/deps/npm/node_modules/abbrev/package.json index 9b71f630b71ae1..927d6f62d50262 100644 --- a/deps/npm/node_modules/abbrev/package.json +++ b/deps/npm/node_modules/abbrev/package.json @@ -1,6 +1,6 @@ { "name": "abbrev", - "version": "1.0.7", + "version": "1.0.9", "description": "Like ruby's abbrev module, but in js", "author": { "name": "Isaac Z. Schlueter", @@ -16,25 +16,28 @@ }, "license": "ISC", "devDependencies": { - "tap": "^1.2.0" + "tap": "^5.7.2" }, - "gitHead": "821d09ce7da33627f91bbd8ed631497ed6f760c2", + "files": [ + "abbrev.js" + ], + "gitHead": "c386cd9dbb1d8d7581718c54d4ba944cc9298d6f", "bugs": { "url": "https://github.com/isaacs/abbrev-js/issues" }, "homepage": "https://github.com/isaacs/abbrev-js#readme", - "_id": "abbrev@1.0.7", - "_shasum": "5b6035b2ee9d4fb5cf859f08a9be81b208491843", - "_from": "abbrev@>=1.0.7 <1.1.0", - "_npmVersion": "2.10.1", - "_nodeVersion": "2.0.1", + "_id": "abbrev@1.0.9", + "_shasum": "91b4792588a7738c25f35dd6f63752a2f8776135", + "_from": "abbrev@>=1.0.9 <1.1.0", + "_npmVersion": "3.9.1", + "_nodeVersion": "4.4.4", "_npmUser": { "name": "isaacs", - "email": "isaacs@npmjs.com" + "email": "i@izs.me" }, "dist": { - "shasum": "5b6035b2ee9d4fb5cf859f08a9be81b208491843", - "tarball": "http://registry.npmjs.org/abbrev/-/abbrev-1.0.7.tgz" + "shasum": "91b4792588a7738c25f35dd6f63752a2f8776135", + "tarball": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz" }, "maintainers": [ { @@ -42,6 +45,10 @@ "email": "i@izs.me" } ], + "_npmOperationalInternal": { + "host": "packages-16-east.internal.npmjs.com", + "tmp": "tmp/abbrev-1.0.9.tgz_1466016055839_0.7825860097073019" + }, "directories": {}, - "_resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.7.tgz" + "_resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz" } diff --git a/deps/npm/node_modules/abbrev/test.js b/deps/npm/node_modules/abbrev/test.js deleted file mode 100644 index eb30e421cb9836..00000000000000 --- a/deps/npm/node_modules/abbrev/test.js +++ /dev/null @@ -1,47 +0,0 @@ -var abbrev = require('./abbrev.js') -var assert = require("assert") -var util = require("util") - -console.log("TAP version 13") -var count = 0 - -function test (list, expect) { - count++ - var actual = abbrev(list) - assert.deepEqual(actual, expect, - "abbrev("+util.inspect(list)+") === " + util.inspect(expect) + "\n"+ - "actual: "+util.inspect(actual)) - actual = abbrev.apply(exports, list) - assert.deepEqual(abbrev.apply(exports, list), expect, - "abbrev("+list.map(JSON.stringify).join(",")+") === " + util.inspect(expect) + "\n"+ - "actual: "+util.inspect(actual)) - console.log('ok - ' + list.join(' ')) -} - -test([ "ruby", "ruby", "rules", "rules", "rules" ], -{ rub: 'ruby' -, ruby: 'ruby' -, rul: 'rules' -, rule: 'rules' -, rules: 'rules' -}) -test(["fool", "foom", "pool", "pope"], -{ fool: 'fool' -, foom: 'foom' -, poo: 'pool' -, pool: 'pool' -, pop: 'pope' -, pope: 'pope' -}) -test(["a", "ab", "abc", "abcd", "abcde", "acde"], -{ a: 'a' -, ab: 'ab' -, abc: 'abc' -, abcd: 'abcd' -, abcde: 'abcde' -, ac: 'acde' -, acd: 'acde' -, acde: 'acde' -}) - -console.log("1..%d", count) diff --git a/deps/npm/node_modules/fstream/.travis.yml b/deps/npm/node_modules/fstream/.travis.yml index a092c82b26fc41..9f5972ab5aa1cd 100644 --- a/deps/npm/node_modules/fstream/.travis.yml +++ b/deps/npm/node_modules/fstream/.travis.yml @@ -1,9 +1,9 @@ language: node_js node_js: - - iojs - - 0.12 - - 0.10 - - 0.8 + - "6" + - "4" + - "0.10" + - "0.12" before_install: - "npm config set spin false" - "npm install -g npm/npm" diff --git a/deps/npm/node_modules/fstream/lib/collect.js b/deps/npm/node_modules/fstream/lib/collect.js index 6245e6ce492d20..e5d4f35833476e 100644 --- a/deps/npm/node_modules/fstream/lib/collect.js +++ b/deps/npm/node_modules/fstream/lib/collect.js @@ -3,6 +3,8 @@ module.exports = collect function collect (stream) { if (stream._collected) return + if (stream._paused) return stream.on('resume', collect.bind(null, stream)) + stream._collected = true stream.pause() diff --git a/deps/npm/node_modules/fstream/package.json b/deps/npm/node_modules/fstream/package.json index 8c008195442823..9f5212a198d70b 100644 --- a/deps/npm/node_modules/fstream/package.json +++ b/deps/npm/node_modules/fstream/package.json @@ -6,10 +6,10 @@ }, "name": "fstream", "description": "Advanced file system stream things", - "version": "1.0.8", + "version": "1.0.10", "repository": { "type": "git", - "url": "git://github.com/isaacs/fstream.git" + "url": "git+https://github.com/npm/fstream.git" }, "main": "fstream.js", "engines": { @@ -31,12 +31,12 @@ "license": "ISC", "readme": "Like FS streams, but with stat on them, and supporting directories and\nsymbolic links, as well as normal files. Also, you can use this to set\nthe stats on a file, even if you don't change its contents, or to create\na symlink, etc.\n\nSo, for example, you can \"write\" a directory, and it'll call `mkdir`. You\ncan specify a uid and gid, and it'll call `chown`. You can specify a\n`mtime` and `atime`, and it'll call `utimes`. You can call it a symlink\nand provide a `linkpath` and it'll call `symlink`.\n\nNote that it won't automatically resolve symbolic links. So, if you\ncall `fstream.Reader('/some/symlink')` then you'll get an object\nthat stats and then ends immediately (since it has no data). To follow\nsymbolic links, do this: `fstream.Reader({path:'/some/symlink', follow:\ntrue })`.\n\nThere are various checks to make sure that the bytes emitted are the\nsame as the intended size, if the size is set.\n\n## Examples\n\n```javascript\nfstream\n .Writer({ path: \"path/to/file\"\n , mode: 0755\n , size: 6\n })\n .write(\"hello\\n\")\n .end()\n```\n\nThis will create the directories if they're missing, and then write\n`hello\\n` into the file, chmod it to 0755, and assert that 6 bytes have\nbeen written when it's done.\n\n```javascript\nfstream\n .Writer({ path: \"path/to/file\"\n , mode: 0755\n , size: 6\n , flags: \"a\"\n })\n .write(\"hello\\n\")\n .end()\n```\n\nYou can pass flags in, if you want to append to a file.\n\n```javascript\nfstream\n .Writer({ path: \"path/to/symlink\"\n , linkpath: \"./file\"\n , SymbolicLink: true\n , mode: \"0755\" // octal strings supported\n })\n .end()\n```\n\nIf isSymbolicLink is a function, it'll be called, and if it returns\ntrue, then it'll treat it as a symlink. If it's not a function, then\nany truish value will make a symlink, or you can set `type:\n'SymbolicLink'`, which does the same thing.\n\nNote that the linkpath is relative to the symbolic link location, not\nthe parent dir or cwd.\n\n```javascript\nfstream\n .Reader(\"path/to/dir\")\n .pipe(fstream.Writer(\"path/to/other/dir\"))\n```\n\nThis will do like `cp -Rp path/to/dir path/to/other/dir`. If the other\ndir exists and isn't a directory, then it'll emit an error. It'll also\nset the uid, gid, mode, etc. to be identical. In this way, it's more\nlike `rsync -a` than simply a copy.\n", "readmeFilename": "README.md", - "gitHead": "d9f81146c50e687f1df04c1a0e7e4c173eb3dae2", + "gitHead": "24fabdec32e334dd3b130d77b38c010e3119b102", "bugs": { - "url": "https://github.com/isaacs/fstream/issues" + "url": "https://github.com/npm/fstream/issues" }, - "homepage": "https://github.com/isaacs/fstream#readme", - "_id": "fstream@1.0.8", - "_shasum": "7e8d7a73abb3647ef36e4b8a15ca801dba03d038", - "_from": "fstream@1.0.8" + "homepage": "https://github.com/npm/fstream#readme", + "_id": "fstream@1.0.10", + "_shasum": "604e8a92fe26ffd9f6fae30399d4984e1ab22822", + "_from": "fstream@>=1.0.10 <1.1.0" } diff --git a/deps/npm/node_modules/glob/README.md b/deps/npm/node_modules/glob/README.md deleted file mode 100644 index 9dd9384fa143c3..00000000000000 --- a/deps/npm/node_modules/glob/README.md +++ /dev/null @@ -1,365 +0,0 @@ -# Glob - -Match files using the patterns the shell uses, like stars and stuff. - -[![Build Status](https://travis-ci.org/isaacs/node-glob.svg?branch=master)](https://travis-ci.org/isaacs/node-glob/) [![Build Status](https://ci.appveyor.com/api/projects/status/kd7f3yftf7unxlsx?svg=true)](https://ci.appveyor.com/project/isaacs/node-glob) [![Coverage Status](https://coveralls.io/repos/isaacs/node-glob/badge.svg?branch=master&service=github)](https://coveralls.io/github/isaacs/node-glob?branch=master) - -This is a glob implementation in JavaScript. It uses the `minimatch` -library to do its matching. - -![](oh-my-glob.gif) - -## Usage - -Install with npm - -``` -npm i glob -``` - -```javascript -var glob = require("glob") - -// options is optional -glob("**/*.js", options, function (er, files) { - // files is an array of filenames. - // If the `nonull` option is set, and nothing - // was found, then files is ["**/*.js"] - // er is an error object or null. -}) -``` - -## Glob Primer - -"Globs" are the patterns you type when you do stuff like `ls *.js` on -the command line, or put `build/*` in a `.gitignore` file. - -Before parsing the path part patterns, braced sections are expanded -into a set. Braced sections start with `{` and end with `}`, with any -number of comma-delimited sections within. Braced sections may contain -slash characters, so `a{/b/c,bcd}` would expand into `a/b/c` and `abcd`. - -The following characters have special magic meaning when used in a -path portion: - -* `*` Matches 0 or more characters in a single path portion -* `?` Matches 1 character -* `[...]` Matches a range of characters, similar to a RegExp range. - If the first character of the range is `!` or `^` then it matches - any character not in the range. -* `!(pattern|pattern|pattern)` Matches anything that does not match - any of the patterns provided. -* `?(pattern|pattern|pattern)` Matches zero or one occurrence of the - patterns provided. -* `+(pattern|pattern|pattern)` Matches one or more occurrences of the - patterns provided. -* `*(a|b|c)` Matches zero or more occurrences of the patterns provided -* `@(pattern|pat*|pat?erN)` Matches exactly one of the patterns - provided -* `**` If a "globstar" is alone in a path portion, then it matches - zero or more directories and subdirectories searching for matches. - It does not crawl symlinked directories. - -### Dots - -If a file or directory path portion has a `.` as the first character, -then it will not match any glob pattern unless that pattern's -corresponding path part also has a `.` as its first character. - -For example, the pattern `a/.*/c` would match the file at `a/.b/c`. -However the pattern `a/*/c` would not, because `*` does not start with -a dot character. - -You can make glob treat dots as normal characters by setting -`dot:true` in the options. - -### Basename Matching - -If you set `matchBase:true` in the options, and the pattern has no -slashes in it, then it will seek for any file anywhere in the tree -with a matching basename. For example, `*.js` would match -`test/simple/basic.js`. - -### Empty Sets - -If no matching files are found, then an empty array is returned. This -differs from the shell, where the pattern itself is returned. For -example: - - $ echo a*s*d*f - a*s*d*f - -To get the bash-style behavior, set the `nonull:true` in the options. - -### See Also: - -* `man sh` -* `man bash` (Search for "Pattern Matching") -* `man 3 fnmatch` -* `man 5 gitignore` -* [minimatch documentation](https://github.com/isaacs/minimatch) - -## glob.hasMagic(pattern, [options]) - -Returns `true` if there are any special characters in the pattern, and -`false` otherwise. - -Note that the options affect the results. If `noext:true` is set in -the options object, then `+(a|b)` will not be considered a magic -pattern. If the pattern has a brace expansion, like `a/{b/c,x/y}` -then that is considered magical, unless `nobrace:true` is set in the -options. - -## glob(pattern, [options], cb) - -* `pattern` `{String}` Pattern to be matched -* `options` `{Object}` -* `cb` `{Function}` - * `err` `{Error | null}` - * `matches` `{Array}` filenames found matching the pattern - -Perform an asynchronous glob search. - -## glob.sync(pattern, [options]) - -* `pattern` `{String}` Pattern to be matched -* `options` `{Object}` -* return: `{Array}` filenames found matching the pattern - -Perform a synchronous glob search. - -## Class: glob.Glob - -Create a Glob object by instantiating the `glob.Glob` class. - -```javascript -var Glob = require("glob").Glob -var mg = new Glob(pattern, options, cb) -``` - -It's an EventEmitter, and starts walking the filesystem to find matches -immediately. - -### new glob.Glob(pattern, [options], [cb]) - -* `pattern` `{String}` pattern to search for -* `options` `{Object}` -* `cb` `{Function}` Called when an error occurs, or matches are found - * `err` `{Error | null}` - * `matches` `{Array}` filenames found matching the pattern - -Note that if the `sync` flag is set in the options, then matches will -be immediately available on the `g.found` member. - -### Properties - -* `minimatch` The minimatch object that the glob uses. -* `options` The options object passed in. -* `aborted` Boolean which is set to true when calling `abort()`. There - is no way at this time to continue a glob search after aborting, but - you can re-use the statCache to avoid having to duplicate syscalls. -* `cache` Convenience object. Each field has the following possible - values: - * `false` - Path does not exist - * `true` - Path exists - * `'FILE'` - Path exists, and is not a directory - * `'DIR'` - Path exists, and is a directory - * `[file, entries, ...]` - Path exists, is a directory, and the - array value is the results of `fs.readdir` -* `statCache` Cache of `fs.stat` results, to prevent statting the same - path multiple times. -* `symlinks` A record of which paths are symbolic links, which is - relevant in resolving `**` patterns. -* `realpathCache` An optional object which is passed to `fs.realpath` - to minimize unnecessary syscalls. It is stored on the instantiated - Glob object, and may be re-used. - -### Events - -* `end` When the matching is finished, this is emitted with all the - matches found. If the `nonull` option is set, and no match was found, - then the `matches` list contains the original pattern. The matches - are sorted, unless the `nosort` flag is set. -* `match` Every time a match is found, this is emitted with the specific - thing that matched. It is not deduplicated or resolved to a realpath. -* `error` Emitted when an unexpected error is encountered, or whenever - any fs error occurs if `options.strict` is set. -* `abort` When `abort()` is called, this event is raised. - -### Methods - -* `pause` Temporarily stop the search -* `resume` Resume the search -* `abort` Stop the search forever - -### Options - -All the options that can be passed to Minimatch can also be passed to -Glob to change pattern matching behavior. Also, some have been added, -or have glob-specific ramifications. - -All options are false by default, unless otherwise noted. - -All options are added to the Glob object, as well. - -If you are running many `glob` operations, you can pass a Glob object -as the `options` argument to a subsequent operation to shortcut some -`stat` and `readdir` calls. At the very least, you may pass in shared -`symlinks`, `statCache`, `realpathCache`, and `cache` options, so that -parallel glob operations will be sped up by sharing information about -the filesystem. - -* `cwd` The current working directory in which to search. Defaults - to `process.cwd()`. -* `root` The place where patterns starting with `/` will be mounted - onto. Defaults to `path.resolve(options.cwd, "/")` (`/` on Unix - systems, and `C:\` or some such on Windows.) -* `dot` Include `.dot` files in normal matches and `globstar` matches. - Note that an explicit dot in a portion of the pattern will always - match dot files. -* `nomount` By default, a pattern starting with a forward-slash will be - "mounted" onto the root setting, so that a valid filesystem path is - returned. Set this flag to disable that behavior. -* `mark` Add a `/` character to directory matches. Note that this - requires additional stat calls. -* `nosort` Don't sort the results. -* `stat` Set to true to stat *all* results. This reduces performance - somewhat, and is completely unnecessary, unless `readdir` is presumed - to be an untrustworthy indicator of file existence. -* `silent` When an unusual error is encountered when attempting to - read a directory, a warning will be printed to stderr. Set the - `silent` option to true to suppress these warnings. -* `strict` When an unusual error is encountered when attempting to - read a directory, the process will just continue on in search of - other matches. Set the `strict` option to raise an error in these - cases. -* `cache` See `cache` property above. Pass in a previously generated - cache object to save some fs calls. -* `statCache` A cache of results of filesystem information, to prevent - unnecessary stat calls. While it should not normally be necessary - to set this, you may pass the statCache from one glob() call to the - options object of another, if you know that the filesystem will not - change between calls. (See "Race Conditions" below.) -* `symlinks` A cache of known symbolic links. You may pass in a - previously generated `symlinks` object to save `lstat` calls when - resolving `**` matches. -* `sync` DEPRECATED: use `glob.sync(pattern, opts)` instead. -* `nounique` In some cases, brace-expanded patterns can result in the - same file showing up multiple times in the result set. By default, - this implementation prevents duplicates in the result set. Set this - flag to disable that behavior. -* `nonull` Set to never return an empty set, instead returning a set - containing the pattern itself. This is the default in glob(3). -* `debug` Set to enable debug logging in minimatch and glob. -* `nobrace` Do not expand `{a,b}` and `{1..3}` brace sets. -* `noglobstar` Do not match `**` against multiple filenames. (Ie, - treat it as a normal `*` instead.) -* `noext` Do not match `+(a|b)` "extglob" patterns. -* `nocase` Perform a case-insensitive match. Note: on - case-insensitive filesystems, non-magic patterns will match by - default, since `stat` and `readdir` will not raise errors. -* `matchBase` Perform a basename-only match if the pattern does not - contain any slash characters. That is, `*.js` would be treated as - equivalent to `**/*.js`, matching all js files in all directories. -* `nodir` Do not match directories, only files. (Note: to match - *only* directories, simply put a `/` at the end of the pattern.) -* `ignore` Add a pattern or an array of glob patterns to exclude matches. - Note: `ignore` patterns are *always* in `dot:true` mode, regardless - of any other settings. -* `follow` Follow symlinked directories when expanding `**` patterns. - Note that this can result in a lot of duplicate references in the - presence of cyclic links. -* `realpath` Set to true to call `fs.realpath` on all of the results. - In the case of a symlink that cannot be resolved, the full absolute - path to the matched entry is returned (though it will usually be a - broken symlink) - -## Comparisons to other fnmatch/glob implementations - -While strict compliance with the existing standards is a worthwhile -goal, some discrepancies exist between node-glob and other -implementations, and are intentional. - -The double-star character `**` is supported by default, unless the -`noglobstar` flag is set. This is supported in the manner of bsdglob -and bash 4.3, where `**` only has special significance if it is the only -thing in a path part. That is, `a/**/b` will match `a/x/y/b`, but -`a/**b` will not. - -Note that symlinked directories are not crawled as part of a `**`, -though their contents may match against subsequent portions of the -pattern. This prevents infinite loops and duplicates and the like. - -If an escaped pattern has no matches, and the `nonull` flag is set, -then glob returns the pattern as-provided, rather than -interpreting the character escapes. For example, -`glob.match([], "\\*a\\?")` will return `"\\*a\\?"` rather than -`"*a?"`. This is akin to setting the `nullglob` option in bash, except -that it does not resolve escaped pattern characters. - -If brace expansion is not disabled, then it is performed before any -other interpretation of the glob pattern. Thus, a pattern like -`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded -**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are -checked for validity. Since those two are valid, matching proceeds. - -### Comments and Negation - -Previously, this module let you mark a pattern as a "comment" if it -started with a `#` character, or a "negated" pattern if it started -with a `!` character. - -These options were deprecated in version 5, and removed in version 6. - -To specify things that should not match, use the `ignore` option. - -## Windows - -**Please only use forward-slashes in glob expressions.** - -Though windows uses either `/` or `\` as its path separator, only `/` -characters are used by this glob implementation. You must use -forward-slashes **only** in glob expressions. Back-slashes will always -be interpreted as escape characters, not path separators. - -Results from absolute patterns such as `/foo/*` are mounted onto the -root setting using `path.join`. On windows, this will by default result -in `/foo/*` matching `C:\foo\bar.txt`. - -## Race Conditions - -Glob searching, by its very nature, is susceptible to race conditions, -since it relies on directory walking and such. - -As a result, it is possible that a file that exists when glob looks for -it may have been deleted or modified by the time it returns the result. - -As part of its internal implementation, this program caches all stat -and readdir calls that it makes, in order to cut down on system -overhead. However, this also makes it even more susceptible to races, -especially if the cache or statCache objects are reused between glob -calls. - -Users are thus advised not to use a glob result as a guarantee of -filesystem state in the face of rapid changes. For the vast majority -of operations, this is never a problem. - -## Contributing - -Any change to behavior (including bugfixes) must come with a test. - -Patches that fail tests or reduce performance will be rejected. - -``` -# to run tests -npm test - -# to re-generate test fixtures -npm run test-regen - -# to benchmark against bash/zsh -npm run bench - -# to profile javascript -npm run prof -``` diff --git a/deps/npm/node_modules/glob/glob.js b/deps/npm/node_modules/glob/glob.js index 4dba04adec43c4..02d15b755dd84e 100644 --- a/deps/npm/node_modules/glob/glob.js +++ b/deps/npm/node_modules/glob/glob.js @@ -41,6 +41,7 @@ module.exports = glob var fs = require('fs') +var rp = require('fs.realpath') var minimatch = require('minimatch') var Minimatch = minimatch.Minimatch var inherits = require('inherits') @@ -232,7 +233,7 @@ Glob.prototype._realpathSet = function (index, cb) { // one or more of the links in the realpath couldn't be // resolved. just return the abs value in that case. p = self._makeAbs(p) - fs.realpath(p, self.realpathCache, function (er, real) { + rp.realpath(p, self.realpathCache, function (er, real) { if (!er) set[real] = true else if (er.syscall === 'stat') diff --git a/deps/npm/node_modules/glob/node_modules/fs.realpath/LICENSE b/deps/npm/node_modules/glob/node_modules/fs.realpath/LICENSE new file mode 100644 index 00000000000000..5bd884c252ac49 --- /dev/null +++ b/deps/npm/node_modules/glob/node_modules/fs.realpath/LICENSE @@ -0,0 +1,43 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +---- + +This library bundles a version of the `fs.realpath` and `fs.realpathSync` +methods from Node.js v0.10 under the terms of the Node.js MIT license. + +Node's license follows, also included at the header of `old.js` which contains +the licensed code: + + Copyright Joyent, Inc. and other Node contributors. + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. diff --git a/deps/npm/node_modules/glob/node_modules/fs.realpath/README.md b/deps/npm/node_modules/glob/node_modules/fs.realpath/README.md new file mode 100644 index 00000000000000..a42ceac62663ac --- /dev/null +++ b/deps/npm/node_modules/glob/node_modules/fs.realpath/README.md @@ -0,0 +1,33 @@ +# fs.realpath + +A backwards-compatible fs.realpath for Node v6 and above + +In Node v6, the JavaScript implementation of fs.realpath was replaced +with a faster (but less resilient) native implementation. That raises +new and platform-specific errors and cannot handle long or excessively +symlink-looping paths. + +This module handles those cases by detecting the new errors and +falling back to the JavaScript implementation. On versions of Node +prior to v6, it has no effect. + +## USAGE + +```js +var rp = require('fs.realpath') + +// async version +rp.realpath(someLongAndLoopingPath, function (er, real) { + // the ELOOP was handled, but it was a bit slower +}) + +// sync version +var real = rp.realpathSync(someLongAndLoopingPath) + +// monkeypatch at your own risk! +// This replaces the fs.realpath/fs.realpathSync builtins +rp.monkeypatch() + +// un-do the monkeypatching +rp.unmonkeypatch() +``` diff --git a/deps/npm/node_modules/glob/node_modules/fs.realpath/index.js b/deps/npm/node_modules/glob/node_modules/fs.realpath/index.js new file mode 100644 index 00000000000000..b09c7c7e6364da --- /dev/null +++ b/deps/npm/node_modules/glob/node_modules/fs.realpath/index.js @@ -0,0 +1,66 @@ +module.exports = realpath +realpath.realpath = realpath +realpath.sync = realpathSync +realpath.realpathSync = realpathSync +realpath.monkeypatch = monkeypatch +realpath.unmonkeypatch = unmonkeypatch + +var fs = require('fs') +var origRealpath = fs.realpath +var origRealpathSync = fs.realpathSync + +var version = process.version +var ok = /^v[0-5]\./.test(version) +var old = require('./old.js') + +function newError (er) { + return er && er.syscall === 'realpath' && ( + er.code === 'ELOOP' || + er.code === 'ENOMEM' || + er.code === 'ENAMETOOLONG' + ) +} + +function realpath (p, cache, cb) { + if (ok) { + return origRealpath(p, cache, cb) + } + + if (typeof cache === 'function') { + cb = cache + cache = null + } + origRealpath(p, cache, function (er, result) { + if (newError(er)) { + old.realpath(p, cache, cb) + } else { + cb(er, result) + } + }) +} + +function realpathSync (p, cache) { + if (ok) { + return origRealpathSync(p, cache) + } + + try { + return origRealpathSync(p, cache) + } catch (er) { + if (newError(er)) { + return old.realpathSync(p, cache) + } else { + throw er + } + } +} + +function monkeypatch () { + fs.realpath = realpath + fs.realpathSync = realpathSync +} + +function unmonkeypatch () { + fs.realpath = origRealpath + fs.realpathSync = origRealpathSync +} diff --git a/deps/npm/node_modules/glob/node_modules/fs.realpath/old.js b/deps/npm/node_modules/glob/node_modules/fs.realpath/old.js new file mode 100644 index 00000000000000..b40305e73fd583 --- /dev/null +++ b/deps/npm/node_modules/glob/node_modules/fs.realpath/old.js @@ -0,0 +1,303 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var pathModule = require('path'); +var isWindows = process.platform === 'win32'; +var fs = require('fs'); + +// JavaScript implementation of realpath, ported from node pre-v6 + +var DEBUG = process.env.NODE_DEBUG && /fs/.test(process.env.NODE_DEBUG); + +function rethrow() { + // Only enable in debug mode. A backtrace uses ~1000 bytes of heap space and + // is fairly slow to generate. + var callback; + if (DEBUG) { + var backtrace = new Error; + callback = debugCallback; + } else + callback = missingCallback; + + return callback; + + function debugCallback(err) { + if (err) { + backtrace.message = err.message; + err = backtrace; + missingCallback(err); + } + } + + function missingCallback(err) { + if (err) { + if (process.throwDeprecation) + throw err; // Forgot a callback but don't know where? Use NODE_DEBUG=fs + else if (!process.noDeprecation) { + var msg = 'fs: missing callback ' + (err.stack || err.message); + if (process.traceDeprecation) + console.trace(msg); + else + console.error(msg); + } + } + } +} + +function maybeCallback(cb) { + return typeof cb === 'function' ? cb : rethrow(); +} + +var normalize = pathModule.normalize; + +// Regexp that finds the next partion of a (partial) path +// result is [base_with_slash, base], e.g. ['somedir/', 'somedir'] +if (isWindows) { + var nextPartRe = /(.*?)(?:[\/\\]+|$)/g; +} else { + var nextPartRe = /(.*?)(?:[\/]+|$)/g; +} + +// Regex to find the device root, including trailing slash. E.g. 'c:\\'. +if (isWindows) { + var splitRootRe = /^(?:[a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?[\\\/]*/; +} else { + var splitRootRe = /^[\/]*/; +} + +exports.realpathSync = function realpathSync(p, cache) { + // make p is absolute + p = pathModule.resolve(p); + + if (cache && Object.prototype.hasOwnProperty.call(cache, p)) { + return cache[p]; + } + + var original = p, + seenLinks = {}, + knownHard = {}; + + // current character position in p + var pos; + // the partial path so far, including a trailing slash if any + var current; + // the partial path without a trailing slash (except when pointing at a root) + var base; + // the partial path scanned in the previous round, with slash + var previous; + + start(); + + function start() { + // Skip over roots + var m = splitRootRe.exec(p); + pos = m[0].length; + current = m[0]; + base = m[0]; + previous = ''; + + // On windows, check that the root exists. On unix there is no need. + if (isWindows && !knownHard[base]) { + fs.lstatSync(base); + knownHard[base] = true; + } + } + + // walk down the path, swapping out linked pathparts for their real + // values + // NB: p.length changes. + while (pos < p.length) { + // find the next part + nextPartRe.lastIndex = pos; + var result = nextPartRe.exec(p); + previous = current; + current += result[0]; + base = previous + result[1]; + pos = nextPartRe.lastIndex; + + // continue if not a symlink + if (knownHard[base] || (cache && cache[base] === base)) { + continue; + } + + var resolvedLink; + if (cache && Object.prototype.hasOwnProperty.call(cache, base)) { + // some known symbolic link. no need to stat again. + resolvedLink = cache[base]; + } else { + var stat = fs.lstatSync(base); + if (!stat.isSymbolicLink()) { + knownHard[base] = true; + if (cache) cache[base] = base; + continue; + } + + // read the link if it wasn't read before + // dev/ino always return 0 on windows, so skip the check. + var linkTarget = null; + if (!isWindows) { + var id = stat.dev.toString(32) + ':' + stat.ino.toString(32); + if (seenLinks.hasOwnProperty(id)) { + linkTarget = seenLinks[id]; + } + } + if (linkTarget === null) { + fs.statSync(base); + linkTarget = fs.readlinkSync(base); + } + resolvedLink = pathModule.resolve(previous, linkTarget); + // track this, if given a cache. + if (cache) cache[base] = resolvedLink; + if (!isWindows) seenLinks[id] = linkTarget; + } + + // resolve the link, then start over + p = pathModule.resolve(resolvedLink, p.slice(pos)); + start(); + } + + if (cache) cache[original] = p; + + return p; +}; + + +exports.realpath = function realpath(p, cache, cb) { + if (typeof cb !== 'function') { + cb = maybeCallback(cache); + cache = null; + } + + // make p is absolute + p = pathModule.resolve(p); + + if (cache && Object.prototype.hasOwnProperty.call(cache, p)) { + return process.nextTick(cb.bind(null, null, cache[p])); + } + + var original = p, + seenLinks = {}, + knownHard = {}; + + // current character position in p + var pos; + // the partial path so far, including a trailing slash if any + var current; + // the partial path without a trailing slash (except when pointing at a root) + var base; + // the partial path scanned in the previous round, with slash + var previous; + + start(); + + function start() { + // Skip over roots + var m = splitRootRe.exec(p); + pos = m[0].length; + current = m[0]; + base = m[0]; + previous = ''; + + // On windows, check that the root exists. On unix there is no need. + if (isWindows && !knownHard[base]) { + fs.lstat(base, function(err) { + if (err) return cb(err); + knownHard[base] = true; + LOOP(); + }); + } else { + process.nextTick(LOOP); + } + } + + // walk down the path, swapping out linked pathparts for their real + // values + function LOOP() { + // stop if scanned past end of path + if (pos >= p.length) { + if (cache) cache[original] = p; + return cb(null, p); + } + + // find the next part + nextPartRe.lastIndex = pos; + var result = nextPartRe.exec(p); + previous = current; + current += result[0]; + base = previous + result[1]; + pos = nextPartRe.lastIndex; + + // continue if not a symlink + if (knownHard[base] || (cache && cache[base] === base)) { + return process.nextTick(LOOP); + } + + if (cache && Object.prototype.hasOwnProperty.call(cache, base)) { + // known symbolic link. no need to stat again. + return gotResolvedLink(cache[base]); + } + + return fs.lstat(base, gotStat); + } + + function gotStat(err, stat) { + if (err) return cb(err); + + // if not a symlink, skip to the next path part + if (!stat.isSymbolicLink()) { + knownHard[base] = true; + if (cache) cache[base] = base; + return process.nextTick(LOOP); + } + + // stat & read the link if not read before + // call gotTarget as soon as the link target is known + // dev/ino always return 0 on windows, so skip the check. + if (!isWindows) { + var id = stat.dev.toString(32) + ':' + stat.ino.toString(32); + if (seenLinks.hasOwnProperty(id)) { + return gotTarget(null, seenLinks[id], base); + } + } + fs.stat(base, function(err) { + if (err) return cb(err); + + fs.readlink(base, function(err, target) { + if (!isWindows) seenLinks[id] = target; + gotTarget(err, target); + }); + }); + } + + function gotTarget(err, target, base) { + if (err) return cb(err); + + var resolvedLink = pathModule.resolve(previous, target); + if (cache) cache[base] = resolvedLink; + gotResolvedLink(resolvedLink); + } + + function gotResolvedLink(resolvedLink) { + // resolve the link, then start over + p = pathModule.resolve(resolvedLink, p.slice(pos)); + start(); + } +}; diff --git a/deps/npm/node_modules/glob/node_modules/fs.realpath/package.json b/deps/npm/node_modules/glob/node_modules/fs.realpath/package.json new file mode 100644 index 00000000000000..55b5aa84f39881 --- /dev/null +++ b/deps/npm/node_modules/glob/node_modules/fs.realpath/package.json @@ -0,0 +1,60 @@ +{ + "name": "fs.realpath", + "version": "1.0.0", + "description": "Use node's fs.realpath, but fall back to the JS implementation if the native one fails", + "main": "index.js", + "dependencies": {}, + "devDependencies": {}, + "scripts": { + "test": "tap test/*.js --cov" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/isaacs/fs.realpath.git" + }, + "keywords": [ + "realpath", + "fs", + "polyfill" + ], + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me/" + }, + "license": "ISC", + "files": [ + "old.js", + "index.js" + ], + "gitHead": "03e7c884431fe185dfebbc9b771aeca339c1807a", + "bugs": { + "url": "https://github.com/isaacs/fs.realpath/issues" + }, + "homepage": "https://github.com/isaacs/fs.realpath#readme", + "_id": "fs.realpath@1.0.0", + "_shasum": "1504ad2523158caa40db4a2787cb01411994ea4f", + "_from": "fs.realpath@>=1.0.0 <2.0.0", + "_npmVersion": "3.9.1", + "_nodeVersion": "4.4.4", + "_npmUser": { + "name": "isaacs", + "email": "i@izs.me" + }, + "dist": { + "shasum": "1504ad2523158caa40db4a2787cb01411994ea4f", + "tarball": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" + }, + "maintainers": [ + { + "name": "isaacs", + "email": "i@izs.me" + } + ], + "_npmOperationalInternal": { + "host": "packages-16-east.internal.npmjs.com", + "tmp": "tmp/fs.realpath-1.0.0.tgz_1466015941059_0.3332864767871797" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" +} diff --git a/deps/npm/node_modules/glob/node_modules/path-is-absolute/package.json b/deps/npm/node_modules/glob/node_modules/path-is-absolute/package.json index 39372636f3fb4f..8f41adea4c1569 100644 --- a/deps/npm/node_modules/glob/node_modules/path-is-absolute/package.json +++ b/deps/npm/node_modules/glob/node_modules/path-is-absolute/package.json @@ -62,7 +62,7 @@ ], "dist": { "shasum": "263dada66ab3f2fb10bf7f9d24dd8f3e570ef912", - "tarball": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz" + "tarball": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz" }, "directories": {}, "_resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz", diff --git a/deps/npm/node_modules/glob/package.json b/deps/npm/node_modules/glob/package.json index 4d5d7f791d6eab..d8c68bca383fc8 100644 --- a/deps/npm/node_modules/glob/package.json +++ b/deps/npm/node_modules/glob/package.json @@ -6,7 +6,7 @@ }, "name": "glob", "description": "a little globber", - "version": "7.0.3", + "version": "7.0.4", "repository": { "type": "git", "url": "git://github.com/isaacs/node-glob.git" @@ -21,6 +21,7 @@ "node": "*" }, "dependencies": { + "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "2 || 3", @@ -43,23 +44,23 @@ "benchclean": "node benchclean.js" }, "license": "ISC", - "gitHead": "2fc2278ab857c7df117213a2fb431de090be6353", + "gitHead": "3f883c43fec4f8046cbea9497add3b8ba4ef0a37", "bugs": { "url": "https://github.com/isaacs/node-glob/issues" }, "homepage": "https://github.com/isaacs/node-glob#readme", - "_id": "glob@7.0.3", - "_shasum": "0aa235931a4a96ac13d60ffac2fb877bd6ed4f58", - "_from": "glob@7.0.3", - "_npmVersion": "3.7.3", - "_nodeVersion": "5.6.0", + "_id": "glob@7.0.4", + "_shasum": "3b44afa0943bdc31b2037b934791e2e084bcb7f6", + "_from": "glob@>=7.0.4 <7.1.0", + "_npmVersion": "3.9.3", + "_nodeVersion": "6.2.1", "_npmUser": { "name": "isaacs", "email": "i@izs.me" }, "dist": { - "shasum": "0aa235931a4a96ac13d60ffac2fb877bd6ed4f58", - "tarball": "http://registry.npmjs.org/glob/-/glob-7.0.3.tgz" + "shasum": "3b44afa0943bdc31b2037b934791e2e084bcb7f6", + "tarball": "https://registry.npmjs.org/glob/-/glob-7.0.4.tgz" }, "maintainers": [ { @@ -69,8 +70,8 @@ ], "_npmOperationalInternal": { "host": "packages-12-west.internal.npmjs.com", - "tmp": "tmp/glob-7.0.3.tgz_1457166529288_0.7840580905321985" + "tmp": "tmp/glob-7.0.4.tgz_1466098181857_0.6043217403348535" }, "directories": {}, - "_resolved": "https://registry.npmjs.org/glob/-/glob-7.0.3.tgz" + "_resolved": "https://registry.npmjs.org/glob/-/glob-7.0.4.tgz" } diff --git a/deps/npm/node_modules/glob/sync.js b/deps/npm/node_modules/glob/sync.js index 301577ab5f228f..bba2dc6a0c14e1 100644 --- a/deps/npm/node_modules/glob/sync.js +++ b/deps/npm/node_modules/glob/sync.js @@ -2,6 +2,7 @@ module.exports = globSync globSync.GlobSync = GlobSync var fs = require('fs') +var rp = require('fs.realpath') var minimatch = require('minimatch') var Minimatch = minimatch.Minimatch var Glob = require('./glob.js').Glob @@ -57,7 +58,7 @@ GlobSync.prototype._finish = function () { for (var p in matchset) { try { p = self._makeAbs(p) - var real = fs.realpathSync(p, self.realpathCache) + var real = rp.realpathSync(p, self.realpathCache) set[real] = true } catch (er) { if (er.syscall === 'stat') diff --git a/deps/npm/node_modules/inflight/package.json b/deps/npm/node_modules/inflight/package.json index e0b63729cc6dc8..f73955183253f2 100644 --- a/deps/npm/node_modules/inflight/package.json +++ b/deps/npm/node_modules/inflight/package.json @@ -1,21 +1,24 @@ { "name": "inflight", - "version": "1.0.4", + "version": "1.0.5", "description": "Add callbacks to requests in flight to avoid async duplication", "main": "inflight.js", + "files": [ + "inflight.js" + ], "dependencies": { "once": "^1.3.0", "wrappy": "1" }, "devDependencies": { - "tap": "^0.4.10" + "tap": "^1.2.0" }, "scripts": { "test": "tap test.js" }, "repository": { "type": "git", - "url": "git://github.com/isaacs/inflight" + "url": "git+https://github.com/npm/inflight.git" }, "author": { "name": "Isaac Z. Schlueter", @@ -27,10 +30,43 @@ }, "homepage": "https://github.com/isaacs/inflight", "license": "ISC", - "readme": "# inflight\n\nAdd callbacks to requests in flight to avoid async duplication\n\n## USAGE\n\n```javascript\nvar inflight = require('inflight')\n\n// some request that does some stuff\nfunction req(key, callback) {\n // key is any random string. like a url or filename or whatever.\n //\n // will return either a falsey value, indicating that the\n // request for this key is already in flight, or a new callback\n // which when called will call all callbacks passed to inflightk\n // with the same key\n callback = inflight(key, callback)\n\n // If we got a falsey value back, then there's already a req going\n if (!callback) return\n\n // this is where you'd fetch the url or whatever\n // callback is also once()-ified, so it can safely be assigned\n // to multiple events etc. First call wins.\n setTimeout(function() {\n callback(null, key)\n }, 100)\n}\n\n// only assigns a single setTimeout\n// when it dings, all cbs get called\nreq('foo', cb1)\nreq('foo', cb2)\nreq('foo', cb3)\nreq('foo', cb4)\n```\n", - "readmeFilename": "README.md", - "gitHead": "c7b5531d572a867064d4a1da9e013e8910b7d1ba", - "_id": "inflight@1.0.4", - "_shasum": "6cbb4521ebd51ce0ec0a936bfd7657ef7e9b172a", - "_from": "inflight@>=1.0.4 <1.1.0" + "gitHead": "559e37b4f6327fca797fe8d7fe8ed6d9cae08821", + "_id": "inflight@1.0.5", + "_shasum": "db3204cd5a9de2e6cd890b85c6e2f66bcf4f620a", + "_from": "inflight@>=1.0.5 <1.1.0", + "_npmVersion": "3.9.1", + "_nodeVersion": "5.10.1", + "_npmUser": { + "name": "zkat", + "email": "kat@sykosomatic.org" + }, + "dist": { + "shasum": "db3204cd5a9de2e6cd890b85c6e2f66bcf4f620a", + "tarball": "https://registry.npmjs.org/inflight/-/inflight-1.0.5.tgz" + }, + "maintainers": [ + { + "name": "iarna", + "email": "me@re-becca.org" + }, + { + "name": "isaacs", + "email": "i@izs.me" + }, + { + "name": "othiym23", + "email": "ogd@aoaioxxysz.net" + }, + { + "name": "zkat", + "email": "kat@sykosomatic.org" + } + ], + "_npmOperationalInternal": { + "host": "packages-12-west.internal.npmjs.com", + "tmp": "tmp/inflight-1.0.5.tgz_1463529611443_0.00041943578980863094" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.5.tgz", + "readme": "ERROR: No README data found!" } diff --git a/deps/npm/node_modules/inflight/test.js b/deps/npm/node_modules/inflight/test.js deleted file mode 100644 index 2bb75b38814a60..00000000000000 --- a/deps/npm/node_modules/inflight/test.js +++ /dev/null @@ -1,97 +0,0 @@ -var test = require('tap').test -var inf = require('./inflight.js') - - -function req (key, cb) { - cb = inf(key, cb) - if (cb) setTimeout(function () { - cb(key) - cb(key) - }) - return cb -} - -test('basic', function (t) { - var calleda = false - var a = req('key', function (k) { - t.notOk(calleda) - calleda = true - t.equal(k, 'key') - if (calledb) t.end() - }) - t.ok(a, 'first returned cb function') - - var calledb = false - var b = req('key', function (k) { - t.notOk(calledb) - calledb = true - t.equal(k, 'key') - if (calleda) t.end() - }) - - t.notOk(b, 'second should get falsey inflight response') -}) - -test('timing', function (t) { - var expect = [ - 'method one', - 'start one', - 'end one', - 'two', - 'tick', - 'three' - ] - var i = 0 - - function log (m) { - t.equal(m, expect[i], m + ' === ' + expect[i]) - ++i - if (i === expect.length) - t.end() - } - - function method (name, cb) { - log('method ' + name) - process.nextTick(cb) - } - - var one = inf('foo', function () { - log('start one') - var three = inf('foo', function () { - log('three') - }) - if (three) method('three', three) - log('end one') - }) - - method('one', one) - - var two = inf('foo', function () { - log('two') - }) - if (two) method('one', two) - - process.nextTick(log.bind(null, 'tick')) -}) - -test('parameters', function (t) { - t.plan(8) - - var a = inf('key', function (first, second, third) { - t.equal(first, 1) - t.equal(second, 2) - t.equal(third, 3) - }) - t.ok(a, 'first returned cb function') - - var b = inf('key', function (first, second, third) { - t.equal(first, 1) - t.equal(second, 2) - t.equal(third, 3) - }) - t.notOk(b, 'second should get falsey inflight response') - - setTimeout(function () { - a(1, 2, 3) - }) -}) diff --git a/deps/npm/node_modules/init-package-json/init-package-json.js b/deps/npm/node_modules/init-package-json/init-package-json.js index 87c72ccf948b7e..7dc4b0a392c2fd 100644 --- a/deps/npm/node_modules/init-package-json/init-package-json.js +++ b/deps/npm/node_modules/init-package-json/init-package-json.js @@ -40,7 +40,7 @@ function init (dir, input, config, cb) { } } - var package = path.resolve(dir, 'package.json') + var packageFile = path.resolve(dir, 'package.json') input = path.resolve(input) var pkg var ctx = { yes: yes(config) } @@ -49,14 +49,14 @@ function init (dir, input, config, cb) { readJson.extraSet = es.filter(function (fn) { return fn.name !== 'authors' && fn.name !== 'mans' }) - readJson(package, function (er, d) { + readJson(packageFile, function (er, d) { readJson.extraSet = es if (er) pkg = {} else pkg = d - ctx.filename = package - ctx.dirname = path.dirname(package) + ctx.filename = packageFile + ctx.dirname = path.dirname(packageFile) ctx.basename = path.basename(ctx.dirname) if (!pkg.version || !semver.valid(pkg.version)) delete pkg.version @@ -80,7 +80,7 @@ function init (dir, input, config, cb) { readJson.extraSet = es.filter(function (fn) { return fn.name !== 'authors' && fn.name !== 'mans' }) - readJson.extras(package, pkg, function (er, pkg) { + readJson.extras(packageFile, pkg, function (er, pkg) { readJson.extraSet = es if (er) return cb(er, pkg) pkg = unParsePeople(pkg) @@ -105,9 +105,9 @@ function init (dir, input, config, cb) { var d = JSON.stringify(pkg, null, 2) + '\n' function write (yes) { - fs.writeFile(package, d, 'utf8', function (er) { + fs.writeFile(packageFile, d, 'utf8', function (er) { if (!er && yes && !config.get('silent')) { - console.log('Wrote to %s:\n\n%s\n', package, d) + console.log('Wrote to %s:\n\n%s\n', packageFile, d) } return cb(er, pkg) }) @@ -115,7 +115,7 @@ function init (dir, input, config, cb) { if (ctx.yes) { return write(true) } - console.log('About to write to %s:\n\n%s\n', package, d) + console.log('About to write to %s:\n\n%s\n', packageFile, d) read({prompt:'Is this ok? ', default: 'yes'}, function (er, ok) { if (!ok || ok.toLowerCase().charAt(0) !== 'y') { console.log('Aborted.') diff --git a/deps/npm/node_modules/init-package-json/node_modules/glob/node_modules/path-is-absolute/package.json b/deps/npm/node_modules/init-package-json/node_modules/glob/node_modules/path-is-absolute/package.json index 39372636f3fb4f..8f41adea4c1569 100644 --- a/deps/npm/node_modules/init-package-json/node_modules/glob/node_modules/path-is-absolute/package.json +++ b/deps/npm/node_modules/init-package-json/node_modules/glob/node_modules/path-is-absolute/package.json @@ -62,7 +62,7 @@ ], "dist": { "shasum": "263dada66ab3f2fb10bf7f9d24dd8f3e570ef912", - "tarball": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz" + "tarball": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz" }, "directories": {}, "_resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz", diff --git a/deps/npm/node_modules/init-package-json/node_modules/glob/package.json b/deps/npm/node_modules/init-package-json/node_modules/glob/package.json index 19e926cbf1035a..d6cebb41e61088 100644 --- a/deps/npm/node_modules/init-package-json/node_modules/glob/package.json +++ b/deps/npm/node_modules/init-package-json/node_modules/glob/package.json @@ -59,7 +59,7 @@ }, "dist": { "shasum": "0f08860f6a155127b2fadd4f9ce24b1aab6e4d22", - "tarball": "http://registry.npmjs.org/glob/-/glob-6.0.4.tgz" + "tarball": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz" }, "maintainers": [ { diff --git a/deps/npm/node_modules/init-package-json/node_modules/promzard/package.json b/deps/npm/node_modules/init-package-json/node_modules/promzard/package.json index 42900314b94c93..a90ea7fdf7b517 100644 --- a/deps/npm/node_modules/init-package-json/node_modules/promzard/package.json +++ b/deps/npm/node_modules/init-package-json/node_modules/promzard/package.json @@ -43,7 +43,7 @@ ], "dist": { "shasum": "26a5d6ee8c7dee4cb12208305acfb93ba382a9ee", - "tarball": "http://registry.npmjs.org/promzard/-/promzard-0.3.0.tgz" + "tarball": "https://registry.npmjs.org/promzard/-/promzard-0.3.0.tgz" }, "directories": {}, "_resolved": "https://registry.npmjs.org/promzard/-/promzard-0.3.0.tgz" diff --git a/deps/npm/node_modules/init-package-json/package.json b/deps/npm/node_modules/init-package-json/package.json index 4be24267cfe9fc..06ba9600ab465d 100644 --- a/deps/npm/node_modules/init-package-json/package.json +++ b/deps/npm/node_modules/init-package-json/package.json @@ -1,6 +1,6 @@ { "name": "init-package-json", - "version": "1.9.3", + "version": "1.9.4", "main": "init-package-json.js", "scripts": { "test": "tap test/*.js" @@ -41,23 +41,23 @@ "prompt", "start" ], - "gitHead": "12eb24ff2f75f84a4a27436bc6f6cb765cbd9ee2", + "gitHead": "3c34250fa58507056a94f3940ee2a28540f83592", "bugs": { "url": "https://github.com/npm/init-package-json/issues" }, "homepage": "https://github.com/npm/init-package-json#readme", - "_id": "init-package-json@1.9.3", - "_shasum": "ca2ff94709b6d9aaad66533c11a0aff645f15c7d", - "_from": "init-package-json@1.9.3", - "_npmVersion": "3.5.4", - "_nodeVersion": "4.2.2", + "_id": "init-package-json@1.9.4", + "_shasum": "b4053d0b40f0cf842a41966937cb3dc0f534e856", + "_from": "init-package-json@>=1.9.4 <1.10.0", + "_npmVersion": "3.9.1", + "_nodeVersion": "5.10.1", "_npmUser": { - "name": "iarna", - "email": "me@re-becca.org" + "name": "zkat", + "email": "kat@sykosomatic.org" }, "dist": { - "shasum": "ca2ff94709b6d9aaad66533c11a0aff645f15c7d", - "tarball": "http://registry.npmjs.org/init-package-json/-/init-package-json-1.9.3.tgz" + "shasum": "b4053d0b40f0cf842a41966937cb3dc0f534e856", + "tarball": "https://registry.npmjs.org/init-package-json/-/init-package-json-1.9.4.tgz" }, "maintainers": [ { @@ -77,6 +77,10 @@ "email": "kat@sykosomatic.org" } ], + "_npmOperationalInternal": { + "host": "packages-16-east.internal.npmjs.com", + "tmp": "tmp/init-package-json-1.9.4.tgz_1463610982259_0.011722659226506948" + }, "directories": {}, - "_resolved": "https://registry.npmjs.org/init-package-json/-/init-package-json-1.9.3.tgz" + "_resolved": "https://registry.npmjs.org/init-package-json/-/init-package-json-1.9.4.tgz" } diff --git a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/.travis.yml b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/.travis.yml index cfe1c9439388b6..1b82118460cfe4 100644 --- a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/.travis.yml +++ b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/.travis.yml @@ -6,6 +6,10 @@ before_install: notifications: email: false matrix: + fast_finish: true + allow_failures: + - env: TASK=browser BROWSER_NAME=ipad BROWSER_VERSION="6.0..latest" + - env: TASK=browser BROWSER_NAME=iphone BROWSER_VERSION="6.0..latest" include: - node_js: '0.8' env: TASK=test @@ -25,24 +29,22 @@ matrix: env: TASK=test - node_js: 5 env: TASK=test - - node_js: node - env: TASK=test - - node_js: node - env: TASK=browser BROWSER_NAME=opera BROWSER_VERSION="11..latest" - - node_js: node + - node_js: 5 + env: TASK=browser BROWSER_NAME=android BROWSER_VERSION="4.0..latest" + - node_js: 5 env: TASK=browser BROWSER_NAME=ie BROWSER_VERSION="9..latest" - - node_js: node - env: TASK=browser BROWSER_NAME=chrome BROWSER_VERSION="41..beta" - - node_js: node - env: TASK=browser BROWSER_NAME=firefox BROWSER_VERSION="36..latest" - - node_js: node - env: TASK=browser BROWSER_NAME=ipad BROWSER_VERSION="['6.1', '7.1', '8.2']" - - node_js: node - env: TASK=browser BROWSER_NAME=iphone BROWSER_VERSION="['6.1', '7.1', '8.2']" - - node_js: node + - node_js: 5 + env: TASK=browser BROWSER_NAME=opera BROWSER_VERSION="11..latest" + - node_js: 5 + env: TASK=browser BROWSER_NAME=chrome BROWSER_VERSION="-3..latest" + - node_js: 5 + env: TASK=browser BROWSER_NAME=firefox BROWSER_VERSION="-3..latest" + - node_js: 5 + env: TASK=browser BROWSER_NAME=ipad BROWSER_VERSION="6.0..latest" + - node_js: 5 + env: TASK=browser BROWSER_NAME=iphone BROWSER_VERSION="6.0..latest" + - node_js: 5 env: TASK=browser BROWSER_NAME=safari BROWSER_VERSION="5..latest" - - node_js: node - env: TASK=browser BROWSER_NAME=android BROWSER_VERSION="4.0..latest" script: "npm run $TASK" env: global: diff --git a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/README.md b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/README.md index 77fafa3da15f9f..1a67c48cd031b5 100644 --- a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/README.md +++ b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/README.md @@ -1,6 +1,6 @@ # readable-stream -***Node-core streams for userland*** [![Build Status](https://travis-ci.org/nodejs/readable-stream.svg?branch=master)](https://travis-ci.org/nodejs/readable-stream) +***Node-core v5.8.0 streams for userland*** [![Build Status](https://travis-ci.org/nodejs/readable-stream.svg?branch=master)](https://travis-ci.org/nodejs/readable-stream) [![NPM](https://nodei.co/npm/readable-stream.png?downloads=true&downloadRank=true)](https://nodei.co/npm/readable-stream/) diff --git a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/doc/stream.markdown b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/doc/stream.markdown index 3988c0cbd0d9c9..0bc3819e63b025 100644 --- a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/doc/stream.markdown +++ b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/doc/stream.markdown @@ -3,27 +3,25 @@ Stability: 2 - Stable A stream is an abstract interface implemented by various objects in -Node.js. For example a [request to an HTTP server][] is a stream, as is -[stdout][]. Streams are readable, writable, or both. All streams are -instances of [EventEmitter][] +Node.js. For example a [request to an HTTP server][http-incoming-message] is a +stream, as is [`process.stdout`][]. Streams are readable, writable, or both. All +streams are instances of [`EventEmitter`][]. You can load the Stream base classes by doing `require('stream')`. There are base classes provided for [Readable][] streams, [Writable][] streams, [Duplex][] streams, and [Transform][] streams. -This document is split up into 3 sections. The first explains the -parts of the API that you need to be aware of to use streams in your -programs. If you never implement a streaming API yourself, you can -stop there. +This document is split up into 3 sections: -The second section explains the parts of the API that you need to use -if you implement your own custom streams yourself. The API is -designed to make this easy for you to do. - -The third section goes into more depth about how streams work, -including some of the internal mechanisms and functions that you -should probably not modify unless you definitely know what you are -doing. +1. The first section explains the parts of the API that you need to be + aware of to use streams in your programs. +2. The second section explains the parts of the API that you need to + use if you implement your own custom streams yourself. The API is designed to + make this easy for you to do. +3. The third section goes into more depth about how streams work, + including some of the internal mechanisms and functions that you + should probably not modify unless you definitely know what you are + doing. ## API for Stream Consumers @@ -37,22 +35,22 @@ and properties depending on whether they are Readable, Writable, or Duplex. If a stream is both Readable and Writable, then it implements all of -the methods and events below. So, a [Duplex][] or [Transform][] stream is +the methods and events. So, a [Duplex][] or [Transform][] stream is fully described by this API, though their implementation may be somewhat different. It is not necessary to implement Stream interfaces in order to consume -streams in your programs. If you **are** implementing streaming +streams in your programs. If you **are** implementing streaming interfaces in your own program, please also refer to -[API for Stream Implementors][] below. +[API for Stream Implementors][]. Almost all Node.js programs, no matter how simple, use Streams in some way. Here is an example of using Streams in an Node.js program: -```javascript -var http = require('http'); +```js +const http = require('http'); -var server = http.createServer(function (req, res) { +var server = http.createServer( (req, res) => { // req is an http.IncomingMessage, which is a Readable Stream // res is an http.ServerResponse, which is a Writable Stream @@ -62,18 +60,18 @@ var server = http.createServer(function (req, res) { req.setEncoding('utf8'); // Readable streams emit 'data' events once a listener is added - req.on('data', function (chunk) { + req.on('data', (chunk) => { body += chunk; }); // the end event tells you that you have entire body - req.on('end', function () { + req.on('end', () => { try { var data = JSON.parse(body); } catch (er) { // uh oh! bad json! res.statusCode = 400; - return res.end('error: ' + er.message); + return res.end(`error: ${er.message}`); } // write back something interesting to the user: @@ -95,65 +93,66 @@ server.listen(1337); ### Class: stream.Duplex Duplex streams are streams that implement both the [Readable][] and -[Writable][] interfaces. See above for usage. +[Writable][] interfaces. Examples of Duplex streams include: -* [tcp sockets][] -* [zlib streams][] -* [crypto streams][] +* [TCP sockets][] +* [zlib streams][zlib] +* [crypto streams][crypto] ### Class: stream.Readable The Readable stream interface is the abstraction for a *source* of -data that you are reading from. In other words, data comes *out* of a +data that you are reading from. In other words, data comes *out* of a Readable stream. A Readable stream will not start emitting data until you indicate that you are ready to receive it. Readable streams have two "modes": a **flowing mode** and a **paused -mode**. When in flowing mode, data is read from the underlying system -and provided to your program as fast as possible. In paused mode, you -must explicitly call `stream.read()` to get chunks of data out. +mode**. When in flowing mode, data is read from the underlying system +and provided to your program as fast as possible. In paused mode, you +must explicitly call [`stream.read()`][stream-read] to get chunks of data out. Streams start out in paused mode. **Note**: If no data event handlers are attached, and there are no -[`pipe()`][] destinations, and the stream is switched into flowing +[`stream.pipe()`][] destinations, and the stream is switched into flowing mode, then data will be lost. You can switch to flowing mode by doing any of the following: -* Adding a [`'data'` event][] handler to listen for data. -* Calling the [`resume()`][] method to explicitly open the flow. -* Calling the [`pipe()`][] method to send the data to a [Writable][]. +* Adding a [`'data'`][] event handler to listen for data. +* Calling the [`stream.resume()`][stream-resume] method to explicitly open the + flow. +* Calling the [`stream.pipe()`][] method to send the data to a [Writable][]. You can switch back to paused mode by doing either of the following: -* If there are no pipe destinations, by calling the [`pause()`][] - method. -* If there are pipe destinations, by removing any [`'data'` event][] +* If there are no pipe destinations, by calling the + [`stream.pause()`][stream-pause] method. +* If there are pipe destinations, by removing any [`'data'`][] event handlers, and removing all pipe destinations by calling the - [`unpipe()`][] method. + [`stream.unpipe()`][] method. -Note that, for backwards compatibility reasons, removing `'data'` -event handlers will **not** automatically pause the stream. Also, if -there are piped destinations, then calling `pause()` will not -guarantee that the stream will *remain* paused once those +Note that, for backwards compatibility reasons, removing [`'data'`][] +event handlers will **not** automatically pause the stream. Also, if +there are piped destinations, then calling [`stream.pause()`][stream-pause] will +not guarantee that the stream will *remain* paused once those destinations drain and ask for more data. Examples of readable streams include: -* [http responses, on the client][] -* [http requests, on the server][] +* [HTTP responses, on the client][http-incoming-message] +* [HTTP requests, on the server][http-incoming-message] * [fs read streams][] -* [zlib streams][] -* [crypto streams][] -* [tcp sockets][] +* [zlib streams][zlib] +* [crypto streams][crypto] +* [TCP sockets][] * [child process stdout and stderr][] -* [process.stdin][] +* [`process.stdin`][] #### Event: 'close' @@ -161,22 +160,22 @@ Emitted when the stream and any of its underlying resources (a file descriptor, for example) have been closed. The event indicates that no more events will be emitted, and no further computation will occur. -Not all streams will emit the 'close' event. +Not all streams will emit the `'close'` event. #### Event: 'data' -* `chunk` {Buffer | String} The chunk of data. +* `chunk` {Buffer|String} The chunk of data. -Attaching a `data` event listener to a stream that has not been +Attaching a `'data'` event listener to a stream that has not been explicitly paused will switch the stream into flowing mode. Data will then be passed as soon as it is available. If you just want to get all the data out of the stream as fast as possible, this is the best way to do so. -```javascript +```js var readable = getReadableStreamSomehow(); -readable.on('data', function(chunk) { +readable.on('data', (chunk) => { console.log('got %d bytes of data', chunk.length); }); ``` @@ -185,16 +184,17 @@ readable.on('data', function(chunk) { This event fires when there will be no more data to read. -Note that the `end` event **will not fire** unless the data is -completely consumed. This can be done by switching into flowing mode, -or by calling `read()` repeatedly until you get to the end. +Note that the `'end'` event **will not fire** unless the data is +completely consumed. This can be done by switching into flowing mode, +or by calling [`stream.read()`][stream-read] repeatedly until you get to the +end. -```javascript +```js var readable = getReadableStreamSomehow(); -readable.on('data', function(chunk) { +readable.on('data', (chunk) => { console.log('got %d bytes of data', chunk.length); }); -readable.on('end', function() { +readable.on('end', () => { console.log('there will be no more data.'); }); ``` @@ -216,30 +216,30 @@ hadn't already. ```javascript var readable = getReadableStreamSomehow(); -readable.on('readable', function() { +readable.on('readable', () => { // there is some data to read now }); ``` -Once the internal buffer is drained, a `readable` event will fire +Once the internal buffer is drained, a `'readable'` event will fire again when more data is available. -The `readable` event is not emitted in the "flowing" mode with the +The `'readable'` event is not emitted in the "flowing" mode with the sole exception of the last one, on end-of-stream. -The 'readable' event indicates that the stream has new information: +The `'readable'` event indicates that the stream has new information: either new data is available or the end of the stream has been reached. -In the former case, `.read()` will return that data. In the latter case, -`.read()` will return null. For instance, in the following example, `foo.txt` -is an empty file: +In the former case, [`stream.read()`][stream-read] will return that data. In the +latter case, [`stream.read()`][stream-read] will return null. For instance, in +the following example, `foo.txt` is an empty file: -```javascript -var fs = require('fs'); +```js +const fs = require('fs'); var rr = fs.createReadStream('foo.txt'); -rr.on('readable', function() { +rr.on('readable', () => { console.log('readable:', rr.read()); }); -rr.on('end', function() { +rr.on('end', () => { console.log('end'); }); ``` @@ -247,20 +247,20 @@ rr.on('end', function() { The output of running this script is: ``` -bash-3.2$ node test.js +$ node test.js readable: null end ``` #### readable.isPaused() -* Return: `Boolean` +* Return: {Boolean} This method returns whether or not the `readable` has been **explicitly** -paused by client code (using `readable.pause()` without a corresponding -`readable.resume()`). +paused by client code (using [`stream.pause()`][stream-pause] without a +corresponding [`stream.resume()`][stream-resume]). -```javascript +```js var readable = new stream.Readable readable.isPaused() // === false @@ -275,16 +275,16 @@ readable.isPaused() // === false * Return: `this` This method will cause a stream in flowing mode to stop emitting -`data` events, switching out of flowing mode. Any data that becomes +[`'data'`][] events, switching out of flowing mode. Any data that becomes available will remain in the internal buffer. -```javascript +```js var readable = getReadableStreamSomehow(); -readable.on('data', function(chunk) { +readable.on('data', (chunk) => { console.log('got %d bytes of data', chunk.length); readable.pause(); console.log('there will be no more data for 1 second'); - setTimeout(function() { + setTimeout(() => { console.log('now data will start flowing again'); readable.resume(); }, 1000); @@ -293,7 +293,7 @@ readable.on('data', function(chunk) { #### readable.pipe(destination[, options]) -* `destination` {[Writable][] Stream} The destination for writing data +* `destination` {stream.Writable} The destination for writing data * `options` {Object} Pipe options * `end` {Boolean} End the writer when the reader ends. Default = `true` @@ -303,7 +303,7 @@ the destination is not overwhelmed by a fast readable stream. Multiple destinations can be piped to safely. -```javascript +```js var readable = getReadableStreamSomehow(); var writable = fs.createWriteStream('file.txt'); // All the data from readable goes into 'file.txt' @@ -313,7 +313,7 @@ readable.pipe(writable); This function returns the destination stream, so you can set up pipe chains like so: -```javascript +```js var r = fs.createReadStream('file.txt'); var z = zlib.createGzip(); var w = fs.createWriteStream('file.txt.gz'); @@ -322,51 +322,51 @@ r.pipe(z).pipe(w); For example, emulating the Unix `cat` command: -```javascript +```js process.stdin.pipe(process.stdout); ``` -By default [`end()`][] is called on the destination when the source stream -emits `end`, so that `destination` is no longer writable. Pass `{ end: -false }` as `options` to keep the destination stream open. +By default [`stream.end()`][stream-end] is called on the destination when the +source stream emits [`'end'`][], so that `destination` is no longer writable. +Pass `{ end: false }` as `options` to keep the destination stream open. This keeps `writer` open so that "Goodbye" can be written at the end. -```javascript +```js reader.pipe(writer, { end: false }); -reader.on('end', function() { +reader.on('end', () => { writer.end('Goodbye\n'); }); ``` -Note that `process.stderr` and `process.stdout` are never closed until +Note that [`process.stderr`][] and [`process.stdout`][] are never closed until the process exits, regardless of the specified options. #### readable.read([size]) * `size` {Number} Optional argument to specify how much data to read. -* Return {String | Buffer | null} +* Return {String|Buffer|Null} The `read()` method pulls some data out of the internal buffer and -returns it. If there is no data available, then it will return +returns it. If there is no data available, then it will return `null`. If you pass in a `size` argument, then it will return that many -bytes. If `size` bytes are not available, then it will return `null`, +bytes. If `size` bytes are not available, then it will return `null`, unless we've ended, in which case it will return the data remaining in the buffer. If you do not specify a `size` argument, then it will return all the data in the internal buffer. -This method should only be called in paused mode. In flowing mode, +This method should only be called in paused mode. In flowing mode, this method is called automatically until the internal buffer is drained. -```javascript +```js var readable = getReadableStreamSomehow(); -readable.on('readable', function() { +readable.on('readable', () => { var chunk; while (null !== (chunk = readable.read())) { console.log('got %d bytes of data', chunk.length); @@ -375,27 +375,27 @@ readable.on('readable', function() { ``` If this method returns a data chunk, then it will also trigger the -emission of a [`'data'` event][]. +emission of a [`'data'`][] event. -Note that calling `readable.read([size])` after the `end` event has been -triggered will return `null`. No runtime error will be raised. +Note that calling [`stream.read([size])`][stream-read] after the [`'end'`][] +event has been triggered will return `null`. No runtime error will be raised. #### readable.resume() * Return: `this` -This method will cause the readable stream to resume emitting `data` +This method will cause the readable stream to resume emitting [`'data'`][] events. -This method will switch the stream into flowing mode. If you do *not* +This method will switch the stream into flowing mode. If you do *not* want to consume the data from a stream, but you *do* want to get to -its `end` event, you can call [`readable.resume()`][] to open the flow of -data. +its [`'end'`][] event, you can call [`stream.resume()`][stream-resume] to open +the flow of data. -```javascript +```js var readable = getReadableStreamSomehow(); readable.resume(); -readable.on('end', function() { +readable.on('end', () => { console.log('got to the end, but did not read anything'); }); ``` @@ -405,22 +405,25 @@ readable.on('end', function() { * `encoding` {String} The encoding to use. * Return: `this` -Call this function to cause the stream to return strings of the -specified encoding instead of Buffer objects. For example, if you do -`readable.setEncoding('utf8')`, then the output data will be -interpreted as UTF-8 data, and returned as strings. If you do -`readable.setEncoding('hex')`, then the data will be encoded in -hexadecimal string format. +Call this function to cause the stream to return strings of the specified +encoding instead of Buffer objects. For example, if you do +`readable.setEncoding('utf8')`, then the output data will be interpreted as +UTF-8 data, and returned as strings. If you do `readable.setEncoding('hex')`, +then the data will be encoded in hexadecimal string format. This properly handles multi-byte characters that would otherwise be potentially mangled if you simply pulled the Buffers directly and -called `buf.toString(encoding)` on them. If you want to read the data +called [`buf.toString(encoding)`][] on them. If you want to read the data as strings, always use this method. -```javascript +Also you can disable any encoding at all with `readable.setEncoding(null)`. +This approach is very useful if you deal with binary data or with large +multi-byte strings spread out over multiple chunks. + +```js var readable = getReadableStreamSomehow(); readable.setEncoding('utf8'); -readable.on('data', function(chunk) { +readable.on('data', (chunk) => { assert.equal(typeof chunk, 'string'); console.log('got %d characters of string data', chunk.length); }); @@ -428,22 +431,23 @@ readable.on('data', function(chunk) { #### readable.unpipe([destination]) -* `destination` {[Writable][] Stream} Optional specific stream to unpipe +* `destination` {stream.Writable} Optional specific stream to unpipe -This method will remove the hooks set up for a previous `pipe()` call. +This method will remove the hooks set up for a previous [`stream.pipe()`][] +call. If the destination is not specified, then all pipes are removed. If the destination is specified, but no pipe is set up for it, then this is a no-op. -```javascript +```js var readable = getReadableStreamSomehow(); var writable = fs.createWriteStream('file.txt'); // All the data from readable goes into 'file.txt', // but only for the first second readable.pipe(writable); -setTimeout(function() { +setTimeout(() => { console.log('stop writing to file.txt'); readable.unpipe(writable); console.log('manually close the file stream'); @@ -453,25 +457,25 @@ setTimeout(function() { #### readable.unshift(chunk) -* `chunk` {Buffer | String} Chunk of data to unshift onto the read queue +* `chunk` {Buffer|String} Chunk of data to unshift onto the read queue This is useful in certain cases where a stream is being consumed by a parser, which needs to "un-consume" some data that it has optimistically pulled out of the source, so that the stream can be passed on to some other party. -Note that `stream.unshift(chunk)` cannot be called after the `end` event +Note that `stream.unshift(chunk)` cannot be called after the [`'end'`][] event has been triggered; a runtime error will be raised. If you find that you must often call `stream.unshift(chunk)` in your -programs, consider implementing a [Transform][] stream instead. (See API -for Stream Implementors, below.) +programs, consider implementing a [Transform][] stream instead. (See [API +for Stream Implementors][].) -```javascript +```js // Pull off a header delimited by \n\n // use unshift() if we get too much // Call the callback with (error, header, stream) -var StringDecoder = require('string_decoder').StringDecoder; +const StringDecoder = require('string_decoder').StringDecoder; function parseHeader(stream, callback) { stream.on('error', callback); stream.on('readable', onReadable); @@ -501,39 +505,41 @@ function parseHeader(stream, callback) { } } ``` -Note that, unlike `stream.push(chunk)`, `stream.unshift(chunk)` will not -end the reading process by resetting the internal reading state of the -stream. This can cause unexpected results if `unshift` is called during a -read (i.e. from within a `_read` implementation on a custom stream). Following -the call to `unshift` with an immediate `stream.push('')` will reset the -reading state appropriately, however it is best to simply avoid calling -`unshift` while in the process of performing a read. + +Note that, unlike [`stream.push(chunk)`][stream-push], `stream.unshift(chunk)` +will not end the reading process by resetting the internal reading state of the +stream. This can cause unexpected results if `unshift()` is called during a +read (i.e. from within a [`stream._read()`][stream-_read] implementation on a +custom stream). Following the call to `unshift()` with an immediate +[`stream.push('')`][stream-push] will reset the reading state appropriately, +however it is best to simply avoid calling `unshift()` while in the process of +performing a read. #### readable.wrap(stream) * `stream` {Stream} An "old style" readable stream Versions of Node.js prior to v0.10 had streams that did not implement the -entire Streams API as it is today. (See "Compatibility" below for +entire Streams API as it is today. (See [Compatibility][] for more information.) -If you are using an older Node.js library that emits `'data'` events and -has a [`pause()`][] method that is advisory only, then you can use the -`wrap()` method to create a [Readable][] stream that uses the old stream -as its data source. +If you are using an older Node.js library that emits [`'data'`][] events and +has a [`stream.pause()`][stream-pause] method that is advisory only, then you +can use the `wrap()` method to create a [Readable][] stream that uses the old +stream as its data source. You will very rarely ever need to call this function, but it exists as a convenience for interacting with old Node.js programs and libraries. For example: -```javascript -var OldReader = require('./old-api-module.js').OldReader; -var oreader = new OldReader; -var Readable = require('stream').Readable; -var myReader = new Readable().wrap(oreader); +```js +const OldReader = require('./old-api-module.js').OldReader; +const Readable = require('stream').Readable; +const oreader = new OldReader; +const myReader = new Readable().wrap(oreader); -myReader.on('readable', function() { +myReader.on('readable', () => { myReader.read(); // etc. }); ``` @@ -541,13 +547,13 @@ myReader.on('readable', function() { ### Class: stream.Transform Transform streams are [Duplex][] streams where the output is in some way -computed from the input. They implement both the [Readable][] and -[Writable][] interfaces. See above for usage. +computed from the input. They implement both the [Readable][] and +[Writable][] interfaces. Examples of Transform streams include: -* [zlib streams][] -* [crypto streams][] +* [zlib streams][zlib] +* [crypto streams][crypto] ### Class: stream.Writable @@ -558,22 +564,22 @@ that you are writing data *to*. Examples of writable streams include: -* [http requests, on the client][] -* [http responses, on the server][] +* [HTTP requests, on the client][] +* [HTTP responses, on the server][] * [fs write streams][] -* [zlib streams][] -* [crypto streams][] -* [tcp sockets][] +* [zlib streams][zlib] +* [crypto streams][crypto] +* [TCP sockets][] * [child process stdin][] -* [process.stdout][], [process.stderr][] +* [`process.stdout`][], [`process.stderr`][] #### Event: 'drain' -If a [`writable.write(chunk)`][] call returns false, then the `drain` -event will indicate when it is appropriate to begin writing more data +If a [`stream.write(chunk)`][stream-write] call returns `false`, then the +`'drain'` event will indicate when it is appropriate to begin writing more data to the stream. -```javascript +```js // Write the data to the supplied writable stream one million times. // Be attentive to back-pressure. function writeOneMillionTimes(writer, data, encoding, callback) { @@ -603,37 +609,37 @@ function writeOneMillionTimes(writer, data, encoding, callback) { #### Event: 'error' -* {Error object} +* {Error} Emitted if there was an error when writing or piping data. #### Event: 'finish' -When the [`end()`][] method has been called, and all data has been flushed -to the underlying system, this event is emitted. +When the [`stream.end()`][stream-end] method has been called, and all data has +been flushed to the underlying system, this event is emitted. ```javascript var writer = getWritableStreamSomehow(); for (var i = 0; i < 100; i ++) { - writer.write('hello, #' + i + '!\n'); + writer.write('hello, #${i}!\n'); } writer.end('this is the end\n'); -writer.on('finish', function() { +writer.on('finish', () => { console.error('all writes are now complete.'); }); ``` #### Event: 'pipe' -* `src` {[Readable][] Stream} source stream that is piping to this writable +* `src` {stream.Readable} source stream that is piping to this writable -This is emitted whenever the `pipe()` method is called on a readable +This is emitted whenever the [`stream.pipe()`][] method is called on a readable stream, adding this writable to its set of destinations. -```javascript +```js var writer = getWritableStreamSomehow(); var reader = getReadableStreamSomehow(); -writer.on('pipe', function(src) { +writer.on('pipe', (src) => { console.error('something is piping into the writer'); assert.equal(src, reader); }); @@ -642,15 +648,16 @@ reader.pipe(writer); #### Event: 'unpipe' -* `src` {[Readable][] Stream} The source stream that [unpiped][] this writable +* `src` {[Readable][] Stream} The source stream that + [unpiped][`stream.unpipe()`] this writable -This is emitted whenever the [`unpipe()`][] method is called on a +This is emitted whenever the [`stream.unpipe()`][] method is called on a readable stream, removing this writable from its set of destinations. -```javascript +```js var writer = getWritableStreamSomehow(); var reader = getReadableStreamSomehow(); -writer.on('unpipe', function(src) { +writer.on('unpipe', (src) => { console.error('something has stopped piping into the writer'); assert.equal(src, reader); }); @@ -662,20 +669,22 @@ reader.unpipe(writer); Forces buffering of all writes. -Buffered data will be flushed either at `.uncork()` or at `.end()` call. +Buffered data will be flushed either at [`stream.uncork()`][] or at +[`stream.end()`][stream-end] call. #### writable.end([chunk][, encoding][, callback]) -* `chunk` {String | Buffer} Optional data to write +* `chunk` {String|Buffer} Optional data to write * `encoding` {String} The encoding, if `chunk` is a String * `callback` {Function} Optional callback for when the stream is finished -Call this method when no more data will be written to the stream. If -supplied, the callback is attached as a listener on the `finish` event. +Call this method when no more data will be written to the stream. If supplied, +the callback is attached as a listener on the [`'finish'`][] event. -Calling [`write()`][] after calling [`end()`][] will raise an error. +Calling [`stream.write()`][stream-write] after calling +[`stream.end()`][stream-end] will raise an error. -```javascript +```js // write 'hello, ' and then end with 'world!' var file = fs.createWriteStream('example.txt'); file.write('hello, '); @@ -691,26 +700,26 @@ Sets the default encoding for a writable stream. #### writable.uncork() -Flush all data, buffered since `.cork()` call. +Flush all data, buffered since [`stream.cork()`][] call. #### writable.write(chunk[, encoding][, callback]) -* `chunk` {String | Buffer} The data to write +* `chunk` {String|Buffer} The data to write * `encoding` {String} The encoding, if `chunk` is a String * `callback` {Function} Callback for when this chunk of data is flushed -* Returns: {Boolean} True if the data was handled completely. +* Returns: {Boolean} `true` if the data was handled completely. This method writes some data to the underlying system, and calls the supplied callback once the data has been fully handled. The return value indicates if you should continue writing right now. If the data had to be buffered internally, then it will return -`false`. Otherwise, it will return `true`. +`false`. Otherwise, it will return `true`. -This return value is strictly advisory. You MAY continue to write, -even if it returns `false`. However, writes will be buffered in -memory, so it is best not to do this excessively. Instead, wait for -the `drain` event before writing more data. +This return value is strictly advisory. You MAY continue to write, +even if it returns `false`. However, writes will be buffered in +memory, so it is best not to do this excessively. Instead, wait for +the [`'drain'`][] event before writing more data. ## API for Stream Implementors @@ -719,11 +728,11 @@ the `drain` event before writing more data. To implement any sort of stream, the pattern is the same: -1. Extend the appropriate parent class in your own subclass. (The - [`util.inherits`][] method is particularly helpful for this.) +1. Extend the appropriate parent class in your own subclass. (The + [`util.inherits()`][] method is particularly helpful for this.) 2. Call the appropriate parent class constructor in your constructor, to be sure that the internal mechanisms are set up properly. -2. Implement one or more specific methods, as detailed below. +3. Implement one or more specific methods, as detailed below. The class to extend and the method(s) to implement depend on the sort of stream class you are writing: @@ -750,7 +759,7 @@ of stream class you are writing:

    [Readable](#stream_class_stream_readable_1)

    -

    [_read][]

    +

    [_read][stream-_read]

    @@ -761,7 +770,7 @@ of stream class you are writing:

    [Writable](#stream_class_stream_writable_1)

    -

    [_write][], _writev

    +

    [_write][stream-_write], [_writev][stream-_writev]

    @@ -772,7 +781,7 @@ of stream class you are writing:

    [Duplex](#stream_class_stream_duplex_1)

    -

    [_read][], [_write][], _writev

    +

    [_read][stream-_read], [_write][stream-_write], [_writev][stream-_writev]

    @@ -783,45 +792,45 @@ of stream class you are writing:

    [Transform](#stream_class_stream_transform_1)

    -

    _transform, _flush

    +

    [_transform][stream-_transform], [_flush][stream-_flush]

    -In your implementation code, it is very important to never call the -methods described in [API for Stream Consumers][] above. Otherwise, you -can potentially cause adverse side effects in programs that consume -your streaming interfaces. +In your implementation code, it is very important to never call the methods +described in [API for Stream Consumers][]. Otherwise, you can potentially cause +adverse side effects in programs that consume your streaming interfaces. ### Class: stream.Duplex -A "duplex" stream is one that is both Readable and Writable, such as a -TCP socket connection. +A "duplex" stream is one that is both Readable and Writable, such as a TCP +socket connection. Note that `stream.Duplex` is an abstract class designed to be extended -with an underlying implementation of the `_read(size)` and -[`_write(chunk, encoding, callback)`][] methods as you would with a -Readable or Writable stream class. +with an underlying implementation of the [`stream._read(size)`][stream-_read] +and [`stream._write(chunk, encoding, callback)`][stream-_write] methods as you +would with a Readable or Writable stream class. -Since JavaScript doesn't have multiple prototypal inheritance, this -class prototypally inherits from Readable, and then parasitically from -Writable. It is thus up to the user to implement both the lowlevel -`_read(n)` method as well as the lowlevel -[`_write(chunk, encoding, callback)`][] method on extension duplex classes. +Since JavaScript doesn't have multiple prototypal inheritance, this class +prototypally inherits from Readable, and then parasitically from Writable. It is +thus up to the user to implement both the low-level +[`stream._read(n)`][stream-_read] method as well as the low-level +[`stream._write(chunk, encoding, callback)`][stream-_write] method on extension +duplex classes. #### new stream.Duplex(options) * `options` {Object} Passed to both Writable and Readable constructors. Also has the following fields: - * `allowHalfOpen` {Boolean} Default=true. If set to `false`, then + * `allowHalfOpen` {Boolean} Default = `true`. If set to `false`, then the stream will automatically end the readable side when the writable side ends and vice versa. - * `readableObjectMode` {Boolean} Default=false. Sets `objectMode` + * `readableObjectMode` {Boolean} Default = `false`. Sets `objectMode` for readable side of the stream. Has no effect if `objectMode` is `true`. - * `writableObjectMode` {Boolean} Default=false. Sets `objectMode` + * `writableObjectMode` {Boolean} Default = `false`. Sets `objectMode` for writable side of the stream. Has no effect if `objectMode` is `true`. @@ -832,7 +841,7 @@ initialized. ### Class: stream.PassThrough This is a trivial implementation of a [Transform][] stream that simply -passes the input bytes across to the output. Its purpose is mainly +passes the input bytes across to the output. Its purpose is mainly for examples and testing, but there are occasionally use cases where it can come in handy as a building block for novel sorts of streams. @@ -841,10 +850,10 @@ it can come in handy as a building block for novel sorts of streams. `stream.Readable` is an abstract class designed to be extended with an -underlying implementation of the [`_read(size)`][] method. +underlying implementation of the [`stream._read(size)`][stream-_read] method. -Please see above under [API for Stream Consumers][] for how to consume -streams in your programs. What follows is an explanation of how to +Please see [API for Stream Consumers][] for how to consume +streams in your programs. What follows is an explanation of how to implement Readable streams in your programs. #### new stream.Readable([options]) @@ -852,12 +861,14 @@ implement Readable streams in your programs. * `options` {Object} * `highWaterMark` {Number} The maximum number of bytes to store in the internal buffer before ceasing to read from the underlying - resource. Default=16kb, or 16 for `objectMode` streams + resource. Default = `16384` (16kb), or `16` for `objectMode` streams * `encoding` {String} If specified, then buffers will be decoded to - strings using the specified encoding. Default=null + strings using the specified encoding. Default = `null` * `objectMode` {Boolean} Whether this stream should behave - as a stream of objects. Meaning that stream.read(n) returns - a single value instead of a Buffer of size n. Default=false + as a stream of objects. Meaning that [`stream.read(n)`][stream-read] returns + a single value instead of a Buffer of size n. Default = `false` + * `read` {Function} Implementation for the [`stream._read()`][stream-_read] + method. In classes that extend the Readable class, make sure to call the Readable constructor so that the buffering settings can be properly @@ -871,29 +882,31 @@ Note: **Implement this method, but do NOT call it directly.** This method is prefixed with an underscore because it is internal to the class that defines it and should only be called by the internal Readable -class methods. All Readable stream implementations must provide a _read +class methods. All Readable stream implementations must provide a \_read method to fetch data from the underlying resource. -When _read is called, if data is available from the resource, `_read` should -start pushing that data into the read queue by calling `this.push(dataChunk)`. -`_read` should continue reading from the resource and pushing data until push -returns false, at which point it should stop reading from the resource. Only -when _read is called again after it has stopped should it start reading -more data from the resource and pushing that data onto the queue. +When `_read()` is called, if data is available from the resource, the `_read()` +implementation should start pushing that data into the read queue by calling +[`this.push(dataChunk)`][stream-push]. `_read()` should continue reading from +the resource and pushing data until push returns `false`, at which point it +should stop reading from the resource. Only when `_read()` is called again after +it has stopped should it start reading more data from the resource and pushing +that data onto the queue. Note: once the `_read()` method is called, it will not be called again until -the `push` method is called. +the [`stream.push()`][stream-push] method is called. -The `size` argument is advisory. Implementations where a "read" is a +The `size` argument is advisory. Implementations where a "read" is a single call that returns data can use this to know how much data to -fetch. Implementations where that is not relevant, such as TCP or +fetch. Implementations where that is not relevant, such as TCP or TLS, may ignore this argument, and simply provide data whenever it -becomes available. There is no need, for example to "wait" until -`size` bytes are available before calling [`stream.push(chunk)`][]. +becomes available. There is no need, for example to "wait" until +`size` bytes are available before calling [`stream.push(chunk)`][stream-push]. #### readable.push(chunk[, encoding]) -* `chunk` {Buffer | null | String} Chunk of data to push into the read queue + +* `chunk` {Buffer|Null|String} Chunk of data to push into the read queue * `encoding` {String} Encoding of String chunks. Must be a valid Buffer encoding, such as `'utf8'` or `'ascii'` * return {Boolean} Whether or not more pushes should be performed @@ -906,15 +919,15 @@ into the queue for subsequent stream processors to consume. If `null` is passed, it signals the end of the stream (EOF), after which no more data can be written. -The data added with `push` can be pulled out by calling the `read()` method -when the `'readable'`event fires. +The data added with `push()` can be pulled out by calling the +[`stream.read()`][stream-read] method when the [`'readable'`][] event fires. -This API is designed to be as flexible as possible. For example, +This API is designed to be as flexible as possible. For example, you may be wrapping a lower-level source which has some sort of -pause/resume mechanism, and a data callback. In those cases, you +pause/resume mechanism, and a data callback. In those cases, you could wrap the low-level source object by doing something like this: -```javascript +```js // source is an object with readStop() and readStart() methods, // and an `ondata` member that gets called when it has data, and // an `onend` member that gets called when the data is over. @@ -925,18 +938,17 @@ function SourceWrapper(options) { Readable.call(this, options); this._source = getLowlevelSourceObject(); - var self = this; // Every time there's data, we push it into the internal buffer. - this._source.ondata = function(chunk) { + this._source.ondata = (chunk) => { // if push() returns false, then we need to stop reading from source - if (!self.push(chunk)) - self._source.readStop(); + if (!this.push(chunk)) + this._source.readStop(); }; // When the source ends, we push the EOF-signaling `null` chunk - this._source.onend = function() { - self.push(null); + this._source.onend = () => { + this.push(null); }; } @@ -951,12 +963,12 @@ SourceWrapper.prototype._read = function(size) { -This is a basic example of a Readable stream. It emits the numerals +This is a basic example of a Readable stream. It emits the numerals from 1 to 1,000,000 in ascending order, and then ends. -```javascript -var Readable = require('stream').Readable; -var util = require('util'); +```js +const Readable = require('stream').Readable; +const util = require('util'); util.inherits(Counter, Readable); function Counter(opt) { @@ -979,24 +991,25 @@ Counter.prototype._read = function() { #### Example: SimpleProtocol v1 (Sub-optimal) -This is similar to the `parseHeader` function described above, but -implemented as a custom stream. Also, note that this implementation -does not convert the incoming data to a string. +This is similar to the `parseHeader` function described +[here](#stream_readable_unshift_chunk), but implemented as a custom stream. +Also, note that this implementation does not convert the incoming data to a +string. -However, this would be better implemented as a [Transform][] stream. See -below for a better implementation. +However, this would be better implemented as a [Transform][] stream. See +[SimpleProtocol v2][] for a better implementation. -```javascript +```js // A parser for a simple data protocol. // The "header" is a JSON object, followed by 2 \n characters, and // then a message body. // // NOTE: This can be done more simply as a Transform stream! -// Using Readable directly for this is sub-optimal. See the +// Using Readable directly for this is sub-optimal. See the // alternative example below under the Transform section. -var Readable = require('stream').Readable; -var util = require('util'); +const Readable = require('stream').Readable; +const util = require('util'); util.inherits(SimpleProtocol, Readable); @@ -1012,13 +1025,13 @@ function SimpleProtocol(source, options) { this._source = source; var self = this; - source.on('end', function() { + source.on('end', () => { self.push(null); }); // give it a kick whenever the source is readable // read(0) will not consume any bytes - source.on('readable', function() { + source.on('readable', () => { self.read(0); }); @@ -1098,19 +1111,24 @@ connected in some way to the input, such as a [zlib][] stream or a [crypto][] stream. There is no requirement that the output be the same size as the input, -the same number of chunks, or arrive at the same time. For example, a +the same number of chunks, or arrive at the same time. For example, a Hash stream will only ever have a single chunk of output which is -provided when the input is ended. A zlib stream will produce output +provided when the input is ended. A zlib stream will produce output that is either much smaller or much larger than its input. -Rather than implement the [`_read()`][] and [`_write()`][] methods, Transform -classes must implement the `_transform()` method, and may optionally -also implement the `_flush()` method. (See below.) +Rather than implement the [`stream._read()`][stream-_read] and +[`stream._write()`][stream-_write] methods, Transform classes must implement the +[`stream._transform()`][stream-_transform] method, and may optionally +also implement the [`stream._flush()`][stream-_flush] method. (See below.) #### new stream.Transform([options]) * `options` {Object} Passed to both Writable and Readable - constructors. + constructors. Also has the following fields: + * `transform` {Function} Implementation for the + [`stream._transform()`][stream-_transform] method. + * `flush` {Function} Implementation for the [`stream._flush()`][stream-_flush] + method. In classes that extend the Transform class, make sure to call the constructor so that the buffering settings can be properly @@ -1118,11 +1136,12 @@ initialized. #### Events: 'finish' and 'end' -The [`finish`][] and [`end`][] events are from the parent Writable -and Readable classes respectively. The `finish` event is fired after -`.end()` is called and all chunks have been processed by `_transform`, -`end` is fired after all data has been output which is after the callback -in `_flush` has been called. +The [`'finish'`][] and [`'end'`][] events are from the parent Writable +and Readable classes respectively. The `'finish'` event is fired after +[`stream.end()`][stream-end] is called and all chunks have been processed by +[`stream._transform()`][stream-_transform], `'end'` is fired after all data has +been output which is after the callback in [`stream._flush()`][stream-_flush] +has been called. #### transform.\_flush(callback) @@ -1134,26 +1153,26 @@ by child classes, and if so, will be called by the internal Transform class methods only. In some cases, your transform operation may need to emit a bit more -data at the end of the stream. For example, a `Zlib` compression +data at the end of the stream. For example, a `Zlib` compression stream will store up some internal state so that it can optimally -compress the output. At the end, however, it needs to do the best it +compress the output. At the end, however, it needs to do the best it can with what is left, so that the data will be complete. -In those cases, you can implement a `_flush` method, which will be +In those cases, you can implement a `_flush()` method, which will be called at the very end, after all the written data is consumed, but -before emitting `end` to signal the end of the readable side. Just -like with `_transform`, call `transform.push(chunk)` zero or more -times, as appropriate, and call `callback` when the flush operation is -complete. +before emitting [`'end'`][] to signal the end of the readable side. Just +like with [`stream._transform()`][stream-_transform], call +`transform.push(chunk)` zero or more times, as appropriate, and call `callback` +when the flush operation is complete. This method is prefixed with an underscore because it is internal to the class that defines it, and should not be called directly by user -programs. However, you **are** expected to override this method in +programs. However, you **are** expected to override this method in your own extension classes. #### transform.\_transform(chunk, encoding, callback) -* `chunk` {Buffer | String} The chunk to be transformed. Will **always** +* `chunk` {Buffer|String} The chunk to be transformed. Will **always** be a buffer unless the `decodeStrings` option was set to `false`. * `encoding` {String} If the chunk is a string, then this is the encoding type. If chunk is a buffer, then this is the special @@ -1165,12 +1184,12 @@ Note: **This function MUST NOT be called directly.** It should be implemented by child classes, and called by the internal Transform class methods only. -All Transform stream implementations must provide a `_transform` +All Transform stream implementations must provide a `_transform()` method to accept input and produce output. -`_transform` should do whatever has to be done in this specific +`_transform()` should do whatever has to be done in this specific Transform class, to handle the bytes being written, and pass them off -to the readable portion of the interface. Do asynchronous I/O, +to the readable portion of the interface. Do asynchronous I/O, process things, and so on. Call `transform.push(outputChunk)` 0 or more times to generate output @@ -1178,12 +1197,12 @@ from this input chunk, depending on how much data you want to output as a result of this chunk. Call the callback function only when the current chunk is completely -consumed. Note that there may or may not be output as a result of any +consumed. Note that there may or may not be output as a result of any particular input chunk. If you supply a second argument to the callback it will be passed to the push method. In other words the following are equivalent: -```javascript +```js transform.prototype._transform = function (data, encoding, callback) { this.push(data); callback(); @@ -1196,22 +1215,23 @@ transform.prototype._transform = function (data, encoding, callback) { This method is prefixed with an underscore because it is internal to the class that defines it, and should not be called directly by user -programs. However, you **are** expected to override this method in +programs. However, you **are** expected to override this method in your own extension classes. #### Example: `SimpleProtocol` parser v2 -The example above of a simple protocol parser can be implemented -simply by using the higher level [Transform][] stream class, similar to -the `parseHeader` and `SimpleProtocol v1` examples above. +The example [here](#stream_example_simpleprotocol_v1_sub_optimal) of a simple +protocol parser can be implemented simply by using the higher level +[Transform][] stream class, similar to the `parseHeader` and `SimpleProtocol +v1` examples. In this example, rather than providing the input as an argument, it would be piped into the parser, which is a more idiomatic Node.js stream approach. ```javascript -var util = require('util'); -var Transform = require('stream').Transform; +const util = require('util'); +const Transform = require('stream').Transform; util.inherits(SimpleProtocol, Transform); function SimpleProtocol(options) { @@ -1282,22 +1302,30 @@ SimpleProtocol.prototype._transform = function(chunk, encoding, done) { `stream.Writable` is an abstract class designed to be extended with an -underlying implementation of the [`_write(chunk, encoding, callback)`][] method. +underlying implementation of the +[`stream._write(chunk, encoding, callback)`][stream-_write] method. -Please see above under [API for Stream Consumers][] for how to consume -writable streams in your programs. What follows is an explanation of +Please see [API for Stream Consumers][] for how to consume +writable streams in your programs. What follows is an explanation of how to implement Writable streams in your programs. #### new stream.Writable([options]) * `options` {Object} - * `highWaterMark` {Number} Buffer level when [`write()`][] starts - returning false. Default=16kb, or 16 for `objectMode` streams + * `highWaterMark` {Number} Buffer level when + [`stream.write()`][stream-write] starts returning `false`. Default = `16384` + (16kb), or `16` for `objectMode` streams. * `decodeStrings` {Boolean} Whether or not to decode strings into - Buffers before passing them to [`_write()`][]. Default=true - * `objectMode` {Boolean} Whether or not the `write(anyObj)` is - a valid operation. If set you can write arbitrary data instead - of only `Buffer` / `String` data. Default=false + Buffers before passing them to [`stream._write()`][stream-_write]. + Default = `true` + * `objectMode` {Boolean} Whether or not the + [`stream.write(anyObj)`][stream-write] is a valid operation. If set you can + write arbitrary data instead of only `Buffer` / `String` data. + Default = `false` + * `write` {Function} Implementation for the + [`stream._write()`][stream-_write] method. + * `writev` {Function} Implementation for the + [`stream._writev()`][stream-_writev] method. In classes that extend the Writable class, make sure to call the constructor so that the buffering settings can be properly @@ -1305,7 +1333,7 @@ initialized. #### writable.\_write(chunk, encoding, callback) -* `chunk` {Buffer | String} The chunk to be written. Will **always** +* `chunk` {Buffer|String} The chunk to be written. Will **always** be a buffer unless the `decodeStrings` option was set to `false`. * `encoding` {String} If the chunk is a string, then this is the encoding type. If chunk is a buffer, then this is the special @@ -1313,8 +1341,9 @@ initialized. * `callback` {Function} Call this function (optionally with an error argument) when you are done processing the supplied chunk. -All Writable stream implementations must provide a [`_write()`][] -method to send data to the underlying resource. +All Writable stream implementations must provide a +[`stream._write()`][stream-_write] method to send data to the underlying +resource. Note: **This function MUST NOT be called directly.** It should be implemented by child classes, and called by the internal Writable @@ -1325,20 +1354,20 @@ signal that the write completed successfully or with an error. If the `decodeStrings` flag is set in the constructor options, then `chunk` may be a string rather than a Buffer, and `encoding` will -indicate the sort of string that it is. This is to support +indicate the sort of string that it is. This is to support implementations that have an optimized handling for certain string -data encodings. If you do not explicitly set the `decodeStrings` +data encodings. If you do not explicitly set the `decodeStrings` option to `false`, then you can safely ignore the `encoding` argument, and assume that `chunk` will always be a Buffer. This method is prefixed with an underscore because it is internal to the class that defines it, and should not be called directly by user -programs. However, you **are** expected to override this method in +programs. However, you **are** expected to override this method in your own extension classes. #### writable.\_writev(chunks, callback) -* `chunks` {Array} The chunks to be written. Each chunk has following +* `chunks` {Array} The chunks to be written. Each chunk has following format: `{ chunk: ..., encoding: ... }`. * `callback` {Function} Call this function (optionally with an error argument) when you are done processing the supplied chunks. @@ -1348,7 +1377,7 @@ implemented by child classes, and called by the internal Writable class methods only. This function is completely optional to implement. In most cases it is -unnecessary. If implemented, it will be called with all the chunks +unnecessary. If implemented, it will be called with all the chunks that are buffered in the write queue. @@ -1356,14 +1385,16 @@ that are buffered in the write queue. -In simple cases there is now the added benefit of being able to construct a stream without inheritance. +In simple cases there is now the added benefit of being able to construct a +stream without inheritance. This can be done by passing the appropriate methods as constructor options: Examples: ### Duplex -```javascript + +```js var duplex = new stream.Duplex({ read: function(n) { // sets this._read under the hood @@ -1400,7 +1431,8 @@ var duplex = new stream.Duplex({ ``` ### Readable -```javascript + +```js var readable = new stream.Readable({ read: function(n) { // sets this._read under the hood @@ -1413,7 +1445,8 @@ var readable = new stream.Readable({ ``` ### Transform -```javascript + +```js var transform = new stream.Transform({ transform: function(chunk, encoding, next) { // sets this._transform under the hood @@ -1436,7 +1469,8 @@ var transform = new stream.Transform({ ``` ### Writable -```javascript + +```js var writable = new stream.Writable({ write: function(chunk, encoding, next) { // sets this._write under the hood @@ -1474,14 +1508,14 @@ The amount of data that will potentially be buffered depends on the `highWaterMark` option which is passed into the constructor. Buffering in Readable streams happens when the implementation calls -[`stream.push(chunk)`][]. If the consumer of the Stream does not call -`stream.read()`, then the data will sit in the internal queue until it -is consumed. +[`stream.push(chunk)`][stream-push]. If the consumer of the Stream does not +call [`stream.read()`][stream-read], then the data will sit in the internal +queue until it is consumed. Buffering in Writable streams happens when the user calls -[`stream.write(chunk)`][] repeatedly, even when `write()` returns `false`. +[`stream.write(chunk)`][stream-write] repeatedly, even when it returns `false`. -The purpose of streams, especially with the `pipe()` method, is to +The purpose of streams, especially with the [`stream.pipe()`][] method, is to limit the buffering of data to acceptable levels, so that sources and destinations of varying speed will not overwhelm the available memory. @@ -1492,36 +1526,37 @@ destinations of varying speed will not overwhelm the available memory. In versions of Node.js prior to v0.10, the Readable stream interface was simpler, but also less powerful and less useful. -* Rather than waiting for you to call the `read()` method, `'data'` - events would start emitting immediately. If you needed to do some - I/O to decide how to handle data, then you had to store the chunks +* Rather than waiting for you to call the [`stream.read()`][stream-read] method, + [`'data'`][] events would start emitting immediately. If you needed to do + some I/O to decide how to handle data, then you had to store the chunks in some kind of buffer so that they would not be lost. -* The [`pause()`][] method was advisory, rather than guaranteed. This - meant that you still had to be prepared to receive `'data'` events - even when the stream was in a paused state. +* The [`stream.pause()`][stream-pause] method was advisory, rather than + guaranteed. This meant that you still had to be prepared to receive + [`'data'`][] events even when the stream was in a paused state. -In Node.js v0.10, the Readable class described below was added. +In Node.js v0.10, the [Readable][] class was added. For backwards compatibility with older Node.js programs, Readable streams -switch into "flowing mode" when a `'data'` event handler is added, or -when the [`resume()`][] method is called. The effect is that, even if -you are not using the new `read()` method and `'readable'` event, you -no longer have to worry about losing `'data'` chunks. +switch into "flowing mode" when a [`'data'`][] event handler is added, or +when the [`stream.resume()`][stream-resume] method is called. The effect is +that, even if you are not using the new [`stream.read()`][stream-read] method +and [`'readable'`][] event, you no longer have to worry about losing +[`'data'`][] chunks. -Most programs will continue to function normally. However, this +Most programs will continue to function normally. However, this introduces an edge case in the following conditions: -* No [`'data'` event][] handler is added. -* The [`resume()`][] method is never called. +* No [`'data'`][] event handler is added. +* The [`stream.resume()`][stream-resume] method is never called. * The stream is not piped to any writable destination. For example, consider the following code: -```javascript +```js // WARNING! BROKEN! -net.createServer(function(socket) { +net.createServer((socket) => { // we add an 'end' method, but never consume the data - socket.on('end', function() { + socket.on('end', () => { // It will never get here. socket.end('I got your message (but didnt read it)\n'); }); @@ -1530,17 +1565,17 @@ net.createServer(function(socket) { ``` In versions of Node.js prior to v0.10, the incoming message data would be -simply discarded. However, in Node.js v0.10 and beyond, +simply discarded. However, in Node.js v0.10 and beyond, the socket will remain paused forever. -The workaround in this situation is to call the `resume()` method to -start the flow of data: +The workaround in this situation is to call the +[`stream.resume()`][stream-resume] method to start the flow of data: -```javascript +```js // Workaround -net.createServer(function(socket) { +net.createServer((socket) => { - socket.on('end', function() { + socket.on('end', () => { socket.end('I got your message (but didnt read it)\n'); }); @@ -1552,7 +1587,7 @@ net.createServer(function(socket) { In addition to new Readable streams switching into flowing mode, pre-v0.10 style streams can be wrapped in a Readable class using the -`wrap()` method. +[`stream.wrap()`][] method. ### Object Mode @@ -1565,33 +1600,33 @@ Streams that are in **object mode** can emit generic JavaScript values other than Buffers and Strings. A Readable stream in object mode will always return a single item from -a call to `stream.read(size)`, regardless of what the size argument -is. +a call to [`stream.read(size)`][stream-read], regardless of what the size +argument is. A Writable stream in object mode will always ignore the `encoding` -argument to `stream.write(data, encoding)`. +argument to [`stream.write(data, encoding)`][stream-write]. The special value `null` still retains its special value for object -mode streams. That is, for object mode readable streams, `null` as a -return value from `stream.read()` indicates that there is no more -data, and [`stream.push(null)`][] will signal the end of stream data +mode streams. That is, for object mode readable streams, `null` as a +return value from [`stream.read()`][stream-read] indicates that there is no more +data, and [`stream.push(null)`][stream-push] will signal the end of stream data (`EOF`). -No streams in Node.js core are object mode streams. This pattern is only +No streams in Node.js core are object mode streams. This pattern is only used by userland streaming libraries. You should set `objectMode` in your stream child class constructor on -the options object. Setting `objectMode` mid-stream is not safe. +the options object. Setting `objectMode` mid-stream is not safe. For Duplex streams `objectMode` can be set exclusively for readable or writable side with `readableObjectMode` and `writableObjectMode` respectively. These options can be used to implement parsers and serializers with Transform streams. -```javascript -var util = require('util'); -var StringDecoder = require('string_decoder').StringDecoder; -var Transform = require('stream').Transform; +```js +const util = require('util'); +const StringDecoder = require('string_decoder').StringDecoder; +const Transform = require('stream').Transform; util.inherits(JSONParseStream, Transform); // Gets \n-delimited JSON string data, and emits the parsed objects @@ -1646,12 +1681,12 @@ JSONParseStream.prototype._flush = function(cb) { There are some cases where you want to trigger a refresh of the underlying readable stream mechanisms, without actually consuming any -data. In that case, you can call `stream.read(0)`, which will always +data. In that case, you can call `stream.read(0)`, which will always return null. If the internal read buffer is below the `highWaterMark`, and the -stream is not currently reading, then calling `read(0)` will trigger -a low-level `_read` call. +stream is not currently reading, then calling `stream.read(0)` will trigger +a low-level [`stream._read()`][stream-_read] call. There is almost never a need to do this. However, you will see some cases in Node.js's internals where this is done, particularly in the @@ -1660,71 +1695,66 @@ Readable stream class internals. ### `stream.push('')` Pushing a zero-byte string or Buffer (when not in [Object mode][]) has an -interesting side effect. Because it *is* a call to -[`stream.push()`][], it will end the `reading` process. However, it +interesting side effect. Because it *is* a call to +[`stream.push()`][stream-push], it will end the `reading` process. However, it does *not* add any data to the readable buffer, so there's nothing for a user to consume. Very rarely, there are cases where you have no data to provide now, but the consumer of your stream (or, perhaps, another bit of your own -code) will know when to check again, by calling `stream.read(0)`. In -those cases, you *may* call `stream.push('')`. +code) will know when to check again, by calling [`stream.read(0)`][stream-read]. +In those cases, you *may* call `stream.push('')`. So far, the only use case for this functionality is in the -[tls.CryptoStream][] class, which is deprecated in Node.js/io.js v1.0. If you +[`tls.CryptoStream`][] class, which is deprecated in Node.js/io.js v1.0. If you find that you have to use `stream.push('')`, please consider another approach, because it almost certainly indicates that something is horribly wrong. -[request to an HTTP server]: https://nodejs.org/docs/v5.1.0/api/http.html#http_http_incomingmessage -[EventEmitter]: https://nodejs.org/docs/v5.1.0/api/events.html#events_class_events_eventemitter -[Object mode]: #stream_object_mode -[`stream.push(chunk)`]: #stream_readable_push_chunk_encoding -[`stream.push(null)`]: #stream_readable_push_chunk_encoding -[`stream.push()`]: #stream_readable_push_chunk_encoding -[`unpipe()`]: #stream_readable_unpipe_destination -[unpiped]: #stream_readable_unpipe_destination -[tcp sockets]: https://nodejs.org/docs/v5.1.0/api/net.html#net_class_net_socket -[http responses, on the client]: https://nodejs.org/docs/v5.1.0/api/http.html#http_http_incomingmessage -[http requests, on the server]: https://nodejs.org/docs/v5.1.0/api/http.html#http_http_incomingmessage -[http requests, on the client]: https://nodejs.org/docs/v5.1.0/api/http.html#http_class_http_clientrequest -[http responses, on the server]: https://nodejs.org/docs/v5.1.0/api/http.html#http_class_http_serverresponse -[fs read streams]: https://nodejs.org/docs/v5.1.0/api/fs.html#fs_class_fs_readstream -[fs write streams]: https://nodejs.org/docs/v5.1.0/api/fs.html#fs_class_fs_writestream -[zlib streams]: zlib.html -[zlib]: zlib.html -[crypto streams]: crypto.html -[crypto]: crypto.html -[tls.CryptoStream]: https://nodejs.org/docs/v5.1.0/api/tls.html#tls_class_cryptostream -[process.stdin]: https://nodejs.org/docs/v5.1.0/api/process.html#process_process_stdin -[stdout]: https://nodejs.org/docs/v5.1.0/api/process.html#process_process_stdout -[process.stdout]: https://nodejs.org/docs/v5.1.0/api/process.html#process_process_stdout -[process.stderr]: https://nodejs.org/docs/v5.1.0/api/process.html#process_process_stderr -[child process stdout and stderr]: https://nodejs.org/docs/v5.1.0/api/child_process.html#child_process_child_stdout -[child process stdin]: https://nodejs.org/docs/v5.1.0/api/child_process.html#child_process_child_stdin +[`'data'`]: #stream_event_data +[`'drain'`]: #stream_event_drain +[`'end'`]: #stream_event_end +[`'finish'`]: #stream_event_finish +[`'readable'`]: #stream_event_readable +[`buf.toString(encoding)`]: https://nodejs.org/docs/v5.8.0/api/buffer.html#buffer_buf_tostring_encoding_start_end +[`EventEmitter`]: https://nodejs.org/docs/v5.8.0/api/events.html#events_class_eventemitter +[`process.stderr`]: https://nodejs.org/docs/v5.8.0/api/process.html#process_process_stderr +[`process.stdin`]: https://nodejs.org/docs/v5.8.0/api/process.html#process_process_stdin +[`process.stdout`]: https://nodejs.org/docs/v5.8.0/api/process.html#process_process_stdout +[`stream.cork()`]: #stream_writable_cork +[`stream.pipe()`]: #stream_readable_pipe_destination_options +[`stream.uncork()`]: #stream_writable_uncork +[`stream.unpipe()`]: #stream_readable_unpipe_destination +[`stream.wrap()`]: #stream_readable_wrap_stream +[`tls.CryptoStream`]: https://nodejs.org/docs/v5.8.0/api/tls.html#tls_class_cryptostream +[`util.inherits()`]: https://nodejs.org/docs/v5.8.0/api/util.html#util_util_inherits_constructor_superconstructor [API for Stream Consumers]: #stream_api_for_stream_consumers [API for Stream Implementors]: #stream_api_for_stream_implementors -[Readable]: #stream_class_stream_readable -[Writable]: #stream_class_stream_writable +[child process stdin]: https://nodejs.org/docs/v5.8.0/api/child_process.html#child_process_child_stdin +[child process stdout and stderr]: https://nodejs.org/docs/v5.8.0/api/child_process.html#child_process_child_stdout +[Compatibility]: #stream_compatibility_with_older_node_js_versions +[crypto]: crypto.html [Duplex]: #stream_class_stream_duplex +[fs read streams]: https://nodejs.org/docs/v5.8.0/api/fs.html#fs_class_fs_readstream +[fs write streams]: https://nodejs.org/docs/v5.8.0/api/fs.html#fs_class_fs_writestream +[HTTP requests, on the client]: https://nodejs.org/docs/v5.8.0/api/http.html#http_class_http_clientrequest +[HTTP responses, on the server]: https://nodejs.org/docs/v5.8.0/api/http.html#http_class_http_serverresponse +[http-incoming-message]: https://nodejs.org/docs/v5.8.0/api/http.html#http_class_http_incomingmessage +[Object mode]: #stream_object_mode +[Readable]: #stream_class_stream_readable +[SimpleProtocol v2]: #stream_example_simpleprotocol_parser_v2 +[stream-_flush]: #stream_transform_flush_callback +[stream-_read]: #stream_readable_read_size_1 +[stream-_transform]: #stream_transform_transform_chunk_encoding_callback +[stream-_write]: #stream_writable_write_chunk_encoding_callback_1 +[stream-_writev]: #stream_writable_writev_chunks_callback +[stream-end]: #stream_writable_end_chunk_encoding_callback +[stream-pause]: #stream_readable_pause +[stream-push]: #stream_readable_push_chunk_encoding +[stream-read]: #stream_readable_read_size +[stream-resume]: #stream_readable_resume +[stream-write]: #stream_writable_write_chunk_encoding_callback +[TCP sockets]: https://nodejs.org/docs/v5.8.0/api/net.html#net_class_net_socket [Transform]: #stream_class_stream_transform -[`end`]: #stream_event_end -[`finish`]: #stream_event_finish -[`_read(size)`]: #stream_readable_read_size_1 -[`_read()`]: #stream_readable_read_size_1 -[_read]: #stream_readable_read_size_1 -[`writable.write(chunk)`]: #stream_writable_write_chunk_encoding_callback -[`write(chunk, encoding, callback)`]: #stream_writable_write_chunk_encoding_callback -[`write()`]: #stream_writable_write_chunk_encoding_callback -[`stream.write(chunk)`]: #stream_writable_write_chunk_encoding_callback -[`_write(chunk, encoding, callback)`]: #stream_writable_write_chunk_encoding_callback_1 -[`_write()`]: #stream_writable_write_chunk_encoding_callback_1 -[_write]: #stream_writable_write_chunk_encoding_callback_1 -[`util.inherits`]: https://nodejs.org/docs/v5.1.0/api/util.html#util_util_inherits_constructor_superconstructor -[`end()`]: #stream_writable_end_chunk_encoding_callback -[`'data'` event]: #stream_event_data -[`resume()`]: #stream_readable_resume -[`readable.resume()`]: #stream_readable_resume -[`pause()`]: #stream_readable_pause -[`unpipe()`]: #stream_readable_unpipe_destination -[`pipe()`]: #stream_readable_pipe_destination_options +[Writable]: #stream_class_stream_writable +[zlib]: zlib.html diff --git a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/lib/_stream_duplex.js b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/lib/_stream_duplex.js index 69558af037cd66..736693b8400fed 100644 --- a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/lib/_stream_duplex.js +++ b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/lib/_stream_duplex.js @@ -6,22 +6,21 @@ 'use strict'; /**/ + var objectKeys = Object.keys || function (obj) { var keys = []; - for (var key in obj) keys.push(key); - return keys; -} + for (var key in obj) { + keys.push(key); + }return keys; +}; /**/ - module.exports = Duplex; /**/ var processNextTick = require('process-nextick-args'); /**/ - - /**/ var util = require('core-util-is'); util.inherits = require('inherits'); @@ -35,26 +34,21 @@ util.inherits(Duplex, Readable); var keys = objectKeys(Writable.prototype); for (var v = 0; v < keys.length; v++) { var method = keys[v]; - if (!Duplex.prototype[method]) - Duplex.prototype[method] = Writable.prototype[method]; + if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method]; } function Duplex(options) { - if (!(this instanceof Duplex)) - return new Duplex(options); + if (!(this instanceof Duplex)) return new Duplex(options); Readable.call(this, options); Writable.call(this, options); - if (options && options.readable === false) - this.readable = false; + if (options && options.readable === false) this.readable = false; - if (options && options.writable === false) - this.writable = false; + if (options && options.writable === false) this.writable = false; this.allowHalfOpen = true; - if (options && options.allowHalfOpen === false) - this.allowHalfOpen = false; + if (options && options.allowHalfOpen === false) this.allowHalfOpen = false; this.once('end', onend); } @@ -63,8 +57,7 @@ function Duplex(options) { function onend() { // if we allow half-open state, or if the writable side ended, // then we're ok. - if (this.allowHalfOpen || this._writableState.ended) - return; + if (this.allowHalfOpen || this._writableState.ended) return; // no more data can be written. // But allow more writes to happen in this tick. @@ -75,8 +68,8 @@ function onEndNT(self) { self.end(); } -function forEach (xs, f) { +function forEach(xs, f) { for (var i = 0, l = xs.length; i < l; i++) { f(xs[i], i); } -} +} \ No newline at end of file diff --git a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/lib/_stream_passthrough.js b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/lib/_stream_passthrough.js index bddfdd01537a40..d06f71f1868d77 100644 --- a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/lib/_stream_passthrough.js +++ b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/lib/_stream_passthrough.js @@ -16,12 +16,11 @@ util.inherits = require('inherits'); util.inherits(PassThrough, Transform); function PassThrough(options) { - if (!(this instanceof PassThrough)) - return new PassThrough(options); + if (!(this instanceof PassThrough)) return new PassThrough(options); Transform.call(this, options); } -PassThrough.prototype._transform = function(chunk, encoding, cb) { +PassThrough.prototype._transform = function (chunk, encoding, cb) { cb(null, chunk); -}; +}; \ No newline at end of file diff --git a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/lib/_stream_readable.js b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/lib/_stream_readable.js index 50852aee7e6e02..54a9d5c553d69e 100644 --- a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/lib/_stream_readable.js +++ b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/lib/_stream_readable.js @@ -6,12 +6,10 @@ module.exports = Readable; var processNextTick = require('process-nextick-args'); /**/ - /**/ var isArray = require('isarray'); /**/ - /**/ var Buffer = require('buffer').Buffer; /**/ @@ -21,21 +19,20 @@ Readable.ReadableState = ReadableState; var EE = require('events'); /**/ -var EElistenerCount = function(emitter, type) { +var EElistenerCount = function (emitter, type) { return emitter.listeners(type).length; }; /**/ - - /**/ var Stream; -(function (){try{ - Stream = require('st' + 'ream'); -}catch(_){}finally{ - if (!Stream) - Stream = require('events').EventEmitter; -}}()) +(function () { + try { + Stream = require('st' + 'ream'); + } catch (_) {} finally { + if (!Stream) Stream = require('events').EventEmitter; + } +})(); /**/ var Buffer = require('buffer').Buffer; @@ -45,11 +42,9 @@ var util = require('core-util-is'); util.inherits = require('inherits'); /**/ - - /**/ var debugUtil = require('util'); -var debug; +var debug = undefined; if (debugUtil && debugUtil.debuglog) { debug = debugUtil.debuglog('stream'); } else { @@ -71,17 +66,16 @@ function ReadableState(options, stream) { // make all the buffer merging and length checks go away this.objectMode = !!options.objectMode; - if (stream instanceof Duplex) - this.objectMode = this.objectMode || !!options.readableObjectMode; + if (stream instanceof Duplex) this.objectMode = this.objectMode || !!options.readableObjectMode; // the point at which it stops calling _read() to fill the buffer // Note: 0 is a valid value, means "don't call _read preemptively ever" var hwm = options.highWaterMark; var defaultHwm = this.objectMode ? 16 : 16 * 1024; - this.highWaterMark = (hwm || hwm === 0) ? hwm : defaultHwm; + this.highWaterMark = hwm || hwm === 0 ? hwm : defaultHwm; // cast to ints. - this.highWaterMark = ~~this.highWaterMark; + this.highWaterMark = ~ ~this.highWaterMark; this.buffer = []; this.length = 0; @@ -103,6 +97,7 @@ function ReadableState(options, stream) { this.needReadable = false; this.emittedReadable = false; this.readableListening = false; + this.resumeScheduled = false; // Crypto is kind of old and crusty. Historically, its default string // encoding is 'binary' so we have to make this configurable. @@ -122,8 +117,7 @@ function ReadableState(options, stream) { this.decoder = null; this.encoding = null; if (options.encoding) { - if (!StringDecoder) - StringDecoder = require('string_decoder/').StringDecoder; + if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder; this.decoder = new StringDecoder(options.encoding); this.encoding = options.encoding; } @@ -133,16 +127,14 @@ var Duplex; function Readable(options) { Duplex = Duplex || require('./_stream_duplex'); - if (!(this instanceof Readable)) - return new Readable(options); + if (!(this instanceof Readable)) return new Readable(options); this._readableState = new ReadableState(options, this); // legacy this.readable = true; - if (options && typeof options.read === 'function') - this._read = options.read; + if (options && typeof options.read === 'function') this._read = options.read; Stream.call(this); } @@ -151,7 +143,7 @@ function Readable(options) { // This returns true if the highWaterMark has not been hit yet, // similar to how Writable.write() returns true if you should // write() some more. -Readable.prototype.push = function(chunk, encoding) { +Readable.prototype.push = function (chunk, encoding) { var state = this._readableState; if (!state.objectMode && typeof chunk === 'string') { @@ -166,12 +158,12 @@ Readable.prototype.push = function(chunk, encoding) { }; // Unshift should *always* be something directly out of read() -Readable.prototype.unshift = function(chunk) { +Readable.prototype.unshift = function (chunk) { var state = this._readableState; return readableAddChunk(this, state, chunk, '', true); }; -Readable.prototype.isPaused = function() { +Readable.prototype.isPaused = function () { return this._readableState.flowing === false; }; @@ -190,26 +182,28 @@ function readableAddChunk(stream, state, chunk, encoding, addToFront) { var e = new Error('stream.unshift() after end event'); stream.emit('error', e); } else { - if (state.decoder && !addToFront && !encoding) + var skipAdd; + if (state.decoder && !addToFront && !encoding) { chunk = state.decoder.write(chunk); + skipAdd = !state.objectMode && chunk.length === 0; + } - if (!addToFront) - state.reading = false; - - // if we want the data now, just emit it. - if (state.flowing && state.length === 0 && !state.sync) { - stream.emit('data', chunk); - stream.read(0); - } else { - // update the buffer info. - state.length += state.objectMode ? 1 : chunk.length; - if (addToFront) - state.buffer.unshift(chunk); - else - state.buffer.push(chunk); - - if (state.needReadable) - emitReadable(stream); + if (!addToFront) state.reading = false; + + // Don't add to the buffer if we've decoded to an empty string chunk and + // we're not in object mode + if (!skipAdd) { + // if we want the data now, just emit it. + if (state.flowing && state.length === 0 && !state.sync) { + stream.emit('data', chunk); + stream.read(0); + } else { + // update the buffer info. + state.length += state.objectMode ? 1 : chunk.length; + if (addToFront) state.buffer.unshift(chunk);else state.buffer.push(chunk); + + if (state.needReadable) emitReadable(stream); + } } maybeReadMore(stream, state); @@ -221,7 +215,6 @@ function readableAddChunk(stream, state, chunk, encoding, addToFront) { return needMoreData(state); } - // if it's past the high water mark, we can push in some more. // Also, if we have no data yet, we can stand some // more bytes. This is to work around cases where hwm=0, @@ -230,16 +223,12 @@ function readableAddChunk(stream, state, chunk, encoding, addToFront) { // needReadable was set, then we ought to push more, so that another // 'readable' event will be triggered. function needMoreData(state) { - return !state.ended && - (state.needReadable || - state.length < state.highWaterMark || - state.length === 0); + return !state.ended && (state.needReadable || state.length < state.highWaterMark || state.length === 0); } // backwards compatibility. -Readable.prototype.setEncoding = function(enc) { - if (!StringDecoder) - StringDecoder = require('string_decoder/').StringDecoder; +Readable.prototype.setEncoding = function (enc) { + if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder; this._readableState.decoder = new StringDecoder(enc); this._readableState.encoding = enc; return this; @@ -264,29 +253,22 @@ function computeNewHighWaterMark(n) { } function howMuchToRead(n, state) { - if (state.length === 0 && state.ended) - return 0; + if (state.length === 0 && state.ended) return 0; - if (state.objectMode) - return n === 0 ? 0 : 1; + if (state.objectMode) return n === 0 ? 0 : 1; if (n === null || isNaN(n)) { // only flow one buffer at a time - if (state.flowing && state.buffer.length) - return state.buffer[0].length; - else - return state.length; + if (state.flowing && state.buffer.length) return state.buffer[0].length;else return state.length; } - if (n <= 0) - return 0; + if (n <= 0) return 0; // If we're asking for more than the target buffer level, // then raise the water mark. Bump up to the next highest // power of 2, to prevent increasing it excessively in tiny // amounts. - if (n > state.highWaterMark) - state.highWaterMark = computeNewHighWaterMark(n); + if (n > state.highWaterMark) state.highWaterMark = computeNewHighWaterMark(n); // don't have that much. return null, unless we've ended. if (n > state.length) { @@ -302,25 +284,19 @@ function howMuchToRead(n, state) { } // you can override either this method, or the async _read(n) below. -Readable.prototype.read = function(n) { +Readable.prototype.read = function (n) { debug('read', n); var state = this._readableState; var nOrig = n; - if (typeof n !== 'number' || n > 0) - state.emittedReadable = false; + if (typeof n !== 'number' || n > 0) state.emittedReadable = false; // if we're doing read(0) to trigger a readable event, but we // already have a bunch of data in the buffer, then just trigger // the 'readable' event and move on. - if (n === 0 && - state.needReadable && - (state.length >= state.highWaterMark || state.ended)) { + if (n === 0 && state.needReadable && (state.length >= state.highWaterMark || state.ended)) { debug('read: emitReadable', state.length, state.ended); - if (state.length === 0 && state.ended) - endReadable(this); - else - emitReadable(this); + if (state.length === 0 && state.ended) endReadable(this);else emitReadable(this); return null; } @@ -328,8 +304,7 @@ Readable.prototype.read = function(n) { // if we've ended, and we're now clear, then finish it up. if (n === 0 && state.ended) { - if (state.length === 0) - endReadable(this); + if (state.length === 0) endReadable(this); return null; } @@ -377,8 +352,7 @@ Readable.prototype.read = function(n) { state.reading = true; state.sync = true; // if the length is currently zero, then we *need* a readable event. - if (state.length === 0) - state.needReadable = true; + if (state.length === 0) state.needReadable = true; // call internal read method this._read(state.highWaterMark); state.sync = false; @@ -386,14 +360,10 @@ Readable.prototype.read = function(n) { // If _read pushed data synchronously, then `reading` will be false, // and we need to re-evaluate how much data we can return to the user. - if (doRead && !state.reading) - n = howMuchToRead(nOrig, state); + if (doRead && !state.reading) n = howMuchToRead(nOrig, state); var ret; - if (n > 0) - ret = fromList(n, state); - else - ret = null; + if (n > 0) ret = fromList(n, state);else ret = null; if (ret === null) { state.needReadable = true; @@ -404,32 +374,24 @@ Readable.prototype.read = function(n) { // If we have nothing in the buffer, then we want to know // as soon as we *do* get something into the buffer. - if (state.length === 0 && !state.ended) - state.needReadable = true; + if (state.length === 0 && !state.ended) state.needReadable = true; // If we tried to read() past the EOF, then emit end on the next tick. - if (nOrig !== n && state.ended && state.length === 0) - endReadable(this); + if (nOrig !== n && state.ended && state.length === 0) endReadable(this); - if (ret !== null) - this.emit('data', ret); + if (ret !== null) this.emit('data', ret); return ret; }; function chunkInvalid(state, chunk) { var er = null; - if (!(Buffer.isBuffer(chunk)) && - typeof chunk !== 'string' && - chunk !== null && - chunk !== undefined && - !state.objectMode) { + if (!Buffer.isBuffer(chunk) && typeof chunk !== 'string' && chunk !== null && chunk !== undefined && !state.objectMode) { er = new TypeError('Invalid non-string/buffer chunk'); } return er; } - function onEofChunk(stream, state) { if (state.ended) return; if (state.decoder) { @@ -454,10 +416,7 @@ function emitReadable(stream) { if (!state.emittedReadable) { debug('emitReadable', state.flowing); state.emittedReadable = true; - if (state.sync) - processNextTick(emitReadable_, stream); - else - emitReadable_(stream); + if (state.sync) processNextTick(emitReadable_, stream);else emitReadable_(stream); } } @@ -467,7 +426,6 @@ function emitReadable_(stream) { flow(stream); } - // at this point, the user has presumably seen the 'readable' event, // and called read() to consume some data. that may have triggered // in turn another _read(n) call, in which case reading = true if @@ -483,15 +441,12 @@ function maybeReadMore(stream, state) { function maybeReadMore_(stream, state) { var len = state.length; - while (!state.reading && !state.flowing && !state.ended && - state.length < state.highWaterMark) { + while (!state.reading && !state.flowing && !state.ended && state.length < state.highWaterMark) { debug('maybeReadMore read 0'); stream.read(0); if (len === state.length) // didn't get any data, stop spinning. - break; - else - len = state.length; + break;else len = state.length; } state.readingMore = false; } @@ -500,11 +455,11 @@ function maybeReadMore_(stream, state) { // call cb(er, data) where data is <= n in length. // for virtual (non-string, non-buffer) streams, "length" is somewhat // arbitrary, and perhaps not very meaningful. -Readable.prototype._read = function(n) { +Readable.prototype._read = function (n) { this.emit('error', new Error('not implemented')); }; -Readable.prototype.pipe = function(dest, pipeOpts) { +Readable.prototype.pipe = function (dest, pipeOpts) { var src = this; var state = this._readableState; @@ -522,15 +477,10 @@ Readable.prototype.pipe = function(dest, pipeOpts) { state.pipesCount += 1; debug('pipe count=%d opts=%j', state.pipesCount, pipeOpts); - var doEnd = (!pipeOpts || pipeOpts.end !== false) && - dest !== process.stdout && - dest !== process.stderr; + var doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process.stdout && dest !== process.stderr; var endFn = doEnd ? onend : cleanup; - if (state.endEmitted) - processNextTick(endFn); - else - src.once('end', endFn); + if (state.endEmitted) processNextTick(endFn);else src.once('end', endFn); dest.on('unpipe', onunpipe); function onunpipe(readable) { @@ -572,9 +522,7 @@ Readable.prototype.pipe = function(dest, pipeOpts) { // flowing again. // So, if this is awaiting a drain, then we just call it now. // If we don't know, then assume that we are waiting for one. - if (state.awaitDrain && - (!dest._writableState || dest._writableState.needDrain)) - ondrain(); + if (state.awaitDrain && (!dest._writableState || dest._writableState.needDrain)) ondrain(); } src.on('data', ondata); @@ -585,10 +533,7 @@ Readable.prototype.pipe = function(dest, pipeOpts) { // If the user unpiped during `dest.write()`, it is possible // to get stuck in a permanently paused state if that write // also returned false. - if (state.pipesCount === 1 && - state.pipes[0] === dest && - src.listenerCount('data') === 1 && - !cleanedUp) { + if (state.pipesCount === 1 && state.pipes[0] === dest && src.listenerCount('data') === 1 && !cleanedUp) { debug('false write response, pause', src._readableState.awaitDrain); src._readableState.awaitDrain++; } @@ -602,18 +547,11 @@ Readable.prototype.pipe = function(dest, pipeOpts) { debug('onerror', er); unpipe(); dest.removeListener('error', onerror); - if (EElistenerCount(dest, 'error') === 0) - dest.emit('error', er); + if (EElistenerCount(dest, 'error') === 0) dest.emit('error', er); } // This is a brutally ugly hack to make sure that our error handler // is attached before any userland ones. NEVER DO THIS. - if (!dest._events || !dest._events.error) - dest.on('error', onerror); - else if (isArray(dest._events.error)) - dest._events.error.unshift(onerror); - else - dest._events.error = [onerror, dest._events.error]; - + if (!dest._events || !dest._events.error) dest.on('error', onerror);else if (isArray(dest._events.error)) dest._events.error.unshift(onerror);else dest._events.error = [onerror, dest._events.error]; // Both close and finish should trigger unpipe, but only once. function onclose() { @@ -646,11 +584,10 @@ Readable.prototype.pipe = function(dest, pipeOpts) { }; function pipeOnDrain(src) { - return function() { + return function () { var state = src._readableState; debug('pipeOnDrain', state.awaitDrain); - if (state.awaitDrain) - state.awaitDrain--; + if (state.awaitDrain) state.awaitDrain--; if (state.awaitDrain === 0 && EElistenerCount(src, 'data')) { state.flowing = true; flow(src); @@ -658,29 +595,24 @@ function pipeOnDrain(src) { }; } - -Readable.prototype.unpipe = function(dest) { +Readable.prototype.unpipe = function (dest) { var state = this._readableState; // if we're not piping anywhere, then do nothing. - if (state.pipesCount === 0) - return this; + if (state.pipesCount === 0) return this; // just one destination. most common case. if (state.pipesCount === 1) { // passed in one, but it's not the right one. - if (dest && dest !== state.pipes) - return this; + if (dest && dest !== state.pipes) return this; - if (!dest) - dest = state.pipes; + if (!dest) dest = state.pipes; // got a match. state.pipes = null; state.pipesCount = 0; state.flowing = false; - if (dest) - dest.emit('unpipe', this); + if (dest) dest.emit('unpipe', this); return this; } @@ -694,20 +626,18 @@ Readable.prototype.unpipe = function(dest) { state.pipesCount = 0; state.flowing = false; - for (var i = 0; i < len; i++) - dests[i].emit('unpipe', this); - return this; + for (var _i = 0; _i < len; _i++) { + dests[_i].emit('unpipe', this); + }return this; } // try to find the right one. var i = indexOf(state.pipes, dest); - if (i === -1) - return this; + if (i === -1) return this; state.pipes.splice(i, 1); state.pipesCount -= 1; - if (state.pipesCount === 1) - state.pipes = state.pipes[0]; + if (state.pipesCount === 1) state.pipes = state.pipes[0]; dest.emit('unpipe', this); @@ -716,7 +646,7 @@ Readable.prototype.unpipe = function(dest) { // set up data events if they are asked for // Ensure readable listeners eventually get something -Readable.prototype.on = function(ev, fn) { +Readable.prototype.on = function (ev, fn) { var res = Stream.prototype.on.call(this, ev, fn); // If listening to data, and it has not explicitly been paused, @@ -725,7 +655,7 @@ Readable.prototype.on = function(ev, fn) { this.resume(); } - if (ev === 'readable' && this.readable) { + if (ev === 'readable' && !this._readableState.endEmitted) { var state = this._readableState; if (!state.readableListening) { state.readableListening = true; @@ -750,7 +680,7 @@ function nReadingNextTick(self) { // pause() and resume() are remnants of the legacy readable stream API // If the user uses them, then switch into old mode. -Readable.prototype.resume = function() { +Readable.prototype.resume = function () { var state = this._readableState; if (!state.flowing) { debug('resume'); @@ -776,11 +706,10 @@ function resume_(stream, state) { state.resumeScheduled = false; stream.emit('resume'); flow(stream); - if (state.flowing && !state.reading) - stream.read(0); + if (state.flowing && !state.reading) stream.read(0); } -Readable.prototype.pause = function() { +Readable.prototype.pause = function () { debug('call pause flowing=%j', this._readableState.flowing); if (false !== this._readableState.flowing) { debug('pause'); @@ -803,32 +732,27 @@ function flow(stream) { // wrap an old-style stream as the async data source. // This is *not* part of the readable stream interface. // It is an ugly unfortunate mess of history. -Readable.prototype.wrap = function(stream) { +Readable.prototype.wrap = function (stream) { var state = this._readableState; var paused = false; var self = this; - stream.on('end', function() { + stream.on('end', function () { debug('wrapped end'); if (state.decoder && !state.ended) { var chunk = state.decoder.end(); - if (chunk && chunk.length) - self.push(chunk); + if (chunk && chunk.length) self.push(chunk); } self.push(null); }); - stream.on('data', function(chunk) { + stream.on('data', function (chunk) { debug('wrapped data'); - if (state.decoder) - chunk = state.decoder.write(chunk); + if (state.decoder) chunk = state.decoder.write(chunk); // don't skip over falsy values in objectMode - if (state.objectMode && (chunk === null || chunk === undefined)) - return; - else if (!state.objectMode && (!chunk || !chunk.length)) - return; + if (state.objectMode && (chunk === null || chunk === undefined)) return;else if (!state.objectMode && (!chunk || !chunk.length)) return; var ret = self.push(chunk); if (!ret) { @@ -841,21 +765,23 @@ Readable.prototype.wrap = function(stream) { // important when wrapping filters and duplexes. for (var i in stream) { if (this[i] === undefined && typeof stream[i] === 'function') { - this[i] = function(method) { return function() { - return stream[method].apply(stream, arguments); - }; }(i); + this[i] = function (method) { + return function () { + return stream[method].apply(stream, arguments); + }; + }(i); } } // proxy certain important events. var events = ['error', 'close', 'destroy', 'pause', 'resume']; - forEach(events, function(ev) { + forEach(events, function (ev) { stream.on(ev, self.emit.bind(self, ev)); }); // when we try to consume some more bytes, simply unpause the // underlying stream. - self._read = function(n) { + self._read = function (n) { debug('wrapped _read', n); if (paused) { paused = false; @@ -866,7 +792,6 @@ Readable.prototype.wrap = function(stream) { return self; }; - // exposed for testing purposes only. Readable._fromList = fromList; @@ -880,21 +805,11 @@ function fromList(n, state) { var ret; // nothing in the list, definitely empty. - if (list.length === 0) - return null; + if (list.length === 0) return null; - if (length === 0) - ret = null; - else if (objectMode) - ret = list.shift(); - else if (!n || n >= length) { + if (length === 0) ret = null;else if (objectMode) ret = list.shift();else if (!n || n >= length) { // read it all, truncate the array. - if (stringMode) - ret = list.join(''); - else if (list.length === 1) - ret = list[0]; - else - ret = Buffer.concat(list, length); + if (stringMode) ret = list.join('');else if (list.length === 1) ret = list[0];else ret = Buffer.concat(list, length); list.length = 0; } else { // read just some of it. @@ -910,25 +825,16 @@ function fromList(n, state) { } else { // complex case. // we have enough to cover it, but it spans past the first buffer. - if (stringMode) - ret = ''; - else - ret = new Buffer(n); + if (stringMode) ret = '';else ret = new Buffer(n); var c = 0; for (var i = 0, l = list.length; i < l && c < n; i++) { var buf = list[0]; var cpy = Math.min(n - c, buf.length); - if (stringMode) - ret += buf.slice(0, cpy); - else - buf.copy(ret, c, 0, cpy); + if (stringMode) ret += buf.slice(0, cpy);else buf.copy(ret, c, 0, cpy); - if (cpy < buf.length) - list[0] = buf.slice(cpy); - else - list.shift(); + if (cpy < buf.length) list[0] = buf.slice(cpy);else list.shift(); c += cpy; } @@ -943,8 +849,7 @@ function endReadable(stream) { // If we get here before consuming all the bytes, then that is a // bug in node. Should never happen. - if (state.length > 0) - throw new Error('endReadable called on non-empty stream'); + if (state.length > 0) throw new Error('endReadable called on non-empty stream'); if (!state.endEmitted) { state.ended = true; @@ -961,15 +866,15 @@ function endReadableNT(state, stream) { } } -function forEach (xs, f) { +function forEach(xs, f) { for (var i = 0, l = xs.length; i < l; i++) { f(xs[i], i); } } -function indexOf (xs, x) { +function indexOf(xs, x) { for (var i = 0, l = xs.length; i < l; i++) { if (xs[i] === x) return i; } return -1; -} +} \ No newline at end of file diff --git a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/lib/_stream_transform.js b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/lib/_stream_transform.js index 3675d18d915610..625cdc17698059 100644 --- a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/lib/_stream_transform.js +++ b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/lib/_stream_transform.js @@ -53,9 +53,8 @@ util.inherits = require('inherits'); util.inherits(Transform, Duplex); - function TransformState(stream) { - this.afterTransform = function(er, data) { + this.afterTransform = function (er, data) { return afterTransform(stream, er, data); }; @@ -63,6 +62,7 @@ function TransformState(stream) { this.transforming = false; this.writecb = null; this.writechunk = null; + this.writeencoding = null; } function afterTransform(stream, er, data) { @@ -71,17 +71,14 @@ function afterTransform(stream, er, data) { var cb = ts.writecb; - if (!cb) - return stream.emit('error', new Error('no writecb in Transform class')); + if (!cb) return stream.emit('error', new Error('no writecb in Transform class')); ts.writechunk = null; ts.writecb = null; - if (data !== null && data !== undefined) - stream.push(data); + if (data !== null && data !== undefined) stream.push(data); - if (cb) - cb(er); + cb(er); var rs = stream._readableState; rs.reading = false; @@ -90,10 +87,8 @@ function afterTransform(stream, er, data) { } } - function Transform(options) { - if (!(this instanceof Transform)) - return new Transform(options); + if (!(this instanceof Transform)) return new Transform(options); Duplex.call(this, options); @@ -111,24 +106,19 @@ function Transform(options) { this._readableState.sync = false; if (options) { - if (typeof options.transform === 'function') - this._transform = options.transform; + if (typeof options.transform === 'function') this._transform = options.transform; - if (typeof options.flush === 'function') - this._flush = options.flush; + if (typeof options.flush === 'function') this._flush = options.flush; } - this.once('prefinish', function() { - if (typeof this._flush === 'function') - this._flush(function(er) { - done(stream, er); - }); - else - done(stream); + this.once('prefinish', function () { + if (typeof this._flush === 'function') this._flush(function (er) { + done(stream, er); + });else done(stream); }); } -Transform.prototype.push = function(chunk, encoding) { +Transform.prototype.push = function (chunk, encoding) { this._transformState.needTransform = false; return Duplex.prototype.push.call(this, chunk, encoding); }; @@ -143,28 +133,25 @@ Transform.prototype.push = function(chunk, encoding) { // Call `cb(err)` when you are done with this chunk. If you pass // an error, then that'll put the hurt on the whole operation. If you // never call cb(), then you'll never get another chunk. -Transform.prototype._transform = function(chunk, encoding, cb) { +Transform.prototype._transform = function (chunk, encoding, cb) { throw new Error('not implemented'); }; -Transform.prototype._write = function(chunk, encoding, cb) { +Transform.prototype._write = function (chunk, encoding, cb) { var ts = this._transformState; ts.writecb = cb; ts.writechunk = chunk; ts.writeencoding = encoding; if (!ts.transforming) { var rs = this._readableState; - if (ts.needTransform || - rs.needReadable || - rs.length < rs.highWaterMark) - this._read(rs.highWaterMark); + if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) this._read(rs.highWaterMark); } }; // Doesn't matter what the args are here. // _transform does all the work. // That we got here means that the readable side wants more data. -Transform.prototype._read = function(n) { +Transform.prototype._read = function (n) { var ts = this._transformState; if (ts.writechunk !== null && ts.writecb && !ts.transforming) { @@ -177,21 +164,17 @@ Transform.prototype._read = function(n) { } }; - function done(stream, er) { - if (er) - return stream.emit('error', er); + if (er) return stream.emit('error', er); // if there's nothing in the write buffer, then that means // that nothing more will ever be provided var ws = stream._writableState; var ts = stream._transformState; - if (ws.length) - throw new Error('calling transform done when ws.length != 0'); + if (ws.length) throw new Error('calling transform done when ws.length != 0'); - if (ts.transforming) - throw new Error('calling transform done when still transforming'); + if (ts.transforming) throw new Error('calling transform done when still transforming'); return stream.push(null); -} +} \ No newline at end of file diff --git a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/lib/_stream_writable.js b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/lib/_stream_writable.js index 1fa5eb695adde6..95916c992a9507 100644 --- a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/lib/_stream_writable.js +++ b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/lib/_stream_writable.js @@ -10,6 +10,9 @@ module.exports = Writable; var processNextTick = require('process-nextick-args'); /**/ +/**/ +var asyncWrite = !process.browser && ['v0.10', 'v0.9.'].indexOf(process.version.slice(0, 5)) > -1 ? setImmediate : processNextTick; +/**/ /**/ var Buffer = require('buffer').Buffer; @@ -17,29 +20,26 @@ var Buffer = require('buffer').Buffer; Writable.WritableState = WritableState; - /**/ var util = require('core-util-is'); util.inherits = require('inherits'); /**/ - /**/ var internalUtil = { deprecate: require('util-deprecate') }; /**/ - - /**/ var Stream; -(function (){try{ - Stream = require('st' + 'ream'); -}catch(_){}finally{ - if (!Stream) - Stream = require('events').EventEmitter; -}}()) +(function () { + try { + Stream = require('st' + 'ream'); + } catch (_) {} finally { + if (!Stream) Stream = require('events').EventEmitter; + } +})(); /**/ var Buffer = require('buffer').Buffer; @@ -65,18 +65,17 @@ function WritableState(options, stream) { // contains buffers or objects. this.objectMode = !!options.objectMode; - if (stream instanceof Duplex) - this.objectMode = this.objectMode || !!options.writableObjectMode; + if (stream instanceof Duplex) this.objectMode = this.objectMode || !!options.writableObjectMode; // the point at which write() starts returning false // Note: 0 is a valid value, means that we always return false if // the entire buffer is not flushed immediately on write() var hwm = options.highWaterMark; var defaultHwm = this.objectMode ? 16 : 16 * 1024; - this.highWaterMark = (hwm || hwm === 0) ? hwm : defaultHwm; + this.highWaterMark = hwm || hwm === 0 ? hwm : defaultHwm; // cast to ints. - this.highWaterMark = ~~this.highWaterMark; + this.highWaterMark = ~ ~this.highWaterMark; this.needDrain = false; // at the start of calling end() @@ -120,7 +119,7 @@ function WritableState(options, stream) { this.bufferProcessing = false; // the callback that's passed to _write(chunk,cb) - this.onwrite = function(er) { + this.onwrite = function (er) { onwrite(stream, er); }; @@ -143,6 +142,14 @@ function WritableState(options, stream) { // True if the error was already emitted and should not be thrown again this.errorEmitted = false; + + // count buffered requests + this.bufferedRequestCount = 0; + + // create the two objects needed to store the corked requests + // they are not a linked list, as no new elements are inserted in there + this.corkedRequestsFree = new CorkedRequest(this); + this.corkedRequestsFree.next = new CorkedRequest(this); } WritableState.prototype.getBuffer = function writableStateGetBuffer() { @@ -155,15 +162,15 @@ WritableState.prototype.getBuffer = function writableStateGetBuffer() { return out; }; -(function (){try { -Object.defineProperty(WritableState.prototype, 'buffer', { - get: internalUtil.deprecate(function() { - return this.getBuffer(); - }, '_writableState.buffer is deprecated. Use _writableState.getBuffer ' + - 'instead.') -}); -}catch(_){}}()); - +(function () { + try { + Object.defineProperty(WritableState.prototype, 'buffer', { + get: internalUtil.deprecate(function () { + return this.getBuffer(); + }, '_writableState.buffer is deprecated. Use _writableState.getBuffer ' + 'instead.') + }); + } catch (_) {} +})(); var Duplex; function Writable(options) { @@ -171,8 +178,7 @@ function Writable(options) { // Writable ctor is applied to Duplexes, though they're not // instanceof Writable, they're instanceof Readable. - if (!(this instanceof Writable) && !(this instanceof Duplex)) - return new Writable(options); + if (!(this instanceof Writable) && !(this instanceof Duplex)) return new Writable(options); this._writableState = new WritableState(options, this); @@ -180,22 +186,19 @@ function Writable(options) { this.writable = true; if (options) { - if (typeof options.write === 'function') - this._write = options.write; + if (typeof options.write === 'function') this._write = options.write; - if (typeof options.writev === 'function') - this._writev = options.writev; + if (typeof options.writev === 'function') this._writev = options.writev; } Stream.call(this); } // Otherwise people can pipe Writable streams, which is just wrong. -Writable.prototype.pipe = function() { +Writable.prototype.pipe = function () { this.emit('error', new Error('Cannot pipe. Not readable.')); }; - function writeAfterEnd(stream, cb) { var er = new Error('write after end'); // TODO: defer error events consistently everywhere, not just the cb @@ -211,11 +214,7 @@ function writeAfterEnd(stream, cb) { function validChunk(stream, state, chunk, cb) { var valid = true; - if (!(Buffer.isBuffer(chunk)) && - typeof chunk !== 'string' && - chunk !== null && - chunk !== undefined && - !state.objectMode) { + if (!Buffer.isBuffer(chunk) && typeof chunk !== 'string' && chunk !== null && chunk !== undefined && !state.objectMode) { var er = new TypeError('Invalid non-string/buffer chunk'); stream.emit('error', er); processNextTick(cb, er); @@ -224,7 +223,7 @@ function validChunk(stream, state, chunk, cb) { return valid; } -Writable.prototype.write = function(chunk, encoding, cb) { +Writable.prototype.write = function (chunk, encoding, cb) { var state = this._writableState; var ret = false; @@ -233,17 +232,11 @@ Writable.prototype.write = function(chunk, encoding, cb) { encoding = null; } - if (Buffer.isBuffer(chunk)) - encoding = 'buffer'; - else if (!encoding) - encoding = state.defaultEncoding; + if (Buffer.isBuffer(chunk)) encoding = 'buffer';else if (!encoding) encoding = state.defaultEncoding; - if (typeof cb !== 'function') - cb = nop; + if (typeof cb !== 'function') cb = nop; - if (state.ended) - writeAfterEnd(this, cb); - else if (validChunk(this, state, chunk, cb)) { + if (state.ended) writeAfterEnd(this, cb);else if (validChunk(this, state, chunk, cb)) { state.pendingcb++; ret = writeOrBuffer(this, state, chunk, encoding, cb); } @@ -251,42 +244,31 @@ Writable.prototype.write = function(chunk, encoding, cb) { return ret; }; -Writable.prototype.cork = function() { +Writable.prototype.cork = function () { var state = this._writableState; state.corked++; }; -Writable.prototype.uncork = function() { +Writable.prototype.uncork = function () { var state = this._writableState; if (state.corked) { state.corked--; - if (!state.writing && - !state.corked && - !state.finished && - !state.bufferProcessing && - state.bufferedRequest) - clearBuffer(this, state); + if (!state.writing && !state.corked && !state.finished && !state.bufferProcessing && state.bufferedRequest) clearBuffer(this, state); } }; Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) { // node::ParseEncoding() requires lower case. - if (typeof encoding === 'string') - encoding = encoding.toLowerCase(); - if (!(['hex', 'utf8', 'utf-8', 'ascii', 'binary', 'base64', -'ucs2', 'ucs-2','utf16le', 'utf-16le', 'raw'] -.indexOf((encoding + '').toLowerCase()) > -1)) - throw new TypeError('Unknown encoding: ' + encoding); + if (typeof encoding === 'string') encoding = encoding.toLowerCase(); + if (!(['hex', 'utf8', 'utf-8', 'ascii', 'binary', 'base64', 'ucs2', 'ucs-2', 'utf16le', 'utf-16le', 'raw'].indexOf((encoding + '').toLowerCase()) > -1)) throw new TypeError('Unknown encoding: ' + encoding); this._writableState.defaultEncoding = encoding; }; function decodeChunk(state, chunk, encoding) { - if (!state.objectMode && - state.decodeStrings !== false && - typeof chunk === 'string') { + if (!state.objectMode && state.decodeStrings !== false && typeof chunk === 'string') { chunk = new Buffer(chunk, encoding); } return chunk; @@ -298,16 +280,14 @@ function decodeChunk(state, chunk, encoding) { function writeOrBuffer(stream, state, chunk, encoding, cb) { chunk = decodeChunk(state, chunk, encoding); - if (Buffer.isBuffer(chunk)) - encoding = 'buffer'; + if (Buffer.isBuffer(chunk)) encoding = 'buffer'; var len = state.objectMode ? 1 : chunk.length; state.length += len; var ret = state.length < state.highWaterMark; // we must ensure that previous needDrain will not be reset to false. - if (!ret) - state.needDrain = true; + if (!ret) state.needDrain = true; if (state.writing || state.corked) { var last = state.lastBufferedRequest; @@ -317,6 +297,7 @@ function writeOrBuffer(stream, state, chunk, encoding, cb) { } else { state.bufferedRequest = state.lastBufferedRequest; } + state.bufferedRequestCount += 1; } else { doWrite(stream, state, false, len, chunk, encoding, cb); } @@ -329,19 +310,13 @@ function doWrite(stream, state, writev, len, chunk, encoding, cb) { state.writecb = cb; state.writing = true; state.sync = true; - if (writev) - stream._writev(chunk, state.onwrite); - else - stream._write(chunk, encoding, state.onwrite); + if (writev) stream._writev(chunk, state.onwrite);else stream._write(chunk, encoding, state.onwrite); state.sync = false; } function onwriteError(stream, state, sync, er, cb) { --state.pendingcb; - if (sync) - processNextTick(cb, er); - else - cb(er); + if (sync) processNextTick(cb, er);else cb(er); stream._writableState.errorEmitted = true; stream.emit('error', er); @@ -361,30 +336,26 @@ function onwrite(stream, er) { onwriteStateUpdate(state); - if (er) - onwriteError(stream, state, sync, er, cb); - else { + if (er) onwriteError(stream, state, sync, er, cb);else { // Check if we're actually ready to finish, but don't emit yet var finished = needFinish(state); - if (!finished && - !state.corked && - !state.bufferProcessing && - state.bufferedRequest) { + if (!finished && !state.corked && !state.bufferProcessing && state.bufferedRequest) { clearBuffer(stream, state); } if (sync) { - processNextTick(afterWrite, stream, state, finished, cb); + /**/ + asyncWrite(afterWrite, stream, state, finished, cb); + /**/ } else { - afterWrite(stream, state, finished, cb); - } + afterWrite(stream, state, finished, cb); + } } } function afterWrite(stream, state, finished, cb) { - if (!finished) - onwriteDrain(stream, state); + if (!finished) onwriteDrain(stream, state); state.pendingcb--; cb(); finishMaybe(stream, state); @@ -400,7 +371,6 @@ function onwriteDrain(stream, state) { } } - // if there's something in the buffer waiting, then process it function clearBuffer(stream, state) { state.bufferProcessing = true; @@ -408,26 +378,26 @@ function clearBuffer(stream, state) { if (stream._writev && entry && entry.next) { // Fast case, write everything using _writev() - var buffer = []; - var cbs = []; + var l = state.bufferedRequestCount; + var buffer = new Array(l); + var holder = state.corkedRequestsFree; + holder.entry = entry; + + var count = 0; while (entry) { - cbs.push(entry.callback); - buffer.push(entry); + buffer[count] = entry; entry = entry.next; + count += 1; } - // count the one we are adding, as well. - // TODO(isaacs) clean this up + doWrite(stream, state, true, state.length, buffer, '', holder.finish); + + // doWrite is always async, defer these to save a bit of time + // as the hot path ends with doWrite state.pendingcb++; state.lastBufferedRequest = null; - doWrite(stream, state, true, state.length, buffer, '', function(err) { - for (var i = 0; i < cbs.length; i++) { - state.pendingcb--; - cbs[i](err); - } - }); - - // Clear buffer + state.corkedRequestsFree = holder.next; + holder.next = null; } else { // Slow case, write chunks one-by-one while (entry) { @@ -447,20 +417,21 @@ function clearBuffer(stream, state) { } } - if (entry === null) - state.lastBufferedRequest = null; + if (entry === null) state.lastBufferedRequest = null; } + + state.bufferedRequestCount = 0; state.bufferedRequest = entry; state.bufferProcessing = false; } -Writable.prototype._write = function(chunk, encoding, cb) { +Writable.prototype._write = function (chunk, encoding, cb) { cb(new Error('not implemented')); }; Writable.prototype._writev = null; -Writable.prototype.end = function(chunk, encoding, cb) { +Writable.prototype.end = function (chunk, encoding, cb) { var state = this._writableState; if (typeof chunk === 'function') { @@ -472,8 +443,7 @@ Writable.prototype.end = function(chunk, encoding, cb) { encoding = null; } - if (chunk !== null && chunk !== undefined) - this.write(chunk, encoding); + if (chunk !== null && chunk !== undefined) this.write(chunk, encoding); // .end() fully uncorks if (state.corked) { @@ -482,17 +452,11 @@ Writable.prototype.end = function(chunk, encoding, cb) { } // ignore unnecessary end() calls. - if (!state.ending && !state.finished) - endWritable(this, state, cb); + if (!state.ending && !state.finished) endWritable(this, state, cb); }; - function needFinish(state) { - return (state.ending && - state.length === 0 && - state.bufferedRequest === null && - !state.finished && - !state.writing); + return state.ending && state.length === 0 && state.bufferedRequest === null && !state.finished && !state.writing; } function prefinish(stream, state) { @@ -520,10 +484,33 @@ function endWritable(stream, state, cb) { state.ending = true; finishMaybe(stream, state); if (cb) { - if (state.finished) - processNextTick(cb); - else - stream.once('finish', cb); + if (state.finished) processNextTick(cb);else stream.once('finish', cb); } state.ended = true; + stream.writable = false; } + +// It seems a linked list but it is not +// there will be only 2 of these for each stream +function CorkedRequest(state) { + var _this = this; + + this.next = null; + this.entry = null; + + this.finish = function (err) { + var entry = _this.entry; + _this.entry = null; + while (entry) { + var cb = entry.callback; + state.pendingcb--; + cb(err); + entry = entry.next; + } + if (state.corkedRequestsFree) { + state.corkedRequestsFree.next = _this; + } else { + state.corkedRequestsFree = _this; + } + }; +} \ No newline at end of file diff --git a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/core-util-is/package.json b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/core-util-is/package.json index ddd227e64f99f4..19fb85922bc035 100644 --- a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/core-util-is/package.json +++ b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/core-util-is/package.json @@ -46,7 +46,7 @@ }, "dist": { "shasum": "b5fd54220aa2bc5ab57aab7140c940754503c1a7", - "tarball": "http://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" + "tarball": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" }, "maintainers": [ { diff --git a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/isarray/.npmignore b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/isarray/.npmignore new file mode 100644 index 00000000000000..3c3629e647f5dd --- /dev/null +++ b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/isarray/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/isarray/.travis.yml b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/isarray/.travis.yml new file mode 100644 index 00000000000000..cc4dba29d959a2 --- /dev/null +++ b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/isarray/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - "0.8" + - "0.10" diff --git a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/isarray/Makefile b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/isarray/Makefile new file mode 100644 index 00000000000000..0ecc29c402c243 --- /dev/null +++ b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/isarray/Makefile @@ -0,0 +1,5 @@ + +test: + @node_modules/.bin/tape test.js + +.PHONY: test diff --git a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/isarray/README.md b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/isarray/README.md index 052a62b8d7b7ae..16d2c59c6195f9 100644 --- a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/isarray/README.md +++ b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/isarray/README.md @@ -3,6 +3,12 @@ `Array#isArray` for older browsers. +[![build status](https://secure.travis-ci.org/juliangruber/isarray.svg)](http://travis-ci.org/juliangruber/isarray) +[![downloads](https://img.shields.io/npm/dm/isarray.svg)](https://www.npmjs.org/package/isarray) + +[![browser support](https://ci.testling.com/juliangruber/isarray.png) +](https://ci.testling.com/juliangruber/isarray) + ## Usage ```js diff --git a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/isarray/build/build.js b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/isarray/build/build.js deleted file mode 100644 index e1856ef0943728..00000000000000 --- a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/isarray/build/build.js +++ /dev/null @@ -1,208 +0,0 @@ - -/** - * Require the given path. - * - * @param {String} path - * @return {Object} exports - * @api public - */ - -function require(path, parent, orig) { - var resolved = require.resolve(path); - - // lookup failed - if (null == resolved) { - orig = orig || path; - parent = parent || 'root'; - var err = new Error('Failed to require "' + orig + '" from "' + parent + '"'); - err.path = orig; - err.parent = parent; - err.require = true; - throw err; - } - - var module = require.modules[resolved]; - - // perform real require() - // by invoking the module's - // registered function - if (!module.exports) { - module.exports = {}; - module.client = module.component = true; - module.call(this, module.exports, require.relative(resolved), module); - } - - return module.exports; -} - -/** - * Registered modules. - */ - -require.modules = {}; - -/** - * Registered aliases. - */ - -require.aliases = {}; - -/** - * Resolve `path`. - * - * Lookup: - * - * - PATH/index.js - * - PATH.js - * - PATH - * - * @param {String} path - * @return {String} path or null - * @api private - */ - -require.resolve = function(path) { - if (path.charAt(0) === '/') path = path.slice(1); - var index = path + '/index.js'; - - var paths = [ - path, - path + '.js', - path + '.json', - path + '/index.js', - path + '/index.json' - ]; - - for (var i = 0; i < paths.length; i++) { - var path = paths[i]; - if (require.modules.hasOwnProperty(path)) return path; - } - - if (require.aliases.hasOwnProperty(index)) { - return require.aliases[index]; - } -}; - -/** - * Normalize `path` relative to the current path. - * - * @param {String} curr - * @param {String} path - * @return {String} - * @api private - */ - -require.normalize = function(curr, path) { - var segs = []; - - if ('.' != path.charAt(0)) return path; - - curr = curr.split('/'); - path = path.split('/'); - - for (var i = 0; i < path.length; ++i) { - if ('..' == path[i]) { - curr.pop(); - } else if ('.' != path[i] && '' != path[i]) { - segs.push(path[i]); - } - } - - return curr.concat(segs).join('/'); -}; - -/** - * Register module at `path` with callback `definition`. - * - * @param {String} path - * @param {Function} definition - * @api private - */ - -require.register = function(path, definition) { - require.modules[path] = definition; -}; - -/** - * Alias a module definition. - * - * @param {String} from - * @param {String} to - * @api private - */ - -require.alias = function(from, to) { - if (!require.modules.hasOwnProperty(from)) { - throw new Error('Failed to alias "' + from + '", it does not exist'); - } - require.aliases[to] = from; -}; - -/** - * Return a require function relative to the `parent` path. - * - * @param {String} parent - * @return {Function} - * @api private - */ - -require.relative = function(parent) { - var p = require.normalize(parent, '..'); - - /** - * lastIndexOf helper. - */ - - function lastIndexOf(arr, obj) { - var i = arr.length; - while (i--) { - if (arr[i] === obj) return i; - } - return -1; - } - - /** - * The relative require() itself. - */ - - function localRequire(path) { - var resolved = localRequire.resolve(path); - return require(resolved, parent, path); - } - - /** - * Resolve relative to the parent. - */ - - localRequire.resolve = function(path) { - var c = path.charAt(0); - if ('/' == c) return path.slice(1); - if ('.' == c) return require.normalize(p, path); - - // resolve deps by returning - // the dep in the nearest "deps" - // directory - var segs = parent.split('/'); - var i = lastIndexOf(segs, 'deps') + 1; - if (!i) i = 0; - path = segs.slice(0, i + 1).join('/') + '/deps/' + path; - return path; - }; - - /** - * Check if module is defined at `path`. - */ - - localRequire.exists = function(path) { - return require.modules.hasOwnProperty(localRequire.resolve(path)); - }; - - return localRequire; -}; -require.register("isarray/index.js", function(exports, require, module){ -module.exports = Array.isArray || function (arr) { - return Object.prototype.toString.call(arr) == '[object Array]'; -}; - -}); -require.alias("isarray/index.js", "isarray/index.js"); diff --git a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/isarray/index.js b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/isarray/index.js index 5f5ad45d46dda9..a57f63495943a0 100644 --- a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/isarray/index.js +++ b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/isarray/index.js @@ -1,3 +1,5 @@ +var toString = {}.toString; + module.exports = Array.isArray || function (arr) { - return Object.prototype.toString.call(arr) == '[object Array]'; + return toString.call(arr) == '[object Array]'; }; diff --git a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/isarray/package.json b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/isarray/package.json index 19228ab6fdcaaf..e86d232e6090f3 100644 --- a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/isarray/package.json +++ b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/isarray/package.json @@ -1,19 +1,16 @@ { "name": "isarray", "description": "Array#isArray for older browsers", - "version": "0.0.1", + "version": "1.0.0", "repository": { "type": "git", "url": "git://github.com/juliangruber/isarray.git" }, "homepage": "https://github.com/juliangruber/isarray", "main": "index.js", - "scripts": { - "test": "tap test/*.js" - }, "dependencies": {}, "devDependencies": { - "tap": "*" + "tape": "~2.13.4" }, "keywords": [ "browser", @@ -26,17 +23,42 @@ "url": "http://juliangruber.com" }, "license": "MIT", - "_id": "isarray@0.0.1", - "dist": { - "shasum": "8a18acfca9a8f4177e09abfc6038939b05d1eedf", - "tarball": "http://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + "testling": { + "files": "test.js", + "browsers": [ + "ie/8..latest", + "firefox/17..latest", + "firefox/nightly", + "chrome/22..latest", + "chrome/canary", + "opera/12..latest", + "opera/next", + "safari/5.1..latest", + "ipad/6.0..latest", + "iphone/6.0..latest", + "android-browser/4.2..latest" + ] }, - "_from": "isarray@0.0.1", - "_npmVersion": "1.2.18", + "scripts": { + "test": "tape test.js" + }, + "gitHead": "2a23a281f369e9ae06394c0fb4d2381355a6ba33", + "bugs": { + "url": "https://github.com/juliangruber/isarray/issues" + }, + "_id": "isarray@1.0.0", + "_shasum": "bb935d48582cba168c06834957a54a3e07124f11", + "_from": "isarray@>=1.0.0 <1.1.0", + "_npmVersion": "3.3.12", + "_nodeVersion": "5.1.0", "_npmUser": { "name": "juliangruber", "email": "julian@juliangruber.com" }, + "dist": { + "shasum": "bb935d48582cba168c06834957a54a3e07124f11", + "tarball": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + }, "maintainers": [ { "name": "juliangruber", @@ -44,10 +66,6 @@ } ], "directories": {}, - "_shasum": "8a18acfca9a8f4177e09abfc6038939b05d1eedf", - "_resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "bugs": { - "url": "https://github.com/juliangruber/isarray/issues" - }, + "_resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "readme": "ERROR: No README data found!" } diff --git a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/isarray/test.js b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/isarray/test.js new file mode 100644 index 00000000000000..f7f7bcd19fec56 --- /dev/null +++ b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/isarray/test.js @@ -0,0 +1,19 @@ +var isArray = require('./'); +var test = require('tape'); + +test('is array', function(t){ + t.ok(isArray([])); + t.notOk(isArray({})); + t.notOk(isArray(null)); + t.notOk(isArray(false)); + + var obj = {}; + obj[0] = true; + t.notOk(isArray(obj)); + + var arr = []; + arr.foo = 'bar'; + t.ok(isArray(arr)); + + t.end(); +}); diff --git a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/process-nextick-args/index.js b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/process-nextick-args/index.js index 571c276783c779..a4f40f845faa65 100644 --- a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/process-nextick-args/index.js +++ b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/process-nextick-args/index.js @@ -8,13 +8,36 @@ if (!process.version || module.exports = process.nextTick; } -function nextTick(fn) { - var args = new Array(arguments.length - 1); - var i = 0; - while (i < args.length) { - args[i++] = arguments[i]; +function nextTick(fn, arg1, arg2, arg3) { + if (typeof fn !== 'function') { + throw new TypeError('"callback" argument must be a function'); + } + var len = arguments.length; + var args, i; + switch (len) { + case 0: + case 1: + return process.nextTick(fn); + case 2: + return process.nextTick(function afterTickOne() { + fn.call(null, arg1); + }); + case 3: + return process.nextTick(function afterTickTwo() { + fn.call(null, arg1, arg2); + }); + case 4: + return process.nextTick(function afterTickThree() { + fn.call(null, arg1, arg2, arg3); + }); + default: + args = new Array(len - 1); + i = 0; + while (i < args.length) { + args[i++] = arguments[i]; + } + return process.nextTick(function afterTick() { + fn.apply(null, args); + }); } - process.nextTick(function afterTick() { - fn.apply(null, args); - }); } diff --git a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/process-nextick-args/package.json b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/process-nextick-args/package.json index 0ccf22578d2caa..211b098d4cbb95 100644 --- a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/process-nextick-args/package.json +++ b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/process-nextick-args/package.json @@ -1,6 +1,6 @@ { "name": "process-nextick-args", - "version": "1.0.6", + "version": "1.0.7", "description": "process.nextTick but always with args", "main": "index.js", "scripts": { @@ -19,19 +19,19 @@ "devDependencies": { "tap": "~0.2.6" }, - "gitHead": "e85787b05a8c3c1adb714f332d822e9162699c78", - "_id": "process-nextick-args@1.0.6", - "_shasum": "0f96b001cea90b12592ce566edb97ec11e69bd05", + "gitHead": "5c00899ab01dd32f93ad4b5743da33da91404f39", + "_id": "process-nextick-args@1.0.7", + "_shasum": "150e20b756590ad3f91093f25a4f2ad8bff30ba3", "_from": "process-nextick-args@>=1.0.6 <1.1.0", - "_npmVersion": "2.14.4", - "_nodeVersion": "4.1.1", + "_npmVersion": "3.8.6", + "_nodeVersion": "5.11.0", "_npmUser": { "name": "cwmma", "email": "calvin.metcalf@gmail.com" }, "dist": { - "shasum": "0f96b001cea90b12592ce566edb97ec11e69bd05", - "tarball": "http://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.6.tgz" + "shasum": "150e20b756590ad3f91093f25a4f2ad8bff30ba3", + "tarball": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz" }, "maintainers": [ { @@ -39,7 +39,11 @@ "email": "calvin.metcalf@gmail.com" } ], + "_npmOperationalInternal": { + "host": "packages-12-west.internal.npmjs.com", + "tmp": "tmp/process-nextick-args-1.0.7.tgz_1462394251778_0.36989671061746776" + }, "directories": {}, - "_resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.6.tgz", + "_resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", "readme": "ERROR: No README data found!" } diff --git a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/string_decoder/package.json b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/string_decoder/package.json index 0364d54ba46af6..8e8b77db7b42cd 100644 --- a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/string_decoder/package.json +++ b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/string_decoder/package.json @@ -46,7 +46,7 @@ ], "dist": { "shasum": "62e203bc41766c6c28c9fc84301dab1c5310fa94", - "tarball": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + "tarball": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "directories": {}, "_resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", diff --git a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/util-deprecate/package.json b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/util-deprecate/package.json index ae0c70f6c633f1..a018135492d81f 100644 --- a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/util-deprecate/package.json +++ b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/node_modules/util-deprecate/package.json @@ -46,7 +46,7 @@ ], "dist": { "shasum": "450d4dc9fa70de732762fbd2d4a28981419a0ccf", - "tarball": "http://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + "tarball": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" }, "directories": {}, "_resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", diff --git a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/package.json b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/package.json index 7590ac88879acf..db3b47ae4072d0 100644 --- a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/package.json +++ b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/readable-stream/package.json @@ -1,23 +1,23 @@ { "name": "readable-stream", - "version": "2.0.5", - "description": "Streams3, a user-land copy of the stream library from iojs v2.x", + "version": "2.0.6", + "description": "Streams3, a user-land copy of the stream library from Node.js", "main": "readable.js", "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.1", - "isarray": "0.0.1", + "isarray": "~1.0.0", "process-nextick-args": "~1.0.6", "string_decoder": "~0.10.x", "util-deprecate": "~1.0.1" }, "devDependencies": { "tap": "~0.2.6", - "tape": "~4.0.0", - "zuul": "~3.0.0" + "tape": "~4.5.1", + "zuul": "~3.9.0" }, "scripts": { - "test": "tap test/parallel/*.js", + "test": "tap test/parallel/*.js test/ours/*.js", "browser": "npm run write-zuul && zuul -- test/browser.js", "write-zuul": "printf \"ui: tape\nbrowsers:\n - name: $BROWSER_NAME\n version: $BROWSER_VERSION\n\">.zuul.yml" }, @@ -34,23 +34,23 @@ "util": false }, "license": "MIT", - "gitHead": "a4f23d8e451267684a8160679ce16e16149fe72b", + "gitHead": "01fb5608a970b42c900b96746cadc13d27dd9d7e", "bugs": { "url": "https://github.com/nodejs/readable-stream/issues" }, "homepage": "https://github.com/nodejs/readable-stream#readme", - "_id": "readable-stream@2.0.5", - "_shasum": "a2426f8dcd4551c77a33f96edf2886a23c829669", + "_id": "readable-stream@2.0.6", + "_shasum": "8f90341e68a53ccc928788dacfcd11b36eb9b78e", "_from": "readable-stream@>=2.0.0 <2.1.0", - "_npmVersion": "3.3.12", - "_nodeVersion": "5.1.1", + "_npmVersion": "3.6.0", + "_nodeVersion": "5.7.0", "_npmUser": { "name": "cwmma", "email": "calvin.metcalf@gmail.com" }, "dist": { - "shasum": "a2426f8dcd4551c77a33f96edf2886a23c829669", - "tarball": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.0.5.tgz" + "shasum": "8f90341e68a53ccc928788dacfcd11b36eb9b78e", + "tarball": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz" }, "maintainers": [ { @@ -70,7 +70,11 @@ "email": "calvin.metcalf@gmail.com" } ], + "_npmOperationalInternal": { + "host": "packages-12-west.internal.npmjs.com", + "tmp": "tmp/readable-stream-2.0.6.tgz_1457893507709_0.369257491780445" + }, "directories": {}, - "_resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.5.tgz", + "_resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", "readme": "ERROR: No README data found!" } diff --git a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/typedarray/package.json b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/typedarray/package.json index b8b59f5c303991..d9df64d83952bb 100644 --- a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/typedarray/package.json +++ b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/typedarray/package.json @@ -58,7 +58,7 @@ "_id": "typedarray@0.0.6", "dist": { "shasum": "867ac74e3864187b1d3d47d996a78ec5c8830777", - "tarball": "http://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz" + "tarball": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz" }, "_from": "typedarray@>=0.0.5 <0.1.0", "_npmVersion": "1.4.3", diff --git a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/package.json b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/package.json index 5a3f8b401e4449..fd2590dddc5cbd 100644 --- a/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/package.json +++ b/deps/npm/node_modules/npm-registry-client/node_modules/concat-stream/package.json @@ -67,7 +67,7 @@ }, "dist": { "shasum": "f3b80acf9e1f48e3875c0688b41b6c31602eea1c", - "tarball": "http://registry.npmjs.org/concat-stream/-/concat-stream-1.5.1.tgz" + "tarball": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.1.tgz" }, "maintainers": [ { diff --git a/deps/npm/node_modules/npm-registry-client/node_modules/retry/package.json b/deps/npm/node_modules/npm-registry-client/node_modules/retry/package.json index dea2f3b175605c..058aefb3320608 100644 --- a/deps/npm/node_modules/npm-registry-client/node_modules/retry/package.json +++ b/deps/npm/node_modules/npm-registry-client/node_modules/retry/package.json @@ -47,7 +47,7 @@ ], "dist": { "shasum": "2367628dc0edb247b1eab649dc53ac8628ac2d5f", - "tarball": "http://registry.npmjs.org/retry/-/retry-0.8.0.tgz" + "tarball": "https://registry.npmjs.org/retry/-/retry-0.8.0.tgz" }, "_resolved": "https://registry.npmjs.org/retry/-/retry-0.8.0.tgz", "readme": "ERROR: No README data found!" diff --git a/deps/npm/node_modules/npm-registry-client/package.json b/deps/npm/node_modules/npm-registry-client/package.json index 362862cfc5f886..1eb87d056b2d5f 100644 --- a/deps/npm/node_modules/npm-registry-client/package.json +++ b/deps/npm/node_modules/npm-registry-client/package.json @@ -6,7 +6,7 @@ }, "name": "npm-registry-client", "description": "Client for the npm registry", - "version": "7.1.0", + "version": "7.1.2", "repository": { "url": "git+https://github.com/npm/npm-registry-client.git" }, @@ -27,7 +27,7 @@ "rimraf": "2", "semver": "2 >=2.2.1 || 3.x || 4 || 5", "slide": "^1.1.3", - "npmlog": "~2.0.0" + "npmlog": "~2.0.0 || ~3.1.0" }, "devDependencies": { "negotiator": "^0.4.9", @@ -37,26 +37,26 @@ "tap": "^1.2.0" }, "optionalDependencies": { - "npmlog": "~2.0.0" + "npmlog": "~2.0.0 || ~3.1.0" }, "license": "ISC", - "gitHead": "d077cb652152a8c265369d9d169cba8a52239fb4", + "gitHead": "0b595c4769f314a12661d537a328cf4e5658a00f", "bugs": { "url": "https://github.com/npm/npm-registry-client/issues" }, "homepage": "https://github.com/npm/npm-registry-client#readme", - "_id": "npm-registry-client@7.1.0", - "_shasum": "e3be14ab279fe5123e15ab5c8a650445415664a5", - "_from": "npm-registry-client@7.1.0", - "_npmVersion": "3.7.5", - "_nodeVersion": "5.4.0", + "_id": "npm-registry-client@7.1.2", + "_shasum": "ddf243a2bd149d35172fe680aff40dfa20054bc3", + "_from": "npm-registry-client@>=7.1.2 <7.2.0", + "_npmVersion": "3.9.2", + "_nodeVersion": "4.4.0", "_npmUser": { "name": "iarna", "email": "me@re-becca.org" }, "dist": { - "shasum": "e3be14ab279fe5123e15ab5c8a650445415664a5", - "tarball": "http://registry.npmjs.org/npm-registry-client/-/npm-registry-client-7.1.0.tgz" + "shasum": "ddf243a2bd149d35172fe680aff40dfa20054bc3", + "tarball": "https://registry.npmjs.org/npm-registry-client/-/npm-registry-client-7.1.2.tgz" }, "maintainers": [ { @@ -77,9 +77,9 @@ } ], "_npmOperationalInternal": { - "host": "packages-5-east.internal.npmjs.com", - "tmp": "tmp/npm-registry-client-7.1.0.tgz_1456435497334_0.35472381697036326" + "host": "packages-16-east.internal.npmjs.com", + "tmp": "tmp/npm-registry-client-7.1.2.tgz_1466040796551_0.645394338760525" }, "directories": {}, - "_resolved": "https://registry.npmjs.org/npm-registry-client/-/npm-registry-client-7.1.0.tgz" + "_resolved": "https://registry.npmjs.org/npm-registry-client/-/npm-registry-client-7.1.2.tgz" } diff --git a/deps/npm/node_modules/npm-user-validate/.travis.yml b/deps/npm/node_modules/npm-user-validate/.travis.yml index a12e3f0fdebc13..6ff074b74880dd 100644 --- a/deps/npm/node_modules/npm-user-validate/.travis.yml +++ b/deps/npm/node_modules/npm-user-validate/.travis.yml @@ -1,4 +1,7 @@ language: node_js +before_install: +- npm install -g npm@latest +sudo: false node_js: - "0.8" - - "0.10" \ No newline at end of file + - "0.10" diff --git a/deps/npm/node_modules/npm-user-validate/npm-user-validate.js b/deps/npm/node_modules/npm-user-validate/npm-user-validate.js index f18e13ccf7271f..c9da9cd1c90f0e 100644 --- a/deps/npm/node_modules/npm-user-validate/npm-user-validate.js +++ b/deps/npm/node_modules/npm-user-validate/npm-user-validate.js @@ -4,9 +4,10 @@ exports.username = username var requirements = exports.requirements = { username: { - lowerCase: 'Username must be lowercase', - urlSafe: 'Username may not contain non-url-safe chars', - dot: 'Username may not start with "."' + length: 'Name length must be less than or equal to 576 characters long', + lowerCase: 'Name must be lowercase', + urlSafe: 'Name may not contain non-url-safe chars', + dot: 'Name may not start with "."' }, password: {}, email: { @@ -27,6 +28,10 @@ function username (un) { return new Error(requirements.username.dot) } + if (un.length > 576) { + return new Error(requirements.username.length) + } + return null } diff --git a/deps/npm/node_modules/npm-user-validate/package.json b/deps/npm/node_modules/npm-user-validate/package.json index 8a27d7cfe1ad49..8109a38fa9549e 100644 --- a/deps/npm/node_modules/npm-user-validate/package.json +++ b/deps/npm/node_modules/npm-user-validate/package.json @@ -1,10 +1,10 @@ { "name": "npm-user-validate", - "version": "0.1.2", + "version": "0.1.4", "description": "User validations for npm", "main": "npm-user-validate.js", "devDependencies": { - "tap": "0.4.3" + "tap": "^1.2.0" }, "scripts": { "test": "tap test/*.js" @@ -23,34 +23,42 @@ "email": "rok@kowalski.gd" }, "license": "BSD-2-Clause", - "gitHead": "e5b280babff5b73fe74b496461bcf424a51881e1", + "gitHead": "ab804940b6846f8cc63f87692cea85b1906c967a", "bugs": { "url": "https://github.com/npm/npm-user-validate/issues" }, "homepage": "https://github.com/npm/npm-user-validate#readme", - "_id": "npm-user-validate@0.1.2", - "_shasum": "d585da0b47c9f41a9e6ca684b6fd84ba41ebe87d", - "_from": "npm-user-validate@>=0.1.1 <0.2.0", - "_npmVersion": "2.10.0", - "_nodeVersion": "2.0.1", + "_id": "npm-user-validate@0.1.4", + "_shasum": "18fcbe53cf921eb8e6339314665b187955b1a837", + "_from": "npm-user-validate@>=0.1.4 <0.2.0", + "_npmVersion": "3.9.6", + "_nodeVersion": "5.11.0", "_npmUser": { - "name": "isaacs", - "email": "isaacs@npmjs.com" + "name": "aredridel", + "email": "aria@npmjs.com" }, "dist": { - "shasum": "d585da0b47c9f41a9e6ca684b6fd84ba41ebe87d", - "tarball": "http://registry.npmjs.org/npm-user-validate/-/npm-user-validate-0.1.2.tgz" + "shasum": "18fcbe53cf921eb8e6339314665b187955b1a837", + "tarball": "https://registry.npmjs.org/npm-user-validate/-/npm-user-validate-0.1.4.tgz" }, "maintainers": [ { - "name": "robertkowalski", - "email": "rok@kowalski.gd" + "name": "aredridel", + "email": "aria@npmjs.com" }, { "name": "isaacs", "email": "i@izs.me" + }, + { + "name": "robertkowalski", + "email": "rok@kowalski.gd" } ], + "_npmOperationalInternal": { + "host": "packages-16-east.internal.npmjs.com", + "tmp": "tmp/npm-user-validate-0.1.4.tgz_1466105686124_0.06683815410360694" + }, "directories": {}, - "_resolved": "https://registry.npmjs.org/npm-user-validate/-/npm-user-validate-0.1.2.tgz" + "_resolved": "https://registry.npmjs.org/npm-user-validate/-/npm-user-validate-0.1.4.tgz" } diff --git a/deps/npm/node_modules/npm-user-validate/test/username.test.js b/deps/npm/node_modules/npm-user-validate/test/username.test.js index d30ec8afe71491..83528eec82a76d 100644 --- a/deps/npm/node_modules/npm-user-validate/test/username.test.js +++ b/deps/npm/node_modules/npm-user-validate/test/username.test.js @@ -2,25 +2,41 @@ var test = require('tap').test var v = require('../npm-user-validate.js').username test('username must be lowercase', function (t) { - err = v('ERRR') + var err = v('ERRR') t.type(err, 'object') + t.match(err.message, /lowercase/) t.end() }) test('username may not contain non-url-safe chars', function (t) { - err = v('f ') + var err = v('f ') t.type(err, 'object') + t.match(err.message, /url-safe/) t.end() }) test('username may not start with "."', function (t) { - err = v('.username') + var err = v('.username') t.type(err, 'object') + t.match(err.message, /start with.*\./) t.end() }) +test('username may not be longer than 576 characters', function (t) { + var err = v('bacon-ipsum-dolor-amet-tongue-short-loin-landjaeger-tenderloin-ball-tip-pork-loin-porchetta-pig-pork-chop-beef-ribs-pork-belly--shankle-t-bone-turducken-tongue-landjaeger-pork-loin-beef-chicken-short-loin-venison-capicola--brisket-leberkas-pork-beef-ribs-kevin-short-ribs-tail-bresaola-ham--rump-fatback-short-ribs-frankfurter-boudin--turkey-cupim-tri-tip-pork-chop-landjaeger-frankfurter-ham-hock---kielbasa-sausage-sirloin-short-loin-bacon-tenderloin-biltong-spare-ribs-cow-beef-ribs-tongue-cupim-filet-mignon-drumstick--pork-chop-tenderloin-brisket-pork-belly-leberkas-and-a-pickle') + t.type(err, 'object') + t.match(err.message, /less than or equal to 576/) + t.end() +}); + +test('username may be as long as 576 characters', function (t) { + var err = v('bacon-ipsum-dolor-amet-tongue-short-loin-landjaeger-tenderloin-ball-tip-pork-loin-porchetta-pig-pork-chop-beef-ribs-pork-belly--shankle-t-bone-turducken-tongue-landjaeger-pork-loin-beef-chicken-short-loin-venison-capicola--brisket-leberkas-pork-beef-ribs-kevin-short-ribs-tail-bresaola-ham--rump-fatback-short-ribs-frankfurter-boudin--turkey-cupim-tri-tip-pork-chop-landjaeger-frankfurter-ham-hock---kielbasa-sausage-sirloin-short-loin-bacon-tenderloin-biltong-spare-ribs-cow-beef-ribs-tongue-cupim-filet-mignon-drumstick--pork-chop-tenderloin-brisket-pork-belly-leberkas-beef') + t.type(err, 'null') + t.end() +}); + test('username is ok', function (t) { - err = v('ente') + var err = v('ente') t.type(err, 'null') t.end() }) diff --git a/deps/npm/node_modules/npmlog/.nyc_output/64996.json b/deps/npm/node_modules/npmlog/.nyc_output/64996.json deleted file mode 100644 index 9e26dfeeb6e641..00000000000000 --- a/deps/npm/node_modules/npmlog/.nyc_output/64996.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/deps/npm/node_modules/npmlog/.nyc_output/64998.json b/deps/npm/node_modules/npmlog/.nyc_output/64998.json deleted file mode 100644 index ba21481f41cce3..00000000000000 --- a/deps/npm/node_modules/npmlog/.nyc_output/64998.json +++ /dev/null @@ -1 +0,0 @@ -{"./log.js":{"path":"./log.js","s":{"1":1,"2":1,"3":1,"4":1,"5":1,"6":1,"7":1,"8":1,"9":1,"10":1,"11":0,"12":0,"13":1,"14":0,"15":0,"16":1,"17":1,"18":1,"19":1,"20":1,"21":1,"22":0,"23":0,"24":1,"25":0,"26":0,"27":1,"28":1,"29":0,"30":0,"31":1,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":1,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":1,"48":1,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":1,"69":3,"70":0,"71":1,"72":13,"73":13,"74":0,"75":1,"76":13,"77":13,"78":0,"79":0,"80":0,"81":1,"82":0,"83":1,"84":0,"85":0,"86":0,"87":0,"88":0,"89":0,"90":0,"91":0,"92":0,"93":1,"94":1,"95":1,"96":1,"97":1,"98":24,"99":24,"100":0,"101":24,"102":24,"103":24,"104":45,"105":45,"106":0,"107":24,"108":0,"109":24,"110":24,"111":24,"112":24,"113":24,"114":23,"115":24,"116":24,"117":24,"118":24,"119":0,"120":0,"121":24,"122":1,"123":24,"124":0,"125":0,"126":24,"127":0,"128":24,"129":24,"130":0,"131":24,"132":8,"133":16,"134":3,"135":13,"136":13,"137":13,"138":13,"139":16,"140":16,"141":16,"142":16,"143":16,"144":16,"145":15,"146":16,"147":16,"148":13,"149":1,"150":95,"151":0,"152":95,"153":1,"154":1,"155":1,"156":0,"157":1,"158":0,"159":1,"160":95,"161":95,"162":45,"163":95,"164":27,"165":95,"166":0,"167":95,"168":0,"169":95,"170":1,"171":95,"172":2,"173":95,"174":1,"175":8,"176":4,"177":8,"178":8,"179":8,"180":8,"181":24,"182":24,"183":24,"184":69,"185":24,"186":8,"187":1,"188":1,"189":1,"190":1,"191":1,"192":1,"193":1,"194":1,"195":1,"196":1,"197":1,"198":1,"199":1},"b":{"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0],"8":[0,0],"9":[13,0],"10":[13,0],"11":[0,0],"12":[0,0],"13":[0,0],"14":[0,24],"15":[0,45],"16":[45,21,21,0],"17":[0,24],"18":[24,1],"19":[23,1],"20":[0,24],"21":[0,24],"22":[0,24],"23":[0,24],"24":[8,16],"25":[3,13],"26":[16,15],"27":[13,0],"28":[16,0],"29":[16,1],"30":[15,1],"31":[0,95],"32":[1,94],"33":[0,1],"34":[0,1],"35":[95,47],"36":[45,50],"37":[27,68],"38":[0,95],"39":[0,95],"40":[1,94],"41":[2,93],"42":[4,4],"43":[8,0]},"f":{"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":3,"15":0,"16":13,"17":13,"18":0,"19":0,"20":0,"21":24,"22":24,"23":16,"24":95,"25":8,"26":24,"27":1},"fnMap":{"1":{"name":"(anonymous_1)","line":14,"loc":{"start":{"line":14,"column":18},"end":{"line":14,"column":30}}},"2":{"name":"(anonymous_2)","line":18,"loc":{"start":{"line":18,"column":19},"end":{"line":18,"column":31}}},"3":{"name":"(anonymous_3)","line":34,"loc":{"start":{"line":34,"column":20},"end":{"line":34,"column":32}}},"4":{"name":"(anonymous_4)","line":39,"loc":{"start":{"line":39,"column":21},"end":{"line":39,"column":33}}},"5":{"name":"(anonymous_5)","line":45,"loc":{"start":{"line":45,"column":23},"end":{"line":45,"column":43}}},"6":{"name":"(anonymous_6)","line":50,"loc":{"start":{"line":50,"column":21},"end":{"line":50,"column":33}}},"7":{"name":"(anonymous_7)","line":59,"loc":{"start":{"line":59,"column":22},"end":{"line":59,"column":34}}},"8":{"name":"(anonymous_8)","line":69,"loc":{"start":{"line":69,"column":15},"end":{"line":69,"column":34}}},"9":{"name":"(anonymous_9)","line":72,"loc":{"start":{"line":72,"column":27},"end":{"line":72,"column":40}}},"10":{"name":"(anonymous_10)","line":74,"loc":{"start":{"line":74,"column":35},"end":{"line":74,"column":48}}},"11":{"name":"(anonymous_11)","line":78,"loc":{"start":{"line":78,"column":17},"end":{"line":78,"column":29}}},"12":{"name":"(anonymous_12)","line":85,"loc":{"start":{"line":85,"column":32},"end":{"line":85,"column":45}}},"13":{"name":"(anonymous_13)","line":87,"loc":{"start":{"line":87,"column":19},"end":{"line":87,"column":31}}},"14":{"name":"(anonymous_14)","line":94,"loc":{"start":{"line":94,"column":28},"end":{"line":94,"column":41}}},"15":{"name":"(anonymous_15)","line":95,"loc":{"start":{"line":95,"column":11},"end":{"line":95,"column":23}}},"16":{"name":"(anonymous_16)","line":98,"loc":{"start":{"line":98,"column":20},"end":{"line":98,"column":32}}},"17":{"name":"(anonymous_17)","line":103,"loc":{"start":{"line":103,"column":19},"end":{"line":103,"column":46}}},"18":{"name":"(anonymous_18)","line":110,"loc":{"start":{"line":110,"column":12},"end":{"line":110,"column":24}}},"19":{"name":"(anonymous_19)","line":114,"loc":{"start":{"line":114,"column":13},"end":{"line":114,"column":25}}},"20":{"name":"(anonymous_20)","line":120,"loc":{"start":{"line":120,"column":12},"end":{"line":120,"column":25}}},"21":{"name":"(anonymous_21)","line":131,"loc":{"start":{"line":131,"column":10},"end":{"line":131,"column":42}}},"22":{"name":"(anonymous_22)","line":173,"loc":{"start":{"line":173,"column":14},"end":{"line":173,"column":27}}},"23":{"name":"(anonymous_23)","line":187,"loc":{"start":{"line":187,"column":35},"end":{"line":187,"column":51}}},"24":{"name":"(anonymous_24)","line":201,"loc":{"start":{"line":201,"column":12},"end":{"line":201,"column":34}}},"25":{"name":"(anonymous_25)","line":221,"loc":{"start":{"line":221,"column":15},"end":{"line":221,"column":46}}},"26":{"name":"(anonymous_26)","line":225,"loc":{"start":{"line":225,"column":30},"end":{"line":225,"column":42}}},"27":{"name":"(anonymous_27)","line":251,"loc":{"start":{"line":251,"column":16},"end":{"line":251,"column":26}}}},"statementMap":{"1":{"start":{"line":2,"column":0},"end":{"line":2,"column":42}},"2":{"start":{"line":3,"column":0},"end":{"line":3,"column":28}},"3":{"start":{"line":4,"column":0},"end":{"line":4,"column":39}},"4":{"start":{"line":5,"column":0},"end":{"line":5,"column":43}},"5":{"start":{"line":6,"column":0},"end":{"line":6,"column":26}},"6":{"start":{"line":8,"column":0},"end":{"line":8,"column":26}},"7":{"start":{"line":9,"column":0},"end":{"line":9,"column":33}},"8":{"start":{"line":10,"column":0},"end":{"line":10,"column":27}},"9":{"start":{"line":13,"column":0},"end":{"line":13,"column":28}},"10":{"start":{"line":14,"column":0},"end":{"line":17,"column":1}},"11":{"start":{"line":15,"column":2},"end":{"line":15,"column":21}},"12":{"start":{"line":16,"column":2},"end":{"line":16,"column":28}},"13":{"start":{"line":18,"column":0},"end":{"line":21,"column":1}},"14":{"start":{"line":19,"column":2},"end":{"line":19,"column":22}},"15":{"start":{"line":20,"column":2},"end":{"line":20,"column":29}},"16":{"start":{"line":24,"column":0},"end":{"line":24,"column":18}},"17":{"start":{"line":26,"column":0},"end":{"line":26,"column":33}},"18":{"start":{"line":27,"column":0},"end":{"line":27,"column":41}},"19":{"start":{"line":30,"column":0},"end":{"line":30,"column":27}},"20":{"start":{"line":32,"column":0},"end":{"line":32,"column":26}},"21":{"start":{"line":34,"column":0},"end":{"line":37,"column":1}},"22":{"start":{"line":35,"column":2},"end":{"line":35,"column":28}},"23":{"start":{"line":36,"column":2},"end":{"line":36,"column":32}},"24":{"start":{"line":39,"column":0},"end":{"line":42,"column":1}},"25":{"start":{"line":40,"column":2},"end":{"line":40,"column":26}},"26":{"start":{"line":41,"column":2},"end":{"line":41,"column":32}},"27":{"start":{"line":44,"column":0},"end":{"line":44,"column":29}},"28":{"start":{"line":45,"column":0},"end":{"line":48,"column":1}},"29":{"start":{"line":46,"column":2},"end":{"line":46,"column":26}},"30":{"start":{"line":47,"column":2},"end":{"line":47,"column":38}},"31":{"start":{"line":50,"column":0},"end":{"line":57,"column":1}},"32":{"start":{"line":51,"column":2},"end":{"line":51,"column":34}},"33":{"start":{"line":51,"column":28},"end":{"line":51,"column":34}},"34":{"start":{"line":52,"column":2},"end":{"line":52,"column":29}},"35":{"start":{"line":53,"column":2},"end":{"line":53,"column":25}},"36":{"start":{"line":53,"column":19},"end":{"line":53,"column":25}},"37":{"start":{"line":54,"column":2},"end":{"line":54,"column":46}},"38":{"start":{"line":55,"column":2},"end":{"line":55,"column":21}},"39":{"start":{"line":56,"column":2},"end":{"line":56,"column":21}},"40":{"start":{"line":59,"column":0},"end":{"line":65,"column":1}},"41":{"start":{"line":60,"column":2},"end":{"line":60,"column":35}},"42":{"start":{"line":60,"column":29},"end":{"line":60,"column":35}},"43":{"start":{"line":61,"column":2},"end":{"line":61,"column":22}},"44":{"start":{"line":62,"column":2},"end":{"line":62,"column":30}},"45":{"start":{"line":63,"column":2},"end":{"line":63,"column":58}},"46":{"start":{"line":64,"column":2},"end":{"line":64,"column":22}},"47":{"start":{"line":67,"column":0},"end":{"line":67,"column":62}},"48":{"start":{"line":69,"column":0},"end":{"line":91,"column":1}},"49":{"start":{"line":72,"column":2},"end":{"line":81,"column":4}},"50":{"start":{"line":73,"column":4},"end":{"line":73,"column":28}},"51":{"start":{"line":73,"column":22},"end":{"line":73,"column":28}},"52":{"start":{"line":74,"column":4},"end":{"line":74,"column":82}},"53":{"start":{"line":74,"column":50},"end":{"line":74,"column":65}},"54":{"start":{"line":74,"column":76},"end":{"line":74,"column":82}},"55":{"start":{"line":75,"column":4},"end":{"line":75,"column":26}},"56":{"start":{"line":75,"column":20},"end":{"line":75,"column":26}},"57":{"start":{"line":76,"column":4},"end":{"line":76,"column":44}},"58":{"start":{"line":76,"column":38},"end":{"line":76,"column":44}},"59":{"start":{"line":77,"column":4},"end":{"line":77,"column":21}},"60":{"start":{"line":78,"column":4},"end":{"line":80,"column":5}},"61":{"start":{"line":79,"column":6},"end":{"line":79,"column":39}},"62":{"start":{"line":84,"column":2},"end":{"line":89,"column":3}},"63":{"start":{"line":85,"column":4},"end":{"line":88,"column":6}},"64":{"start":{"line":86,"column":6},"end":{"line":86,"column":27}},"65":{"start":{"line":87,"column":6},"end":{"line":87,"column":82}},"66":{"start":{"line":87,"column":33},"end":{"line":87,"column":81}},"67":{"start":{"line":90,"column":2},"end":{"line":90,"column":16}},"68":{"start":{"line":94,"column":0},"end":{"line":96,"column":2}},"69":{"start":{"line":95,"column":2},"end":{"line":95,"column":90}},"70":{"start":{"line":95,"column":25},"end":{"line":95,"column":89}},"71":{"start":{"line":98,"column":0},"end":{"line":101,"column":1}},"72":{"start":{"line":99,"column":2},"end":{"line":99,"column":35}},"73":{"start":{"line":99,"column":29},"end":{"line":99,"column":35}},"74":{"start":{"line":100,"column":2},"end":{"line":100,"column":19}},"75":{"start":{"line":103,"column":0},"end":{"line":107,"column":11}},"76":{"start":{"line":104,"column":2},"end":{"line":104,"column":35}},"77":{"start":{"line":104,"column":29},"end":{"line":104,"column":35}},"78":{"start":{"line":105,"column":2},"end":{"line":105,"column":61}},"79":{"start":{"line":105,"column":25},"end":{"line":105,"column":61}},"80":{"start":{"line":106,"column":2},"end":{"line":106,"column":34}},"81":{"start":{"line":110,"column":0},"end":{"line":112,"column":1}},"82":{"start":{"line":111,"column":2},"end":{"line":111,"column":21}},"83":{"start":{"line":114,"column":0},"end":{"line":124,"column":1}},"84":{"start":{"line":115,"column":2},"end":{"line":115,"column":27}},"85":{"start":{"line":115,"column":21},"end":{"line":115,"column":27}},"86":{"start":{"line":116,"column":2},"end":{"line":116,"column":22}},"87":{"start":{"line":118,"column":2},"end":{"line":118,"column":22}},"88":{"start":{"line":119,"column":2},"end":{"line":119,"column":19}},"89":{"start":{"line":120,"column":2},"end":{"line":122,"column":10}},"90":{"start":{"line":121,"column":4},"end":{"line":121,"column":19}},"91":{"start":{"line":123,"column":2},"end":{"line":123,"column":49}},"92":{"start":{"line":123,"column":28},"end":{"line":123,"column":49}},"93":{"start":{"line":126,"column":0},"end":{"line":126,"column":16}},"94":{"start":{"line":128,"column":0},"end":{"line":128,"column":10}},"95":{"start":{"line":129,"column":0},"end":{"line":129,"column":15}},"96":{"start":{"line":130,"column":0},"end":{"line":130,"column":25}},"97":{"start":{"line":131,"column":0},"end":{"line":171,"column":11}},"98":{"start":{"line":132,"column":2},"end":{"line":132,"column":26}},"99":{"start":{"line":133,"column":2},"end":{"line":136,"column":3}},"100":{"start":{"line":134,"column":4},"end":{"line":135,"column":39}},"101":{"start":{"line":138,"column":2},"end":{"line":138,"column":41}},"102":{"start":{"line":139,"column":2},"end":{"line":139,"column":18}},"103":{"start":{"line":140,"column":2},"end":{"line":148,"column":3}},"104":{"start":{"line":141,"column":4},"end":{"line":141,"column":35}},"105":{"start":{"line":144,"column":4},"end":{"line":147,"column":5}},"106":{"start":{"line":146,"column":6},"end":{"line":146,"column":40}},"107":{"start":{"line":149,"column":2},"end":{"line":149,"column":36}},"108":{"start":{"line":149,"column":13},"end":{"line":149,"column":36}},"109":{"start":{"line":150,"column":2},"end":{"line":150,"column":38}},"110":{"start":{"line":152,"column":2},"end":{"line":156,"column":27}},"111":{"start":{"line":158,"column":2},"end":{"line":158,"column":21}},"112":{"start":{"line":159,"column":2},"end":{"line":159,"column":28}},"113":{"start":{"line":160,"column":2},"end":{"line":160,"column":38}},"114":{"start":{"line":160,"column":16},"end":{"line":160,"column":38}},"115":{"start":{"line":162,"column":2},"end":{"line":162,"column":21}},"116":{"start":{"line":163,"column":2},"end":{"line":163,"column":30}},"117":{"start":{"line":164,"column":2},"end":{"line":164,"column":34}},"118":{"start":{"line":165,"column":2},"end":{"line":168,"column":3}},"119":{"start":{"line":166,"column":4},"end":{"line":166,"column":39}},"120":{"start":{"line":167,"column":4},"end":{"line":167,"column":49}},"121":{"start":{"line":170,"column":2},"end":{"line":170,"column":17}},"122":{"start":{"line":173,"column":0},"end":{"line":199,"column":1}},"123":{"start":{"line":174,"column":2},"end":{"line":177,"column":3}},"124":{"start":{"line":175,"column":4},"end":{"line":175,"column":24}},"125":{"start":{"line":176,"column":4},"end":{"line":176,"column":10}},"126":{"start":{"line":178,"column":2},"end":{"line":178,"column":54}},"127":{"start":{"line":178,"column":28},"end":{"line":178,"column":54}},"128":{"start":{"line":179,"column":2},"end":{"line":179,"column":30}},"129":{"start":{"line":180,"column":2},"end":{"line":180,"column":29}},"130":{"start":{"line":180,"column":23},"end":{"line":180,"column":29}},"131":{"start":{"line":181,"column":2},"end":{"line":181,"column":41}},"132":{"start":{"line":181,"column":35},"end":{"line":181,"column":41}},"133":{"start":{"line":182,"column":2},"end":{"line":182,"column":35}},"134":{"start":{"line":182,"column":29},"end":{"line":182,"column":35}},"135":{"start":{"line":184,"column":2},"end":{"line":184,"column":32}},"136":{"start":{"line":185,"column":2},"end":{"line":185,"column":41}},"137":{"start":{"line":186,"column":2},"end":{"line":186,"column":22}},"138":{"start":{"line":187,"column":2},"end":{"line":197,"column":10}},"139":{"start":{"line":188,"column":4},"end":{"line":191,"column":5}},"140":{"start":{"line":189,"column":6},"end":{"line":189,"column":49}},"141":{"start":{"line":190,"column":6},"end":{"line":190,"column":21}},"142":{"start":{"line":192,"column":4},"end":{"line":192,"column":40}},"143":{"start":{"line":193,"column":4},"end":{"line":193,"column":26}},"144":{"start":{"line":194,"column":4},"end":{"line":194,"column":26}},"145":{"start":{"line":194,"column":11},"end":{"line":194,"column":26}},"146":{"start":{"line":195,"column":4},"end":{"line":195,"column":35}},"147":{"start":{"line":196,"column":4},"end":{"line":196,"column":33}},"148":{"start":{"line":198,"column":2},"end":{"line":198,"column":21}},"149":{"start":{"line":201,"column":0},"end":{"line":219,"column":1}},"150":{"start":{"line":202,"column":2},"end":{"line":202,"column":26}},"151":{"start":{"line":202,"column":20},"end":{"line":202,"column":26}},"152":{"start":{"line":203,"column":2},"end":{"line":209,"column":3}},"153":{"start":{"line":204,"column":4},"end":{"line":204,"column":62}},"154":{"start":{"line":205,"column":4},"end":{"line":205,"column":20}},"155":{"start":{"line":206,"column":4},"end":{"line":206,"column":54}},"156":{"start":{"line":206,"column":28},"end":{"line":206,"column":54}},"157":{"start":{"line":207,"column":4},"end":{"line":207,"column":63}},"158":{"start":{"line":207,"column":31},"end":{"line":207,"column":63}},"159":{"start":{"line":208,"column":4},"end":{"line":208,"column":48}},"160":{"start":{"line":211,"column":2},"end":{"line":211,"column":21}},"161":{"start":{"line":212,"column":2},"end":{"line":212,"column":42}},"162":{"start":{"line":212,"column":16},"end":{"line":212,"column":42}},"163":{"start":{"line":213,"column":2},"end":{"line":213,"column":42}},"164":{"start":{"line":213,"column":16},"end":{"line":213,"column":42}},"165":{"start":{"line":214,"column":2},"end":{"line":214,"column":36}},"166":{"start":{"line":214,"column":18},"end":{"line":214,"column":36}},"167":{"start":{"line":215,"column":2},"end":{"line":215,"column":46}},"168":{"start":{"line":215,"column":23},"end":{"line":215,"column":46}},"169":{"start":{"line":216,"column":2},"end":{"line":216,"column":42}},"170":{"start":{"line":216,"column":21},"end":{"line":216,"column":42}},"171":{"start":{"line":217,"column":2},"end":{"line":217,"column":36}},"172":{"start":{"line":217,"column":18},"end":{"line":217,"column":36}},"173":{"start":{"line":218,"column":2},"end":{"line":218,"column":32}},"174":{"start":{"line":221,"column":0},"end":{"line":234,"column":1}},"175":{"start":{"line":222,"column":2},"end":{"line":222,"column":23}},"176":{"start":{"line":222,"column":13},"end":{"line":222,"column":23}},"177":{"start":{"line":223,"column":2},"end":{"line":223,"column":22}},"178":{"start":{"line":224,"column":2},"end":{"line":224,"column":25}},"179":{"start":{"line":225,"column":2},"end":{"line":232,"column":14}},"180":{"start":{"line":225,"column":18},"end":{"line":232,"column":14}},"181":{"start":{"line":226,"column":4},"end":{"line":226,"column":43}},"182":{"start":{"line":227,"column":4},"end":{"line":227,"column":14}},"183":{"start":{"line":228,"column":4},"end":{"line":230,"column":5}},"184":{"start":{"line":229,"column":6},"end":{"line":229,"column":29}},"185":{"start":{"line":231,"column":4},"end":{"line":231,"column":34}},"186":{"start":{"line":233,"column":2},"end":{"line":233,"column":23}},"187":{"start":{"line":236,"column":0},"end":{"line":236,"column":35}},"188":{"start":{"line":237,"column":0},"end":{"line":237,"column":47}},"189":{"start":{"line":239,"column":0},"end":{"line":239,"column":14}},"190":{"start":{"line":240,"column":0},"end":{"line":240,"column":15}},"191":{"start":{"line":241,"column":0},"end":{"line":241,"column":13}},"192":{"start":{"line":242,"column":0},"end":{"line":242,"column":59}},"193":{"start":{"line":243,"column":0},"end":{"line":243,"column":66}},"194":{"start":{"line":244,"column":0},"end":{"line":244,"column":43}},"195":{"start":{"line":245,"column":0},"end":{"line":245,"column":56}},"196":{"start":{"line":246,"column":0},"end":{"line":246,"column":65}},"197":{"start":{"line":247,"column":0},"end":{"line":247,"column":63}},"198":{"start":{"line":248,"column":0},"end":{"line":248,"column":32}},"199":{"start":{"line":251,"column":0},"end":{"line":251,"column":29}}},"branchMap":{"1":{"line":51,"type":"if","locations":[{"start":{"line":51,"column":2},"end":{"line":51,"column":2}},{"start":{"line":51,"column":2},"end":{"line":51,"column":2}}]},"2":{"line":53,"type":"if","locations":[{"start":{"line":53,"column":2},"end":{"line":53,"column":2}},{"start":{"line":53,"column":2},"end":{"line":53,"column":2}}]},"3":{"line":60,"type":"if","locations":[{"start":{"line":60,"column":2},"end":{"line":60,"column":2}},{"start":{"line":60,"column":2},"end":{"line":60,"column":2}}]},"4":{"line":73,"type":"if","locations":[{"start":{"line":73,"column":4},"end":{"line":73,"column":4}},{"start":{"line":73,"column":4},"end":{"line":73,"column":4}}]},"5":{"line":74,"type":"if","locations":[{"start":{"line":74,"column":4},"end":{"line":74,"column":4}},{"start":{"line":74,"column":4},"end":{"line":74,"column":4}}]},"6":{"line":75,"type":"if","locations":[{"start":{"line":75,"column":4},"end":{"line":75,"column":4}},{"start":{"line":75,"column":4},"end":{"line":75,"column":4}}]},"7":{"line":76,"type":"if","locations":[{"start":{"line":76,"column":4},"end":{"line":76,"column":4}},{"start":{"line":76,"column":4},"end":{"line":76,"column":4}}]},"8":{"line":84,"type":"if","locations":[{"start":{"line":84,"column":2},"end":{"line":84,"column":2}},{"start":{"line":84,"column":2},"end":{"line":84,"column":2}}]},"9":{"line":99,"type":"if","locations":[{"start":{"line":99,"column":2},"end":{"line":99,"column":2}},{"start":{"line":99,"column":2},"end":{"line":99,"column":2}}]},"10":{"line":104,"type":"if","locations":[{"start":{"line":104,"column":2},"end":{"line":104,"column":2}},{"start":{"line":104,"column":2},"end":{"line":104,"column":2}}]},"11":{"line":105,"type":"if","locations":[{"start":{"line":105,"column":2},"end":{"line":105,"column":2}},{"start":{"line":105,"column":2},"end":{"line":105,"column":2}}]},"12":{"line":115,"type":"if","locations":[{"start":{"line":115,"column":2},"end":{"line":115,"column":2}},{"start":{"line":115,"column":2},"end":{"line":115,"column":2}}]},"13":{"line":123,"type":"if","locations":[{"start":{"line":123,"column":2},"end":{"line":123,"column":2}},{"start":{"line":123,"column":2},"end":{"line":123,"column":2}}]},"14":{"line":133,"type":"if","locations":[{"start":{"line":133,"column":2},"end":{"line":133,"column":2}},{"start":{"line":133,"column":2},"end":{"line":133,"column":2}}]},"15":{"line":144,"type":"if","locations":[{"start":{"line":144,"column":4},"end":{"line":144,"column":4}},{"start":{"line":144,"column":4},"end":{"line":144,"column":4}}]},"16":{"line":144,"type":"binary-expr","locations":[{"start":{"line":144,"column":8},"end":{"line":144,"column":31}},{"start":{"line":144,"column":35},"end":{"line":144,"column":38}},{"start":{"line":145,"column":9},"end":{"line":145,"column":29}},{"start":{"line":145,"column":34},"end":{"line":145,"column":43}}]},"17":{"line":149,"type":"if","locations":[{"start":{"line":149,"column":2},"end":{"line":149,"column":2}},{"start":{"line":149,"column":2},"end":{"line":149,"column":2}}]},"18":{"line":154,"type":"binary-expr","locations":[{"start":{"line":154,"column":27},"end":{"line":154,"column":33}},{"start":{"line":154,"column":37},"end":{"line":154,"column":39}}]},"19":{"line":160,"type":"if","locations":[{"start":{"line":160,"column":2},"end":{"line":160,"column":2}},{"start":{"line":160,"column":2},"end":{"line":160,"column":2}}]},"20":{"line":165,"type":"if","locations":[{"start":{"line":165,"column":2},"end":{"line":165,"column":2}},{"start":{"line":165,"column":2},"end":{"line":165,"column":2}}]},"21":{"line":174,"type":"if","locations":[{"start":{"line":174,"column":2},"end":{"line":174,"column":2}},{"start":{"line":174,"column":2},"end":{"line":174,"column":2}}]},"22":{"line":178,"type":"if","locations":[{"start":{"line":178,"column":2},"end":{"line":178,"column":2}},{"start":{"line":178,"column":2},"end":{"line":178,"column":2}}]},"23":{"line":180,"type":"if","locations":[{"start":{"line":180,"column":2},"end":{"line":180,"column":2}},{"start":{"line":180,"column":2},"end":{"line":180,"column":2}}]},"24":{"line":181,"type":"if","locations":[{"start":{"line":181,"column":2},"end":{"line":181,"column":2}},{"start":{"line":181,"column":2},"end":{"line":181,"column":2}}]},"25":{"line":182,"type":"if","locations":[{"start":{"line":182,"column":2},"end":{"line":182,"column":2}},{"start":{"line":182,"column":2},"end":{"line":182,"column":2}}]},"26":{"line":182,"type":"binary-expr","locations":[{"start":{"line":182,"column":6},"end":{"line":182,"column":11}},{"start":{"line":182,"column":15},"end":{"line":182,"column":27}}]},"27":{"line":185,"type":"binary-expr","locations":[{"start":{"line":185,"column":13},"end":{"line":185,"column":30}},{"start":{"line":185,"column":34},"end":{"line":185,"column":41}}]},"28":{"line":188,"type":"if","locations":[{"start":{"line":188,"column":4},"end":{"line":188,"column":4}},{"start":{"line":188,"column":4},"end":{"line":188,"column":4}}]},"29":{"line":193,"type":"binary-expr","locations":[{"start":{"line":193,"column":12},"end":{"line":193,"column":20}},{"start":{"line":193,"column":24},"end":{"line":193,"column":26}}]},"30":{"line":194,"type":"if","locations":[{"start":{"line":194,"column":4},"end":{"line":194,"column":4}},{"start":{"line":194,"column":4},"end":{"line":194,"column":4}}]},"31":{"line":202,"type":"if","locations":[{"start":{"line":202,"column":2},"end":{"line":202,"column":2}},{"start":{"line":202,"column":2},"end":{"line":202,"column":2}}]},"32":{"line":203,"type":"if","locations":[{"start":{"line":203,"column":2},"end":{"line":203,"column":2}},{"start":{"line":203,"column":2},"end":{"line":203,"column":2}}]},"33":{"line":206,"type":"if","locations":[{"start":{"line":206,"column":4},"end":{"line":206,"column":4}},{"start":{"line":206,"column":4},"end":{"line":206,"column":4}}]},"34":{"line":207,"type":"if","locations":[{"start":{"line":207,"column":4},"end":{"line":207,"column":4}},{"start":{"line":207,"column":4},"end":{"line":207,"column":4}}]},"35":{"line":211,"type":"binary-expr","locations":[{"start":{"line":211,"column":10},"end":{"line":211,"column":15}},{"start":{"line":211,"column":19},"end":{"line":211,"column":21}}]},"36":{"line":212,"type":"if","locations":[{"start":{"line":212,"column":2},"end":{"line":212,"column":2}},{"start":{"line":212,"column":2},"end":{"line":212,"column":2}}]},"37":{"line":213,"type":"if","locations":[{"start":{"line":213,"column":2},"end":{"line":213,"column":2}},{"start":{"line":213,"column":2},"end":{"line":213,"column":2}}]},"38":{"line":214,"type":"if","locations":[{"start":{"line":214,"column":2},"end":{"line":214,"column":2}},{"start":{"line":214,"column":2},"end":{"line":214,"column":2}}]},"39":{"line":215,"type":"if","locations":[{"start":{"line":215,"column":2},"end":{"line":215,"column":2}},{"start":{"line":215,"column":2},"end":{"line":215,"column":2}}]},"40":{"line":216,"type":"if","locations":[{"start":{"line":216,"column":2},"end":{"line":216,"column":2}},{"start":{"line":216,"column":2},"end":{"line":216,"column":2}}]},"41":{"line":217,"type":"if","locations":[{"start":{"line":217,"column":2},"end":{"line":217,"column":2}},{"start":{"line":217,"column":2},"end":{"line":217,"column":2}}]},"42":{"line":222,"type":"if","locations":[{"start":{"line":222,"column":2},"end":{"line":222,"column":2}},{"start":{"line":222,"column":2},"end":{"line":222,"column":2}}]},"43":{"line":225,"type":"if","locations":[{"start":{"line":225,"column":2},"end":{"line":225,"column":2}},{"start":{"line":225,"column":2},"end":{"line":225,"column":2}}]}}}} \ No newline at end of file diff --git a/deps/npm/node_modules/npmlog/.nyc_output/65000.json b/deps/npm/node_modules/npmlog/.nyc_output/65000.json deleted file mode 100644 index 77f20aa72f5034..00000000000000 --- a/deps/npm/node_modules/npmlog/.nyc_output/65000.json +++ /dev/null @@ -1 +0,0 @@ -{"./log.js":{"path":"./log.js","s":{"1":1,"2":1,"3":1,"4":1,"5":1,"6":1,"7":1,"8":1,"9":1,"10":1,"11":0,"12":0,"13":1,"14":0,"15":0,"16":1,"17":1,"18":1,"19":1,"20":1,"21":1,"22":0,"23":0,"24":1,"25":0,"26":0,"27":1,"28":1,"29":0,"30":0,"31":1,"32":10,"33":1,"34":9,"35":9,"36":0,"37":9,"38":9,"39":9,"40":1,"41":12,"42":4,"43":8,"44":8,"45":8,"46":8,"47":1,"48":1,"49":4,"50":172,"51":16,"52":156,"53":468,"54":12,"55":144,"56":4,"57":140,"58":55,"59":85,"60":85,"61":1,"62":4,"63":1,"64":3,"65":3,"66":1,"67":4,"68":1,"69":3,"70":3,"71":1,"72":11,"73":1,"74":10,"75":1,"76":22,"77":1,"78":21,"79":11,"80":21,"81":1,"82":0,"83":1,"84":0,"85":0,"86":0,"87":0,"88":0,"89":0,"90":0,"91":0,"92":0,"93":1,"94":1,"95":1,"96":1,"97":1,"98":1,"99":1,"100":0,"101":1,"102":1,"103":1,"104":1,"105":1,"106":0,"107":1,"108":0,"109":1,"110":1,"111":1,"112":1,"113":1,"114":1,"115":1,"116":1,"117":1,"118":1,"119":0,"120":0,"121":1,"122":1,"123":1,"124":0,"125":0,"126":1,"127":1,"128":1,"129":1,"130":0,"131":1,"132":0,"133":1,"134":0,"135":1,"136":1,"137":1,"138":1,"139":1,"140":0,"141":0,"142":1,"143":1,"144":1,"145":1,"146":1,"147":1,"148":1,"149":1,"150":4,"151":0,"152":4,"153":0,"154":0,"155":0,"156":0,"157":0,"158":0,"159":0,"160":4,"161":4,"162":2,"163":4,"164":1,"165":4,"166":0,"167":4,"168":0,"169":4,"170":0,"171":4,"172":0,"173":4,"174":1,"175":7,"176":3,"177":7,"178":7,"179":7,"180":7,"181":1,"182":1,"183":1,"184":2,"185":1,"186":7,"187":1,"188":1,"189":1,"190":1,"191":1,"192":1,"193":1,"194":1,"195":1,"196":1,"197":1,"198":1,"199":1},"b":{"1":[1,9],"2":[0,9],"3":[4,8],"4":[16,156],"5":[12,144],"6":[4,140],"7":[55,85],"8":[1,3],"9":[1,10],"10":[1,21],"11":[11,10],"12":[0,0],"13":[0,0],"14":[0,1],"15":[0,1],"16":[1,0,0,0],"17":[0,1],"18":[1,0],"19":[1,0],"20":[0,1],"21":[0,1],"22":[1,0],"23":[0,1],"24":[0,1],"25":[0,1],"26":[1,1],"27":[1,0],"28":[0,1],"29":[1,0],"30":[1,0],"31":[0,4],"32":[0,4],"33":[0,0],"34":[0,0],"35":[4,2],"36":[2,2],"37":[1,3],"38":[0,4],"39":[0,4],"40":[0,4],"41":[0,4],"42":[3,4],"43":[7,0]},"f":{"1":0,"2":0,"3":0,"4":0,"5":0,"6":10,"7":12,"8":4,"9":172,"10":468,"11":1,"12":3,"13":1,"14":3,"15":3,"16":11,"17":22,"18":0,"19":0,"20":0,"21":1,"22":1,"23":1,"24":4,"25":7,"26":1,"27":0},"fnMap":{"1":{"name":"(anonymous_1)","line":14,"loc":{"start":{"line":14,"column":18},"end":{"line":14,"column":30}}},"2":{"name":"(anonymous_2)","line":18,"loc":{"start":{"line":18,"column":19},"end":{"line":18,"column":31}}},"3":{"name":"(anonymous_3)","line":34,"loc":{"start":{"line":34,"column":20},"end":{"line":34,"column":32}}},"4":{"name":"(anonymous_4)","line":39,"loc":{"start":{"line":39,"column":21},"end":{"line":39,"column":33}}},"5":{"name":"(anonymous_5)","line":45,"loc":{"start":{"line":45,"column":23},"end":{"line":45,"column":43}}},"6":{"name":"(anonymous_6)","line":50,"loc":{"start":{"line":50,"column":21},"end":{"line":50,"column":33}}},"7":{"name":"(anonymous_7)","line":59,"loc":{"start":{"line":59,"column":22},"end":{"line":59,"column":34}}},"8":{"name":"(anonymous_8)","line":69,"loc":{"start":{"line":69,"column":15},"end":{"line":69,"column":34}}},"9":{"name":"(anonymous_9)","line":72,"loc":{"start":{"line":72,"column":27},"end":{"line":72,"column":40}}},"10":{"name":"(anonymous_10)","line":74,"loc":{"start":{"line":74,"column":35},"end":{"line":74,"column":48}}},"11":{"name":"(anonymous_11)","line":78,"loc":{"start":{"line":78,"column":17},"end":{"line":78,"column":29}}},"12":{"name":"(anonymous_12)","line":85,"loc":{"start":{"line":85,"column":32},"end":{"line":85,"column":45}}},"13":{"name":"(anonymous_13)","line":87,"loc":{"start":{"line":87,"column":19},"end":{"line":87,"column":31}}},"14":{"name":"(anonymous_14)","line":94,"loc":{"start":{"line":94,"column":28},"end":{"line":94,"column":41}}},"15":{"name":"(anonymous_15)","line":95,"loc":{"start":{"line":95,"column":11},"end":{"line":95,"column":23}}},"16":{"name":"(anonymous_16)","line":98,"loc":{"start":{"line":98,"column":20},"end":{"line":98,"column":32}}},"17":{"name":"(anonymous_17)","line":103,"loc":{"start":{"line":103,"column":19},"end":{"line":103,"column":46}}},"18":{"name":"(anonymous_18)","line":110,"loc":{"start":{"line":110,"column":12},"end":{"line":110,"column":24}}},"19":{"name":"(anonymous_19)","line":114,"loc":{"start":{"line":114,"column":13},"end":{"line":114,"column":25}}},"20":{"name":"(anonymous_20)","line":120,"loc":{"start":{"line":120,"column":12},"end":{"line":120,"column":25}}},"21":{"name":"(anonymous_21)","line":131,"loc":{"start":{"line":131,"column":10},"end":{"line":131,"column":42}}},"22":{"name":"(anonymous_22)","line":173,"loc":{"start":{"line":173,"column":14},"end":{"line":173,"column":27}}},"23":{"name":"(anonymous_23)","line":187,"loc":{"start":{"line":187,"column":35},"end":{"line":187,"column":51}}},"24":{"name":"(anonymous_24)","line":201,"loc":{"start":{"line":201,"column":12},"end":{"line":201,"column":34}}},"25":{"name":"(anonymous_25)","line":221,"loc":{"start":{"line":221,"column":15},"end":{"line":221,"column":46}}},"26":{"name":"(anonymous_26)","line":225,"loc":{"start":{"line":225,"column":30},"end":{"line":225,"column":42}}},"27":{"name":"(anonymous_27)","line":251,"loc":{"start":{"line":251,"column":16},"end":{"line":251,"column":26}}}},"statementMap":{"1":{"start":{"line":2,"column":0},"end":{"line":2,"column":42}},"2":{"start":{"line":3,"column":0},"end":{"line":3,"column":28}},"3":{"start":{"line":4,"column":0},"end":{"line":4,"column":39}},"4":{"start":{"line":5,"column":0},"end":{"line":5,"column":43}},"5":{"start":{"line":6,"column":0},"end":{"line":6,"column":26}},"6":{"start":{"line":8,"column":0},"end":{"line":8,"column":26}},"7":{"start":{"line":9,"column":0},"end":{"line":9,"column":33}},"8":{"start":{"line":10,"column":0},"end":{"line":10,"column":27}},"9":{"start":{"line":13,"column":0},"end":{"line":13,"column":28}},"10":{"start":{"line":14,"column":0},"end":{"line":17,"column":1}},"11":{"start":{"line":15,"column":2},"end":{"line":15,"column":21}},"12":{"start":{"line":16,"column":2},"end":{"line":16,"column":28}},"13":{"start":{"line":18,"column":0},"end":{"line":21,"column":1}},"14":{"start":{"line":19,"column":2},"end":{"line":19,"column":22}},"15":{"start":{"line":20,"column":2},"end":{"line":20,"column":29}},"16":{"start":{"line":24,"column":0},"end":{"line":24,"column":18}},"17":{"start":{"line":26,"column":0},"end":{"line":26,"column":33}},"18":{"start":{"line":27,"column":0},"end":{"line":27,"column":41}},"19":{"start":{"line":30,"column":0},"end":{"line":30,"column":27}},"20":{"start":{"line":32,"column":0},"end":{"line":32,"column":26}},"21":{"start":{"line":34,"column":0},"end":{"line":37,"column":1}},"22":{"start":{"line":35,"column":2},"end":{"line":35,"column":28}},"23":{"start":{"line":36,"column":2},"end":{"line":36,"column":32}},"24":{"start":{"line":39,"column":0},"end":{"line":42,"column":1}},"25":{"start":{"line":40,"column":2},"end":{"line":40,"column":26}},"26":{"start":{"line":41,"column":2},"end":{"line":41,"column":32}},"27":{"start":{"line":44,"column":0},"end":{"line":44,"column":29}},"28":{"start":{"line":45,"column":0},"end":{"line":48,"column":1}},"29":{"start":{"line":46,"column":2},"end":{"line":46,"column":26}},"30":{"start":{"line":47,"column":2},"end":{"line":47,"column":38}},"31":{"start":{"line":50,"column":0},"end":{"line":57,"column":1}},"32":{"start":{"line":51,"column":2},"end":{"line":51,"column":34}},"33":{"start":{"line":51,"column":28},"end":{"line":51,"column":34}},"34":{"start":{"line":52,"column":2},"end":{"line":52,"column":29}},"35":{"start":{"line":53,"column":2},"end":{"line":53,"column":25}},"36":{"start":{"line":53,"column":19},"end":{"line":53,"column":25}},"37":{"start":{"line":54,"column":2},"end":{"line":54,"column":46}},"38":{"start":{"line":55,"column":2},"end":{"line":55,"column":21}},"39":{"start":{"line":56,"column":2},"end":{"line":56,"column":21}},"40":{"start":{"line":59,"column":0},"end":{"line":65,"column":1}},"41":{"start":{"line":60,"column":2},"end":{"line":60,"column":35}},"42":{"start":{"line":60,"column":29},"end":{"line":60,"column":35}},"43":{"start":{"line":61,"column":2},"end":{"line":61,"column":22}},"44":{"start":{"line":62,"column":2},"end":{"line":62,"column":30}},"45":{"start":{"line":63,"column":2},"end":{"line":63,"column":58}},"46":{"start":{"line":64,"column":2},"end":{"line":64,"column":22}},"47":{"start":{"line":67,"column":0},"end":{"line":67,"column":62}},"48":{"start":{"line":69,"column":0},"end":{"line":91,"column":1}},"49":{"start":{"line":72,"column":2},"end":{"line":81,"column":4}},"50":{"start":{"line":73,"column":4},"end":{"line":73,"column":28}},"51":{"start":{"line":73,"column":22},"end":{"line":73,"column":28}},"52":{"start":{"line":74,"column":4},"end":{"line":74,"column":82}},"53":{"start":{"line":74,"column":50},"end":{"line":74,"column":65}},"54":{"start":{"line":74,"column":76},"end":{"line":74,"column":82}},"55":{"start":{"line":75,"column":4},"end":{"line":75,"column":26}},"56":{"start":{"line":75,"column":20},"end":{"line":75,"column":26}},"57":{"start":{"line":76,"column":4},"end":{"line":76,"column":44}},"58":{"start":{"line":76,"column":38},"end":{"line":76,"column":44}},"59":{"start":{"line":77,"column":4},"end":{"line":77,"column":21}},"60":{"start":{"line":78,"column":4},"end":{"line":80,"column":5}},"61":{"start":{"line":79,"column":6},"end":{"line":79,"column":39}},"62":{"start":{"line":84,"column":2},"end":{"line":89,"column":3}},"63":{"start":{"line":85,"column":4},"end":{"line":88,"column":6}},"64":{"start":{"line":86,"column":6},"end":{"line":86,"column":27}},"65":{"start":{"line":87,"column":6},"end":{"line":87,"column":82}},"66":{"start":{"line":87,"column":33},"end":{"line":87,"column":81}},"67":{"start":{"line":90,"column":2},"end":{"line":90,"column":16}},"68":{"start":{"line":94,"column":0},"end":{"line":96,"column":2}},"69":{"start":{"line":95,"column":2},"end":{"line":95,"column":90}},"70":{"start":{"line":95,"column":25},"end":{"line":95,"column":89}},"71":{"start":{"line":98,"column":0},"end":{"line":101,"column":1}},"72":{"start":{"line":99,"column":2},"end":{"line":99,"column":35}},"73":{"start":{"line":99,"column":29},"end":{"line":99,"column":35}},"74":{"start":{"line":100,"column":2},"end":{"line":100,"column":19}},"75":{"start":{"line":103,"column":0},"end":{"line":107,"column":11}},"76":{"start":{"line":104,"column":2},"end":{"line":104,"column":35}},"77":{"start":{"line":104,"column":29},"end":{"line":104,"column":35}},"78":{"start":{"line":105,"column":2},"end":{"line":105,"column":61}},"79":{"start":{"line":105,"column":25},"end":{"line":105,"column":61}},"80":{"start":{"line":106,"column":2},"end":{"line":106,"column":34}},"81":{"start":{"line":110,"column":0},"end":{"line":112,"column":1}},"82":{"start":{"line":111,"column":2},"end":{"line":111,"column":21}},"83":{"start":{"line":114,"column":0},"end":{"line":124,"column":1}},"84":{"start":{"line":115,"column":2},"end":{"line":115,"column":27}},"85":{"start":{"line":115,"column":21},"end":{"line":115,"column":27}},"86":{"start":{"line":116,"column":2},"end":{"line":116,"column":22}},"87":{"start":{"line":118,"column":2},"end":{"line":118,"column":22}},"88":{"start":{"line":119,"column":2},"end":{"line":119,"column":19}},"89":{"start":{"line":120,"column":2},"end":{"line":122,"column":10}},"90":{"start":{"line":121,"column":4},"end":{"line":121,"column":19}},"91":{"start":{"line":123,"column":2},"end":{"line":123,"column":49}},"92":{"start":{"line":123,"column":28},"end":{"line":123,"column":49}},"93":{"start":{"line":126,"column":0},"end":{"line":126,"column":16}},"94":{"start":{"line":128,"column":0},"end":{"line":128,"column":10}},"95":{"start":{"line":129,"column":0},"end":{"line":129,"column":15}},"96":{"start":{"line":130,"column":0},"end":{"line":130,"column":25}},"97":{"start":{"line":131,"column":0},"end":{"line":171,"column":11}},"98":{"start":{"line":132,"column":2},"end":{"line":132,"column":26}},"99":{"start":{"line":133,"column":2},"end":{"line":136,"column":3}},"100":{"start":{"line":134,"column":4},"end":{"line":135,"column":39}},"101":{"start":{"line":138,"column":2},"end":{"line":138,"column":41}},"102":{"start":{"line":139,"column":2},"end":{"line":139,"column":18}},"103":{"start":{"line":140,"column":2},"end":{"line":148,"column":3}},"104":{"start":{"line":141,"column":4},"end":{"line":141,"column":35}},"105":{"start":{"line":144,"column":4},"end":{"line":147,"column":5}},"106":{"start":{"line":146,"column":6},"end":{"line":146,"column":40}},"107":{"start":{"line":149,"column":2},"end":{"line":149,"column":36}},"108":{"start":{"line":149,"column":13},"end":{"line":149,"column":36}},"109":{"start":{"line":150,"column":2},"end":{"line":150,"column":38}},"110":{"start":{"line":152,"column":2},"end":{"line":156,"column":27}},"111":{"start":{"line":158,"column":2},"end":{"line":158,"column":21}},"112":{"start":{"line":159,"column":2},"end":{"line":159,"column":28}},"113":{"start":{"line":160,"column":2},"end":{"line":160,"column":38}},"114":{"start":{"line":160,"column":16},"end":{"line":160,"column":38}},"115":{"start":{"line":162,"column":2},"end":{"line":162,"column":21}},"116":{"start":{"line":163,"column":2},"end":{"line":163,"column":30}},"117":{"start":{"line":164,"column":2},"end":{"line":164,"column":34}},"118":{"start":{"line":165,"column":2},"end":{"line":168,"column":3}},"119":{"start":{"line":166,"column":4},"end":{"line":166,"column":39}},"120":{"start":{"line":167,"column":4},"end":{"line":167,"column":49}},"121":{"start":{"line":170,"column":2},"end":{"line":170,"column":17}},"122":{"start":{"line":173,"column":0},"end":{"line":199,"column":1}},"123":{"start":{"line":174,"column":2},"end":{"line":177,"column":3}},"124":{"start":{"line":175,"column":4},"end":{"line":175,"column":24}},"125":{"start":{"line":176,"column":4},"end":{"line":176,"column":10}},"126":{"start":{"line":178,"column":2},"end":{"line":178,"column":54}},"127":{"start":{"line":178,"column":28},"end":{"line":178,"column":54}},"128":{"start":{"line":179,"column":2},"end":{"line":179,"column":30}},"129":{"start":{"line":180,"column":2},"end":{"line":180,"column":29}},"130":{"start":{"line":180,"column":23},"end":{"line":180,"column":29}},"131":{"start":{"line":181,"column":2},"end":{"line":181,"column":41}},"132":{"start":{"line":181,"column":35},"end":{"line":181,"column":41}},"133":{"start":{"line":182,"column":2},"end":{"line":182,"column":35}},"134":{"start":{"line":182,"column":29},"end":{"line":182,"column":35}},"135":{"start":{"line":184,"column":2},"end":{"line":184,"column":32}},"136":{"start":{"line":185,"column":2},"end":{"line":185,"column":41}},"137":{"start":{"line":186,"column":2},"end":{"line":186,"column":22}},"138":{"start":{"line":187,"column":2},"end":{"line":197,"column":10}},"139":{"start":{"line":188,"column":4},"end":{"line":191,"column":5}},"140":{"start":{"line":189,"column":6},"end":{"line":189,"column":49}},"141":{"start":{"line":190,"column":6},"end":{"line":190,"column":21}},"142":{"start":{"line":192,"column":4},"end":{"line":192,"column":40}},"143":{"start":{"line":193,"column":4},"end":{"line":193,"column":26}},"144":{"start":{"line":194,"column":4},"end":{"line":194,"column":26}},"145":{"start":{"line":194,"column":11},"end":{"line":194,"column":26}},"146":{"start":{"line":195,"column":4},"end":{"line":195,"column":35}},"147":{"start":{"line":196,"column":4},"end":{"line":196,"column":33}},"148":{"start":{"line":198,"column":2},"end":{"line":198,"column":21}},"149":{"start":{"line":201,"column":0},"end":{"line":219,"column":1}},"150":{"start":{"line":202,"column":2},"end":{"line":202,"column":26}},"151":{"start":{"line":202,"column":20},"end":{"line":202,"column":26}},"152":{"start":{"line":203,"column":2},"end":{"line":209,"column":3}},"153":{"start":{"line":204,"column":4},"end":{"line":204,"column":62}},"154":{"start":{"line":205,"column":4},"end":{"line":205,"column":20}},"155":{"start":{"line":206,"column":4},"end":{"line":206,"column":54}},"156":{"start":{"line":206,"column":28},"end":{"line":206,"column":54}},"157":{"start":{"line":207,"column":4},"end":{"line":207,"column":63}},"158":{"start":{"line":207,"column":31},"end":{"line":207,"column":63}},"159":{"start":{"line":208,"column":4},"end":{"line":208,"column":48}},"160":{"start":{"line":211,"column":2},"end":{"line":211,"column":21}},"161":{"start":{"line":212,"column":2},"end":{"line":212,"column":42}},"162":{"start":{"line":212,"column":16},"end":{"line":212,"column":42}},"163":{"start":{"line":213,"column":2},"end":{"line":213,"column":42}},"164":{"start":{"line":213,"column":16},"end":{"line":213,"column":42}},"165":{"start":{"line":214,"column":2},"end":{"line":214,"column":36}},"166":{"start":{"line":214,"column":18},"end":{"line":214,"column":36}},"167":{"start":{"line":215,"column":2},"end":{"line":215,"column":46}},"168":{"start":{"line":215,"column":23},"end":{"line":215,"column":46}},"169":{"start":{"line":216,"column":2},"end":{"line":216,"column":42}},"170":{"start":{"line":216,"column":21},"end":{"line":216,"column":42}},"171":{"start":{"line":217,"column":2},"end":{"line":217,"column":36}},"172":{"start":{"line":217,"column":18},"end":{"line":217,"column":36}},"173":{"start":{"line":218,"column":2},"end":{"line":218,"column":32}},"174":{"start":{"line":221,"column":0},"end":{"line":234,"column":1}},"175":{"start":{"line":222,"column":2},"end":{"line":222,"column":23}},"176":{"start":{"line":222,"column":13},"end":{"line":222,"column":23}},"177":{"start":{"line":223,"column":2},"end":{"line":223,"column":22}},"178":{"start":{"line":224,"column":2},"end":{"line":224,"column":25}},"179":{"start":{"line":225,"column":2},"end":{"line":232,"column":14}},"180":{"start":{"line":225,"column":18},"end":{"line":232,"column":14}},"181":{"start":{"line":226,"column":4},"end":{"line":226,"column":43}},"182":{"start":{"line":227,"column":4},"end":{"line":227,"column":14}},"183":{"start":{"line":228,"column":4},"end":{"line":230,"column":5}},"184":{"start":{"line":229,"column":6},"end":{"line":229,"column":29}},"185":{"start":{"line":231,"column":4},"end":{"line":231,"column":34}},"186":{"start":{"line":233,"column":2},"end":{"line":233,"column":23}},"187":{"start":{"line":236,"column":0},"end":{"line":236,"column":35}},"188":{"start":{"line":237,"column":0},"end":{"line":237,"column":47}},"189":{"start":{"line":239,"column":0},"end":{"line":239,"column":14}},"190":{"start":{"line":240,"column":0},"end":{"line":240,"column":15}},"191":{"start":{"line":241,"column":0},"end":{"line":241,"column":13}},"192":{"start":{"line":242,"column":0},"end":{"line":242,"column":59}},"193":{"start":{"line":243,"column":0},"end":{"line":243,"column":66}},"194":{"start":{"line":244,"column":0},"end":{"line":244,"column":43}},"195":{"start":{"line":245,"column":0},"end":{"line":245,"column":56}},"196":{"start":{"line":246,"column":0},"end":{"line":246,"column":65}},"197":{"start":{"line":247,"column":0},"end":{"line":247,"column":63}},"198":{"start":{"line":248,"column":0},"end":{"line":248,"column":32}},"199":{"start":{"line":251,"column":0},"end":{"line":251,"column":29}}},"branchMap":{"1":{"line":51,"type":"if","locations":[{"start":{"line":51,"column":2},"end":{"line":51,"column":2}},{"start":{"line":51,"column":2},"end":{"line":51,"column":2}}]},"2":{"line":53,"type":"if","locations":[{"start":{"line":53,"column":2},"end":{"line":53,"column":2}},{"start":{"line":53,"column":2},"end":{"line":53,"column":2}}]},"3":{"line":60,"type":"if","locations":[{"start":{"line":60,"column":2},"end":{"line":60,"column":2}},{"start":{"line":60,"column":2},"end":{"line":60,"column":2}}]},"4":{"line":73,"type":"if","locations":[{"start":{"line":73,"column":4},"end":{"line":73,"column":4}},{"start":{"line":73,"column":4},"end":{"line":73,"column":4}}]},"5":{"line":74,"type":"if","locations":[{"start":{"line":74,"column":4},"end":{"line":74,"column":4}},{"start":{"line":74,"column":4},"end":{"line":74,"column":4}}]},"6":{"line":75,"type":"if","locations":[{"start":{"line":75,"column":4},"end":{"line":75,"column":4}},{"start":{"line":75,"column":4},"end":{"line":75,"column":4}}]},"7":{"line":76,"type":"if","locations":[{"start":{"line":76,"column":4},"end":{"line":76,"column":4}},{"start":{"line":76,"column":4},"end":{"line":76,"column":4}}]},"8":{"line":84,"type":"if","locations":[{"start":{"line":84,"column":2},"end":{"line":84,"column":2}},{"start":{"line":84,"column":2},"end":{"line":84,"column":2}}]},"9":{"line":99,"type":"if","locations":[{"start":{"line":99,"column":2},"end":{"line":99,"column":2}},{"start":{"line":99,"column":2},"end":{"line":99,"column":2}}]},"10":{"line":104,"type":"if","locations":[{"start":{"line":104,"column":2},"end":{"line":104,"column":2}},{"start":{"line":104,"column":2},"end":{"line":104,"column":2}}]},"11":{"line":105,"type":"if","locations":[{"start":{"line":105,"column":2},"end":{"line":105,"column":2}},{"start":{"line":105,"column":2},"end":{"line":105,"column":2}}]},"12":{"line":115,"type":"if","locations":[{"start":{"line":115,"column":2},"end":{"line":115,"column":2}},{"start":{"line":115,"column":2},"end":{"line":115,"column":2}}]},"13":{"line":123,"type":"if","locations":[{"start":{"line":123,"column":2},"end":{"line":123,"column":2}},{"start":{"line":123,"column":2},"end":{"line":123,"column":2}}]},"14":{"line":133,"type":"if","locations":[{"start":{"line":133,"column":2},"end":{"line":133,"column":2}},{"start":{"line":133,"column":2},"end":{"line":133,"column":2}}]},"15":{"line":144,"type":"if","locations":[{"start":{"line":144,"column":4},"end":{"line":144,"column":4}},{"start":{"line":144,"column":4},"end":{"line":144,"column":4}}]},"16":{"line":144,"type":"binary-expr","locations":[{"start":{"line":144,"column":8},"end":{"line":144,"column":31}},{"start":{"line":144,"column":35},"end":{"line":144,"column":38}},{"start":{"line":145,"column":9},"end":{"line":145,"column":29}},{"start":{"line":145,"column":34},"end":{"line":145,"column":43}}]},"17":{"line":149,"type":"if","locations":[{"start":{"line":149,"column":2},"end":{"line":149,"column":2}},{"start":{"line":149,"column":2},"end":{"line":149,"column":2}}]},"18":{"line":154,"type":"binary-expr","locations":[{"start":{"line":154,"column":27},"end":{"line":154,"column":33}},{"start":{"line":154,"column":37},"end":{"line":154,"column":39}}]},"19":{"line":160,"type":"if","locations":[{"start":{"line":160,"column":2},"end":{"line":160,"column":2}},{"start":{"line":160,"column":2},"end":{"line":160,"column":2}}]},"20":{"line":165,"type":"if","locations":[{"start":{"line":165,"column":2},"end":{"line":165,"column":2}},{"start":{"line":165,"column":2},"end":{"line":165,"column":2}}]},"21":{"line":174,"type":"if","locations":[{"start":{"line":174,"column":2},"end":{"line":174,"column":2}},{"start":{"line":174,"column":2},"end":{"line":174,"column":2}}]},"22":{"line":178,"type":"if","locations":[{"start":{"line":178,"column":2},"end":{"line":178,"column":2}},{"start":{"line":178,"column":2},"end":{"line":178,"column":2}}]},"23":{"line":180,"type":"if","locations":[{"start":{"line":180,"column":2},"end":{"line":180,"column":2}},{"start":{"line":180,"column":2},"end":{"line":180,"column":2}}]},"24":{"line":181,"type":"if","locations":[{"start":{"line":181,"column":2},"end":{"line":181,"column":2}},{"start":{"line":181,"column":2},"end":{"line":181,"column":2}}]},"25":{"line":182,"type":"if","locations":[{"start":{"line":182,"column":2},"end":{"line":182,"column":2}},{"start":{"line":182,"column":2},"end":{"line":182,"column":2}}]},"26":{"line":182,"type":"binary-expr","locations":[{"start":{"line":182,"column":6},"end":{"line":182,"column":11}},{"start":{"line":182,"column":15},"end":{"line":182,"column":27}}]},"27":{"line":185,"type":"binary-expr","locations":[{"start":{"line":185,"column":13},"end":{"line":185,"column":30}},{"start":{"line":185,"column":34},"end":{"line":185,"column":41}}]},"28":{"line":188,"type":"if","locations":[{"start":{"line":188,"column":4},"end":{"line":188,"column":4}},{"start":{"line":188,"column":4},"end":{"line":188,"column":4}}]},"29":{"line":193,"type":"binary-expr","locations":[{"start":{"line":193,"column":12},"end":{"line":193,"column":20}},{"start":{"line":193,"column":24},"end":{"line":193,"column":26}}]},"30":{"line":194,"type":"if","locations":[{"start":{"line":194,"column":4},"end":{"line":194,"column":4}},{"start":{"line":194,"column":4},"end":{"line":194,"column":4}}]},"31":{"line":202,"type":"if","locations":[{"start":{"line":202,"column":2},"end":{"line":202,"column":2}},{"start":{"line":202,"column":2},"end":{"line":202,"column":2}}]},"32":{"line":203,"type":"if","locations":[{"start":{"line":203,"column":2},"end":{"line":203,"column":2}},{"start":{"line":203,"column":2},"end":{"line":203,"column":2}}]},"33":{"line":206,"type":"if","locations":[{"start":{"line":206,"column":4},"end":{"line":206,"column":4}},{"start":{"line":206,"column":4},"end":{"line":206,"column":4}}]},"34":{"line":207,"type":"if","locations":[{"start":{"line":207,"column":4},"end":{"line":207,"column":4}},{"start":{"line":207,"column":4},"end":{"line":207,"column":4}}]},"35":{"line":211,"type":"binary-expr","locations":[{"start":{"line":211,"column":10},"end":{"line":211,"column":15}},{"start":{"line":211,"column":19},"end":{"line":211,"column":21}}]},"36":{"line":212,"type":"if","locations":[{"start":{"line":212,"column":2},"end":{"line":212,"column":2}},{"start":{"line":212,"column":2},"end":{"line":212,"column":2}}]},"37":{"line":213,"type":"if","locations":[{"start":{"line":213,"column":2},"end":{"line":213,"column":2}},{"start":{"line":213,"column":2},"end":{"line":213,"column":2}}]},"38":{"line":214,"type":"if","locations":[{"start":{"line":214,"column":2},"end":{"line":214,"column":2}},{"start":{"line":214,"column":2},"end":{"line":214,"column":2}}]},"39":{"line":215,"type":"if","locations":[{"start":{"line":215,"column":2},"end":{"line":215,"column":2}},{"start":{"line":215,"column":2},"end":{"line":215,"column":2}}]},"40":{"line":216,"type":"if","locations":[{"start":{"line":216,"column":2},"end":{"line":216,"column":2}},{"start":{"line":216,"column":2},"end":{"line":216,"column":2}}]},"41":{"line":217,"type":"if","locations":[{"start":{"line":217,"column":2},"end":{"line":217,"column":2}},{"start":{"line":217,"column":2},"end":{"line":217,"column":2}}]},"42":{"line":222,"type":"if","locations":[{"start":{"line":222,"column":2},"end":{"line":222,"column":2}},{"start":{"line":222,"column":2},"end":{"line":222,"column":2}}]},"43":{"line":225,"type":"if","locations":[{"start":{"line":225,"column":2},"end":{"line":225,"column":2}},{"start":{"line":225,"column":2},"end":{"line":225,"column":2}}]}}}} \ No newline at end of file diff --git a/deps/npm/node_modules/npmlog/.travis.yml b/deps/npm/node_modules/npmlog/.travis.yml deleted file mode 100644 index e76e1ac81ff366..00000000000000 --- a/deps/npm/node_modules/npmlog/.travis.yml +++ /dev/null @@ -1,14 +0,0 @@ -language: node_js -sudo: false -node_js: - - "5" - - "4" - - iojs - - "0.12" - - "0.10" - - "0.8" -before_install: - - "npm install -g npm" -script: "npm test" -notifications: - slack: npm-inc:kRqQjto7YbINqHPb1X6nS3g8 diff --git a/deps/npm/node_modules/npmlog/example.js b/deps/npm/node_modules/npmlog/example.js deleted file mode 100644 index c009fb15777fbe..00000000000000 --- a/deps/npm/node_modules/npmlog/example.js +++ /dev/null @@ -1,39 +0,0 @@ -var log = require('./log.js') - -log.heading = 'npm' - -console.error('log.level=silly') -log.level = 'silly' -log.silly('silly prefix', 'x = %j', {foo:{bar:'baz'}}) -log.verbose('verbose prefix', 'x = %j', {foo:{bar:'baz'}}) -log.info('info prefix', 'x = %j', {foo:{bar:'baz'}}) -log.http('http prefix', 'x = %j', {foo:{bar:'baz'}}) -log.warn('warn prefix', 'x = %j', {foo:{bar:'baz'}}) -log.error('error prefix', 'x = %j', {foo:{bar:'baz'}}) -log.silent('silent prefix', 'x = %j', {foo:{bar:'baz'}}) - -console.error('log.level=silent') -log.level = 'silent' -log.silly('silly prefix', 'x = %j', {foo:{bar:'baz'}}) -log.verbose('verbose prefix', 'x = %j', {foo:{bar:'baz'}}) -log.info('info prefix', 'x = %j', {foo:{bar:'baz'}}) -log.http('http prefix', 'x = %j', {foo:{bar:'baz'}}) -log.warn('warn prefix', 'x = %j', {foo:{bar:'baz'}}) -log.error('error prefix', 'x = %j', {foo:{bar:'baz'}}) -log.silent('silent prefix', 'x = %j', {foo:{bar:'baz'}}) - -console.error('log.level=info') -log.level = 'info' -log.silly('silly prefix', 'x = %j', {foo:{bar:'baz'}}) -log.verbose('verbose prefix', 'x = %j', {foo:{bar:'baz'}}) -log.info('info prefix', 'x = %j', {foo:{bar:'baz'}}) -log.http('http prefix', 'x = %j', {foo:{bar:'baz'}}) -log.warn('warn prefix', 'x = %j', {foo:{bar:'baz'}}) -log.error('error prefix', 'x = %j', {foo:{bar:'baz'}}) -log.silent('silent prefix', 'x = %j', {foo:{bar:'baz'}}) -log.error('404', 'This is a longer\n'+ - 'message, with some details\n'+ - 'and maybe a stack.\n'+ - new Error('a 404 error').stack) -log.addLevel('noise', 10000, {beep: true}) -log.noise(false, 'LOUD NOISES') diff --git a/deps/npm/node_modules/npmlog/node_modules/are-we-there-yet/node_modules/delegates/package.json b/deps/npm/node_modules/npmlog/node_modules/are-we-there-yet/node_modules/delegates/package.json index 56526bcd3ee117..353a46db79b362 100644 --- a/deps/npm/node_modules/npmlog/node_modules/are-we-there-yet/node_modules/delegates/package.json +++ b/deps/npm/node_modules/npmlog/node_modules/are-we-there-yet/node_modules/delegates/package.json @@ -43,7 +43,7 @@ ], "dist": { "shasum": "84c6e159b81904fdca59a0ef44cd870d31250f9a", - "tarball": "http://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz" + "tarball": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz" }, "directories": {}, "_resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", diff --git a/deps/npm/node_modules/npmlog/node_modules/are-we-there-yet/package.json b/deps/npm/node_modules/npmlog/node_modules/are-we-there-yet/package.json index c4339a033c572b..af6ea5e3f4230b 100644 --- a/deps/npm/node_modules/npmlog/node_modules/are-we-there-yet/package.json +++ b/deps/npm/node_modules/npmlog/node_modules/are-we-there-yet/package.json @@ -52,5 +52,6 @@ "tmp": "tmp/are-we-there-yet-1.1.2.tgz_1458084397358_0.15847722673788667" }, "directories": {}, - "_resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.2.tgz" + "_resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.2.tgz", + "readme": "ERROR: No README data found!" } diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/has-unicode/package.json b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/has-unicode/package.json index 66ce401975ef9b..39d090bb2b9d36 100644 --- a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/has-unicode/package.json +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/has-unicode/package.json @@ -39,7 +39,7 @@ }, "dist": { "shasum": "a3cd96c307ba41d559c5a2ee408c12a11c4c2ec3", - "tarball": "http://registry.npmjs.org/has-unicode/-/has-unicode-2.0.0.tgz" + "tarball": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.0.tgz" }, "maintainers": [ { diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/LICENSE b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/LICENSE index bcbe13d67a9621..e0c69d56032d15 100644 --- a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/LICENSE +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/LICENSE @@ -1,23 +1,47 @@ -The MIT License (MIT) +Copyright jQuery Foundation and other contributors -Copyright 2012-2016 The Dojo Foundation -Based on Underscore.js, copyright 2009-2016 Jeremy Ashkenas, +Based on Underscore.js, copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +This software consists of voluntary contributions made by many +individuals. For exact contribution history, see the revision history +available at https://github.com/lodash/lodash + +The following license applies to all parts of this software except as +documented below: + +==== + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +==== + +Copyright and related rights for sample code are waived via CC0. Sample +code is defined as all source code displayed within the prose of the +documentation. + +CC0: http://creativecommons.org/publicdomain/zero/1.0/ + +==== + +Files located in the node_modules and vendor directories are externally +maintained libraries used by this software which have their own +licenses; we recommend you read them, as their terms may differ from the +terms above. diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/README.md b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/README.md index f43453bf2e04eb..57fb585913f433 100644 --- a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/README.md +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/README.md @@ -1,4 +1,4 @@ -# lodash.pad v4.1.0 +# lodash.pad v4.4.0 The [lodash](https://lodash.com/) method `_.pad` exported as a [Node.js](https://nodejs.org/) module. @@ -15,4 +15,4 @@ In Node.js: var pad = require('lodash.pad'); ``` -See the [documentation](https://lodash.com/docs#pad) or [package source](https://github.com/lodash/lodash/blob/4.1.0-npm-packages/lodash.pad) for more details. +See the [documentation](https://lodash.com/docs#pad) or [package source](https://github.com/lodash/lodash/blob/4.4.0-npm-packages/lodash.pad) for more details. diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/index.js b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/index.js index 6220e0f831a714..876fbb967490ae 100644 --- a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/index.js +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/index.js @@ -1,22 +1,25 @@ /** - * lodash 4.1.0 (Custom Build) + * lodash (Custom Build) * Build: `lodash modularize exports="npm" -o ./` - * Copyright 2012-2016 The Dojo Foundation + * Copyright jQuery Foundation and other contributors + * Released under MIT license * Based on Underscore.js 1.8.3 - * Copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors */ -var repeat = require('lodash.repeat'), +var baseSlice = require('lodash._baseslice'), + baseToString = require('lodash._basetostring'), toString = require('lodash.tostring'); /** Used as references for various `Number` constants. */ var INFINITY = 1 / 0, + MAX_SAFE_INTEGER = 9007199254740991, MAX_INTEGER = 1.7976931348623157e+308, NAN = 0 / 0; /** `Object#toString` result references. */ var funcTag = '[object Function]', - genTag = '[object GeneratorFunction]'; + genTag = '[object GeneratorFunction]', + symbolTag = '[object Symbol]'; /** Used to match leading and trailing whitespace. */ var reTrim = /^\s+|\s+$/g; @@ -95,7 +98,8 @@ function stringToArray(string) { var objectProto = Object.prototype; /** - * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) * of values. */ var objectToString = objectProto.toString; @@ -104,30 +108,69 @@ var objectToString = objectProto.toString; var nativeCeil = Math.ceil, nativeFloor = Math.floor; +/** + * The base implementation of `_.repeat` which doesn't coerce arguments. + * + * @private + * @param {string} string The string to repeat. + * @param {number} n The number of times to repeat the string. + * @returns {string} Returns the repeated string. + */ +function baseRepeat(string, n) { + var result = ''; + if (!string || n < 1 || n > MAX_SAFE_INTEGER) { + return result; + } + // Leverage the exponentiation by squaring algorithm for a faster repeat. + // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details. + do { + if (n % 2) { + result += string; + } + n = nativeFloor(n / 2); + if (n) { + string += string; + } + } while (n); + + return result; +} + +/** + * Casts `array` to a slice if it's needed. + * + * @private + * @param {Array} array The array to inspect. + * @param {number} start The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the cast slice. + */ +function castSlice(array, start, end) { + var length = array.length; + end = end === undefined ? length : end; + return (!start && end >= length) ? array : baseSlice(array, start, end); +} + /** * Creates the padding for `string` based on `length`. The `chars` string * is truncated if the number of characters exceeds `length`. * * @private - * @param {string} string The string to create padding for. - * @param {number} [length=0] The padding length. + * @param {number} length The padding length. * @param {string} [chars=' '] The string used as padding. * @returns {string} Returns the padding for `string`. */ -function createPadding(string, length, chars) { - length = toInteger(length); +function createPadding(length, chars) { + chars = chars === undefined ? ' ' : baseToString(chars); - var strLength = stringSize(string); - if (!length || strLength >= length) { - return ''; + var charsLength = chars.length; + if (charsLength < 2) { + return charsLength ? baseRepeat(chars, length) : chars; } - var padLength = length - strLength; - chars = chars === undefined ? ' ' : (chars + ''); - - var result = repeat(chars, nativeCeil(padLength / stringSize(chars))); + var result = baseRepeat(chars, nativeCeil(length / stringSize(chars))); return reHasComplexSymbol.test(chars) - ? stringToArray(result).slice(0, padLength).join('') - : result.slice(0, padLength); + ? castSlice(stringToArray(result), 0, length).join('') + : result.slice(0, length); } /** @@ -135,9 +178,11 @@ function createPadding(string, length, chars) { * * @static * @memberOf _ + * @since 0.1.0 * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @returns {boolean} Returns `true` if `value` is correctly classified, + * else `false`. * @example * * _.isFunction(_); @@ -148,18 +193,20 @@ function createPadding(string, length, chars) { */ function isFunction(value) { // The use of `Object#toString` avoids issues with the `typeof` operator - // in Safari 8 which returns 'object' for typed array constructors, and - // PhantomJS 1.9 which returns 'function' for `NodeList` instances. + // in Safari 8 which returns 'object' for typed array and weak map constructors, + // and PhantomJS 1.9 which returns 'function' for `NodeList` instances. var tag = isObject(value) ? objectToString.call(value) : ''; return tag == funcTag || tag == genTag; } /** - * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`. - * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/6.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) * * @static * @memberOf _ + * @since 0.1.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is an object, else `false`. @@ -183,30 +230,80 @@ function isObject(value) { } /** - * Converts `value` to an integer. + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". * - * **Note:** This function is loosely based on [`ToInteger`](http://www.ecma-international.org/ecma-262/6.0/#sec-tointeger). + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ +function isObjectLike(value) { + return !!value && typeof value == 'object'; +} + +/** + * Checks if `value` is classified as a `Symbol` primitive or object. * * @static * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, + * else `false`. + * @example + * + * _.isSymbol(Symbol.iterator); + * // => true + * + * _.isSymbol('abc'); + * // => false + */ +function isSymbol(value) { + return typeof value == 'symbol' || + (isObjectLike(value) && objectToString.call(value) == symbolTag); +} + +/** + * Converts `value` to a finite number. + * + * @static + * @memberOf _ + * @since 4.12.0 * @category Lang * @param {*} value The value to convert. - * @returns {number} Returns the converted integer. + * @returns {number} Returns the converted number. * @example * - * _.toInteger(3); - * // => 3 + * _.toFinite(3.2); + * // => 3.2 * - * _.toInteger(Number.MIN_VALUE); - * // => 0 + * _.toFinite(Number.MIN_VALUE); + * // => 5e-324 * - * _.toInteger(Infinity); + * _.toFinite(Infinity); * // => 1.7976931348623157e+308 * - * _.toInteger('3'); - * // => 3 + * _.toFinite('3.2'); + * // => 3.2 */ -function toInteger(value) { +function toFinite(value) { if (!value) { return value === 0 ? value : 0; } @@ -215,8 +312,40 @@ function toInteger(value) { var sign = (value < 0 ? -1 : 1); return sign * MAX_INTEGER; } - var remainder = value % 1; - return value === value ? (remainder ? value - remainder : value) : 0; + return value === value ? value : 0; +} + +/** + * Converts `value` to an integer. + * + * **Note:** This function is loosely based on + * [`ToInteger`](http://www.ecma-international.org/ecma-262/6.0/#sec-tointeger). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted integer. + * @example + * + * _.toInteger(3.2); + * // => 3 + * + * _.toInteger(Number.MIN_VALUE); + * // => 0 + * + * _.toInteger(Infinity); + * // => 1.7976931348623157e+308 + * + * _.toInteger('3.2'); + * // => 3 + */ +function toInteger(value) { + var result = toFinite(value), + remainder = result % 1; + + return result === result ? (remainder ? result - remainder : result) : 0; } /** @@ -224,13 +353,14 @@ function toInteger(value) { * * @static * @memberOf _ + * @since 4.0.0 * @category Lang * @param {*} value The value to process. * @returns {number} Returns the number. * @example * - * _.toNumber(3); - * // => 3 + * _.toNumber(3.2); + * // => 3.2 * * _.toNumber(Number.MIN_VALUE); * // => 5e-324 @@ -238,10 +368,16 @@ function toInteger(value) { * _.toNumber(Infinity); * // => Infinity * - * _.toNumber('3'); - * // => 3 + * _.toNumber('3.2'); + * // => 3.2 */ function toNumber(value) { + if (typeof value == 'number') { + return value; + } + if (isSymbol(value)) { + return NAN; + } if (isObject(value)) { var other = isFunction(value.valueOf) ? value.valueOf() : value; value = isObject(other) ? (other + '') : other; @@ -262,6 +398,7 @@ function toNumber(value) { * * @static * @memberOf _ + * @since 3.0.0 * @category String * @param {string} [string=''] The string to pad. * @param {number} [length=0] The padding length. @@ -282,15 +419,16 @@ function pad(string, length, chars) { string = toString(string); length = toInteger(length); - var strLength = stringSize(string); + var strLength = length ? stringSize(string) : 0; if (!length || strLength >= length) { return string; } - var mid = (length - strLength) / 2, - leftLength = nativeFloor(mid), - rightLength = nativeCeil(mid); - - return createPadding('', leftLength, chars) + string + createPadding('', rightLength, chars); + var mid = (length - strLength) / 2; + return ( + createPadding(nativeFloor(mid), chars) + + string + + createPadding(nativeCeil(mid), chars) + ); } module.exports = pad; diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/node_modules/lodash._baseslice/LICENSE b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/node_modules/lodash._baseslice/LICENSE new file mode 100644 index 00000000000000..b054ca5a3ac7d6 --- /dev/null +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/node_modules/lodash._baseslice/LICENSE @@ -0,0 +1,22 @@ +Copyright 2012-2016 The Dojo Foundation +Based on Underscore.js, copyright 2009-2016 Jeremy Ashkenas, +DocumentCloud and Investigative Reporters & Editors + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/node_modules/lodash._baseslice/README.md b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/node_modules/lodash._baseslice/README.md new file mode 100644 index 00000000000000..8cd4181ccdc00d --- /dev/null +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/node_modules/lodash._baseslice/README.md @@ -0,0 +1,18 @@ +# lodash._baseslice v4.0.0 + +The internal [lodash](https://lodash.com/) function `baseSlice` exported as a [Node.js](https://nodejs.org/) module. + +## Installation + +Using npm: +```bash +$ {sudo -H} npm i -g npm +$ npm i --save lodash._baseslice +``` + +In Node.js: +```js +var baseSlice = require('lodash._baseslice'); +``` + +See the [package source](https://github.com/lodash/lodash/blob/4.0.0-npm-packages/lodash._baseslice) for more details. diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/node_modules/lodash._baseslice/index.js b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/node_modules/lodash._baseslice/index.js new file mode 100644 index 00000000000000..59293c3d0037a8 --- /dev/null +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/node_modules/lodash._baseslice/index.js @@ -0,0 +1,40 @@ +/** + * lodash 4.0.0 (Custom Build) + * Build: `lodash modularize exports="npm" -o ./` + * Copyright 2012-2016 The Dojo Foundation + * Based on Underscore.js 1.8.3 + * Copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + * Available under MIT license + */ + +/** + * The base implementation of `_.slice` without an iteratee call guard. + * + * @private + * @param {Array} array The array to slice. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the slice of `array`. + */ +function baseSlice(array, start, end) { + var index = -1, + length = array.length; + + if (start < 0) { + start = -start > length ? 0 : (length + start); + } + end = end > length ? length : end; + if (end < 0) { + end += length; + } + length = start > end ? 0 : ((end - start) >>> 0); + start >>>= 0; + + var result = Array(length); + while (++index < length) { + result[index] = array[index + start]; + } + return result; +} + +module.exports = baseSlice; diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/node_modules/lodash._baseslice/package.json b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/node_modules/lodash._baseslice/package.json new file mode 100644 index 00000000000000..a8e4a8520c7ad0 --- /dev/null +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/node_modules/lodash._baseslice/package.json @@ -0,0 +1,70 @@ +{ + "name": "lodash._baseslice", + "version": "4.0.0", + "description": "The internal lodash function `baseSlice` exported as a module.", + "homepage": "https://lodash.com/", + "icon": "https://lodash.com/icon.svg", + "license": "MIT", + "author": { + "name": "John-David Dalton", + "email": "john.david.dalton@gmail.com", + "url": "http://allyoucanleet.com/" + }, + "contributors": [ + { + "name": "John-David Dalton", + "email": "john.david.dalton@gmail.com", + "url": "http://allyoucanleet.com/" + }, + { + "name": "Blaine Bublitz", + "email": "blaine@iceddev.com", + "url": "https://github.com/phated" + }, + { + "name": "Mathias Bynens", + "email": "mathias@qiwi.be", + "url": "https://mathiasbynens.be/" + } + ], + "repository": { + "type": "git", + "url": "git+https://github.com/lodash/lodash.git" + }, + "scripts": { + "test": "echo \"See https://travis-ci.org/lodash/lodash-cli for testing details.\"" + }, + "bugs": { + "url": "https://github.com/lodash/lodash/issues" + }, + "_id": "lodash._baseslice@4.0.0", + "_shasum": "f5ce1df982948ecaff63f223853415b7b9763704", + "_from": "lodash._baseslice@>=4.0.0 <4.1.0", + "_npmVersion": "2.14.15", + "_nodeVersion": "5.4.0", + "_npmUser": { + "name": "jdalton", + "email": "john.david.dalton@gmail.com" + }, + "dist": { + "shasum": "f5ce1df982948ecaff63f223853415b7b9763704", + "tarball": "https://registry.npmjs.org/lodash._baseslice/-/lodash._baseslice-4.0.0.tgz" + }, + "maintainers": [ + { + "name": "jdalton", + "email": "john.david.dalton@gmail.com" + }, + { + "name": "mathias", + "email": "mathias@qiwi.be" + }, + { + "name": "phated", + "email": "blaine@iceddev.com" + } + ], + "directories": {}, + "_resolved": "https://registry.npmjs.org/lodash._baseslice/-/lodash._baseslice-4.0.0.tgz", + "readme": "ERROR: No README data found!" +} diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.repeat/LICENSE b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/node_modules/lodash._basetostring/LICENSE similarity index 100% rename from deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.repeat/LICENSE rename to deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/node_modules/lodash._basetostring/LICENSE diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/node_modules/lodash._basetostring/README.md b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/node_modules/lodash._basetostring/README.md new file mode 100644 index 00000000000000..ba060c94dadea0 --- /dev/null +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/node_modules/lodash._basetostring/README.md @@ -0,0 +1,18 @@ +# lodash._basetostring v4.12.0 + +The internal [lodash](https://lodash.com/) function `baseToString` exported as a [Node.js](https://nodejs.org/) module. + +## Installation + +Using npm: +```bash +$ {sudo -H} npm i -g npm +$ npm i --save lodash._basetostring +``` + +In Node.js: +```js +var baseToString = require('lodash._basetostring'); +``` + +See the [package source](https://github.com/lodash/lodash/blob/4.12.0-npm-packages/lodash._basetostring) for more details. diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/node_modules/lodash._basetostring/index.js b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/node_modules/lodash._basetostring/index.js new file mode 100644 index 00000000000000..d5848107499c34 --- /dev/null +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/node_modules/lodash._basetostring/index.js @@ -0,0 +1,153 @@ +/** + * lodash (Custom Build) + * Build: `lodash modularize exports="npm" -o ./` + * Copyright jQuery Foundation and other contributors + * Released under MIT license + * Based on Underscore.js 1.8.3 + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + */ + +/** Used as references for various `Number` constants. */ +var INFINITY = 1 / 0; + +/** `Object#toString` result references. */ +var symbolTag = '[object Symbol]'; + +/** Used to determine if values are of the language type `Object`. */ +var objectTypes = { + 'function': true, + 'object': true +}; + +/** Detect free variable `exports`. */ +var freeExports = (objectTypes[typeof exports] && exports && !exports.nodeType) + ? exports + : undefined; + +/** Detect free variable `module`. */ +var freeModule = (objectTypes[typeof module] && module && !module.nodeType) + ? module + : undefined; + +/** Detect free variable `global` from Node.js. */ +var freeGlobal = checkGlobal(freeExports && freeModule && typeof global == 'object' && global); + +/** Detect free variable `self`. */ +var freeSelf = checkGlobal(objectTypes[typeof self] && self); + +/** Detect free variable `window`. */ +var freeWindow = checkGlobal(objectTypes[typeof window] && window); + +/** Detect `this` as the global object. */ +var thisGlobal = checkGlobal(objectTypes[typeof this] && this); + +/** + * Used as a reference to the global object. + * + * The `this` value is used if it's the global object to avoid Greasemonkey's + * restricted `window` object, otherwise the `window` object is used. + */ +var root = freeGlobal || + ((freeWindow !== (thisGlobal && thisGlobal.window)) && freeWindow) || + freeSelf || thisGlobal || Function('return this')(); + +/** + * Checks if `value` is a global object. + * + * @private + * @param {*} value The value to check. + * @returns {null|Object} Returns `value` if it's a global object, else `null`. + */ +function checkGlobal(value) { + return (value && value.Object === Object) ? value : null; +} + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * of values. + */ +var objectToString = objectProto.toString; + +/** Built-in value references. */ +var Symbol = root.Symbol; + +/** Used to convert symbols to primitives and strings. */ +var symbolProto = Symbol ? Symbol.prototype : undefined, + symbolToString = symbolProto ? symbolProto.toString : undefined; + +/** + * The base implementation of `_.toString` which doesn't convert nullish + * values to empty strings. + * + * @private + * @param {*} value The value to process. + * @returns {string} Returns the string. + */ +function baseToString(value) { + // Exit early for strings to avoid a performance hit in some environments. + if (typeof value == 'string') { + return value; + } + if (isSymbol(value)) { + return symbolToString ? symbolToString.call(value) : ''; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; +} + +/** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ +function isObjectLike(value) { + return !!value && typeof value == 'object'; +} + +/** + * Checks if `value` is classified as a `Symbol` primitive or object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, + * else `false`. + * @example + * + * _.isSymbol(Symbol.iterator); + * // => true + * + * _.isSymbol('abc'); + * // => false + */ +function isSymbol(value) { + return typeof value == 'symbol' || + (isObjectLike(value) && objectToString.call(value) == symbolTag); +} + +module.exports = baseToString; diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/node_modules/lodash._basetostring/package.json b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/node_modules/lodash._basetostring/package.json new file mode 100644 index 00000000000000..474798f13467c2 --- /dev/null +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/node_modules/lodash._basetostring/package.json @@ -0,0 +1,74 @@ +{ + "name": "lodash._basetostring", + "version": "4.12.0", + "description": "The internal lodash function `baseToString` exported as a module.", + "homepage": "https://lodash.com/", + "icon": "https://lodash.com/icon.svg", + "license": "MIT", + "author": { + "name": "John-David Dalton", + "email": "john.david.dalton@gmail.com", + "url": "http://allyoucanleet.com/" + }, + "contributors": [ + { + "name": "John-David Dalton", + "email": "john.david.dalton@gmail.com", + "url": "http://allyoucanleet.com/" + }, + { + "name": "Blaine Bublitz", + "email": "blaine.bublitz@gmail.com", + "url": "https://github.com/phated" + }, + { + "name": "Mathias Bynens", + "email": "mathias@qiwi.be", + "url": "https://mathiasbynens.be/" + } + ], + "repository": { + "type": "git", + "url": "git+https://github.com/lodash/lodash.git" + }, + "scripts": { + "test": "echo \"See https://travis-ci.org/lodash/lodash-cli for testing details.\"" + }, + "bugs": { + "url": "https://github.com/lodash/lodash/issues" + }, + "_id": "lodash._basetostring@4.12.0", + "_shasum": "9327c9dc5158866b7fa4b9d42f4638e5766dd9df", + "_from": "lodash._basetostring@>=4.12.0 <4.13.0", + "_npmVersion": "2.15.5", + "_nodeVersion": "5.5.0", + "_npmUser": { + "name": "jdalton", + "email": "john.david.dalton@gmail.com" + }, + "dist": { + "shasum": "9327c9dc5158866b7fa4b9d42f4638e5766dd9df", + "tarball": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-4.12.0.tgz" + }, + "maintainers": [ + { + "name": "jdalton", + "email": "john.david.dalton@gmail.com" + }, + { + "name": "mathias", + "email": "mathias@qiwi.be" + }, + { + "name": "phated", + "email": "blaine@iceddev.com" + } + ], + "_npmOperationalInternal": { + "host": "packages-16-east.internal.npmjs.com", + "tmp": "tmp/lodash._basetostring-4.12.0.tgz_1463062033665_0.6722894972190261" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-4.12.0.tgz", + "readme": "ERROR: No README data found!" +} diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/node_modules/lodash.tostring/LICENSE b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/node_modules/lodash.tostring/LICENSE new file mode 100644 index 00000000000000..e0c69d56032d15 --- /dev/null +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/node_modules/lodash.tostring/LICENSE @@ -0,0 +1,47 @@ +Copyright jQuery Foundation and other contributors + +Based on Underscore.js, copyright Jeremy Ashkenas, +DocumentCloud and Investigative Reporters & Editors + +This software consists of voluntary contributions made by many +individuals. For exact contribution history, see the revision history +available at https://github.com/lodash/lodash + +The following license applies to all parts of this software except as +documented below: + +==== + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +==== + +Copyright and related rights for sample code are waived via CC0. Sample +code is defined as all source code displayed within the prose of the +documentation. + +CC0: http://creativecommons.org/publicdomain/zero/1.0/ + +==== + +Files located in the node_modules and vendor directories are externally +maintained libraries used by this software which have their own +licenses; we recommend you read them, as their terms may differ from the +terms above. diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.tostring/README.md b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/node_modules/lodash.tostring/README.md similarity index 80% rename from deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.tostring/README.md rename to deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/node_modules/lodash.tostring/README.md index b3858fd68e7866..75aa6b0699b4df 100644 --- a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.tostring/README.md +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/node_modules/lodash.tostring/README.md @@ -1,4 +1,4 @@ -# lodash.tostring v4.1.2 +# lodash.tostring v4.1.3 The [lodash](https://lodash.com/) method `_.toString` exported as a [Node.js](https://nodejs.org/) module. @@ -15,4 +15,4 @@ In Node.js: var toString = require('lodash.tostring'); ``` -See the [documentation](https://lodash.com/docs#toString) or [package source](https://github.com/lodash/lodash/blob/4.1.2-npm-packages/lodash.tostring) for more details. +See the [documentation](https://lodash.com/docs#toString) or [package source](https://github.com/lodash/lodash/blob/4.1.3-npm-packages/lodash.tostring) for more details. diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.tostring/index.js b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/node_modules/lodash.tostring/index.js similarity index 81% rename from deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.tostring/index.js rename to deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/node_modules/lodash.tostring/index.js index 5c0e3e2b987eb6..8a2cde39290e82 100644 --- a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.tostring/index.js +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/node_modules/lodash.tostring/index.js @@ -1,10 +1,10 @@ /** - * lodash 4.1.2 (Custom Build) + * lodash (Custom Build) * Build: `lodash modularize exports="npm" -o ./` - * Copyright 2012-2016 The Dojo Foundation + * Copyright jQuery Foundation and other contributors + * Released under MIT license * Based on Underscore.js 1.8.3 - * Copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors */ /** Used as references for various `Number` constants. */ @@ -66,7 +66,8 @@ function checkGlobal(value) { var objectProto = Object.prototype; /** - * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) * of values. */ var objectToString = objectProto.toString; @@ -78,12 +79,33 @@ var Symbol = root.Symbol; var symbolProto = Symbol ? Symbol.prototype : undefined, symbolToString = symbolProto ? symbolProto.toString : undefined; +/** + * The base implementation of `_.toString` which doesn't convert nullish + * values to empty strings. + * + * @private + * @param {*} value The value to process. + * @returns {string} Returns the string. + */ +function baseToString(value) { + // Exit early for strings to avoid a performance hit in some environments. + if (typeof value == 'string') { + return value; + } + if (isSymbol(value)) { + return symbolToString ? symbolToString.call(value) : ''; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; +} + /** * Checks if `value` is object-like. A value is object-like if it's not `null` * and has a `typeof` result of "object". * * @static * @memberOf _ + * @since 4.0.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is object-like, else `false`. @@ -110,9 +132,11 @@ function isObjectLike(value) { * * @static * @memberOf _ + * @since 4.0.0 * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @returns {boolean} Returns `true` if `value` is correctly classified, + * else `false`. * @example * * _.isSymbol(Symbol.iterator); @@ -127,11 +151,12 @@ function isSymbol(value) { } /** - * Converts `value` to a string if it's not one. An empty string is returned - * for `null` and `undefined` values. The sign of `-0` is preserved. + * Converts `value` to a string. An empty string is returned for `null` + * and `undefined` values. The sign of `-0` is preserved. * * @static * @memberOf _ + * @since 4.0.0 * @category Lang * @param {*} value The value to process. * @returns {string} Returns the string. @@ -147,18 +172,7 @@ function isSymbol(value) { * // => '1,2,3' */ function toString(value) { - // Exit early for strings to avoid a performance hit in some environments. - if (typeof value == 'string') { - return value; - } - if (value == null) { - return ''; - } - if (isSymbol(value)) { - return symbolToString ? symbolToString.call(value) : ''; - } - var result = (value + ''); - return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; + return value == null ? '' : baseToString(value); } module.exports = toString; diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.tostring/package.json b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/node_modules/lodash.tostring/package.json similarity index 77% rename from deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.tostring/package.json rename to deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/node_modules/lodash.tostring/package.json index daf01553a964eb..dca724cd869c8a 100644 --- a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.tostring/package.json +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/node_modules/lodash.tostring/package.json @@ -1,6 +1,6 @@ { "name": "lodash.tostring", - "version": "4.1.2", + "version": "4.1.3", "description": "The lodash method `_.toString` exported as a module.", "homepage": "https://lodash.com/", "icon": "https://lodash.com/icon.svg", @@ -41,18 +41,18 @@ "bugs": { "url": "https://github.com/lodash/lodash/issues" }, - "_id": "lodash.tostring@4.1.2", - "_shasum": "7d326a5cf64da4298f2fd35b688d848267535288", - "_from": "lodash.tostring@4.1.2", - "_npmVersion": "2.14.17", + "_id": "lodash.tostring@4.1.3", + "_shasum": "5697f62973f30105a76c2deb3e2d1669f04fd825", + "_from": "lodash.tostring@>=4.0.0 <5.0.0", + "_npmVersion": "2.15.5", "_nodeVersion": "5.5.0", "_npmUser": { "name": "jdalton", "email": "john.david.dalton@gmail.com" }, "dist": { - "shasum": "7d326a5cf64da4298f2fd35b688d848267535288", - "tarball": "http://registry.npmjs.org/lodash.tostring/-/lodash.tostring-4.1.2.tgz" + "shasum": "5697f62973f30105a76c2deb3e2d1669f04fd825", + "tarball": "https://registry.npmjs.org/lodash.tostring/-/lodash.tostring-4.1.3.tgz" }, "maintainers": [ { @@ -69,10 +69,10 @@ } ], "_npmOperationalInternal": { - "host": "packages-13-west.internal.npmjs.com", - "tmp": "tmp/lodash.tostring-4.1.2.tgz_1456896853027_0.8195764778647572" + "host": "packages-16-east.internal.npmjs.com", + "tmp": "tmp/lodash.tostring-4.1.3.tgz_1463062634002_0.7874096168670803" }, "directories": {}, - "_resolved": "https://registry.npmjs.org/lodash.tostring/-/lodash.tostring-4.1.2.tgz", + "_resolved": "https://registry.npmjs.org/lodash.tostring/-/lodash.tostring-4.1.3.tgz", "readme": "ERROR: No README data found!" } diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/package.json b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/package.json index 5bf072f9710dac..cf622e87073fb8 100644 --- a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/package.json +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.pad/package.json @@ -1,6 +1,6 @@ { "name": "lodash.pad", - "version": "4.1.0", + "version": "4.4.0", "description": "The lodash method `_.pad` exported as a module.", "homepage": "https://lodash.com/", "icon": "https://lodash.com/icon.svg", @@ -22,7 +22,7 @@ }, { "name": "Blaine Bublitz", - "email": "blaine@iceddev.com", + "email": "blaine.bublitz@gmail.com", "url": "https://github.com/phated" }, { @@ -39,24 +39,25 @@ "test": "echo \"See https://travis-ci.org/lodash/lodash-cli for testing details.\"" }, "dependencies": { - "lodash.repeat": "^4.0.0", + "lodash._baseslice": "~4.0.0", + "lodash._basetostring": "~4.12.0", "lodash.tostring": "^4.0.0" }, "bugs": { "url": "https://github.com/lodash/lodash/issues" }, - "_id": "lodash.pad@4.1.0", - "_shasum": "dbbe3a9681fccb69970473a2263f50c196ac3aa9", + "_id": "lodash.pad@4.4.0", + "_shasum": "faa38df26c0a69ec5086a82246c958e150dcb1ab", "_from": "lodash.pad@>=4.1.0 <5.0.0", - "_npmVersion": "2.14.18", + "_npmVersion": "2.15.5", "_nodeVersion": "5.5.0", "_npmUser": { "name": "jdalton", "email": "john.david.dalton@gmail.com" }, "dist": { - "shasum": "dbbe3a9681fccb69970473a2263f50c196ac3aa9", - "tarball": "https://registry.npmjs.org/lodash.pad/-/lodash.pad-4.1.0.tgz" + "shasum": "faa38df26c0a69ec5086a82246c958e150dcb1ab", + "tarball": "https://registry.npmjs.org/lodash.pad/-/lodash.pad-4.4.0.tgz" }, "maintainers": [ { @@ -73,9 +74,10 @@ } ], "_npmOperationalInternal": { - "host": "packages-9-west.internal.npmjs.com", - "tmp": "tmp/lodash.pad-4.1.0.tgz_1455615516420_0.3130727862007916" + "host": "packages-12-west.internal.npmjs.com", + "tmp": "tmp/lodash.pad-4.4.0.tgz_1463062450475_0.3613762252498418" }, "directories": {}, - "_resolved": "https://registry.npmjs.org/lodash.pad/-/lodash.pad-4.1.0.tgz" + "_resolved": "https://registry.npmjs.org/lodash.pad/-/lodash.pad-4.4.0.tgz", + "readme": "ERROR: No README data found!" } diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/LICENSE b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/LICENSE index bcbe13d67a9621..e0c69d56032d15 100644 --- a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/LICENSE +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/LICENSE @@ -1,23 +1,47 @@ -The MIT License (MIT) +Copyright jQuery Foundation and other contributors -Copyright 2012-2016 The Dojo Foundation -Based on Underscore.js, copyright 2009-2016 Jeremy Ashkenas, +Based on Underscore.js, copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +This software consists of voluntary contributions made by many +individuals. For exact contribution history, see the revision history +available at https://github.com/lodash/lodash + +The following license applies to all parts of this software except as +documented below: + +==== + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +==== + +Copyright and related rights for sample code are waived via CC0. Sample +code is defined as all source code displayed within the prose of the +documentation. + +CC0: http://creativecommons.org/publicdomain/zero/1.0/ + +==== + +Files located in the node_modules and vendor directories are externally +maintained libraries used by this software which have their own +licenses; we recommend you read them, as their terms may differ from the +terms above. diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/README.md b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/README.md index ac84987849bf1a..909eef8f2215ef 100644 --- a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/README.md +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/README.md @@ -1,4 +1,4 @@ -# lodash.padend v4.2.0 +# lodash.padend v4.5.0 The [lodash](https://lodash.com/) method `_.padEnd` exported as a [Node.js](https://nodejs.org/) module. @@ -15,4 +15,4 @@ In Node.js: var padEnd = require('lodash.padend'); ``` -See the [documentation](https://lodash.com/docs#padEnd) or [package source](https://github.com/lodash/lodash/blob/4.2.0-npm-packages/lodash.padend) for more details. +See the [documentation](https://lodash.com/docs#padEnd) or [package source](https://github.com/lodash/lodash/blob/4.5.0-npm-packages/lodash.padend) for more details. diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/index.js b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/index.js index d7c813a1dbd015..5af50372e338dd 100644 --- a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/index.js +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/index.js @@ -1,22 +1,25 @@ /** - * lodash 4.2.0 (Custom Build) + * lodash (Custom Build) * Build: `lodash modularize exports="npm" -o ./` - * Copyright 2012-2016 The Dojo Foundation + * Copyright jQuery Foundation and other contributors + * Released under MIT license * Based on Underscore.js 1.8.3 - * Copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors */ -var repeat = require('lodash.repeat'), +var baseSlice = require('lodash._baseslice'), + baseToString = require('lodash._basetostring'), toString = require('lodash.tostring'); /** Used as references for various `Number` constants. */ var INFINITY = 1 / 0, + MAX_SAFE_INTEGER = 9007199254740991, MAX_INTEGER = 1.7976931348623157e+308, NAN = 0 / 0; /** `Object#toString` result references. */ var funcTag = '[object Function]', - genTag = '[object GeneratorFunction]'; + genTag = '[object GeneratorFunction]', + symbolTag = '[object Symbol]'; /** Used to match leading and trailing whitespace. */ var reTrim = /^\s+|\s+$/g; @@ -95,38 +98,79 @@ function stringToArray(string) { var objectProto = Object.prototype; /** - * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) * of values. */ var objectToString = objectProto.toString; /* Built-in method references for those with the same name as other `lodash` methods. */ -var nativeCeil = Math.ceil; +var nativeCeil = Math.ceil, + nativeFloor = Math.floor; + +/** + * The base implementation of `_.repeat` which doesn't coerce arguments. + * + * @private + * @param {string} string The string to repeat. + * @param {number} n The number of times to repeat the string. + * @returns {string} Returns the repeated string. + */ +function baseRepeat(string, n) { + var result = ''; + if (!string || n < 1 || n > MAX_SAFE_INTEGER) { + return result; + } + // Leverage the exponentiation by squaring algorithm for a faster repeat. + // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details. + do { + if (n % 2) { + result += string; + } + n = nativeFloor(n / 2); + if (n) { + string += string; + } + } while (n); + + return result; +} + +/** + * Casts `array` to a slice if it's needed. + * + * @private + * @param {Array} array The array to inspect. + * @param {number} start The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the cast slice. + */ +function castSlice(array, start, end) { + var length = array.length; + end = end === undefined ? length : end; + return (!start && end >= length) ? array : baseSlice(array, start, end); +} /** * Creates the padding for `string` based on `length`. The `chars` string * is truncated if the number of characters exceeds `length`. * * @private - * @param {string} string The string to create padding for. - * @param {number} [length=0] The padding length. + * @param {number} length The padding length. * @param {string} [chars=' '] The string used as padding. * @returns {string} Returns the padding for `string`. */ -function createPadding(string, length, chars) { - length = toInteger(length); +function createPadding(length, chars) { + chars = chars === undefined ? ' ' : baseToString(chars); - var strLength = stringSize(string); - if (!length || strLength >= length) { - return ''; + var charsLength = chars.length; + if (charsLength < 2) { + return charsLength ? baseRepeat(chars, length) : chars; } - var padLength = length - strLength; - chars = chars === undefined ? ' ' : (chars + ''); - - var result = repeat(chars, nativeCeil(padLength / stringSize(chars))); + var result = baseRepeat(chars, nativeCeil(length / stringSize(chars))); return reHasComplexSymbol.test(chars) - ? stringToArray(result).slice(0, padLength).join('') - : result.slice(0, padLength); + ? castSlice(stringToArray(result), 0, length).join('') + : result.slice(0, length); } /** @@ -134,9 +178,11 @@ function createPadding(string, length, chars) { * * @static * @memberOf _ + * @since 0.1.0 * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @returns {boolean} Returns `true` if `value` is correctly classified, + * else `false`. * @example * * _.isFunction(_); @@ -147,18 +193,20 @@ function createPadding(string, length, chars) { */ function isFunction(value) { // The use of `Object#toString` avoids issues with the `typeof` operator - // in Safari 8 which returns 'object' for typed array constructors, and - // PhantomJS 1.9 which returns 'function' for `NodeList` instances. + // in Safari 8 which returns 'object' for typed array and weak map constructors, + // and PhantomJS 1.9 which returns 'function' for `NodeList` instances. var tag = isObject(value) ? objectToString.call(value) : ''; return tag == funcTag || tag == genTag; } /** - * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`. - * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/6.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) * * @static * @memberOf _ + * @since 0.1.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is an object, else `false`. @@ -182,30 +230,80 @@ function isObject(value) { } /** - * Converts `value` to an integer. + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". * - * **Note:** This function is loosely based on [`ToInteger`](http://www.ecma-international.org/ecma-262/6.0/#sec-tointeger). + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ +function isObjectLike(value) { + return !!value && typeof value == 'object'; +} + +/** + * Checks if `value` is classified as a `Symbol` primitive or object. * * @static * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, + * else `false`. + * @example + * + * _.isSymbol(Symbol.iterator); + * // => true + * + * _.isSymbol('abc'); + * // => false + */ +function isSymbol(value) { + return typeof value == 'symbol' || + (isObjectLike(value) && objectToString.call(value) == symbolTag); +} + +/** + * Converts `value` to a finite number. + * + * @static + * @memberOf _ + * @since 4.12.0 * @category Lang * @param {*} value The value to convert. - * @returns {number} Returns the converted integer. + * @returns {number} Returns the converted number. * @example * - * _.toInteger(3); - * // => 3 + * _.toFinite(3.2); + * // => 3.2 * - * _.toInteger(Number.MIN_VALUE); - * // => 0 + * _.toFinite(Number.MIN_VALUE); + * // => 5e-324 * - * _.toInteger(Infinity); + * _.toFinite(Infinity); * // => 1.7976931348623157e+308 * - * _.toInteger('3'); - * // => 3 + * _.toFinite('3.2'); + * // => 3.2 */ -function toInteger(value) { +function toFinite(value) { if (!value) { return value === 0 ? value : 0; } @@ -214,8 +312,40 @@ function toInteger(value) { var sign = (value < 0 ? -1 : 1); return sign * MAX_INTEGER; } - var remainder = value % 1; - return value === value ? (remainder ? value - remainder : value) : 0; + return value === value ? value : 0; +} + +/** + * Converts `value` to an integer. + * + * **Note:** This function is loosely based on + * [`ToInteger`](http://www.ecma-international.org/ecma-262/6.0/#sec-tointeger). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted integer. + * @example + * + * _.toInteger(3.2); + * // => 3 + * + * _.toInteger(Number.MIN_VALUE); + * // => 0 + * + * _.toInteger(Infinity); + * // => 1.7976931348623157e+308 + * + * _.toInteger('3.2'); + * // => 3 + */ +function toInteger(value) { + var result = toFinite(value), + remainder = result % 1; + + return result === result ? (remainder ? result - remainder : result) : 0; } /** @@ -223,13 +353,14 @@ function toInteger(value) { * * @static * @memberOf _ + * @since 4.0.0 * @category Lang * @param {*} value The value to process. * @returns {number} Returns the number. * @example * - * _.toNumber(3); - * // => 3 + * _.toNumber(3.2); + * // => 3.2 * * _.toNumber(Number.MIN_VALUE); * // => 5e-324 @@ -237,10 +368,16 @@ function toInteger(value) { * _.toNumber(Infinity); * // => Infinity * - * _.toNumber('3'); - * // => 3 + * _.toNumber('3.2'); + * // => 3.2 */ function toNumber(value) { + if (typeof value == 'number') { + return value; + } + if (isSymbol(value)) { + return NAN; + } if (isObject(value)) { var other = isFunction(value.valueOf) ? value.valueOf() : value; value = isObject(other) ? (other + '') : other; @@ -261,6 +398,7 @@ function toNumber(value) { * * @static * @memberOf _ + * @since 4.0.0 * @category String * @param {string} [string=''] The string to pad. * @param {number} [length=0] The padding length. @@ -279,7 +417,12 @@ function toNumber(value) { */ function padEnd(string, length, chars) { string = toString(string); - return string + createPadding(string, length, chars); + length = toInteger(length); + + var strLength = length ? stringSize(string) : 0; + return (length && strLength < length) + ? (string + createPadding(length - strLength, chars)) + : string; } module.exports = padEnd; diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/node_modules/lodash._baseslice/LICENSE b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/node_modules/lodash._baseslice/LICENSE new file mode 100644 index 00000000000000..b054ca5a3ac7d6 --- /dev/null +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/node_modules/lodash._baseslice/LICENSE @@ -0,0 +1,22 @@ +Copyright 2012-2016 The Dojo Foundation +Based on Underscore.js, copyright 2009-2016 Jeremy Ashkenas, +DocumentCloud and Investigative Reporters & Editors + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/node_modules/lodash._baseslice/README.md b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/node_modules/lodash._baseslice/README.md new file mode 100644 index 00000000000000..8cd4181ccdc00d --- /dev/null +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/node_modules/lodash._baseslice/README.md @@ -0,0 +1,18 @@ +# lodash._baseslice v4.0.0 + +The internal [lodash](https://lodash.com/) function `baseSlice` exported as a [Node.js](https://nodejs.org/) module. + +## Installation + +Using npm: +```bash +$ {sudo -H} npm i -g npm +$ npm i --save lodash._baseslice +``` + +In Node.js: +```js +var baseSlice = require('lodash._baseslice'); +``` + +See the [package source](https://github.com/lodash/lodash/blob/4.0.0-npm-packages/lodash._baseslice) for more details. diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/node_modules/lodash._baseslice/index.js b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/node_modules/lodash._baseslice/index.js new file mode 100644 index 00000000000000..59293c3d0037a8 --- /dev/null +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/node_modules/lodash._baseslice/index.js @@ -0,0 +1,40 @@ +/** + * lodash 4.0.0 (Custom Build) + * Build: `lodash modularize exports="npm" -o ./` + * Copyright 2012-2016 The Dojo Foundation + * Based on Underscore.js 1.8.3 + * Copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + * Available under MIT license + */ + +/** + * The base implementation of `_.slice` without an iteratee call guard. + * + * @private + * @param {Array} array The array to slice. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the slice of `array`. + */ +function baseSlice(array, start, end) { + var index = -1, + length = array.length; + + if (start < 0) { + start = -start > length ? 0 : (length + start); + } + end = end > length ? length : end; + if (end < 0) { + end += length; + } + length = start > end ? 0 : ((end - start) >>> 0); + start >>>= 0; + + var result = Array(length); + while (++index < length) { + result[index] = array[index + start]; + } + return result; +} + +module.exports = baseSlice; diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/node_modules/lodash._baseslice/package.json b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/node_modules/lodash._baseslice/package.json new file mode 100644 index 00000000000000..a8e4a8520c7ad0 --- /dev/null +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/node_modules/lodash._baseslice/package.json @@ -0,0 +1,70 @@ +{ + "name": "lodash._baseslice", + "version": "4.0.0", + "description": "The internal lodash function `baseSlice` exported as a module.", + "homepage": "https://lodash.com/", + "icon": "https://lodash.com/icon.svg", + "license": "MIT", + "author": { + "name": "John-David Dalton", + "email": "john.david.dalton@gmail.com", + "url": "http://allyoucanleet.com/" + }, + "contributors": [ + { + "name": "John-David Dalton", + "email": "john.david.dalton@gmail.com", + "url": "http://allyoucanleet.com/" + }, + { + "name": "Blaine Bublitz", + "email": "blaine@iceddev.com", + "url": "https://github.com/phated" + }, + { + "name": "Mathias Bynens", + "email": "mathias@qiwi.be", + "url": "https://mathiasbynens.be/" + } + ], + "repository": { + "type": "git", + "url": "git+https://github.com/lodash/lodash.git" + }, + "scripts": { + "test": "echo \"See https://travis-ci.org/lodash/lodash-cli for testing details.\"" + }, + "bugs": { + "url": "https://github.com/lodash/lodash/issues" + }, + "_id": "lodash._baseslice@4.0.0", + "_shasum": "f5ce1df982948ecaff63f223853415b7b9763704", + "_from": "lodash._baseslice@>=4.0.0 <4.1.0", + "_npmVersion": "2.14.15", + "_nodeVersion": "5.4.0", + "_npmUser": { + "name": "jdalton", + "email": "john.david.dalton@gmail.com" + }, + "dist": { + "shasum": "f5ce1df982948ecaff63f223853415b7b9763704", + "tarball": "https://registry.npmjs.org/lodash._baseslice/-/lodash._baseslice-4.0.0.tgz" + }, + "maintainers": [ + { + "name": "jdalton", + "email": "john.david.dalton@gmail.com" + }, + { + "name": "mathias", + "email": "mathias@qiwi.be" + }, + { + "name": "phated", + "email": "blaine@iceddev.com" + } + ], + "directories": {}, + "_resolved": "https://registry.npmjs.org/lodash._baseslice/-/lodash._baseslice-4.0.0.tgz", + "readme": "ERROR: No README data found!" +} diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/node_modules/lodash._basetostring/LICENSE b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/node_modules/lodash._basetostring/LICENSE new file mode 100644 index 00000000000000..e0c69d56032d15 --- /dev/null +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/node_modules/lodash._basetostring/LICENSE @@ -0,0 +1,47 @@ +Copyright jQuery Foundation and other contributors + +Based on Underscore.js, copyright Jeremy Ashkenas, +DocumentCloud and Investigative Reporters & Editors + +This software consists of voluntary contributions made by many +individuals. For exact contribution history, see the revision history +available at https://github.com/lodash/lodash + +The following license applies to all parts of this software except as +documented below: + +==== + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +==== + +Copyright and related rights for sample code are waived via CC0. Sample +code is defined as all source code displayed within the prose of the +documentation. + +CC0: http://creativecommons.org/publicdomain/zero/1.0/ + +==== + +Files located in the node_modules and vendor directories are externally +maintained libraries used by this software which have their own +licenses; we recommend you read them, as their terms may differ from the +terms above. diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/node_modules/lodash._basetostring/README.md b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/node_modules/lodash._basetostring/README.md new file mode 100644 index 00000000000000..ba060c94dadea0 --- /dev/null +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/node_modules/lodash._basetostring/README.md @@ -0,0 +1,18 @@ +# lodash._basetostring v4.12.0 + +The internal [lodash](https://lodash.com/) function `baseToString` exported as a [Node.js](https://nodejs.org/) module. + +## Installation + +Using npm: +```bash +$ {sudo -H} npm i -g npm +$ npm i --save lodash._basetostring +``` + +In Node.js: +```js +var baseToString = require('lodash._basetostring'); +``` + +See the [package source](https://github.com/lodash/lodash/blob/4.12.0-npm-packages/lodash._basetostring) for more details. diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/node_modules/lodash._basetostring/index.js b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/node_modules/lodash._basetostring/index.js new file mode 100644 index 00000000000000..d5848107499c34 --- /dev/null +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/node_modules/lodash._basetostring/index.js @@ -0,0 +1,153 @@ +/** + * lodash (Custom Build) + * Build: `lodash modularize exports="npm" -o ./` + * Copyright jQuery Foundation and other contributors + * Released under MIT license + * Based on Underscore.js 1.8.3 + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + */ + +/** Used as references for various `Number` constants. */ +var INFINITY = 1 / 0; + +/** `Object#toString` result references. */ +var symbolTag = '[object Symbol]'; + +/** Used to determine if values are of the language type `Object`. */ +var objectTypes = { + 'function': true, + 'object': true +}; + +/** Detect free variable `exports`. */ +var freeExports = (objectTypes[typeof exports] && exports && !exports.nodeType) + ? exports + : undefined; + +/** Detect free variable `module`. */ +var freeModule = (objectTypes[typeof module] && module && !module.nodeType) + ? module + : undefined; + +/** Detect free variable `global` from Node.js. */ +var freeGlobal = checkGlobal(freeExports && freeModule && typeof global == 'object' && global); + +/** Detect free variable `self`. */ +var freeSelf = checkGlobal(objectTypes[typeof self] && self); + +/** Detect free variable `window`. */ +var freeWindow = checkGlobal(objectTypes[typeof window] && window); + +/** Detect `this` as the global object. */ +var thisGlobal = checkGlobal(objectTypes[typeof this] && this); + +/** + * Used as a reference to the global object. + * + * The `this` value is used if it's the global object to avoid Greasemonkey's + * restricted `window` object, otherwise the `window` object is used. + */ +var root = freeGlobal || + ((freeWindow !== (thisGlobal && thisGlobal.window)) && freeWindow) || + freeSelf || thisGlobal || Function('return this')(); + +/** + * Checks if `value` is a global object. + * + * @private + * @param {*} value The value to check. + * @returns {null|Object} Returns `value` if it's a global object, else `null`. + */ +function checkGlobal(value) { + return (value && value.Object === Object) ? value : null; +} + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * of values. + */ +var objectToString = objectProto.toString; + +/** Built-in value references. */ +var Symbol = root.Symbol; + +/** Used to convert symbols to primitives and strings. */ +var symbolProto = Symbol ? Symbol.prototype : undefined, + symbolToString = symbolProto ? symbolProto.toString : undefined; + +/** + * The base implementation of `_.toString` which doesn't convert nullish + * values to empty strings. + * + * @private + * @param {*} value The value to process. + * @returns {string} Returns the string. + */ +function baseToString(value) { + // Exit early for strings to avoid a performance hit in some environments. + if (typeof value == 'string') { + return value; + } + if (isSymbol(value)) { + return symbolToString ? symbolToString.call(value) : ''; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; +} + +/** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ +function isObjectLike(value) { + return !!value && typeof value == 'object'; +} + +/** + * Checks if `value` is classified as a `Symbol` primitive or object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, + * else `false`. + * @example + * + * _.isSymbol(Symbol.iterator); + * // => true + * + * _.isSymbol('abc'); + * // => false + */ +function isSymbol(value) { + return typeof value == 'symbol' || + (isObjectLike(value) && objectToString.call(value) == symbolTag); +} + +module.exports = baseToString; diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/node_modules/lodash._basetostring/package.json b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/node_modules/lodash._basetostring/package.json new file mode 100644 index 00000000000000..474798f13467c2 --- /dev/null +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/node_modules/lodash._basetostring/package.json @@ -0,0 +1,74 @@ +{ + "name": "lodash._basetostring", + "version": "4.12.0", + "description": "The internal lodash function `baseToString` exported as a module.", + "homepage": "https://lodash.com/", + "icon": "https://lodash.com/icon.svg", + "license": "MIT", + "author": { + "name": "John-David Dalton", + "email": "john.david.dalton@gmail.com", + "url": "http://allyoucanleet.com/" + }, + "contributors": [ + { + "name": "John-David Dalton", + "email": "john.david.dalton@gmail.com", + "url": "http://allyoucanleet.com/" + }, + { + "name": "Blaine Bublitz", + "email": "blaine.bublitz@gmail.com", + "url": "https://github.com/phated" + }, + { + "name": "Mathias Bynens", + "email": "mathias@qiwi.be", + "url": "https://mathiasbynens.be/" + } + ], + "repository": { + "type": "git", + "url": "git+https://github.com/lodash/lodash.git" + }, + "scripts": { + "test": "echo \"See https://travis-ci.org/lodash/lodash-cli for testing details.\"" + }, + "bugs": { + "url": "https://github.com/lodash/lodash/issues" + }, + "_id": "lodash._basetostring@4.12.0", + "_shasum": "9327c9dc5158866b7fa4b9d42f4638e5766dd9df", + "_from": "lodash._basetostring@>=4.12.0 <4.13.0", + "_npmVersion": "2.15.5", + "_nodeVersion": "5.5.0", + "_npmUser": { + "name": "jdalton", + "email": "john.david.dalton@gmail.com" + }, + "dist": { + "shasum": "9327c9dc5158866b7fa4b9d42f4638e5766dd9df", + "tarball": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-4.12.0.tgz" + }, + "maintainers": [ + { + "name": "jdalton", + "email": "john.david.dalton@gmail.com" + }, + { + "name": "mathias", + "email": "mathias@qiwi.be" + }, + { + "name": "phated", + "email": "blaine@iceddev.com" + } + ], + "_npmOperationalInternal": { + "host": "packages-16-east.internal.npmjs.com", + "tmp": "tmp/lodash._basetostring-4.12.0.tgz_1463062033665_0.6722894972190261" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-4.12.0.tgz", + "readme": "ERROR: No README data found!" +} diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/node_modules/lodash.tostring/LICENSE b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/node_modules/lodash.tostring/LICENSE new file mode 100644 index 00000000000000..e0c69d56032d15 --- /dev/null +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/node_modules/lodash.tostring/LICENSE @@ -0,0 +1,47 @@ +Copyright jQuery Foundation and other contributors + +Based on Underscore.js, copyright Jeremy Ashkenas, +DocumentCloud and Investigative Reporters & Editors + +This software consists of voluntary contributions made by many +individuals. For exact contribution history, see the revision history +available at https://github.com/lodash/lodash + +The following license applies to all parts of this software except as +documented below: + +==== + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +==== + +Copyright and related rights for sample code are waived via CC0. Sample +code is defined as all source code displayed within the prose of the +documentation. + +CC0: http://creativecommons.org/publicdomain/zero/1.0/ + +==== + +Files located in the node_modules and vendor directories are externally +maintained libraries used by this software which have their own +licenses; we recommend you read them, as their terms may differ from the +terms above. diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/node_modules/lodash.tostring/README.md b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/node_modules/lodash.tostring/README.md new file mode 100644 index 00000000000000..75aa6b0699b4df --- /dev/null +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/node_modules/lodash.tostring/README.md @@ -0,0 +1,18 @@ +# lodash.tostring v4.1.3 + +The [lodash](https://lodash.com/) method `_.toString` exported as a [Node.js](https://nodejs.org/) module. + +## Installation + +Using npm: +```bash +$ {sudo -H} npm i -g npm +$ npm i --save lodash.tostring +``` + +In Node.js: +```js +var toString = require('lodash.tostring'); +``` + +See the [documentation](https://lodash.com/docs#toString) or [package source](https://github.com/lodash/lodash/blob/4.1.3-npm-packages/lodash.tostring) for more details. diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/node_modules/lodash.tostring/index.js b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/node_modules/lodash.tostring/index.js new file mode 100644 index 00000000000000..8a2cde39290e82 --- /dev/null +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/node_modules/lodash.tostring/index.js @@ -0,0 +1,178 @@ +/** + * lodash (Custom Build) + * Build: `lodash modularize exports="npm" -o ./` + * Copyright jQuery Foundation and other contributors + * Released under MIT license + * Based on Underscore.js 1.8.3 + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + */ + +/** Used as references for various `Number` constants. */ +var INFINITY = 1 / 0; + +/** `Object#toString` result references. */ +var symbolTag = '[object Symbol]'; + +/** Used to determine if values are of the language type `Object`. */ +var objectTypes = { + 'function': true, + 'object': true +}; + +/** Detect free variable `exports`. */ +var freeExports = (objectTypes[typeof exports] && exports && !exports.nodeType) + ? exports + : undefined; + +/** Detect free variable `module`. */ +var freeModule = (objectTypes[typeof module] && module && !module.nodeType) + ? module + : undefined; + +/** Detect free variable `global` from Node.js. */ +var freeGlobal = checkGlobal(freeExports && freeModule && typeof global == 'object' && global); + +/** Detect free variable `self`. */ +var freeSelf = checkGlobal(objectTypes[typeof self] && self); + +/** Detect free variable `window`. */ +var freeWindow = checkGlobal(objectTypes[typeof window] && window); + +/** Detect `this` as the global object. */ +var thisGlobal = checkGlobal(objectTypes[typeof this] && this); + +/** + * Used as a reference to the global object. + * + * The `this` value is used if it's the global object to avoid Greasemonkey's + * restricted `window` object, otherwise the `window` object is used. + */ +var root = freeGlobal || + ((freeWindow !== (thisGlobal && thisGlobal.window)) && freeWindow) || + freeSelf || thisGlobal || Function('return this')(); + +/** + * Checks if `value` is a global object. + * + * @private + * @param {*} value The value to check. + * @returns {null|Object} Returns `value` if it's a global object, else `null`. + */ +function checkGlobal(value) { + return (value && value.Object === Object) ? value : null; +} + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * of values. + */ +var objectToString = objectProto.toString; + +/** Built-in value references. */ +var Symbol = root.Symbol; + +/** Used to convert symbols to primitives and strings. */ +var symbolProto = Symbol ? Symbol.prototype : undefined, + symbolToString = symbolProto ? symbolProto.toString : undefined; + +/** + * The base implementation of `_.toString` which doesn't convert nullish + * values to empty strings. + * + * @private + * @param {*} value The value to process. + * @returns {string} Returns the string. + */ +function baseToString(value) { + // Exit early for strings to avoid a performance hit in some environments. + if (typeof value == 'string') { + return value; + } + if (isSymbol(value)) { + return symbolToString ? symbolToString.call(value) : ''; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; +} + +/** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ +function isObjectLike(value) { + return !!value && typeof value == 'object'; +} + +/** + * Checks if `value` is classified as a `Symbol` primitive or object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, + * else `false`. + * @example + * + * _.isSymbol(Symbol.iterator); + * // => true + * + * _.isSymbol('abc'); + * // => false + */ +function isSymbol(value) { + return typeof value == 'symbol' || + (isObjectLike(value) && objectToString.call(value) == symbolTag); +} + +/** + * Converts `value` to a string. An empty string is returned for `null` + * and `undefined` values. The sign of `-0` is preserved. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to process. + * @returns {string} Returns the string. + * @example + * + * _.toString(null); + * // => '' + * + * _.toString(-0); + * // => '-0' + * + * _.toString([1, 2, 3]); + * // => '1,2,3' + */ +function toString(value) { + return value == null ? '' : baseToString(value); +} + +module.exports = toString; diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.repeat/package.json b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/node_modules/lodash.tostring/package.json similarity index 65% rename from deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.repeat/package.json rename to deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/node_modules/lodash.tostring/package.json index 2d808082598013..dca724cd869c8a 100644 --- a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.repeat/package.json +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/node_modules/lodash.tostring/package.json @@ -1,13 +1,13 @@ { - "name": "lodash.repeat", - "version": "4.0.2", - "description": "The lodash method `_.repeat` exported as a module.", + "name": "lodash.tostring", + "version": "4.1.3", + "description": "The lodash method `_.toString` exported as a module.", "homepage": "https://lodash.com/", "icon": "https://lodash.com/icon.svg", "license": "MIT", "keywords": [ "lodash-modularized", - "repeat" + "tostring" ], "author": { "name": "John-David Dalton", @@ -38,24 +38,21 @@ "scripts": { "test": "echo \"See https://travis-ci.org/lodash/lodash-cli for testing details.\"" }, - "dependencies": { - "lodash.tostring": "^4.0.0" - }, "bugs": { "url": "https://github.com/lodash/lodash/issues" }, - "_id": "lodash.repeat@4.0.2", - "_shasum": "72c4e409757448c99e3c4c334ab066b789ca3f3b", - "_from": "lodash.repeat@4.0.2", - "_npmVersion": "2.15.3", + "_id": "lodash.tostring@4.1.3", + "_shasum": "5697f62973f30105a76c2deb3e2d1669f04fd825", + "_from": "lodash.tostring@>=4.0.0 <5.0.0", + "_npmVersion": "2.15.5", "_nodeVersion": "5.5.0", "_npmUser": { "name": "jdalton", "email": "john.david.dalton@gmail.com" }, "dist": { - "shasum": "72c4e409757448c99e3c4c334ab066b789ca3f3b", - "tarball": "https://registry.npmjs.org/lodash.repeat/-/lodash.repeat-4.0.2.tgz" + "shasum": "5697f62973f30105a76c2deb3e2d1669f04fd825", + "tarball": "https://registry.npmjs.org/lodash.tostring/-/lodash.tostring-4.1.3.tgz" }, "maintainers": [ { @@ -68,14 +65,14 @@ }, { "name": "phated", - "email": "blaine@iceddev.com" + "email": "blaine.bublitz@gmail.com" } ], "_npmOperationalInternal": { - "host": "packages-12-west.internal.npmjs.com", - "tmp": "tmp/lodash.repeat-4.0.2.tgz_1460126921614_0.3440221941564232" + "host": "packages-16-east.internal.npmjs.com", + "tmp": "tmp/lodash.tostring-4.1.3.tgz_1463062634002_0.7874096168670803" }, "directories": {}, - "_resolved": "https://registry.npmjs.org/lodash.repeat/-/lodash.repeat-4.0.2.tgz", + "_resolved": "https://registry.npmjs.org/lodash.tostring/-/lodash.tostring-4.1.3.tgz", "readme": "ERROR: No README data found!" } diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/package.json b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/package.json index c73abf999253b5..c5573d0f8f12b5 100644 --- a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/package.json +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padend/package.json @@ -1,6 +1,6 @@ { "name": "lodash.padend", - "version": "4.2.0", + "version": "4.5.0", "description": "The lodash method `_.padEnd` exported as a module.", "homepage": "https://lodash.com/", "icon": "https://lodash.com/icon.svg", @@ -22,7 +22,7 @@ }, { "name": "Blaine Bublitz", - "email": "blaine@iceddev.com", + "email": "blaine.bublitz@gmail.com", "url": "https://github.com/phated" }, { @@ -39,24 +39,25 @@ "test": "echo \"See https://travis-ci.org/lodash/lodash-cli for testing details.\"" }, "dependencies": { - "lodash.repeat": "^4.0.0", + "lodash._baseslice": "~4.0.0", + "lodash._basetostring": "~4.12.0", "lodash.tostring": "^4.0.0" }, "bugs": { "url": "https://github.com/lodash/lodash/issues" }, - "_id": "lodash.padend@4.2.0", - "_shasum": "b84e8c3401d4538055c6e321a51e3aee19881a18", + "_id": "lodash.padend@4.5.0", + "_shasum": "a289e9377ee2e6de8ba7f11f3a8eb326070b7619", "_from": "lodash.padend@>=4.1.0 <5.0.0", - "_npmVersion": "2.14.18", + "_npmVersion": "2.15.5", "_nodeVersion": "5.5.0", "_npmUser": { "name": "jdalton", "email": "john.david.dalton@gmail.com" }, "dist": { - "shasum": "b84e8c3401d4538055c6e321a51e3aee19881a18", - "tarball": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.2.0.tgz" + "shasum": "a289e9377ee2e6de8ba7f11f3a8eb326070b7619", + "tarball": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.5.0.tgz" }, "maintainers": [ { @@ -73,9 +74,10 @@ } ], "_npmOperationalInternal": { - "host": "packages-6-west.internal.npmjs.com", - "tmp": "tmp/lodash.padend-4.2.0.tgz_1455615519416_0.9670630963519216" + "host": "packages-12-west.internal.npmjs.com", + "tmp": "tmp/lodash.padend-4.5.0.tgz_1463062451966_0.5034168094862252" }, "directories": {}, - "_resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.2.0.tgz" + "_resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.5.0.tgz", + "readme": "ERROR: No README data found!" } diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/LICENSE b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/LICENSE index bcbe13d67a9621..e0c69d56032d15 100644 --- a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/LICENSE +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/LICENSE @@ -1,23 +1,47 @@ -The MIT License (MIT) +Copyright jQuery Foundation and other contributors -Copyright 2012-2016 The Dojo Foundation -Based on Underscore.js, copyright 2009-2016 Jeremy Ashkenas, +Based on Underscore.js, copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +This software consists of voluntary contributions made by many +individuals. For exact contribution history, see the revision history +available at https://github.com/lodash/lodash + +The following license applies to all parts of this software except as +documented below: + +==== + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +==== + +Copyright and related rights for sample code are waived via CC0. Sample +code is defined as all source code displayed within the prose of the +documentation. + +CC0: http://creativecommons.org/publicdomain/zero/1.0/ + +==== + +Files located in the node_modules and vendor directories are externally +maintained libraries used by this software which have their own +licenses; we recommend you read them, as their terms may differ from the +terms above. diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/README.md b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/README.md index d3176b0012afb9..bcc1c5aa6710e0 100644 --- a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/README.md +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/README.md @@ -1,4 +1,4 @@ -# lodash.padstart v4.2.0 +# lodash.padstart v4.5.0 The [lodash](https://lodash.com/) method `_.padStart` exported as a [Node.js](https://nodejs.org/) module. @@ -15,4 +15,4 @@ In Node.js: var padStart = require('lodash.padstart'); ``` -See the [documentation](https://lodash.com/docs#padStart) or [package source](https://github.com/lodash/lodash/blob/4.2.0-npm-packages/lodash.padstart) for more details. +See the [documentation](https://lodash.com/docs#padStart) or [package source](https://github.com/lodash/lodash/blob/4.5.0-npm-packages/lodash.padstart) for more details. diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/index.js b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/index.js index 9f403a1f857fae..456889536633cb 100644 --- a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/index.js +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/index.js @@ -1,22 +1,25 @@ /** - * lodash 4.2.0 (Custom Build) + * lodash (Custom Build) * Build: `lodash modularize exports="npm" -o ./` - * Copyright 2012-2016 The Dojo Foundation + * Copyright jQuery Foundation and other contributors + * Released under MIT license * Based on Underscore.js 1.8.3 - * Copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors */ -var repeat = require('lodash.repeat'), +var baseSlice = require('lodash._baseslice'), + baseToString = require('lodash._basetostring'), toString = require('lodash.tostring'); /** Used as references for various `Number` constants. */ var INFINITY = 1 / 0, + MAX_SAFE_INTEGER = 9007199254740991, MAX_INTEGER = 1.7976931348623157e+308, NAN = 0 / 0; /** `Object#toString` result references. */ var funcTag = '[object Function]', - genTag = '[object GeneratorFunction]'; + genTag = '[object GeneratorFunction]', + symbolTag = '[object Symbol]'; /** Used to match leading and trailing whitespace. */ var reTrim = /^\s+|\s+$/g; @@ -95,38 +98,79 @@ function stringToArray(string) { var objectProto = Object.prototype; /** - * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) * of values. */ var objectToString = objectProto.toString; /* Built-in method references for those with the same name as other `lodash` methods. */ -var nativeCeil = Math.ceil; +var nativeCeil = Math.ceil, + nativeFloor = Math.floor; + +/** + * The base implementation of `_.repeat` which doesn't coerce arguments. + * + * @private + * @param {string} string The string to repeat. + * @param {number} n The number of times to repeat the string. + * @returns {string} Returns the repeated string. + */ +function baseRepeat(string, n) { + var result = ''; + if (!string || n < 1 || n > MAX_SAFE_INTEGER) { + return result; + } + // Leverage the exponentiation by squaring algorithm for a faster repeat. + // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details. + do { + if (n % 2) { + result += string; + } + n = nativeFloor(n / 2); + if (n) { + string += string; + } + } while (n); + + return result; +} + +/** + * Casts `array` to a slice if it's needed. + * + * @private + * @param {Array} array The array to inspect. + * @param {number} start The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the cast slice. + */ +function castSlice(array, start, end) { + var length = array.length; + end = end === undefined ? length : end; + return (!start && end >= length) ? array : baseSlice(array, start, end); +} /** * Creates the padding for `string` based on `length`. The `chars` string * is truncated if the number of characters exceeds `length`. * * @private - * @param {string} string The string to create padding for. - * @param {number} [length=0] The padding length. + * @param {number} length The padding length. * @param {string} [chars=' '] The string used as padding. * @returns {string} Returns the padding for `string`. */ -function createPadding(string, length, chars) { - length = toInteger(length); +function createPadding(length, chars) { + chars = chars === undefined ? ' ' : baseToString(chars); - var strLength = stringSize(string); - if (!length || strLength >= length) { - return ''; + var charsLength = chars.length; + if (charsLength < 2) { + return charsLength ? baseRepeat(chars, length) : chars; } - var padLength = length - strLength; - chars = chars === undefined ? ' ' : (chars + ''); - - var result = repeat(chars, nativeCeil(padLength / stringSize(chars))); + var result = baseRepeat(chars, nativeCeil(length / stringSize(chars))); return reHasComplexSymbol.test(chars) - ? stringToArray(result).slice(0, padLength).join('') - : result.slice(0, padLength); + ? castSlice(stringToArray(result), 0, length).join('') + : result.slice(0, length); } /** @@ -134,9 +178,11 @@ function createPadding(string, length, chars) { * * @static * @memberOf _ + * @since 0.1.0 * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @returns {boolean} Returns `true` if `value` is correctly classified, + * else `false`. * @example * * _.isFunction(_); @@ -147,18 +193,20 @@ function createPadding(string, length, chars) { */ function isFunction(value) { // The use of `Object#toString` avoids issues with the `typeof` operator - // in Safari 8 which returns 'object' for typed array constructors, and - // PhantomJS 1.9 which returns 'function' for `NodeList` instances. + // in Safari 8 which returns 'object' for typed array and weak map constructors, + // and PhantomJS 1.9 which returns 'function' for `NodeList` instances. var tag = isObject(value) ? objectToString.call(value) : ''; return tag == funcTag || tag == genTag; } /** - * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`. - * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/6.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) * * @static * @memberOf _ + * @since 0.1.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is an object, else `false`. @@ -182,30 +230,80 @@ function isObject(value) { } /** - * Converts `value` to an integer. + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". * - * **Note:** This function is loosely based on [`ToInteger`](http://www.ecma-international.org/ecma-262/6.0/#sec-tointeger). + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ +function isObjectLike(value) { + return !!value && typeof value == 'object'; +} + +/** + * Checks if `value` is classified as a `Symbol` primitive or object. * * @static * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, + * else `false`. + * @example + * + * _.isSymbol(Symbol.iterator); + * // => true + * + * _.isSymbol('abc'); + * // => false + */ +function isSymbol(value) { + return typeof value == 'symbol' || + (isObjectLike(value) && objectToString.call(value) == symbolTag); +} + +/** + * Converts `value` to a finite number. + * + * @static + * @memberOf _ + * @since 4.12.0 * @category Lang * @param {*} value The value to convert. - * @returns {number} Returns the converted integer. + * @returns {number} Returns the converted number. * @example * - * _.toInteger(3); - * // => 3 + * _.toFinite(3.2); + * // => 3.2 * - * _.toInteger(Number.MIN_VALUE); - * // => 0 + * _.toFinite(Number.MIN_VALUE); + * // => 5e-324 * - * _.toInteger(Infinity); + * _.toFinite(Infinity); * // => 1.7976931348623157e+308 * - * _.toInteger('3'); - * // => 3 + * _.toFinite('3.2'); + * // => 3.2 */ -function toInteger(value) { +function toFinite(value) { if (!value) { return value === 0 ? value : 0; } @@ -214,8 +312,40 @@ function toInteger(value) { var sign = (value < 0 ? -1 : 1); return sign * MAX_INTEGER; } - var remainder = value % 1; - return value === value ? (remainder ? value - remainder : value) : 0; + return value === value ? value : 0; +} + +/** + * Converts `value` to an integer. + * + * **Note:** This function is loosely based on + * [`ToInteger`](http://www.ecma-international.org/ecma-262/6.0/#sec-tointeger). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted integer. + * @example + * + * _.toInteger(3.2); + * // => 3 + * + * _.toInteger(Number.MIN_VALUE); + * // => 0 + * + * _.toInteger(Infinity); + * // => 1.7976931348623157e+308 + * + * _.toInteger('3.2'); + * // => 3 + */ +function toInteger(value) { + var result = toFinite(value), + remainder = result % 1; + + return result === result ? (remainder ? result - remainder : result) : 0; } /** @@ -223,13 +353,14 @@ function toInteger(value) { * * @static * @memberOf _ + * @since 4.0.0 * @category Lang * @param {*} value The value to process. * @returns {number} Returns the number. * @example * - * _.toNumber(3); - * // => 3 + * _.toNumber(3.2); + * // => 3.2 * * _.toNumber(Number.MIN_VALUE); * // => 5e-324 @@ -237,10 +368,16 @@ function toInteger(value) { * _.toNumber(Infinity); * // => Infinity * - * _.toNumber('3'); - * // => 3 + * _.toNumber('3.2'); + * // => 3.2 */ function toNumber(value) { + if (typeof value == 'number') { + return value; + } + if (isSymbol(value)) { + return NAN; + } if (isObject(value)) { var other = isFunction(value.valueOf) ? value.valueOf() : value; value = isObject(other) ? (other + '') : other; @@ -261,6 +398,7 @@ function toNumber(value) { * * @static * @memberOf _ + * @since 4.0.0 * @category String * @param {string} [string=''] The string to pad. * @param {number} [length=0] The padding length. @@ -279,7 +417,12 @@ function toNumber(value) { */ function padStart(string, length, chars) { string = toString(string); - return createPadding(string, length, chars) + string; + length = toInteger(length); + + var strLength = length ? stringSize(string) : 0; + return (length && strLength < length) + ? (createPadding(length - strLength, chars) + string) + : string; } module.exports = padStart; diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/node_modules/lodash._baseslice/LICENSE b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/node_modules/lodash._baseslice/LICENSE new file mode 100644 index 00000000000000..b054ca5a3ac7d6 --- /dev/null +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/node_modules/lodash._baseslice/LICENSE @@ -0,0 +1,22 @@ +Copyright 2012-2016 The Dojo Foundation +Based on Underscore.js, copyright 2009-2016 Jeremy Ashkenas, +DocumentCloud and Investigative Reporters & Editors + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/node_modules/lodash._baseslice/README.md b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/node_modules/lodash._baseslice/README.md new file mode 100644 index 00000000000000..8cd4181ccdc00d --- /dev/null +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/node_modules/lodash._baseslice/README.md @@ -0,0 +1,18 @@ +# lodash._baseslice v4.0.0 + +The internal [lodash](https://lodash.com/) function `baseSlice` exported as a [Node.js](https://nodejs.org/) module. + +## Installation + +Using npm: +```bash +$ {sudo -H} npm i -g npm +$ npm i --save lodash._baseslice +``` + +In Node.js: +```js +var baseSlice = require('lodash._baseslice'); +``` + +See the [package source](https://github.com/lodash/lodash/blob/4.0.0-npm-packages/lodash._baseslice) for more details. diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/node_modules/lodash._baseslice/index.js b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/node_modules/lodash._baseslice/index.js new file mode 100644 index 00000000000000..59293c3d0037a8 --- /dev/null +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/node_modules/lodash._baseslice/index.js @@ -0,0 +1,40 @@ +/** + * lodash 4.0.0 (Custom Build) + * Build: `lodash modularize exports="npm" -o ./` + * Copyright 2012-2016 The Dojo Foundation + * Based on Underscore.js 1.8.3 + * Copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + * Available under MIT license + */ + +/** + * The base implementation of `_.slice` without an iteratee call guard. + * + * @private + * @param {Array} array The array to slice. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the slice of `array`. + */ +function baseSlice(array, start, end) { + var index = -1, + length = array.length; + + if (start < 0) { + start = -start > length ? 0 : (length + start); + } + end = end > length ? length : end; + if (end < 0) { + end += length; + } + length = start > end ? 0 : ((end - start) >>> 0); + start >>>= 0; + + var result = Array(length); + while (++index < length) { + result[index] = array[index + start]; + } + return result; +} + +module.exports = baseSlice; diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/node_modules/lodash._baseslice/package.json b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/node_modules/lodash._baseslice/package.json new file mode 100644 index 00000000000000..a8e4a8520c7ad0 --- /dev/null +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/node_modules/lodash._baseslice/package.json @@ -0,0 +1,70 @@ +{ + "name": "lodash._baseslice", + "version": "4.0.0", + "description": "The internal lodash function `baseSlice` exported as a module.", + "homepage": "https://lodash.com/", + "icon": "https://lodash.com/icon.svg", + "license": "MIT", + "author": { + "name": "John-David Dalton", + "email": "john.david.dalton@gmail.com", + "url": "http://allyoucanleet.com/" + }, + "contributors": [ + { + "name": "John-David Dalton", + "email": "john.david.dalton@gmail.com", + "url": "http://allyoucanleet.com/" + }, + { + "name": "Blaine Bublitz", + "email": "blaine@iceddev.com", + "url": "https://github.com/phated" + }, + { + "name": "Mathias Bynens", + "email": "mathias@qiwi.be", + "url": "https://mathiasbynens.be/" + } + ], + "repository": { + "type": "git", + "url": "git+https://github.com/lodash/lodash.git" + }, + "scripts": { + "test": "echo \"See https://travis-ci.org/lodash/lodash-cli for testing details.\"" + }, + "bugs": { + "url": "https://github.com/lodash/lodash/issues" + }, + "_id": "lodash._baseslice@4.0.0", + "_shasum": "f5ce1df982948ecaff63f223853415b7b9763704", + "_from": "lodash._baseslice@>=4.0.0 <4.1.0", + "_npmVersion": "2.14.15", + "_nodeVersion": "5.4.0", + "_npmUser": { + "name": "jdalton", + "email": "john.david.dalton@gmail.com" + }, + "dist": { + "shasum": "f5ce1df982948ecaff63f223853415b7b9763704", + "tarball": "https://registry.npmjs.org/lodash._baseslice/-/lodash._baseslice-4.0.0.tgz" + }, + "maintainers": [ + { + "name": "jdalton", + "email": "john.david.dalton@gmail.com" + }, + { + "name": "mathias", + "email": "mathias@qiwi.be" + }, + { + "name": "phated", + "email": "blaine@iceddev.com" + } + ], + "directories": {}, + "_resolved": "https://registry.npmjs.org/lodash._baseslice/-/lodash._baseslice-4.0.0.tgz", + "readme": "ERROR: No README data found!" +} diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/node_modules/lodash._basetostring/LICENSE b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/node_modules/lodash._basetostring/LICENSE new file mode 100644 index 00000000000000..e0c69d56032d15 --- /dev/null +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/node_modules/lodash._basetostring/LICENSE @@ -0,0 +1,47 @@ +Copyright jQuery Foundation and other contributors + +Based on Underscore.js, copyright Jeremy Ashkenas, +DocumentCloud and Investigative Reporters & Editors + +This software consists of voluntary contributions made by many +individuals. For exact contribution history, see the revision history +available at https://github.com/lodash/lodash + +The following license applies to all parts of this software except as +documented below: + +==== + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +==== + +Copyright and related rights for sample code are waived via CC0. Sample +code is defined as all source code displayed within the prose of the +documentation. + +CC0: http://creativecommons.org/publicdomain/zero/1.0/ + +==== + +Files located in the node_modules and vendor directories are externally +maintained libraries used by this software which have their own +licenses; we recommend you read them, as their terms may differ from the +terms above. diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/node_modules/lodash._basetostring/README.md b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/node_modules/lodash._basetostring/README.md new file mode 100644 index 00000000000000..ba060c94dadea0 --- /dev/null +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/node_modules/lodash._basetostring/README.md @@ -0,0 +1,18 @@ +# lodash._basetostring v4.12.0 + +The internal [lodash](https://lodash.com/) function `baseToString` exported as a [Node.js](https://nodejs.org/) module. + +## Installation + +Using npm: +```bash +$ {sudo -H} npm i -g npm +$ npm i --save lodash._basetostring +``` + +In Node.js: +```js +var baseToString = require('lodash._basetostring'); +``` + +See the [package source](https://github.com/lodash/lodash/blob/4.12.0-npm-packages/lodash._basetostring) for more details. diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/node_modules/lodash._basetostring/index.js b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/node_modules/lodash._basetostring/index.js new file mode 100644 index 00000000000000..d5848107499c34 --- /dev/null +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/node_modules/lodash._basetostring/index.js @@ -0,0 +1,153 @@ +/** + * lodash (Custom Build) + * Build: `lodash modularize exports="npm" -o ./` + * Copyright jQuery Foundation and other contributors + * Released under MIT license + * Based on Underscore.js 1.8.3 + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + */ + +/** Used as references for various `Number` constants. */ +var INFINITY = 1 / 0; + +/** `Object#toString` result references. */ +var symbolTag = '[object Symbol]'; + +/** Used to determine if values are of the language type `Object`. */ +var objectTypes = { + 'function': true, + 'object': true +}; + +/** Detect free variable `exports`. */ +var freeExports = (objectTypes[typeof exports] && exports && !exports.nodeType) + ? exports + : undefined; + +/** Detect free variable `module`. */ +var freeModule = (objectTypes[typeof module] && module && !module.nodeType) + ? module + : undefined; + +/** Detect free variable `global` from Node.js. */ +var freeGlobal = checkGlobal(freeExports && freeModule && typeof global == 'object' && global); + +/** Detect free variable `self`. */ +var freeSelf = checkGlobal(objectTypes[typeof self] && self); + +/** Detect free variable `window`. */ +var freeWindow = checkGlobal(objectTypes[typeof window] && window); + +/** Detect `this` as the global object. */ +var thisGlobal = checkGlobal(objectTypes[typeof this] && this); + +/** + * Used as a reference to the global object. + * + * The `this` value is used if it's the global object to avoid Greasemonkey's + * restricted `window` object, otherwise the `window` object is used. + */ +var root = freeGlobal || + ((freeWindow !== (thisGlobal && thisGlobal.window)) && freeWindow) || + freeSelf || thisGlobal || Function('return this')(); + +/** + * Checks if `value` is a global object. + * + * @private + * @param {*} value The value to check. + * @returns {null|Object} Returns `value` if it's a global object, else `null`. + */ +function checkGlobal(value) { + return (value && value.Object === Object) ? value : null; +} + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * of values. + */ +var objectToString = objectProto.toString; + +/** Built-in value references. */ +var Symbol = root.Symbol; + +/** Used to convert symbols to primitives and strings. */ +var symbolProto = Symbol ? Symbol.prototype : undefined, + symbolToString = symbolProto ? symbolProto.toString : undefined; + +/** + * The base implementation of `_.toString` which doesn't convert nullish + * values to empty strings. + * + * @private + * @param {*} value The value to process. + * @returns {string} Returns the string. + */ +function baseToString(value) { + // Exit early for strings to avoid a performance hit in some environments. + if (typeof value == 'string') { + return value; + } + if (isSymbol(value)) { + return symbolToString ? symbolToString.call(value) : ''; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; +} + +/** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ +function isObjectLike(value) { + return !!value && typeof value == 'object'; +} + +/** + * Checks if `value` is classified as a `Symbol` primitive or object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, + * else `false`. + * @example + * + * _.isSymbol(Symbol.iterator); + * // => true + * + * _.isSymbol('abc'); + * // => false + */ +function isSymbol(value) { + return typeof value == 'symbol' || + (isObjectLike(value) && objectToString.call(value) == symbolTag); +} + +module.exports = baseToString; diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/node_modules/lodash._basetostring/package.json b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/node_modules/lodash._basetostring/package.json new file mode 100644 index 00000000000000..474798f13467c2 --- /dev/null +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/node_modules/lodash._basetostring/package.json @@ -0,0 +1,74 @@ +{ + "name": "lodash._basetostring", + "version": "4.12.0", + "description": "The internal lodash function `baseToString` exported as a module.", + "homepage": "https://lodash.com/", + "icon": "https://lodash.com/icon.svg", + "license": "MIT", + "author": { + "name": "John-David Dalton", + "email": "john.david.dalton@gmail.com", + "url": "http://allyoucanleet.com/" + }, + "contributors": [ + { + "name": "John-David Dalton", + "email": "john.david.dalton@gmail.com", + "url": "http://allyoucanleet.com/" + }, + { + "name": "Blaine Bublitz", + "email": "blaine.bublitz@gmail.com", + "url": "https://github.com/phated" + }, + { + "name": "Mathias Bynens", + "email": "mathias@qiwi.be", + "url": "https://mathiasbynens.be/" + } + ], + "repository": { + "type": "git", + "url": "git+https://github.com/lodash/lodash.git" + }, + "scripts": { + "test": "echo \"See https://travis-ci.org/lodash/lodash-cli for testing details.\"" + }, + "bugs": { + "url": "https://github.com/lodash/lodash/issues" + }, + "_id": "lodash._basetostring@4.12.0", + "_shasum": "9327c9dc5158866b7fa4b9d42f4638e5766dd9df", + "_from": "lodash._basetostring@>=4.12.0 <4.13.0", + "_npmVersion": "2.15.5", + "_nodeVersion": "5.5.0", + "_npmUser": { + "name": "jdalton", + "email": "john.david.dalton@gmail.com" + }, + "dist": { + "shasum": "9327c9dc5158866b7fa4b9d42f4638e5766dd9df", + "tarball": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-4.12.0.tgz" + }, + "maintainers": [ + { + "name": "jdalton", + "email": "john.david.dalton@gmail.com" + }, + { + "name": "mathias", + "email": "mathias@qiwi.be" + }, + { + "name": "phated", + "email": "blaine@iceddev.com" + } + ], + "_npmOperationalInternal": { + "host": "packages-16-east.internal.npmjs.com", + "tmp": "tmp/lodash._basetostring-4.12.0.tgz_1463062033665_0.6722894972190261" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-4.12.0.tgz", + "readme": "ERROR: No README data found!" +} diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/node_modules/lodash.tostring/LICENSE b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/node_modules/lodash.tostring/LICENSE new file mode 100644 index 00000000000000..e0c69d56032d15 --- /dev/null +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/node_modules/lodash.tostring/LICENSE @@ -0,0 +1,47 @@ +Copyright jQuery Foundation and other contributors + +Based on Underscore.js, copyright Jeremy Ashkenas, +DocumentCloud and Investigative Reporters & Editors + +This software consists of voluntary contributions made by many +individuals. For exact contribution history, see the revision history +available at https://github.com/lodash/lodash + +The following license applies to all parts of this software except as +documented below: + +==== + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +==== + +Copyright and related rights for sample code are waived via CC0. Sample +code is defined as all source code displayed within the prose of the +documentation. + +CC0: http://creativecommons.org/publicdomain/zero/1.0/ + +==== + +Files located in the node_modules and vendor directories are externally +maintained libraries used by this software which have their own +licenses; we recommend you read them, as their terms may differ from the +terms above. diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/node_modules/lodash.tostring/README.md b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/node_modules/lodash.tostring/README.md new file mode 100644 index 00000000000000..75aa6b0699b4df --- /dev/null +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/node_modules/lodash.tostring/README.md @@ -0,0 +1,18 @@ +# lodash.tostring v4.1.3 + +The [lodash](https://lodash.com/) method `_.toString` exported as a [Node.js](https://nodejs.org/) module. + +## Installation + +Using npm: +```bash +$ {sudo -H} npm i -g npm +$ npm i --save lodash.tostring +``` + +In Node.js: +```js +var toString = require('lodash.tostring'); +``` + +See the [documentation](https://lodash.com/docs#toString) or [package source](https://github.com/lodash/lodash/blob/4.1.3-npm-packages/lodash.tostring) for more details. diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/node_modules/lodash.tostring/index.js b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/node_modules/lodash.tostring/index.js new file mode 100644 index 00000000000000..8a2cde39290e82 --- /dev/null +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/node_modules/lodash.tostring/index.js @@ -0,0 +1,178 @@ +/** + * lodash (Custom Build) + * Build: `lodash modularize exports="npm" -o ./` + * Copyright jQuery Foundation and other contributors + * Released under MIT license + * Based on Underscore.js 1.8.3 + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + */ + +/** Used as references for various `Number` constants. */ +var INFINITY = 1 / 0; + +/** `Object#toString` result references. */ +var symbolTag = '[object Symbol]'; + +/** Used to determine if values are of the language type `Object`. */ +var objectTypes = { + 'function': true, + 'object': true +}; + +/** Detect free variable `exports`. */ +var freeExports = (objectTypes[typeof exports] && exports && !exports.nodeType) + ? exports + : undefined; + +/** Detect free variable `module`. */ +var freeModule = (objectTypes[typeof module] && module && !module.nodeType) + ? module + : undefined; + +/** Detect free variable `global` from Node.js. */ +var freeGlobal = checkGlobal(freeExports && freeModule && typeof global == 'object' && global); + +/** Detect free variable `self`. */ +var freeSelf = checkGlobal(objectTypes[typeof self] && self); + +/** Detect free variable `window`. */ +var freeWindow = checkGlobal(objectTypes[typeof window] && window); + +/** Detect `this` as the global object. */ +var thisGlobal = checkGlobal(objectTypes[typeof this] && this); + +/** + * Used as a reference to the global object. + * + * The `this` value is used if it's the global object to avoid Greasemonkey's + * restricted `window` object, otherwise the `window` object is used. + */ +var root = freeGlobal || + ((freeWindow !== (thisGlobal && thisGlobal.window)) && freeWindow) || + freeSelf || thisGlobal || Function('return this')(); + +/** + * Checks if `value` is a global object. + * + * @private + * @param {*} value The value to check. + * @returns {null|Object} Returns `value` if it's a global object, else `null`. + */ +function checkGlobal(value) { + return (value && value.Object === Object) ? value : null; +} + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * of values. + */ +var objectToString = objectProto.toString; + +/** Built-in value references. */ +var Symbol = root.Symbol; + +/** Used to convert symbols to primitives and strings. */ +var symbolProto = Symbol ? Symbol.prototype : undefined, + symbolToString = symbolProto ? symbolProto.toString : undefined; + +/** + * The base implementation of `_.toString` which doesn't convert nullish + * values to empty strings. + * + * @private + * @param {*} value The value to process. + * @returns {string} Returns the string. + */ +function baseToString(value) { + // Exit early for strings to avoid a performance hit in some environments. + if (typeof value == 'string') { + return value; + } + if (isSymbol(value)) { + return symbolToString ? symbolToString.call(value) : ''; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; +} + +/** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ +function isObjectLike(value) { + return !!value && typeof value == 'object'; +} + +/** + * Checks if `value` is classified as a `Symbol` primitive or object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, + * else `false`. + * @example + * + * _.isSymbol(Symbol.iterator); + * // => true + * + * _.isSymbol('abc'); + * // => false + */ +function isSymbol(value) { + return typeof value == 'symbol' || + (isObjectLike(value) && objectToString.call(value) == symbolTag); +} + +/** + * Converts `value` to a string. An empty string is returned for `null` + * and `undefined` values. The sign of `-0` is preserved. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to process. + * @returns {string} Returns the string. + * @example + * + * _.toString(null); + * // => '' + * + * _.toString(-0); + * // => '-0' + * + * _.toString([1, 2, 3]); + * // => '1,2,3' + */ +function toString(value) { + return value == null ? '' : baseToString(value); +} + +module.exports = toString; diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/node_modules/lodash.tostring/package.json b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/node_modules/lodash.tostring/package.json new file mode 100644 index 00000000000000..dca724cd869c8a --- /dev/null +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/node_modules/lodash.tostring/package.json @@ -0,0 +1,78 @@ +{ + "name": "lodash.tostring", + "version": "4.1.3", + "description": "The lodash method `_.toString` exported as a module.", + "homepage": "https://lodash.com/", + "icon": "https://lodash.com/icon.svg", + "license": "MIT", + "keywords": [ + "lodash-modularized", + "tostring" + ], + "author": { + "name": "John-David Dalton", + "email": "john.david.dalton@gmail.com", + "url": "http://allyoucanleet.com/" + }, + "contributors": [ + { + "name": "John-David Dalton", + "email": "john.david.dalton@gmail.com", + "url": "http://allyoucanleet.com/" + }, + { + "name": "Blaine Bublitz", + "email": "blaine.bublitz@gmail.com", + "url": "https://github.com/phated" + }, + { + "name": "Mathias Bynens", + "email": "mathias@qiwi.be", + "url": "https://mathiasbynens.be/" + } + ], + "repository": { + "type": "git", + "url": "git+https://github.com/lodash/lodash.git" + }, + "scripts": { + "test": "echo \"See https://travis-ci.org/lodash/lodash-cli for testing details.\"" + }, + "bugs": { + "url": "https://github.com/lodash/lodash/issues" + }, + "_id": "lodash.tostring@4.1.3", + "_shasum": "5697f62973f30105a76c2deb3e2d1669f04fd825", + "_from": "lodash.tostring@>=4.0.0 <5.0.0", + "_npmVersion": "2.15.5", + "_nodeVersion": "5.5.0", + "_npmUser": { + "name": "jdalton", + "email": "john.david.dalton@gmail.com" + }, + "dist": { + "shasum": "5697f62973f30105a76c2deb3e2d1669f04fd825", + "tarball": "https://registry.npmjs.org/lodash.tostring/-/lodash.tostring-4.1.3.tgz" + }, + "maintainers": [ + { + "name": "jdalton", + "email": "john.david.dalton@gmail.com" + }, + { + "name": "mathias", + "email": "mathias@qiwi.be" + }, + { + "name": "phated", + "email": "blaine.bublitz@gmail.com" + } + ], + "_npmOperationalInternal": { + "host": "packages-16-east.internal.npmjs.com", + "tmp": "tmp/lodash.tostring-4.1.3.tgz_1463062634002_0.7874096168670803" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/lodash.tostring/-/lodash.tostring-4.1.3.tgz", + "readme": "ERROR: No README data found!" +} diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/package.json b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/package.json index 2dd0b3cae7608b..560c4eb39af01c 100644 --- a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/package.json +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.padstart/package.json @@ -1,6 +1,6 @@ { "name": "lodash.padstart", - "version": "4.2.0", + "version": "4.5.0", "description": "The lodash method `_.padStart` exported as a module.", "homepage": "https://lodash.com/", "icon": "https://lodash.com/icon.svg", @@ -22,7 +22,7 @@ }, { "name": "Blaine Bublitz", - "email": "blaine@iceddev.com", + "email": "blaine.bublitz@gmail.com", "url": "https://github.com/phated" }, { @@ -39,24 +39,25 @@ "test": "echo \"See https://travis-ci.org/lodash/lodash-cli for testing details.\"" }, "dependencies": { - "lodash.repeat": "^4.0.0", + "lodash._baseslice": "~4.0.0", + "lodash._basetostring": "~4.12.0", "lodash.tostring": "^4.0.0" }, "bugs": { "url": "https://github.com/lodash/lodash/issues" }, - "_id": "lodash.padstart@4.2.0", - "_shasum": "e36f89fd6c3b5072219087695b765de83ec96985", + "_id": "lodash.padstart@4.5.0", + "_shasum": "3ea190f6734841c3364d279d11e056726b60a79a", "_from": "lodash.padstart@>=4.1.0 <5.0.0", - "_npmVersion": "2.14.18", + "_npmVersion": "2.15.5", "_nodeVersion": "5.5.0", "_npmUser": { "name": "jdalton", "email": "john.david.dalton@gmail.com" }, "dist": { - "shasum": "e36f89fd6c3b5072219087695b765de83ec96985", - "tarball": "https://registry.npmjs.org/lodash.padstart/-/lodash.padstart-4.2.0.tgz" + "shasum": "3ea190f6734841c3364d279d11e056726b60a79a", + "tarball": "https://registry.npmjs.org/lodash.padstart/-/lodash.padstart-4.5.0.tgz" }, "maintainers": [ { @@ -73,9 +74,10 @@ } ], "_npmOperationalInternal": { - "host": "packages-6-west.internal.npmjs.com", - "tmp": "tmp/lodash.padstart-4.2.0.tgz_1455615522339_0.6710881665349007" + "host": "packages-12-west.internal.npmjs.com", + "tmp": "tmp/lodash.padstart-4.5.0.tgz_1463062453524_0.18468116875737906" }, "directories": {}, - "_resolved": "https://registry.npmjs.org/lodash.padstart/-/lodash.padstart-4.2.0.tgz" + "_resolved": "https://registry.npmjs.org/lodash.padstart/-/lodash.padstart-4.5.0.tgz", + "readme": "ERROR: No README data found!" } diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.repeat/README.md b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.repeat/README.md deleted file mode 100644 index 9d626e83f8c191..00000000000000 --- a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.repeat/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# lodash.repeat v4.0.2 - -The [lodash](https://lodash.com/) method `_.repeat` exported as a [Node.js](https://nodejs.org/) module. - -## Installation - -Using npm: -```bash -$ {sudo -H} npm i -g npm -$ npm i --save lodash.repeat -``` - -In Node.js: -```js -var repeat = require('lodash.repeat'); -``` - -See the [documentation](https://lodash.com/docs#repeat) or [package source](https://github.com/lodash/lodash/blob/4.0.2-npm-packages/lodash.repeat) for more details. diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.repeat/index.js b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.repeat/index.js deleted file mode 100644 index 5c290973169fec..00000000000000 --- a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.repeat/index.js +++ /dev/null @@ -1,463 +0,0 @@ -/** - * lodash 4.0.2 (Custom Build) - * Build: `lodash modularize exports="npm" -o ./` - * Copyright jQuery Foundation and other contributors - * Released under MIT license - * Based on Underscore.js 1.8.3 - * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - */ -var toString = require('lodash.tostring'); - -/** Used as references for various `Number` constants. */ -var INFINITY = 1 / 0, - MAX_SAFE_INTEGER = 9007199254740991, - MAX_INTEGER = 1.7976931348623157e+308, - NAN = 0 / 0; - -/** `Object#toString` result references. */ -var funcTag = '[object Function]', - genTag = '[object GeneratorFunction]', - symbolTag = '[object Symbol]'; - -/** Used to match leading and trailing whitespace. */ -var reTrim = /^\s+|\s+$/g; - -/** Used to detect bad signed hexadecimal string values. */ -var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; - -/** Used to detect binary string values. */ -var reIsBinary = /^0b[01]+$/i; - -/** Used to detect octal string values. */ -var reIsOctal = /^0o[0-7]+$/i; - -/** Used to detect unsigned integer values. */ -var reIsUint = /^(?:0|[1-9]\d*)$/; - -/** Built-in method references without a dependency on `root`. */ -var freeParseInt = parseInt; - -/** - * Checks if `value` is a valid array-like index. - * - * @private - * @param {*} value The value to check. - * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. - * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. - */ -function isIndex(value, length) { - value = (typeof value == 'number' || reIsUint.test(value)) ? +value : -1; - length = length == null ? MAX_SAFE_INTEGER : length; - return value > -1 && value % 1 == 0 && value < length; -} - -/** Used for built-in method references. */ -var objectProto = Object.prototype; - -/** - * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) - * of values. - */ -var objectToString = objectProto.toString; - -/* Built-in method references for those with the same name as other `lodash` methods. */ -var nativeFloor = Math.floor; - -/** - * The base implementation of `_.property` without support for deep paths. - * - * @private - * @param {string} key The key of the property to get. - * @returns {Function} Returns the new function. - */ -function baseProperty(key) { - return function(object) { - return object == null ? undefined : object[key]; - }; -} - -/** - * The base implementation of `_.repeat` which doesn't coerce arguments. - * - * @private - * @param {string} string The string to repeat. - * @param {number} n The number of times to repeat the string. - * @returns {string} Returns the repeated string. - */ -function baseRepeat(string, n) { - var result = ''; - if (!string || n < 1 || n > MAX_SAFE_INTEGER) { - return result; - } - // Leverage the exponentiation by squaring algorithm for a faster repeat. - // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details. - do { - if (n % 2) { - result += string; - } - n = nativeFloor(n / 2); - if (n) { - string += string; - } - } while (n); - - return result; -} - -/** - * Gets the "length" property value of `object`. - * - * **Note:** This function is used to avoid a - * [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792) that affects - * Safari on at least iOS 8.1-8.3 ARM64. - * - * @private - * @param {Object} object The object to query. - * @returns {*} Returns the "length" value. - */ -var getLength = baseProperty('length'); - -/** - * Checks if the given arguments are from an iteratee call. - * - * @private - * @param {*} value The potential iteratee value argument. - * @param {*} index The potential iteratee index or key argument. - * @param {*} object The potential iteratee object argument. - * @returns {boolean} Returns `true` if the arguments are from an iteratee call, - * else `false`. - */ -function isIterateeCall(value, index, object) { - if (!isObject(object)) { - return false; - } - var type = typeof index; - if (type == 'number' - ? (isArrayLike(object) && isIndex(index, object.length)) - : (type == 'string' && index in object) - ) { - return eq(object[index], value); - } - return false; -} - -/** - * Performs a - * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) - * comparison between two values to determine if they are equivalent. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to compare. - * @param {*} other The other value to compare. - * @returns {boolean} Returns `true` if the values are equivalent, else `false`. - * @example - * - * var object = { 'user': 'fred' }; - * var other = { 'user': 'fred' }; - * - * _.eq(object, object); - * // => true - * - * _.eq(object, other); - * // => false - * - * _.eq('a', 'a'); - * // => true - * - * _.eq('a', Object('a')); - * // => false - * - * _.eq(NaN, NaN); - * // => true - */ -function eq(value, other) { - return value === other || (value !== value && other !== other); -} - -/** - * Checks if `value` is array-like. A value is considered array-like if it's - * not a function and has a `value.length` that's an integer greater than or - * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is array-like, else `false`. - * @example - * - * _.isArrayLike([1, 2, 3]); - * // => true - * - * _.isArrayLike(document.body.children); - * // => true - * - * _.isArrayLike('abc'); - * // => true - * - * _.isArrayLike(_.noop); - * // => false - */ -function isArrayLike(value) { - return value != null && isLength(getLength(value)) && !isFunction(value); -} - -/** - * Checks if `value` is classified as a `Function` object. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is correctly classified, - * else `false`. - * @example - * - * _.isFunction(_); - * // => true - * - * _.isFunction(/abc/); - * // => false - */ -function isFunction(value) { - // The use of `Object#toString` avoids issues with the `typeof` operator - // in Safari 8 which returns 'object' for typed array and weak map constructors, - // and PhantomJS 1.9 which returns 'function' for `NodeList` instances. - var tag = isObject(value) ? objectToString.call(value) : ''; - return tag == funcTag || tag == genTag; -} - -/** - * Checks if `value` is a valid array-like length. - * - * **Note:** This function is loosely based on - * [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength). - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a valid length, - * else `false`. - * @example - * - * _.isLength(3); - * // => true - * - * _.isLength(Number.MIN_VALUE); - * // => false - * - * _.isLength(Infinity); - * // => false - * - * _.isLength('3'); - * // => false - */ -function isLength(value) { - return typeof value == 'number' && - value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; -} - -/** - * Checks if `value` is the - * [language type](http://www.ecma-international.org/ecma-262/6.0/#sec-ecmascript-language-types) - * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an object, else `false`. - * @example - * - * _.isObject({}); - * // => true - * - * _.isObject([1, 2, 3]); - * // => true - * - * _.isObject(_.noop); - * // => true - * - * _.isObject(null); - * // => false - */ -function isObject(value) { - var type = typeof value; - return !!value && (type == 'object' || type == 'function'); -} - -/** - * Checks if `value` is object-like. A value is object-like if it's not `null` - * and has a `typeof` result of "object". - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is object-like, else `false`. - * @example - * - * _.isObjectLike({}); - * // => true - * - * _.isObjectLike([1, 2, 3]); - * // => true - * - * _.isObjectLike(_.noop); - * // => false - * - * _.isObjectLike(null); - * // => false - */ -function isObjectLike(value) { - return !!value && typeof value == 'object'; -} - -/** - * Checks if `value` is classified as a `Symbol` primitive or object. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is correctly classified, - * else `false`. - * @example - * - * _.isSymbol(Symbol.iterator); - * // => true - * - * _.isSymbol('abc'); - * // => false - */ -function isSymbol(value) { - return typeof value == 'symbol' || - (isObjectLike(value) && objectToString.call(value) == symbolTag); -} - -/** - * Converts `value` to an integer. - * - * **Note:** This function is loosely based on - * [`ToInteger`](http://www.ecma-international.org/ecma-262/6.0/#sec-tointeger). - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to convert. - * @returns {number} Returns the converted integer. - * @example - * - * _.toInteger(3); - * // => 3 - * - * _.toInteger(Number.MIN_VALUE); - * // => 0 - * - * _.toInteger(Infinity); - * // => 1.7976931348623157e+308 - * - * _.toInteger('3'); - * // => 3 - */ -function toInteger(value) { - if (!value) { - return value === 0 ? value : 0; - } - value = toNumber(value); - if (value === INFINITY || value === -INFINITY) { - var sign = (value < 0 ? -1 : 1); - return sign * MAX_INTEGER; - } - var remainder = value % 1; - return value === value ? (remainder ? value - remainder : value) : 0; -} - -/** - * Converts `value` to a number. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to process. - * @returns {number} Returns the number. - * @example - * - * _.toNumber(3); - * // => 3 - * - * _.toNumber(Number.MIN_VALUE); - * // => 5e-324 - * - * _.toNumber(Infinity); - * // => Infinity - * - * _.toNumber('3'); - * // => 3 - */ -function toNumber(value) { - if (typeof value == 'number') { - return value; - } - if (isSymbol(value)) { - return NAN; - } - if (isObject(value)) { - var other = isFunction(value.valueOf) ? value.valueOf() : value; - value = isObject(other) ? (other + '') : other; - } - if (typeof value != 'string') { - return value === 0 ? value : +value; - } - value = value.replace(reTrim, ''); - var isBinary = reIsBinary.test(value); - return (isBinary || reIsOctal.test(value)) - ? freeParseInt(value.slice(2), isBinary ? 2 : 8) - : (reIsBadHex.test(value) ? NAN : +value); -} - -/** - * Repeats the given string `n` times. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category String - * @param {string} [string=''] The string to repeat. - * @param {number} [n=1] The number of times to repeat the string. - * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. - * @returns {string} Returns the repeated string. - * @example - * - * _.repeat('*', 3); - * // => '***' - * - * _.repeat('abc', 2); - * // => 'abcabc' - * - * _.repeat('abc', 0); - * // => '' - */ -function repeat(string, n, guard) { - if ((guard ? isIterateeCall(string, n, guard) : n === undefined)) { - n = 1; - } else { - n = toInteger(n); - } - return baseRepeat(toString(string), n); -} - -module.exports = repeat; diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.tostring/LICENSE b/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.tostring/LICENSE deleted file mode 100644 index bcbe13d67a9621..00000000000000 --- a/deps/npm/node_modules/npmlog/node_modules/gauge/node_modules/lodash.tostring/LICENSE +++ /dev/null @@ -1,23 +0,0 @@ -The MIT License (MIT) - -Copyright 2012-2016 The Dojo Foundation -Based on Underscore.js, copyright 2009-2016 Jeremy Ashkenas, -DocumentCloud and Investigative Reporters & Editors - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/deps/npm/node_modules/npmlog/node_modules/gauge/package.json b/deps/npm/node_modules/npmlog/node_modules/gauge/package.json index b8422d3d91994c..57652359b1f524 100644 --- a/deps/npm/node_modules/npmlog/node_modules/gauge/package.json +++ b/deps/npm/node_modules/npmlog/node_modules/gauge/package.json @@ -59,5 +59,6 @@ "tmp": "tmp/gauge-1.2.7.tgz_1455835409513_0.6293477965518832" }, "directories": {}, - "_resolved": "https://registry.npmjs.org/gauge/-/gauge-1.2.7.tgz" + "_resolved": "https://registry.npmjs.org/gauge/-/gauge-1.2.7.tgz", + "readme": "ERROR: No README data found!" } diff --git a/deps/npm/node_modules/npmlog/package.json b/deps/npm/node_modules/npmlog/package.json index 6e8c2abc5b6cfc..271d21e459cda8 100644 --- a/deps/npm/node_modules/npmlog/package.json +++ b/deps/npm/node_modules/npmlog/package.json @@ -6,12 +6,15 @@ }, "name": "npmlog", "description": "logger for npm", - "version": "2.0.3", + "version": "2.0.4", "repository": { "type": "git", "url": "git+https://github.com/npm/npmlog.git" }, "main": "log.js", + "files": [ + "log.js" + ], "scripts": { "test": "tap test/*.js" }, @@ -24,23 +27,23 @@ "tap": "~5.7.0" }, "license": "ISC", - "gitHead": "9dfe26296118ceb5443e76f347f256c35e7ca999", + "gitHead": "3732fd4ba1ca2d47c6102343e6c3fb7e66df7fe5", "bugs": { "url": "https://github.com/npm/npmlog/issues" }, "homepage": "https://github.com/npm/npmlog#readme", - "_id": "npmlog@2.0.3", - "_shasum": "020f99351f0c02e399c674ba256e7c4d3b3dd298", - "_from": "npmlog@2.0.3", - "_npmVersion": "3.8.1", - "_nodeVersion": "4.2.2", + "_id": "npmlog@2.0.4", + "_shasum": "98b52530f2514ca90d09ec5b22c8846722375692", + "_from": "npmlog@>=2.0.4 <2.1.0", + "_npmVersion": "3.9.1", + "_nodeVersion": "5.10.1", "_npmUser": { - "name": "iarna", - "email": "me@re-becca.org" + "name": "zkat", + "email": "kat@sykosomatic.org" }, "dist": { - "shasum": "020f99351f0c02e399c674ba256e7c4d3b3dd298", - "tarball": "https://registry.npmjs.org/npmlog/-/npmlog-2.0.3.tgz" + "shasum": "98b52530f2514ca90d09ec5b22c8846722375692", + "tarball": "https://registry.npmjs.org/npmlog/-/npmlog-2.0.4.tgz" }, "maintainers": [ { @@ -54,12 +57,17 @@ { "name": "othiym23", "email": "ogd@aoaioxxysz.net" + }, + { + "name": "zkat", + "email": "kat@sykosomatic.org" } ], "_npmOperationalInternal": { - "host": "packages-13-west.internal.npmjs.com", - "tmp": "tmp/npmlog-2.0.3.tgz_1458089035965_0.5096880353521556" + "host": "packages-12-west.internal.npmjs.com", + "tmp": "tmp/npmlog-2.0.4.tgz_1463616637725_0.461703865788877" }, "directories": {}, - "_resolved": "https://registry.npmjs.org/npmlog/-/npmlog-2.0.3.tgz" + "_resolved": "https://registry.npmjs.org/npmlog/-/npmlog-2.0.4.tgz", + "readme": "ERROR: No README data found!" } diff --git a/deps/npm/node_modules/npmlog/test/basic.js b/deps/npm/node_modules/npmlog/test/basic.js deleted file mode 100644 index 1887d3a2a8cd4e..00000000000000 --- a/deps/npm/node_modules/npmlog/test/basic.js +++ /dev/null @@ -1,235 +0,0 @@ -var tap = require('tap') -var log = require('../') - -var result = [] -var logEvents = [] -var logInfoEvents = [] -var logPrefixEvents = [] - -var util = require('util') - -var resultExpect = -[ '\u001b[37m\u001b[40mnpm\u001b[0m \u001b[0m\u001b[7msill\u001b[0m \u001b[0m\u001b[35msilly prefix\u001b[0m x = {"foo":{"bar":"baz"}}\n', - '\u001b[0m\u001b[37m\u001b[40mnpm\u001b[0m \u001b[0m\u001b[34m\u001b[40mverb\u001b[0m \u001b[0m\u001b[35mverbose prefix\u001b[0m x = {"foo":{"bar":"baz"}}\n', - '\u001b[0m\u001b[37m\u001b[40mnpm\u001b[0m \u001b[0m\u001b[32minfo\u001b[0m \u001b[0m\u001b[35minfo prefix\u001b[0m x = {"foo":{"bar":"baz"}}\n', - '\u001b[0m\u001b[37m\u001b[40mnpm\u001b[0m \u001b[0m\u001b[32m\u001b[40mhttp\u001b[0m \u001b[0m\u001b[35mhttp prefix\u001b[0m x = {"foo":{"bar":"baz"}}\n', - '\u001b[0m\u001b[37m\u001b[40mnpm\u001b[0m \u001b[0m\u001b[30m\u001b[43mWARN\u001b[0m \u001b[0m\u001b[35mwarn prefix\u001b[0m x = {"foo":{"bar":"baz"}}\n', - '\u001b[0m\u001b[37m\u001b[40mnpm\u001b[0m \u001b[0m\u001b[31m\u001b[40mERR!\u001b[0m \u001b[0m\u001b[35merror prefix\u001b[0m x = {"foo":{"bar":"baz"}}\n', - '\u001b[0m\u001b[37m\u001b[40mnpm\u001b[0m \u001b[0m\u001b[32minfo\u001b[0m \u001b[0m\u001b[35minfo prefix\u001b[0m x = {"foo":{"bar":"baz"}}\n', - '\u001b[0m\u001b[37m\u001b[40mnpm\u001b[0m \u001b[0m\u001b[32m\u001b[40mhttp\u001b[0m \u001b[0m\u001b[35mhttp prefix\u001b[0m x = {"foo":{"bar":"baz"}}\n', - '\u001b[0m\u001b[37m\u001b[40mnpm\u001b[0m \u001b[0m\u001b[30m\u001b[43mWARN\u001b[0m \u001b[0m\u001b[35mwarn prefix\u001b[0m x = {"foo":{"bar":"baz"}}\n', - '\u001b[0m\u001b[37m\u001b[40mnpm\u001b[0m \u001b[0m\u001b[31m\u001b[40mERR!\u001b[0m \u001b[0m\u001b[35merror prefix\u001b[0m x = {"foo":{"bar":"baz"}}\n', - '\u001b[0m\u001b[37m\u001b[40mnpm\u001b[0m \u001b[0m\u001b[31m\u001b[40mERR!\u001b[0m \u001b[0m\u001b[35m404\u001b[0m This is a longer\n', - '\u001b[0m\u001b[37m\u001b[40mnpm\u001b[0m \u001b[0m\u001b[31m\u001b[40mERR!\u001b[0m \u001b[0m\u001b[35m404\u001b[0m message, with some details\n', - '\u001b[0m\u001b[37m\u001b[40mnpm\u001b[0m \u001b[0m\u001b[31m\u001b[40mERR!\u001b[0m \u001b[0m\u001b[35m404\u001b[0m and maybe a stack.\n', - '\u001b[0m\u001b[37m\u001b[40mnpm\u001b[0m \u001b[0m\u001b[31m\u001b[40mERR!\u001b[0m \u001b[0m\u001b[35m404\u001b[0m \n', - '\u001b[0m\u001b[37m\u001b[40mnpm\u001b[0m \u001b[0m\u0007noise\u001b[0m\u001b[35m\u001b[0m LOUD NOISES\n', - '\u001b[0m\u001b[37m\u001b[40mnpm\u001b[0m \u001b[0m\u0007noise\u001b[0m \u001b[0m\u001b[35merror\u001b[0m erroring\n', - '\u001b[0m' ] - -var logPrefixEventsExpect = -[ { id: 2, - level: 'info', - prefix: 'info prefix', - message: 'x = {"foo":{"bar":"baz"}}', - messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] }, - { id: 9, - level: 'info', - prefix: 'info prefix', - message: 'x = {"foo":{"bar":"baz"}}', - messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] }, - { id: 16, - level: 'info', - prefix: 'info prefix', - message: 'x = {"foo":{"bar":"baz"}}', - messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] } ] - -// should be the same. -var logInfoEventsExpect = logPrefixEventsExpect - -var logEventsExpect = -[ { id: 0, - level: 'silly', - prefix: 'silly prefix', - message: 'x = {"foo":{"bar":"baz"}}', - messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] }, - { id: 1, - level: 'verbose', - prefix: 'verbose prefix', - message: 'x = {"foo":{"bar":"baz"}}', - messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] }, - { id: 2, - level: 'info', - prefix: 'info prefix', - message: 'x = {"foo":{"bar":"baz"}}', - messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] }, - { id: 3, - level: 'http', - prefix: 'http prefix', - message: 'x = {"foo":{"bar":"baz"}}', - messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] }, - { id: 4, - level: 'warn', - prefix: 'warn prefix', - message: 'x = {"foo":{"bar":"baz"}}', - messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] }, - { id: 5, - level: 'error', - prefix: 'error prefix', - message: 'x = {"foo":{"bar":"baz"}}', - messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] }, - { id: 6, - level: 'silent', - prefix: 'silent prefix', - message: 'x = {"foo":{"bar":"baz"}}', - messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] }, - { id: 7, - level: 'silly', - prefix: 'silly prefix', - message: 'x = {"foo":{"bar":"baz"}}', - messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] }, - { id: 8, - level: 'verbose', - prefix: 'verbose prefix', - message: 'x = {"foo":{"bar":"baz"}}', - messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] }, - { id: 9, - level: 'info', - prefix: 'info prefix', - message: 'x = {"foo":{"bar":"baz"}}', - messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] }, - { id: 10, - level: 'http', - prefix: 'http prefix', - message: 'x = {"foo":{"bar":"baz"}}', - messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] }, - { id: 11, - level: 'warn', - prefix: 'warn prefix', - message: 'x = {"foo":{"bar":"baz"}}', - messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] }, - { id: 12, - level: 'error', - prefix: 'error prefix', - message: 'x = {"foo":{"bar":"baz"}}', - messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] }, - { id: 13, - level: 'silent', - prefix: 'silent prefix', - message: 'x = {"foo":{"bar":"baz"}}', - messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] }, - { id: 14, - level: 'silly', - prefix: 'silly prefix', - message: 'x = {"foo":{"bar":"baz"}}', - messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] }, - { id: 15, - level: 'verbose', - prefix: 'verbose prefix', - message: 'x = {"foo":{"bar":"baz"}}', - messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] }, - { id: 16, - level: 'info', - prefix: 'info prefix', - message: 'x = {"foo":{"bar":"baz"}}', - messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] }, - { id: 17, - level: 'http', - prefix: 'http prefix', - message: 'x = {"foo":{"bar":"baz"}}', - messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] }, - { id: 18, - level: 'warn', - prefix: 'warn prefix', - message: 'x = {"foo":{"bar":"baz"}}', - messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] }, - { id: 19, - level: 'error', - prefix: 'error prefix', - message: 'x = {"foo":{"bar":"baz"}}', - messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] }, - { id: 20, - level: 'silent', - prefix: 'silent prefix', - message: 'x = {"foo":{"bar":"baz"}}', - messageRaw: [ 'x = %j', { foo: { bar: 'baz' } } ] }, - { id: 21, - level: 'error', - prefix: '404', - message: 'This is a longer\nmessage, with some details\nand maybe a stack.\n', - messageRaw: [ 'This is a longer\nmessage, with some details\nand maybe a stack.\n' ] }, - { id: 22, - level: 'noise', - prefix: false, - message: 'LOUD NOISES', - messageRaw: [ 'LOUD NOISES' ] }, - { id: 23, - level: 'noise', - prefix: 'error', - message: 'erroring', - messageRaw: [ 'erroring' ] } ] - -var Stream = require('stream').Stream -var s = new Stream() -s.write = function (m) { - result.push(m) -} - -s.writable = true -s.isTTY = true -s.end = function () {} - -log.stream = s - -log.heading = 'npm' - - -tap.test('basic', function (t) { - log.on('log', logEvents.push.bind(logEvents)) - log.on('log.info', logInfoEvents.push.bind(logInfoEvents)) - log.on('info prefix', logPrefixEvents.push.bind(logPrefixEvents)) - - console.error('log.level=silly') - log.level = 'silly' - log.silly('silly prefix', 'x = %j', {foo:{bar:'baz'}}) - log.verbose('verbose prefix', 'x = %j', {foo:{bar:'baz'}}) - log.info('info prefix', 'x = %j', {foo:{bar:'baz'}}) - log.http('http prefix', 'x = %j', {foo:{bar:'baz'}}) - log.warn('warn prefix', 'x = %j', {foo:{bar:'baz'}}) - log.error('error prefix', 'x = %j', {foo:{bar:'baz'}}) - log.silent('silent prefix', 'x = %j', {foo:{bar:'baz'}}) - - console.error('log.level=silent') - log.level = 'silent' - log.silly('silly prefix', 'x = %j', {foo:{bar:'baz'}}) - log.verbose('verbose prefix', 'x = %j', {foo:{bar:'baz'}}) - log.info('info prefix', 'x = %j', {foo:{bar:'baz'}}) - log.http('http prefix', 'x = %j', {foo:{bar:'baz'}}) - log.warn('warn prefix', 'x = %j', {foo:{bar:'baz'}}) - log.error('error prefix', 'x = %j', {foo:{bar:'baz'}}) - log.silent('silent prefix', 'x = %j', {foo:{bar:'baz'}}) - - console.error('log.level=info') - log.level = 'info' - log.silly('silly prefix', 'x = %j', {foo:{bar:'baz'}}) - log.verbose('verbose prefix', 'x = %j', {foo:{bar:'baz'}}) - log.info('info prefix', 'x = %j', {foo:{bar:'baz'}}) - log.http('http prefix', 'x = %j', {foo:{bar:'baz'}}) - log.warn('warn prefix', 'x = %j', {foo:{bar:'baz'}}) - log.error('error prefix', 'x = %j', {foo:{bar:'baz'}}) - log.silent('silent prefix', 'x = %j', {foo:{bar:'baz'}}) - log.error('404', 'This is a longer\n'+ - 'message, with some details\n'+ - 'and maybe a stack.\n') - log.addLevel('noise', 10000, {beep: true}) - log.noise(false, 'LOUD NOISES') - log.noise('error', 'erroring') - - t.deepEqual(result.join('').trim(), resultExpect.join('').trim(), 'result') - t.deepEqual(log.record, logEventsExpect, 'record') - t.deepEqual(logEvents, logEventsExpect, 'logEvents') - t.deepEqual(logInfoEvents, logInfoEventsExpect, 'logInfoEvents') - t.deepEqual(logPrefixEvents, logPrefixEventsExpect, 'logPrefixEvents') - - t.end() -}) diff --git a/deps/npm/node_modules/npmlog/test/progress.js b/deps/npm/node_modules/npmlog/test/progress.js deleted file mode 100644 index 68dca2afc73575..00000000000000 --- a/deps/npm/node_modules/npmlog/test/progress.js +++ /dev/null @@ -1,131 +0,0 @@ -'use strict' - -var test = require('tap').test -var Progress = require('are-we-there-yet') -var log = require('../log.js') - -var actions = [] -log.gauge = { - enable: function () { - actions.push(['enable']) - }, - disable: function () { - actions.push(['disable']) - }, - hide: function () { - actions.push(['hide']) - }, - show: function (name, completed) { - actions.push(['show', name, completed]) - }, - pulse: function (name) { - actions.push(['pulse', name]) - } -} - -function didActions(t, msg, output) { - var tests = [] - for (var ii = 0; ii < output.length; ++ ii) { - for (var jj = 0; jj < output[ii].length; ++ jj) { - tests.push({cmd: ii, arg: jj}) - } - } - t.is(actions.length, output.length, msg) - tests.forEach(function (test) { - t.is(actions[test.cmd] ? actions[test.cmd][test.arg] : null, - output[test.cmd][test.arg], - msg + ': ' + output[test.cmd] + (test.arg ? ' arg #'+test.arg : '')) - }) - actions = [] -} - -function resetTracker() { - log.disableProgress() - log.tracker = new Progress.TrackerGroup() - log.enableProgress() - actions = [] -} - -test('enableProgress', function (t) { - t.plan(6) - resetTracker() - log.disableProgress() - actions = [] - log.enableProgress() - didActions(t, 'enableProgress', [ [ 'enable' ], [ 'show', undefined, 0 ] ]) - log.enableProgress() - didActions(t, 'enableProgress again', []) -}) - -test('disableProgress', function (t) { - t.plan(4) - resetTracker() - log.disableProgress() - didActions(t, 'disableProgress', [ [ 'hide' ], [ 'disable' ] ]) - log.disableProgress() - didActions(t, 'disableProgress again', []) -}) - -test('showProgress', function (t) { - t.plan(5) - resetTracker() - log.disableProgress() - actions = [] - log.showProgress('foo') - didActions(t, 'showProgress disabled', []) - log.enableProgress() - actions = [] - log.showProgress('foo') - didActions(t, 'showProgress', [ [ 'show', 'foo', 0 ] ]) -}) - -test('clearProgress', function (t) { - t.plan(3) - resetTracker() - log.clearProgress() - didActions(t, 'clearProgress', [ [ 'hide' ] ]) - log.disableProgress() - actions = [] - log.clearProgress() - didActions(t, 'clearProgress disabled', [ ]) -}) - -test("newItem", function (t) { - t.plan(12) - resetTracker() - actions = [] - var a = log.newItem("test", 10) - didActions(t, "newItem", [ [ 'show', 'test', 0 ] ]) - a.completeWork(5) - didActions(t, "newItem:completeWork", [ [ 'show', 'test', 0.5 ] ]) - a.finish() - didActions(t, "newItem:finish", [ [ 'show', 'test', 1 ] ]) -}) - -// test that log objects proxy through. And test that completion status filters up -test("newGroup", function (t) { - t.plan(23) - resetTracker() - var a = log.newGroup("newGroup") - didActions(t, 'newGroup', [[ 'show', 'newGroup', 0 ]]) - a.warn("test", "this is a test") - didActions(t, "newGroup:warn", [ [ 'pulse', 'test' ], [ 'hide' ], [ 'show', undefined, 0 ] ]) - var b = a.newItem("newGroup2", 10) - didActions(t, "newGroup:newItem", [ [ 'show', 'newGroup2', 0 ] ]) - b.completeWork(5) - didActions(t, "newGroup:completeWork", [ [ 'show', 'newGroup2', 0.5] ]) - a.finish() - didActions(t, "newGroup:finish", [ [ 'show', 'newGroup', 1 ] ]) -}) - -test("newStream", function (t) { - t.plan(13) - resetTracker() - var a = log.newStream("newStream", 10) - didActions(t, "newStream", [ [ 'show', 'newStream', 0 ] ]) - a.write("abcde") - didActions(t, "newStream", [ [ 'show', 'newStream', 0.5 ] ]) - a.write("fghij") - didActions(t, "newStream", [ [ 'show', 'newStream', 1 ] ]) - t.is(log.tracker.completed(), 1, "Overall completion") -}) diff --git a/deps/npm/node_modules/readable-stream/.npmignore b/deps/npm/node_modules/readable-stream/.npmignore index 38344f87a62766..265ff739e071cd 100644 --- a/deps/npm/node_modules/readable-stream/.npmignore +++ b/deps/npm/node_modules/readable-stream/.npmignore @@ -2,4 +2,7 @@ build/ test/ examples/ fs.js -zlib.js \ No newline at end of file +zlib.js +.zuul.yml +.nyc_output +coverage diff --git a/deps/npm/node_modules/readable-stream/README.md b/deps/npm/node_modules/readable-stream/README.md index c4e4a34a7ae0fa..ae9e3363c8e8a3 100644 --- a/deps/npm/node_modules/readable-stream/README.md +++ b/deps/npm/node_modules/readable-stream/README.md @@ -1,6 +1,6 @@ # readable-stream -***Node-core v5.9.1 streams for userland*** [![Build Status](https://travis-ci.org/nodejs/readable-stream.svg?branch=master)](https://travis-ci.org/nodejs/readable-stream) +***Node-core v6.1.0 streams for userland*** [![Build Status](https://travis-ci.org/nodejs/readable-stream.svg?branch=master)](https://travis-ci.org/nodejs/readable-stream) [![NPM](https://nodei.co/npm/readable-stream.png?downloads=true&downloadRank=true)](https://nodei.co/npm/readable-stream/) @@ -16,7 +16,7 @@ npm install --save readable-stream ***Node-core streams for userland*** This package is a mirror of the Streams2 and Streams3 implementations in -Node-core, including [documentation](doc/stream.markdown). +Node-core, including [documentation](doc/stream.md). If you want to guarantee a stable streams base, regardless of what version of Node you, or the users of your libraries are using, use **readable-stream** *only* and avoid the *"stream"* module in Node-core, for background see [this blogpost](http://r.va.gg/2014/06/why-i-dont-use-nodes-core-stream-module.html). diff --git a/deps/npm/node_modules/readable-stream/doc/stream.markdown b/deps/npm/node_modules/readable-stream/doc/stream.md similarity index 97% rename from deps/npm/node_modules/readable-stream/doc/stream.markdown rename to deps/npm/node_modules/readable-stream/doc/stream.md index ecf997a3f5a14f..c907ca0e7b726a 100644 --- a/deps/npm/node_modules/readable-stream/doc/stream.markdown +++ b/deps/npm/node_modules/readable-stream/doc/stream.md @@ -160,7 +160,8 @@ Emitted when the stream and any of its underlying resources (a file descriptor, for example) have been closed. The event indicates that no more events will be emitted, and no further computation will occur. -Not all streams will emit the `'close'` event. +Not all streams will emit the `'close'` event as the `'close'` event is +optional. #### Event: 'data' @@ -201,7 +202,7 @@ readable.on('end', () => { #### Event: 'error' -* {Error Object} +* {Error} Emitted if there was an error receiving data. @@ -490,7 +491,7 @@ function parseHeader(stream, callback) { var split = str.split(/\n\n/); header += split.shift(); var remaining = split.join('\n\n'); - var buf = new Buffer(remaining, 'utf8'); + var buf = Buffer.from(remaining, 'utf8'); if (buf.length) stream.unshift(buf); stream.removeListener('error', callback); @@ -573,6 +574,15 @@ Examples of writable streams include: * [child process stdin][] * [`process.stdout`][], [`process.stderr`][] +#### Event: 'close' + +Emitted when the stream and any of its underlying resources (a file descriptor, +for example) have been closed. The event indicates that no more events will be +emitted, and no further computation will occur. + +Not all streams will emit the `'close'` event as the `'close'` event is +optional. + #### Event: 'drain' If a [`stream.write(chunk)`][stream-write] call returns `false`, then the @@ -695,6 +705,7 @@ file.end('world!'); #### writable.setDefaultEncoding(encoding) * `encoding` {String} The new default encoding +* Return: `this` Sets the default encoding for a writable stream. @@ -985,7 +996,7 @@ Counter.prototype._read = function() { this.push(null); else { var str = '' + i; - var buf = new Buffer(str, 'ascii'); + var buf = Buffer.from(str, 'ascii'); this.push(buf); } }; @@ -1717,30 +1728,30 @@ horribly wrong. [`'end'`]: #stream_event_end [`'finish'`]: #stream_event_finish [`'readable'`]: #stream_event_readable -[`buf.toString(encoding)`]: https://nodejs.org/docs/v5.9.1/api/buffer.html#buffer_buf_tostring_encoding_start_end -[`EventEmitter`]: https://nodejs.org/docs/v5.9.1/api/events.html#events_class_eventemitter -[`process.stderr`]: https://nodejs.org/docs/v5.9.1/api/process.html#process_process_stderr -[`process.stdin`]: https://nodejs.org/docs/v5.9.1/api/process.html#process_process_stdin -[`process.stdout`]: https://nodejs.org/docs/v5.9.1/api/process.html#process_process_stdout +[`buf.toString(encoding)`]: https://nodejs.org/docs/v6.1.0/api/buffer.html#buffer_buf_tostring_encoding_start_end +[`EventEmitter`]: https://nodejs.org/docs/v6.1.0/api/events.html#events_class_eventemitter +[`process.stderr`]: https://nodejs.org/docs/v6.1.0/api/process.html#process_process_stderr +[`process.stdin`]: https://nodejs.org/docs/v6.1.0/api/process.html#process_process_stdin +[`process.stdout`]: https://nodejs.org/docs/v6.1.0/api/process.html#process_process_stdout [`stream.cork()`]: #stream_writable_cork [`stream.pipe()`]: #stream_readable_pipe_destination_options [`stream.uncork()`]: #stream_writable_uncork [`stream.unpipe()`]: #stream_readable_unpipe_destination [`stream.wrap()`]: #stream_readable_wrap_stream -[`tls.CryptoStream`]: https://nodejs.org/docs/v5.9.1/api/tls.html#tls_class_cryptostream -[`util.inherits()`]: https://nodejs.org/docs/v5.9.1/api/util.html#util_util_inherits_constructor_superconstructor +[`tls.CryptoStream`]: https://nodejs.org/docs/v6.1.0/api/tls.html#tls_class_cryptostream +[`util.inherits()`]: https://nodejs.org/docs/v6.1.0/api/util.html#util_util_inherits_constructor_superconstructor [API for Stream Consumers]: #stream_api_for_stream_consumers [API for Stream Implementors]: #stream_api_for_stream_implementors -[child process stdin]: https://nodejs.org/docs/v5.9.1/api/child_process.html#child_process_child_stdin -[child process stdout and stderr]: https://nodejs.org/docs/v5.9.1/api/child_process.html#child_process_child_stdout +[child process stdin]: https://nodejs.org/docs/v6.1.0/api/child_process.html#child_process_child_stdin +[child process stdout and stderr]: https://nodejs.org/docs/v6.1.0/api/child_process.html#child_process_child_stdout [Compatibility]: #stream_compatibility_with_older_node_js_versions [crypto]: crypto.html [Duplex]: #stream_class_stream_duplex -[fs read streams]: https://nodejs.org/docs/v5.9.1/api/fs.html#fs_class_fs_readstream -[fs write streams]: https://nodejs.org/docs/v5.9.1/api/fs.html#fs_class_fs_writestream -[HTTP requests, on the client]: https://nodejs.org/docs/v5.9.1/api/http.html#http_class_http_clientrequest -[HTTP responses, on the server]: https://nodejs.org/docs/v5.9.1/api/http.html#http_class_http_serverresponse -[http-incoming-message]: https://nodejs.org/docs/v5.9.1/api/http.html#http_class_http_incomingmessage +[fs read streams]: https://nodejs.org/docs/v6.1.0/api/fs.html#fs_class_fs_readstream +[fs write streams]: https://nodejs.org/docs/v6.1.0/api/fs.html#fs_class_fs_writestream +[HTTP requests, on the client]: https://nodejs.org/docs/v6.1.0/api/http.html#http_class_http_clientrequest +[HTTP responses, on the server]: https://nodejs.org/docs/v6.1.0/api/http.html#http_class_http_serverresponse +[http-incoming-message]: https://nodejs.org/docs/v6.1.0/api/http.html#http_class_http_incomingmessage [Object mode]: #stream_object_mode [Readable]: #stream_class_stream_readable [SimpleProtocol v2]: #stream_example_simpleprotocol_parser_v2 @@ -1755,7 +1766,7 @@ horribly wrong. [stream-read]: #stream_readable_read_size [stream-resume]: #stream_readable_resume [stream-write]: #stream_writable_write_chunk_encoding_callback -[TCP sockets]: https://nodejs.org/docs/v5.9.1/api/net.html#net_class_net_socket +[TCP sockets]: https://nodejs.org/docs/v6.1.0/api/net.html#net_class_net_socket [Transform]: #stream_class_stream_transform [Writable]: #stream_class_stream_writable [zlib]: zlib.html diff --git a/deps/npm/node_modules/readable-stream/lib/_stream_readable.js b/deps/npm/node_modules/readable-stream/lib/_stream_readable.js index 54a9d5c553d69e..79914fa684cbb1 100644 --- a/deps/npm/node_modules/readable-stream/lib/_stream_readable.js +++ b/deps/npm/node_modules/readable-stream/lib/_stream_readable.js @@ -10,15 +10,11 @@ var processNextTick = require('process-nextick-args'); var isArray = require('isarray'); /**/ -/**/ -var Buffer = require('buffer').Buffer; -/**/ - Readable.ReadableState = ReadableState; -var EE = require('events'); - /**/ +var EE = require('events').EventEmitter; + var EElistenerCount = function (emitter, type) { return emitter.listeners(type).length; }; @@ -36,6 +32,9 @@ var Stream; /**/ var Buffer = require('buffer').Buffer; +/**/ +var bufferShim = require('buffer-shims'); +/**/ /**/ var util = require('core-util-is'); @@ -44,7 +43,7 @@ util.inherits = require('inherits'); /**/ var debugUtil = require('util'); -var debug = undefined; +var debug = void 0; if (debugUtil && debugUtil.debuglog) { debug = debugUtil.debuglog('stream'); } else { @@ -56,6 +55,19 @@ var StringDecoder; util.inherits(Readable, Stream); +var hasPrependListener = typeof EE.prototype.prependListener === 'function'; + +function prependListener(emitter, event, fn) { + if (hasPrependListener) return emitter.prependListener(event, fn); + + // This is a brutally ugly hack to make sure that our error handler + // is attached before any userland ones. NEVER DO THIS. This is here + // only because this code needs to continue to work with older versions + // of Node.js that do not include the prependListener() method. The goal + // is to eventually remove this hack. + if (!emitter._events || !emitter._events[event]) emitter.on(event, fn);else if (isArray(emitter._events[event])) emitter._events[event].unshift(fn);else emitter._events[event] = [fn, emitter._events[event]]; +} + var Duplex; function ReadableState(options, stream) { Duplex = Duplex || require('./_stream_duplex'); @@ -149,7 +161,7 @@ Readable.prototype.push = function (chunk, encoding) { if (!state.objectMode && typeof chunk === 'string') { encoding = encoding || state.defaultEncoding; if (encoding !== state.encoding) { - chunk = new Buffer(chunk, encoding); + chunk = bufferShim.from(chunk, encoding); encoding = ''; } } @@ -179,8 +191,8 @@ function readableAddChunk(stream, state, chunk, encoding, addToFront) { var e = new Error('stream.push() after EOF'); stream.emit('error', e); } else if (state.endEmitted && addToFront) { - var e = new Error('stream.unshift() after end event'); - stream.emit('error', e); + var _e = new Error('stream.unshift() after end event'); + stream.emit('error', _e); } else { var skipAdd; if (state.decoder && !addToFront && !encoding) { @@ -533,7 +545,8 @@ Readable.prototype.pipe = function (dest, pipeOpts) { // If the user unpiped during `dest.write()`, it is possible // to get stuck in a permanently paused state if that write // also returned false. - if (state.pipesCount === 1 && state.pipes[0] === dest && src.listenerCount('data') === 1 && !cleanedUp) { + // => Check whether `dest` is still a piping destination. + if ((state.pipesCount === 1 && state.pipes === dest || state.pipesCount > 1 && indexOf(state.pipes, dest) !== -1) && !cleanedUp) { debug('false write response, pause', src._readableState.awaitDrain); src._readableState.awaitDrain++; } @@ -549,9 +562,9 @@ Readable.prototype.pipe = function (dest, pipeOpts) { dest.removeListener('error', onerror); if (EElistenerCount(dest, 'error') === 0) dest.emit('error', er); } - // This is a brutally ugly hack to make sure that our error handler - // is attached before any userland ones. NEVER DO THIS. - if (!dest._events || !dest._events.error) dest.on('error', onerror);else if (isArray(dest._events.error)) dest._events.error.unshift(onerror);else dest._events.error = [onerror, dest._events.error]; + + // Make sure our error handler is attached before userland ones. + prependListener(dest, 'error', onerror); // Both close and finish should trigger unpipe, but only once. function onclose() { @@ -825,16 +838,16 @@ function fromList(n, state) { } else { // complex case. // we have enough to cover it, but it spans past the first buffer. - if (stringMode) ret = '';else ret = new Buffer(n); + if (stringMode) ret = '';else ret = bufferShim.allocUnsafe(n); var c = 0; for (var i = 0, l = list.length; i < l && c < n; i++) { - var buf = list[0]; - var cpy = Math.min(n - c, buf.length); + var _buf = list[0]; + var cpy = Math.min(n - c, _buf.length); - if (stringMode) ret += buf.slice(0, cpy);else buf.copy(ret, c, 0, cpy); + if (stringMode) ret += _buf.slice(0, cpy);else _buf.copy(ret, c, 0, cpy); - if (cpy < buf.length) list[0] = buf.slice(cpy);else list.shift(); + if (cpy < _buf.length) list[0] = _buf.slice(cpy);else list.shift(); c += cpy; } @@ -849,7 +862,7 @@ function endReadable(stream) { // If we get here before consuming all the bytes, then that is a // bug in node. Should never happen. - if (state.length > 0) throw new Error('endReadable called on non-empty stream'); + if (state.length > 0) throw new Error('"endReadable()" called on non-empty stream'); if (!state.endEmitted) { state.ended = true; diff --git a/deps/npm/node_modules/readable-stream/lib/_stream_transform.js b/deps/npm/node_modules/readable-stream/lib/_stream_transform.js index 625cdc17698059..dbc996ede62363 100644 --- a/deps/npm/node_modules/readable-stream/lib/_stream_transform.js +++ b/deps/npm/node_modules/readable-stream/lib/_stream_transform.js @@ -134,7 +134,7 @@ Transform.prototype.push = function (chunk, encoding) { // an error, then that'll put the hurt on the whole operation. If you // never call cb(), then you'll never get another chunk. Transform.prototype._transform = function (chunk, encoding, cb) { - throw new Error('not implemented'); + throw new Error('Not implemented'); }; Transform.prototype._write = function (chunk, encoding, cb) { @@ -172,9 +172,9 @@ function done(stream, er) { var ws = stream._writableState; var ts = stream._transformState; - if (ws.length) throw new Error('calling transform done when ws.length != 0'); + if (ws.length) throw new Error('Calling transform done when ws.length != 0'); - if (ts.transforming) throw new Error('calling transform done when still transforming'); + if (ts.transforming) throw new Error('Calling transform done when still transforming'); return stream.push(null); } \ No newline at end of file diff --git a/deps/npm/node_modules/readable-stream/lib/_stream_writable.js b/deps/npm/node_modules/readable-stream/lib/_stream_writable.js index 95916c992a9507..ed5efcbd203208 100644 --- a/deps/npm/node_modules/readable-stream/lib/_stream_writable.js +++ b/deps/npm/node_modules/readable-stream/lib/_stream_writable.js @@ -14,10 +14,6 @@ var processNextTick = require('process-nextick-args'); var asyncWrite = !process.browser && ['v0.10', 'v0.9.'].indexOf(process.version.slice(0, 5)) > -1 ? setImmediate : processNextTick; /**/ -/**/ -var Buffer = require('buffer').Buffer; -/**/ - Writable.WritableState = WritableState; /**/ @@ -43,6 +39,9 @@ var Stream; /**/ var Buffer = require('buffer').Buffer; +/**/ +var bufferShim = require('buffer-shims'); +/**/ util.inherits(Writable, Stream); @@ -146,10 +145,9 @@ function WritableState(options, stream) { // count buffered requests this.bufferedRequestCount = 0; - // create the two objects needed to store the corked requests - // they are not a linked list, as no new elements are inserted in there + // allocate the first CorkedRequest, there is always + // one allocated and free to use, and we maintain at most two this.corkedRequestsFree = new CorkedRequest(this); - this.corkedRequestsFree.next = new CorkedRequest(this); } WritableState.prototype.getBuffer = function writableStateGetBuffer() { @@ -196,7 +194,7 @@ function Writable(options) { // Otherwise people can pipe Writable streams, which is just wrong. Writable.prototype.pipe = function () { - this.emit('error', new Error('Cannot pipe. Not readable.')); + this.emit('error', new Error('Cannot pipe, not readable')); }; function writeAfterEnd(stream, cb) { @@ -213,9 +211,16 @@ function writeAfterEnd(stream, cb) { // how many bytes or characters. function validChunk(stream, state, chunk, cb) { var valid = true; - - if (!Buffer.isBuffer(chunk) && typeof chunk !== 'string' && chunk !== null && chunk !== undefined && !state.objectMode) { - var er = new TypeError('Invalid non-string/buffer chunk'); + var er = false; + // Always throw error if a null is written + // if we are not in object mode then throw + // if it is not a buffer, string, or undefined. + if (chunk === null) { + er = new TypeError('May not write null values to stream'); + } else if (!Buffer.isBuffer(chunk) && typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) { + er = new TypeError('Invalid non-string/buffer chunk'); + } + if (er) { stream.emit('error', er); processNextTick(cb, er); valid = false; @@ -265,11 +270,12 @@ Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) { if (typeof encoding === 'string') encoding = encoding.toLowerCase(); if (!(['hex', 'utf8', 'utf-8', 'ascii', 'binary', 'base64', 'ucs2', 'ucs-2', 'utf16le', 'utf-16le', 'raw'].indexOf((encoding + '').toLowerCase()) > -1)) throw new TypeError('Unknown encoding: ' + encoding); this._writableState.defaultEncoding = encoding; + return this; }; function decodeChunk(state, chunk, encoding) { if (!state.objectMode && state.decodeStrings !== false && typeof chunk === 'string') { - chunk = new Buffer(chunk, encoding); + chunk = bufferShim.from(chunk, encoding); } return chunk; } @@ -392,12 +398,16 @@ function clearBuffer(stream, state) { doWrite(stream, state, true, state.length, buffer, '', holder.finish); - // doWrite is always async, defer these to save a bit of time + // doWrite is almost always async, defer these to save a bit of time // as the hot path ends with doWrite state.pendingcb++; state.lastBufferedRequest = null; - state.corkedRequestsFree = holder.next; - holder.next = null; + if (holder.next) { + state.corkedRequestsFree = holder.next; + holder.next = null; + } else { + state.corkedRequestsFree = new CorkedRequest(state); + } } else { // Slow case, write chunks one-by-one while (entry) { diff --git a/deps/npm/node_modules/readable-stream/node_modules/buffer-shims/index.js b/deps/npm/node_modules/readable-stream/node_modules/buffer-shims/index.js new file mode 100644 index 00000000000000..1cab4c05e1ac2a --- /dev/null +++ b/deps/npm/node_modules/readable-stream/node_modules/buffer-shims/index.js @@ -0,0 +1,108 @@ +'use strict'; + +var buffer = require('buffer'); +var Buffer = buffer.Buffer; +var SlowBuffer = buffer.SlowBuffer; +var MAX_LEN = buffer.kMaxLength || 2147483647; +exports.alloc = function alloc(size, fill, encoding) { + if (typeof Buffer.alloc === 'function') { + return Buffer.alloc(size, fill, encoding); + } + if (typeof encoding === 'number') { + throw new TypeError('encoding must not be number'); + } + if (typeof size !== 'number') { + throw new TypeError('size must be a number'); + } + if (size > MAX_LEN) { + throw new RangeError('size is too large'); + } + var enc = encoding; + var _fill = fill; + if (_fill === undefined) { + enc = undefined; + _fill = 0; + } + var buf = new Buffer(size); + if (typeof _fill === 'string') { + var fillBuf = new Buffer(_fill, enc); + var flen = fillBuf.length; + var i = -1; + while (++i < size) { + buf[i] = fillBuf[i % flen]; + } + } else { + buf.fill(_fill); + } + return buf; +} +exports.allocUnsafe = function allocUnsafe(size) { + if (typeof Buffer.allocUnsafe === 'function') { + return Buffer.allocUnsafe(size); + } + if (typeof size !== 'number') { + throw new TypeError('size must be a number'); + } + if (size > MAX_LEN) { + throw new RangeError('size is too large'); + } + return new Buffer(size); +} +exports.from = function from(value, encodingOrOffset, length) { + if (typeof Buffer.from === 'function' && (!global.Uint8Array || Uint8Array.from !== Buffer.from)) { + return Buffer.from(value, encodingOrOffset, length); + } + if (typeof value === 'number') { + throw new TypeError('"value" argument must not be a number'); + } + if (typeof value === 'string') { + return new Buffer(value, encodingOrOffset); + } + if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) { + var offset = encodingOrOffset; + if (arguments.length === 1) { + return new Buffer(value); + } + if (typeof offset === 'undefined') { + offset = 0; + } + var len = length; + if (typeof len === 'undefined') { + len = value.byteLength - offset; + } + if (offset >= value.byteLength) { + throw new RangeError('\'offset\' is out of bounds'); + } + if (len > value.byteLength - offset) { + throw new RangeError('\'length\' is out of bounds'); + } + return new Buffer(value.slice(offset, offset + len)); + } + if (Buffer.isBuffer(value)) { + var out = new Buffer(value.length); + value.copy(out, 0, 0, value.length); + return out; + } + if (value) { + if (Array.isArray(value) || (typeof ArrayBuffer !== 'undefined' && value.buffer instanceof ArrayBuffer) || 'length' in value) { + return new Buffer(value); + } + if (value.type === 'Buffer' && Array.isArray(value.data)) { + return new Buffer(value.data); + } + } + + throw new TypeError('First argument must be a string, Buffer, ' + 'ArrayBuffer, Array, or array-like object.'); +} +exports.allocUnsafeSlow = function allocUnsafeSlow(size) { + if (typeof Buffer.allocUnsafeSlow === 'function') { + return Buffer.allocUnsafeSlow(size); + } + if (typeof size !== 'number') { + throw new TypeError('size must be a number'); + } + if (size >= MAX_LEN) { + throw new RangeError('size is too large'); + } + return new SlowBuffer(size); +} diff --git a/deps/npm/node_modules/which/node_modules/is-absolute/node_modules/is-relative/LICENSE-MIT b/deps/npm/node_modules/readable-stream/node_modules/buffer-shims/license.md similarity index 79% rename from deps/npm/node_modules/which/node_modules/is-absolute/node_modules/is-relative/LICENSE-MIT rename to deps/npm/node_modules/readable-stream/node_modules/buffer-shims/license.md index b576e8d484df60..01cfaefe2fcaff 100644 --- a/deps/npm/node_modules/which/node_modules/is-absolute/node_modules/is-relative/LICENSE-MIT +++ b/deps/npm/node_modules/readable-stream/node_modules/buffer-shims/license.md @@ -1,6 +1,4 @@ -The MIT License (MIT) - -Copyright (c) 2014 Jon Schlinkert +# Copyright (c) 2016 Calvin Metcalf Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -9,13 +7,13 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +**THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.** diff --git a/deps/npm/node_modules/readable-stream/node_modules/buffer-shims/package.json b/deps/npm/node_modules/readable-stream/node_modules/buffer-shims/package.json new file mode 100644 index 00000000000000..fe079c9657d9fc --- /dev/null +++ b/deps/npm/node_modules/readable-stream/node_modules/buffer-shims/package.json @@ -0,0 +1,51 @@ +{ + "name": "buffer-shims", + "version": "1.0.0", + "description": "some shims for node buffers", + "main": "index.js", + "scripts": { + "test": "tape test/*.js" + }, + "files": [ + "index.js" + ], + "license": "MIT", + "devDependencies": { + "tape": "^4.5.1" + }, + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/calvinmetcalf/buffer-shims.git" + }, + "gitHead": "ea89b3857ab5b8203957922a84e9a48cf4c47e0a", + "bugs": { + "url": "https://github.com/calvinmetcalf/buffer-shims/issues" + }, + "_id": "buffer-shims@1.0.0", + "_shasum": "9978ce317388c649ad8793028c3477ef044a8b51", + "_from": "buffer-shims@>=1.0.0 <2.0.0", + "_npmVersion": "3.8.6", + "_nodeVersion": "5.11.0", + "_npmUser": { + "name": "cwmma", + "email": "calvin.metcalf@gmail.com" + }, + "dist": { + "shasum": "9978ce317388c649ad8793028c3477ef044a8b51", + "tarball": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz" + }, + "maintainers": [ + { + "name": "cwmma", + "email": "calvin.metcalf@gmail.com" + } + ], + "_npmOperationalInternal": { + "host": "packages-16-east.internal.npmjs.com", + "tmp": "tmp/buffer-shims-1.0.0.tgz_1462560889323_0.8640750856138766" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", + "readme": "ERROR: No README data found!", + "homepage": "https://github.com/calvinmetcalf/buffer-shims#readme" +} diff --git a/deps/npm/node_modules/readable-stream/node_modules/buffer-shims/readme.md b/deps/npm/node_modules/readable-stream/node_modules/buffer-shims/readme.md new file mode 100644 index 00000000000000..7ea6475e284e8e --- /dev/null +++ b/deps/npm/node_modules/readable-stream/node_modules/buffer-shims/readme.md @@ -0,0 +1,21 @@ +buffer-shims +=== + +functions to make sure the new buffer methods work in older browsers. + +```js +var bufferShim = require('buffer-shims'); +bufferShim.from('foo'); +bufferShim.alloc(9, 'cafeface', 'hex'); +bufferShim.allocUnsafe(15); +bufferShim.allocUnsafeSlow(21); +``` + +should just use the original in newer nodes and on older nodes uses fallbacks. + +Known Issues +=== +- this does not patch the buffer object, only the constructor stuff +- it's actually a polyfill + +![](https://i.imgur.com/zxII3jJ.gif) diff --git a/deps/npm/node_modules/readable-stream/node_modules/core-util-is/package.json b/deps/npm/node_modules/readable-stream/node_modules/core-util-is/package.json index ddd227e64f99f4..19fb85922bc035 100644 --- a/deps/npm/node_modules/readable-stream/node_modules/core-util-is/package.json +++ b/deps/npm/node_modules/readable-stream/node_modules/core-util-is/package.json @@ -46,7 +46,7 @@ }, "dist": { "shasum": "b5fd54220aa2bc5ab57aab7140c940754503c1a7", - "tarball": "http://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" + "tarball": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" }, "maintainers": [ { diff --git a/deps/npm/node_modules/readable-stream/node_modules/isarray/package.json b/deps/npm/node_modules/readable-stream/node_modules/isarray/package.json index 703ea43cb4d5ac..e86d232e6090f3 100644 --- a/deps/npm/node_modules/readable-stream/node_modules/isarray/package.json +++ b/deps/npm/node_modules/readable-stream/node_modules/isarray/package.json @@ -57,7 +57,7 @@ }, "dist": { "shasum": "bb935d48582cba168c06834957a54a3e07124f11", - "tarball": "http://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + "tarball": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" }, "maintainers": [ { diff --git a/deps/npm/node_modules/readable-stream/node_modules/string_decoder/package.json b/deps/npm/node_modules/readable-stream/node_modules/string_decoder/package.json index 0364d54ba46af6..8e8b77db7b42cd 100644 --- a/deps/npm/node_modules/readable-stream/node_modules/string_decoder/package.json +++ b/deps/npm/node_modules/readable-stream/node_modules/string_decoder/package.json @@ -46,7 +46,7 @@ ], "dist": { "shasum": "62e203bc41766c6c28c9fc84301dab1c5310fa94", - "tarball": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + "tarball": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "directories": {}, "_resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", diff --git a/deps/npm/node_modules/readable-stream/node_modules/util-deprecate/package.json b/deps/npm/node_modules/readable-stream/node_modules/util-deprecate/package.json index ae0c70f6c633f1..a018135492d81f 100644 --- a/deps/npm/node_modules/readable-stream/node_modules/util-deprecate/package.json +++ b/deps/npm/node_modules/readable-stream/node_modules/util-deprecate/package.json @@ -46,7 +46,7 @@ ], "dist": { "shasum": "450d4dc9fa70de732762fbd2d4a28981419a0ccf", - "tarball": "http://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + "tarball": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" }, "directories": {}, "_resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", diff --git a/deps/npm/node_modules/readable-stream/package.json b/deps/npm/node_modules/readable-stream/package.json index 745c4d8ef25272..af4c325431dd09 100644 --- a/deps/npm/node_modules/readable-stream/package.json +++ b/deps/npm/node_modules/readable-stream/package.json @@ -1,9 +1,10 @@ { "name": "readable-stream", - "version": "2.1.2", + "version": "2.1.4", "description": "Streams3, a user-land copy of the stream library from Node.js", "main": "readable.js", "dependencies": { + "buffer-shims": "^1.0.0", "core-util-is": "~1.0.0", "inherits": "~2.0.1", "isarray": "~1.0.0", @@ -12,15 +13,17 @@ "util-deprecate": "~1.0.1" }, "devDependencies": { + "assert": "~1.4.0", "nyc": "^6.4.0", "tap": "~0.7.1", "tape": "~4.5.1", - "zuul": "~3.9.0" + "zuul": "~3.9.0", + "zuul-ngrok": "^4.0.0" }, "scripts": { "test": "tap test/parallel/*.js test/ours/*.js", "browser": "npm run write-zuul && zuul -- test/browser.js", - "write-zuul": "printf \"ui: tape\nbrowsers:\n - name: $BROWSER_NAME\n version: $BROWSER_VERSION\n\">.zuul.yml", + "write-zuul": "printf \"ui: tape\ntunnel: ngrok\nbrowsers:\n - name: $BROWSER_NAME\n version: $BROWSER_VERSION\n\">.zuul.yml", "local": "zuul --local -- test/browser.js", "cover": "nyc npm test", "report": "nyc report --reporter=lcov" @@ -43,22 +46,22 @@ ] }, "license": "MIT", - "gitHead": "06754eed4f2b882b589f8667ecc8aadcf916045f", + "gitHead": "7752832fba237929388dea6c96911a0a6379abfc", "bugs": { "url": "https://github.com/nodejs/readable-stream/issues" }, - "_id": "readable-stream@2.1.2", - "_shasum": "a92b6e854f13ff0685e4ca7dce6cf73d3e319422", - "_from": "readable-stream@2.1.2", - "_npmVersion": "3.8.3", - "_nodeVersion": "5.10.1", + "_id": "readable-stream@2.1.4", + "_shasum": "70b9791c6fcb8480db44bd155a0f6bb58f172468", + "_from": "readable-stream@>=2.1.4 <2.2.0", + "_npmVersion": "3.8.6", + "_nodeVersion": "5.11.0", "_npmUser": { "name": "cwmma", "email": "calvin.metcalf@gmail.com" }, "dist": { - "shasum": "a92b6e854f13ff0685e4ca7dce6cf73d3e319422", - "tarball": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.2.tgz" + "shasum": "70b9791c6fcb8480db44bd155a0f6bb58f172468", + "tarball": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.4.tgz" }, "maintainers": [ { @@ -80,10 +83,10 @@ ], "_npmOperationalInternal": { "host": "packages-12-west.internal.npmjs.com", - "tmp": "tmp/readable-stream-2.1.2.tgz_1461933796258_0.5075750169344246" + "tmp": "tmp/readable-stream-2.1.4.tgz_1463679605032_0.6917394688352942" }, "directories": {}, - "_resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.2.tgz", + "_resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.4.tgz", "readme": "ERROR: No README data found!", "homepage": "https://github.com/nodejs/readable-stream#readme" } diff --git a/deps/npm/node_modules/which/CHANGELOG.md b/deps/npm/node_modules/which/CHANGELOG.md index 03879364f87804..56106119e9a645 100644 --- a/deps/npm/node_modules/which/CHANGELOG.md +++ b/deps/npm/node_modules/which/CHANGELOG.md @@ -1,6 +1,15 @@ # Changes +## v1.2.10 + +* Use env.PATH only, not env.Path + +## v1.2.9 + +* fix for paths starting with ../ +* Remove unused `is-absolute` module + ## v1.2.8 * bullet items in changelog that contain (but don't start with) # diff --git a/deps/npm/node_modules/which/node_modules/is-absolute/LICENSE b/deps/npm/node_modules/which/node_modules/is-absolute/LICENSE deleted file mode 100644 index 904ab073b70946..00000000000000 --- a/deps/npm/node_modules/which/node_modules/is-absolute/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014-2015, Jon Schlinkert.Copyright (c) 2009-2015, TJ Holowaychuk. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/deps/npm/node_modules/which/node_modules/is-absolute/README.md b/deps/npm/node_modules/which/node_modules/is-absolute/README.md deleted file mode 100644 index 2347828a3e73dd..00000000000000 --- a/deps/npm/node_modules/which/node_modules/is-absolute/README.md +++ /dev/null @@ -1,53 +0,0 @@ -# is-absolute [![NPM version](https://badge.fury.io/js/is-absolute.svg)](http://badge.fury.io/js/is-absolute) [![Build Status](https://travis-ci.org/jonschlinkert/is-absolute.svg)](https://travis-ci.org/jonschlinkert/is-absolute) - -> Return true if a file path is absolute. - -Based on the `isAbsolute` utility method in [express](https://github.com/visionmedia/express). - -## Install with [npm](npmjs.org) - -```bash -npm i is-absolute --save -``` - -## Usage - -```js -var isAbsolute = require('is-absolute'); -console.log(isAbsolute('a/b/c.js')); -//=> 'false'; -``` - -## Running tests -Install dev dependencies. - -```bash -npm i -d && npm test -``` - - -## Contributing -Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/is-absolute/issues) - - -## Other projects -* [is-relative](https://github.com/jonschlinkert/is-relative): Returns `true` if the path appears to be relative. -* [is-dotfile](https://github.com/regexps/is-dotfile): Return true if a file path is (or has) a dotfile. -* [is-glob](https://github.com/jonschlinkert/is-glob): Returns `true` if the given string looks like a glob pattern. -* [cwd](https://github.com/jonschlinkert/cwd): Node.js util for easily getting the current working directory of a project based on package.json or the given path. -* [git-config-path](https://github.com/jonschlinkert/git-config-path): Resolve the path to the user's global .gitconfig. - -## Author - -**Jon Schlinkert** - -+ [github/jonschlinkert](https://github.com/jonschlinkert) -+ [twitter/jonschlinkert](http://twitter.com/jonschlinkert) - -## License -Copyright (c) 2014-2015 Jon Schlinkert -Released under the MIT license - -*** - -_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on March 05, 2015._ diff --git a/deps/npm/node_modules/which/node_modules/is-absolute/index.js b/deps/npm/node_modules/which/node_modules/is-absolute/index.js deleted file mode 100644 index 9df4d5c2406a97..00000000000000 --- a/deps/npm/node_modules/which/node_modules/is-absolute/index.js +++ /dev/null @@ -1,26 +0,0 @@ -/*! - * is-absolute - * - * Copyright (c) 2014-2015, Jon Schlinkert. - * Licensed under the MIT License. - */ - -'use strict'; - -var isRelative = require('is-relative'); - -module.exports = function isAbsolute(filepath) { - if ('/' === filepath[0]) { - return true; - } - if (':' === filepath[1] && '\\' === filepath[2]) { - return true; - } - // Microsoft Azure absolute filepath - if ('\\\\' == filepath.substring(0, 2)) { - return true; - } - if (!isRelative(filepath)) { - return true; - } -}; diff --git a/deps/npm/node_modules/which/node_modules/is-absolute/node_modules/is-relative/README.md b/deps/npm/node_modules/which/node_modules/is-absolute/node_modules/is-relative/README.md deleted file mode 100644 index 5d7a2a2aabb928..00000000000000 --- a/deps/npm/node_modules/which/node_modules/is-absolute/node_modules/is-relative/README.md +++ /dev/null @@ -1,38 +0,0 @@ -# is-relative [![NPM version](https://badge.fury.io/js/is-relative.svg)](http://badge.fury.io/js/is-relative) - -> Returns `true` if the path appears to be relative. - -## Install -### Install with [npm](npmjs.org) - -```bash -npm i is-relative --save -``` - -## Usage -### [isRelative](index.js#L16) - -* `filepath` **{String}**: Path to test. -* `returns`: {Boolean} - -```js -var isRelative = require('is-relative'); -isRelative('README.md'); -//=> true -``` - - -## Author - -**Jon Schlinkert** - -+ [github/jonschlinkert](https://github.com/jonschlinkert) -+ [twitter/jonschlinkert](http://twitter.com/jonschlinkert) - -## License -Copyright (c) 2014 Jon Schlinkert -Released under the MIT license - -*** - -_This file was generated by [verb](https://github.com/assemble/verb) on November 17, 2014._ \ No newline at end of file diff --git a/deps/npm/node_modules/which/node_modules/is-absolute/node_modules/is-relative/index.js b/deps/npm/node_modules/which/node_modules/is-absolute/node_modules/is-relative/index.js deleted file mode 100644 index ffc760a82a5dab..00000000000000 --- a/deps/npm/node_modules/which/node_modules/is-absolute/node_modules/is-relative/index.js +++ /dev/null @@ -1,21 +0,0 @@ -'use strict'; - -/** - * ```js - * var isRelative = require('is-relative'); - * isRelative('README.md'); - * //=> true - * ``` - * - * @name isRelative - * @param {String} `filepath` Path to test. - * @return {Boolean} - * @api public - */ - -module.exports = function isRelative(filepath) { - if (typeof filepath !== 'string') { - throw new Error('isRelative expects a string.'); - } - return !/^([a-z]+:)?[\\\/]/i.test(filepath); -}; \ No newline at end of file diff --git a/deps/npm/node_modules/which/node_modules/is-absolute/node_modules/is-relative/package.json b/deps/npm/node_modules/which/node_modules/is-absolute/node_modules/is-relative/package.json deleted file mode 100644 index d582081dd157ca..00000000000000 --- a/deps/npm/node_modules/which/node_modules/is-absolute/node_modules/is-relative/package.json +++ /dev/null @@ -1,76 +0,0 @@ -{ - "name": "is-relative", - "description": "Returns `true` if the path appears to be relative.", - "version": "0.1.3", - "homepage": "https://github.com/jonschlinkert/is-relative", - "author": { - "name": "Jon Schlinkert", - "url": "https://github.com/jonschlinkert" - }, - "repository": { - "type": "git", - "url": "git://github.com/jonschlinkert/is-relative.git" - }, - "bugs": { - "url": "https://github.com/jonschlinkert/is-relative/issues" - }, - "licenses": [ - { - "type": "MIT", - "url": "https://github.com/jonschlinkert/is-relative/blob/master/LICENSE-MIT" - } - ], - "keywords": [ - "absolute", - "check", - "file", - "filepath", - "is", - "normalize", - "path", - "path.relative", - "relative", - "resolve", - "slash", - "slashes", - "uri", - "url" - ], - "main": "index.js", - "files": [ - "index.js", - "LICENSE-MIT" - ], - "engines": { - "node": ">=0.10.0" - }, - "scripts": { - "test": "mocha -R spec" - }, - "devDependencies": { - "mocha": "*", - "verb": ">= 0.2.6", - "verb-tag-jscomments": "^0.1.4" - }, - "_id": "is-relative@0.1.3", - "_shasum": "905fee8ae86f45b3ec614bc3c15c869df0876e82", - "_from": "is-relative@>=0.1.0 <0.2.0", - "_npmVersion": "1.4.9", - "_npmUser": { - "name": "jonschlinkert", - "email": "github@sellside.com" - }, - "maintainers": [ - { - "name": "jonschlinkert", - "email": "github@sellside.com" - } - ], - "dist": { - "shasum": "905fee8ae86f45b3ec614bc3c15c869df0876e82", - "tarball": "http://registry.npmjs.org/is-relative/-/is-relative-0.1.3.tgz" - }, - "directories": {}, - "_resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.1.3.tgz", - "readme": "ERROR: No README data found!" -} diff --git a/deps/npm/node_modules/which/node_modules/is-absolute/package.json b/deps/npm/node_modules/which/node_modules/is-absolute/package.json deleted file mode 100644 index 4f954b855f11d4..00000000000000 --- a/deps/npm/node_modules/which/node_modules/is-absolute/package.json +++ /dev/null @@ -1,76 +0,0 @@ -{ - "name": "is-absolute", - "description": "Return true if a file path is absolute.", - "version": "0.1.7", - "homepage": "https://github.com/jonschlinkert/is-absolute", - "author": { - "name": "Jon Schlinkert", - "url": "https://github.com/jonschlinkert" - }, - "repository": { - "type": "git", - "url": "git://github.com/jonschlinkert/is-absolute.git" - }, - "bugs": { - "url": "https://github.com/jonschlinkert/is-absolute/issues" - }, - "license": { - "type": "MIT", - "url": "https://github.com/jonschlinkert/is-absolute/blob/master/LICENSE" - }, - "files": [ - "index.js" - ], - "main": "index.js", - "engines": { - "node": ">=0.10.0" - }, - "scripts": { - "test": "mocha" - }, - "dependencies": { - "is-relative": "^0.1.0" - }, - "devDependencies": { - "mocha": "*" - }, - "keywords": [ - "absolute", - "check", - "file", - "filepath", - "is", - "normalize", - "path", - "path.relative", - "relative", - "resolve", - "slash", - "slashes", - "uri", - "url" - ], - "gitHead": "90cca7b671620bf28b778a61fddc8a986a2e1095", - "_id": "is-absolute@0.1.7", - "_shasum": "847491119fccb5fb436217cc737f7faad50f603f", - "_from": "is-absolute@>=0.1.7 <0.2.0", - "_npmVersion": "2.5.1", - "_nodeVersion": "0.12.0", - "_npmUser": { - "name": "jonschlinkert", - "email": "github@sellside.com" - }, - "maintainers": [ - { - "name": "jonschlinkert", - "email": "github@sellside.com" - } - ], - "dist": { - "shasum": "847491119fccb5fb436217cc737f7faad50f603f", - "tarball": "http://registry.npmjs.org/is-absolute/-/is-absolute-0.1.7.tgz" - }, - "directories": {}, - "_resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.1.7.tgz", - "readme": "ERROR: No README data found!" -} diff --git a/deps/npm/node_modules/which/node_modules/isexe/package.json b/deps/npm/node_modules/which/node_modules/isexe/package.json index 0787bc7599d469..328d69c54f0487 100644 --- a/deps/npm/node_modules/which/node_modules/isexe/package.json +++ b/deps/npm/node_modules/which/node_modules/isexe/package.json @@ -41,7 +41,7 @@ }, "dist": { "shasum": "36f3e22e60750920f5e7241a476a8c6a42275ad0", - "tarball": "http://registry.npmjs.org/isexe/-/isexe-1.1.2.tgz" + "tarball": "https://registry.npmjs.org/isexe/-/isexe-1.1.2.tgz" }, "maintainers": [ { diff --git a/deps/npm/node_modules/which/package.json b/deps/npm/node_modules/which/package.json index 964ddcf56b4800..90b621d8cc3585 100644 --- a/deps/npm/node_modules/which/package.json +++ b/deps/npm/node_modules/which/package.json @@ -6,7 +6,7 @@ }, "name": "which", "description": "Like which(1) unix command. Find the first instance of an executable in the PATH.", - "version": "1.2.8", + "version": "1.2.10", "repository": { "type": "git", "url": "git://github.com/isaacs/node-which.git" @@ -17,7 +17,6 @@ }, "license": "ISC", "dependencies": { - "is-absolute": "^0.1.7", "isexe": "^1.1.1" }, "devDependencies": { @@ -34,23 +33,23 @@ "which.js", "bin/which" ], - "gitHead": "e4de2c25e9163b1f55323792f0fc5806e948ffc1", + "gitHead": "3f590834623ee940d922e12b1c8b9cbf24bd5012", "bugs": { "url": "https://github.com/isaacs/node-which/issues" }, "homepage": "https://github.com/isaacs/node-which#readme", - "_id": "which@1.2.8", - "_shasum": "37fa9f6eab30e49b8ef6eea24681c5799d52ebd6", - "_from": "which@1.2.8", - "_npmVersion": "3.8.9", - "_nodeVersion": "5.6.0", + "_id": "which@1.2.10", + "_shasum": "91cd9bd0751322411b659b40f054b21de957ab2d", + "_from": "which@>=1.2.10 <1.3.0", + "_npmVersion": "3.9.1", + "_nodeVersion": "4.4.4", "_npmUser": { "name": "isaacs", "email": "i@izs.me" }, "dist": { - "shasum": "37fa9f6eab30e49b8ef6eea24681c5799d52ebd6", - "tarball": "https://registry.npmjs.org/which/-/which-1.2.8.tgz" + "shasum": "91cd9bd0751322411b659b40f054b21de957ab2d", + "tarball": "https://registry.npmjs.org/which/-/which-1.2.10.tgz" }, "maintainers": [ { @@ -60,9 +59,9 @@ ], "_npmOperationalInternal": { "host": "packages-12-west.internal.npmjs.com", - "tmp": "tmp/which-1.2.8.tgz_1462472514341_0.746755798580125" + "tmp": "tmp/which-1.2.10.tgz_1465116744337_0.4818702598568052" }, "directories": {}, - "_resolved": "https://registry.npmjs.org/which/-/which-1.2.8.tgz", + "_resolved": "https://registry.npmjs.org/which/-/which-1.2.10.tgz", "readme": "ERROR: No README data found!" } diff --git a/deps/npm/node_modules/which/which.js b/deps/npm/node_modules/which/which.js index 4ba14cd02f24cc..5a9b15ca60403f 100644 --- a/deps/npm/node_modules/which/which.js +++ b/deps/npm/node_modules/which/which.js @@ -9,7 +9,6 @@ var path = require('path') var COLON = isWindows ? ';' : ':' var isexe = require('isexe') var fs = require('fs') -var isAbsolute = require('is-absolute') function getNotFoundError (cmd) { var er = new Error('not found: ' + cmd) @@ -20,7 +19,7 @@ function getNotFoundError (cmd) { function getPathInfo (cmd, opt) { var colon = opt.colon || COLON - var pathEnv = opt.path || process.env.Path || process.env.PATH || '' + var pathEnv = opt.path || process.env.PATH || '' var pathExt = [''] pathEnv = pathEnv.split(colon) @@ -75,7 +74,7 @@ function which (cmd, opt, cb) { pathPart = pathPart.slice(1, -1) var p = path.join(pathPart, cmd) - if (!pathPart && (/^\./).test(cmd)) { + if (!pathPart && (/^\.[\\\/]/).test(cmd)) { p = cmd.slice(0, 2) + p } ;(function E (ii, ll) { @@ -109,7 +108,7 @@ function whichSync (cmd, opt) { pathPart = pathPart.slice(1, -1) var p = path.join(pathPart, cmd) - if (!pathPart && (/^\./).test(cmd)) { + if (!pathPart && /^\.[\\\/]/.test(cmd)) { p = cmd.slice(0, 2) + p } for (var j = 0, ll = pathExt.length; j < ll; j ++) { diff --git a/deps/npm/node_modules/wrappy/package.json b/deps/npm/node_modules/wrappy/package.json index b88e66283290ba..4028270c7f83be 100644 --- a/deps/npm/node_modules/wrappy/package.json +++ b/deps/npm/node_modules/wrappy/package.json @@ -1,21 +1,24 @@ { "name": "wrappy", - "version": "1.0.1", + "version": "1.0.2", "description": "Callback wrapping utility", "main": "wrappy.js", + "files": [ + "wrappy.js" + ], "directories": { "test": "test" }, "dependencies": {}, "devDependencies": { - "tap": "^0.4.12" + "tap": "^2.3.1" }, "scripts": { - "test": "tap test/*.js" + "test": "tap --coverage test/*.js" }, "repository": { "type": "git", - "url": "https://github.com/npm/wrappy" + "url": "git+https://github.com/npm/wrappy.git" }, "author": { "name": "Isaac Z. Schlueter", @@ -27,26 +30,34 @@ "url": "https://github.com/npm/wrappy/issues" }, "homepage": "https://github.com/npm/wrappy", - "gitHead": "006a8cbac6b99988315834c207896eed71fd069a", - "_id": "wrappy@1.0.1", - "_shasum": "1e65969965ccbc2db4548c6b84a6f2c5aedd4739", - "_from": "wrappy@1.0.1", - "_npmVersion": "2.0.0", - "_nodeVersion": "0.10.31", + "gitHead": "71d91b6dc5bdeac37e218c2cf03f9ab55b60d214", + "_id": "wrappy@1.0.2", + "_shasum": "b5243d8f3ec1aa35f1364605bc0d1036e30ab69f", + "_from": "wrappy@>=1.0.2 <1.1.0", + "_npmVersion": "3.9.1", + "_nodeVersion": "5.10.1", "_npmUser": { - "name": "isaacs", - "email": "i@izs.me" + "name": "zkat", + "email": "kat@sykosomatic.org" + }, + "dist": { + "shasum": "b5243d8f3ec1aa35f1364605bc0d1036e30ab69f", + "tarball": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" }, "maintainers": [ { "name": "isaacs", "email": "i@izs.me" + }, + { + "name": "zkat", + "email": "kat@sykosomatic.org" } ], - "dist": { - "shasum": "1e65969965ccbc2db4548c6b84a6f2c5aedd4739", - "tarball": "http://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz" + "_npmOperationalInternal": { + "host": "packages-16-east.internal.npmjs.com", + "tmp": "tmp/wrappy-1.0.2.tgz_1463527848281_0.037129373755306005" }, - "_resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz", + "_resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "readme": "ERROR: No README data found!" } diff --git a/deps/npm/node_modules/wrappy/test/basic.js b/deps/npm/node_modules/wrappy/test/basic.js deleted file mode 100644 index 5ed0fcdfd9c52e..00000000000000 --- a/deps/npm/node_modules/wrappy/test/basic.js +++ /dev/null @@ -1,51 +0,0 @@ -var test = require('tap').test -var wrappy = require('../wrappy.js') - -test('basic', function (t) { - function onceifier (cb) { - var called = false - return function () { - if (called) return - called = true - return cb.apply(this, arguments) - } - } - onceifier.iAmOnce = {} - var once = wrappy(onceifier) - t.equal(once.iAmOnce, onceifier.iAmOnce) - - var called = 0 - function boo () { - t.equal(called, 0) - called++ - } - // has some rando property - boo.iAmBoo = true - - var onlyPrintOnce = once(boo) - - onlyPrintOnce() // prints 'boo' - onlyPrintOnce() // does nothing - t.equal(called, 1) - - // random property is retained! - t.equal(onlyPrintOnce.iAmBoo, true) - - var logs = [] - var logwrap = wrappy(function (msg, cb) { - logs.push(msg + ' wrapping cb') - return function () { - logs.push(msg + ' before cb') - var ret = cb.apply(this, arguments) - logs.push(msg + ' after cb') - } - }) - - var c = logwrap('foo', function () { - t.same(logs, [ 'foo wrapping cb', 'foo before cb' ]) - }) - c() - t.same(logs, [ 'foo wrapping cb', 'foo before cb', 'foo after cb' ]) - - t.end() -}) diff --git a/deps/npm/package.json b/deps/npm/package.json index 50ec15a47e955c..a509afa6d5127e 100644 --- a/deps/npm/package.json +++ b/deps/npm/package.json @@ -1,5 +1,5 @@ { - "version": "2.15.5", + "version": "2.15.8", "name": "npm", "description": "a package manager for JavaScript", "keywords": [ @@ -30,7 +30,7 @@ "main": "./lib/npm.js", "bin": "./bin/npm-cli.js", "dependencies": { - "abbrev": "~1.0.7", + "abbrev": "~1.0.9", "ansi": "~0.3.1", "ansicolors": "~0.3.2", "ansistyles": "~0.1.3", @@ -47,17 +47,17 @@ "editor": "~1.0.0", "fs-vacuum": "~1.2.9", "fs-write-stream-atomic": "~1.0.8", - "fstream": "~1.0.8", + "fstream": "~1.0.10", "fstream-npm": "~1.0.7", "github-url-from-git": "~1.4.0", "github-url-from-username-repo": "~1.0.2", - "glob": "~7.0.3", + "glob": "~7.0.4", "graceful-fs": "~4.1.4", "hosted-git-info": "~2.1.4", "inflight": "~1.0.4", "inherits": "~2.0.1", "ini": "~1.3.4", - "init-package-json": "~1.9.3", + "init-package-json": "~1.9.4", "lockfile": "~1.0.1", "lru-cache": "~4.0.1", "minimatch": "~3.0.0", @@ -69,9 +69,9 @@ "npm-cache-filename": "~1.0.2", "npm-install-checks": "~1.0.7", "npm-package-arg": "~4.1.0", - "npm-registry-client": "~7.1.0", - "npm-user-validate": "~0.1.2", - "npmlog": "~2.0.3", + "npm-registry-client": "~7.1.2", + "npm-user-validate": "~0.1.4", + "npmlog": "~2.0.4", "once": "~1.3.3", "opener": "~1.4.1", "osenv": "~0.1.3", @@ -79,7 +79,7 @@ "read": "~1.0.7", "read-installed": "~4.0.3", "read-package-json": "~2.0.4", - "readable-stream": "~2.1.2", + "readable-stream": "~2.1.4", "realize-package-specifier": "~3.0.1", "request": "~2.72.0", "retry": "~0.9.0", @@ -96,8 +96,8 @@ "umask": "~1.1.0", "validate-npm-package-license": "~3.0.1", "validate-npm-package-name": "~2.2.2", - "which": "~1.2.8", - "wrappy": "~1.0.1", + "which": "~1.2.10", + "wrappy": "~1.0.2", "write-file-atomic": "~1.1.4" }, "bundleDependencies": [ @@ -179,7 +179,7 @@ "marked-man": "~0.1.5", "npm-registry-couchapp": "~2.6.12", "npm-registry-mock": "~1.0.1", - "require-inject": "~1.3.1", + "require-inject": "~1.4.0", "sprintf-js": "~1.0.3", "tacks": "~1.2.1", "tap": "~5.7.1" diff --git a/deps/npm/test/common-tap.js b/deps/npm/test/common-tap.js index de0a9f416d79d8..06c1e3f9f7eb7c 100644 --- a/deps/npm/test/common-tap.js +++ b/deps/npm/test/common-tap.js @@ -5,7 +5,6 @@ if (!global.setImmediate || !require('timers').setImmediate) { setTimeout.apply(this, args) } } - var spawn = require('child_process').spawn var path = require('path') @@ -25,7 +24,7 @@ var bin = exports.bin = require.resolve('../bin/npm-cli.js') var chain = require('slide').chain var once = require('once') -exports.npm = function (cmd, opts, cb) { +exports.npm = function npm (cmd, opts, cb) { cb = once(cb) cmd = [bin].concat(cmd) opts = opts || {} @@ -60,7 +59,7 @@ exports.npm = function (cmd, opts, cb) { return child } -exports.makeGitRepo = function (params, cb) { +exports.makeGitRepo = function makeGitRepo (params, cb) { // git must be called after npm.load because it uses config var git = require('../lib/utils/git.js') @@ -85,3 +84,14 @@ exports.makeGitRepo = function (params, cb) { chain(commands, cb) } + +exports.rmFromInShrinkwrap = function rmFromInShrinkwrap (obj) { + for (var i in obj) { + if (i === "from") + delete obj[i] + else if (i === "dependencies") + for (var j in obj[i]) + exports.rmFromInShrinkwrap(obj[i][j]) + } + return obj +} \ No newline at end of file diff --git a/deps/npm/test/common.js b/deps/npm/test/common.js deleted file mode 100644 index 2755056b1b491c..00000000000000 --- a/deps/npm/test/common.js +++ /dev/null @@ -1,7 +0,0 @@ - -// whatever, it's just tests. -;["util","assert"].forEach(function (thing) { - thing = require("thing") - for (var i in thing) global[i] = thing[i] -} - diff --git a/deps/npm/test/packages/npm-test-shrinkwrap/test.js b/deps/npm/test/packages/npm-test-shrinkwrap/test.js deleted file mode 100644 index fba90ec6516311..00000000000000 --- a/deps/npm/test/packages/npm-test-shrinkwrap/test.js +++ /dev/null @@ -1,35 +0,0 @@ -var path = require("path") -var assert = require("assert") - -process.env.npm_config_prefix = process.cwd() -delete process.env.npm_config_global -delete process.env.npm_config_depth - -var npm = process.env.npm_execpath - -require("child_process").execFile(process.execPath, [npm, "ls", "--json"], { - stdio: "pipe", env: process.env, cwd: process.cwd() }, - function (err, stdout, stderr) { - if (err) throw err - - var actual = JSON.parse(stdout) - var expected = require("./npm-shrinkwrap.json") - rmFrom(actual) - actual = actual.dependencies - rmFrom(expected) - expected = expected.dependencies - console.error(JSON.stringify(actual, null, 2)) - console.error(JSON.stringify(expected, null, 2)) - - assert.deepEqual(actual, expected) -}) - -function rmFrom (obj) { - for (var i in obj) { - if (i === "from") - delete obj[i] - else if (i === "dependencies") - for (var j in obj[i]) - rmFrom(obj[i][j]) - } -} diff --git a/deps/npm/test/tap/install-shrinkwrap-equals-ls.js b/deps/npm/test/tap/install-shrinkwrap-equals-ls.js new file mode 100644 index 00000000000000..1c324e56c2524c --- /dev/null +++ b/deps/npm/test/tap/install-shrinkwrap-equals-ls.js @@ -0,0 +1,288 @@ +var fs = require('graceful-fs') +var path = require('path') + +var mkdirp = require('mkdirp') +var osenv = require('osenv') +var rimraf = require('rimraf') +var test = require('tap').test + +var common = require('../common-tap.js') + +var pkg = path.join(__dirname, 'install-shrinkwrap-equals-ls') + +var EXEC_OPTS = {cwd: pkg} + +var json = { + "name": "install-shrinkwrap-equals-ls", + "version": "1.0.0", + "dependencies": { + "react": "^0.14.0", + "react-bootstrap": "^0.28.1", + "react-dom": "^0.14.0" + } +} + +var shrinkwrap = { + "name": "install-shrinkwrap-equals-ls", + "version": "1.0.0", + "dependencies": { + "react": { + "version": "0.14.8", + "from": "react@>=0.14.0 <0.15.0", + "resolved": "https://registry.npmjs.org/react/-/react-0.14.8.tgz", + "dependencies": { + "envify": { + "version": "3.4.0", + "from": "envify@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/envify/-/envify-3.4.0.tgz", + "dependencies": { + "through": { + "version": "2.3.8", + "from": "through@>=2.3.4 <2.4.0", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz" + }, + "jstransform": { + "version": "10.1.0", + "from": "jstransform@>=10.0.1 <11.0.0", + "resolved": "https://registry.npmjs.org/jstransform/-/jstransform-10.1.0.tgz", + "dependencies": { + "base62": { + "version": "0.1.1", + "from": "base62@0.1.1", + "resolved": "https://registry.npmjs.org/base62/-/base62-0.1.1.tgz" + }, + "esprima-fb": { + "version": "13001.1001.0-dev-harmony-fb", + "from": "esprima-fb@13001.1001.0-dev-harmony-fb", + "resolved": "https://registry.npmjs.org/esprima-fb/-/esprima-fb-13001.1001.0-dev-harmony-fb.tgz" + }, + "source-map": { + "version": "0.1.31", + "from": "source-map@0.1.31", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.31.tgz", + "dependencies": { + "amdefine": { + "version": "1.0.0", + "from": "amdefine@>=0.0.4", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.0.tgz" + } + } + } + } + } + } + }, + "fbjs": { + "version": "0.6.1", + "from": "fbjs@>=0.6.1 <0.7.0", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.6.1.tgz", + "dependencies": { + "core-js": { + "version": "1.2.6", + "from": "core-js@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.6.tgz" + }, + "loose-envify": { + "version": "1.1.0", + "from": "loose-envify@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.1.0.tgz", + "dependencies": { + "js-tokens": { + "version": "1.0.3", + "from": "js-tokens@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-1.0.3.tgz" + } + } + }, + "promise": { + "version": "7.1.1", + "from": "promise@>=7.0.3 <8.0.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.1.1.tgz", + "dependencies": { + "asap": { + "version": "2.0.3", + "from": "asap@>=2.0.3 <2.1.0", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.3.tgz" + } + } + }, + "ua-parser-js": { + "version": "0.7.10", + "from": "ua-parser-js@>=0.7.9 <0.8.0", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.10.tgz" + }, + "whatwg-fetch": { + "version": "0.9.0", + "from": "whatwg-fetch@>=0.9.0 <0.10.0", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-0.9.0.tgz" + } + } + } + } + }, + "react-bootstrap": { + "version": "0.28.5", + "from": "react-bootstrap@>=0.28.1 <0.29.0", + "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-0.28.5.tgz", + "dependencies": { + "babel-runtime": { + "version": "5.8.38", + "from": "babel-runtime@>=5.8.25 <6.0.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-5.8.38.tgz", + "dependencies": { + "core-js": { + "version": "1.2.6", + "from": "core-js@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.6.tgz" + } + } + }, + "classnames": { + "version": "2.2.3", + "from": "classnames@>=2.1.5 <3.0.0", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.3.tgz" + }, + "dom-helpers": { + "version": "2.4.0", + "from": "dom-helpers@>=2.4.0 <3.0.0", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-2.4.0.tgz" + }, + "invariant": { + "version": "2.2.1", + "from": "invariant@>=2.1.2 <3.0.0", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.1.tgz", + "dependencies": { + "loose-envify": { + "version": "1.1.0", + "from": "loose-envify@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.1.0.tgz", + "dependencies": { + "js-tokens": { + "version": "1.0.3", + "from": "js-tokens@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-1.0.3.tgz" + } + } + } + } + }, + "keycode": { + "version": "2.1.1", + "from": "keycode@>=2.1.0 <3.0.0", + "resolved": "https://registry.npmjs.org/keycode/-/keycode-2.1.1.tgz" + }, + "lodash-compat": { + "version": "3.10.2", + "from": "lodash-compat@>=3.10.1 <4.0.0", + "resolved": "https://registry.npmjs.org/lodash-compat/-/lodash-compat-3.10.2.tgz" + }, + "react-overlays": { + "version": "0.6.3", + "from": "react-overlays@>=0.6.0 <0.7.0", + "resolved": "https://registry.npmjs.org/react-overlays/-/react-overlays-0.6.3.tgz", + "dependencies": { + "react-prop-types": { + "version": "0.2.2", + "from": "react-prop-types@>=0.2.1 <0.3.0", + "resolved": "https://registry.npmjs.org/react-prop-types/-/react-prop-types-0.2.2.tgz" + } + } + }, + "react-prop-types": { + "version": "0.3.0", + "from": "react-prop-types@>=0.3.0 <0.4.0", + "resolved": "https://registry.npmjs.org/react-prop-types/-/react-prop-types-0.3.0.tgz" + }, + "uncontrollable": { + "version": "3.2.3", + "from": "uncontrollable@>=3.1.3 <4.0.0", + "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-3.2.3.tgz" + }, + "warning": { + "version": "2.1.0", + "from": "warning@>=2.1.0 <3.0.0", + "resolved": "https://registry.npmjs.org/warning/-/warning-2.1.0.tgz", + "dependencies": { + "loose-envify": { + "version": "1.1.0", + "from": "loose-envify@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.1.0.tgz", + "dependencies": { + "js-tokens": { + "version": "1.0.3", + "from": "js-tokens@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-1.0.3.tgz" + } + } + } + } + } + } + }, + "react-dom": { + "version": "0.14.8", + "from": "react-dom@>=0.14.0 <0.15.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-0.14.8.tgz" + } + } +} + + +test('setup', function (t) { + setup() + t.end() +}) + +test('An npm install with shrinkwrap equals npm ls --json', function (t) { + common.npm( + [ + '--loglevel', 'silent', + 'install' + ], + EXEC_OPTS, + function (err, code) { + t.ifError(err, 'npm install ran without issue') + t.notOk(code, 'npm install exited with code 0') + common.npm( + [ + '--loglevel', 'silent', + 'ls', '--json' + ], + EXEC_OPTS, + function (err, code, out) { + t.ifError(err, 'npm ls --json ran without issue') + t.notOk(code, 'npm ls --json exited with code 0') + var actual = common.rmFromInShrinkwrap(JSON.parse(out)) + var expected = common.rmFromInShrinkwrap( + JSON.parse(JSON.stringify(shrinkwrap)) + ) + t.deepEqual(actual, expected) + t.end() + }) + } + ) +}) + +test('cleanup', function (t) { + cleanup() + t.end() +}) + +function cleanup () { + process.chdir(__dirname) + rimraf.sync(pkg) +} + +function setup () { + cleanup() + mkdirp.sync(pkg) + process.chdir(pkg) + fs.writeFileSync( + 'package.json', + JSON.stringify(json, null, 2) + ) + fs.writeFileSync( + 'npm-shrinkwrap.json', + JSON.stringify(shrinkwrap, null, 2) + ) +} diff --git a/deps/npm/test/tap/legacy-shrinkwrap.js b/deps/npm/test/tap/legacy-shrinkwrap.js index 6f5303037707a0..2c51bf1e3b8669 100644 --- a/deps/npm/test/tap/legacy-shrinkwrap.js +++ b/deps/npm/test/tap/legacy-shrinkwrap.js @@ -100,21 +100,12 @@ test('shrinkwrap', function (t) { var actual = JSON.parse(stdout) var expected = require(path.resolve(basepath, 'npm-shrinkwrap.json')) // from is expected to vary - t.isDeeply(rmFrom(actual), rmFrom(expected)) + t.isDeeply( + common.rmFromInShrinkwrap(actual), + common.rmFromInShrinkwrap(expected) + ) t.done() } - - function rmFrom (obj) { - for (var i in obj) { - if (i === 'from') { - delete obj[i] - } else if (i === 'dependencies') { - for (var j in obj[i]) { - rmFrom(obj[i][j]) - } - } - } - } }) test('cleanup', function (t) { diff --git a/deps/v8/src/arm64/lithium-codegen-arm64.cc b/deps/v8/src/arm64/lithium-codegen-arm64.cc index 074926b83b7700..fb17397fd4db2e 100644 --- a/deps/v8/src/arm64/lithium-codegen-arm64.cc +++ b/deps/v8/src/arm64/lithium-codegen-arm64.cc @@ -2801,6 +2801,8 @@ void LCodeGen::DoDoubleToIntOrSmi(LDoubleToIntOrSmi* instr) { void LCodeGen::DoDrop(LDrop* instr) { __ Drop(instr->count()); + + RecordPushedArgumentsDelta(instr->hydrogen_value()->argument_delta()); } diff --git a/deps/v8/test/mjsunit/regress/regress-arm64-spillslots.js b/deps/v8/test/mjsunit/regress/regress-arm64-spillslots.js new file mode 100644 index 00000000000000..1791b248431186 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-arm64-spillslots.js @@ -0,0 +1,34 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax + +"use strict"; + +function Message(message) { + this.message = message; +} + +function Inlined(input) { + var dummy = arguments[1] === undefined; + if (input instanceof Message) { + return input; + } + print("unreachable, but we must create register allocation complexity"); + return []; +} + +function Process(input) { + var ret = []; + ret.push(Inlined(input[0], 1, 2)); + return ret; +} + +var input = [new Message("TEST PASS")]; + +Process(input); +Process(input); +%OptimizeFunctionOnNextCall(Process); +var result = Process(input); +assertEquals("TEST PASS", result[0].message); diff --git a/deps/v8/tools/gen-postmortem-metadata.py b/deps/v8/tools/gen-postmortem-metadata.py index 0f90b26698ed4b..0bd7952894e698 100644 --- a/deps/v8/tools/gen-postmortem-metadata.py +++ b/deps/v8/tools/gen-postmortem-metadata.py @@ -224,6 +224,20 @@ } ''' +# +# Get the base class +# +def get_base_class(klass): + if (klass == 'Object'): + return klass; + + if (not (klass in klasses)): + return None; + + k = klasses[klass]; + + return get_base_class(k['parent']); + # # Loads class hierarchy and type information from "objects.h". # @@ -262,12 +276,14 @@ def load_objects(): typestr += line; continue; - match = re.match('class (\w[^\s:]*)(: public (\w[^\s{]*))?\s*{', + match = re.match('class (\w[^:]*)(: public (\w[^{]*))?\s*{\s*', line); if (match): - klass = match.group(1); + klass = match.group(1).rstrip().lstrip(); pklass = match.group(3); + if (pklass): + pklass = pklass.rstrip().lstrip(); klasses[klass] = { 'parent': pklass }; # @@ -518,6 +534,9 @@ def emit_config(): keys.sort(); for klassname in keys: pklass = klasses[klassname]['parent']; + bklass = get_base_class(klassname); + if (bklass != 'Object'): + continue; if (pklass == None): continue; diff --git a/doc/api/_toc.markdown b/doc/api/_toc.markdown index 5c8fbdd7901e20..2527ad84e2e360 100644 --- a/doc/api/_toc.markdown +++ b/doc/api/_toc.markdown @@ -1,7 +1,10 @@ @// NB(chrisdickinson): if you move this file, be sure to update tools/doc/html.js to @// point at the new location. * [About these Docs](documentation.html) -* [Synopsis](synopsis.html) +* [Usage & Example](synopsis.html) + +
    + * [Assertion Testing](assert.html) * [Buffer](buffer.html) * [C/C++ Addons](addons.html) @@ -39,3 +42,8 @@ * [V8](v8.html) * [VM](vm.html) * [ZLIB](zlib.html) + +
    + +* [GitHub Repo & Issue Tracker](https://github.com/nodejs/node) +* [Mailing List](http://groups.google.com/group/nodejs) diff --git a/doc/api/buffer.markdown b/doc/api/buffer.markdown index 4e6cdd546d88a9..2a0b45d0e46a03 100644 --- a/doc/api/buffer.markdown +++ b/doc/api/buffer.markdown @@ -18,7 +18,7 @@ The size of the `Buffer` is established when it is created and cannot be resized. The `Buffer` class is a global within Node.js, making it unlikely that one -would need to ever use `require('buffer')`. +would need to ever use `require('buffer').Buffer`. ```js const buf1 = new Buffer(10); @@ -799,8 +799,8 @@ buf.readUInt8(1); * Return: {Number} Reads an unsigned 16-bit integer from the Buffer at the specified `offset` with -specified endian format (`readInt32BE()` returns big endian, -`readInt32LE()` returns little endian). +specified endian format (`readUInt16BE()` returns big endian, +`readUInt16LE()` returns little endian). Setting `noAssert` to `true` skips validation of the `offset`. This allows the `offset` to be beyond the end of the Buffer. @@ -832,8 +832,8 @@ buf.readUInt16LE(2); * Return: {Number} Reads an unsigned 32-bit integer from the Buffer at the specified `offset` with -specified endian format (`readInt32BE()` returns big endian, -`readInt32LE()` returns little endian). +specified endian format (`readUInt32BE()` returns big endian, +`readUInt32LE()` returns little endian). Setting `noAssert` to `true` skips validation of the `offset`. This allows the `offset` to be beyond the end of the Buffer. diff --git a/doc/api/child_process.markdown b/doc/api/child_process.markdown index a7d7a55d8106e1..cc8b8ce8c67b97 100644 --- a/doc/api/child_process.markdown +++ b/doc/api/child_process.markdown @@ -139,13 +139,13 @@ generated output. ```js const exec = require('child_process').exec; -const child = exec('cat *.js bad_file | wc -l', - (error, stdout, stderr) => { - console.log(`stdout: ${stdout}`); - console.log(`stderr: ${stderr}`); - if (error !== null) { - console.log(`exec error: ${error}`); - } +exec('cat *.js bad_file | wc -l', (error, stdout, stderr) => { + if (error) { + console.error(`exec error: ${error}`); + return; + } + console.log(`stdout: ${stdout}`); + console.log(`stderr: ${stderr}`); }); ``` diff --git a/doc/api/cluster.markdown b/doc/api/cluster.markdown index b14c3aaf2bfc83..4c25d58516d309 100644 --- a/doc/api/cluster.markdown +++ b/doc/api/cluster.markdown @@ -140,9 +140,9 @@ Similar to the `cluster.on('exit')` event, but specific to this worker. ```js const worker = cluster.fork(); worker.on('exit', (code, signal) => { - if( signal ) { + if (signal) { console.log(`worker was killed by signal: ${signal}`); - } else if( code !== 0 ) { + } else if (code !== 0) { console.log(`worker exited with error code: ${code}`); } else { console.log('worker success!'); @@ -285,7 +285,7 @@ if (cluster.isMaster) { server.listen(8000); process.on('message', (msg) => { - if(msg === 'shutdown') { + if (msg === 'shutdown') { // initiate graceful close of any connections to server } }); @@ -485,8 +485,8 @@ The `addressType` is one of: ## Event: 'message' -* `worker` {cluster.Worker} * `message` {Object} +* `handle` {undefined|Object} Emitted when any worker receives a message. diff --git a/doc/api/crypto.markdown b/doc/api/crypto.markdown index 3b103bdeaa4241..f0d21238be3670 100644 --- a/doc/api/crypto.markdown +++ b/doc/api/crypto.markdown @@ -719,7 +719,7 @@ console.log(sign.sign(private_key, 'hex')); // Prints the calculated signature ``` -A [`sign`][] instance can also be created by just passing in the digest +A `Sign` instance can also be created by just passing in the digest algorithm name, in which case OpenSSL will infer the full signature algorithm from the type of the PEM-formatted private key, including algorithms that do not have directly exposed name constants, e.g. 'ecdsa-with-SHA256'. diff --git a/doc/api/debugger.markdown b/doc/api/debugger.markdown index bbde4f0f4b3753..2bbaf9049eb5fb 100644 --- a/doc/api/debugger.markdown +++ b/doc/api/debugger.markdown @@ -152,6 +152,7 @@ after) * `watchers` - List all watchers and their values (automatically listed on each breakpoint) * `repl` - Open debugger's repl for evaluation in debugging script's context +* `exec expr` - Execute an expression in debugging script's context ### Execution control diff --git a/doc/api/documentation.markdown b/doc/api/documentation.markdown index 4d357e39efab37..2922c011f5845c 100644 --- a/doc/api/documentation.markdown +++ b/doc/api/documentation.markdown @@ -21,7 +21,7 @@ documentation is generated using the `tools/doc/generate.js` program. The HTML template is located at `doc/template.html`. -If you find a error in this documentation, please [submit an issue][] +If you find an error in this documentation, please [submit an issue][] or see [the contributing guide][] for directions on how to submit a patch. ## Stability Index diff --git a/doc/api/errors.markdown b/doc/api/errors.markdown index efb469ec46f05d..8f5a0abf3321df 100644 --- a/doc/api/errors.markdown +++ b/doc/api/errors.markdown @@ -231,7 +231,7 @@ function MyError() { } // Without passing MyError to captureStackTrace, the MyError -// frame would should up in the .stack property. by passing +// frame would show up in the .stack property. By passing // the constructor, we omit that frame and all frames above it. new MyError().stack ``` diff --git a/doc/api/events.markdown b/doc/api/events.markdown index 500d046f9e59f7..464a0f61570113 100644 --- a/doc/api/events.markdown +++ b/doc/api/events.markdown @@ -130,7 +130,7 @@ myEmitter.emit('event'); ``` Using the `eventEmitter.once()` method, it is possible to register a listener -that is immediately unregistered after it is called. +that is unregistered before it is called. ```js const myEmitter = new MyEmitter(); @@ -338,9 +338,8 @@ Returns a reference to the `EventEmitter` so calls can be chained. ### emitter.once(eventName, listener) -Adds a **one time** `listener` function for the event named `eventName`. This -listener is invoked only the next time `eventName` is triggered, after which -it is removed. +Adds a **one time** `listener` function for the event named `eventName`. The +next time `eventName` is triggered, this listener is removed and then invoked. ```js server.once('connection', (stream) => { diff --git a/doc/api/fs.markdown b/doc/api/fs.markdown index 87e7fcaa365a29..ed87141c07cc2d 100644 --- a/doc/api/fs.markdown +++ b/doc/api/fs.markdown @@ -438,8 +438,8 @@ Synchronous fdatasync(2). Returns `undefined`. ## fs.fstat(fd, callback) Asynchronous fstat(2). The callback gets two arguments `(err, stats)` where -`stats` is a `fs.Stats` object. `fstat()` is identical to [`stat()`][], except that -the file to be stat-ed is specified by the file descriptor `fd`. +`stats` is a [`fs.Stats`][] object. `fstat()` is identical to [`stat()`][], +except that the file to be stat-ed is specified by the file descriptor `fd`. ## fs.fstatSync(fd) @@ -504,9 +504,9 @@ Synchronous link(2). Returns `undefined`. ## fs.lstat(path, callback) Asynchronous lstat(2). The callback gets two arguments `(err, stats)` where -`stats` is a `fs.Stats` object. `lstat()` is identical to `stat()`, except that if -`path` is a symbolic link, then the link itself is stat-ed, not the file that it -refers to. +`stats` is a [`fs.Stats`][] object. `lstat()` is identical to `stat()`, +except that if `path` is a symbolic link, then the link itself is stat-ed, +not the file that it refers to. ## fs.lstatSync(path) @@ -823,9 +823,10 @@ to be notified of filesystem changes. * On Windows systems, this feature depends on `ReadDirectoryChangesW`. If the underlying functionality is not available for some reason, then -`fs.watch` will not be able to function. For example, watching files or -directories on network file systems (NFS, SMB, etc.) often doesn't work -reliably or at all. +`fs.watch` will not be able to function. For example, watching files or +directories can be unreliable, and in some cases impossible, on network file +systems (NFS, SMB, etc), or host file systems when using virtualization software +such as Vagrant, Docker, etc. You can still use `fs.watchFile`, which uses stat polling, but it is slower and less reliable. diff --git a/doc/api/globals.markdown b/doc/api/globals.markdown index 643ab4334b20a6..f70c52aae4904e 100644 --- a/doc/api/globals.markdown +++ b/doc/api/globals.markdown @@ -5,6 +5,10 @@ These objects are available in all modules. Some of these objects aren't actually in the global scope but in the module scope - this will be noted. +The objects listed here are specific to Node.js. There are a number of +[built-in objects][] that are part of the JavaScript language itself, which are +also globally accessible. + ## Class: Buffer @@ -38,7 +42,7 @@ For instance, given two modules: `a` and `b`, where `b` is a dependency of References to `__dirname` within `b.js` will return `/Users/mjr/app/node_modules/b` while references to `__dirname` within `a.js` -will return `/Users/mj/app`. +will return `/Users/mjr/app`. ## \_\_filename @@ -209,3 +213,4 @@ but rather than loading the module, just return the resolved filename. [`setImmediate`]: timers.html#timers_setimmediate_callback_arg [`setInterval`]: timers.html#timers_setinterval_callback_delay_arg [`setTimeout`]: timers.html#timers_settimeout_callback_delay_arg +[built-in objects]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects diff --git a/doc/api/modules.markdown b/doc/api/modules.markdown index 20c8b175cd9340..836285b26f491d 100644 --- a/doc/api/modules.markdown +++ b/doc/api/modules.markdown @@ -30,8 +30,9 @@ The module `circle.js` has exported the functions `area()` and `circumference()`. To add functions and objects to the root of your module, you can add them to the special `exports` object. -Variables local to the module will be private, as though the module was wrapped -in a function. In this example the variable `PI` is private to `circle.js`. +Variables local to the module will be private, because the module is wrapped +in a function by Node.js (see [module wrapper](#modules_the_module_wrapper)). +In this example, the variable `PI` is private to `circle.js`. If you want the root of your module's export to be a function (such as a constructor) or if you want to export a complete object in one assignment @@ -425,6 +426,30 @@ These are mostly for historic reasons. **You are highly encouraged to place your dependencies locally in `node_modules` folders.** They will be loaded faster, and more reliably. +## The module wrapper + + + +Before a module's code is executed, Node.js will wrap it with a function +wrapper that looks like the following: + +```js +(function (exports, require, module, __filename, __dirname) { +// Your module code actually lives in here +}); +``` + +By doing this, Node.js achieves a few things: + +- It keeps top-level variables (defined with `var`, `const` or `let`) scoped to +the module rather than the global object. +- It helps to provide some global-looking variables that are actually specific +to the module, such as: + - The `module` and `exports` objects that the implementor can use to export + values from the module. + - The convenience variables `__filename` and `__dirname`, containing the + module's absolute filename and directory path. + ## The `module` Object diff --git a/doc/api/repl.markdown b/doc/api/repl.markdown index 2b61e5da38e1f9..a6d78b61d446b8 100644 --- a/doc/api/repl.markdown +++ b/doc/api/repl.markdown @@ -13,7 +13,7 @@ dropped into the REPL. It has simplistic emacs line-editing. ``` $ node Type '.help' for options. -> a = [ 1, 2, 3]; +> a = [1, 2, 3]; [ 1, 2, 3 ] > a.forEach((v) => { ... console.log(v); diff --git a/doc/api/synopsis.markdown b/doc/api/synopsis.markdown index 7dd3b8fe99d7fd..134c0dbed7286e 100644 --- a/doc/api/synopsis.markdown +++ b/doc/api/synopsis.markdown @@ -1,29 +1,43 @@ -# Synopsis +# Usage +`node [options] [v8 options] [script.js | -e "script"] [arguments]` + +Please see the [Command Line Options][] document for information about +different options and ways to run scripts with Node. + +## Example + An example of a [web server][] written with Node.js which responds with `'Hello World'`: ```js const http = require('http'); -http.createServer( (request, response) => { - response.writeHead(200, {'Content-Type': 'text/plain'}); - response.end('Hello World\n'); -}).listen(8124); +const hostname = '127.0.0.1'; +const port = 3000; + +const server = http.createServer((req, res) => { + res.statusCode = 200; + res.setHeader('Content-Type', 'text/plain'); + res.end('Hello World\n'); +}); -console.log('Server running at http://127.0.0.1:8124/'); +server.listen(port, hostname, () => { + console.log(`Server running at http://${hostname}:${port}/`); +}); ``` To run the server, put the code into a file called `example.js` and execute -it with the node program +it with Node.js: ``` $ node example.js -Server running at http://127.0.0.1:8124/ +Server running at http://127.0.0.1:3000/ ``` All of the examples in the documentation can be run similarly. +[Command Line Options]: cli.html#cli_command_line_options [web server]: http.html diff --git a/doc/api_assets/style.css b/doc/api_assets/style.css index 0024035ca171bd..a8e4b32611164b 100644 --- a/doc/api_assets/style.css +++ b/doc/api_assets/style.css @@ -50,35 +50,6 @@ em code { font-style: normal; } -::-webkit-scrollbar { - -webkit-appearance: none; -} - -::-webkit-scrollbar-button { - display: none; -} - -::-webkit-scrollbar-track { - background: #fff; -} - -::-webkit-scrollbar-thumb { - min-height: 48px; - background: #d2d2d2; - background-clip: padding-box; - border: 3px solid #fff; - border-radius: 5px; -} - -::-webkit-scrollbar-thumb:active { - background: #888; - border-width: 2px; -} - -::-webkit-scrollbar { - width: 10px; -} - #changelog #gtoc { display: none; } @@ -87,6 +58,12 @@ em code { font-size: .8em; } +.line { + width: calc(100% - 1em); + display: block; + padding-bottom: 1px; +} + .api_stability { color: white !important; margin: 0 0 1em 0; @@ -202,6 +179,12 @@ header h1 { padding-top: 1em; } +#apicontent .line { + width: calc(50% - 1em); + margin: 1em 1em .95em; + background-color: #ccc; +} + #toc + h1 { margin-top: 1em; padding-top: 0; @@ -380,10 +363,22 @@ a code { #column2 ul { list-style: none; - margin: 1.25em 0; + margin: .9em 0 .5em; background: #333; } +#column2 > :first-child { + margin: 1.25em 1em; +} + +#column2 > ul:nth-child(2) { + margin: 1.25em 0 .5em; +} + +#column2 > ul:last-child { + margin: .9em 0 1.25em; +} + #column2 ul li { padding-left: 1.4em; margin-bottom: .5em; @@ -391,6 +386,11 @@ a code { font-size: .8em; } +#column2 .line { + margin: 0 .5em; + background-color: #707070; +} + #column2 ul li:last-child { margin-bottom: 0; } @@ -467,3 +467,16 @@ th > *:last-child, td > *:last-child { font-size: 3.5em; } } + +@media print { + html { + height: auto; + } + #column2.interior { + display: none; + } + #column1.interior { + margin-left: auto; + overflow-y: auto; + } +} diff --git a/doc/node.1 b/doc/node.1 index 9835af74a8f40c..0382a095db6d77 100644 --- a/doc/node.1 +++ b/doc/node.1 @@ -59,7 +59,7 @@ Syntax check the script without executing. .TP .BR \-i ", " \-\-interactive -Opens the REPL even if stdin does not appear to be a terminal. +Open the REPL even if stdin does not appear to be a terminal. .TP .BR \-r ", " \-\-require " " \fImodule\fR @@ -80,7 +80,7 @@ Throw errors for deprecations. .TP .BR \-\-trace\-sync\-io -Prints a stack trace whenever synchronous I/O is detected after the first turn +Print a stack trace whenever synchronous I/O is detected after the first turn of the event loop. .TP diff --git a/doc/onboarding-extras.md b/doc/onboarding-extras.md index 2f35e2778c3a2c..55db6107350951 100644 --- a/doc/onboarding-extras.md +++ b/doc/onboarding-extras.md @@ -1,26 +1,24 @@ ## Who to CC in issues -* `lib/buffer`: @trevnorris -* `lib/child_process`: @cjihrig, @bnoordhuis, @piscisaereus -* `lib/cluster`: @cjihrig, @bnoordhuis, @piscisaereus -* `lib/{crypto,tls,https}`: @indutny, @shigeki, @nodejs/crypto -* `lib/domains`: @misterdjules -* `lib/{_}http{*}`: @indutny, @bnoordhuis, @nodejs/http -* `lib/net`: @indutny, @bnoordhuis, @piscisaereus, @chrisdickinson, @nodejs/streams -* `lib/{_}stream{s|*}`: @nodejs/streams -* `lib/repl`: @fishrock123 -* `lib/timers`: @fishrock123, @misterdjules -* `lib/zlib`: @indutny, @bnoordhuis - -* `src/async-wrap.*`: @trevnorris -* `src/node_crypto.*`: @indutny, @shigeki, @nodejs/crypto - -* `test/*`: @nodejs/testing, @trott - -* `tools/eslint`, `.eslintrc`: @silverwind, @trott - -* upgrading v8: @bnoordhuis / @targos / @ofrobots -* upgrading npm: @thealphanerd, @fishrock123 +| subsystem | maintainers | +| --- | --- | +| `lib/buffer` | @trevnorris | +| `lib/child_process` | @cjihrig, @bnoordhuis | +| `lib/cluster` | @cjihrig, @bnoordhuis | +| `lib/{crypto,tls,https}` | @nodejs/crypto | +| `lib/domains` | @misterdjules | +| `lib/{_}http{*}` | @indutny, @bnoordhuis, @mscdex, @nodejs/http | +| `lib/net` | @indutny, @bnoordhuis, @nodejs/streams | +| `lib/{_}stream{s|*}` | @nodejs/streams | +| `lib/repl` | @fishrock123 | +| `lib/timers` | @fishrock123, @misterdjules | +| `lib/zlib` | @indutny, @bnoordhuis | +| `src/async-wrap.*` | @trevnorris | +| `src/node_crypto.*` | @nodejs/crypto | +| `test/*` | @nodejs/testing | +| `tools/eslint`, `.eslintrc` | @silverwind, @trott | +| upgrading v8 | @bnoordhuis, @targos, @ofrobots | +| upgrading npm | @thealphanerd, @fishrock123 | When things need extra attention, are controversial, or `semver-major`: @nodejs/ctc @@ -52,6 +50,8 @@ Please use these when possible / appropriate * `feature request` - Any issue that requests a new feature (usually not PRs) * `good first contribution` - Issues suitable for newcomers to process +-- + * `semver-{minor,major}` * be conservative – that is, if a change has the remote *chance* of breaking something, go for semver-major * when adding a semver label, add a comment explaining why you're adding it @@ -94,7 +94,7 @@ to update from nodejs/node: * prefer to make the originating user update the code, since they have it fresh in mind * first, reattempt with `git am -3` (3-way merge)` * if `-3` still fails, and you need to get it merged: - * `git fetch origin pull/N/head:pr-N && git checkout pr-N && git rebase master` + * `git fetch upstream pull/N/head:pr-N && git checkout pr-N && git rebase master` ## best practices diff --git a/doc/releases.md b/doc/releases.md index 512deb34acf84d..b7e00683693027 100644 --- a/doc/releases.md +++ b/doc/releases.md @@ -127,7 +127,7 @@ See https://github.com/nodejs/node/labels/confirmed-bug for complete and current * Include the full list of commits since the last release here. Do not include "Working on X.Y.Z+1" commits. ``` -The release type should be either Stable, LTS, or Maintenance, depending on the type of release being produced. +The release type should be either Current, LTS, or Maintenance, depending on the type of release being produced. ### 4. Create Release Commit @@ -187,7 +187,7 @@ Jenkins collects the artifacts from the builds, allowing you to download and ins Once you have produced builds that you're happy with, create a new tag. By waiting until this stage to create tags, you can discard a proposed release if something goes wrong or additional commits are required. Once you have created a tag and pushed it to GitHub, you ***should not*** delete and re-tag. If you make a mistake after tagging then you'll have to version-bump and start again and count that tag/version as lost. -Tag summaries have a predictable format, look at a recent tag to see, `git tag -v v5.3.0`. The message should look something like `2015-12-16 Node.js v5.3.0 (Stable) Release`. +Tag summaries have a predictable format, look at a recent tag to see, `git tag -v v6.0.0`. The message should look something like `2016-04-26 Node.js v6.0.0 (Current) Release`. Create a tag using the following command: diff --git a/doc/template.html b/doc/template.html index dec3f50670226e..71e3a21e1d4d5c 100644 --- a/doc/template.html +++ b/doc/template.html @@ -13,7 +13,7 @@
    __GTOC__ diff --git a/doc/topics/the-event-loop-timers-and-nexttick.md b/doc/topics/the-event-loop-timers-and-nexttick.md index 2676b94da37ef4..ebb46a0b1f22d9 100644 --- a/doc/topics/the-event-loop-timers-and-nexttick.md +++ b/doc/topics/the-event-loop-timers-and-nexttick.md @@ -170,7 +170,7 @@ through its queue of callbacks executing them synchronously until either the queue has been exhausted, or the system-dependent hard limit is reached. -* _If the `poll` queue is **empty**, one of two more things will +* _If the `poll` queue **is empty**_, one of two more things will happen: * If scripts have been scheduled by `setImmediate()`, the event loop will end the `poll` phase and continue to the `check` phase to @@ -218,15 +218,15 @@ ways depending on when they are called. * `setTimeout()` schedules a script to be run after a minimum threshold in ms has elapsed. -The order in which they are execute varies depending on the context in -which they are called. If both are called in the main module then you -are bound to how fast your process go, which is impacted by other -programs running on your machine. +The order in which the timers are executed will vary depending on the +context in which they are called. If both are called from within the +main module, then timing will be bound by the performance of the process +(which can be impacted by other applications running on the machine). -For example, if we run the following script which is not within a I/O -cycle (i.e. the main module), the order in which the two functions are -executed is non-deterministic as it is based upon how fast your process -goes (which is impacted by other programs running on your machine): +For example, if we run the following script which is not within an I/O +cycle (i.e. the main module), the order in which the two timers are +executed is non-deterministic, as it is bound by the performance of the +process: ```js diff --git a/lib/_debugger.js b/lib/_debugger.js index 2bb9b7834cd654..411db79d087798 100644 --- a/lib/_debugger.js +++ b/lib/_debugger.js @@ -142,7 +142,7 @@ Protocol.prototype.serialize = function(req) { const NO_FRAME = -1; function Client() { - net.Stream.call(this); + net.Socket.call(this); var protocol = this.protocol = new Protocol(this); this._reqCallbacks = []; var socket = this; @@ -161,7 +161,7 @@ function Client() { protocol.onResponse = (res) => this._onResponse(res); } -inherits(Client, net.Stream); +inherits(Client, net.Socket); exports.Client = Client; @@ -547,8 +547,8 @@ Client.prototype.mirrorObject = function(handle, depth, cb) { mirrorValue = '[?]'; } - if (Array.isArray(mirror) && typeof prop.name !== 'number') { - // Skip the 'length' property. + // Skip the 'length' property. + if (Array.isArray(mirror) && prop.name === 'length') { return; } @@ -657,6 +657,7 @@ const commands = [ 'unwatch', 'watchers', 'repl', + 'exec', 'restart', 'kill', 'list', @@ -949,6 +950,12 @@ Interface.prototype.controlEval = function(code, context, filename, callback) { } } + // exec process.title => exec("process.title"); + var match = code.match(/^\s*exec\s+([^\n]*)/); + if (match) { + code = 'exec(' + JSON.stringify(match[1]) + ')'; + } + var result = vm.runInContext(code, context, filename); // Repl should not ask for next command @@ -1521,6 +1528,18 @@ Interface.prototype.pause_ = function() { }; +// execute expression +Interface.prototype.exec = function(code) { + this.debugEval(code, null, null, (err, result) => { + if (err) { + this.error(err); + } else { + this.print(util.inspect(result, {colors: true})); + } + }); +}; + + // Kill child process Interface.prototype.kill = function() { if (!this.child) return; @@ -1726,11 +1745,12 @@ Interface.prototype.trySpawn = function(cb) { client.connect(port, host); } - self.print('connecting to ' + host + ':' + port + ' ..', true); if (isRemote) { + self.print('connecting to ' + host + ':' + port + ' ..', true); attemptConnect(); } else { this.child.stderr.once('data', function() { + self.print('connecting to ' + host + ':' + port + ' ..', true); setImmediate(attemptConnect); }); } diff --git a/lib/_http_common.js b/lib/_http_common.js index 328b6eea8affba..08f93d8c4d04a2 100644 --- a/lib/_http_common.js +++ b/lib/_http_common.js @@ -225,10 +225,56 @@ exports.httpSocketSetup = httpSocketSetup; /** * Verifies that the given val is a valid HTTP token * per the rules defined in RFC 7230 + * See https://tools.ietf.org/html/rfc7230#section-3.2.6 + * + * This implementation of checkIsHttpToken() loops over the string instead of + * using a regular expression since the former is up to 180% faster with v8 4.9 + * depending on the string length (the shorter the string, the larger the + * performance difference) **/ -const token = /^[a-zA-Z0-9_!#$%&'*+.^`|~-]+$/; function checkIsHttpToken(val) { - return typeof val === 'string' && token.test(val); + if (typeof val !== 'string' || val.length === 0) + return false; + + for (var i = 0, len = val.length; i < len; i++) { + var ch = val.charCodeAt(i); + + if (ch >= 65 && ch <= 90) // A-Z + continue; + + if (ch >= 97 && ch <= 122) // a-z + continue; + + // ^ => 94 + // _ => 95 + // ` => 96 + // | => 124 + // ~ => 126 + if (ch === 94 || ch === 95 || ch === 96 || ch === 124 || ch === 126) + continue; + + if (ch >= 48 && ch <= 57) // 0-9 + continue; + + // ! => 33 + // # => 35 + // $ => 36 + // % => 37 + // & => 38 + // ' => 39 + // * => 42 + // + => 43 + // - => 45 + // . => 46 + if (ch >= 33 && ch <= 46) { + if (ch === 34 || ch === 40 || ch === 41 || ch === 44) + return false; + continue; + } + + return false; + } + return true; } exports._checkIsHttpToken = checkIsHttpToken; diff --git a/lib/_stream_readable.js b/lib/_stream_readable.js index 3588b828dc40c8..c9beafa9bee8e7 100644 --- a/lib/_stream_readable.js +++ b/lib/_stream_readable.js @@ -530,11 +530,17 @@ Readable.prototype.pipe = function(dest, pipeOpts) { ondrain(); } + // If the user pushes more data while we're writing to dest then we'll end up + // in ondata again. However, we only want to increase awaitDrain once because + // dest will only emit one 'drain' event for the multiple writes. + // => Introduce a guard on increasing awaitDrain. + var increasedAwaitDrain = false; src.on('data', ondata); function ondata(chunk) { debug('ondata'); + increasedAwaitDrain = false; var ret = dest.write(chunk); - if (false === ret) { + if (false === ret && !increasedAwaitDrain) { // If the user unpiped during `dest.write()`, it is possible // to get stuck in a permanently paused state if that write // also returned false. @@ -544,6 +550,7 @@ Readable.prototype.pipe = function(dest, pipeOpts) { !cleanedUp) { debug('false write response, pause', src._readableState.awaitDrain); src._readableState.awaitDrain++; + increasedAwaitDrain = true; } src.pause(); } @@ -727,6 +734,7 @@ function resume_(stream, state) { } state.resumeScheduled = false; + state.awaitDrain = 0; stream.emit('resume'); flow(stream); if (state.flowing && !state.reading) diff --git a/lib/buffer.js b/lib/buffer.js index eff91be2882630..3fe08c81b91ebf 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -263,6 +263,7 @@ function byteLength(string, encoding) { case 'ascii': case 'binary': // Deprecated + // eslint-disable-next-line no-fallthrough case 'raw': case 'raws': return len; diff --git a/lib/child_process.js b/lib/child_process.js index ddbb0448d90c20..dda613afdeeec6 100644 --- a/lib/child_process.js +++ b/lib/child_process.js @@ -458,9 +458,10 @@ function checkExecSyncError(ret) { ret.error = null; if (!err) { - var msg = 'Command failed: ' + - (ret.cmd ? ret.cmd : ret.args.join(' ')) + - (ret.stderr ? '\n' + ret.stderr.toString() : ''); + var msg = 'Command failed: '; + msg += ret.cmd || ret.args.join(' '); + if (ret.stderr) + msg += '\n' + ret.stderr.toString(); err = new Error(msg); } diff --git a/lib/internal/repl.js b/lib/internal/repl.js index 371446a83bd4fd..cea681f5837494 100644 --- a/lib/internal/repl.js +++ b/lib/internal/repl.js @@ -93,7 +93,10 @@ function setupHistory(repl, historyPath, oldHistoryPath, ready) { var writing = false; var pending = false; repl.pause(); - fs.open(historyPath, 'a+', oninit); + // History files are conventionally not readable by others: + // https://github.com/nodejs/node/issues/3392 + // https://github.com/nodejs/node/pull/3394 + fs.open(historyPath, 'a+', 0o0600, oninit); function oninit(err, hnd) { if (err) { diff --git a/lib/net.js b/lib/net.js index 020f9bd4573f4d..c1de0384ea42a9 100644 --- a/lib/net.js +++ b/lib/net.js @@ -97,7 +97,6 @@ exports._normalizeConnectArgs = normalizeConnectArgs; // called when creating new Socket, or when re-using a closed Socket function initSocketHandle(self) { self.destroyed = false; - self.bytesRead = 0; self._bytesDispatched = 0; self._sockname = null; @@ -112,6 +111,10 @@ function initSocketHandle(self) { } } + +const BYTES_READ = Symbol('bytesRead'); + + function Socket(options) { if (!(this instanceof Socket)) return new Socket(options); @@ -179,6 +182,9 @@ function Socket(options) { // Reserve properties this.server = null; this._server = null; + + // Used after `.destroy()` + this[BYTES_READ] = 0; } util.inherits(Socket, stream.Duplex); @@ -472,6 +478,9 @@ Socket.prototype._destroy = function(exception, cb) { if (this !== process.stderr) debug('close handle'); var isException = exception ? true : false; + // `bytesRead` should be accessible after `.destroy()` + this[BYTES_READ] = this._handle.bytesRead; + this._handle.close(function() { debug('emit close'); self.emit('close', isException); @@ -523,10 +532,6 @@ function onread(nread, buffer) { // will prevent this from being called again until _read() gets // called again. - // if it's not enough data, we'll just call handle.readStart() - // again right away. - self.bytesRead += nread; - // Optimization: emit the original buffer with end points var ret = self.push(buffer); @@ -582,16 +587,27 @@ Socket.prototype._getpeername = function() { return this._peername; }; +function protoGetter(name, callback) { + Object.defineProperty(Socket.prototype, name, { + configurable: false, + enumerable: true, + get: callback + }); +} + +protoGetter('bytesRead', function bytesRead() { + return this._handle ? this._handle.bytesRead : this[BYTES_READ]; +}); -Socket.prototype.__defineGetter__('remoteAddress', function() { +protoGetter('remoteAddress', function remoteAddress() { return this._getpeername().address; }); -Socket.prototype.__defineGetter__('remoteFamily', function() { +protoGetter('remoteFamily', function remoteFamily() { return this._getpeername().family; }); -Socket.prototype.__defineGetter__('remotePort', function() { +protoGetter('remotePort', function remotePort() { return this._getpeername().port; }); @@ -610,12 +626,12 @@ Socket.prototype._getsockname = function() { }; -Socket.prototype.__defineGetter__('localAddress', function() { +protoGetter('localAddress', function localAddress() { return this._getsockname().address; }); -Socket.prototype.__defineGetter__('localPort', function() { +protoGetter('localPort', function localPort() { return this._getsockname().port; }); @@ -727,7 +743,7 @@ function createWriteReq(req, handle, data, encoding) { } -Socket.prototype.__defineGetter__('bytesWritten', function() { +protoGetter('bytesWritten', function bytesWritten() { var bytes = this._bytesDispatched; const state = this._writableState; const data = this._pendingData; diff --git a/lib/readline.js b/lib/readline.js index 74656896314531..2e799e21a3233a 100644 --- a/lib/readline.js +++ b/lib/readline.js @@ -977,6 +977,7 @@ exports.emitKeypressEvents = emitKeypressEvents; */ // Regexes used for ansi escape code splitting +// eslint-disable-next-line no-control-regex const metaKeyCodeReAnywhere = /(?:\x1b)([a-zA-Z0-9])/; const functionKeyCodeReAnywhere = new RegExp('(?:\x1b+)(O|N|\\[|\\[\\[)(?:' + [ '(\\d+)(?:;(\\d+))?([~^$])', diff --git a/lib/repl.js b/lib/repl.js index bff367929ff0a3..71377b1cc7582d 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -70,8 +70,8 @@ exports._builtinLibs = ['assert', 'buffer', 'child_process', 'cluster', 'string_decoder', 'tls', 'tty', 'url', 'util', 'v8', 'vm', 'zlib']; -const BLOCK_SCOPED_ERROR = 'Block-scoped declarations (let, ' + - 'const, function, class) not yet supported outside strict mode'; +const BLOCK_SCOPED_ERROR = 'Block-scoped declarations (let, const, function, ' + + 'class) not yet supported outside strict mode'; class LineParser { diff --git a/lib/util.js b/lib/util.js index 8cebbaa07516c2..c370d9509e1ca3 100644 --- a/lib/util.js +++ b/lib/util.js @@ -426,9 +426,12 @@ function formatPrimitive(ctx, value) { var type = typeof value; if (type === 'string') { - var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') - .replace(/'/g, "\\'") - .replace(/\\"/g, '"') + '\''; + var simple = '\'' + + JSON.stringify(value) + .replace(/^"|"$/g, '') + .replace(/'/g, "\\'") + .replace(/\\"/g, '"') + + '\''; return ctx.stylize(simple, 'string'); } if (type === 'number') { diff --git a/lib/zlib.js b/lib/zlib.js index 8cced1f88ff79d..6715ff11604920 100644 --- a/lib/zlib.js +++ b/lib/zlib.js @@ -6,8 +6,8 @@ const binding = process.binding('zlib'); const util = require('util'); const assert = require('assert').ok; const kMaxLength = require('buffer').kMaxLength; -const kRangeErrorMessage = 'Cannot create final Buffer. ' + - 'It would be larger than 0x' + kMaxLength.toString(16) + ' bytes.'; +const kRangeErrorMessage = 'Cannot create final Buffer. It would be larger ' + + 'than 0x' + kMaxLength.toString(16) + ' bytes.'; // zlib doesn't provide these, so kludge them in following the same // const naming scheme zlib uses. diff --git a/src/async-wrap-inl.h b/src/async-wrap-inl.h index 1d9ebe27e45bef..f2d2c3ecf1c7b4 100644 --- a/src/async-wrap-inl.h +++ b/src/async-wrap-inl.h @@ -49,7 +49,7 @@ inline AsyncWrap::AsyncWrap(Environment* env, argv[2] = parent->object(); v8::MaybeLocal ret = - init_fn->Call(env->context(), object, ARRAY_SIZE(argv), argv); + init_fn->Call(env->context(), object, arraysize(argv), argv); if (ret.IsEmpty()) FatalError("node::AsyncWrap::AsyncWrap", "init hook threw"); diff --git a/src/cares_wrap.cc b/src/cares_wrap.cc index 66d5d08fe656fe..41b545468f55a8 100644 --- a/src/cares_wrap.cc +++ b/src/cares_wrap.cc @@ -310,7 +310,7 @@ class QueryWrap : public AsyncWrap { Integer::New(env()->isolate(), 0), answer }; - MakeCallback(env()->oncomplete_string(), ARRAY_SIZE(argv), argv); + MakeCallback(env()->oncomplete_string(), arraysize(argv), argv); } void CallOnComplete(Local answer, Local family) { @@ -321,7 +321,7 @@ class QueryWrap : public AsyncWrap { answer, family }; - MakeCallback(env()->oncomplete_string(), ARRAY_SIZE(argv), argv); + MakeCallback(env()->oncomplete_string(), arraysize(argv), argv); } void ParseError(int status) { @@ -994,7 +994,7 @@ void AfterGetAddrInfo(uv_getaddrinfo_t* req, int status, struct addrinfo* res) { uv_freeaddrinfo(res); // Make the callback into JavaScript - req_wrap->MakeCallback(env->oncomplete_string(), ARRAY_SIZE(argv), argv); + req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv); delete req_wrap; } @@ -1025,7 +1025,7 @@ void AfterGetNameInfo(uv_getnameinfo_t* req, } // Make the callback into JavaScript - req_wrap->MakeCallback(env->oncomplete_string(), ARRAY_SIZE(argv), argv); + req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv); delete req_wrap; } diff --git a/src/debug-agent.cc b/src/debug-agent.cc index 93d2ce71f11a38..df6e75d07ff38c 100644 --- a/src/debug-agent.cc +++ b/src/debug-agent.cc @@ -22,7 +22,7 @@ #include "debug-agent.h" #include "node.h" -#include "node_internals.h" // ARRAY_SIZE +#include "node_internals.h" // arraysize #include "env.h" #include "env-inl.h" #include "v8.h" @@ -175,9 +175,9 @@ void Agent::WorkerRun() { isolate, &child_loop_, context, - ARRAY_SIZE(argv), + arraysize(argv), argv, - ARRAY_SIZE(argv), + arraysize(argv), argv); child_env_ = env; @@ -301,7 +301,7 @@ void Agent::ChildSignalCb(uv_async_t* signal) { MakeCallback(isolate, api, "onmessage", - ARRAY_SIZE(argv), + arraysize(argv), argv); delete msg; } diff --git a/src/env.h b/src/env.h index ea5e8fea6edf62..1531d9911e310b 100644 --- a/src/env.h +++ b/src/env.h @@ -54,6 +54,7 @@ namespace node { V(buffer_string, "buffer") \ V(bytes_string, "bytes") \ V(bytes_parsed_string, "bytesParsed") \ + V(bytes_read_string, "bytesRead") \ V(callback_string, "callback") \ V(change_string, "change") \ V(oncertcb_string, "oncertcb") \ diff --git a/src/fs_event_wrap.cc b/src/fs_event_wrap.cc index 7768f94459c16a..a9f96389121c9e 100644 --- a/src/fs_event_wrap.cc +++ b/src/fs_event_wrap.cc @@ -159,7 +159,7 @@ void FSEventWrap::OnEvent(uv_fs_event_t* handle, const char* filename, argv[2] = OneByteString(env->isolate(), filename); } - wrap->MakeCallback(env->onchange_string(), ARRAY_SIZE(argv), argv); + wrap->MakeCallback(env->onchange_string(), arraysize(argv), argv); } diff --git a/src/js_stream.cc b/src/js_stream.cc index 25938f111ba6ac..e81709a8056965 100644 --- a/src/js_stream.cc +++ b/src/js_stream.cc @@ -75,7 +75,7 @@ int JSStream::DoShutdown(ShutdownWrap* req_wrap) { req_wrap->Dispatched(); Local res = - MakeCallback(env()->onshutdown_string(), ARRAY_SIZE(argv), argv); + MakeCallback(env()->onshutdown_string(), arraysize(argv), argv); return res->Int32Value(); } @@ -103,7 +103,7 @@ int JSStream::DoWrite(WriteWrap* w, w->Dispatched(); Local res = - MakeCallback(env()->onwrite_string(), ARRAY_SIZE(argv), argv); + MakeCallback(env()->onwrite_string(), arraysize(argv), argv); return res->Int32Value(); } diff --git a/src/node.cc b/src/node.cc index 869196f1397ca8..85383fa166661c 100644 --- a/src/node.cc +++ b/src/node.cc @@ -1097,7 +1097,7 @@ void PromiseRejectCallback(PromiseRejectMessage message) { Local args[] = { event, promise, value }; Local process = env->process_object(); - callback->Call(process, ARRAY_SIZE(args), args); + callback->Call(process, arraysize(args), args); } void SetupPromises(const FunctionCallbackInfo& args) { @@ -2453,12 +2453,12 @@ static void EnvGetter(Local property, WCHAR buffer[32767]; // The maximum size allowed for environment variables. DWORD result = GetEnvironmentVariableW(reinterpret_cast(*key), buffer, - ARRAY_SIZE(buffer)); + arraysize(buffer)); // If result >= sizeof buffer the buffer was too small. That should never // happen. If result == 0 and result != ERROR_SUCCESS the variable was not // not found. if ((result > 0 || GetLastError() == ERROR_SUCCESS) && - result < ARRAY_SIZE(buffer)) { + result < arraysize(buffer)) { const uint16_t* two_byte_buffer = reinterpret_cast(buffer); Local rc = String::NewFromTwoByte(isolate, two_byte_buffer); return info.GetReturnValue().Set(rc); @@ -3457,7 +3457,7 @@ static void EnableDebug(Environment* env) { FIXED_ONE_BYTE_STRING(env->isolate(), "internalMessage"), message }; - MakeCallback(env, env->process_object(), "emit", ARRAY_SIZE(argv), argv); + MakeCallback(env, env->process_object(), "emit", arraysize(argv), argv); // Enabled debugger, possibly making it wait on a semaphore env->debugger_agent()->Enable(); @@ -3578,7 +3578,7 @@ static int RegisterDebugSignalHandler() { if (GetDebugSignalHandlerMappingName(pid, mapping_name, - ARRAY_SIZE(mapping_name)) < 0) { + arraysize(mapping_name)) < 0) { return -1; } @@ -3641,7 +3641,7 @@ static void DebugProcess(const FunctionCallbackInfo& args) { if (GetDebugSignalHandlerMappingName(pid, mapping_name, - ARRAY_SIZE(mapping_name)) < 0) { + arraysize(mapping_name)) < 0) { env->ThrowErrnoException(errno, "sprintf"); goto out; } @@ -3918,7 +3918,7 @@ void EmitBeforeExit(Environment* env) { FIXED_ONE_BYTE_STRING(env->isolate(), "beforeExit"), process_object->Get(exit_code)->ToInteger(env->isolate()) }; - MakeCallback(env, process_object, "emit", ARRAY_SIZE(args), args); + MakeCallback(env, process_object, "emit", arraysize(args), args); } @@ -3937,7 +3937,7 @@ int EmitExit(Environment* env) { Integer::New(env->isolate(), code) }; - MakeCallback(env, process_object, "emit", ARRAY_SIZE(args), args); + MakeCallback(env, process_object, "emit", arraysize(args), args); // Reload exit code, it may be changed by `emit('exit')` return process_object->Get(exitCode)->Int32Value(); diff --git a/src/node_contextify.cc b/src/node_contextify.cc index 8235dcd49e093c..18bbc580054349 100644 --- a/src/node_contextify.cc +++ b/src/node_contextify.cc @@ -161,7 +161,7 @@ class ContextifyContext { CHECK(clone_property_method->IsFunction()); } Local args[] = { global, key, sandbox_obj }; - clone_property_method->Call(global, ARRAY_SIZE(args), args); + clone_property_method->Call(global, arraysize(args), args); } } } diff --git a/src/node_counters.cc b/src/node_counters.cc index ca05e253199af5..9853784e557136 100644 --- a/src/node_counters.cc +++ b/src/node_counters.cc @@ -98,7 +98,7 @@ void InitPerfCounters(Environment* env, Local target) { #undef NODE_PROBE }; - for (int i = 0; i < ARRAY_SIZE(tab); i++) { + for (size_t i = 0; i < arraysize(tab); i++) { Local key = OneByteString(env->isolate(), tab[i].name); Local val = env->NewFunctionTemplate(tab[i].func)->GetFunction(); target->Set(key, val); diff --git a/src/node_crypto.cc b/src/node_crypto.cc index 382a42f22727f8..21e4d33cab9316 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -760,7 +760,7 @@ void SecureContext::AddRootCerts(const FunctionCallbackInfo& args) { if (!root_cert_store) { root_cert_store = X509_STORE_new(); - for (size_t i = 0; i < ARRAY_SIZE(root_certs); i++) { + for (size_t i = 0; i < arraysize(root_certs); i++) { BIO* bp = NodeBIO::NewFixed(root_certs[i], strlen(root_certs[i])); if (bp == nullptr) { return; @@ -1092,7 +1092,7 @@ int SecureContext::TicketKeyCallback(SSL* ssl, Local ret = node::MakeCallback(env, sc->object(), env->ticketkeycallback_string(), - ARRAY_SIZE(argv), + arraysize(argv), argv); Local arr = ret.As(); @@ -1284,7 +1284,7 @@ int SSLWrap::NewSessionCallback(SSL* s, SSL_SESSION* sess) { sess->session_id_length).ToLocalChecked(); Local argv[] = { session, buff }; w->new_session_wait_ = true; - w->MakeCallback(env->onnewsession_string(), ARRAY_SIZE(argv), argv); + w->MakeCallback(env->onnewsession_string(), arraysize(argv), argv); return 0; } @@ -1318,7 +1318,7 @@ void SSLWrap::OnClientHello(void* arg, Boolean::New(env->isolate(), hello.ocsp_request())); Local argv[] = { hello_obj }; - w->MakeCallback(env->onclienthello_string(), ARRAY_SIZE(argv), argv); + w->MakeCallback(env->onclienthello_string(), arraysize(argv), argv); } @@ -1393,8 +1393,8 @@ static Local X509ToObject(Environment* env, X509* cert) { int nids[] = { NID_subject_alt_name, NID_info_access }; Local keys[] = { env->subjectaltname_string(), env->infoaccess_string() }; - CHECK_EQ(ARRAY_SIZE(nids), ARRAY_SIZE(keys)); - for (unsigned int i = 0; i < ARRAY_SIZE(nids); i++) { + CHECK_EQ(arraysize(nids), arraysize(keys)); + for (size_t i = 0; i < arraysize(nids); i++) { int index = X509_get_ext_by_NID(cert, nids[i], -1); if (index < 0) continue; @@ -2128,7 +2128,7 @@ int SSLWrap::SSLCertCallback(SSL* s, void* arg) { info->Set(env->ocsp_request_string(), Boolean::New(env->isolate(), ocsp)); Local argv[] = { info }; - w->MakeCallback(env->oncertcb_string(), ARRAY_SIZE(argv), argv); + w->MakeCallback(env->oncertcb_string(), arraysize(argv), argv); if (!w->cert_cb_running_) return 1; @@ -2491,7 +2491,7 @@ inline CheckResult CheckWhitelistedServerCert(X509_STORE_CTX* ctx) { CHECK(ret); void* result = bsearch(hash, WhitelistedCNNICHashes, - ARRAY_SIZE(WhitelistedCNNICHashes), + arraysize(WhitelistedCNNICHashes), CNNIC_WHITELIST_HASH_LEN, compar); if (result == nullptr) { sk_X509_pop_free(chain, X509_free); @@ -4229,7 +4229,7 @@ void DiffieHellman::DiffieHellmanGroup( bool initialized = false; const node::Utf8Value group_name(env->isolate(), args[0]); - for (unsigned int i = 0; i < ARRAY_SIZE(modp_groups); ++i) { + for (size_t i = 0; i < arraysize(modp_groups); ++i) { const modp_group* it = modp_groups + i; if (strcasecmp(*group_name, it->name) != 0) @@ -4883,7 +4883,7 @@ void EIO_PBKDF2After(uv_work_t* work_req, int status) { Context::Scope context_scope(env->context()); Local argv[2]; EIO_PBKDF2After(req, argv); - req->MakeCallback(env->ondone_string(), ARRAY_SIZE(argv), argv); + req->MakeCallback(env->ondone_string(), arraysize(argv), argv); delete req; } @@ -5124,7 +5124,7 @@ void RandomBytesAfter(uv_work_t* work_req, int status) { Context::Scope context_scope(env->context()); Local argv[2]; RandomBytesCheck(req, argv); - req->MakeCallback(env->ondone_string(), ARRAY_SIZE(argv), argv); + req->MakeCallback(env->ondone_string(), arraysize(argv), argv); delete req; } diff --git a/src/node_dtrace.cc b/src/node_dtrace.cc index 568972bab3f90f..b92a0dd411b981 100644 --- a/src/node_dtrace.cc +++ b/src/node_dtrace.cc @@ -257,7 +257,7 @@ void InitDTrace(Environment* env, Local target) { #undef NODE_PROBE }; - for (unsigned int i = 0; i < ARRAY_SIZE(tab); i++) { + for (size_t i = 0; i < arraysize(tab); i++) { Local key = OneByteString(env->isolate(), tab[i].name); Local val = env->NewFunctionTemplate(tab[i].func)->GetFunction(); target->Set(key, val); diff --git a/src/node_file.cc b/src/node_file.cc index b6ef7d5b78f70e..b31435ecc0a77c 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -429,7 +429,7 @@ Local BuildStatsObject(Environment* env, const uv_stat_t* s) { // Call out to JavaScript to create the stats object. Local stats = - env->fs_stats_constructor_function()->NewInstance(ARRAY_SIZE(argv), argv); + env->fs_stats_constructor_function()->NewInstance(arraysize(argv), argv); if (stats.IsEmpty()) return handle_scope.Escape(Local()); @@ -932,7 +932,7 @@ static void WriteBuffers(const FunctionCallbackInfo& args) { uv_buf_t s_iovs[1024]; // use stack allocation when possible uv_buf_t* iovs; - if (chunkCount > ARRAY_SIZE(s_iovs)) + if (chunkCount > arraysize(s_iovs)) iovs = new uv_buf_t[chunkCount]; else iovs = s_iovs; diff --git a/src/node_http_parser.cc b/src/node_http_parser.cc index 9225915e12f7fd..8c976b2e9f0b4c 100644 --- a/src/node_http_parser.cc +++ b/src/node_http_parser.cc @@ -189,7 +189,7 @@ class Parser : public BaseObject { if (num_fields_ == num_values_) { // start of new field name num_fields_++; - if (num_fields_ == ARRAY_SIZE(fields_)) { + if (num_fields_ == arraysize(fields_)) { // ran out of space - flush to javascript land Flush(); num_fields_ = 1; @@ -198,7 +198,7 @@ class Parser : public BaseObject { fields_[num_fields_ - 1].Reset(); } - CHECK_LT(num_fields_, static_cast(ARRAY_SIZE(fields_))); + CHECK_LT(num_fields_, arraysize(fields_)); CHECK_EQ(num_fields_, num_values_ + 1); fields_[num_fields_ - 1].Update(at, length); @@ -214,7 +214,7 @@ class Parser : public BaseObject { values_[num_values_ - 1].Reset(); } - CHECK_LT(num_values_, static_cast(ARRAY_SIZE(values_))); + CHECK_LT(num_values_, arraysize(values_)); CHECK_EQ(num_values_, num_fields_); values_[num_values_ - 1].Update(at, length); @@ -248,7 +248,7 @@ class Parser : public BaseObject { return 0; Local undefined = Undefined(env()->isolate()); - for (size_t i = 0; i < ARRAY_SIZE(argv); i++) + for (size_t i = 0; i < arraysize(argv); i++) argv[i] = undefined; if (have_flushed_) { @@ -287,7 +287,7 @@ class Parser : public BaseObject { argv[A_UPGRADE] = Boolean::New(env()->isolate(), parser_.upgrade); Local head_response = - cb.As()->Call(obj, ARRAY_SIZE(argv), argv); + cb.As()->Call(obj, arraysize(argv), argv); if (head_response.IsEmpty()) { got_exception_ = true; @@ -322,7 +322,7 @@ class Parser : public BaseObject { Integer::NewFromUnsigned(env()->isolate(), length) }; - Local r = cb.As()->Call(obj, ARRAY_SIZE(argv), argv); + Local r = cb.As()->Call(obj, arraysize(argv), argv); if (r.IsEmpty()) { got_exception_ = true; @@ -377,11 +377,11 @@ class Parser : public BaseObject { url_.Save(); status_message_.Save(); - for (int i = 0; i < num_fields_; i++) { + for (size_t i = 0; i < num_fields_; i++) { fields_[i].Save(); } - for (int i = 0; i < num_values_; i++) { + for (size_t i = 0; i < num_values_; i++) { values_[i].Save(); } } @@ -631,11 +631,9 @@ class Parser : public BaseObject { } Local CreateHeaders() { - // num_values_ is either -1 or the entry # of the last header - // so num_values_ == 0 means there's a single header Local headers = Array::New(env()->isolate(), 2 * num_values_); - for (int i = 0; i < num_values_; ++i) { + for (size_t i = 0; i < num_values_; ++i) { headers->Set(2 * i, fields_[i].ToString(env())); headers->Set(2 * i + 1, values_[i].ToString(env())); } @@ -659,7 +657,7 @@ class Parser : public BaseObject { url_.ToString(env()) }; - Local r = cb.As()->Call(obj, ARRAY_SIZE(argv), argv); + Local r = cb.As()->Call(obj, arraysize(argv), argv); if (r.IsEmpty()) got_exception_ = true; @@ -687,8 +685,8 @@ class Parser : public BaseObject { StringPtr values_[32]; // header values StringPtr url_; StringPtr status_message_; - int num_fields_; - int num_values_; + size_t num_fields_; + size_t num_values_; bool have_flushed_; bool got_exception_; Local current_buffer_; diff --git a/src/node_internals.h b/src/node_internals.h index 5ff6b63d21ab15..3df7676d2a9d51 100644 --- a/src/node_internals.h +++ b/src/node_internals.h @@ -109,8 +109,11 @@ inline static int snprintf(char *buffer, size_t n, const char *format, ...) { #endif #endif -#ifndef ARRAY_SIZE -# define ARRAY_SIZE(a) (sizeof((a)) / sizeof((a)[0])) +#if defined(_MSC_VER) && _MSC_VER < 1900 +#define arraysize(a) (sizeof(a) / sizeof(*a)) // Workaround for VS 2013. +#else +template +constexpr size_t arraysize(const T(&)[N]) { return N; } #endif #ifndef ROUND_UP diff --git a/src/node_lttng.cc b/src/node_lttng.cc index 876bcda92f82fa..41ccdf33411563 100644 --- a/src/node_lttng.cc +++ b/src/node_lttng.cc @@ -250,7 +250,7 @@ void InitLTTNG(Environment* env, Local target) { #undef NODE_PROBE }; - for (unsigned int i = 0; i < ARRAY_SIZE(tab); i++) { + for (size_t i = 0; i < arraysize(tab); i++) { Local key = OneByteString(env->isolate(), tab[i].name); Local val = env->NewFunctionTemplate(tab[i].func)->GetFunction(); target->Set(key, val); diff --git a/src/node_stat_watcher.cc b/src/node_stat_watcher.cc index bd1cb73248e99c..4fa01794f6c6da 100644 --- a/src/node_stat_watcher.cc +++ b/src/node_stat_watcher.cc @@ -70,7 +70,7 @@ void StatWatcher::Callback(uv_fs_poll_t* handle, BuildStatsObject(env, prev), Integer::New(env->isolate(), status) }; - wrap->MakeCallback(env->onchange_string(), ARRAY_SIZE(argv), argv); + wrap->MakeCallback(env->onchange_string(), arraysize(argv), argv); } diff --git a/src/node_version.h b/src/node_version.h index 55e2ef69f35461..bf2a9fc0df8f3e 100644 --- a/src/node_version.h +++ b/src/node_version.h @@ -8,7 +8,7 @@ #define NODE_VERSION_IS_LTS 1 #define NODE_VERSION_LTS_CODENAME "Argon" -#define NODE_VERSION_IS_RELEASE 0 +#define NODE_VERSION_IS_RELEASE 1 #ifndef NODE_STRINGIFY #define NODE_STRINGIFY(n) NODE_STRINGIFY_HELPER(n) diff --git a/src/node_win32_etw_provider-inl.h b/src/node_win32_etw_provider-inl.h index 3fef20cc1488c1..04cd31cee3c2f6 100644 --- a/src/node_win32_etw_provider-inl.h +++ b/src/node_win32_etw_provider-inl.h @@ -202,7 +202,7 @@ void NODE_V8SYMBOL_RESET() { #define SETSYMBUF(s) \ wcscpy(symbuf, s); \ - symbol_len = ARRAY_SIZE(s) - 1; + symbol_len = arraysize(s) - 1; void NODE_V8SYMBOL_ADD(LPCSTR symbol, int symbol_len, diff --git a/src/node_win32_etw_provider.cc b/src/node_win32_etw_provider.cc index c6bfbeaaf6c989..6877f1977dae8b 100644 --- a/src/node_win32_etw_provider.cc +++ b/src/node_win32_etw_provider.cc @@ -56,7 +56,7 @@ struct v8tags trace_codes[] = { // If prefix is not in filtered list return -1, // else return length of prefix and marker. int FilterCodeEvents(const char* name, size_t len) { - for (int i = 0; i < ARRAY_SIZE(trace_codes); i++) { + for (size_t i = 0; i < arraysize(trace_codes); i++) { size_t prelen = trace_codes[i].prelen; if (prelen < len) { if (strncmp(name, trace_codes[i].prefix, prelen) == 0) { diff --git a/src/node_zlib.cc b/src/node_zlib.cc index da60d4430f3042..29649e32c7dbbc 100644 --- a/src/node_zlib.cc +++ b/src/node_zlib.cc @@ -313,7 +313,7 @@ class ZCtx : public AsyncWrap { // call the write() cb Local args[2] = { avail_in, avail_out }; - ctx->MakeCallback(env->callback_string(), ARRAY_SIZE(args), args); + ctx->MakeCallback(env->callback_string(), arraysize(args), args); ctx->Unref(); if (ctx->pending_close_) @@ -335,7 +335,7 @@ class ZCtx : public AsyncWrap { OneByteString(env->isolate(), message), Number::New(env->isolate(), ctx->err_) }; - ctx->MakeCallback(env->onerror_string(), ARRAY_SIZE(args), args); + ctx->MakeCallback(env->onerror_string(), arraysize(args), args); // no hope of rescue. if (ctx->write_in_progress_) diff --git a/src/pipe_wrap.cc b/src/pipe_wrap.cc index 84164723e95b99..e3377d402f5ab1 100644 --- a/src/pipe_wrap.cc +++ b/src/pipe_wrap.cc @@ -183,7 +183,7 @@ void PipeWrap::OnConnection(uv_stream_t* handle, int status) { }; if (status != 0) { - pipe_wrap->MakeCallback(env->onconnection_string(), ARRAY_SIZE(argv), argv); + pipe_wrap->MakeCallback(env->onconnection_string(), arraysize(argv), argv); return; } @@ -198,7 +198,7 @@ void PipeWrap::OnConnection(uv_stream_t* handle, int status) { // Successful accept. Call the onconnection callback in JavaScript land. argv[1] = client_obj; - pipe_wrap->MakeCallback(env->onconnection_string(), ARRAY_SIZE(argv), argv); + pipe_wrap->MakeCallback(env->onconnection_string(), arraysize(argv), argv); } // TODO(bnoordhuis) Maybe share this with TCPWrap? @@ -233,7 +233,7 @@ void PipeWrap::AfterConnect(uv_connect_t* req, int status) { Boolean::New(env->isolate(), writable) }; - req_wrap->MakeCallback(env->oncomplete_string(), ARRAY_SIZE(argv), argv); + req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv); delete req_wrap; } diff --git a/src/process_wrap.cc b/src/process_wrap.cc index 3456d2be8fbab8..420c71d7ea4052 100644 --- a/src/process_wrap.cc +++ b/src/process_wrap.cc @@ -254,7 +254,7 @@ class ProcessWrap : public HandleWrap { OneByteString(env->isolate(), signo_string(term_signal)) }; - wrap->MakeCallback(env->onexit_string(), ARRAY_SIZE(argv), argv); + wrap->MakeCallback(env->onexit_string(), arraysize(argv), argv); } uv_process_t process_; diff --git a/src/stream_base-inl.h b/src/stream_base-inl.h index 81114a265e9a08..099e105334cedf 100644 --- a/src/stream_base-inl.h +++ b/src/stream_base-inl.h @@ -43,6 +43,13 @@ void StreamBase::AddMethods(Environment* env, v8::DEFAULT, attributes); + t->InstanceTemplate()->SetAccessor(env->bytes_read_string(), + GetBytesRead, + nullptr, + env->as_external(), + v8::DEFAULT, + attributes); + env->SetProtoMethod(t, "readStart", JSMethod); env->SetProtoMethod(t, "readStop", JSMethod); if ((flags & kFlagNoShutdown) == 0) @@ -79,6 +86,16 @@ void StreamBase::GetFD(Local key, } +template +void StreamBase::GetBytesRead(Local key, + const PropertyCallbackInfo& args) { + StreamBase* wrap = Unwrap(args.Holder()); + + // uint64_t -> double. 53bits is enough for all real cases. + args.GetReturnValue().Set(static_cast(wrap->bytes_read_)); +} + + template void StreamBase::GetExternal(Local key, const PropertyCallbackInfo& args) { diff --git a/src/stream_base.cc b/src/stream_base.cc index 27ae0fee7b1309..f9fed08d134c50 100644 --- a/src/stream_base.cc +++ b/src/stream_base.cc @@ -83,7 +83,7 @@ void StreamBase::AfterShutdown(ShutdownWrap* req_wrap, int status) { }; if (req_wrap->object()->Has(env->oncomplete_string())) - req_wrap->MakeCallback(env->oncomplete_string(), ARRAY_SIZE(argv), argv); + req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv); delete req_wrap; } @@ -130,7 +130,7 @@ int StreamBase::Writev(const FunctionCallbackInfo& args) { if (storage_size > INT_MAX) return UV_ENOBUFS; - if (ARRAY_SIZE(bufs_) < count) + if (arraysize(bufs_) < count) bufs = new uv_buf_t[count]; WriteWrap* req_wrap = WriteWrap::New(env, @@ -388,7 +388,7 @@ void StreamBase::AfterWrite(WriteWrap* req_wrap, int status) { } if (req_wrap->object()->Has(env->oncomplete_string())) - req_wrap->MakeCallback(env->oncomplete_string(), ARRAY_SIZE(argv), argv); + req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv); req_wrap->Dispose(); } @@ -416,10 +416,10 @@ void StreamBase::EmitData(ssize_t nread, node::MakeCallback(env, GetObject(), env->onread_string(), - ARRAY_SIZE(argv), + arraysize(argv), argv); } else { - async->MakeCallback(env->onread_string(), ARRAY_SIZE(argv), argv); + async->MakeCallback(env->onread_string(), arraysize(argv), argv); } } diff --git a/src/stream_base.h b/src/stream_base.h index fad2ddd2e086f0..e722a208a8af68 100644 --- a/src/stream_base.h +++ b/src/stream_base.h @@ -136,7 +136,7 @@ class StreamResource { uv_handle_type pending, void* ctx); - StreamResource() { + StreamResource() : bytes_read_(0) { } virtual ~StreamResource() = default; @@ -160,9 +160,11 @@ class StreamResource { alloc_cb_.fn(size, buf, alloc_cb_.ctx); } - inline void OnRead(size_t nread, + inline void OnRead(ssize_t nread, const uv_buf_t* buf, uv_handle_type pending = UV_UNKNOWN_HANDLE) { + if (nread > 0) + bytes_read_ += static_cast(nread); if (!read_cb_.is_empty()) read_cb_.fn(nread, buf, pending, read_cb_.ctx); } @@ -182,6 +184,9 @@ class StreamResource { Callback after_write_cb_; Callback alloc_cb_; Callback read_cb_; + uint64_t bytes_read_; + + friend class StreamBase; }; class StreamBase : public StreamResource { @@ -249,6 +254,10 @@ class StreamBase : public StreamResource { static void GetExternal(v8::Local key, const v8::PropertyCallbackInfo& args); + template + static void GetBytesRead(v8::Local key, + const v8::PropertyCallbackInfo& args); + template & args)> diff --git a/src/tcp_wrap.cc b/src/tcp_wrap.cc index 3f3e6a0ad4a752..0214be100228c4 100644 --- a/src/tcp_wrap.cc +++ b/src/tcp_wrap.cc @@ -269,7 +269,7 @@ void TCPWrap::OnConnection(uv_stream_t* handle, int status) { argv[1] = client_obj; } - tcp_wrap->MakeCallback(env->onconnection_string(), ARRAY_SIZE(argv), argv); + tcp_wrap->MakeCallback(env->onconnection_string(), arraysize(argv), argv); } @@ -295,7 +295,7 @@ void TCPWrap::AfterConnect(uv_connect_t* req, int status) { v8::True(env->isolate()) }; - req_wrap->MakeCallback(env->oncomplete_string(), ARRAY_SIZE(argv), argv); + req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv); delete req_wrap; } diff --git a/src/tls_wrap.cc b/src/tls_wrap.cc index 85730b34936b55..48ec8a54a98c79 100644 --- a/src/tls_wrap.cc +++ b/src/tls_wrap.cc @@ -283,8 +283,8 @@ void TLSWrap::EncOut() { } char* data[kSimultaneousBufferCount]; - size_t size[ARRAY_SIZE(data)]; - size_t count = ARRAY_SIZE(data); + size_t size[arraysize(data)]; + size_t count = arraysize(data); write_size_ = NodeBIO::FromBIO(enc_out_)->PeekMultiple(data, size, &count); CHECK(write_size_ != 0 && count != 0); @@ -295,7 +295,7 @@ void TLSWrap::EncOut() { this, EncOutCb); - uv_buf_t buf[ARRAY_SIZE(data)]; + uv_buf_t buf[arraysize(data)]; for (size_t i = 0; i < count; i++) buf[i] = uv_buf_init(data[i], size[i]); int err = stream_->DoWrite(write_req, buf, count, nullptr); diff --git a/src/udp_wrap.cc b/src/udp_wrap.cc index cb678f14fb3826..8c460ebac6ff22 100644 --- a/src/udp_wrap.cc +++ b/src/udp_wrap.cc @@ -380,14 +380,14 @@ void UDPWrap::OnRecv(uv_udp_t* handle, if (nread < 0) { if (buf->base != nullptr) free(buf->base); - wrap->MakeCallback(env->onmessage_string(), ARRAY_SIZE(argv), argv); + wrap->MakeCallback(env->onmessage_string(), arraysize(argv), argv); return; } char* base = static_cast(realloc(buf->base, nread)); argv[2] = Buffer::New(env, base, nread).ToLocalChecked(); argv[3] = AddressToJS(env, addr); - wrap->MakeCallback(env->onmessage_string(), ARRAY_SIZE(argv), argv); + wrap->MakeCallback(env->onmessage_string(), arraysize(argv), argv); } diff --git a/src/util.cc b/src/util.cc index 903fbbba134bd9..858e4b396534b3 100644 --- a/src/util.cc +++ b/src/util.cc @@ -5,6 +5,10 @@ namespace node { Utf8Value::Utf8Value(v8::Isolate* isolate, v8::Local value) : length_(0), str_(str_st_) { + // Make sure result is always zero-terminated, even if conversion to string + // fails. + str_st_[0] = '\0'; + if (value.IsEmpty()) return; diff --git a/test/addons/stringbytes-external-exceed-max/test-stringbytes-external-at-max.js b/test/addons/stringbytes-external-exceed-max/test-stringbytes-external-at-max.js index a5d937d521d887..3f548112278cd6 100644 --- a/test/addons/stringbytes-external-exceed-max/test-stringbytes-external-at-max.js +++ b/test/addons/stringbytes-external-exceed-max/test-stringbytes-external-at-max.js @@ -8,10 +8,9 @@ const assert = require('assert'); // v8::String::kMaxLength defined in v8.h const kStringMaxLength = process.binding('buffer').kStringMaxLength; -const skipMessage = - '1..0 # Skipped: intensive toString tests due to memory confinements'; +const skipMessage = 'intensive toString tests due to memory confinements'; if (!common.enoughTestMem) { - console.log(skipMessage); + common.skip(skipMessage); return; } @@ -20,13 +19,13 @@ try { } catch (e) { // If the exception is not due to memory confinement then rethrow it. if (e.message !== 'Invalid array buffer length') throw (e); - console.log(skipMessage); + common.skip(skipMessage); return; } // Ensure we have enough memory available for future allocations to succeed. if (!binding.ensureAllocation(2 * kStringMaxLength)) { - console.log(skipMessage); + common.skip(skipMessage); return; } diff --git a/test/addons/stringbytes-external-exceed-max/test-stringbytes-external-exceed-max-by-1-ascii.js b/test/addons/stringbytes-external-exceed-max/test-stringbytes-external-exceed-max-by-1-ascii.js index dee30d9fef0f97..b106e3d25aa085 100644 --- a/test/addons/stringbytes-external-exceed-max/test-stringbytes-external-exceed-max-by-1-ascii.js +++ b/test/addons/stringbytes-external-exceed-max/test-stringbytes-external-exceed-max-by-1-ascii.js @@ -4,10 +4,9 @@ const common = require('../../common'); const binding = require('./build/Release/binding'); const assert = require('assert'); -const skipMessage = - '1..0 # Skipped: intensive toString tests due to memory confinements'; +const skipMessage = 'intensive toString tests due to memory confinements'; if (!common.enoughTestMem) { - console.log(skipMessage); + common.skip(skipMessage); return; } @@ -20,13 +19,13 @@ try { } catch (e) { // If the exception is not due to memory confinement then rethrow it. if (e.message !== 'Invalid array buffer length') throw (e); - console.log(skipMessage); + common.skip(skipMessage); return; } // Ensure we have enough memory available for future allocations to succeed. if (!binding.ensureAllocation(2 * kStringMaxLength)) { - console.log(skipMessage); + common.skip(skipMessage); return; } diff --git a/test/addons/stringbytes-external-exceed-max/test-stringbytes-external-exceed-max-by-1-base64.js b/test/addons/stringbytes-external-exceed-max/test-stringbytes-external-exceed-max-by-1-base64.js index f06052d31611fc..1df9d228d961d9 100644 --- a/test/addons/stringbytes-external-exceed-max/test-stringbytes-external-exceed-max-by-1-base64.js +++ b/test/addons/stringbytes-external-exceed-max/test-stringbytes-external-exceed-max-by-1-base64.js @@ -4,10 +4,9 @@ const common = require('../../common'); const binding = require('./build/Release/binding'); const assert = require('assert'); -const skipMessage = - '1..0 # Skipped: intensive toString tests due to memory confinements'; +const skipMessage = 'intensive toString tests due to memory confinements'; if (!common.enoughTestMem) { - console.log(skipMessage); + common.skip(skipMessage); return; } @@ -20,13 +19,13 @@ try { } catch (e) { // If the exception is not due to memory confinement then rethrow it. if (e.message !== 'Invalid array buffer length') throw (e); - console.log(skipMessage); + common.skip(skipMessage); return; } // Ensure we have enough memory available for future allocations to succeed. if (!binding.ensureAllocation(2 * kStringMaxLength)) { - console.log(skipMessage); + common.skip(skipMessage); return; } diff --git a/test/addons/stringbytes-external-exceed-max/test-stringbytes-external-exceed-max-by-1-binary.js b/test/addons/stringbytes-external-exceed-max/test-stringbytes-external-exceed-max-by-1-binary.js index 9af82da07eb706..de27859a06e1bc 100644 --- a/test/addons/stringbytes-external-exceed-max/test-stringbytes-external-exceed-max-by-1-binary.js +++ b/test/addons/stringbytes-external-exceed-max/test-stringbytes-external-exceed-max-by-1-binary.js @@ -4,10 +4,9 @@ const common = require('../../common'); const binding = require('./build/Release/binding'); const assert = require('assert'); -const skipMessage = - '1..0 # Skipped: intensive toString tests due to memory confinements'; +const skipMessage = 'intensive toString tests due to memory confinements'; if (!common.enoughTestMem) { - console.log(skipMessage); + common.skip(skipMessage); return; } @@ -20,13 +19,13 @@ try { } catch (e) { // If the exception is not due to memory confinement then rethrow it. if (e.message !== 'Invalid array buffer length') throw (e); - console.log(skipMessage); + common.skip(skipMessage); return; } // Ensure we have enough memory available for future allocations to succeed. if (!binding.ensureAllocation(2 * kStringMaxLength)) { - console.log(skipMessage); + common.skip(skipMessage); return; } diff --git a/test/addons/stringbytes-external-exceed-max/test-stringbytes-external-exceed-max-by-1-hex.js b/test/addons/stringbytes-external-exceed-max/test-stringbytes-external-exceed-max-by-1-hex.js index a1d54460a22d8e..4dbcf0efd86e39 100644 --- a/test/addons/stringbytes-external-exceed-max/test-stringbytes-external-exceed-max-by-1-hex.js +++ b/test/addons/stringbytes-external-exceed-max/test-stringbytes-external-exceed-max-by-1-hex.js @@ -4,10 +4,9 @@ const common = require('../../common'); const binding = require('./build/Release/binding'); const assert = require('assert'); -const skipMessage = - '1..0 # Skipped: intensive toString tests due to memory confinements'; +const skipMessage = 'intensive toString tests due to memory confinements'; if (!common.enoughTestMem) { - console.log(skipMessage); + common.skip(skipMessage); return; } @@ -20,13 +19,13 @@ try { } catch (e) { // If the exception is not due to memory confinement then rethrow it. if (e.message !== 'Invalid array buffer length') throw (e); - console.log(skipMessage); + common.skip(skipMessage); return; } // Ensure we have enough memory available for future allocations to succeed. if (!binding.ensureAllocation(2 * kStringMaxLength)) { - console.log(skipMessage); + common.skip(skipMessage); return; } diff --git a/test/addons/stringbytes-external-exceed-max/test-stringbytes-external-exceed-max-by-1-utf8.js b/test/addons/stringbytes-external-exceed-max/test-stringbytes-external-exceed-max-by-1-utf8.js index 546e2a1a134fbd..0333bc850b5c42 100644 --- a/test/addons/stringbytes-external-exceed-max/test-stringbytes-external-exceed-max-by-1-utf8.js +++ b/test/addons/stringbytes-external-exceed-max/test-stringbytes-external-exceed-max-by-1-utf8.js @@ -4,10 +4,9 @@ const common = require('../../common'); const binding = require('./build/Release/binding'); const assert = require('assert'); -const skipMessage = - '1..0 # Skipped: intensive toString tests due to memory confinements'; +const skipMessage = 'intensive toString tests due to memory confinements'; if (!common.enoughTestMem) { - console.log(skipMessage); + common.skip(skipMessage); return; } @@ -20,13 +19,13 @@ try { } catch (e) { // If the exception is not due to memory confinement then rethrow it. if (e.message !== 'Invalid array buffer length') throw (e); - console.log(skipMessage); + common.skip(skipMessage); return; } // Ensure we have enough memory available for future allocations to succeed. if (!binding.ensureAllocation(2 * kStringMaxLength)) { - console.log(skipMessage); + common.skip(skipMessage); return; } diff --git a/test/addons/stringbytes-external-exceed-max/test-stringbytes-external-exceed-max-by-2.js b/test/addons/stringbytes-external-exceed-max/test-stringbytes-external-exceed-max-by-2.js index 94f6602cda40c6..094dee899030cc 100644 --- a/test/addons/stringbytes-external-exceed-max/test-stringbytes-external-exceed-max-by-2.js +++ b/test/addons/stringbytes-external-exceed-max/test-stringbytes-external-exceed-max-by-2.js @@ -4,10 +4,9 @@ const common = require('../../common'); const binding = require('./build/Release/binding'); const assert = require('assert'); -const skipMessage = - '1..0 # Skipped: intensive toString tests due to memory confinements'; +const skipMessage = 'intensive toString tests due to memory confinements'; if (!common.enoughTestMem) { - console.log(skipMessage); + common.skip(skipMessage); return; } @@ -20,13 +19,13 @@ try { } catch (e) { // If the exception is not due to memory confinement then rethrow it. if (e.message !== 'Invalid array buffer length') throw (e); - console.log(skipMessage); + common.skip(skipMessage); return; } // Ensure we have enough memory available for future allocations to succeed. if (!binding.ensureAllocation(2 * kStringMaxLength)) { - console.log(skipMessage); + common.skip(skipMessage); return; } diff --git a/test/addons/stringbytes-external-exceed-max/test-stringbytes-external-exceed-max.js b/test/addons/stringbytes-external-exceed-max/test-stringbytes-external-exceed-max.js index 41a14118cf538a..ce4a488cca1d95 100644 --- a/test/addons/stringbytes-external-exceed-max/test-stringbytes-external-exceed-max.js +++ b/test/addons/stringbytes-external-exceed-max/test-stringbytes-external-exceed-max.js @@ -4,10 +4,9 @@ const common = require('../../common'); const binding = require('./build/Release/binding'); const assert = require('assert'); -const skipMessage = - '1..0 # Skipped: intensive toString tests due to memory confinements'; +const skipMessage = 'intensive toString tests due to memory confinements'; if (!common.enoughTestMem) { - console.log(skipMessage); + common.skip(skipMessage); return; } @@ -20,13 +19,13 @@ try { } catch (e) { // If the exception is not due to memory confinement then rethrow it. if (e.message !== 'Invalid array buffer length') throw (e); - console.log(skipMessage); + common.skip(skipMessage); return; } // Ensure we have enough memory available for future allocations to succeed. if (!binding.ensureAllocation(2 * kStringMaxLength)) { - console.log(skipMessage); + common.skip(skipMessage); return; } diff --git a/test/common.js b/test/common.js index d56bc15329af52..801e356b749255 100644 --- a/test/common.js +++ b/test/common.js @@ -459,6 +459,10 @@ exports.fail = function(msg) { assert.fail(null, null, msg); }; +exports.skip = function(msg) { + console.log(`1..0 # Skipped: ${msg}`); +}; + // Returns true if the exit code "exitCode" and/or signal name "signal" // represent the exit code and/or signal name of a node process that aborted, // false otherwise. diff --git a/test/debugger/test-debugger-repl-break-in-module.js b/test/debugger/test-debugger-repl-break-in-module.js index e439e08c24cd30..d855dc64f4aa25 100644 --- a/test/debugger/test-debugger-repl-break-in-module.js +++ b/test/debugger/test-debugger-repl-break-in-module.js @@ -7,7 +7,7 @@ repl.startDebugger('break-in-module/main.js'); // -- SET BREAKPOINT -- // Set breakpoint by file name + line number where the file is not loaded yet -repl.addTest('sb("mod.js", 23)', [ +repl.addTest('sb("mod.js", 2)', [ /Warning: script 'mod\.js' was not loaded yet\./, /1/, /2/, /3/, /4/, /5/, /6/ ]); @@ -20,8 +20,8 @@ repl.addTest('sb(")^$*+?}{|][(.js\\\\", 1)', [ // continue - the breakpoint should be triggered repl.addTest('c', [ - /break in .*[\\\/]mod\.js:23/, - /21/, /22/, /23/, /24/, /25/ + /break in .*[\\\/]mod\.js:2/, + /1/, /2/, /3/, /4/ ]); // -- RESTORE BREAKPOINT ON RESTART -- @@ -33,7 +33,7 @@ repl.addTest('restart', [].concat( ], repl.handshakeLines, [ - /Restoring breakpoint mod.js:23/, + /Restoring breakpoint mod.js:2/, /Warning: script 'mod\.js' was not loaded yet\./, /Restoring breakpoint \).*:\d+/, /Warning: script '\)[^']*' was not loaded yet\./ @@ -42,14 +42,14 @@ repl.addTest('restart', [].concat( // continue - the breakpoint should be triggered repl.addTest('c', [ - /break in .*[\\\/]mod\.js:23/, - /21/, /22/, /23/, /24/, /25/ + /break in .*[\\\/]mod\.js:2/, + /1/, /2/, /3/, /4/ ]); // -- CLEAR BREAKPOINT SET IN MODULE TO BE LOADED -- -repl.addTest('cb("mod.js", 23)', [ - /18/, /./, /./, /./, /./, /./, /./, /./, /26/ +repl.addTest('cb("mod.js", 2)', [ + /1/, /2/, /3/, /4/, /5/ ]); repl.addTest('c', [ diff --git a/test/debugger/test-debugger-repl.js b/test/debugger/test-debugger-repl.js index f93570c50156ce..8a87d40d163af7 100644 --- a/test/debugger/test-debugger-repl.js +++ b/test/debugger/test-debugger-repl.js @@ -51,10 +51,20 @@ addTest('sb("setInterval()", "!(setInterval.flag++)")', [ // Continue addTest('c', [ - /break in node.js:\d+/, + /break in timers.js:\d+/, /\d/, /\d/, /\d/, /\d/, /\d/ ]); +// Execute +addTest('exec process.title', [ + /node/ +]); + +// Execute +addTest('exec exec process.title', [ + /SyntaxError: Unexpected identifier/ +]); + // REPL and process.env regression addTest('repl', [ /Ctrl/ @@ -65,3 +75,7 @@ addTest('for (var i in process.env) delete process.env[i]', []); addTest('process.env', [ /\{\}/ ]); + +addTest('arr = [{foo: "bar"}]', [ + /\[ \{ foo: 'bar' \} \]/ +]); diff --git a/test/disabled/tls_server.js b/test/disabled/tls_server.js index cc381a61c31dfd..14e48f6b31a50f 100644 --- a/test/disabled/tls_server.js +++ b/test/disabled/tls_server.js @@ -13,7 +13,7 @@ var certPem = fs.readFileSync(common.fixturesDir + '/cert.pem'); try { var credentials = crypto.createCredentials({key: keyPem, cert: certPem}); } catch (e) { - console.log('1..0 # Skipped: node compiled without OpenSSL.'); + common.skip('node compiled without OpenSSL.'); return; } var i = 0; diff --git a/test/doctool/test-doctool-html.js b/test/doctool/test-doctool-html.js new file mode 100644 index 00000000000000..afd89489f11ed4 --- /dev/null +++ b/test/doctool/test-doctool-html.js @@ -0,0 +1,48 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const fs = require('fs'); + +const html = require('../../tools/doc/html.js'); + +// Test data is a list of objects with two properties. +// The file property is the file path. +// The html property is some html which will be generated by the doctool. +// This html will be stripped of all whitespace because we don't currently +// have an html parser. +const testData = [ + { + 'file': common.fixturesDir + '/sample_document.md', + 'html': '
    1. fish
    2. fish

    3. Redfish

    4. ' + + '
    5. Bluefish
    ' + }, + { + 'file': common.fixturesDir + '/order_of_end_tags_5873.md', + 'html': '

    ClassMethod: Buffer.from(array) ' + + '#

    ' + }, +]; + +testData.forEach(function(item) { + // Normalize expected data by stripping whitespace + const expected = item.html.replace(/\s/g, ''); + + fs.readFile(item.file, 'utf8', common.mustCall(function(err, input) { + assert.ifError(err); + html(input, 'foo', 'doc/template.html', + common.mustCall(function(err, output) { + assert.ifError(err); + + const actual = output.replace(/\s/g, ''); + // Assert that the input stripped of all whitespace contains the + // expected list + assert.notEqual(actual.indexOf(expected), -1); + })); + })); +}); diff --git a/test/doctool/test-doctool-json.js b/test/doctool/test-doctool-json.js new file mode 100644 index 00000000000000..31e260fcb02d43 --- /dev/null +++ b/test/doctool/test-doctool-json.js @@ -0,0 +1,78 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const fs = require('fs'); + +const json = require('../../tools/doc/json.js'); + +// Outputs valid json with the expected fields when given simple markdown +// Test data is a list of objects with two properties. +// The file property is the file path. +// The json property is some json which will be generated by the doctool. +var testData = [ + { + 'file': common.fixturesDir + '/sample_document.md', + 'json': { + 'source': 'foo', + 'modules': [ { 'textRaw': 'Sample Markdown', + 'name': 'sample_markdown', + 'modules': [ { 'textRaw':'Seussian Rhymes', + 'name': 'seussian_rhymes', + 'desc': '
      \n
    1. fish
    2. \n
    3. fish

      \n
    4. \n
    5. ' + + '

      Red fish

      \n
    6. \n
    7. Blue fish
    8. \n
    \n', + 'type': 'module', + 'displayName': 'Seussian Rhymes' + } ], + 'type': 'module', + 'displayName': 'Sample Markdown' + } ] + } + }, + { + 'file': common.fixturesDir + '/order_of_end_tags_5873.md', + 'json': { + 'source':'foo', + 'modules': [ { + 'textRaw': 'Title', + 'name': 'title', + 'modules': [ { + 'textRaw': 'Subsection', + 'name': 'subsection', + 'classMethods': [ { + 'textRaw': 'Class Method: Buffer.from(array)', + 'type':'classMethod', + 'name':'from', + 'signatures': [ { + 'params': [ { + 'textRaw': '`array` {Array} ', + 'name': 'array', + 'type': 'Array' + } ] + }, + { + 'params' : [ { + 'name': 'array' + } ] + } + ] + } ], + 'type': 'module', + 'displayName': 'Subsection' + } ], + 'type': 'module', + 'displayName': 'Title' + } ] + } + } +]; + +testData.forEach(function(item) { + fs.readFile(item.file, 'utf8', common.mustCall(function(err, input) { + assert.ifError(err); + json(input, 'foo', common.mustCall(function(err, output) { + assert.ifError(err); + assert.deepStrictEqual(output, item.json); + })); + })); +}); diff --git a/test/doctool/testcfg.py b/test/doctool/testcfg.py new file mode 100644 index 00000000000000..5778d2f0c5ba5a --- /dev/null +++ b/test/doctool/testcfg.py @@ -0,0 +1,7 @@ +import os +import sys +sys.path.append(os.path.join(os.path.dirname(__file__), '..')) +import testpy + +def GetConfiguration(context, root): + return testpy.SimpleTestConfiguration(context, root, 'doctool') diff --git a/test/fixtures/breakpoints.js b/test/fixtures/breakpoints.js index 4824767ff0051d..43cfca1c9b11ab 100644 --- a/test/fixtures/breakpoints.js +++ b/test/fixtures/breakpoints.js @@ -9,12 +9,12 @@ function b() { return ['hello', 'world'].join(' '); } a(); +debugger; a(1); b(); b(); - setInterval(function() { }, 5000); diff --git a/test/fixtures/order_of_end_tags_5873.md b/test/fixtures/order_of_end_tags_5873.md new file mode 100644 index 00000000000000..3eb7dadcb32b1a --- /dev/null +++ b/test/fixtures/order_of_end_tags_5873.md @@ -0,0 +1,6 @@ +# Title + +## Subsection + +### Class Method: Buffer.from(array) +* `array` {Array} diff --git a/test/fixtures/sample_document.md b/test/fixtures/sample_document.md new file mode 100644 index 00000000000000..d1ba308b6d9c26 --- /dev/null +++ b/test/fixtures/sample_document.md @@ -0,0 +1,8 @@ +# Sample Markdown + +## Seussian Rhymes +1. fish +2. fish + +* Red fish +* Blue fish diff --git a/test/internet/test-dgram-broadcast-multi-process.js b/test/internet/test-dgram-broadcast-multi-process.js index 344f6506afdeb1..60bf46b5dc0b71 100644 --- a/test/internet/test-dgram-broadcast-multi-process.js +++ b/test/internet/test-dgram-broadcast-multi-process.js @@ -16,7 +16,7 @@ const messages = [ ]; if (common.inFreeBSDJail) { - console.log('1..0 # Skipped: in a FreeBSD jail'); + common.skip('in a FreeBSD jail'); return; } diff --git a/test/internet/test-dgram-multicast-multi-process.js b/test/internet/test-dgram-multicast-multi-process.js index 69d7bbe3173787..dfbe9a3077b94a 100644 --- a/test/internet/test-dgram-multicast-multi-process.js +++ b/test/internet/test-dgram-multicast-multi-process.js @@ -17,7 +17,7 @@ const listeners = 3; // Skip test in FreeBSD jails. if (common.inFreeBSDJail) { - console.log('1..0 # Skipped: In a FreeBSD jail'); + common.skip('In a FreeBSD jail'); return; } @@ -91,7 +91,7 @@ function launchChildProcess(index) { worker.pid, count); assert.strictEqual(count, messages.length, - 'A worker received an invalid multicast message'); + 'A worker received an invalid multicast message'); }); clearTimeout(timer); diff --git a/test/internet/test-dns-ipv6.js b/test/internet/test-dns-ipv6.js index 38a5c3bf735175..2929361f16ecc8 100644 --- a/test/internet/test-dns-ipv6.js +++ b/test/internet/test-dns-ipv6.js @@ -11,7 +11,7 @@ let running = false; const queue = []; if (!common.hasIPv6) { - console.log('1..0 # Skipped: this test, no IPv6 support'); + common.skip('this test, no IPv6 support'); return; } diff --git a/test/internet/test-http-https-default-ports.js b/test/internet/test-http-https-default-ports.js index dbc50c650332e1..33d5436733f545 100644 --- a/test/internet/test-http-https-default-ports.js +++ b/test/internet/test-http-https-default-ports.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var https = require('https'); diff --git a/test/internet/test-tls-connnect-cnnic.js b/test/internet/test-tls-connnect-cnnic.js index 01e15340c99dfb..038e23d2374584 100644 --- a/test/internet/test-tls-connnect-cnnic.js +++ b/test/internet/test-tls-connnect-cnnic.js @@ -10,7 +10,7 @@ var common = require('../common'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } diff --git a/test/internet/test-tls-connnect-melissadata.js b/test/internet/test-tls-connnect-melissadata.js index 36795f3553050c..7ab7f2aa7a7895 100644 --- a/test/internet/test-tls-connnect-melissadata.js +++ b/test/internet/test-tls-connnect-melissadata.js @@ -4,7 +4,7 @@ var common = require('../common'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } diff --git a/test/internet/test-tls-reuse-host-from-socket.js b/test/internet/test-tls-reuse-host-from-socket.js index 2ba6b5c816cb2f..22af92e2769715 100644 --- a/test/internet/test-tls-reuse-host-from-socket.js +++ b/test/internet/test-tls-reuse-host-from-socket.js @@ -1,27 +1,17 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); +const common = require('../common'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } -var tls = require('tls'); +const tls = require('tls'); -var net = require('net'); -var connected = false; -var secure = false; +const net = require('net'); -process.on('exit', function() { - assert(connected); - assert(secure); - console.log('ok'); -}); - -var socket = net.connect(443, 'www.google.com', function() { - connected = true; - var secureSocket = tls.connect({ socket: socket }, function() { - secure = true; +const socket = net.connect(443, 'www.example.org', common.mustCall(() => { + const secureSocket = tls.connect({socket: socket}, common.mustCall(() => { secureSocket.destroy(); - }); -}); + console.log('ok'); + })); +})); diff --git a/test/known_issues/known_issues.status b/test/known_issues/known_issues.status new file mode 100644 index 00000000000000..12e4b10d06d578 --- /dev/null +++ b/test/known_issues/known_issues.status @@ -0,0 +1,20 @@ +prefix known_issues + +# If a known issue does not apply to a platform, list the test name in the +# appropriate section below, without ".js", followed by ": SKIP". Example: +# sample-test : SKIP + +[true] # This section applies to all platforms + +[$system==win32] +test-stdout-buffer-flush-on-exit: SKIP + +[$system==linux] + +[$system==macos] + +[$system==solaris] + +[$system==freebsd] + +[$system==aix] diff --git a/test/known_issues/test-stdout-buffer-flush-on-exit.js b/test/known_issues/test-stdout-buffer-flush-on-exit.js index f4ea0b5e01b2e1..be290810079956 100644 --- a/test/known_issues/test-stdout-buffer-flush-on-exit.js +++ b/test/known_issues/test-stdout-buffer-flush-on-exit.js @@ -5,16 +5,23 @@ require('../common'); const assert = require('assert'); const execSync = require('child_process').execSync; -const longLine = 'foo bar baz quux quuz aaa bbb ccc'.repeat(65536); +const lineSeed = 'foo bar baz quux quuz aaa bbb ccc'; if (process.argv[2] === 'child') { + const longLine = lineSeed.repeat(parseInt(process.argv[4], 10)); process.on('exit', () => { console.log(longLine); }); process.exit(); } -const cmd = `${process.execPath} ${__filename} child`; -const stdout = execSync(cmd).toString().trim(); +[16, 18, 20].forEach((exponent) => { + const bigNum = Math.pow(2, exponent); + const longLine = lineSeed.repeat(bigNum); + const cmd = `${process.execPath} ${__filename} child ${exponent} ${bigNum}`; + const stdout = execSync(cmd).toString().trim(); + + assert.strictEqual(stdout, longLine, `failed with exponent ${exponent}`); +}); + -assert.strictEqual(stdout, longLine); diff --git a/test/parallel/test-assert.js b/test/parallel/test-assert.js index 460829a16ea884..80af439e7f36ec 100644 --- a/test/parallel/test-assert.js +++ b/test/parallel/test-assert.js @@ -461,7 +461,7 @@ try { } catch (e) { assert.equal(e.toString().split('\n')[0], 'AssertionError: oh no'); assert.equal(e.generatedMessage, false, - 'Message incorrectly marked as generated'); + 'Message incorrectly marked as generated'); } // Verify that throws() and doesNotThrow() throw on non-function block diff --git a/test/parallel/test-buffer.js b/test/parallel/test-buffer.js index 99d1c129ca8805..d0ebe64db9453a 100644 --- a/test/parallel/test-buffer.js +++ b/test/parallel/test-buffer.js @@ -464,17 +464,17 @@ assert.equal('TWFu', (new Buffer('Man')).toString('base64')); { // big example const quote = 'Man is distinguished, not only by his reason, but by this ' + - 'singular passion from other animals, which is a lust ' + - 'of the mind, that by a perseverance of delight in the ' + - 'continued and indefatigable generation of knowledge, exceeds ' + - 'the short vehemence of any carnal pleasure.'; + 'singular passion from other animals, which is a lust ' + + 'of the mind, that by a perseverance of delight in the ' + + 'continued and indefatigable generation of knowledge, ' + + 'exceeds the short vehemence of any carnal pleasure.'; const expected = 'TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb' + - '24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBh' + - 'bmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnk' + - 'gYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIG' + - 'FuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBle' + - 'GNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVh' + - 'c3VyZS4='; + '24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlci' + + 'BhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQ' + + 'gYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGlu' + + 'dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZ' + + 'GdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm' + + '5hbCBwbGVhc3VyZS4='; assert.equal(expected, (new Buffer(quote)).toString('base64')); let b = new Buffer(1024); @@ -484,11 +484,11 @@ assert.equal('TWFu', (new Buffer('Man')).toString('base64')); // check that the base64 decoder ignores whitespace const expectedWhite = expected.slice(0, 60) + ' \n' + - expected.slice(60, 120) + ' \n' + - expected.slice(120, 180) + ' \n' + - expected.slice(180, 240) + ' \n' + - expected.slice(240, 300) + '\n' + - expected.slice(300, 360) + '\n'; + expected.slice(60, 120) + ' \n' + + expected.slice(120, 180) + ' \n' + + expected.slice(180, 240) + ' \n' + + expected.slice(240, 300) + '\n' + + expected.slice(300, 360) + '\n'; b = new Buffer(1024); bytesWritten = b.write(expectedWhite, 0, 'base64'); assert.equal(quote.length, bytesWritten); @@ -502,11 +502,11 @@ assert.equal('TWFu', (new Buffer('Man')).toString('base64')); // check that the base64 decoder ignores illegal chars const expectedIllegal = expected.slice(0, 60) + ' \x80' + - expected.slice(60, 120) + ' \xff' + - expected.slice(120, 180) + ' \x00' + - expected.slice(180, 240) + ' \x98' + - expected.slice(240, 300) + '\x03' + - expected.slice(300, 360); + expected.slice(60, 120) + ' \xff' + + expected.slice(120, 180) + ' \x00' + + expected.slice(180, 240) + ' \x98' + + expected.slice(240, 300) + '\x03' + + expected.slice(300, 360); b = new Buffer(expectedIllegal, 'base64'); assert.equal(quote.length, b.length); assert.equal(quote, b.toString('ascii', 0, quote.length)); @@ -571,18 +571,30 @@ assert.equal(new Buffer('KioqKioqKioqKioqKioqKioqKio', 'base64').toString(), '********************'); // handle padding graciously, multiple-of-4 or not -assert.equal(new Buffer('72INjkR5fchcxk9+VgdGPFJDxUBFR5/rMFsghgxADiw==', - 'base64').length, 32); -assert.equal(new Buffer('72INjkR5fchcxk9+VgdGPFJDxUBFR5/rMFsghgxADiw=', - 'base64').length, 32); -assert.equal(new Buffer('72INjkR5fchcxk9+VgdGPFJDxUBFR5/rMFsghgxADiw', - 'base64').length, 32); -assert.equal(new Buffer('w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg==', - 'base64').length, 31); -assert.equal(new Buffer('w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg=', - 'base64').length, 31); -assert.equal(new Buffer('w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg', - 'base64').length, 31); +assert.equal( + new Buffer('72INjkR5fchcxk9+VgdGPFJDxUBFR5/rMFsghgxADiw==', 'base64').length, + 32 +); +assert.equal( + new Buffer('72INjkR5fchcxk9+VgdGPFJDxUBFR5/rMFsghgxADiw=', 'base64').length, + 32 +); +assert.equal( + new Buffer('72INjkR5fchcxk9+VgdGPFJDxUBFR5/rMFsghgxADiw', 'base64').length, + 32 +); +assert.equal( + new Buffer('w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg==', 'base64').length, + 31 +); +assert.equal( + new Buffer('w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg=', 'base64').length, + 31 +); +assert.equal( + new Buffer('w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg', 'base64').length, + 31 +); // This string encodes single '.' character in UTF-16 var dot = new Buffer('//4uAA==', 'base64'); @@ -1273,7 +1285,7 @@ if (common.hasCrypto) { crypto.createHash('sha1').update(b2).digest('hex') ); } else { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); } // Test Compare diff --git a/test/parallel/test-child-process-fork-dgram.js b/test/parallel/test-child-process-fork-dgram.js index b4904c51b1714f..ce2535a0605122 100644 --- a/test/parallel/test-child-process-fork-dgram.js +++ b/test/parallel/test-child-process-fork-dgram.js @@ -19,7 +19,7 @@ var assert = require('assert'); var common = require('../common'); if (common.isWindows) { - console.log('1..0 # Skipped: Sending dgram sockets to child processes is ' + + common.skip('Sending dgram sockets to child processes is ' + 'not supported'); return; } diff --git a/test/parallel/test-cluster-basic.js b/test/parallel/test-cluster-basic.js index 60bd27b24eee89..5a5efabbab821a 100644 --- a/test/parallel/test-cluster-basic.js +++ b/test/parallel/test-cluster-basic.js @@ -4,7 +4,7 @@ var assert = require('assert'); var cluster = require('cluster'); assert.equal('NODE_UNIQUE_ID' in process.env, false, - 'NODE_UNIQUE_ID should be removed on startup'); + 'NODE_UNIQUE_ID should be removed on startup'); function forEach(obj, fn) { Object.keys(obj).forEach(function(name, index) { @@ -93,7 +93,7 @@ else if (cluster.isMaster) { worker = cluster.fork(); assert.equal(worker.id, 1); assert.ok(worker instanceof cluster.Worker, - 'the worker is not a instance of the Worker constructor'); + 'the worker is not a instance of the Worker constructor'); //Check event forEach(checks.worker.events, function(bool, name, index) { diff --git a/test/parallel/test-cluster-bind-privileged-port.js b/test/parallel/test-cluster-bind-privileged-port.js index 56449eaaf2e02f..9f4ef8ee5e8b81 100644 --- a/test/parallel/test-cluster-bind-privileged-port.js +++ b/test/parallel/test-cluster-bind-privileged-port.js @@ -5,12 +5,12 @@ var cluster = require('cluster'); var net = require('net'); if (common.isWindows) { - console.log('1..0 # Skipped: not reliable on Windows.'); + common.skip('not reliable on Windows.'); return; } if (process.getuid() === 0) { - console.log('1..0 # Skipped: Test is not supposed to be run as root.'); + common.skip('Test is not supposed to be run as root.'); return; } diff --git a/test/parallel/test-cluster-dgram-1.js b/test/parallel/test-cluster-dgram-1.js index 9404c55f2bb547..b1164e3653abdc 100644 --- a/test/parallel/test-cluster-dgram-1.js +++ b/test/parallel/test-cluster-dgram-1.js @@ -9,7 +9,7 @@ var dgram = require('dgram'); if (common.isWindows) { - console.log('1..0 # Skipped: dgram clustering is currently not supported ' + + common.skip('dgram clustering is currently not supported ' + 'on windows.'); return; } diff --git a/test/parallel/test-cluster-dgram-2.js b/test/parallel/test-cluster-dgram-2.js index 69e9e9d7500f59..d963dc09c6682c 100644 --- a/test/parallel/test-cluster-dgram-2.js +++ b/test/parallel/test-cluster-dgram-2.js @@ -8,7 +8,7 @@ var dgram = require('dgram'); if (common.isWindows) { - console.log('1..0 # Skipped: dgram clustering is currently not supported ' + + common.skip('dgram clustering is currently not supported ' + 'on windows.'); return; } diff --git a/test/parallel/test-cluster-dgram-reuse.js b/test/parallel/test-cluster-dgram-reuse.js index 1de6ad1e5f74dc..bd39a3958de4e6 100644 --- a/test/parallel/test-cluster-dgram-reuse.js +++ b/test/parallel/test-cluster-dgram-reuse.js @@ -5,7 +5,7 @@ const cluster = require('cluster'); const dgram = require('dgram'); if (common.isWindows) { - console.log('1..0 # Skipped: dgram clustering is currently not supported ' + + common.skip('dgram clustering is currently not supported ' + 'on windows.'); return; } diff --git a/test/parallel/test-cluster-disconnect-handles.js b/test/parallel/test-cluster-disconnect-handles.js index 0ae0a0406f4db8..e2015254c5247b 100644 --- a/test/parallel/test-cluster-disconnect-handles.js +++ b/test/parallel/test-cluster-disconnect-handles.js @@ -10,7 +10,7 @@ const net = require('net'); const Protocol = require('_debugger').Protocol; if (common.isWindows) { - console.log('1..0 # Skipped: SCHED_RR not reliable on Windows'); + common.skip('SCHED_RR not reliable on Windows'); return; } diff --git a/test/parallel/test-cluster-disconnect-race.js b/test/parallel/test-cluster-disconnect-race.js index 97d55a20b1ac51..e89b9e134fa83f 100644 --- a/test/parallel/test-cluster-disconnect-race.js +++ b/test/parallel/test-cluster-disconnect-race.js @@ -9,7 +9,7 @@ const net = require('net'); const cluster = require('cluster'); if (common.isWindows) { - console.log('1..0 # Skipped: This test does not apply to Windows.'); + common.skip('This test does not apply to Windows.'); return; } diff --git a/test/parallel/test-cluster-disconnect-unshared-udp.js b/test/parallel/test-cluster-disconnect-unshared-udp.js index 2547ffae1f66f1..902538485d1c6f 100644 --- a/test/parallel/test-cluster-disconnect-unshared-udp.js +++ b/test/parallel/test-cluster-disconnect-unshared-udp.js @@ -3,7 +3,7 @@ const common = require('../common'); if (common.isWindows) { - console.log('1..0 # Skipped: on windows, because clustered dgram is ENOTSUP'); + common.skip('on windows, because clustered dgram is ENOTSUP'); return; } diff --git a/test/parallel/test-cluster-http-pipe.js b/test/parallel/test-cluster-http-pipe.js index cb9b090f08e801..8ea634b3034ebb 100644 --- a/test/parallel/test-cluster-http-pipe.js +++ b/test/parallel/test-cluster-http-pipe.js @@ -6,7 +6,7 @@ const cluster = require('cluster'); const http = require('http'); if (common.isWindows) { - console.log('1..0 # Skipped: It is not possible to send pipe handles over ' + + common.skip('It is not possible to send pipe handles over ' + 'the IPC pipe on Windows'); return; } diff --git a/test/parallel/test-cluster-shared-handle-bind-privileged-port.js b/test/parallel/test-cluster-shared-handle-bind-privileged-port.js index a02a2ef5b6b4f1..90bab2febe41e7 100644 --- a/test/parallel/test-cluster-shared-handle-bind-privileged-port.js +++ b/test/parallel/test-cluster-shared-handle-bind-privileged-port.js @@ -5,12 +5,12 @@ var cluster = require('cluster'); var net = require('net'); if (common.isWindows) { - console.log('1..0 # Skipped: not reliable on Windows'); + common.skip('not reliable on Windows'); return; } if (process.getuid() === 0) { - console.log('1..0 # Skipped: as this test should not be run as `root`'); + common.skip('as this test should not be run as `root`'); return; } diff --git a/test/parallel/test-cluster-worker-exit.js b/test/parallel/test-cluster-worker-exit.js index ccb213f0df9601..60c80ec938555d 100644 --- a/test/parallel/test-cluster-worker-exit.js +++ b/test/parallel/test-cluster-worker-exit.js @@ -107,7 +107,7 @@ function checkResults(expected_results, results) { const expected = expected_results[k]; var msg = (expected[1] || '') + - (' [expected: ' + expected[0] + ' / actual: ' + actual + ']'); + (' [expected: ' + expected[0] + ' / actual: ' + actual + ']'); if (expected && expected.length) { assert.equal(actual, expected[0], msg); diff --git a/test/parallel/test-cluster-worker-kill.js b/test/parallel/test-cluster-worker-kill.js index 1f44c93488b1e6..7c2465f9a463d1 100644 --- a/test/parallel/test-cluster-worker-kill.js +++ b/test/parallel/test-cluster-worker-kill.js @@ -90,7 +90,7 @@ function checkResults(expected_results, results) { const expected = expected_results[k]; var msg = (expected[1] || '') + - (' [expected: ' + expected[0] + ' / actual: ' + actual + ']'); + (' [expected: ' + expected[0] + ' / actual: ' + actual + ']'); if (expected && expected.length) { assert.equal(actual, expected[0], msg); } else { diff --git a/test/parallel/test-crypto-authenticated.js b/test/parallel/test-crypto-authenticated.js index fa9a78c26e5b59..57edb3f7d134c1 100644 --- a/test/parallel/test-crypto-authenticated.js +++ b/test/parallel/test-crypto-authenticated.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var crypto = require('crypto'); @@ -56,7 +56,7 @@ for (var i in TEST_CASES) { var test = TEST_CASES[i]; if (ciphers.indexOf(test.algo) == -1) { - console.log('1..0 # Skipped: unsupported ' + test.algo + ' test'); + common.skip('unsupported ' + test.algo + ' test'); continue; } diff --git a/test/parallel/test-crypto-binary-default.js b/test/parallel/test-crypto-binary-default.js index 6418f52fd16397..129bbcacef151e 100644 --- a/test/parallel/test-crypto-binary-default.js +++ b/test/parallel/test-crypto-binary-default.js @@ -8,7 +8,7 @@ var assert = require('assert'); var constants = require('constants'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var crypto = require('crypto'); @@ -347,8 +347,11 @@ var a4 = crypto.createHash('sha1').update('Test123').digest('buffer'); if (!common.hasFipsCrypto) { var a0 = crypto.createHash('md5').update('Test123').digest('binary'); - assert.equal(a0, 'h\u00ea\u00cb\u0097\u00d8o\fF!\u00fa+\u000e\u0017\u00ca' + - '\u00bd\u008c', 'Test MD5 as binary'); + assert.equal( + a0, + 'h\u00ea\u00cb\u0097\u00d8o\fF!\u00fa+\u000e\u0017\u00ca\u00bd\u008c', + 'Test MD5 as binary' + ); } assert.equal(a1, '8308651804facb7b9af8ffc53a33a22d6a1c8ac2', 'Test SHA1'); diff --git a/test/parallel/test-crypto-certificate.js b/test/parallel/test-crypto-certificate.js index 9948303f32315e..66a5da04073825 100644 --- a/test/parallel/test-crypto-certificate.js +++ b/test/parallel/test-crypto-certificate.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var crypto = require('crypto'); diff --git a/test/parallel/test-crypto-cipher-decipher.js b/test/parallel/test-crypto-cipher-decipher.js index 5f867739abe7ed..2f03aa5db4db52 100644 --- a/test/parallel/test-crypto-cipher-decipher.js +++ b/test/parallel/test-crypto-cipher-decipher.js @@ -3,11 +3,11 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } if (common.hasFipsCrypto) { - console.log('1..0 # Skipped: not supported in FIPS mode'); + common.skip('not supported in FIPS mode'); return; } var crypto = require('crypto'); diff --git a/test/parallel/test-crypto-cipheriv-decipheriv.js b/test/parallel/test-crypto-cipheriv-decipheriv.js index d325c0facf7e54..377f0f3ee43615 100644 --- a/test/parallel/test-crypto-cipheriv-decipheriv.js +++ b/test/parallel/test-crypto-cipheriv-decipheriv.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var crypto = require('crypto'); diff --git a/test/parallel/test-crypto-dh-odd-key.js b/test/parallel/test-crypto-dh-odd-key.js index 503ba2fe089e3e..13c9844084395a 100644 --- a/test/parallel/test-crypto-dh-odd-key.js +++ b/test/parallel/test-crypto-dh-odd-key.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var crypto = require('crypto'); diff --git a/test/parallel/test-crypto-dh.js b/test/parallel/test-crypto-dh.js index d3919457ea5033..e6b1de2475c897 100644 --- a/test/parallel/test-crypto-dh.js +++ b/test/parallel/test-crypto-dh.js @@ -4,7 +4,7 @@ var assert = require('assert'); var constants = require('constants'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var crypto = require('crypto'); diff --git a/test/parallel/test-crypto-domain.js b/test/parallel/test-crypto-domain.js index 349ce7e1fc9e9d..9bb6c0229648e7 100644 --- a/test/parallel/test-crypto-domain.js +++ b/test/parallel/test-crypto-domain.js @@ -4,7 +4,7 @@ var assert = require('assert'); var domain = require('domain'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var crypto = require('crypto'); diff --git a/test/parallel/test-crypto-domains.js b/test/parallel/test-crypto-domains.js index ca93d20fdf25b3..9036228bf6b16d 100644 --- a/test/parallel/test-crypto-domains.js +++ b/test/parallel/test-crypto-domains.js @@ -7,7 +7,7 @@ var expect = ['pbkdf2', 'randomBytes', 'pseudoRandomBytes']; var errors = 0; if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var crypto = require('crypto'); diff --git a/test/parallel/test-crypto-ecb.js b/test/parallel/test-crypto-ecb.js index d47ec8a8091f38..dbdb486e9bcf7f 100644 --- a/test/parallel/test-crypto-ecb.js +++ b/test/parallel/test-crypto-ecb.js @@ -3,11 +3,11 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } if (common.hasFipsCrypto) { - console.log('1..0 # Skipped: BF-ECB is not FIPS 140-2 compatible'); + common.skip('BF-ECB is not FIPS 140-2 compatible'); return; } var crypto = require('crypto'); diff --git a/test/parallel/test-crypto-from-binary.js b/test/parallel/test-crypto-from-binary.js index b2782e04f28ff0..3bd27efffd2c5f 100644 --- a/test/parallel/test-crypto-from-binary.js +++ b/test/parallel/test-crypto-from-binary.js @@ -7,7 +7,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var crypto = require('crypto'); diff --git a/test/parallel/test-crypto-hash-stream-pipe.js b/test/parallel/test-crypto-hash-stream-pipe.js index c41f91241d58ea..a2b19a69e5bb31 100644 --- a/test/parallel/test-crypto-hash-stream-pipe.js +++ b/test/parallel/test-crypto-hash-stream-pipe.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var crypto = require('crypto'); diff --git a/test/parallel/test-crypto-hash.js b/test/parallel/test-crypto-hash.js index 90ff1fd727d104..8272aedcc51e1f 100644 --- a/test/parallel/test-crypto-hash.js +++ b/test/parallel/test-crypto-hash.js @@ -5,7 +5,7 @@ var fs = require('fs'); var path = require('path'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var crypto = require('crypto'); @@ -39,8 +39,11 @@ a8 = a8.read(); if (!common.hasFipsCrypto) { var a0 = crypto.createHash('md5').update('Test123').digest('binary'); - assert.equal(a0, 'h\u00ea\u00cb\u0097\u00d8o\fF!\u00fa+\u000e\u0017\u00ca' + - '\u00bd\u008c', 'Test MD5 as binary'); + assert.equal( + a0, + 'h\u00ea\u00cb\u0097\u00d8o\fF!\u00fa+\u000e\u0017\u00ca\u00bd\u008c', + 'Test MD5 as binary' + ); } assert.equal(a1, '8308651804facb7b9af8ffc53a33a22d6a1c8ac2', 'Test SHA1'); assert.equal(a2, '2bX1jws4GYKTlxhloUB09Z66PoJZW+y+hq5R8dnx9l4=', diff --git a/test/parallel/test-crypto-hmac.js b/test/parallel/test-crypto-hmac.js index 600dd0dbb2c8bd..cc92e048524cf1 100644 --- a/test/parallel/test-crypto-hmac.js +++ b/test/parallel/test-crypto-hmac.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var crypto = require('crypto'); diff --git a/test/parallel/test-crypto-padding-aes256.js b/test/parallel/test-crypto-padding-aes256.js index 550aa5c061f7ef..97ed6bab29d021 100644 --- a/test/parallel/test-crypto-padding-aes256.js +++ b/test/parallel/test-crypto-padding-aes256.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var crypto = require('crypto'); diff --git a/test/parallel/test-crypto-padding.js b/test/parallel/test-crypto-padding.js index bc2011d3d892f5..a6174728735601 100644 --- a/test/parallel/test-crypto-padding.js +++ b/test/parallel/test-crypto-padding.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var crypto = require('crypto'); diff --git a/test/parallel/test-crypto-pbkdf2.js b/test/parallel/test-crypto-pbkdf2.js index b48b1edd5baf8b..0b0ab13cbbfc5d 100644 --- a/test/parallel/test-crypto-pbkdf2.js +++ b/test/parallel/test-crypto-pbkdf2.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var crypto = require('crypto'); diff --git a/test/parallel/test-crypto-random.js b/test/parallel/test-crypto-random.js index 2d28cccc4cfa3c..b4e36dfa045c05 100644 --- a/test/parallel/test-crypto-random.js +++ b/test/parallel/test-crypto-random.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var crypto = require('crypto'); diff --git a/test/parallel/test-crypto-rsa-dsa.js b/test/parallel/test-crypto-rsa-dsa.js index bd13ef0d912a61..ee3868e539afad 100644 --- a/test/parallel/test-crypto-rsa-dsa.js +++ b/test/parallel/test-crypto-rsa-dsa.js @@ -5,7 +5,7 @@ var fs = require('fs'); var constants = require('constants'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var crypto = require('crypto'); diff --git a/test/parallel/test-crypto-sign-verify.js b/test/parallel/test-crypto-sign-verify.js index 1bfaad3f7d026b..e8d892a8d63f15 100644 --- a/test/parallel/test-crypto-sign-verify.js +++ b/test/parallel/test-crypto-sign-verify.js @@ -4,7 +4,7 @@ var assert = require('assert'); var fs = require('fs'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var crypto = require('crypto'); diff --git a/test/parallel/test-crypto-stream.js b/test/parallel/test-crypto-stream.js index bf0fc2ca1d00df..652b81eab44878 100644 --- a/test/parallel/test-crypto-stream.js +++ b/test/parallel/test-crypto-stream.js @@ -5,7 +5,7 @@ var stream = require('stream'); var util = require('util'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var crypto = require('crypto'); diff --git a/test/parallel/test-crypto-verify-failure.js b/test/parallel/test-crypto-verify-failure.js index 2bc4ce5433739d..f260ccfe128eaf 100644 --- a/test/parallel/test-crypto-verify-failure.js +++ b/test/parallel/test-crypto-verify-failure.js @@ -2,7 +2,7 @@ var common = require('../common'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var crypto = require('crypto'); diff --git a/test/parallel/test-crypto.js b/test/parallel/test-crypto.js index 192e4287c47d03..271541d54a242d 100644 --- a/test/parallel/test-crypto.js +++ b/test/parallel/test-crypto.js @@ -4,7 +4,7 @@ var assert = require('assert'); var util = require('util'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var crypto = require('crypto'); diff --git a/test/parallel/test-cwd-enoent-preload.js b/test/parallel/test-cwd-enoent-preload.js index 7f11880ee0278a..b2f7ae0a4aed08 100644 --- a/test/parallel/test-cwd-enoent-preload.js +++ b/test/parallel/test-cwd-enoent-preload.js @@ -6,7 +6,7 @@ const spawn = require('child_process').spawn; // Fails with EINVAL on SmartOS, EBUSY on Windows, EBUSY on AIX. if (process.platform === 'sunos' || common.isWindows || common.isAix) { - console.log('1..0 # Skipped: cannot rmdir current working directory'); + common.skip('cannot rmdir current working directory'); return; } diff --git a/test/parallel/test-cwd-enoent-repl.js b/test/parallel/test-cwd-enoent-repl.js index 82342ce64487a3..3c8b543cf139d6 100644 --- a/test/parallel/test-cwd-enoent-repl.js +++ b/test/parallel/test-cwd-enoent-repl.js @@ -6,7 +6,7 @@ var spawn = require('child_process').spawn; // Fails with EINVAL on SmartOS, EBUSY on Windows, EBUSY on AIX. if (process.platform === 'sunos' || common.isWindows || common.isAix) { - console.log('1..0 # Skipped: cannot rmdir current working directory'); + common.skip('cannot rmdir current working directory'); return; } diff --git a/test/parallel/test-cwd-enoent.js b/test/parallel/test-cwd-enoent.js index c6b3925ce3baa3..9ff9f86405a333 100644 --- a/test/parallel/test-cwd-enoent.js +++ b/test/parallel/test-cwd-enoent.js @@ -6,7 +6,7 @@ var spawn = require('child_process').spawn; // Fails with EINVAL on SmartOS, EBUSY on Windows, EBUSY on AIX. if (process.platform === 'sunos' || common.isWindows || common.isAix) { - console.log('1..0 # Skipped: cannot rmdir current working directory'); + common.skip('cannot rmdir current working directory'); return; } diff --git a/test/parallel/test-dgram-bind-default-address.js b/test/parallel/test-dgram-bind-default-address.js index 75069e3618623a..3d786209260408 100644 --- a/test/parallel/test-dgram-bind-default-address.js +++ b/test/parallel/test-dgram-bind-default-address.js @@ -5,7 +5,7 @@ var dgram = require('dgram'); // skip test in FreeBSD jails since 0.0.0.0 will resolve to default interface if (common.inFreeBSDJail) { - console.log('1..0 # Skipped: In a FreeBSD jail'); + common.skip('In a FreeBSD jail'); return; } @@ -16,7 +16,7 @@ dgram.createSocket('udp4').bind(common.PORT + 0, common.mustCall(function() { })); if (!common.hasIPv6) { - console.log('1..0 # Skipped: udp6 part of test, because no IPv6 support'); + common.skip('udp6 part of test, because no IPv6 support'); return; } diff --git a/test/parallel/test-dgram-empty-packet.js b/test/parallel/test-dgram-empty-packet.js index 66cdbb92ac8f1b..696102bcb9f303 100644 --- a/test/parallel/test-dgram-empty-packet.js +++ b/test/parallel/test-dgram-empty-packet.js @@ -7,7 +7,7 @@ var client; var timer; if (process.platform === 'darwin') { - console.log('1..0 # Skipped: because of 17894467 Apple bug'); + common.skip('because of 17894467 Apple bug'); return; } diff --git a/test/parallel/test-dgram-membership.js b/test/parallel/test-dgram-membership.js new file mode 100644 index 00000000000000..ed5fb2897cbd3a --- /dev/null +++ b/test/parallel/test-dgram-membership.js @@ -0,0 +1,87 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const dgram = require('dgram'); +const multicastAddress = '224.0.0.114'; + +const setup = () => { + return dgram.createSocket({type: 'udp4', reuseAddr: true}); +}; + +// addMembership() on closed socket should throw +{ + const socket = setup(); + socket.close(common.mustCall(() => { + assert.throws(() => { socket.addMembership(multicastAddress); }, + /Not running/); + })); +} + +// dropMembership() on closed socket should throw +{ + const socket = setup(); + socket.close(common.mustCall(() => { + assert.throws(() => { socket.dropMembership(multicastAddress); }, + /Not running/); + })); +} + +// addMembership() with no argument should throw +{ + const socket = setup(); + assert.throws(() => { socket.addMembership(); }, + /multicast address must be specified/); + socket.close(); +} + +// dropMembership() with no argument should throw +{ + const socket = setup(); + assert.throws(() => { socket.dropMembership(); }, + /multicast address must be specified/); + socket.close(); +} + +// addMembership() with invalid multicast address should throw +{ + const socket = setup(); + assert.throws(() => { socket.addMembership('256.256.256.256'); }, /EINVAL/); + socket.close(); +} + +// dropMembership() with invalid multicast address should throw +{ + const socket = setup(); + assert.throws(() => { socket.dropMembership('256.256.256.256'); }, /EINVAL/); + socket.close(); +} + +// addMembership() with valid socket and multicast address should not throw +{ + const socket = setup(); + assert.doesNotThrow(() => { socket.addMembership(multicastAddress); }); + socket.close(); +} + +// dropMembership() without previous addMembership should throw +{ + const socket = setup(); + assert.throws( + () => { socket.dropMembership(multicastAddress); }, + /EADDRNOTAVAIL/ + ); + socket.close(); +} + +// dropMembership() after addMembership() should not throw +{ + const socket = setup(); + assert.doesNotThrow( + () => { + socket.addMembership(multicastAddress); + socket.dropMembership(multicastAddress); + } + ); + socket.close(); +} diff --git a/test/parallel/test-dgram-send-empty-buffer.js b/test/parallel/test-dgram-send-empty-buffer.js index 6732bab159ee49..190a3fe61edefe 100644 --- a/test/parallel/test-dgram-send-empty-buffer.js +++ b/test/parallel/test-dgram-send-empty-buffer.js @@ -3,7 +3,7 @@ const common = require('../common'); const dgram = require('dgram'); if (process.platform === 'darwin') { - console.log('1..0 # Skipped: because of 17894467 Apple bug'); + common.skip('because of 17894467 Apple bug'); return; } diff --git a/test/parallel/test-dh-padding.js b/test/parallel/test-dh-padding.js index 7d482b78f63a7c..a9cd95225abedb 100644 --- a/test/parallel/test-dh-padding.js +++ b/test/parallel/test-dh-padding.js @@ -1,11 +1,11 @@ 'use strict'; -require('../common'); +const common = require('../common'); var assert = require('assert'); try { var crypto = require('crypto'); } catch (e) { - console.log('1..0 # Skipped: node compiled without OpenSSL.'); + common.skip('node compiled without OpenSSL.'); return; } diff --git a/test/parallel/test-domain-crypto.js b/test/parallel/test-domain-crypto.js index e6dbccf86ca39e..1109591fee9631 100644 --- a/test/parallel/test-domain-crypto.js +++ b/test/parallel/test-domain-crypto.js @@ -1,14 +1,16 @@ -/* eslint-disable required-modules */ 'use strict'; +const common = require('../common'); + try { var crypto = require('crypto'); } catch (e) { - console.log('1..0 # Skipped: node compiled without OpenSSL.'); + common.skip('node compiled without OpenSSL.'); return; } // Pollution of global is intentional as part of test. +common.globalCheck = false; // See https://github.com/nodejs/node/commit/d1eff9ab global.domain = require('domain'); diff --git a/test/parallel/test-domain-exit-dispose-again.js b/test/parallel/test-domain-exit-dispose-again.js index 7360e79412296d..0928addd9ace55 100644 --- a/test/parallel/test-domain-exit-dispose-again.js +++ b/test/parallel/test-domain-exit-dispose-again.js @@ -38,7 +38,7 @@ setTimeout(function firstTimer() { d.dispose(); console.error(err); console.error('in domain error handler', - process.domain, process.domain === d); + process.domain, process.domain === d); }); d.run(function() { diff --git a/test/parallel/test-domain-no-error-handler-abort-on-uncaught.js b/test/parallel/test-domain-no-error-handler-abort-on-uncaught.js index 1ed7b1ee636e06..9fedba4ee6c541 100644 --- a/test/parallel/test-domain-no-error-handler-abort-on-uncaught.js +++ b/test/parallel/test-domain-no-error-handler-abort-on-uncaught.js @@ -182,8 +182,8 @@ if (process.argv[2] === 'child') { child.on('exit', function onExit(exitCode, signal) { const errMsg = 'Test at index ' + testIndex + ' should have aborted ' + - 'but instead exited with exit code ' + exitCode + ' and signal ' + - signal; + 'but instead exited with exit code ' + exitCode + + ' and signal ' + signal; assert(common.nodeProcessAborted(exitCode, signal), errMsg); }); }); diff --git a/test/parallel/test-domain-throw-error-then-throw-from-uncaught-exception-handler.js b/test/parallel/test-domain-throw-error-then-throw-from-uncaught-exception-handler.js index 499988107dae27..ae86ef2cdf20d3 100644 --- a/test/parallel/test-domain-throw-error-then-throw-from-uncaught-exception-handler.js +++ b/test/parallel/test-domain-throw-error-then-throw-from-uncaught-exception-handler.js @@ -62,8 +62,8 @@ function runTestWithoutAbortOnUncaughtException() { 'include domain\'s error\'s message'); assert.notEqual(err.code, 0, - 'child process should have exited with a non-zero exit code, ' + - 'but did not'); + 'child process should have exited with a non-zero ' + + 'exit code, but did not'); }); } @@ -72,8 +72,8 @@ function runTestWithAbortOnUncaughtException() { withAbortOnUncaughtException: true }), function onTestDone(err, stdout, stderr) { assert.notEqual(err.code, RAN_UNCAUGHT_EXCEPTION_HANDLER_EXIT_CODE, - 'child process should not have run its uncaughtException event ' + - 'handler'); + 'child process should not have run its uncaughtException ' + + 'event handler'); assert(common.nodeProcessAborted(err.code, err.signal), 'process should have aborted, but did not'); }); diff --git a/test/parallel/test-domain-timers.js b/test/parallel/test-domain-timers.js index a97b300da02d31..58989e812bba50 100644 --- a/test/parallel/test-domain-timers.js +++ b/test/parallel/test-domain-timers.js @@ -34,7 +34,7 @@ timeout = setTimeout(function() {}, 10 * 1000); process.on('exit', function() { assert.equal(timeout_err.message, 'Timeout UNREFd', - 'Domain should catch timer error'); + 'Domain should catch timer error'); assert.equal(immediate_err.message, 'Immediate Error', - 'Domain should catch immediate error'); + 'Domain should catch immediate error'); }); diff --git a/test/parallel/test-domain-top-level-error-handler-clears-stack.js b/test/parallel/test-domain-top-level-error-handler-clears-stack.js index a5fec1f65ef029..f2095f09b7836c 100644 --- a/test/parallel/test-domain-top-level-error-handler-clears-stack.js +++ b/test/parallel/test-domain-top-level-error-handler-clears-stack.js @@ -23,7 +23,7 @@ d.on('error', common.mustCall(function() { // call to process._fatalException, and so on recursively and // indefinitely. console.error('domains stack length should be 1, but instead is:', - domain._stack.length); + domain._stack.length); process.exit(1); } }); diff --git a/test/parallel/test-dsa-fips-invalid-key.js b/test/parallel/test-dsa-fips-invalid-key.js index 2d30ef6891008a..ede3adab66c527 100644 --- a/test/parallel/test-dsa-fips-invalid-key.js +++ b/test/parallel/test-dsa-fips-invalid-key.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasFipsCrypto) { - console.log('1..0 # Skipped: node compiled without FIPS OpenSSL.'); + common.skip('node compiled without FIPS OpenSSL.'); return; } diff --git a/test/parallel/test-error-reporting.js b/test/parallel/test-error-reporting.js index b5b70eeb3b2add..567642d3e83e2b 100644 --- a/test/parallel/test-error-reporting.js +++ b/test/parallel/test-error-reporting.js @@ -8,7 +8,7 @@ var exits = 0; function errExec(script, callback) { var cmd = '"' + process.argv[0] + '" "' + - path.join(common.fixturesDir, script) + '"'; + path.join(common.fixturesDir, script) + '"'; return exec(cmd, function(err, stdout, stderr) { // There was some error assert.ok(err); diff --git a/test/parallel/test-file-write-stream2.js b/test/parallel/test-file-write-stream2.js index e95760bc2d9a4e..e11f7e7815f1d0 100644 --- a/test/parallel/test-file-write-stream2.js +++ b/test/parallel/test-file-write-stream2.js @@ -24,8 +24,8 @@ process.on('exit', function() { console.log(' expected: %j', cb_expected); console.log(' occurred: %j', cb_occurred); assert.strictEqual(cb_occurred, cb_expected, - 'events missing or out of order: "' + - cb_occurred + '" !== "' + cb_expected + '"'); + 'events missing or out of order: "' + + cb_occurred + '" !== "' + cb_expected + '"'); } else { console.log('ok'); } diff --git a/test/parallel/test-file-write-stream3.js b/test/parallel/test-file-write-stream3.js index caa0f106f4d91e..55806e8d22774c 100644 --- a/test/parallel/test-file-write-stream3.js +++ b/test/parallel/test-file-write-stream3.js @@ -24,8 +24,8 @@ process.on('exit', function() { console.log(' expected: %j', cb_expected); console.log(' occurred: %j', cb_occurred); assert.strictEqual(cb_occurred, cb_expected, - 'events missing or out of order: "' + - cb_occurred + '" !== "' + cb_expected + '"'); + 'events missing or out of order: "' + + cb_occurred + '" !== "' + cb_expected + '"'); } }); diff --git a/test/parallel/test-fs-append-file-sync.js b/test/parallel/test-fs-append-file-sync.js index 42e0790e1f7227..78cfaecaf5225c 100644 --- a/test/parallel/test-fs-append-file-sync.js +++ b/test/parallel/test-fs-append-file-sync.js @@ -8,12 +8,12 @@ var currentFileData = 'ABCD'; var num = 220; var data = '南越国是前203年至前111年存在于岭南地区的一个国家,国都位于番禺,疆域包括今天中国的广东、' + - '广西两省区的大部份地区,福建省、湖南、贵州、云南的一小部份地区和越南的北部。' + - '南越国是秦朝灭亡后,由南海郡尉赵佗于前203年起兵兼并桂林郡和象郡后建立。' + - '前196年和前179年,南越国曾先后两次名义上臣属于西汉,成为西汉的“外臣”。前112年,' + - '南越国末代君主赵建德与西汉发生战争,被汉武帝于前111年所灭。南越国共存在93年,' + - '历经五代君主。南越国是岭南地区的第一个有记载的政权国家,采用封建制和郡县制并存的制度,' + - '它的建立保证了秦末乱世岭南地区社会秩序的稳定,有效的改善了岭南地区落后的政治、##济现状。\n'; + '广西两省区的大部份地区,福建省、湖南、贵州、云南的一小部份地区和越南的北部。' + + '南越国是秦朝灭亡后,由南海郡尉赵佗于前203年起兵兼并桂林郡和象郡后建立。' + + '前196年和前179年,南越国曾先后两次名义上臣属于西汉,成为西汉的“外臣”。前112年,' + + '南越国末代君主赵建德与西汉发生战争,被汉武帝于前111年所灭。南越国共存在93年,' + + '历经五代君主。南越国是岭南地区的第一个有记载的政权国家,采用封建制和郡县制并存的制度,' + + '它的建立保证了秦末乱世岭南地区社会秩序的稳定,有效的改善了岭南地区落后的政治、##济现状。\n'; common.refreshTmpDir(); diff --git a/test/parallel/test-fs-long-path.js b/test/parallel/test-fs-long-path.js index eadbcd1f78df98..d0945f1e518e42 100644 --- a/test/parallel/test-fs-long-path.js +++ b/test/parallel/test-fs-long-path.js @@ -5,7 +5,7 @@ var path = require('path'); var assert = require('assert'); if (!common.isWindows) { - console.log('1..0 # Skipped: this test is Windows-specific.'); + common.skip('this test is Windows-specific.'); return; } diff --git a/test/parallel/test-fs-readfile-error.js b/test/parallel/test-fs-readfile-error.js index c61449a2db9b56..c2b3c015512497 100644 --- a/test/parallel/test-fs-readfile-error.js +++ b/test/parallel/test-fs-readfile-error.js @@ -7,7 +7,7 @@ var path = require('path'); // `fs.readFile('/')` does not fail on FreeBSD, because you can open and read // the directory there. if (process.platform === 'freebsd') { - console.log('1..0 # Skipped: platform not supported.'); + common.skip('platform not supported.'); return; } diff --git a/test/parallel/test-fs-readfile-pipe-large.js b/test/parallel/test-fs-readfile-pipe-large.js index a39f66ef80234f..2050e2f4268dda 100644 --- a/test/parallel/test-fs-readfile-pipe-large.js +++ b/test/parallel/test-fs-readfile-pipe-large.js @@ -6,7 +6,7 @@ var path = require('path'); // simulate `cat readfile.js | node readfile.js` if (common.isWindows || common.isAix) { - console.log(`1..0 # Skipped: No /dev/stdin on ${process.platform}.`); + common.skip(`No /dev/stdin on ${process.platform}.`); return; } diff --git a/test/parallel/test-fs-readfile-pipe.js b/test/parallel/test-fs-readfile-pipe.js index d4db43db6edbb9..f9736000a566a1 100644 --- a/test/parallel/test-fs-readfile-pipe.js +++ b/test/parallel/test-fs-readfile-pipe.js @@ -5,7 +5,7 @@ var assert = require('assert'); // simulate `cat readfile.js | node readfile.js` if (common.isWindows || common.isAix) { - console.log(`1..0 # Skipped: No /dev/stdin on ${process.platform}.`); + common.skip(`No /dev/stdin on ${process.platform}.`); return; } diff --git a/test/parallel/test-fs-readfilesync-pipe-large.js b/test/parallel/test-fs-readfilesync-pipe-large.js index ce667094d14fe0..ccee29b5007069 100644 --- a/test/parallel/test-fs-readfilesync-pipe-large.js +++ b/test/parallel/test-fs-readfilesync-pipe-large.js @@ -6,7 +6,7 @@ var path = require('path'); // simulate `cat readfile.js | node readfile.js` if (common.isWindows || common.isAix) { - console.log(`1..0 # Skipped: No /dev/stdin on ${process.platform}.`); + common.skip(`No /dev/stdin on ${process.platform}.`); return; } diff --git a/test/parallel/test-fs-realpath.js b/test/parallel/test-fs-realpath.js index aa397e51d16409..d627c01487c2c2 100644 --- a/test/parallel/test-fs-realpath.js +++ b/test/parallel/test-fs-realpath.js @@ -82,7 +82,7 @@ function test_simple_error_callback(cb) { function test_simple_relative_symlink(callback) { console.log('test_simple_relative_symlink'); if (skipSymlinks) { - console.log('1..0 # Skipped: symlink test (no privs)'); + common.skip('symlink test (no privs)'); return runNextTest(); } const entry = common.tmpDir + '/symlink'; @@ -131,7 +131,7 @@ function test_simple_absolute_symlink(callback) { function test_deep_relative_file_symlink(callback) { console.log('test_deep_relative_file_symlink'); if (skipSymlinks) { - console.log('1..0 # Skipped: symlink test (no privs)'); + common.skip('symlink test (no privs)'); return runNextTest(); } @@ -160,7 +160,7 @@ function test_deep_relative_file_symlink(callback) { function test_deep_relative_dir_symlink(callback) { console.log('test_deep_relative_dir_symlink'); if (skipSymlinks) { - console.log('1..0 # Skipped: symlink test (no privs)'); + common.skip('symlink test (no privs)'); return runNextTest(); } var expected = path.join(common.fixturesDir, 'cycles', 'folder'); @@ -188,7 +188,7 @@ function test_deep_relative_dir_symlink(callback) { function test_cyclic_link_protection(callback) { console.log('test_cyclic_link_protection'); if (skipSymlinks) { - console.log('1..0 # Skipped: symlink test (no privs)'); + common.skip('symlink test (no privs)'); return runNextTest(); } var entry = common.tmpDir + '/cycles/realpath-3a'; @@ -211,7 +211,7 @@ function test_cyclic_link_protection(callback) { function test_cyclic_link_overprotection(callback) { console.log('test_cyclic_link_overprotection'); if (skipSymlinks) { - console.log('1..0 # Skipped: symlink test (no privs)'); + common.skip('symlink test (no privs)'); return runNextTest(); } var cycles = common.tmpDir + '/cycles'; @@ -232,7 +232,7 @@ function test_cyclic_link_overprotection(callback) { function test_relative_input_cwd(callback) { console.log('test_relative_input_cwd'); if (skipSymlinks) { - console.log('1..0 # Skipped: symlink test (no privs)'); + common.skip('symlink test (no privs)'); return runNextTest(); } @@ -271,7 +271,7 @@ function test_deep_symlink_mix(callback) { if (common.isWindows) { // This one is a mix of files and directories, and it's quite tricky // to get the file/dir links sorted out correctly. - console.log('1..0 # Skipped: symlink test (no privs)'); + common.skip('symlink test (no privs)'); return runNextTest(); } @@ -338,14 +338,14 @@ function test_escape_cwd(cb) { console.log('test_escape_cwd'); asynctest(fs.realpath, ['..'], cb, function(er, uponeActual) { assert.equal(upone, uponeActual, - 'realpath("..") expected: ' + path.resolve(upone) + - ' actual:' + uponeActual); + 'realpath("..") expected: ' + path.resolve(upone) + + ' actual:' + uponeActual); }); } var uponeActual = fs.realpathSync('..'); assert.equal(upone, uponeActual, - 'realpathSync("..") expected: ' + path.resolve(upone) + - ' actual:' + uponeActual); + 'realpathSync("..") expected: ' + path.resolve(upone) + + ' actual:' + uponeActual); // going up with .. multiple times @@ -358,7 +358,7 @@ assert.equal(upone, uponeActual, function test_up_multiple(cb) { console.error('test_up_multiple'); if (skipSymlinks) { - console.log('1..0 # Skipped: symlink test (no privs)'); + common.skip('symlink test (no privs)'); return runNextTest(); } function cleanup() { diff --git a/test/parallel/test-fs-symlink.js b/test/parallel/test-fs-symlink.js index b506013b0a23f5..bac0677b340393 100644 --- a/test/parallel/test-fs-symlink.js +++ b/test/parallel/test-fs-symlink.js @@ -13,7 +13,7 @@ if (common.isWindows) { // We'll only try to run symlink test if we have enough privileges. exec('whoami /priv', function(err, o) { if (err || o.indexOf('SeCreateSymbolicLinkPrivilege') == -1) { - console.log('1..0 # Skipped: insufficient privileges'); + common.skip('insufficient privileges'); return; } }); diff --git a/test/parallel/test-fs-watch-recursive.js b/test/parallel/test-fs-watch-recursive.js index 9c68b5e3557242..7853baaa02b797 100644 --- a/test/parallel/test-fs-watch-recursive.js +++ b/test/parallel/test-fs-watch-recursive.js @@ -3,7 +3,7 @@ const common = require('../common'); if (!(process.platform === 'darwin' || common.isWindows)) { - console.log('1..0 # Skipped: recursive option is darwin/windows specific'); + common.skip('recursive option is darwin/windows specific'); return; } diff --git a/test/parallel/test-http-1.0.js b/test/parallel/test-http-1.0.js index b4cb62534c4f6e..facf5c98eacb83 100644 --- a/test/parallel/test-http-1.0.js +++ b/test/parallel/test-http-1.0.js @@ -88,11 +88,11 @@ function test(handler, request_generator, response_validator) { } function response_validator(server_response, client_got_eof, timed_out) { - var expected_response = ('HTTP/1.1 200 OK\r\n' + - 'Content-Type: text/plain\r\n' + - 'Connection: close\r\n' + - '\r\n' + - 'Hello, world!'); + var expected_response = 'HTTP/1.1 200 OK\r\n' + + 'Content-Type: text/plain\r\n' + + 'Connection: close\r\n' + + '\r\n' + + 'Hello, world!'; assert.equal(expected_response, server_response); assert.equal(true, client_got_eof); @@ -125,17 +125,17 @@ function test(handler, request_generator, response_validator) { } function response_validator(server_response, client_got_eof, timed_out) { - var expected_response = ('HTTP/1.1 200 OK\r\n' + - 'Content-Type: text/plain\r\n' + - 'Connection: close\r\n' + - 'Transfer-Encoding: chunked\r\n' + - '\r\n' + - '7\r\n' + - 'Hello, \r\n' + - '6\r\n' + - 'world!\r\n' + - '0\r\n' + - '\r\n'); + var expected_response = 'HTTP/1.1 200 OK\r\n' + + 'Content-Type: text/plain\r\n' + + 'Connection: close\r\n' + + 'Transfer-Encoding: chunked\r\n' + + '\r\n' + + '7\r\n' + + 'Hello, \r\n' + + '6\r\n' + + 'world!\r\n' + + '0\r\n' + + '\r\n'; assert.equal(expected_response, server_response); assert.equal(true, client_got_eof); diff --git a/test/parallel/test-http-agent-error-on-idle.js b/test/parallel/test-http-agent-error-on-idle.js index e3388ee0dcbd96..f609efc8d59b6d 100644 --- a/test/parallel/test-http-agent-error-on-idle.js +++ b/test/parallel/test-http-agent-error-on-idle.js @@ -47,7 +47,7 @@ server.listen(common.PORT, function() { function done() { assert.equal(Object.keys(agent.freeSockets).length, 0, - 'expect the freeSockets pool to be empty'); + 'expect the freeSockets pool to be empty'); agent.destroy(); server.close(); diff --git a/test/parallel/test-http-agent-keepalive.js b/test/parallel/test-http-agent-keepalive.js index 6800e893e329da..85c0ad5dbc2b4f 100644 --- a/test/parallel/test-http-agent-keepalive.js +++ b/test/parallel/test-http-agent-keepalive.js @@ -74,7 +74,7 @@ function remoteClose() { setTimeout(function() { assert.equal(agent.sockets[name], undefined); assert.equal(agent.freeSockets[name], undefined, - 'freeSockets is not empty'); + 'freeSockets is not empty'); remoteError(); }, common.platformTimeout(200)); }); diff --git a/test/parallel/test-http-agent-maxsockets.js b/test/parallel/test-http-agent-maxsockets.js index e11aa2addad746..11f8d28a7389e2 100644 --- a/test/parallel/test-http-agent-maxsockets.js +++ b/test/parallel/test-http-agent-maxsockets.js @@ -30,7 +30,7 @@ function done() { } var freepool = agent.freeSockets[Object.keys(agent.freeSockets)[0]]; assert.equal(freepool.length, 2, - 'expect keep 2 free sockets, but got ' + freepool.length); + 'expect keep 2 free sockets, but got ' + freepool.length); agent.destroy(); server.close(); } diff --git a/test/parallel/test-http-chunk-problem.js b/test/parallel/test-http-chunk-problem.js index 6a5710e38e9f1b..26df0b95e29572 100644 --- a/test/parallel/test-http-chunk-problem.js +++ b/test/parallel/test-http-chunk-problem.js @@ -3,7 +3,7 @@ const common = require('../common'); const assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } diff --git a/test/parallel/test-http-default-port.js b/test/parallel/test-http-default-port.js index 69d81e9b9724ce..c0a1ed50e34d1b 100644 --- a/test/parallel/test-http-default-port.js +++ b/test/parallel/test-http-default-port.js @@ -18,7 +18,7 @@ let gotHttpResp = false; if (common.hasCrypto) { var https = require('https'); } else { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); } process.on('exit', function() { diff --git a/test/parallel/test-http-destroyed-socket-write2.js b/test/parallel/test-http-destroyed-socket-write2.js index ac6ab92c17c072..7588393840f2cc 100644 --- a/test/parallel/test-http-destroyed-socket-write2.js +++ b/test/parallel/test-http-destroyed-socket-write2.js @@ -29,16 +29,21 @@ server.listen(common.PORT, function() { switch (er.code) { // This is the expected case case 'ECONNRESET': - // On windows this sometimes manifests as ECONNABORTED + break; + + // On Windows, this sometimes manifests as ECONNABORTED case 'ECONNABORTED': + break; + // This test is timing sensitive so an EPIPE is not out of the question. // It should be infrequent, given the 50 ms timeout, but not impossible. case 'EPIPE': break; + default: assert.strictEqual(er.code, - 'ECONNRESET', - 'Writing to a torn down client should RESET or ABORT'); + 'ECONNRESET', + 'Write to a torn down client should RESET or ABORT'); break; } diff --git a/test/parallel/test-http-dns-error.js b/test/parallel/test-http-dns-error.js index 37e9fca62e01e4..f1f144a60a24c0 100644 --- a/test/parallel/test-http-dns-error.js +++ b/test/parallel/test-http-dns-error.js @@ -7,7 +7,7 @@ var http = require('http'); if (common.hasCrypto) { var https = require('https'); } else { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); } var host = '*'.repeat(256); @@ -36,7 +36,7 @@ function test(mod) { if (common.hasCrypto) { test(https); } else { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); } test(http); diff --git a/test/parallel/test-http-full-response.js b/test/parallel/test-http-full-response.js index 767efa3cd6657e..331f2171d828b4 100644 --- a/test/parallel/test-http-full-response.js +++ b/test/parallel/test-http-full-response.js @@ -24,7 +24,7 @@ function runAb(opts, callback) { exec(command, function(err, stdout, stderr) { if (err) { if (/ab|apr/mi.test(stderr)) { - console.log('1..0 # Skipped: problem spawning `ab`.\n' + stderr); + common.skip('problem spawning `ab`.\n' + stderr); process.reallyExit(0); } process.exit(); diff --git a/test/parallel/test-http-localaddress.js b/test/parallel/test-http-localaddress.js index c7bb9f0301e407..9bf213a880444b 100644 --- a/test/parallel/test-http-localaddress.js +++ b/test/parallel/test-http-localaddress.js @@ -4,7 +4,7 @@ const http = require('http'); const assert = require('assert'); if (!common.hasMultiLocalhost()) { - console.log('1..0 # Skipped: platform-specific test.'); + common.skip('platform-specific test.'); return; } diff --git a/test/parallel/test-http-parser-bad-ref.js b/test/parallel/test-http-parser-bad-ref.js index 545a9c1fef11c4..01179641175e02 100644 --- a/test/parallel/test-http-parser-bad-ref.js +++ b/test/parallel/test-http-parser-bad-ref.js @@ -75,10 +75,12 @@ demoBug('POST /1', '/22 HTTP/1.1\r\n' + 'Content-Length: 4\r\n\r\n' + 'pong'); +/* eslint-disable align-function-arguments */ demoBug('POST /1/22 HTTP/1.1\r\n' + 'Content-Type: tex', 't/plain\r\n' + 'Content-Length: 4\r\n\r\n' + 'pong'); +/* eslint-enable align-function-arguments */ process.on('exit', function() { assert.equal(2, headersComplete); diff --git a/test/parallel/test-http-url.parse-https.request.js b/test/parallel/test-http-url.parse-https.request.js index df01ae64f81dba..d843d9838d9914 100644 --- a/test/parallel/test-http-url.parse-https.request.js +++ b/test/parallel/test-http-url.parse-https.request.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var https = require('https'); diff --git a/test/parallel/test-http-url.parse-post.js b/test/parallel/test-http-url.parse-post.js index b6a0fdeb255235..7611b0856320a6 100644 --- a/test/parallel/test-http-url.parse-post.js +++ b/test/parallel/test-http-url.parse-post.js @@ -14,7 +14,7 @@ function check(request) { assert.strictEqual(request.url, '/asdf?qwer=zxcv'); //the host header should use the url.parse.hostname assert.strictEqual(request.headers.host, - testURL.hostname + ':' + testURL.port); + testURL.hostname + ':' + testURL.port); } var server = http.createServer(function(request, response) { diff --git a/test/parallel/test-https-agent-servername.js b/test/parallel/test-https-agent-servername.js index f7d5e5a40d8679..1ebed86a82878a 100644 --- a/test/parallel/test-https-agent-servername.js +++ b/test/parallel/test-https-agent-servername.js @@ -2,7 +2,7 @@ var common = require('../common'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } diff --git a/test/parallel/test-https-agent-session-eviction.js b/test/parallel/test-https-agent-session-eviction.js index df6fdc3658c2c9..37f4fa3e564439 100644 --- a/test/parallel/test-https-agent-session-eviction.js +++ b/test/parallel/test-https-agent-session-eviction.js @@ -3,7 +3,7 @@ const common = require('../common'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } diff --git a/test/parallel/test-https-agent-session-reuse.js b/test/parallel/test-https-agent-session-reuse.js index 2c202524456a75..1421d545783ac3 100644 --- a/test/parallel/test-https-agent-session-reuse.js +++ b/test/parallel/test-https-agent-session-reuse.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } diff --git a/test/parallel/test-https-agent-sni.js b/test/parallel/test-https-agent-sni.js index 117075f68264b4..b8f6c8cde8520c 100644 --- a/test/parallel/test-https-agent-sni.js +++ b/test/parallel/test-https-agent-sni.js @@ -3,7 +3,7 @@ const common = require('../common'); const assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } const https = require('https'); diff --git a/test/parallel/test-https-agent.js b/test/parallel/test-https-agent.js index 9dea313e42ed8e..08d35337121acf 100644 --- a/test/parallel/test-https-agent.js +++ b/test/parallel/test-https-agent.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var https = require('https'); diff --git a/test/parallel/test-https-byteswritten.js b/test/parallel/test-https-byteswritten.js index 4d42714f3dc4c0..2f8856ca999833 100644 --- a/test/parallel/test-https-byteswritten.js +++ b/test/parallel/test-https-byteswritten.js @@ -4,7 +4,7 @@ var assert = require('assert'); var fs = require('fs'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var https = require('https'); diff --git a/test/parallel/test-https-client-checkServerIdentity.js b/test/parallel/test-https-client-checkServerIdentity.js index e49427dcc76f6e..f16285860afe60 100644 --- a/test/parallel/test-https-client-checkServerIdentity.js +++ b/test/parallel/test-https-client-checkServerIdentity.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var https = require('https'); diff --git a/test/parallel/test-https-client-get-url.js b/test/parallel/test-https-client-get-url.js index e8922de9434a03..50875e6d452da7 100644 --- a/test/parallel/test-https-client-get-url.js +++ b/test/parallel/test-https-client-get-url.js @@ -6,7 +6,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var https = require('https'); diff --git a/test/parallel/test-https-client-reject.js b/test/parallel/test-https-client-reject.js index fc76e5b80f5806..ee19de2acdd0ab 100644 --- a/test/parallel/test-https-client-reject.js +++ b/test/parallel/test-https-client-reject.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var https = require('https'); diff --git a/test/parallel/test-https-client-resume.js b/test/parallel/test-https-client-resume.js index 8f849b14b5818a..b91f3d83148ff1 100644 --- a/test/parallel/test-https-client-resume.js +++ b/test/parallel/test-https-client-resume.js @@ -6,7 +6,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var https = require('https'); diff --git a/test/parallel/test-https-close.js b/test/parallel/test-https-close.js index 8a9a4f89960af0..18237a612bde31 100644 --- a/test/parallel/test-https-close.js +++ b/test/parallel/test-https-close.js @@ -3,7 +3,7 @@ const common = require('../common'); const fs = require('fs'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } const https = require('https'); diff --git a/test/parallel/test-https-connecting-to-http.js b/test/parallel/test-https-connecting-to-http.js index 755abf9427fb32..2b705b4cfabb5b 100644 --- a/test/parallel/test-https-connecting-to-http.js +++ b/test/parallel/test-https-connecting-to-http.js @@ -6,7 +6,7 @@ var assert = require('assert'); var http = require('http'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var https = require('https'); diff --git a/test/parallel/test-https-drain.js b/test/parallel/test-https-drain.js index 1ba5e2a4679f6d..e4ce6d9890353f 100644 --- a/test/parallel/test-https-drain.js +++ b/test/parallel/test-https-drain.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var https = require('https'); diff --git a/test/parallel/test-https-eof-for-eom.js b/test/parallel/test-https-eof-for-eom.js index 50d909373ff5b0..5431d33c3d394f 100644 --- a/test/parallel/test-https-eof-for-eom.js +++ b/test/parallel/test-https-eof-for-eom.js @@ -11,7 +11,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var https = require('https'); diff --git a/test/parallel/test-https-foafssl.js b/test/parallel/test-https-foafssl.js index 5e480bf6adc1e5..fa6200c845e229 100644 --- a/test/parallel/test-https-foafssl.js +++ b/test/parallel/test-https-foafssl.js @@ -2,7 +2,7 @@ var common = require('../common'); if (!common.opensslCli) { - console.log('1..0 # Skipped: node compiled without OpenSSL CLI.'); + common.skip('node compiled without OpenSSL CLI.'); return; } @@ -13,7 +13,7 @@ var fs = require('fs'); var spawn = require('child_process').spawn; if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var https = require('https'); diff --git a/test/parallel/test-https-host-headers.js b/test/parallel/test-https-host-headers.js index 1e71fd5b9ef5b7..4c292d7e8bbd6f 100644 --- a/test/parallel/test-https-host-headers.js +++ b/test/parallel/test-https-host-headers.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var https = require('https'); diff --git a/test/parallel/test-https-localaddress-bind-error.js b/test/parallel/test-https-localaddress-bind-error.js index f5bb1f84c310b3..75f915a05cc250 100644 --- a/test/parallel/test-https-localaddress-bind-error.js +++ b/test/parallel/test-https-localaddress-bind-error.js @@ -4,7 +4,7 @@ var assert = require('assert'); var fs = require('fs'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var https = require('https'); diff --git a/test/parallel/test-https-localaddress.js b/test/parallel/test-https-localaddress.js index bce65d58e296f2..ed70d0281cfdc2 100644 --- a/test/parallel/test-https-localaddress.js +++ b/test/parallel/test-https-localaddress.js @@ -4,13 +4,13 @@ const fs = require('fs'); const assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var https = require('https'); if (!common.hasMultiLocalhost()) { - console.log('1..0 # Skipped: platform-specific test.'); + common.skip('platform-specific test.'); return; } diff --git a/test/parallel/test-https-pfx.js b/test/parallel/test-https-pfx.js index 5e080b4e3ded12..0d2c6d367a6e9a 100644 --- a/test/parallel/test-https-pfx.js +++ b/test/parallel/test-https-pfx.js @@ -4,7 +4,7 @@ var assert = require('assert'); var fs = require('fs'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var https = require('https'); diff --git a/test/parallel/test-https-req-split.js b/test/parallel/test-https-req-split.js index 479fff36b4e5d2..d7b49b6d71b284 100644 --- a/test/parallel/test-https-req-split.js +++ b/test/parallel/test-https-req-split.js @@ -6,7 +6,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var https = require('https'); diff --git a/test/parallel/test-https-set-timeout-server.js b/test/parallel/test-https-set-timeout-server.js index bfea7c4d5d5f48..176d056b66cfac 100644 --- a/test/parallel/test-https-set-timeout-server.js +++ b/test/parallel/test-https-set-timeout-server.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var https = require('https'); diff --git a/test/parallel/test-https-simple.js b/test/parallel/test-https-simple.js index 92f9bde2ef802a..14ebb29e2d88ff 100644 --- a/test/parallel/test-https-simple.js +++ b/test/parallel/test-https-simple.js @@ -2,7 +2,7 @@ const common = require('../common'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } diff --git a/test/parallel/test-https-socket-options.js b/test/parallel/test-https-socket-options.js index 2adf8c798dff65..0306c659026dfd 100644 --- a/test/parallel/test-https-socket-options.js +++ b/test/parallel/test-https-socket-options.js @@ -2,7 +2,7 @@ var common = require('../common'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var https = require('https'); diff --git a/test/parallel/test-https-strict.js b/test/parallel/test-https-strict.js index 04561959de130f..9f845470b0f2e9 100644 --- a/test/parallel/test-https-strict.js +++ b/test/parallel/test-https-strict.js @@ -6,7 +6,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var https = require('https'); diff --git a/test/parallel/test-https-timeout-server-2.js b/test/parallel/test-https-timeout-server-2.js index a195ce1938b9cd..f543150de7e118 100644 --- a/test/parallel/test-https-timeout-server-2.js +++ b/test/parallel/test-https-timeout-server-2.js @@ -4,7 +4,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var https = require('https'); diff --git a/test/parallel/test-https-timeout-server.js b/test/parallel/test-https-timeout-server.js index f6d5d75a88abbe..8e362da82f8119 100644 --- a/test/parallel/test-https-timeout-server.js +++ b/test/parallel/test-https-timeout-server.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var https = require('https'); diff --git a/test/parallel/test-https-timeout.js b/test/parallel/test-https-timeout.js index 2b41dadaec7857..20ee1d6868fa46 100644 --- a/test/parallel/test-https-timeout.js +++ b/test/parallel/test-https-timeout.js @@ -2,7 +2,7 @@ var common = require('../common'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var https = require('https'); diff --git a/test/parallel/test-https-truncate.js b/test/parallel/test-https-truncate.js index 83506c65d6f3cc..c9bf1766a2b360 100644 --- a/test/parallel/test-https-truncate.js +++ b/test/parallel/test-https-truncate.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var https = require('https'); diff --git a/test/parallel/test-intl.js b/test/parallel/test-intl.js index 551cc013131427..7c24ad69b31146 100644 --- a/test/parallel/test-intl.js +++ b/test/parallel/test-intl.js @@ -1,5 +1,5 @@ 'use strict'; -require('../common'); +const common = require('../common'); var assert = require('assert'); // does node think that i18n was enabled? @@ -24,7 +24,7 @@ if (!haveIntl) { '"Intl" object is NOT present but v8_enable_i18n_support is ' + enablei18n; assert.equal(enablei18n, false, erMsg); - console.log('1..0 # Skipped: Intl tests because Intl object not present.'); + common.skip('Intl tests because Intl object not present.'); } else { const erMsg = @@ -46,7 +46,7 @@ if (!haveIntl) { // If list is specified and doesn't contain 'en' then return. if (process.config.variables.icu_locales && !haveLocale('en')) { - console.log('1..0 # Skipped: detailed Intl tests because English is not ' + + common.skip('detailed Intl tests because English is not ' + 'listed as supported.'); // Smoke test. Does it format anything, or fail? console.log('Date(0) formatted to: ' + dtf.format(date0)); diff --git a/test/parallel/test-listen-fd-cluster.js b/test/parallel/test-listen-fd-cluster.js index 419efc7c099bf0..92aadfd49f8acd 100644 --- a/test/parallel/test-listen-fd-cluster.js +++ b/test/parallel/test-listen-fd-cluster.js @@ -9,7 +9,7 @@ var cluster = require('cluster'); console.error('Cluster listen fd test', process.argv[2] || 'runner'); if (common.isWindows) { - console.log('1..0 # Skipped: This test is disabled on windows.'); + common.skip('This test is disabled on windows.'); return; } diff --git a/test/parallel/test-listen-fd-detached-inherit.js b/test/parallel/test-listen-fd-detached-inherit.js index 472b1e8ff939f0..abe3b7ca5126b9 100644 --- a/test/parallel/test-listen-fd-detached-inherit.js +++ b/test/parallel/test-listen-fd-detached-inherit.js @@ -7,7 +7,7 @@ var PORT = common.PORT; var spawn = require('child_process').spawn; if (common.isWindows) { - console.log('1..0 # Skipped: This test is disabled on windows.'); + common.skip('This test is disabled on windows.'); return; } diff --git a/test/parallel/test-listen-fd-detached.js b/test/parallel/test-listen-fd-detached.js index 12c8c3ddc43fac..1bb1a7f13336a5 100644 --- a/test/parallel/test-listen-fd-detached.js +++ b/test/parallel/test-listen-fd-detached.js @@ -7,7 +7,7 @@ var PORT = common.PORT; var spawn = require('child_process').spawn; if (common.isWindows) { - console.log('1..0 # Skipped: This test is disabled on windows.'); + common.skip('This test is disabled on windows.'); return; } diff --git a/test/parallel/test-listen-fd-server.js b/test/parallel/test-listen-fd-server.js index 3e0fa521f75334..25a5393bd4a2fb 100644 --- a/test/parallel/test-listen-fd-server.js +++ b/test/parallel/test-listen-fd-server.js @@ -6,7 +6,7 @@ var net = require('net'); var PORT = common.PORT; if (common.isWindows) { - console.log('1..0 # Skipped: This test is disabled on windows.'); + common.skip('This test is disabled on windows.'); return; } diff --git a/test/parallel/test-module-loading-error.js b/test/parallel/test-module-loading-error.js index 072a6aadcb8c62..145530985401e4 100644 --- a/test/parallel/test-module-loading-error.js +++ b/test/parallel/test-module-loading-error.js @@ -1,5 +1,5 @@ 'use strict'; -require('../common'); +const common = require('../common'); var assert = require('assert'); console.error('load test-module-loading-error.js'); @@ -13,7 +13,7 @@ var error_desc = { var dlerror_msg = error_desc[process.platform]; if (!dlerror_msg) { - console.log('1..0 # Skipped: platform not supported.'); + common.skip('platform not supported.'); return; } diff --git a/test/parallel/test-net-better-error-messages-port-hostname.js b/test/parallel/test-net-better-error-messages-port-hostname.js index 9db6fb26f57285..23089baf448a39 100644 --- a/test/parallel/test-net-better-error-messages-port-hostname.js +++ b/test/parallel/test-net-better-error-messages-port-hostname.js @@ -3,12 +3,12 @@ var common = require('../common'); var net = require('net'); var assert = require('assert'); -var c = net.createConnection(common.PORT, '...'); +var c = net.createConnection(common.PORT, '***'); c.on('connect', common.fail); c.on('error', common.mustCall(function(e) { assert.equal(e.code, 'ENOTFOUND'); assert.equal(e.port, common.PORT); - assert.equal(e.hostname, '...'); + assert.equal(e.hostname, '***'); })); diff --git a/test/parallel/test-net-bytes-read.js b/test/parallel/test-net-bytes-read.js new file mode 100644 index 00000000000000..5473ca96ca2cb6 --- /dev/null +++ b/test/parallel/test-net-bytes-read.js @@ -0,0 +1,37 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const net = require('net'); + +const big = Buffer(1024 * 1024); + +const server = net.createServer((socket) => { + socket.end(big); + server.close(); +}).listen(common.PORT, () => { + let prev = 0; + + function checkRaise(value) { + assert(value > prev); + prev = value; + } + + const socket = net.connect(common.PORT, () => { + socket.on('data', (chunk) => { + checkRaise(socket.bytesRead); + }); + + socket.on('end', common.mustCall(() => { + assert.equal(socket.bytesRead, prev); + assert.equal(big.length, prev); + })); + + socket.on('close', common.mustCall(() => { + assert(!socket._handle); + assert.equal(socket.bytesRead, prev); + assert.equal(big.length, prev); + })); + }); + socket.end(); +}); diff --git a/test/parallel/test-net-connect-immediate-finish.js b/test/parallel/test-net-connect-immediate-finish.js index a5403732ec1d0d..6114233677f5cb 100644 --- a/test/parallel/test-net-connect-immediate-finish.js +++ b/test/parallel/test-net-connect-immediate-finish.js @@ -3,14 +3,14 @@ const common = require('../common'); const assert = require('assert'); const net = require('net'); -const client = net.connect({host: '...', port: common.PORT}); +const client = net.connect({host: '***', port: common.PORT}); client.once('error', common.mustCall(function(err) { assert(err); assert.strictEqual(err.code, err.errno); assert.strictEqual(err.code, 'ENOTFOUND'); assert.strictEqual(err.host, err.hostname); - assert.strictEqual(err.host, '...'); + assert.strictEqual(err.host, '***'); assert.strictEqual(err.syscall, 'getaddrinfo'); })); diff --git a/test/parallel/test-net-connect-options-ipv6.js b/test/parallel/test-net-connect-options-ipv6.js index 5cce7325f91967..f84c02678ff654 100644 --- a/test/parallel/test-net-connect-options-ipv6.js +++ b/test/parallel/test-net-connect-options-ipv6.js @@ -4,7 +4,7 @@ const assert = require('assert'); const net = require('net'); if (!common.hasIPv6) { - console.log('1..0 # Skipped: no IPv6 support'); + common.skip('no IPv6 support'); return; } @@ -60,7 +60,7 @@ function tryConnect() { if (host) tryConnect(); else { - console.log('1..0 # Skipped: no IPv6 localhost support'); + common.skip('no IPv6 localhost support'); server.close(); } return; diff --git a/test/parallel/test-net-socket-local-address.js b/test/parallel/test-net-socket-local-address.js index 379bed363e75e8..2569c363f49ce7 100644 --- a/test/parallel/test-net-socket-local-address.js +++ b/test/parallel/test-net-socket-local-address.js @@ -5,7 +5,7 @@ const net = require('net'); // skip test in FreeBSD jails if (common.inFreeBSDJail) { - console.log('1..0 # Skipped: In a FreeBSD jail'); + common.skip('In a FreeBSD jail'); return; } diff --git a/test/parallel/test-npm-install.js b/test/parallel/test-npm-install.js index b6ef67bf322ea3..c716e48aefedab 100644 --- a/test/parallel/test-npm-install.js +++ b/test/parallel/test-npm-install.js @@ -32,11 +32,12 @@ const pkgPath = path.join(common.tmpDir, 'package.json'); fs.writeFileSync(pkgPath, pkgContent); +const env = Object.create(process.env); +env['PATH'] = path.dirname(process.execPath); + const proc = spawn(process.execPath, args, { cwd: common.tmpDir, - env: { - PATH: path.dirname(process.execPath) - } + env: env }); function handleExit(code, signalCode) { diff --git a/test/parallel/test-path.js b/test/parallel/test-path.js index 1432cb63a10ae4..a2c6f2a3e3792e 100644 --- a/test/parallel/test-path.js +++ b/test/parallel/test-path.js @@ -76,7 +76,6 @@ assert.equal(path.win32.dirname('\\\\unc\\share\\foo\\bar\\'), assert.equal(path.win32.dirname('\\\\unc\\share\\foo\\bar\\baz'), '\\\\unc\\share\\foo\\bar'); - assert.equal(path.extname(''), ''); assert.equal(path.extname('/path/to/file'), ''); assert.equal(path.extname('/path/to/file.ext'), '.ext'); diff --git a/test/parallel/test-process-exec-argv.js b/test/parallel/test-process-exec-argv.js index c2b663ac67eb60..178b84c23fcc70 100644 --- a/test/parallel/test-process-exec-argv.js +++ b/test/parallel/test-process-exec-argv.js @@ -15,7 +15,7 @@ if (process.argv[2] === 'child') { out += chunk; }); - child.on('exit', function() { - assert.deepEqual(JSON.parse(out), execArgv); + child.on('close', function() { + assert.deepStrictEqual(JSON.parse(out), execArgv); }); } diff --git a/test/parallel/test-process-getgroups.js b/test/parallel/test-process-getgroups.js index 08eab8d5a8afe2..6d07692a764e52 100644 --- a/test/parallel/test-process-getgroups.js +++ b/test/parallel/test-process-getgroups.js @@ -1,10 +1,10 @@ 'use strict'; -require('../common'); +const common = require('../common'); var assert = require('assert'); var exec = require('child_process').exec; if (process.platform === 'darwin') { - console.log('1..0 # Skipped: Output of `id -G` is unreliable on Darwin.'); + common.skip('Output of `id -G` is unreliable on Darwin.'); return; } diff --git a/test/parallel/test-process-remove-all-signal-listeners.js b/test/parallel/test-process-remove-all-signal-listeners.js index 59c2ae926b1cc2..f05e1f9dec79ef 100644 --- a/test/parallel/test-process-remove-all-signal-listeners.js +++ b/test/parallel/test-process-remove-all-signal-listeners.js @@ -5,7 +5,7 @@ const spawn = require('child_process').spawn; const common = require('../common'); if (common.isWindows) { - console.log('1..0 # Skipped: Win32 doesn\'t have signals, just a kind of ' + + common.skip('Win32 doesn\'t have signals, just a kind of ' + 'emulation, insufficient for this test to apply.'); return; } diff --git a/test/parallel/test-readline-undefined-columns.js b/test/parallel/test-readline-undefined-columns.js index 24f138f46bce11..f3197ff59a9a55 100644 --- a/test/parallel/test-readline-undefined-columns.js +++ b/test/parallel/test-readline-undefined-columns.js @@ -28,8 +28,8 @@ oStream.on('data', function(data) { oStream.on('end', function() { const expect = 'process.stdout\r\n' + - 'process.stdin\r\n' + - 'process.stderr'; + 'process.stdin\r\n' + + 'process.stderr'; assert(new RegExp(expect).test(output)); }); diff --git a/test/parallel/test-regress-GH-1531.js b/test/parallel/test-regress-GH-1531.js index 097611e1bfb11b..79766934edec5b 100644 --- a/test/parallel/test-regress-GH-1531.js +++ b/test/parallel/test-regress-GH-1531.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var https = require('https'); diff --git a/test/parallel/test-regress-GH-3542.js b/test/parallel/test-regress-GH-3542.js index 77b8cdd69817ac..72d46375b45c9e 100644 --- a/test/parallel/test-regress-GH-3542.js +++ b/test/parallel/test-regress-GH-3542.js @@ -7,7 +7,7 @@ let succeeded = 0; // This test is only relevant on Windows. if (!common.isWindows) { - console.log('1..0 # Skipped: Windows specific test.'); + common.skip('Windows specific test.'); return; } diff --git a/test/parallel/test-repl-history-perm.js b/test/parallel/test-repl-history-perm.js new file mode 100644 index 00000000000000..c7d2852539a01d --- /dev/null +++ b/test/parallel/test-repl-history-perm.js @@ -0,0 +1,53 @@ +'use strict'; +// Flags: --expose_internals + +const common = require('../common'); + +if (common.isWindows) { + common.skip('Win32 uses ACLs for file permissions, ' + + 'modes are always 0666 and says nothing about group/other ' + + 'read access.'); + return; +} + +const assert = require('assert'); +const path = require('path'); +const fs = require('fs'); +const repl = require('internal/repl'); +const Duplex = require('stream').Duplex; +// Invoking the REPL should create a repl history file at the specified path +// and mode 600. + +var stream = new Duplex(); +stream.pause = stream.resume = function() {}; +// ends immediately +stream._read = function() { + this.push(null); +}; +stream._write = function(c, e, cb) { + cb(); +}; +stream.readable = stream.writable = true; + +common.refreshTmpDir(); +const replHistoryPath = path.join(common.tmpDir, '.node_repl_history'); + +const checkResults = common.mustCall(function(err, r) { + if (err) + throw err; + r.input.end(); + const stat = fs.statSync(replHistoryPath); + assert.strictEqual( + stat.mode & 0o777, 0o600, + 'REPL history file should be mode 0600'); +}); + +repl.createInternalRepl( + {NODE_REPL_HISTORY: replHistoryPath}, + { + terminal: true, + input: stream, + output: stream + }, + checkResults +); diff --git a/test/parallel/test-require-long-path.js b/test/parallel/test-require-long-path.js index c30a76a5a9e099..1a8ce1b7dfd2c3 100644 --- a/test/parallel/test-require-long-path.js +++ b/test/parallel/test-require-long-path.js @@ -4,7 +4,7 @@ const fs = require('fs'); const path = require('path'); if (!common.isWindows) { - console.log('1..0 # Skipped: this test is Windows-specific.'); + common.skip('this test is Windows-specific.'); return; } diff --git a/test/parallel/test-require-process.js b/test/parallel/test-require-process.js index 33634930b4e614..4e5821add13183 100644 --- a/test/parallel/test-require-process.js +++ b/test/parallel/test-require-process.js @@ -4,4 +4,4 @@ var assert = require('assert'); var nativeProcess = require('process'); assert.strictEqual(nativeProcess, process, - 'require("process") should return a reference to global process'); + 'require("process") should return global process reference'); diff --git a/test/parallel/test-setproctitle.js b/test/parallel/test-setproctitle.js index 40107f5774962f..90d7b7a10df92c 100644 --- a/test/parallel/test-setproctitle.js +++ b/test/parallel/test-setproctitle.js @@ -1,13 +1,13 @@ 'use strict'; // Original test written by Jakub Lekstan +const common = require('../common'); // FIXME add sunos support if ('linux freebsd darwin'.indexOf(process.platform) === -1) { - console.log(`1..0 # Skipped: Unsupported platform [${process.platform}]`); + common.skip(`Unsupported platform [${process.platform}]`); return; } -require('../common'); var assert = require('assert'); var exec = require('child_process').exec; var path = require('path'); diff --git a/test/parallel/test-signal-handler.js b/test/parallel/test-signal-handler.js index dc37a8a1f6704a..43198de726d20e 100644 --- a/test/parallel/test-signal-handler.js +++ b/test/parallel/test-signal-handler.js @@ -4,7 +4,7 @@ const common = require('../common'); const assert = require('assert'); if (common.isWindows) { - console.log('1..0 # Skipped: SIGUSR1 and SIGHUP signals are not supported'); + common.skip('SIGUSR1 and SIGHUP signals are not supported'); return; } diff --git a/test/parallel/test-spawn-cmd-named-pipe.js b/test/parallel/test-spawn-cmd-named-pipe.js index 5371577e6c458c..fafc5b2167ba59 100644 --- a/test/parallel/test-spawn-cmd-named-pipe.js +++ b/test/parallel/test-spawn-cmd-named-pipe.js @@ -4,7 +4,7 @@ const assert = require('assert'); // This test is intended for Windows only if (!common.isWindows) { - console.log('1..0 # Skipped: this test is Windows-specific.'); + common.skip('this test is Windows-specific.'); return; } diff --git a/test/parallel/test-stdin-from-file.js b/test/parallel/test-stdin-from-file.js index 862405b5d9b71a..d6e3afeae6fdee 100644 --- a/test/parallel/test-stdin-from-file.js +++ b/test/parallel/test-stdin-from-file.js @@ -9,7 +9,7 @@ var stdoutScript = join(common.fixturesDir, 'echo-close-check.js'); var tmpFile = join(common.tmpDir, 'stdin.txt'); var cmd = '"' + process.argv[0] + '" "' + stdoutScript + '" < "' + - tmpFile + '"'; + tmpFile + '"'; var string = 'abc\nümlaut.\nsomething else\n' + '南越国是前203年至前111年存在于岭南地区的一个国家,国都位于番禺,' + diff --git a/test/parallel/test-stdio-closed.js b/test/parallel/test-stdio-closed.js index bf9a57bd688ffc..0f94289ee96534 100644 --- a/test/parallel/test-stdio-closed.js +++ b/test/parallel/test-stdio-closed.js @@ -4,7 +4,7 @@ var assert = require('assert'); var spawn = require('child_process').spawn; if (common.isWindows) { - console.log('1..0 # Skipped: platform not supported.'); + common.skip('platform not supported.'); return; } diff --git a/test/parallel/test-stdout-close-catch.js b/test/parallel/test-stdout-close-catch.js index 470fa9843cb9de..15315fe82c6df5 100644 --- a/test/parallel/test-stdout-close-catch.js +++ b/test/parallel/test-stdout-close-catch.js @@ -9,7 +9,7 @@ var testScript = path.join(common.fixturesDir, 'catch-stdout-error.js'); var cmd = JSON.stringify(process.execPath) + ' ' + JSON.stringify(testScript) + ' | ' + JSON.stringify(process.execPath) + ' ' + - '-pe "process.exit(1);"'; + '-pe "process.stdin.on(\'data\' , () => process.exit(1))"'; var child = child_process.exec(cmd); var output = ''; diff --git a/test/parallel/test-stream-pipe-await-drain-manual-resume.js b/test/parallel/test-stream-pipe-await-drain-manual-resume.js new file mode 100644 index 00000000000000..d26741b8bb4825 --- /dev/null +++ b/test/parallel/test-stream-pipe-await-drain-manual-resume.js @@ -0,0 +1,54 @@ +'use strict'; +const common = require('../common'); +const stream = require('stream'); + +// A consumer stream with a very low highWaterMark, which starts in a state +// where it buffers the chunk it receives rather than indicating that they +// have been consumed. +const writable = new stream.Writable({ + highWaterMark: 5 +}); + +let isCurrentlyBufferingWrites = true; +const queue = []; + +writable._write = (chunk, encoding, cb) => { + if (isCurrentlyBufferingWrites) + queue.push({chunk, cb}); + else + cb(); +}; + +const readable = new stream.Readable({ + read() {} +}); + +readable.pipe(writable); + +readable.once('pause', common.mustCall(() => { + // First pause, resume manually. The next write() to writable will still + // return false, because chunks are still being buffered, so it will increase + // the awaitDrain counter again. + process.nextTick(common.mustCall(() => { + readable.resume(); + })); + + readable.once('pause', common.mustCall(() => { + // Second pause, handle all chunks from now on. Once all callbacks that + // are currently queued up are handled, the awaitDrain drain counter should + // fall back to 0 and all chunks that are pending on the readable side + // should be flushed. + isCurrentlyBufferingWrites = false; + for (const queued of queue) + queued.cb(); + })); +})); + +readable.push(Buffer(100)); // Fill the writable HWM, first 'pause'. +readable.push(Buffer(100)); // Second 'pause'. +readable.push(Buffer(100)); // Should get through to the writable. +readable.push(null); + +writable.on('finish', common.mustCall(() => { + // Everything okay, all chunks were written. +})); diff --git a/test/parallel/test-stream-pipe-await-drain-push-while-write.js b/test/parallel/test-stream-pipe-await-drain-push-while-write.js new file mode 100644 index 00000000000000..1dfdfdb80c8d71 --- /dev/null +++ b/test/parallel/test-stream-pipe-await-drain-push-while-write.js @@ -0,0 +1,28 @@ +'use strict'; +const common = require('../common'); +const stream = require('stream'); + +// A writable stream which pushes data onto the stream which pipes into it, +// but only the first time it's written to. Since it's not paused at this time, +// a second write will occur. If the pipe increases awaitDrain twice, we'll +// never get subsequent chunks because 'drain' is only emitted once. +const writable = new stream.Writable({ + write: common.mustCall((chunk, encoding, cb) => { + if (chunk.length === 32 * 1024) { // first chunk + readable.push(new Buffer(33 * 1024)); // above hwm + } + cb(); + }, 3) +}); + +// A readable stream which produces two buffers. +const bufs = [new Buffer(32 * 1024), new Buffer(33 * 1024)]; // above hwm +const readable = new stream.Readable({ + read: function() { + while (bufs.length > 0) { + this.push(bufs.shift()); + } + } +}); + +readable.pipe(writable); diff --git a/test/parallel/test-stream2-unpipe-drain.js b/test/parallel/test-stream2-unpipe-drain.js index daad70a282a44c..39c3b19069b444 100644 --- a/test/parallel/test-stream2-unpipe-drain.js +++ b/test/parallel/test-stream2-unpipe-drain.js @@ -4,7 +4,7 @@ var assert = require('assert'); var stream = require('stream'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var crypto = require('crypto'); diff --git a/test/parallel/test-tick-processor.js b/test/parallel/test-tick-processor.js index b22e2ec14a3c6e..686e7178360ef9 100644 --- a/test/parallel/test-tick-processor.js +++ b/test/parallel/test-tick-processor.js @@ -10,7 +10,7 @@ var common = require('../common'); // addresses correctly and runs out of memory // Disabling until we get a fix upstreamed into V8 if (common.isAix) { - console.log('1..0 # Skipped: Aix address range too big for scripts.'); + common.skip('Aix address range too big for scripts.'); return; } @@ -32,7 +32,7 @@ if (common.isWindows || common.isAix || common.isLinuxPPCBE || common.isFreeBSD) { - console.log('1..0 # Skipped: C++ symbols are not mapped for this os.'); + common.skip('C++ symbols are not mapped for this os.'); return; } runTest(/RunInDebugContext/, diff --git a/test/parallel/test-timers-ordering.js b/test/parallel/test-timers-ordering.js index cef91e58e78c3d..c23af9d8307e9a 100644 --- a/test/parallel/test-timers-ordering.js +++ b/test/parallel/test-timers-ordering.js @@ -19,7 +19,7 @@ var f = function(i) { var now = Timer.now(); console.log(i, now); assert(now >= last_ts + 1, - 'current ts ' + now + ' < prev ts ' + last_ts + ' + 1'); + 'current ts ' + now + ' < prev ts ' + last_ts + ' + 1'); last_ts = now; // schedule next iteration diff --git a/test/parallel/test-timers-reset-process-domain-on-throw.js b/test/parallel/test-timers-reset-process-domain-on-throw.js index ab3ffd3596ed53..55e7ef57dcafc4 100644 --- a/test/parallel/test-timers-reset-process-domain-on-throw.js +++ b/test/parallel/test-timers-reset-process-domain-on-throw.js @@ -36,8 +36,8 @@ function secondTimer() { // secondTimer was scheduled before any domain had been created, so its // callback should not have any active domain set when it runs. if (process.domain !== null) { - console.log('process.domain should be null in this timer callback, but ' + - 'instead is:', process.domain); + console.log('process.domain should be null in this timer callback, but is:', + process.domain); // Do not use assert here, as it throws errors and if a domain with an error // handler is active, then asserting wouldn't make the test fail. process.exit(1); diff --git a/test/parallel/test-tls-0-dns-altname.js b/test/parallel/test-tls-0-dns-altname.js index 793b56426f9463..bafbcd419a503d 100644 --- a/test/parallel/test-tls-0-dns-altname.js +++ b/test/parallel/test-tls-0-dns-altname.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-alert-handling.js b/test/parallel/test-tls-alert-handling.js index 5e63384b0026f1..7abde524bddd1c 100644 --- a/test/parallel/test-tls-alert-handling.js +++ b/test/parallel/test-tls-alert-handling.js @@ -3,12 +3,12 @@ var common = require('../common'); var assert = require('assert'); if (!common.opensslCli) { - console.log('1..0 # Skipped: node compiled without OpenSSL CLI.'); + common.skip('node compiled without OpenSSL CLI.'); return; } if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } diff --git a/test/parallel/test-tls-alert.js b/test/parallel/test-tls-alert.js index 4eedeaa7854944..6ebb1e9e0d704b 100644 --- a/test/parallel/test-tls-alert.js +++ b/test/parallel/test-tls-alert.js @@ -3,12 +3,12 @@ var common = require('../common'); var assert = require('assert'); if (!common.opensslCli) { - console.log('1..0 # Skipped: node compiled without OpenSSL CLI.'); + common.skip('node compiled without OpenSSL CLI.'); return; } if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-async-cb-after-socket-end.js b/test/parallel/test-tls-async-cb-after-socket-end.js index d89a4e9930ca6a..902d37951a2099 100644 --- a/test/parallel/test-tls-async-cb-after-socket-end.js +++ b/test/parallel/test-tls-async-cb-after-socket-end.js @@ -7,7 +7,7 @@ var fs = require('fs'); var constants = require('constants'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } diff --git a/test/parallel/test-tls-cert-regression.js b/test/parallel/test-tls-cert-regression.js index 6e546600b68f6c..9a4ac91876bc17 100644 --- a/test/parallel/test-tls-cert-regression.js +++ b/test/parallel/test-tls-cert-regression.js @@ -3,32 +3,35 @@ var assert = require('assert'); var common = require('../common'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); -var cert = '-----BEGIN CERTIFICATE-----\n' + - 'MIIBfjCCASgCCQDmmNjAojbDQjANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJB\n' + - 'VTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0\n' + - 'cyBQdHkgTHRkMCAXDTE0MDExNjE3NTMxM1oYDzIyODcxMDMxMTc1MzEzWjBFMQsw\n' + - 'CQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJu\n' + - 'ZXQgV2lkZ2l0cyBQdHkgTHRkMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAPKwlfMX\n' + - '6HGZIt1xm7fna72eWcOYfUfSxSugghvqYgJt2Oi3lH+wsU1O9FzRIVmpeIjDXhbp\n' + - 'Mjsa1HtzSiccPXsCAwEAATANBgkqhkiG9w0BAQUFAANBAHOoKy0NkyfiYH7Ne5ka\n' + - 'uvCyndyeB4d24FlfqEUlkfaWCZlNKRaV9YhLDiEg3BcIreFo4brtKQfZzTRs0GVm\n' + - 'KHg=\n' + - '-----END CERTIFICATE-----'; -var key = '-----BEGIN RSA PRIVATE KEY-----\n' + - 'MIIBPQIBAAJBAPKwlfMX6HGZIt1xm7fna72eWcOYfUfSxSugghvqYgJt2Oi3lH+w\n' + - 'sU1O9FzRIVmpeIjDXhbpMjsa1HtzSiccPXsCAwEAAQJBAM4uU9aJE0OfdE1p/X+K\n' + - 'LrCT3XMdFCJ24GgmHyOURtwDy18upQJecDVdcZp16fjtOPmaW95GoYRyifB3R4I5\n' + - 'RxECIQD7jRM9slCSVV8xp9kOJQNpHjhRQYVGBn+pyllS2sb+RQIhAPb7Y+BIccri\n' + - 'NWnuhwCW8hA7Fkj/kaBdAwyW7L3Tvui/AiEAiqLCovMecre4Yi6GcsQ1b/6mvSmm\n' + - 'IOS+AT6zIfXPTB0CIQCJKGR3ymN/Qw5crL1GQ41cHCQtF9ickOq/lBUW+j976wIh\n' + - 'AOaJnkQrmurlRdePX6LvN/LgGAQoxwovfjcOYNnZsIVY\n' + - '-----END RSA PRIVATE KEY-----'; +var cert = +`-----BEGIN CERTIFICATE----- +MIIBfjCCASgCCQDmmNjAojbDQjANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJB +VTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0 +cyBQdHkgTHRkMCAXDTE0MDExNjE3NTMxM1oYDzIyODcxMDMxMTc1MzEzWjBFMQsw +CQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJu +ZXQgV2lkZ2l0cyBQdHkgTHRkMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAPKwlfMX +6HGZIt1xm7fna72eWcOYfUfSxSugghvqYgJt2Oi3lH+wsU1O9FzRIVmpeIjDXhbp +Mjsa1HtzSiccPXsCAwEAATANBgkqhkiG9w0BAQUFAANBAHOoKy0NkyfiYH7Ne5ka +uvCyndyeB4d24FlfqEUlkfaWCZlNKRaV9YhLDiEg3BcIreFo4brtKQfZzTRs0GVm +KHg= +-----END CERTIFICATE-----`; + +var key = +`-----BEGIN RSA PRIVATE KEY----- +MIIBPQIBAAJBAPKwlfMX6HGZIt1xm7fna72eWcOYfUfSxSugghvqYgJt2Oi3lH+w +sU1O9FzRIVmpeIjDXhbpMjsa1HtzSiccPXsCAwEAAQJBAM4uU9aJE0OfdE1p/X+K +LrCT3XMdFCJ24GgmHyOURtwDy18upQJecDVdcZp16fjtOPmaW95GoYRyifB3R4I5 +RxECIQD7jRM9slCSVV8xp9kOJQNpHjhRQYVGBn+pyllS2sb+RQIhAPb7Y+BIccri +NWnuhwCW8hA7Fkj/kaBdAwyW7L3Tvui/AiEAiqLCovMecre4Yi6GcsQ1b/6mvSmm +IOS+AT6zIfXPTB0CIQCJKGR3ymN/Qw5crL1GQ41cHCQtF9ickOq/lBUW+j976wIh +AOaJnkQrmurlRdePX6LvN/LgGAQoxwovfjcOYNnZsIVY +-----END RSA PRIVATE KEY-----`; function test(cert, key, cb) { var server = tls.createServer({ diff --git a/test/parallel/test-tls-check-server-identity.js b/test/parallel/test-tls-check-server-identity.js index 8d2155b94ea9af..c7d0a7ba1606ec 100644 --- a/test/parallel/test-tls-check-server-identity.js +++ b/test/parallel/test-tls-check-server-identity.js @@ -4,7 +4,7 @@ var assert = require('assert'); var util = require('util'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-cipher-list.js b/test/parallel/test-tls-cipher-list.js index 70c99dd91e439c..c6abce18ba3f9e 100644 --- a/test/parallel/test-tls-cipher-list.js +++ b/test/parallel/test-tls-cipher-list.js @@ -2,7 +2,7 @@ const common = require('../common'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } diff --git a/test/parallel/test-tls-client-abort.js b/test/parallel/test-tls-client-abort.js index 934162c35a426f..d2fcf3e687e676 100644 --- a/test/parallel/test-tls-client-abort.js +++ b/test/parallel/test-tls-client-abort.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-client-abort2.js b/test/parallel/test-tls-client-abort2.js index 194882e7d52e08..4bb8f00cf5fc30 100644 --- a/test/parallel/test-tls-client-abort2.js +++ b/test/parallel/test-tls-client-abort2.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-client-default-ciphers.js b/test/parallel/test-tls-client-default-ciphers.js index 9905fc45bdcd24..ebfc072dd33054 100644 --- a/test/parallel/test-tls-client-default-ciphers.js +++ b/test/parallel/test-tls-client-default-ciphers.js @@ -3,7 +3,7 @@ var assert = require('assert'); var common = require('../common'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-client-destroy-soon.js b/test/parallel/test-tls-client-destroy-soon.js index 554ac686dbdfbe..9031f29e8d0f72 100644 --- a/test/parallel/test-tls-client-destroy-soon.js +++ b/test/parallel/test-tls-client-destroy-soon.js @@ -7,7 +7,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-client-reject.js b/test/parallel/test-tls-client-reject.js index 2f9ea230a06828..db53eb4b129ee5 100644 --- a/test/parallel/test-tls-client-reject.js +++ b/test/parallel/test-tls-client-reject.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-client-resume.js b/test/parallel/test-tls-client-resume.js index 002151b7d82160..b7fd2fc9d9fb46 100644 --- a/test/parallel/test-tls-client-resume.js +++ b/test/parallel/test-tls-client-resume.js @@ -7,7 +7,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-client-verify.js b/test/parallel/test-tls-client-verify.js index b4014ab351db2b..ed142b86529fd6 100644 --- a/test/parallel/test-tls-client-verify.js +++ b/test/parallel/test-tls-client-verify.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-close-error.js b/test/parallel/test-tls-close-error.js index bd38cb55f7a17b..e338e8ecb7fd9f 100644 --- a/test/parallel/test-tls-close-error.js +++ b/test/parallel/test-tls-close-error.js @@ -4,7 +4,7 @@ var assert = require('assert'); var common = require('../common'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-close-notify.js b/test/parallel/test-tls-close-notify.js index 5545f4512d5f39..d06484af8b9942 100644 --- a/test/parallel/test-tls-close-notify.js +++ b/test/parallel/test-tls-close-notify.js @@ -3,7 +3,7 @@ var assert = require('assert'); var common = require('../common'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-cnnic-whitelist.js b/test/parallel/test-tls-cnnic-whitelist.js index 85e1d90e027b88..2b2a818969d9e9 100644 --- a/test/parallel/test-tls-cnnic-whitelist.js +++ b/test/parallel/test-tls-cnnic-whitelist.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } diff --git a/test/parallel/test-tls-connect-given-socket.js b/test/parallel/test-tls-connect-given-socket.js index 2fd44d870103b6..41ea94883ef74c 100644 --- a/test/parallel/test-tls-connect-given-socket.js +++ b/test/parallel/test-tls-connect-given-socket.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-connect-no-host.js b/test/parallel/test-tls-connect-no-host.js index a6ead6ea6dceae..86203d7f42d5ef 100644 --- a/test/parallel/test-tls-connect-no-host.js +++ b/test/parallel/test-tls-connect-no-host.js @@ -2,7 +2,7 @@ var common = require('../common'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-connect-pipe.js b/test/parallel/test-tls-connect-pipe.js index ae8062635c85b5..acf64f9af7cef3 100644 --- a/test/parallel/test-tls-connect-pipe.js +++ b/test/parallel/test-tls-connect-pipe.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-connect-simple.js b/test/parallel/test-tls-connect-simple.js index f56b4baed72aaa..f21417cef8f311 100644 --- a/test/parallel/test-tls-connect-simple.js +++ b/test/parallel/test-tls-connect-simple.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-connect.js b/test/parallel/test-tls-connect.js index ce4317ac302738..3853ea66bc80f4 100644 --- a/test/parallel/test-tls-connect.js +++ b/test/parallel/test-tls-connect.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-delayed-attach-error.js b/test/parallel/test-tls-delayed-attach-error.js index aec76d11b5628a..0fef55ff7721ad 100644 --- a/test/parallel/test-tls-delayed-attach-error.js +++ b/test/parallel/test-tls-delayed-attach-error.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-delayed-attach.js b/test/parallel/test-tls-delayed-attach.js index 2fbafd8ecb312a..ba2002dde305ea 100644 --- a/test/parallel/test-tls-delayed-attach.js +++ b/test/parallel/test-tls-delayed-attach.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-destroy-whilst-write.js b/test/parallel/test-tls-destroy-whilst-write.js index 26c20264735926..4f6ede968be408 100644 --- a/test/parallel/test-tls-destroy-whilst-write.js +++ b/test/parallel/test-tls-destroy-whilst-write.js @@ -2,7 +2,7 @@ var common = require('../common'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-dhe.js b/test/parallel/test-tls-dhe.js index ffcf52947f0bd3..4bf1b7bf2339fd 100644 --- a/test/parallel/test-tls-dhe.js +++ b/test/parallel/test-tls-dhe.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-ecdh-disable.js b/test/parallel/test-tls-ecdh-disable.js index 9bfb5f871a4822..a7e18a319afae2 100644 --- a/test/parallel/test-tls-ecdh-disable.js +++ b/test/parallel/test-tls-ecdh-disable.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-ecdh.js b/test/parallel/test-tls-ecdh.js index a6e16114b955ae..9ecd5c16e010d3 100644 --- a/test/parallel/test-tls-ecdh.js +++ b/test/parallel/test-tls-ecdh.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-econnreset.js b/test/parallel/test-tls-econnreset.js index 6ef629a159a948..7acf98a35340d1 100644 --- a/test/parallel/test-tls-econnreset.js +++ b/test/parallel/test-tls-econnreset.js @@ -3,43 +3,46 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); -var cacert = '-----BEGIN CERTIFICATE-----\n' + - 'MIIBxTCCAX8CAnXnMA0GCSqGSIb3DQEBBQUAMH0xCzAJBgNVBAYTAlVTMQswCQYD\n' + - 'VQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEZMBcGA1UEChMQU3Ryb25n\n' + - 'TG9vcCwgSW5jLjESMBAGA1UECxMJU3Ryb25nT3BzMRowGAYDVQQDExFjYS5zdHJv\n' + - 'bmdsb29wLmNvbTAeFw0xNDAxMTcyMjE1MDdaFw00MTA2MDMyMjE1MDdaMH0xCzAJ\n' + - 'BgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEZ\n' + - 'MBcGA1UEChMQU3Ryb25nTG9vcCwgSW5jLjESMBAGA1UECxMJU3Ryb25nT3BzMRow\n' + - 'GAYDVQQDExFjYS5zdHJvbmdsb29wLmNvbTBMMA0GCSqGSIb3DQEBAQUAAzsAMDgC\n' + - 'MQDKbQ6rIR5t1q1v4Ha36jrq0IkyUohy9EYNvLnXUly1PGqxby0ILlAVJ8JawpY9\n' + - 'AVkCAwEAATANBgkqhkiG9w0BAQUFAAMxALA1uS4CqQXRSAyYTfio5oyLGz71a+NM\n' + - '+0AFLBwh5AQjhGd0FcenU4OfHxyDEOJT/Q==\n' + - '-----END CERTIFICATE-----\n'; +var cacert = +`-----BEGIN CERTIFICATE----- +MIIBxTCCAX8CAnXnMA0GCSqGSIb3DQEBBQUAMH0xCzAJBgNVBAYTAlVTMQswCQYD +VQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEZMBcGA1UEChMQU3Ryb25n +TG9vcCwgSW5jLjESMBAGA1UECxMJU3Ryb25nT3BzMRowGAYDVQQDExFjYS5zdHJv +bmdsb29wLmNvbTAeFw0xNDAxMTcyMjE1MDdaFw00MTA2MDMyMjE1MDdaMH0xCzAJ +BgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEZ +MBcGA1UEChMQU3Ryb25nTG9vcCwgSW5jLjESMBAGA1UECxMJU3Ryb25nT3BzMRow +GAYDVQQDExFjYS5zdHJvbmdsb29wLmNvbTBMMA0GCSqGSIb3DQEBAQUAAzsAMDgC +MQDKbQ6rIR5t1q1v4Ha36jrq0IkyUohy9EYNvLnXUly1PGqxby0ILlAVJ8JawpY9 +AVkCAwEAATANBgkqhkiG9w0BAQUFAAMxALA1uS4CqQXRSAyYTfio5oyLGz71a+NM ++0AFLBwh5AQjhGd0FcenU4OfHxyDEOJT/Q== +-----END CERTIFICATE-----`; -var cert = '-----BEGIN CERTIFICATE-----\n' + - 'MIIBfDCCATYCAgQaMA0GCSqGSIb3DQEBBQUAMH0xCzAJBgNVBAYTAlVTMQswCQYD\n' + - 'VQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEZMBcGA1UEChMQU3Ryb25n\n' + - 'TG9vcCwgSW5jLjESMBAGA1UECxMJU3Ryb25nT3BzMRowGAYDVQQDExFjYS5zdHJv\n' + - 'bmdsb29wLmNvbTAeFw0xNDAxMTcyMjE1MDdaFw00MTA2MDMyMjE1MDdaMBkxFzAV\n' + - 'BgNVBAMTDnN0cm9uZ2xvb3AuY29tMEwwDQYJKoZIhvcNAQEBBQADOwAwOAIxAMfk\n' + - 'I0LWU15pPUwIQNMnRVhhOibi0TQmAau8FBtgwEfGK01WpfGUaJr1a41K8Uq7xwID\n' + - 'AQABoxkwFzAVBgNVHREEDjAMhwQAAAAAhwR/AAABMA0GCSqGSIb3DQEBBQUAAzEA\n' + - 'cGpYrhkrb7mIh9DNhV0qp7pGjqBzlHqB7KQXw2luLDp//6dyHBMexDCQznkhZKRU\n' + - '-----END CERTIFICATE-----\n'; +var cert = +`-----BEGIN CERTIFICATE----- +MIIBfDCCATYCAgQaMA0GCSqGSIb3DQEBBQUAMH0xCzAJBgNVBAYTAlVTMQswCQYD +VQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEZMBcGA1UEChMQU3Ryb25n +TG9vcCwgSW5jLjESMBAGA1UECxMJU3Ryb25nT3BzMRowGAYDVQQDExFjYS5zdHJv +bmdsb29wLmNvbTAeFw0xNDAxMTcyMjE1MDdaFw00MTA2MDMyMjE1MDdaMBkxFzAV +BgNVBAMTDnN0cm9uZ2xvb3AuY29tMEwwDQYJKoZIhvcNAQEBBQADOwAwOAIxAMfk +I0LWU15pPUwIQNMnRVhhOibi0TQmAau8FBtgwEfGK01WpfGUaJr1a41K8Uq7xwID +AQABoxkwFzAVBgNVHREEDjAMhwQAAAAAhwR/AAABMA0GCSqGSIb3DQEBBQUAAzEA +cGpYrhkrb7mIh9DNhV0qp7pGjqBzlHqB7KQXw2luLDp//6dyHBMexDCQznkhZKRU +-----END CERTIFICATE-----`; -var key = '-----BEGIN RSA PRIVATE KEY-----\n' + - 'MIH0AgEAAjEAx+QjQtZTXmk9TAhA0ydFWGE6JuLRNCYBq7wUG2DAR8YrTVal8ZRo\n' + - 'mvVrjUrxSrvHAgMBAAECMBCGccvSwC2r8Z9Zh1JtirQVxaL1WWpAQfmVwLe0bAgg\n' + - '/JWMU/6hS36TsYyZMxwswQIZAPTAfht/zDLb7Hwgu2twsS1Ra9w/yyvtlwIZANET\n' + - '26votwJAHK1yUrZGA5nnp5qcmQ/JUQIZAII5YV/UUZvF9D/fUplJ7puENPWNY9bN\n' + - 'pQIZAMMwxuS3XiO7two2sQF6W+JTYyX1DPCwAQIZAOYg1TvEGT38k8e8jygv8E8w\n' + - 'YqrWTeQFNQ==\n' + - '-----END RSA PRIVATE KEY-----\n'; +var key = +`-----BEGIN RSA PRIVATE KEY----- +MIH0AgEAAjEAx+QjQtZTXmk9TAhA0ydFWGE6JuLRNCYBq7wUG2DAR8YrTVal8ZRo +mvVrjUrxSrvHAgMBAAECMBCGccvSwC2r8Z9Zh1JtirQVxaL1WWpAQfmVwLe0bAgg +/JWMU/6hS36TsYyZMxwswQIZAPTAfht/zDLb7Hwgu2twsS1Ra9w/yyvtlwIZANET +26votwJAHK1yUrZGA5nnp5qcmQ/JUQIZAII5YV/UUZvF9D/fUplJ7puENPWNY9bN +pQIZAMMwxuS3XiO7two2sQF6W+JTYyX1DPCwAQIZAOYg1TvEGT38k8e8jygv8E8w +YqrWTeQFNQ== +-----END RSA PRIVATE KEY-----`; var ca = [ cert, cacert ]; diff --git a/test/parallel/test-tls-external-accessor.js b/test/parallel/test-tls-external-accessor.js index 919af0e8f33e4f..08a4ad16e8b4d4 100644 --- a/test/parallel/test-tls-external-accessor.js +++ b/test/parallel/test-tls-external-accessor.js @@ -4,7 +4,7 @@ const common = require('../common'); const assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } diff --git a/test/parallel/test-tls-fast-writing.js b/test/parallel/test-tls-fast-writing.js index 2a0130c162228d..98156854c5fc8e 100644 --- a/test/parallel/test-tls-fast-writing.js +++ b/test/parallel/test-tls-fast-writing.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-friendly-error-message.js b/test/parallel/test-tls-friendly-error-message.js index ee2c21f6b5c220..38197b6201770f 100644 --- a/test/parallel/test-tls-friendly-error-message.js +++ b/test/parallel/test-tls-friendly-error-message.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-getcipher.js b/test/parallel/test-tls-getcipher.js index 646d396eca9a86..9e525b8c477792 100644 --- a/test/parallel/test-tls-getcipher.js +++ b/test/parallel/test-tls-getcipher.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-handshake-error.js b/test/parallel/test-tls-handshake-error.js index f65440ed93b1a3..3bb583bb2c7802 100644 --- a/test/parallel/test-tls-handshake-error.js +++ b/test/parallel/test-tls-handshake-error.js @@ -4,7 +4,7 @@ var assert = require('assert'); var common = require('../common'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-handshake-nohang.js b/test/parallel/test-tls-handshake-nohang.js index 374ac02a2f45b5..052833a50e3462 100644 --- a/test/parallel/test-tls-handshake-nohang.js +++ b/test/parallel/test-tls-handshake-nohang.js @@ -2,7 +2,7 @@ var common = require('../common'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-hello-parser-failure.js b/test/parallel/test-tls-hello-parser-failure.js index 3378583af220f2..e35fa5483010a3 100644 --- a/test/parallel/test-tls-hello-parser-failure.js +++ b/test/parallel/test-tls-hello-parser-failure.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-honorcipherorder.js b/test/parallel/test-tls-honorcipherorder.js index 28c930b07edc28..dd3ead8d42db3d 100644 --- a/test/parallel/test-tls-honorcipherorder.js +++ b/test/parallel/test-tls-honorcipherorder.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-inception.js b/test/parallel/test-tls-inception.js index 8946f52bdd63d4..2f4429c41d93e2 100644 --- a/test/parallel/test-tls-inception.js +++ b/test/parallel/test-tls-inception.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-interleave.js b/test/parallel/test-tls-interleave.js index fd93a05e593107..0c78e3e71a20c4 100644 --- a/test/parallel/test-tls-interleave.js +++ b/test/parallel/test-tls-interleave.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-invoke-queued.js b/test/parallel/test-tls-invoke-queued.js index efa5c0aa9aa31d..8b0d0e1271d4b2 100644 --- a/test/parallel/test-tls-invoke-queued.js +++ b/test/parallel/test-tls-invoke-queued.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-js-stream.js b/test/parallel/test-tls-js-stream.js index 1c5e749911b6be..ddfcaf94bf19c4 100644 --- a/test/parallel/test-tls-js-stream.js +++ b/test/parallel/test-tls-js-stream.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-junk-closes-server.js b/test/parallel/test-tls-junk-closes-server.js index 5ee4e025f5dc18..5e20e753395912 100644 --- a/test/parallel/test-tls-junk-closes-server.js +++ b/test/parallel/test-tls-junk-closes-server.js @@ -2,7 +2,7 @@ var common = require('../common'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-junk-server.js b/test/parallel/test-tls-junk-server.js index 4eb8129a11dfd6..af454730218f60 100644 --- a/test/parallel/test-tls-junk-server.js +++ b/test/parallel/test-tls-junk-server.js @@ -2,7 +2,7 @@ const common = require('../common'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } diff --git a/test/parallel/test-tls-key-mismatch.js b/test/parallel/test-tls-key-mismatch.js index 2e17a4931078c7..f0eb8121bd68e5 100644 --- a/test/parallel/test-tls-key-mismatch.js +++ b/test/parallel/test-tls-key-mismatch.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-legacy-onselect.js b/test/parallel/test-tls-legacy-onselect.js index d3b20d5d8a4cef..6151d503c4d0a5 100644 --- a/test/parallel/test-tls-legacy-onselect.js +++ b/test/parallel/test-tls-legacy-onselect.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-max-send-fragment.js b/test/parallel/test-tls-max-send-fragment.js index 746994a69ca421..29243c93177e3a 100644 --- a/test/parallel/test-tls-max-send-fragment.js +++ b/test/parallel/test-tls-max-send-fragment.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-multi-key.js b/test/parallel/test-tls-multi-key.js index 17b409f284dcba..8c8fd5ded4a0b6 100644 --- a/test/parallel/test-tls-multi-key.js +++ b/test/parallel/test-tls-multi-key.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-no-cert-required.js b/test/parallel/test-tls-no-cert-required.js index 97863606cf2a96..72e24c59f63ae1 100644 --- a/test/parallel/test-tls-no-cert-required.js +++ b/test/parallel/test-tls-no-cert-required.js @@ -2,7 +2,7 @@ var common = require('../common'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-no-rsa-key.js b/test/parallel/test-tls-no-rsa-key.js index ff9806cdb02614..2d2055eae8f5b5 100644 --- a/test/parallel/test-tls-no-rsa-key.js +++ b/test/parallel/test-tls-no-rsa-key.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-no-sslv23.js b/test/parallel/test-tls-no-sslv23.js index 702019a0bc8575..0db61afe0e97ec 100644 --- a/test/parallel/test-tls-no-sslv23.js +++ b/test/parallel/test-tls-no-sslv23.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-no-sslv3.js b/test/parallel/test-tls-no-sslv3.js index 44a8b4e2c0f920..3ab62a26724149 100644 --- a/test/parallel/test-tls-no-sslv3.js +++ b/test/parallel/test-tls-no-sslv3.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); @@ -12,7 +12,7 @@ var fs = require('fs'); var spawn = require('child_process').spawn; if (common.opensslCli === false) { - console.log('1..0 # Skipped: node compiled without OpenSSL CLI.'); + common.skip('node compiled without OpenSSL CLI.'); return; } @@ -52,7 +52,7 @@ server.on('clientError', (err) => errors.push(err)); process.on('exit', function() { if (/unknown option -ssl3/.test(stderr)) { - console.log('1..0 # Skipped: `openssl s_client -ssl3` not supported.'); + common.skip('`openssl s_client -ssl3` not supported.'); } else { assert.equal(errors.length, 1); assert(/:wrong version number/.test(errors[0].message)); diff --git a/test/parallel/test-tls-npn-server-client.js b/test/parallel/test-tls-npn-server-client.js index d74d65c8b03bd7..446d249c60856d 100644 --- a/test/parallel/test-tls-npn-server-client.js +++ b/test/parallel/test-tls-npn-server-client.js @@ -1,6 +1,6 @@ 'use strict'; if (!process.features.tls_npn) { - console.log('1..0 # Skipped: node compiled without OpenSSL or ' + + common.skip('node compiled without OpenSSL or ' + 'with old OpenSSL version.'); return; } @@ -10,7 +10,7 @@ const assert = require('assert'); const fs = require('fs'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-ocsp-callback.js b/test/parallel/test-tls-ocsp-callback.js index e9443f45357995..07ce53c53f02f8 100644 --- a/test/parallel/test-tls-ocsp-callback.js +++ b/test/parallel/test-tls-ocsp-callback.js @@ -2,17 +2,17 @@ var common = require('../common'); if (!process.features.tls_ocsp) { - console.log('1..0 # Skipped: node compiled without OpenSSL or ' + + common.skip('node compiled without OpenSSL or ' + 'with old OpenSSL version.'); return; } if (!common.opensslCli) { - console.log('1..0 # Skipped: node compiled without OpenSSL CLI.'); + common.skip('node compiled without OpenSSL CLI.'); return; } if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-on-empty-socket.js b/test/parallel/test-tls-on-empty-socket.js index 84c95a99db5f7d..1b5a3f342f5cbc 100644 --- a/test/parallel/test-tls-on-empty-socket.js +++ b/test/parallel/test-tls-on-empty-socket.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-over-http-tunnel.js b/test/parallel/test-tls-over-http-tunnel.js index cf3ad776f7c9de..eab72e411555b4 100644 --- a/test/parallel/test-tls-over-http-tunnel.js +++ b/test/parallel/test-tls-over-http-tunnel.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var https = require('https'); diff --git a/test/parallel/test-tls-parse-cert-string.js b/test/parallel/test-tls-parse-cert-string.js index 11128783871fe4..6607d6974c95b3 100644 --- a/test/parallel/test-tls-parse-cert-string.js +++ b/test/parallel/test-tls-parse-cert-string.js @@ -4,8 +4,8 @@ require('../common'); const assert = require('assert'); const tls = require('tls'); -const singles = 'C=US\nST=CA\nL=SF\nO=Node.js Foundation\nOU=Node.js\nCN=ca1\n' - + 'emailAddress=ry@clouds.org'; +const singles = 'C=US\nST=CA\nL=SF\nO=Node.js Foundation\nOU=Node.js\n' + + 'CN=ca1\nemailAddress=ry@clouds.org'; const singlesOut = tls.parseCertString(singles); assert.deepEqual(singlesOut, { C: 'US', @@ -18,7 +18,7 @@ assert.deepEqual(singlesOut, { }); const doubles = 'OU=Domain Control Validated\nOU=PositiveSSL Wildcard\n' + - 'CN=*.nodejs.org'; + 'CN=*.nodejs.org'; const doublesOut = tls.parseCertString(doubles); assert.deepEqual(doublesOut, { OU: [ 'Domain Control Validated', 'PositiveSSL Wildcard' ], diff --git a/test/parallel/test-tls-passphrase.js b/test/parallel/test-tls-passphrase.js index 05015399553fc8..f04c8e28076068 100644 --- a/test/parallel/test-tls-passphrase.js +++ b/test/parallel/test-tls-passphrase.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-pause.js b/test/parallel/test-tls-pause.js index a19c4aee403d87..4943cfdfefe883 100644 --- a/test/parallel/test-tls-pause.js +++ b/test/parallel/test-tls-pause.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-peer-certificate-encoding.js b/test/parallel/test-tls-peer-certificate-encoding.js index 32b1583a0c4840..00f42c4065907b 100644 --- a/test/parallel/test-tls-peer-certificate-encoding.js +++ b/test/parallel/test-tls-peer-certificate-encoding.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-peer-certificate-multi-keys.js b/test/parallel/test-tls-peer-certificate-multi-keys.js index 50ce9037f8d755..c70620389fa198 100644 --- a/test/parallel/test-tls-peer-certificate-multi-keys.js +++ b/test/parallel/test-tls-peer-certificate-multi-keys.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-peer-certificate.js b/test/parallel/test-tls-peer-certificate.js index e043c5933b98ed..a6618d5fc62d62 100644 --- a/test/parallel/test-tls-peer-certificate.js +++ b/test/parallel/test-tls-peer-certificate.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-pfx-gh-5100-regr.js b/test/parallel/test-tls-pfx-gh-5100-regr.js index 865ac2ba3f299a..4123efde71c7c6 100644 --- a/test/parallel/test-tls-pfx-gh-5100-regr.js +++ b/test/parallel/test-tls-pfx-gh-5100-regr.js @@ -3,7 +3,7 @@ const common = require('../common'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: node compiled without crypto.'); + common.skip('node compiled without crypto.'); return; } diff --git a/test/parallel/test-tls-regr-gh-5108.js b/test/parallel/test-tls-regr-gh-5108.js index 5efcb76eab9c7f..af295fe0db170d 100644 --- a/test/parallel/test-tls-regr-gh-5108.js +++ b/test/parallel/test-tls-regr-gh-5108.js @@ -2,7 +2,7 @@ const common = require('../common'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } diff --git a/test/parallel/test-tls-request-timeout.js b/test/parallel/test-tls-request-timeout.js index 0db2a613afc9e4..6c24c0c2ce0ba1 100644 --- a/test/parallel/test-tls-request-timeout.js +++ b/test/parallel/test-tls-request-timeout.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-securepair-server.js b/test/parallel/test-tls-securepair-server.js index ef182f3b5ded19..f846f36d3ff89a 100644 --- a/test/parallel/test-tls-securepair-server.js +++ b/test/parallel/test-tls-securepair-server.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-server-connection-server.js b/test/parallel/test-tls-server-connection-server.js index 534a16a440ca6c..41847cb8b362d0 100644 --- a/test/parallel/test-tls-server-connection-server.js +++ b/test/parallel/test-tls-server-connection-server.js @@ -2,7 +2,7 @@ const common = require('../common'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } diff --git a/test/parallel/test-tls-server-verify.js b/test/parallel/test-tls-server-verify.js index c9d4d263f5be7d..f1a6132a661a38 100644 --- a/test/parallel/test-tls-server-verify.js +++ b/test/parallel/test-tls-server-verify.js @@ -2,7 +2,7 @@ var common = require('../common'); if (!common.opensslCli) { - console.log('1..0 # Skipped: node compiled without OpenSSL CLI.'); + common.skip('node compiled without OpenSSL CLI.'); return; } @@ -99,7 +99,7 @@ var testCases = ]; if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-session-cache.js b/test/parallel/test-tls-session-cache.js index ddceb973f5fc80..c2bebc39dd1934 100644 --- a/test/parallel/test-tls-session-cache.js +++ b/test/parallel/test-tls-session-cache.js @@ -2,12 +2,12 @@ var common = require('../common'); if (!common.opensslCli) { - console.log('1..0 # Skipped: node compiled without OpenSSL CLI.'); + common.skip('node compiled without OpenSSL CLI.'); return; } if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } diff --git a/test/parallel/test-tls-set-ciphers.js b/test/parallel/test-tls-set-ciphers.js index 696644cdc43a5b..efdd4260adbad3 100644 --- a/test/parallel/test-tls-set-ciphers.js +++ b/test/parallel/test-tls-set-ciphers.js @@ -2,12 +2,12 @@ var common = require('../common'); if (!common.opensslCli) { - console.log('1..0 # Skipped: node compiled without OpenSSL CLI.'); + common.skip('node compiled without OpenSSL CLI.'); return; } if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } diff --git a/test/parallel/test-tls-set-encoding.js b/test/parallel/test-tls-set-encoding.js index ec728dad0c88ec..bd34ede8f5c188 100644 --- a/test/parallel/test-tls-set-encoding.js +++ b/test/parallel/test-tls-set-encoding.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-sni-option.js b/test/parallel/test-tls-sni-option.js index 83e62133363677..5a07225fb58b25 100644 --- a/test/parallel/test-tls-sni-option.js +++ b/test/parallel/test-tls-sni-option.js @@ -1,6 +1,6 @@ 'use strict'; if (!process.features.tls_sni) { - console.log('1..0 # Skipped: node compiled without OpenSSL or ' + + common.skip('node compiled without OpenSSL or ' + 'with old OpenSSL version.'); return; } @@ -10,7 +10,7 @@ const assert = require('assert'); const fs = require('fs'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-sni-server-client.js b/test/parallel/test-tls-sni-server-client.js index 733713c8e72df8..62b22b5289e8fa 100644 --- a/test/parallel/test-tls-sni-server-client.js +++ b/test/parallel/test-tls-sni-server-client.js @@ -1,6 +1,6 @@ 'use strict'; if (!process.features.tls_sni) { - console.log('1..0 # Skipped: node compiled without OpenSSL or ' + + common.skip('node compiled without OpenSSL or ' + 'with old OpenSSL version.'); return; } @@ -10,7 +10,7 @@ const assert = require('assert'); const fs = require('fs'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-socket-default-options.js b/test/parallel/test-tls-socket-default-options.js index c2c6e518bbc4d8..70f24ebf2b80ef 100644 --- a/test/parallel/test-tls-socket-default-options.js +++ b/test/parallel/test-tls-socket-default-options.js @@ -3,7 +3,7 @@ const common = require('../common'); const assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } const tls = require('tls'); diff --git a/test/parallel/test-tls-ticket-cluster.js b/test/parallel/test-tls-ticket-cluster.js index 1fd1776ca8199f..4d1667a7adcab2 100644 --- a/test/parallel/test-tls-ticket-cluster.js +++ b/test/parallel/test-tls-ticket-cluster.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-ticket.js b/test/parallel/test-tls-ticket.js index ed776100026596..0e43ffaeaea0cb 100644 --- a/test/parallel/test-tls-ticket.js +++ b/test/parallel/test-tls-ticket.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-timeout-server-2.js b/test/parallel/test-tls-timeout-server-2.js index 29cce0f6af8eca..44847e057311dc 100644 --- a/test/parallel/test-tls-timeout-server-2.js +++ b/test/parallel/test-tls-timeout-server-2.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-timeout-server.js b/test/parallel/test-tls-timeout-server.js index e3ed246386647f..20cd2aa7207b96 100644 --- a/test/parallel/test-tls-timeout-server.js +++ b/test/parallel/test-tls-timeout-server.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-wrap-timeout.js b/test/parallel/test-tls-wrap-timeout.js index d9e260f99e70c4..c260a03bf37b28 100644 --- a/test/parallel/test-tls-wrap-timeout.js +++ b/test/parallel/test-tls-wrap-timeout.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tls-zero-clear-in.js b/test/parallel/test-tls-zero-clear-in.js index 652d6d176d7324..7b50bbd81e729c 100644 --- a/test/parallel/test-tls-zero-clear-in.js +++ b/test/parallel/test-tls-zero-clear-in.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/parallel/test-tty-wrap.js b/test/parallel/test-tty-wrap.js index 5e124dc89f7b87..c307c46c2fccca 100644 --- a/test/parallel/test-tty-wrap.js +++ b/test/parallel/test-tty-wrap.js @@ -1,12 +1,12 @@ 'use strict'; -require('../common'); +const common = require('../common'); var assert = require('assert'); var TTY = process.binding('tty_wrap').TTY; var isTTY = process.binding('tty_wrap').isTTY; if (isTTY(1) == false) { - console.log('1..0 # Skipped: fd 1 is not a tty.'); + common.skip('fd 1 is not a tty.'); return; } diff --git a/test/parallel/test-vm-static-this.js b/test/parallel/test-vm-static-this.js index 143e4e12216d5e..a3cf2d820c3423 100644 --- a/test/parallel/test-vm-static-this.js +++ b/test/parallel/test-vm-static-this.js @@ -21,8 +21,8 @@ assert.equal(2, global.hello); console.error('pass values'); var code = 'foo = 1;' + - 'bar = 2;' + - 'if (typeof baz !== \'undefined\') throw new Error(\'test fail\');'; + 'bar = 2;' + + 'if (typeof baz !== \'undefined\') throw new Error(\'test fail\');'; global.foo = 2; global.obj = { foo: 0, baz: 3 }; /* eslint-disable no-unused-vars */ diff --git a/test/parallel/test-zlib-convenience-methods.js b/test/parallel/test-zlib-convenience-methods.js index 70c102efd2862c..ccb3347266a9b4 100644 --- a/test/parallel/test-zlib-convenience-methods.js +++ b/test/parallel/test-zlib-convenience-methods.js @@ -23,8 +23,8 @@ var opts = { zlib[method[0]](expect, opts, function(err, result) { zlib[method[1]](result, opts, function(err, result) { assert.equal(result, expect, - 'Should get original string after ' + - method[0] + '/' + method[1] + ' with options.'); + 'Should get original string after ' + + method[0] + '/' + method[1] + ' with options.'); hadRun++; }); }); @@ -32,8 +32,8 @@ var opts = { zlib[method[0]](expect, function(err, result) { zlib[method[1]](result, function(err, result) { assert.equal(result, expect, - 'Should get original string after ' + - method[0] + '/' + method[1] + ' without options.'); + 'Should get original string after ' + + method[0] + '/' + method[1] + ' without options.'); hadRun++; }); }); @@ -41,15 +41,15 @@ var opts = { var result = zlib[method[0] + 'Sync'](expect, opts); result = zlib[method[1] + 'Sync'](result, opts); assert.equal(result, expect, - 'Should get original string after ' + - method[0] + '/' + method[1] + ' with options.'); + 'Should get original string after ' + + method[0] + '/' + method[1] + ' with options.'); hadRun++; result = zlib[method[0] + 'Sync'](expect); result = zlib[method[1] + 'Sync'](result); assert.equal(result, expect, - 'Should get original string after ' + - method[0] + '/' + method[1] + ' without options.'); + 'Should get original string after ' + + method[0] + '/' + method[1] + ' without options.'); hadRun++; }); diff --git a/test/parallel/test-zlib-flush-drain.js b/test/parallel/test-zlib-flush-drain.js index 14a42e76cc3874..fcc17ad589d11f 100644 --- a/test/parallel/test-zlib-flush-drain.js +++ b/test/parallel/test-zlib-flush-drain.js @@ -38,11 +38,11 @@ deflater.on('drain', function() { process.once('exit', function() { assert.equal(beforeFlush, true, - 'before calling flush the writable stream should need to drain'); + 'before calling flush, writable stream should need to drain'); assert.equal(afterFlush, false, - 'after calling flush the writable stream should not need to drain'); + 'after calling flush, writable stream should not need to drain'); assert.equal(drainCount, 1, - 'the deflater should have emitted a single drain event'); + 'the deflater should have emitted a single drain event'); assert.equal(flushCount, 2, - 'flush should be called twice'); + 'flush should be called twice'); }); diff --git a/test/parallel/test-zlib-from-string.js b/test/parallel/test-zlib-from-string.js index 14c747fc433692..1c9f0eb012d261 100644 --- a/test/parallel/test-zlib-from-string.js +++ b/test/parallel/test-zlib-from-string.js @@ -5,27 +5,32 @@ require('../common'); var assert = require('assert'); var zlib = require('zlib'); -var inputString = 'ΩΩLorem ipsum dolor sit amet, consectetur adipiscing el' + - 'it. Morbi faucibus, purus at gravida dictum, libero arcu convallis la' + - 'cus, in commodo libero metus eu nisi. Nullam commodo, neque nec porta' + - ' placerat, nisi est fermentum augue, vitae gravida tellus sapien sit ' + - 'amet tellus. Aenean non diam orci. Proin quis elit turpis. Suspendiss' + - 'e non diam ipsum. Suspendisse nec ullamcorper odio. Vestibulum arcu m' + - 'i, sodales non suscipit id, ultrices ut massa. Sed ac sem sit amet ar' + - 'cu malesuada fermentum. Nunc sed. '; -var expectedBase64Deflate = 'eJxdUUtOQzEMvMoc4OndgT0gJCT2buJWlpI4jePeqZfpm' + - 'XAKLRKbLOzx/HK73q6vOrhCunlF1qIDJhNUeW5I2ozT5OkDlKWLJWkncJG5403HQXAkT3' + - 'Jw29B9uIEmToMukglZ0vS6ociBh4JG8sV4oVLEUCitK2kxq1WzPnChHDzsaGKy491Lofo' + - 'AbWh8do43oeuYhB5EPCjcLjzYJo48KrfQBvnJecNFJvHT1+RSQsGoC7dn2t/xjhduTA1N' + - 'WyQIZR0pbHwMDatnD+crPqKSqGPHp1vnlsWM/07ubf7bheF7kqSj84Bm0R1fYTfaK8vqq' + - 'qfKBtNMhe3OZh6N95CTvMX5HJJi4xOVzCgUOIMSLH7wmeOHaFE4RdpnGavKtrB5xzfO/Ll9'; -var expectedBase64Gzip = 'H4sIAAAAAAAAA11RS05DMQy8yhzg6d2BPSAkJPZu4laWkjiN' + - '496pl+mZcAotEpss7PH8crverq86uEK6eUXWogMmE1R5bkjajNPk6QOUpYslaSdwkbnjT' + - 'cdBcCRPcnDb0H24gSZOgy6SCVnS9LqhyIGHgkbyxXihUsRQKK0raTGrVbM+cKEcPOxoYr' + - 'Lj3Uuh+gBtaHx2jjeh65iEHkQ8KNwuPNgmjjwqt9AG+cl5w0Um8dPX5FJCwagLt2fa3/G' + - 'OF25MDU1bJAhlHSlsfAwNq2cP5ys+opKoY8enW+eWxYz/Tu5t/tuF4XuSpKPzgGbRHV9h' + - 'N9ory+qqp8oG00yF7c5mHo33kJO8xfkckmLjE5XMKBQ4gxIsfvCZ44doUThF2mcZq8q2s' + - 'HnHNzRtagj5AQAA'; +var inputString = 'ΩΩLorem ipsum dolor sit amet, consectetur adipiscing elit.' + + ' Morbi faucibus, purus at gravida dictum, libero arcu conv' + + 'allis lacus, in commodo libero metus eu nisi. Nullam commo' + + 'do, neque nec porta placerat, nisi est fermentum augue, vi' + + 'tae gravida tellus sapien sit amet tellus. Aenean non diam' + + ' orci. Proin quis elit turpis. Suspendisse non diam ipsum.' + + ' Suspendisse nec ullamcorper odio. Vestibulum arcu mi, sod' + + 'ales non suscipit id, ultrices ut massa. Sed ac sem sit am' + + 'et arcu malesuada fermentum. Nunc sed. '; +var expectedBase64Deflate = 'eJxdUUtOQzEMvMoc4OndgT0gJCT2buJWlpI4jePeqZfpmXAK' + + 'LRKbLOzx/HK73q6vOrhCunlF1qIDJhNUeW5I2ozT5OkDlKWL' + + 'JWkncJG5403HQXAkT3Jw29B9uIEmToMukglZ0vS6ociBh4JG' + + '8sV4oVLEUCitK2kxq1WzPnChHDzsaGKy491LofoAbWh8do43' + + 'oeuYhB5EPCjcLjzYJo48KrfQBvnJecNFJvHT1+RSQsGoC7dn' + + '2t/xjhduTA1NWyQIZR0pbHwMDatnD+crPqKSqGPHp1vnlsWM' + + '/07ubf7bheF7kqSj84Bm0R1fYTfaK8vqqqfKBtNMhe3OZh6N' + + '95CTvMX5HJJi4xOVzCgUOIMSLH7wmeOHaFE4RdpnGavKtrB5' + + 'xzfO/Ll9'; +var expectedBase64Gzip = 'H4sIAAAAAAAAA11RS05DMQy8yhzg6d2BPSAkJPZu4laWkjiN496' + + 'pl+mZcAotEpss7PH8crverq86uEK6eUXWogMmE1R5bkjajNPk6Q' + + 'OUpYslaSdwkbnjTcdBcCRPcnDb0H24gSZOgy6SCVnS9LqhyIGHg' + + 'kbyxXihUsRQKK0raTGrVbM+cKEcPOxoYrLj3Uuh+gBtaHx2jjeh' + + '65iEHkQ8KNwuPNgmjjwqt9AG+cl5w0Um8dPX5FJCwagLt2fa3/G' + + 'OF25MDU1bJAhlHSlsfAwNq2cP5ys+opKoY8enW+eWxYz/Tu5t/t' + + 'uF4XuSpKPzgGbRHV9hN9ory+qqp8oG00yF7c5mHo33kJO8xfkck' + + 'mLjE5XMKBQ4gxIsfvCZ44doUThF2mcZq8q2sHnHNzRtagj5AQAA'; zlib.deflate(inputString, function(err, buffer) { assert.equal(buffer.toString('base64'), expectedBase64Deflate, diff --git a/test/parallel/test-zlib-random-byte-pipes.js b/test/parallel/test-zlib-random-byte-pipes.js index 4b28b3871800d1..286f47bf114211 100644 --- a/test/parallel/test-zlib-random-byte-pipes.js +++ b/test/parallel/test-zlib-random-byte-pipes.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var crypto = require('crypto'); diff --git a/test/parallel/test-zlib.js b/test/parallel/test-zlib.js index 305d28865d992b..caaa62c69ae70b 100644 --- a/test/parallel/test-zlib.js +++ b/test/parallel/test-zlib.js @@ -165,9 +165,9 @@ Object.keys(tests).forEach(function(file) { // verify that the same exact buffer comes out the other end. buf.on('data', function(c) { var msg = file + ' ' + - chunkSize + ' ' + - JSON.stringify(opts) + ' ' + - Def.name + ' -> ' + Inf.name; + chunkSize + ' ' + + JSON.stringify(opts) + ' ' + + Def.name + ' -> ' + Inf.name; var ok = true; var testNum = ++done; for (var i = 0; i < Math.max(c.length, test.length); i++) { diff --git a/test/pummel/test-abort-fatal-error.js b/test/pummel/test-abort-fatal-error.js index 20d5c137d53aaf..f84440b9270d72 100644 --- a/test/pummel/test-abort-fatal-error.js +++ b/test/pummel/test-abort-fatal-error.js @@ -3,7 +3,7 @@ var assert = require('assert'); var common = require('../common'); if (common.isWindows) { - console.log('1..0 # Skipped: no RLIMIT_NOFILE on Windows'); + common.skip('no RLIMIT_NOFILE on Windows'); return; } diff --git a/test/pummel/test-crypto-dh.js b/test/pummel/test-crypto-dh.js index d4e1c493b7266d..dfef8c6a657cf2 100644 --- a/test/pummel/test-crypto-dh.js +++ b/test/pummel/test-crypto-dh.js @@ -5,7 +5,7 @@ const assert = require('assert'); try { var crypto = require('crypto'); } catch (e) { - console.log('1..0 # Skipped: node compiled without OpenSSL.'); + common.skip('node compiled without OpenSSL.'); return; } diff --git a/test/pummel/test-dh-regr.js b/test/pummel/test-dh-regr.js index e6b2f82bd9e465..3ebf8d44382fe9 100644 --- a/test/pummel/test-dh-regr.js +++ b/test/pummel/test-dh-regr.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var crypto = require('crypto'); diff --git a/test/pummel/test-dtrace-jsstack.js b/test/pummel/test-dtrace-jsstack.js index f53c950baa32e9..b50794bd7b78cf 100644 --- a/test/pummel/test-dtrace-jsstack.js +++ b/test/pummel/test-dtrace-jsstack.js @@ -1,10 +1,10 @@ 'use strict'; -require('../common'); +const common = require('../common'); var assert = require('assert'); var os = require('os'); if (os.type() != 'SunOS') { - console.log('1..0 # Skipped: no DTRACE support'); + common.skip('no DTRACE support'); return; } @@ -80,4 +80,3 @@ dtrace.on('exit', function(code) { }); setTimeout(doogle, 10); - diff --git a/test/pummel/test-https-ci-reneg-attack.js b/test/pummel/test-https-ci-reneg-attack.js index 05622c896e4005..701963606e6d80 100644 --- a/test/pummel/test-https-ci-reneg-attack.js +++ b/test/pummel/test-https-ci-reneg-attack.js @@ -4,7 +4,7 @@ var assert = require('assert'); var spawn = require('child_process').spawn; if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); @@ -13,7 +13,7 @@ var https = require('https'); var fs = require('fs'); if (!common.opensslCli) { - console.log('1..0 # Skipped: node compiled without OpenSSL CLI.'); + common.skip('node compiled without OpenSSL CLI.'); return; } diff --git a/test/pummel/test-https-large-response.js b/test/pummel/test-https-large-response.js index 1979c6737f76b3..36d8e368709770 100644 --- a/test/pummel/test-https-large-response.js +++ b/test/pummel/test-https-large-response.js @@ -5,7 +5,7 @@ var assert = require('assert'); var fs = require('fs'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var https = require('https'); diff --git a/test/pummel/test-https-no-reader.js b/test/pummel/test-https-no-reader.js index d9d2b64cc73d62..0e48ebfc10347f 100644 --- a/test/pummel/test-https-no-reader.js +++ b/test/pummel/test-https-no-reader.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var https = require('https'); diff --git a/test/pummel/test-keep-alive.js b/test/pummel/test-keep-alive.js index 46190555b27263..1861b2df970e18 100644 --- a/test/pummel/test-keep-alive.js +++ b/test/pummel/test-keep-alive.js @@ -8,7 +8,7 @@ var http = require('http'); var url = require('url'); if (common.isWindows) { - console.log('1..0 # Skipped: no `wrk` on windows'); + common.skip('no `wrk` on windows'); return; } diff --git a/test/pummel/test-regress-GH-892.js b/test/pummel/test-regress-GH-892.js index 11cab1b8b6230e..8bbf3c8f1a0ff4 100644 --- a/test/pummel/test-regress-GH-892.js +++ b/test/pummel/test-regress-GH-892.js @@ -10,7 +10,7 @@ var assert = require('assert'); var spawn = require('child_process').spawn; if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var https = require('https'); diff --git a/test/pummel/test-tls-ci-reneg-attack.js b/test/pummel/test-tls-ci-reneg-attack.js index 3fad5e6a4e7aac..b62b8944357ee7 100644 --- a/test/pummel/test-tls-ci-reneg-attack.js +++ b/test/pummel/test-tls-ci-reneg-attack.js @@ -4,7 +4,7 @@ var assert = require('assert'); var spawn = require('child_process').spawn; if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); @@ -12,7 +12,7 @@ var tls = require('tls'); var fs = require('fs'); if (!common.opensslCli) { - console.log('1..0 # Skipped: node compiled without OpenSSL CLI.'); + common.skip('node compiled without OpenSSL CLI.'); return; } diff --git a/test/pummel/test-tls-connect-memleak.js b/test/pummel/test-tls-connect-memleak.js index b8ddc78fab6e4e..3b6cf203cd80c1 100644 --- a/test/pummel/test-tls-connect-memleak.js +++ b/test/pummel/test-tls-connect-memleak.js @@ -5,7 +5,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/pummel/test-tls-securepair-client.js b/test/pummel/test-tls-securepair-client.js index 3d33ef8f21623f..5dd2af65b2ba5f 100644 --- a/test/pummel/test-tls-securepair-client.js +++ b/test/pummel/test-tls-securepair-client.js @@ -4,12 +4,12 @@ var common = require('../common'); if (!common.opensslCli) { - console.log('1..0 # Skipped: node compiled without OpenSSL CLI.'); + common.skip('node compiled without OpenSSL CLI.'); return; } if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } diff --git a/test/pummel/test-tls-server-large-request.js b/test/pummel/test-tls-server-large-request.js index cb740c63ed7d68..cd201a0aa71b27 100644 --- a/test/pummel/test-tls-server-large-request.js +++ b/test/pummel/test-tls-server-large-request.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/pummel/test-tls-session-timeout.js b/test/pummel/test-tls-session-timeout.js index 64548e204342e6..225d743eb8ab89 100644 --- a/test/pummel/test-tls-session-timeout.js +++ b/test/pummel/test-tls-session-timeout.js @@ -2,12 +2,12 @@ var common = require('../common'); if (!common.opensslCli) { - console.log('1..0 # Skipped: node compiled without OpenSSL CLI.'); + common.skip('node compiled without OpenSSL CLI.'); return; } if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } diff --git a/test/pummel/test-tls-throttle.js b/test/pummel/test-tls-throttle.js index 0e5cd455c8c4c4..d80544eae610e7 100644 --- a/test/pummel/test-tls-throttle.js +++ b/test/pummel/test-tls-throttle.js @@ -6,7 +6,7 @@ var common = require('../common'); var assert = require('assert'); if (!common.hasCrypto) { - console.log('1..0 # Skipped: missing crypto'); + common.skip('missing crypto'); return; } var tls = require('tls'); diff --git a/test/sequential/test-child-process-emfile.js b/test/sequential/test-child-process-emfile.js index 2ac0b6c0b23a73..f186db54016a40 100644 --- a/test/sequential/test-child-process-emfile.js +++ b/test/sequential/test-child-process-emfile.js @@ -5,7 +5,7 @@ const child_process = require('child_process'); const fs = require('fs'); if (common.isWindows) { - console.log('1..0 # Skipped: no RLIMIT_NOFILE on Windows'); + common.skip('no RLIMIT_NOFILE on Windows'); return; } diff --git a/test/sequential/test-module-loading.js b/test/sequential/test-module-loading.js index 8e7f641326e7c9..fea3ac04298901 100644 --- a/test/sequential/test-module-loading.js +++ b/test/sequential/test-module-loading.js @@ -251,12 +251,12 @@ assert.deepEqual(children, { assert.throws(function() { console.error('require non-string'); require({ foo: 'bar' }); -}, 'path must be a string'); +}, /path must be a string/); assert.throws(function() { console.error('require empty string'); require(''); -}, 'missing path'); +}, /missing path/); process.on('exit', function() { assert.ok(a.A instanceof Function); diff --git a/test/sequential/test-net-server-address.js b/test/sequential/test-net-server-address.js index ddc65c2df2b828..b49a94d8560df0 100644 --- a/test/sequential/test-net-server-address.js +++ b/test/sequential/test-net-server-address.js @@ -20,7 +20,7 @@ server_ipv4.listen(common.PORT, common.localhostIPv4, function() { }); if (!common.hasIPv6) { - console.log('1..0 # Skipped: ipv6 part of test, no IPv6 support'); + common.skip('ipv6 part of test, no IPv6 support'); return; } diff --git a/test/sequential/test-vm-timeout-rethrow.js b/test/sequential/test-vm-timeout-rethrow.js index dd513b5a694de0..f0f9c0b9c51063 100644 --- a/test/sequential/test-vm-timeout-rethrow.js +++ b/test/sequential/test-vm-timeout-rethrow.js @@ -6,8 +6,8 @@ var spawn = require('child_process').spawn; if (process.argv[2] === 'child') { var code = 'var j = 0;\n' + - 'for (var i = 0; i < 1000000; i++) j += add(i, i + 1);\n' + - 'j;'; + 'for (var i = 0; i < 1000000; i++) j += add(i, i + 1);\n' + + 'j;'; var ctx = vm.createContext({ add: function(x, y) { diff --git a/tools/doc/html.js b/tools/doc/html.js index feb99cd810415c..a232117439bbc7 100644 --- a/tools/doc/html.js +++ b/tools/doc/html.js @@ -11,11 +11,11 @@ module.exports = toHTML; // TODO(chrisdickinson): never stop vomitting / fix this. var gtocPath = path.resolve(path.join( __dirname, - '..', - '..', - 'doc', - 'api', - '_toc.markdown' + '..', + '..', + 'doc', + 'api', + '_toc.markdown' )); var gtocLoading = null; var gtocData = null; diff --git a/tools/doc/type-parser.js b/tools/doc/type-parser.js index 2e6c5bea919c19..a5698892b8e4f9 100644 --- a/tools/doc/type-parser.js +++ b/tools/doc/type-parser.js @@ -1,9 +1,9 @@ 'use strict'; const nodeDocUrl = ''; const jsDocUrl = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/' + - 'Reference/Global_Objects/'; + 'Reference/Global_Objects/'; const jsPrimitiveUrl = 'https://developer.mozilla.org/en-US/docs/Web/' + - 'JavaScript/Data_structures'; + 'JavaScript/Data_structures'; const jsPrimitives = [ 'Number', 'String', 'Boolean', 'Null', 'Symbol' ]; diff --git a/tools/eslint-rules/align-function-arguments.js b/tools/eslint-rules/align-function-arguments.js new file mode 100644 index 00000000000000..a8cd71660d7d60 --- /dev/null +++ b/tools/eslint-rules/align-function-arguments.js @@ -0,0 +1,70 @@ +/** + * @fileoverview Align arguments in multiline function calls + * @author Rich Trott + */ +'use strict'; + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +function checkArgumentAlignment(context, node) { + + function isNodeFirstInLine(node, byEndLocation) { + const firstToken = byEndLocation === true ? context.getLastToken(node, 1) : + context.getTokenBefore(node); + const startLine = byEndLocation === true ? node.loc.end.line : + node.loc.start.line; + const endLine = firstToken ? firstToken.loc.end.line : -1; + + return startLine !== endLine; + } + + if (node.arguments.length === 0) + return; + + var msg = ''; + const first = node.arguments[0]; + var currentLine = first.loc.start.line; + const firstColumn = first.loc.start.column; + + const ignoreTypes = [ + 'ArrowFunctionExpression', + 'CallExpression', + 'FunctionExpression', + 'ObjectExpression', + 'TemplateLiteral' + ]; + + const args = node.arguments; + + // For now, don't bother trying to validate potentially complicating things + // like closures. Different people will have very different ideas and it's + // probably best to implement configuration options. + if (args.some((node) => { return ignoreTypes.indexOf(node.type) !== -1; })) { + return; + } + + if (!isNodeFirstInLine(node)) { + return; + } + + args.slice(1).forEach((argument) => { + if (argument.loc.start.line === currentLine + 1) { + if (argument.loc.start.column !== firstColumn) { + msg = 'Function called with argument in column ' + + `${argument.loc.start.column}, expected in ${firstColumn}`; + } + } + currentLine = argument.loc.start.line; + }); + + if (msg) + context.report(node, msg); +} + +module.exports = function(context) { + return { + 'CallExpression': (node) => checkArgumentAlignment(context, node) + }; +}; diff --git a/tools/eslint-rules/align-multiline-assignment.js b/tools/eslint-rules/align-multiline-assignment.js new file mode 100644 index 00000000000000..3e79c6f7cd4ac5 --- /dev/null +++ b/tools/eslint-rules/align-multiline-assignment.js @@ -0,0 +1,69 @@ +/** + * @fileoverview Align multiline variable assignments + * @author Rich Trott + */ +'use strict'; + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ +function getBinaryExpressionStarts(binaryExpression, starts) { + starts = starts || []; + function getStartsFromOneSide(side, starts) { + starts.push(side.loc.start); + if (side.type === 'BinaryExpression') { + starts = getBinaryExpressionStarts(side, starts); + } + return starts; + } + + starts = getStartsFromOneSide(binaryExpression.left, starts); + starts = getStartsFromOneSide(binaryExpression.right, starts); + return starts; +} + +function checkExpressionAlignment(expression) { + if (!expression) + return; + + var msg = ''; + + switch (expression.type) { + case 'BinaryExpression': + var starts = getBinaryExpressionStarts(expression); + var startLine = starts[0].line; + const startColumn = starts[0].column; + starts.forEach((loc) => { + if (loc.line > startLine) { + startLine = loc.line; + if (loc.column !== startColumn) { + msg = 'Misaligned multiline assignment'; + } + } + }); + break; + } + return msg; +} + +function testAssignment(context, node) { + const msg = checkExpressionAlignment(node.right); + if (msg) + context.report(node, msg); +} + +function testDecleration(context, node) { + node.declarations.forEach((declaration) => { + const msg = checkExpressionAlignment(declaration.init); + // const start = declaration.init.loc.start; + if (msg) + context.report(node, msg); + }); +} + +module.exports = function(context) { + return { + 'AssignmentExpression': (node) => testAssignment(context, node), + 'VariableDeclaration': (node) => testDecleration(context, node) + }; +}; diff --git a/tools/eslint/CHANGELOG.md b/tools/eslint/CHANGELOG.md index 9454793b4245da..9b40e8ce14cfc8 100644 --- a/tools/eslint/CHANGELOG.md +++ b/tools/eslint/CHANGELOG.md @@ -1,3 +1,95 @@ +v2.9.0 - April 29, 2016 + +* a8a2cd8 Fix: Avoid autoconfig crashes from inline comments (fixes #5992) (#5999) (Ian VanSchooten) +* 23b00e0 Upgrade: npm-license to 0.3.2 (fixes #5996) (#5998) (alberto) +* 377167d Upgrade: ignore to 3.1.2 (fixes #5979) (#5988) (alberto) +* 141b778 Fix: no-control-regex literal handling fixed. (fixes #5737) (#5943) (Efe Gürkan YALAMAN) +* 577757d Fix: Clarify color option (fixes #5928) (#5974) (Grant Snodgrass) +* e7e6581 Docs: Update CLA link (#5980) (Gustav Nikolaj) +* 0be26bc Build: Add nodejs 6 to travis (fixes #5971) (#5973) (Gyandeep Singh) +* e606523 New: Rule `no-unsafe-finally` (fixes #5808) (#5932) (Onur Temizkan) +* 42d1ecc Chore: Add metadata to existing rules - Batch 7 (refs #5417) (#5969) (Vitor Balocco) +* e2ad1ec Update: object-shorthand lints computed methods (fixes #5871) (#5963) (Chris Sauvé) +* d24516a Chore: Add metadata to existing rules - Batch 6 (refs #5417) (#5966) (Vitor Balocco) +* 1e7a3ef Fix: `id-match` false positive in property values (fixes #5885) (#5960) (Mike Sherov) +* 51ddd4b Update: Use process @abstract when processing @return (fixes #5941) (#5945) (Simon Schick) +* 52a4bea Update: Add autofix for `no-whitespace-before-property` (fixes #5927) (#5951) (alberto) +* 46e058d Docs: Correct typo in configuring.md (#5957) (Nick S. Plekhanov) +* 5f8abab Chore: Add metadata to existing rules - Batch 5 (refs #5417) (#5944) (Vitor Balocco) +* 0562f77 Chore: Add missing newlines to test cases (fixes #5947) (Rich Trott) +* fc78e78 Chore: Enable quote-props rule in eslint-config-eslint (refs #5188) (#5938) (Gyandeep Singh) +* 43f6d05 Docs: Update docs to refer to column (#5937) (Sashko Stubailo) +* 586478e Update: Add autofix for `comma-dangle` (fixes #3805) (#5925) (alberto) +* a4f9c5a Docs: Distinguish examples in rules under Stylistic Issues part 3 (Kenneth Williams) +* e7c0737 Chore: Enable no-console rule in eslint-config-eslint (refs #5188) (Kevin Partington) +* 0023fe6 Build: Add “chore” to commit tags (fixes #5880) (#5929) (Mike Sherov) +* 25d626a Upgrade: espree 3.1.4 (fixes #5923, fixes #5756) (Kai Cataldo) +* a01b412 New: Add `no-useless-computed-key` rule (fixes #5402) (Burak Yigit Kaya) +* 9afb9cb Chore: Remove workaround for espree and escope bugs (fixes #5852) (alberto) +* 3ffc582 Chore: Update copyright and license info (alberto) +* 249eb40 Docs: Clarify init sets up local installation (fixes #5874) (Kai Cataldo) +* 6cd8c86 Docs: Describe options in rules under Possible Errors part 1 (Mark Pedrotti) +* f842d18 Fix: `no-this-before-super` crash on unreachable paths (fixes #5894) (Toru Nagashima) +* a02960b Docs: Fix missing delimiter in README links (Kevin Partington) +* 3a9e72c Docs: Update developer guide with new standards (Nicholas C. Zakas) +* cb78585 Update: Add `allowUnboundThis` to `prefer-arrow-callback` (fixes #4668) (Burak Yigit Kaya) +* 02be29f Chore: Remove CLA check from bot (Nicholas C. Zakas) +* 220713e Chore: Add metadata to existing rules - Batch 4 (refs #5417) (Vitor Balocco) +* df53414 Chore: Include jQuery Foundation info (Nicholas C. Zakas) +* f1b2992 Fix: `no-useless-escape` false positive in JSXAttribute (fixes #5882) (Toru Nagashima) +* 74674ad Docs: Move `sort-imports` to 'ECMAScript 6' (Kenneth Williams) +* ae69ddb Docs: Fix severity type in example (Kenneth Williams) +* 19f6fff Update: Autofixing does multiple passes (refs #5329) (Nicholas C. Zakas) +* 1e4b0ca Docs: Reduce length of paragraphs in rules index (Mark Pedrotti) +* 8cfe1eb Docs: Fix a wrong option (Zach Orlovsky) +* 8f6739f Docs: Add alberto as reviewer (alberto) +* 2ae4938 Docs: Fix message for `inline-config` option (alberto) +* 089900b Docs: Fix a wrong rule name in an example (Toru Nagashima) +* c032b41 Docs: Fix emphasis (Toru Nagashima) +* ae606f0 Docs: Update JSCS info in README (alberto) +* a9c5323 Fix: Install ESLint on init if not installed (fixes #5833) (Kai Cataldo) +* ed38358 Docs: Removed incorrect example (James M. Greene) +* af3113c Docs: Fix config comments in indent docs (Brandon Mills) +* 2b39461 Update: `commentPattern` option for `default-case` rule (fixes #5803) (Artyom Lvov) + +v2.8.0 - April 15, 2016 + +* a8821a5 Docs: Distinguish examples in rules under Stylistic Issues part 2 (Kenneth Williams) +* 76913b6 Update: Add metadata to existing rules - Batch 3 (refs #5417) (Vitor Balocco) +* 34ad8d2 Fix: Check that module.paths exists (fixes #5791) (Nicholas C. Zakas) +* 37239b1 Docs: Add new members of the team (Ilya Volodin) +* fb3c2eb Update: allow template literals (fixes #5234) (Jonathan Haines) +* 5a4a935 Update: Add metadata to existing rules - Batch 2 (refs #5417) (Vitor Balocco) +* ea2e625 Fix: newline-before-return handles return as first token (fixes #5816) (Kevin Partington) +* f8db9c9 Update: add nestedBinaryExpressions to no-extra-parens (fixes #3065) (Ilya Volodin) +* 0045d57 Update: `allowNamedFunctions` in `prefer-arrow-callback` (fixes #5675) (alberto) +* 19da72a Update: Add metadata to existing rules - Batch 1 (refs #5417) (Vitor Balocco) +* cc14e43 Fix: `no-fallthrough` empty case with comment (fixes #5799) (alberto) +* 13c8b14 Fix: LogicalExpression checks for short circuit (fixes #5693) (Vamshi krishna) +* 73b225e Fix: Document and fix metadata (refs #5417) (Ilya Volodin) +* 882d199 Docs: Improve options description in `no-redeclare` (alberto) +* 6a71ceb Docs: Improve options description in `no-params-reassign` (alberto) +* 24b6215 Update: Include 'typeof' in rule 'no-constant-condition' (fixes #5228) (Vamshi krishna) +* a959063 Docs: Remove link to deprecated ESLintTester project (refs #3110) (Trey Thomas) +* 6fd7d82 Update: Change order in `eslint --init` env options (fixes #5742) (alberto) +* c59d909 Fix: Extra paren check around object arrow bodies (fixes #5789) (Brandon Mills) +* 6f88546 Docs: Use double quotes for better Win compatibility (fixes #5796) (alberto) +* 02743d5 Fix: catch self-assignment operators in `no-magic-number` (fixes #4400) (alberto) +* c94e74e Docs: Make rule descriptions more consistent (Kenneth Williams) +* 6028252 Docs: Distinguish examples in rules under Stylistic Issues part 1 (Mark Pedrotti) +* ccd8ca9 Fix: Added property onlyDeclaration to id-match rule (fixes #3488) (Gajus Kuizinas) +* 6703c02 Update: no-useless-escape / exact locations of errors (fixes #5751) (Onur Temizkan) +* 3d84b91 Fix: ignore trailing whitespace in template literal (fixes #5786) (Kai Cataldo) +* b0e6bc4 Update: add allowEmptyCatch option to no-empty (fixes #5800) (Kai Cataldo) +* f1f1dd7 Docs: Add @pedrottimark as a committer (Brandon Mills) +* 228f201 Update: `commentPattern` option for `no-fallthrough` rule (fixes #5757) (Artyom Lvov) +* 41db670 Docs: Clarify disable inline comments (Kai Cataldo) +* 9c9a295 Docs: Add note about shell vs node glob parameters in cli (alberto) +* 5308ff9 Docs: Add code backticks to sentence in fixable rules (Mark Pedrotti) +* 965ec06 Docs: fix the examples for space-before-function-paren. (Craig Silverstein) +* 2b202fc Update: Add ignore option to space-before-function-parens (fixes #4127) (Craig Silverstein) +* 24c12ba Fix: improve `constructor-super` errors for literals (fixes #5449) (Toru Nagashima) + v2.7.0 - April 4, 2016 * 134cb1f Revert "Update: adds nestedBinaryExpressions for no-extra-parens rule (fixes #3065)" (Ilya Volodin) diff --git a/tools/eslint/LICENSE b/tools/eslint/LICENSE index 3f7b4baaa16466..d41bdf7951f077 100644 --- a/tools/eslint/LICENSE +++ b/tools/eslint/LICENSE @@ -1,5 +1,5 @@ ESLint -Copyright (c) 2013 Nicholas C. Zakas. All rights reserved. +Copyright jQuery Foundation and other contributors, https://jquery.org/ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/tools/eslint/README.md b/tools/eslint/README.md index a7864f8abbc6bf..9cbb090926474b 100644 --- a/tools/eslint/README.md +++ b/tools/eslint/README.md @@ -8,7 +8,15 @@ # ESLint -[Website](http://eslint.org) | [Configuring](http://eslint.org/docs/user-guide/configuring) | [Rules](http://eslint.org/docs/rules/) | [Contributing](http://eslint.org/docs/developer-guide/contributing) | [Reporting Bugs](http://eslint.org/docs/developer-guide/contributing/reporting-bugs) | [Twitter](https://twitter.com/geteslint) | [Mailing List](https://groups.google.com/group/eslint) | [Chat Room](https://gitter.im/eslint/eslint) +[Website](http://eslint.org) | +[Configuring](http://eslint.org/docs/user-guide/configuring) | +[Rules](http://eslint.org/docs/rules/) | +[Contributing](http://eslint.org/docs/developer-guide/contributing) | +[Reporting Bugs](http://eslint.org/docs/developer-guide/contributing/reporting-bugs) | +[Code of Conduct](https://jquery.org/conduct/) | +[Twitter](https://twitter.com/geteslint) | +[Mailing List](https://groups.google.com/group/eslint) | +[Chat Room](https://gitter.im/eslint/eslint) ESLint is a tool for identifying and reporting on patterns found in ECMAScript/JavaScript code. In many ways, it is similar to JSLint and JSHint with a few exceptions: @@ -32,6 +40,8 @@ After that, you can run ESLint on any JavaScript file: eslint test.js test2.js +**Note:** `eslint --init` is intended for setting up and configuring ESLint on a per-project basis and will perform a local installation of ESLint and its plugins in the directory in which it is run. If you prefer using a global installation of ESLint, any plugins used in your configuration must also be installed globally. + ## Configuration After running `eslint --init`, you'll have a `.eslintrc` file in your directory. In it, you'll see some rules configured like this: @@ -67,13 +77,19 @@ These folks keep the project moving and are resources for help: * Brandon Mills ([@btmills](https://github.com/btmills)) - reviewer * Gyandeep Singh ([@gyandeeps](https://github.com/gyandeeps)) - reviewer * Toru Nagashima ([@mysticatea](https://github.com/mysticatea)) - reviewer +* Alberto Rodríguez ([@alberto](https://github.com/alberto)) - reviewer * Mathias Schreck ([@lo1tuma](https://github.com/lo1tuma)) - committer * Jamund Ferguson ([@xjamundx](https://github.com/xjamundx)) - committer * Ian VanSchooten ([@ianvs](https://github.com/ianvs)) - committer * Burak Yiğit Kaya ([@byk](https://github.com/byk)) - committer -* Alberto Rodríguez ([@alberto](https://github.com/alberto)) - committer * Kai Cataldo ([@kaicataldo](https://github.com/kaicataldo)) - committer * Michael Ficarra ([@michaelficarra](https://github.com/michaelficarra)) - committer +* Mark Pedrotti ([@pedrottimark](https://github.com/pedrottimark)) - committer +* Oleg Gaidarenko ([@markelog](https://github.com/markelog)) - committer +* Mike Sherov [@mikesherov](https://github.com/mikesherov)) - committer +* Henry Zhu ([@hzoo](https://github.com/hzoo)) - committer +* Marat Dulin ([@mdevils](https://github.com/mdevils)) - committer +* Alexej Yaroshevich ([@zxqfox](https://github.com/zxqfox)) - committer ## Releases @@ -98,15 +114,19 @@ I do like JSHint. And I like Anton and Rick. Neither of those were deciding fact That's not really a question, but I got it. I'm not trying to convince you that ESLint is better than JSHint. The only thing I know is that ESLint is better than JSHint for what I'm doing. In the off chance you're doing something similar, it might be better for you. Otherwise, keep using JSHint, I'm certainly not going to tell you to stop using it. -### How does ESLint performance compare to JSHint and JSCS? +### How does ESLint performance compare to JSHint? ESLint is slower than JSHint, usually 2-3x slower on a single file. This is because ESLint uses Espree to construct an AST before it can evaluate your code whereas JSHint evaluates your code as it's being parsed. The speed is also based on the number of rules you enable; the more rules you enable, the slower the process. Despite being slower, we believe that ESLint is fast enough to replace JSHint without causing significant pain. -ESLint is faster than JSCS, as ESLint uses a single-pass traversal for analysis whereas JSCS using a querying model. +### I heard ESLint is going to replace JSCS? + +Yes. Since we are solving the same problems, ESLint and JSCS teams have decided to join forces and work together in the development of ESLint instead of competing with each other. You can read more about this in both [ESLint](http://eslint.org/blog/2016/04/welcoming-jscs-to-eslint) and [JSCS](https://medium.com/@markelog/jscs-end-of-the-line-bc9bf0b3fdb2#.u76sx334n) announcements. + +### So, should I stop using JSCS and start using ESLint? -If you are using both JSHint and JSCS on your files, then using just ESLint will be faster. +Not yet. We are still working to smooth the transition. You can see our progress [here](https://github.com/eslint/eslint/milestones/JSCS%20Compatibility). We’ll announce when all of the changes necessary to support JSCS users in ESLint are complete and will start encouraging JSCS users to switch to ESLint at that time. Meanwhile, we recommend you to upgrade to JSCS 3.0 and provide feedback to the team. ### Is ESLint just linting or does it also check style? diff --git a/tools/eslint/bin/eslint.js b/tools/eslint/bin/eslint.js old mode 100644 new mode 100755 index 19e5720a711f92..1dbdbe8338e5d0 --- a/tools/eslint/bin/eslint.js +++ b/tools/eslint/bin/eslint.js @@ -3,8 +3,6 @@ /** * @fileoverview Main CLI that is run via the eslint command. * @author Nicholas C. Zakas - * @copyright 2013 Nicholas C. Zakas. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; diff --git a/tools/eslint/conf/cli-options.js b/tools/eslint/conf/cli-options.js index 02d1f53542a435..83c815987b83e5 100644 --- a/tools/eslint/conf/cli-options.js +++ b/tools/eslint/conf/cli-options.js @@ -1,8 +1,6 @@ /** * @fileoverview Default CLIEngineOptions. * @author Ian VanSchooten - * @copyright 2016 Ian VanSchooten. All rights reserved. - * See LICENSE in root directory for full license. */ "use strict"; diff --git a/tools/eslint/conf/environments.js b/tools/eslint/conf/environments.js index 13c6da81f1afc2..ee76503827cb24 100644 --- a/tools/eslint/conf/environments.js +++ b/tools/eslint/conf/environments.js @@ -1,7 +1,6 @@ /** * @fileoverview Defines environment settings and globals. * @author Elan Shanker - * @copyright 2014 Elan Shanker. All rights reserved. */ "use strict"; diff --git a/tools/eslint/conf/eslint.json b/tools/eslint/conf/eslint.json index 21af92e0da9859..33336a504f66e3 100644 --- a/tools/eslint/conf/eslint.json +++ b/tools/eslint/conf/eslint.json @@ -109,11 +109,13 @@ "no-unmodified-loop-condition": "off", "no-unneeded-ternary": "off", "no-unreachable": "error", + "no-unsafe-finally": "off", "no-unused-expressions": "off", "no-unused-labels": "error", "no-unused-vars": "error", "no-use-before-define": "off", "no-useless-call": "off", + "no-useless-computed-key": "off", "no-useless-concat": "off", "no-useless-constructor": "off", "no-useless-escape": "off", diff --git a/tools/eslint/lib/ast-utils.js b/tools/eslint/lib/ast-utils.js index 63b1fb628fd80d..e008beeb2aea44 100644 --- a/tools/eslint/lib/ast-utils.js +++ b/tools/eslint/lib/ast-utils.js @@ -1,8 +1,6 @@ /** * @fileoverview Common utils for AST. * @author Gyandeep Singh - * @copyright 2015 Gyandeep Singh. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; diff --git a/tools/eslint/lib/cli-engine.js b/tools/eslint/lib/cli-engine.js index 2cc62f955eac5f..7fa1a794ea01ba 100644 --- a/tools/eslint/lib/cli-engine.js +++ b/tools/eslint/lib/cli-engine.js @@ -1,8 +1,6 @@ /** * @fileoverview Main CLI object. * @author Nicholas C. Zakas - * @copyright 2014 Nicholas C. Zakas. All rights reserved. - * See LICENSE in root directory for full license. */ "use strict"; @@ -115,6 +113,79 @@ function calculateStatsPerRun(results) { }); } +/** + * Performs multiple autofix passes over the text until as many fixes as possible + * have been applied. + * @param {string} text The source text to apply fixes to. + * @param {Object} config The ESLint config object to use. + * @param {Object} options The ESLint options object to use. + * @param {string} options.filename The filename from which the text was read. + * @param {boolean} options.allowInlineConfig Flag indicating if inline comments + * should be allowed. + * @returns {Object} The result of the fix operation as returned from the + * SourceCodeFixer. + * @private + */ +function multipassFix(text, config, options) { + + var messages = [], + fixedResult, + fixed = false, + passNumber = 0, + lastMessageCount, + MAX_PASSES = 10; + + /** + * This loop continues until one of the following is true: + * + * 1. No more fixes have been applied. + * 2. There are no more linting errors reported. + * 3. The number of linting errors is no different between two passes. + * 4. Ten passes have been made. + * + * That means anytime a fix is successfully applied, there will be another pass. + * Essentially, guaranteeing a minimum of two passes. + */ + do { + passNumber++; + lastMessageCount = messages.length; + + debug("Linting code for " + options.filename + " (pass " + passNumber + ")"); + messages = eslint.verify(text, config, options); + + debug("Generating fixed text for " + options.filename + " (pass " + passNumber + ")"); + fixedResult = SourceCodeFixer.applyFixes(eslint.getSourceCode(), messages); + + // keep track if any fixes were ever applied - important for return value + fixed = fixed || fixedResult.fixed; + + // update to use the fixed output instead of the original text + text = fixedResult.output; + + } while ( + fixedResult.fixed && fixedResult.messages.length > 0 && + fixedResult.messages.length !== lastMessageCount && + passNumber < MAX_PASSES + ); + + + /* + * If the last result had fixes, we need to lint again to me sure we have + * the most up-to-date information. + */ + if (fixedResult.fixed) { + fixedResult.messages = eslint.verify(text, config, options); + } + + + // ensure the last result properly reflects if fixes were done + fixedResult.fixed = fixed; + fixedResult.output = text; + + return fixedResult; + +} + /** * Processes an source code using ESLint. * @param {string} text The source code to check. @@ -179,15 +250,17 @@ function processText(text, configHelper, filename, fix, allowInlineConfig) { } else { - messages = eslint.verify(text, config, { - filename: filename, - allowInlineConfig: allowInlineConfig - }); - if (fix) { - debug("Generating fixed text for " + filename); - fixedResult = SourceCodeFixer.applyFixes(eslint.getSourceCode(), messages); + fixedResult = multipassFix(text, config, { + filename: filename, + allowInlineConfig: allowInlineConfig + }); messages = fixedResult.messages; + } else { + messages = eslint.verify(text, config, { + filename: filename, + allowInlineConfig: allowInlineConfig + }); } } 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 afb9980430a6b0..4e55cccee64869 100644 --- a/tools/eslint/lib/code-path-analysis/code-path-analyzer.js +++ b/tools/eslint/lib/code-path-analysis/code-path-analyzer.js @@ -1,8 +1,6 @@ /** * @fileoverview A class of the code path analyzer. * @author Toru Nagashima - * @copyright 2015 Toru Nagashima. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; diff --git a/tools/eslint/lib/code-path-analysis/code-path-segment.js b/tools/eslint/lib/code-path-analysis/code-path-segment.js index ea292efc36cf7f..d5361ccd07413b 100644 --- a/tools/eslint/lib/code-path-analysis/code-path-segment.js +++ b/tools/eslint/lib/code-path-analysis/code-path-segment.js @@ -1,8 +1,6 @@ /** * @fileoverview A class of the code path segment. * @author Toru Nagashima - * @copyright 2015 Toru Nagashima. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; @@ -11,8 +9,7 @@ // Requirements //------------------------------------------------------------------------------ -var assert = require("assert"), - debug = require("./debug-helpers"); +var debug = require("./debug-helpers"); //------------------------------------------------------------------------------ // Helpers @@ -178,7 +175,13 @@ CodePathSegment.newNext = function(id, allPrevSegments) { * @returns {CodePathSegment} The created segment. */ CodePathSegment.newUnreachable = function(id, allPrevSegments) { - return new CodePathSegment(id, flattenUnusedSegments(allPrevSegments), false); + var segment = new CodePathSegment(id, flattenUnusedSegments(allPrevSegments), false); + + // In `if (a) return a; foo();` case, the unreachable segment preceded by + // the return statement is not used but must not be remove. + CodePathSegment.markUsed(segment); + + return segment; }; /** @@ -203,7 +206,9 @@ CodePathSegment.newDisconnected = function(id, allPrevSegments) { * @returns {void} */ CodePathSegment.markUsed = function(segment) { - assert(!segment.internal.used, segment.id + " is marked twice."); + if (segment.internal.used) { + return; + } segment.internal.used = true; var i; 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 b620ed718bd542..0492d832c2c40f 100644 --- a/tools/eslint/lib/code-path-analysis/code-path-state.js +++ b/tools/eslint/lib/code-path-analysis/code-path-state.js @@ -1,8 +1,6 @@ /** * @fileoverview A class to manage state of generating a code path. * @author Toru Nagashima - * @copyright 2015 Toru Nagashima. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; diff --git a/tools/eslint/lib/code-path-analysis/code-path.js b/tools/eslint/lib/code-path-analysis/code-path.js index 2b45ed944f8497..035e34e712e002 100644 --- a/tools/eslint/lib/code-path-analysis/code-path.js +++ b/tools/eslint/lib/code-path-analysis/code-path.js @@ -1,8 +1,6 @@ /** * @fileoverview A class of the code path. * @author Toru Nagashima - * @copyright 2015 Toru Nagashima. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; diff --git a/tools/eslint/lib/code-path-analysis/debug-helpers.js b/tools/eslint/lib/code-path-analysis/debug-helpers.js index 6ecfabe955d92d..e68c94bc496a0d 100644 --- a/tools/eslint/lib/code-path-analysis/debug-helpers.js +++ b/tools/eslint/lib/code-path-analysis/debug-helpers.js @@ -1,8 +1,6 @@ /** * @fileoverview Helpers to debug for code path analysis. * @author Toru Nagashima - * @copyright 2015 Toru Nagashima. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; diff --git a/tools/eslint/lib/code-path-analysis/fork-context.js b/tools/eslint/lib/code-path-analysis/fork-context.js index af82e68e0c7d4f..00e0f97c40300f 100644 --- a/tools/eslint/lib/code-path-analysis/fork-context.js +++ b/tools/eslint/lib/code-path-analysis/fork-context.js @@ -5,8 +5,6 @@ * This has a fork list and manages it. * * @author Toru Nagashima - * @copyright 2015 Toru Nagashima. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; diff --git a/tools/eslint/lib/code-path-analysis/id-generator.js b/tools/eslint/lib/code-path-analysis/id-generator.js index 530ea95844593e..f33858cacd4071 100644 --- a/tools/eslint/lib/code-path-analysis/id-generator.js +++ b/tools/eslint/lib/code-path-analysis/id-generator.js @@ -5,8 +5,6 @@ * information of the code path. * * @author Toru Nagashima - * @copyright 2015 Toru Nagashima. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; diff --git a/tools/eslint/lib/config.js b/tools/eslint/lib/config.js index cf14717d4f617d..b9c70619532c72 100644 --- a/tools/eslint/lib/config.js +++ b/tools/eslint/lib/config.js @@ -1,11 +1,8 @@ /** * @fileoverview Responsible for loading config files * @author Seth McLaughlin - * @copyright 2014-2016 Nicholas C. Zakas. All rights reserved. - * @copyright 2014 Michael McLaughlin. All rights reserved. - * @copyright 2013 Seth McLaughlin. All rights reserved. - * See LICENSE in root directory for full license. */ + "use strict"; //------------------------------------------------------------------------------ diff --git a/tools/eslint/lib/config/autoconfig.js b/tools/eslint/lib/config/autoconfig.js index ccb9f1a2fe7e2b..be3d0970741935 100644 --- a/tools/eslint/lib/config/autoconfig.js +++ b/tools/eslint/lib/config/autoconfig.js @@ -1,8 +1,6 @@ /** * @fileoverview Used for creating a suggested configuration based on project code. * @author Ian VanSchooten - * @copyright 2015 Ian VanSchooten. All rights reserved. - * See LICENSE in root directory for full license. */ "use strict"; @@ -312,7 +310,13 @@ Registry.prototype = { var lintResults = eslint.verify(sourceCodes[filename], lintConfig); lintResults.forEach(function(result) { - lintedRegistry.rules[result.ruleId][ruleSetIdx].errorCount += 1; + + // 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]) { + lintedRegistry.rules[result.ruleId][ruleSetIdx].errorCount += 1; + } }); ruleSetIdx += 1; diff --git a/tools/eslint/lib/config/config-file.js b/tools/eslint/lib/config/config-file.js index f5ef3e88c6e3d5..51a81c733163ca 100644 --- a/tools/eslint/lib/config/config-file.js +++ b/tools/eslint/lib/config/config-file.js @@ -1,8 +1,6 @@ /** * @fileoverview Helper to locate and load configuration files. * @author Nicholas C. Zakas - * @copyright 2015 Nicholas C. Zakas. All rights reserved. - * See LICENSE file in root directory for full license. */ /* eslint no-use-before-define: 0 */ diff --git a/tools/eslint/lib/config/config-initializer.js b/tools/eslint/lib/config/config-initializer.js index f1d5121e4ab4bb..3d0e78fefe1140 100644 --- a/tools/eslint/lib/config/config-initializer.js +++ b/tools/eslint/lib/config/config-initializer.js @@ -1,7 +1,6 @@ /** * @fileoverview Config initialization wizard. * @author Ilya Volodin - * @copyright 2015 Ilya Volodin. All rights reserved. */ "use strict"; @@ -50,6 +49,10 @@ function writeFile(config, format) { ConfigFile.write(config, "./.eslintrc" + extname); log.info("Successfully created .eslintrc" + extname + " file in " + process.cwd()); + + if (config.installedESLint) { + log.info("ESLint was installed locally. We recommend using this local copy instead of your globally-installed copy."); + } } /** @@ -76,12 +79,24 @@ function installModules(config) { if (modules.length === 0) { return; } + + // Add eslint to list in case user does not have it installed locally + modules.unshift("eslint"); + installStatus = npmUtil.checkDevDeps(modules); // Install packages which aren't already installed modulesToInstall = Object.keys(installStatus).filter(function(module) { - return installStatus[module] === false; + var notInstalled = installStatus[module] === false; + + if (module === "eslint" && notInstalled) { + log.info("Local ESLint installation not found."); + config.installedESLint = true; + } + + return notInstalled; }); + if (modulesToInstall.length > 0) { log.info("Installing " + modulesToInstall.join(", ")); npmUtil.installSyncSaveDev(modulesToInstall); @@ -366,7 +381,7 @@ function promptUser(callback) { name: "env", message: "Where will your code run?", default: ["browser"], - choices: [{name: "Node", value: "node"}, {name: "Browser", value: "browser"}] + choices: [{name: "Browser", value: "browser"}, {name: "Node", value: "node"}] }, { type: "confirm", diff --git a/tools/eslint/lib/config/config-ops.js b/tools/eslint/lib/config/config-ops.js index 6cf406ce57fa18..727d3afa049b5d 100644 --- a/tools/eslint/lib/config/config-ops.js +++ b/tools/eslint/lib/config/config-ops.js @@ -2,8 +2,6 @@ * @fileoverview Config file operations. This file must be usable in the browser, * so no Node-specific code can be here. * @author Nicholas C. Zakas - * @copyright 2015 Nicholas C. Zakas. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; diff --git a/tools/eslint/lib/config/config-rule.js b/tools/eslint/lib/config/config-rule.js index 513e0f4bda309b..c0a394efee10fd 100644 --- a/tools/eslint/lib/config/config-rule.js +++ b/tools/eslint/lib/config/config-rule.js @@ -1,8 +1,6 @@ /** * @fileoverview Create configurations for a rule * @author Ian VanSchooten - * @copyright 2016 Ian VanSchooten. All rights reserved. - * See LICENSE in root directory for full license. */ "use strict"; diff --git a/tools/eslint/lib/config/config-validator.js b/tools/eslint/lib/config/config-validator.js index d273b26683c375..ebc70516c195d5 100644 --- a/tools/eslint/lib/config/config-validator.js +++ b/tools/eslint/lib/config/config-validator.js @@ -1,8 +1,6 @@ /** * @fileoverview Validates configs. * @author Brandon Mills - * @copyright 2015 Brandon Mills - * See LICENSE file in root directory for full license. */ "use strict"; @@ -37,16 +35,16 @@ function getRuleOptionsSchema(id) { if (Array.isArray(schema)) { if (schema.length) { return { - "type": "array", - "items": schema, - "minItems": 0, - "maxItems": schema.length + type: "array", + items: schema, + minItems: 0, + maxItems: schema.length }; } else { return { - "type": "array", - "minItems": 0, - "maxItems": 0 + type: "array", + minItems: 0, + maxItems: 0 }; } } diff --git a/tools/eslint/lib/config/environments.js b/tools/eslint/lib/config/environments.js index 6470eec1b38bc8..e7711836e51419 100644 --- a/tools/eslint/lib/config/environments.js +++ b/tools/eslint/lib/config/environments.js @@ -1,8 +1,6 @@ /** * @fileoverview Environments manager * @author Nicholas C. Zakas - * @copyright 2016 Nicholas C. Zakas. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; diff --git a/tools/eslint/lib/config/plugins.js b/tools/eslint/lib/config/plugins.js index d1bfbd83fa0c37..e157eb123c9df5 100644 --- a/tools/eslint/lib/config/plugins.js +++ b/tools/eslint/lib/config/plugins.js @@ -1,8 +1,6 @@ /** * @fileoverview Plugins manager * @author Nicholas C. Zakas - * @copyright 2016 Nicholas C. Zakas. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; diff --git a/tools/eslint/lib/eslint.js b/tools/eslint/lib/eslint.js index b3e6c7483b23d8..3a52bb3af1825d 100644 --- a/tools/eslint/lib/eslint.js +++ b/tools/eslint/lib/eslint.js @@ -1,9 +1,8 @@ /** * @fileoverview Main ESLint object. * @author Nicholas C. Zakas - * @copyright 2013 Nicholas C. Zakas. All rights reserved. - * See LICENSE file in root directory for full license. */ + "use strict"; //------------------------------------------------------------------------------ @@ -345,11 +344,11 @@ function modifyConfigsFromComments(filename, ast, config, reportingConfig, messa } } else { // comment.type === "Line" if (match[1] === "eslint-disable-line") { - disableReporting(reportingConfig, { "line": comment.loc.start.line, "column": 0 }, Object.keys(parseListConfig(value))); + disableReporting(reportingConfig, { line: comment.loc.start.line, column: 0 }, Object.keys(parseListConfig(value))); enableReporting(reportingConfig, comment.loc.end, Object.keys(parseListConfig(value))); } else if (match[1] === "eslint-disable-next-line") { disableReporting(reportingConfig, comment.loc.start, Object.keys(parseListConfig(value))); - enableReporting(reportingConfig, { "line": comment.loc.start.line + 2 }, Object.keys(parseListConfig(value))); + enableReporting(reportingConfig, { line: comment.loc.start.line + 2 }, Object.keys(parseListConfig(value))); } } } @@ -964,7 +963,7 @@ module.exports = (function() { }; // ensure there's range and text properties as well as metadata switch, otherwise it's not a valid fix - if (fix && Array.isArray(fix.range) && (typeof fix.text === "string") && (!meta || !meta.docs || meta.docs.fixable)) { + if (fix && Array.isArray(fix.range) && (typeof fix.text === "string") && (!meta || meta.fixable)) { problem.fix = fix; } diff --git a/tools/eslint/lib/file-finder.js b/tools/eslint/lib/file-finder.js index 9e24659df7030d..4dbb7544a37077 100644 --- a/tools/eslint/lib/file-finder.js +++ b/tools/eslint/lib/file-finder.js @@ -1,10 +1,8 @@ /** * @fileoverview Util class to find config files. * @author Aliaksei Shytkin - * @copyright 2014 Michael McLaughlin. All rights reserved. - * @copyright 2014 Aliaksei Shytkin. All rights reserved. - * See LICENSE in root directory for full license. */ + "use strict"; //------------------------------------------------------------------------------ diff --git a/tools/eslint/lib/formatters/html.js b/tools/eslint/lib/formatters/html.js index e8b5cd78deeb70..da3f7596fd04b6 100644 --- a/tools/eslint/lib/formatters/html.js +++ b/tools/eslint/lib/formatters/html.js @@ -1,7 +1,6 @@ /** * @fileoverview HTML reporter * @author Julian Laval - * @copyright 2015 Julian Laval. All rights reserved. */ "use strict"; diff --git a/tools/eslint/lib/formatters/json.js b/tools/eslint/lib/formatters/json.js index c1101970efa468..82138af1874855 100644 --- a/tools/eslint/lib/formatters/json.js +++ b/tools/eslint/lib/formatters/json.js @@ -1,7 +1,6 @@ /** * @fileoverview JSON reporter * @author Burak Yigit Kaya aka BYK - * @copyright 2015 Burak Yigit Kaya. All rights reserved. */ "use strict"; diff --git a/tools/eslint/lib/formatters/table.js b/tools/eslint/lib/formatters/table.js index faa691c6ea4866..e2876444556b24 100644 --- a/tools/eslint/lib/formatters/table.js +++ b/tools/eslint/lib/formatters/table.js @@ -1,7 +1,6 @@ /** * @fileoverview "table reporter. * @author Gajus Kuizinas - * @copyright 2016 Gajus Kuizinas . All rights reserved. */ "use strict"; diff --git a/tools/eslint/lib/formatters/unix.js b/tools/eslint/lib/formatters/unix.js index ba2e31f2f80db1..ce429fee25b9ce 100644 --- a/tools/eslint/lib/formatters/unix.js +++ b/tools/eslint/lib/formatters/unix.js @@ -1,7 +1,6 @@ /** * @fileoverview unix-style formatter. * @author oshi-shinobu - * @copyright 2015 oshi-shinobu. All rights reserved. */ "use strict"; diff --git a/tools/eslint/lib/formatters/visualstudio.js b/tools/eslint/lib/formatters/visualstudio.js index d0a3d99eb793ee..5d53dde289ed04 100644 --- a/tools/eslint/lib/formatters/visualstudio.js +++ b/tools/eslint/lib/formatters/visualstudio.js @@ -1,8 +1,6 @@ /** * @fileoverview Visual Studio compatible formatter * @author Ronald Pijnacker - * @copyright 2015 Ronald Pijnacker. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; diff --git a/tools/eslint/lib/ignored-paths.js b/tools/eslint/lib/ignored-paths.js index d907b49589d3b5..c6a710a9b56757 100644 --- a/tools/eslint/lib/ignored-paths.js +++ b/tools/eslint/lib/ignored-paths.js @@ -2,6 +2,7 @@ * @fileoverview Responsible for loading ignore config files and managing ignore patterns * @author Jonathan Rajavuori */ + "use strict"; //------------------------------------------------------------------------------ diff --git a/tools/eslint/lib/logging.js b/tools/eslint/lib/logging.js index f0ded092955c63..3a60879c617923 100644 --- a/tools/eslint/lib/logging.js +++ b/tools/eslint/lib/logging.js @@ -1,10 +1,12 @@ /** * @fileoverview Handle logging for ESLint * @author Gyandeep Singh - * @copyright 2015 Gyandeep Singh. All rights reserved. */ + "use strict"; +/* eslint no-console: "off" */ + /* istanbul ignore next */ module.exports = { diff --git a/tools/eslint/lib/options.js b/tools/eslint/lib/options.js index e7f70ea0925dab..7d614585810cb9 100644 --- a/tools/eslint/lib/options.js +++ b/tools/eslint/lib/options.js @@ -1,8 +1,8 @@ /** * @fileoverview Options configuration for optionator. * @author George Zahariev - * See LICENSE in root directory for full license. */ + "use strict"; //------------------------------------------------------------------------------ @@ -173,8 +173,8 @@ module.exports = optionator({ { option: "color", type: "Boolean", - default: "true", - description: "Disable color in piped output" + alias: "no-color", + description: "Force enabling/disabling of color" }, { heading: "Miscellaneous" @@ -213,7 +213,7 @@ module.exports = optionator({ option: "inline-config", type: "Boolean", default: "true", - description: "Allow comments to change eslint config/rules" + description: "Prevent comments from changing config or rules" }, { option: "print-config", diff --git a/tools/eslint/lib/rule-context.js b/tools/eslint/lib/rule-context.js index 03f5b886fdbdbb..88e68abd73e932 100644 --- a/tools/eslint/lib/rule-context.js +++ b/tools/eslint/lib/rule-context.js @@ -1,8 +1,6 @@ /** * @fileoverview RuleContext utility for rules * @author Nicholas C. Zakas - * @copyright 2013 Nicholas C. Zakas. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; diff --git a/tools/eslint/lib/rules/accessor-pairs.js b/tools/eslint/lib/rules/accessor-pairs.js index 8f8f5293dc2c0c..1b91ef2715ae3b 100644 --- a/tools/eslint/lib/rules/accessor-pairs.js +++ b/tools/eslint/lib/rules/accessor-pairs.js @@ -1,7 +1,6 @@ /** * @fileoverview Rule to flag wrapping non-iife in parens * @author Gyandeep Singh - * @copyright 2015 Gyandeep Singh. All rights reserved. */ "use strict"; @@ -79,16 +78,16 @@ module.exports = { recommended: false }, schema: [{ - "type": "object", - "properties": { - "getWithoutSet": { - "type": "boolean" + type: "object", + properties: { + getWithoutSet: { + type: "boolean" }, - "setWithoutGet": { - "type": "boolean" + setWithoutGet: { + type: "boolean" } }, - "additionalProperties": false + additionalProperties: false }] }, create: function(context) { @@ -147,7 +146,7 @@ module.exports = { } return { - "ObjectExpression": function(node) { + ObjectExpression: function(node) { if (checkSetWithoutGet || checkGetWithoutSet) { checkLonelySetGet(node); } diff --git a/tools/eslint/lib/rules/array-bracket-spacing.js b/tools/eslint/lib/rules/array-bracket-spacing.js index 617d6279b1d4c1..379ed0fa59f74e 100644 --- a/tools/eslint/lib/rules/array-bracket-spacing.js +++ b/tools/eslint/lib/rules/array-bracket-spacing.js @@ -1,10 +1,6 @@ /** * @fileoverview Disallows or enforces spaces inside of array brackets. * @author Jamund Ferguson - * @copyright 2015 Jamund Ferguson. All rights reserved. - * @copyright 2014 Brandyn Bennett. All rights reserved. - * @copyright 2014 Michael Ficarra. No rights reserved. - * @copyright 2014 Vignesh Anand. All rights reserved. */ "use strict"; @@ -19,27 +15,27 @@ module.exports = { docs: { description: "Enforce spacing inside array brackets", category: "Stylistic Issues", - recommended: false, - fixable: "whitespace" + recommended: false }, + fixable: "whitespace", schema: [ { - "enum": ["always", "never"] + enum: ["always", "never"] }, { - "type": "object", - "properties": { - "singleValue": { - "type": "boolean" + type: "object", + properties: { + singleValue: { + type: "boolean" }, - "objectsInArrays": { - "type": "boolean" + objectsInArrays: { + type: "boolean" }, - "arraysInArrays": { - "type": "boolean" + arraysInArrays: { + type: "boolean" } }, - "additionalProperties": false + additionalProperties: false } ] }, diff --git a/tools/eslint/lib/rules/array-callback-return.js b/tools/eslint/lib/rules/array-callback-return.js index 01fe01dd851d81..714c189c6b5495 100644 --- a/tools/eslint/lib/rules/array-callback-return.js +++ b/tools/eslint/lib/rules/array-callback-return.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to enforce return statements in callbacks of array's methods * @author Toru Nagashima - * @copyright 2015 Toru Nagashima. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; @@ -166,76 +164,86 @@ function isCallbackOfArrayMethod(node) { // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var funcInfo = { - upper: null, - codePath: null, - hasReturn: false, - shouldCheck: false - }; - - /** - * Checks whether or not the last code path segment is reachable. - * Then reports this function if the segment is reachable. - * - * If the last code path segment is reachable, there are paths which are not - * returned or thrown. - * - * @param {ASTNode} node - A node to check. - * @returns {void} - */ - function checkLastSegment(node) { - if (funcInfo.shouldCheck && - funcInfo.codePath.currentSegments.some(isReachable) - ) { - context.report({ - node: 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." - }); - } - } - - return { - - // Stacks this function's information. - "onCodePathStart": function(codePath, node) { - funcInfo = { - upper: funcInfo, - codePath: codePath, - hasReturn: false, - shouldCheck: - TARGET_NODE_TYPE.test(node.type) && - node.body.type === "BlockStatement" && - isCallbackOfArrayMethod(node) - }; +module.exports = { + meta: { + docs: { + description: "enforce `return` statements in callbacks of array methods", + category: "Best Practices", + recommended: false }, - // Pops this function's information. - "onCodePathEnd": function() { - funcInfo = funcInfo.upper; - }, - - // Checks the return statement is valid. - "ReturnStatement": function(node) { - if (funcInfo.shouldCheck) { - funcInfo.hasReturn = true; + schema: [] + }, + + create: function(context) { + var funcInfo = { + upper: null, + codePath: null, + hasReturn: false, + shouldCheck: false + }; + + /** + * Checks whether or not the last code path segment is reachable. + * Then reports this function if the segment is reachable. + * + * If the last code path segment is reachable, there are paths which are not + * returned or thrown. + * + * @param {ASTNode} node - A node to check. + * @returns {void} + */ + function checkLastSegment(node) { + if (funcInfo.shouldCheck && + funcInfo.codePath.currentSegments.some(isReachable) + ) { + context.report({ + node: 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." + }); + } + } - if (!node.argument) { - context.report({ - node: node, - message: "Expected a return value." - }); + return { + + // Stacks this function's information. + onCodePathStart: function(codePath, node) { + funcInfo = { + upper: funcInfo, + codePath: codePath, + hasReturn: false, + shouldCheck: + TARGET_NODE_TYPE.test(node.type) && + node.body.type === "BlockStatement" && + isCallbackOfArrayMethod(node) + }; + }, + + // Pops this function's information. + onCodePathEnd: function() { + funcInfo = funcInfo.upper; + }, + + // Checks the return statement is valid. + ReturnStatement: function(node) { + if (funcInfo.shouldCheck) { + funcInfo.hasReturn = true; + + if (!node.argument) { + context.report({ + node: node, + message: "Expected a return value." + }); + } } - } - }, + }, - // Reports a given function if the last path is reachable. - "FunctionExpression:exit": checkLastSegment, - "ArrowFunctionExpression:exit": checkLastSegment - }; + // Reports a given function if the last path is reachable. + "FunctionExpression:exit": checkLastSegment, + "ArrowFunctionExpression:exit": checkLastSegment + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/arrow-body-style.js b/tools/eslint/lib/rules/arrow-body-style.js index 3acf4942cab6c1..79fde90f805d15 100644 --- a/tools/eslint/lib/rules/arrow-body-style.js +++ b/tools/eslint/lib/rules/arrow-body-style.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to require braces in arrow function body. * @author Alberto Rodríguez - * @copyright 2015 Alberto Rodríguez. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; @@ -10,50 +8,60 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var always = context.options[0] === "always"; - var asNeeded = !context.options[0] || context.options[0] === "as-needed"; +module.exports = { + meta: { + docs: { + description: "require braces around arrow function bodies", + category: "ECMAScript 6", + recommended: false + }, - /** - * Determines whether a arrow function body needs braces - * @param {ASTNode} node The arrow function node. - * @returns {void} - */ - function validate(node) { - var arrowBody = node.body; + schema: [ + { + enum: ["always", "as-needed"] + } + ] + }, - if (arrowBody.type === "BlockStatement") { - var blockBody = arrowBody.body; + create: function(context) { + var always = context.options[0] === "always"; + var asNeeded = !context.options[0] || context.options[0] === "as-needed"; - if (blockBody.length !== 1) { - return; - } + /** + * Determines whether a arrow function body needs braces + * @param {ASTNode} node The arrow function node. + * @returns {void} + */ + function validate(node) { + var arrowBody = node.body; - if (asNeeded && blockBody[0].type === "ReturnStatement") { - context.report({ - node: node, - loc: arrowBody.loc.start, - message: "Unexpected block statement surrounding arrow body." - }); - } - } else { - if (always) { - context.report({ - node: node, - loc: arrowBody.loc.start, - message: "Expected block statement surrounding arrow body." - }); + if (arrowBody.type === "BlockStatement") { + var blockBody = arrowBody.body; + + if (blockBody.length !== 1) { + return; + } + + if (asNeeded && blockBody[0].type === "ReturnStatement") { + context.report({ + node: node, + loc: arrowBody.loc.start, + message: "Unexpected block statement surrounding arrow body." + }); + } + } else { + if (always) { + context.report({ + node: node, + loc: arrowBody.loc.start, + message: "Expected block statement surrounding arrow body." + }); + } } } - } - - return { - "ArrowFunctionExpression": validate - }; -}; -module.exports.schema = [ - { - "enum": ["always", "as-needed"] + return { + ArrowFunctionExpression: validate + }; } -]; +}; diff --git a/tools/eslint/lib/rules/arrow-parens.js b/tools/eslint/lib/rules/arrow-parens.js index 2332dda12134c2..78ce045017106f 100644 --- a/tools/eslint/lib/rules/arrow-parens.js +++ b/tools/eslint/lib/rules/arrow-parens.js @@ -1,7 +1,6 @@ /** * @fileoverview Rule to require parens in arrow function arguments. * @author Jxck - * @copyright 2015 Jxck. All rights reserved. */ "use strict"; @@ -9,44 +8,54 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var message = "Expected parentheses around arrow function argument."; - var asNeededMessage = "Unexpected parentheses around single function argument"; - var asNeeded = context.options[0] === "as-needed"; - - /** - * Determines whether a arrow function argument end with `)` - * @param {ASTNode} node The arrow function node. - * @returns {void} - */ - function parens(node) { - var token = context.getFirstToken(node); - - // as-needed: x => x - if (asNeeded && node.params.length === 1 && node.params[0].type === "Identifier") { - if (token.type === "Punctuator" && token.value === "(") { - context.report(node, asNeededMessage); +module.exports = { + meta: { + docs: { + description: "require parentheses around arrow function arguments", + category: "ECMAScript 6", + recommended: false + }, + + schema: [ + { + enum: ["always", "as-needed"] + } + ] + }, + + create: function(context) { + var message = "Expected parentheses around arrow function argument."; + var asNeededMessage = "Unexpected parentheses around single function argument"; + var asNeeded = context.options[0] === "as-needed"; + + /** + * Determines whether a arrow function argument end with `)` + * @param {ASTNode} node The arrow function node. + * @returns {void} + */ + function parens(node) { + var token = context.getFirstToken(node); + + // as-needed: x => x + if (asNeeded && node.params.length === 1 && node.params[0].type === "Identifier") { + if (token.type === "Punctuator" && token.value === "(") { + context.report(node, asNeededMessage); + } + return; } - return; - } - if (token.type === "Identifier") { - var after = context.getTokenAfter(token); + if (token.type === "Identifier") { + var after = context.getTokenAfter(token); - // (x) => x - if (after.value !== ")") { - context.report(node, message); + // (x) => x + if (after.value !== ")") { + context.report(node, message); + } } } - } - return { - "ArrowFunctionExpression": parens - }; -}; - -module.exports.schema = [ - { - "enum": ["always", "as-needed"] + return { + ArrowFunctionExpression: parens + }; } -]; +}; diff --git a/tools/eslint/lib/rules/arrow-spacing.js b/tools/eslint/lib/rules/arrow-spacing.js index e1ea0daaa40a1c..82cec87ed2798b 100644 --- a/tools/eslint/lib/rules/arrow-spacing.js +++ b/tools/eslint/lib/rules/arrow-spacing.js @@ -1,7 +1,6 @@ /** * @fileoverview Rule to define spacing before/after arrow function's arrow. * @author Jxck - * @copyright 2015 Jxck. All rights reserved. */ "use strict"; @@ -9,125 +8,137 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - // merge rules with default - var rule = { before: true, after: true }, - option = context.options[0] || {}; - - rule.before = option.before !== false; - rule.after = option.after !== false; - - /** - * Get tokens of arrow(`=>`) and before/after arrow. - * @param {ASTNode} node The arrow function node. - * @returns {Object} Tokens of arrow and before/after arrow. - */ - function getTokens(node) { - var t = context.getFirstToken(node); - var before; - - while (t.type !== "Punctuator" || t.value !== "=>") { - before = t; - t = context.getTokenAfter(t); - } - var after = context.getTokenAfter(t); - - return { before: before, arrow: t, after: after }; - } - - /** - * Count spaces before/after arrow(`=>`) token. - * @param {Object} tokens Tokens before/after arrow. - * @returns {Object} count of space before/after arrow. - */ - function countSpaces(tokens) { - var before = tokens.arrow.range[0] - tokens.before.range[1]; - var after = tokens.after.range[0] - tokens.arrow.range[1]; - - return { before: before, after: after }; - } +module.exports = { + meta: { + docs: { + description: "enforce consistent spacing before and after the arrow in arrow functions", + category: "ECMAScript 6", + recommended: false + }, - /** - * Determines whether space(s) before after arrow(`=>`) is satisfy rule. - * if before/after value is `true`, there should be space(s). - * if before/after value is `false`, there should be no space. - * @param {ASTNode} node The arrow function node. - * @returns {void} - */ - function spaces(node) { - var tokens = getTokens(node); - var countSpace = countSpaces(tokens); - - if (rule.before) { - - // should be space(s) before arrow - if (countSpace.before === 0) { - context.report({ - node: tokens.before, - message: "Missing space before =>", - fix: function(fixer) { - return fixer.insertTextBefore(tokens.arrow, " "); + fixable: "whitespace", + + schema: [ + { + type: "object", + properties: { + before: { + type: "boolean" + }, + after: { + type: "boolean" } - }); + }, + additionalProperties: false } - } else { - - // should be no space before arrow - if (countSpace.before > 0) { - context.report({ - node: tokens.before, - message: "Unexpected space before =>", - fix: function(fixer) { - return fixer.removeRange([tokens.before.range[1], tokens.arrow.range[0]]); - } - }); + ] + }, + + create: function(context) { + + // merge rules with default + var rule = { before: true, after: true }, + option = context.options[0] || {}; + + rule.before = option.before !== false; + rule.after = option.after !== false; + + /** + * Get tokens of arrow(`=>`) and before/after arrow. + * @param {ASTNode} node The arrow function node. + * @returns {Object} Tokens of arrow and before/after arrow. + */ + function getTokens(node) { + var t = context.getFirstToken(node); + var before; + + while (t.type !== "Punctuator" || t.value !== "=>") { + before = t; + t = context.getTokenAfter(t); } + var after = context.getTokenAfter(t); + + return { before: before, arrow: t, after: after }; } - if (rule.after) { + /** + * Count spaces before/after arrow(`=>`) token. + * @param {Object} tokens Tokens before/after arrow. + * @returns {Object} count of space before/after arrow. + */ + function countSpaces(tokens) { + var before = tokens.arrow.range[0] - tokens.before.range[1]; + var after = tokens.after.range[0] - tokens.arrow.range[1]; - // should be space(s) after arrow - if (countSpace.after === 0) { - context.report({ - node: tokens.after, - message: "Missing space after =>", - fix: function(fixer) { - return fixer.insertTextAfter(tokens.arrow, " "); - } - }); - } - } else { - - // should be no space after arrow - if (countSpace.after > 0) { - context.report({ - node: tokens.after, - message: "Unexpected space after =>", - fix: function(fixer) { - return fixer.removeRange([tokens.arrow.range[1], tokens.after.range[0]]); - } - }); - } + return { before: before, after: after }; } - } - return { - "ArrowFunctionExpression": spaces - }; -}; + /** + * Determines whether space(s) before after arrow(`=>`) is satisfy rule. + * if before/after value is `true`, there should be space(s). + * if before/after value is `false`, there should be no space. + * @param {ASTNode} node The arrow function node. + * @returns {void} + */ + function spaces(node) { + var tokens = getTokens(node); + var countSpace = countSpaces(tokens); + + if (rule.before) { + + // should be space(s) before arrow + if (countSpace.before === 0) { + context.report({ + node: tokens.before, + message: "Missing space before =>", + fix: function(fixer) { + return fixer.insertTextBefore(tokens.arrow, " "); + } + }); + } + } else { + + // should be no space before arrow + if (countSpace.before > 0) { + context.report({ + node: tokens.before, + message: "Unexpected space before =>", + fix: function(fixer) { + return fixer.removeRange([tokens.before.range[1], tokens.arrow.range[0]]); + } + }); + } + } -module.exports.schema = [ - { - "type": "object", - "properties": { - "before": { - "type": "boolean" - }, - "after": { - "type": "boolean" + if (rule.after) { + + // should be space(s) after arrow + if (countSpace.after === 0) { + context.report({ + node: tokens.after, + message: "Missing space after =>", + fix: function(fixer) { + return fixer.insertTextAfter(tokens.arrow, " "); + } + }); + } + } else { + + // should be no space after arrow + if (countSpace.after > 0) { + context.report({ + node: tokens.after, + message: "Unexpected space after =>", + fix: function(fixer) { + return fixer.removeRange([tokens.arrow.range[1], tokens.after.range[0]]); + } + }); + } } - }, - "additionalProperties": false + } + + return { + ArrowFunctionExpression: spaces + }; } -]; +}; diff --git a/tools/eslint/lib/rules/block-scoped-var.js b/tools/eslint/lib/rules/block-scoped-var.js index 42d8422a007ca9..3da07adcba1a1f 100644 --- a/tools/eslint/lib/rules/block-scoped-var.js +++ b/tools/eslint/lib/rules/block-scoped-var.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to check for "block scoped" variables by binding context * @author Matt DuVall - * @copyright 2015 Toru Nagashima. All rights reserved. - * @copyright 2015 Mathieu M-Gosselin. All rights reserved. */ "use strict"; @@ -10,101 +8,111 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var stack = []; +module.exports = { + meta: { + docs: { + description: "enforce the use of variables within the scope they are defined", + category: "Best Practices", + recommended: false + }, - /** - * Makes a block scope. - * @param {ASTNode} node - A node of a scope. - * @returns {void} - */ - function enterScope(node) { - stack.push(node.range); - } + schema: [] + }, - /** - * Pops the last block scope. - * @returns {void} - */ - function exitScope() { - stack.pop(); - } - - /** - * Reports a given reference. - * @param {escope.Reference} reference - A reference to report. - * @returns {void} - */ - function report(reference) { - var identifier = reference.identifier; - - context.report( - identifier, - "'{{name}}' used outside of binding context.", - {name: identifier.name}); - } + create: function(context) { + var stack = []; - /** - * Finds and reports references which are outside of valid scopes. - * @param {ASTNode} node - A node to get variables. - * @returns {void} - */ - function checkForVariables(node) { - if (node.kind !== "var") { - return; + /** + * Makes a block scope. + * @param {ASTNode} node - A node of a scope. + * @returns {void} + */ + function enterScope(node) { + stack.push(node.range); } - // Defines a predicate to check whether or not a given reference is outside of valid scope. - var scopeRange = stack[stack.length - 1]; - /** - * Check if a reference is out of scope - * @param {ASTNode} reference node to examine - * @returns {boolean} True is its outside the scope - * @private + * Pops the last block scope. + * @returns {void} */ - function isOutsideOfScope(reference) { - var idRange = reference.identifier.range; - - return idRange[0] < scopeRange[0] || idRange[1] > scopeRange[1]; + function exitScope() { + stack.pop(); } - // Gets declared variables, and checks its references. - var variables = context.getDeclaredVariables(node); - - for (var i = 0; i < variables.length; ++i) { + /** + * Reports a given reference. + * @param {escope.Reference} reference - A reference to report. + * @returns {void} + */ + function report(reference) { + var identifier = reference.identifier; - // Reports. - variables[i] - .references - .filter(isOutsideOfScope) - .forEach(report); + context.report( + identifier, + "'{{name}}' used outside of binding context.", + {name: identifier.name}); } - } - return { - "Program": function(node) { - stack = [node.range]; - }, + /** + * Finds and reports references which are outside of valid scopes. + * @param {ASTNode} node - A node to get variables. + * @returns {void} + */ + function checkForVariables(node) { + if (node.kind !== "var") { + return; + } + + // Defines a predicate to check whether or not a given reference is outside of valid scope. + var scopeRange = stack[stack.length - 1]; + + /** + * Check if a reference is out of scope + * @param {ASTNode} reference node to examine + * @returns {boolean} True is its outside the scope + * @private + */ + function isOutsideOfScope(reference) { + var idRange = reference.identifier.range; + + return idRange[0] < scopeRange[0] || idRange[1] > scopeRange[1]; + } + + // Gets declared variables, and checks its references. + var variables = context.getDeclaredVariables(node); + + for (var i = 0; i < variables.length; ++i) { + + // Reports. + variables[i] + .references + .filter(isOutsideOfScope) + .forEach(report); + } + } - // Manages scopes. - "BlockStatement": enterScope, - "BlockStatement:exit": exitScope, - "ForStatement": enterScope, - "ForStatement:exit": exitScope, - "ForInStatement": enterScope, - "ForInStatement:exit": exitScope, - "ForOfStatement": enterScope, - "ForOfStatement:exit": exitScope, - "SwitchStatement": enterScope, - "SwitchStatement:exit": exitScope, - "CatchClause": enterScope, - "CatchClause:exit": exitScope, - - // Finds and reports references which are outside of valid scope. - "VariableDeclaration": checkForVariables - }; + return { + Program: function(node) { + stack = [node.range]; + }, + + // Manages scopes. + BlockStatement: enterScope, + "BlockStatement:exit": exitScope, + ForStatement: enterScope, + "ForStatement:exit": exitScope, + ForInStatement: enterScope, + "ForInStatement:exit": exitScope, + ForOfStatement: enterScope, + "ForOfStatement:exit": exitScope, + SwitchStatement: enterScope, + "SwitchStatement:exit": exitScope, + CatchClause: enterScope, + "CatchClause:exit": exitScope, + + // Finds and reports references which are outside of valid scope. + VariableDeclaration: checkForVariables + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/block-spacing.js b/tools/eslint/lib/rules/block-spacing.js index 5e9d990253409f..b6dc6e701d25a8 100644 --- a/tools/eslint/lib/rules/block-spacing.js +++ b/tools/eslint/lib/rules/block-spacing.js @@ -1,7 +1,6 @@ /** * @fileoverview A rule to disallow or enforce spaces inside of single line blocks. * @author Toru Nagashima - * @copyright 2015 Toru Nagashima. All rights reserved. */ "use strict"; @@ -12,109 +11,121 @@ var util = require("../ast-utils"); // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var always = (context.options[0] !== "never"), - message = always ? "Requires a space" : "Unexpected space(s)", - sourceCode = context.getSourceCode(); - - /** - * Gets the open brace token from a given node. - * @param {ASTNode} node - A BlockStatement/SwitchStatement node to get. - * @returns {Token} The token of the open brace. - */ - function getOpenBrace(node) { - if (node.type === "SwitchStatement") { - if (node.cases.length > 0) { - return context.getTokenBefore(node.cases[0]); - } - return context.getLastToken(node, 1); - } - return context.getFirstToken(node); - } +module.exports = { + meta: { + docs: { + description: "enforce consistent spacing inside single-line blocks", + category: "Stylistic Issues", + recommended: false + }, - /** - * Checks whether or not: - * - given tokens are on same line. - * - there is/isn't a space between given tokens. - * @param {Token} left - A token to check. - * @param {Token} right - The token which is next to `left`. - * @returns {boolean} - * When the option is `"always"`, `true` if there are one or more spaces between given tokens. - * When the option is `"never"`, `true` if there are not any spaces between given tokens. - * If given tokens are not on same line, it's always `true`. - */ - function isValid(left, right) { - return ( - !util.isTokenOnSameLine(left, right) || - sourceCode.isSpaceBetweenTokens(left, right) === always - ); - } + fixable: "whitespace", + + schema: [ + {enum: ["always", "never"]} + ] + }, + + create: function(context) { + var always = (context.options[0] !== "never"), + message = always ? "Requires a space" : "Unexpected space(s)", + sourceCode = context.getSourceCode(); - /** - * Reports invalid spacing style inside braces. - * @param {ASTNode} node - A BlockStatement/SwitchStatement node to get. - * @returns {void} - */ - function checkSpacingInsideBraces(node) { - - // Gets braces and the first/last token of content. - var openBrace = getOpenBrace(node); - var closeBrace = context.getLastToken(node); - var firstToken = sourceCode.getTokenOrCommentAfter(openBrace); - var lastToken = sourceCode.getTokenOrCommentBefore(closeBrace); - - // Skip if the node is invalid or empty. - if (openBrace.type !== "Punctuator" || - openBrace.value !== "{" || - closeBrace.type !== "Punctuator" || - closeBrace.value !== "}" || - firstToken === closeBrace - ) { - return; + /** + * Gets the open brace token from a given node. + * @param {ASTNode} node - A BlockStatement/SwitchStatement node to get. + * @returns {Token} The token of the open brace. + */ + function getOpenBrace(node) { + if (node.type === "SwitchStatement") { + if (node.cases.length > 0) { + return context.getTokenBefore(node.cases[0]); + } + return context.getLastToken(node, 1); + } + return context.getFirstToken(node); } - // Skip line comments for option never - if (!always && firstToken.type === "Line") { - return; + /** + * Checks whether or not: + * - given tokens are on same line. + * - there is/isn't a space between given tokens. + * @param {Token} left - A token to check. + * @param {Token} right - The token which is next to `left`. + * @returns {boolean} + * When the option is `"always"`, `true` if there are one or more spaces between given tokens. + * When the option is `"never"`, `true` if there are not any spaces between given tokens. + * If given tokens are not on same line, it's always `true`. + */ + function isValid(left, right) { + return ( + !util.isTokenOnSameLine(left, right) || + sourceCode.isSpaceBetweenTokens(left, right) === always + ); } - // Check. - if (!isValid(openBrace, firstToken)) { - context.report({ - node: node, - loc: openBrace.loc.start, - message: message + " after '{'.", - fix: function(fixer) { - if (always) { - return fixer.insertTextBefore(firstToken, " "); - } + /** + * Reports invalid spacing style inside braces. + * @param {ASTNode} node - A BlockStatement/SwitchStatement node to get. + * @returns {void} + */ + function checkSpacingInsideBraces(node) { - return fixer.removeRange([openBrace.range[1], firstToken.range[0]]); - } - }); - } - if (!isValid(lastToken, closeBrace)) { - context.report({ - node: node, - loc: closeBrace.loc.start, - message: message + " before '}'.", - fix: function(fixer) { - if (always) { - return fixer.insertTextAfter(lastToken, " "); + // Gets braces and the first/last token of content. + var openBrace = getOpenBrace(node); + var closeBrace = context.getLastToken(node); + var firstToken = sourceCode.getTokenOrCommentAfter(openBrace); + var lastToken = sourceCode.getTokenOrCommentBefore(closeBrace); + + // Skip if the node is invalid or empty. + if (openBrace.type !== "Punctuator" || + openBrace.value !== "{" || + closeBrace.type !== "Punctuator" || + closeBrace.value !== "}" || + firstToken === closeBrace + ) { + return; + } + + // Skip line comments for option never + if (!always && firstToken.type === "Line") { + return; + } + + // Check. + if (!isValid(openBrace, firstToken)) { + context.report({ + node: node, + loc: openBrace.loc.start, + message: message + " after '{'.", + fix: function(fixer) { + if (always) { + return fixer.insertTextBefore(firstToken, " "); + } + + return fixer.removeRange([openBrace.range[1], firstToken.range[0]]); } + }); + } + if (!isValid(lastToken, closeBrace)) { + context.report({ + node: node, + loc: closeBrace.loc.start, + message: message + " before '}'.", + fix: function(fixer) { + if (always) { + return fixer.insertTextAfter(lastToken, " "); + } - return fixer.removeRange([lastToken.range[1], closeBrace.range[0]]); - } - }); + return fixer.removeRange([lastToken.range[1], closeBrace.range[0]]); + } + }); + } } - } - return { - BlockStatement: checkSpacingInsideBraces, - SwitchStatement: checkSpacingInsideBraces - }; + return { + BlockStatement: checkSpacingInsideBraces, + SwitchStatement: checkSpacingInsideBraces + }; + } }; - -module.exports.schema = [ - {enum: ["always", "never"]} -]; diff --git a/tools/eslint/lib/rules/brace-style.js b/tools/eslint/lib/rules/brace-style.js index 4887d66b8d8592..785a71e4e7b0aa 100644 --- a/tools/eslint/lib/rules/brace-style.js +++ b/tools/eslint/lib/rules/brace-style.js @@ -9,226 +9,236 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var style = context.options[0] || "1tbs", - params = context.options[1] || {}, - sourceCode = context.getSourceCode(); - - var OPEN_MESSAGE = "Opening curly brace does not appear on the same line as controlling statement.", - OPEN_MESSAGE_ALLMAN = "Opening curly brace appears on the same line as controlling statement.", - BODY_MESSAGE = "Statement inside of curly braces should be on next line.", - CLOSE_MESSAGE = "Closing curly brace does not appear on the same line as the subsequent block.", - CLOSE_MESSAGE_SINGLE = "Closing curly brace should be on the same line as opening curly brace or on the line after the previous block.", - CLOSE_MESSAGE_STROUSTRUP_ALLMAN = "Closing curly brace appears on the same line as the subsequent block."; - - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- - - /** - * 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 === "}"; - } - - /** - * 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() { - var blockProperties = arguments; - - return function(node) { - Array.prototype.forEach.call(blockProperties, function(blockProp) { - var block = node[blockProp], - previousToken, - curlyToken, - curlyTokenEnd, - allOnSameLine; - - if (!isBlock(block)) { - return; - } - - previousToken = sourceCode.getTokenBefore(block); - curlyToken = sourceCode.getFirstToken(block); - curlyTokenEnd = sourceCode.getLastToken(block); - allOnSameLine = previousToken.loc.start.line === curlyTokenEnd.loc.start.line; +module.exports = { + meta: { + docs: { + description: "enforce consistent brace style for blocks", + category: "Stylistic Issues", + recommended: false + }, - if (allOnSameLine && params.allowSingleLine) { - return; - } + schema: [ + { + enum: ["1tbs", "stroustrup", "allman"] + }, + { + type: "object", + properties: { + allowSingleLine: { + type: "boolean" + } + }, + additionalProperties: false + } + ] + }, - if (style !== "allman" && previousToken.loc.start.line !== curlyToken.loc.start.line) { - context.report(node, OPEN_MESSAGE); - } else if (style === "allman" && previousToken.loc.start.line === curlyToken.loc.start.line) { - context.report(node, OPEN_MESSAGE_ALLMAN); - } + create: function(context) { + var style = context.options[0] || "1tbs", + params = context.options[1] || {}, + sourceCode = context.getSourceCode(); + + var OPEN_MESSAGE = "Opening curly brace does not appear on the same line as controlling statement.", + OPEN_MESSAGE_ALLMAN = "Opening curly brace appears on the same line as controlling statement.", + BODY_MESSAGE = "Statement inside of curly braces should be on next line.", + CLOSE_MESSAGE = "Closing curly brace does not appear on the same line as the subsequent block.", + CLOSE_MESSAGE_SINGLE = "Closing curly brace should be on the same line as opening curly brace or on the line after the previous block.", + CLOSE_MESSAGE_STROUSTRUP_ALLMAN = "Closing curly brace appears on the same line as the subsequent block."; + + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- + + /** + * 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"; + } - if (!block.body.length) { - return; - } + /** + * 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 === "}"; + } - if (curlyToken.loc.start.line === block.body[0].loc.start.line) { - context.report(block.body[0], BODY_MESSAGE); - } + /** + * 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() { + var blockProperties = arguments; + + return function(node) { + Array.prototype.forEach.call(blockProperties, function(blockProp) { + var block = node[blockProp], + previousToken, + curlyToken, + curlyTokenEnd, + allOnSameLine; + + if (!isBlock(block)) { + return; + } + + previousToken = sourceCode.getTokenBefore(block); + curlyToken = sourceCode.getFirstToken(block); + curlyTokenEnd = sourceCode.getLastToken(block); + 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) { + context.report(node, OPEN_MESSAGE); + } else if (style === "allman" && previousToken.loc.start.line === curlyToken.loc.start.line) { + context.report(node, OPEN_MESSAGE_ALLMAN); + } + + if (!block.body.length) { + return; + } + + if (curlyToken.loc.start.line === block.body[0].loc.start.line) { + context.report(block.body[0], BODY_MESSAGE); + } + + if (curlyTokenEnd.loc.start.line === block.body[block.body.length - 1].loc.start.line) { + context.report(block.body[block.body.length - 1], CLOSE_MESSAGE_SINGLE); + } + }); + }; + } - if (curlyTokenEnd.loc.start.line === block.body[block.body.length - 1].loc.start.line) { - context.report(block.body[block.body.length - 1], CLOSE_MESSAGE_SINGLE); + /** + * Enforces the configured brace style on IfStatements + * @param {ASTNode} node An IfStatement node. + * @returns {void} + * @private + */ + function checkIfStatement(node) { + var tokens; + + checkBlock("consequent", "alternate")(node); + + if (node.alternate) { + + 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])) { + context.report(node.alternate, CLOSE_MESSAGE); + } + } else if (tokens[0].loc.start.line === tokens[1].loc.start.line) { + context.report(node.alternate, CLOSE_MESSAGE_STROUSTRUP_ALLMAN); } - }); - }; - } - - /** - * Enforces the configured brace style on IfStatements - * @param {ASTNode} node An IfStatement node. - * @returns {void} - * @private - */ - function checkIfStatement(node) { - var tokens; - - checkBlock("consequent", "alternate")(node); - - if (node.alternate) { - 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])) { - context.report(node.alternate, CLOSE_MESSAGE); - } - } else if (tokens[0].loc.start.line === tokens[1].loc.start.line) { - context.report(node.alternate, CLOSE_MESSAGE_STROUSTRUP_ALLMAN); } - } - } - /** - * Enforces the configured brace style on TryStatements - * @param {ASTNode} node A TryStatement node. - * @returns {void} - * @private - */ - function checkTryStatement(node) { - var tokens; - - checkBlock("block", "finalizer")(node); - - if (isBlock(node.finalizer)) { - tokens = sourceCode.getTokensBefore(node.finalizer, 2); - if (style === "1tbs") { - if (tokens[0].loc.start.line !== tokens[1].loc.start.line) { - context.report(node.finalizer, CLOSE_MESSAGE); + /** + * Enforces the configured brace style on TryStatements + * @param {ASTNode} node A TryStatement node. + * @returns {void} + * @private + */ + function checkTryStatement(node) { + var tokens; + + checkBlock("block", "finalizer")(node); + + if (isBlock(node.finalizer)) { + tokens = sourceCode.getTokensBefore(node.finalizer, 2); + if (style === "1tbs") { + if (tokens[0].loc.start.line !== tokens[1].loc.start.line) { + context.report(node.finalizer, CLOSE_MESSAGE); + } + } else if (tokens[0].loc.start.line === tokens[1].loc.start.line) { + context.report(node.finalizer, CLOSE_MESSAGE_STROUSTRUP_ALLMAN); } - } else if (tokens[0].loc.start.line === tokens[1].loc.start.line) { - context.report(node.finalizer, CLOSE_MESSAGE_STROUSTRUP_ALLMAN); } } - } - /** - * Enforces the configured brace style on CatchClauses - * @param {ASTNode} node A CatchClause node. - * @returns {void} - * @private - */ - function checkCatchClause(node) { - var previousToken = sourceCode.getTokenBefore(node), - firstToken = sourceCode.getFirstToken(node); - - checkBlock("body")(node); - - if (isBlock(node.body)) { - if (style === "1tbs") { - if (previousToken.loc.start.line !== firstToken.loc.start.line) { - context.report(node, CLOSE_MESSAGE); - } - } else { - if (previousToken.loc.start.line === firstToken.loc.start.line) { - context.report(node, CLOSE_MESSAGE_STROUSTRUP_ALLMAN); + /** + * Enforces the configured brace style on CatchClauses + * @param {ASTNode} node A CatchClause node. + * @returns {void} + * @private + */ + function checkCatchClause(node) { + var previousToken = sourceCode.getTokenBefore(node), + firstToken = sourceCode.getFirstToken(node); + + checkBlock("body")(node); + + if (isBlock(node.body)) { + if (style === "1tbs") { + if (previousToken.loc.start.line !== firstToken.loc.start.line) { + context.report(node, CLOSE_MESSAGE); + } + } else { + if (previousToken.loc.start.line === firstToken.loc.start.line) { + context.report(node, CLOSE_MESSAGE_STROUSTRUP_ALLMAN); + } } } } - } - /** - * Enforces the configured brace style on SwitchStatements - * @param {ASTNode} node A SwitchStatement node. - * @returns {void} - * @private - */ - function checkSwitchStatement(node) { - var tokens; - - if (node.cases && node.cases.length) { - tokens = sourceCode.getTokensBefore(node.cases[0], 2); - } else { - tokens = sourceCode.getLastTokens(node, 3); - } + /** + * Enforces the configured brace style on SwitchStatements + * @param {ASTNode} node A SwitchStatement node. + * @returns {void} + * @private + */ + function checkSwitchStatement(node) { + var tokens; + + if (node.cases && node.cases.length) { + tokens = sourceCode.getTokensBefore(node.cases[0], 2); + } else { + tokens = sourceCode.getLastTokens(node, 3); + } - if (style !== "allman" && tokens[0].loc.start.line !== tokens[1].loc.start.line) { - context.report(node, OPEN_MESSAGE); - } else if (style === "allman" && tokens[0].loc.start.line === tokens[1].loc.start.line) { - context.report(node, OPEN_MESSAGE_ALLMAN); + if (style !== "allman" && tokens[0].loc.start.line !== tokens[1].loc.start.line) { + context.report(node, OPEN_MESSAGE); + } else if (style === "allman" && tokens[0].loc.start.line === tokens[1].loc.start.line) { + context.report(node, OPEN_MESSAGE_ALLMAN); + } } - } - //-------------------------------------------------------------------------- - // Public API - //-------------------------------------------------------------------------- - - 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 - }; - -}; + //-------------------------------------------------------------------------- + // Public API + //-------------------------------------------------------------------------- + + 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 + }; -module.exports.schema = [ - { - "enum": ["1tbs", "stroustrup", "allman"] - }, - { - "type": "object", - "properties": { - "allowSingleLine": { - "type": "boolean" - } - }, - "additionalProperties": false } -]; +}; diff --git a/tools/eslint/lib/rules/callback-return.js b/tools/eslint/lib/rules/callback-return.js index 7680386cf4d46f..a995da3a98f354 100644 --- a/tools/eslint/lib/rules/callback-return.js +++ b/tools/eslint/lib/rules/callback-return.js @@ -1,7 +1,6 @@ /** * @fileoverview Enforce return after a callback. * @author Jamund Ferguson - * @copyright 2015 Jamund Ferguson. All rights reserved. */ "use strict"; @@ -9,136 +8,146 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - var callbacks = context.options[0] || ["callback", "cb", "next"]; - - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- - - /** - * Find the closest parent matching a list of types. - * @param {ASTNode} node The node whose parents we are searching - * @param {Array} types The node types to match - * @returns {ASTNode} The matched node or undefined. - */ - function findClosestParentOfType(node, types) { - if (!node.parent) { - return null; - } - if (types.indexOf(node.parent.type) === -1) { - return findClosestParentOfType(node.parent, types); +module.exports = { + meta: { + docs: { + description: "require `return` statements after callbacks", + category: "Node.js and CommonJS", + recommended: false + }, + + schema: [{ + type: "array", + items: { type: "string" } + }] + }, + + create: function(context) { + + var callbacks = context.options[0] || ["callback", "cb", "next"]; + + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- + + /** + * Find the closest parent matching a list of types. + * @param {ASTNode} node The node whose parents we are searching + * @param {Array} types The node types to match + * @returns {ASTNode} The matched node or undefined. + */ + function findClosestParentOfType(node, types) { + if (!node.parent) { + return null; + } + if (types.indexOf(node.parent.type) === -1) { + return findClosestParentOfType(node.parent, types); + } + return node.parent; } - return node.parent; - } - - /** - * Check to see if a CallExpression is in our callback list. - * @param {ASTNode} node The node to check against our callback names list. - * @returns {Boolean} Whether or not this function matches our callback name. - */ - function isCallback(node) { - return node.callee.type === "Identifier" && callbacks.indexOf(node.callee.name) > -1; - } - /** - * Determines whether or not the callback is part of a callback expression. - * @param {ASTNode} node The callback node - * @param {ASTNode} parentNode The expression node - * @returns {boolean} Whether or not this is part of a callback expression - */ - function isCallbackExpression(node, parentNode) { - - // ensure the parent node exists and is an expression - if (!parentNode || parentNode.type !== "ExpressionStatement") { - return false; + /** + * Check to see if a CallExpression is in our callback list. + * @param {ASTNode} node The node to check against our callback names list. + * @returns {Boolean} Whether or not this function matches our callback name. + */ + function isCallback(node) { + return node.callee.type === "Identifier" && callbacks.indexOf(node.callee.name) > -1; } - // cb() - if (parentNode.expression === node) { - return true; - } + /** + * Determines whether or not the callback is part of a callback expression. + * @param {ASTNode} node The callback node + * @param {ASTNode} parentNode The expression node + * @returns {boolean} Whether or not this is part of a callback expression + */ + function isCallbackExpression(node, parentNode) { + + // ensure the parent node exists and is an expression + if (!parentNode || parentNode.type !== "ExpressionStatement") { + return false; + } - // special case for cb && cb() and similar - if (parentNode.expression.type === "BinaryExpression" || parentNode.expression.type === "LogicalExpression") { - if (parentNode.expression.right === node) { + // cb() + if (parentNode.expression === node) { return true; } + + // special case for cb && cb() and similar + if (parentNode.expression.type === "BinaryExpression" || parentNode.expression.type === "LogicalExpression") { + if (parentNode.expression.right === node) { + return true; + } + } + + return false; } - return false; - } + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- + return { + CallExpression: function(node) { - return { - "CallExpression": function(node) { + // if we"re not a callback we can return + if (!isCallback(node)) { + return; + } - // if we"re not a callback we can return - if (!isCallback(node)) { - return; - } + // find the closest block, return or loop + var closestBlock = findClosestParentOfType(node, ["BlockStatement", "ReturnStatement", "ArrowFunctionExpression"]) || {}, + lastItem, parentType; - // find the closest block, return or loop - var closestBlock = findClosestParentOfType(node, ["BlockStatement", "ReturnStatement", "ArrowFunctionExpression"]) || {}, - lastItem, parentType; + // if our parent is a return we know we're ok + if (closestBlock.type === "ReturnStatement") { + return; + } - // if our parent is a return we know we're ok - if (closestBlock.type === "ReturnStatement") { - return; - } + // arrow functions don't always have blocks and implicitly return + if (closestBlock.type === "ArrowFunctionExpression") { + return; + } - // arrow functions don't always have blocks and implicitly return - if (closestBlock.type === "ArrowFunctionExpression") { - return; - } + // block statements are part of functions and most if statements + if (closestBlock.type === "BlockStatement") { - // block statements are part of functions and most if statements - if (closestBlock.type === "BlockStatement") { + // find the last item in the block + lastItem = closestBlock.body[closestBlock.body.length - 1]; - // find the last item in the block - lastItem = closestBlock.body[closestBlock.body.length - 1]; + // if the callback is the last thing in a block that might be ok + if (isCallbackExpression(node, lastItem)) { - // if the callback is the last thing in a block that might be ok - if (isCallbackExpression(node, lastItem)) { + parentType = closestBlock.parent.type; - parentType = closestBlock.parent.type; + // but only if the block is part of a function + if (parentType === "FunctionExpression" || + parentType === "FunctionDeclaration" || + parentType === "ArrowFunctionExpression" + ) { + return; + } - // but only if the block is part of a function - if (parentType === "FunctionExpression" || - parentType === "FunctionDeclaration" || - parentType === "ArrowFunctionExpression" - ) { - return; } - } + // ending a block with a return is also ok + if (lastItem.type === "ReturnStatement") { - // ending a block with a return is also ok - if (lastItem.type === "ReturnStatement") { - - // but only if the callback is immediately before - if (isCallbackExpression(node, closestBlock.body[closestBlock.body.length - 2])) { - return; + // but only if the callback is immediately before + if (isCallbackExpression(node, closestBlock.body[closestBlock.body.length - 2])) { + return; + } } + } - } + // as long as you're the child of a function at this point you should be asked to return + if (findClosestParentOfType(node, ["FunctionDeclaration", "FunctionExpression", "ArrowFunctionExpression"])) { + context.report(node, "Expected return with your callback function."); + } - // as long as you're the child of a function at this point you should be asked to return - if (findClosestParentOfType(node, ["FunctionDeclaration", "FunctionExpression", "ArrowFunctionExpression"])) { - context.report(node, "Expected return with your callback function."); } - } - - }; + }; + } }; - -module.exports.schema = [{ - type: "array", - items: { type: "string" } -}]; diff --git a/tools/eslint/lib/rules/camelcase.js b/tools/eslint/lib/rules/camelcase.js index d8f87fcf3fe964..28f9e8296b1926 100644 --- a/tools/eslint/lib/rules/camelcase.js +++ b/tools/eslint/lib/rules/camelcase.js @@ -1,7 +1,6 @@ /** * @fileoverview Rule to flag non-camelcased identifiers * @author Nicholas C. Zakas - * @copyright 2015 Dieter Oberkofler. All rights reserved. */ "use strict"; @@ -10,116 +9,126 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- - - // contains reported nodes to avoid reporting twice on destructuring with shorthand notation - var reported = []; - - /** - * Checks if a string contains an underscore and isn't all upper-case - * @param {String} name The string to check. - * @returns {boolean} if the string is underscored - * @private - */ - function isUnderscored(name) { - - // if there's an underscore, it might be A_CONSTANT, which is okay - return name.indexOf("_") > -1 && name !== name.toUpperCase(); - } - - /** - * Reports an AST node as a rule violation. - * @param {ASTNode} node The node to report. - * @returns {void} - * @private - */ - function report(node) { - if (reported.indexOf(node) < 0) { - reported.push(node); - context.report(node, "Identifier '{{name}}' is not in camel case.", { name: node.name }); - } - } - - var options = context.options[0] || {}, - properties = options.properties || ""; - - if (properties !== "always" && properties !== "never") { - properties = "always"; - } - - return { +module.exports = { + meta: { + docs: { + description: "enforce camelcase naming convention", + category: "Stylistic Issues", + recommended: false + }, - "Identifier": function(node) { + schema: [ + { + type: "object", + properties: { + properties: { + enum: ["always", "never"] + } + }, + additionalProperties: false + } + ] + }, - /* - * Leading and trailing underscores are commonly used to flag - * private/protected identifiers, strip them - */ - var name = node.name.replace(/^_+|_+$/g, ""), - effectiveParent = (node.parent.type === "MemberExpression") ? node.parent.parent : node.parent; + create: function(context) { - // MemberExpressions get special rules - if (node.parent.type === "MemberExpression") { + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- - // "never" check properties - if (properties === "never") { - return; - } + // contains reported nodes to avoid reporting twice on destructuring with shorthand notation + var reported = []; - // Always report underscored object names - if (node.parent.object.type === "Identifier" && - node.parent.object.name === node.name && - isUnderscored(name)) { - report(node); + /** + * Checks if a string contains an underscore and isn't all upper-case + * @param {String} name The string to check. + * @returns {boolean} if the string is underscored + * @private + */ + function isUnderscored(name) { - // Report AssignmentExpressions only if they are the left side of the assignment - } else if (effectiveParent.type === "AssignmentExpression" && - isUnderscored(name) && - (effectiveParent.right.type !== "MemberExpression" || - effectiveParent.left.type === "MemberExpression" && - effectiveParent.left.property.name === node.name)) { - report(node); - } + // if there's an underscore, it might be A_CONSTANT, which is okay + return name.indexOf("_") > -1 && name !== name.toUpperCase(); + } - // Properties have their own rules - } else if (node.parent.type === "Property") { + /** + * Reports an AST node as a rule violation. + * @param {ASTNode} node The node to report. + * @returns {void} + * @private + */ + function report(node) { + if (reported.indexOf(node) < 0) { + reported.push(node); + context.report(node, "Identifier '{{name}}' is not in camel case.", { name: node.name }); + } + } - // "never" check properties - if (properties === "never") { - return; - } + var options = context.options[0] || {}, + properties = options.properties || ""; - if (node.parent.parent && node.parent.parent.type === "ObjectPattern" && - node.parent.key === node && node.parent.value !== node) { - return; - } + if (properties !== "always" && properties !== "never") { + properties = "always"; + } - if (isUnderscored(name) && effectiveParent.type !== "CallExpression") { + return { + + Identifier: function(node) { + + /* + * Leading and trailing underscores are commonly used to flag + * private/protected identifiers, strip them + */ + var name = node.name.replace(/^_+|_+$/g, ""), + effectiveParent = (node.parent.type === "MemberExpression") ? node.parent.parent : node.parent; + + // MemberExpressions get special rules + if (node.parent.type === "MemberExpression") { + + // "never" check properties + if (properties === "never") { + return; + } + + // Always report underscored object names + if (node.parent.object.type === "Identifier" && + node.parent.object.name === node.name && + isUnderscored(name)) { + report(node); + + // Report AssignmentExpressions only if they are the left side of the assignment + } else if (effectiveParent.type === "AssignmentExpression" && + isUnderscored(name) && + (effectiveParent.right.type !== "MemberExpression" || + effectiveParent.left.type === "MemberExpression" && + effectiveParent.left.property.name === node.name)) { + report(node); + } + + // Properties have their own rules + } else if (node.parent.type === "Property") { + + // "never" check properties + if (properties === "never") { + return; + } + + if (node.parent.parent && node.parent.parent.type === "ObjectPattern" && + node.parent.key === node && node.parent.value !== node) { + return; + } + + if (isUnderscored(name) && effectiveParent.type !== "CallExpression") { + report(node); + } + + // Report anything that is underscored that isn't a CallExpression + } else if (isUnderscored(name) && effectiveParent.type !== "CallExpression") { report(node); } - - // Report anything that is underscored that isn't a CallExpression - } else if (isUnderscored(name) && effectiveParent.type !== "CallExpression") { - report(node); } - } - }; - -}; + }; -module.exports.schema = [ - { - "type": "object", - "properties": { - "properties": { - "enum": ["always", "never"] - } - }, - "additionalProperties": false } -]; +}; diff --git a/tools/eslint/lib/rules/comma-dangle.js b/tools/eslint/lib/rules/comma-dangle.js index 4aab8939304585..7c2451b60876e8 100644 --- a/tools/eslint/lib/rules/comma-dangle.js +++ b/tools/eslint/lib/rules/comma-dangle.js @@ -1,10 +1,6 @@ /** * @fileoverview Rule to forbid or enforce dangling commas. * @author Ian Christian Myers - * @copyright 2015 Toru Nagashima - * @copyright 2015 Mathias Schreck - * @copyright 2013 Ian Christian Myers - * See LICENSE file in root directory for full license. */ "use strict"; @@ -24,203 +20,204 @@ var lodash = require("lodash"); * @returns {boolean} `true` if a trailing comma is allowed. */ function isTrailingCommaAllowed(node, lastItem) { - switch (node.type) { - case "ArrayPattern": - - // TODO(t-nagashima): Remove SpreadElement after https://github.com/eslint/espree/issues/194 was fixed. - return ( - lastItem.type !== "RestElement" && - lastItem.type !== "SpreadElement" - ); - - // TODO(t-nagashima): Remove this case after https://github.com/eslint/espree/issues/195 was fixed. - case "ArrayExpression": - return ( - node.parent.type !== "ForOfStatement" || - node.parent.left !== node || - lastItem.type !== "SpreadElement" - ); - - default: - return true; - } + return node.type !== "ArrayPattern" || lastItem.type !== "RestElement"; } //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var mode = context.options[0]; - var UNEXPECTED_MESSAGE = "Unexpected trailing comma."; - var MISSING_MESSAGE = "Missing trailing comma."; - - /** - * Checks whether or not a given node is multiline. - * This rule handles a given node as multiline when the closing parenthesis - * and the last element are not on the same line. - * - * @param {ASTNode} node - A node to check. - * @returns {boolean} `true` if the node is multiline. - */ - function isMultiline(node) { - var lastItem = lodash.last(node.properties || node.elements || node.specifiers); - - if (!lastItem) { - return false; +module.exports = { + meta: { + docs: { + description: "require or disallow trailing commas", + category: "Possible Errors", + recommended: true + }, + + fixable: "code", + + schema: [ + { + enum: ["always", "always-multiline", "only-multiline", "never"] + } + ] + }, + + create: function(context) { + var mode = context.options[0]; + var UNEXPECTED_MESSAGE = "Unexpected trailing comma."; + var MISSING_MESSAGE = "Missing trailing comma."; + + /** + * Checks whether or not a given node is multiline. + * This rule handles a given node as multiline when the closing parenthesis + * and the last element are not on the same line. + * + * @param {ASTNode} node - A node to check. + * @returns {boolean} `true` if the node is multiline. + */ + function isMultiline(node) { + var lastItem = lodash.last(node.properties || node.elements || node.specifiers); + + if (!lastItem) { + return false; + } + + var sourceCode = context.getSourceCode(), + penultimateToken = sourceCode.getLastToken(lastItem), + lastToken = sourceCode.getTokenAfter(penultimateToken); + + // parentheses are a pain + while (lastToken.value === ")") { + penultimateToken = lastToken; + lastToken = sourceCode.getTokenAfter(lastToken); + } + + if (lastToken.value === ",") { + penultimateToken = lastToken; + lastToken = sourceCode.getTokenAfter(lastToken); + } + + return lastToken.loc.end.line !== penultimateToken.loc.end.line; } - var sourceCode = context.getSourceCode(), - penultimateToken = sourceCode.getLastToken(lastItem), - lastToken = sourceCode.getTokenAfter(penultimateToken); - - // parentheses are a pain - while (lastToken.value === ")") { - penultimateToken = lastToken; - lastToken = sourceCode.getTokenAfter(lastToken); + /** + * Reports a trailing comma if it exists. + * + * @param {ASTNode} node - A node to check. Its type is one of + * ObjectExpression, ObjectPattern, ArrayExpression, ArrayPattern, + * ImportDeclaration, and ExportNamedDeclaration. + * @returns {void} + */ + function forbidTrailingComma(node) { + var lastItem = lodash.last(node.properties || node.elements || node.specifiers); + + if (!lastItem || (node.type === "ImportDeclaration" && lastItem.type !== "ImportSpecifier")) { + return; + } + + var sourceCode = context.getSourceCode(), + trailingToken; + + // last item can be surrounded by parentheses for object and array literals + if (node.type === "ObjectExpression" || node.type === "ArrayExpression") { + trailingToken = sourceCode.getTokenBefore(sourceCode.getLastToken(node)); + } else { + trailingToken = sourceCode.getTokenAfter(lastItem); + } + + if (trailingToken.value === ",") { + context.report({ + node: lastItem, + loc: trailingToken.loc.start, + message: UNEXPECTED_MESSAGE, + fix: function(fixer) { + return fixer.remove(trailingToken); + } + }); + } } - if (lastToken.value === ",") { - penultimateToken = lastToken; - lastToken = sourceCode.getTokenAfter(lastToken); + /** + * Reports the last element of a given node if it does not have a trailing + * comma. + * + * If a given node is `ArrayPattern` which has `RestElement`, the trailing + * comma is disallowed, so report if it exists. + * + * @param {ASTNode} node - A node to check. Its type is one of + * ObjectExpression, ObjectPattern, ArrayExpression, ArrayPattern, + * ImportDeclaration, and ExportNamedDeclaration. + * @returns {void} + */ + function forceTrailingComma(node) { + var lastItem = lodash.last(node.properties || node.elements || node.specifiers); + + if (!lastItem || (node.type === "ImportDeclaration" && lastItem.type !== "ImportSpecifier")) { + return; + } + if (!isTrailingCommaAllowed(node, lastItem)) { + forbidTrailingComma(node); + return; + } + + var sourceCode = context.getSourceCode(), + trailingToken; + + // last item can be surrounded by parentheses for object and array literals + if (node.type === "ObjectExpression" || node.type === "ArrayExpression") { + trailingToken = sourceCode.getTokenBefore(sourceCode.getLastToken(node)); + } else { + trailingToken = sourceCode.getTokenAfter(lastItem); + } + + if (trailingToken.value !== ",") { + context.report({ + node: lastItem, + loc: lastItem.loc.end, + message: MISSING_MESSAGE, + fix: function(fixer) { + return fixer.insertTextAfter(lastItem, ","); + } + }); + } } - return lastToken.loc.end.line !== penultimateToken.loc.end.line; - } - - /** - * Reports a trailing comma if it exists. - * - * @param {ASTNode} node - A node to check. Its type is one of - * ObjectExpression, ObjectPattern, ArrayExpression, ArrayPattern, - * ImportDeclaration, and ExportNamedDeclaration. - * @returns {void} - */ - function forbidTrailingComma(node) { - var lastItem = lodash.last(node.properties || node.elements || node.specifiers); - - if (!lastItem || (node.type === "ImportDeclaration" && lastItem.type !== "ImportSpecifier")) { - return; + /** + * If a given node is multiline, reports the last element of a given node + * when it does not have a trailing comma. + * Otherwise, reports a trailing comma if it exists. + * + * @param {ASTNode} node - A node to check. Its type is one of + * ObjectExpression, ObjectPattern, ArrayExpression, ArrayPattern, + * ImportDeclaration, and ExportNamedDeclaration. + * @returns {void} + */ + function forceTrailingCommaIfMultiline(node) { + if (isMultiline(node)) { + forceTrailingComma(node); + } else { + forbidTrailingComma(node); + } } - var sourceCode = context.getSourceCode(), - trailingToken; - - // last item can be surrounded by parentheses for object and array literals - if (node.type === "ObjectExpression" || node.type === "ArrayExpression") { - trailingToken = sourceCode.getTokenBefore(sourceCode.getLastToken(node)); - } else { - trailingToken = sourceCode.getTokenAfter(lastItem); + /** + * Only if a given node is not multiline, reports the last element of a given node + * when it does not have a trailing comma. + * Otherwise, reports a trailing comma if it exists. + * + * @param {ASTNode} node - A node to check. Its type is one of + * ObjectExpression, ObjectPattern, ArrayExpression, ArrayPattern, + * ImportDeclaration, and ExportNamedDeclaration. + * @returns {void} + */ + function allowTrailingCommaIfMultiline(node) { + if (!isMultiline(node)) { + forbidTrailingComma(node); + } } - if (trailingToken.value === ",") { - context.report( - lastItem, - trailingToken.loc.start, - UNEXPECTED_MESSAGE); - } - } - - /** - * Reports the last element of a given node if it does not have a trailing - * comma. - * - * If a given node is `ArrayPattern` which has `RestElement`, the trailing - * comma is disallowed, so report if it exists. - * - * @param {ASTNode} node - A node to check. Its type is one of - * ObjectExpression, ObjectPattern, ArrayExpression, ArrayPattern, - * ImportDeclaration, and ExportNamedDeclaration. - * @returns {void} - */ - function forceTrailingComma(node) { - var lastItem = lodash.last(node.properties || node.elements || node.specifiers); - - if (!lastItem || (node.type === "ImportDeclaration" && lastItem.type !== "ImportSpecifier")) { - return; - } - if (!isTrailingCommaAllowed(node, lastItem)) { - forbidTrailingComma(node); - return; - } - - var sourceCode = context.getSourceCode(), - trailingToken; + // Chooses a checking function. + var checkForTrailingComma; - // last item can be surrounded by parentheses for object and array literals - if (node.type === "ObjectExpression" || node.type === "ArrayExpression") { - trailingToken = sourceCode.getTokenBefore(sourceCode.getLastToken(node)); + if (mode === "always") { + checkForTrailingComma = forceTrailingComma; + } else if (mode === "always-multiline") { + checkForTrailingComma = forceTrailingCommaIfMultiline; + } else if (mode === "only-multiline") { + checkForTrailingComma = allowTrailingCommaIfMultiline; } else { - trailingToken = sourceCode.getTokenAfter(lastItem); + checkForTrailingComma = forbidTrailingComma; } - if (trailingToken.value !== ",") { - context.report( - lastItem, - lastItem.loc.end, - MISSING_MESSAGE); - } + return { + ObjectExpression: checkForTrailingComma, + ObjectPattern: checkForTrailingComma, + ArrayExpression: checkForTrailingComma, + ArrayPattern: checkForTrailingComma, + ImportDeclaration: checkForTrailingComma, + ExportNamedDeclaration: checkForTrailingComma + }; } - - /** - * If a given node is multiline, reports the last element of a given node - * when it does not have a trailing comma. - * Otherwise, reports a trailing comma if it exists. - * - * @param {ASTNode} node - A node to check. Its type is one of - * ObjectExpression, ObjectPattern, ArrayExpression, ArrayPattern, - * ImportDeclaration, and ExportNamedDeclaration. - * @returns {void} - */ - function forceTrailingCommaIfMultiline(node) { - if (isMultiline(node)) { - forceTrailingComma(node); - } else { - forbidTrailingComma(node); - } - } - - /** - * Only if a given node is not multiline, reports the last element of a given node - * when it does not have a trailing comma. - * Otherwise, reports a trailing comma if it exists. - * - * @param {ASTNode} node - A node to check. Its type is one of - * ObjectExpression, ObjectPattern, ArrayExpression, ArrayPattern, - * ImportDeclaration, and ExportNamedDeclaration. - * @returns {void} - */ - function allowTrailingCommaIfMultiline(node) { - if (!isMultiline(node)) { - forbidTrailingComma(node); - } - } - - // Chooses a checking function. - var checkForTrailingComma; - - if (mode === "always") { - checkForTrailingComma = forceTrailingComma; - } else if (mode === "always-multiline") { - checkForTrailingComma = forceTrailingCommaIfMultiline; - } else if (mode === "only-multiline") { - checkForTrailingComma = allowTrailingCommaIfMultiline; - } else { - checkForTrailingComma = forbidTrailingComma; - } - - return { - "ObjectExpression": checkForTrailingComma, - "ObjectPattern": checkForTrailingComma, - "ArrayExpression": checkForTrailingComma, - "ArrayPattern": checkForTrailingComma, - "ImportDeclaration": checkForTrailingComma, - "ExportNamedDeclaration": checkForTrailingComma - }; }; - -module.exports.schema = [ - { - "enum": ["always", "always-multiline", "only-multiline", "never"] - } -]; diff --git a/tools/eslint/lib/rules/comma-spacing.js b/tools/eslint/lib/rules/comma-spacing.js index 7d2b2d794933ab..2a4ec1f4173b4c 100644 --- a/tools/eslint/lib/rules/comma-spacing.js +++ b/tools/eslint/lib/rules/comma-spacing.js @@ -1,7 +1,6 @@ /** * @fileoverview Comma spacing - validates spacing before and after comma * @author Vignesh Anand aka vegetableman. - * @copyright 2014 Vignesh Anand. All rights reserved. */ "use strict"; @@ -11,173 +10,185 @@ var astUtils = require("../ast-utils"); // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - var sourceCode = context.getSourceCode(); - var tokensAndComments = sourceCode.tokensAndComments; - - var options = { - before: context.options[0] ? !!context.options[0].before : false, - after: context.options[0] ? !!context.options[0].after : true - }; - - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- - - // list of comma tokens to ignore for the check of leading whitespace - var 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 === ","); - } +module.exports = { + meta: { + docs: { + description: "enforce consistent spacing before and after commas", + category: "Stylistic Issues", + recommended: false + }, - /** - * Reports a spacing error with an appropriate message. - * @param {ASTNode} node The binary expression node to report. - * @param {string} dir Is the error "before" or "after" the comma? - * @param {ASTNode} otherNode The node at the left or right of `node` - * @returns {void} - * @private - */ - function report(node, dir, otherNode) { - context.report({ - node: node, - fix: function(fixer) { - if (options[dir]) { - if (dir === "before") { - return fixer.insertTextBefore(node, " "); - } else { - return fixer.insertTextAfter(node, " "); + fixable: "whitespace", + + schema: [ + { + type: "object", + properties: { + before: { + type: "boolean" + }, + after: { + type: "boolean" } - } else { - var start, end; - var newText = ""; + }, + additionalProperties: false + } + ] + }, + + create: function(context) { + + var sourceCode = context.getSourceCode(); + var tokensAndComments = sourceCode.tokensAndComments; + + var options = { + before: context.options[0] ? !!context.options[0].before : false, + after: context.options[0] ? !!context.options[0].after : true + }; + + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- + + // list of comma tokens to ignore for the check of leading whitespace + var 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 === ","); + } - if (dir === "before") { - start = otherNode.range[1]; - end = node.range[0]; + /** + * Reports a spacing error with an appropriate message. + * @param {ASTNode} node The binary expression node to report. + * @param {string} dir Is the error "before" or "after" the comma? + * @param {ASTNode} otherNode The node at the left or right of `node` + * @returns {void} + * @private + */ + function report(node, dir, otherNode) { + context.report({ + node: node, + fix: function(fixer) { + if (options[dir]) { + if (dir === "before") { + return fixer.insertTextBefore(node, " "); + } else { + return fixer.insertTextAfter(node, " "); + } } else { - start = node.range[1]; - end = otherNode.range[0]; + var start, end; + var 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); } - - return fixer.replaceTextRange([start, end], newText); - } - }, - message: options[dir] ? - "A space is required " + dir + " ','." : - "There should be no space " + dir + " ','." - }); - } - - /** - * Validates the spacing around a comma token. - * @param {Object} tokens - The tokens to be validated. - * @param {Token} tokens.comma The token representing the comma. - * @param {Token} [tokens.left] The last token before the comma. - * @param {Token} [tokens.right] The first token after the comma. - * @param {Token|ASTNode} reportItem The item to use when reporting an error. - * @returns {void} - * @private - */ - function validateCommaItemSpacing(tokens, reportItem) { - if (tokens.left && astUtils.isTokenOnSameLine(tokens.left, tokens.comma) && - (options.before !== sourceCode.isSpaceBetweenTokens(tokens.left, tokens.comma)) - ) { - report(reportItem, "before", tokens.left); + }, + message: options[dir] ? + "A space is required " + dir + " ','." : + "There should be no space " + dir + " ','." + }); } - if (tokens.right && !options.after && tokens.right.type === "Line") { - return; - } + /** + * Validates the spacing around a comma token. + * @param {Object} tokens - The tokens to be validated. + * @param {Token} tokens.comma The token representing the comma. + * @param {Token} [tokens.left] The last token before the comma. + * @param {Token} [tokens.right] The first token after the comma. + * @param {Token|ASTNode} reportItem The item to use when reporting an error. + * @returns {void} + * @private + */ + function validateCommaItemSpacing(tokens, reportItem) { + if (tokens.left && astUtils.isTokenOnSameLine(tokens.left, tokens.comma) && + (options.before !== sourceCode.isSpaceBetweenTokens(tokens.left, tokens.comma)) + ) { + report(reportItem, "before", tokens.left); + } + + if (tokens.right && !options.after && tokens.right.type === "Line") { + return; + } - if (tokens.right && astUtils.isTokenOnSameLine(tokens.comma, tokens.right) && - (options.after !== sourceCode.isSpaceBetweenTokens(tokens.comma, tokens.right)) - ) { - report(reportItem, "after", tokens.right); + if (tokens.right && astUtils.isTokenOnSameLine(tokens.comma, tokens.right) && + (options.after !== sourceCode.isSpaceBetweenTokens(tokens.comma, tokens.right)) + ) { + report(reportItem, "after", tokens.right); + } } - } - /** - * Adds null elements of the given ArrayExpression or ArrayPattern node to the ignore list. - * @param {ASTNode} node An ArrayExpression or ArrayPattern node. - * @returns {void} - */ - function addNullElementsToIgnoreList(node) { - var previousToken = context.getFirstToken(node); + /** + * Adds null elements of the given ArrayExpression or ArrayPattern node to the ignore list. + * @param {ASTNode} node An ArrayExpression or ArrayPattern node. + * @returns {void} + */ + function addNullElementsToIgnoreList(node) { + var previousToken = context.getFirstToken(node); - node.elements.forEach(function(element) { - var token; + node.elements.forEach(function(element) { + var token; - if (element === null) { - token = context.getTokenAfter(previousToken); + if (element === null) { + token = context.getTokenAfter(previousToken); - if (isComma(token)) { - commaTokensToIgnore.push(token); + if (isComma(token)) { + commaTokensToIgnore.push(token); + } + } else { + token = context.getTokenAfter(element); } - } else { - token = context.getTokenAfter(element); - } - previousToken = token; - }); - } + previousToken = token; + }); + } - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- - return { - "Program:exit": function() { + return { + "Program:exit": function() { - var previousToken, - nextToken; + var previousToken, + nextToken; - tokensAndComments.forEach(function(token, i) { + tokensAndComments.forEach(function(token, i) { - if (!isComma(token)) { - return; - } - - if (token && token.type === "JSXText") { - return; - } + if (!isComma(token)) { + return; + } - previousToken = tokensAndComments[i - 1]; - nextToken = tokensAndComments[i + 1]; + if (token && token.type === "JSXText") { + return; + } - validateCommaItemSpacing({ - comma: token, - left: isComma(previousToken) || commaTokensToIgnore.indexOf(token) > -1 ? null : previousToken, - right: isComma(nextToken) ? null : nextToken - }, token); - }); - }, - "ArrayExpression": addNullElementsToIgnoreList, - "ArrayPattern": addNullElementsToIgnoreList + previousToken = tokensAndComments[i - 1]; + nextToken = tokensAndComments[i + 1]; - }; + validateCommaItemSpacing({ + comma: token, + left: isComma(previousToken) || commaTokensToIgnore.indexOf(token) > -1 ? null : previousToken, + right: isComma(nextToken) ? null : nextToken + }, token); + }); + }, + ArrayExpression: addNullElementsToIgnoreList, + ArrayPattern: addNullElementsToIgnoreList -}; + }; -module.exports.schema = [ - { - "type": "object", - "properties": { - "before": { - "type": "boolean" - }, - "after": { - "type": "boolean" - } - }, - "additionalProperties": false } -]; +}; diff --git a/tools/eslint/lib/rules/comma-style.js b/tools/eslint/lib/rules/comma-style.js index af001372c55249..9c7d266d3dd270 100644 --- a/tools/eslint/lib/rules/comma-style.js +++ b/tools/eslint/lib/rules/comma-style.js @@ -1,8 +1,6 @@ /** * @fileoverview Comma style - enforces comma styles of two types: last and first * @author Vignesh Anand aka vegetableman - * @copyright 2014 Vignesh Anand. All rights reserved. - * @copyright 2015 Evan Simmons. All rights reserved. */ "use strict"; @@ -13,174 +11,184 @@ var astUtils = require("../ast-utils"); // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - var style = context.options[0] || "last", - exceptions = {}; +module.exports = { + meta: { + docs: { + description: "enforce consistent comma style", + category: "Stylistic Issues", + recommended: false + }, - if (context.options.length === 2 && context.options[1].hasOwnProperty("exceptions")) { - exceptions = context.options[1].exceptions; - } + schema: [ + { + enum: ["first", "last"] + }, + { + type: "object", + properties: { + exceptions: { + type: "object", + additionalProperties: { + type: "boolean" + } + } + }, + additionalProperties: false + } + ] + }, - //-------------------------------------------------------------------------- - // 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 === ","); - } + create: function(context) { - /** - * Validates the spacing around single items in lists. - * @param {Token} previousItemToken The last token from the previous item. - * @param {Token} commaToken The token representing the comma. - * @param {Token} currentItemToken The first token of the current item. - * @param {Token} reportItem The item to use when reporting an error. - * @returns {void} - * @private - */ - function validateCommaItemSpacing(previousItemToken, commaToken, currentItemToken, reportItem) { + var style = context.options[0] || "last", + exceptions = {}; - // if single line - if (astUtils.isTokenOnSameLine(commaToken, currentItemToken) && - astUtils.isTokenOnSameLine(previousItemToken, commaToken)) { + if (context.options.length === 2 && context.options[1].hasOwnProperty("exceptions")) { + exceptions = context.options[1].exceptions; + } - return; + //-------------------------------------------------------------------------- + // 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 === ","); + } - } else if (!astUtils.isTokenOnSameLine(commaToken, currentItemToken) && - !astUtils.isTokenOnSameLine(previousItemToken, commaToken)) { + /** + * Validates the spacing around single items in lists. + * @param {Token} previousItemToken The last token from the previous item. + * @param {Token} commaToken The token representing the comma. + * @param {Token} currentItemToken The first token of the current item. + * @param {Token} reportItem The item to use when reporting an error. + * @returns {void} + * @private + */ + function validateCommaItemSpacing(previousItemToken, commaToken, currentItemToken, reportItem) { - // lone comma - context.report(reportItem, { - line: commaToken.loc.end.line, - column: commaToken.loc.start.column - }, "Bad line breaking before and after ','."); + // if single line + if (astUtils.isTokenOnSameLine(commaToken, currentItemToken) && + astUtils.isTokenOnSameLine(previousItemToken, commaToken)) { - } else if (style === "first" && !astUtils.isTokenOnSameLine(commaToken, currentItemToken)) { + return; - context.report(reportItem, "',' should be placed first."); + } else if (!astUtils.isTokenOnSameLine(commaToken, currentItemToken) && + !astUtils.isTokenOnSameLine(previousItemToken, commaToken)) { - } else if (style === "last" && astUtils.isTokenOnSameLine(commaToken, currentItemToken)) { + // lone comma + context.report(reportItem, { + line: commaToken.loc.end.line, + column: commaToken.loc.start.column + }, "Bad line breaking before and after ','."); - context.report(reportItem, { - line: commaToken.loc.end.line, - column: commaToken.loc.end.column - }, "',' should be placed last."); - } - } + } else if (style === "first" && !astUtils.isTokenOnSameLine(commaToken, currentItemToken)) { - /** - * Checks the comma placement with regards to a declaration/property/element - * @param {ASTNode} node The binary expression node to check - * @param {string} property The property of the node containing child nodes. - * @private - * @returns {void} - */ - function validateComma(node, property) { - var items = node[property], - arrayLiteral = (node.type === "ArrayExpression"), - previousItemToken; + context.report(reportItem, "',' should be placed first."); - if (items.length > 1 || arrayLiteral) { + } else if (style === "last" && astUtils.isTokenOnSameLine(commaToken, currentItemToken)) { - // seed as opening [ - previousItemToken = context.getFirstToken(node); + context.report(reportItem, { + line: commaToken.loc.end.line, + column: commaToken.loc.end.column + }, "',' should be placed last."); + } + } - items.forEach(function(item) { - var commaToken = item ? context.getTokenBefore(item) : previousItemToken, - currentItemToken = item ? context.getFirstToken(item) : context.getTokenAfter(commaToken), - reportItem = item || currentItemToken; + /** + * Checks the comma placement with regards to a declaration/property/element + * @param {ASTNode} node The binary expression node to check + * @param {string} property The property of the node containing child nodes. + * @private + * @returns {void} + */ + function validateComma(node, property) { + var items = node[property], + arrayLiteral = (node.type === "ArrayExpression"), + previousItemToken; + + if (items.length > 1 || arrayLiteral) { + + // seed as opening [ + previousItemToken = context.getFirstToken(node); + + items.forEach(function(item) { + var commaToken = item ? context.getTokenBefore(item) : previousItemToken, + currentItemToken = item ? context.getFirstToken(item) : context.getTokenAfter(commaToken), + reportItem = item || currentItemToken; + + /* + * This works by comparing three token locations: + * - previousItemToken is the last token of the previous item + * - commaToken is the location of the comma before the current item + * - currentItemToken is the first token of the current item + * + * These values get switched around if item is undefined. + * previousItemToken will refer to the last token not belonging + * to the current item, which could be a comma or an opening + * square bracket. currentItemToken could be a comma. + * + * All comparisons are done based on these tokens directly, so + * they are always valid regardless of an undefined item. + */ + if (isComma(commaToken)) { + validateCommaItemSpacing(previousItemToken, commaToken, + currentItemToken, reportItem); + } + + previousItemToken = item ? context.getLastToken(item) : previousItemToken; + }); /* - * This works by comparing three token locations: - * - previousItemToken is the last token of the previous item - * - commaToken is the location of the comma before the current item - * - currentItemToken is the first token of the current item - * - * These values get switched around if item is undefined. - * previousItemToken will refer to the last token not belonging - * to the current item, which could be a comma or an opening - * square bracket. currentItemToken could be a comma. - * - * All comparisons are done based on these tokens directly, so - * they are always valid regardless of an undefined item. + * Special case for array literals that have empty last items, such + * as [ 1, 2, ]. These arrays only have two items show up in the + * AST, so we need to look at the token to verify that there's no + * dangling comma. */ - if (isComma(commaToken)) { - validateCommaItemSpacing(previousItemToken, commaToken, - currentItemToken, reportItem); - } - - previousItemToken = item ? context.getLastToken(item) : previousItemToken; - }); - - /* - * Special case for array literals that have empty last items, such - * as [ 1, 2, ]. These arrays only have two items show up in the - * AST, so we need to look at the token to verify that there's no - * dangling comma. - */ - if (arrayLiteral) { - - var lastToken = context.getLastToken(node), - nextToLastToken = context.getTokenBefore(lastToken); - - if (isComma(nextToLastToken)) { - validateCommaItemSpacing( - context.getTokenBefore(nextToLastToken), - nextToLastToken, - lastToken, - lastToken - ); + if (arrayLiteral) { + + var lastToken = context.getLastToken(node), + nextToLastToken = context.getTokenBefore(lastToken); + + if (isComma(nextToLastToken)) { + validateCommaItemSpacing( + context.getTokenBefore(nextToLastToken), + nextToLastToken, + lastToken, + lastToken + ); + } } } } - } - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- - var nodes = {}; + var nodes = {}; - if (!exceptions.VariableDeclaration) { - nodes.VariableDeclaration = function(node) { - validateComma(node, "declarations"); - }; - } - if (!exceptions.ObjectExpression) { - nodes.ObjectExpression = function(node) { - validateComma(node, "properties"); - }; - } - if (!exceptions.ArrayExpression) { - nodes.ArrayExpression = function(node) { - validateComma(node, "elements"); - }; - } - - return nodes; -}; + if (!exceptions.VariableDeclaration) { + nodes.VariableDeclaration = function(node) { + validateComma(node, "declarations"); + }; + } + if (!exceptions.ObjectExpression) { + nodes.ObjectExpression = function(node) { + validateComma(node, "properties"); + }; + } + if (!exceptions.ArrayExpression) { + nodes.ArrayExpression = function(node) { + validateComma(node, "elements"); + }; + } -module.exports.schema = [ - { - "enum": ["first", "last"] - }, - { - "type": "object", - "properties": { - "exceptions": { - "type": "object", - "additionalProperties": { - "type": "boolean" - } - } - }, - "additionalProperties": false + return nodes; } -]; +}; diff --git a/tools/eslint/lib/rules/complexity.js b/tools/eslint/lib/rules/complexity.js index 0cbdd0aad29303..029b739808d6d7 100644 --- a/tools/eslint/lib/rules/complexity.js +++ b/tools/eslint/lib/rules/complexity.js @@ -10,143 +10,153 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var option = context.options[0], - THRESHOLD = 20; +module.exports = { + meta: { + docs: { + description: "enforce a maximum cyclomatic complexity allowed in a program", + category: "Best Practices", + recommended: false + }, + + schema: [ + { + oneOf: [ + { + type: "integer", + minimum: 0 + }, + { + type: "object", + properties: { + maximum: { + type: "integer", + minimum: 0 + }, + max: { + type: "integer", + minimum: 0 + } + }, + additionalProperties: false + } + ] + } + ] + }, - if (typeof option === "object" && option.hasOwnProperty("maximum") && typeof option.maximum === "number") { - THRESHOLD = option.maximum; - } - if (typeof option === "object" && option.hasOwnProperty("max") && typeof option.max === "number") { - THRESHOLD = option.max; - } - if (typeof option === "number") { - THRESHOLD = option; - } + create: function(context) { + var option = context.options[0], + THRESHOLD = 20; - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- + if (typeof option === "object" && option.hasOwnProperty("maximum") && typeof option.maximum === "number") { + THRESHOLD = option.maximum; + } + if (typeof option === "object" && option.hasOwnProperty("max") && typeof option.max === "number") { + THRESHOLD = option.max; + } + if (typeof option === "number") { + THRESHOLD = option; + } - // Using a stack to store complexity (handling nested functions) - var fns = []; + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- - /** - * When parsing a new function, store it in our function stack - * @returns {void} - * @private - */ - function startFunction() { - fns.push(1); - } + // Using a stack to store complexity (handling nested functions) + var fns = []; - /** - * Evaluate the node at the end of function - * @param {ASTNode} node node to evaluate - * @returns {void} - * @private - */ - function endFunction(node) { - var complexity = fns.pop(), - name = "anonymous"; - - if (node.id) { - name = node.id.name; - } else if (node.parent.type === "MethodDefinition" || node.parent.type === "Property") { - name = node.parent.key.name; + /** + * When parsing a new function, store it in our function stack + * @returns {void} + * @private + */ + function startFunction() { + fns.push(1); } - if (complexity > THRESHOLD) { - context.report(node, "Function '{{name}}' has a complexity of {{complexity}}.", { name: name, complexity: complexity }); - } - } + /** + * Evaluate the node at the end of function + * @param {ASTNode} node node to evaluate + * @returns {void} + * @private + */ + function endFunction(node) { + var complexity = fns.pop(), + name = "anonymous"; + + if (node.id) { + name = node.id.name; + } else if (node.parent.type === "MethodDefinition" || node.parent.type === "Property") { + name = node.parent.key.name; + } - /** - * Increase the complexity of the function in context - * @returns {void} - * @private - */ - function increaseComplexity() { - if (fns.length) { - fns[fns.length - 1]++; + if (complexity > THRESHOLD) { + context.report(node, "Function '{{name}}' has a complexity of {{complexity}}.", { name: name, complexity: complexity }); + } } - } - /** - * Increase the switch complexity in context - * @param {ASTNode} node node to evaluate - * @returns {void} - * @private - */ - function increaseSwitchComplexity(node) { - - // Avoiding `default` - if (node.test) { - increaseComplexity(node); + /** + * Increase the complexity of the function in context + * @returns {void} + * @private + */ + function increaseComplexity() { + if (fns.length) { + fns[fns.length - 1]++; + } } - } - /** - * Increase the logical path complexity in context - * @param {ASTNode} node node to evaluate - * @returns {void} - * @private - */ - function increaseLogicalComplexity(node) { - - // Avoiding && - if (node.operator === "||") { - increaseComplexity(node); + /** + * Increase the switch complexity in context + * @param {ASTNode} node node to evaluate + * @returns {void} + * @private + */ + function increaseSwitchComplexity(node) { + + // Avoiding `default` + if (node.test) { + increaseComplexity(node); + } } - } - //-------------------------------------------------------------------------- - // Public API - //-------------------------------------------------------------------------- - - return { - "FunctionDeclaration": startFunction, - "FunctionExpression": startFunction, - "ArrowFunctionExpression": startFunction, - "FunctionDeclaration:exit": endFunction, - "FunctionExpression:exit": endFunction, - "ArrowFunctionExpression:exit": endFunction, - - "CatchClause": increaseComplexity, - "ConditionalExpression": increaseComplexity, - "LogicalExpression": increaseLogicalComplexity, - "ForStatement": increaseComplexity, - "ForInStatement": increaseComplexity, - "ForOfStatement": increaseComplexity, - "IfStatement": increaseComplexity, - "SwitchCase": increaseSwitchComplexity, - "WhileStatement": increaseComplexity, - "DoWhileStatement": increaseComplexity - }; + /** + * Increase the logical path complexity in context + * @param {ASTNode} node node to evaluate + * @returns {void} + * @private + */ + function increaseLogicalComplexity(node) { + + // Avoiding && + if (node.operator === "||") { + increaseComplexity(node); + } + } -}; + //-------------------------------------------------------------------------- + // Public API + //-------------------------------------------------------------------------- + + return { + FunctionDeclaration: startFunction, + FunctionExpression: startFunction, + ArrowFunctionExpression: startFunction, + "FunctionDeclaration:exit": endFunction, + "FunctionExpression:exit": endFunction, + "ArrowFunctionExpression:exit": endFunction, + + CatchClause: increaseComplexity, + ConditionalExpression: increaseComplexity, + LogicalExpression: increaseLogicalComplexity, + ForStatement: increaseComplexity, + ForInStatement: increaseComplexity, + ForOfStatement: increaseComplexity, + IfStatement: increaseComplexity, + SwitchCase: increaseSwitchComplexity, + WhileStatement: increaseComplexity, + DoWhileStatement: increaseComplexity + }; -module.exports.schema = [ - { - "oneOf": [ - { - "type": "integer", - "minimum": 0 - }, - { - "type": "object", - "properties": { - "maximum": { - "type": "integer", - "minimum": 0 - }, - "max": { - "type": "integer", - "minimum": 0 - } - }, - "additionalProperties": false - } - ] } -]; +}; diff --git a/tools/eslint/lib/rules/computed-property-spacing.js b/tools/eslint/lib/rules/computed-property-spacing.js index 6462dfb90ee8f3..1ae674e90dbd2a 100644 --- a/tools/eslint/lib/rules/computed-property-spacing.js +++ b/tools/eslint/lib/rules/computed-property-spacing.js @@ -1,7 +1,6 @@ /** * @fileoverview Disallows or enforces spaces inside computed properties. * @author Jamund Ferguson - * @copyright 2015 Jamund Ferguson. All rights reserved. */ "use strict"; @@ -11,143 +10,155 @@ var astUtils = require("../ast-utils"); // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var sourceCode = context.getSourceCode(); - var propertyNameMustBeSpaced = context.options[0] === "always"; // default is "never" - - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- - - /** - * Reports that there shouldn't be a space after the first token - * @param {ASTNode} node - The node to report in the event of an error. - * @param {Token} token - The token to use for the report. - * @param {Token} tokenAfter - The token after `token`. - * @returns {void} - */ - function reportNoBeginningSpace(node, token, tokenAfter) { - context.report({ - node: node, - loc: token.loc.start, - message: "There should be no space after '" + token.value + "'", - fix: function(fixer) { - return fixer.removeRange([token.range[1], tokenAfter.range[0]]); - } - }); - } - - /** - * Reports that there shouldn't be a space before the last token - * @param {ASTNode} node - The node to report in the event of an error. - * @param {Token} token - The token to use for the report. - * @param {Token} tokenBefore - The token before `token`. - * @returns {void} - */ - function reportNoEndingSpace(node, token, tokenBefore) { - context.report({ - node: node, - loc: token.loc.start, - message: "There should be no space before '" + token.value + "'", - fix: function(fixer) { - return fixer.removeRange([tokenBefore.range[1], token.range[0]]); - } - }); - } - - /** - * Reports that there should be a space after the first token - * @param {ASTNode} node - The node to report in the event of an error. - * @param {Token} token - The token to use for the report. - * @returns {void} - */ - function reportRequiredBeginningSpace(node, token) { - context.report({ - node: node, - loc: token.loc.start, - message: "A space is required after '" + token.value + "'", - fix: function(fixer) { - return fixer.insertTextAfter(token, " "); - } - }); - } +module.exports = { + meta: { + docs: { + description: "enforce consistent spacing inside computed property brackets", + category: "Stylistic Issues", + recommended: false + }, - /** - * Reports that there should be a space before the last token - * @param {ASTNode} node - The node to report in the event of an error. - * @param {Token} token - The token to use for the report. - * @returns {void} - */ - function reportRequiredEndingSpace(node, token) { - context.report({ - node: node, - loc: token.loc.start, - message: "A space is required before '" + token.value + "'", - fix: function(fixer) { - return fixer.insertTextBefore(token, " "); - } - }); - } + fixable: "whitespace", - /** - * Returns a function that checks the spacing of a node on the property name - * that was passed in. - * @param {String} propertyName The property on the node to check for spacing - * @returns {Function} A function that will check spacing on a node - */ - function checkSpacing(propertyName) { - return function(node) { - if (!node.computed) { - return; + schema: [ + { + enum: ["always", "never"] } + ] + }, + + create: function(context) { + var sourceCode = context.getSourceCode(); + var propertyNameMustBeSpaced = context.options[0] === "always"; // default is "never" + + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- + + /** + * Reports that there shouldn't be a space after the first token + * @param {ASTNode} node - The node to report in the event of an error. + * @param {Token} token - The token to use for the report. + * @param {Token} tokenAfter - The token after `token`. + * @returns {void} + */ + function reportNoBeginningSpace(node, token, tokenAfter) { + context.report({ + node: node, + loc: token.loc.start, + message: "There should be no space after '" + token.value + "'", + fix: function(fixer) { + return fixer.removeRange([token.range[1], tokenAfter.range[0]]); + } + }); + } + + /** + * Reports that there shouldn't be a space before the last token + * @param {ASTNode} node - The node to report in the event of an error. + * @param {Token} token - The token to use for the report. + * @param {Token} tokenBefore - The token before `token`. + * @returns {void} + */ + function reportNoEndingSpace(node, token, tokenBefore) { + context.report({ + node: node, + loc: token.loc.start, + message: "There should be no space before '" + token.value + "'", + fix: function(fixer) { + return fixer.removeRange([tokenBefore.range[1], token.range[0]]); + } + }); + } + + /** + * Reports that there should be a space after the first token + * @param {ASTNode} node - The node to report in the event of an error. + * @param {Token} token - The token to use for the report. + * @returns {void} + */ + function reportRequiredBeginningSpace(node, token) { + context.report({ + node: node, + loc: token.loc.start, + message: "A space is required after '" + token.value + "'", + fix: function(fixer) { + return fixer.insertTextAfter(token, " "); + } + }); + } + + /** + * Reports that there should be a space before the last token + * @param {ASTNode} node - The node to report in the event of an error. + * @param {Token} token - The token to use for the report. + * @returns {void} + */ + function reportRequiredEndingSpace(node, token) { + context.report({ + node: node, + loc: token.loc.start, + message: "A space is required before '" + token.value + "'", + fix: function(fixer) { + return fixer.insertTextBefore(token, " "); + } + }); + } + + /** + * Returns a function that checks the spacing of a node on the property name + * that was passed in. + * @param {String} propertyName The property on the node to check for spacing + * @returns {Function} A function that will check spacing on a node + */ + function checkSpacing(propertyName) { + return function(node) { + if (!node.computed) { + return; + } - var property = node[propertyName]; - - var before = context.getTokenBefore(property), - first = context.getFirstToken(property), - last = context.getLastToken(property), - after = context.getTokenAfter(property); - - if (astUtils.isTokenOnSameLine(before, first)) { - if (propertyNameMustBeSpaced) { - if (!sourceCode.isSpaceBetweenTokens(before, first) && astUtils.isTokenOnSameLine(before, first)) { - reportRequiredBeginningSpace(node, before); - } - } else { - if (sourceCode.isSpaceBetweenTokens(before, first)) { - reportNoBeginningSpace(node, before, first); + var property = node[propertyName]; + + var before = context.getTokenBefore(property), + first = context.getFirstToken(property), + last = context.getLastToken(property), + after = context.getTokenAfter(property); + + if (astUtils.isTokenOnSameLine(before, first)) { + if (propertyNameMustBeSpaced) { + if (!sourceCode.isSpaceBetweenTokens(before, first) && astUtils.isTokenOnSameLine(before, first)) { + reportRequiredBeginningSpace(node, before); + } + } else { + if (sourceCode.isSpaceBetweenTokens(before, first)) { + reportNoBeginningSpace(node, before, first); + } } } - } - if (astUtils.isTokenOnSameLine(last, after)) { - if (propertyNameMustBeSpaced) { - if (!sourceCode.isSpaceBetweenTokens(last, after) && astUtils.isTokenOnSameLine(last, after)) { - reportRequiredEndingSpace(node, after); - } - } else { - if (sourceCode.isSpaceBetweenTokens(last, after)) { - reportNoEndingSpace(node, after, last); + if (astUtils.isTokenOnSameLine(last, after)) { + if (propertyNameMustBeSpaced) { + if (!sourceCode.isSpaceBetweenTokens(last, after) && astUtils.isTokenOnSameLine(last, after)) { + reportRequiredEndingSpace(node, after); + } + } else { + if (sourceCode.isSpaceBetweenTokens(last, after)) { + reportNoEndingSpace(node, after, last); + } } } - } - }; - } - + }; + } - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- - return { - Property: checkSpacing("key"), - MemberExpression: checkSpacing("property") - }; + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- -}; + return { + Property: checkSpacing("key"), + MemberExpression: checkSpacing("property") + }; -module.exports.schema = [ - { - "enum": ["always", "never"] } -]; +}; diff --git a/tools/eslint/lib/rules/consistent-return.js b/tools/eslint/lib/rules/consistent-return.js index af0b58230405d6..0e9a8c8b0f41cf 100644 --- a/tools/eslint/lib/rules/consistent-return.js +++ b/tools/eslint/lib/rules/consistent-return.js @@ -27,100 +27,110 @@ function isUnreachable(segment) { // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var funcInfo = null; - - /** - * Checks whether of not the implicit returning is consistent if the last - * code path segment is reachable. - * - * @param {ASTNode} node - A program/function node to check. - * @returns {void} - */ - function checkLastSegment(node) { - var loc, type; - - /* - * Skip if it expected no return value or unreachable. - * When unreachable, all paths are returned or thrown. - */ - if (!funcInfo.hasReturnValue || - funcInfo.codePath.currentSegments.every(isUnreachable) || - astUtils.isES5Constructor(node) - ) { - return; - } - - // Adjust a location and a message. - if (node.type === "Program") { - - // The head of program. - loc = {line: 1, column: 0}; - type = "program"; - } else if (node.type === "ArrowFunctionExpression") { - - // `=>` token - loc = context.getSourceCode().getTokenBefore(node.body).loc.start; - type = "function"; - } else if ( - node.parent.type === "MethodDefinition" || - (node.parent.type === "Property" && node.parent.method) - ) { - - // Method name. - loc = node.parent.key.loc.start; - type = "method"; - } else { - - // Function name or `function` keyword. - loc = (node.id || node).loc.start; - type = "function"; - } +module.exports = { + meta: { + docs: { + description: "require `return` statements to either always or never specify values", + category: "Best Practices", + recommended: false + }, - // Reports. - context.report({ - node: node, - loc: loc, - message: "Expected to return a value at the end of this {{type}}.", - data: {type: type} - }); - } + schema: [] + }, - return { - - // Initializes/Disposes state of each code path. - "onCodePathStart": function(codePath) { - funcInfo = { - upper: funcInfo, - codePath: codePath, - hasReturn: false, - hasReturnValue: false, - message: "" - }; - }, - "onCodePathEnd": function() { - funcInfo = funcInfo.upper; - }, + create: function(context) { + var funcInfo = null; - // Reports a given return statement if it's inconsistent. - "ReturnStatement": function(node) { - var hasReturnValue = Boolean(node.argument); + /** + * Checks whether of not the implicit returning is consistent if the last + * code path segment is reachable. + * + * @param {ASTNode} node - A program/function node to check. + * @returns {void} + */ + function checkLastSegment(node) { + var loc, type; + + /* + * Skip if it expected no return value or unreachable. + * When unreachable, all paths are returned or thrown. + */ + if (!funcInfo.hasReturnValue || + funcInfo.codePath.currentSegments.every(isUnreachable) || + astUtils.isES5Constructor(node) + ) { + return; + } - if (!funcInfo.hasReturn) { - funcInfo.hasReturn = true; - funcInfo.hasReturnValue = hasReturnValue; - funcInfo.message = "Expected " + (hasReturnValue ? "a" : "no") + " return value."; - } else if (funcInfo.hasReturnValue !== hasReturnValue) { - context.report({node: node, message: funcInfo.message}); + // Adjust a location and a message. + if (node.type === "Program") { + + // The head of program. + loc = {line: 1, column: 0}; + type = "program"; + } else if (node.type === "ArrowFunctionExpression") { + + // `=>` token + loc = context.getSourceCode().getTokenBefore(node.body).loc.start; + type = "function"; + } else if ( + node.parent.type === "MethodDefinition" || + (node.parent.type === "Property" && node.parent.method) + ) { + + // Method name. + loc = node.parent.key.loc.start; + type = "method"; + } else { + + // Function name or `function` keyword. + loc = (node.id || node).loc.start; + type = "function"; } - }, - // Reports a given program/function if the implicit returning is not consistent. - "Program:exit": checkLastSegment, - "FunctionDeclaration:exit": checkLastSegment, - "FunctionExpression:exit": checkLastSegment, - "ArrowFunctionExpression:exit": checkLastSegment - }; -}; + // Reports. + context.report({ + node: node, + loc: loc, + message: "Expected to return a value at the end of this {{type}}.", + data: {type: type} + }); + } -module.exports.schema = []; + return { + + // Initializes/Disposes state of each code path. + onCodePathStart: function(codePath) { + funcInfo = { + upper: funcInfo, + codePath: codePath, + hasReturn: false, + hasReturnValue: false, + message: "" + }; + }, + onCodePathEnd: function() { + funcInfo = funcInfo.upper; + }, + + // Reports a given return statement if it's inconsistent. + ReturnStatement: function(node) { + var hasReturnValue = Boolean(node.argument); + + if (!funcInfo.hasReturn) { + funcInfo.hasReturn = true; + funcInfo.hasReturnValue = hasReturnValue; + funcInfo.message = "Expected " + (hasReturnValue ? "a" : "no") + " return value."; + } else if (funcInfo.hasReturnValue !== hasReturnValue) { + context.report({node: node, message: funcInfo.message}); + } + }, + + // Reports a given program/function if the implicit returning is not consistent. + "Program:exit": checkLastSegment, + "FunctionDeclaration:exit": checkLastSegment, + "FunctionExpression:exit": checkLastSegment, + "ArrowFunctionExpression:exit": checkLastSegment + }; + } +}; diff --git a/tools/eslint/lib/rules/consistent-this.js b/tools/eslint/lib/rules/consistent-this.js index 09c6a91d1a944b..042e1a0aaeddd5 100644 --- a/tools/eslint/lib/rules/consistent-this.js +++ b/tools/eslint/lib/rules/consistent-this.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to enforce consistent naming of "this" context variables * @author Raphael Pigulla - * @copyright 2015 Timothy Jones. All rights reserved. - * @copyright 2015 David Aurelio. All rights reserved. */ "use strict"; @@ -10,131 +8,141 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var aliases = []; - - if (context.options.length === 0) { - aliases.push("that"); - } else { - aliases = context.options; - } - - /** - * Reports that a variable declarator or assignment expression is assigning - * a non-'this' value to the specified alias. - * @param {ASTNode} node - The assigning node. - * @param {string} alias - the name of the alias that was incorrectly used. - * @returns {void} - */ - function reportBadAssignment(node, alias) { - context.report(node, - "Designated alias '{{alias}}' is not assigned to 'this'.", - { alias: alias }); - } +module.exports = { + meta: { + docs: { + description: "enforce consistent naming when capturing the current execution context", + category: "Stylistic Issues", + recommended: false + }, - /** - * Checks that an assignment to an identifier only assigns 'this' to the - * appropriate alias, and the alias is only assigned to 'this'. - * @param {ASTNode} node - The assigning node. - * @param {Identifier} name - The name of the variable assigned to. - * @param {Expression} value - The value of the assignment. - * @returns {void} - */ - function checkAssignment(node, name, value) { - var isThis = value.type === "ThisExpression"; - - if (aliases.indexOf(name) !== -1) { - if (!isThis || node.operator && node.operator !== "=") { - reportBadAssignment(node, name); - } - } else if (isThis) { - context.report(node, - "Unexpected alias '{{name}}' for 'this'.", { name: name }); + schema: { + type: "array", + items: { + type: "string", + minLength: 1 + }, + uniqueItems: true } - } + }, - /** - * Ensures that a variable declaration of the alias in a program or function - * is assigned to the correct value. - * @param {string} alias alias the check the assignment of. - * @param {object} scope scope of the current code we are checking. - * @private - * @returns {void} - */ - function checkWasAssigned(alias, scope) { - var variable = scope.set.get(alias); - - if (!variable) { - return; - } + create: function(context) { + var aliases = []; - if (variable.defs.some(function(def) { - return def.node.type === "VariableDeclarator" && - def.node.init !== null; - })) { - return; + if (context.options.length === 0) { + aliases.push("that"); + } else { + aliases = context.options; } - // The alias has been declared and not assigned: check it was - // assigned later in the same scope. - if (!variable.references.some(function(reference) { - var write = reference.writeExpr; - - return ( - reference.from === scope && - write && write.type === "ThisExpression" && - write.parent.operator === "=" - ); - })) { - variable.defs.map(function(def) { - return def.node; - }).forEach(function(node) { - reportBadAssignment(node, alias); - }); + /** + * Reports that a variable declarator or assignment expression is assigning + * a non-'this' value to the specified alias. + * @param {ASTNode} node - The assigning node. + * @param {string} alias - the name of the alias that was incorrectly used. + * @returns {void} + */ + function reportBadAssignment(node, alias) { + context.report(node, + "Designated alias '{{alias}}' is not assigned to 'this'.", + { alias: alias }); } - } - - /** - * Check each alias to ensure that is was assinged to the correct value. - * @returns {void} - */ - function ensureWasAssigned() { - var scope = context.getScope(); - aliases.forEach(function(alias) { - checkWasAssigned(alias, scope); - }); - } - - return { - "Program:exit": ensureWasAssigned, - "FunctionExpression:exit": ensureWasAssigned, - "FunctionDeclaration:exit": ensureWasAssigned, + /** + * Checks that an assignment to an identifier only assigns 'this' to the + * appropriate alias, and the alias is only assigned to 'this'. + * @param {ASTNode} node - The assigning node. + * @param {Identifier} name - The name of the variable assigned to. + * @param {Expression} value - The value of the assignment. + * @returns {void} + */ + function checkAssignment(node, name, value) { + var isThis = value.type === "ThisExpression"; + + if (aliases.indexOf(name) !== -1) { + if (!isThis || node.operator && node.operator !== "=") { + reportBadAssignment(node, name); + } + } else if (isThis) { + context.report(node, + "Unexpected alias '{{name}}' for 'this'.", { name: name }); + } + } - "VariableDeclarator": function(node) { - var id = node.id; - var isDestructuring = - id.type === "ArrayPattern" || id.type === "ObjectPattern"; + /** + * Ensures that a variable declaration of the alias in a program or function + * is assigned to the correct value. + * @param {string} alias alias the check the assignment of. + * @param {object} scope scope of the current code we are checking. + * @private + * @returns {void} + */ + function checkWasAssigned(alias, scope) { + var variable = scope.set.get(alias); + + if (!variable) { + return; + } - if (node.init !== null && !isDestructuring) { - checkAssignment(node, id.name, node.init); + if (variable.defs.some(function(def) { + return def.node.type === "VariableDeclarator" && + def.node.init !== null; + })) { + return; } - }, - "AssignmentExpression": function(node) { - if (node.left.type === "Identifier") { - checkAssignment(node, node.left.name, node.right); + // The alias has been declared and not assigned: check it was + // assigned later in the same scope. + if (!variable.references.some(function(reference) { + var write = reference.writeExpr; + + return ( + reference.from === scope && + write && write.type === "ThisExpression" && + write.parent.operator === "=" + ); + })) { + variable.defs.map(function(def) { + return def.node; + }).forEach(function(node) { + reportBadAssignment(node, alias); + }); } } - }; -}; + /** + * Check each alias to ensure that is was assinged to the correct value. + * @returns {void} + */ + function ensureWasAssigned() { + var scope = context.getScope(); -module.exports.schema = { - "type": "array", - "items": { - "type": "string", - "minLength": 1 - }, - "uniqueItems": true + aliases.forEach(function(alias) { + checkWasAssigned(alias, scope); + }); + } + + return { + "Program:exit": ensureWasAssigned, + "FunctionExpression:exit": ensureWasAssigned, + "FunctionDeclaration:exit": ensureWasAssigned, + + VariableDeclarator: function(node) { + var id = node.id; + var isDestructuring = + id.type === "ArrayPattern" || id.type === "ObjectPattern"; + + if (node.init !== null && !isDestructuring) { + checkAssignment(node, id.name, node.init); + } + }, + + AssignmentExpression: function(node) { + if (node.left.type === "Identifier") { + checkAssignment(node, node.left.name, node.right); + } + } + }; + + } }; diff --git a/tools/eslint/lib/rules/constructor-super.js b/tools/eslint/lib/rules/constructor-super.js index 9e0b9eac8e82d2..4b2aacf5755281 100644 --- a/tools/eslint/lib/rules/constructor-super.js +++ b/tools/eslint/lib/rules/constructor-super.js @@ -1,21 +1,24 @@ /** * @fileoverview A rule to verify `super()` callings in constructor. * @author Toru Nagashima - * @copyright 2015 Toru Nagashima. All rights reserved. */ "use strict"; -//------------------------------------------------------------------------------ -// Requirements -//------------------------------------------------------------------------------ - -var astUtils = require("../ast-utils"); - //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ +/** + * Checks whether a given code path segment is reachable or not. + * + * @param {CodePathSegment} segment - A code path segment to check. + * @returns {boolean} `true` if the segment is reachable. + */ +function isReachable(segment) { + return segment.reachable; +} + /** * Checks whether or not a given node is a constructor. * @param {ASTNode} node - A node to check. This node type is one of @@ -31,273 +34,352 @@ function isConstructorFunction(node) { ); } +/** + * Checks whether a given node can be a constructor or not. + * + * @param {ASTNode} node - A node to check. + * @returns {boolean} `true` if the node can be a constructor. + */ +function isPossibleConstructor(node) { + if (!node) { + return false; + } + + switch (node.type) { + case "ClassExpression": + case "FunctionExpression": + case "ThisExpression": + case "MemberExpression": + case "CallExpression": + case "NewExpression": + case "YieldExpression": + case "TaggedTemplateExpression": + case "MetaProperty": + return true; + + case "Identifier": + return node.name !== "undefined"; + + case "AssignmentExpression": + return isPossibleConstructor(node.right); + + case "LogicalExpression": + return ( + isPossibleConstructor(node.left) || + isPossibleConstructor(node.right) + ); + + case "ConditionalExpression": + return ( + isPossibleConstructor(node.alternate) || + isPossibleConstructor(node.consequent) + ); + + case "SequenceExpression": + var lastExpression = node.expressions[node.expressions.length - 1]; + + return isPossibleConstructor(lastExpression); + + default: + return false; + } +} + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - /* - * {{hasExtends: boolean, scope: Scope, codePath: CodePath}[]} - * Information for each constructor. - * - upper: Information of the upper constructor. - * - hasExtends: A flag which shows whether own class has a valid `extends` - * part. - * - scope: The scope of own class. - * - codePath: The code path object of the constructor. - */ - var funcInfo = null; - - /* - * {Map} - * Information for each code path segment. - * - calledInSomePaths: A flag of be called `super()` in some code paths. - * - calledInEveryPaths: A flag of be called `super()` in all code paths. - * - validNodes: - */ - var segInfoMap = Object.create(null); - - /** - * Gets the flag which shows `super()` is called in some paths. - * @param {CodePathSegment} segment - A code path segment to get. - * @returns {boolean} The flag which shows `super()` is called in some paths - */ - function isCalledInSomePath(segment) { - return segInfoMap[segment.id].calledInSomePaths; - } +module.exports = { + meta: { + docs: { + description: "require `super()` calls in constructors", + category: "ECMAScript 6", + recommended: true + }, - /** - * Gets the flag which shows `super()` is called in all paths. - * @param {CodePathSegment} segment - A code path segment to get. - * @returns {boolean} The flag which shows `super()` is called in all paths. - */ - function isCalledInEveryPath(segment) { + schema: [] + }, + + create: function(context) { /* - * If specific segment is the looped segment of the current segment, - * skip the segment. - * If not skipped, this never becomes true after a loop. + * {{hasExtends: boolean, scope: Scope, codePath: CodePath}[]} + * Information for each constructor. + * - upper: Information of the upper constructor. + * - hasExtends: A flag which shows whether own class has a valid `extends` + * part. + * - scope: The scope of own class. + * - codePath: The code path object of the constructor. */ - if (segment.nextSegments.length === 1 && - segment.nextSegments[0].isLoopedPrevSegment(segment) - ) { - return true; - } - return segInfoMap[segment.id].calledInEveryPaths; - } - - return { + var funcInfo = null; - /** - * Stacks a constructor information. - * @param {CodePath} codePath - A code path which was started. - * @param {ASTNode} node - The current node. - * @returns {void} + /* + * {Map} + * Information for each code path segment. + * - calledInSomePaths: A flag of be called `super()` in some code paths. + * - calledInEveryPaths: A flag of be called `super()` in all code paths. + * - validNodes: */ - "onCodePathStart": function(codePath, node) { - if (isConstructorFunction(node)) { - - // Class > ClassBody > MethodDefinition > FunctionExpression - var classNode = node.parent.parent.parent; - - funcInfo = { - upper: funcInfo, - isConstructor: true, - hasExtends: Boolean( - classNode.superClass && - !astUtils.isNullOrUndefined(classNode.superClass) - ), - codePath: codePath - }; - } else { - funcInfo = { - upper: funcInfo, - isConstructor: false, - hasExtends: false, - codePath: codePath - }; - } - }, + var segInfoMap = Object.create(null); /** - * Pops a constructor information. - * And reports if `super()` lacked. - * @param {CodePath} codePath - A code path which was ended. - * @param {ASTNode} node - The current node. - * @returns {void} + * Gets the flag which shows `super()` is called in some paths. + * @param {CodePathSegment} segment - A code path segment to get. + * @returns {boolean} The flag which shows `super()` is called in some paths */ - "onCodePathEnd": function(codePath, node) { - - // Skip if own class which has a valid `extends` part. - var hasExtends = funcInfo.hasExtends; - - funcInfo = funcInfo.upper; - - if (!hasExtends) { - return; - } - - // Reports if `super()` lacked. - var segments = codePath.returnedSegments; - var calledInEveryPaths = segments.every(isCalledInEveryPath); - var calledInSomePaths = segments.some(isCalledInSomePath); - - if (!calledInEveryPaths) { - context.report({ - message: calledInSomePaths ? - "Lacked a call of 'super()' in some code paths." : - "Expected to call 'super()'.", - node: node.parent - }); - } - }, + function isCalledInSomePath(segment) { + return segment.reachable && segInfoMap[segment.id].calledInSomePaths; + } /** - * Initialize information of a given code path segment. - * @param {CodePathSegment} segment - A code path segment to initialize. - * @returns {void} + * Gets the flag which shows `super()` is called in all paths. + * @param {CodePathSegment} segment - A code path segment to get. + * @returns {boolean} The flag which shows `super()` is called in all paths. */ - "onCodePathSegmentStart": function(segment) { + function isCalledInEveryPath(segment) { /* - * Skip if this is not in a constructor of a class which has a - * valid `extends` part. + * If specific segment is the looped segment of the current segment, + * skip the segment. + * If not skipped, this never becomes true after a loop. */ - if (!(funcInfo && funcInfo.isConstructor && funcInfo.hasExtends)) { - return; + if (segment.nextSegments.length === 1 && + segment.nextSegments[0].isLoopedPrevSegment(segment) + ) { + return true; } + return segment.reachable && segInfoMap[segment.id].calledInEveryPaths; + } - // Initialize info. - var info = segInfoMap[segment.id] = { - calledInSomePaths: false, - calledInEveryPaths: false, - validNodes: [] - }; + return { - // When there are previous segments, aggregates these. - var prevSegments = segment.prevSegments; + /** + * Stacks a constructor information. + * @param {CodePath} codePath - A code path which was started. + * @param {ASTNode} node - The current node. + * @returns {void} + */ + onCodePathStart: function(codePath, node) { + if (isConstructorFunction(node)) { + + // Class > ClassBody > MethodDefinition > FunctionExpression + var classNode = node.parent.parent.parent; + var superClass = classNode.superClass; + + funcInfo = { + upper: funcInfo, + isConstructor: true, + hasExtends: Boolean(superClass), + superIsConstructor: isPossibleConstructor(superClass), + codePath: codePath + }; + } else { + funcInfo = { + upper: funcInfo, + isConstructor: false, + hasExtends: false, + superIsConstructor: false, + codePath: codePath + }; + } + }, + + /** + * Pops a constructor information. + * And reports if `super()` lacked. + * @param {CodePath} codePath - A code path which was ended. + * @param {ASTNode} node - The current node. + * @returns {void} + */ + onCodePathEnd: function(codePath, node) { + var hasExtends = funcInfo.hasExtends; - if (prevSegments.length > 0) { - info.calledInSomePaths = prevSegments.some(isCalledInSomePath); - info.calledInEveryPaths = prevSegments.every(isCalledInEveryPath); - } - }, + // Pop. + funcInfo = funcInfo.upper; - /** - * Update information of the code path segment when a code path was - * looped. - * @param {CodePathSegment} fromSegment - The code path segment of the - * end of a loop. - * @param {CodePathSegment} toSegment - A code path segment of the head - * of a loop. - * @returns {void} - */ - "onCodePathSegmentLoop": function(fromSegment, toSegment) { + if (!hasExtends) { + return; + } - /* - * Skip if this is not in a constructor of a class which has a - * valid `extends` part. - */ - if (!(funcInfo && funcInfo.isConstructor && funcInfo.hasExtends)) { - return; - } + // Reports if `super()` lacked. + var segments = codePath.returnedSegments; + var calledInEveryPaths = segments.every(isCalledInEveryPath); + var calledInSomePaths = segments.some(isCalledInSomePath); - // Update information inside of the loop. - var isRealLoop = toSegment.prevSegments.length >= 2; + if (!calledInEveryPaths) { + context.report({ + message: calledInSomePaths ? + "Lacked a call of 'super()' in some code paths." : + "Expected to call 'super()'.", + node: node.parent + }); + } + }, + + /** + * Initialize information of a given code path segment. + * @param {CodePathSegment} segment - A code path segment to initialize. + * @returns {void} + */ + onCodePathSegmentStart: function(segment) { + if (!(funcInfo && funcInfo.isConstructor && funcInfo.hasExtends)) { + return; + } - funcInfo.codePath.traverseSegments( - {first: toSegment, last: fromSegment}, - function(segment) { - var info = segInfoMap[segment.id]; + // Initialize info. + var info = segInfoMap[segment.id] = { + calledInSomePaths: false, + calledInEveryPaths: false, + validNodes: [] + }; - // Updates flags. - var prevSegments = segment.prevSegments; + // When there are previous segments, aggregates these. + var prevSegments = segment.prevSegments; + if (prevSegments.length > 0) { info.calledInSomePaths = prevSegments.some(isCalledInSomePath); info.calledInEveryPaths = prevSegments.every(isCalledInEveryPath); + } + }, + + /** + * Update information of the code path segment when a code path was + * looped. + * @param {CodePathSegment} fromSegment - The code path segment of the + * end of a loop. + * @param {CodePathSegment} toSegment - A code path segment of the head + * of a loop. + * @returns {void} + */ + onCodePathSegmentLoop: function(fromSegment, toSegment) { + if (!(funcInfo && funcInfo.isConstructor && funcInfo.hasExtends)) { + return; + } + + // Update information inside of the loop. + var isRealLoop = toSegment.prevSegments.length >= 2; + + funcInfo.codePath.traverseSegments( + {first: toSegment, last: fromSegment}, + function(segment) { + var info = segInfoMap[segment.id]; + var prevSegments = segment.prevSegments; + + // Updates flags. + info.calledInSomePaths = prevSegments.some(isCalledInSomePath); + info.calledInEveryPaths = prevSegments.every(isCalledInEveryPath); + + // If flags become true anew, reports the valid nodes. + if (info.calledInSomePaths || isRealLoop) { + var nodes = info.validNodes; + + info.validNodes = []; - // If flags become true anew, reports the valid nodes. - if (info.calledInSomePaths || isRealLoop) { - var nodes = info.validNodes; + for (var i = 0; i < nodes.length; ++i) { + var node = nodes[i]; - info.validNodes = []; + context.report({ + message: "Unexpected duplicate 'super()'.", + node: node + }); + } + } + } + ); + }, + + /** + * Checks for a call of `super()`. + * @param {ASTNode} node - A CallExpression node to check. + * @returns {void} + */ + "CallExpression:exit": function(node) { + if (!(funcInfo && funcInfo.isConstructor)) { + return; + } + + // Skips except `super()`. + if (node.callee.type !== "Super") { + return; + } + + // Reports if needed. + if (funcInfo.hasExtends) { + var segments = funcInfo.codePath.currentSegments; + var reachable = false; + var duplicate = false; - for (var i = 0; i < nodes.length; ++i) { - var node = nodes[i]; + for (var i = 0; i < segments.length; ++i) { + var segment = segments[i]; + if (segment.reachable) { + var info = segInfoMap[segment.id]; + + reachable = true; + duplicate = duplicate || info.calledInSomePaths; + info.calledInSomePaths = info.calledInEveryPaths = true; + } + } + + if (reachable) { + if (duplicate) { context.report({ message: "Unexpected duplicate 'super()'.", node: node }); + } else if (!funcInfo.superIsConstructor) { + context.report({ + message: "Unexpected 'super()' because 'super' is not a constructor.", + node: node + }); + } else { + info.validNodes.push(node); } } + } else if (funcInfo.codePath.currentSegments.some(isReachable)) { + context.report({ + message: "Unexpected 'super()'.", + node: node + }); } - ); - }, - - /** - * Checks for a call of `super()`. - * @param {ASTNode} node - A CallExpression node to check. - * @returns {void} - */ - "CallExpression:exit": function(node) { + }, - // Skip if the node is not `super()`. - if (node.callee.type !== "Super") { - return; - } - - // Skip if this is not in a constructor. - if (!(funcInfo && funcInfo.isConstructor)) { - return; - } + /** + * Set the mark to the returned path as `super()` was called. + * @param {ASTNode} node - A ReturnStatement node to check. + * @returns {void} + */ + ReturnStatement: function(node) { + if (!(funcInfo && funcInfo.isConstructor && funcInfo.hasExtends)) { + return; + } - // Reports if needed. - if (funcInfo.hasExtends) { + // Skips if no argument. + if (!node.argument) { + return; + } - /* - * This class has a valid `extends` part. - * Checks duplicate `super()`; - */ + // Returning argument is a substitute of 'super()'. var segments = funcInfo.codePath.currentSegments; - var duplicate = false; for (var i = 0; i < segments.length; ++i) { - var info = segInfoMap[segments[i].id]; + var segment = segments[i]; - duplicate = duplicate || info.calledInSomePaths; - info.calledInSomePaths = info.calledInEveryPaths = true; - } + if (segment.reachable) { + var info = segInfoMap[segment.id]; - if (duplicate) { - context.report({ - message: "Unexpected duplicate 'super()'.", - node: node - }); - } else { - info.validNodes.push(node); + info.calledInSomePaths = info.calledInEveryPaths = true; + } } - } else { - - /* - * This class does not have a valid `extends` part. - * Disallow `super()`. - */ - context.report({ - message: "Unexpected 'super()'.", - node: node - }); - } - }, + }, - /** - * Resets state. - * @returns {void} - */ - "Program:exit": function() { - segInfoMap = Object.create(null); - } - }; + /** + * Resets state. + * @returns {void} + */ + "Program:exit": function() { + segInfoMap = Object.create(null); + } + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/curly.js b/tools/eslint/lib/rules/curly.js index 5253a3fb6bbdbf..0bc5fdb3de4261 100644 --- a/tools/eslint/lib/rules/curly.js +++ b/tools/eslint/lib/rules/curly.js @@ -1,7 +1,6 @@ /** * @fileoverview Rule to flag statements without curly braces * @author Nicholas C. Zakas - * @copyright 2015 Ivan Nikulin. All rights reserved. */ "use strict"; @@ -15,280 +14,290 @@ var astUtils = require("../ast-utils"); // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - var multiOnly = (context.options[0] === "multi"); - var multiLine = (context.options[0] === "multi-line"); - var multiOrNest = (context.options[0] === "multi-or-nest"); - var consistent = (context.options[1] === "consistent"); - - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- - - /** - * Determines if a given node is a one-liner that's on the same line as it's preceding code. - * @param {ASTNode} node The node to check. - * @returns {boolean} True if the node is a one-liner that's on the same line as it's preceding code. - * @private - */ - function isCollapsedOneLiner(node) { - var before = context.getTokenBefore(node), - last = context.getLastToken(node); - - return before.loc.start.line === last.loc.end.line; - } - - /** - * Determines if a given node is a one-liner. - * @param {ASTNode} node The node to check. - * @returns {boolean} True if the node is a one-liner. - * @private - */ - function isOneLiner(node) { - var first = context.getFirstToken(node), - last = context.getLastToken(node); - - return first.loc.start.line === last.loc.end.line; - } +module.exports = { + meta: { + docs: { + description: "enforce consistent brace style for all control statements", + category: "Best Practices", + recommended: false + }, - /** - * 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) { - var sourceCode = context.getSourceCode(); - var token = sourceCode.getTokenAfter(node.consequent); - - while (token.type !== "Keyword" || token.value !== "else") { - token = sourceCode.getTokenAfter(token); + schema: { + anyOf: [ + { + type: "array", + items: [ + { + enum: ["all"] + } + ], + minItems: 0, + maxItems: 1 + }, + { + type: "array", + items: [ + { + enum: ["multi", "multi-line", "multi-or-nest"] + }, + { + enum: ["consistent"] + } + ], + minItems: 0, + maxItems: 2 + } + ] + } + }, + + create: function(context) { + + var multiOnly = (context.options[0] === "multi"); + var multiLine = (context.options[0] === "multi-line"); + var multiOrNest = (context.options[0] === "multi-or-nest"); + var consistent = (context.options[1] === "consistent"); + + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- + + /** + * Determines if a given node is a one-liner that's on the same line as it's preceding code. + * @param {ASTNode} node The node to check. + * @returns {boolean} True if the node is a one-liner that's on the same line as it's preceding code. + * @private + */ + function isCollapsedOneLiner(node) { + var before = context.getTokenBefore(node), + last = context.getLastToken(node); + + return before.loc.start.line === last.loc.end.line; } - return token; - } + /** + * Determines if a given node is a one-liner. + * @param {ASTNode} node The node to check. + * @returns {boolean} True if the node is a one-liner. + * @private + */ + function isOneLiner(node) { + var first = context.getFirstToken(node), + last = context.getLastToken(node); + + return first.loc.start.line === last.loc.end.line; + } - /** - * Checks a given IfStatement node requires braces of the consequent chunk. - * This returns `true` when below: - * - * 1. The given node has the `alternate` node. - * 2. There is a `IfStatement` which doesn't have `alternate` node in the - * trailing statement chain of the `consequent` node. - * - * @param {ASTNode} node - A IfStatement node to check. - * @returns {boolean} `true` if the node requires braces of the consequent chunk. - */ - function requiresBraceOfConsequent(node) { - if (node.alternate && node.consequent.type === "BlockStatement") { - if (node.consequent.body.length >= 2) { - return true; + /** + * 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) { + var sourceCode = context.getSourceCode(); + var token = sourceCode.getTokenAfter(node.consequent); + + while (token.type !== "Keyword" || token.value !== "else") { + token = sourceCode.getTokenAfter(token); } - node = node.consequent.body[0]; - while (node) { - if (node.type === "IfStatement" && !node.alternate) { + return token; + } + + /** + * Checks a given IfStatement node requires braces of the consequent chunk. + * This returns `true` when below: + * + * 1. The given node has the `alternate` node. + * 2. There is a `IfStatement` which doesn't have `alternate` node in the + * trailing statement chain of the `consequent` node. + * + * @param {ASTNode} node - A IfStatement node to check. + * @returns {boolean} `true` if the node requires braces of the consequent chunk. + */ + function requiresBraceOfConsequent(node) { + if (node.alternate && node.consequent.type === "BlockStatement") { + if (node.consequent.body.length >= 2) { return true; } - node = astUtils.getTrailingStatement(node); + + node = node.consequent.body[0]; + while (node) { + if (node.type === "IfStatement" && !node.alternate) { + return true; + } + node = astUtils.getTrailingStatement(node); + } } - } - return false; - } + return false; + } - /** - * Reports "Expected { after ..." error - * @param {ASTNode} node The node to report. - * @param {string} name The name to report. - * @param {string} suffix Additional string to add to the end of a report. - * @returns {void} - * @private - */ - function reportExpectedBraceError(node, name, suffix) { - context.report({ - node: node, - loc: (name !== "else" ? node : getElseKeyword(node)).loc.start, - message: "Expected { after '{{name}}'{{suffix}}.", - data: { - name: name, - suffix: (suffix ? " " + suffix : "") - } - }); - } + /** + * Reports "Expected { after ..." error + * @param {ASTNode} node The node to report. + * @param {string} name The name to report. + * @param {string} suffix Additional string to add to the end of a report. + * @returns {void} + * @private + */ + function reportExpectedBraceError(node, name, suffix) { + context.report({ + node: node, + loc: (name !== "else" ? node : getElseKeyword(node)).loc.start, + message: "Expected { after '{{name}}'{{suffix}}.", + data: { + name: name, + suffix: (suffix ? " " + suffix : "") + } + }); + } - /** - * Reports "Unnecessary { after ..." error - * @param {ASTNode} node The node to report. - * @param {string} name The name to report. - * @param {string} suffix Additional string to add to the end of a report. - * @returns {void} - * @private - */ - function reportUnnecessaryBraceError(node, name, suffix) { - context.report({ - node: node, - loc: (name !== "else" ? node : getElseKeyword(node)).loc.start, - message: "Unnecessary { after '{{name}}'{{suffix}}.", - data: { - name: name, - suffix: (suffix ? " " + suffix : "") - } - }); - } + /** + * Reports "Unnecessary { after ..." error + * @param {ASTNode} node The node to report. + * @param {string} name The name to report. + * @param {string} suffix Additional string to add to the end of a report. + * @returns {void} + * @private + */ + function reportUnnecessaryBraceError(node, name, suffix) { + context.report({ + node: node, + loc: (name !== "else" ? node : getElseKeyword(node)).loc.start, + message: "Unnecessary { after '{{name}}'{{suffix}}.", + data: { + name: name, + suffix: (suffix ? " " + suffix : "") + } + }); + } - /** - * Prepares to check the body of a node to see if it's a block statement. - * @param {ASTNode} node The node to report if there's a problem. - * @param {ASTNode} body The body node to check for blocks. - * @param {string} name The name to report if there's a problem. - * @param {string} suffix Additional string to add to the end of a report. - * @returns {object} a prepared check object, with "actual", "expected", "check" properties. - * "actual" will be `true` or `false` whether the body is already a block statement. - * "expected" will be `true` or `false` if the body should be a block statement or not, or - * `null` if it doesn't matter, depending on the rule options. It can be modified to change - * the final behavior of "check". - * "check" will be a function reporting appropriate problems depending on the other - * properties. - */ - function prepareCheck(node, body, name, suffix) { - var hasBlock = (body.type === "BlockStatement"); - var expected = null; - - if (node.type === "IfStatement" && node.consequent === body && requiresBraceOfConsequent(node)) { - expected = true; - } else if (multiOnly) { - if (hasBlock && body.body.length === 1) { - expected = false; - } - } else if (multiLine) { - if (!isCollapsedOneLiner(body)) { + /** + * Prepares to check the body of a node to see if it's a block statement. + * @param {ASTNode} node The node to report if there's a problem. + * @param {ASTNode} body The body node to check for blocks. + * @param {string} name The name to report if there's a problem. + * @param {string} suffix Additional string to add to the end of a report. + * @returns {object} a prepared check object, with "actual", "expected", "check" properties. + * "actual" will be `true` or `false` whether the body is already a block statement. + * "expected" will be `true` or `false` if the body should be a block statement or not, or + * `null` if it doesn't matter, depending on the rule options. It can be modified to change + * the final behavior of "check". + * "check" will be a function reporting appropriate problems depending on the other + * properties. + */ + function prepareCheck(node, body, name, suffix) { + var hasBlock = (body.type === "BlockStatement"); + var expected = null; + + if (node.type === "IfStatement" && node.consequent === body && requiresBraceOfConsequent(node)) { expected = true; - } - } else if (multiOrNest) { - if (hasBlock && body.body.length === 1 && isOneLiner(body.body[0])) { - expected = false; - } else if (!isOneLiner(body)) { + } else if (multiOnly) { + if (hasBlock && body.body.length === 1) { + expected = false; + } + } else if (multiLine) { + if (!isCollapsedOneLiner(body)) { + expected = true; + } + } else if (multiOrNest) { + if (hasBlock && body.body.length === 1 && isOneLiner(body.body[0])) { + expected = false; + } else if (!isOneLiner(body)) { + expected = true; + } + } else { expected = true; } - } else { - expected = true; - } - return { - actual: hasBlock, - expected: expected, - check: function() { - if (this.expected !== null && this.expected !== this.actual) { - if (this.expected) { - reportExpectedBraceError(node, name, suffix); - } else { - reportUnnecessaryBraceError(node, name, suffix); + return { + actual: hasBlock, + expected: expected, + check: function() { + if (this.expected !== null && this.expected !== this.actual) { + if (this.expected) { + reportExpectedBraceError(node, name, suffix); + } else { + reportUnnecessaryBraceError(node, name, suffix); + } } } - } - }; - } - - /** - * Prepares to check the bodies of a "if", "else if" and "else" chain. - * @param {ASTNode} node The first IfStatement node of the chain. - * @returns {object[]} prepared checks for each body of the chain. See `prepareCheck` for more - * information. - */ - function prepareIfChecks(node) { - var preparedChecks = []; - - do { - preparedChecks.push(prepareCheck(node, node.consequent, "if", "condition")); - if (node.alternate && node.alternate.type !== "IfStatement") { - preparedChecks.push(prepareCheck(node, node.alternate, "else")); - break; - } - node = node.alternate; - } while (node); - - if (consistent) { - - /* - * If any node should have or already have braces, make sure they - * all have braces. - * If all nodes shouldn't have braces, make sure they don't. - */ - var expected = preparedChecks.some(function(preparedCheck) { - if (preparedCheck.expected !== null) { - return preparedCheck.expected; - } - return preparedCheck.actual; - }); - - preparedChecks.forEach(function(preparedCheck) { - preparedCheck.expected = expected; - }); + }; } - return preparedChecks; - } - - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- + /** + * Prepares to check the bodies of a "if", "else if" and "else" chain. + * @param {ASTNode} node The first IfStatement node of the chain. + * @returns {object[]} prepared checks for each body of the chain. See `prepareCheck` for more + * information. + */ + function prepareIfChecks(node) { + var preparedChecks = []; + + do { + preparedChecks.push(prepareCheck(node, node.consequent, "if", "condition")); + if (node.alternate && node.alternate.type !== "IfStatement") { + preparedChecks.push(prepareCheck(node, node.alternate, "else")); + break; + } + node = node.alternate; + } while (node); + + if (consistent) { + + /* + * If any node should have or already have braces, make sure they + * all have braces. + * If all nodes shouldn't have braces, make sure they don't. + */ + var expected = preparedChecks.some(function(preparedCheck) { + if (preparedCheck.expected !== null) { + return preparedCheck.expected; + } + return preparedCheck.actual; + }); - return { - "IfStatement": function(node) { - if (node.parent.type !== "IfStatement") { - prepareIfChecks(node).forEach(function(preparedCheck) { - preparedCheck.check(); + preparedChecks.forEach(function(preparedCheck) { + preparedCheck.expected = expected; }); } - }, - "WhileStatement": function(node) { - prepareCheck(node, node.body, "while", "condition").check(); - }, + return preparedChecks; + } - "DoWhileStatement": function(node) { - prepareCheck(node, node.body, "do").check(); - }, + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- - "ForStatement": function(node) { - prepareCheck(node, node.body, "for", "condition").check(); - }, + return { + IfStatement: function(node) { + if (node.parent.type !== "IfStatement") { + prepareIfChecks(node).forEach(function(preparedCheck) { + preparedCheck.check(); + }); + } + }, - "ForInStatement": function(node) { - prepareCheck(node, node.body, "for-in").check(); - }, + WhileStatement: function(node) { + prepareCheck(node, node.body, "while", "condition").check(); + }, - "ForOfStatement": function(node) { - prepareCheck(node, node.body, "for-of").check(); - } - }; -}; + DoWhileStatement: function(node) { + prepareCheck(node, node.body, "do").check(); + }, -module.exports.schema = { - "anyOf": [ - { - "type": "array", - "items": [ - { - "enum": ["all"] - } - ], - "minItems": 0, - "maxItems": 1 - }, - { - "type": "array", - "items": [ - { - "enum": ["multi", "multi-line", "multi-or-nest"] - }, - { - "enum": ["consistent"] - } - ], - "minItems": 0, - "maxItems": 2 - } - ] + ForStatement: function(node) { + prepareCheck(node, node.body, "for", "condition").check(); + }, + + ForInStatement: function(node) { + prepareCheck(node, node.body, "for-in").check(); + }, + + ForOfStatement: function(node) { + prepareCheck(node, node.body, "for-of").check(); + } + }; + } }; diff --git a/tools/eslint/lib/rules/default-case.js b/tools/eslint/lib/rules/default-case.js index 6bcc791238a3e7..a4f3eef3cc0768 100644 --- a/tools/eslint/lib/rules/default-case.js +++ b/tools/eslint/lib/rules/default-case.js @@ -4,67 +4,89 @@ */ "use strict"; -var COMMENT_VALUE = "no default"; +var DEFAULT_COMMENT_PATTERN = /^no default$/; //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- - - /** - * Shortcut to get last element of array - * @param {*[]} collection Array - * @returns {*} Last element - */ - function last(collection) { - return collection[collection.length - 1]; - } +module.exports = { + meta: { + docs: { + description: "require `default` cases in switch statements", + category: "Best Practices", + recommended: false + }, + + schema: [{ + type: "object", + properties: { + commentPattern: { + type: "string" + } + }, + additionalProperties: false + }] + }, + + create: function(context) { + var options = context.options[0] || {}; + var commentPattern = options.commentPattern ? + new RegExp(options.commentPattern) : + DEFAULT_COMMENT_PATTERN; + + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- + + /** + * Shortcut to get last element of array + * @param {*[]} collection Array + * @returns {*} Last element + */ + function last(collection) { + return collection[collection.length - 1]; + } - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- - return { + return { - "SwitchStatement": function(node) { + SwitchStatement: function(node) { - if (!node.cases.length) { + if (!node.cases.length) { - /* - * skip check of empty switch because there is no easy way - * to extract comments inside it now - */ - return; - } + /* + * skip check of empty switch because there is no easy way + * to extract comments inside it now + */ + return; + } - var hasDefault = node.cases.some(function(v) { - return v.test === null; - }); + var hasDefault = node.cases.some(function(v) { + return v.test === null; + }); - if (!hasDefault) { + if (!hasDefault) { - var comment; - var comments; + var comment; + var comments; - var lastCase = last(node.cases); + var lastCase = last(node.cases); - comments = context.getComments(lastCase).trailing; + comments = context.getComments(lastCase).trailing; - if (comments.length) { - comment = last(comments); - } + if (comments.length) { + comment = last(comments); + } - if (!comment || comment.value.trim() !== COMMENT_VALUE) { - context.report(node, "Expected a default case."); + if (!comment || !commentPattern.test(comment.value.trim())) { + context.report(node, "Expected a default case."); + } } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/dot-location.js b/tools/eslint/lib/rules/dot-location.js index 89e82269aa874e..0e1c257d392a2a 100644 --- a/tools/eslint/lib/rules/dot-location.js +++ b/tools/eslint/lib/rules/dot-location.js @@ -1,7 +1,6 @@ /** * @fileoverview Validates newlines before and after dots * @author Greg Cochard - * @copyright 2015 Greg Cochard */ "use strict"; @@ -12,51 +11,61 @@ var astUtils = require("../ast-utils"); // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "enforce consistent newlines before and after dots", + category: "Best Practices", + recommended: false + }, - var config = context.options[0], - onObject; + schema: [ + { + enum: ["object", "property"] + } + ] + }, + + create: function(context) { + + var config = context.options[0], + onObject; - // default to onObject if no preference is passed - onObject = config === "object" || !config; + // default to onObject if no preference is passed + onObject = config === "object" || !config; - /** - * Reports if the dot between object and property is on the correct loccation. - * @param {ASTNode} obj The object owning the property. - * @param {ASTNode} prop The property of the object. - * @param {ASTNode} node The corresponding node of the token. - * @returns {void} - */ - function checkDotLocation(obj, prop, node) { - var dot = context.getTokenBefore(prop); + /** + * Reports if the dot between object and property is on the correct loccation. + * @param {ASTNode} obj The object owning the property. + * @param {ASTNode} prop The property of the object. + * @param {ASTNode} node The corresponding node of the token. + * @returns {void} + */ + function checkDotLocation(obj, prop, node) { + var dot = context.getTokenBefore(prop); - if (dot.type === "Punctuator" && dot.value === ".") { - if (onObject) { - if (!astUtils.isTokenOnSameLine(obj, dot)) { - context.report(node, dot.loc.start, "Expected dot to be on same line as object."); + if (dot.type === "Punctuator" && dot.value === ".") { + if (onObject) { + if (!astUtils.isTokenOnSameLine(obj, dot)) { + context.report(node, dot.loc.start, "Expected dot to be on same line as object."); + } + } else if (!astUtils.isTokenOnSameLine(dot, prop)) { + context.report(node, dot.loc.start, "Expected dot to be on same line as property."); } - } else if (!astUtils.isTokenOnSameLine(dot, prop)) { - context.report(node, dot.loc.start, "Expected dot to be on same line as property."); } } - } - /** - * Checks the spacing of the dot within a member expression. - * @param {ASTNode} node The node to check. - * @returns {void} - */ - function checkNode(node) { - checkDotLocation(node.object, node.property, node); - } - - return { - "MemberExpression": checkNode - }; -}; + /** + * Checks the spacing of the dot within a member expression. + * @param {ASTNode} node The node to check. + * @returns {void} + */ + function checkNode(node) { + checkDotLocation(node.object, node.property, node); + } -module.exports.schema = [ - { - "enum": ["object", "property"] + return { + MemberExpression: checkNode + }; } -]; +}; diff --git a/tools/eslint/lib/rules/dot-notation.js b/tools/eslint/lib/rules/dot-notation.js index f4d0bca6d280da..07e0b0a8db82a7 100644 --- a/tools/eslint/lib/rules/dot-notation.js +++ b/tools/eslint/lib/rules/dot-notation.js @@ -11,50 +11,60 @@ var validIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/; var keywords = require("../util/keywords"); -module.exports = function(context) { - var options = context.options[0] || {}; - var allowKeywords = options.allowKeywords === void 0 || !!options.allowKeywords; +module.exports = { + meta: { + docs: { + description: "enforce dot notation whenever possible", + category: "Best Practices", + recommended: false + }, - var allowPattern; + schema: [ + { + type: "object", + properties: { + allowKeywords: { + type: "boolean" + }, + allowPattern: { + type: "string" + } + }, + additionalProperties: false + } + ] + }, - if (options.allowPattern) { - allowPattern = new RegExp(options.allowPattern); - } + create: function(context) { + var options = context.options[0] || {}; + var allowKeywords = options.allowKeywords === void 0 || !!options.allowKeywords; - return { - "MemberExpression": function(node) { - if ( - node.computed && - node.property.type === "Literal" && - validIdentifier.test(node.property.value) && - (allowKeywords || keywords.indexOf("" + node.property.value) === -1) - ) { - if (!(allowPattern && allowPattern.test(node.property.value))) { - context.report(node.property, "[" + JSON.stringify(node.property.value) + "] is better written in dot notation."); - } - } - if ( - !allowKeywords && - !node.computed && - keywords.indexOf("" + node.property.name) !== -1 - ) { - context.report(node.property, "." + node.property.name + " is a syntax error."); - } + var allowPattern; + + if (options.allowPattern) { + allowPattern = new RegExp(options.allowPattern); } - }; -}; -module.exports.schema = [ - { - "type": "object", - "properties": { - "allowKeywords": { - "type": "boolean" - }, - "allowPattern": { - "type": "string" + return { + MemberExpression: function(node) { + if ( + node.computed && + node.property.type === "Literal" && + validIdentifier.test(node.property.value) && + (allowKeywords || keywords.indexOf("" + node.property.value) === -1) + ) { + if (!(allowPattern && allowPattern.test(node.property.value))) { + context.report(node.property, "[" + JSON.stringify(node.property.value) + "] is better written in dot notation."); + } + } + if ( + !allowKeywords && + !node.computed && + keywords.indexOf("" + node.property.name) !== -1 + ) { + context.report(node.property, "." + node.property.name + " is a syntax error."); + } } - }, - "additionalProperties": false + }; } -]; +}; diff --git a/tools/eslint/lib/rules/eol-last.js b/tools/eslint/lib/rules/eol-last.js index fe5b0aa425bfff..1bd7c2897a6e71 100644 --- a/tools/eslint/lib/rules/eol-last.js +++ b/tools/eslint/lib/rules/eol-last.js @@ -8,43 +8,55 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- - - return { - - "Program": function checkBadEOF(node) { - - // Get the whole source code, not for node only. - var src = context.getSource(), - location = {column: 1}, - linebreakStyle = context.options[0] || "unix", - linebreak = linebreakStyle === "unix" ? "\n" : "\r\n"; - - if (src[src.length - 1] !== "\n") { - - // file is not newline-terminated - location.line = src.split(/\n/g).length; - context.report({ - node: node, - loc: location, - message: "Newline required at end of file but not found.", - fix: function(fixer) { - return fixer.insertTextAfterRange([0, src.length], linebreak); - } - }); +module.exports = { + meta: { + docs: { + description: "enforce at least one newline at the end of files", + category: "Stylistic Issues", + recommended: false + }, + + fixable: "whitespace", + + schema: [ + { + enum: ["unix", "windows"] + } + ] + }, + + create: function(context) { + + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + return { + + Program: function checkBadEOF(node) { + + // Get the whole source code, not for node only. + var src = context.getSource(), + location = {column: 1}, + linebreakStyle = context.options[0] || "unix", + linebreak = linebreakStyle === "unix" ? "\n" : "\r\n"; + + if (src[src.length - 1] !== "\n") { + + // file is not newline-terminated + location.line = src.split(/\n/g).length; + context.report({ + node: node, + loc: location, + message: "Newline required at end of file but not found.", + fix: function(fixer) { + return fixer.insertTextAfterRange([0, src.length], linebreak); + } + }); + } } - } - - }; -}; + }; -module.exports.schema = [ - { - "enum": ["unix", "windows"] } -]; +}; diff --git a/tools/eslint/lib/rules/eqeqeq.js b/tools/eslint/lib/rules/eqeqeq.js index 613a3e18edc88e..f1d1d1542928f6 100644 --- a/tools/eslint/lib/rules/eqeqeq.js +++ b/tools/eslint/lib/rules/eqeqeq.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to flag statements that use != and == instead of !== and === * @author Nicholas C. Zakas - * @copyright 2013 Nicholas C. Zakas. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; @@ -11,91 +9,101 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - /** - * Checks if an expression is a typeof expression - * @param {ASTNode} node The node to check - * @returns {boolean} if the node is a typeof expression - */ - function isTypeOf(node) { - return node.type === "UnaryExpression" && node.operator === "typeof"; - } - - /** - * Checks if either operand of a binary expression is a typeof operation - * @param {ASTNode} node The node to check - * @returns {boolean} if one of the operands is typeof - * @private - */ - function isTypeOfBinary(node) { - return isTypeOf(node.left) || isTypeOf(node.right); - } +module.exports = { + meta: { + docs: { + description: "require the use of `===` and `!==`", + category: "Best Practices", + recommended: false + }, + + schema: [ + { + enum: ["smart", "allow-null"] + } + ] + }, + + create: function(context) { + + /** + * Checks if an expression is a typeof expression + * @param {ASTNode} node The node to check + * @returns {boolean} if the node is a typeof expression + */ + function isTypeOf(node) { + return node.type === "UnaryExpression" && node.operator === "typeof"; + } - /** - * Checks if operands are literals of the same type (via typeof) - * @param {ASTNode} node The node to check - * @returns {boolean} if operands are of same type - * @private - */ - function areLiteralsAndSameType(node) { - return node.left.type === "Literal" && node.right.type === "Literal" && - typeof node.left.value === typeof node.right.value; - } + /** + * Checks if either operand of a binary expression is a typeof operation + * @param {ASTNode} node The node to check + * @returns {boolean} if one of the operands is typeof + * @private + */ + function isTypeOfBinary(node) { + return isTypeOf(node.left) || isTypeOf(node.right); + } - /** - * Checks if one of the operands is a literal null - * @param {ASTNode} node The node to check - * @returns {boolean} if operands are null - * @private - */ - function isNullCheck(node) { - return (node.right.type === "Literal" && node.right.value === null) || - (node.left.type === "Literal" && node.left.value === null); - } + /** + * Checks if operands are literals of the same type (via typeof) + * @param {ASTNode} node The node to check + * @returns {boolean} if operands are of same type + * @private + */ + function areLiteralsAndSameType(node) { + return node.left.type === "Literal" && node.right.type === "Literal" && + typeof node.left.value === typeof node.right.value; + } - /** - * Gets the location (line and column) of the binary expression's operator - * @param {ASTNode} node The binary expression node to check - * @param {String} operator The operator to find - * @returns {Object} { line, column } location of operator - * @private - */ - function getOperatorLocation(node) { - var opToken = context.getTokenAfter(node.left); - - return {line: opToken.loc.start.line, column: opToken.loc.start.column}; - } + /** + * Checks if one of the operands is a literal null + * @param {ASTNode} node The node to check + * @returns {boolean} if operands are null + * @private + */ + function isNullCheck(node) { + return (node.right.type === "Literal" && node.right.value === null) || + (node.left.type === "Literal" && node.left.value === null); + } - return { - "BinaryExpression": function(node) { - if (node.operator !== "==" && node.operator !== "!=") { - return; - } + /** + * Gets the location (line and column) of the binary expression's operator + * @param {ASTNode} node The binary expression node to check + * @param {String} operator The operator to find + * @returns {Object} { line, column } location of operator + * @private + */ + function getOperatorLocation(node) { + var opToken = context.getTokenAfter(node.left); + + return {line: opToken.loc.start.line, column: opToken.loc.start.column}; + } - if (context.options[0] === "smart" && (isTypeOfBinary(node) || - areLiteralsAndSameType(node) || isNullCheck(node))) { - return; - } + return { + BinaryExpression: function(node) { + if (node.operator !== "==" && node.operator !== "!=") { + return; + } - if (context.options[0] === "allow-null" && isNullCheck(node)) { - return; - } + if (context.options[0] === "smart" && (isTypeOfBinary(node) || + areLiteralsAndSameType(node) || isNullCheck(node))) { + return; + } - context.report({ - node: node, - loc: getOperatorLocation(node), - message: "Expected '{{op}}=' and instead saw '{{op}}'.", - data: { op: node.operator } - }); + if (context.options[0] === "allow-null" && isNullCheck(node)) { + return; + } - } - }; + context.report({ + node: node, + loc: getOperatorLocation(node), + message: "Expected '{{op}}=' and instead saw '{{op}}'.", + data: { op: node.operator } + }); -}; + } + }; -module.exports.schema = [ - { - "enum": ["smart", "allow-null"] } -]; +}; diff --git a/tools/eslint/lib/rules/func-names.js b/tools/eslint/lib/rules/func-names.js index a4fb59edd6333d..51a1ffe0468704 100644 --- a/tools/eslint/lib/rules/func-names.js +++ b/tools/eslint/lib/rules/func-names.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to warn when a function expression does not have a name. * @author Kyle T. Nunery - * @copyright 2015 Brandon Mills. All rights reserved. - * @copyright 2014 Kyle T. Nunery. All rights reserved. */ "use strict"; @@ -11,35 +9,45 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - /** - * Determines whether the current FunctionExpression node is a get, set, or - * shorthand method in an object literal or a class. - * @returns {boolean} True if the node is a get, set, or shorthand method. - */ - function isObjectOrClassMethod() { - var parent = context.getAncestors().pop(); - - return (parent.type === "MethodDefinition" || ( - parent.type === "Property" && ( - parent.method || - parent.kind === "get" || - parent.kind === "set" - ) - )); - } +module.exports = { + meta: { + docs: { + description: "enforce named `function` expressions", + category: "Stylistic Issues", + recommended: false + }, + + schema: [] + }, + + create: function(context) { + + /** + * Determines whether the current FunctionExpression node is a get, set, or + * shorthand method in an object literal or a class. + * @returns {boolean} True if the node is a get, set, or shorthand method. + */ + function isObjectOrClassMethod() { + var parent = context.getAncestors().pop(); + + return (parent.type === "MethodDefinition" || ( + parent.type === "Property" && ( + parent.method || + parent.kind === "get" || + parent.kind === "set" + ) + )); + } - return { - "FunctionExpression": function(node) { + return { + FunctionExpression: function(node) { - var name = node.id && node.id.name; + var name = node.id && node.id.name; - if (!name && !isObjectOrClassMethod()) { - context.report(node, "Missing function expression name."); + if (!name && !isObjectOrClassMethod()) { + context.report(node, "Missing function expression name."); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/func-style.js b/tools/eslint/lib/rules/func-style.js index 661c0157388b1f..9dad6c0755656d 100644 --- a/tools/eslint/lib/rules/func-style.js +++ b/tools/eslint/lib/rules/func-style.js @@ -1,7 +1,6 @@ /** * @fileoverview Rule to enforce a particular function style * @author Nicholas C. Zakas - * @copyright 2013 Nicholas C. Zakas. All rights reserved. */ "use strict"; @@ -9,76 +8,86 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "enforce the consistent use of either `function` declarations or expressions", + category: "Stylistic Issues", + recommended: false + }, + + schema: [ + { + enum: ["declaration", "expression"] + }, + { + type: "object", + properties: { + allowArrowFunctions: { + type: "boolean" + } + }, + additionalProperties: false + } + ] + }, - var style = context.options[0], - allowArrowFunctions = context.options[1] && context.options[1].allowArrowFunctions === true, - enforceDeclarations = (style === "declaration"), - stack = []; + create: function(context) { - var nodesToCheck = { - "Program": function() { + var style = context.options[0], + allowArrowFunctions = context.options[1] && context.options[1].allowArrowFunctions === true, + enforceDeclarations = (style === "declaration"), stack = []; - }, - "FunctionDeclaration": function(node) { - stack.push(false); + var nodesToCheck = { + Program: function() { + stack = []; + }, - if (!enforceDeclarations && node.parent.type !== "ExportDefaultDeclaration") { - context.report(node, "Expected a function expression."); - } - }, - "FunctionDeclaration:exit": function() { - stack.pop(); - }, + FunctionDeclaration: function(node) { + stack.push(false); - "FunctionExpression": function(node) { - stack.push(false); + if (!enforceDeclarations && node.parent.type !== "ExportDefaultDeclaration") { + context.report(node, "Expected a function expression."); + } + }, + "FunctionDeclaration:exit": function() { + stack.pop(); + }, - if (enforceDeclarations && node.parent.type === "VariableDeclarator") { - context.report(node.parent, "Expected a function declaration."); - } - }, - "FunctionExpression:exit": function() { - stack.pop(); - }, + FunctionExpression: function(node) { + stack.push(false); - "ThisExpression": function() { - if (stack.length > 0) { - stack[stack.length - 1] = true; - } - } - }; + if (enforceDeclarations && node.parent.type === "VariableDeclarator") { + context.report(node.parent, "Expected a function declaration."); + } + }, + "FunctionExpression:exit": function() { + stack.pop(); + }, - if (!allowArrowFunctions) { - nodesToCheck.ArrowFunctionExpression = function() { - stack.push(false); + ThisExpression: function() { + if (stack.length > 0) { + stack[stack.length - 1] = true; + } + } }; - nodesToCheck["ArrowFunctionExpression:exit"] = function(node) { - var hasThisExpr = stack.pop(); + if (!allowArrowFunctions) { + nodesToCheck.ArrowFunctionExpression = function() { + stack.push(false); + }; - if (enforceDeclarations && !hasThisExpr && node.parent.type === "VariableDeclarator") { - context.report(node.parent, "Expected a function declaration."); - } - }; - } + nodesToCheck["ArrowFunctionExpression:exit"] = function(node) { + var hasThisExpr = stack.pop(); - return nodesToCheck; + if (enforceDeclarations && !hasThisExpr && node.parent.type === "VariableDeclarator") { + context.report(node.parent, "Expected a function declaration."); + } + }; + } -}; + return nodesToCheck; -module.exports.schema = [ - { - "enum": ["declaration", "expression"] - }, - { - "type": "object", - "properties": { - "allowArrowFunctions": { - "type": "boolean" - } - }, - "additionalProperties": false } -]; +}; diff --git a/tools/eslint/lib/rules/generator-star-spacing.js b/tools/eslint/lib/rules/generator-star-spacing.js index 94f2ca1f6968e8..f05f9f4201b1eb 100644 --- a/tools/eslint/lib/rules/generator-star-spacing.js +++ b/tools/eslint/lib/rules/generator-star-spacing.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to check the spacing around the * in generator functions. * @author Jamund Ferguson - * @copyright 2015 Brandon Mills. All rights reserved. - * @copyright 2014 Jamund Ferguson. All rights reserved. */ "use strict"; @@ -11,102 +9,114 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "enforce consistent spacing around `*` operators in generator functions", + category: "ECMAScript 6", + recommended: false + }, - var mode = (function(option) { - if (!option || typeof option === "string") { - return { - before: { before: true, after: false }, - after: { before: false, after: true }, - both: { before: true, after: true }, - neither: { before: false, after: false } - }[option || "before"]; - } - return option; - }(context.options[0])); - - /** - * Checks the spacing between two tokens before or after the star token. - * @param {string} side Either "before" or "after". - * @param {Token} leftToken `function` keyword token if side is "before", or - * star token if side is "after". - * @param {Token} rightToken Star token if side is "before", or identifier - * token if side is "after". - * @returns {void} - */ - function checkSpacing(side, leftToken, rightToken) { - if (!!(rightToken.range[0] - leftToken.range[1]) !== mode[side]) { - var after = leftToken.value === "*"; - var spaceRequired = mode[side]; - var node = after ? leftToken : rightToken; - var type = spaceRequired ? "Missing" : "Unexpected"; - var message = type + " space " + side + " *."; - - context.report({ - node: node, - message: message, - fix: function(fixer) { - if (spaceRequired) { - if (after) { - return fixer.insertTextAfter(node, " "); - } - return fixer.insertTextBefore(node, " "); + fixable: "whitespace", + + schema: [ + { + oneOf: [ + { + enum: ["before", "after", "both", "neither"] + }, + { + type: "object", + properties: { + before: {type: "boolean"}, + after: {type: "boolean"} + }, + additionalProperties: false } - return fixer.removeRange([leftToken.range[1], rightToken.range[0]]); - } - }); - } - } + ] + } + ] + }, - /** - * Enforces the spacing around the star if node is a generator function. - * @param {ASTNode} node A function expression or declaration node. - * @returns {void} - */ - function checkFunction(node) { - var prevToken, starToken, nextToken; + create: function(context) { - if (!node.generator) { - return; - } + var mode = (function(option) { + if (!option || typeof option === "string") { + return { + before: { before: true, after: false }, + after: { before: false, after: true }, + both: { before: true, after: true }, + neither: { before: false, after: false } + }[option || "before"]; + } + return option; + }(context.options[0])); - if (node.parent.method || node.parent.type === "MethodDefinition") { - starToken = context.getTokenBefore(node, 1); - } else { - starToken = context.getFirstToken(node, 1); - } + /** + * Checks the spacing between two tokens before or after the star token. + * @param {string} side Either "before" or "after". + * @param {Token} leftToken `function` keyword token if side is "before", or + * star token if side is "after". + * @param {Token} rightToken Star token if side is "before", or identifier + * token if side is "after". + * @returns {void} + */ + function checkSpacing(side, leftToken, rightToken) { + if (!!(rightToken.range[0] - leftToken.range[1]) !== mode[side]) { + var after = leftToken.value === "*"; + var spaceRequired = mode[side]; + var node = after ? leftToken : rightToken; + var type = spaceRequired ? "Missing" : "Unexpected"; + var message = type + " space " + side + " *."; - // Only check before when preceded by `function` keyword - prevToken = context.getTokenBefore(starToken); - if (prevToken.value === "function" || prevToken.value === "static") { - checkSpacing("before", prevToken, starToken); + context.report({ + node: node, + message: message, + fix: function(fixer) { + if (spaceRequired) { + if (after) { + return fixer.insertTextAfter(node, " "); + } + return fixer.insertTextBefore(node, " "); + } + return fixer.removeRange([leftToken.range[1], rightToken.range[0]]); + } + }); + } } - nextToken = context.getTokenAfter(starToken); - checkSpacing("after", starToken, nextToken); - } + /** + * Enforces the spacing around the star if node is a generator function. + * @param {ASTNode} node A function expression or declaration node. + * @returns {void} + */ + function checkFunction(node) { + var prevToken, starToken, nextToken; - return { - "FunctionDeclaration": checkFunction, - "FunctionExpression": checkFunction - }; + if (!node.generator) { + return; + } -}; + if (node.parent.method || node.parent.type === "MethodDefinition") { + starToken = context.getTokenBefore(node, 1); + } else { + starToken = context.getFirstToken(node, 1); + } -module.exports.schema = [ - { - "oneOf": [ - { - "enum": ["before", "after", "both", "neither"] - }, - { - "type": "object", - "properties": { - "before": {"type": "boolean"}, - "after": {"type": "boolean"} - }, - "additionalProperties": false + // Only check before when preceded by `function` keyword + prevToken = context.getTokenBefore(starToken); + if (prevToken.value === "function" || prevToken.value === "static") { + checkSpacing("before", prevToken, starToken); } - ] + + nextToken = context.getTokenAfter(starToken); + checkSpacing("after", starToken, nextToken); + } + + return { + FunctionDeclaration: checkFunction, + FunctionExpression: checkFunction + }; + } -]; +}; diff --git a/tools/eslint/lib/rules/global-require.js b/tools/eslint/lib/rules/global-require.js index d6939644581deb..d1298719a9a80d 100644 --- a/tools/eslint/lib/rules/global-require.js +++ b/tools/eslint/lib/rules/global-require.js @@ -1,7 +1,6 @@ /** * @fileoverview Rule for disallowing require() outside of the top-level module context * @author Jamund Ferguson - * @copyright 2015 Jamund Ferguson. All rights reserved. */ "use strict"; @@ -49,22 +48,32 @@ function isShadowed(scope, node) { return reference && reference.resolved && reference.resolved.defs.length > 0; } -module.exports = function(context) { - return { - "CallExpression": function(node) { - var currentScope = context.getScope(), - isGoodRequire; +module.exports = { + meta: { + docs: { + description: "require `require()` calls to be placed at top-level module scope", + category: "Node.js and CommonJS", + recommended: false + }, - if (node.callee.name === "require" && !isShadowed(currentScope, node.callee)) { - isGoodRequire = context.getAncestors().every(function(parent) { - return ACCEPTABLE_PARENTS.indexOf(parent.type) > -1; - }); - if (!isGoodRequire) { - context.report(node, "Unexpected require()."); + schema: [] + }, + + create: function(context) { + return { + CallExpression: function(node) { + var currentScope = context.getScope(), + isGoodRequire; + + if (node.callee.name === "require" && !isShadowed(currentScope, node.callee)) { + isGoodRequire = context.getAncestors().every(function(parent) { + return ACCEPTABLE_PARENTS.indexOf(parent.type) > -1; + }); + if (!isGoodRequire) { + context.report(node, "Unexpected require()."); + } } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/guard-for-in.js b/tools/eslint/lib/rules/guard-for-in.js index 925e11817b0d15..b43dda39e46968 100644 --- a/tools/eslint/lib/rules/guard-for-in.js +++ b/tools/eslint/lib/rules/guard-for-in.js @@ -9,24 +9,34 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "require `for-in` loops to include an `if` statement", + category: "Best Practices", + recommended: false + }, - return { + schema: [] + }, - "ForInStatement": function(node) { + create: function(context) { - /* - * If the for-in statement has {}, then the real body is the body - * of the BlockStatement. Otherwise, just use body as provided. - */ - var body = node.body.type === "BlockStatement" ? node.body.body[0] : node.body; + return { - if (body && body.type !== "IfStatement") { - context.report(node, "The body of a for-in should be wrapped in an if statement to filter unwanted properties from the prototype."); + ForInStatement: function(node) { + + /* + * If the for-in statement has {}, then the real body is the body + * of the BlockStatement. Otherwise, just use body as provided. + */ + var body = node.body.type === "BlockStatement" ? node.body.body[0] : node.body; + + if (body && body.type !== "IfStatement") { + context.report(node, "The body of a for-in should be wrapped in an if statement to filter unwanted properties from the prototype."); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/handle-callback-err.js b/tools/eslint/lib/rules/handle-callback-err.js index 622288c99625af..09bf0da9771428 100644 --- a/tools/eslint/lib/rules/handle-callback-err.js +++ b/tools/eslint/lib/rules/handle-callback-err.js @@ -1,8 +1,6 @@ /** * @fileoverview Ensure handling of errors when we know they exist. * @author Jamund Ferguson - * @copyright 2015 Mathias Schreck. - * @copyright 2014 Jamund Ferguson. All rights reserved. */ "use strict"; @@ -11,73 +9,83 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "require error handling in callbacks", + category: "Node.js and CommonJS", + recommended: false + }, - var errorArgument = context.options[0] || "err"; + schema: [ + { + type: "string" + } + ] + }, - /** - * Checks if the given argument should be interpreted as a regexp pattern. - * @param {string} stringToCheck The string which should be checked. - * @returns {boolean} Whether or not the string should be interpreted as a pattern. - */ - function isPattern(stringToCheck) { - var firstChar = stringToCheck[0]; + create: function(context) { - return firstChar === "^"; - } + var errorArgument = context.options[0] || "err"; - /** - * Checks if the given name matches the configured error argument. - * @param {string} name The name which should be compared. - * @returns {boolean} Whether or not the given name matches the configured error variable name. - */ - function matchesConfiguredErrorName(name) { - if (isPattern(errorArgument)) { - var regexp = new RegExp(errorArgument); + /** + * Checks if the given argument should be interpreted as a regexp pattern. + * @param {string} stringToCheck The string which should be checked. + * @returns {boolean} Whether or not the string should be interpreted as a pattern. + */ + function isPattern(stringToCheck) { + var firstChar = stringToCheck[0]; - return regexp.test(name); + return firstChar === "^"; } - return name === errorArgument; - } - /** - * Get the parameters of a given function scope. - * @param {object} scope The function scope. - * @returns {array} All parameters of the given scope. - */ - function getParameters(scope) { - return scope.variables.filter(function(variable) { - return variable.defs[0] && variable.defs[0].type === "Parameter"; - }); - } + /** + * Checks if the given name matches the configured error argument. + * @param {string} name The name which should be compared. + * @returns {boolean} Whether or not the given name matches the configured error variable name. + */ + function matchesConfiguredErrorName(name) { + if (isPattern(errorArgument)) { + var regexp = new RegExp(errorArgument); - /** - * Check to see if we're handling the error object properly. - * @param {ASTNode} node The AST node to check. - * @returns {void} - */ - function checkForError(node) { - var scope = context.getScope(), - parameters = getParameters(scope), - firstParameter = parameters[0]; - - if (firstParameter && matchesConfiguredErrorName(firstParameter.name)) { - if (firstParameter.references.length === 0) { - context.report(node, "Expected error to be handled."); + return regexp.test(name); } + return name === errorArgument; } - } - return { - "FunctionDeclaration": checkForError, - "FunctionExpression": checkForError, - "ArrowFunctionExpression": checkForError - }; + /** + * Get the parameters of a given function scope. + * @param {object} scope The function scope. + * @returns {array} All parameters of the given scope. + */ + function getParameters(scope) { + return scope.variables.filter(function(variable) { + return variable.defs[0] && variable.defs[0].type === "Parameter"; + }); + } -}; + /** + * Check to see if we're handling the error object properly. + * @param {ASTNode} node The AST node to check. + * @returns {void} + */ + function checkForError(node) { + var scope = context.getScope(), + parameters = getParameters(scope), + firstParameter = parameters[0]; + + if (firstParameter && matchesConfiguredErrorName(firstParameter.name)) { + if (firstParameter.references.length === 0) { + context.report(node, "Expected error to be handled."); + } + } + } + + return { + FunctionDeclaration: checkForError, + FunctionExpression: checkForError, + ArrowFunctionExpression: checkForError + }; -module.exports.schema = [ - { - "type": "string" } -]; +}; diff --git a/tools/eslint/lib/rules/id-blacklist.js b/tools/eslint/lib/rules/id-blacklist.js index 42eaf53786ff7d..142d8d21f4bc63 100644 --- a/tools/eslint/lib/rules/id-blacklist.js +++ b/tools/eslint/lib/rules/id-blacklist.js @@ -1,11 +1,7 @@ /** * @fileoverview Rule that warns when identifier names that are - blacklisted in the configuration are used. + * blacklisted in the configuration are used. * @author Keith Cirkel (http://keithcirkel.co.uk) - * Based on id-match rule: - * @author Matthieu Larcher - * @copyright 2015 Matthieu Larcher. All rights reserved. - * See LICENSE in root directory for full license. */ "use strict"; @@ -14,97 +10,108 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- +module.exports = { + meta: { + docs: { + description: "disallow specified identifiers", + category: "Stylistic Issues", + recommended: false + }, + + schema: { + type: "array", + items: { + type: "string" + }, + uniqueItems: true + } + }, - var blacklist = context.options; + create: function(context) { - /** - * Checks if a string matches the provided pattern - * @param {String} name The string to check. - * @returns {boolean} if the string is a match - * @private - */ - function isInvalid(name) { - return blacklist.indexOf(name) !== -1; - } + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- - /** - * Verifies if we should report an error or not based on the effective - * parent node and the identifier name. - * @param {ASTNode} effectiveParent The effective parent node of the node to be reported - * @param {String} name The identifier name of the identifier node - * @returns {boolean} whether an error should be reported or not - */ - function shouldReport(effectiveParent, name) { - return effectiveParent.type !== "CallExpression" - && effectiveParent.type !== "NewExpression" && - isInvalid(name); - } + var blacklist = context.options; - /** - * Reports an AST node as a rule violation. - * @param {ASTNode} node The node to report. - * @returns {void} - * @private - */ - function report(node) { - context.report(node, "Identifier '{{name}}' is blacklisted", { - name: node.name - }); - } - return { + /** + * Checks if a string matches the provided pattern + * @param {String} name The string to check. + * @returns {boolean} if the string is a match + * @private + */ + function isInvalid(name) { + return blacklist.indexOf(name) !== -1; + } - "Identifier": function(node) { - var name = node.name, - effectiveParent = (node.parent.type === "MemberExpression") ? node.parent.parent : node.parent; + /** + * Verifies if we should report an error or not based on the effective + * parent node and the identifier name. + * @param {ASTNode} effectiveParent The effective parent node of the node to be reported + * @param {String} name The identifier name of the identifier node + * @returns {boolean} whether an error should be reported or not + */ + function shouldReport(effectiveParent, name) { + return effectiveParent.type !== "CallExpression" + && effectiveParent.type !== "NewExpression" && + isInvalid(name); + } - // MemberExpressions get special rules - if (node.parent.type === "MemberExpression") { + /** + * Reports an AST node as a rule violation. + * @param {ASTNode} node The node to report. + * @returns {void} + * @private + */ + function report(node) { + context.report(node, "Identifier '{{name}}' is blacklisted", { + name: node.name + }); + } - // Always check object names - if (node.parent.object.type === "Identifier" && - node.parent.object.name === node.name) { - if (isInvalid(name)) { - report(node); + return { + + Identifier: function(node) { + var name = node.name, + effectiveParent = (node.parent.type === "MemberExpression") ? node.parent.parent : node.parent; + + // MemberExpressions get special rules + if (node.parent.type === "MemberExpression") { + + // Always check object names + if (node.parent.object.type === "Identifier" && + node.parent.object.name === node.name) { + if (isInvalid(name)) { + report(node); + } + + // Report AssignmentExpressions only if they are the left side of the assignment + } else if (effectiveParent.type === "AssignmentExpression" && + (effectiveParent.right.type !== "MemberExpression" || + effectiveParent.left.type === "MemberExpression" && + effectiveParent.left.property.name === node.name)) { + if (isInvalid(name)) { + report(node); + } } - // Report AssignmentExpressions only if they are the left side of the assignment - } else if (effectiveParent.type === "AssignmentExpression" && - (effectiveParent.right.type !== "MemberExpression" || - effectiveParent.left.type === "MemberExpression" && - effectiveParent.left.property.name === node.name)) { - if (isInvalid(name)) { + // Properties have their own rules + } else if (node.parent.type === "Property") { + + if (shouldReport(effectiveParent, name)) { report(node); } - } - // Properties have their own rules - } else if (node.parent.type === "Property") { - - if (shouldReport(effectiveParent, name)) { + // Report anything that is a match and not a CallExpression + } else if (shouldReport(effectiveParent, name)) { report(node); } - - // Report anything that is a match and not a CallExpression - } else if (shouldReport(effectiveParent, name)) { - report(node); } - } - }; + }; -}; -module.exports.schema = { - "type": "array", - "items": { - "type": "string" - }, - "uniqueItems": true + } }; diff --git a/tools/eslint/lib/rules/id-length.js b/tools/eslint/lib/rules/id-length.js index 783ef55c39ced9..43437513acb480 100644 --- a/tools/eslint/lib/rules/id-length.js +++ b/tools/eslint/lib/rules/id-length.js @@ -1,9 +1,7 @@ /** * @fileoverview Rule that warns when identifier names are shorter or longer - * than the values provided in configuration. + * than the values provided in configuration. * @author Burak Yigit Kaya aka BYK - * @copyright 2015 Burak Yigit Kaya. All rights reserved. - * @copyright 2015 Mathieu M-Gosselin. All rights reserved. */ "use strict"; @@ -12,98 +10,105 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var options = context.options[0] || {}; - var minLength = typeof options.min !== "undefined" ? options.min : 2; - var maxLength = typeof options.max !== "undefined" ? options.max : Infinity; - var properties = options.properties !== "never"; - var exceptions = (options.exceptions ? options.exceptions : []) - .reduce(function(obj, item) { - obj[item] = true; +module.exports = { + meta: { + docs: { + description: "enforce minimum and maximum identifier lengths", + category: "Stylistic Issues", + recommended: false + }, - return obj; - }, {}); + schema: [ + { + type: "object", + properties: { + min: { + type: "number" + }, + max: { + type: "number" + }, + exceptions: { + type: "array", + uniqueItems: true, + items: { + type: "string" + } + }, + properties: { + enum: ["always", "never"] + } + }, + additionalProperties: false + } + ] + }, - var SUPPORTED_EXPRESSIONS = { - "MemberExpression": properties && function(parent) { - return !parent.computed && ( + create: function(context) { + var options = context.options[0] || {}; + var minLength = typeof options.min !== "undefined" ? options.min : 2; + var maxLength = typeof options.max !== "undefined" ? options.max : Infinity; + var properties = options.properties !== "never"; + var exceptions = (options.exceptions ? options.exceptions : []) + .reduce(function(obj, item) { + obj[item] = true; - // regular property assignment - parent.parent.left === parent || ( + return obj; + }, {}); - // or the last identifier in an ObjectPattern destructuring - parent.parent.type === "Property" && parent.parent.value === parent && - parent.parent.parent.type === "ObjectPattern" && parent.parent.parent.parent.left === parent.parent.parent - ) - ); - }, - "AssignmentPattern": function(parent, node) { - return parent.left === node; - }, - "VariableDeclarator": function(parent, node) { - return parent.id === node; - }, - "Property": properties && function(parent, node) { - return parent.key === node; - }, - "ImportDefaultSpecifier": true, - "RestElement": true, - "FunctionExpression": true, - "ArrowFunctionExpression": true, - "ClassDeclaration": true, - "FunctionDeclaration": true, - "MethodDefinition": true, - "CatchClause": true - }; + var SUPPORTED_EXPRESSIONS = { + MemberExpression: properties && function(parent) { + return !parent.computed && ( - return { - Identifier: function(node) { - var name = node.name; - var parent = node.parent; + // regular property assignment + (parent.parent.left === parent || // or the last identifier in an ObjectPattern destructuring + parent.parent.type === "Property" && parent.parent.value === parent && + parent.parent.parent.type === "ObjectPattern" && parent.parent.parent.parent.left === parent.parent.parent) + ); + }, + AssignmentPattern: function(parent, node) { + return parent.left === node; + }, + VariableDeclarator: function(parent, node) { + return parent.id === node; + }, + Property: properties && function(parent, node) { + return parent.key === node; + }, + ImportDefaultSpecifier: true, + RestElement: true, + FunctionExpression: true, + ArrowFunctionExpression: true, + ClassDeclaration: true, + FunctionDeclaration: true, + MethodDefinition: true, + CatchClause: true + }; - var isShort = name.length < minLength; - var isLong = name.length > maxLength; + return { + Identifier: function(node) { + var name = node.name; + var parent = node.parent; - if (!(isShort || isLong) || exceptions[name]) { - return; // Nothing to report - } + var isShort = name.length < minLength; + var isLong = name.length > maxLength; - var isValidExpression = SUPPORTED_EXPRESSIONS[parent.type]; + if (!(isShort || isLong) || exceptions[name]) { + return; // Nothing to report + } - if (isValidExpression && (isValidExpression === true || isValidExpression(parent, node))) { - context.report( - node, - isShort ? - "Identifier name '{{name}}' is too short. (< {{min}})" : - "Identifier name '{{name}}' is too long. (> {{max}})", - { name: name, min: minLength, max: maxLength } - ); - } - } - }; -}; + var isValidExpression = SUPPORTED_EXPRESSIONS[parent.type]; -module.exports.schema = [ - { - "type": "object", - "properties": { - "min": { - "type": "number" - }, - "max": { - "type": "number" - }, - "exceptions": { - "type": "array", - "uniqueItems": true, - "items": { - "type": "string" + if (isValidExpression && (isValidExpression === true || isValidExpression(parent, node))) { + context.report( + node, + isShort ? + "Identifier name '{{name}}' is too short. (< {{min}})" : + "Identifier name '{{name}}' is too long. (> {{max}})", + { name: name, min: minLength, max: maxLength } + ); } - }, - "properties": { - "enum": ["always", "never"] } - }, - "additionalProperties": false + }; } -]; +}; diff --git a/tools/eslint/lib/rules/id-match.js b/tools/eslint/lib/rules/id-match.js index df6fe6c8015c56..4c9f4351088c57 100644 --- a/tools/eslint/lib/rules/id-match.js +++ b/tools/eslint/lib/rules/id-match.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to flag non-matching identifiers * @author Matthieu Larcher - * @copyright 2015 Matthieu Larcher. All rights reserved. - * See LICENSE in root directory for full license. */ "use strict"; @@ -11,121 +9,132 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "require identifiers to match a specified regular expression", + category: "Stylistic Issues", + recommended: false + }, + + schema: [ + { + type: "string" + }, + { + type: "object", + properties: { + properties: { + type: "boolean" + } + } + } + ] + }, - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- + create: function(context) { - var pattern = context.options[0] || "^.+$", - regexp = new RegExp(pattern); + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- - var options = context.options[1] || {}, - properties = options.properties; + var pattern = context.options[0] || "^.+$", + regexp = new RegExp(pattern); - // cast to boolean and default to false - properties = !!properties; + var options = context.options[1] || {}, + properties = !!options.properties, + onlyDeclarations = !!options.onlyDeclarations; + /** + * Checks if a string matches the provided pattern + * @param {String} name The string to check. + * @returns {boolean} if the string is a match + * @private + */ + function isInvalid(name) { + return !regexp.test(name); + } - /** - * Checks if a string matches the provided pattern - * @param {String} name The string to check. - * @returns {boolean} if the string is a match - * @private - */ - function isInvalid(name) { - return !regexp.test(name); - } + /** + * Verifies if we should report an error or not based on the effective + * parent node and the identifier name. + * @param {ASTNode} effectiveParent The effective parent node of the node to be reported + * @param {String} name The identifier name of the identifier node + * @returns {boolean} whether an error should be reported or not + */ + function shouldReport(effectiveParent, name) { + return effectiveParent.type !== "CallExpression" + && effectiveParent.type !== "NewExpression" && + isInvalid(name); + } - /** - * Verifies if we should report an error or not based on the effective - * parent node and the identifier name. - * @param {ASTNode} effectiveParent The effective parent node of the node to be reported - * @param {String} name The identifier name of the identifier node - * @returns {boolean} whether an error should be reported or not - */ - function shouldReport(effectiveParent, name) { - return effectiveParent.type !== "CallExpression" - && effectiveParent.type !== "NewExpression" && - isInvalid(name); - } + /** + * Reports an AST node as a rule violation. + * @param {ASTNode} node The node to report. + * @returns {void} + * @private + */ + function report(node) { + context.report(node, "Identifier '{{name}}' does not match the pattern '{{pattern}}'.", { + name: node.name, + pattern: pattern + }); + } - /** - * Reports an AST node as a rule violation. - * @param {ASTNode} node The node to report. - * @returns {void} - * @private - */ - function report(node) { - context.report(node, "Identifier '{{name}}' does not match the pattern '{{pattern}}'.", { - name: node.name, - pattern: pattern - }); - } + return { - return { + Identifier: function(node) { + var name = node.name, + parent = node.parent, + effectiveParent = (parent.type === "MemberExpression") ? parent.parent : parent; - "Identifier": function(node) { - var name = node.name, - effectiveParent = (node.parent.type === "MemberExpression") ? node.parent.parent : node.parent; + if (parent.type === "MemberExpression") { - // MemberExpressions get special rules - if (node.parent.type === "MemberExpression") { + if (!properties) { + return; + } - // return early if properties is false - if (!properties) { - return; - } + // Always check object names + if (parent.object.type === "Identifier" && + parent.object.name === name) { + if (isInvalid(name)) { + report(node); + } - // Always check object names - if (node.parent.object.type === "Identifier" && - node.parent.object.name === node.name) { - if (isInvalid(name)) { - report(node); + // Report AssignmentExpressions only if they are the left side of the assignment + } else if (effectiveParent.type === "AssignmentExpression" && + (effectiveParent.right.type !== "MemberExpression" || + effectiveParent.left.type === "MemberExpression" && + effectiveParent.left.property.name === name)) { + if (isInvalid(name)) { + report(node); + } } - // Report AssignmentExpressions only if they are the left side of the assignment - } else if (effectiveParent.type === "AssignmentExpression" && - (effectiveParent.right.type !== "MemberExpression" || - effectiveParent.left.type === "MemberExpression" && - effectiveParent.left.property.name === node.name)) { - if (isInvalid(name)) { + } else if (parent.type === "Property") { + + if (!properties || parent.key.name !== name) { + return; + } + + if (shouldReport(effectiveParent, name)) { report(node); } - } - // Properties have their own rules - } else if (node.parent.type === "Property") { + } else { + var isDeclaration = effectiveParent.type === "FunctionDeclaration" || effectiveParent.type === "VariableDeclarator"; - // return early if properties is false - if (!properties) { - return; - } + if (onlyDeclarations && !isDeclaration) { + return; + } - if (shouldReport(effectiveParent, name)) { - report(node); + if (shouldReport(effectiveParent, name)) { + report(node); + } } - - // Report anything that is a match and not a CallExpression - } else if (shouldReport(effectiveParent, name)) { - report(node); } - } - - }; -}; + }; -module.exports.schema = [ - { - "type": "string" - }, - { - "type": "object", - "properties": { - "properties": { - "type": "boolean" - } - } } -]; +}; diff --git a/tools/eslint/lib/rules/indent.js b/tools/eslint/lib/rules/indent.js index 24a6241f59dd6b..3e8f4b92e1849b 100644 --- a/tools/eslint/lib/rules/indent.js +++ b/tools/eslint/lib/rules/indent.js @@ -1,31 +1,10 @@ /** * @fileoverview This option sets a specific tab width for your code - + * * This rule has been ported and modified from nodeca. * @author Vitaly Puzrin * @author Gyandeep Singh - * @copyright 2015 Vitaly Puzrin. All rights reserved. - * @copyright 2015 Gyandeep Singh. All rights reserved. - Copyright (C) 2014 by Vitaly Puzrin - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ + */ "use strict"; @@ -35,742 +14,754 @@ var util = require("util"); var lodash = require("lodash"); -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "enforce consistent indentation", + category: "Stylistic Issues", + recommended: false + }, - var MESSAGE = "Expected indentation of {{needed}} {{type}} {{characters}} but found {{gotten}}."; - var DEFAULT_VARIABLE_INDENT = 1; + fixable: "whitespace", - var indentType = "space"; - var indentSize = 4; - var options = { - SwitchCase: 0, - VariableDeclarator: { - var: DEFAULT_VARIABLE_INDENT, - let: DEFAULT_VARIABLE_INDENT, - const: DEFAULT_VARIABLE_INDENT - } - }; - - if (context.options.length) { - if (context.options[0] === "tab") { - indentSize = 1; - indentType = "tab"; - } else /* istanbul ignore else : this will be caught by options validation */ if (typeof context.options[0] === "number") { - indentSize = context.options[0]; - indentType = "space"; - } + schema: [ + { + oneOf: [ + { + enum: ["tab"] + }, + { + type: "integer", + minimum: 0 + } + ] + }, + { + type: "object", + properties: { + SwitchCase: { + type: "integer", + minimum: 0 + }, + VariableDeclarator: { + oneOf: [ + { + type: "integer", + minimum: 0 + }, + { + type: "object", + properties: { + var: { + type: "integer", + minimum: 0 + }, + let: { + type: "integer", + minimum: 0 + }, + const: { + type: "integer", + minimum: 0 + } + } + } + ] + } + }, + additionalProperties: false + } + ] + }, + + create: function(context) { + + var MESSAGE = "Expected indentation of {{needed}} {{type}} {{characters}} but found {{gotten}}."; + var DEFAULT_VARIABLE_INDENT = 1; + + var indentType = "space"; + var indentSize = 4; + var options = { + SwitchCase: 0, + VariableDeclarator: { + var: DEFAULT_VARIABLE_INDENT, + let: DEFAULT_VARIABLE_INDENT, + const: DEFAULT_VARIABLE_INDENT + } + }; + + if (context.options.length) { + if (context.options[0] === "tab") { + indentSize = 1; + indentType = "tab"; + } else /* istanbul ignore else : this will be caught by options validation */ if (typeof context.options[0] === "number") { + indentSize = context.options[0]; + indentType = "space"; + } - if (context.options[1]) { - var opts = context.options[1]; + if (context.options[1]) { + var opts = context.options[1]; - options.SwitchCase = opts.SwitchCase || 0; - var variableDeclaratorRules = opts.VariableDeclarator; + options.SwitchCase = opts.SwitchCase || 0; + var variableDeclaratorRules = opts.VariableDeclarator; - if (typeof variableDeclaratorRules === "number") { - options.VariableDeclarator = { - var: variableDeclaratorRules, - let: variableDeclaratorRules, - const: variableDeclaratorRules - }; - } else if (typeof variableDeclaratorRules === "object") { - lodash.assign(options.VariableDeclarator, variableDeclaratorRules); + if (typeof variableDeclaratorRules === "number") { + options.VariableDeclarator = { + var: variableDeclaratorRules, + let: variableDeclaratorRules, + const: variableDeclaratorRules + }; + } else if (typeof variableDeclaratorRules === "object") { + lodash.assign(options.VariableDeclarator, variableDeclaratorRules); + } } } - } - var indentPattern = { - normal: indentType === "space" ? /^ +/ : /^\t+/, - excludeCommas: indentType === "space" ? /^[ ,]+/ : /^[\t,]+/ - }; - - var caseIndentStore = {}; - - /** - * Reports a given indent violation and properly pluralizes the message - * @param {ASTNode} node Node violating the indent rule - * @param {int} needed Expected indentation character count - * @param {int} gotten Indentation character count in the actual node/code - * @param {Object=} loc Error line and column location - * @param {boolean} isLastNodeCheck Is the error for last node check - * @returns {void} - */ - function report(node, needed, gotten, loc, isLastNodeCheck) { - var msgContext = { - needed: needed, - type: indentType, - characters: needed === 1 ? "character" : "characters", - gotten: gotten + var indentPattern = { + normal: indentType === "space" ? /^ +/ : /^\t+/, + excludeCommas: indentType === "space" ? /^[ ,]+/ : /^[\t,]+/ }; - var indentChar = indentType === "space" ? " " : "\t"; + + var caseIndentStore = {}; /** - * Responsible for fixing the indentation issue fix - * @returns {Function} function to be executed by the fixer - * @private + * Reports a given indent violation and properly pluralizes the message + * @param {ASTNode} node Node violating the indent rule + * @param {int} needed Expected indentation character count + * @param {int} gotten Indentation character count in the actual node/code + * @param {Object=} loc Error line and column location + * @param {boolean} isLastNodeCheck Is the error for last node check + * @returns {void} */ - function getFixerFunction() { - var rangeToFix = []; - - if (needed > gotten) { - var spaces = "" + new Array(needed - gotten + 1).join(indentChar); // replace with repeat in future + function report(node, needed, gotten, loc, isLastNodeCheck) { + var msgContext = { + needed: needed, + type: indentType, + characters: needed === 1 ? "character" : "characters", + gotten: gotten + }; + var indentChar = indentType === "space" ? " " : "\t"; + + /** + * Responsible for fixing the indentation issue fix + * @returns {Function} function to be executed by the fixer + * @private + */ + function getFixerFunction() { + var rangeToFix = []; + + if (needed > gotten) { + var spaces = "" + new Array(needed - gotten + 1).join(indentChar); // replace with repeat in future + + if (isLastNodeCheck === true) { + rangeToFix = [ + node.range[1] - 1, + node.range[1] - 1 + ]; + } else { + rangeToFix = [ + node.range[0], + node.range[0] + ]; + } - if (isLastNodeCheck === true) { - rangeToFix = [ - node.range[1] - 1, - node.range[1] - 1 - ]; + return function(fixer) { + return fixer.insertTextBeforeRange(rangeToFix, spaces); + }; } else { - rangeToFix = [ - node.range[0], - node.range[0] - ]; - } + if (isLastNodeCheck === true) { + rangeToFix = [ + node.range[1] - (gotten - needed) - 1, + node.range[1] - 1 + ]; + } else { + rangeToFix = [ + node.range[0] - (gotten - needed), + node.range[0] + ]; + } - return function(fixer) { - return fixer.insertTextBeforeRange(rangeToFix, spaces); - }; - } else { - if (isLastNodeCheck === true) { - rangeToFix = [ - node.range[1] - (gotten - needed) - 1, - node.range[1] - 1 - ]; - } else { - rangeToFix = [ - node.range[0] - (gotten - needed), - node.range[0] - ]; + return function(fixer) { + return fixer.removeRange(rangeToFix); + }; } + } - return function(fixer) { - return fixer.removeRange(rangeToFix); - }; + if (loc) { + context.report({ + node: node, + loc: loc, + message: MESSAGE, + data: msgContext, + fix: getFixerFunction() + }); + } else { + context.report({ + node: node, + message: MESSAGE, + data: msgContext, + fix: getFixerFunction() + }); } } - if (loc) { - context.report({ - node: node, - loc: loc, - message: MESSAGE, - data: msgContext, - fix: getFixerFunction() - }); - } else { - context.report({ - node: node, - message: MESSAGE, - data: msgContext, - fix: getFixerFunction() - }); + /** + * Get node indent + * @param {ASTNode|Token} node Node to examine + * @param {boolean} [byLastLine=false] get indent of node's last line + * @param {boolean} [excludeCommas=false] skip comma on start of line + * @returns {int} Indent + */ + function getNodeIndent(node, byLastLine, excludeCommas) { + var token = byLastLine ? context.getLastToken(node) : context.getFirstToken(node); + var src = context.getSource(token, token.loc.start.column); + var regExp = excludeCommas ? indentPattern.excludeCommas : indentPattern.normal; + var indent = regExp.exec(src); + + return indent ? indent[0].length : 0; } - } - /** - * Get node indent - * @param {ASTNode|Token} node Node to examine - * @param {boolean} [byLastLine=false] get indent of node's last line - * @param {boolean} [excludeCommas=false] skip comma on start of line - * @returns {int} Indent - */ - function getNodeIndent(node, byLastLine, excludeCommas) { - var token = byLastLine ? context.getLastToken(node) : context.getFirstToken(node); - var src = context.getSource(token, token.loc.start.column); - var regExp = excludeCommas ? indentPattern.excludeCommas : indentPattern.normal; - var indent = regExp.exec(src); - - return indent ? indent[0].length : 0; - } + /** + * Checks node is the first in its own start line. By default it looks by start line. + * @param {ASTNode} node The node to check + * @param {boolean} [byEndLocation=false] Lookup based on start position or end + * @returns {boolean} true if its the first in the its start line + */ + function isNodeFirstInLine(node, byEndLocation) { + var firstToken = byEndLocation === true ? context.getLastToken(node, 1) : context.getTokenBefore(node), + startLine = byEndLocation === true ? node.loc.end.line : node.loc.start.line, + endLine = firstToken ? firstToken.loc.end.line : -1; - /** - * Checks node is the first in its own start line. By default it looks by start line. - * @param {ASTNode} node The node to check - * @param {boolean} [byEndLocation=false] Lookup based on start position or end - * @returns {boolean} true if its the first in the its start line - */ - function isNodeFirstInLine(node, byEndLocation) { - var firstToken = byEndLocation === true ? context.getLastToken(node, 1) : context.getTokenBefore(node), - startLine = byEndLocation === true ? node.loc.end.line : node.loc.start.line, - endLine = firstToken ? firstToken.loc.end.line : -1; - - return startLine !== endLine; - } + return startLine !== endLine; + } - /** - * Check indent for node - * @param {ASTNode} node Node to check - * @param {int} indent needed indent - * @param {boolean} [excludeCommas=false] skip comma on start of line - * @returns {void} - */ - function checkNodeIndent(node, indent, excludeCommas) { - var nodeIndent = getNodeIndent(node, false, excludeCommas); - - if ( - node.type !== "ArrayExpression" && node.type !== "ObjectExpression" && - nodeIndent !== indent && isNodeFirstInLine(node) - ) { - report(node, indent, nodeIndent); + /** + * Check indent for node + * @param {ASTNode} node Node to check + * @param {int} indent needed indent + * @param {boolean} [excludeCommas=false] skip comma on start of line + * @returns {void} + */ + function checkNodeIndent(node, indent, excludeCommas) { + var nodeIndent = getNodeIndent(node, false, excludeCommas); + + if ( + node.type !== "ArrayExpression" && node.type !== "ObjectExpression" && + nodeIndent !== indent && isNodeFirstInLine(node) + ) { + report(node, indent, nodeIndent); + } } - } - /** - * Check indent for nodes list - * @param {ASTNode[]} nodes list of node objects - * @param {int} indent needed indent - * @param {boolean} [excludeCommas=false] skip comma on start of line - * @returns {void} - */ - function checkNodesIndent(nodes, indent, excludeCommas) { - nodes.forEach(function(node) { - if (node.type === "IfStatement" && node.alternate) { - var elseToken = context.getTokenBefore(node.alternate); - - checkNodeIndent(elseToken, indent, excludeCommas); - } - checkNodeIndent(node, indent, excludeCommas); - }); - } + /** + * Check indent for nodes list + * @param {ASTNode[]} nodes list of node objects + * @param {int} indent needed indent + * @param {boolean} [excludeCommas=false] skip comma on start of line + * @returns {void} + */ + function checkNodesIndent(nodes, indent, excludeCommas) { + nodes.forEach(function(node) { + if (node.type === "IfStatement" && node.alternate) { + var elseToken = context.getTokenBefore(node.alternate); - /** - * Check last node line indent this detects, that block closed correctly - * @param {ASTNode} node Node to examine - * @param {int} lastLineIndent needed indent - * @returns {void} - */ - function checkLastNodeLineIndent(node, lastLineIndent) { - var lastToken = context.getLastToken(node); - var endIndent = getNodeIndent(lastToken, true); - - if (endIndent !== lastLineIndent && isNodeFirstInLine(node, true)) { - report( - node, - lastLineIndent, - endIndent, - { line: lastToken.loc.start.line, column: lastToken.loc.start.column }, - true - ); + checkNodeIndent(elseToken, indent, excludeCommas); + } + checkNodeIndent(node, indent, excludeCommas); + }); } - } - /** - * Check first node line indent is correct - * @param {ASTNode} node Node to examine - * @param {int} firstLineIndent needed indent - * @returns {void} - */ - function checkFirstNodeLineIndent(node, firstLineIndent) { - var startIndent = getNodeIndent(node, false); - - if (startIndent !== firstLineIndent && isNodeFirstInLine(node)) { - report( - node, - firstLineIndent, - startIndent, - { line: node.loc.start.line, column: node.loc.start.column } - ); + /** + * Check last node line indent this detects, that block closed correctly + * @param {ASTNode} node Node to examine + * @param {int} lastLineIndent needed indent + * @returns {void} + */ + function checkLastNodeLineIndent(node, lastLineIndent) { + var lastToken = context.getLastToken(node); + var endIndent = getNodeIndent(lastToken, true); + + if (endIndent !== lastLineIndent && isNodeFirstInLine(node, true)) { + report( + node, + lastLineIndent, + endIndent, + { line: lastToken.loc.start.line, column: lastToken.loc.start.column }, + true + ); + } } - } - /** - * Returns the VariableDeclarator based on the current node - * if not present then return null - * @param {ASTNode} node node to examine - * @returns {ASTNode|void} if found then node otherwise null - */ - function getVariableDeclaratorNode(node) { - var parent = node.parent; - - while (parent.type !== "VariableDeclarator" && parent.type !== "Program") { - parent = parent.parent; + /** + * Check first node line indent is correct + * @param {ASTNode} node Node to examine + * @param {int} firstLineIndent needed indent + * @returns {void} + */ + function checkFirstNodeLineIndent(node, firstLineIndent) { + var startIndent = getNodeIndent(node, false); + + if (startIndent !== firstLineIndent && isNodeFirstInLine(node)) { + report( + node, + firstLineIndent, + startIndent, + { line: node.loc.start.line, column: node.loc.start.column } + ); + } } - return parent.type === "VariableDeclarator" ? parent : null; - } + /** + * Returns the VariableDeclarator based on the current node + * if not present then return null + * @param {ASTNode} node node to examine + * @returns {ASTNode|void} if found then node otherwise null + */ + function getVariableDeclaratorNode(node) { + var parent = node.parent; - /** - * Check to see if the node is part of the multi-line variable declaration. - * Also if its on the same line as the varNode - * @param {ASTNode} node node to check - * @param {ASTNode} varNode variable declaration node to check against - * @returns {boolean} True if all the above condition satisfy - */ - function isNodeInVarOnTop(node, varNode) { - return varNode && - varNode.parent.loc.start.line === node.loc.start.line && - varNode.parent.declarations.length > 1; - } + while (parent.type !== "VariableDeclarator" && parent.type !== "Program") { + parent = parent.parent; + } - /** - * Check to see if the argument before the callee node is multi-line and - * there should only be 1 argument before the callee node - * @param {ASTNode} node node to check - * @returns {boolean} True if arguments are multi-line - */ - function isArgBeforeCalleeNodeMultiline(node) { - var parent = node.parent; - - if (parent.arguments.length >= 2 && parent.arguments[1] === node) { - return parent.arguments[0].loc.end.line > parent.arguments[0].loc.start.line; + return parent.type === "VariableDeclarator" ? parent : null; } - return false; - } - - /** - * Check indent for function block content - * @param {ASTNode} node node to examine - * @returns {void} - */ - function checkIndentInFunctionBlock(node) { - - /* - * Search first caller in chain. - * Ex.: - * - * Models <- Identifier - * .User - * .find() - * .exec(function() { - * // function body - * }); - * - * Looks for 'Models' + /** + * Check to see if the node is part of the multi-line variable declaration. + * Also if its on the same line as the varNode + * @param {ASTNode} node node to check + * @param {ASTNode} varNode variable declaration node to check against + * @returns {boolean} True if all the above condition satisfy */ - var calleeNode = node.parent; // FunctionExpression - var indent; + function isNodeInVarOnTop(node, varNode) { + return varNode && + varNode.parent.loc.start.line === node.loc.start.line && + varNode.parent.declarations.length > 1; + } - if (calleeNode.parent && - (calleeNode.parent.type === "Property" || - calleeNode.parent.type === "ArrayExpression")) { + /** + * Check to see if the argument before the callee node is multi-line and + * there should only be 1 argument before the callee node + * @param {ASTNode} node node to check + * @returns {boolean} True if arguments are multi-line + */ + function isArgBeforeCalleeNodeMultiline(node) { + var parent = node.parent; - // If function is part of array or object, comma can be put at left - indent = getNodeIndent(calleeNode, false, false); - } else { + if (parent.arguments.length >= 2 && parent.arguments[1] === node) { + return parent.arguments[0].loc.end.line > parent.arguments[0].loc.start.line; + } - // If function is standalone, simple calculate indent - indent = getNodeIndent(calleeNode); + return false; } - if (calleeNode.parent.type === "CallExpression") { - var calleeParent = calleeNode.parent; - - if (calleeNode.type !== "FunctionExpression" && calleeNode.type !== "ArrowFunctionExpression") { - if (calleeParent && calleeParent.loc.start.line < node.loc.start.line) { - indent = getNodeIndent(calleeParent); - } + /** + * Check indent for function block content + * @param {ASTNode} node node to examine + * @returns {void} + */ + function checkIndentInFunctionBlock(node) { + + /* + * Search first caller in chain. + * Ex.: + * + * Models <- Identifier + * .User + * .find() + * .exec(function() { + * // function body + * }); + * + * Looks for 'Models' + */ + var calleeNode = node.parent; // FunctionExpression + var indent; + + if (calleeNode.parent && + (calleeNode.parent.type === "Property" || + calleeNode.parent.type === "ArrayExpression")) { + + // If function is part of array or object, comma can be put at left + indent = getNodeIndent(calleeNode, false, false); } else { - if (isArgBeforeCalleeNodeMultiline(calleeNode) && - calleeParent.callee.loc.start.line === calleeParent.callee.loc.end.line && - !isNodeFirstInLine(calleeNode)) { - indent = getNodeIndent(calleeParent); + + // If function is standalone, simple calculate indent + indent = getNodeIndent(calleeNode); + } + + if (calleeNode.parent.type === "CallExpression") { + var calleeParent = calleeNode.parent; + + if (calleeNode.type !== "FunctionExpression" && calleeNode.type !== "ArrowFunctionExpression") { + if (calleeParent && calleeParent.loc.start.line < node.loc.start.line) { + indent = getNodeIndent(calleeParent); + } + } else { + if (isArgBeforeCalleeNodeMultiline(calleeNode) && + calleeParent.callee.loc.start.line === calleeParent.callee.loc.end.line && + !isNodeFirstInLine(calleeNode)) { + indent = getNodeIndent(calleeParent); + } } } - } - // function body indent should be indent + indent size - indent += indentSize; + // function body indent should be indent + indent size + indent += indentSize; - // check if the node is inside a variable - var parentVarNode = getVariableDeclaratorNode(node); + // check if the node is inside a variable + var parentVarNode = getVariableDeclaratorNode(node); - if (parentVarNode && isNodeInVarOnTop(node, parentVarNode)) { - indent += indentSize * options.VariableDeclarator[parentVarNode.parent.kind]; - } + if (parentVarNode && isNodeInVarOnTop(node, parentVarNode)) { + indent += indentSize * options.VariableDeclarator[parentVarNode.parent.kind]; + } - if (node.body.length > 0) { - checkNodesIndent(node.body, indent); - } + if (node.body.length > 0) { + checkNodesIndent(node.body, indent); + } - checkLastNodeLineIndent(node, indent - indentSize); - } + checkLastNodeLineIndent(node, indent - indentSize); + } - /** - * Checks if the given node starts and ends on the same line - * @param {ASTNode} node The node to check - * @returns {boolean} Whether or not the block starts and ends on the same line. - */ - function isSingleLineNode(node) { - var lastToken = context.getLastToken(node), - startLine = node.loc.start.line, - endLine = lastToken.loc.end.line; + /** + * Checks if the given node starts and ends on the same line + * @param {ASTNode} node The node to check + * @returns {boolean} Whether or not the block starts and ends on the same line. + */ + function isSingleLineNode(node) { + var lastToken = context.getLastToken(node), + startLine = node.loc.start.line, + endLine = lastToken.loc.end.line; - return startLine === endLine; - } + return startLine === endLine; + } - /** - * Check to see if the first element inside an array is an object and on the same line as the node - * If the node is not an array then it will return false. - * @param {ASTNode} node node to check - * @returns {boolean} success/failure - */ - function isFirstArrayElementOnSameLine(node) { - if (node.type === "ArrayExpression" && node.elements[0]) { - return node.elements[0].loc.start.line === node.loc.start.line && node.elements[0].type === "ObjectExpression"; - } else { - return false; + /** + * Check to see if the first element inside an array is an object and on the same line as the node + * If the node is not an array then it will return false. + * @param {ASTNode} node node to check + * @returns {boolean} success/failure + */ + function isFirstArrayElementOnSameLine(node) { + if (node.type === "ArrayExpression" && node.elements[0]) { + return node.elements[0].loc.start.line === node.loc.start.line && node.elements[0].type === "ObjectExpression"; + } else { + return false; + } } - } - /** - * Check indent for array block content or object block content - * @param {ASTNode} node node to examine - * @returns {void} - */ - function checkIndentInArrayOrObjectBlock(node) { + /** + * Check indent for array block content or object block content + * @param {ASTNode} node node to examine + * @returns {void} + */ + function checkIndentInArrayOrObjectBlock(node) { - // Skip inline - if (isSingleLineNode(node)) { - return; - } + // Skip inline + if (isSingleLineNode(node)) { + return; + } - var elements = (node.type === "ArrayExpression") ? node.elements : node.properties; + var elements = (node.type === "ArrayExpression") ? node.elements : node.properties; - // filter out empty elements example would be [ , 2] so remove first element as espree considers it as null - elements = elements.filter(function(elem) { - return elem !== null; - }); + // filter out empty elements example would be [ , 2] so remove first element as espree considers it as null + elements = elements.filter(function(elem) { + return elem !== null; + }); - // Skip if first element is in same line with this node - if (elements.length > 0 && elements[0].loc.start.line === node.loc.start.line) { - return; - } + // Skip if first element is in same line with this node + if (elements.length > 0 && elements[0].loc.start.line === node.loc.start.line) { + return; + } - var nodeIndent; - var elementsIndent; - var parentVarNode = getVariableDeclaratorNode(node); + var nodeIndent; + var elementsIndent; + var parentVarNode = getVariableDeclaratorNode(node); - // TODO - come up with a better strategy in future - if (isNodeFirstInLine(node)) { - var parent = node.parent; - var effectiveParent = parent; + // TODO - come up with a better strategy in future + if (isNodeFirstInLine(node)) { + var parent = node.parent; + var effectiveParent = parent; - if (parent.type === "MemberExpression") { - if (isNodeFirstInLine(parent)) { - effectiveParent = parent.parent.parent; - } else { - effectiveParent = parent.parent; + if (parent.type === "MemberExpression") { + if (isNodeFirstInLine(parent)) { + effectiveParent = parent.parent.parent; + } else { + effectiveParent = parent.parent; + } } - } - nodeIndent = getNodeIndent(effectiveParent); - if (parentVarNode && parentVarNode.loc.start.line !== node.loc.start.line) { - if (parent.type !== "VariableDeclarator" || parentVarNode === parentVarNode.parent.declarations[0]) { - if (parent.type === "VariableDeclarator" && parentVarNode.loc.start.line === effectiveParent.loc.start.line) { - nodeIndent = nodeIndent + (indentSize * options.VariableDeclarator[parentVarNode.parent.kind]); - } else if ( - parent.type === "ObjectExpression" || - parent.type === "ArrayExpression" || - parent.type === "CallExpression" || - parent.type === "ArrowFunctionExpression" || - parent.type === "NewExpression" - ) { - nodeIndent = nodeIndent + indentSize; + nodeIndent = getNodeIndent(effectiveParent); + if (parentVarNode && parentVarNode.loc.start.line !== node.loc.start.line) { + if (parent.type !== "VariableDeclarator" || parentVarNode === parentVarNode.parent.declarations[0]) { + if (parent.type === "VariableDeclarator" && parentVarNode.loc.start.line === effectiveParent.loc.start.line) { + nodeIndent = nodeIndent + (indentSize * options.VariableDeclarator[parentVarNode.parent.kind]); + } else if ( + parent.type === "ObjectExpression" || + parent.type === "ArrayExpression" || + parent.type === "CallExpression" || + parent.type === "ArrowFunctionExpression" || + parent.type === "NewExpression" + ) { + nodeIndent = nodeIndent + indentSize; + } } + } else if (!parentVarNode && !isFirstArrayElementOnSameLine(parent) && effectiveParent.type !== "MemberExpression" && effectiveParent.type !== "ExpressionStatement" && effectiveParent.type !== "AssignmentExpression" && effectiveParent.type !== "Property") { + nodeIndent = nodeIndent + indentSize; } - } else if (!parentVarNode && !isFirstArrayElementOnSameLine(parent) && effectiveParent.type !== "MemberExpression" && effectiveParent.type !== "ExpressionStatement" && effectiveParent.type !== "AssignmentExpression" && effectiveParent.type !== "Property") { - nodeIndent = nodeIndent + indentSize; + + elementsIndent = nodeIndent + indentSize; + + checkFirstNodeLineIndent(node, nodeIndent); + } else { + nodeIndent = getNodeIndent(node); + elementsIndent = nodeIndent + indentSize; } - elementsIndent = nodeIndent + indentSize; + /* + * Check if the node is a multiple variable declaration; if so, then + * make sure indentation takes that into account. + */ + if (isNodeInVarOnTop(node, parentVarNode)) { + elementsIndent += indentSize * options.VariableDeclarator[parentVarNode.parent.kind]; + } - checkFirstNodeLineIndent(node, nodeIndent); - } else { - nodeIndent = getNodeIndent(node); - elementsIndent = nodeIndent + indentSize; + // Comma can be placed before property name + checkNodesIndent(elements, elementsIndent, true); + + if (elements.length > 0) { + + // Skip last block line check if last item in same line + if (elements[elements.length - 1].loc.end.line === node.loc.end.line) { + return; + } + } + + checkLastNodeLineIndent(node, elementsIndent - indentSize); } - /* - * Check if the node is a multiple variable declaration; if so, then - * make sure indentation takes that into account. + /** + * Check if the node or node body is a BlockStatement or not + * @param {ASTNode} node node to test + * @returns {boolean} True if it or its body is a block statement */ - if (isNodeInVarOnTop(node, parentVarNode)) { - elementsIndent += indentSize * options.VariableDeclarator[parentVarNode.parent.kind]; + function isNodeBodyBlock(node) { + return node.type === "BlockStatement" || node.type === "ClassBody" || (node.body && node.body.type === "BlockStatement") || + (node.consequent && node.consequent.type === "BlockStatement"); } - // Comma can be placed before property name - checkNodesIndent(elements, elementsIndent, true); - - if (elements.length > 0) { + /** + * Check indentation for blocks + * @param {ASTNode} node node to check + * @returns {void} + */ + function blockIndentationCheck(node) { - // Skip last block line check if last item in same line - if (elements[elements.length - 1].loc.end.line === node.loc.end.line) { + // Skip inline blocks + if (isSingleLineNode(node)) { return; } - } - checkLastNodeLineIndent(node, elementsIndent - indentSize); - } + if (node.parent && ( + node.parent.type === "FunctionExpression" || + node.parent.type === "FunctionDeclaration" || + node.parent.type === "ArrowFunctionExpression" + )) { + checkIndentInFunctionBlock(node); + return; + } - /** - * Check if the node or node body is a BlockStatement or not - * @param {ASTNode} node node to test - * @returns {boolean} True if it or its body is a block statement - */ - function isNodeBodyBlock(node) { - return node.type === "BlockStatement" || node.type === "ClassBody" || (node.body && node.body.type === "BlockStatement") || - (node.consequent && node.consequent.type === "BlockStatement"); - } + var indent; + var nodesToCheck = []; - /** - * Check indentation for blocks - * @param {ASTNode} node node to check - * @returns {void} - */ - function blockIndentationCheck(node) { + /* + * For this statements we should check indent from statement beginning, + * not from the beginning of the block. + */ + var statementsWithProperties = [ + "IfStatement", "WhileStatement", "ForStatement", "ForInStatement", "ForOfStatement", "DoWhileStatement", "ClassDeclaration" + ]; - // Skip inline blocks - if (isSingleLineNode(node)) { - return; - } + if (node.parent && statementsWithProperties.indexOf(node.parent.type) !== -1 && isNodeBodyBlock(node)) { + indent = getNodeIndent(node.parent); + } else { + indent = getNodeIndent(node); + } - if (node.parent && ( - node.parent.type === "FunctionExpression" || - node.parent.type === "FunctionDeclaration" || - node.parent.type === "ArrowFunctionExpression" - )) { - checkIndentInFunctionBlock(node); - return; - } + if (node.type === "IfStatement" && node.consequent.type !== "BlockStatement") { + nodesToCheck = [node.consequent]; + } else if (util.isArray(node.body)) { + nodesToCheck = node.body; + } else { + nodesToCheck = [node.body]; + } - var indent; - var nodesToCheck = []; + if (nodesToCheck.length > 0) { + checkNodesIndent(nodesToCheck, indent + indentSize); + } - /* - * For this statements we should check indent from statement beginning, - * not from the beginning of the block. - */ - var statementsWithProperties = [ - "IfStatement", "WhileStatement", "ForStatement", "ForInStatement", "ForOfStatement", "DoWhileStatement", "ClassDeclaration" - ]; - - if (node.parent && statementsWithProperties.indexOf(node.parent.type) !== -1 && isNodeBodyBlock(node)) { - indent = getNodeIndent(node.parent); - } else { - indent = getNodeIndent(node); + if (node.type === "BlockStatement") { + checkLastNodeLineIndent(node, indent); + } } - if (node.type === "IfStatement" && node.consequent.type !== "BlockStatement") { - nodesToCheck = [node.consequent]; - } else if (util.isArray(node.body)) { - nodesToCheck = node.body; - } else { - nodesToCheck = [node.body]; - } + /** + * Filter out the elements which are on the same line of each other or the node. + * basically have only 1 elements from each line except the variable declaration line. + * @param {ASTNode} node Variable declaration node + * @returns {ASTNode[]} Filtered elements + */ + function filterOutSameLineVars(node) { + return node.declarations.reduce(function(finalCollection, elem) { + var lastElem = finalCollection[finalCollection.length - 1]; - if (nodesToCheck.length > 0) { - checkNodesIndent(nodesToCheck, indent + indentSize); - } + if ((elem.loc.start.line !== node.loc.start.line && !lastElem) || + (lastElem && lastElem.loc.start.line !== elem.loc.start.line)) { + finalCollection.push(elem); + } - if (node.type === "BlockStatement") { - checkLastNodeLineIndent(node, indent); + return finalCollection; + }, []); } - } - /** - * Filter out the elements which are on the same line of each other or the node. - * basically have only 1 elements from each line except the variable declaration line. - * @param {ASTNode} node Variable declaration node - * @returns {ASTNode[]} Filtered elements - */ - function filterOutSameLineVars(node) { - return node.declarations.reduce(function(finalCollection, elem) { - var lastElem = finalCollection[finalCollection.length - 1]; + /** + * Check indentation for variable declarations + * @param {ASTNode} node node to examine + * @returns {void} + */ + function checkIndentInVariableDeclarations(node) { + var elements = filterOutSameLineVars(node); + var nodeIndent = getNodeIndent(node); + var lastElement = elements[elements.length - 1]; - if ((elem.loc.start.line !== node.loc.start.line && !lastElem) || - (lastElem && lastElem.loc.start.line !== elem.loc.start.line)) { - finalCollection.push(elem); - } + var elementsIndent = nodeIndent + indentSize * options.VariableDeclarator[node.kind]; - return finalCollection; - }, []); - } + // Comma can be placed before declaration + checkNodesIndent(elements, elementsIndent, true); - /** - * Check indentation for variable declarations - * @param {ASTNode} node node to examine - * @returns {void} - */ - function checkIndentInVariableDeclarations(node) { - var elements = filterOutSameLineVars(node); - var nodeIndent = getNodeIndent(node); - var lastElement = elements[elements.length - 1]; + // Only check the last line if there is any token after the last item + if (context.getLastToken(node).loc.end.line <= lastElement.loc.end.line) { + return; + } - var elementsIndent = nodeIndent + indentSize * options.VariableDeclarator[node.kind]; + var tokenBeforeLastElement = context.getTokenBefore(lastElement); - // Comma can be placed before declaration - checkNodesIndent(elements, elementsIndent, true); + if (tokenBeforeLastElement.value === ",") { - // Only check the last line if there is any token after the last item - if (context.getLastToken(node).loc.end.line <= lastElement.loc.end.line) { - return; + // Special case for comma-first syntax where the semicolon is indented + checkLastNodeLineIndent(node, getNodeIndent(tokenBeforeLastElement)); + } else { + checkLastNodeLineIndent(node, elementsIndent - indentSize); + } } - var tokenBeforeLastElement = context.getTokenBefore(lastElement); - - if (tokenBeforeLastElement.value === ",") { - - // Special case for comma-first syntax where the semicolon is indented - checkLastNodeLineIndent(node, getNodeIndent(tokenBeforeLastElement)); - } else { - checkLastNodeLineIndent(node, elementsIndent - indentSize); + /** + * Check and decide whether to check for indentation for blockless nodes + * Scenarios are for or while statements without braces around them + * @param {ASTNode} node node to examine + * @returns {void} + */ + function blockLessNodes(node) { + if (node.body.type !== "BlockStatement") { + blockIndentationCheck(node); + } } - } - /** - * Check and decide whether to check for indentation for blockless nodes - * Scenarios are for or while statements without braces around them - * @param {ASTNode} node node to examine - * @returns {void} - */ - function blockLessNodes(node) { - if (node.body.type !== "BlockStatement") { - blockIndentationCheck(node); - } - } + /** + * Returns the expected indentation for the case statement + * @param {ASTNode} node node to examine + * @param {int} [switchIndent] indent for switch statement + * @returns {int} indent size + */ + function expectedCaseIndent(node, switchIndent) { + var switchNode = (node.type === "SwitchStatement") ? node : node.parent; + var caseIndent; - /** - * Returns the expected indentation for the case statement - * @param {ASTNode} node node to examine - * @param {int} [switchIndent] indent for switch statement - * @returns {int} indent size - */ - function expectedCaseIndent(node, switchIndent) { - var switchNode = (node.type === "SwitchStatement") ? node : node.parent; - var caseIndent; - - if (caseIndentStore[switchNode.loc.start.line]) { - return caseIndentStore[switchNode.loc.start.line]; - } else { - if (typeof switchIndent === "undefined") { - switchIndent = getNodeIndent(switchNode); - } - - if (switchNode.cases.length > 0 && options.SwitchCase === 0) { - caseIndent = switchIndent; + if (caseIndentStore[switchNode.loc.start.line]) { + return caseIndentStore[switchNode.loc.start.line]; } else { - caseIndent = switchIndent + (indentSize * options.SwitchCase); - } - - caseIndentStore[switchNode.loc.start.line] = caseIndent; - return caseIndent; - } - } + if (typeof switchIndent === "undefined") { + switchIndent = getNodeIndent(switchNode); + } - return { - "Program": function(node) { - if (node.body.length > 0) { + if (switchNode.cases.length > 0 && options.SwitchCase === 0) { + caseIndent = switchIndent; + } else { + caseIndent = switchIndent + (indentSize * options.SwitchCase); + } - // Root nodes should have no indent - checkNodesIndent(node.body, getNodeIndent(node)); + caseIndentStore[switchNode.loc.start.line] = caseIndent; + return caseIndent; } - }, + } - "ClassBody": blockIndentationCheck, + return { + Program: function(node) { + if (node.body.length > 0) { - "BlockStatement": blockIndentationCheck, + // Root nodes should have no indent + checkNodesIndent(node.body, getNodeIndent(node)); + } + }, - "WhileStatement": blockLessNodes, + ClassBody: blockIndentationCheck, - "ForStatement": blockLessNodes, + BlockStatement: blockIndentationCheck, - "ForInStatement": blockLessNodes, + WhileStatement: blockLessNodes, - "ForOfStatement": blockLessNodes, + ForStatement: blockLessNodes, - "DoWhileStatement": blockLessNodes, + ForInStatement: blockLessNodes, - "IfStatement": function(node) { - if (node.consequent.type !== "BlockStatement" && node.consequent.loc.start.line > node.loc.start.line) { - blockIndentationCheck(node); - } - }, + ForOfStatement: blockLessNodes, - "VariableDeclaration": function(node) { - if (node.declarations[node.declarations.length - 1].loc.start.line > node.declarations[0].loc.start.line) { - checkIndentInVariableDeclarations(node); - } - }, + DoWhileStatement: blockLessNodes, - "ObjectExpression": function(node) { - checkIndentInArrayOrObjectBlock(node); - }, + IfStatement: function(node) { + if (node.consequent.type !== "BlockStatement" && node.consequent.loc.start.line > node.loc.start.line) { + blockIndentationCheck(node); + } + }, - "ArrayExpression": function(node) { - checkIndentInArrayOrObjectBlock(node); - }, + VariableDeclaration: function(node) { + if (node.declarations[node.declarations.length - 1].loc.start.line > node.declarations[0].loc.start.line) { + checkIndentInVariableDeclarations(node); + } + }, - "SwitchStatement": function(node) { + ObjectExpression: function(node) { + checkIndentInArrayOrObjectBlock(node); + }, - // Switch is not a 'BlockStatement' - var switchIndent = getNodeIndent(node); - var caseIndent = expectedCaseIndent(node, switchIndent); + ArrayExpression: function(node) { + checkIndentInArrayOrObjectBlock(node); + }, - checkNodesIndent(node.cases, caseIndent); + SwitchStatement: function(node) { + // Switch is not a 'BlockStatement' + var switchIndent = getNodeIndent(node); + var caseIndent = expectedCaseIndent(node, switchIndent); - checkLastNodeLineIndent(node, switchIndent); - }, + checkNodesIndent(node.cases, caseIndent); - "SwitchCase": function(node) { - // Skip inline cases - if (isSingleLineNode(node)) { - return; - } - var caseIndent = expectedCaseIndent(node); + checkLastNodeLineIndent(node, switchIndent); + }, - checkNodesIndent(node.consequent, caseIndent + indentSize); - } - }; + SwitchCase: function(node) { -}; + // Skip inline cases + if (isSingleLineNode(node)) { + return; + } + var caseIndent = expectedCaseIndent(node); -module.exports.schema = [ - { - "oneOf": [ - { - "enum": ["tab"] - }, - { - "type": "integer", - "minimum": 0 + checkNodesIndent(node.consequent, caseIndent + indentSize); } - ] - }, - { - "type": "object", - "properties": { - "SwitchCase": { - "type": "integer", - "minimum": 0 - }, - "VariableDeclarator": { - "oneOf": [ - { - "type": "integer", - "minimum": 0 - }, - { - "type": "object", - "properties": { - "var": { - "type": "integer", - "minimum": 0 - }, - "let": { - "type": "integer", - "minimum": 0 - }, - "const": { - "type": "integer", - "minimum": 0 - } - } - } - ] - } - }, - "additionalProperties": false + }; + } -]; +}; diff --git a/tools/eslint/lib/rules/init-declarations.js b/tools/eslint/lib/rules/init-declarations.js index 10fbf185c160c4..66b0a0aea43c1a 100644 --- a/tools/eslint/lib/rules/init-declarations.js +++ b/tools/eslint/lib/rules/init-declarations.js @@ -1,7 +1,6 @@ /** * @fileoverview A rule to control the style of variable initializations. * @author Colin Ihrig - * @copyright 2015 Colin Ihrig. All rights reserved. */ "use strict"; @@ -43,74 +42,84 @@ function isInitialized(node) { // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "require or disallow initialization in `var` declarations", + category: "Variables", + recommended: false + }, - var MODE_ALWAYS = "always", - MODE_NEVER = "never"; + schema: { + anyOf: [ + { + type: "array", + items: [ + { + enum: ["always"] + } + ], + minItems: 0, + maxItems: 1 + }, + { + type: "array", + items: [ + { + enum: ["never"] + }, + { + type: "object", + properties: { + ignoreForLoopInit: { + type: "boolean" + } + }, + additionalProperties: false + } + ], + minItems: 0, + maxItems: 2 + } + ] + } + }, - var mode = context.options[0] || MODE_ALWAYS; - var params = context.options[1] || {}; + create: function(context) { - //-------------------------------------------------------------------------- - // Public API - //-------------------------------------------------------------------------- + var MODE_ALWAYS = "always", + MODE_NEVER = "never"; - return { - "VariableDeclaration:exit": function(node) { + var mode = context.options[0] || MODE_ALWAYS; + var params = context.options[1] || {}; - var kind = node.kind, - declarations = node.declarations; + //-------------------------------------------------------------------------- + // Public API + //-------------------------------------------------------------------------- - for (var i = 0; i < declarations.length; ++i) { - var declaration = declarations[i], - id = declaration.id, - initialized = isInitialized(declaration), - isIgnoredForLoop = params.ignoreForLoopInit && isForLoop(node.parent); + return { + "VariableDeclaration:exit": function(node) { - if (id.type !== "Identifier") { - continue; - } + var kind = node.kind, + declarations = node.declarations; - if (mode === MODE_ALWAYS && !initialized) { - context.report(declaration, "Variable '" + id.name + "' should be initialized on declaration."); - } else if (mode === MODE_NEVER && kind !== "const" && initialized && !isIgnoredForLoop) { - context.report(declaration, "Variable '" + id.name + "' should not be initialized on declaration."); - } - } - } - }; -}; + for (var i = 0; i < declarations.length; ++i) { + var declaration = declarations[i], + id = declaration.id, + initialized = isInitialized(declaration), + isIgnoredForLoop = params.ignoreForLoopInit && isForLoop(node.parent); -module.exports.schema = { - "anyOf": [ - { - "type": "array", - "items": [ - { - "enum": ["always"] - } - ], - "minItems": 0, - "maxItems": 1 - }, - { - "type": "array", - "items": [ - { - "enum": ["never"] - }, - { - "type": "object", - "properties": { - "ignoreForLoopInit": { - "type": "boolean" - } - }, - "additionalProperties": false + if (id.type !== "Identifier") { + continue; + } + + if (mode === MODE_ALWAYS && !initialized) { + context.report(declaration, "Variable '" + id.name + "' should be initialized on declaration."); + } else if (mode === MODE_NEVER && kind !== "const" && initialized && !isIgnoredForLoop) { + context.report(declaration, "Variable '" + id.name + "' should not be initialized on declaration."); + } } - ], - "minItems": 0, - "maxItems": 2 - } - ] + } + }; + } }; diff --git a/tools/eslint/lib/rules/jsx-quotes.js b/tools/eslint/lib/rules/jsx-quotes.js index 486aa818622901..6b3a2efef7143c 100644 --- a/tools/eslint/lib/rules/jsx-quotes.js +++ b/tools/eslint/lib/rules/jsx-quotes.js @@ -1,7 +1,6 @@ /** * @fileoverview A rule to ensure consistent quotes used in jsx syntax. * @author Mathias Schreck - * @copyright 2015 Mathias Schreck */ "use strict"; @@ -37,39 +36,51 @@ var QUOTE_SETTINGS = { // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var quoteOption = context.options[0] || "prefer-double", - setting = QUOTE_SETTINGS[quoteOption]; +module.exports = { + meta: { + docs: { + description: "enforce the consistent use of either double or single quotes in JSX attributes", + category: "Stylistic Issues", + recommended: false + }, - /** - * Checks if the given string literal node uses the expected quotes - * @param {ASTNode} node - A string literal node. - * @returns {boolean} Whether or not the string literal used the expected quotes. - * @public - */ - function usesExpectedQuotes(node) { - return node.value.indexOf(setting.quote) !== -1 || astUtils.isSurroundedBy(node.raw, setting.quote); - } - - return { - "JSXAttribute": function(node) { - var attributeValue = node.value; + fixable: "whitespace", - if (attributeValue && astUtils.isStringLiteral(attributeValue) && !usesExpectedQuotes(attributeValue)) { - context.report({ - node: attributeValue, - message: "Unexpected usage of " + setting.description + ".", - fix: function(fixer) { - return fixer.replaceText(attributeValue, setting.convert(attributeValue.raw)); - } - }); + schema: [ + { + enum: [ "prefer-single", "prefer-double" ] } + ] + }, + + create: function(context) { + var quoteOption = context.options[0] || "prefer-double", + setting = QUOTE_SETTINGS[quoteOption]; + + /** + * Checks if the given string literal node uses the expected quotes + * @param {ASTNode} node - A string literal node. + * @returns {boolean} Whether or not the string literal used the expected quotes. + * @public + */ + function usesExpectedQuotes(node) { + return node.value.indexOf(setting.quote) !== -1 || astUtils.isSurroundedBy(node.raw, setting.quote); } - }; -}; -module.exports.schema = [ - { - "enum": [ "prefer-single", "prefer-double" ] + return { + JSXAttribute: function(node) { + var attributeValue = node.value; + + if (attributeValue && astUtils.isStringLiteral(attributeValue) && !usesExpectedQuotes(attributeValue)) { + context.report({ + node: attributeValue, + message: "Unexpected usage of " + setting.description + ".", + fix: function(fixer) { + return fixer.replaceText(attributeValue, setting.convert(attributeValue.raw)); + } + }); + } + } + }; } -]; +}; diff --git a/tools/eslint/lib/rules/key-spacing.js b/tools/eslint/lib/rules/key-spacing.js index c317e4a2c81156..1bc14aefec05ab 100644 --- a/tools/eslint/lib/rules/key-spacing.js +++ b/tools/eslint/lib/rules/key-spacing.js @@ -1,7 +1,6 @@ /** * @fileoverview Rule to specify spacing of object literal keys and values * @author Brandon Mills - * @copyright 2014 Brandon Mills. All rights reserved. */ "use strict"; @@ -111,332 +110,341 @@ var messages = { value: "{{error}} space before value for {{computed}}key '{{key}}'." }; -module.exports = function(context) { - - /** - * OPTIONS - * "key-spacing": [2, { - * beforeColon: false, - * afterColon: true, - * align: "colon" // Optional, or "value" - * } - */ - - var options = context.options[0] || {}, - multiLineOptions = initOptions({}, (options.multiLine || options)), - singleLineOptions = initOptions({}, (options.singleLine || options)); - - /** - * Determines if the given property is key-value property. - * @param {ASTNode} property Property node to check. - * @returns {Boolean} Whether the property is a key-value property. - */ - function isKeyValueProperty(property) { - return !( - property.method || - property.shorthand || - property.kind !== "init" || - property.type !== "Property" // Could be "ExperimentalSpreadProperty" or "SpreadProperty" - ); - } +module.exports = { + meta: { + docs: { + description: "enforce consistent spacing between keys and values in object literal properties", + category: "Stylistic Issues", + recommended: false + }, - /** - * Starting from the given a node (a property.key node here) looks forward - * until it finds the last token before a colon punctuator and returns it. - * @param {ASTNode} node The node to start looking from. - * @returns {ASTNode} The last token before a colon punctuator. - */ - function getLastTokenBeforeColon(node) { - var prevNode; - - while (node && (node.type !== "Punctuator" || node.value !== ":")) { - prevNode = node; - node = context.getTokenAfter(node); + schema: [{ + anyOf: [ + { + type: "object", + properties: { + align: { + enum: ["colon", "value"] + }, + mode: { + enum: ["strict", "minimum"] + }, + beforeColon: { + type: "boolean" + }, + afterColon: { + type: "boolean" + } + }, + additionalProperties: false + }, + { + type: "object", + properties: { + singleLine: { + type: "object", + properties: { + mode: { + enum: ["strict", "minimum"] + }, + beforeColon: { + type: "boolean" + }, + afterColon: { + type: "boolean" + } + }, + additionalProperties: false + }, + multiLine: { + type: "object", + properties: { + align: { + enum: ["colon", "value"] + }, + mode: { + enum: ["strict", "minimum"] + }, + beforeColon: { + type: "boolean" + }, + afterColon: { + type: "boolean" + } + }, + additionalProperties: false + } + }, + additionalProperties: false + } + ] + }] + }, + + create: function(context) { + + /** + * OPTIONS + * "key-spacing": [2, { + * beforeColon: false, + * afterColon: true, + * align: "colon" // Optional, or "value" + * } + */ + + var options = context.options[0] || {}, + multiLineOptions = initOptions({}, (options.multiLine || options)), + singleLineOptions = initOptions({}, (options.singleLine || options)); + + /** + * Determines if the given property is key-value property. + * @param {ASTNode} property Property node to check. + * @returns {Boolean} Whether the property is a key-value property. + */ + function isKeyValueProperty(property) { + return !( + (property.method || + property.shorthand || + property.kind !== "init" || property.type !== "Property") // Could be "ExperimentalSpreadProperty" or "SpreadProperty" + ); } - return prevNode; - } - - /** - * Starting from the given a node (a property.key node here) looks forward - * until it finds the colon punctuator and returns it. - * @param {ASTNode} node The node to start looking from. - * @returns {ASTNode} The colon punctuator. - */ - function getNextColon(node) { + /** + * Starting from the given a node (a property.key node here) looks forward + * until it finds the last token before a colon punctuator and returns it. + * @param {ASTNode} node The node to start looking from. + * @returns {ASTNode} The last token before a colon punctuator. + */ + function getLastTokenBeforeColon(node) { + var prevNode; + + while (node && (node.type !== "Punctuator" || node.value !== ":")) { + prevNode = node; + node = context.getTokenAfter(node); + } - while (node && (node.type !== "Punctuator" || node.value !== ":")) { - node = context.getTokenAfter(node); + return prevNode; } - return node; - } + /** + * Starting from the given a node (a property.key node here) looks forward + * until it finds the colon punctuator and returns it. + * @param {ASTNode} node The node to start looking from. + * @returns {ASTNode} The colon punctuator. + */ + function getNextColon(node) { - /** - * Gets an object literal property's key as the identifier name or string value. - * @param {ASTNode} property Property node whose key to retrieve. - * @returns {string} The property's key. - */ - function getKey(property) { - var key = property.key; + while (node && (node.type !== "Punctuator" || node.value !== ":")) { + node = context.getTokenAfter(node); + } - if (property.computed) { - return context.getSource().slice(key.range[0], key.range[1]); + return node; } - return property.key.name || property.key.value; - } + /** + * Gets an object literal property's key as the identifier name or string value. + * @param {ASTNode} property Property node whose key to retrieve. + * @returns {string} The property's key. + */ + function getKey(property) { + var key = property.key; - /** - * Reports an appropriately-formatted error if spacing is incorrect on one - * side of the colon. - * @param {ASTNode} property Key-value pair in an object literal. - * @param {string} side Side being verified - either "key" or "value". - * @param {string} whitespace Actual whitespace string. - * @param {int} expected Expected whitespace length. - * @param {string} mode Value of the mode as "strict" or "minimum" - * @returns {void} - */ - function report(property, side, whitespace, expected, mode) { - var diff = whitespace.length - expected, - key = property.key, - firstTokenAfterColon = context.getTokenAfter(getNextColon(key)), - location = side === "key" ? key.loc.start : firstTokenAfterColon.loc.start; - - if (( - diff && mode === "strict" || - diff < 0 && mode === "minimum" || - diff > 0 && !expected && mode === "minimum") && - !(expected && containsLineTerminator(whitespace)) - ) { - context.report(property[side], location, messages[side], { - error: diff > 0 ? "Extra" : "Missing", - computed: property.computed ? "computed " : "", - key: getKey(property) - }); + if (property.computed) { + return context.getSource().slice(key.range[0], key.range[1]); + } + + return property.key.name || property.key.value; } - } - /** - * Gets the number of characters in a key, including quotes around string - * keys and braces around computed property keys. - * @param {ASTNode} property Property of on object literal. - * @returns {int} Width of the key. - */ - function getKeyWidth(property) { - var startToken, endToken; + /** + * Reports an appropriately-formatted error if spacing is incorrect on one + * side of the colon. + * @param {ASTNode} property Key-value pair in an object literal. + * @param {string} side Side being verified - either "key" or "value". + * @param {string} whitespace Actual whitespace string. + * @param {int} expected Expected whitespace length. + * @param {string} mode Value of the mode as "strict" or "minimum" + * @returns {void} + */ + function report(property, side, whitespace, expected, mode) { + var diff = whitespace.length - expected, + key = property.key, + firstTokenAfterColon = context.getTokenAfter(getNextColon(key)), + location = side === "key" ? key.loc.start : firstTokenAfterColon.loc.start; + + if (( + diff && mode === "strict" || + diff < 0 && mode === "minimum" || + diff > 0 && !expected && mode === "minimum") && + !(expected && containsLineTerminator(whitespace)) + ) { + context.report(property[side], location, messages[side], { + error: diff > 0 ? "Extra" : "Missing", + computed: property.computed ? "computed " : "", + key: getKey(property) + }); + } + } - startToken = context.getFirstToken(property); - endToken = getLastTokenBeforeColon(property.key); + /** + * Gets the number of characters in a key, including quotes around string + * keys and braces around computed property keys. + * @param {ASTNode} property Property of on object literal. + * @returns {int} Width of the key. + */ + function getKeyWidth(property) { + var startToken, endToken; - return endToken.range[1] - startToken.range[0]; - } + startToken = context.getFirstToken(property); + endToken = getLastTokenBeforeColon(property.key); - /** - * Gets the whitespace around the colon in an object literal property. - * @param {ASTNode} property Property node from an object literal. - * @returns {Object} Whitespace before and after the property's colon. - */ - function getPropertyWhitespace(property) { - var whitespace = /(\s*):(\s*)/.exec(context.getSource().slice( - property.key.range[1], property.value.range[0] - )); - - if (whitespace) { - return { - beforeColon: whitespace[1], - afterColon: whitespace[2] - }; + return endToken.range[1] - startToken.range[0]; } - return null; - } - /** - * Creates groups of properties. - * @param {ASTNode} node ObjectExpression node being evaluated. - * @returns {Array.} Groups of property AST node lists. - */ - function createGroups(node) { - if (node.properties.length === 1) { - return [node.properties]; + /** + * Gets the whitespace around the colon in an object literal property. + * @param {ASTNode} property Property node from an object literal. + * @returns {Object} Whitespace before and after the property's colon. + */ + function getPropertyWhitespace(property) { + var whitespace = /(\s*):(\s*)/.exec(context.getSource().slice( + property.key.range[1], property.value.range[0] + )); + + if (whitespace) { + return { + beforeColon: whitespace[1], + afterColon: whitespace[2] + }; + } + return null; } - return node.properties.reduce(function(groups, property) { - var currentGroup = last(groups), - prev = last(currentGroup); - - if (!prev || continuesPropertyGroup(prev, property)) { - currentGroup.push(property); - } else { - groups.push([property]); + /** + * Creates groups of properties. + * @param {ASTNode} node ObjectExpression node being evaluated. + * @returns {Array.} Groups of property AST node lists. + */ + function createGroups(node) { + if (node.properties.length === 1) { + return [node.properties]; } - return groups; - }, [ - [] - ]); - } + return node.properties.reduce(function(groups, property) { + var currentGroup = last(groups), + prev = last(currentGroup); - /** - * Verifies correct vertical alignment of a group of properties. - * @param {ASTNode[]} properties List of Property AST nodes. - * @returns {void} - */ - function verifyGroupAlignment(properties) { - var length = properties.length, - widths = properties.map(getKeyWidth), // Width of keys, including quotes - targetWidth = Math.max.apply(null, widths), - i, property, whitespace, width, - align = multiLineOptions.align, - beforeColon = multiLineOptions.beforeColon, - afterColon = multiLineOptions.afterColon, - mode = multiLineOptions.mode; - - // Conditionally include one space before or after colon - targetWidth += (align === "colon" ? beforeColon : afterColon); - - for (i = 0; i < length; i++) { - property = properties[i]; - whitespace = getPropertyWhitespace(property); - if (whitespace) { // Object literal getters/setters lack a colon - width = widths[i]; - - if (align === "value") { - report(property, "key", whitespace.beforeColon, beforeColon, mode); - report(property, "value", whitespace.afterColon, targetWidth - width, mode); - } else { // align = "colon" - report(property, "key", whitespace.beforeColon, targetWidth - width, mode); - report(property, "value", whitespace.afterColon, afterColon, mode); + if (!prev || continuesPropertyGroup(prev, property)) { + currentGroup.push(property); + } else { + groups.push([property]); + } + + return groups; + }, [ + [] + ]); + } + + /** + * Verifies correct vertical alignment of a group of properties. + * @param {ASTNode[]} properties List of Property AST nodes. + * @returns {void} + */ + function verifyGroupAlignment(properties) { + var length = properties.length, + widths = properties.map(getKeyWidth), // Width of keys, including quotes + targetWidth = Math.max.apply(null, widths), + i, property, whitespace, width, + align = multiLineOptions.align, + beforeColon = multiLineOptions.beforeColon, + afterColon = multiLineOptions.afterColon, + mode = multiLineOptions.mode; + + // Conditionally include one space before or after colon + targetWidth += (align === "colon" ? beforeColon : afterColon); + + for (i = 0; i < length; i++) { + property = properties[i]; + whitespace = getPropertyWhitespace(property); + if (whitespace) { // Object literal getters/setters lack a colon + width = widths[i]; + + if (align === "value") { + report(property, "key", whitespace.beforeColon, beforeColon, mode); + report(property, "value", whitespace.afterColon, targetWidth - width, mode); + } else { // align = "colon" + report(property, "key", whitespace.beforeColon, targetWidth - width, mode); + report(property, "value", whitespace.afterColon, afterColon, mode); + } } } } - } - /** - * Verifies vertical alignment, taking into account groups of properties. - * @param {ASTNode} node ObjectExpression node being evaluated. - * @returns {void} - */ - function verifyAlignment(node) { - createGroups(node).forEach(function(group) { - verifyGroupAlignment(group.filter(isKeyValueProperty)); - }); - } + /** + * Verifies vertical alignment, taking into account groups of properties. + * @param {ASTNode} node ObjectExpression node being evaluated. + * @returns {void} + */ + function verifyAlignment(node) { + createGroups(node).forEach(function(group) { + verifyGroupAlignment(group.filter(isKeyValueProperty)); + }); + } - /** - * Verifies spacing of property conforms to specified options. - * @param {ASTNode} node Property node being evaluated. - * @param {Object} lineOptions Configured singleLine or multiLine options - * @returns {void} - */ - function verifySpacing(node, lineOptions) { - var actual = getPropertyWhitespace(node); - - if (actual) { // Object literal getters/setters lack colons - report(node, "key", actual.beforeColon, lineOptions.beforeColon, lineOptions.mode); - report(node, "value", actual.afterColon, lineOptions.afterColon, lineOptions.mode); + /** + * Verifies spacing of property conforms to specified options. + * @param {ASTNode} node Property node being evaluated. + * @param {Object} lineOptions Configured singleLine or multiLine options + * @returns {void} + */ + function verifySpacing(node, lineOptions) { + var actual = getPropertyWhitespace(node); + + if (actual) { // Object literal getters/setters lack colons + report(node, "key", actual.beforeColon, lineOptions.beforeColon, lineOptions.mode); + report(node, "value", actual.afterColon, lineOptions.afterColon, lineOptions.mode); + } } - } - /** - * Verifies spacing of each property in a list. - * @param {ASTNode[]} properties List of Property AST nodes. - * @returns {void} - */ - function verifyListSpacing(properties) { - var length = properties.length; + /** + * Verifies spacing of each property in a list. + * @param {ASTNode[]} properties List of Property AST nodes. + * @returns {void} + */ + function verifyListSpacing(properties) { + var length = properties.length; - for (var i = 0; i < length; i++) { - verifySpacing(properties[i], singleLineOptions); + for (var i = 0; i < length; i++) { + verifySpacing(properties[i], singleLineOptions); + } } - } - //-------------------------------------------------------------------------- - // Public API - //-------------------------------------------------------------------------- + //-------------------------------------------------------------------------- + // Public API + //-------------------------------------------------------------------------- - if (multiLineOptions.align) { // Verify vertical alignment + if (multiLineOptions.align) { // Verify vertical alignment - return { - "ObjectExpression": function(node) { - if (isSingleLine(node)) { - verifyListSpacing(node.properties.filter(isKeyValueProperty)); - } else { - verifyAlignment(node); + return { + ObjectExpression: function(node) { + if (isSingleLine(node)) { + verifyListSpacing(node.properties.filter(isKeyValueProperty)); + } else { + verifyAlignment(node); + } } - } - }; + }; - } else { // Obey beforeColon and afterColon in each property as configured + } else { // Obey beforeColon and afterColon in each property as configured - return { - "Property": function(node) { - verifySpacing(node, isSingleLine(node.parent) ? singleLineOptions : multiLineOptions); - } - }; + return { + Property: function(node) { + verifySpacing(node, isSingleLine(node.parent) ? singleLineOptions : multiLineOptions); + } + }; - } + } + } }; - -module.exports.schema = [{ - "anyOf": [ - { - "type": "object", - "properties": { - "align": { - "enum": ["colon", "value"] - }, - "mode": { - "enum": ["strict", "minimum"] - }, - "beforeColon": { - "type": "boolean" - }, - "afterColon": { - "type": "boolean" - } - }, - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "singleLine": { - "type": "object", - "properties": { - "mode": { - "enum": ["strict", "minimum"] - }, - "beforeColon": { - "type": "boolean" - }, - "afterColon": { - "type": "boolean" - } - }, - "additionalProperties": false - }, - "multiLine": { - "type": "object", - "properties": { - "align": { - "enum": ["colon", "value"] - }, - "mode": { - "enum": ["strict", "minimum"] - }, - "beforeColon": { - "type": "boolean" - }, - "afterColon": { - "type": "boolean" - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - } - ] -}]; diff --git a/tools/eslint/lib/rules/keyword-spacing.js b/tools/eslint/lib/rules/keyword-spacing.js index 2630b46f9684c2..f771029a581d44 100644 --- a/tools/eslint/lib/rules/keyword-spacing.js +++ b/tools/eslint/lib/rules/keyword-spacing.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to enforce spacing before and after keywords. * @author Toru Nagashima - * @copyright 2015 Toru Nagashima. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; @@ -65,470 +63,482 @@ function isCloseParenOfTemplate(token) { // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var sourceCode = context.getSourceCode(); - - /** - * Reports a given token if there are not space(s) before the token. - * - * @param {Token} token - A token to report. - * @param {RegExp|undefined} pattern - Optional. A pattern of the previous - * token to check. - * @returns {void} - */ - function expectSpaceBefore(token, pattern) { - pattern = pattern || PREV_TOKEN; - - var prevToken = sourceCode.getTokenBefore(token); - - if (prevToken && - (CHECK_TYPE.test(prevToken.type) || pattern.test(prevToken.value)) && - !isOpenParenOfTemplate(prevToken) && - astUtils.isTokenOnSameLine(prevToken, token) && - !sourceCode.isSpaceBetweenTokens(prevToken, token) - ) { - context.report({ - loc: token.loc.start, - message: "Expected space(s) before \"{{value}}\".", - data: token, - fix: function(fixer) { - return fixer.insertTextBefore(token, " "); - } - }); - } - } +module.exports = { + meta: { + docs: { + description: "enforce consistent spacing before and after keywords", + category: "Stylistic Issues", + recommended: false + }, - /** - * Reports a given token if there are space(s) before the token. - * - * @param {Token} token - A token to report. - * @param {RegExp|undefined} pattern - Optional. A pattern of the previous - * token to check. - * @returns {void} - */ - function unexpectSpaceBefore(token, pattern) { - pattern = pattern || PREV_TOKEN; - - var prevToken = sourceCode.getTokenBefore(token); - - if (prevToken && - (CHECK_TYPE.test(prevToken.type) || pattern.test(prevToken.value)) && - !isOpenParenOfTemplate(prevToken) && - astUtils.isTokenOnSameLine(prevToken, token) && - sourceCode.isSpaceBetweenTokens(prevToken, token) - ) { - context.report({ - loc: token.loc.start, - message: "Unexpected space(s) before \"{{value}}\".", - data: token, - fix: function(fixer) { - return fixer.removeRange([prevToken.range[1], token.range[0]]); - } - }); + fixable: "whitespace", + + schema: [ + { + type: "object", + properties: { + before: {type: "boolean"}, + after: {type: "boolean"}, + overrides: { + type: "object", + properties: KEYS.reduce(function(retv, key) { + retv[key] = { + type: "object", + properties: { + before: {type: "boolean"}, + after: {type: "boolean"} + }, + additionalProperties: false + }; + return retv; + }, {}), + additionalProperties: false + } + }, + additionalProperties: false + } + ] + }, + + create: function(context) { + var sourceCode = context.getSourceCode(); + + /** + * Reports a given token if there are not space(s) before the token. + * + * @param {Token} token - A token to report. + * @param {RegExp|undefined} pattern - Optional. A pattern of the previous + * token to check. + * @returns {void} + */ + function expectSpaceBefore(token, pattern) { + pattern = pattern || PREV_TOKEN; + + var prevToken = sourceCode.getTokenBefore(token); + + if (prevToken && + (CHECK_TYPE.test(prevToken.type) || pattern.test(prevToken.value)) && + !isOpenParenOfTemplate(prevToken) && + astUtils.isTokenOnSameLine(prevToken, token) && + !sourceCode.isSpaceBetweenTokens(prevToken, token) + ) { + context.report({ + loc: token.loc.start, + message: "Expected space(s) before \"{{value}}\".", + data: token, + fix: function(fixer) { + return fixer.insertTextBefore(token, " "); + } + }); + } } - } - /** - * Reports a given token if there are not space(s) after the token. - * - * @param {Token} token - A token to report. - * @param {RegExp|undefined} pattern - Optional. A pattern of the next - * token to check. - * @returns {void} - */ - function expectSpaceAfter(token, pattern) { - pattern = pattern || NEXT_TOKEN; - - var nextToken = sourceCode.getTokenAfter(token); - - if (nextToken && - (CHECK_TYPE.test(nextToken.type) || pattern.test(nextToken.value)) && - !isCloseParenOfTemplate(nextToken) && - astUtils.isTokenOnSameLine(token, nextToken) && - !sourceCode.isSpaceBetweenTokens(token, nextToken) - ) { - context.report({ - loc: token.loc.start, - message: "Expected space(s) after \"{{value}}\".", - data: token, - fix: function(fixer) { - return fixer.insertTextAfter(token, " "); - } - }); + /** + * Reports a given token if there are space(s) before the token. + * + * @param {Token} token - A token to report. + * @param {RegExp|undefined} pattern - Optional. A pattern of the previous + * token to check. + * @returns {void} + */ + function unexpectSpaceBefore(token, pattern) { + pattern = pattern || PREV_TOKEN; + + var prevToken = sourceCode.getTokenBefore(token); + + if (prevToken && + (CHECK_TYPE.test(prevToken.type) || pattern.test(prevToken.value)) && + !isOpenParenOfTemplate(prevToken) && + astUtils.isTokenOnSameLine(prevToken, token) && + sourceCode.isSpaceBetweenTokens(prevToken, token) + ) { + context.report({ + loc: token.loc.start, + message: "Unexpected space(s) before \"{{value}}\".", + data: token, + fix: function(fixer) { + return fixer.removeRange([prevToken.range[1], token.range[0]]); + } + }); + } } - } - /** - * Reports a given token if there are space(s) after the token. - * - * @param {Token} token - A token to report. - * @param {RegExp|undefined} pattern - Optional. A pattern of the next - * token to check. - * @returns {void} - */ - function unexpectSpaceAfter(token, pattern) { - pattern = pattern || NEXT_TOKEN; - - var nextToken = sourceCode.getTokenAfter(token); - - if (nextToken && - (CHECK_TYPE.test(nextToken.type) || pattern.test(nextToken.value)) && - !isCloseParenOfTemplate(nextToken) && - astUtils.isTokenOnSameLine(token, nextToken) && - sourceCode.isSpaceBetweenTokens(token, nextToken) - ) { - context.report({ - loc: token.loc.start, - message: "Unexpected space(s) after \"{{value}}\".", - data: token, - fix: function(fixer) { - return fixer.removeRange([token.range[1], nextToken.range[0]]); - } - }); + /** + * Reports a given token if there are not space(s) after the token. + * + * @param {Token} token - A token to report. + * @param {RegExp|undefined} pattern - Optional. A pattern of the next + * token to check. + * @returns {void} + */ + function expectSpaceAfter(token, pattern) { + pattern = pattern || NEXT_TOKEN; + + var nextToken = sourceCode.getTokenAfter(token); + + if (nextToken && + (CHECK_TYPE.test(nextToken.type) || pattern.test(nextToken.value)) && + !isCloseParenOfTemplate(nextToken) && + astUtils.isTokenOnSameLine(token, nextToken) && + !sourceCode.isSpaceBetweenTokens(token, nextToken) + ) { + context.report({ + loc: token.loc.start, + message: "Expected space(s) after \"{{value}}\".", + data: token, + fix: function(fixer) { + return fixer.insertTextAfter(token, " "); + } + }); + } } - } - /** - * Parses the option object and determines check methods for each keyword. - * - * @param {object|undefined} options - The option object to parse. - * @returns {object} - Normalized option object. - * Keys are keywords (there are for every keyword). - * Values are instances of `{"before": function, "after": function}`. - */ - function parseOptions(options) { - var before = !options || options.before !== false; - var after = !options || options.after !== false; - var defaultValue = { - before: before ? expectSpaceBefore : unexpectSpaceBefore, - after: after ? expectSpaceAfter : unexpectSpaceAfter - }; - var overrides = (options && options.overrides) || {}; - var retv = Object.create(null); - - for (var i = 0; i < KEYS.length; ++i) { - var key = KEYS[i]; - var override = overrides[key]; - - if (override) { - var thisBefore = ("before" in override) ? override.before : before; - var thisAfter = ("after" in override) ? override.after : after; - - retv[key] = { - before: thisBefore ? expectSpaceBefore : unexpectSpaceBefore, - after: thisAfter ? expectSpaceAfter : unexpectSpaceAfter - }; - } else { - retv[key] = defaultValue; + /** + * Reports a given token if there are space(s) after the token. + * + * @param {Token} token - A token to report. + * @param {RegExp|undefined} pattern - Optional. A pattern of the next + * token to check. + * @returns {void} + */ + function unexpectSpaceAfter(token, pattern) { + pattern = pattern || NEXT_TOKEN; + + var nextToken = sourceCode.getTokenAfter(token); + + if (nextToken && + (CHECK_TYPE.test(nextToken.type) || pattern.test(nextToken.value)) && + !isCloseParenOfTemplate(nextToken) && + astUtils.isTokenOnSameLine(token, nextToken) && + sourceCode.isSpaceBetweenTokens(token, nextToken) + ) { + context.report({ + loc: token.loc.start, + message: "Unexpected space(s) after \"{{value}}\".", + data: token, + fix: function(fixer) { + return fixer.removeRange([token.range[1], nextToken.range[0]]); + } + }); } } - return retv; - } + /** + * Parses the option object and determines check methods for each keyword. + * + * @param {object|undefined} options - The option object to parse. + * @returns {object} - Normalized option object. + * Keys are keywords (there are for every keyword). + * Values are instances of `{"before": function, "after": function}`. + */ + function parseOptions(options) { + var before = !options || options.before !== false; + var after = !options || options.after !== false; + var defaultValue = { + before: before ? expectSpaceBefore : unexpectSpaceBefore, + after: after ? expectSpaceAfter : unexpectSpaceAfter + }; + var overrides = (options && options.overrides) || {}; + var retv = Object.create(null); + + for (var i = 0; i < KEYS.length; ++i) { + var key = KEYS[i]; + var override = overrides[key]; + + if (override) { + var thisBefore = ("before" in override) ? override.before : before; + var thisAfter = ("after" in override) ? override.after : after; - var checkMethodMap = parseOptions(context.options[0]); - - /** - * Reports a given token if usage of spacing followed by the token is - * invalid. - * - * @param {Token} token - A token to report. - * @param {RegExp|undefined} pattern - Optional. A pattern of the previous - * token to check. - * @returns {void} - */ - function checkSpacingBefore(token, pattern) { - checkMethodMap[token.value].before(token, pattern); - } + retv[key] = { + before: thisBefore ? expectSpaceBefore : unexpectSpaceBefore, + after: thisAfter ? expectSpaceAfter : unexpectSpaceAfter + }; + } else { + retv[key] = defaultValue; + } + } - /** - * Reports a given token if usage of spacing preceded by the token is - * invalid. - * - * @param {Token} token - A token to report. - * @param {RegExp|undefined} pattern - Optional. A pattern of the next - * token to check. - * @returns {void} - */ - function checkSpacingAfter(token, pattern) { - checkMethodMap[token.value].after(token, pattern); - } + return retv; + } - /** - * Reports a given token if usage of spacing around the token is invalid. - * - * @param {Token} token - A token to report. - * @returns {void} - */ - function checkSpacingAround(token) { - checkSpacingBefore(token); - checkSpacingAfter(token); - } + var checkMethodMap = parseOptions(context.options[0]); + + /** + * Reports a given token if usage of spacing followed by the token is + * invalid. + * + * @param {Token} token - A token to report. + * @param {RegExp|undefined} pattern - Optional. A pattern of the previous + * token to check. + * @returns {void} + */ + function checkSpacingBefore(token, pattern) { + checkMethodMap[token.value].before(token, pattern); + } - /** - * Reports the first token of a given node if the first token is a keyword - * and usage of spacing around the token is invalid. - * - * @param {ASTNode|null} node - A node to report. - * @returns {void} - */ - function checkSpacingAroundFirstToken(node) { - var firstToken = node && sourceCode.getFirstToken(node); - - if (firstToken && firstToken.type === "Keyword") { - checkSpacingAround(firstToken); + /** + * Reports a given token if usage of spacing preceded by the token is + * invalid. + * + * @param {Token} token - A token to report. + * @param {RegExp|undefined} pattern - Optional. A pattern of the next + * token to check. + * @returns {void} + */ + function checkSpacingAfter(token, pattern) { + checkMethodMap[token.value].after(token, pattern); } - } - /** - * Reports the first token of a given node if the first token is a keyword - * and usage of spacing followed by the token is invalid. - * - * This is used for unary operators (e.g. `typeof`), `function`, and `super`. - * Other rules are handling usage of spacing preceded by those keywords. - * - * @param {ASTNode|null} node - A node to report. - * @returns {void} - */ - function checkSpacingBeforeFirstToken(node) { - var firstToken = node && sourceCode.getFirstToken(node); - - if (firstToken && firstToken.type === "Keyword") { - checkSpacingBefore(firstToken); + /** + * Reports a given token if usage of spacing around the token is invalid. + * + * @param {Token} token - A token to report. + * @returns {void} + */ + function checkSpacingAround(token) { + checkSpacingBefore(token); + checkSpacingAfter(token); } - } - /** - * Reports the previous token of a given node if the token is a keyword and - * usage of spacing around the token is invalid. - * - * @param {ASTNode|null} node - A node to report. - * @returns {void} - */ - function checkSpacingAroundTokenBefore(node) { - if (node) { - var token = sourceCode.getTokenBefore(node); - - while (token.type !== "Keyword") { - token = sourceCode.getTokenBefore(token); + /** + * Reports the first token of a given node if the first token is a keyword + * and usage of spacing around the token is invalid. + * + * @param {ASTNode|null} node - A node to report. + * @returns {void} + */ + function checkSpacingAroundFirstToken(node) { + var firstToken = node && sourceCode.getFirstToken(node); + + if (firstToken && firstToken.type === "Keyword") { + checkSpacingAround(firstToken); } - - checkSpacingAround(token); } - } - /** - * Reports `class` and `extends` keywords of a given node if usage of - * spacing around those keywords is invalid. - * - * @param {ASTNode} node - A node to report. - * @returns {void} - */ - function checkSpacingForClass(node) { - checkSpacingAroundFirstToken(node); - checkSpacingAroundTokenBefore(node.superClass); - } - - /** - * Reports `if` and `else` keywords of a given node if usage of spacing - * around those keywords is invalid. - * - * @param {ASTNode} node - A node to report. - * @returns {void} - */ - function checkSpacingForIfStatement(node) { - checkSpacingAroundFirstToken(node); - checkSpacingAroundTokenBefore(node.alternate); - } + /** + * Reports the first token of a given node if the first token is a keyword + * and usage of spacing followed by the token is invalid. + * + * This is used for unary operators (e.g. `typeof`), `function`, and `super`. + * Other rules are handling usage of spacing preceded by those keywords. + * + * @param {ASTNode|null} node - A node to report. + * @returns {void} + */ + function checkSpacingBeforeFirstToken(node) { + var firstToken = node && sourceCode.getFirstToken(node); + + if (firstToken && firstToken.type === "Keyword") { + checkSpacingBefore(firstToken); + } + } - /** - * Reports `try`, `catch`, and `finally` keywords of a given node if usage - * of spacing around those keywords is invalid. - * - * @param {ASTNode} node - A node to report. - * @returns {void} - */ - function checkSpacingForTryStatement(node) { - checkSpacingAroundFirstToken(node); - checkSpacingAroundFirstToken(node.handler); - checkSpacingAroundTokenBefore(node.finalizer); - } + /** + * Reports the previous token of a given node if the token is a keyword and + * usage of spacing around the token is invalid. + * + * @param {ASTNode|null} node - A node to report. + * @returns {void} + */ + function checkSpacingAroundTokenBefore(node) { + if (node) { + var token = sourceCode.getTokenBefore(node); + + while (token.type !== "Keyword") { + token = sourceCode.getTokenBefore(token); + } - /** - * Reports `do` and `while` keywords of a given node if usage of spacing - * around those keywords is invalid. - * - * @param {ASTNode} node - A node to report. - * @returns {void} - */ - function checkSpacingForDoWhileStatement(node) { - checkSpacingAroundFirstToken(node); - checkSpacingAroundTokenBefore(node.test); - } + checkSpacingAround(token); + } + } - /** - * Reports `for` and `in` keywords of a given node if usage of spacing - * around those keywords is invalid. - * - * @param {ASTNode} node - A node to report. - * @returns {void} - */ - function checkSpacingForForInStatement(node) { - checkSpacingAroundFirstToken(node); - checkSpacingAroundTokenBefore(node.right); - } + /** + * Reports `class` and `extends` keywords of a given node if usage of + * spacing around those keywords is invalid. + * + * @param {ASTNode} node - A node to report. + * @returns {void} + */ + function checkSpacingForClass(node) { + checkSpacingAroundFirstToken(node); + checkSpacingAroundTokenBefore(node.superClass); + } - /** - * Reports `for` and `of` keywords of a given node if usage of spacing - * around those keywords is invalid. - * - * @param {ASTNode} node - A node to report. - * @returns {void} - */ - function checkSpacingForForOfStatement(node) { - checkSpacingAroundFirstToken(node); - - // `of` is not a keyword token. - var token = sourceCode.getTokenBefore(node.right); - - while (token.value !== "of") { - token = sourceCode.getTokenBefore(token); + /** + * Reports `if` and `else` keywords of a given node if usage of spacing + * around those keywords is invalid. + * + * @param {ASTNode} node - A node to report. + * @returns {void} + */ + function checkSpacingForIfStatement(node) { + checkSpacingAroundFirstToken(node); + checkSpacingAroundTokenBefore(node.alternate); } - checkSpacingAround(token); - } - /** - * Reports `import`, `export`, `as`, and `from` keywords of a given node if - * usage of spacing around those keywords is invalid. - * - * This rule handles the `*` token in module declarations. - * - * import*as A from "./a"; /*error Expected space(s) after "import". - * error Expected space(s) before "as". - * - * @param {ASTNode} node - A node to report. - * @returns {void} - */ - function checkSpacingForModuleDeclaration(node) { - var firstToken = sourceCode.getFirstToken(node); - - checkSpacingBefore(firstToken, PREV_TOKEN_M); - checkSpacingAfter(firstToken, NEXT_TOKEN_M); - - if (node.source) { - var fromToken = sourceCode.getTokenBefore(node.source); - - checkSpacingBefore(fromToken, PREV_TOKEN_M); - checkSpacingAfter(fromToken, NEXT_TOKEN_M); + /** + * Reports `try`, `catch`, and `finally` keywords of a given node if usage + * of spacing around those keywords is invalid. + * + * @param {ASTNode} node - A node to report. + * @returns {void} + */ + function checkSpacingForTryStatement(node) { + checkSpacingAroundFirstToken(node); + checkSpacingAroundFirstToken(node.handler); + checkSpacingAroundTokenBefore(node.finalizer); } - } - /** - * Reports `as` keyword of a given node if usage of spacing around this - * keyword is invalid. - * - * @param {ASTNode} node - A node to report. - * @returns {void} - */ - function checkSpacingForImportNamespaceSpecifier(node) { - var asToken = sourceCode.getFirstToken(node, 1); - - checkSpacingBefore(asToken, PREV_TOKEN_M); - } + /** + * Reports `do` and `while` keywords of a given node if usage of spacing + * around those keywords is invalid. + * + * @param {ASTNode} node - A node to report. + * @returns {void} + */ + function checkSpacingForDoWhileStatement(node) { + checkSpacingAroundFirstToken(node); + checkSpacingAroundTokenBefore(node.test); + } - /** - * Reports `static`, `get`, and `set` keywords of a given node if usage of - * spacing around those keywords is invalid. - * - * @param {ASTNode} node - A node to report. - * @returns {void} - */ - function checkSpacingForProperty(node) { - if (node.static) { + /** + * Reports `for` and `in` keywords of a given node if usage of spacing + * around those keywords is invalid. + * + * @param {ASTNode} node - A node to report. + * @returns {void} + */ + function checkSpacingForForInStatement(node) { checkSpacingAroundFirstToken(node); + checkSpacingAroundTokenBefore(node.right); } - if (node.kind === "get" || node.kind === "set") { - var token = sourceCode.getFirstToken( - node, - node.static ? 1 : 0 - ); + /** + * Reports `for` and `of` keywords of a given node if usage of spacing + * around those keywords is invalid. + * + * @param {ASTNode} node - A node to report. + * @returns {void} + */ + function checkSpacingForForOfStatement(node) { + checkSpacingAroundFirstToken(node); + + // `of` is not a keyword token. + var token = sourceCode.getTokenBefore(node.right); + + while (token.value !== "of") { + token = sourceCode.getTokenBefore(token); + } checkSpacingAround(token); } - } - return { - - // Statements - DebuggerStatement: checkSpacingAroundFirstToken, - WithStatement: checkSpacingAroundFirstToken, - - // Statements - Control flow - BreakStatement: checkSpacingAroundFirstToken, - ContinueStatement: checkSpacingAroundFirstToken, - ReturnStatement: checkSpacingAroundFirstToken, - ThrowStatement: checkSpacingAroundFirstToken, - TryStatement: checkSpacingForTryStatement, - - // Statements - Choice - IfStatement: checkSpacingForIfStatement, - SwitchStatement: checkSpacingAroundFirstToken, - SwitchCase: checkSpacingAroundFirstToken, - - // Statements - Loops - DoWhileStatement: checkSpacingForDoWhileStatement, - ForInStatement: checkSpacingForForInStatement, - ForOfStatement: checkSpacingForForOfStatement, - ForStatement: checkSpacingAroundFirstToken, - WhileStatement: checkSpacingAroundFirstToken, - - // Statements - Declarations - ClassDeclaration: checkSpacingForClass, - ExportNamedDeclaration: checkSpacingForModuleDeclaration, - ExportDefaultDeclaration: checkSpacingAroundFirstToken, - ExportAllDeclaration: checkSpacingForModuleDeclaration, - FunctionDeclaration: checkSpacingBeforeFirstToken, - ImportDeclaration: checkSpacingForModuleDeclaration, - VariableDeclaration: checkSpacingAroundFirstToken, - - // Expressions - ClassExpression: checkSpacingForClass, - FunctionExpression: checkSpacingBeforeFirstToken, - NewExpression: checkSpacingBeforeFirstToken, - Super: checkSpacingBeforeFirstToken, - ThisExpression: checkSpacingBeforeFirstToken, - UnaryExpression: checkSpacingBeforeFirstToken, - YieldExpression: checkSpacingBeforeFirstToken, - - // Others - ImportNamespaceSpecifier: checkSpacingForImportNamespaceSpecifier, - MethodDefinition: checkSpacingForProperty, - Property: checkSpacingForProperty - }; -}; + /** + * Reports `import`, `export`, `as`, and `from` keywords of a given node if + * usage of spacing around those keywords is invalid. + * + * This rule handles the `*` token in module declarations. + * + * import*as A from "./a"; /*error Expected space(s) after "import". + * error Expected space(s) before "as". + * + * @param {ASTNode} node - A node to report. + * @returns {void} + */ + function checkSpacingForModuleDeclaration(node) { + var firstToken = sourceCode.getFirstToken(node); + + checkSpacingBefore(firstToken, PREV_TOKEN_M); + checkSpacingAfter(firstToken, NEXT_TOKEN_M); + + if (node.source) { + var fromToken = sourceCode.getTokenBefore(node.source); + + checkSpacingBefore(fromToken, PREV_TOKEN_M); + checkSpacingAfter(fromToken, NEXT_TOKEN_M); + } + } -module.exports.schema = [ - { - "type": "object", - "properties": { - "before": {"type": "boolean"}, - "after": {"type": "boolean"}, - "overrides": { - "type": "object", - "properties": KEYS.reduce(function(retv, key) { - retv[key] = { - "type": "object", - "properties": { - "before": {"type": "boolean"}, - "after": {"type": "boolean"} - }, - "additionalProperties": false - }; - return retv; - }, {}), - "additionalProperties": false + /** + * Reports `as` keyword of a given node if usage of spacing around this + * keyword is invalid. + * + * @param {ASTNode} node - A node to report. + * @returns {void} + */ + function checkSpacingForImportNamespaceSpecifier(node) { + var asToken = sourceCode.getFirstToken(node, 1); + + checkSpacingBefore(asToken, PREV_TOKEN_M); + } + + /** + * Reports `static`, `get`, and `set` keywords of a given node if usage of + * spacing around those keywords is invalid. + * + * @param {ASTNode} node - A node to report. + * @returns {void} + */ + function checkSpacingForProperty(node) { + if (node.static) { + checkSpacingAroundFirstToken(node); } - }, - "additionalProperties": false + if (node.kind === "get" || node.kind === "set") { + var token = sourceCode.getFirstToken( + node, + node.static ? 1 : 0 + ); + + checkSpacingAround(token); + } + } + + return { + + // Statements + DebuggerStatement: checkSpacingAroundFirstToken, + WithStatement: checkSpacingAroundFirstToken, + + // Statements - Control flow + BreakStatement: checkSpacingAroundFirstToken, + ContinueStatement: checkSpacingAroundFirstToken, + ReturnStatement: checkSpacingAroundFirstToken, + ThrowStatement: checkSpacingAroundFirstToken, + TryStatement: checkSpacingForTryStatement, + + // Statements - Choice + IfStatement: checkSpacingForIfStatement, + SwitchStatement: checkSpacingAroundFirstToken, + SwitchCase: checkSpacingAroundFirstToken, + + // Statements - Loops + DoWhileStatement: checkSpacingForDoWhileStatement, + ForInStatement: checkSpacingForForInStatement, + ForOfStatement: checkSpacingForForOfStatement, + ForStatement: checkSpacingAroundFirstToken, + WhileStatement: checkSpacingAroundFirstToken, + + // Statements - Declarations + ClassDeclaration: checkSpacingForClass, + ExportNamedDeclaration: checkSpacingForModuleDeclaration, + ExportDefaultDeclaration: checkSpacingAroundFirstToken, + ExportAllDeclaration: checkSpacingForModuleDeclaration, + FunctionDeclaration: checkSpacingBeforeFirstToken, + ImportDeclaration: checkSpacingForModuleDeclaration, + VariableDeclaration: checkSpacingAroundFirstToken, + + // Expressions + ClassExpression: checkSpacingForClass, + FunctionExpression: checkSpacingBeforeFirstToken, + NewExpression: checkSpacingBeforeFirstToken, + Super: checkSpacingBeforeFirstToken, + ThisExpression: checkSpacingBeforeFirstToken, + UnaryExpression: checkSpacingBeforeFirstToken, + YieldExpression: checkSpacingBeforeFirstToken, + + // Others + ImportNamespaceSpecifier: checkSpacingForImportNamespaceSpecifier, + MethodDefinition: checkSpacingForProperty, + Property: checkSpacingForProperty + }; } -]; +}; diff --git a/tools/eslint/lib/rules/linebreak-style.js b/tools/eslint/lib/rules/linebreak-style.js index 7643ea77109739..d99d7e58579c74 100644 --- a/tools/eslint/lib/rules/linebreak-style.js +++ b/tools/eslint/lib/rules/linebreak-style.js @@ -1,9 +1,6 @@ /** * @fileoverview Rule to enforce a single linebreak style. * @author Erik Mueller - * @copyright 2015 Varun Verma. All rights reserverd. - * @copyright 2015 James Whitney. All rights reserved. - * @copyright 2015 Erik Mueller. All rights reserved. */ "use strict"; @@ -12,69 +9,81 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "enforce consistent linebreak style", + category: "Stylistic Issues", + recommended: false + }, - var EXPECTED_LF_MSG = "Expected linebreaks to be 'LF' but found 'CRLF'.", - EXPECTED_CRLF_MSG = "Expected linebreaks to be 'CRLF' but found 'LF'."; + fixable: "whitespace", - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- + schema: [ + { + enum: ["unix", "windows"] + } + ] + }, - /** - * Builds a fix function that replaces text at the specified range in the source text. - * @param {int[]} range The range to replace - * @param {string} text The text to insert. - * @returns {function} Fixer function - * @private - */ - function createFix(range, text) { - return function(fixer) { - return fixer.replaceTextRange(range, text); - }; - } + create: function(context) { - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- + var EXPECTED_LF_MSG = "Expected linebreaks to be 'LF' but found 'CRLF'.", + EXPECTED_CRLF_MSG = "Expected linebreaks to be 'CRLF' but found 'LF'."; - return { - "Program": function checkForlinebreakStyle(node) { - var linebreakStyle = context.options[0] || "unix", - expectedLF = linebreakStyle === "unix", - expectedLFChars = expectedLF ? "\n" : "\r\n", - source = context.getSource(), - pattern = /\r\n|\r|\n|\u2028|\u2029/g, - match, - index, - range; + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- - var i = 0; + /** + * Builds a fix function that replaces text at the specified range in the source text. + * @param {int[]} range The range to replace + * @param {string} text The text to insert. + * @returns {function} Fixer function + * @private + */ + function createFix(range, text) { + return function(fixer) { + return fixer.replaceTextRange(range, text); + }; + } - while ((match = pattern.exec(source)) !== null) { - i++; - if (match[0] === expectedLFChars) { - continue; - } + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- - index = match.index; - range = [index, index + match[0].length]; - context.report({ - node: node, - loc: { - line: i, - column: context.getSourceLines()[i - 1].length - }, - message: expectedLF ? EXPECTED_LF_MSG : EXPECTED_CRLF_MSG, - fix: createFix(range, expectedLFChars) - }); - } - } - }; -}; + return { + Program: function checkForlinebreakStyle(node) { + var linebreakStyle = context.options[0] || "unix", + expectedLF = linebreakStyle === "unix", + expectedLFChars = expectedLF ? "\n" : "\r\n", + source = context.getSource(), + pattern = /\r\n|\r|\n|\u2028|\u2029/g, + match, + index, + range; + + var i = 0; -module.exports.schema = [ - { - "enum": ["unix", "windows"] + while ((match = pattern.exec(source)) !== null) { + i++; + if (match[0] === expectedLFChars) { + continue; + } + + index = match.index; + range = [index, index + match[0].length]; + context.report({ + node: node, + loc: { + line: i, + column: context.getSourceLines()[i - 1].length + }, + message: expectedLF ? EXPECTED_LF_MSG : EXPECTED_CRLF_MSG, + fix: createFix(range, expectedLFChars) + }); + } + } + }; } -]; +}; diff --git a/tools/eslint/lib/rules/lines-around-comment.js b/tools/eslint/lib/rules/lines-around-comment.js index 16d220c954241c..92fc3252ae9ff6 100644 --- a/tools/eslint/lib/rules/lines-around-comment.js +++ b/tools/eslint/lib/rules/lines-around-comment.js @@ -1,9 +1,6 @@ /** * @fileoverview Enforces empty lines around comments. * @author Jamund Ferguson - * @copyright 2015 Mathieu M-Gosselin. All rights reserved. - * @copyright 2015 Jamund Ferguson. All rights reserved. - * @copyright 2015 Gyandeep Singh. All rights reserved. */ "use strict"; @@ -68,272 +65,282 @@ function contains(val, array) { // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "require empty lines around comments", + category: "Stylistic Issues", + recommended: false + }, - var options = context.options[0] ? lodash.assign({}, context.options[0]) : {}; + schema: [ + { + type: "object", + properties: { + beforeBlockComment: { + type: "boolean" + }, + afterBlockComment: { + type: "boolean" + }, + beforeLineComment: { + type: "boolean" + }, + afterLineComment: { + type: "boolean" + }, + allowBlockStart: { + type: "boolean" + }, + allowBlockEnd: { + type: "boolean" + }, + allowObjectStart: { + type: "boolean" + }, + allowObjectEnd: { + type: "boolean" + }, + allowArrayStart: { + type: "boolean" + }, + allowArrayEnd: { + type: "boolean" + } + }, + additionalProperties: false + } + ] + }, - options.beforeLineComment = options.beforeLineComment || false; - options.afterLineComment = options.afterLineComment || false; - options.beforeBlockComment = typeof options.beforeBlockComment !== "undefined" ? options.beforeBlockComment : true; - options.afterBlockComment = options.afterBlockComment || false; - options.allowBlockStart = options.allowBlockStart || false; - options.allowBlockEnd = options.allowBlockEnd || false; + create: function(context) { - var sourceCode = context.getSourceCode(); + var options = context.options[0] ? lodash.assign({}, context.options[0]) : {}; - /** - * Returns whether or not comments are on lines starting with or ending with code - * @param {ASTNode} node The comment node to check. - * @returns {boolean} True if the comment is not alone. - */ - function codeAroundComment(node) { - var token; + options.beforeLineComment = options.beforeLineComment || false; + options.afterLineComment = options.afterLineComment || false; + options.beforeBlockComment = typeof options.beforeBlockComment !== "undefined" ? options.beforeBlockComment : true; + options.afterBlockComment = options.afterBlockComment || false; + options.allowBlockStart = options.allowBlockStart || false; + options.allowBlockEnd = options.allowBlockEnd || false; - token = node; - do { - token = sourceCode.getTokenOrCommentBefore(token); - } while (token && (token.type === "Block" || token.type === "Line")); + var sourceCode = context.getSourceCode(); - if (token && token.loc.end.line === node.loc.start.line) { - return true; - } + /** + * Returns whether or not comments are on lines starting with or ending with code + * @param {ASTNode} node The comment node to check. + * @returns {boolean} True if the comment is not alone. + */ + function codeAroundComment(node) { + var token; - token = node; - do { - token = sourceCode.getTokenOrCommentAfter(token); - } while (token && (token.type === "Block" || token.type === "Line")); + token = node; + do { + token = sourceCode.getTokenOrCommentBefore(token); + } while (token && (token.type === "Block" || token.type === "Line")); - if (token && token.loc.start.line === node.loc.end.line) { - return true; - } + if (token && token.loc.end.line === node.loc.start.line) { + return true; + } - return false; - } + token = node; + do { + token = sourceCode.getTokenOrCommentAfter(token); + } while (token && (token.type === "Block" || token.type === "Line")); - /** - * Returns whether or not comments are inside a node type or not. - * @param {ASTNode} node The Comment node. - * @param {ASTNode} parent The Comment parent node. - * @param {string} nodeType The parent type to check against. - * @returns {boolean} True if the comment is inside nodeType. - */ - function isCommentInsideNodeType(node, parent, nodeType) { - return parent.type === nodeType || - (parent.body && parent.body.type === nodeType) || - (parent.consequent && parent.consequent.type === nodeType); - } + if (token && token.loc.start.line === node.loc.end.line) { + return true; + } - /** - * Returns whether or not comments are at the parent start or not. - * @param {ASTNode} node The Comment node. - * @param {string} nodeType The parent type to check against. - * @returns {boolean} True if the comment is at parent start. - */ - function isCommentAtParentStart(node, nodeType) { - var ancestors = context.getAncestors(); - var parent; - - if (ancestors.length) { - parent = ancestors.pop(); + return false; } - return parent && isCommentInsideNodeType(node, parent, nodeType) && - node.loc.start.line - parent.loc.start.line === 1; - } - - /** - * Returns whether or not comments are at the parent end or not. - * @param {ASTNode} node The Comment node. - * @param {string} nodeType The parent type to check against. - * @returns {boolean} True if the comment is at parent end. - */ - function isCommentAtParentEnd(node, nodeType) { - var ancestors = context.getAncestors(); - var parent; - - if (ancestors.length) { - parent = ancestors.pop(); + /** + * Returns whether or not comments are inside a node type or not. + * @param {ASTNode} node The Comment node. + * @param {ASTNode} parent The Comment parent node. + * @param {string} nodeType The parent type to check against. + * @returns {boolean} True if the comment is inside nodeType. + */ + function isCommentInsideNodeType(node, parent, nodeType) { + return parent.type === nodeType || + (parent.body && parent.body.type === nodeType) || + (parent.consequent && parent.consequent.type === nodeType); } - return parent && isCommentInsideNodeType(node, parent, nodeType) && - parent.loc.end.line - node.loc.end.line === 1; - } - - /** - * Returns whether or not comments are at the block start or not. - * @param {ASTNode} node The Comment node. - * @returns {boolean} True if the comment is at block start. - */ - function isCommentAtBlockStart(node) { - return isCommentAtParentStart(node, "ClassBody") || isCommentAtParentStart(node, "BlockStatement") || isCommentAtParentStart(node, "SwitchCase"); - } - - /** - * Returns whether or not comments are at the block end or not. - * @param {ASTNode} node The Comment node. - * @returns {boolean} True if the comment is at block end. - */ - function isCommentAtBlockEnd(node) { - return isCommentAtParentEnd(node, "ClassBody") || isCommentAtParentEnd(node, "BlockStatement") || isCommentAtParentEnd(node, "SwitchCase") || isCommentAtParentEnd(node, "SwitchStatement"); - } - - /** - * Returns whether or not comments are at the object start or not. - * @param {ASTNode} node The Comment node. - * @returns {boolean} True if the comment is at object start. - */ - function isCommentAtObjectStart(node) { - return isCommentAtParentStart(node, "ObjectExpression") || isCommentAtParentStart(node, "ObjectPattern"); - } + /** + * Returns whether or not comments are at the parent start or not. + * @param {ASTNode} node The Comment node. + * @param {string} nodeType The parent type to check against. + * @returns {boolean} True if the comment is at parent start. + */ + function isCommentAtParentStart(node, nodeType) { + var ancestors = context.getAncestors(); + var parent; + + if (ancestors.length) { + parent = ancestors.pop(); + } - /** - * Returns whether or not comments are at the object end or not. - * @param {ASTNode} node The Comment node. - * @returns {boolean} True if the comment is at object end. - */ - function isCommentAtObjectEnd(node) { - return isCommentAtParentEnd(node, "ObjectExpression") || isCommentAtParentEnd(node, "ObjectPattern"); - } + return parent && isCommentInsideNodeType(node, parent, nodeType) && + node.loc.start.line - parent.loc.start.line === 1; + } - /** - * Returns whether or not comments are at the array start or not. - * @param {ASTNode} node The Comment node. - * @returns {boolean} True if the comment is at array start. - */ - function isCommentAtArrayStart(node) { - return isCommentAtParentStart(node, "ArrayExpression") || isCommentAtParentStart(node, "ArrayPattern"); - } + /** + * Returns whether or not comments are at the parent end or not. + * @param {ASTNode} node The Comment node. + * @param {string} nodeType The parent type to check against. + * @returns {boolean} True if the comment is at parent end. + */ + function isCommentAtParentEnd(node, nodeType) { + var ancestors = context.getAncestors(); + var parent; + + if (ancestors.length) { + parent = ancestors.pop(); + } - /** - * Returns whether or not comments are at the array end or not. - * @param {ASTNode} node The Comment node. - * @returns {boolean} True if the comment is at array end. - */ - function isCommentAtArrayEnd(node) { - return isCommentAtParentEnd(node, "ArrayExpression") || isCommentAtParentEnd(node, "ArrayPattern"); - } + return parent && isCommentInsideNodeType(node, parent, nodeType) && + parent.loc.end.line - node.loc.end.line === 1; + } - /** - * Checks if a comment node has lines around it (ignores inline comments) - * @param {ASTNode} node The Comment node. - * @param {Object} opts Options to determine the newline. - * @param {Boolean} opts.after Should have a newline after this line. - * @param {Boolean} opts.before Should have a newline before this line. - * @returns {void} - */ - function checkForEmptyLine(node, opts) { - - var lines = context.getSourceLines(), - numLines = lines.length + 1, - comments = context.getAllComments(), - commentLines = getCommentLineNums(comments), - emptyLines = getEmptyLineNums(lines), - commentAndEmptyLines = commentLines.concat(emptyLines); - - var after = opts.after, - before = opts.before; - - var prevLineNum = node.loc.start.line - 1, - nextLineNum = node.loc.end.line + 1, - commentIsNotAlone = codeAroundComment(node); - - var blockStartAllowed = options.allowBlockStart && isCommentAtBlockStart(node), - blockEndAllowed = options.allowBlockEnd && isCommentAtBlockEnd(node), - objectStartAllowed = options.allowObjectStart && isCommentAtObjectStart(node), - objectEndAllowed = options.allowObjectEnd && isCommentAtObjectEnd(node), - arrayStartAllowed = options.allowArrayStart && isCommentAtArrayStart(node), - arrayEndAllowed = options.allowArrayEnd && isCommentAtArrayEnd(node); - - var exceptionStartAllowed = blockStartAllowed || objectStartAllowed || arrayStartAllowed; - var exceptionEndAllowed = blockEndAllowed || objectEndAllowed || arrayEndAllowed; - - // ignore top of the file and bottom of the file - if (prevLineNum < 1) { - before = false; + /** + * Returns whether or not comments are at the block start or not. + * @param {ASTNode} node The Comment node. + * @returns {boolean} True if the comment is at block start. + */ + function isCommentAtBlockStart(node) { + return isCommentAtParentStart(node, "ClassBody") || isCommentAtParentStart(node, "BlockStatement") || isCommentAtParentStart(node, "SwitchCase"); } - if (nextLineNum >= numLines) { - after = false; + + /** + * Returns whether or not comments are at the block end or not. + * @param {ASTNode} node The Comment node. + * @returns {boolean} True if the comment is at block end. + */ + function isCommentAtBlockEnd(node) { + return isCommentAtParentEnd(node, "ClassBody") || isCommentAtParentEnd(node, "BlockStatement") || isCommentAtParentEnd(node, "SwitchCase") || isCommentAtParentEnd(node, "SwitchStatement"); } - // we ignore all inline comments - if (commentIsNotAlone) { - return; + /** + * Returns whether or not comments are at the object start or not. + * @param {ASTNode} node The Comment node. + * @returns {boolean} True if the comment is at object start. + */ + function isCommentAtObjectStart(node) { + return isCommentAtParentStart(node, "ObjectExpression") || isCommentAtParentStart(node, "ObjectPattern"); } - // check for newline before - if (!exceptionStartAllowed && before && !contains(prevLineNum, commentAndEmptyLines)) { - context.report(node, "Expected line before comment."); + /** + * Returns whether or not comments are at the object end or not. + * @param {ASTNode} node The Comment node. + * @returns {boolean} True if the comment is at object end. + */ + function isCommentAtObjectEnd(node) { + return isCommentAtParentEnd(node, "ObjectExpression") || isCommentAtParentEnd(node, "ObjectPattern"); } - // check for newline after - if (!exceptionEndAllowed && after && !contains(nextLineNum, commentAndEmptyLines)) { - context.report(node, "Expected line after comment."); + /** + * Returns whether or not comments are at the array start or not. + * @param {ASTNode} node The Comment node. + * @returns {boolean} True if the comment is at array start. + */ + function isCommentAtArrayStart(node) { + return isCommentAtParentStart(node, "ArrayExpression") || isCommentAtParentStart(node, "ArrayPattern"); } - } + /** + * Returns whether or not comments are at the array end or not. + * @param {ASTNode} node The Comment node. + * @returns {boolean} True if the comment is at array end. + */ + function isCommentAtArrayEnd(node) { + return isCommentAtParentEnd(node, "ArrayExpression") || isCommentAtParentEnd(node, "ArrayPattern"); + } - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- + /** + * Checks if a comment node has lines around it (ignores inline comments) + * @param {ASTNode} node The Comment node. + * @param {Object} opts Options to determine the newline. + * @param {Boolean} opts.after Should have a newline after this line. + * @param {Boolean} opts.before Should have a newline before this line. + * @returns {void} + */ + function checkForEmptyLine(node, opts) { + + var lines = context.getSourceLines(), + numLines = lines.length + 1, + comments = context.getAllComments(), + commentLines = getCommentLineNums(comments), + emptyLines = getEmptyLineNums(lines), + commentAndEmptyLines = commentLines.concat(emptyLines); + + var after = opts.after, + before = opts.before; + + var prevLineNum = node.loc.start.line - 1, + nextLineNum = node.loc.end.line + 1, + commentIsNotAlone = codeAroundComment(node); + + var blockStartAllowed = options.allowBlockStart && isCommentAtBlockStart(node), + blockEndAllowed = options.allowBlockEnd && isCommentAtBlockEnd(node), + objectStartAllowed = options.allowObjectStart && isCommentAtObjectStart(node), + objectEndAllowed = options.allowObjectEnd && isCommentAtObjectEnd(node), + arrayStartAllowed = options.allowArrayStart && isCommentAtArrayStart(node), + arrayEndAllowed = options.allowArrayEnd && isCommentAtArrayEnd(node); + + var exceptionStartAllowed = blockStartAllowed || objectStartAllowed || arrayStartAllowed; + var exceptionEndAllowed = blockEndAllowed || objectEndAllowed || arrayEndAllowed; + + // ignore top of the file and bottom of the file + if (prevLineNum < 1) { + before = false; + } + if (nextLineNum >= numLines) { + after = false; + } - return { + // we ignore all inline comments + if (commentIsNotAlone) { + return; + } - "LineComment": function(node) { - if (options.beforeLineComment || options.afterLineComment) { - checkForEmptyLine(node, { - after: options.afterLineComment, - before: options.beforeLineComment - }); + // check for newline before + if (!exceptionStartAllowed && before && !contains(prevLineNum, commentAndEmptyLines)) { + context.report(node, "Expected line before comment."); } - }, - "BlockComment": function(node) { - if (options.beforeBlockComment || options.afterBlockComment) { - checkForEmptyLine(node, { - after: options.afterBlockComment, - before: options.beforeBlockComment - }); + // check for newline after + if (!exceptionEndAllowed && after && !contains(nextLineNum, commentAndEmptyLines)) { + context.report(node, "Expected line after comment."); } + } - }; -}; + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- -module.exports.schema = [ - { - "type": "object", - "properties": { - "beforeBlockComment": { - "type": "boolean" - }, - "afterBlockComment": { - "type": "boolean" - }, - "beforeLineComment": { - "type": "boolean" - }, - "afterLineComment": { - "type": "boolean" - }, - "allowBlockStart": { - "type": "boolean" - }, - "allowBlockEnd": { - "type": "boolean" - }, - "allowObjectStart": { - "type": "boolean" - }, - "allowObjectEnd": { - "type": "boolean" - }, - "allowArrayStart": { - "type": "boolean" + return { + + LineComment: function(node) { + if (options.beforeLineComment || options.afterLineComment) { + checkForEmptyLine(node, { + after: options.afterLineComment, + before: options.beforeLineComment + }); + } }, - "allowArrayEnd": { - "type": "boolean" + + BlockComment: function(node) { + if (options.beforeBlockComment || options.afterBlockComment) { + checkForEmptyLine(node, { + after: options.afterBlockComment, + before: options.beforeBlockComment + }); + } } - }, - "additionalProperties": false + + }; } -]; +}; diff --git a/tools/eslint/lib/rules/max-depth.js b/tools/eslint/lib/rules/max-depth.js index 22fa2f5f0b27f1..317f06c68f397a 100644 --- a/tools/eslint/lib/rules/max-depth.js +++ b/tools/eslint/lib/rules/max-depth.js @@ -1,7 +1,6 @@ /** * @fileoverview A rule to set the maximum depth block can be nested in a function. * @author Ian Christian Myers - * @copyright 2013 Ian Christian Myers. All rights reserved. */ "use strict"; @@ -10,131 +9,141 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "enforce a maximum depth that blocks can be nested", + category: "Stylistic Issues", + recommended: false + }, - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- + schema: [ + { + oneOf: [ + { + type: "integer", + minimum: 0 + }, + { + type: "object", + properties: { + maximum: { + type: "integer", + minimum: 0 + }, + max: { + type: "integer", + minimum: 0 + } + }, + additionalProperties: false + } + ] + } + ] + }, - var functionStack = [], - option = context.options[0], - maxDepth = 4; + create: function(context) { - if (typeof option === "object" && option.hasOwnProperty("maximum") && typeof option.maximum === "number") { - maxDepth = option.maximum; - } - if (typeof option === "object" && option.hasOwnProperty("max") && typeof option.max === "number") { - maxDepth = option.max; - } - if (typeof option === "number") { - maxDepth = option; - } + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- - /** - * When parsing a new function, store it in our function stack - * @returns {void} - * @private - */ - function startFunction() { - functionStack.push(0); - } + var functionStack = [], + option = context.options[0], + maxDepth = 4; - /** - * When parsing is done then pop out the reference - * @returns {void} - * @private - */ - function endFunction() { - functionStack.pop(); - } + if (typeof option === "object" && option.hasOwnProperty("maximum") && typeof option.maximum === "number") { + maxDepth = option.maximum; + } + if (typeof option === "object" && option.hasOwnProperty("max") && typeof option.max === "number") { + maxDepth = option.max; + } + if (typeof option === "number") { + maxDepth = option; + } - /** - * Save the block and Evaluate the node - * @param {ASTNode} node node to evaluate - * @returns {void} - * @private - */ - function pushBlock(node) { - var len = ++functionStack[functionStack.length - 1]; - - if (len > maxDepth) { - context.report(node, "Blocks are nested too deeply ({{depth}}).", - { depth: len }); + /** + * When parsing a new function, store it in our function stack + * @returns {void} + * @private + */ + function startFunction() { + functionStack.push(0); } - } - /** - * Pop the saved block - * @returns {void} - * @private - */ - function popBlock() { - functionStack[functionStack.length - 1]--; - } + /** + * When parsing is done then pop out the reference + * @returns {void} + * @private + */ + function endFunction() { + functionStack.pop(); + } - //-------------------------------------------------------------------------- - // Public API - //-------------------------------------------------------------------------- + /** + * Save the block and Evaluate the node + * @param {ASTNode} node node to evaluate + * @returns {void} + * @private + */ + function pushBlock(node) { + var len = ++functionStack[functionStack.length - 1]; + + if (len > maxDepth) { + context.report(node, "Blocks are nested too deeply ({{depth}}).", + { depth: len }); + } + } - return { - "Program": startFunction, - "FunctionDeclaration": startFunction, - "FunctionExpression": startFunction, - "ArrowFunctionExpression": startFunction, + /** + * Pop the saved block + * @returns {void} + * @private + */ + function popBlock() { + functionStack[functionStack.length - 1]--; + } - "IfStatement": function(node) { - if (node.parent.type !== "IfStatement") { - pushBlock(node); - } - }, - "SwitchStatement": pushBlock, - "TryStatement": pushBlock, - "DoWhileStatement": pushBlock, - "WhileStatement": pushBlock, - "WithStatement": pushBlock, - "ForStatement": pushBlock, - "ForInStatement": pushBlock, - "ForOfStatement": pushBlock, - - "IfStatement:exit": popBlock, - "SwitchStatement:exit": popBlock, - "TryStatement:exit": popBlock, - "DoWhileStatement:exit": popBlock, - "WhileStatement:exit": popBlock, - "WithStatement:exit": popBlock, - "ForStatement:exit": popBlock, - "ForInStatement:exit": popBlock, - "ForOfStatement:exit": popBlock, - - "FunctionDeclaration:exit": endFunction, - "FunctionExpression:exit": endFunction, - "ArrowFunctionExpression:exit": endFunction, - "Program:exit": endFunction - }; + //-------------------------------------------------------------------------- + // Public API + //-------------------------------------------------------------------------- -}; + return { + Program: startFunction, + FunctionDeclaration: startFunction, + FunctionExpression: startFunction, + ArrowFunctionExpression: startFunction, -module.exports.schema = [ - { - "oneOf": [ - { - "type": "integer", - "minimum": 0 + IfStatement: function(node) { + if (node.parent.type !== "IfStatement") { + pushBlock(node); + } }, - { - "type": "object", - "properties": { - "maximum": { - "type": "integer", - "minimum": 0 - }, - "max": { - "type": "integer", - "minimum": 0 - } - }, - "additionalProperties": false - } - ] + SwitchStatement: pushBlock, + TryStatement: pushBlock, + DoWhileStatement: pushBlock, + WhileStatement: pushBlock, + WithStatement: pushBlock, + ForStatement: pushBlock, + ForInStatement: pushBlock, + ForOfStatement: pushBlock, + + "IfStatement:exit": popBlock, + "SwitchStatement:exit": popBlock, + "TryStatement:exit": popBlock, + "DoWhileStatement:exit": popBlock, + "WhileStatement:exit": popBlock, + "WithStatement:exit": popBlock, + "ForStatement:exit": popBlock, + "ForInStatement:exit": popBlock, + "ForOfStatement:exit": popBlock, + + "FunctionDeclaration:exit": endFunction, + "FunctionExpression:exit": endFunction, + "ArrowFunctionExpression:exit": endFunction, + "Program:exit": endFunction + }; + } -]; +}; diff --git a/tools/eslint/lib/rules/max-len.js b/tools/eslint/lib/rules/max-len.js index 610cdf2bacfd3a..1ba539a1192e43 100644 --- a/tools/eslint/lib/rules/max-len.js +++ b/tools/eslint/lib/rules/max-len.js @@ -1,245 +1,258 @@ /** * @fileoverview Rule to check for max length on a line. * @author Matt DuVall - * @copyright 2013 Matt DuVall. All rights reserved. */ "use strict"; //------------------------------------------------------------------------------ -// Rule Definition +// Constants //------------------------------------------------------------------------------ -module.exports = function(context) { - - /* - * Inspired by http://tools.ietf.org/html/rfc3986#appendix-B, however: - * - They're matching an entire string that we know is a URI - * - We're matching part of a string where we think there *might* be a URL - * - We're only concerned about URLs, as picking out any URI would cause - * too many false positives - * - We don't care about matching the entire URL, any small segment is fine - */ - var URL_REGEXP = /[^:/?#]:\/\/[^?#]/; - - /** - * Computes the length of a line that may contain tabs. The width of each - * tab will be the number of spaces to the next tab stop. - * @param {string} line The line. - * @param {int} tabWidth The width of each tab stop in spaces. - * @returns {int} The computed line length. - * @private - */ - function computeLineLength(line, tabWidth) { - var extraCharacterCount = 0; - - line.replace(/\t/g, function(match, offset) { - var totalOffset = offset + extraCharacterCount, - previousTabStopOffset = tabWidth ? totalOffset % tabWidth : 0, - spaceCount = tabWidth - previousTabStopOffset; - - extraCharacterCount += spaceCount - 1; // -1 for the replaced tab - }); - return line.length + extraCharacterCount; - } - - // The options object must be the last option specified… - var lastOption = context.options[context.options.length - 1]; - var options = typeof lastOption === "object" ? Object.create(lastOption) : {}; - - // …but max code length… - if (typeof context.options[0] === "number") { - options.code = context.options[0]; - } +var OPTIONS_SCHEMA = { + type: "object", + properties: { + code: { + type: "integer", + minimum: 0 + }, + comments: { + type: "integer", + minimum: 0 + }, + tabWidth: { + type: "integer", + minimum: 0 + }, + ignorePattern: { + type: "string" + }, + ignoreComments: { + type: "boolean" + }, + ignoreUrls: { + type: "boolean" + }, + ignoreTrailingComments: { + type: "boolean" + } + }, + additionalProperties: false +}; - // …and tabWidth can be optionally specified directly as integers. - if (typeof context.options[1] === "number") { - options.tabWidth = context.options[1]; - } +var OPTIONS_OR_INTEGER_SCHEMA = { + anyOf: [ + OPTIONS_SCHEMA, + { + type: "integer", + minimum: 0 + } + ] +}; - var maxLength = options.code || 80, - tabWidth = options.tabWidth || 4, - ignorePattern = options.ignorePattern || null, - ignoreComments = options.ignoreComments || false, - ignoreTrailingComments = options.ignoreTrailingComments || options.ignoreComments || false, - ignoreUrls = options.ignoreUrls || false, - maxCommentLength = options.comments; +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ - if (ignorePattern) { - ignorePattern = new RegExp(ignorePattern); - } +module.exports = { + meta: { + docs: { + description: "enforce a maximum line length", + category: "Stylistic Issues", + recommended: false + }, - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- - - /** - * Tells if a given comment is trailing: it starts on the current line and - * extends to or past the end of the current line. - * @param {string} line The source line we want to check for a trailing comment on - * @param {number} lineNumber The one-indexed line number for line - * @param {ASTNode} comment The comment to inspect - * @returns {boolean} If the comment is trailing on the given line - */ - function isTrailingComment(line, lineNumber, comment) { - return comment && - (comment.loc.start.line === lineNumber && lineNumber <= comment.loc.end.line) && - (comment.loc.end.line > lineNumber || comment.loc.end.column === line.length); - } + schema: [ + OPTIONS_OR_INTEGER_SCHEMA, + OPTIONS_OR_INTEGER_SCHEMA, + OPTIONS_SCHEMA + ] + }, - /** - * Tells if a comment encompasses the entire line. - * @param {string} line The source line with a trailing comment - * @param {number} lineNumber The one-indexed line number this is on - * @param {ASTNode} comment The comment to remove - * @returns {boolean} If the comment covers the entire line - */ - function isFullLineComment(line, lineNumber, comment) { - var start = comment.loc.start, - end = comment.loc.end; - - return comment && - (start.line < lineNumber || (start.line === lineNumber && start.column === 0)) && - (end.line > lineNumber || end.column === line.length); - } + create: function(context) { + + /* + * Inspired by http://tools.ietf.org/html/rfc3986#appendix-B, however: + * - They're matching an entire string that we know is a URI + * - We're matching part of a string where we think there *might* be a URL + * - We're only concerned about URLs, as picking out any URI would cause + * too many false positives + * - We don't care about matching the entire URL, any small segment is fine + */ + var URL_REGEXP = /[^:/?#]:\/\/[^?#]/; + + /** + * Computes the length of a line that may contain tabs. The width of each + * tab will be the number of spaces to the next tab stop. + * @param {string} line The line. + * @param {int} tabWidth The width of each tab stop in spaces. + * @returns {int} The computed line length. + * @private + */ + function computeLineLength(line, tabWidth) { + var extraCharacterCount = 0; + + line.replace(/\t/g, function(match, offset) { + var totalOffset = offset + extraCharacterCount, + previousTabStopOffset = tabWidth ? totalOffset % tabWidth : 0, + spaceCount = tabWidth - previousTabStopOffset; + + extraCharacterCount += spaceCount - 1; // -1 for the replaced tab + }); + return line.length + extraCharacterCount; + } - /** - * Gets the line after the comment and any remaining trailing whitespace is - * stripped. - * @param {string} line The source line with a trailing comment - * @param {number} lineNumber The one-indexed line number this is on - * @param {ASTNode} comment The comment to remove - * @returns {string} Line without comment and trailing whitepace - */ - function stripTrailingComment(line, lineNumber, comment) { - - // loc.column is zero-indexed - return line.slice(0, comment.loc.start.column).replace(/\s+$/, ""); - } + // The options object must be the last option specified… + var lastOption = context.options[context.options.length - 1]; + var options = typeof lastOption === "object" ? Object.create(lastOption) : {}; - /** - * Check the program for max length - * @param {ASTNode} node Node to examine - * @returns {void} - * @private - */ - function checkProgramForMaxLength(node) { + // …but max code length… + if (typeof context.options[0] === "number") { + options.code = context.options[0]; + } - // split (honors line-ending) - var lines = context.getSourceLines(), + // …and tabWidth can be optionally specified directly as integers. + if (typeof context.options[1] === "number") { + options.tabWidth = context.options[1]; + } - // list of comments to ignore - comments = ignoreComments || maxCommentLength || ignoreTrailingComments ? context.getAllComments() : [], + var maxLength = options.code || 80, + tabWidth = options.tabWidth || 4, + ignorePattern = options.ignorePattern || null, + ignoreComments = options.ignoreComments || false, + ignoreTrailingComments = options.ignoreTrailingComments || options.ignoreComments || false, + ignoreUrls = options.ignoreUrls || false, + maxCommentLength = options.comments; - // we iterate over comments in parallel with the lines - commentsIndex = 0; + if (ignorePattern) { + ignorePattern = new RegExp(ignorePattern); + } - lines.forEach(function(line, i) { + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- + + /** + * Tells if a given comment is trailing: it starts on the current line and + * extends to or past the end of the current line. + * @param {string} line The source line we want to check for a trailing comment on + * @param {number} lineNumber The one-indexed line number for line + * @param {ASTNode} comment The comment to inspect + * @returns {boolean} If the comment is trailing on the given line + */ + function isTrailingComment(line, lineNumber, comment) { + return comment && + (comment.loc.start.line === lineNumber && lineNumber <= comment.loc.end.line) && + (comment.loc.end.line > lineNumber || comment.loc.end.column === line.length); + } - // i is zero-indexed, line numbers are one-indexed - var lineNumber = i + 1; + /** + * Tells if a comment encompasses the entire line. + * @param {string} line The source line with a trailing comment + * @param {number} lineNumber The one-indexed line number this is on + * @param {ASTNode} comment The comment to remove + * @returns {boolean} If the comment covers the entire line + */ + function isFullLineComment(line, lineNumber, comment) { + var start = comment.loc.start, + end = comment.loc.end; + + return comment && + (start.line < lineNumber || (start.line === lineNumber && start.column === 0)) && + (end.line > lineNumber || end.column === line.length); + } - /* - * if we're checking comment length; we need to know whether this - * line is a comment - */ - var lineIsComment = false; + /** + * Gets the line after the comment and any remaining trailing whitespace is + * stripped. + * @param {string} line The source line with a trailing comment + * @param {number} lineNumber The one-indexed line number this is on + * @param {ASTNode} comment The comment to remove + * @returns {string} Line without comment and trailing whitepace + */ + function stripTrailingComment(line, lineNumber, comment) { + + // loc.column is zero-indexed + return line.slice(0, comment.loc.start.column).replace(/\s+$/, ""); + } - /* - * We can short-circuit the comment checks if we're already out of - * comments to check. - */ - if (commentsIndex < comments.length) { + /** + * Check the program for max length + * @param {ASTNode} node Node to examine + * @returns {void} + * @private + */ + function checkProgramForMaxLength(node) { + + // split (honors line-ending) + var lines = context.getSourceLines(), + + // list of comments to ignore + comments = ignoreComments || maxCommentLength || ignoreTrailingComments ? context.getAllComments() : [], + + // we iterate over comments in parallel with the lines + commentsIndex = 0; + + lines.forEach(function(line, i) { + + // i is zero-indexed, line numbers are one-indexed + var lineNumber = i + 1; + + /* + * if we're checking comment length; we need to know whether this + * line is a comment + */ + var lineIsComment = false; + + /* + * We can short-circuit the comment checks if we're already out of + * comments to check. + */ + if (commentsIndex < comments.length) { + + // iterate over comments until we find one past the current line + do { + var comment = comments[++commentsIndex]; + } while (comment && comment.loc.start.line <= lineNumber); + + // and step back by one + comment = comments[--commentsIndex]; + + if (isFullLineComment(line, lineNumber, comment)) { + lineIsComment = true; + } else if (ignoreTrailingComments && isTrailingComment(line, lineNumber, comment)) { + line = stripTrailingComment(line, lineNumber, comment); + } + } + if (ignorePattern && ignorePattern.test(line) || + ignoreUrls && URL_REGEXP.test(line)) { - // iterate over comments until we find one past the current line - do { - var comment = comments[++commentsIndex]; - } while (comment && comment.loc.start.line <= lineNumber); + // ignore this line + return; + } - // and step back by one - comment = comments[--commentsIndex]; + var lineLength = computeLineLength(line, tabWidth); - if (isFullLineComment(line, lineNumber, comment)) { - lineIsComment = true; - } else if (ignoreTrailingComments && isTrailingComment(line, lineNumber, comment)) { - line = stripTrailingComment(line, lineNumber, comment); + if (lineIsComment && ignoreComments) { + return; } - } - if (ignorePattern && ignorePattern.test(line) || - ignoreUrls && URL_REGEXP.test(line)) { - - // ignore this line - return; - } - - var lineLength = computeLineLength(line, tabWidth); - - if (lineIsComment && ignoreComments) { - return; - } - - if (lineIsComment && lineLength > maxCommentLength) { - context.report(node, { line: lineNumber, column: 0 }, "Line " + (i + 1) + " exceeds the maximum comment line length of " + maxCommentLength + "."); - } else if (lineLength > maxLength) { - context.report(node, { line: lineNumber, column: 0 }, "Line " + (i + 1) + " exceeds the maximum line length of " + maxLength + "."); - } - }); - } + if (lineIsComment && lineLength > maxCommentLength) { + context.report(node, { line: lineNumber, column: 0 }, "Line " + (i + 1) + " exceeds the maximum comment line length of " + maxCommentLength + "."); + } else if (lineLength > maxLength) { + context.report(node, { line: lineNumber, column: 0 }, "Line " + (i + 1) + " exceeds the maximum line length of " + maxLength + "."); + } + }); + } - //-------------------------------------------------------------------------- - // Public API - //-------------------------------------------------------------------------- - return { - "Program": checkProgramForMaxLength - }; + //-------------------------------------------------------------------------- + // Public API + //-------------------------------------------------------------------------- -}; + return { + Program: checkProgramForMaxLength + }; -var OPTIONS_SCHEMA = { - "type": "object", - "properties": { - "code": { - "type": "integer", - "minimum": 0 - }, - "comments": { - "type": "integer", - "minimum": 0 - }, - "tabWidth": { - "type": "integer", - "minimum": 0 - }, - "ignorePattern": { - "type": "string" - }, - "ignoreComments": { - "type": "boolean" - }, - "ignoreUrls": { - "type": "boolean" - }, - "ignoreTrailingComments": { - "type": "boolean" - } - }, - "additionalProperties": false -}; - -var OPTIONS_OR_INTEGER_SCHEMA = { - "anyOf": [ - OPTIONS_SCHEMA, - { - "type": "integer", - "minimum": 0 - } - ] + } }; - -module.exports.schema = [ - OPTIONS_OR_INTEGER_SCHEMA, - OPTIONS_OR_INTEGER_SCHEMA, - OPTIONS_SCHEMA -]; diff --git a/tools/eslint/lib/rules/max-nested-callbacks.js b/tools/eslint/lib/rules/max-nested-callbacks.js index 21b411b25138f4..06554127c63242 100644 --- a/tools/eslint/lib/rules/max-nested-callbacks.js +++ b/tools/eslint/lib/rules/max-nested-callbacks.js @@ -1,7 +1,6 @@ /** * @fileoverview Rule to enforce a maximum number of nested callbacks. * @author Ian Christian Myers - * @copyright 2013 Ian Christian Myers. All rights reserved. */ "use strict"; @@ -10,94 +9,104 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "enforce a maximum depth that callbacks can be nested", + category: "Stylistic Issues", + recommended: false + }, - //-------------------------------------------------------------------------- - // Constants - //-------------------------------------------------------------------------- - var option = context.options[0], - THRESHOLD = 10; + schema: [ + { + oneOf: [ + { + type: "integer", + minimum: 0 + }, + { + type: "object", + properties: { + maximum: { + type: "integer", + minimum: 0 + }, + max: { + type: "integer", + minimum: 0 + } + }, + additionalProperties: false + } + ] + } + ] + }, - if (typeof option === "object" && option.hasOwnProperty("maximum") && typeof option.maximum === "number") { - THRESHOLD = option.maximum; - } - if (typeof option === "object" && option.hasOwnProperty("max") && typeof option.max === "number") { - THRESHOLD = option.max; - } - if (typeof option === "number") { - THRESHOLD = option; - } + create: function(context) { - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- + //-------------------------------------------------------------------------- + // Constants + //-------------------------------------------------------------------------- + var option = context.options[0], + THRESHOLD = 10; - var callbackStack = []; + if (typeof option === "object" && option.hasOwnProperty("maximum") && typeof option.maximum === "number") { + THRESHOLD = option.maximum; + } + if (typeof option === "object" && option.hasOwnProperty("max") && typeof option.max === "number") { + THRESHOLD = option.max; + } + if (typeof option === "number") { + THRESHOLD = option; + } - /** - * Checks a given function node for too many callbacks. - * @param {ASTNode} node The node to check. - * @returns {void} - * @private - */ - function checkFunction(node) { - var parent = node.parent; + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- - if (parent.type === "CallExpression") { - callbackStack.push(node); - } + var callbackStack = []; - if (callbackStack.length > THRESHOLD) { - var opts = {num: callbackStack.length, max: THRESHOLD}; + /** + * Checks a given function node for too many callbacks. + * @param {ASTNode} node The node to check. + * @returns {void} + * @private + */ + function checkFunction(node) { + var parent = node.parent; - context.report(node, "Too many nested callbacks ({{num}}). Maximum allowed is {{max}}.", opts); - } - } + if (parent.type === "CallExpression") { + callbackStack.push(node); + } - /** - * Pops the call stack. - * @returns {void} - * @private - */ - function popStack() { - callbackStack.pop(); - } + if (callbackStack.length > THRESHOLD) { + var opts = {num: callbackStack.length, max: THRESHOLD}; - //-------------------------------------------------------------------------- - // Public API - //-------------------------------------------------------------------------- + context.report(node, "Too many nested callbacks ({{num}}). Maximum allowed is {{max}}.", opts); + } + } - return { - "ArrowFunctionExpression": checkFunction, - "ArrowFunctionExpression:exit": popStack, + /** + * Pops the call stack. + * @returns {void} + * @private + */ + function popStack() { + callbackStack.pop(); + } - "FunctionExpression": checkFunction, - "FunctionExpression:exit": popStack - }; + //-------------------------------------------------------------------------- + // Public API + //-------------------------------------------------------------------------- -}; + return { + ArrowFunctionExpression: checkFunction, + "ArrowFunctionExpression:exit": popStack, + + FunctionExpression: checkFunction, + "FunctionExpression:exit": popStack + }; -module.exports.schema = [ - { - "oneOf": [ - { - "type": "integer", - "minimum": 0 - }, - { - "type": "object", - "properties": { - "maximum": { - "type": "integer", - "minimum": 0 - }, - "max": { - "type": "integer", - "minimum": 0 - } - }, - "additionalProperties": false - } - ] } -]; +}; diff --git a/tools/eslint/lib/rules/max-params.js b/tools/eslint/lib/rules/max-params.js index d1cfe470922933..5d9d64fac10af9 100644 --- a/tools/eslint/lib/rules/max-params.js +++ b/tools/eslint/lib/rules/max-params.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to flag when a function has too many parameters * @author Ilya Volodin - * @copyright 2014 Nicholas C. Zakas. All rights reserved. - * @copyright 2013 Ilya Volodin. All rights reserved. */ "use strict"; @@ -11,65 +9,75 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "enforce a maximum number of parameters in `function` definitions", + category: "Stylistic Issues", + recommended: false + }, - var option = context.options[0], - numParams = 3; + schema: [ + { + oneOf: [ + { + type: "integer", + minimum: 0 + }, + { + type: "object", + properties: { + maximum: { + type: "integer", + minimum: 0 + }, + max: { + type: "integer", + minimum: 0 + } + }, + additionalProperties: false + } + ] + } + ] + }, - if (typeof option === "object" && option.hasOwnProperty("maximum") && typeof option.maximum === "number") { - numParams = option.maximum; - } - if (typeof option === "object" && option.hasOwnProperty("max") && typeof option.max === "number") { - numParams = option.max; - } - if (typeof option === "number") { - numParams = option; - } + create: function(context) { + + var option = context.options[0], + numParams = 3; - /** - * Checks a function to see if it has too many parameters. - * @param {ASTNode} node The node to check. - * @returns {void} - * @private - */ - function checkFunction(node) { - if (node.params.length > numParams) { - context.report(node, "This function has too many parameters ({{count}}). Maximum allowed is {{max}}.", { - count: node.params.length, - max: numParams - }); + if (typeof option === "object" && option.hasOwnProperty("maximum") && typeof option.maximum === "number") { + numParams = option.maximum; + } + if (typeof option === "object" && option.hasOwnProperty("max") && typeof option.max === "number") { + numParams = option.max; + } + if (typeof option === "number") { + numParams = option; } - } - return { - "FunctionDeclaration": checkFunction, - "ArrowFunctionExpression": checkFunction, - "FunctionExpression": checkFunction - }; + /** + * Checks a function to see if it has too many parameters. + * @param {ASTNode} node The node to check. + * @returns {void} + * @private + */ + function checkFunction(node) { + if (node.params.length > numParams) { + context.report(node, "This function has too many parameters ({{count}}). Maximum allowed is {{max}}.", { + count: node.params.length, + max: numParams + }); + } + } -}; + return { + FunctionDeclaration: checkFunction, + ArrowFunctionExpression: checkFunction, + FunctionExpression: checkFunction + }; -module.exports.schema = [ - { - "oneOf": [ - { - "type": "integer", - "minimum": 0 - }, - { - "type": "object", - "properties": { - "maximum": { - "type": "integer", - "minimum": 0 - }, - "max": { - "type": "integer", - "minimum": 0 - } - }, - "additionalProperties": false - } - ] } -]; +}; diff --git a/tools/eslint/lib/rules/max-statements-per-line.js b/tools/eslint/lib/rules/max-statements-per-line.js index 465c5a00b0eebb..64058f0d30bf2b 100644 --- a/tools/eslint/lib/rules/max-statements-per-line.js +++ b/tools/eslint/lib/rules/max-statements-per-line.js @@ -1,9 +1,6 @@ /** * @fileoverview Specify the maximum number of statements allowed per line. * @author Kenneth Williams - * @copyright 2016 Kenneth Williams. All rights reserved. - * @copyright 2016 Michael Ficarra. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; @@ -11,96 +8,106 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "enforce a maximum number of statements allowed per line", + category: "Stylistic Issues", + recommended: false + }, - var options = context.options[0] || {}, - lastStatementLine = 0, - numberOfStatementsOnThisLine = 0, - maxStatementsPerLine = typeof options.max !== "undefined" ? options.max : 1; + schema: [ + { + type: "object", + properties: { + max: { + type: "integer" + } + }, + additionalProperties: false + } + ] + }, - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- + create: function(context) { - /** - * Reports a node - * @param {ASTNode} node The node to report - * @returns {void} - * @private - */ - function report(node) { - context.report( - node, - "This line has too many statements. Maximum allowed is {{max}}.", - { max: maxStatementsPerLine }); - } + var options = context.options[0] || {}, + lastStatementLine = 0, + numberOfStatementsOnThisLine = 0, + maxStatementsPerLine = typeof options.max !== "undefined" ? options.max : 1; - /** - * Enforce a maximum number of statements per line - * @param {ASTNode} nodes Array of nodes to evaluate - * @returns {void} - * @private - */ - function enforceMaxStatementsPerLine(nodes) { - if (nodes.length < 1) { - return; - } + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- - for (var i = 0, l = nodes.length; i < l; ++i) { - var currentStatement = nodes[i]; + /** + * Reports a node + * @param {ASTNode} node The node to report + * @returns {void} + * @private + */ + function report(node) { + context.report( + node, + "This line has too many statements. Maximum allowed is {{max}}.", + { max: maxStatementsPerLine }); + } - if (currentStatement.loc.start.line === lastStatementLine) { - ++numberOfStatementsOnThisLine; - } else { - numberOfStatementsOnThisLine = 1; - lastStatementLine = currentStatement.loc.end.line; + /** + * Enforce a maximum number of statements per line + * @param {ASTNode} nodes Array of nodes to evaluate + * @returns {void} + * @private + */ + function enforceMaxStatementsPerLine(nodes) { + if (nodes.length < 1) { + return; } - if (numberOfStatementsOnThisLine === maxStatementsPerLine + 1) { - report(currentStatement); + + for (var i = 0, l = nodes.length; i < l; ++i) { + var currentStatement = nodes[i]; + + if (currentStatement.loc.start.line === lastStatementLine) { + ++numberOfStatementsOnThisLine; + } else { + numberOfStatementsOnThisLine = 1; + lastStatementLine = currentStatement.loc.end.line; + } + if (numberOfStatementsOnThisLine === maxStatementsPerLine + 1) { + report(currentStatement); + } } } - } - /** - * Check each line in the body of a node - * @param {ASTNode} node node to evaluate - * @returns {void} - * @private - */ - function checkLinesInBody(node) { - enforceMaxStatementsPerLine(node.body); - } - - /** - * Check each line in the consequent of a switch case - * @param {ASTNode} node node to evaluate - * @returns {void} - * @private - */ - function checkLinesInConsequent(node) { - enforceMaxStatementsPerLine(node.consequent); - } + /** + * Check each line in the body of a node + * @param {ASTNode} node node to evaluate + * @returns {void} + * @private + */ + function checkLinesInBody(node) { + enforceMaxStatementsPerLine(node.body); + } - //-------------------------------------------------------------------------- - // Public API - //-------------------------------------------------------------------------- + /** + * Check each line in the consequent of a switch case + * @param {ASTNode} node node to evaluate + * @returns {void} + * @private + */ + function checkLinesInConsequent(node) { + enforceMaxStatementsPerLine(node.consequent); + } - return { - "Program": checkLinesInBody, - "BlockStatement": checkLinesInBody, - "SwitchCase": checkLinesInConsequent - }; + //-------------------------------------------------------------------------- + // Public API + //-------------------------------------------------------------------------- -}; + return { + Program: checkLinesInBody, + BlockStatement: checkLinesInBody, + SwitchCase: checkLinesInConsequent + }; -module.exports.schema = [ - { - "type": "object", - "properties": { - "max": { - "type": "integer" - } - }, - "additionalProperties": false } -]; +}; diff --git a/tools/eslint/lib/rules/max-statements.js b/tools/eslint/lib/rules/max-statements.js index e608958ebae6d0..72904c64bad0c4 100644 --- a/tools/eslint/lib/rules/max-statements.js +++ b/tools/eslint/lib/rules/max-statements.js @@ -1,7 +1,6 @@ /** * @fileoverview A rule to set the maximum number of statements in a function. * @author Ian Christian Myers - * @copyright 2013 Ian Christian Myers. All rights reserved. */ "use strict"; @@ -10,141 +9,151 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "enforce a maximum number of statements allowed in `function` blocks", + category: "Stylistic Issues", + recommended: false + }, + + schema: [ + { + oneOf: [ + { + type: "integer", + minimum: 0 + }, + { + type: "object", + properties: { + maximum: { + type: "integer", + minimum: 0 + }, + max: { + type: "integer", + minimum: 0 + } + }, + additionalProperties: false + } + ] + }, + { + type: "object", + properties: { + ignoreTopLevelFunctions: { + type: "boolean" + } + }, + additionalProperties: false + } + ] + }, - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- + create: function(context) { - var functionStack = [], - option = context.options[0], - maxStatements = 10, - ignoreTopLevelFunctions = context.options[1] && context.options[1].ignoreTopLevelFunctions || false, - topLevelFunctions = []; + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- - if (typeof option === "object" && option.hasOwnProperty("maximum") && typeof option.maximum === "number") { - maxStatements = option.maximum; - } - if (typeof option === "object" && option.hasOwnProperty("max") && typeof option.max === "number") { - maxStatements = option.max; - } - if (typeof option === "number") { - maxStatements = option; - } + var functionStack = [], + option = context.options[0], + maxStatements = 10, + ignoreTopLevelFunctions = context.options[1] && context.options[1].ignoreTopLevelFunctions || false, + topLevelFunctions = []; - /** - * Reports a node if it has too many statements - * @param {ASTNode} node node to evaluate - * @param {int} count Number of statements in node - * @param {int} max Maximum number of statements allowed - * @returns {void} - * @private - */ - function reportIfTooManyStatements(node, count, max) { - if (count > max) { - context.report( - node, - "This function has too many statements ({{count}}). Maximum allowed is {{max}}.", - { count: count, max: max }); + if (typeof option === "object" && option.hasOwnProperty("maximum") && typeof option.maximum === "number") { + maxStatements = option.maximum; + } + if (typeof option === "object" && option.hasOwnProperty("max") && typeof option.max === "number") { + maxStatements = option.max; + } + if (typeof option === "number") { + maxStatements = option; } - } - - /** - * When parsing a new function, store it in our function stack - * @returns {void} - * @private - */ - function startFunction() { - functionStack.push(0); - } - /** - * Evaluate the node at the end of function - * @param {ASTNode} node node to evaluate - * @returns {void} - * @private - */ - function endFunction(node) { - var count = functionStack.pop(); - - if (ignoreTopLevelFunctions && functionStack.length === 0) { - topLevelFunctions.push({ node: node, count: count}); - } else { - reportIfTooManyStatements(node, count, maxStatements); + /** + * Reports a node if it has too many statements + * @param {ASTNode} node node to evaluate + * @param {int} count Number of statements in node + * @param {int} max Maximum number of statements allowed + * @returns {void} + * @private + */ + function reportIfTooManyStatements(node, count, max) { + if (count > max) { + context.report( + node, + "This function has too many statements ({{count}}). Maximum allowed is {{max}}.", + { count: count, max: max }); + } } - } - /** - * Increment the count of the functions - * @param {ASTNode} node node to evaluate - * @returns {void} - * @private - */ - function countStatements(node) { - functionStack[functionStack.length - 1] += node.body.length; - } + /** + * When parsing a new function, store it in our function stack + * @returns {void} + * @private + */ + function startFunction() { + functionStack.push(0); + } - //-------------------------------------------------------------------------- - // Public API - //-------------------------------------------------------------------------- + /** + * Evaluate the node at the end of function + * @param {ASTNode} node node to evaluate + * @returns {void} + * @private + */ + function endFunction(node) { + var count = functionStack.pop(); + + if (ignoreTopLevelFunctions && functionStack.length === 0) { + topLevelFunctions.push({ node: node, count: count}); + } else { + reportIfTooManyStatements(node, count, maxStatements); + } + } - return { - "FunctionDeclaration": startFunction, - "FunctionExpression": startFunction, - "ArrowFunctionExpression": startFunction, + /** + * Increment the count of the functions + * @param {ASTNode} node node to evaluate + * @returns {void} + * @private + */ + function countStatements(node) { + functionStack[functionStack.length - 1] += node.body.length; + } - "BlockStatement": countStatements, + //-------------------------------------------------------------------------- + // Public API + //-------------------------------------------------------------------------- - "FunctionDeclaration:exit": endFunction, - "FunctionExpression:exit": endFunction, - "ArrowFunctionExpression:exit": endFunction, + return { + FunctionDeclaration: startFunction, + FunctionExpression: startFunction, + ArrowFunctionExpression: startFunction, - "Program:exit": function() { - if (topLevelFunctions.length === 1) { - return; - } + BlockStatement: countStatements, - topLevelFunctions.forEach(function(element) { - var count = element.count; - var node = element.node; + "FunctionDeclaration:exit": endFunction, + "FunctionExpression:exit": endFunction, + "ArrowFunctionExpression:exit": endFunction, - reportIfTooManyStatements(node, count, maxStatements); - }); - } - }; + "Program:exit": function() { + if (topLevelFunctions.length === 1) { + return; + } -}; + topLevelFunctions.forEach(function(element) { + var count = element.count; + var node = element.node; -module.exports.schema = [ - { - "oneOf": [ - { - "type": "integer", - "minimum": 0 - }, - { - "type": "object", - "properties": { - "maximum": { - "type": "integer", - "minimum": 0 - }, - "max": { - "type": "integer", - "minimum": 0 - } - }, - "additionalProperties": false + reportIfTooManyStatements(node, count, maxStatements); + }); } - ] - }, - { - "type": "object", - "properties": { - "ignoreTopLevelFunctions": { - "type": "boolean" - } - }, - "additionalProperties": false + }; + } -]; +}; diff --git a/tools/eslint/lib/rules/new-cap.js b/tools/eslint/lib/rules/new-cap.js index f43c59fd99951a..697b60d0f10c87 100644 --- a/tools/eslint/lib/rules/new-cap.js +++ b/tools/eslint/lib/rules/new-cap.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to flag use of constructors without capital letters * @author Nicholas C. Zakas - * @copyright 2014 Jordan Harband. All rights reserved. - * @copyright 2013-2014 Nicholas C. Zakas. All rights reserved. */ "use strict"; @@ -76,174 +74,184 @@ function calculateCapIsNewExceptions(config) { // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "require constructor `function` names to begin with a capital letter", + category: "Stylistic Issues", + recommended: false + }, + + schema: [ + { + type: "object", + properties: { + newIsCap: { + type: "boolean" + }, + capIsNew: { + type: "boolean" + }, + newIsCapExceptions: { + type: "array", + items: { + type: "string" + } + }, + capIsNewExceptions: { + type: "array", + items: { + type: "string" + } + }, + properties: { + type: "boolean" + } + }, + additionalProperties: false + } + ] + }, + + create: function(context) { - var config = context.options[0] ? lodash.assign({}, context.options[0]) : {}; + var config = context.options[0] ? lodash.assign({}, context.options[0]) : {}; - config.newIsCap = config.newIsCap !== false; - config.capIsNew = config.capIsNew !== false; - var skipProperties = config.properties === false; + config.newIsCap = config.newIsCap !== false; + config.capIsNew = config.capIsNew !== false; + var skipProperties = config.properties === false; - var newIsCapExceptions = checkArray(config, "newIsCapExceptions", []).reduce(invert, {}); + var newIsCapExceptions = checkArray(config, "newIsCapExceptions", []).reduce(invert, {}); - var capIsNewExceptions = calculateCapIsNewExceptions(config); + var capIsNewExceptions = calculateCapIsNewExceptions(config); - var listeners = {}; + var listeners = {}; - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- - /** - * Get exact callee name from expression - * @param {ASTNode} node CallExpression or NewExpression node - * @returns {string} name - */ - function extractNameFromExpression(node) { + /** + * Get exact callee name from expression + * @param {ASTNode} node CallExpression or NewExpression node + * @returns {string} name + */ + function extractNameFromExpression(node) { - var name = "", - property; + var name = "", + property; - if (node.callee.type === "MemberExpression") { - property = node.callee.property; + if (node.callee.type === "MemberExpression") { + property = node.callee.property; - if (property.type === "Literal" && (typeof property.value === "string")) { - name = property.value; - } else if (property.type === "Identifier" && !node.callee.computed) { - name = property.name; + if (property.type === "Literal" && (typeof property.value === "string")) { + name = property.value; + } else if (property.type === "Identifier" && !node.callee.computed) { + name = property.name; + } + } else { + name = node.callee.name; } - } else { - name = node.callee.name; + return name; } - return name; - } - /** - * Returns the capitalization state of the string - - * Whether the first character is uppercase, lowercase, or non-alphabetic - * @param {string} str String - * @returns {string} capitalization state: "non-alpha", "lower", or "upper" - */ - function getCap(str) { - var firstChar = str.charAt(0); - - var firstCharLower = firstChar.toLowerCase(); - var firstCharUpper = firstChar.toUpperCase(); - - if (firstCharLower === firstCharUpper) { - - // char has no uppercase variant, so it's non-alphabetic - return "non-alpha"; - } else if (firstChar === firstCharLower) { - return "lower"; - } else { - return "upper"; + /** + * Returns the capitalization state of the string - + * Whether the first character is uppercase, lowercase, or non-alphabetic + * @param {string} str String + * @returns {string} capitalization state: "non-alpha", "lower", or "upper" + */ + function getCap(str) { + var firstChar = str.charAt(0); + + var firstCharLower = firstChar.toLowerCase(); + var firstCharUpper = firstChar.toUpperCase(); + + if (firstCharLower === firstCharUpper) { + + // char has no uppercase variant, so it's non-alphabetic + return "non-alpha"; + } else if (firstChar === firstCharLower) { + return "lower"; + } else { + return "upper"; + } } - } - /** - * Check if capitalization is allowed for a CallExpression - * @param {Object} allowedMap Object mapping calleeName to a Boolean - * @param {ASTNode} node CallExpression node - * @param {string} calleeName Capitalized callee name from a CallExpression - * @returns {Boolean} Returns true if the callee may be capitalized - */ - function isCapAllowed(allowedMap, node, calleeName) { - if (allowedMap[calleeName] || allowedMap[context.getSource(node.callee)]) { - return true; - } + /** + * Check if capitalization is allowed for a CallExpression + * @param {Object} allowedMap Object mapping calleeName to a Boolean + * @param {ASTNode} node CallExpression node + * @param {string} calleeName Capitalized callee name from a CallExpression + * @returns {Boolean} Returns true if the callee may be capitalized + */ + function isCapAllowed(allowedMap, node, calleeName) { + if (allowedMap[calleeName] || allowedMap[context.getSource(node.callee)]) { + return true; + } - if (calleeName === "UTC" && node.callee.type === "MemberExpression") { + if (calleeName === "UTC" && node.callee.type === "MemberExpression") { + + // allow if callee is Date.UTC + return node.callee.object.type === "Identifier" && + node.callee.object.name === "Date"; + } - // allow if callee is Date.UTC - return node.callee.object.type === "Identifier" && - node.callee.object.name === "Date"; + return skipProperties && node.callee.type === "MemberExpression"; } - return skipProperties && node.callee.type === "MemberExpression"; - } + /** + * Reports the given message for the given node. The location will be the start of the property or the callee. + * @param {ASTNode} node CallExpression or NewExpression node. + * @param {string} message The message to report. + * @returns {void} + */ + function report(node, message) { + var callee = node.callee; + + if (callee.type === "MemberExpression") { + callee = callee.property; + } - /** - * Reports the given message for the given node. The location will be the start of the property or the callee. - * @param {ASTNode} node CallExpression or NewExpression node. - * @param {string} message The message to report. - * @returns {void} - */ - function report(node, message) { - var callee = node.callee; - - if (callee.type === "MemberExpression") { - callee = callee.property; + context.report(node, callee.loc.start, message); } - context.report(node, callee.loc.start, message); - } - - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- - if (config.newIsCap) { - listeners.NewExpression = function(node) { + if (config.newIsCap) { + listeners.NewExpression = function(node) { - var constructorName = extractNameFromExpression(node); + var constructorName = extractNameFromExpression(node); - if (constructorName) { - var capitalization = getCap(constructorName); - var isAllowed = capitalization !== "lower" || isCapAllowed(newIsCapExceptions, node, constructorName); + if (constructorName) { + var capitalization = getCap(constructorName); + var isAllowed = capitalization !== "lower" || isCapAllowed(newIsCapExceptions, node, constructorName); - if (!isAllowed) { - report(node, "A constructor name should not start with a lowercase letter."); + if (!isAllowed) { + report(node, "A constructor name should not start with a lowercase letter."); + } } - } - }; - } + }; + } - if (config.capIsNew) { - listeners.CallExpression = function(node) { + if (config.capIsNew) { + listeners.CallExpression = function(node) { - var calleeName = extractNameFromExpression(node); + var calleeName = extractNameFromExpression(node); - if (calleeName) { - var capitalization = getCap(calleeName); - var isAllowed = capitalization !== "upper" || isCapAllowed(capIsNewExceptions, node, calleeName); + if (calleeName) { + var capitalization = getCap(calleeName); + var isAllowed = capitalization !== "upper" || isCapAllowed(capIsNewExceptions, node, calleeName); - if (!isAllowed) { - report(node, "A function with a name starting with an uppercase letter should only be used as a constructor."); + if (!isAllowed) { + report(node, "A function with a name starting with an uppercase letter should only be used as a constructor."); + } } - } - }; - } - - return listeners; -}; + }; + } -module.exports.schema = [ - { - "type": "object", - "properties": { - "newIsCap": { - "type": "boolean" - }, - "capIsNew": { - "type": "boolean" - }, - "newIsCapExceptions": { - "type": "array", - "items": { - "type": "string" - } - }, - "capIsNewExceptions": { - "type": "array", - "items": { - "type": "string" - } - }, - "properties": { - "type": "boolean" - } - }, - "additionalProperties": false + return listeners; } -]; +}; diff --git a/tools/eslint/lib/rules/new-parens.js b/tools/eslint/lib/rules/new-parens.js index 13c8e3d8248b3e..0d7a84e3cc4b07 100644 --- a/tools/eslint/lib/rules/new-parens.js +++ b/tools/eslint/lib/rules/new-parens.js @@ -9,22 +9,32 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - return { - - "NewExpression": function(node) { - var tokens = context.getTokens(node); - var prenticesTokens = tokens.filter(function(token) { - return token.value === "(" || token.value === ")"; - }); - - if (prenticesTokens.length < 2) { - context.report(node, "Missing '()' invoking a constructor"); +module.exports = { + meta: { + docs: { + description: "require parentheses when invoking a constructor with no arguments", + category: "Stylistic Issues", + recommended: false + }, + + schema: [] + }, + + create: function(context) { + + return { + + NewExpression: function(node) { + var tokens = context.getTokens(node); + var prenticesTokens = tokens.filter(function(token) { + return token.value === "(" || token.value === ")"; + }); + + if (prenticesTokens.length < 2) { + context.report(node, "Missing '()' invoking a constructor"); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/newline-after-var.js b/tools/eslint/lib/rules/newline-after-var.js index 34431e2c8cddcd..fd80c8c5422d97 100644 --- a/tools/eslint/lib/rules/newline-after-var.js +++ b/tools/eslint/lib/rules/newline-after-var.js @@ -1,9 +1,6 @@ /** * @fileoverview Rule to check empty newline after "var" statement * @author Gopal Venkatesan - * @copyright 2015 Gopal Venkatesan. All rights reserved. - * @copyright 2015 Casey Visco. All rights reserved. - * @copyright 2015 Ian VanSchooten. All rights reserved. */ "use strict"; @@ -12,159 +9,169 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - var ALWAYS_MESSAGE = "Expected blank line after variable declarations.", - NEVER_MESSAGE = "Unexpected blank line after variable declarations."; - - var sourceCode = context.getSourceCode(); - - // Default `mode` to "always". - var mode = context.options[0] === "never" ? "never" : "always"; - - // Cache starting and ending line numbers of comments for faster lookup - var commentEndLine = context.getAllComments().reduce(function(result, token) { - result[token.loc.start.line] = token.loc.end.line; - return result; - }, {}); - - - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- - - /** - * Determine if provided keyword is a variable declaration - * @private - * @param {string} keyword - keyword to test - * @returns {boolean} True if `keyword` is a type of var - */ - function isVar(keyword) { - return keyword === "var" || keyword === "let" || keyword === "const"; - } - - /** - * Determine if provided keyword is a variant of for specifiers - * @private - * @param {string} keyword - keyword to test - * @returns {boolean} True if `keyword` is a variant of for specifier - */ - function isForTypeSpecifier(keyword) { - return keyword === "ForStatement" || keyword === "ForInStatement" || keyword === "ForOfStatement"; - } - - /** - * Determine if provided keyword is an export specifiers - * @private - * @param {string} nodeType - nodeType to test - * @returns {boolean} True if `nodeType` is an export specifier - */ - function isExportSpecifier(nodeType) { - return nodeType === "ExportNamedDeclaration" || nodeType === "ExportSpecifier" || - nodeType === "ExportDefaultDeclaration" || nodeType === "ExportAllDeclaration"; - } - - /** - * Determine if provided node is the last of their parent block. - * @private - * @param {ASTNode} node - node to test - * @returns {boolean} True if `node` is last of their parent block. - */ - function isLastNode(node) { - var token = sourceCode.getTokenAfter(node); - - return !token || (token.type === "Punctuator" && token.value === "}"); - } - - /** - * Determine if a token starts more than one line after a comment ends - * @param {token} token The token being checked - * @param {integer} commentStartLine The line number on which the comment starts - * @returns {boolean} True if `token` does not start immediately after a comment - */ - function hasBlankLineAfterComment(token, commentStartLine) { - var commentEnd = commentEndLine[commentStartLine]; - - // If there's another comment, repeat check for blank line - if (commentEndLine[commentEnd + 1]) { - return hasBlankLineAfterComment(token, commentEnd + 1); +module.exports = { + meta: { + docs: { + description: "require or disallow an empty line after `var` declarations", + category: "Stylistic Issues", + recommended: false + }, + + schema: [ + { + enum: ["never", "always"] + } + ] + }, + + create: function(context) { + + var ALWAYS_MESSAGE = "Expected blank line after variable declarations.", + NEVER_MESSAGE = "Unexpected blank line after variable declarations."; + + var sourceCode = context.getSourceCode(); + + // Default `mode` to "always". + var mode = context.options[0] === "never" ? "never" : "always"; + + // Cache starting and ending line numbers of comments for faster lookup + var commentEndLine = context.getAllComments().reduce(function(result, token) { + result[token.loc.start.line] = token.loc.end.line; + return result; + }, {}); + + + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- + + /** + * Determine if provided keyword is a variable declaration + * @private + * @param {string} keyword - keyword to test + * @returns {boolean} True if `keyword` is a type of var + */ + function isVar(keyword) { + return keyword === "var" || keyword === "let" || keyword === "const"; } - return (token.loc.start.line > commentEndLine[commentStartLine] + 1); - } - - /** - * Checks that a blank line exists after a variable declaration when mode is - * set to "always", or checks that there is no blank line when mode is set - * to "never" - * @private - * @param {ASTNode} node - `VariableDeclaration` node to test - * @returns {void} - */ - function checkForBlankLine(node) { - var lastToken = sourceCode.getLastToken(node), - nextToken = sourceCode.getTokenAfter(node), - nextLineNum = lastToken.loc.end.line + 1, - noNextLineToken, - hasNextLineComment; - - // Ignore if there is no following statement - if (!nextToken) { - return; + /** + * Determine if provided keyword is a variant of for specifiers + * @private + * @param {string} keyword - keyword to test + * @returns {boolean} True if `keyword` is a variant of for specifier + */ + function isForTypeSpecifier(keyword) { + return keyword === "ForStatement" || keyword === "ForInStatement" || keyword === "ForOfStatement"; } - // Ignore if parent of node is a for variant - if (isForTypeSpecifier(node.parent.type)) { - return; + /** + * Determine if provided keyword is an export specifiers + * @private + * @param {string} nodeType - nodeType to test + * @returns {boolean} True if `nodeType` is an export specifier + */ + function isExportSpecifier(nodeType) { + return nodeType === "ExportNamedDeclaration" || nodeType === "ExportSpecifier" || + nodeType === "ExportDefaultDeclaration" || nodeType === "ExportAllDeclaration"; } - // Ignore if parent of node is an export specifier - if (isExportSpecifier(node.parent.type)) { - return; - } + /** + * Determine if provided node is the last of their parent block. + * @private + * @param {ASTNode} node - node to test + * @returns {boolean} True if `node` is last of their parent block. + */ + function isLastNode(node) { + var token = sourceCode.getTokenAfter(node); - // Some coding styles use multiple `var` statements, so do nothing if - // the next token is a `var` statement. - if (nextToken.type === "Keyword" && isVar(nextToken.value)) { - return; + return !token || (token.type === "Punctuator" && token.value === "}"); } - // Ignore if it is last statement in a block - if (isLastNode(node)) { - return; + /** + * Determine if a token starts more than one line after a comment ends + * @param {token} token The token being checked + * @param {integer} commentStartLine The line number on which the comment starts + * @returns {boolean} True if `token` does not start immediately after a comment + */ + function hasBlankLineAfterComment(token, commentStartLine) { + var commentEnd = commentEndLine[commentStartLine]; + + // If there's another comment, repeat check for blank line + if (commentEndLine[commentEnd + 1]) { + return hasBlankLineAfterComment(token, commentEnd + 1); + } + + return (token.loc.start.line > commentEndLine[commentStartLine] + 1); } - // Next statement is not a `var`... - noNextLineToken = nextToken.loc.start.line > nextLineNum; - hasNextLineComment = (typeof commentEndLine[nextLineNum] !== "undefined"); - - if (mode === "never" && noNextLineToken && !hasNextLineComment) { - context.report(node, NEVER_MESSAGE, { identifier: node.name }); + /** + * Checks that a blank line exists after a variable declaration when mode is + * set to "always", or checks that there is no blank line when mode is set + * to "never" + * @private + * @param {ASTNode} node - `VariableDeclaration` node to test + * @returns {void} + */ + function checkForBlankLine(node) { + var lastToken = sourceCode.getLastToken(node), + nextToken = sourceCode.getTokenAfter(node), + nextLineNum = lastToken.loc.end.line + 1, + noNextLineToken, + hasNextLineComment; + + // Ignore if there is no following statement + if (!nextToken) { + return; + } + + // Ignore if parent of node is a for variant + if (isForTypeSpecifier(node.parent.type)) { + return; + } + + // Ignore if parent of node is an export specifier + if (isExportSpecifier(node.parent.type)) { + return; + } + + // Some coding styles use multiple `var` statements, so do nothing if + // the next token is a `var` statement. + if (nextToken.type === "Keyword" && isVar(nextToken.value)) { + return; + } + + // Ignore if it is last statement in a block + if (isLastNode(node)) { + return; + } + + // Next statement is not a `var`... + noNextLineToken = nextToken.loc.start.line > nextLineNum; + hasNextLineComment = (typeof commentEndLine[nextLineNum] !== "undefined"); + + if (mode === "never" && noNextLineToken && !hasNextLineComment) { + context.report(node, NEVER_MESSAGE, { identifier: node.name }); + } + + // Token on the next line, or comment without blank line + if ( + mode === "always" && ( + !noNextLineToken || + hasNextLineComment && !hasBlankLineAfterComment(nextToken, nextLineNum) + ) + ) { + context.report(node, ALWAYS_MESSAGE, { identifier: node.name }); + } } - // Token on the next line, or comment without blank line - if ( - mode === "always" && ( - !noNextLineToken || - hasNextLineComment && !hasBlankLineAfterComment(nextToken, nextLineNum) - ) - ) { - context.report(node, ALWAYS_MESSAGE, { identifier: node.name }); - } - } - - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- - return { - "VariableDeclaration": checkForBlankLine - }; + return { + VariableDeclaration: checkForBlankLine + }; -}; - -module.exports.schema = [ - { - "enum": ["never", "always"] } -]; +}; diff --git a/tools/eslint/lib/rules/newline-before-return.js b/tools/eslint/lib/rules/newline-before-return.js index 6cc2944a435c19..77f3aedaa80868 100644 --- a/tools/eslint/lib/rules/newline-before-return.js +++ b/tools/eslint/lib/rules/newline-before-return.js @@ -1,9 +1,6 @@ - /** * @fileoverview Rule to require newlines before `return` statement * @author Kai Cataldo - * @copyright 2016 Kai Cataldo. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; @@ -11,133 +8,159 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var sourceCode = context.getSourceCode(); - - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- - - /** - * Tests whether node is preceded by supplied tokens - * @param {ASTNode} node - node to check - * @param {array} testTokens - array of tokens to test against - * @returns {boolean} Whether or not the node is preceded by one of the supplied tokens - * @private - */ - function isPrecededByTokens(node, testTokens) { - var tokenBefore = sourceCode.getTokenBefore(node); - - return testTokens.some(function(token) { - return tokenBefore.value === token; - }); - } - - /** - * Checks whether node is the first node after statement or in block - * @param {ASTNode} node - node to check - * @returns {boolean} Whether or not the node is the first node after statement or in block - * @private - */ - function isFirstNode(node) { - var parentType = node.parent.type; - - if (node.parent.body) { - return Array.isArray(node.parent.body) - ? node.parent.body[0] === node - : node.parent.body === node; +module.exports = { + meta: { + docs: { + description: "require an empty line before `return` statements", + category: "Stylistic Issues", + recommended: false + }, + + schema: [] + }, + + create: function(context) { + var sourceCode = context.getSourceCode(); + + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- + + /** + * Tests whether node is preceded by supplied tokens + * @param {ASTNode} node - node to check + * @param {array} testTokens - array of tokens to test against + * @returns {boolean} Whether or not the node is preceded by one of the supplied tokens + * @private + */ + function isPrecededByTokens(node, testTokens) { + var tokenBefore = sourceCode.getTokenBefore(node); + + return testTokens.some(function(token) { + return tokenBefore.value === token; + }); } - if (parentType === "IfStatement") { - return isPrecededByTokens(node, ["else", ")"]); - } else if (parentType === "DoWhileStatement") { - return isPrecededByTokens(node, ["do"]); - } else if (parentType === "SwitchCase") { - return isPrecededByTokens(node, [":"]); - } else { - return isPrecededByTokens(node, [")"]); - } - } - - /** - * Returns the number of lines of comments that precede the node - * @param {ASTNode} node - node to check for overlapping comments - * @param {token} tokenBefore - previous token to check for overlapping comments - * @returns {number} Number of lines of comments that precede the node - * @private - */ - function calcCommentLines(node, tokenBefore) { - var comments = sourceCode.getComments(node).leading; - var numLinesComments = 0; - - if (!comments.length) { - return numLinesComments; - } - - comments.forEach(function(comment) { - numLinesComments++; - - if (comment.type === "Block") { - numLinesComments += comment.loc.end.line - comment.loc.start.line; + /** + * Checks whether node is the first node after statement or in block + * @param {ASTNode} node - node to check + * @returns {boolean} Whether or not the node is the first node after statement or in block + * @private + */ + function isFirstNode(node) { + var parentType = node.parent.type; + + if (node.parent.body) { + return Array.isArray(node.parent.body) + ? node.parent.body[0] === node + : node.parent.body === node; } - // avoid counting lines with inline comments twice - if (comment.loc.start.line === tokenBefore.loc.end.line) { - numLinesComments--; + if (parentType === "IfStatement") { + return isPrecededByTokens(node, ["else", ")"]); + } else if (parentType === "DoWhileStatement") { + return isPrecededByTokens(node, ["do"]); + } else if (parentType === "SwitchCase") { + return isPrecededByTokens(node, [":"]); + } else { + return isPrecededByTokens(node, [")"]); } + } - if (comment.loc.end.line === node.loc.start.line) { - numLinesComments--; + /** + * Returns the number of lines of comments that precede the node + * @param {ASTNode} node - node to check for overlapping comments + * @param {number} lineNumTokenBefore - line number of previous token, to check for overlapping comments + * @returns {number} Number of lines of comments that precede the node + * @private + */ + function calcCommentLines(node, lineNumTokenBefore) { + var comments = sourceCode.getComments(node).leading, + numLinesComments = 0; + + if (!comments.length) { + return numLinesComments; } - }); - return numLinesComments; - } + comments.forEach(function(comment) { + numLinesComments++; - /** - * Checks whether node is preceded by a newline - * @param {ASTNode} node - node to check - * @returns {boolean} Whether or not the node is preceded by a newline - * @private - */ - function hasNewlineBefore(node) { - var tokenBefore = sourceCode.getTokenBefore(node); - var lineNumTokenBefore = tokenBefore.loc.end.line; - var lineNumNode = node.loc.start.line; - var commentLines = calcCommentLines(node, tokenBefore); - - return (lineNumNode - lineNumTokenBefore - commentLines) > 1; - } + if (comment.type === "Block") { + numLinesComments += comment.loc.end.line - comment.loc.start.line; + } - /** - * Reports expected/unexpected newline before return statement - * @param {ASTNode} node - the node to report in the event of an error - * @param {boolean} isExpected - whether the newline is expected or not - * @returns {void} - * @private - */ - function reportError(node, isExpected) { - var expected = isExpected ? "Expected" : "Unexpected"; - - context.report({ - node: node, - message: expected + " newline before return statement." - }); - } + // avoid counting lines with inline comments twice + if (comment.loc.start.line === lineNumTokenBefore) { + numLinesComments--; + } + + if (comment.loc.end.line === node.loc.start.line) { + numLinesComments--; + } + }); - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- + return numLinesComments; + } - return { - ReturnStatement: function(node) { - if (isFirstNode(node) && hasNewlineBefore(node)) { - reportError(node, false); - } else if (!isFirstNode(node) && !hasNewlineBefore(node)) { - reportError(node, true); + /** + * Checks whether node is preceded by a newline + * @param {ASTNode} node - node to check + * @returns {boolean} Whether or not the node is preceded by a newline + * @private + */ + function hasNewlineBefore(node) { + var tokenBefore = sourceCode.getTokenBefore(node), + lineNumNode = node.loc.start.line, + lineNumTokenBefore, + commentLines; + + /** + * Global return (at the beginning of a script) is a special case. + * If there is no token before `return`, then we expect no line + * break before the return. Comments are allowed to occupy lines + * before the global return, just no blank lines. + * Setting lineNumTokenBefore to zero in that case results in the + * desired behavior. + */ + if (tokenBefore) { + lineNumTokenBefore = tokenBefore.loc.end.line; + } else { + lineNumTokenBefore = 0; // global return at beginning of script } + + commentLines = calcCommentLines(node, lineNumTokenBefore); + + return (lineNumNode - lineNumTokenBefore - commentLines) > 1; + } + + /** + * Reports expected/unexpected newline before return statement + * @param {ASTNode} node - the node to report in the event of an error + * @param {boolean} isExpected - whether the newline is expected or not + * @returns {void} + * @private + */ + function reportError(node, isExpected) { + var expected = isExpected ? "Expected" : "Unexpected"; + + context.report({ + node: node, + message: expected + " newline before return statement." + }); } - }; -}; -module.exports.schema = []; + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + return { + ReturnStatement: function(node) { + if (isFirstNode(node) && hasNewlineBefore(node)) { + reportError(node, false); + } else if (!isFirstNode(node) && !hasNewlineBefore(node)) { + reportError(node, true); + } + } + }; + } +}; diff --git a/tools/eslint/lib/rules/newline-per-chained-call.js b/tools/eslint/lib/rules/newline-per-chained-call.js index f7df4c29d66112..80401415aa8033 100644 --- a/tools/eslint/lib/rules/newline-per-chained-call.js +++ b/tools/eslint/lib/rules/newline-per-chained-call.js @@ -2,8 +2,6 @@ * @fileoverview Rule to ensure newline per method call when chaining calls * @author Rajendra Patil * @author Burak Yigit Kaya - * @copyright 2016 Rajendra Patil. All rights reserved. - * @copyright 2016 Burak Yigit Kaya. All rights reserved. */ "use strict"; @@ -12,45 +10,55 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "require a newline after each call in a method chain", + category: "Stylistic Issues", + recommended: false + }, - var options = context.options[0] || {}, - ignoreChainWithDepth = options.ignoreChainWithDepth || 2; + schema: [{ + type: "object", + properties: { + ignoreChainWithDepth: { + type: "integer", + minimum: 1, + maximum: 10 + } + }, + additionalProperties: false + }] + }, - return { - "CallExpression:exit": function(node) { - if (!node.callee || node.callee.type !== "MemberExpression") { - return; - } + create: function(context) { - var callee = node.callee; - var parent = callee.object; - var depth = 1; + var options = context.options[0] || {}, + ignoreChainWithDepth = options.ignoreChainWithDepth || 2; - while (parent && parent.callee) { - depth += 1; - parent = parent.callee.object; - } + return { + "CallExpression:exit": function(node) { + if (!node.callee || node.callee.type !== "MemberExpression") { + return; + } + + var callee = node.callee; + var parent = callee.object; + var depth = 1; - if (depth > ignoreChainWithDepth && callee.property.loc.start.line === callee.object.loc.end.line) { - context.report( - callee.property, - callee.property.loc.start, - "Expected line break after `" + context.getSource(callee.object).replace(/\r\n|\r|\n/g, "\\n") + "`." - ); + while (parent && parent.callee) { + depth += 1; + parent = parent.callee.object; + } + + if (depth > ignoreChainWithDepth && callee.property.loc.start.line === callee.object.loc.end.line) { + context.report( + callee.property, + callee.property.loc.start, + "Expected line break after `" + context.getSource(callee.object).replace(/\r\n|\r|\n/g, "\\n") + "`." + ); + } } - } - }; + }; + } }; - -module.exports.schema = [{ - "type": "object", - "properties": { - "ignoreChainWithDepth": { - "type": "integer", - "minimum": 1, - "maximum": 10 - } - }, - "additionalProperties": false -}]; diff --git a/tools/eslint/lib/rules/no-alert.js b/tools/eslint/lib/rules/no-alert.js index ea1e689544840a..e491dfefc5504e 100644 --- a/tools/eslint/lib/rules/no-alert.js +++ b/tools/eslint/lib/rules/no-alert.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to flag use of alert, confirm, prompt * @author Nicholas C. Zakas - * @copyright 2015 Mathias Schreck - * @copyright 2013 Nicholas C. Zakas */ "use strict"; @@ -98,39 +96,49 @@ function isGlobalThisReferenceOrGlobalWindow(scope, globalScope, node) { // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var globalScope; +module.exports = { + meta: { + docs: { + description: "disallow the use of `alert`, `confirm`, and `prompt`", + category: "Best Practices", + recommended: false + }, - return { + schema: [] + }, - "Program": function() { - globalScope = context.getScope(); - }, + create: function(context) { + var globalScope; - "CallExpression": function(node) { - var callee = node.callee, - identifierName, - currentScope = context.getScope(); + return { - // without window. - if (callee.type === "Identifier") { - identifierName = callee.name; + Program: function() { + globalScope = context.getScope(); + }, - if (!isShadowed(currentScope, globalScope, callee) && isProhibitedIdentifier(callee.name)) { - report(context, node, identifierName); - } + CallExpression: function(node) { + var callee = node.callee, + identifierName, + currentScope = context.getScope(); + + // without window. + if (callee.type === "Identifier") { + identifierName = callee.name; + + if (!isShadowed(currentScope, globalScope, callee) && isProhibitedIdentifier(callee.name)) { + report(context, node, identifierName); + } - } else if (callee.type === "MemberExpression" && isGlobalThisReferenceOrGlobalWindow(currentScope, globalScope, callee.object)) { - identifierName = getPropertyName(callee); + } else if (callee.type === "MemberExpression" && isGlobalThisReferenceOrGlobalWindow(currentScope, globalScope, callee.object)) { + identifierName = getPropertyName(callee); - if (isProhibitedIdentifier(identifierName)) { - report(context, node, identifierName); + if (isProhibitedIdentifier(identifierName)) { + report(context, node, identifierName); + } } - } - } - }; + } + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-array-constructor.js b/tools/eslint/lib/rules/no-array-constructor.js index ecf5837228b12a..389725c62c7305 100644 --- a/tools/eslint/lib/rules/no-array-constructor.js +++ b/tools/eslint/lib/rules/no-array-constructor.js @@ -9,29 +9,39 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - /** - * Disallow construction of dense arrays using the Array constructor - * @param {ASTNode} node node to evaluate - * @returns {void} - * @private - */ - function check(node) { - if ( - node.arguments.length !== 1 && - node.callee.type === "Identifier" && - node.callee.name === "Array" - ) { - context.report(node, "The array literal notation [] is preferrable."); +module.exports = { + meta: { + docs: { + description: "disallow `Array` constructors", + category: "Stylistic Issues", + recommended: false + }, + + schema: [] + }, + + create: function(context) { + + /** + * Disallow construction of dense arrays using the Array constructor + * @param {ASTNode} node node to evaluate + * @returns {void} + * @private + */ + function check(node) { + if ( + node.arguments.length !== 1 && + node.callee.type === "Identifier" && + node.callee.name === "Array" + ) { + context.report(node, "The array literal notation [] is preferrable."); + } } - } - return { - "CallExpression": check, - "NewExpression": check - }; + return { + CallExpression: check, + NewExpression: check + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-bitwise.js b/tools/eslint/lib/rules/no-bitwise.js index 9655525396e7e3..0294998ecc1022 100644 --- a/tools/eslint/lib/rules/no-bitwise.js +++ b/tools/eslint/lib/rules/no-bitwise.js @@ -18,82 +18,92 @@ var BITWISE_OPERATORS = [ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var options = context.options[0] || {}; - var allowed = options.allow || []; - var int32Hint = options.int32Hint === true; - - /** - * Reports an unexpected use of a bitwise operator. - * @param {ASTNode} node Node which contains the bitwise operator. - * @returns {void} - */ - function report(node) { - context.report(node, "Unexpected use of '{{operator}}'.", { operator: node.operator }); - } +module.exports = { + meta: { + docs: { + description: "disallow bitwise operators", + category: "Stylistic Issues", + recommended: false + }, - /** - * Checks if the given node has a bitwise operator. - * @param {ASTNode} node The node to check. - * @returns {boolean} Whether or not the node has a bitwise operator. - */ - function hasBitwiseOperator(node) { - return BITWISE_OPERATORS.indexOf(node.operator) !== -1; - } + schema: [ + { + type: "object", + properties: { + allow: { + type: "array", + items: { + enum: BITWISE_OPERATORS + }, + uniqueItems: true + }, + int32Hint: { + type: "boolean" + } + }, + additionalProperties: false + } + ] + }, - /** - * Checks if exceptions were provided, e.g. `{ allow: ['~', '|'] }`. - * @param {ASTNode} node The node to check. - * @returns {boolean} Whether or not the node has a bitwise operator. - */ - function allowedOperator(node) { - return allowed.indexOf(node.operator) !== -1; - } + create: function(context) { + var options = context.options[0] || {}; + var allowed = options.allow || []; + var int32Hint = options.int32Hint === true; - /** - * Checks if the given bitwise operator is used for integer typecasting, i.e. "|0" - * @param {ASTNode} node The node to check. - * @returns {boolean} whether the node is used in integer typecasting. - */ - function isInt32Hint(node) { - return int32Hint && node.operator === "|" && node.right && - node.right.type === "Literal" && node.right.value === 0; - } + /** + * Reports an unexpected use of a bitwise operator. + * @param {ASTNode} node Node which contains the bitwise operator. + * @returns {void} + */ + function report(node) { + context.report(node, "Unexpected use of '{{operator}}'.", { operator: node.operator }); + } - /** - * Report if the given node contains a bitwise operator. - * @param {ASTNode} node The node to check. - * @returns {void} - */ - function checkNodeForBitwiseOperator(node) { - if (hasBitwiseOperator(node) && !allowedOperator(node) && !isInt32Hint(node)) { - report(node); + /** + * Checks if the given node has a bitwise operator. + * @param {ASTNode} node The node to check. + * @returns {boolean} Whether or not the node has a bitwise operator. + */ + function hasBitwiseOperator(node) { + return BITWISE_OPERATORS.indexOf(node.operator) !== -1; } - } - return { - "AssignmentExpression": checkNodeForBitwiseOperator, - "BinaryExpression": checkNodeForBitwiseOperator, - "UnaryExpression": checkNodeForBitwiseOperator - }; + /** + * Checks if exceptions were provided, e.g. `{ allow: ['~', '|'] }`. + * @param {ASTNode} node The node to check. + * @returns {boolean} Whether or not the node has a bitwise operator. + */ + function allowedOperator(node) { + return allowed.indexOf(node.operator) !== -1; + } -}; + /** + * Checks if the given bitwise operator is used for integer typecasting, i.e. "|0" + * @param {ASTNode} node The node to check. + * @returns {boolean} whether the node is used in integer typecasting. + */ + function isInt32Hint(node) { + return int32Hint && node.operator === "|" && node.right && + node.right.type === "Literal" && node.right.value === 0; + } -module.exports.schema = [ - { - "type": "object", - "properties": { - "allow": { - "type": "array", - "items": { - "enum": BITWISE_OPERATORS - }, - "uniqueItems": true - }, - "int32Hint": { - "type": "boolean" + /** + * Report if the given node contains a bitwise operator. + * @param {ASTNode} node The node to check. + * @returns {void} + */ + function checkNodeForBitwiseOperator(node) { + if (hasBitwiseOperator(node) && !allowedOperator(node) && !isInt32Hint(node)) { + report(node); } - }, - "additionalProperties": false + } + + return { + AssignmentExpression: checkNodeForBitwiseOperator, + BinaryExpression: checkNodeForBitwiseOperator, + UnaryExpression: checkNodeForBitwiseOperator + }; + } -]; +}; diff --git a/tools/eslint/lib/rules/no-caller.js b/tools/eslint/lib/rules/no-caller.js index aacb3feffbeb46..0405fdaeb90303 100644 --- a/tools/eslint/lib/rules/no-caller.js +++ b/tools/eslint/lib/rules/no-caller.js @@ -9,21 +9,31 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow the use of `arguments.caller` or `arguments.callee`", + category: "Best Practices", + recommended: false + }, - return { + schema: [] + }, - "MemberExpression": function(node) { - var objectName = node.object.name, - propertyName = node.property.name; + create: function(context) { - if (objectName === "arguments" && !node.computed && propertyName && propertyName.match(/^calle[er]$/)) { - context.report(node, "Avoid arguments.{{property}}.", { property: propertyName }); - } + return { - } - }; + MemberExpression: function(node) { + var objectName = node.object.name, + propertyName = node.property.name; -}; + if (objectName === "arguments" && !node.computed && propertyName && propertyName.match(/^calle[er]$/)) { + context.report(node, "Avoid arguments.{{property}}.", { property: propertyName }); + } -module.exports.schema = []; + } + }; + + } +}; diff --git a/tools/eslint/lib/rules/no-case-declarations.js b/tools/eslint/lib/rules/no-case-declarations.js index 4969d4f1bf1a32..8ef202538ec573 100644 --- a/tools/eslint/lib/rules/no-case-declarations.js +++ b/tools/eslint/lib/rules/no-case-declarations.js @@ -1,7 +1,6 @@ /** * @fileoverview Rule to flag use of an lexical declarations inside a case clause * @author Erik Arvidsson - * @copyright 2015 Erik Arvidsson. All rights reserved. */ "use strict"; @@ -9,40 +8,50 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - /** - * Checks whether or not a node is a lexical declaration. - * @param {ASTNode} node A direct child statement of a switch case. - * @returns {boolean} Whether or not the node is a lexical declaration. - */ - function isLexicalDeclaration(node) { - switch (node.type) { - case "FunctionDeclaration": - case "ClassDeclaration": - return true; - case "VariableDeclaration": - return node.kind !== "var"; - default: - return false; +module.exports = { + meta: { + docs: { + description: "disallow lexical declarations in case clauses", + category: "Best Practices", + recommended: true + }, + + schema: [] + }, + + create: function(context) { + + /** + * Checks whether or not a node is a lexical declaration. + * @param {ASTNode} node A direct child statement of a switch case. + * @returns {boolean} Whether or not the node is a lexical declaration. + */ + function isLexicalDeclaration(node) { + switch (node.type) { + case "FunctionDeclaration": + case "ClassDeclaration": + return true; + case "VariableDeclaration": + return node.kind !== "var"; + default: + return false; + } } - } - return { - "SwitchCase": function(node) { - for (var i = 0; i < node.consequent.length; i++) { - var statement = node.consequent[i]; + return { + SwitchCase: function(node) { + for (var i = 0; i < node.consequent.length; i++) { + var statement = node.consequent[i]; - if (isLexicalDeclaration(statement)) { - context.report({ - node: node, - message: "Unexpected lexical declaration in case block." - }); + if (isLexicalDeclaration(statement)) { + context.report({ + node: node, + message: "Unexpected lexical declaration in case block." + }); + } } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-catch-shadow.js b/tools/eslint/lib/rules/no-catch-shadow.js index 88eeb02fa6182c..4a206833c08928 100644 --- a/tools/eslint/lib/rules/no-catch-shadow.js +++ b/tools/eslint/lib/rules/no-catch-shadow.js @@ -15,44 +15,54 @@ var astUtils = require("../ast-utils"); // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- - - /** - * Check if the parameters are been shadowed - * @param {object} scope current scope - * @param {string} name parameter name - * @returns {boolean} True is its been shadowed - */ - function paramIsShadowing(scope, name) { - return astUtils.getVariableByName(scope, name) !== null; - } +module.exports = { + meta: { + docs: { + description: "disallow `catch` clause parameters from shadowing variables in the outer scope", + category: "Variables", + recommended: false + }, - //-------------------------------------------------------------------------- - // Public API - //-------------------------------------------------------------------------- + schema: [] + }, - return { + create: function(context) { - "CatchClause": function(node) { - var scope = context.getScope(); + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- - // When blockBindings is enabled, CatchClause creates its own scope - // so start from one upper scope to exclude the current node - if (scope.block === node) { - scope = scope.upper; - } + /** + * Check if the parameters are been shadowed + * @param {object} scope current scope + * @param {string} name parameter name + * @returns {boolean} True is its been shadowed + */ + function paramIsShadowing(scope, name) { + return astUtils.getVariableByName(scope, name) !== null; + } + + //-------------------------------------------------------------------------- + // Public API + //-------------------------------------------------------------------------- + + return { - if (paramIsShadowing(scope, node.param.name)) { - context.report(node, "Value of '{{name}}' may be overwritten in IE 8 and earlier.", - { name: node.param.name }); + CatchClause: function(node) { + var scope = context.getScope(); + + // When blockBindings is enabled, CatchClause creates its own scope + // so start from one upper scope to exclude the current node + if (scope.block === node) { + scope = scope.upper; + } + + if (paramIsShadowing(scope, node.param.name)) { + context.report(node, "Value of '{{name}}' may be overwritten in IE 8 and earlier.", + { name: node.param.name }); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-class-assign.js b/tools/eslint/lib/rules/no-class-assign.js index 82f8e31fc34265..1e4d3243d8b918 100644 --- a/tools/eslint/lib/rules/no-class-assign.js +++ b/tools/eslint/lib/rules/no-class-assign.js @@ -1,7 +1,6 @@ /** * @fileoverview A rule to disallow modifying variables of class declarations * @author Toru Nagashima - * @copyright 2015 Toru Nagashima. All rights reserved. */ "use strict"; @@ -12,37 +11,47 @@ var astUtils = require("../ast-utils"); // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - /** - * Finds and reports references that are non initializer and writable. - * @param {Variable} variable - A variable to check. - * @returns {void} - */ - function checkVariable(variable) { - astUtils.getModifyingReferences(variable.references).forEach(function(reference) { - context.report( - reference.identifier, - "'{{name}}' is a class.", - {name: reference.identifier.name}); - - }); - } +module.exports = { + meta: { + docs: { + description: "disallow reassigning class members", + category: "ECMAScript 6", + recommended: true + }, + + schema: [] + }, + + create: function(context) { + + /** + * Finds and reports references that are non initializer and writable. + * @param {Variable} variable - A variable to check. + * @returns {void} + */ + function checkVariable(variable) { + astUtils.getModifyingReferences(variable.references).forEach(function(reference) { + context.report( + reference.identifier, + "'{{name}}' is a class.", + {name: reference.identifier.name}); + + }); + } + + /** + * Finds and reports references that are non initializer and writable. + * @param {ASTNode} node - A ClassDeclaration/ClassExpression node to check. + * @returns {void} + */ + function checkForClass(node) { + context.getDeclaredVariables(node).forEach(checkVariable); + } + + return { + ClassDeclaration: checkForClass, + ClassExpression: checkForClass + }; - /** - * Finds and reports references that are non initializer and writable. - * @param {ASTNode} node - A ClassDeclaration/ClassExpression node to check. - * @returns {void} - */ - function checkForClass(node) { - context.getDeclaredVariables(node).forEach(checkVariable); } - - return { - "ClassDeclaration": checkForClass, - "ClassExpression": checkForClass - }; - }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-cond-assign.js b/tools/eslint/lib/rules/no-cond-assign.js index f4bb8425cc77e1..27b99c6b545916 100644 --- a/tools/eslint/lib/rules/no-cond-assign.js +++ b/tools/eslint/lib/rules/no-cond-assign.js @@ -5,130 +5,140 @@ "use strict"; var NODE_DESCRIPTIONS = { - "DoWhileStatement": "a 'do...while' statement", - "ForStatement": "a 'for' statement", - "IfStatement": "an 'if' statement", - "WhileStatement": "a 'while' statement" + DoWhileStatement: "a 'do...while' statement", + ForStatement: "a 'for' statement", + IfStatement: "an 'if' statement", + WhileStatement: "a 'while' statement" }; //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - var prohibitAssign = (context.options[0] || "except-parens"); - - /** - * Check whether an AST node is the test expression for a conditional statement. - * @param {!Object} node The node to test. - * @returns {boolean} `true` if the node is the text expression for a conditional statement; otherwise, `false`. - */ - function isConditionalTestExpression(node) { - return node.parent && - node.parent.test && - node === node.parent.test; - } - - /** - * Given an AST node, perform a bottom-up search for the first ancestor that represents a conditional statement. - * @param {!Object} node The node to use at the start of the search. - * @returns {?Object} The closest ancestor node that represents a conditional statement. - */ - function findConditionalAncestor(node) { - var currentAncestor = node; - - do { - if (isConditionalTestExpression(currentAncestor)) { - return currentAncestor.parent; +module.exports = { + meta: { + docs: { + description: "disallow assignment operators in conditional expressions", + category: "Possible Errors", + recommended: true + }, + + schema: [ + { + enum: ["except-parens", "always"] } - } while ((currentAncestor = currentAncestor.parent)); + ] + }, + + create: function(context) { + + var prohibitAssign = (context.options[0] || "except-parens"); + + /** + * Check whether an AST node is the test expression for a conditional statement. + * @param {!Object} node The node to test. + * @returns {boolean} `true` if the node is the text expression for a conditional statement; otherwise, `false`. + */ + function isConditionalTestExpression(node) { + return node.parent && + node.parent.test && + node === node.parent.test; + } - return null; - } + /** + * Given an AST node, perform a bottom-up search for the first ancestor that represents a conditional statement. + * @param {!Object} node The node to use at the start of the search. + * @returns {?Object} The closest ancestor node that represents a conditional statement. + */ + function findConditionalAncestor(node) { + var currentAncestor = node; + + do { + if (isConditionalTestExpression(currentAncestor)) { + return currentAncestor.parent; + } + } while ((currentAncestor = currentAncestor.parent)); + + 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) { - var previousToken = context.getTokenBefore(node), - nextToken = context.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 parentheses. + * @param {!Object} node The node to test. + * @returns {boolean} `true` if the code is enclosed in parentheses; otherwise, `false`. + */ + function isParenthesised(node) { + var previousToken = context.getTokenBefore(node), + nextToken = context.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. - * @returns {boolean} `true` if the code is enclosed in two sets of parentheses; otherwise, `false`. - */ - function isParenthesisedTwice(node) { - var previousToken = context.getTokenBefore(node, 1), - nextToken = context.getTokenAfter(node, 1); - - return isParenthesised(node) && - 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. + * @returns {boolean} `true` if the code is enclosed in two sets of parentheses; otherwise, `false`. + */ + function isParenthesisedTwice(node) { + var previousToken = context.getTokenBefore(node, 1), + nextToken = context.getTokenAfter(node, 1); + + return isParenthesised(node) && + previousToken.value === "(" && previousToken.range[1] <= node.range[0] && + nextToken.value === ")" && nextToken.range[0] >= node.range[1]; + } - /** - * Check a conditional statement's test expression for top-level assignments that are not enclosed in parentheses. - * @param {!Object} node The node for the conditional statement. - * @returns {void} - */ - function testForAssign(node) { - if (node.test && - (node.test.type === "AssignmentExpression") && - (node.type === "ForStatement" ? - !isParenthesised(node.test) : - !isParenthesisedTwice(node.test) - ) - ) { - - // must match JSHint's error message - context.report({ - node: node, - loc: node.test.loc.start, - message: "Expected a conditional expression and instead saw an assignment." - }); + /** + * Check a conditional statement's test expression for top-level assignments that are not enclosed in parentheses. + * @param {!Object} node The node for the conditional statement. + * @returns {void} + */ + function testForAssign(node) { + if (node.test && + (node.test.type === "AssignmentExpression") && + (node.type === "ForStatement" ? + !isParenthesised(node.test) : + !isParenthesisedTwice(node.test) + ) + ) { + + // must match JSHint's error message + context.report({ + node: node, + loc: node.test.loc.start, + message: "Expected a conditional expression and instead saw an assignment." + }); + } + } + + /** + * Check whether an assignment expression is descended from a conditional statement's test expression. + * @param {!Object} node The node for the assignment expression. + * @returns {void} + */ + function testForConditionalAncestor(node) { + var ancestor = findConditionalAncestor(node); + + if (ancestor) { + context.report(ancestor, "Unexpected assignment within {{type}}.", { + type: NODE_DESCRIPTIONS[ancestor.type] || ancestor.type + }); + } } - } - /** - * Check whether an assignment expression is descended from a conditional statement's test expression. - * @param {!Object} node The node for the assignment expression. - * @returns {void} - */ - function testForConditionalAncestor(node) { - var ancestor = findConditionalAncestor(node); - - if (ancestor) { - context.report(ancestor, "Unexpected assignment within {{type}}.", { - type: NODE_DESCRIPTIONS[ancestor.type] || ancestor.type - }); + if (prohibitAssign === "always") { + return { + AssignmentExpression: testForConditionalAncestor + }; } - } - if (prohibitAssign === "always") { return { - "AssignmentExpression": testForConditionalAncestor + DoWhileStatement: testForAssign, + ForStatement: testForAssign, + IfStatement: testForAssign, + WhileStatement: testForAssign }; - } - - return { - "DoWhileStatement": testForAssign, - "ForStatement": testForAssign, - "IfStatement": testForAssign, - "WhileStatement": testForAssign - }; -}; - -module.exports.schema = [ - { - "enum": ["except-parens", "always"] } -]; +}; diff --git a/tools/eslint/lib/rules/no-confusing-arrow.js b/tools/eslint/lib/rules/no-confusing-arrow.js index 8756cf431d39fc..d951a53cf97685 100644 --- a/tools/eslint/lib/rules/no-confusing-arrow.js +++ b/tools/eslint/lib/rules/no-confusing-arrow.js @@ -2,28 +2,6 @@ * @fileoverview A rule to warn against using arrow functions when they could be * confused with comparisions * @author Jxck - * @copyright 2015 Luke Karrys. All rights reserved. - * The MIT License (MIT) - - * Copyright (c) 2015 Jxck - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. */ "use strict"; @@ -47,31 +25,41 @@ function isConditional(node) { // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var config = context.options[0] || {}; +module.exports = { + meta: { + docs: { + description: "disallow arrow functions where they could be confused with comparisons", + category: "ECMAScript 6", + recommended: false + }, + + schema: [{ + type: "object", + properties: { + allowParens: {type: "boolean"} + }, + additionalProperties: false + }] + }, - /** - * Reports if an arrow function contains an ambiguous conditional. - * @param {ASTNode} node - A node to check and report. - * @returns {void} - */ - function checkArrowFunc(node) { - var body = node.body; + create: function(context) { + var config = context.options[0] || {}; - if (isConditional(body) && !(config.allowParens && astUtils.isParenthesised(context, body))) { - context.report(node, "Arrow function used ambiguously with a conditional expression."); + /** + * Reports if an arrow function contains an ambiguous conditional. + * @param {ASTNode} node - A node to check and report. + * @returns {void} + */ + function checkArrowFunc(node) { + var body = node.body; + + if (isConditional(body) && !(config.allowParens && astUtils.isParenthesised(context, body))) { + context.report(node, "Arrow function used ambiguously with a conditional expression."); + } } - } - return { - "ArrowFunctionExpression": checkArrowFunc - }; + return { + ArrowFunctionExpression: checkArrowFunc + }; + } }; - -module.exports.schema = [{ - type: "object", - properties: { - allowParens: {type: "boolean"} - }, - additionalProperties: false -}]; diff --git a/tools/eslint/lib/rules/no-console.js b/tools/eslint/lib/rules/no-console.js index 3efbbd4f24f5f7..18a897409f6586 100644 --- a/tools/eslint/lib/rules/no-console.js +++ b/tools/eslint/lib/rules/no-console.js @@ -1,7 +1,6 @@ /** * @fileoverview Rule to flag use of console object * @author Nicholas C. Zakas - * @copyright 2016 Eric Correia. All rights reserved. */ "use strict"; @@ -10,47 +9,57 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow the use of `console`", + category: "Possible Errors", + recommended: true + }, - return { + schema: [ + { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string" + }, + minItems: 1, + uniqueItems: true + } + }, + additionalProperties: false + } + ] + }, - "MemberExpression": function(node) { + create: function(context) { - if (node.object.name === "console") { - var blockConsole = true; + return { - if (context.options.length > 0) { - var allowedProperties = context.options[0].allow; - var passedProperty = node.property.name; - var propertyIsAllowed = (allowedProperties.indexOf(passedProperty) > -1); + MemberExpression: function(node) { - if (propertyIsAllowed) { - blockConsole = false; + if (node.object.name === "console") { + var blockConsole = true; + + if (context.options.length > 0) { + var allowedProperties = context.options[0].allow; + var passedProperty = node.property.name; + var propertyIsAllowed = (allowedProperties.indexOf(passedProperty) > -1); + + if (propertyIsAllowed) { + blockConsole = false; + } } - } - if (blockConsole) { - context.report(node, "Unexpected console statement."); + if (blockConsole) { + context.report(node, "Unexpected console statement."); + } } } - } - }; - -}; + }; -module.exports.schema = [ - { - "type": "object", - "properties": { - "allow": { - "type": "array", - "items": { - "type": "string" - }, - "minItems": 1, - "uniqueItems": true - } - }, - "additionalProperties": false } -]; +}; diff --git a/tools/eslint/lib/rules/no-const-assign.js b/tools/eslint/lib/rules/no-const-assign.js index d10e1b26d6cd32..344e05a644ee67 100644 --- a/tools/eslint/lib/rules/no-const-assign.js +++ b/tools/eslint/lib/rules/no-const-assign.js @@ -1,7 +1,6 @@ /** * @fileoverview A rule to disallow modifying variables that are declared using `const` * @author Toru Nagashima - * @copyright 2015 Toru Nagashima. All rights reserved. */ "use strict"; @@ -12,30 +11,40 @@ var astUtils = require("../ast-utils"); // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - /** - * Finds and reports references that are non initializer and writable. - * @param {Variable} variable - A variable to check. - * @returns {void} - */ - function checkVariable(variable) { - astUtils.getModifyingReferences(variable.references).forEach(function(reference) { - context.report( - reference.identifier, - "'{{name}}' is constant.", - {name: reference.identifier.name}); - }); - } +module.exports = { + meta: { + docs: { + description: "disallow reassigning `const` variables", + category: "ECMAScript 6", + recommended: true + }, + + schema: [] + }, + + create: function(context) { + + /** + * Finds and reports references that are non initializer and writable. + * @param {Variable} variable - A variable to check. + * @returns {void} + */ + function checkVariable(variable) { + astUtils.getModifyingReferences(variable.references).forEach(function(reference) { + context.report( + reference.identifier, + "'{{name}}' is constant.", + {name: reference.identifier.name}); + }); + } - return { - "VariableDeclaration": function(node) { - if (node.kind === "const") { - context.getDeclaredVariables(node).forEach(checkVariable); + return { + VariableDeclaration: function(node) { + if (node.kind === "const") { + context.getDeclaredVariables(node).forEach(checkVariable); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-constant-condition.js b/tools/eslint/lib/rules/no-constant-condition.js index a8251d1f9595f5..0072491bee5133 100644 --- a/tools/eslint/lib/rules/no-constant-condition.js +++ b/tools/eslint/lib/rules/no-constant-condition.js @@ -1,7 +1,6 @@ /** * @fileoverview Rule to flag use constant conditions * @author Christian Schulz - * @copyright 2014 Christian Schulz. All rights reserved. */ "use strict"; @@ -10,69 +9,110 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- - - /** - * Checks if a node has a constant truthiness value. - * @param {ASTNode} node The AST node to check. - * @returns {Bool} true when node's truthiness is constant - * @private - */ - function isConstant(node) { - switch (node.type) { - case "Literal": - case "ArrowFunctionExpression": - case "FunctionExpression": - case "ObjectExpression": - case "ArrayExpression": - return true; - - case "UnaryExpression": - return isConstant(node.argument); - - case "BinaryExpression": - case "LogicalExpression": - return isConstant(node.left) && isConstant(node.right) && node.operator !== "in"; - - case "AssignmentExpression": - return (node.operator === "=") && isConstant(node.right); - - case "SequenceExpression": - return isConstant(node.expressions[node.expressions.length - 1]); - - // no default +module.exports = { + meta: { + docs: { + description: "disallow constant expressions in conditions", + category: "Possible Errors", + recommended: true + }, + + schema: [] + }, + + create: function(context) { + + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- + + + /** + * Checks if a branch node of LogicalExpression short circuits the whole condition + * @param {ASTNode} node The branch of main condition which needs to be checked + * @param {string} operator The operator of the main LogicalExpression. + * @returns {boolean} true when condition short circuits whole condition + */ + function isLogicalIdentity(node, operator) { + switch (node.type) { + case "Literal": + return (operator === "||" && node.value === true) || + (operator === "&&" && node.value === false); + case "LogicalExpression": + return isLogicalIdentity(node.left, node.operator) || + isLogicalIdentity(node.right, node.operator); + + // no default + } + return false; } - return false; - } - /** - * Reports when the given node contains a constant condition. - * @param {ASTNode} node The AST node to check. - * @returns {void} - * @private - */ - function checkConstantCondition(node) { - if (node.test && isConstant(node.test)) { - context.report(node, "Unexpected constant condition."); + /** + * Checks if a node has a constant truthiness value. + * @param {ASTNode} node The AST node to check. + * @param {boolean} inBooleanPosition `false` if checking branch of a condition. + * `true` in all other cases + * @returns {Bool} true when node's truthiness is constant + * @private + */ + function isConstant(node, inBooleanPosition) { + switch (node.type) { + case "Literal": + case "ArrowFunctionExpression": + case "FunctionExpression": + case "ObjectExpression": + case "ArrayExpression": + return true; + + case "UnaryExpression": + return (node.operator === "typeof" && inBooleanPosition) || + isConstant(node.argument, true); + + case "BinaryExpression": + return isConstant(node.left, false) && + isConstant(node.right, false) && + node.operator !== "in"; + case "LogicalExpression": + var isLeftConstant = isConstant(node.left, inBooleanPosition); + var isRightConstant = isConstant(node.right, inBooleanPosition); + var isLeftShortCircuit = (isLeftConstant && isLogicalIdentity(node.left, node.operator)); + var isRightShortCircuit = (isRightConstant && isLogicalIdentity(node.right, node.operator)); + + return (isLeftConstant && isRightConstant) || isLeftShortCircuit || isRightShortCircuit; + case "AssignmentExpression": + return (node.operator === "=") && isConstant(node.right, inBooleanPosition); + + case "SequenceExpression": + return isConstant(node.expressions[node.expressions.length - 1], inBooleanPosition); + + // no default + } + return false; } - } - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- + /** + * Reports when the given node contains a constant condition. + * @param {ASTNode} node The AST node to check. + * @returns {void} + * @private + */ + function checkConstantCondition(node) { + if (node.test && isConstant(node.test, true)) { + context.report(node, "Unexpected constant condition."); + } + } - return { - "ConditionalExpression": checkConstantCondition, - "IfStatement": checkConstantCondition, - "WhileStatement": checkConstantCondition, - "DoWhileStatement": checkConstantCondition, - "ForStatement": checkConstantCondition - }; + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- -}; + return { + ConditionalExpression: checkConstantCondition, + IfStatement: checkConstantCondition, + WhileStatement: checkConstantCondition, + DoWhileStatement: checkConstantCondition, + ForStatement: checkConstantCondition + }; -module.exports.schema = []; + } +}; diff --git a/tools/eslint/lib/rules/no-continue.js b/tools/eslint/lib/rules/no-continue.js index 89fa1848e9572e..246df89ebe4283 100644 --- a/tools/eslint/lib/rules/no-continue.js +++ b/tools/eslint/lib/rules/no-continue.js @@ -1,7 +1,6 @@ /** * @fileoverview Rule to flag use of continue statement * @author Borislav Zhivkov - * @copyright 2015 Borislav Zhivkov. All rights reserved. */ "use strict"; @@ -10,14 +9,24 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow `continue` statements", + category: "Stylistic Issues", + recommended: false + }, - return { - "ContinueStatement": function(node) { - context.report(node, "Unexpected use of continue statement"); - } - }; + schema: [] + }, -}; + create: function(context) { + + return { + ContinueStatement: function(node) { + context.report(node, "Unexpected use of continue statement"); + } + }; -module.exports.schema = []; + } +}; diff --git a/tools/eslint/lib/rules/no-control-regex.js b/tools/eslint/lib/rules/no-control-regex.js index 98d22840196090..74e03f03c56f40 100644 --- a/tools/eslint/lib/rules/no-control-regex.js +++ b/tools/eslint/lib/rules/no-control-regex.js @@ -9,51 +9,87 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - /** - * Get the regex expression - * @param {ASTNode} node node to evaluate - * @returns {*} Regex if found else null - * @private - */ - function getRegExp(node) { - if (node.value instanceof RegExp) { - return node.value; - } else if (typeof node.value === "string") { - - var parent = context.getAncestors().pop(); - - if ((parent.type === "NewExpression" || parent.type === "CallExpression") && - parent.callee.type === "Identifier" && parent.callee.name === "RegExp" - ) { - - // there could be an invalid regular expression string - try { - return new RegExp(node.value); - } catch (ex) { - return null; +module.exports = { + meta: { + docs: { + description: "disallow control characters in regular expressions", + category: "Possible Errors", + recommended: true + }, + + schema: [] + }, + + create: function(context) { + + /** + * Get the regex expression + * @param {ASTNode} node node to evaluate + * @returns {*} Regex if found else null + * @private + */ + function getRegExp(node) { + if (node.value instanceof RegExp) { + return node.value; + } else if (typeof node.value === "string") { + + var parent = context.getAncestors().pop(); + + if ((parent.type === "NewExpression" || parent.type === "CallExpression") && + parent.callee.type === "Identifier" && parent.callee.name === "RegExp" + ) { + + // there could be an invalid regular expression string + try { + return new RegExp(node.value); + } catch (ex) { + return null; + } } } + + return null; } - return null; - } + /** + * Check if given regex string has control characters in it + * @param {String} regexStr regex as string to check + * @returns {Boolean} returns true if finds control characters on given string + * @private + */ + function hasControlCharacters(regexStr) { - return { - "Literal": function(node) { - var computedValue, - regex = getRegExp(node); + // check control characters, if RegExp object used + var hasControlChars = /[\x00-\x1f]/.test(regexStr); // eslint-disable-line no-control-regex - if (regex) { - computedValue = regex.toString(); - if (/[\x00-\x1f]/.test(computedValue)) { - context.report(node, "Unexpected control character in regular expression."); - } + // check substr, if regex literal used + var subStrIndex = regexStr.search(/\\x[01][0-9a-f]/i); + + if (!hasControlChars && subStrIndex > -1) { + + // is it escaped, check backslash count + var possibleEscapeCharacters = regexStr.substr(0, subStrIndex).match(/\\+$/gi); + + hasControlChars = possibleEscapeCharacters === null || !(possibleEscapeCharacters[0].length % 2); } + + return hasControlChars; } - }; -}; + return { + Literal: function(node) { + var computedValue, + regex = getRegExp(node); + + if (regex) { + computedValue = regex.toString(); -module.exports.schema = []; + if (hasControlCharacters(computedValue)) { + context.report(node, "Unexpected control character in regular expression."); + } + } + } + }; + + } +}; diff --git a/tools/eslint/lib/rules/no-debugger.js b/tools/eslint/lib/rules/no-debugger.js index 7d86e76d4fdfa1..552294bd674224 100644 --- a/tools/eslint/lib/rules/no-debugger.js +++ b/tools/eslint/lib/rules/no-debugger.js @@ -9,14 +9,24 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow the use of `debugger`", + category: "Possible Errors", + recommended: true + }, - return { - "DebuggerStatement": function(node) { - context.report(node, "Unexpected 'debugger' statement."); - } - }; + schema: [] + }, -}; + create: function(context) { + + return { + DebuggerStatement: function(node) { + context.report(node, "Unexpected 'debugger' statement."); + } + }; -module.exports.schema = []; + } +}; diff --git a/tools/eslint/lib/rules/no-delete-var.js b/tools/eslint/lib/rules/no-delete-var.js index d6ffbd107a60cb..c1d717a15ba573 100644 --- a/tools/eslint/lib/rules/no-delete-var.js +++ b/tools/eslint/lib/rules/no-delete-var.js @@ -9,17 +9,27 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow deleting variables", + category: "Variables", + recommended: true + }, - return { + schema: [] + }, - "UnaryExpression": function(node) { - if (node.operator === "delete" && node.argument.type === "Identifier") { - context.report(node, "Variables should not be deleted."); + create: function(context) { + + return { + + UnaryExpression: function(node) { + if (node.operator === "delete" && node.argument.type === "Identifier") { + context.report(node, "Variables should not be deleted."); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-div-regex.js b/tools/eslint/lib/rules/no-div-regex.js index 61e7a1c4d889ee..58c44662cb98d3 100644 --- a/tools/eslint/lib/rules/no-div-regex.js +++ b/tools/eslint/lib/rules/no-div-regex.js @@ -9,19 +9,29 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow division operators explicitly at the beginning of regular expressions", + category: "Best Practices", + recommended: false + }, - return { + schema: [] + }, - "Literal": function(node) { - var token = context.getFirstToken(node); + create: function(context) { - if (token.type === "RegularExpression" && token.value[1] === "=") { - context.report(node, "A regular expression literal can be confused with '/='."); + return { + + Literal: function(node) { + var token = context.getFirstToken(node); + + if (token.type === "RegularExpression" && token.value[1] === "=") { + context.report(node, "A regular expression literal can be confused with '/='."); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-dupe-args.js b/tools/eslint/lib/rules/no-dupe-args.js index 5de9b500b65fa1..e927ce2b3a8576 100644 --- a/tools/eslint/lib/rules/no-dupe-args.js +++ b/tools/eslint/lib/rules/no-dupe-args.js @@ -1,9 +1,6 @@ /** * @fileoverview Rule to flag duplicate arguments * @author Jamund Ferguson - * @copyright 2015 Jamund Ferguson. All rights reserved. - * @copyright 2015 Toru Nagashima. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; @@ -12,64 +9,65 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow duplicate arguments in `function` definitions", + category: "Possible Errors", + recommended: true + }, - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- + schema: [] + }, - /** - * Checks whether or not a given definition is a parameter's. - * @param {escope.DefEntry} def - A definition to check. - * @returns {boolean} `true` if the definition is a parameter's. - */ - function isParameter(def) { - return def.type === "Parameter"; - } + create: function(context) { - /** - * Determines if a given node has duplicate parameters. - * @param {ASTNode} node The node to check. - * @returns {void} - * @private - */ - function checkParams(node) { - var variables = context.getDeclaredVariables(node); - var keyMap = Object.create(null); + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- - for (var i = 0; i < variables.length; ++i) { - var variable = variables[i]; + /** + * Checks whether or not a given definition is a parameter's. + * @param {escope.DefEntry} def - A definition to check. + * @returns {boolean} `true` if the definition is a parameter's. + */ + function isParameter(def) { + return def.type === "Parameter"; + } - // TODO(nagashima): Remove this duplication check after https://github.com/estools/escope/pull/79 - var key = "$" + variable.name; // to avoid __proto__. + /** + * Determines if a given node has duplicate parameters. + * @param {ASTNode} node The node to check. + * @returns {void} + * @private + */ + function checkParams(node) { + var variables = context.getDeclaredVariables(node); - if (!isParameter(variable.defs[0]) || keyMap[key]) { - continue; - } - keyMap[key] = true; + for (var i = 0; i < variables.length; ++i) { + var variable = variables[i]; - // Checks and reports duplications. - var defs = variable.defs.filter(isParameter); + // Checks and reports duplications. + var defs = variable.defs.filter(isParameter); - if (defs.length >= 2) { - context.report({ - node: node, - message: "Duplicate param '{{name}}'.", - data: {name: variable.name} - }); + if (defs.length >= 2) { + context.report({ + node: node, + message: "Duplicate param '{{name}}'.", + data: {name: variable.name} + }); + } } } - } - //-------------------------------------------------------------------------- - // Public API - //-------------------------------------------------------------------------- + //-------------------------------------------------------------------------- + // Public API + //-------------------------------------------------------------------------- - return { - "FunctionDeclaration": checkParams, - "FunctionExpression": checkParams - }; + return { + FunctionDeclaration: checkParams, + FunctionExpression: checkParams + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-dupe-class-members.js b/tools/eslint/lib/rules/no-dupe-class-members.js index d61b05136d0f1d..883020bdfe5e96 100644 --- a/tools/eslint/lib/rules/no-dupe-class-members.js +++ b/tools/eslint/lib/rules/no-dupe-class-members.js @@ -1,7 +1,6 @@ /** * @fileoverview A rule to disallow duplicate name in class members. * @author Toru Nagashima - * @copyright 2015 Toru Nagashima. All rights reserved. */ "use strict"; @@ -10,91 +9,101 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var stack = []; - - /** - * Gets state of a given member name. - * @param {string} name - A name of a member. - * @param {boolean} isStatic - A flag which specifies that is a static member. - * @returns {object} A state of a given member name. - * - retv.init {boolean} A flag which shows the name is declared as normal member. - * - retv.get {boolean} A flag which shows the name is declared as getter. - * - retv.set {boolean} A flag which shows the name is declared as setter. - */ - function getState(name, isStatic) { - var stateMap = stack[stack.length - 1]; - var key = "$" + name; // to avoid "__proto__". - - if (!stateMap[key]) { - stateMap[key] = { - nonStatic: {init: false, get: false, set: false}, - static: {init: false, get: false, set: false} - }; - } - - return stateMap[key][isStatic ? "static" : "nonStatic"]; - } - - /** - * Gets the name text of a given node. - * - * @param {ASTNode} node - A node to get the name. - * @returns {string} The name text of the node. - */ - function getName(node) { - switch (node.type) { - case "Identifier": return node.name; - case "Literal": return String(node.value); - - /* istanbul ignore next: syntax error */ - default: return ""; - } - } - - return { - - // Initializes the stack of state of member declarations. - "Program": function() { - stack = []; - }, - - // Initializes state of member declarations for the class. - "ClassBody": function() { - stack.push(Object.create(null)); - }, - - // Disposes the state for the class. - "ClassBody:exit": function() { - stack.pop(); +module.exports = { + meta: { + docs: { + description: "disallow duplicate class members", + category: "ECMAScript 6", + recommended: true }, - // Reports the node if its name has been declared already. - "MethodDefinition": function(node) { - if (node.computed) { - return; + schema: [] + }, + + create: function(context) { + var stack = []; + + /** + * Gets state of a given member name. + * @param {string} name - A name of a member. + * @param {boolean} isStatic - A flag which specifies that is a static member. + * @returns {object} A state of a given member name. + * - retv.init {boolean} A flag which shows the name is declared as normal member. + * - retv.get {boolean} A flag which shows the name is declared as getter. + * - retv.set {boolean} A flag which shows the name is declared as setter. + */ + function getState(name, isStatic) { + var stateMap = stack[stack.length - 1]; + var key = "$" + name; // to avoid "__proto__". + + if (!stateMap[key]) { + stateMap[key] = { + nonStatic: {init: false, get: false, set: false}, + static: {init: false, get: false, set: false} + }; } - var name = getName(node.key); - var state = getState(name, node.static); - var isDuplicate = false; - - if (node.kind === "get") { - isDuplicate = (state.init || state.get); - state.get = true; - } else if (node.kind === "set") { - isDuplicate = (state.init || state.set); - state.set = true; - } else { - isDuplicate = (state.init || state.get || state.set); - state.init = true; - } + return stateMap[key][isStatic ? "static" : "nonStatic"]; + } - if (isDuplicate) { - context.report(node, "Duplicate name '{{name}}'.", {name: name}); + /** + * Gets the name text of a given node. + * + * @param {ASTNode} node - A node to get the name. + * @returns {string} The name text of the node. + */ + function getName(node) { + switch (node.type) { + case "Identifier": return node.name; + case "Literal": return String(node.value); + + /* istanbul ignore next: syntax error */ + default: return ""; } } - }; -}; -module.exports.schema = []; + return { + + // Initializes the stack of state of member declarations. + Program: function() { + stack = []; + }, + + // Initializes state of member declarations for the class. + ClassBody: function() { + stack.push(Object.create(null)); + }, + + // Disposes the state for the class. + "ClassBody:exit": function() { + stack.pop(); + }, + + // Reports the node if its name has been declared already. + MethodDefinition: function(node) { + if (node.computed) { + return; + } + + var name = getName(node.key); + var state = getState(name, node.static); + var isDuplicate = false; + + if (node.kind === "get") { + isDuplicate = (state.init || state.get); + state.get = true; + } else if (node.kind === "set") { + isDuplicate = (state.init || state.set); + state.set = true; + } else { + isDuplicate = (state.init || state.get || state.set); + state.init = true; + } + + if (isDuplicate) { + context.report(node, "Duplicate name '{{name}}'.", {name: name}); + } + } + }; + } +}; diff --git a/tools/eslint/lib/rules/no-dupe-keys.js b/tools/eslint/lib/rules/no-dupe-keys.js index e07f081b4b8570..26f009b3bfe0ca 100644 --- a/tools/eslint/lib/rules/no-dupe-keys.js +++ b/tools/eslint/lib/rules/no-dupe-keys.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to flag use of duplicate keys in an object. * @author Ian Christian Myers - * @copyright 2013 Ian Christian Myers. All rights reserved. - * @copyright 2013 Nicholas C. Zakas. All rights reserved. */ "use strict"; @@ -11,38 +9,48 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow duplicate keys in object literals", + category: "Possible Errors", + recommended: true + }, - return { + schema: [] + }, - "ObjectExpression": function(node) { + create: function(context) { - // Object that will be a map of properties--safe because we will - // prefix all of the keys. - var nodeProps = Object.create(null); + return { - node.properties.forEach(function(property) { + ObjectExpression: function(node) { - if (property.type !== "Property") { - return; - } + // Object that will be a map of properties--safe because we will + // prefix all of the keys. + var nodeProps = Object.create(null); - var keyName = property.key.name || property.key.value, - key = property.kind + "-" + keyName, - checkProperty = (!property.computed || property.key.type === "Literal"); + node.properties.forEach(function(property) { - if (checkProperty) { - if (nodeProps[key]) { - context.report(node, property.loc.start, "Duplicate key '{{key}}'.", { key: keyName }); - } else { - nodeProps[key] = true; + if (property.type !== "Property") { + return; } - } - }); - } - }; + var keyName = property.key.name || property.key.value, + key = property.kind + "-" + keyName, + checkProperty = (!property.computed || property.key.type === "Literal"); -}; + if (checkProperty) { + if (nodeProps[key]) { + context.report(node, property.loc.start, "Duplicate key '{{key}}'.", { key: keyName }); + } else { + nodeProps[key] = true; + } + } + }); -module.exports.schema = []; + } + }; + + } +}; diff --git a/tools/eslint/lib/rules/no-duplicate-case.js b/tools/eslint/lib/rules/no-duplicate-case.js index d56fca7696600d..1308730a6311cd 100644 --- a/tools/eslint/lib/rules/no-duplicate-case.js +++ b/tools/eslint/lib/rules/no-duplicate-case.js @@ -1,9 +1,7 @@ /** * @fileoverview Rule to disallow a duplicate case label. - * @author Dieter Oberkofler + * @author Dieter Oberkofler * @author Burak Yigit Kaya - * @copyright 2015 Dieter Oberkofler. All rights reserved. - * @copyright 2015 Burak Yigit Kaya. All rights reserved. */ "use strict"; @@ -12,23 +10,33 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow duplicate case labels", + category: "Possible Errors", + recommended: true + }, - return { - "SwitchStatement": function(node) { - var mapping = {}; + schema: [] + }, - node.cases.forEach(function(switchCase) { - var key = context.getSource(switchCase.test); + create: function(context) { - if (mapping[key]) { - context.report(switchCase, "Duplicate case label."); - } else { - mapping[key] = switchCase; - } - }); - } - }; -}; + return { + SwitchStatement: function(node) { + var mapping = {}; + + node.cases.forEach(function(switchCase) { + var key = context.getSource(switchCase.test); -module.exports.schema = []; + if (mapping[key]) { + context.report(switchCase, "Duplicate case label."); + } else { + mapping[key] = switchCase; + } + }); + } + }; + } +}; diff --git a/tools/eslint/lib/rules/no-duplicate-imports.js b/tools/eslint/lib/rules/no-duplicate-imports.js index 6c0edbb9990e08..44432f48635982 100644 --- a/tools/eslint/lib/rules/no-duplicate-imports.js +++ b/tools/eslint/lib/rules/no-duplicate-imports.js @@ -1,8 +1,6 @@ /** * @fileoverview Restrict usage of duplicate imports. * @author Simen Bekkhus - * @copyright 2016 Simen Bekkhus. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; @@ -98,29 +96,39 @@ function handleExports(context, importsInFile, exportsInFile) { }; } -module.exports = function(context) { - var includeExports = (context.options[0] || {}).includeExports, - importsInFile = [], - exportsInFile = []; +module.exports = { + meta: { + docs: { + description: "disallow duplicate module imports", + category: "ECMAScript 6", + recommended: false + }, + + schema: [{ + type: "object", + properties: { + includeExports: { + type: "boolean" + } + }, + additionalProperties: false + }] + }, - var handlers = { - "ImportDeclaration": handleImports(context, includeExports, importsInFile, exportsInFile) - }; + create: function(context) { + var includeExports = (context.options[0] || {}).includeExports, + importsInFile = [], + exportsInFile = []; - if (includeExports) { - handlers.ExportNamedDeclaration = handleExports(context, importsInFile, exportsInFile); - handlers.ExportAllDeclaration = handleExports(context, importsInFile, exportsInFile); - } - - return handlers; -}; + var handlers = { + ImportDeclaration: handleImports(context, includeExports, importsInFile, exportsInFile) + }; -module.exports.schema = [{ - "type": "object", - "properties": { - "includeExports": { - "type": "boolean" + if (includeExports) { + handlers.ExportNamedDeclaration = handleExports(context, importsInFile, exportsInFile); + handlers.ExportAllDeclaration = handleExports(context, importsInFile, exportsInFile); } - }, - "additionalProperties": false -}]; + + return handlers; + } +}; diff --git a/tools/eslint/lib/rules/no-else-return.js b/tools/eslint/lib/rules/no-else-return.js index 33a519e4e0b79c..4678d320af9689 100644 --- a/tools/eslint/lib/rules/no-else-return.js +++ b/tools/eslint/lib/rules/no-else-return.js @@ -9,140 +9,150 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- - - /** - * Display the context report if rule is violated - * - * @param {Node} node The 'else' node - * @returns {void} - */ - function displayReport(node) { - context.report(node, "Unexpected 'else' after 'return'."); - } +module.exports = { + meta: { + docs: { + description: "disallow `else` blocks after `return` statements in `if` statements", + category: "Best Practices", + recommended: false + }, + + schema: [] + }, + + create: function(context) { + + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- + + /** + * Display the context report if rule is violated + * + * @param {Node} node The 'else' node + * @returns {void} + */ + function displayReport(node) { + context.report(node, "Unexpected 'else' after 'return'."); + } - /** - * Check to see if the node is a ReturnStatement - * - * @param {Node} node The node being evaluated - * @returns {boolean} True if node is a return - */ - function checkForReturn(node) { - return node.type === "ReturnStatement"; - } + /** + * Check to see if the node is a ReturnStatement + * + * @param {Node} node The node being evaluated + * @returns {boolean} True if node is a return + */ + function checkForReturn(node) { + return node.type === "ReturnStatement"; + } - /** - * Naive return checking, does not iterate through the whole - * BlockStatement because we make the assumption that the ReturnStatement - * will be the last node in the body of the BlockStatement. - * - * @param {Node} node The consequent/alternate node - * @returns {boolean} True if it has a return - */ - function naiveHasReturn(node) { - if (node.type === "BlockStatement") { - var body = node.body, - lastChildNode = body[body.length - 1]; - - return lastChildNode && checkForReturn(lastChildNode); + /** + * Naive return checking, does not iterate through the whole + * BlockStatement because we make the assumption that the ReturnStatement + * will be the last node in the body of the BlockStatement. + * + * @param {Node} node The consequent/alternate node + * @returns {boolean} True if it has a return + */ + function naiveHasReturn(node) { + if (node.type === "BlockStatement") { + var body = node.body, + lastChildNode = body[body.length - 1]; + + return lastChildNode && checkForReturn(lastChildNode); + } + return checkForReturn(node); } - return checkForReturn(node); - } - /** - * Check to see if the node is valid for evaluation, - * meaning it has an else and not an else-if - * - * @param {Node} node The node being evaluated - * @returns {boolean} True if the node is valid - */ - function hasElse(node) { - return node.alternate && node.consequent && node.alternate.type !== "IfStatement"; - } + /** + * Check to see if the node is valid for evaluation, + * meaning it has an else and not an else-if + * + * @param {Node} node The node being evaluated + * @returns {boolean} True if the node is valid + */ + function hasElse(node) { + return node.alternate && node.consequent && node.alternate.type !== "IfStatement"; + } - /** - * If the consequent is an IfStatement, check to see if it has an else - * and both its consequent and alternate path return, meaning this is - * a nested case of rule violation. If-Else not considered currently. - * - * @param {Node} node The consequent node - * @returns {boolean} True if this is a nested rule violation - */ - function checkForIf(node) { - return node.type === "IfStatement" && hasElse(node) && - naiveHasReturn(node.alternate) && naiveHasReturn(node.consequent); - } + /** + * If the consequent is an IfStatement, check to see if it has an else + * and both its consequent and alternate path return, meaning this is + * a nested case of rule violation. If-Else not considered currently. + * + * @param {Node} node The consequent node + * @returns {boolean} True if this is a nested rule violation + */ + function checkForIf(node) { + return node.type === "IfStatement" && hasElse(node) && + naiveHasReturn(node.alternate) && naiveHasReturn(node.consequent); + } - /** - * Check the consequent/body node to make sure it is not - * a ReturnStatement or an IfStatement that returns on both - * code paths. - * - * @param {Node} node The consequent or body node - * @param {Node} alternate The alternate node - * @returns {boolean} `true` if it is a Return/If node that always returns. - */ - function checkForReturnOrIf(node) { - return checkForReturn(node) || checkForIf(node); - } + /** + * Check the consequent/body node to make sure it is not + * a ReturnStatement or an IfStatement that returns on both + * code paths. + * + * @param {Node} node The consequent or body node + * @param {Node} alternate The alternate node + * @returns {boolean} `true` if it is a Return/If node that always returns. + */ + function checkForReturnOrIf(node) { + return checkForReturn(node) || checkForIf(node); + } - /** - * Check whether a node returns in every codepath. - * @param {Node} node The node to be checked - * @returns {boolean} `true` if it returns on every codepath. - */ - function alwaysReturns(node) { - if (node.type === "BlockStatement") { + /** + * Check whether a node returns in every codepath. + * @param {Node} node The node to be checked + * @returns {boolean} `true` if it returns on every codepath. + */ + function alwaysReturns(node) { + if (node.type === "BlockStatement") { - // If we have a BlockStatement, check each consequent body node. - return node.body.some(checkForReturnOrIf); - } else { + // If we have a BlockStatement, check each consequent body node. + return node.body.some(checkForReturnOrIf); + } else { - /* - * If not a block statement, make sure the consequent isn't a - * ReturnStatement or an IfStatement with returns on both paths. - */ - return checkForReturnOrIf(node); + /* + * If not a block statement, make sure the consequent isn't a + * ReturnStatement or an IfStatement with returns on both paths. + */ + return checkForReturnOrIf(node); + } } - } - - //-------------------------------------------------------------------------- - // Public API - //-------------------------------------------------------------------------- - return { + //-------------------------------------------------------------------------- + // Public API + //-------------------------------------------------------------------------- - "IfStatement": function(node) { - var parent = context.getAncestors().pop(), - consequents, - alternate; + 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) { - return; - } + IfStatement: function(node) { + var parent = context.getAncestors().pop(), + consequents, + alternate; - for (consequents = []; node.type === "IfStatement"; node = node.alternate) { - if (!node.alternate) { + // Only "top-level" if statements are checked, meaning the first `if` + // in a `if-else-if-...` chain. + if (parent.type === "IfStatement" && parent.alternate === node) { return; } - consequents.push(node.consequent); - alternate = node.alternate; - } - if (consequents.every(alwaysReturns)) { - displayReport(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); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-empty-character-class.js b/tools/eslint/lib/rules/no-empty-character-class.js index d6341a124a4e98..e015e0cc067d20 100644 --- a/tools/eslint/lib/rules/no-empty-character-class.js +++ b/tools/eslint/lib/rules/no-empty-character-class.js @@ -27,20 +27,30 @@ var regex = /^\/([^\\[]|\\.|\[([^\\\]]|\\.)+\])*\/[gimuy]*$/; // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow empty character classes in regular expressions", + category: "Possible Errors", + recommended: true + }, - return { + schema: [] + }, - "Literal": function(node) { - var token = context.getFirstToken(node); + create: function(context) { - if (token.type === "RegularExpression" && !regex.test(token.value)) { - context.report(node, "Empty class."); + return { + + Literal: function(node) { + var token = context.getFirstToken(node); + + if (token.type === "RegularExpression" && !regex.test(token.value)) { + context.report(node, "Empty class."); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-empty-function.js b/tools/eslint/lib/rules/no-empty-function.js index 9ff304d4d7d664..412614b501099c 100644 --- a/tools/eslint/lib/rules/no-empty-function.js +++ b/tools/eslint/lib/rules/no-empty-function.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to disallow empty functions. * @author Toru Nagashima - * @copyright 2016 Toru Nagashima. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; @@ -96,55 +94,65 @@ function getKind(node) { // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var options = context.options[0] || {}; - var allowed = options.allow || []; - - /** - * Reports a given function node if the node matches the following patterns. - * - * - Not allowed by options. - * - The body is empty. - * - The body doesn't have any comments. - * - * @param {ASTNode} node - A function node to report. This is one of - * an ArrowFunctionExpression, a FunctionDeclaration, or a - * FunctionExpression. - * @returns {void} - */ - function reportIfEmpty(node) { - var kind = getKind(node); - - if (allowed.indexOf(kind) === -1 && - node.body.type === "BlockStatement" && - node.body.body.length === 0 && - context.getComments(node.body).trailing.length === 0 - ) { - context.report({ - node: node, - loc: node.body.loc.start, - message: "Unexpected empty " + SHOW_KIND[kind] + "." - }); - } - } - - return { - ArrowFunctionExpression: reportIfEmpty, - FunctionDeclaration: reportIfEmpty, - FunctionExpression: reportIfEmpty - }; -}; +module.exports = { + meta: { + docs: { + description: "disallow empty functions", + category: "Best Practices", + recommended: false + }, -module.exports.schema = [ - { - type: "object", - properties: { - allow: { - type: "array", - items: {enum: ALLOW_OPTIONS}, - uniqueItems: true + schema: [ + { + type: "object", + properties: { + allow: { + type: "array", + items: {enum: ALLOW_OPTIONS}, + uniqueItems: true + } + }, + additionalProperties: false } - }, - additionalProperties: false + ] + }, + + create: function(context) { + var options = context.options[0] || {}; + var allowed = options.allow || []; + + /** + * Reports a given function node if the node matches the following patterns. + * + * - Not allowed by options. + * - The body is empty. + * - The body doesn't have any comments. + * + * @param {ASTNode} node - A function node to report. This is one of + * an ArrowFunctionExpression, a FunctionDeclaration, or a + * FunctionExpression. + * @returns {void} + */ + function reportIfEmpty(node) { + var kind = getKind(node); + + if (allowed.indexOf(kind) === -1 && + node.body.type === "BlockStatement" && + node.body.body.length === 0 && + context.getComments(node.body).trailing.length === 0 + ) { + context.report({ + node: node, + loc: node.body.loc.start, + message: "Unexpected empty " + SHOW_KIND[kind] + "." + }); + } + } + + return { + ArrowFunctionExpression: reportIfEmpty, + FunctionDeclaration: reportIfEmpty, + FunctionExpression: reportIfEmpty + }; } -]; +}; diff --git a/tools/eslint/lib/rules/no-empty-pattern.js b/tools/eslint/lib/rules/no-empty-pattern.js index aa8515ad191317..afd8b1e393e36b 100644 --- a/tools/eslint/lib/rules/no-empty-pattern.js +++ b/tools/eslint/lib/rules/no-empty-pattern.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to disallow an empty pattern * @author Alberto Rodríguez - * @copyright 2015 Alberto Rodríguez. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; @@ -10,19 +8,29 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - return { - "ObjectPattern": function(node) { - if (node.properties.length === 0) { - context.report(node, "Unexpected empty object pattern."); - } +module.exports = { + meta: { + docs: { + description: "disallow empty destructuring patterns", + category: "Best Practices", + recommended: true }, - "ArrayPattern": function(node) { - if (node.elements.length === 0) { - context.report(node, "Unexpected empty array pattern."); + + schema: [] + }, + + create: function(context) { + return { + ObjectPattern: function(node) { + if (node.properties.length === 0) { + context.report(node, "Unexpected empty object pattern."); + } + }, + ArrayPattern: function(node) { + if (node.elements.length === 0) { + context.report(node, "Unexpected empty array pattern."); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-empty.js b/tools/eslint/lib/rules/no-empty.js index df40433d7b7114..8f32428304c471 100644 --- a/tools/eslint/lib/rules/no-empty.js +++ b/tools/eslint/lib/rules/no-empty.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to flag use of an empty block statement * @author Nicholas C. Zakas - * @copyright Nicholas C. Zakas. All rights reserved. - * @copyright 2015 Dieter Oberkofler. All rights reserved. */ "use strict"; @@ -12,36 +10,63 @@ var FUNCTION_TYPE = /^(?:ArrowFunctionExpression|Function(?:Declaration|Expression))$/; -module.exports = function(context) { - return { - "BlockStatement": function(node) { +module.exports = { + meta: { + docs: { + description: "disallow empty block statements", + category: "Possible Errors", + recommended: true + }, - // if the body is not empty, we can just return immediately - if (node.body.length !== 0) { - return; + schema: [ + { + type: "object", + properties: { + allowEmptyCatch: { + type: "boolean" + } + }, + additionalProperties: false } + ] + }, - // a function is generally allowed to be empty - if (FUNCTION_TYPE.test(node.parent.type)) { - return; - } + create: function(context) { + var options = context.options[0] || {}, + allowEmptyCatch = options.allowEmptyCatch || false; - // any other block is only allowed to be empty, if it contains a comment - if (context.getComments(node).trailing.length > 0) { - return; - } + return { + BlockStatement: function(node) { - context.report(node, "Empty block statement."); - }, + // if the body is not empty, we can just return immediately + if (node.body.length !== 0) { + return; + } + + // a function is generally allowed to be empty + if (FUNCTION_TYPE.test(node.parent.type)) { + return; + } - "SwitchStatement": function(node) { + if (allowEmptyCatch && node.parent.type === "CatchClause") { + return; + } - if (typeof node.cases === "undefined" || node.cases.length === 0) { - context.report(node, "Empty switch statement."); + // any other block is only allowed to be empty, if it contains a comment + if (context.getComments(node).trailing.length > 0) { + return; + } + + context.report(node, "Empty block statement."); + }, + + SwitchStatement: function(node) { + + if (typeof node.cases === "undefined" || node.cases.length === 0) { + context.report(node, "Empty switch statement."); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-eq-null.js b/tools/eslint/lib/rules/no-eq-null.js index 92d88920ae6843..da039bb9d7de4c 100644 --- a/tools/eslint/lib/rules/no-eq-null.js +++ b/tools/eslint/lib/rules/no-eq-null.js @@ -10,20 +10,30 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow `null` comparisons without type-checking operators", + category: "Best Practices", + recommended: false + }, - return { + schema: [] + }, - "BinaryExpression": function(node) { - var badOperator = node.operator === "==" || node.operator === "!="; + create: function(context) { - if (node.right.type === "Literal" && node.right.raw === "null" && badOperator || - node.left.type === "Literal" && node.left.raw === "null" && badOperator) { - context.report(node, "Use ‘===’ to compare with ‘null’."); + return { + + BinaryExpression: function(node) { + var badOperator = node.operator === "==" || node.operator === "!="; + + if (node.right.type === "Literal" && node.right.raw === "null" && badOperator || + node.left.type === "Literal" && node.left.raw === "null" && badOperator) { + context.report(node, "Use ‘===’ to compare with ‘null’."); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-eval.js b/tools/eslint/lib/rules/no-eval.js index 7c47c892f95859..04db4b96b477aa 100644 --- a/tools/eslint/lib/rules/no-eval.js +++ b/tools/eslint/lib/rules/no-eval.js @@ -1,9 +1,6 @@ /** * @fileoverview Rule to flag use of eval() statement * @author Nicholas C. Zakas - * @copyright 2015 Toru Nagashima. All rights reserved. - * @copyright 2015 Mathias Schreck. All rights reserved. - * @copyright 2013 Nicholas C. Zakas. All rights reserved. */ "use strict"; @@ -77,140 +74,170 @@ function isMember(node, name) { // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var allowIndirect = Boolean( - context.options[0] && - context.options[0].allowIndirect - ); - var sourceCode = context.getSourceCode(); - var funcInfo = null; - - /** - * Pushs a variable scope (Program or Function) information to the stack. - * - * This is used in order to check whether or not `this` binding is a - * reference to the global object. - * - * @param {ASTNode} node - A node of the scope. This is one of Program, - * FunctionDeclaration, FunctionExpression, and ArrowFunctionExpression. - * @returns {void} - */ - function enterVarScope(node) { - var strict = context.getScope().isStrict; - - funcInfo = { - upper: funcInfo, - node: node, - strict: strict, - defaultThis: false, - initialized: strict - }; - } +module.exports = { + meta: { + docs: { + description: "disallow the use of `eval()`", + category: "Best Practices", + recommended: false + }, - /** - * Pops a variable scope from the stack. - * - * @returns {void} - */ - function exitVarScope() { - funcInfo = funcInfo.upper; - } + schema: [ + { + type: "object", + properties: { + allowIndirect: {type: "boolean"} + }, + additionalProperties: false + } + ] + }, + + create: function(context) { + var allowIndirect = Boolean( + context.options[0] && + context.options[0].allowIndirect + ); + var sourceCode = context.getSourceCode(); + var funcInfo = null; + + /** + * Pushs a variable scope (Program or Function) information to the stack. + * + * This is used in order to check whether or not `this` binding is a + * reference to the global object. + * + * @param {ASTNode} node - A node of the scope. This is one of Program, + * FunctionDeclaration, FunctionExpression, and ArrowFunctionExpression. + * @returns {void} + */ + function enterVarScope(node) { + var strict = context.getScope().isStrict; - /** - * Reports a given node. - * - * `node` is `Identifier` or `MemberExpression`. - * The parent of `node` might be `CallExpression`. - * - * The location of the report is always `eval` `Identifier` (or possibly - * `Literal`). The type of the report is `CallExpression` if the parent is - * `CallExpression`. Otherwise, it's the given node type. - * - * @param {ASTNode} node - A node to report. - * @returns {void} - */ - function report(node) { - var locationNode = node; - var parent = node.parent; - - if (node.type === "MemberExpression") { - locationNode = node.property; + funcInfo = { + upper: funcInfo, + node: node, + strict: strict, + defaultThis: false, + initialized: strict + }; } - if (parent.type === "CallExpression" && parent.callee === node) { - node = parent; + + /** + * Pops a variable scope from the stack. + * + * @returns {void} + */ + function exitVarScope() { + funcInfo = funcInfo.upper; } - context.report({ - node: node, - loc: locationNode.loc.start, - message: "eval can be harmful." - }); - } + /** + * Reports a given node. + * + * `node` is `Identifier` or `MemberExpression`. + * The parent of `node` might be `CallExpression`. + * + * The location of the report is always `eval` `Identifier` (or possibly + * `Literal`). The type of the report is `CallExpression` if the parent is + * `CallExpression`. Otherwise, it's the given node type. + * + * @param {ASTNode} node - A node to report. + * @returns {void} + */ + function report(node) { + var locationNode = node; + var parent = node.parent; + + if (node.type === "MemberExpression") { + locationNode = node.property; + } + if (parent.type === "CallExpression" && parent.callee === node) { + node = parent; + } - /** - * Reports accesses of `eval` via the global object. - * - * @param {escope.Scope} globalScope - The global scope. - * @returns {void} - */ - function reportAccessingEvalViaGlobalObject(globalScope) { - for (var i = 0; i < candidatesOfGlobalObject.length; ++i) { - var name = candidatesOfGlobalObject[i]; - var variable = astUtils.getVariableByName(globalScope, name); + context.report({ + node: node, + loc: locationNode.loc.start, + message: "eval can be harmful." + }); + } - if (!variable) { - continue; - } + /** + * Reports accesses of `eval` via the global object. + * + * @param {escope.Scope} globalScope - The global scope. + * @returns {void} + */ + function reportAccessingEvalViaGlobalObject(globalScope) { + for (var i = 0; i < candidatesOfGlobalObject.length; ++i) { + var name = candidatesOfGlobalObject[i]; + var variable = astUtils.getVariableByName(globalScope, name); + + if (!variable) { + continue; + } - var references = variable.references; + var references = variable.references; - for (var j = 0; j < references.length; ++j) { - var identifier = references[j].identifier; - var node = identifier.parent; + for (var j = 0; j < references.length; ++j) { + var identifier = references[j].identifier; + var node = identifier.parent; - // To detect code like `window.window.eval`. - while (isMember(node, name)) { - node = node.parent; - } + // To detect code like `window.window.eval`. + while (isMember(node, name)) { + node = node.parent; + } - // Reports. - if (isMember(node, "eval")) { - report(node); + // Reports. + if (isMember(node, "eval")) { + report(node); + } } } } - } - /** - * Reports all accesses of `eval` (excludes direct calls to eval). - * - * @param {escope.Scope} globalScope - The global scope. - * @returns {void} - */ - function reportAccessingEval(globalScope) { - var variable = astUtils.getVariableByName(globalScope, "eval"); - - if (!variable) { - return; - } + /** + * Reports all accesses of `eval` (excludes direct calls to eval). + * + * @param {escope.Scope} globalScope - The global scope. + * @returns {void} + */ + function reportAccessingEval(globalScope) { + var variable = astUtils.getVariableByName(globalScope, "eval"); + + if (!variable) { + return; + } - var references = variable.references; + var references = variable.references; - for (var i = 0; i < references.length; ++i) { - var reference = references[i]; - var id = reference.identifier; + for (var i = 0; i < references.length; ++i) { + var reference = references[i]; + var id = reference.identifier; - if (id.name === "eval" && !astUtils.isCallee(id)) { + if (id.name === "eval" && !astUtils.isCallee(id)) { - // Is accessing to eval (excludes direct calls to eval) - report(id); + // Is accessing to eval (excludes direct calls to eval) + report(id); + } } } - } - if (allowIndirect) { + if (allowIndirect) { + + // Checks only direct calls to eval. It's simple! + return { + "CallExpression:exit": function(node) { + var callee = node.callee; + + if (isIdentifier(callee, "eval")) { + report(callee); + } + } + }; + } - // Checks only direct calls to eval. It's simple! return { "CallExpression:exit": function(node) { var callee = node.callee; @@ -218,84 +245,64 @@ module.exports = function(context) { if (isIdentifier(callee, "eval")) { report(callee); } - } - }; - } - - return { - "CallExpression:exit": function(node) { - var callee = node.callee; - - if (isIdentifier(callee, "eval")) { - report(callee); - } - }, - - "Program": function(node) { - var scope = context.getScope(), - features = context.parserOptions.ecmaFeatures || {}, - strict = - scope.isStrict || - node.sourceType === "module" || - (features.globalReturn && scope.childScopes[0].isStrict); - - funcInfo = { - upper: null, - node: node, - strict: strict, - defaultThis: true, - initialized: true - }; - }, - - "Program:exit": function() { - var globalScope = context.getScope(); - - exitVarScope(); - reportAccessingEval(globalScope); - reportAccessingEvalViaGlobalObject(globalScope); - }, - - "FunctionDeclaration": enterVarScope, - "FunctionDeclaration:exit": exitVarScope, - "FunctionExpression": enterVarScope, - "FunctionExpression:exit": exitVarScope, - "ArrowFunctionExpression": enterVarScope, - "ArrowFunctionExpression:exit": exitVarScope, - - "ThisExpression": function(node) { - if (!isMember(node.parent, "eval")) { - return; - } + }, + + Program: function(node) { + var scope = context.getScope(), + features = context.parserOptions.ecmaFeatures || {}, + strict = + scope.isStrict || + node.sourceType === "module" || + (features.globalReturn && scope.childScopes[0].isStrict); + + funcInfo = { + upper: null, + node: node, + strict: strict, + defaultThis: true, + initialized: true + }; + }, + + "Program:exit": function() { + var globalScope = context.getScope(); + + exitVarScope(); + reportAccessingEval(globalScope); + reportAccessingEvalViaGlobalObject(globalScope); + }, + + FunctionDeclaration: enterVarScope, + "FunctionDeclaration:exit": exitVarScope, + FunctionExpression: enterVarScope, + "FunctionExpression:exit": exitVarScope, + ArrowFunctionExpression: enterVarScope, + "ArrowFunctionExpression:exit": exitVarScope, + + ThisExpression: function(node) { + if (!isMember(node.parent, "eval")) { + return; + } - /* - * `this.eval` is found. - * Checks whether or not the value of `this` is the global object. - */ - if (!funcInfo.initialized) { - funcInfo.initialized = true; - funcInfo.defaultThis = astUtils.isDefaultThisBinding( - funcInfo.node, - sourceCode - ); - } + /* + * `this.eval` is found. + * Checks whether or not the value of `this` is the global object. + */ + if (!funcInfo.initialized) { + funcInfo.initialized = true; + funcInfo.defaultThis = astUtils.isDefaultThisBinding( + funcInfo.node, + sourceCode + ); + } - if (!funcInfo.strict && funcInfo.defaultThis) { + if (!funcInfo.strict && funcInfo.defaultThis) { - // `this.eval` is possible built-in `eval`. - report(node.parent); + // `this.eval` is possible built-in `eval`. + report(node.parent); + } } - } - }; - -}; + }; -module.exports.schema = [ - { - "type": "object", - "properties": { - "allowIndirect": {"type": "boolean"} - }, - "additionalProperties": false } -]; +}; diff --git a/tools/eslint/lib/rules/no-ex-assign.js b/tools/eslint/lib/rules/no-ex-assign.js index e658e475b46b27..bf3afc6cd3f485 100644 --- a/tools/eslint/lib/rules/no-ex-assign.js +++ b/tools/eslint/lib/rules/no-ex-assign.js @@ -11,27 +11,37 @@ var astUtils = require("../ast-utils"); // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - /** - * Finds and reports references that are non initializer and writable. - * @param {Variable} variable - A variable to check. - * @returns {void} - */ - function checkVariable(variable) { - astUtils.getModifyingReferences(variable.references).forEach(function(reference) { - context.report( - reference.identifier, - "Do not assign to the exception parameter."); - }); - } - - return { - "CatchClause": function(node) { - context.getDeclaredVariables(node).forEach(checkVariable); +module.exports = { + meta: { + docs: { + description: "disallow reassigning exceptions in `catch` clauses", + category: "Possible Errors", + recommended: true + }, + + schema: [] + }, + + create: function(context) { + + /** + * Finds and reports references that are non initializer and writable. + * @param {Variable} variable - A variable to check. + * @returns {void} + */ + function checkVariable(variable) { + astUtils.getModifyingReferences(variable.references).forEach(function(reference) { + context.report( + reference.identifier, + "Do not assign to the exception parameter."); + }); } - }; -}; + return { + CatchClause: function(node) { + context.getDeclaredVariables(node).forEach(checkVariable); + } + }; -module.exports.schema = []; + } +}; diff --git a/tools/eslint/lib/rules/no-extend-native.js b/tools/eslint/lib/rules/no-extend-native.js index cf2cf33f3a02e5..69d4931ab6e82b 100644 --- a/tools/eslint/lib/rules/no-extend-native.js +++ b/tools/eslint/lib/rules/no-extend-native.js @@ -15,87 +15,97 @@ var globals = require("globals"); // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - var config = context.options[0] || {}; - var exceptions = config.exceptions || []; - var modifiedBuiltins = Object.keys(globals.builtin).filter(function(builtin) { - return builtin[0].toUpperCase() === builtin[0]; - }); - - if (exceptions.length) { - modifiedBuiltins = modifiedBuiltins.filter(function(builtIn) { - return exceptions.indexOf(builtIn) === -1; - }); - } - - return { - - // handle the Array.prototype.extra style case - "AssignmentExpression": function(node) { - var lhs = node.left, - affectsProto; +module.exports = { + meta: { + docs: { + description: "disallow extending native types", + category: "Best Practices", + recommended: false + }, - if (lhs.type !== "MemberExpression" || lhs.object.type !== "MemberExpression") { - return; + schema: [ + { + type: "object", + properties: { + exceptions: { + type: "array", + items: { + type: "string" + }, + uniqueItems: true + } + }, + additionalProperties: false } + ] + }, - affectsProto = lhs.object.computed ? - lhs.object.property.type === "Literal" && lhs.object.property.value === "prototype" : - lhs.object.property.name === "prototype"; + create: function(context) { - if (!affectsProto) { - return; - } + var config = context.options[0] || {}; + var exceptions = config.exceptions || []; + var modifiedBuiltins = Object.keys(globals.builtin).filter(function(builtin) { + return builtin[0].toUpperCase() === builtin[0]; + }); - modifiedBuiltins.forEach(function(builtin) { - if (lhs.object.object.name === builtin) { - context.report(node, builtin + " prototype is read only, properties should not be added."); - } + if (exceptions.length) { + modifiedBuiltins = modifiedBuiltins.filter(function(builtIn) { + return exceptions.indexOf(builtIn) === -1; }); - }, + } - // handle the Object.definePropert[y|ies](Array.prototype) case - "CallExpression": function(node) { + return { - var callee = node.callee, - subject, - object; + // handle the Array.prototype.extra style case + AssignmentExpression: function(node) { + var lhs = node.left, + affectsProto; - // only worry about Object.definePropert[y|ies] - if (callee.type === "MemberExpression" && - callee.object.name === "Object" && - (callee.property.name === "defineProperty" || callee.property.name === "defineProperties")) { + if (lhs.type !== "MemberExpression" || lhs.object.type !== "MemberExpression") { + return; + } - // verify the object being added to is a native prototype - subject = node.arguments[0]; - object = subject && subject.object; - if (object && - object.type === "Identifier" && - (modifiedBuiltins.indexOf(object.name) > -1) && - subject.property.name === "prototype") { + affectsProto = lhs.object.computed ? + lhs.object.property.type === "Literal" && lhs.object.property.value === "prototype" : + lhs.object.property.name === "prototype"; - context.report(node, object.name + " prototype is read only, properties should not be added."); + if (!affectsProto) { + return; } - } - } - }; - -}; + modifiedBuiltins.forEach(function(builtin) { + if (lhs.object.object.name === builtin) { + context.report(node, builtin + " prototype is read only, properties should not be added."); + } + }); + }, + + // handle the Object.definePropert[y|ies](Array.prototype) case + CallExpression: function(node) { + + var callee = node.callee, + subject, + object; + + // only worry about Object.definePropert[y|ies] + if (callee.type === "MemberExpression" && + callee.object.name === "Object" && + (callee.property.name === "defineProperty" || callee.property.name === "defineProperties")) { + + // verify the object being added to is a native prototype + subject = node.arguments[0]; + object = subject && subject.object; + if (object && + object.type === "Identifier" && + (modifiedBuiltins.indexOf(object.name) > -1) && + subject.property.name === "prototype") { + + context.report(node, object.name + " prototype is read only, properties should not be added."); + } + } -module.exports.schema = [ - { - "type": "object", - "properties": { - "exceptions": { - "type": "array", - "items": { - "type": "string" - }, - "uniqueItems": true } - }, - "additionalProperties": false + }; + } -]; +}; diff --git a/tools/eslint/lib/rules/no-extra-bind.js b/tools/eslint/lib/rules/no-extra-bind.js index cd800eabd7733a..f75e2fcc25782d 100644 --- a/tools/eslint/lib/rules/no-extra-bind.js +++ b/tools/eslint/lib/rules/no-extra-bind.js @@ -1,9 +1,6 @@ /** * @fileoverview Rule to flag unnecessary bind calls * @author Bence Dányi - * @copyright 2014 Bence Dányi. All rights reserved. - * @copyright 2016 Toru Nagashima. All rights reserved. - * See LICENSE in root directory for full license. */ "use strict"; @@ -11,139 +8,149 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var scopeInfo = null; +module.exports = { + meta: { + docs: { + description: "disallow unnecessary calls to `.bind()`", + category: "Best Practices", + recommended: false + }, - /** - * Reports a given function node. - * - * @param {ASTNode} node - A node to report. This is a FunctionExpression or - * an ArrowFunctionExpression. - * @returns {void} - */ - function report(node) { - context.report({ - node: node.parent.parent, - message: "The function binding is unnecessary.", - loc: node.parent.property.loc.start - }); - } + schema: [] + }, - /** - * Gets the property name of a given node. - * If the property name is dynamic, this returns an empty string. - * - * @param {ASTNode} node - A node to check. This is a MemberExpression. - * @returns {string} The property name of the node. - */ - function getPropertyName(node) { - if (node.computed) { - switch (node.property.type) { - case "Literal": - return String(node.property.value); - case "TemplateLiteral": - if (node.property.expressions.length === 0) { - return node.property.quasis[0].value.cooked; - } + create: function(context) { + var scopeInfo = null; - // fallthrough - default: - return false; - } + /** + * Reports a given function node. + * + * @param {ASTNode} node - A node to report. This is a FunctionExpression or + * an ArrowFunctionExpression. + * @returns {void} + */ + function report(node) { + context.report({ + node: node.parent.parent, + message: "The function binding is unnecessary.", + loc: node.parent.property.loc.start + }); } - return node.property.name; - } - /** - * Checks whether or not a given function node is the callee of `.bind()` - * method. - * - * e.g. `(function() {}.bind(foo))` - * - * @param {ASTNode} node - A node to report. This is a FunctionExpression or - * an ArrowFunctionExpression. - * @returns {boolean} `true` if the node is the callee of `.bind()` method. - */ - function isCalleeOfBindMethod(node) { - var parent = node.parent; - var grandparent = parent.parent; + /** + * Gets the property name of a given node. + * If the property name is dynamic, this returns an empty string. + * + * @param {ASTNode} node - A node to check. This is a MemberExpression. + * @returns {string} The property name of the node. + */ + function getPropertyName(node) { + if (node.computed) { + switch (node.property.type) { + case "Literal": + return String(node.property.value); + case "TemplateLiteral": + if (node.property.expressions.length === 0) { + return node.property.quasis[0].value.cooked; + } - return ( - grandparent && - grandparent.type === "CallExpression" && - grandparent.callee === parent && - grandparent.arguments.length === 1 && - parent.type === "MemberExpression" && - parent.object === node && - getPropertyName(parent) === "bind" - ); - } + // fallthrough + default: + return false; + } + } + return node.property.name; + } - /** - * Adds a scope information object to the stack. - * - * @param {ASTNode} node - A node to add. This node is a FunctionExpression - * or a FunctionDeclaration node. - * @returns {void} - */ - function enterFunction(node) { - scopeInfo = { - isBound: isCalleeOfBindMethod(node), - thisFound: false, - upper: scopeInfo - }; - } + /** + * Checks whether or not a given function node is the callee of `.bind()` + * method. + * + * e.g. `(function() {}.bind(foo))` + * + * @param {ASTNode} node - A node to report. This is a FunctionExpression or + * an ArrowFunctionExpression. + * @returns {boolean} `true` if the node is the callee of `.bind()` method. + */ + function isCalleeOfBindMethod(node) { + var parent = node.parent; + var grandparent = parent.parent; - /** - * Removes the scope information object from the top of the stack. - * At the same time, this reports the function node if the function has - * `.bind()` and the `this` keywords found. - * - * @param {ASTNode} node - A node to remove. This node is a - * FunctionExpression or a FunctionDeclaration node. - * @returns {void} - */ - function exitFunction(node) { - if (scopeInfo.isBound && !scopeInfo.thisFound) { - report(node); + return ( + grandparent && + grandparent.type === "CallExpression" && + grandparent.callee === parent && + grandparent.arguments.length === 1 && + parent.type === "MemberExpression" && + parent.object === node && + getPropertyName(parent) === "bind" + ); } - scopeInfo = scopeInfo.upper; - } + /** + * Adds a scope information object to the stack. + * + * @param {ASTNode} node - A node to add. This node is a FunctionExpression + * or a FunctionDeclaration node. + * @returns {void} + */ + function enterFunction(node) { + scopeInfo = { + isBound: isCalleeOfBindMethod(node), + thisFound: false, + upper: scopeInfo + }; + } - /** - * Reports a given arrow function if the function is callee of `.bind()` - * method. - * - * @param {ASTNode} node - A node to report. This node is an - * ArrowFunctionExpression. - * @returns {void} - */ - function exitArrowFunction(node) { - if (isCalleeOfBindMethod(node)) { - report(node); + /** + * Removes the scope information object from the top of the stack. + * At the same time, this reports the function node if the function has + * `.bind()` and the `this` keywords found. + * + * @param {ASTNode} node - A node to remove. This node is a + * FunctionExpression or a FunctionDeclaration node. + * @returns {void} + */ + function exitFunction(node) { + if (scopeInfo.isBound && !scopeInfo.thisFound) { + report(node); + } + + scopeInfo = scopeInfo.upper; } - } - /** - * Set the mark as the `this` keyword was found in this scope. - * - * @returns {void} - */ - function markAsThisFound() { - if (scopeInfo) { - scopeInfo.thisFound = true; + /** + * Reports a given arrow function if the function is callee of `.bind()` + * method. + * + * @param {ASTNode} node - A node to report. This node is an + * ArrowFunctionExpression. + * @returns {void} + */ + function exitArrowFunction(node) { + if (isCalleeOfBindMethod(node)) { + report(node); + } } - } - return { - "ArrowFunctionExpression:exit": exitArrowFunction, - "FunctionDeclaration": enterFunction, - "FunctionDeclaration:exit": exitFunction, - "FunctionExpression": enterFunction, - "FunctionExpression:exit": exitFunction, - "ThisExpression": markAsThisFound - }; -}; + /** + * Set the mark as the `this` keyword was found in this scope. + * + * @returns {void} + */ + function markAsThisFound() { + if (scopeInfo) { + scopeInfo.thisFound = true; + } + } -module.exports.schema = []; + return { + "ArrowFunctionExpression:exit": exitArrowFunction, + FunctionDeclaration: enterFunction, + "FunctionDeclaration:exit": exitFunction, + FunctionExpression: enterFunction, + "FunctionExpression:exit": exitFunction, + ThisExpression: markAsThisFound + }; + } +}; diff --git a/tools/eslint/lib/rules/no-extra-boolean-cast.js b/tools/eslint/lib/rules/no-extra-boolean-cast.js index c7ee1adc6b87fb..f14da0821dbbed 100644 --- a/tools/eslint/lib/rules/no-extra-boolean-cast.js +++ b/tools/eslint/lib/rules/no-extra-boolean-cast.js @@ -9,72 +9,82 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - // Node types which have a test which will coerce values to booleans. - var BOOLEAN_NODE_TYPES = [ - "IfStatement", - "DoWhileStatement", - "WhileStatement", - "ConditionalExpression", - "ForStatement" - ]; - - /** - * Check if a node is in a context where its value would be coerced to a boolean at runtime. - * - * @param {Object} node The node - * @param {Object} parent Its parent - * @returns {Boolean} If it is in a boolean context - */ - function isInBooleanContext(node, parent) { - return ( - (BOOLEAN_NODE_TYPES.indexOf(parent.type) !== -1 && - node === parent.test) || - - // ! - (parent.type === "UnaryExpression" && - parent.operator === "!") - ); - } +module.exports = { + meta: { + docs: { + description: "disallow unnecessary boolean casts", + category: "Possible Errors", + recommended: true + }, + schema: [] + }, - return { - "UnaryExpression": function(node) { - var ancestors = context.getAncestors(), - parent = ancestors.pop(), - grandparent = ancestors.pop(); + create: function(context) { - // Exit early if it's guaranteed not to match - if (node.operator !== "!" || - parent.type !== "UnaryExpression" || - parent.operator !== "!") { - return; - } + // Node types which have a test which will coerce values to booleans. + var BOOLEAN_NODE_TYPES = [ + "IfStatement", + "DoWhileStatement", + "WhileStatement", + "ConditionalExpression", + "ForStatement" + ]; - if (isInBooleanContext(parent, grandparent) || + /** + * Check if a node is in a context where its value would be coerced to a boolean at runtime. + * + * @param {Object} node The node + * @param {Object} parent Its parent + * @returns {Boolean} If it is in a boolean context + */ + function isInBooleanContext(node, parent) { + return ( + (BOOLEAN_NODE_TYPES.indexOf(parent.type) !== -1 && + node === parent.test) || - // Boolean() and new Boolean() - ((grandparent.type === "CallExpression" || grandparent.type === "NewExpression") && - grandparent.callee.type === "Identifier" && - grandparent.callee.name === "Boolean") - ) { - context.report(node, "Redundant double negation."); - } - }, - "CallExpression": function(node) { - var parent = node.parent; + // ! + (parent.type === "UnaryExpression" && + parent.operator === "!") + ); + } - if (node.callee.type !== "Identifier" || node.callee.name !== "Boolean") { - return; - } - if (isInBooleanContext(node, parent)) { - context.report(node, "Redundant Boolean call."); + return { + UnaryExpression: function(node) { + var ancestors = context.getAncestors(), + parent = ancestors.pop(), + grandparent = ancestors.pop(); + + // Exit early if it's guaranteed not to match + if (node.operator !== "!" || + parent.type !== "UnaryExpression" || + parent.operator !== "!") { + return; + } + + if (isInBooleanContext(parent, grandparent) || + + // Boolean() and new Boolean() + ((grandparent.type === "CallExpression" || grandparent.type === "NewExpression") && + grandparent.callee.type === "Identifier" && + grandparent.callee.name === "Boolean") + ) { + context.report(node, "Redundant double negation."); + } + }, + CallExpression: function(node) { + var parent = node.parent; + + if (node.callee.type !== "Identifier" || node.callee.name !== "Boolean") { + return; + } + + if (isInBooleanContext(node, parent)) { + context.report(node, "Redundant Boolean call."); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-extra-label.js b/tools/eslint/lib/rules/no-extra-label.js index c11a7035764d30..f1a48e3688e96d 100644 --- a/tools/eslint/lib/rules/no-extra-label.js +++ b/tools/eslint/lib/rules/no-extra-label.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to disallow unnecessary labels * @author Toru Nagashima - * @copyright 2016 Toru Nagashima. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; @@ -17,116 +15,126 @@ var astUtils = require("../ast-utils"); // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var scopeInfo = null; - - /** - * Creates a new scope with a breakable statement. - * - * @param {ASTNode} node - A node to create. This is a BreakableStatement. - * @returns {void} - */ - function enterBreakableStatement(node) { - scopeInfo = { - label: astUtils.getLabel(node), - breakable: true, - upper: scopeInfo - }; - } +module.exports = { + meta: { + docs: { + description: "disallow unnecessary labels", + category: "Best Practices", + recommended: false + }, - /** - * Removes the top scope of the stack. - * - * @returns {void} - */ - function exitBreakableStatement() { - scopeInfo = scopeInfo.upper; - } + schema: [] + }, - /** - * Creates a new scope with a labeled statement. - * - * This ignores it if the body is a breakable statement. - * In this case it's handled in the `enterBreakableStatement` function. - * - * @param {ASTNode} node - A node to create. This is a LabeledStatement. - * @returns {void} - */ - function enterLabeledStatement(node) { - if (!astUtils.isBreakableStatement(node.body)) { + create: function(context) { + var scopeInfo = null; + + /** + * Creates a new scope with a breakable statement. + * + * @param {ASTNode} node - A node to create. This is a BreakableStatement. + * @returns {void} + */ + function enterBreakableStatement(node) { scopeInfo = { - label: node.label.name, - breakable: false, + label: astUtils.getLabel(node), + breakable: true, upper: scopeInfo }; } - } - /** - * Removes the top scope of the stack. - * - * This ignores it if the body is a breakable statement. - * In this case it's handled in the `exitBreakableStatement` function. - * - * @param {ASTNode} node - A node. This is a LabeledStatement. - * @returns {void} - */ - function exitLabeledStatement(node) { - if (!astUtils.isBreakableStatement(node.body)) { + /** + * Removes the top scope of the stack. + * + * @returns {void} + */ + function exitBreakableStatement() { scopeInfo = scopeInfo.upper; } - } - /** - * Reports a given control node if it's unnecessary. - * - * @param {ASTNode} node - A node. This is a BreakStatement or a - * ContinueStatement. - * @returns {void} - */ - function reportIfUnnecessary(node) { - if (!node.label) { - return; + /** + * Creates a new scope with a labeled statement. + * + * This ignores it if the body is a breakable statement. + * In this case it's handled in the `enterBreakableStatement` function. + * + * @param {ASTNode} node - A node to create. This is a LabeledStatement. + * @returns {void} + */ + function enterLabeledStatement(node) { + if (!astUtils.isBreakableStatement(node.body)) { + scopeInfo = { + label: node.label.name, + breakable: false, + upper: scopeInfo + }; + } } - var labelNode = node.label; - var label = labelNode.name; - var info = scopeInfo; - - while (info) { - if (info.breakable || info.label === label) { - if (info.breakable && info.label === label) { - context.report({ - node: labelNode, - message: "This label '{{name}}' is unnecessary.", - data: labelNode - }); - } + /** + * Removes the top scope of the stack. + * + * This ignores it if the body is a breakable statement. + * In this case it's handled in the `exitBreakableStatement` function. + * + * @param {ASTNode} node - A node. This is a LabeledStatement. + * @returns {void} + */ + function exitLabeledStatement(node) { + if (!astUtils.isBreakableStatement(node.body)) { + scopeInfo = scopeInfo.upper; + } + } + + /** + * Reports a given control node if it's unnecessary. + * + * @param {ASTNode} node - A node. This is a BreakStatement or a + * ContinueStatement. + * @returns {void} + */ + function reportIfUnnecessary(node) { + if (!node.label) { return; } - info = info.upper; + var labelNode = node.label; + var label = labelNode.name; + var info = scopeInfo; + + while (info) { + if (info.breakable || info.label === label) { + if (info.breakable && info.label === label) { + context.report({ + node: labelNode, + message: "This label '{{name}}' is unnecessary.", + data: labelNode + }); + } + return; + } + + info = info.upper; + } } - } - return { - "WhileStatement": enterBreakableStatement, - "WhileStatement:exit": exitBreakableStatement, - "DoWhileStatement": enterBreakableStatement, - "DoWhileStatement:exit": exitBreakableStatement, - "ForStatement": enterBreakableStatement, - "ForStatement:exit": exitBreakableStatement, - "ForInStatement": enterBreakableStatement, - "ForInStatement:exit": exitBreakableStatement, - "ForOfStatement": enterBreakableStatement, - "ForOfStatement:exit": exitBreakableStatement, - "SwitchStatement": enterBreakableStatement, - "SwitchStatement:exit": exitBreakableStatement, - "LabeledStatement": enterLabeledStatement, - "LabeledStatement:exit": exitLabeledStatement, - "BreakStatement": reportIfUnnecessary, - "ContinueStatement": reportIfUnnecessary - }; + return { + WhileStatement: enterBreakableStatement, + "WhileStatement:exit": exitBreakableStatement, + DoWhileStatement: enterBreakableStatement, + "DoWhileStatement:exit": exitBreakableStatement, + ForStatement: enterBreakableStatement, + "ForStatement:exit": exitBreakableStatement, + ForInStatement: enterBreakableStatement, + "ForInStatement:exit": exitBreakableStatement, + ForOfStatement: enterBreakableStatement, + "ForOfStatement:exit": exitBreakableStatement, + SwitchStatement: enterBreakableStatement, + "SwitchStatement:exit": exitBreakableStatement, + LabeledStatement: enterLabeledStatement, + "LabeledStatement:exit": exitLabeledStatement, + BreakStatement: reportIfUnnecessary, + ContinueStatement: reportIfUnnecessary + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-extra-parens.js b/tools/eslint/lib/rules/no-extra-parens.js index 50f5160b208c56..cf129394ba0fd2 100644 --- a/tools/eslint/lib/rules/no-extra-parens.js +++ b/tools/eslint/lib/rules/no-extra-parens.js @@ -1,8 +1,6 @@ /** * @fileoverview Disallow parenthesising higher precedence subexpressions. * @author Michael Ficarra - * @copyright 2014 Michael Ficarra. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; @@ -12,569 +10,583 @@ var astUtils = require("../ast-utils.js"); -module.exports = function(context) { - var isParenthesised = astUtils.isParenthesised.bind(astUtils, context); - var ALL_NODES = context.options[0] !== "functions"; - var EXCEPT_COND_ASSIGN = ALL_NODES && context.options[1] && context.options[1].conditionalAssign === false; - var sourceCode = context.getSourceCode(); - - /** - * Determines if this rule should be enforced for a node given the current configuration. - * @param {ASTNode} node - The node to be checked. - * @returns {boolean} True if the rule should be enforced for this node. - * @private - */ - function ruleApplies(node) { - return ALL_NODES || node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression"; - } +module.exports = { + meta: { + docs: { + description: "disallow unnecessary parentheses", + category: "Possible Errors", + recommended: false + }, - /** - * Determines if a node is surrounded by parentheses twice. - * @param {ASTNode} node - The node to be checked. - * @returns {boolean} True if the node is doubly parenthesised. - * @private - */ - function isParenthesisedTwice(node) { - var previousToken = context.getTokenBefore(node, 1), - nextToken = context.getTokenAfter(node, 1); - - return isParenthesised(node) && previousToken && nextToken && - previousToken.value === "(" && previousToken.range[1] <= node.range[0] && - nextToken.value === ")" && nextToken.range[0] >= node.range[1]; - } + schema: { + anyOf: [ + { + type: "array", + items: [ + { + enum: ["functions"] + } + ], + minItems: 0, + maxItems: 1 + }, + { + type: "array", + items: [ + { + enum: ["all"] + }, + { + type: "object", + properties: { + conditionalAssign: {type: "boolean"}, + nestedBinaryExpressions: {type: "boolean"} + }, + additionalProperties: false + } + ], + minItems: 0, + maxItems: 2 + } + ] + } + }, + + create: function(context) { + var isParenthesised = astUtils.isParenthesised.bind(astUtils, context); + var ALL_NODES = context.options[0] !== "functions"; + var EXCEPT_COND_ASSIGN = ALL_NODES && context.options[1] && context.options[1].conditionalAssign === false; + var NESTED_BINARY = ALL_NODES && context.options[1] && context.options[1].nestedBinaryExpressions === false; + var sourceCode = context.getSourceCode(); + + /** + * Determines if this rule should be enforced for a node given the current configuration. + * @param {ASTNode} node - The node to be checked. + * @returns {boolean} True if the rule should be enforced for this node. + * @private + */ + function ruleApplies(node) { + return ALL_NODES || node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression"; + } - /** - * Determines if a node is surrounded by (potentially) invalid parentheses. - * @param {ASTNode} node - The node to be checked. - * @returns {boolean} True if the node is incorrectly parenthesised. - * @private - */ - function hasExcessParens(node) { - return ruleApplies(node) && isParenthesised(node); - } + /** + * Determines if a node is surrounded by parentheses twice. + * @param {ASTNode} node - The node to be checked. + * @returns {boolean} True if the node is doubly parenthesised. + * @private + */ + function isParenthesisedTwice(node) { + var previousToken = context.getTokenBefore(node, 1), + nextToken = context.getTokenAfter(node, 1); + + return isParenthesised(node) && previousToken && nextToken && + previousToken.value === "(" && previousToken.range[1] <= node.range[0] && + nextToken.value === ")" && nextToken.range[0] >= node.range[1]; + } - /** - * Determines if a node that is expected to be parenthesised is surrounded by - * (potentially) invalid extra parentheses. - * @param {ASTNode} node - The node to be checked. - * @returns {boolean} True if the node is has an unexpected extra pair of parentheses. - * @private - */ - function hasDoubleExcessParens(node) { - return ruleApplies(node) && isParenthesisedTwice(node); - } + /** + * Determines if a node is surrounded by (potentially) invalid parentheses. + * @param {ASTNode} node - The node to be checked. + * @returns {boolean} True if the node is incorrectly parenthesised. + * @private + */ + function hasExcessParens(node) { + return ruleApplies(node) && isParenthesised(node); + } - /** - * Determines if a node test expression is allowed to have a parenthesised assignment - * @param {ASTNode} node - The node to be checked. - * @returns {boolean} True if the assignment can be parenthesised. - * @private - */ - function isCondAssignException(node) { - return EXCEPT_COND_ASSIGN && node.test.type === "AssignmentExpression"; - } + /** + * Determines if a node that is expected to be parenthesised is surrounded by + * (potentially) invalid extra parentheses. + * @param {ASTNode} node - The node to be checked. + * @returns {boolean} True if the node is has an unexpected extra pair of parentheses. + * @private + */ + function hasDoubleExcessParens(node) { + return ruleApplies(node) && isParenthesisedTwice(node); + } - /** - * Determines if a node following a [no LineTerminator here] restriction is - * surrounded by (potentially) invalid extra parentheses. - * @param {Token} token - The token preceding the [no LineTerminator here] restriction. - * @param {ASTNode} node - The node to be checked. - * @returns {boolean} True if the node is incorrectly parenthesised. - * @private - */ - function hasExcessParensNoLineTerminator(token, node) { - if (token.loc.end.line === node.loc.start.line) { - return hasExcessParens(node); + /** + * Determines if a node test expression is allowed to have a parenthesised assignment + * @param {ASTNode} node - The node to be checked. + * @returns {boolean} True if the assignment can be parenthesised. + * @private + */ + function isCondAssignException(node) { + return EXCEPT_COND_ASSIGN && node.test.type === "AssignmentExpression"; } - return hasDoubleExcessParens(node); - } + /** + * Determines if a node following a [no LineTerminator here] restriction is + * surrounded by (potentially) invalid extra parentheses. + * @param {Token} token - The token preceding the [no LineTerminator here] restriction. + * @param {ASTNode} node - The node to be checked. + * @returns {boolean} True if the node is incorrectly parenthesised. + * @private + */ + function hasExcessParensNoLineTerminator(token, node) { + if (token.loc.end.line === node.loc.start.line) { + return hasExcessParens(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) { - var parent = node.parent; + return hasDoubleExcessParens(node); + } - while (parent) { - switch (parent.type) { - case "SequenceExpression": - if (parent.expressions[0] !== node || isParenthesised(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) { + var 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; - } - break; + } - case "UnaryExpression": - case "UpdateExpression": - if (parent.prefix || isParenthesised(node)) { - return false; - } - break; + node = parent; + parent = parent.parent; + } - case "BinaryExpression": - case "LogicalExpression": - if (parent.left !== node || isParenthesised(node)) { - return false; - } - break; + /* istanbul ignore next */ + throw new Error("unreachable"); + } - case "ConditionalExpression": - if (parent.test !== node || isParenthesised(node)) { - return false; - } - break; + /** + * Get the precedence level based on the node type + * @param {ASTNode} node node to evaluate + * @returns {int} precedence level + * @private + */ + function precedence(node) { - case "CallExpression": - if (parent.callee !== node || isParenthesised(node)) { - return false; - } - break; + switch (node.type) { + case "SequenceExpression": + return 0; - case "MemberExpression": - if (parent.object !== node || isParenthesised(node)) { - return false; - } - break; + case "AssignmentExpression": + case "ArrowFunctionExpression": + case "YieldExpression": + return 1; - case "ExpressionStatement": - return true; + case "ConditionalExpression": + return 3; - default: - return false; - } + case "LogicalExpression": + switch (node.operator) { + case "||": + return 4; + case "&&": + return 5; - node = parent; - parent = parent.parent; - } + // no default + } - /* istanbul ignore next */ - throw new Error("unreachable"); - } + /* falls through */ - /** - * Get the precedence level based on the node type - * @param {ASTNode} node node to evaluate - * @returns {int} precedence level - * @private - */ - function precedence(node) { - - switch (node.type) { - case "SequenceExpression": - return 0; - - case "AssignmentExpression": - case "ArrowFunctionExpression": - case "YieldExpression": - return 1; - - case "ConditionalExpression": - return 3; - - case "LogicalExpression": - switch (node.operator) { - case "||": - return 4; - case "&&": - return 5; - - // no default - } + case "BinaryExpression": - /* falls through */ - - case "BinaryExpression": - - switch (node.operator) { - case "|": - return 6; - case "^": - return 7; - case "&": - return 8; - case "==": - case "!=": - case "===": - case "!==": - return 9; - case "<": - case "<=": - case ">": - case ">=": - case "in": - case "instanceof": - return 10; - case "<<": - case ">>": - case ">>>": - return 11; - case "+": - case "-": - return 12; - case "*": - case "/": - case "%": - return 13; - - // no default - } + switch (node.operator) { + case "|": + return 6; + case "^": + return 7; + case "&": + return 8; + case "==": + case "!=": + case "===": + case "!==": + return 9; + case "<": + case "<=": + case ">": + case ">=": + case "in": + case "instanceof": + return 10; + case "<<": + case ">>": + case ">>>": + return 11; + case "+": + case "-": + return 12; + case "*": + case "/": + case "%": + return 13; + + // no default + } - /* falls through */ + /* falls through */ - case "UnaryExpression": - return 14; + case "UnaryExpression": + return 14; - case "UpdateExpression": - return 15; + case "UpdateExpression": + return 15; - case "CallExpression": + case "CallExpression": - // IIFE is allowed to have parens in any position (#655) - if (node.callee.type === "FunctionExpression") { - return -1; - } - return 16; + // IIFE is allowed to have parens in any position (#655) + if (node.callee.type === "FunctionExpression") { + return -1; + } + return 16; - case "NewExpression": - return 17; + case "NewExpression": + return 17; - // no default + // no default + } + return 18; } - return 18; - } - /** - * Report the node - * @param {ASTNode} node node to evaluate - * @returns {void} - * @private - */ - function report(node) { - var previousToken = context.getTokenBefore(node); - - context.report(node, previousToken.loc.start, "Gratuitous parentheses around expression."); - } + /** + * Report the node + * @param {ASTNode} node node to evaluate + * @returns {void} + * @private + */ + function report(node) { + var previousToken = context.getTokenBefore(node); - /** - * Evaluate Unary update - * @param {ASTNode} node node to evaluate - * @returns {void} - * @private - */ - function dryUnaryUpdate(node) { - if (hasExcessParens(node.argument) && precedence(node.argument) >= precedence(node)) { - report(node.argument); + context.report(node, previousToken.loc.start, "Gratuitous parentheses around expression."); } - } - /** - * Evaluate a new call - * @param {ASTNode} node node to evaluate - * @returns {void} - * @private - */ - function dryCallNew(node) { - if (hasExcessParens(node.callee) && precedence(node.callee) >= precedence(node) && !( - node.type === "CallExpression" && - node.callee.type === "FunctionExpression" && - - // One set of parentheses are allowed for a function expression - !hasDoubleExcessParens(node.callee) - )) { - report(node.callee); + /** + * Evaluate Unary update + * @param {ASTNode} node node to evaluate + * @returns {void} + * @private + */ + function dryUnaryUpdate(node) { + if (hasExcessParens(node.argument) && precedence(node.argument) >= precedence(node)) { + report(node.argument); + } } - if (node.arguments.length === 1) { - if (hasDoubleExcessParens(node.arguments[0]) && precedence(node.arguments[0]) >= precedence({type: "AssignmentExpression"})) { - report(node.arguments[0]); + + /** + * Evaluate a new call + * @param {ASTNode} node node to evaluate + * @returns {void} + * @private + */ + function dryCallNew(node) { + if (hasExcessParens(node.callee) && precedence(node.callee) >= precedence(node) && !( + node.type === "CallExpression" && + node.callee.type === "FunctionExpression" && + + // One set of parentheses are allowed for a function expression + !hasDoubleExcessParens(node.callee) + )) { + report(node.callee); } - } else { - [].forEach.call(node.arguments, function(arg) { - if (hasExcessParens(arg) && precedence(arg) >= precedence({type: "AssignmentExpression"})) { - report(arg); + if (node.arguments.length === 1) { + if (hasDoubleExcessParens(node.arguments[0]) && precedence(node.arguments[0]) >= precedence({type: "AssignmentExpression"})) { + report(node.arguments[0]); } - }); + } else { + [].forEach.call(node.arguments, function(arg) { + if (hasExcessParens(arg) && precedence(arg) >= precedence({type: "AssignmentExpression"})) { + report(arg); + } + }); + } } - } - /** - * Evaluate binary logicals - * @param {ASTNode} node node to evaluate - * @returns {void} - * @private - */ - function dryBinaryLogical(node) { - var prec = precedence(node); - - if (hasExcessParens(node.left) && precedence(node.left) >= prec) { - report(node.left); - } - if (hasExcessParens(node.right) && precedence(node.right) > prec) { - report(node.right); + /** + * Evaluate binary logicals + * @param {ASTNode} node node to evaluate + * @returns {void} + * @private + */ + function dryBinaryLogical(node) { + if (!NESTED_BINARY) { + var prec = precedence(node); + + if (hasExcessParens(node.left) && precedence(node.left) >= prec) { + report(node.left); + } + if (hasExcessParens(node.right) && precedence(node.right) > prec) { + report(node.right); + } + } } - } - return { - "ArrayExpression": function(node) { - [].forEach.call(node.elements, function(e) { - if (e && hasExcessParens(e) && precedence(e) >= precedence({type: "AssignmentExpression"})) { - report(e); + return { + ArrayExpression: function(node) { + [].forEach.call(node.elements, function(e) { + if (e && hasExcessParens(e) && precedence(e) >= precedence({type: "AssignmentExpression"})) { + report(e); + } + }); + }, + + ArrowFunctionExpression: function(node) { + if (node.body.type !== "BlockStatement") { + if (sourceCode.getFirstToken(node.body).value !== "{" && hasExcessParens(node.body) && precedence(node.body) >= precedence({type: "AssignmentExpression"})) { + report(node.body); + return; + } + + // Object literals *must* be parenthesised + if (node.body.type === "ObjectExpression" && hasDoubleExcessParens(node.body)) { + report(node.body); + return; + } } - }); - }, + }, - "ArrowFunctionExpression": function(node) { - if (node.body.type !== "BlockStatement") { - if (node.body.type !== "ObjectExpression" && hasExcessParens(node.body) && precedence(node.body) >= precedence({type: "AssignmentExpression"})) { - report(node.body); - return; + AssignmentExpression: function(node) { + if (hasExcessParens(node.right) && precedence(node.right) >= precedence(node)) { + report(node.right); } + }, + + BinaryExpression: dryBinaryLogical, + CallExpression: dryCallNew, - // Object literals *must* be parenthesised - if (node.body.type === "ObjectExpression" && hasDoubleExcessParens(node.body)) { - report(node.body); - return; + ConditionalExpression: function(node) { + if (hasExcessParens(node.test) && precedence(node.test) >= precedence({type: "LogicalExpression", operator: "||"})) { + report(node.test); } - } - }, + if (hasExcessParens(node.consequent) && precedence(node.consequent) >= precedence({type: "AssignmentExpression"})) { + report(node.consequent); + } + if (hasExcessParens(node.alternate) && precedence(node.alternate) >= precedence({type: "AssignmentExpression"})) { + report(node.alternate); + } + }, - "AssignmentExpression": function(node) { - if (hasExcessParens(node.right) && precedence(node.right) >= precedence(node)) { - report(node.right); - } - }, + DoWhileStatement: function(node) { + if (hasDoubleExcessParens(node.test) && !isCondAssignException(node)) { + report(node.test); + } + }, + + ExpressionStatement: function(node) { + var firstToken, secondToken, firstTokens; + + if (hasExcessParens(node.expression)) { + firstTokens = context.getFirstTokens(node.expression, 2); + firstToken = firstTokens[0]; + secondToken = firstTokens[1]; + + if ( + !firstToken || + firstToken.value !== "{" && + firstToken.value !== "function" && + firstToken.value !== "class" && + ( + firstToken.value !== "let" || + !secondToken || + secondToken.value !== "[" + ) + ) { + report(node.expression); + } + } + }, - "BinaryExpression": dryBinaryLogical, - "CallExpression": dryCallNew, + ForInStatement: function(node) { + if (hasExcessParens(node.right)) { + report(node.right); + } + }, - "ConditionalExpression": function(node) { - if (hasExcessParens(node.test) && precedence(node.test) >= precedence({type: "LogicalExpression", operator: "||"})) { - report(node.test); - } - if (hasExcessParens(node.consequent) && precedence(node.consequent) >= precedence({type: "AssignmentExpression"})) { - report(node.consequent); - } - if (hasExcessParens(node.alternate) && precedence(node.alternate) >= precedence({type: "AssignmentExpression"})) { - report(node.alternate); - } - }, + ForOfStatement: function(node) { + if (hasExcessParens(node.right)) { + report(node.right); + } + }, - "DoWhileStatement": function(node) { - if (hasDoubleExcessParens(node.test) && !isCondAssignException(node)) { - report(node.test); - } - }, + ForStatement: function(node) { + if (node.init && hasExcessParens(node.init)) { + report(node.init); + } + + if (node.test && hasExcessParens(node.test) && !isCondAssignException(node)) { + report(node.test); + } + + if (node.update && hasExcessParens(node.update)) { + report(node.update); + } + }, - "ExpressionStatement": function(node) { - var firstToken, secondToken, firstTokens; + IfStatement: function(node) { + if (hasDoubleExcessParens(node.test) && !isCondAssignException(node)) { + report(node.test); + } + }, - if (hasExcessParens(node.expression)) { - firstTokens = context.getFirstTokens(node.expression, 2); - firstToken = firstTokens[0]; - secondToken = firstTokens[1]; + LogicalExpression: dryBinaryLogical, + MemberExpression: function(node) { if ( - !firstToken || - firstToken.value !== "{" && - firstToken.value !== "function" && - firstToken.value !== "class" && + hasExcessParens(node.object) && + precedence(node.object) >= precedence(node) && ( - firstToken.value !== "let" || - !secondToken || - secondToken.value !== "[" + node.computed || + !( + (node.object.type === "Literal" && + typeof node.object.value === "number" && + /^[0-9]+$/.test(context.getFirstToken(node.object).value)) + || + + // 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.expression); + report(node.object); } - } - }, - - "ForInStatement": function(node) { - if (hasExcessParens(node.right)) { - report(node.right); - } - }, - - "ForOfStatement": function(node) { - if (hasExcessParens(node.right)) { - report(node.right); - } - }, + if (node.computed && hasExcessParens(node.property)) { + report(node.property); + } + }, - "ForStatement": function(node) { - if (node.init && hasExcessParens(node.init)) { - report(node.init); - } + NewExpression: dryCallNew, - if (node.test && hasExcessParens(node.test) && !isCondAssignException(node)) { - report(node.test); - } + ObjectExpression: function(node) { + [].forEach.call(node.properties, function(e) { + var v = e.value; - if (node.update && hasExcessParens(node.update)) { - report(node.update); - } - }, + if (v && hasExcessParens(v) && precedence(v) >= precedence({type: "AssignmentExpression"})) { + report(v); + } + }); + }, - "IfStatement": function(node) { - if (hasDoubleExcessParens(node.test) && !isCondAssignException(node)) { - report(node.test); - } - }, + ReturnStatement: function(node) { + var returnToken = sourceCode.getFirstToken(node); - "LogicalExpression": dryBinaryLogical, - - "MemberExpression": function(node) { - if ( - hasExcessParens(node.object) && - precedence(node.object) >= precedence(node) && - ( - node.computed || - !( - (node.object.type === "Literal" && - typeof node.object.value === "number" && - /^[0-9]+$/.test(context.getFirstToken(node.object).value)) - || + if (node.argument && + hasExcessParensNoLineTerminator(returnToken, node.argument) && // 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); - } - if (node.computed && hasExcessParens(node.property)) { - report(node.property); - } - }, - - "NewExpression": dryCallNew, - - "ObjectExpression": function(node) { - [].forEach.call(node.properties, function(e) { - var v = e.value; - - if (v && hasExcessParens(v) && precedence(v) >= precedence({type: "AssignmentExpression"})) { - report(v); + !(node.argument.type === "Literal" && node.argument.regex)) { + report(node.argument); } - }); - }, + }, - "ReturnStatement": function(node) { - var returnToken = sourceCode.getFirstToken(node); - - if (node.argument && - hasExcessParensNoLineTerminator(returnToken, node.argument) && - - // RegExp literal is allowed to have parens (#1589) - !(node.argument.type === "Literal" && node.argument.regex)) { - report(node.argument); - } - }, + SequenceExpression: function(node) { + [].forEach.call(node.expressions, function(e) { + if (hasExcessParens(e) && precedence(e) >= precedence(node)) { + report(e); + } + }); + }, - "SequenceExpression": function(node) { - [].forEach.call(node.expressions, function(e) { - if (hasExcessParens(e) && precedence(e) >= precedence(node)) { - report(e); + SwitchCase: function(node) { + if (node.test && hasExcessParens(node.test)) { + report(node.test); } - }); - }, + }, - "SwitchCase": function(node) { - if (node.test && hasExcessParens(node.test)) { - report(node.test); - } - }, - - "SwitchStatement": function(node) { - if (hasDoubleExcessParens(node.discriminant)) { - report(node.discriminant); - } - }, + SwitchStatement: function(node) { + if (hasDoubleExcessParens(node.discriminant)) { + report(node.discriminant); + } + }, - "ThrowStatement": function(node) { - var throwToken = sourceCode.getFirstToken(node); + ThrowStatement: function(node) { + var throwToken = sourceCode.getFirstToken(node); - if (hasExcessParensNoLineTerminator(throwToken, node.argument)) { - report(node.argument); - } - }, + if (hasExcessParensNoLineTerminator(throwToken, node.argument)) { + report(node.argument); + } + }, - "UnaryExpression": dryUnaryUpdate, - "UpdateExpression": dryUnaryUpdate, + UnaryExpression: dryUnaryUpdate, + UpdateExpression: dryUnaryUpdate, - "VariableDeclarator": function(node) { - if (node.init && hasExcessParens(node.init) && - precedence(node.init) >= precedence({type: "AssignmentExpression"}) && + VariableDeclarator: function(node) { + if (node.init && hasExcessParens(node.init) && + precedence(node.init) >= precedence({type: "AssignmentExpression"}) && - // RegExp literal is allowed to have parens (#1589) - !(node.init.type === "Literal" && node.init.regex)) { - report(node.init); - } - }, + // RegExp literal is allowed to have parens (#1589) + !(node.init.type === "Literal" && node.init.regex)) { + report(node.init); + } + }, - "WhileStatement": function(node) { - if (hasDoubleExcessParens(node.test) && !isCondAssignException(node)) { - report(node.test); - } - }, + WhileStatement: function(node) { + if (hasDoubleExcessParens(node.test) && !isCondAssignException(node)) { + report(node.test); + } + }, - "WithStatement": function(node) { - if (hasDoubleExcessParens(node.object)) { - report(node.object); - } - }, + WithStatement: function(node) { + if (hasDoubleExcessParens(node.object)) { + report(node.object); + } + }, - "YieldExpression": function(node) { - var yieldToken; + YieldExpression: function(node) { + var yieldToken; - if (node.argument) { - yieldToken = sourceCode.getFirstToken(node); + if (node.argument) { + yieldToken = sourceCode.getFirstToken(node); - if ((precedence(node.argument) >= precedence(node) && - hasExcessParensNoLineTerminator(yieldToken, node.argument)) || - hasDoubleExcessParens(node.argument)) { - report(node.argument); + if ((precedence(node.argument) >= precedence(node) && + hasExcessParensNoLineTerminator(yieldToken, node.argument)) || + hasDoubleExcessParens(node.argument)) { + report(node.argument); + } } } - } - }; + }; -}; - -module.exports.schema = { - "anyOf": [ - { - "type": "array", - "items": [ - { - "enum": ["functions"] - } - ], - "minItems": 0, - "maxItems": 1 - }, - { - "type": "array", - "items": [ - { - "enum": ["all"] - }, - { - "type": "object", - "properties": { - "conditionalAssign": {"type": "boolean"} - }, - "additionalProperties": false - } - ], - "minItems": 0, - "maxItems": 2 - } - ] + } }; diff --git a/tools/eslint/lib/rules/no-extra-semi.js b/tools/eslint/lib/rules/no-extra-semi.js index 9639ae178eaaf8..e451b9e42e3367 100644 --- a/tools/eslint/lib/rules/no-extra-semi.js +++ b/tools/eslint/lib/rules/no-extra-semi.js @@ -9,76 +9,87 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - /** - * Reports an unnecessary semicolon error. - * @param {Node|Token} nodeOrToken - A node or a token to be reported. - * @returns {void} - */ - function report(nodeOrToken) { - context.report({ - node: nodeOrToken, - message: "Unnecessary semicolon.", - fix: function(fixer) { - return fixer.remove(nodeOrToken); - } - }); - } +module.exports = { + meta: { + docs: { + description: "disallow unnecessary semicolons", + category: "Possible Errors", + recommended: true + }, - /** - * Checks for a part of a class body. - * This checks tokens from a specified token to a next MethodDefinition or the end of class body. - * - * @param {Token} firstToken - The first token to check. - * @returns {void} - */ - function checkForPartOfClassBody(firstToken) { - for (var token = firstToken; - token.type === "Punctuator" && token.value !== "}"; - token = context.getTokenAfter(token) - ) { - if (token.value === ";") { - report(token); - } - } - } + fixable: "code", + schema: [] + }, - return { + create: function(context) { /** - * Reports this empty statement, except if the parent node is a loop. - * @param {Node} node - A EmptyStatement node to be reported. + * Reports an unnecessary semicolon error. + * @param {Node|Token} nodeOrToken - A node or a token to be reported. * @returns {void} */ - "EmptyStatement": function(node) { - var parent = node.parent, - allowedParentTypes = ["ForStatement", "ForInStatement", "ForOfStatement", "WhileStatement", "DoWhileStatement"]; - - if (allowedParentTypes.indexOf(parent.type) === -1) { - report(node); - } - }, - - /** - * Checks tokens from the head of this class body to the first MethodDefinition or the end of this class body. - * @param {Node} node - A ClassBody node to check. - * @returns {void} - */ - "ClassBody": function(node) { - checkForPartOfClassBody(context.getFirstToken(node, 1)); // 0 is `{`. - }, + function report(nodeOrToken) { + context.report({ + node: nodeOrToken, + message: "Unnecessary semicolon.", + fix: function(fixer) { + return fixer.remove(nodeOrToken); + } + }); + } /** - * Checks tokens from this MethodDefinition to the next MethodDefinition or the end of this class body. - * @param {Node} node - A MethodDefinition node of the start point. + * Checks for a part of a class body. + * This checks tokens from a specified token to a next MethodDefinition or the end of class body. + * + * @param {Token} firstToken - The first token to check. * @returns {void} */ - "MethodDefinition": function(node) { - checkForPartOfClassBody(context.getTokenAfter(node)); + function checkForPartOfClassBody(firstToken) { + for (var token = firstToken; + token.type === "Punctuator" && token.value !== "}"; + token = context.getTokenAfter(token) + ) { + if (token.value === ";") { + report(token); + } + } } - }; -}; + return { + + /** + * Reports this empty statement, except if the parent node is a loop. + * @param {Node} node - A EmptyStatement node to be reported. + * @returns {void} + */ + EmptyStatement: function(node) { + var parent = node.parent, + allowedParentTypes = ["ForStatement", "ForInStatement", "ForOfStatement", "WhileStatement", "DoWhileStatement"]; -module.exports.schema = []; + if (allowedParentTypes.indexOf(parent.type) === -1) { + report(node); + } + }, + + /** + * Checks tokens from the head of this class body to the first MethodDefinition or the end of this class body. + * @param {Node} node - A ClassBody node to check. + * @returns {void} + */ + ClassBody: function(node) { + checkForPartOfClassBody(context.getFirstToken(node, 1)); // 0 is `{`. + }, + + /** + * Checks tokens from this MethodDefinition to the next MethodDefinition or the end of this class body. + * @param {Node} node - A MethodDefinition node of the start point. + * @returns {void} + */ + MethodDefinition: function(node) { + checkForPartOfClassBody(context.getTokenAfter(node)); + } + }; + + } +}; diff --git a/tools/eslint/lib/rules/no-fallthrough.js b/tools/eslint/lib/rules/no-fallthrough.js index 1e5d40c7ff77f0..2edb4972bafd0a 100644 --- a/tools/eslint/lib/rules/no-fallthrough.js +++ b/tools/eslint/lib/rules/no-fallthrough.js @@ -14,19 +14,20 @@ var lodash = require("lodash"); // Helpers //------------------------------------------------------------------------------ -var FALLTHROUGH_COMMENT = /falls?\s?through/i; +var DEFAULT_FALLTHROUGH_COMMENT = /falls?\s?through/i; /** * Checks whether or not a given node has a fallthrough comment. * @param {ASTNode} node - A SwitchCase node to get comments. * @param {RuleContext} context - A rule context which stores comments. - * @returns {boolean} `true` if the node has a fallthrough comment. + * @param {RegExp} fallthroughCommentPattern - A pattern to match comment to. + * @returns {boolean} `true` if the node has a valid fallthrough comment. */ -function hasFallthroughComment(node, context) { +function hasFallthroughComment(node, context, fallthroughCommentPattern) { var sourceCode = context.getSourceCode(); var comment = lodash.last(sourceCode.getComments(node).leading); - return Boolean(comment && FALLTHROUGH_COMMENT.test(comment.value)); + return Boolean(comment && fallthroughCommentPattern.test(comment.value)); } /** @@ -38,58 +39,97 @@ function isReachable(segment) { return segment.reachable; } +/** + * Checks whether a node and a token are separated by blank lines + * @param {ASTNode} node - The node to check + * @param {Token} token - The token to compare against + * @returns {boolean} `true` if there are blank lines between node and token + */ +function hasBlankLinesBetween(node, token) { + return token.loc.start.line > node.loc.end.line + 1; +} + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var currentCodePath = null; - - /* - * We need to use leading comments of the next SwitchCase node because - * trailing comments is wrong if semicolons are omitted. - */ - var fallthroughCase = null; - - return { - "onCodePathStart": function(codePath) { - currentCodePath = codePath; - }, - "onCodePathEnd": function() { - currentCodePath = currentCodePath.upper; +module.exports = { + meta: { + docs: { + description: "disallow fallthrough of `case` statements", + category: "Best Practices", + recommended: true }, - "SwitchCase": function(node) { - - /* - * Checks whether or not there is a fallthrough comment. - * And reports the previous fallthrough node if that does not exist. - */ - if (fallthroughCase && !hasFallthroughComment(node, context)) { - context.report({ - message: "Expected a 'break' statement before '{{type}}'.", - data: {type: node.test ? "case" : "default"}, - node: node - }); + schema: [ + { + type: "object", + properties: { + commentPattern: { + type: "string" + } + }, + additionalProperties: false } - fallthroughCase = null; - }, + ] + }, + + create: function(context) { + var options = context.options[0] || {}; + var currentCodePath = null; + var sourceCode = context.getSourceCode(); + + /* + * We need to use leading comments of the next SwitchCase node because + * trailing comments is wrong if semicolons are omitted. + */ + var fallthroughCase = null; + var fallthroughCommentPattern = null; + + if (options.commentPattern) { + fallthroughCommentPattern = new RegExp(options.commentPattern); + } else { + fallthroughCommentPattern = DEFAULT_FALLTHROUGH_COMMENT; + } - "SwitchCase:exit": function(node) { - - /* - * `reachable` meant fall through because statements preceded by - * `break`, `return`, or `throw` are unreachable. - * And allows empty cases and the last case. - */ - if (currentCodePath.currentSegments.some(isReachable) && - node.consequent.length > 0 && - lodash.last(node.parent.cases) !== node - ) { - fallthroughCase = node; + return { + onCodePathStart: function(codePath) { + currentCodePath = codePath; + }, + onCodePathEnd: function() { + currentCodePath = currentCodePath.upper; + }, + + SwitchCase: function(node) { + + /* + * Checks whether or not there is a fallthrough comment. + * And reports the previous fallthrough node if that does not exist. + */ + if (fallthroughCase && !hasFallthroughComment(node, context, fallthroughCommentPattern)) { + context.report({ + message: "Expected a 'break' statement before '{{type}}'.", + data: {type: node.test ? "case" : "default"}, + node: node + }); + } + fallthroughCase = null; + }, + + "SwitchCase:exit": function(node) { + var nextToken = sourceCode.getTokenAfter(node); + + /* + * `reachable` meant fall through because statements preceded by + * `break`, `return`, or `throw` are unreachable. + * And allows empty cases and the last case. + */ + if (currentCodePath.currentSegments.some(isReachable) && + (node.consequent.length > 0 || hasBlankLinesBetween(node, nextToken)) && + lodash.last(node.parent.cases) !== node) { + fallthroughCase = node; + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-floating-decimal.js b/tools/eslint/lib/rules/no-floating-decimal.js index 61a84f5e46efaa..56ebd3989a4eb8 100644 --- a/tools/eslint/lib/rules/no-floating-decimal.js +++ b/tools/eslint/lib/rules/no-floating-decimal.js @@ -9,22 +9,32 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow leading or trailing decimal points in numeric literals", + category: "Best Practices", + recommended: false + }, - return { - "Literal": function(node) { + schema: [] + }, - if (typeof node.value === "number") { - if (node.raw.indexOf(".") === 0) { - context.report(node, "A leading decimal point can be confused with a dot."); - } - if (node.raw.indexOf(".") === node.raw.length - 1) { - context.report(node, "A trailing decimal point can be confused with a dot."); + create: function(context) { + + return { + Literal: function(node) { + + if (typeof node.value === "number") { + if (node.raw.indexOf(".") === 0) { + context.report(node, "A leading decimal point can be confused with a dot."); + } + if (node.raw.indexOf(".") === node.raw.length - 1) { + context.report(node, "A trailing decimal point can be confused with a dot."); + } } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-func-assign.js b/tools/eslint/lib/rules/no-func-assign.js index f72c8c0150762a..ac3afe55c05533 100644 --- a/tools/eslint/lib/rules/no-func-assign.js +++ b/tools/eslint/lib/rules/no-func-assign.js @@ -1,7 +1,6 @@ /** * @fileoverview Rule to flag use of function declaration identifiers as variables. * @author Ian Christian Myers - * @copyright 2013 Ian Christian Myers. All rights reserved. */ "use strict"; @@ -12,46 +11,56 @@ var astUtils = require("../ast-utils"); // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - /** - * Reports a reference if is non initializer and writable. - * @param {References} references - Collection of reference to check. - * @returns {void} - */ - function checkReference(references) { - astUtils.getModifyingReferences(references).forEach(function(reference) { - context.report( - reference.identifier, - "'{{name}}' is a function.", - {name: reference.identifier.name}); - }); - } +module.exports = { + meta: { + docs: { + description: "disallow reassigning `function` declarations", + category: "Possible Errors", + recommended: true + }, + + schema: [] + }, + + create: function(context) { - /** - * Finds and reports references that are non initializer and writable. - * @param {Variable} variable - A variable to check. - * @returns {void} - */ - function checkVariable(variable) { - if (variable.defs[0].type === "FunctionName") { - checkReference(variable.references); + /** + * Reports a reference if is non initializer and writable. + * @param {References} references - Collection of reference to check. + * @returns {void} + */ + function checkReference(references) { + astUtils.getModifyingReferences(references).forEach(function(reference) { + context.report( + reference.identifier, + "'{{name}}' is a function.", + {name: reference.identifier.name}); + }); } - } - /** - * Checks parameters of a given function node. - * @param {ASTNode} node - A function node to check. - * @returns {void} - */ - function checkForFunction(node) { - context.getDeclaredVariables(node).forEach(checkVariable); - } + /** + * Finds and reports references that are non initializer and writable. + * @param {Variable} variable - A variable to check. + * @returns {void} + */ + function checkVariable(variable) { + if (variable.defs[0].type === "FunctionName") { + checkReference(variable.references); + } + } - return { - "FunctionDeclaration": checkForFunction, - "FunctionExpression": checkForFunction - }; -}; + /** + * Checks parameters of a given function node. + * @param {ASTNode} node - A function node to check. + * @returns {void} + */ + function checkForFunction(node) { + context.getDeclaredVariables(node).forEach(checkVariable); + } -module.exports.schema = []; + return { + FunctionDeclaration: checkForFunction, + FunctionExpression: checkForFunction + }; + } +}; diff --git a/tools/eslint/lib/rules/no-implicit-coercion.js b/tools/eslint/lib/rules/no-implicit-coercion.js index 2bc96485c305b7..058d9f3572e4c9 100644 --- a/tools/eslint/lib/rules/no-implicit-coercion.js +++ b/tools/eslint/lib/rules/no-implicit-coercion.js @@ -1,7 +1,6 @@ /** * @fileoverview A rule to disallow the type conversions with shorter notations. * @author Toru Nagashima - * @copyright 2015 Toru Nagashima. All rights reserved. */ "use strict"; @@ -144,104 +143,114 @@ function getOtherOperand(node, value) { // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var options = parseOptions(context.options[0]), - operatorAllowed = false; +module.exports = { + meta: { + docs: { + description: "disallow shorthand type conversions", + category: "Best Practices", + recommended: false + }, - return { - "UnaryExpression": function(node) { - - // !!foo - operatorAllowed = options.allow.indexOf("!!") >= 0; - if (!operatorAllowed && options.boolean && isDoubleLogicalNegating(node)) { - context.report( - node, - "use `Boolean({{code}})` instead.", { - code: context.getSource(node.argument.argument) - }); - } + schema: [{ + type: "object", + properties: { + boolean: { + type: "boolean" + }, + number: { + type: "boolean" + }, + string: { + type: "boolean" + }, + allow: { + type: "array", + items: { + enum: ALLOWABLE_OPERATORS + }, + uniqueItems: true + } + }, + additionalProperties: false + }] + }, - // ~foo.indexOf(bar) - operatorAllowed = options.allow.indexOf("~") >= 0; - if (!operatorAllowed && options.boolean && isBinaryNegatingOfIndexOf(node)) { - context.report( - node, - "use `{{code}} !== -1` instead.", { - code: context.getSource(node.argument) - }); - } + create: function(context) { + var options = parseOptions(context.options[0]), + operatorAllowed = false; - // +foo - operatorAllowed = options.allow.indexOf("+") >= 0; - if (!operatorAllowed && options.number && node.operator === "+" && !isNumeric(node.argument)) { - context.report( - node, - "use `Number({{code}})` instead.", { - code: context.getSource(node.argument) - }); - } - }, + return { + UnaryExpression: function(node) { - // Use `:exit` to prevent double reporting - "BinaryExpression:exit": function(node) { + // !!foo + operatorAllowed = options.allow.indexOf("!!") >= 0; + if (!operatorAllowed && options.boolean && isDoubleLogicalNegating(node)) { + context.report( + node, + "use `Boolean({{code}})` instead.", { + code: context.getSource(node.argument.argument) + }); + } - // 1 * foo - operatorAllowed = options.allow.indexOf("*") >= 0; - var nonNumericOperand = !operatorAllowed && options.number && isMultiplyByOne(node) && getNonNumericOperand(node); + // ~foo.indexOf(bar) + operatorAllowed = options.allow.indexOf("~") >= 0; + if (!operatorAllowed && options.boolean && isBinaryNegatingOfIndexOf(node)) { + context.report( + node, + "use `{{code}} !== -1` instead.", { + code: context.getSource(node.argument) + }); + } - if (nonNumericOperand) { - context.report( - node, - "use `Number({{code}})` instead.", { - code: context.getSource(nonNumericOperand) - }); - } + // +foo + operatorAllowed = options.allow.indexOf("+") >= 0; + if (!operatorAllowed && options.number && node.operator === "+" && !isNumeric(node.argument)) { + context.report( + node, + "use `Number({{code}})` instead.", { + code: context.getSource(node.argument) + }); + } + }, - // "" + foo - operatorAllowed = options.allow.indexOf("+") >= 0; - if (!operatorAllowed && options.string && isConcatWithEmptyString(node)) { - context.report( - node, - "use `String({{code}})` instead.", { - code: context.getSource(getOtherOperand(node, "")) - }); - } - }, + // Use `:exit` to prevent double reporting + "BinaryExpression:exit": function(node) { - "AssignmentExpression": function(node) { + // 1 * foo + operatorAllowed = options.allow.indexOf("*") >= 0; + var nonNumericOperand = !operatorAllowed && options.number && isMultiplyByOne(node) && getNonNumericOperand(node); - // foo += "" - operatorAllowed = options.allow.indexOf("+") >= 0; - if (options.string && isAppendEmptyString(node)) { - context.report( - node, - "use `{{code}} = String({{code}})` instead.", { - code: context.getSource(getOtherOperand(node, "")) - }); - } - } - }; -}; + if (nonNumericOperand) { + context.report( + node, + "use `Number({{code}})` instead.", { + code: context.getSource(nonNumericOperand) + }); + } -module.exports.schema = [{ - "type": "object", - "properties": { - "boolean": { - "type": "boolean" - }, - "number": { - "type": "boolean" - }, - "string": { - "type": "boolean" - }, - "allow": { - "type": "array", - "items": { - "enum": ALLOWABLE_OPERATORS + // "" + foo + operatorAllowed = options.allow.indexOf("+") >= 0; + if (!operatorAllowed && options.string && isConcatWithEmptyString(node)) { + context.report( + node, + "use `String({{code}})` instead.", { + code: context.getSource(getOtherOperand(node, "")) + }); + } }, - "uniqueItems": true - } - }, - "additionalProperties": false -}]; + + AssignmentExpression: function(node) { + + // foo += "" + operatorAllowed = options.allow.indexOf("+") >= 0; + if (options.string && isAppendEmptyString(node)) { + context.report( + node, + "use `{{code}} = String({{code}})` instead.", { + code: context.getSource(getOtherOperand(node, "")) + }); + } + } + }; + } +}; diff --git a/tools/eslint/lib/rules/no-implicit-globals.js b/tools/eslint/lib/rules/no-implicit-globals.js index 045ebffed20bd2..c2768ea1a0951f 100644 --- a/tools/eslint/lib/rules/no-implicit-globals.js +++ b/tools/eslint/lib/rules/no-implicit-globals.js @@ -1,9 +1,7 @@ /** * @fileoverview Rule to check for implicit global variables and functions. * @author Joshua Peek - * @copyright 2015 Joshua Peek. All rights reserved. - * See LICENSE file in root directory for full license. -*/ + */ "use strict"; @@ -11,37 +9,47 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - return { - "Program": function() { - var scope = context.getScope(); - - scope.variables.forEach(function(variable) { - if (variable.writeable) { - return; - } - - variable.defs.forEach(function(def) { - if (def.type === "FunctionName" || (def.type === "Variable" && def.parent.kind === "var")) { - context.report(def.node, "Implicit global variable, assign as global property instead."); +module.exports = { + meta: { + docs: { + description: "disallow `var` and named `function` declarations in the global scope", + category: "Best Practices", + recommended: false + }, + + schema: [] + }, + + create: function(context) { + return { + Program: function() { + var scope = context.getScope(); + + scope.variables.forEach(function(variable) { + if (variable.writeable) { + return; } + + variable.defs.forEach(function(def) { + if (def.type === "FunctionName" || (def.type === "Variable" && def.parent.kind === "var")) { + context.report(def.node, "Implicit global variable, assign as global property instead."); + } + }); }); - }); - scope.implicit.variables.forEach(function(variable) { - var scopeVariable = scope.set.get(variable.name); + scope.implicit.variables.forEach(function(variable) { + var scopeVariable = scope.set.get(variable.name); - if (scopeVariable && scopeVariable.writeable) { - return; - } + if (scopeVariable && scopeVariable.writeable) { + return; + } - variable.defs.forEach(function(def) { - context.report(def.node, "Implicit global variable, assign as global property instead."); + variable.defs.forEach(function(def) { + context.report(def.node, "Implicit global variable, assign as global property instead."); + }); }); - }); - } - }; + } + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-implied-eval.js b/tools/eslint/lib/rules/no-implied-eval.js index eea0f7fe4180a1..7c1ed2fb6eb989 100644 --- a/tools/eslint/lib/rules/no-implied-eval.js +++ b/tools/eslint/lib/rules/no-implied-eval.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to flag use of implied eval via setTimeout and setInterval * @author James Allardice - * @copyright 2015 Mathias Schreck. All rights reserved. - * @copyright 2013 James Allardice. All rights reserved. */ "use strict"; @@ -11,142 +9,152 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var CALLEE_RE = /set(?:Timeout|Interval)|execScript/; - - /* - * Figures out if we should inspect a given binary expression. Is a stack - * of stacks, where the first element in each substack is a CallExpression. - */ - var impliedEvalAncestorsStack = []; - - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- - - /** - * Get the last element of an array, without modifying arr, like pop(), but non-destructive. - * @param {array} arr What to inspect - * @returns {*} The last element of arr - * @private - */ - function last(arr) { - return arr ? arr[arr.length - 1] : null; - } - - /** - * Checks if the given MemberExpression node is a potentially implied eval identifier on window. - * @param {ASTNode} node The MemberExpression node to check. - * @returns {boolean} Whether or not the given node is potentially an implied eval. - * @private - */ - function isImpliedEvalMemberExpression(node) { - var object = node.object, - property = node.property, - hasImpliedEvalName = CALLEE_RE.test(property.name) || CALLEE_RE.test(property.value); - - return object.name === "window" && hasImpliedEvalName; - } - - /** - * Determines if a node represents a call to a potentially implied eval. - * - * This checks the callee name and that there's an argument, but not the type of the argument. - * - * @param {ASTNode} node The CallExpression to check. - * @returns {boolean} True if the node matches, false if not. - * @private - */ - function isImpliedEvalCallExpression(node) { - var isMemberExpression = (node.callee.type === "MemberExpression"), - isIdentifier = (node.callee.type === "Identifier"), - isImpliedEvalCallee = - (isIdentifier && CALLEE_RE.test(node.callee.name)) || - (isMemberExpression && isImpliedEvalMemberExpression(node.callee)); - - return isImpliedEvalCallee && node.arguments.length; - } - - /** - * Checks that the parent is a direct descendent of an potential implied eval CallExpression, and if the parent is a CallExpression, that we're the first argument. - * @param {ASTNode} node The node to inspect the parent of. - * @returns {boolean} Was the parent a direct descendent, and is the child therefore potentially part of a dangerous argument? - * @private - */ - function hasImpliedEvalParent(node) { - - // make sure our parent is marked - return node.parent === last(last(impliedEvalAncestorsStack)) && - - // if our parent is a CallExpression, make sure we're the first argument - (node.parent.type !== "CallExpression" || node === node.parent.arguments[0]); - } +module.exports = { + meta: { + docs: { + description: "disallow the use of `eval()`-like methods", + category: "Best Practices", + recommended: false + }, - /** - * Checks if our parent is marked as part of an implied eval argument. If - * so, collapses the top of impliedEvalAncestorsStack and reports on the - * original CallExpression. - * @param {ASTNode} node The CallExpression to check. - * @returns {boolean} True if the node matches, false if not. - * @private - */ - function checkString(node) { - if (hasImpliedEvalParent(node)) { - - // remove the entire substack, to avoid duplicate reports - var substack = impliedEvalAncestorsStack.pop(); - - context.report(substack[0], "Implied eval. Consider passing a function instead of a string."); + schema: [] + }, + + create: function(context) { + var CALLEE_RE = /set(?:Timeout|Interval)|execScript/; + + /* + * Figures out if we should inspect a given binary expression. Is a stack + * of stacks, where the first element in each substack is a CallExpression. + */ + var impliedEvalAncestorsStack = []; + + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- + + /** + * Get the last element of an array, without modifying arr, like pop(), but non-destructive. + * @param {array} arr What to inspect + * @returns {*} The last element of arr + * @private + */ + function last(arr) { + return arr ? arr[arr.length - 1] : null; } - } - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- - - return { - "CallExpression": function(node) { - if (isImpliedEvalCallExpression(node)) { + /** + * Checks if the given MemberExpression node is a potentially implied eval identifier on window. + * @param {ASTNode} node The MemberExpression node to check. + * @returns {boolean} Whether or not the given node is potentially an implied eval. + * @private + */ + function isImpliedEvalMemberExpression(node) { + var object = node.object, + property = node.property, + hasImpliedEvalName = CALLEE_RE.test(property.name) || CALLEE_RE.test(property.value); + + return object.name === "window" && hasImpliedEvalName; + } - // call expressions create a new substack - impliedEvalAncestorsStack.push([node]); - } - }, + /** + * Determines if a node represents a call to a potentially implied eval. + * + * This checks the callee name and that there's an argument, but not the type of the argument. + * + * @param {ASTNode} node The CallExpression to check. + * @returns {boolean} True if the node matches, false if not. + * @private + */ + function isImpliedEvalCallExpression(node) { + var isMemberExpression = (node.callee.type === "MemberExpression"), + isIdentifier = (node.callee.type === "Identifier"), + isImpliedEvalCallee = + (isIdentifier && CALLEE_RE.test(node.callee.name)) || + (isMemberExpression && isImpliedEvalMemberExpression(node.callee)); + + return isImpliedEvalCallee && node.arguments.length; + } - "CallExpression:exit": function(node) { - if (node === last(last(impliedEvalAncestorsStack))) { + /** + * Checks that the parent is a direct descendent of an potential implied eval CallExpression, and if the parent is a CallExpression, that we're the first argument. + * @param {ASTNode} node The node to inspect the parent of. + * @returns {boolean} Was the parent a direct descendent, and is the child therefore potentially part of a dangerous argument? + * @private + */ + function hasImpliedEvalParent(node) { - /* Destroys the entire sub-stack, rather than just using - * last(impliedEvalAncestorsStack).pop(), as a CallExpression is - * always the bottom of a impliedEvalAncestorsStack substack. - */ - impliedEvalAncestorsStack.pop(); - } - }, + // make sure our parent is marked + return node.parent === last(last(impliedEvalAncestorsStack)) && - "BinaryExpression": function(node) { - if (node.operator === "+" && hasImpliedEvalParent(node)) { - last(impliedEvalAncestorsStack).push(node); - } - }, + // if our parent is a CallExpression, make sure we're the first argument + (node.parent.type !== "CallExpression" || node === node.parent.arguments[0]); + } - "BinaryExpression:exit": function(node) { - if (node === last(last(impliedEvalAncestorsStack))) { - last(impliedEvalAncestorsStack).pop(); + /** + * Checks if our parent is marked as part of an implied eval argument. If + * so, collapses the top of impliedEvalAncestorsStack and reports on the + * original CallExpression. + * @param {ASTNode} node The CallExpression to check. + * @returns {boolean} True if the node matches, false if not. + * @private + */ + function checkString(node) { + if (hasImpliedEvalParent(node)) { + + // remove the entire substack, to avoid duplicate reports + var substack = impliedEvalAncestorsStack.pop(); + + context.report(substack[0], "Implied eval. Consider passing a function instead of a string."); } - }, + } - "Literal": function(node) { - if (typeof node.value === "string") { + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + return { + CallExpression: function(node) { + if (isImpliedEvalCallExpression(node)) { + + // call expressions create a new substack + impliedEvalAncestorsStack.push([node]); + } + }, + + "CallExpression:exit": function(node) { + if (node === last(last(impliedEvalAncestorsStack))) { + + /* Destroys the entire sub-stack, rather than just using + * last(impliedEvalAncestorsStack).pop(), as a CallExpression is + * always the bottom of a impliedEvalAncestorsStack substack. + */ + impliedEvalAncestorsStack.pop(); + } + }, + + BinaryExpression: function(node) { + if (node.operator === "+" && hasImpliedEvalParent(node)) { + last(impliedEvalAncestorsStack).push(node); + } + }, + + "BinaryExpression:exit": function(node) { + if (node === last(last(impliedEvalAncestorsStack))) { + last(impliedEvalAncestorsStack).pop(); + } + }, + + Literal: function(node) { + if (typeof node.value === "string") { + checkString(node); + } + }, + + TemplateLiteral: function(node) { checkString(node); } - }, - - "TemplateLiteral": function(node) { - checkString(node); - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-inline-comments.js b/tools/eslint/lib/rules/no-inline-comments.js index 4048802bc8c46a..7835ed30fcc0fe 100644 --- a/tools/eslint/lib/rules/no-inline-comments.js +++ b/tools/eslint/lib/rules/no-inline-comments.js @@ -1,7 +1,6 @@ /** * @fileoverview Enforces or disallows inline comments. * @author Greg Cochard - * @copyright 2014 Greg Cochard. All rights reserved. */ "use strict"; @@ -11,44 +10,54 @@ var astUtils = require("../ast-utils"); // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow inline comments after code", + category: "Stylistic Issues", + recommended: false + }, - /** - * Will check that comments are not on lines starting with or ending with code - * @param {ASTNode} node The comment node to check - * @private - * @returns {void} - */ - function testCodeAroundComment(node) { + schema: [] + }, - // Get the whole line and cut it off at the start of the comment - var startLine = String(context.getSourceLines()[node.loc.start.line - 1]); - var endLine = String(context.getSourceLines()[node.loc.end.line - 1]); + create: function(context) { - var preamble = startLine.slice(0, node.loc.start.column).trim(); + /** + * Will check that comments are not on lines starting with or ending with code + * @param {ASTNode} node The comment node to check + * @private + * @returns {void} + */ + function testCodeAroundComment(node) { - // Also check after the comment - var postamble = endLine.slice(node.loc.end.column).trim(); + // Get the whole line and cut it off at the start of the comment + var startLine = String(context.getSourceLines()[node.loc.start.line - 1]); + var endLine = String(context.getSourceLines()[node.loc.end.line - 1]); - // Check that this comment isn't an ESLint directive - var isDirective = astUtils.isDirectiveComment(node); + var preamble = startLine.slice(0, node.loc.start.column).trim(); - // Should be empty if there was only whitespace around the comment - if (!isDirective && (preamble || postamble)) { - context.report(node, "Unexpected comment inline with code."); + // Also check after the comment + var postamble = endLine.slice(node.loc.end.column).trim(); + + // Check that this comment isn't an ESLint directive + var isDirective = astUtils.isDirectiveComment(node); + + // Should be empty if there was only whitespace around the comment + if (!isDirective && (preamble || postamble)) { + context.report(node, "Unexpected comment inline with code."); + } } - } - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- - return { + return { - "LineComment": testCodeAroundComment, - "BlockComment": testCodeAroundComment + LineComment: testCodeAroundComment, + BlockComment: testCodeAroundComment - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-inner-declarations.js b/tools/eslint/lib/rules/no-inner-declarations.js index 8dcd3e827c9b55..3471ce8cc735b8 100644 --- a/tools/eslint/lib/rules/no-inner-declarations.js +++ b/tools/eslint/lib/rules/no-inner-declarations.js @@ -1,7 +1,6 @@ /** * @fileoverview Rule to enforce declarations in program or function body root. * @author Brandon Mills - * @copyright 2014 Brandon Mills. All rights reserved. */ "use strict"; @@ -10,71 +9,81 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - /** - * Find the nearest Program or Function ancestor node. - * @returns {Object} Ancestor's type and distance from node. - */ - function nearestBody() { - var ancestors = context.getAncestors(), - ancestor = ancestors.pop(), - generation = 1; - - while (ancestor && ["Program", "FunctionDeclaration", - "FunctionExpression", "ArrowFunctionExpression" - ].indexOf(ancestor.type) < 0) { - generation += 1; - ancestor = ancestors.pop(); - } +module.exports = { + meta: { + docs: { + description: "disallow `function` or `var` declarations in nested blocks", + category: "Possible Errors", + recommended: true + }, - return { + schema: [ + { + enum: ["functions", "both"] + } + ] + }, - // Type of containing ancestor - type: ancestor.type, + create: function(context) { - // Separation between ancestor and node - distance: generation - }; - } + /** + * Find the nearest Program or Function ancestor node. + * @returns {Object} Ancestor's type and distance from node. + */ + function nearestBody() { + var ancestors = context.getAncestors(), + ancestor = ancestors.pop(), + generation = 1; - /** - * Ensure that a given node is at a program or function body's root. - * @param {ASTNode} node Declaration node to check. - * @returns {void} - */ - function check(node) { - var body = nearestBody(node), - valid = ((body.type === "Program" && body.distance === 1) || - body.distance === 2); - - if (!valid) { - context.report(node, "Move {{type}} declaration to {{body}} root.", - { - type: (node.type === "FunctionDeclaration" ? - "function" : "variable"), - body: (body.type === "Program" ? - "program" : "function body") - } - ); + while (ancestor && ["Program", "FunctionDeclaration", + "FunctionExpression", "ArrowFunctionExpression" + ].indexOf(ancestor.type) < 0) { + generation += 1; + ancestor = ancestors.pop(); + } + + return { + + // Type of containing ancestor + type: ancestor.type, + + // Separation between ancestor and node + distance: generation + }; } - } - return { + /** + * Ensure that a given node is at a program or function body's root. + * @param {ASTNode} node Declaration node to check. + * @returns {void} + */ + function check(node) { + var body = nearestBody(node), + valid = ((body.type === "Program" && body.distance === 1) || + body.distance === 2); - "FunctionDeclaration": check, - "VariableDeclaration": function(node) { - if (context.options[0] === "both" && node.kind === "var") { - check(node); + if (!valid) { + context.report(node, "Move {{type}} declaration to {{body}} root.", + { + type: (node.type === "FunctionDeclaration" ? + "function" : "variable"), + body: (body.type === "Program" ? + "program" : "function body") + } + ); } } - }; + return { -}; + FunctionDeclaration: check, + VariableDeclaration: function(node) { + if (context.options[0] === "both" && node.kind === "var") { + check(node); + } + } + + }; -module.exports.schema = [ - { - "enum": ["functions", "both"] } -]; +}; diff --git a/tools/eslint/lib/rules/no-invalid-regexp.js b/tools/eslint/lib/rules/no-invalid-regexp.js index 014e70583877e7..6f8b8673786532 100644 --- a/tools/eslint/lib/rules/no-invalid-regexp.js +++ b/tools/eslint/lib/rules/no-invalid-regexp.js @@ -1,7 +1,6 @@ /** * @fileoverview Validate strings passed to the RegExp constructor * @author Michael Ficarra - * @copyright 2014 Michael Ficarra. All rights reserved. */ "use strict"; @@ -15,73 +14,83 @@ var espree = require("espree"); // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - var options = context.options[0], - allowedFlags = ""; +module.exports = { + meta: { + docs: { + description: "disallow invalid regular expression strings in `RegExp` constructors", + category: "Possible Errors", + recommended: true + }, + + schema: [{ + type: "object", + properties: { + allowConstructorFlags: { + type: "array", + items: { + type: "string" + } + } + }, + additionalProperties: false + }] + }, - if (options && options.allowConstructorFlags) { - allowedFlags = options.allowConstructorFlags.join(""); - } + create: function(context) { - /** - * Check if node is a string - * @param {ASTNode} node node to evaluate - * @returns {boolean} True if its a string - * @private - */ - function isString(node) { - return node && node.type === "Literal" && typeof node.value === "string"; - } + var options = context.options[0], + allowedFlags = ""; - /** - * Validate strings passed to the RegExp constructor - * @param {ASTNode} node node to evaluate - * @returns {void} - * @private - */ - function check(node) { - if (node.callee.type === "Identifier" && node.callee.name === "RegExp" && isString(node.arguments[0])) { - var flags = isString(node.arguments[1]) ? node.arguments[1].value : ""; - - if (allowedFlags) { - flags = flags.replace(new RegExp("[" + allowedFlags + "]", "gi"), ""); - } + if (options && options.allowConstructorFlags) { + allowedFlags = options.allowConstructorFlags.join(""); + } - try { - void new RegExp(node.arguments[0].value); - } catch (e) { - context.report(node, e.message); - } + /** + * Check if node is a string + * @param {ASTNode} node node to evaluate + * @returns {boolean} True if its a string + * @private + */ + function isString(node) { + return node && node.type === "Literal" && typeof node.value === "string"; + } - if (flags) { + /** + * Validate strings passed to the RegExp constructor + * @param {ASTNode} node node to evaluate + * @returns {void} + * @private + */ + function check(node) { + if (node.callee.type === "Identifier" && node.callee.name === "RegExp" && isString(node.arguments[0])) { + var flags = isString(node.arguments[1]) ? node.arguments[1].value : ""; + + if (allowedFlags) { + flags = flags.replace(new RegExp("[" + allowedFlags + "]", "gi"), ""); + } try { - espree.parse("/./" + flags, context.parserOptions); - } catch (ex) { - context.report(node, "Invalid flags supplied to RegExp constructor '" + flags + "'"); + void new RegExp(node.arguments[0].value); + } catch (e) { + context.report(node, e.message); } - } - } - } - - return { - "CallExpression": check, - "NewExpression": check - }; + if (flags) { -}; + try { + espree.parse("/./" + flags, context.parserOptions); + } catch (ex) { + context.report(node, "Invalid flags supplied to RegExp constructor '" + flags + "'"); + } + } -module.exports.schema = [{ - "type": "object", - "properties": { - "allowConstructorFlags": { - "type": "array", - "items": { - "type": "string" } } - }, - "additionalProperties": false -}]; + + return { + CallExpression: check, + NewExpression: check + }; + + } +}; diff --git a/tools/eslint/lib/rules/no-invalid-this.js b/tools/eslint/lib/rules/no-invalid-this.js index 0a9e535542c298..198bfd706ad49d 100644 --- a/tools/eslint/lib/rules/no-invalid-this.js +++ b/tools/eslint/lib/rules/no-invalid-this.js @@ -1,8 +1,6 @@ /** * @fileoverview A rule to disallow `this` keywords outside of classes or class-like objects. * @author Toru Nagashima - * @copyright 2015 Toru Nagashima. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; @@ -17,98 +15,108 @@ var astUtils = require("../ast-utils"); // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var stack = [], - sourceCode = context.getSourceCode(); - - /** - * Gets the current checking context. - * - * The return value has a flag that whether or not `this` keyword is valid. - * The flag is initialized when got at the first time. - * - * @returns {{valid: boolean}} - * an object which has a flag that whether or not `this` keyword is valid. - */ - stack.getCurrent = function() { - var current = this[this.length - 1]; - - if (!current.init) { - current.init = true; - current.valid = !astUtils.isDefaultThisBinding( - current.node, - sourceCode); - } - return current; - }; - - /** - * Pushs new checking context into the stack. - * - * The checking context is not initialized yet. - * Because most functions don't have `this` keyword. - * When `this` keyword was found, the checking context is initialized. - * - * @param {ASTNode} node - A function node that was entered. - * @returns {void} - */ - function enterFunction(node) { - - // `this` can be invalid only under strict mode. - stack.push({ - init: !context.getScope().isStrict, - node: node, - valid: true - }); - } - - /** - * Pops the current checking context from the stack. - * @returns {void} - */ - function exitFunction() { - stack.pop(); - } - - return { +module.exports = { + meta: { + docs: { + description: "disallow `this` keywords outside of classes or class-like objects", + category: "Best Practices", + recommended: false + }, - /* - * `this` is invalid only under strict mode. - * Modules is always strict mode. + schema: [] + }, + + create: function(context) { + var stack = [], + sourceCode = context.getSourceCode(); + + /** + * Gets the current checking context. + * + * The return value has a flag that whether or not `this` keyword is valid. + * The flag is initialized when got at the first time. + * + * @returns {{valid: boolean}} + * an object which has a flag that whether or not `this` keyword is valid. + */ + stack.getCurrent = function() { + var current = this[this.length - 1]; + + if (!current.init) { + current.init = true; + current.valid = !astUtils.isDefaultThisBinding( + current.node, + sourceCode); + } + return current; + }; + + /** + * Pushs new checking context into the stack. + * + * The checking context is not initialized yet. + * Because most functions don't have `this` keyword. + * When `this` keyword was found, the checking context is initialized. + * + * @param {ASTNode} node - A function node that was entered. + * @returns {void} */ - "Program": function(node) { - var scope = context.getScope(), - features = context.parserOptions.ecmaFeatures || {}; + function enterFunction(node) { + // `this` can be invalid only under strict mode. stack.push({ - init: true, + init: !context.getScope().isStrict, node: node, - valid: !( - scope.isStrict || - node.sourceType === "module" || - (features.globalReturn && scope.childScopes[0].isStrict) - ) + valid: true }); - }, + } - "Program:exit": function() { + /** + * Pops the current checking context from the stack. + * @returns {void} + */ + function exitFunction() { stack.pop(); - }, - - "FunctionDeclaration": enterFunction, - "FunctionDeclaration:exit": exitFunction, - "FunctionExpression": enterFunction, - "FunctionExpression:exit": exitFunction, - - // Reports if `this` of the current context is invalid. - "ThisExpression": function(node) { - var current = stack.getCurrent(); + } - if (current && !current.valid) { - context.report(node, "Unexpected 'this'."); + return { + + /* + * `this` is invalid only under strict mode. + * Modules is always strict mode. + */ + Program: function(node) { + var scope = context.getScope(), + features = context.parserOptions.ecmaFeatures || {}; + + stack.push({ + init: true, + node: node, + valid: !( + scope.isStrict || + node.sourceType === "module" || + (features.globalReturn && scope.childScopes[0].isStrict) + ) + }); + }, + + "Program:exit": function() { + stack.pop(); + }, + + FunctionDeclaration: enterFunction, + "FunctionDeclaration:exit": exitFunction, + FunctionExpression: enterFunction, + "FunctionExpression:exit": exitFunction, + + // Reports if `this` of the current context is invalid. + ThisExpression: function(node) { + var current = stack.getCurrent(); + + if (current && !current.valid) { + context.report(node, "Unexpected 'this'."); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-irregular-whitespace.js b/tools/eslint/lib/rules/no-irregular-whitespace.js index a849f060bd9e96..1dbea8f5a936fa 100644 --- a/tools/eslint/lib/rules/no-irregular-whitespace.js +++ b/tools/eslint/lib/rules/no-irregular-whitespace.js @@ -2,7 +2,6 @@ * @fileoverview Rule to disalow whitespace that is not a tab or space, whitespace inside strings and comments are allowed * @author Jonathan Kingston * @author Christophe Porteneuve - * @copyright 2014 Jonathan Kingston. All rights reserved. */ "use strict"; @@ -11,187 +10,197 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow irregular whitespace outside of strings and comments", + category: "Possible Errors", + recommended: true + }, + + schema: [ + { + type: "object", + properties: { + skipComments: { + type: "boolean" + } + }, + additionalProperties: false + } + ] + }, + + create: function(context) { - var irregularWhitespace = /[\u0085\u00A0\ufeff\f\v\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u202f\u205f\u3000]+/mg, - irregularLineTerminators = /[\u2028\u2029]/mg; + var irregularWhitespace = /[\u0085\u00A0\ufeff\f\v\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u202f\u205f\u3000]+/mg, + irregularLineTerminators = /[\u2028\u2029]/mg; - // Module store of errors that we have found - var errors = []; + // Module store of errors that we have found + var errors = []; - // Comment nodes. We accumulate these as we go, so we can be sure to trigger them after the whole `Program` entity is parsed, even for top-of-file comments. - var commentNodes = []; + // Comment nodes. We accumulate these as we go, so we can be sure to trigger them after the whole `Program` entity is parsed, even for top-of-file comments. + var commentNodes = []; - // Lookup the `skipComments` option, which defaults to `false`. - var options = context.options[0] || {}; - var skipComments = !!options.skipComments; + // Lookup the `skipComments` option, which defaults to `false`. + var options = context.options[0] || {}; + var skipComments = !!options.skipComments; - /** - * Removes errors that occur inside a string node - * @param {ASTNode} node to check for matching errors. - * @returns {void} - * @private - */ - function removeWhitespaceError(node) { - var locStart = node.loc.start; - var locEnd = node.loc.end; + /** + * Removes errors that occur inside a string node + * @param {ASTNode} node to check for matching errors. + * @returns {void} + * @private + */ + function removeWhitespaceError(node) { + var locStart = node.loc.start; + var locEnd = node.loc.end; - errors = errors.filter(function(error) { - var errorLoc = error[1]; + errors = errors.filter(function(error) { + var errorLoc = error[1]; + + if (errorLoc.line >= locStart.line && errorLoc.line <= locEnd.line) { + if (errorLoc.column >= locStart.column && (errorLoc.column <= locEnd.column || errorLoc.line < locEnd.line)) { + return false; + } + } + return true; + }); + } - if (errorLoc.line >= locStart.line && errorLoc.line <= locEnd.line) { - if (errorLoc.column >= locStart.column && (errorLoc.column <= locEnd.column || errorLoc.line < locEnd.line)) { - return false; + /** + * Checks identifier or literal nodes for errors that we are choosing to ignore and calls the relevant methods to remove the errors + * @param {ASTNode} node to check for matching errors. + * @returns {void} + * @private + */ + function removeInvalidNodeErrorsInIdentifierOrLiteral(node) { + if (typeof node.value === "string") { + + // If we have irregular characters remove them from the errors list + if (node.raw.match(irregularWhitespace) || node.raw.match(irregularLineTerminators)) { + removeWhitespaceError(node); } } - return true; - }); - } + } - /** - * Checks identifier or literal nodes for errors that we are choosing to ignore and calls the relevant methods to remove the errors - * @param {ASTNode} node to check for matching errors. - * @returns {void} - * @private - */ - function removeInvalidNodeErrorsInIdentifierOrLiteral(node) { - if (typeof node.value === "string") { - - // If we have irregular characters remove them from the errors list - if (node.raw.match(irregularWhitespace) || node.raw.match(irregularLineTerminators)) { + /** + * Checks comment nodes for errors that we are choosing to ignore and calls the relevant methods to remove the errors + * @param {ASTNode} node to check for matching errors. + * @returns {void} + * @private + */ + function removeInvalidNodeErrorsInComment(node) { + if (node.value.match(irregularWhitespace) || node.value.match(irregularLineTerminators)) { removeWhitespaceError(node); } } - } - /** - * Checks comment nodes for errors that we are choosing to ignore and calls the relevant methods to remove the errors - * @param {ASTNode} node to check for matching errors. - * @returns {void} - * @private - */ - function removeInvalidNodeErrorsInComment(node) { - if (node.value.match(irregularWhitespace) || node.value.match(irregularLineTerminators)) { - removeWhitespaceError(node); + /** + * Checks the program source for irregular whitespace + * @param {ASTNode} node The program node + * @returns {void} + * @private + */ + function checkForIrregularWhitespace(node) { + var sourceLines = context.getSourceLines(); + + sourceLines.forEach(function(sourceLine, lineIndex) { + var lineNumber = lineIndex + 1, + location, + match; + + while ((match = irregularWhitespace.exec(sourceLine)) !== null) { + location = { + line: lineNumber, + column: match.index + }; + + errors.push([node, location, "Irregular whitespace not allowed"]); + } + }); } - } - /** - * Checks the program source for irregular whitespace - * @param {ASTNode} node The program node - * @returns {void} - * @private - */ - function checkForIrregularWhitespace(node) { - var sourceLines = context.getSourceLines(); - - sourceLines.forEach(function(sourceLine, lineIndex) { - var lineNumber = lineIndex + 1, + /** + * Checks the program source for irregular line terminators + * @param {ASTNode} node The program node + * @returns {void} + * @private + */ + function checkForIrregularLineTerminators(node) { + var source = context.getSource(), + sourceLines = context.getSourceLines(), + linebreaks = source.match(/\r\n|\r|\n|\u2028|\u2029/g), + lastLineIndex = -1, + lineIndex, location, match; - while ((match = irregularWhitespace.exec(sourceLine)) !== null) { + while ((match = irregularLineTerminators.exec(source)) !== null) { + lineIndex = linebreaks.indexOf(match[0], lastLineIndex + 1) || 0; + location = { - line: lineNumber, - column: match.index + line: lineIndex + 1, + column: sourceLines[lineIndex].length }; errors.push([node, location, "Irregular whitespace not allowed"]); + lastLineIndex = lineIndex; } - }); - } - - /** - * Checks the program source for irregular line terminators - * @param {ASTNode} node The program node - * @returns {void} - * @private - */ - function checkForIrregularLineTerminators(node) { - var source = context.getSource(), - sourceLines = context.getSourceLines(), - linebreaks = source.match(/\r\n|\r|\n|\u2028|\u2029/g), - lastLineIndex = -1, - lineIndex, - location, - match; - - while ((match = irregularLineTerminators.exec(source)) !== null) { - lineIndex = linebreaks.indexOf(match[0], lastLineIndex + 1) || 0; - - location = { - line: lineIndex + 1, - column: sourceLines[lineIndex].length - }; - - errors.push([node, location, "Irregular whitespace not allowed"]); - lastLineIndex = lineIndex; } - } - - /** - * Stores a comment node (`LineComment` or `BlockComment`) for later stripping of errors within; a necessary deferring of processing to deal with top-of-file comments. - * @param {ASTNode} node The comment node - * @returns {void} - * @private - */ - function rememberCommentNode(node) { - commentNodes.push(node); - } - - /** - * A no-op function to act as placeholder for comment accumulation when the `skipComments` option is `false`. - * @returns {void} - * @private - */ - function noop() {} - - return { - "Program": function(node) { - - /* - * As we can easily fire warnings for all white space issues with - * all the source its simpler to fire them here. - * This means we can check all the application code without having - * to worry about issues caused in the parser tokens. - * When writing this code also evaluating per node was missing out - * connecting tokens in some cases. - * We can later filter the errors when they are found to be not an - * issue in nodes we don't care about. - */ - - checkForIrregularWhitespace(node); - checkForIrregularLineTerminators(node); - }, - - "Identifier": removeInvalidNodeErrorsInIdentifierOrLiteral, - "Literal": removeInvalidNodeErrorsInIdentifierOrLiteral, - "LineComment": skipComments ? rememberCommentNode : noop, - "BlockComment": skipComments ? rememberCommentNode : noop, - "Program:exit": function() { - - if (skipComments) { - // First strip errors occurring in comment nodes. We have to do this post-`Program` to deal with top-of-file comments. - commentNodes.forEach(removeInvalidNodeErrorsInComment); - } - - // If we have any errors remaining report on them - errors.forEach(function(error) { - context.report.apply(context, error); - }); + /** + * Stores a comment node (`LineComment` or `BlockComment`) for later stripping of errors within; a necessary deferring of processing to deal with top-of-file comments. + * @param {ASTNode} node The comment node + * @returns {void} + * @private + */ + function rememberCommentNode(node) { + commentNodes.push(node); } - }; -}; -module.exports.schema = [ - { - "type": "object", - "properties": { - "skipComments": { - "type": "boolean" + /** + * A no-op function to act as placeholder for comment accumulation when the `skipComments` option is `false`. + * @returns {void} + * @private + */ + function noop() {} + + return { + Program: function(node) { + + /* + * As we can easily fire warnings for all white space issues with + * all the source its simpler to fire them here. + * This means we can check all the application code without having + * to worry about issues caused in the parser tokens. + * When writing this code also evaluating per node was missing out + * connecting tokens in some cases. + * We can later filter the errors when they are found to be not an + * issue in nodes we don't care about. + */ + + checkForIrregularWhitespace(node); + checkForIrregularLineTerminators(node); + }, + + Identifier: removeInvalidNodeErrorsInIdentifierOrLiteral, + Literal: removeInvalidNodeErrorsInIdentifierOrLiteral, + LineComment: skipComments ? rememberCommentNode : noop, + BlockComment: skipComments ? rememberCommentNode : noop, + "Program:exit": function() { + + if (skipComments) { + + // First strip errors occurring in comment nodes. We have to do this post-`Program` to deal with top-of-file comments. + commentNodes.forEach(removeInvalidNodeErrorsInComment); + } + + // If we have any errors remaining report on them + errors.forEach(function(error) { + context.report.apply(context, error); + }); } - }, - "additionalProperties": false + }; } -]; +}; diff --git a/tools/eslint/lib/rules/no-iterator.js b/tools/eslint/lib/rules/no-iterator.js index 817980c99f663a..67c1c1bb2a22fc 100644 --- a/tools/eslint/lib/rules/no-iterator.js +++ b/tools/eslint/lib/rules/no-iterator.js @@ -9,20 +9,30 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow the use of the `__iterator__` property", + category: "Best Practices", + recommended: false + }, - return { + schema: [] + }, - "MemberExpression": function(node) { + create: function(context) { - if (node.property && - (node.property.type === "Identifier" && node.property.name === "__iterator__" && !node.computed) || - (node.property.type === "Literal" && node.property.value === "__iterator__")) { - context.report(node, "Reserved name '__iterator__'."); + return { + + MemberExpression: function(node) { + + if (node.property && + (node.property.type === "Identifier" && node.property.name === "__iterator__" && !node.computed) || + (node.property.type === "Literal" && node.property.value === "__iterator__")) { + context.report(node, "Reserved name '__iterator__'."); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-label-var.js b/tools/eslint/lib/rules/no-label-var.js index 20fbfc182df41f..7c6d56f3552a3a 100644 --- a/tools/eslint/lib/rules/no-label-var.js +++ b/tools/eslint/lib/rules/no-label-var.js @@ -15,43 +15,53 @@ var astUtils = require("../ast-utils"); // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- - - /** - * Check if the identifier is present inside current scope - * @param {object} scope current scope - * @param {string} name To evaluate - * @returns {boolean} True if its present - * @private - */ - function findIdentifier(scope, name) { - return astUtils.getVariableByName(scope, name) !== null; - } +module.exports = { + meta: { + docs: { + description: "disallow labels that share a name with a variable", + category: "Variables", + recommended: false + }, + + schema: [] + }, + + create: function(context) { - //-------------------------------------------------------------------------- - // Public API - //-------------------------------------------------------------------------- + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- + + /** + * Check if the identifier is present inside current scope + * @param {object} scope current scope + * @param {string} name To evaluate + * @returns {boolean} True if its present + * @private + */ + function findIdentifier(scope, name) { + return astUtils.getVariableByName(scope, name) !== null; + } - return { + //-------------------------------------------------------------------------- + // Public API + //-------------------------------------------------------------------------- - "LabeledStatement": function(node) { + return { - // Fetch the innermost scope. - var scope = context.getScope(); + LabeledStatement: function(node) { - // Recursively find the identifier walking up the scope, starting - // with the innermost scope. - if (findIdentifier(scope, node.label.name)) { - context.report(node, "Found identifier with same name as label."); + // Fetch the innermost scope. + var scope = context.getScope(); + + // Recursively find the identifier walking up the scope, starting + // with the innermost scope. + if (findIdentifier(scope, node.label.name)) { + context.report(node, "Found identifier with same name as label."); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-labels.js b/tools/eslint/lib/rules/no-labels.js index fe42c3d886d594..da0cd8e7426643 100644 --- a/tools/eslint/lib/rules/no-labels.js +++ b/tools/eslint/lib/rules/no-labels.js @@ -1,8 +1,6 @@ /** * @fileoverview Disallow Labeled Statements * @author Nicholas C. Zakas - * @copyright 2014 Nicholas C. Zakas. All rights reserved. - * See LICENSE in root directory for full license. */ "use strict"; @@ -16,120 +14,130 @@ var LOOP_TYPES = /^(?:While|DoWhile|For|ForIn|ForOf)Statement$/; // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var options = context.options[0]; - var allowLoop = Boolean(options && options.allowLoop); - var allowSwitch = Boolean(options && options.allowSwitch); - var scopeInfo = null; - - /** - * Gets the kind of a given node. - * - * @param {ASTNode} node - A node to get. - * @returns {string} The kind of the node. - */ - function getBodyKind(node) { - var type = node.type; - - if (LOOP_TYPES.test(type)) { - return "loop"; - } - if (type === "SwitchStatement") { - return "switch"; - } - return "other"; - } +module.exports = { + meta: { + docs: { + description: "disallow labeled statements", + category: "Best Practices", + recommended: false + }, - /** - * Checks whether the label of a given kind is allowed or not. - * - * @param {string} kind - A kind to check. - * @returns {boolean} `true` if the kind is allowed. - */ - function isAllowed(kind) { - switch (kind) { - case "loop": return allowLoop; - case "switch": return allowSwitch; - default: return false; + schema: [ + { + type: "object", + properties: { + allowLoop: { + type: "boolean" + }, + allowSwitch: { + type: "boolean" + } + }, + additionalProperties: false + } + ] + }, + + create: function(context) { + var options = context.options[0]; + var allowLoop = Boolean(options && options.allowLoop); + var allowSwitch = Boolean(options && options.allowSwitch); + var scopeInfo = null; + + /** + * Gets the kind of a given node. + * + * @param {ASTNode} node - A node to get. + * @returns {string} The kind of the node. + */ + function getBodyKind(node) { + var type = node.type; + + if (LOOP_TYPES.test(type)) { + return "loop"; + } + if (type === "SwitchStatement") { + return "switch"; + } + return "other"; } - } - /** - * Checks whether a given name is a label of a loop or not. - * - * @param {string} label - A name of a label to check. - * @returns {boolean} `true` if the name is a label of a loop. - */ - function getKind(label) { - var info = scopeInfo; - - while (info) { - if (info.label === label) { - return info.kind; + /** + * Checks whether the label of a given kind is allowed or not. + * + * @param {string} kind - A kind to check. + * @returns {boolean} `true` if the kind is allowed. + */ + function isAllowed(kind) { + switch (kind) { + case "loop": return allowLoop; + case "switch": return allowSwitch; + default: return false; } - info = info.upper; } - /* istanbul ignore next: syntax error */ - return "other"; - } - - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- - - return { - "LabeledStatement": function(node) { - scopeInfo = { - label: node.label.name, - kind: getBodyKind(node.body), - upper: scopeInfo - }; - }, - - "LabeledStatement:exit": function(node) { - if (!isAllowed(scopeInfo.kind)) { - context.report({ - node: node, - message: "Unexpected labeled statement." - }); + /** + * Checks whether a given name is a label of a loop or not. + * + * @param {string} label - A name of a label to check. + * @returns {boolean} `true` if the name is a label of a loop. + */ + function getKind(label) { + var info = scopeInfo; + + while (info) { + if (info.label === label) { + return info.kind; + } + info = info.upper; } - scopeInfo = scopeInfo.upper; - }, + /* istanbul ignore next: syntax error */ + return "other"; + } - "BreakStatement": function(node) { - if (node.label && !isAllowed(getKind(node.label.name))) { - context.report({ - node: node, - message: "Unexpected label in break statement." - }); - } - }, + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + return { + LabeledStatement: function(node) { + scopeInfo = { + label: node.label.name, + kind: getBodyKind(node.body), + upper: scopeInfo + }; + }, - "ContinueStatement": function(node) { - if (node.label && !isAllowed(getKind(node.label.name))) { - context.report({ - node: node, - message: "Unexpected label in continue statement." - }); - } - } - }; + "LabeledStatement:exit": function(node) { + if (!isAllowed(scopeInfo.kind)) { + context.report({ + node: node, + message: "Unexpected labeled statement." + }); + } -}; + scopeInfo = scopeInfo.upper; + }, -module.exports.schema = [ - { - type: "object", - properties: { - allowLoop: { - type: "boolean" + BreakStatement: function(node) { + if (node.label && !isAllowed(getKind(node.label.name))) { + context.report({ + node: node, + message: "Unexpected label in break statement." + }); + } }, - allowSwitch: { - type: "boolean" + + ContinueStatement: function(node) { + if (node.label && !isAllowed(getKind(node.label.name))) { + context.report({ + node: node, + message: "Unexpected label in continue statement." + }); + } } - }, - additionalProperties: false + }; + } -]; +}; diff --git a/tools/eslint/lib/rules/no-lone-blocks.js b/tools/eslint/lib/rules/no-lone-blocks.js index 976a817b5e3075..113cd89b937c66 100644 --- a/tools/eslint/lib/rules/no-lone-blocks.js +++ b/tools/eslint/lib/rules/no-lone-blocks.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to flag blocks with no reason to exist * @author Brandon Mills - * @copyright 2015 Roberto Vidal. All rights reserved. - * @copyright 2014 Brandon Mills. All rights reserved. */ "use strict"; @@ -11,94 +9,104 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - // A stack of lone blocks to be checked for block-level bindings - var loneBlocks = [], - ruleDef; - - /** - * Reports a node as invalid. - * @param {ASTNode} node - The node to be reported. - * @returns {void} - */ - function report(node) { - var parent = context.getAncestors().pop(); - - context.report(node, parent.type === "Program" ? - "Block is redundant." : - "Nested block is redundant." - ); - } - - /** - * Checks for any ocurrence of BlockStatement > BlockStatement or Program > BlockStatement - * @returns {boolean} True if the current node is a lone block. - */ - function isLoneBlock() { - var parent = context.getAncestors().pop(); +module.exports = { + meta: { + docs: { + description: "disallow unnecessary nested blocks", + category: "Best Practices", + recommended: false + }, + + schema: [] + }, + + create: function(context) { + + // A stack of lone blocks to be checked for block-level bindings + var loneBlocks = [], + ruleDef; + + /** + * Reports a node as invalid. + * @param {ASTNode} node - The node to be reported. + * @returns {void} + */ + function report(node) { + var parent = context.getAncestors().pop(); + + context.report(node, parent.type === "Program" ? + "Block is redundant." : + "Nested block is redundant." + ); + } - return parent.type === "BlockStatement" || parent.type === "Program"; - } + /** + * Checks for any ocurrence of BlockStatement > BlockStatement or Program > BlockStatement + * @returns {boolean} True if the current node is a lone block. + */ + function isLoneBlock() { + var parent = context.getAncestors().pop(); - /** - * Checks the enclosing block of the current node for block-level bindings, - * and "marks it" as valid if any. - * @returns {void} - */ - function markLoneBlock() { - if (loneBlocks.length === 0) { - return; + return parent.type === "BlockStatement" || parent.type === "Program"; } - var block = context.getAncestors().pop(); + /** + * Checks the enclosing block of the current node for block-level bindings, + * and "marks it" as valid if any. + * @returns {void} + */ + function markLoneBlock() { + if (loneBlocks.length === 0) { + return; + } - if (loneBlocks[loneBlocks.length - 1] === block) { - loneBlocks.pop(); - } - } + var block = context.getAncestors().pop(); - // Default rule definition: report all lone blocks - ruleDef = { - BlockStatement: function(node) { - if (isLoneBlock(node)) { - report(node); + if (loneBlocks[loneBlocks.length - 1] === block) { + loneBlocks.pop(); } } - }; - // ES6: report blocks without block-level bindings - if (context.parserOptions.ecmaVersion >= 6) { + // Default rule definition: report all lone blocks ruleDef = { - "BlockStatement": function(node) { + BlockStatement: function(node) { if (isLoneBlock(node)) { - loneBlocks.push(node); - } - }, - "BlockStatement:exit": function(node) { - if (loneBlocks.length > 0 && loneBlocks[loneBlocks.length - 1] === node) { - loneBlocks.pop(); report(node); } } }; - ruleDef.VariableDeclaration = function(node) { - if (node.kind === "let" || node.kind === "const") { - markLoneBlock(node); - } - }; + // ES6: report blocks without block-level bindings + if (context.parserOptions.ecmaVersion >= 6) { + ruleDef = { + BlockStatement: function(node) { + if (isLoneBlock(node)) { + loneBlocks.push(node); + } + }, + "BlockStatement:exit": function(node) { + if (loneBlocks.length > 0 && loneBlocks[loneBlocks.length - 1] === node) { + loneBlocks.pop(); + report(node); + } + } + }; - ruleDef.FunctionDeclaration = function(node) { - if (context.getScope().isStrict) { - markLoneBlock(node); - } - }; + ruleDef.VariableDeclaration = function(node) { + if (node.kind === "let" || node.kind === "const") { + markLoneBlock(node); + } + }; - ruleDef.ClassDeclaration = markLoneBlock; - } + ruleDef.FunctionDeclaration = function(node) { + if (context.getScope().isStrict) { + markLoneBlock(node); + } + }; - return ruleDef; -}; + ruleDef.ClassDeclaration = markLoneBlock; + } -module.exports.schema = []; + return ruleDef; + } +}; diff --git a/tools/eslint/lib/rules/no-lonely-if.js b/tools/eslint/lib/rules/no-lonely-if.js index 0d8ab9124a6e53..1efd1acc018265 100644 --- a/tools/eslint/lib/rules/no-lonely-if.js +++ b/tools/eslint/lib/rules/no-lonely-if.js @@ -8,23 +8,33 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow `if` statements as the only statement in `else` blocks", + category: "Stylistic Issues", + recommended: false + }, - return { - "IfStatement": function(node) { - var ancestors = context.getAncestors(), - parent = ancestors.pop(), - grandparent = ancestors.pop(); + schema: [] + }, - if (parent && parent.type === "BlockStatement" && - parent.body.length === 1 && grandparent && - grandparent.type === "IfStatement" && - parent === grandparent.alternate) { - context.report(node, "Unexpected if as the only statement in an else block."); + create: function(context) { + + return { + IfStatement: function(node) { + var ancestors = context.getAncestors(), + parent = ancestors.pop(), + grandparent = ancestors.pop(); + + if (parent && parent.type === "BlockStatement" && + parent.body.length === 1 && grandparent && + grandparent.type === "IfStatement" && + parent === grandparent.alternate) { + context.report(node, "Unexpected if as the only statement in an else block."); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-loop-func.js b/tools/eslint/lib/rules/no-loop-func.js index 0ab2fb853ac4e6..2b76093cce4d8f 100644 --- a/tools/eslint/lib/rules/no-loop-func.js +++ b/tools/eslint/lib/rules/no-loop-func.js @@ -1,7 +1,6 @@ /** * @fileoverview Rule to flag creation of function inside a loop * @author Ilya Volodin - * @copyright 2013 Ilya Volodin. All rights reserved. */ "use strict"; @@ -152,38 +151,48 @@ function isSafe(funcNode, loopNode, reference) { // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - /** - * Reports functions which match the following condition: - * - * - has a loop node in ancestors. - * - has any references which refers to an unsafe variable. - * - * @param {ASTNode} node The AST node to check. - * @returns {boolean} Whether or not the node is within a loop. - */ - function checkForLoops(node) { - var loopNode = getContainingLoopNode(node); - - if (!loopNode) { - return; +module.exports = { + meta: { + docs: { + description: "disallow `function` declarations and expressions inside loop statements", + category: "Best Practices", + recommended: false + }, + + schema: [] + }, + + create: function(context) { + + /** + * Reports functions which match the following condition: + * + * - has a loop node in ancestors. + * - has any references which refers to an unsafe variable. + * + * @param {ASTNode} node The AST node to check. + * @returns {boolean} Whether or not the node is within a loop. + */ + function checkForLoops(node) { + var loopNode = getContainingLoopNode(node); + + if (!loopNode) { + return; + } + + var references = context.getScope().through; + + if (references.length > 0 && + !references.every(isSafe.bind(null, node, loopNode)) + ) { + context.report(node, "Don't make functions within a loop"); + } } - var references = context.getScope().through; - - if (references.length > 0 && - !references.every(isSafe.bind(null, node, loopNode)) - ) { - context.report(node, "Don't make functions within a loop"); - } + return { + ArrowFunctionExpression: checkForLoops, + FunctionExpression: checkForLoops, + FunctionDeclaration: checkForLoops + }; } - - return { - "ArrowFunctionExpression": checkForLoops, - "FunctionExpression": checkForLoops, - "FunctionDeclaration": checkForLoops - }; }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-magic-numbers.js b/tools/eslint/lib/rules/no-magic-numbers.js index e7532bd51ecd84..2e7434c1a58f16 100644 --- a/tools/eslint/lib/rules/no-magic-numbers.js +++ b/tools/eslint/lib/rules/no-magic-numbers.js @@ -1,32 +1,6 @@ /** * @fileoverview Rule to flag statements that use magic numbers (adapted from https://github.com/danielstjules/buddy.js) * @author Vincent Lemeunier - * @copyright 2015 Vincent Lemeunier. All rights reserved. - * - * This rule was adapted from danielstjules/buddy.js - * The MIT License (MIT) - * - * Copyright (c) 2014 Daniel St. Jules - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * See LICENSE file in root directory for full license. */ "use strict"; @@ -35,125 +9,136 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var config = context.options[0] || {}, - detectObjects = !!config.detectObjects, - enforceConst = !!config.enforceConst, - ignore = config.ignore || [], - ignoreArrayIndexes = !!config.ignoreArrayIndexes; +module.exports = { + meta: { + docs: { + description: "disallow magic numbers", + category: "Best Practices", + recommended: false + }, - /** - * Returns whether the node is number literal - * @param {Node} node - the node literal being evaluated - * @returns {boolean} true if the node is a number literal - */ - function isNumber(node) { - return typeof node.value === "number"; - } + schema: [{ + type: "object", + properties: { + detectObjects: { + type: "boolean" + }, + enforceConst: { + type: "boolean" + }, + ignore: { + type: "array", + items: { + type: "number" + }, + uniqueItems: true + }, + ignoreArrayIndexes: { + type: "boolean" + } + }, + additionalProperties: false + }] + }, - /** - * Returns whether the number should be ignored - * @param {number} num - the number - * @returns {boolean} true if the number should be ignored - */ - function shouldIgnoreNumber(num) { - return ignore.indexOf(num) !== -1; - } + create: function(context) { + var config = context.options[0] || {}, + detectObjects = !!config.detectObjects, + enforceConst = !!config.enforceConst, + ignore = config.ignore || [], + ignoreArrayIndexes = !!config.ignoreArrayIndexes; + + /** + * Returns whether the node is number literal + * @param {Node} node - the node literal being evaluated + * @returns {boolean} true if the node is a number literal + */ + function isNumber(node) { + return typeof node.value === "number"; + } - /** - * Returns whether the number should be ignored when used as a radix within parseInt() or Number.parseInt() - * @param {ASTNode} parent - the non-"UnaryExpression" parent - * @param {ASTNode} node - the node literal being evaluated - * @returns {boolean} true if the number should be ignored - */ - function shouldIgnoreParseInt(parent, node) { - return parent.type === "CallExpression" && node === parent.arguments[1] && - (parent.callee.name === "parseInt" || - parent.callee.type === "MemberExpression" && - parent.callee.object.name === "Number" && - parent.callee.property.name === "parseInt"); - } + /** + * Returns whether the number should be ignored + * @param {number} num - the number + * @returns {boolean} true if the number should be ignored + */ + function shouldIgnoreNumber(num) { + return ignore.indexOf(num) !== -1; + } - /** - * Returns whether the number should be ignored when used to define a JSX prop - * @param {ASTNode} parent - the non-"UnaryExpression" parent - * @returns {boolean} true if the number should be ignored - */ - function shouldIgnoreJSXNumbers(parent) { - return parent.type.indexOf("JSX") === 0; - } + /** + * Returns whether the number should be ignored when used as a radix within parseInt() or Number.parseInt() + * @param {ASTNode} parent - the non-"UnaryExpression" parent + * @param {ASTNode} node - the node literal being evaluated + * @returns {boolean} true if the number should be ignored + */ + function shouldIgnoreParseInt(parent, node) { + return parent.type === "CallExpression" && node === parent.arguments[1] && + (parent.callee.name === "parseInt" || + parent.callee.type === "MemberExpression" && + parent.callee.object.name === "Number" && + parent.callee.property.name === "parseInt"); + } - /** - * Returns whether the number should be ignored when used as an array index with enabled 'ignoreArrayIndexes' option. - * @param {ASTNode} parent - the non-"UnaryExpression" parent. - * @returns {boolean} true if the number should be ignored - */ - function shouldIgnoreArrayIndexes(parent) { - return parent.type === "MemberExpression" && ignoreArrayIndexes; - } + /** + * Returns whether the number should be ignored when used to define a JSX prop + * @param {ASTNode} parent - the non-"UnaryExpression" parent + * @returns {boolean} true if the number should be ignored + */ + function shouldIgnoreJSXNumbers(parent) { + return parent.type.indexOf("JSX") === 0; + } + + /** + * Returns whether the number should be ignored when used as an array index with enabled 'ignoreArrayIndexes' option. + * @param {ASTNode} parent - the non-"UnaryExpression" parent. + * @returns {boolean} true if the number should be ignored + */ + function shouldIgnoreArrayIndexes(parent) { + return parent.type === "MemberExpression" && ignoreArrayIndexes; + } - return { - "Literal": function(node) { - var parent = node.parent, - value = node.value, - raw = node.raw, - okTypes = detectObjects ? [] : ["ObjectExpression", "Property", "AssignmentExpression"]; + return { + Literal: function(node) { + var parent = node.parent, + value = node.value, + raw = node.raw, + okTypes = detectObjects ? [] : ["ObjectExpression", "Property", "AssignmentExpression"]; - if (!isNumber(node)) { - return; - } + if (!isNumber(node)) { + return; + } - // For negative magic numbers: update the value and parent node - if (parent.type === "UnaryExpression" && parent.operator === "-") { - node = parent; - parent = node.parent; - value = -value; - raw = "-" + raw; - } + // For negative magic numbers: update the value and parent node + if (parent.type === "UnaryExpression" && parent.operator === "-") { + node = parent; + parent = node.parent; + value = -value; + raw = "-" + raw; + } - if (shouldIgnoreNumber(value) || - shouldIgnoreParseInt(parent, node) || - shouldIgnoreArrayIndexes(parent) || - shouldIgnoreJSXNumbers(parent)) { - return; - } + if (shouldIgnoreNumber(value) || + shouldIgnoreParseInt(parent, node) || + shouldIgnoreArrayIndexes(parent) || + shouldIgnoreJSXNumbers(parent)) { + return; + } - if (parent.type === "VariableDeclarator") { - if (enforceConst && parent.parent.kind !== "const") { + if (parent.type === "VariableDeclarator") { + if (enforceConst && parent.parent.kind !== "const") { + context.report({ + node: node, + message: "Number constants declarations must use 'const'" + }); + } + } else if (okTypes.indexOf(parent.type) === -1 || + (parent.type === "AssignmentExpression" && parent.operator !== "=")) { context.report({ node: node, - message: "Number constants declarations must use 'const'" + message: "No magic number: " + raw }); } - } else if (okTypes.indexOf(parent.type) === -1) { - context.report({ - node: node, - message: "No magic number: " + raw - }); } - } - }; + }; + } }; - -module.exports.schema = [{ - "type": "object", - "properties": { - "detectObjects": { - "type": "boolean" - }, - "enforceConst": { - "type": "boolean" - }, - "ignore": { - "type": "array", - "items": { - "type": "number" - }, - "uniqueItems": true - }, - "ignoreArrayIndexes": { - "type": "boolean" - } - }, - "additionalProperties": false -}]; diff --git a/tools/eslint/lib/rules/no-mixed-requires.js b/tools/eslint/lib/rules/no-mixed-requires.js index 63494d95256bb7..b6d365a9dbb52d 100644 --- a/tools/eslint/lib/rules/no-mixed-requires.js +++ b/tools/eslint/lib/rules/no-mixed-requires.js @@ -9,204 +9,214 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow `require` calls to be mixed with regular `var` declarations", + category: "Node.js and CommonJS", + recommended: false + }, + + schema: [ + { + oneOf: [ + { + type: "boolean" + }, + { + type: "object", + properties: { + grouping: { + type: "boolean" + }, + allowCall: { + type: "boolean" + } + }, + additionalProperties: false + } + ] + } + ] + }, - var grouping = false, - allowCall = false, - options = context.options[0]; + create: function(context) { - if (typeof options === "object") { - grouping = options.grouping; - allowCall = options.allowCall; - } else { - grouping = !!options; - } + var grouping = false, + allowCall = false, + options = context.options[0]; - /** - * Returns the list of built-in modules. - * - * @returns {string[]} An array of built-in Node.js modules. - */ - function getBuiltinModules() { - - /* - * This list is generated using: - * `require("repl")._builtinLibs.concat('repl').sort()` - * This particular list is as per nodejs v0.12.2 and iojs v0.7.1 + if (typeof options === "object") { + grouping = options.grouping; + allowCall = options.allowCall; + } else { + grouping = !!options; + } + + /** + * Returns the list of built-in modules. + * + * @returns {string[]} An array of built-in Node.js modules. */ - return [ - "assert", "buffer", "child_process", "cluster", "crypto", - "dgram", "dns", "domain", "events", "fs", "http", "https", - "net", "os", "path", "punycode", "querystring", "readline", - "repl", "smalloc", "stream", "string_decoder", "tls", "tty", - "url", "util", "v8", "vm", "zlib" - ]; - } + function getBuiltinModules() { + + /* + * This list is generated using: + * `require("repl")._builtinLibs.concat('repl').sort()` + * This particular list is as per nodejs v0.12.2 and iojs v0.7.1 + */ + return [ + "assert", "buffer", "child_process", "cluster", "crypto", + "dgram", "dns", "domain", "events", "fs", "http", "https", + "net", "os", "path", "punycode", "querystring", "readline", + "repl", "smalloc", "stream", "string_decoder", "tls", "tty", + "url", "util", "v8", "vm", "zlib" + ]; + } - var BUILTIN_MODULES = getBuiltinModules(); + var BUILTIN_MODULES = getBuiltinModules(); - var DECL_REQUIRE = "require", - DECL_UNINITIALIZED = "uninitialized", - DECL_OTHER = "other"; + var DECL_REQUIRE = "require", + DECL_UNINITIALIZED = "uninitialized", + DECL_OTHER = "other"; - var REQ_CORE = "core", - REQ_FILE = "file", - REQ_MODULE = "module", - REQ_COMPUTED = "computed"; + var REQ_CORE = "core", + REQ_FILE = "file", + REQ_MODULE = "module", + REQ_COMPUTED = "computed"; - /** - * Determines the type of a declaration statement. - * @param {ASTNode} initExpression The init node of the VariableDeclarator. - * @returns {string} The type of declaration represented by the expression. - */ - function getDeclarationType(initExpression) { - if (!initExpression) { + /** + * Determines the type of a declaration statement. + * @param {ASTNode} initExpression The init node of the VariableDeclarator. + * @returns {string} The type of declaration represented by the expression. + */ + function getDeclarationType(initExpression) { + if (!initExpression) { - // "var x;" - return DECL_UNINITIALIZED; - } + // "var x;" + return DECL_UNINITIALIZED; + } - if (initExpression.type === "CallExpression" && - initExpression.callee.type === "Identifier" && - initExpression.callee.name === "require" - ) { + if (initExpression.type === "CallExpression" && + initExpression.callee.type === "Identifier" && + initExpression.callee.name === "require" + ) { - // "var x = require('util');" - return DECL_REQUIRE; - } else if (allowCall && - initExpression.type === "CallExpression" && - initExpression.callee.type === "CallExpression" - ) { + // "var x = require('util');" + return DECL_REQUIRE; + } else if (allowCall && + initExpression.type === "CallExpression" && + initExpression.callee.type === "CallExpression" + ) { - // "var x = require('diagnose')('sub-module');" - return getDeclarationType(initExpression.callee); - } else if (initExpression.type === "MemberExpression") { + // "var x = require('diagnose')('sub-module');" + return getDeclarationType(initExpression.callee); + } else if (initExpression.type === "MemberExpression") { - // "var x = require('glob').Glob;" - return getDeclarationType(initExpression.object); - } + // "var x = require('glob').Glob;" + return getDeclarationType(initExpression.object); + } - // "var x = 42;" - return DECL_OTHER; - } + // "var x = 42;" + return DECL_OTHER; + } - /** - * Determines the type of module that is loaded via require. - * @param {ASTNode} initExpression The init node of the VariableDeclarator. - * @returns {string} The module type. - */ - function inferModuleType(initExpression) { - if (initExpression.type === "MemberExpression") { + /** + * Determines the type of module that is loaded via require. + * @param {ASTNode} initExpression The init node of the VariableDeclarator. + * @returns {string} The module type. + */ + function inferModuleType(initExpression) { + if (initExpression.type === "MemberExpression") { - // "var x = require('glob').Glob;" - return inferModuleType(initExpression.object); - } else if (initExpression.arguments.length === 0) { + // "var x = require('glob').Glob;" + return inferModuleType(initExpression.object); + } else if (initExpression.arguments.length === 0) { - // "var x = require();" - return REQ_COMPUTED; - } + // "var x = require();" + return REQ_COMPUTED; + } - var arg = initExpression.arguments[0]; + var arg = initExpression.arguments[0]; - if (arg.type !== "Literal" || typeof arg.value !== "string") { + if (arg.type !== "Literal" || typeof arg.value !== "string") { - // "var x = require(42);" - return REQ_COMPUTED; - } + // "var x = require(42);" + return REQ_COMPUTED; + } - if (BUILTIN_MODULES.indexOf(arg.value) !== -1) { + if (BUILTIN_MODULES.indexOf(arg.value) !== -1) { - // "var fs = require('fs');" - return REQ_CORE; - } else if (/^\.{0,2}\//.test(arg.value)) { + // "var fs = require('fs');" + return REQ_CORE; + } else if (/^\.{0,2}\//.test(arg.value)) { - // "var utils = require('./utils');" - return REQ_FILE; - } else { + // "var utils = require('./utils');" + return REQ_FILE; + } else { - // "var async = require('async');" - return REQ_MODULE; + // "var async = require('async');" + return REQ_MODULE; + } } - } - /** - * Check if the list of variable declarations is mixed, i.e. whether it - * contains both require and other declarations. - * @param {ASTNode} declarations The list of VariableDeclarators. - * @returns {boolean} True if the declarations are mixed, false if not. - */ - function isMixed(declarations) { - var contains = {}; - - declarations.forEach(function(declaration) { - var type = getDeclarationType(declaration.init); - - contains[type] = true; - }); - - return !!( - contains[DECL_REQUIRE] && - (contains[DECL_UNINITIALIZED] || contains[DECL_OTHER]) - ); - } + /** + * Check if the list of variable declarations is mixed, i.e. whether it + * contains both require and other declarations. + * @param {ASTNode} declarations The list of VariableDeclarators. + * @returns {boolean} True if the declarations are mixed, false if not. + */ + function isMixed(declarations) { + var contains = {}; - /** - * Check if all require declarations in the given list are of the same - * type. - * @param {ASTNode} declarations The list of VariableDeclarators. - * @returns {boolean} True if the declarations are grouped, false if not. - */ - function isGrouped(declarations) { - var found = {}; - - declarations.forEach(function(declaration) { - if (getDeclarationType(declaration.init) === DECL_REQUIRE) { - found[inferModuleType(declaration.init)] = true; - } - }); + declarations.forEach(function(declaration) { + var type = getDeclarationType(declaration.init); - return Object.keys(found).length <= 1; - } + contains[type] = true; + }); + return !!( + contains[DECL_REQUIRE] && + (contains[DECL_UNINITIALIZED] || contains[DECL_OTHER]) + ); + } - return { + /** + * Check if all require declarations in the given list are of the same + * type. + * @param {ASTNode} declarations The list of VariableDeclarators. + * @returns {boolean} True if the declarations are grouped, false if not. + */ + function isGrouped(declarations) { + var found = {}; - "VariableDeclaration": function(node) { + declarations.forEach(function(declaration) { + if (getDeclarationType(declaration.init) === DECL_REQUIRE) { + found[inferModuleType(declaration.init)] = true; + } + }); - if (isMixed(node.declarations)) { - context.report( - node, - "Do not mix 'require' and other declarations." - ); - } else if (grouping && !isGrouped(node.declarations)) { - context.report( - node, - "Do not mix core, module, file and computed requires." - ); - } + return Object.keys(found).length <= 1; } - }; -}; -module.exports.schema = [ - { - "oneOf": [ - { - "type": "boolean" - }, - { - "type": "object", - "properties": { - "grouping": { - "type": "boolean" - }, - "allowCall": { - "type": "boolean" - } - }, - "additionalProperties": false + return { + + VariableDeclaration: function(node) { + + if (isMixed(node.declarations)) { + context.report( + node, + "Do not mix 'require' and other declarations." + ); + } else if (grouping && !isGrouped(node.declarations)) { + context.report( + node, + "Do not mix core, module, file and computed requires." + ); + } } - ] + }; + } -]; +}; diff --git a/tools/eslint/lib/rules/no-mixed-spaces-and-tabs.js b/tools/eslint/lib/rules/no-mixed-spaces-and-tabs.js index b7b191cf02b42d..b3cdd38a600f97 100644 --- a/tools/eslint/lib/rules/no-mixed-spaces-and-tabs.js +++ b/tools/eslint/lib/rules/no-mixed-spaces-and-tabs.js @@ -1,9 +1,6 @@ /** * @fileoverview Disallow mixed spaces and tabs for indentation * @author Jary Niebur - * @copyright 2014 Nicholas C. Zakas. All rights reserved. - * @copyright 2014 Jary Niebur. All rights reserved. - * See LICENSE in root directory for full license. */ "use strict"; @@ -11,126 +8,136 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow mixed spaces and tabs for indentation", + category: "Stylistic Issues", + recommended: true + }, - var smartTabs, - ignoredLocs = []; + schema: [ + { + enum: ["smart-tabs", true, false] + } + ] + }, - switch (context.options[0]) { - case true: // Support old syntax, maybe add deprecation warning here - case "smart-tabs": - smartTabs = true; - break; - default: - smartTabs = false; - } + create: function(context) { - /** - * Determines if a given line and column are before a location. - * @param {Location} loc The location object from an AST node. - * @param {int} line The line to check. - * @param {int} column The column to check. - * @returns {boolean} True if the line and column are before the location, false if not. - * @private - */ - function beforeLoc(loc, line, column) { - if (line < loc.start.line) { - return true; - } - return line === loc.start.line && column < loc.start.column; - } + var smartTabs, + ignoredLocs = []; - /** - * Determines if a given line and column are after a location. - * @param {Location} loc The location object from an AST node. - * @param {int} line The line to check. - * @param {int} column The column to check. - * @returns {boolean} True if the line and column are after the location, false if not. - * @private - */ - function afterLoc(loc, line, column) { - if (line > loc.end.line) { - return true; + switch (context.options[0]) { + case true: // Support old syntax, maybe add deprecation warning here + case "smart-tabs": + smartTabs = true; + break; + default: + smartTabs = false; } - return line === loc.end.line && column > loc.end.column; - } - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- - - return { + /** + * Determines if a given line and column are before a location. + * @param {Location} loc The location object from an AST node. + * @param {int} line The line to check. + * @param {int} column The column to check. + * @returns {boolean} True if the line and column are before the location, false if not. + * @private + */ + function beforeLoc(loc, line, column) { + if (line < loc.start.line) { + return true; + } + return line === loc.start.line && column < loc.start.column; + } - "TemplateElement": function(node) { - ignoredLocs.push(node.loc); - }, + /** + * Determines if a given line and column are after a location. + * @param {Location} loc The location object from an AST node. + * @param {int} line The line to check. + * @param {int} column The column to check. + * @returns {boolean} True if the line and column are after the location, false if not. + * @private + */ + function afterLoc(loc, line, column) { + if (line > loc.end.line) { + return true; + } + return line === loc.end.line && column > loc.end.column; + } - "Program:exit": function(node) { - - /* - * At least one space followed by a tab - * or the reverse before non-tab/-space - * characters begin. - */ - var regex = /^(?=[\t ]*(\t | \t))/, - match, - lines = context.getSourceLines(), - comments = context.getAllComments(); - - comments.forEach(function(comment) { - ignoredLocs.push(comment.loc); - }); - - ignoredLocs.sort(function(first, second) { - if (beforeLoc(first, second.start.line, second.start.column)) { - return 1; - } + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- - if (beforeLoc(second, first.start.line, second.start.column)) { - return -1; - } + return { - return 0; - }); + TemplateElement: function(node) { + ignoredLocs.push(node.loc); + }, - if (smartTabs) { + "Program:exit": function(node) { /* * At least one space followed by a tab - * before non-tab/-space characters begin. + * or the reverse before non-tab/-space + * characters begin. */ - regex = /^(?=[\t ]* \t)/; - } - - lines.forEach(function(line, i) { - match = regex.exec(line); + var regex = /^(?=[\t ]*(\t | \t))/, + match, + lines = context.getSourceLines(), + comments = context.getAllComments(); + + comments.forEach(function(comment) { + ignoredLocs.push(comment.loc); + }); + + ignoredLocs.sort(function(first, second) { + if (beforeLoc(first, second.start.line, second.start.column)) { + return 1; + } - if (match) { - var lineNumber = i + 1, - column = match.index + 1; + if (beforeLoc(second, first.start.line, second.start.column)) { + return -1; + } - for (var j = 0; j < ignoredLocs.length; j++) { - if (beforeLoc(ignoredLocs[j], lineNumber, column)) { - continue; - } - if (afterLoc(ignoredLocs[j], lineNumber, column)) { - continue; - } + return 0; + }); - return; - } + if (smartTabs) { - context.report(node, { line: lineNumber, column: column }, "Mixed spaces and tabs."); + /* + * At least one space followed by a tab + * before non-tab/-space characters begin. + */ + regex = /^(?=[\t ]* \t)/; } - }); - } - }; + lines.forEach(function(line, i) { + match = regex.exec(line); -}; + if (match) { + var lineNumber = i + 1, + column = match.index + 1; + + for (var j = 0; j < ignoredLocs.length; j++) { + if (beforeLoc(ignoredLocs[j], lineNumber, column)) { + continue; + } + if (afterLoc(ignoredLocs[j], lineNumber, column)) { + continue; + } + + return; + } + + context.report(node, { line: lineNumber, column: column }, "Mixed spaces and tabs."); + } + }); + } + + }; -module.exports.schema = [ - { - "enum": ["smart-tabs", true, false] } -]; +}; diff --git a/tools/eslint/lib/rules/no-multi-spaces.js b/tools/eslint/lib/rules/no-multi-spaces.js index e57bdd3910da56..d6c0e4198d16b3 100644 --- a/tools/eslint/lib/rules/no-multi-spaces.js +++ b/tools/eslint/lib/rules/no-multi-spaces.js @@ -1,8 +1,6 @@ /** * @fileoverview Disallow use of multiple spaces. * @author Nicholas C. Zakas - * @copyright 2015 Brandon Mills. All rights reserved. - * @copyright 2015 Nicholas C. Zakas. All rights reserved. */ "use strict"; @@ -11,129 +9,141 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - // the index of the last comment that was checked - var exceptions = { "Property": true }, - hasExceptions = true, - options = context.options[0], - lastCommentIndex = 0; +module.exports = { + meta: { + docs: { + description: "disallow multiple spaces", + category: "Best Practices", + recommended: false + }, - if (options && options.exceptions) { - Object.keys(options.exceptions).forEach(function(key) { - if (options.exceptions[key]) { - exceptions[key] = true; - } else { - delete exceptions[key]; + fixable: "whitespace", + + schema: [ + { + type: "object", + properties: { + exceptions: { + type: "object", + patternProperties: { + "^([A-Z][a-z]*)+$": { + type: "boolean" + } + }, + additionalProperties: false + } + }, + additionalProperties: false } - }); - hasExceptions = Object.keys(exceptions).length > 0; - } + ] + }, + + create: function(context) { + + // the index of the last comment that was checked + var exceptions = { Property: true }, + hasExceptions = true, + options = context.options[0], + lastCommentIndex = 0; + + if (options && options.exceptions) { + Object.keys(options.exceptions).forEach(function(key) { + if (options.exceptions[key]) { + exceptions[key] = true; + } else { + delete exceptions[key]; + } + }); + hasExceptions = Object.keys(exceptions).length > 0; + } + + /** + * Determines if a given source index is in a comment or not by checking + * the index against the comment range. Since the check goes straight + * through the file, once an index is passed a certain comment, we can + * go to the next comment to check that. + * @param {int} index The source index to check. + * @param {ASTNode[]} comments An array of comment nodes. + * @returns {boolean} True if the index is within a comment, false if not. + * @private + */ + function isIndexInComment(index, comments) { + + var comment; + + while (lastCommentIndex < comments.length) { + + comment = comments[lastCommentIndex]; + + if (comment.range[0] <= index && index < comment.range[1]) { + return true; + } else if (index > comment.range[1]) { + lastCommentIndex++; + } else { + break; + } - /** - * Determines if a given source index is in a comment or not by checking - * the index against the comment range. Since the check goes straight - * through the file, once an index is passed a certain comment, we can - * go to the next comment to check that. - * @param {int} index The source index to check. - * @param {ASTNode[]} comments An array of comment nodes. - * @returns {boolean} True if the index is within a comment, false if not. - * @private - */ - function isIndexInComment(index, comments) { - - var comment; - - while (lastCommentIndex < comments.length) { - - comment = comments[lastCommentIndex]; - - if (comment.range[0] <= index && index < comment.range[1]) { - return true; - } else if (index > comment.range[1]) { - lastCommentIndex++; - } else { - break; } + return false; } - return false; - } + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + return { + Program: function() { + + var source = context.getSource(), + allComments = context.getAllComments(), + pattern = /[^\n\r\u2028\u2029\t ].? {2,}/g, // note: repeating space + token, + previousToken, + parent; + + + /** + * Creates a fix function that removes the multiple spaces between the two tokens + * @param {RuleFixer} leftToken left token + * @param {RuleFixer} rightToken right token + * @returns {function} fix function + * @private + */ + function createFix(leftToken, rightToken) { + return function(fixer) { + return fixer.replaceTextRange([leftToken.range[1], rightToken.range[0]], " "); + }; + } - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- - - return { - "Program": function() { - - var source = context.getSource(), - allComments = context.getAllComments(), - pattern = /[^\n\r\u2028\u2029\t ].? {2,}/g, // note: repeating space - token, - previousToken, - parent; - - - /** - * Creates a fix function that removes the multiple spaces between the two tokens - * @param {RuleFixer} leftToken left token - * @param {RuleFixer} rightToken right token - * @returns {function} fix function - * @private - */ - function createFix(leftToken, rightToken) { - return function(fixer) { - return fixer.replaceTextRange([leftToken.range[1], rightToken.range[0]], " "); - }; - } + while (pattern.test(source)) { - while (pattern.test(source)) { + // do not flag anything inside of comments + if (!isIndexInComment(pattern.lastIndex, allComments)) { - // do not flag anything inside of comments - if (!isIndexInComment(pattern.lastIndex, allComments)) { + token = context.getTokenByRangeStart(pattern.lastIndex); + if (token) { + previousToken = context.getTokenBefore(token); - token = context.getTokenByRangeStart(pattern.lastIndex); - if (token) { - previousToken = context.getTokenBefore(token); + if (hasExceptions) { + parent = context.getNodeByRangeIndex(pattern.lastIndex - 1); + } - if (hasExceptions) { - parent = context.getNodeByRangeIndex(pattern.lastIndex - 1); + if (!parent || !exceptions[parent.type]) { + context.report({ + node: token, + loc: token.loc.start, + message: "Multiple spaces found before '{{value}}'.", + data: { value: token.value }, + fix: createFix(previousToken, token) + }); + } } - if (!parent || !exceptions[parent.type]) { - context.report({ - node: token, - loc: token.loc.start, - message: "Multiple spaces found before '{{value}}'.", - data: { value: token.value }, - fix: createFix(previousToken, token) - }); - } } - } } - } - }; - -}; + }; -module.exports.schema = [ - { - "type": "object", - "properties": { - "exceptions": { - "type": "object", - "patternProperties": { - "^([A-Z][a-z]*)+$": { - "type": "boolean" - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false } -]; +}; diff --git a/tools/eslint/lib/rules/no-multi-str.js b/tools/eslint/lib/rules/no-multi-str.js index 470c65871ea6a1..fe7fee4a60a38c 100644 --- a/tools/eslint/lib/rules/no-multi-str.js +++ b/tools/eslint/lib/rules/no-multi-str.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to flag when using multiline strings * @author Ilya Volodin - * @copyright 2014 Nicholas C. Zakas. All rights reserved. - * @copyright 2013 Ilya Volodin. All rights reserved. */ "use strict"; @@ -11,33 +9,43 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - /** - * Determines if a given node is part of JSX syntax. - * @param {ASTNode} node The node to check. - * @returns {boolean} True if the node is a JSX node, false if not. - * @private - */ - function isJSXElement(node) { - return node.type.indexOf("JSX") === 0; - } +module.exports = { + meta: { + docs: { + description: "disallow multiline strings", + category: "Best Practices", + recommended: false + }, + + schema: [] + }, + + create: function(context) { + + /** + * Determines if a given node is part of JSX syntax. + * @param {ASTNode} node The node to check. + * @returns {boolean} True if the node is a JSX node, false if not. + * @private + */ + function isJSXElement(node) { + return node.type.indexOf("JSX") === 0; + } - //-------------------------------------------------------------------------- - // Public API - //-------------------------------------------------------------------------- + //-------------------------------------------------------------------------- + // Public API + //-------------------------------------------------------------------------- - return { + return { - "Literal": function(node) { - var lineBreak = /\n/; + Literal: function(node) { + var lineBreak = /\n/; - if (lineBreak.test(node.raw) && !isJSXElement(node.parent)) { - context.report(node, "Multiline support is limited to browsers supporting ES5 only."); + if (lineBreak.test(node.raw) && !isJSXElement(node.parent)) { + context.report(node, "Multiline support is limited to browsers supporting ES5 only."); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-multiple-empty-lines.js b/tools/eslint/lib/rules/no-multiple-empty-lines.js index 34b9b8eff93ffd..02a41fdbe34f8c 100644 --- a/tools/eslint/lib/rules/no-multiple-empty-lines.js +++ b/tools/eslint/lib/rules/no-multiple-empty-lines.js @@ -2,7 +2,6 @@ * @fileoverview Disallows multiple blank lines. * implementation adapted from the no-trailing-spaces rule. * @author Greg Cochard - * @copyright 2014 Greg Cochard. All rights reserved. */ "use strict"; @@ -10,152 +9,162 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow multiple empty lines", + category: "Stylistic Issues", + recommended: false + }, - // Use options.max or 2 as default - var max = 2, - maxEOF, - maxBOF; + schema: [ + { + type: "object", + properties: { + max: { + type: "integer", + minimum: 0 + }, + maxEOF: { + type: "integer", + minimum: 0 + }, + maxBOF: { + type: "integer", + minimum: 0 + } + }, + required: ["max"], + additionalProperties: false + } + ] + }, - // store lines that appear empty but really aren't - var notEmpty = []; + create: function(context) { - if (context.options.length) { - max = context.options[0].max; - maxEOF = context.options[0].maxEOF; - maxBOF = context.options[0].maxBOF; - } + // Use options.max or 2 as default + var max = 2, + maxEOF, + maxBOF; - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- + // store lines that appear empty but really aren't + var notEmpty = []; - return { + if (context.options.length) { + max = context.options[0].max; + maxEOF = context.options[0].maxEOF; + maxBOF = context.options[0].maxBOF; + } - "TemplateLiteral": function(node) { - var start = node.loc.start.line; - var end = node.loc.end.line; + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- - while (start <= end) { - notEmpty.push(start); - start++; - } - }, + return { + + TemplateLiteral: function(node) { + var start = node.loc.start.line; + var end = node.loc.end.line; - "Program:exit": function checkBlankLines(node) { - var lines = context.getSourceLines(), - currentLocation = -1, - lastLocation, - blankCounter = 0, - location, - firstOfEndingBlankLines, - firstNonBlankLine = -1, - trimmedLines = []; - - lines.forEach(function(str, i) { - var trimmed = str.trim(); - - if ((firstNonBlankLine === -1) && (trimmed !== "")) { - firstNonBlankLine = i; + while (start <= end) { + notEmpty.push(start); + start++; } + }, + + "Program:exit": function checkBlankLines(node) { + var lines = context.getSourceLines(), + currentLocation = -1, + lastLocation, + blankCounter = 0, + location, + firstOfEndingBlankLines, + firstNonBlankLine = -1, + trimmedLines = []; + + lines.forEach(function(str, i) { + var trimmed = str.trim(); + + if ((firstNonBlankLine === -1) && (trimmed !== "")) { + firstNonBlankLine = i; + } - trimmedLines.push(trimmed); - }); + trimmedLines.push(trimmed); + }); - // add the notEmpty lines in there with a placeholder - notEmpty.forEach(function(x, i) { - trimmedLines[i] = x; - }); + // add the notEmpty lines in there with a placeholder + notEmpty.forEach(function(x, i) { + trimmedLines[i] = x; + }); - if (typeof maxEOF === "undefined") { + if (typeof maxEOF === "undefined") { - /* - * Swallow the final newline, as some editors add it - * automatically and we don't want it to cause an issue - */ - if (trimmedLines[trimmedLines.length - 1] === "") { - trimmedLines = trimmedLines.slice(0, -1); - } + /* + * Swallow the final newline, as some editors add it + * automatically and we don't want it to cause an issue + */ + if (trimmedLines[trimmedLines.length - 1] === "") { + trimmedLines = trimmedLines.slice(0, -1); + } - firstOfEndingBlankLines = trimmedLines.length; - } else { + firstOfEndingBlankLines = trimmedLines.length; + } else { - // save the number of the first of the last blank lines - firstOfEndingBlankLines = trimmedLines.length; - while (trimmedLines[firstOfEndingBlankLines - 1] === "" - && firstOfEndingBlankLines > 0) { - firstOfEndingBlankLines--; + // save the number of the first of the last blank lines + firstOfEndingBlankLines = trimmedLines.length; + while (trimmedLines[firstOfEndingBlankLines - 1] === "" + && firstOfEndingBlankLines > 0) { + firstOfEndingBlankLines--; + } } - } - // Aggregate and count blank lines - if (firstNonBlankLine > maxBOF) { - context.report(node, 0, - "Too many blank lines at the beginning of file. Max of " + maxBOF + " allowed."); - } + // Aggregate and count blank lines + if (firstNonBlankLine > maxBOF) { + context.report(node, 0, + "Too many blank lines at the beginning of file. Max of " + maxBOF + " allowed."); + } - lastLocation = currentLocation; - currentLocation = trimmedLines.indexOf("", currentLocation + 1); - while (currentLocation !== -1) { lastLocation = currentLocation; currentLocation = trimmedLines.indexOf("", currentLocation + 1); - if (lastLocation === currentLocation - 1) { - blankCounter++; - } else { - location = { - line: lastLocation + 1, - column: 1 - }; - - if (lastLocation < firstOfEndingBlankLines) { - - // within the file, not at the end - if (blankCounter >= max) { - context.report({ - node: node, - loc: location, - message: "More than " + max + " blank " + (max === 1 ? "line" : "lines") + " not allowed." - }); - } + while (currentLocation !== -1) { + lastLocation = currentLocation; + currentLocation = trimmedLines.indexOf("", currentLocation + 1); + if (lastLocation === currentLocation - 1) { + blankCounter++; } else { - - // inside the last blank lines - if (blankCounter > maxEOF) { - context.report({ - node: node, - loc: location, - message: "Too many blank lines at the end of file. Max of " + maxEOF + " allowed." - }); + location = { + line: lastLocation + 1, + column: 1 + }; + + if (lastLocation < firstOfEndingBlankLines) { + + // within the file, not at the end + if (blankCounter >= max) { + context.report({ + node: node, + loc: location, + message: "More than " + max + " blank " + (max === 1 ? "line" : "lines") + " not allowed." + }); + } + } else { + + // inside the last blank lines + if (blankCounter > maxEOF) { + context.report({ + node: node, + loc: location, + message: "Too many blank lines at the end of file. Max of " + maxEOF + " allowed." + }); + } } - } - // Finally, reset the blank counter - blankCounter = 0; + // Finally, reset the blank counter + blankCounter = 0; + } } } - } - }; + }; -}; - -module.exports.schema = [ - { - "type": "object", - "properties": { - "max": { - "type": "integer", - "minimum": 0 - }, - "maxEOF": { - "type": "integer", - "minimum": 0 - }, - "maxBOF": { - "type": "integer", - "minimum": 0 - } - }, - "required": ["max"], - "additionalProperties": false } -]; +}; diff --git a/tools/eslint/lib/rules/no-native-reassign.js b/tools/eslint/lib/rules/no-native-reassign.js index b4323369e42c03..7d45e277d502c1 100644 --- a/tools/eslint/lib/rules/no-native-reassign.js +++ b/tools/eslint/lib/rules/no-native-reassign.js @@ -9,65 +9,75 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var config = context.options[0]; - var exceptions = (config && config.exceptions) || []; +module.exports = { + meta: { + docs: { + description: "disallow reassigning native objects", + category: "Best Practices", + recommended: false + }, - /** - * Reports write references. - * @param {Reference} reference - A reference to check. - * @param {int} index - The index of the reference in the references. - * @param {Reference[]} references - The array that the reference belongs to. - * @returns {void} - */ - function checkReference(reference, index, references) { - var identifier = reference.identifier; + schema: [ + { + type: "object", + properties: { + exceptions: { + type: "array", + items: {type: "string"}, + uniqueItems: true + } + }, + additionalProperties: false + } + ] + }, - if (reference.init === false && - reference.isWrite() && + create: function(context) { + var config = context.options[0]; + var exceptions = (config && config.exceptions) || []; - // Destructuring assignments can have multiple default value, - // so possibly there are multiple writeable references for the same identifier. - (index === 0 || references[index - 1].identifier !== identifier) - ) { - context.report({ - node: identifier, - message: "{{name}} is a read-only native object.", - data: identifier - }); - } - } + /** + * Reports write references. + * @param {Reference} reference - A reference to check. + * @param {int} index - The index of the reference in the references. + * @param {Reference[]} references - The array that the reference belongs to. + * @returns {void} + */ + function checkReference(reference, index, references) { + var identifier = reference.identifier; - /** - * Reports write references if a given variable is readonly builtin. - * @param {Variable} variable - A variable to check. - * @returns {void} - */ - function checkVariable(variable) { - if (variable.writeable === false && exceptions.indexOf(variable.name) === -1) { - variable.references.forEach(checkReference); - } - } + if (reference.init === false && + reference.isWrite() && - return { - "Program": function() { - var globalScope = context.getScope(); + // Destructuring assignments can have multiple default value, + // so possibly there are multiple writeable references for the same identifier. + (index === 0 || references[index - 1].identifier !== identifier) + ) { + context.report({ + node: identifier, + message: "{{name}} is a read-only native object.", + data: identifier + }); + } + } - globalScope.variables.forEach(checkVariable); + /** + * Reports write references if a given variable is readonly builtin. + * @param {Variable} variable - A variable to check. + * @returns {void} + */ + function checkVariable(variable) { + if (variable.writeable === false && exceptions.indexOf(variable.name) === -1) { + variable.references.forEach(checkReference); + } } - }; -}; -module.exports.schema = [ - { - "type": "object", - "properties": { - "exceptions": { - "type": "array", - "items": {"type": "string"}, - "uniqueItems": true + return { + Program: function() { + var globalScope = context.getScope(); + + globalScope.variables.forEach(checkVariable); } - }, - "additionalProperties": false + }; } -]; +}; diff --git a/tools/eslint/lib/rules/no-negated-condition.js b/tools/eslint/lib/rules/no-negated-condition.js index 0d5b283e54aef6..5f1037472c5e07 100644 --- a/tools/eslint/lib/rules/no-negated-condition.js +++ b/tools/eslint/lib/rules/no-negated-condition.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to disallow a negated condition * @author Alberto Rodríguez - * @copyright 2015 Alberto Rodríguez. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; @@ -10,65 +8,75 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow negated conditions", + category: "Stylistic Issues", + recommended: false + }, - /** - * Determines if a given node is an if-else without a condition on the else - * @param {ASTNode} node The node to check. - * @returns {boolean} True if the node has an else without an if. - * @private - */ - function hasElseWithoutCondition(node) { - return node.alternate && node.alternate.type !== "IfStatement"; - } + schema: [] + }, - /** - * Determines if a given node is a negated unary expression - * @param {Object} test The test object to check. - * @returns {boolean} True if the node is a negated unary expression. - * @private - */ - function isNegatedUnaryExpression(test) { - return test.type === "UnaryExpression" && test.operator === "!"; - } + create: function(context) { - /** - * Determines if a given node is a negated binary expression - * @param {Test} test The test to check. - * @returns {boolean} True if the node is a negated binary expression. - * @private - */ - function isNegatedBinaryExpression(test) { - return test.type === "BinaryExpression" && - (test.operator === "!=" || test.operator === "!=="); - } + /** + * Determines if a given node is an if-else without a condition on the else + * @param {ASTNode} node The node to check. + * @returns {boolean} True if the node has an else without an if. + * @private + */ + function hasElseWithoutCondition(node) { + return node.alternate && node.alternate.type !== "IfStatement"; + } - /** - * Determines if a given node has a negated if expression - * @param {ASTNode} node The node to check. - * @returns {boolean} True if the node has a negated if expression. - * @private - */ - function isNegatedIf(node) { - return isNegatedUnaryExpression(node.test) || isNegatedBinaryExpression(node.test); - } + /** + * Determines if a given node is a negated unary expression + * @param {Object} test The test object to check. + * @returns {boolean} True if the node is a negated unary expression. + * @private + */ + function isNegatedUnaryExpression(test) { + return test.type === "UnaryExpression" && test.operator === "!"; + } - return { - "IfStatement": function(node) { - if (!hasElseWithoutCondition(node)) { - return; - } + /** + * Determines if a given node is a negated binary expression + * @param {Test} test The test to check. + * @returns {boolean} True if the node is a negated binary expression. + * @private + */ + function isNegatedBinaryExpression(test) { + return test.type === "BinaryExpression" && + (test.operator === "!=" || test.operator === "!=="); + } - if (isNegatedIf(node)) { - context.report(node, "Unexpected negated condition."); - } - }, - "ConditionalExpression": function(node) { - if (isNegatedIf(node)) { - context.report(node, "Unexpected negated condition."); - } + /** + * Determines if a given node has a negated if expression + * @param {ASTNode} node The node to check. + * @returns {boolean} True if the node has a negated if expression. + * @private + */ + function isNegatedIf(node) { + return isNegatedUnaryExpression(node.test) || isNegatedBinaryExpression(node.test); } - }; -}; -module.exports.schema = []; + return { + IfStatement: function(node) { + if (!hasElseWithoutCondition(node)) { + return; + } + + if (isNegatedIf(node)) { + context.report(node, "Unexpected negated condition."); + } + }, + ConditionalExpression: function(node) { + if (isNegatedIf(node)) { + context.report(node, "Unexpected negated condition."); + } + } + }; + } +}; diff --git a/tools/eslint/lib/rules/no-negated-in-lhs.js b/tools/eslint/lib/rules/no-negated-in-lhs.js index 67be9bb06d386e..891b75dd2f4171 100644 --- a/tools/eslint/lib/rules/no-negated-in-lhs.js +++ b/tools/eslint/lib/rules/no-negated-in-lhs.js @@ -9,17 +9,27 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow negating the left operand in `in` expressions", + category: "Possible Errors", + recommended: true + }, - return { + schema: [] + }, - "BinaryExpression": function(node) { - if (node.operator === "in" && node.left.type === "UnaryExpression" && node.left.operator === "!") { - context.report(node, "The 'in' expression's left operand is negated"); + create: function(context) { + + return { + + BinaryExpression: function(node) { + if (node.operator === "in" && node.left.type === "UnaryExpression" && node.left.operator === "!") { + context.report(node, "The 'in' expression's left operand is negated"); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-nested-ternary.js b/tools/eslint/lib/rules/no-nested-ternary.js index 2686ebd9814ac0..34f9eaaa8dbc8a 100644 --- a/tools/eslint/lib/rules/no-nested-ternary.js +++ b/tools/eslint/lib/rules/no-nested-ternary.js @@ -9,16 +9,26 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow nested ternary expressions", + category: "Stylistic Issues", + recommended: false + }, - return { - "ConditionalExpression": function(node) { - if (node.alternate.type === "ConditionalExpression" || - node.consequent.type === "ConditionalExpression") { - context.report(node, "Do not nest ternary expressions"); + schema: [] + }, + + create: function(context) { + + return { + ConditionalExpression: function(node) { + if (node.alternate.type === "ConditionalExpression" || + node.consequent.type === "ConditionalExpression") { + context.report(node, "Do not nest ternary expressions"); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-new-func.js b/tools/eslint/lib/rules/no-new-func.js index cbc0248fb11b70..7b01db0cd28d4b 100644 --- a/tools/eslint/lib/rules/no-new-func.js +++ b/tools/eslint/lib/rules/no-new-func.js @@ -9,29 +9,39 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- - - /** - * Checks if the callee is the Function constructor, and if so, reports an issue. - * @param {ASTNode} node The node to check and report on - * @returns {void} - * @private - */ - function validateCallee(node) { - if (node.callee.name === "Function") { - context.report(node, "The Function constructor is eval."); +module.exports = { + meta: { + docs: { + description: "disallow `new` operators with the `Function` object", + category: "Best Practices", + recommended: false + }, + + schema: [] + }, + + create: function(context) { + + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- + + /** + * Checks if the callee is the Function constructor, and if so, reports an issue. + * @param {ASTNode} node The node to check and report on + * @returns {void} + * @private + */ + function validateCallee(node) { + if (node.callee.name === "Function") { + context.report(node, "The Function constructor is eval."); + } } - } - return { - "NewExpression": validateCallee, - "CallExpression": validateCallee - }; + return { + NewExpression: validateCallee, + CallExpression: validateCallee + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-new-object.js b/tools/eslint/lib/rules/no-new-object.js index dd1cd10d758227..4fc2a3bebb09f6 100644 --- a/tools/eslint/lib/rules/no-new-object.js +++ b/tools/eslint/lib/rules/no-new-object.js @@ -9,17 +9,27 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow `Object` constructors", + category: "Stylistic Issues", + recommended: false + }, - return { + schema: [] + }, - "NewExpression": function(node) { - if (node.callee.name === "Object") { - context.report(node, "The object literal notation {} is preferrable."); + create: function(context) { + + return { + + NewExpression: function(node) { + if (node.callee.name === "Object") { + context.report(node, "The object literal notation {} is preferrable."); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-new-require.js b/tools/eslint/lib/rules/no-new-require.js index cd2eec562fcd64..b39d9c3e373e26 100644 --- a/tools/eslint/lib/rules/no-new-require.js +++ b/tools/eslint/lib/rules/no-new-require.js @@ -9,17 +9,27 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow `new` operators with calls to `require`", + category: "Node.js and CommonJS", + recommended: false + }, - return { + schema: [] + }, - "NewExpression": function(node) { - if (node.callee.type === "Identifier" && node.callee.name === "require") { - context.report(node, "Unexpected use of new with require."); + create: function(context) { + + return { + + NewExpression: function(node) { + if (node.callee.type === "Identifier" && node.callee.name === "require") { + context.report(node, "Unexpected use of new with require."); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-new-symbol.js b/tools/eslint/lib/rules/no-new-symbol.js index 143deec0a3c996..c7c524641ee6bd 100644 --- a/tools/eslint/lib/rules/no-new-symbol.js +++ b/tools/eslint/lib/rules/no-new-symbol.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to disallow use of the new operator with the `Symbol` object * @author Alberto Rodríguez - * @copyright 2016 Alberto Rodríguez. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; @@ -11,25 +9,35 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - return { - "Program:exit": function() { - var globalScope = context.getScope(); - var variable = globalScope.set.get("Symbol"); - - if (variable && variable.defs.length === 0) { - variable.references.forEach(function(ref) { - var node = ref.identifier; - - if (node.parent && node.parent.type === "NewExpression") { - context.report(node, "`Symbol` cannot be called as a constructor."); - } - }); +module.exports = { + meta: { + docs: { + description: "disallow `new` operators with the `Symbol` object", + category: "ECMAScript 6", + recommended: true + }, + + schema: [] + }, + + create: function(context) { + + return { + "Program:exit": function() { + var globalScope = context.getScope(); + var variable = globalScope.set.get("Symbol"); + + if (variable && variable.defs.length === 0) { + variable.references.forEach(function(ref) { + var node = ref.identifier; + + if (node.parent && node.parent.type === "NewExpression") { + context.report(node, "`Symbol` cannot be called as a constructor."); + } + }); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-new-wrappers.js b/tools/eslint/lib/rules/no-new-wrappers.js index 88c22c13c4b3f3..eec774fdcad14f 100644 --- a/tools/eslint/lib/rules/no-new-wrappers.js +++ b/tools/eslint/lib/rules/no-new-wrappers.js @@ -9,19 +9,29 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow `new` operators with the `String`, `Number`, and `Boolean` objects", + category: "Best Practices", + recommended: false + }, - return { + schema: [] + }, - "NewExpression": function(node) { - var wrapperObjects = ["String", "Number", "Boolean", "Math", "JSON"]; + create: function(context) { - if (wrapperObjects.indexOf(node.callee.name) > -1) { - context.report(node, "Do not use {{fn}} as a constructor.", { fn: node.callee.name }); + return { + + NewExpression: function(node) { + var wrapperObjects = ["String", "Number", "Boolean", "Math", "JSON"]; + + if (wrapperObjects.indexOf(node.callee.name) > -1) { + context.report(node, "Do not use {{fn}} as a constructor.", { fn: node.callee.name }); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-new.js b/tools/eslint/lib/rules/no-new.js index e431d4fb78e3b6..154bced9bcfb29 100644 --- a/tools/eslint/lib/rules/no-new.js +++ b/tools/eslint/lib/rules/no-new.js @@ -10,18 +10,28 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow `new` operators outside of assignments or comparisons", + category: "Best Practices", + recommended: false + }, - return { + schema: [] + }, - "ExpressionStatement": function(node) { + create: function(context) { - if (node.expression.type === "NewExpression") { - context.report(node, "Do not use 'new' for side effects."); + return { + + ExpressionStatement: function(node) { + + if (node.expression.type === "NewExpression") { + context.report(node, "Do not use 'new' for side effects."); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-obj-calls.js b/tools/eslint/lib/rules/no-obj-calls.js index e8f1c94611295b..0f58ab93dbd6d6 100644 --- a/tools/eslint/lib/rules/no-obj-calls.js +++ b/tools/eslint/lib/rules/no-obj-calls.js @@ -9,21 +9,31 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow calling global object properties as functions", + category: "Possible Errors", + recommended: true + }, - return { - "CallExpression": function(node) { + schema: [] + }, - if (node.callee.type === "Identifier") { - var name = node.callee.name; + create: function(context) { - if (name === "Math" || name === "JSON") { - context.report(node, "'{{name}}' is not a function.", { name: name }); + return { + CallExpression: function(node) { + + if (node.callee.type === "Identifier") { + var name = node.callee.name; + + if (name === "Math" || name === "JSON") { + context.report(node, "'{{name}}' is not a function.", { name: name }); + } } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-octal-escape.js b/tools/eslint/lib/rules/no-octal-escape.js index 16e58316ddaba0..3ca01324b5ea2d 100644 --- a/tools/eslint/lib/rules/no-octal-escape.js +++ b/tools/eslint/lib/rules/no-octal-escape.js @@ -9,31 +9,41 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow octal escape sequences in string literals", + category: "Best Practices", + recommended: false + }, - return { + schema: [] + }, - "Literal": function(node) { - if (typeof node.value !== "string") { - return; - } + create: function(context) { + + return { - var match = node.raw.match(/^([^\\]|\\[^0-7])*\\([0-3][0-7]{1,2}|[4-7][0-7]|[0-7])/), - octalDigit; + Literal: function(node) { + if (typeof node.value !== "string") { + return; + } - if (match) { - octalDigit = match[2]; + var match = node.raw.match(/^([^\\]|\\[^0-7])*\\([0-3][0-7]{1,2}|[4-7][0-7]|[0-7])/), + octalDigit; - // \0 is actually not considered an octal - if (match[2] !== "0" || typeof match[3] !== "undefined") { - context.report(node, "Don't use octal: '\\{{octalDigit}}'. Use '\\u....' instead.", - { octalDigit: octalDigit }); + if (match) { + octalDigit = match[2]; + + // \0 is actually not considered an octal + if (match[2] !== "0" || typeof match[3] !== "undefined") { + context.report(node, "Don't use octal: '\\{{octalDigit}}'. Use '\\u....' instead.", + { octalDigit: octalDigit }); + } } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-octal.js b/tools/eslint/lib/rules/no-octal.js index 5a00c9506ecae3..1332dde5e8234f 100644 --- a/tools/eslint/lib/rules/no-octal.js +++ b/tools/eslint/lib/rules/no-octal.js @@ -9,17 +9,27 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow octal literals", + category: "Best Practices", + recommended: true + }, - return { + schema: [] + }, - "Literal": function(node) { - if (typeof node.value === "number" && /^0[0-7]/.test(node.raw)) { - context.report(node, "Octal literals should not be used."); + create: function(context) { + + return { + + Literal: function(node) { + if (typeof node.value === "number" && /^0[0-7]/.test(node.raw)) { + context.report(node, "Octal literals should not be used."); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-param-reassign.js b/tools/eslint/lib/rules/no-param-reassign.js index 9c7dc0bff23a11..fad61fc0c1eb9b 100644 --- a/tools/eslint/lib/rules/no-param-reassign.js +++ b/tools/eslint/lib/rules/no-param-reassign.js @@ -1,7 +1,6 @@ /** * @fileoverview Disallow reassignment of function parameters. * @author Nat Burns - * @copyright 2014 Nat Burns. All rights reserved. */ "use strict"; @@ -11,128 +10,138 @@ var stopNodePattern = /(?:Statement|Declaration|Function(?:Expression)?|Program)$/; -module.exports = function(context) { - var props = context.options[0] && Boolean(context.options[0].props); - - /** - * Checks whether or not the reference modifies properties of its variable. - * @param {Reference} reference - A reference to check. - * @returns {boolean} Whether or not the reference modifies properties of its variable. - */ - function isModifyingProp(reference) { - var node = reference.identifier; - var parent = node.parent; - - while (parent && !stopNodePattern.test(parent.type)) { - switch (parent.type) { - - // e.g. foo.a = 0; - case "AssignmentExpression": - return parent.left === node; - - // e.g. ++foo.a; - case "UpdateExpression": - return true; +module.exports = { + meta: { + docs: { + description: "disallow reassigning `function` parameters", + category: "Best Practices", + recommended: false + }, - // e.g. delete foo.a; - case "UnaryExpression": - if (parent.operator === "delete") { + schema: [ + { + type: "object", + properties: { + props: {type: "boolean"} + }, + additionalProperties: false + } + ] + }, + + create: function(context) { + var props = context.options[0] && Boolean(context.options[0].props); + + /** + * Checks whether or not the reference modifies properties of its variable. + * @param {Reference} reference - A reference to check. + * @returns {boolean} Whether or not the reference modifies properties of its variable. + */ + function isModifyingProp(reference) { + var node = reference.identifier; + var parent = node.parent; + + while (parent && !stopNodePattern.test(parent.type)) { + switch (parent.type) { + + // e.g. foo.a = 0; + case "AssignmentExpression": + return parent.left === node; + + // e.g. ++foo.a; + case "UpdateExpression": return true; - } - break; - - // EXCLUDES: e.g. cache.get(foo.a).b = 0; - case "CallExpression": - if (parent.callee !== node) { - return false; - } - break; - - // EXCLUDES: e.g. cache[foo.a] = 0; - case "MemberExpression": - if (parent.property === node) { - return false; - } - break; - - default: - break; + + // e.g. delete foo.a; + case "UnaryExpression": + if (parent.operator === "delete") { + return true; + } + break; + + // EXCLUDES: e.g. cache.get(foo.a).b = 0; + case "CallExpression": + if (parent.callee !== node) { + return false; + } + break; + + // EXCLUDES: e.g. cache[foo.a] = 0; + case "MemberExpression": + if (parent.property === node) { + return false; + } + break; + + default: + break; + } + + node = parent; + parent = node.parent; } - node = parent; - parent = node.parent; + return false; } - return false; - } - - /** - * Reports a reference if is non initializer and writable. - * @param {Reference} reference - A reference to check. - * @param {int} index - The index of the reference in the references. - * @param {Reference[]} references - The array that the reference belongs to. - * @returns {void} - */ - function checkReference(reference, index, references) { - var identifier = reference.identifier; - - if (identifier && - !reference.init && - - // Destructuring assignments can have multiple default value, - // so possibly there are multiple writeable references for the same identifier. - (index === 0 || references[index - 1].identifier !== identifier) - ) { - if (reference.isWrite()) { - context.report( - identifier, - "Assignment to function parameter '{{name}}'.", - {name: identifier.name}); - } else if (props && isModifyingProp(reference)) { - context.report( - identifier, - "Assignment to property of function parameter '{{name}}'.", - {name: identifier.name}); + /** + * Reports a reference if is non initializer and writable. + * @param {Reference} reference - A reference to check. + * @param {int} index - The index of the reference in the references. + * @param {Reference[]} references - The array that the reference belongs to. + * @returns {void} + */ + function checkReference(reference, index, references) { + var identifier = reference.identifier; + + if (identifier && + !reference.init && + + // Destructuring assignments can have multiple default value, + // so possibly there are multiple writeable references for the same identifier. + (index === 0 || references[index - 1].identifier !== identifier) + ) { + if (reference.isWrite()) { + context.report( + identifier, + "Assignment to function parameter '{{name}}'.", + {name: identifier.name}); + } else if (props && isModifyingProp(reference)) { + context.report( + identifier, + "Assignment to property of function parameter '{{name}}'.", + {name: identifier.name}); + } } } - } - /** - * Finds and reports references that are non initializer and writable. - * @param {Variable} variable - A variable to check. - * @returns {void} - */ - function checkVariable(variable) { - if (variable.defs[0].type === "Parameter") { - variable.references.forEach(checkReference); + /** + * Finds and reports references that are non initializer and writable. + * @param {Variable} variable - A variable to check. + * @returns {void} + */ + function checkVariable(variable) { + if (variable.defs[0].type === "Parameter") { + variable.references.forEach(checkReference); + } } - } - - /** - * Checks parameters of a given function node. - * @param {ASTNode} node - A function node to check. - * @returns {void} - */ - function checkForFunction(node) { - context.getDeclaredVariables(node).forEach(checkVariable); - } - return { + /** + * Checks parameters of a given function node. + * @param {ASTNode} node - A function node to check. + * @returns {void} + */ + function checkForFunction(node) { + context.getDeclaredVariables(node).forEach(checkVariable); + } - // `:exit` is needed for the `node.parent` property of identifier nodes. - "FunctionDeclaration:exit": checkForFunction, - "FunctionExpression:exit": checkForFunction, - "ArrowFunctionExpression:exit": checkForFunction - }; + return { -}; + // `:exit` is needed for the `node.parent` property of identifier nodes. + "FunctionDeclaration:exit": checkForFunction, + "FunctionExpression:exit": checkForFunction, + "ArrowFunctionExpression:exit": checkForFunction + }; -module.exports.schema = [ - { - "type": "object", - "properties": { - "props": {"type": "boolean"} - }, - "additionalProperties": false } -]; +}; diff --git a/tools/eslint/lib/rules/no-path-concat.js b/tools/eslint/lib/rules/no-path-concat.js index c6d512bc0e76c9..1412c6c32e3546 100644 --- a/tools/eslint/lib/rules/no-path-concat.js +++ b/tools/eslint/lib/rules/no-path-concat.js @@ -8,32 +8,42 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow string concatenation with `__dirname` and `__filename`", + category: "Node.js and CommonJS", + recommended: false + }, - var MATCHER = /^__(?:dir|file)name$/; + schema: [] + }, - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- + create: function(context) { - return { + var MATCHER = /^__(?:dir|file)name$/; - "BinaryExpression": function(node) { + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- - var left = node.left, - right = node.right; + return { - if (node.operator === "+" && - ((left.type === "Identifier" && MATCHER.test(left.name)) || - (right.type === "Identifier" && MATCHER.test(right.name))) - ) { + BinaryExpression: function(node) { - context.report(node, "Use path.join() or path.resolve() instead of + to create paths."); + var left = node.left, + right = node.right; + + if (node.operator === "+" && + ((left.type === "Identifier" && MATCHER.test(left.name)) || + (right.type === "Identifier" && MATCHER.test(right.name))) + ) { + + context.report(node, "Use path.join() or path.resolve() instead of + to create paths."); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-plusplus.js b/tools/eslint/lib/rules/no-plusplus.js index 42df6a5f2d3d0b..159a42be2c13d1 100644 --- a/tools/eslint/lib/rules/no-plusplus.js +++ b/tools/eslint/lib/rules/no-plusplus.js @@ -10,36 +10,46 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow the unary operators `++` and `--`", + category: "Stylistic Issues", + recommended: false + }, - var config = context.options[0], - allowInForAfterthought = false; + schema: [ + { + type: "object", + properties: { + allowForLoopAfterthoughts: { + type: "boolean" + } + }, + additionalProperties: false + } + ] + }, - if (typeof config === "object") { - allowInForAfterthought = config.allowForLoopAfterthoughts === true; - } + create: function(context) { - return { + var config = context.options[0], + allowInForAfterthought = false; - "UpdateExpression": function(node) { - if (allowInForAfterthought && node.parent.type === "ForStatement") { - return; - } - context.report(node, "Unary operator '" + node.operator + "' used."); + if (typeof config === "object") { + allowInForAfterthought = config.allowForLoopAfterthoughts === true; } - }; - -}; + return { -module.exports.schema = [ - { - "type": "object", - "properties": { - "allowForLoopAfterthoughts": { - "type": "boolean" + UpdateExpression: function(node) { + if (allowInForAfterthought && node.parent.type === "ForStatement") { + return; + } + context.report(node, "Unary operator '" + node.operator + "' used."); } - }, - "additionalProperties": false + + }; + } -]; +}; diff --git a/tools/eslint/lib/rules/no-process-env.js b/tools/eslint/lib/rules/no-process-env.js index 6a5395e57976fe..af48c78029880e 100644 --- a/tools/eslint/lib/rules/no-process-env.js +++ b/tools/eslint/lib/rules/no-process-env.js @@ -1,7 +1,6 @@ /** * @fileoverview Disallow the use of process.env() * @author Vignesh Anand - * @copyright 2014 Vignesh Anand. All rights reserved. */ "use strict"; @@ -9,22 +8,32 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow the use of `process.env`", + category: "Node.js and CommonJS", + recommended: false + }, - return { + schema: [] + }, - "MemberExpression": function(node) { - var objectName = node.object.name, - propertyName = node.property.name; + create: function(context) { - if (objectName === "process" && !node.computed && propertyName && propertyName === "env") { - context.report(node, "Unexpected use of process.env."); - } + return { - } + MemberExpression: function(node) { + var objectName = node.object.name, + propertyName = node.property.name; - }; + if (objectName === "process" && !node.computed && propertyName && propertyName === "env") { + context.report(node, "Unexpected use of process.env."); + } -}; + } -module.exports.schema = []; + }; + + } +}; diff --git a/tools/eslint/lib/rules/no-process-exit.js b/tools/eslint/lib/rules/no-process-exit.js index a1fa3b29dae713..6d8674418bb590 100644 --- a/tools/eslint/lib/rules/no-process-exit.js +++ b/tools/eslint/lib/rules/no-process-exit.js @@ -8,26 +8,36 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow the use of `process.exit()`", + category: "Node.js and CommonJS", + recommended: false + }, - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- + schema: [] + }, - return { + create: function(context) { - "CallExpression": function(node) { - var callee = node.callee; + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- - if (callee.type === "MemberExpression" && callee.object.name === "process" && - callee.property.name === "exit" - ) { - context.report(node, "Don't use process.exit(); throw an error instead."); + return { + + CallExpression: function(node) { + var callee = node.callee; + + if (callee.type === "MemberExpression" && callee.object.name === "process" && + callee.property.name === "exit" + ) { + context.report(node, "Don't use process.exit(); throw an error instead."); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-proto.js b/tools/eslint/lib/rules/no-proto.js index f91a46afebf8c5..325f3d1c019b64 100644 --- a/tools/eslint/lib/rules/no-proto.js +++ b/tools/eslint/lib/rules/no-proto.js @@ -9,20 +9,30 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow the use of the `__proto__` property", + category: "Best Practices", + recommended: false + }, - return { + schema: [] + }, - "MemberExpression": function(node) { + create: function(context) { - if (node.property && - (node.property.type === "Identifier" && node.property.name === "__proto__" && !node.computed) || - (node.property.type === "Literal" && node.property.value === "__proto__")) { - context.report(node, "The '__proto__' property is deprecated."); + return { + + MemberExpression: function(node) { + + if (node.property && + (node.property.type === "Identifier" && node.property.name === "__proto__" && !node.computed) || + (node.property.type === "Literal" && node.property.value === "__proto__")) { + context.report(node, "The '__proto__' property is deprecated."); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-redeclare.js b/tools/eslint/lib/rules/no-redeclare.js index 83a6eed9f03205..4253cc85334658 100644 --- a/tools/eslint/lib/rules/no-redeclare.js +++ b/tools/eslint/lib/rules/no-redeclare.js @@ -9,88 +9,98 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var options = { - builtinGlobals: Boolean(context.options[0] && context.options[0].builtinGlobals) - }; +module.exports = { + meta: { + docs: { + description: "disallow `var` redeclaration", + category: "Best Practices", + recommended: true + }, + + schema: [ + { + type: "object", + properties: { + builtinGlobals: {type: "boolean"} + }, + additionalProperties: false + } + ] + }, + + create: function(context) { + var options = { + builtinGlobals: Boolean(context.options[0] && context.options[0].builtinGlobals) + }; - /** - * Find variables in a given scope and flag redeclared ones. - * @param {Scope} scope - An escope scope object. - * @returns {void} - * @private - */ - function findVariablesInScope(scope) { - scope.variables.forEach(function(variable) { - var hasBuiltin = options.builtinGlobals && "writeable" in variable; - var count = (hasBuiltin ? 1 : 0) + variable.identifiers.length; + /** + * Find variables in a given scope and flag redeclared ones. + * @param {Scope} scope - An escope scope object. + * @returns {void} + * @private + */ + function findVariablesInScope(scope) { + scope.variables.forEach(function(variable) { + var hasBuiltin = options.builtinGlobals && "writeable" in variable; + var count = (hasBuiltin ? 1 : 0) + variable.identifiers.length; - if (count >= 2) { - variable.identifiers.sort(function(a, b) { - return a.range[1] - b.range[1]; - }); + if (count >= 2) { + variable.identifiers.sort(function(a, b) { + return a.range[1] - b.range[1]; + }); - for (var i = (hasBuiltin ? 0 : 1), l = variable.identifiers.length; i < l; i++) { - context.report( - variable.identifiers[i], - "'{{a}}' is already defined", - {a: variable.name}); + for (var i = (hasBuiltin ? 0 : 1), l = variable.identifiers.length; i < l; i++) { + context.report( + variable.identifiers[i], + "'{{a}}' is already defined", + {a: variable.name}); + } } - } - }); + }); - } + } - /** - * Find variables in the current scope. - * @param {ASTNode} node - The Program node. - * @returns {void} - * @private - */ - function checkForGlobal(node) { - var scope = context.getScope(), - parserOptions = context.parserOptions, - ecmaFeatures = parserOptions.ecmaFeatures || {}; + /** + * Find variables in the current scope. + * @param {ASTNode} node - The Program node. + * @returns {void} + * @private + */ + function checkForGlobal(node) { + var scope = context.getScope(), + parserOptions = context.parserOptions, + ecmaFeatures = parserOptions.ecmaFeatures || {}; - // Nodejs env or modules has a special scope. - if (ecmaFeatures.globalReturn || node.sourceType === "module") { - findVariablesInScope(scope.childScopes[0]); - } else { - findVariablesInScope(scope); + // Nodejs env or modules has a special scope. + if (ecmaFeatures.globalReturn || node.sourceType === "module") { + findVariablesInScope(scope.childScopes[0]); + } else { + findVariablesInScope(scope); + } } - } - /** - * Find variables in the current scope. - * @returns {void} - * @private - */ - function checkForBlock() { - findVariablesInScope(context.getScope()); - } + /** + * Find variables in the current scope. + * @returns {void} + * @private + */ + function checkForBlock() { + findVariablesInScope(context.getScope()); + } - if (context.parserOptions.ecmaVersion >= 6) { - return { - "Program": checkForGlobal, - "BlockStatement": checkForBlock, - "SwitchStatement": checkForBlock - }; - } else { - return { - "Program": checkForGlobal, - "FunctionDeclaration": checkForBlock, - "FunctionExpression": checkForBlock, - "ArrowFunctionExpression": checkForBlock - }; + if (context.parserOptions.ecmaVersion >= 6) { + return { + Program: checkForGlobal, + BlockStatement: checkForBlock, + SwitchStatement: checkForBlock + }; + } else { + return { + Program: checkForGlobal, + FunctionDeclaration: checkForBlock, + FunctionExpression: checkForBlock, + ArrowFunctionExpression: checkForBlock + }; + } } }; - -module.exports.schema = [ - { - "type": "object", - "properties": { - "builtinGlobals": {"type": "boolean"} - }, - "additionalProperties": false - } -]; diff --git a/tools/eslint/lib/rules/no-regex-spaces.js b/tools/eslint/lib/rules/no-regex-spaces.js index 0de9a49f35a108..05841319243807 100644 --- a/tools/eslint/lib/rules/no-regex-spaces.js +++ b/tools/eslint/lib/rules/no-regex-spaces.js @@ -9,27 +9,37 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - return { - - "Literal": function(node) { - var token = context.getFirstToken(node), - nodeType = token.type, - nodeValue = token.value, - multipleSpacesRegex = /( {2,})+?/, - regexResults; - - if (nodeType === "RegularExpression") { - regexResults = multipleSpacesRegex.exec(nodeValue); - - if (regexResults !== null) { - context.report(node, "Spaces are hard to count. Use {" + regexResults[0].length + "}."); +module.exports = { + meta: { + docs: { + description: "disallow multiple spaces in regular expression literals", + category: "Possible Errors", + recommended: true + }, + + schema: [] + }, + + create: function(context) { + + return { + + Literal: function(node) { + var token = context.getFirstToken(node), + nodeType = token.type, + nodeValue = token.value, + multipleSpacesRegex = /( {2,})+?/, + regexResults; + + if (nodeType === "RegularExpression") { + regexResults = multipleSpacesRegex.exec(nodeValue); + + if (regexResults !== null) { + context.report(node, "Spaces are hard to count. Use {" + regexResults[0].length + "}."); + } } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-restricted-globals.js b/tools/eslint/lib/rules/no-restricted-globals.js index 3cb64a485e9a10..b24ecec4f275a6 100644 --- a/tools/eslint/lib/rules/no-restricted-globals.js +++ b/tools/eslint/lib/rules/no-restricted-globals.js @@ -1,8 +1,6 @@ /** * @fileoverview Restrict usage of specified globals. * @author Benoît Zugmeyer - * @copyright 2016 Benoît Zugmeyer. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; @@ -10,62 +8,72 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var restrictedGlobals = context.options; +module.exports = { + meta: { + docs: { + description: "disallow specified global variables", + category: "Variables", + recommended: false + }, - // if no globals are restricted we don't need to check - if (restrictedGlobals.length === 0) { - return {}; - } - - /** - * Report a variable to be used as a restricted global. - * @param {Reference} reference the variable reference - * @returns {void} - * @private - */ - function reportReference(reference) { - context.report(reference.identifier, "Unexpected use of '{{name}}'", { - name: reference.identifier.name - }); - } - - /** - * Check if the given name is a restricted global name. - * @param {string} name name of a variable - * @returns {boolean} whether the variable is a restricted global or not - * @private - */ - function isRestricted(name) { - return restrictedGlobals.indexOf(name) >= 0; - } + schema: { + type: "array", + items: { + type: "string" + }, + uniqueItems: true + } + }, - return { - "Program": function() { - var scope = context.getScope(); + create: function(context) { + var restrictedGlobals = context.options; - // Report variables declared elsewhere (ex: variables defined as "global" by eslint) - scope.variables.forEach(function(variable) { - if (!variable.defs.length && isRestricted(variable.name)) { - variable.references.forEach(reportReference); - } - }); + // if no globals are restricted we don't need to check + if (restrictedGlobals.length === 0) { + return {}; + } - // Report variables not declared at all - scope.through.forEach(function(reference) { - if (isRestricted(reference.identifier.name)) { - reportReference(reference); - } + /** + * Report a variable to be used as a restricted global. + * @param {Reference} reference the variable reference + * @returns {void} + * @private + */ + function reportReference(reference) { + context.report(reference.identifier, "Unexpected use of '{{name}}'", { + name: reference.identifier.name }); + } + /** + * Check if the given name is a restricted global name. + * @param {string} name name of a variable + * @returns {boolean} whether the variable is a restricted global or not + * @private + */ + function isRestricted(name) { + return restrictedGlobals.indexOf(name) >= 0; } - }; -}; -module.exports.schema = { - "type": "array", - "items": { - "type": "string" - }, - "uniqueItems": true + return { + Program: function() { + var scope = context.getScope(); + + // Report variables declared elsewhere (ex: variables defined as "global" by eslint) + scope.variables.forEach(function(variable) { + if (!variable.defs.length && isRestricted(variable.name)) { + variable.references.forEach(reportReference); + } + }); + + // Report variables not declared at all + scope.through.forEach(function(reference) { + if (isRestricted(reference.identifier.name)) { + reportReference(reference); + } + }); + + } + }; + } }; diff --git a/tools/eslint/lib/rules/no-restricted-imports.js b/tools/eslint/lib/rules/no-restricted-imports.js index 0ecd2b310813ed..3129ce72784b2a 100644 --- a/tools/eslint/lib/rules/no-restricted-imports.js +++ b/tools/eslint/lib/rules/no-restricted-imports.js @@ -1,8 +1,6 @@ /** * @fileoverview Restrict usage of specified node imports. * @author Guy Ellis - * @copyright 2015 Guy Ellis. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; @@ -10,34 +8,44 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var restrictedImports = context.options; +module.exports = { + meta: { + docs: { + description: "disallow specified modules when loaded by `import`", + category: "ECMAScript 6", + recommended: false + }, - // if no imports are restricted we don"t need to check - if (restrictedImports.length === 0) { - return {}; - } + schema: { + type: "array", + items: { + type: "string" + }, + uniqueItems: true + } + }, + + create: function(context) { + var restrictedImports = context.options; + + // if no imports are restricted we don"t need to check + if (restrictedImports.length === 0) { + return {}; + } - return { - "ImportDeclaration": function(node) { - if (node && node.source && node.source.value) { + return { + ImportDeclaration: function(node) { + if (node && node.source && node.source.value) { - var value = node.source.value.trim(); + var value = node.source.value.trim(); - if (restrictedImports.indexOf(value) !== -1) { - context.report(node, "'{{importName}}' import is restricted from being used.", { - importName: value - }); + if (restrictedImports.indexOf(value) !== -1) { + context.report(node, "'{{importName}}' import is restricted from being used.", { + importName: value + }); + } } } - } - }; -}; - -module.exports.schema = { - "type": "array", - "items": { - "type": "string" - }, - "uniqueItems": true + }; + } }; diff --git a/tools/eslint/lib/rules/no-restricted-modules.js b/tools/eslint/lib/rules/no-restricted-modules.js index 97097c41b05172..43e53915628a77 100644 --- a/tools/eslint/lib/rules/no-restricted-modules.js +++ b/tools/eslint/lib/rules/no-restricted-modules.js @@ -8,74 +8,84 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow specified modules when loaded by `require`", + category: "Node.js and CommonJS", + recommended: false + }, - // trim restricted module names - var restrictedModules = context.options; + schema: { + type: "array", + items: { + type: "string" + }, + uniqueItems: true + } + }, - // if no modules are restricted we don't need to check the CallExpressions - if (restrictedModules.length === 0) { - return {}; - } + create: function(context) { - /** - * Function to check if a node is a string literal. - * @param {ASTNode} node The node to check. - * @returns {boolean} If the node is a string literal. - */ - function isString(node) { - return node && node.type === "Literal" && typeof node.value === "string"; - } + // trim restricted module names + var restrictedModules = context.options; - /** - * Function to check if a node is a require call. - * @param {ASTNode} node The node to check. - * @returns {boolean} If the node is a require call. - */ - function isRequireCall(node) { - return node.callee.type === "Identifier" && node.callee.name === "require"; - } - - /** - * Function to check if a node has an argument that is an restricted module and return its name. - * @param {ASTNode} node The node to check - * @returns {undefined|String} restricted module name or undefined if node argument isn't restricted. - */ - function getRestrictedModuleName(node) { - var moduleName; + // if no modules are restricted we don't need to check the CallExpressions + if (restrictedModules.length === 0) { + return {}; + } - // node has arguments and first argument is string - if (node.arguments.length && isString(node.arguments[0])) { - var argumentValue = node.arguments[0].value.trim(); + /** + * Function to check if a node is a string literal. + * @param {ASTNode} node The node to check. + * @returns {boolean} If the node is a string literal. + */ + function isString(node) { + return node && node.type === "Literal" && typeof node.value === "string"; + } - // check if argument value is in restricted modules array - if (restrictedModules.indexOf(argumentValue) !== -1) { - moduleName = argumentValue; - } + /** + * Function to check if a node is a require call. + * @param {ASTNode} node The node to check. + * @returns {boolean} If the node is a require call. + */ + function isRequireCall(node) { + return node.callee.type === "Identifier" && node.callee.name === "require"; } - return moduleName; - } + /** + * Function to check if a node has an argument that is an restricted module and return its name. + * @param {ASTNode} node The node to check + * @returns {undefined|String} restricted module name or undefined if node argument isn't restricted. + */ + function getRestrictedModuleName(node) { + var moduleName; - return { - "CallExpression": function(node) { - if (isRequireCall(node)) { - var restrictedModuleName = getRestrictedModuleName(node); + // node has arguments and first argument is string + if (node.arguments.length && isString(node.arguments[0])) { + var argumentValue = node.arguments[0].value.trim(); - if (restrictedModuleName) { - context.report(node, "'{{moduleName}}' module is restricted from being used.", { - moduleName: restrictedModuleName - }); + // check if argument value is in restricted modules array + if (restrictedModules.indexOf(argumentValue) !== -1) { + moduleName = argumentValue; } } + + return moduleName; } - }; -}; -module.exports.schema = { - "type": "array", - "items": { - "type": "string" - }, - "uniqueItems": true + return { + CallExpression: function(node) { + if (isRequireCall(node)) { + var restrictedModuleName = getRestrictedModuleName(node); + + if (restrictedModuleName) { + context.report(node, "'{{moduleName}}' module is restricted from being used.", { + moduleName: restrictedModuleName + }); + } + } + } + }; + } }; diff --git a/tools/eslint/lib/rules/no-restricted-syntax.js b/tools/eslint/lib/rules/no-restricted-syntax.js index 52175835c89677..cd9eb603f9870b 100644 --- a/tools/eslint/lib/rules/no-restricted-syntax.js +++ b/tools/eslint/lib/rules/no-restricted-syntax.js @@ -1,7 +1,6 @@ /** * @fileoverview Rule to flag use of certain node types * @author Burak Yigit Kaya - * @copyright 2015 Burak Yigit Kaya. All rights reserved. */ "use strict"; @@ -11,34 +10,44 @@ var nodeTypes = require("espree").Syntax; -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow specified syntax", + category: "Stylistic Issues", + recommended: false + }, + + schema: { + type: "array", + items: [ + { + enum: Object.keys(nodeTypes).map(function(k) { + return nodeTypes[k]; + }) + } + ], + uniqueItems: true, + minItems: 0 + } + }, - /** - * 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, "Using '{{type}}' is not allowed.", node); - } + create: function(context) { - return context.options.reduce(function(result, nodeType) { - result[nodeType] = warn; + /** + * 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, "Using '{{type}}' is not allowed.", node); + } - return result; - }, {}); + return context.options.reduce(function(result, nodeType) { + result[nodeType] = warn; -}; + return result; + }, {}); -module.exports.schema = { - "type": "array", - "items": [ - { - "enum": Object.keys(nodeTypes).map(function(k) { - return nodeTypes[k]; - }) - } - ], - "uniqueItems": true, - "minItems": 0 + } }; diff --git a/tools/eslint/lib/rules/no-return-assign.js b/tools/eslint/lib/rules/no-return-assign.js index dc02897d4101d3..0d9e0b4b07b318 100644 --- a/tools/eslint/lib/rules/no-return-assign.js +++ b/tools/eslint/lib/rules/no-return-assign.js @@ -34,41 +34,51 @@ function isEnclosedInParens(node, context) { // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var always = (context.options[0] || "except-parens") !== "except-parens"; - - /** - * Check whether return statement contains assignment - * @param {ASTNode} nodeToCheck node to check - * @param {ASTNode} nodeToReport node to report - * @param {string} message message to report - * @returns {void} - * @private - */ - function checkForAssignInReturn(nodeToCheck, nodeToReport, message) { - if (isAssignment(nodeToCheck) && (always || !isEnclosedInParens(nodeToCheck, context))) { - context.report(nodeToReport, message); - } - } +module.exports = { + meta: { + docs: { + description: "disallow assignment operators in `return` statements", + category: "Best Practices", + recommended: false + }, - return { - "ReturnStatement": function(node) { - var message = "Return statement should not contain assignment."; + schema: [ + { + enum: ["except-parens", "always"] + } + ] + }, - checkForAssignInReturn(node.argument, node, message); - }, - "ArrowFunctionExpression": function(node) { - if (node.body.type !== "BlockStatement") { - var message = "Arrow function should not return assignment."; + create: function(context) { + var always = (context.options[0] || "except-parens") !== "except-parens"; - checkForAssignInReturn(node.body, node, message); + /** + * Check whether return statement contains assignment + * @param {ASTNode} nodeToCheck node to check + * @param {ASTNode} nodeToReport node to report + * @param {string} message message to report + * @returns {void} + * @private + */ + function checkForAssignInReturn(nodeToCheck, nodeToReport, message) { + if (isAssignment(nodeToCheck) && (always || !isEnclosedInParens(nodeToCheck, context))) { + context.report(nodeToReport, message); } } - }; -}; -module.exports.schema = [ - { - "enum": ["except-parens", "always"] + return { + ReturnStatement: function(node) { + var message = "Return statement should not contain assignment."; + + checkForAssignInReturn(node.argument, node, message); + }, + ArrowFunctionExpression: function(node) { + if (node.body.type !== "BlockStatement") { + var message = "Arrow function should not return assignment."; + + checkForAssignInReturn(node.body, node, message); + } + } + }; } -]; +}; diff --git a/tools/eslint/lib/rules/no-script-url.js b/tools/eslint/lib/rules/no-script-url.js index 9526061b24fe3e..0605cd86429054 100644 --- a/tools/eslint/lib/rules/no-script-url.js +++ b/tools/eslint/lib/rules/no-script-url.js @@ -11,24 +11,34 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow `javascript", + category: "Best Practices", + recommended: false + }, - return { + schema: [] + }, - "Literal": function(node) { + create: function(context) { - var value; + return { - if (node.value && typeof node.value === "string") { - value = node.value.toLowerCase(); + Literal: function(node) { - if (value.indexOf("javascript:") === 0) { - context.report(node, "Script URL is a form of eval."); + var value; + + if (node.value && typeof node.value === "string") { + value = node.value.toLowerCase(); + + if (value.indexOf("javascript:") === 0) { + context.report(node, "Script URL is a form of eval."); + } } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-self-assign.js b/tools/eslint/lib/rules/no-self-assign.js index 2a03cab4072cf2..bcccc3d8380a09 100644 --- a/tools/eslint/lib/rules/no-self-assign.js +++ b/tools/eslint/lib/rules/no-self-assign.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to disallow assignments where both sides are exactly the same * @author Toru Nagashima - * @copyright 2016 Toru Nagashima. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; @@ -97,29 +95,39 @@ function eachSelfAssignment(left, right, report) { // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - /** - * Reports a given node as self assignments. - * - * @param {ASTNode} node - A node to report. This is an Identifier node. - * @returns {void} - */ - function report(node) { - context.report({ - node: node, - message: "'{{name}}' is assigned to itself.", - data: node - }); - } +module.exports = { + meta: { + docs: { + description: "disallow assignments where both sides are exactly the same", + category: "Best Practices", + recommended: true + }, + + schema: [] + }, + + create: function(context) { + + /** + * Reports a given node as self assignments. + * + * @param {ASTNode} node - A node to report. This is an Identifier node. + * @returns {void} + */ + function report(node) { + context.report({ + node: node, + message: "'{{name}}' is assigned to itself.", + data: node + }); + } - return { - "AssignmentExpression": function(node) { - if (node.operator === "=") { - eachSelfAssignment(node.left, node.right, report); + return { + AssignmentExpression: function(node) { + if (node.operator === "=") { + eachSelfAssignment(node.left, node.right, report); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-self-compare.js b/tools/eslint/lib/rules/no-self-compare.js index 9ab99d48f87d52..eef05080b75a15 100644 --- a/tools/eslint/lib/rules/no-self-compare.js +++ b/tools/eslint/lib/rules/no-self-compare.js @@ -10,21 +10,31 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow comparisons where both sides are exactly the same", + category: "Best Practices", + recommended: false + }, - return { + schema: [] + }, - "BinaryExpression": function(node) { - var operators = ["===", "==", "!==", "!=", ">", "<", ">=", "<="]; + create: function(context) { - if (operators.indexOf(node.operator) > -1 && - (node.left.type === "Identifier" && node.right.type === "Identifier" && node.left.name === node.right.name || - node.left.type === "Literal" && node.right.type === "Literal" && node.left.value === node.right.value)) { - context.report(node, "Comparing to itself is potentially pointless."); + return { + + BinaryExpression: function(node) { + var operators = ["===", "==", "!==", "!=", ">", "<", ">=", "<="]; + + if (operators.indexOf(node.operator) > -1 && + (node.left.type === "Identifier" && node.right.type === "Identifier" && node.left.name === node.right.name || + node.left.type === "Literal" && node.right.type === "Literal" && node.left.value === node.right.value)) { + context.report(node, "Comparing to itself is potentially pointless."); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-sequences.js b/tools/eslint/lib/rules/no-sequences.js index 032c879f8e5d49..ea20a4b955dce0 100644 --- a/tools/eslint/lib/rules/no-sequences.js +++ b/tools/eslint/lib/rules/no-sequences.js @@ -9,89 +9,99 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - /** - * Parts of the grammar that are required to have parens. - */ - var parenthesized = { - "DoWhileStatement": "test", - "IfStatement": "test", - "SwitchStatement": "discriminant", - "WhileStatement": "test", - "WithStatement": "object" - - // Omitting CallExpression - commas are parsed as argument separators - // Omitting NewExpression - commas are parsed as argument separators - // Omitting ForInStatement - parts aren't individually parenthesised - // Omitting ForStatement - parts aren't individually parenthesised - }; - - /** - * Determines whether a node is required by the grammar to be wrapped in - * parens, e.g. the test of an if statement. - * @param {ASTNode} node - The AST node - * @returns {boolean} True if parens around node belong to parent node. - */ - function requiresExtraParens(node) { - return node.parent && parenthesized[node.parent.type] && - node === node.parent[parenthesized[node.parent.type]]; - } - - /** - * Check if a node is wrapped in parens. - * @param {ASTNode} node - The AST node - * @returns {boolean} True if the node has a paren on each side. - */ - function isParenthesised(node) { - var previousToken = context.getTokenBefore(node), - nextToken = context.getTokenAfter(node); - - return previousToken && nextToken && - previousToken.value === "(" && previousToken.range[1] <= node.range[0] && - nextToken.value === ")" && nextToken.range[0] >= node.range[1]; - } +module.exports = { + meta: { + docs: { + description: "disallow comma operators", + category: "Best Practices", + recommended: false + }, + + schema: [] + }, + + create: function(context) { + + /** + * Parts of the grammar that are required to have parens. + */ + var parenthesized = { + DoWhileStatement: "test", + IfStatement: "test", + SwitchStatement: "discriminant", + WhileStatement: "test", + WithStatement: "object" + + // Omitting CallExpression - commas are parsed as argument separators + // Omitting NewExpression - commas are parsed as argument separators + // Omitting ForInStatement - parts aren't individually parenthesised + // Omitting ForStatement - parts aren't individually parenthesised + }; + + /** + * Determines whether a node is required by the grammar to be wrapped in + * parens, e.g. the test of an if statement. + * @param {ASTNode} node - The AST node + * @returns {boolean} True if parens around node belong to parent node. + */ + function requiresExtraParens(node) { + return node.parent && parenthesized[node.parent.type] && + node === node.parent[parenthesized[node.parent.type]]; + } - /** - * Check if a node is wrapped in two levels of parens. - * @param {ASTNode} node - The AST node - * @returns {boolean} True if two parens surround the node on each side. - */ - function isParenthesisedTwice(node) { - var previousToken = context.getTokenBefore(node, 1), - nextToken = context.getTokenAfter(node, 1); - - return isParenthesised(node) && previousToken && nextToken && - previousToken.value === "(" && previousToken.range[1] <= node.range[0] && - nextToken.value === ")" && nextToken.range[0] >= node.range[1]; - } + /** + * Check if a node is wrapped in parens. + * @param {ASTNode} node - The AST node + * @returns {boolean} True if the node has a paren on each side. + */ + function isParenthesised(node) { + var previousToken = context.getTokenBefore(node), + nextToken = context.getTokenAfter(node); + + return previousToken && nextToken && + previousToken.value === "(" && previousToken.range[1] <= node.range[0] && + nextToken.value === ")" && nextToken.range[0] >= node.range[1]; + } - return { - "SequenceExpression": function(node) { + /** + * Check if a node is wrapped in two levels of parens. + * @param {ASTNode} node - The AST node + * @returns {boolean} True if two parens surround the node on each side. + */ + function isParenthesisedTwice(node) { + var previousToken = context.getTokenBefore(node, 1), + nextToken = context.getTokenAfter(node, 1); + + return isParenthesised(node) && previousToken && nextToken && + previousToken.value === "(" && previousToken.range[1] <= node.range[0] && + nextToken.value === ")" && nextToken.range[0] >= node.range[1]; + } - // Always allow sequences in for statement update - if (node.parent.type === "ForStatement" && - (node === node.parent.init || node === node.parent.update)) { - return; - } + return { + SequenceExpression: function(node) { - // Wrapping a sequence in extra parens indicates intent - if (requiresExtraParens(node)) { - if (isParenthesisedTwice(node)) { + // Always allow sequences in for statement update + if (node.parent.type === "ForStatement" && + (node === node.parent.init || node === node.parent.update)) { return; } - } else { - if (isParenthesised(node)) { - return; + + // Wrapping a sequence in extra parens indicates intent + if (requiresExtraParens(node)) { + if (isParenthesisedTwice(node)) { + return; + } + } else { + if (isParenthesised(node)) { + return; + } } - } - var child = context.getTokenAfter(node.expressions[0]); + var child = context.getTokenAfter(node.expressions[0]); - context.report(node, child.loc.start, "Unexpected use of comma operator."); - } - }; + context.report(node, child.loc.start, "Unexpected use of comma operator."); + } + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-shadow-restricted-names.js b/tools/eslint/lib/rules/no-shadow-restricted-names.js index e39cd00f472e7f..b7731d9d6767bb 100644 --- a/tools/eslint/lib/rules/no-shadow-restricted-names.js +++ b/tools/eslint/lib/rules/no-shadow-restricted-names.js @@ -1,7 +1,6 @@ /** * @fileoverview Disallow shadowing of NaN, undefined, and Infinity (ES5 section 15.1.1) * @author Michael Ficarra - * @copyright 2013 Michael Ficarra. All rights reserved. */ "use strict"; @@ -9,46 +8,56 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow identifiers from shadowing restricted names", + category: "Variables", + recommended: false + }, - var RESTRICTED = ["undefined", "NaN", "Infinity", "arguments", "eval"]; + schema: [] + }, - /** - * Check if the node name is present inside the restricted list - * @param {ASTNode} id id to evaluate - * @returns {void} - * @private - */ - function checkForViolation(id) { - if (RESTRICTED.indexOf(id.name) > -1) { - context.report(id, "Shadowing of global property '" + id.name + "'."); - } - } + create: function(context) { - return { - "VariableDeclarator": function(node) { - checkForViolation(node.id); - }, - "ArrowFunctionExpression": function(node) { - [].map.call(node.params, checkForViolation); - }, - "FunctionExpression": function(node) { - if (node.id) { - checkForViolation(node.id); + var RESTRICTED = ["undefined", "NaN", "Infinity", "arguments", "eval"]; + + /** + * Check if the node name is present inside the restricted list + * @param {ASTNode} id id to evaluate + * @returns {void} + * @private + */ + function checkForViolation(id) { + if (RESTRICTED.indexOf(id.name) > -1) { + context.report(id, "Shadowing of global property '" + id.name + "'."); } - [].map.call(node.params, checkForViolation); - }, - "FunctionDeclaration": function(node) { - if (node.id) { + } + + return { + VariableDeclarator: function(node) { checkForViolation(node.id); + }, + ArrowFunctionExpression: function(node) { [].map.call(node.params, checkForViolation); + }, + FunctionExpression: function(node) { + if (node.id) { + checkForViolation(node.id); + } + [].map.call(node.params, checkForViolation); + }, + FunctionDeclaration: function(node) { + if (node.id) { + checkForViolation(node.id); + [].map.call(node.params, checkForViolation); + } + }, + CatchClause: function(node) { + checkForViolation(node.param); } - }, - "CatchClause": function(node) { - checkForViolation(node.param); - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-shadow.js b/tools/eslint/lib/rules/no-shadow.js index 16432d6b02c6c0..ee0dd69f3a571f 100644 --- a/tools/eslint/lib/rules/no-shadow.js +++ b/tools/eslint/lib/rules/no-shadow.js @@ -1,7 +1,6 @@ /** * @fileoverview Rule to flag on declaring variables already declared in the outer scope * @author Ilya Volodin - * @copyright 2013 Ilya Volodin. All rights reserved. */ "use strict"; @@ -16,164 +15,174 @@ var astUtils = require("../ast-utils"); // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - var options = { - builtinGlobals: Boolean(context.options[0] && context.options[0].builtinGlobals), - hoist: (context.options[0] && context.options[0].hoist) || "functions", - allow: (context.options[0] && context.options[0].allow) || [] - }; - - /** - * Check if variable name is allowed. - * - * @param {ASTNode} variable The variable to check. - * @returns {boolean} Whether or not the variable name is allowed. - */ - function isAllowed(variable) { - return options.allow.indexOf(variable.name) !== -1; - } - - /** - * Checks if a variable of the class name in the class scope of ClassDeclaration. - * - * ClassDeclaration creates two variables of its name into its outer scope and its class scope. - * So we should ignore the variable in the class scope. - * - * @param {Object} variable The variable to check. - * @returns {boolean} Whether or not the variable of the class name in the class scope of ClassDeclaration. - */ - function isDuplicatedClassNameVariable(variable) { - var block = variable.scope.block; - - return block.type === "ClassDeclaration" && block.id === variable.identifiers[0]; - } +module.exports = { + meta: { + docs: { + description: "disallow `var` declarations from shadowing variables in the outer scope", + category: "Variables", + recommended: false + }, - /** - * Checks if a variable is inside the initializer of scopeVar. - * - * To avoid reporting at declarations such as `var a = function a() {};`. - * But it should report `var a = function(a) {};` or `var a = function() { function a() {} };`. - * - * @param {Object} variable The variable to check. - * @param {Object} scopeVar The scope variable to look for. - * @returns {boolean} Whether or not the variable is inside initializer of scopeVar. - */ - function isOnInitializer(variable, scopeVar) { - var outerScope = scopeVar.scope; - var outerDef = scopeVar.defs[0]; - var outer = outerDef && outerDef.parent && outerDef.parent.range; - var innerScope = variable.scope; - var innerDef = variable.defs[0]; - var inner = innerDef && innerDef.name.range; - - return ( - outer && - inner && - outer[0] < inner[0] && - inner[1] < outer[1] && - ((innerDef.type === "FunctionName" && innerDef.node.type === "FunctionExpression") || innerDef.node.type === "ClassExpression") && - outerScope === innerScope.upper - ); - } + schema: [ + { + type: "object", + properties: { + builtinGlobals: {type: "boolean"}, + hoist: {enum: ["all", "functions", "never"]}, + allow: { + type: "array", + items: { + type: "string" + } + } + }, + additionalProperties: false + } + ] + }, + + create: function(context) { + + var options = { + builtinGlobals: Boolean(context.options[0] && context.options[0].builtinGlobals), + hoist: (context.options[0] && context.options[0].hoist) || "functions", + allow: (context.options[0] && context.options[0].allow) || [] + }; + + /** + * Check if variable name is allowed. + * + * @param {ASTNode} variable The variable to check. + * @returns {boolean} Whether or not the variable name is allowed. + */ + function isAllowed(variable) { + return options.allow.indexOf(variable.name) !== -1; + } - /** - * Get a range of a variable's identifier node. - * @param {Object} variable The variable to get. - * @returns {Array|undefined} The range of the variable's identifier node. - */ - function getNameRange(variable) { - var def = variable.defs[0]; + /** + * Checks if a variable of the class name in the class scope of ClassDeclaration. + * + * ClassDeclaration creates two variables of its name into its outer scope and its class scope. + * So we should ignore the variable in the class scope. + * + * @param {Object} variable The variable to check. + * @returns {boolean} Whether or not the variable of the class name in the class scope of ClassDeclaration. + */ + function isDuplicatedClassNameVariable(variable) { + var block = variable.scope.block; + + return block.type === "ClassDeclaration" && block.id === variable.identifiers[0]; + } - return def && def.name.range; - } + /** + * Checks if a variable is inside the initializer of scopeVar. + * + * To avoid reporting at declarations such as `var a = function a() {};`. + * But it should report `var a = function(a) {};` or `var a = function() { function a() {} };`. + * + * @param {Object} variable The variable to check. + * @param {Object} scopeVar The scope variable to look for. + * @returns {boolean} Whether or not the variable is inside initializer of scopeVar. + */ + function isOnInitializer(variable, scopeVar) { + var outerScope = scopeVar.scope; + var outerDef = scopeVar.defs[0]; + var outer = outerDef && outerDef.parent && outerDef.parent.range; + var innerScope = variable.scope; + var innerDef = variable.defs[0]; + var inner = innerDef && innerDef.name.range; + + return ( + outer && + inner && + outer[0] < inner[0] && + inner[1] < outer[1] && + ((innerDef.type === "FunctionName" && innerDef.node.type === "FunctionExpression") || innerDef.node.type === "ClassExpression") && + outerScope === innerScope.upper + ); + } - /** - * Checks if a variable is in TDZ of scopeVar. - * @param {Object} variable The variable to check. - * @param {Object} scopeVar The variable of TDZ. - * @returns {boolean} Whether or not the variable is in TDZ of scopeVar. - */ - function isInTdz(variable, scopeVar) { - var outerDef = scopeVar.defs[0]; - var inner = getNameRange(variable); - var outer = getNameRange(scopeVar); - - return ( - inner && - outer && - inner[1] < outer[0] && - - // Excepts FunctionDeclaration if is {"hoist":"function"}. - (options.hoist !== "functions" || !outerDef || outerDef.node.type !== "FunctionDeclaration") - ); - } + /** + * Get a range of a variable's identifier node. + * @param {Object} variable The variable to get. + * @returns {Array|undefined} The range of the variable's identifier node. + */ + function getNameRange(variable) { + var def = variable.defs[0]; - /** - * Checks the current context for shadowed variables. - * @param {Scope} scope - Fixme - * @returns {void} - */ - function checkForShadows(scope) { - var variables = scope.variables; - - for (var i = 0; i < variables.length; ++i) { - var variable = variables[i]; - - // Skips "arguments" or variables of a class name in the class scope of ClassDeclaration. - if (variable.identifiers.length === 0 || - isDuplicatedClassNameVariable(variable) || - isAllowed(variable) - ) { - continue; - } + return def && def.name.range; + } - // Gets shadowed variable. - var shadowed = astUtils.getVariableByName(scope.upper, variable.name); - - if (shadowed && - (shadowed.identifiers.length > 0 || (options.builtinGlobals && "writeable" in shadowed)) && - !isOnInitializer(variable, shadowed) && - !(options.hoist !== "all" && isInTdz(variable, shadowed)) - ) { - context.report({ - node: variable.identifiers[0], - message: "'{{name}}' is already declared in the upper scope.", - data: variable - }); - } + /** + * Checks if a variable is in TDZ of scopeVar. + * @param {Object} variable The variable to check. + * @param {Object} scopeVar The variable of TDZ. + * @returns {boolean} Whether or not the variable is in TDZ of scopeVar. + */ + function isInTdz(variable, scopeVar) { + var outerDef = scopeVar.defs[0]; + var inner = getNameRange(variable); + var outer = getNameRange(scopeVar); + + return ( + inner && + outer && + inner[1] < outer[0] && + + // Excepts FunctionDeclaration if is {"hoist":"function"}. + (options.hoist !== "functions" || !outerDef || outerDef.node.type !== "FunctionDeclaration") + ); } - } - return { - "Program:exit": function() { - var globalScope = context.getScope(); - var stack = globalScope.childScopes.slice(); - var scope; + /** + * Checks the current context for shadowed variables. + * @param {Scope} scope - Fixme + * @returns {void} + */ + function checkForShadows(scope) { + var variables = scope.variables; + + for (var i = 0; i < variables.length; ++i) { + var variable = variables[i]; + + // Skips "arguments" or variables of a class name in the class scope of ClassDeclaration. + if (variable.identifiers.length === 0 || + isDuplicatedClassNameVariable(variable) || + isAllowed(variable) + ) { + continue; + } - while (stack.length) { - scope = stack.pop(); - stack.push.apply(stack, scope.childScopes); - checkForShadows(scope); + // Gets shadowed variable. + var shadowed = astUtils.getVariableByName(scope.upper, variable.name); + + if (shadowed && + (shadowed.identifiers.length > 0 || (options.builtinGlobals && "writeable" in shadowed)) && + !isOnInitializer(variable, shadowed) && + !(options.hoist !== "all" && isInTdz(variable, shadowed)) + ) { + context.report({ + node: variable.identifiers[0], + message: "'{{name}}' is already declared in the upper scope.", + data: variable + }); + } } } - }; -}; + return { + "Program:exit": function() { + var globalScope = context.getScope(); + var stack = globalScope.childScopes.slice(); + var scope; -module.exports.schema = [ - { - "type": "object", - "properties": { - "builtinGlobals": {"type": "boolean"}, - "hoist": {"enum": ["all", "functions", "never"]}, - "allow": { - "type": "array", - "items": { - "type": "string" + while (stack.length) { + scope = stack.pop(); + stack.push.apply(stack, scope.childScopes); + checkForShadows(scope); } } - }, - "additionalProperties": false + }; + } -]; +}; diff --git a/tools/eslint/lib/rules/no-spaced-func.js b/tools/eslint/lib/rules/no-spaced-func.js index 551a3c609717c5..f0a16121136cf6 100644 --- a/tools/eslint/lib/rules/no-spaced-func.js +++ b/tools/eslint/lib/rules/no-spaced-func.js @@ -9,52 +9,63 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - var sourceCode = context.getSourceCode(); - - /** - * Check if open space is present in a function name - * @param {ASTNode} node node to evaluate - * @returns {void} - * @private - */ - function detectOpenSpaces(node) { - var lastCalleeToken = sourceCode.getLastToken(node.callee), - prevToken = lastCalleeToken, - 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); - } +module.exports = { + meta: { + docs: { + description: "disallow spacing between `function` identifiers and their applications", + category: "Stylistic Issues", + recommended: false + }, + + fixable: "whitespace", + schema: [] + }, + + create: function(context) { + + var sourceCode = context.getSourceCode(); + + /** + * Check if open space is present in a function name + * @param {ASTNode} node node to evaluate + * @returns {void} + * @private + */ + function detectOpenSpaces(node) { + var lastCalleeToken = sourceCode.getLastToken(node.callee), + prevToken = lastCalleeToken, + parenToken = sourceCode.getTokenAfter(lastCalleeToken); - // look for a space between the callee and the open paren - if (parenToken && - parenToken.range[1] < node.range[1] && - sourceCode.isSpaceBetweenTokens(prevToken, parenToken) - ) { - context.report({ - node: node, - loc: lastCalleeToken.loc.start, - message: "Unexpected space between function name and paren.", - fix: function(fixer) { - return fixer.removeRange([prevToken.range[1], parenToken.range[0]]); - } - }); + // advances to an open parenthesis. + while ( + parenToken && + parenToken.range[1] < node.range[1] && + parenToken.value !== "(" + ) { + prevToken = parenToken; + parenToken = sourceCode.getTokenAfter(parenToken); + } + + // look for a space between the callee and the open paren + if (parenToken && + parenToken.range[1] < node.range[1] && + sourceCode.isSpaceBetweenTokens(prevToken, parenToken) + ) { + context.report({ + node: node, + loc: lastCalleeToken.loc.start, + message: "Unexpected space between function name and paren.", + fix: function(fixer) { + return fixer.removeRange([prevToken.range[1], parenToken.range[0]]); + } + }); + } } - } - return { - "CallExpression": detectOpenSpaces, - "NewExpression": detectOpenSpaces - }; + return { + CallExpression: detectOpenSpaces, + NewExpression: detectOpenSpaces + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-sparse-arrays.js b/tools/eslint/lib/rules/no-sparse-arrays.js index 808ec99bfc16fa..b1ae0ba74036b4 100644 --- a/tools/eslint/lib/rules/no-sparse-arrays.js +++ b/tools/eslint/lib/rules/no-sparse-arrays.js @@ -8,26 +8,36 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow sparse arrays", + category: "Possible Errors", + recommended: true + }, + schema: [] + }, - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- + create: function(context) { - return { - "ArrayExpression": function(node) { + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- - var emptySpot = node.elements.indexOf(null) > -1; + return { - if (emptySpot) { - context.report(node, "Unexpected comma in middle of array."); + ArrayExpression: function(node) { + + var emptySpot = node.elements.indexOf(null) > -1; + + if (emptySpot) { + context.report(node, "Unexpected comma in middle of array."); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-sync.js b/tools/eslint/lib/rules/no-sync.js index 481514b83d492b..be6860e75af4ac 100644 --- a/tools/eslint/lib/rules/no-sync.js +++ b/tools/eslint/lib/rules/no-sync.js @@ -11,20 +11,30 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow synchronous methods", + category: "Node.js and CommonJS", + recommended: false + }, - return { + schema: [] + }, - "MemberExpression": function(node) { - var propertyName = node.property.name, - syncRegex = /.*Sync$/; + create: function(context) { - if (syncRegex.exec(propertyName) !== null) { - context.report(node, "Unexpected sync method: '" + propertyName + "'."); + return { + + MemberExpression: function(node) { + var propertyName = node.property.name, + syncRegex = /.*Sync$/; + + if (syncRegex.exec(propertyName) !== null) { + context.report(node, "Unexpected sync method: '" + propertyName + "'."); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-ternary.js b/tools/eslint/lib/rules/no-ternary.js index 79f8576b5fc8a7..fb986152bbf74b 100644 --- a/tools/eslint/lib/rules/no-ternary.js +++ b/tools/eslint/lib/rules/no-ternary.js @@ -9,16 +9,26 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow ternary operators", + category: "Stylistic Issues", + recommended: false + }, - return { + schema: [] + }, - "ConditionalExpression": function(node) { - context.report(node, "Ternary operator used."); - } + create: function(context) { - }; + return { -}; + ConditionalExpression: function(node) { + context.report(node, "Ternary operator used."); + } + + }; -module.exports.schema = []; + } +}; diff --git a/tools/eslint/lib/rules/no-this-before-super.js b/tools/eslint/lib/rules/no-this-before-super.js index 4e6c47fda8d851..fb172f47f3a6fa 100644 --- a/tools/eslint/lib/rules/no-this-before-super.js +++ b/tools/eslint/lib/rules/no-this-before-super.js @@ -1,7 +1,6 @@ /** * @fileoverview A rule to disallow using `this`/`super` before `super()`. * @author Toru Nagashima - * @copyright 2015 Toru Nagashima. All rights reserved. */ "use strict"; @@ -35,248 +34,266 @@ function isConstructorFunction(node) { // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - /* - * Information for each constructor. - * - upper: Information of the upper constructor. - * - hasExtends: A flag which shows whether the owner class has a valid - * `extends` part. - * - scope: The scope of the owner class. - * - codePath: The code path of this constructor. - */ - var funcInfo = null; - - /* - * Information for each code path segment. - * Each key is the id of a code path segment. - * Each value is an object: - * - superCalled: The flag which shows `super()` called in all code paths. - * - invalidNodes: The array of invalid ThisExpression and Super nodes. - */ - var segInfoMap = Object.create(null); - - /** - * Gets whether or not `super()` is called in a given code path segment. - * @param {CodePathSegment} segment - A code path segment to get. - * @returns {boolean} `true` if `super()` is called. - */ - function isCalled(segment) { - return segInfoMap[segment.id].superCalled; - } +module.exports = { + meta: { + docs: { + description: "disallow `this`/`super` before calling `super()` in constructors", + category: "ECMAScript 6", + recommended: true + }, - /** - * Checks whether or not this is in a constructor. - * @returns {boolean} `true` if this is in a constructor. - */ - function isInConstructorOfDerivedClass() { - return Boolean(funcInfo && funcInfo.isConstructor && funcInfo.hasExtends); - } + schema: [] + }, - /** - * Checks whether or not this is before `super()` is called. - * @returns {boolean} `true` if this is before `super()` is called. - */ - function isBeforeCallOfSuper() { - return ( - isInConstructorOfDerivedClass(funcInfo) && - !funcInfo.codePath.currentSegments.every(isCalled) - ); - } + create: function(context) { - /** - * Sets a given node as invalid. - * @param {ASTNode} node - A node to set as invalid. This is one of - * a ThisExpression and a Super. - * @returns {void} - */ - function setInvalid(node) { - var segments = funcInfo.codePath.currentSegments; - - for (var i = 0; i < segments.length; ++i) { - segInfoMap[segments[i].id].invalidNodes.push(node); - } - } - - /** - * Sets the current segment as `super` was called. - * @returns {void} - */ - function setSuperCalled() { - var segments = funcInfo.codePath.currentSegments; + /* + * Information for each constructor. + * - upper: Information of the upper constructor. + * - hasExtends: A flag which shows whether the owner class has a valid + * `extends` part. + * - scope: The scope of the owner class. + * - codePath: The code path of this constructor. + */ + var funcInfo = null; + + /* + * Information for each code path segment. + * Each key is the id of a code path segment. + * Each value is an object: + * - superCalled: The flag which shows `super()` called in all code paths. + * - invalidNodes: The array of invalid ThisExpression and Super nodes. + */ + var segInfoMap = Object.create(null); - for (var i = 0; i < segments.length; ++i) { - segInfoMap[segments[i].id].superCalled = true; + /** + * Gets whether or not `super()` is called in a given code path segment. + * @param {CodePathSegment} segment - A code path segment to get. + * @returns {boolean} `true` if `super()` is called. + */ + function isCalled(segment) { + return !segment.reachable || segInfoMap[segment.id].superCalled; } - } - return { + /** + * Checks whether or not this is in a constructor. + * @returns {boolean} `true` if this is in a constructor. + */ + function isInConstructorOfDerivedClass() { + return Boolean(funcInfo && funcInfo.isConstructor && funcInfo.hasExtends); + } /** - * Adds information of a constructor into the stack. - * @param {CodePath} codePath - A code path which was started. - * @param {ASTNode} node - The current node. - * @returns {void} + * Checks whether or not this is before `super()` is called. + * @returns {boolean} `true` if this is before `super()` is called. */ - "onCodePathStart": function(codePath, node) { - if (isConstructorFunction(node)) { - - // Class > ClassBody > MethodDefinition > FunctionExpression - var classNode = node.parent.parent.parent; - - funcInfo = { - upper: funcInfo, - isConstructor: true, - hasExtends: Boolean( - classNode.superClass && - !astUtils.isNullOrUndefined(classNode.superClass) - ), - codePath: codePath - }; - } else { - funcInfo = { - upper: funcInfo, - isConstructor: false, - hasExtends: false, - codePath: codePath - }; - } - }, + function isBeforeCallOfSuper() { + return ( + isInConstructorOfDerivedClass(funcInfo) && + !funcInfo.codePath.currentSegments.every(isCalled) + ); + } /** - * Removes the top of stack item. - * - * And this treverses all segments of this code path then reports every - * invalid node. - * - * @param {CodePath} codePath - A code path which was ended. - * @param {ASTNode} node - The current node. + * Sets a given node as invalid. + * @param {ASTNode} node - A node to set as invalid. This is one of + * a ThisExpression and a Super. * @returns {void} */ - "onCodePathEnd": function(codePath) { - var isDerivedClass = funcInfo.hasExtends; - - funcInfo = funcInfo.upper; - if (!isDerivedClass) { - return; - } - - codePath.traverseSegments(function(segment, controller) { - var info = segInfoMap[segment.id]; + function setInvalid(node) { + var segments = funcInfo.codePath.currentSegments; - for (var i = 0; i < info.invalidNodes.length; ++i) { - var invalidNode = info.invalidNodes[i]; + for (var i = 0; i < segments.length; ++i) { + var segment = segments[i]; - context.report({ - message: "'{{kind}}' is not allowed before 'super()'.", - node: invalidNode, - data: { - kind: invalidNode.type === "Super" ? "super" : "this" - } - }); - } - - if (info.superCalled) { - controller.skip(); + if (segment.reachable) { + segInfoMap[segment.id].invalidNodes.push(node); } - }); - }, + } + } /** - * Initialize information of a given code path segment. - * @param {CodePathSegment} segment - A code path segment to initialize. + * Sets the current segment as `super` was called. * @returns {void} */ - "onCodePathSegmentStart": function(segment) { - if (!isInConstructorOfDerivedClass(funcInfo)) { - return; - } + function setSuperCalled() { + var segments = funcInfo.codePath.currentSegments; - // Initialize info. - segInfoMap[segment.id] = { - superCalled: ( - segment.prevSegments.length > 0 && - segment.prevSegments.every(isCalled) - ), - invalidNodes: [] - }; - }, + for (var i = 0; i < segments.length; ++i) { + var segment = segments[i]; - /** - * Update information of the code path segment when a code path was - * looped. - * @param {CodePathSegment} fromSegment - The code path segment of the - * end of a loop. - * @param {CodePathSegment} toSegment - A code path segment of the head - * of a loop. - * @returns {void} - */ - "onCodePathSegmentLoop": function(fromSegment, toSegment) { - if (!isInConstructorOfDerivedClass(funcInfo)) { - return; + if (segment.reachable) { + segInfoMap[segment.id].superCalled = true; + } } + } - // Update information inside of the loop. - funcInfo.codePath.traverseSegments( - {first: toSegment, last: fromSegment}, - function(segment, controller) { + return { + + /** + * Adds information of a constructor into the stack. + * @param {CodePath} codePath - A code path which was started. + * @param {ASTNode} node - The current node. + * @returns {void} + */ + onCodePathStart: function(codePath, node) { + if (isConstructorFunction(node)) { + + // Class > ClassBody > MethodDefinition > FunctionExpression + var classNode = node.parent.parent.parent; + + funcInfo = { + upper: funcInfo, + isConstructor: true, + hasExtends: Boolean( + classNode.superClass && + !astUtils.isNullOrUndefined(classNode.superClass) + ), + codePath: codePath + }; + } else { + funcInfo = { + upper: funcInfo, + isConstructor: false, + hasExtends: false, + codePath: codePath + }; + } + }, + + /** + * Removes the top of stack item. + * + * And this treverses all segments of this code path then reports every + * invalid node. + * + * @param {CodePath} codePath - A code path which was ended. + * @param {ASTNode} node - The current node. + * @returns {void} + */ + onCodePathEnd: function(codePath) { + var isDerivedClass = funcInfo.hasExtends; + + funcInfo = funcInfo.upper; + if (!isDerivedClass) { + return; + } + + codePath.traverseSegments(function(segment, controller) { var info = segInfoMap[segment.id]; + for (var i = 0; i < info.invalidNodes.length; ++i) { + var invalidNode = info.invalidNodes[i]; + + context.report({ + message: "'{{kind}}' is not allowed before 'super()'.", + node: invalidNode, + data: { + kind: invalidNode.type === "Super" ? "super" : "this" + } + }); + } + if (info.superCalled) { - info.invalidNodes = []; controller.skip(); - } else if ( - segment.prevSegments.length > 0 && - segment.prevSegments.every(isCalled) - ) { - info.superCalled = true; - info.invalidNodes = []; } + }); + }, + + /** + * Initialize information of a given code path segment. + * @param {CodePathSegment} segment - A code path segment to initialize. + * @returns {void} + */ + onCodePathSegmentStart: function(segment) { + if (!isInConstructorOfDerivedClass(funcInfo)) { + return; } - ); - }, - - /** - * Reports if this is before `super()`. - * @param {ASTNode} node - A target node. - * @returns {void} - */ - "ThisExpression": function(node) { - if (isBeforeCallOfSuper()) { - setInvalid(node); - } - }, - /** - * Reports if this is before `super()`. - * @param {ASTNode} node - A target node. - * @returns {void} - */ - "Super": function(node) { - if (!astUtils.isCallee(node) && isBeforeCallOfSuper()) { - setInvalid(node); - } - }, + // Initialize info. + segInfoMap[segment.id] = { + superCalled: ( + segment.prevSegments.length > 0 && + segment.prevSegments.every(isCalled) + ), + invalidNodes: [] + }; + }, + + /** + * Update information of the code path segment when a code path was + * looped. + * @param {CodePathSegment} fromSegment - The code path segment of the + * end of a loop. + * @param {CodePathSegment} toSegment - A code path segment of the head + * of a loop. + * @returns {void} + */ + onCodePathSegmentLoop: function(fromSegment, toSegment) { + if (!isInConstructorOfDerivedClass(funcInfo)) { + return; + } - /** - * Marks `super()` called. - * @param {ASTNode} node - A target node. - * @returns {void} - */ - "CallExpression:exit": function(node) { - if (node.callee.type === "Super" && isBeforeCallOfSuper()) { - setSuperCalled(); + // Update information inside of the loop. + funcInfo.codePath.traverseSegments( + {first: toSegment, last: fromSegment}, + function(segment, controller) { + var info = segInfoMap[segment.id]; + + if (info.superCalled) { + info.invalidNodes = []; + controller.skip(); + } else if ( + segment.prevSegments.length > 0 && + segment.prevSegments.every(isCalled) + ) { + info.superCalled = true; + info.invalidNodes = []; + } + } + ); + }, + + /** + * Reports if this is before `super()`. + * @param {ASTNode} node - A target node. + * @returns {void} + */ + ThisExpression: function(node) { + if (isBeforeCallOfSuper()) { + setInvalid(node); + } + }, + + /** + * Reports if this is before `super()`. + * @param {ASTNode} node - A target node. + * @returns {void} + */ + Super: function(node) { + if (!astUtils.isCallee(node) && isBeforeCallOfSuper()) { + setInvalid(node); + } + }, + + /** + * Marks `super()` called. + * @param {ASTNode} node - A target node. + * @returns {void} + */ + "CallExpression:exit": function(node) { + if (node.callee.type === "Super" && isBeforeCallOfSuper()) { + setSuperCalled(); + } + }, + + /** + * Resets state. + * @returns {void} + */ + "Program:exit": function() { + segInfoMap = Object.create(null); } - }, - - /** - * Resets state. - * @returns {void} - */ - "Program:exit": function() { - segInfoMap = Object.create(null); - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-throw-literal.js b/tools/eslint/lib/rules/no-throw-literal.js index 745850dc8dd30e..bedf94379e81f3 100644 --- a/tools/eslint/lib/rules/no-throw-literal.js +++ b/tools/eslint/lib/rules/no-throw-literal.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to restrict what can be thrown as an exception. * @author Dieter Oberkofler - * @copyright 2015 Ian VanSchooten. All rights reserved. - * @copyright 2015 Dieter Oberkofler. All rights reserved. */ "use strict"; @@ -49,23 +47,33 @@ function couldBeError(node) { // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow throwing literals as exceptions", + category: "Best Practices", + recommended: false + }, - return { + schema: [] + }, - "ThrowStatement": function(node) { - if (!couldBeError(node.argument)) { - context.report(node, "Expected an object to be thrown."); - } else if (node.argument.type === "Identifier") { - if (node.argument.name === "undefined") { - context.report(node, "Do not throw undefined."); + create: function(context) { + + return { + + ThrowStatement: function(node) { + if (!couldBeError(node.argument)) { + context.report(node, "Expected an object to be thrown."); + } else if (node.argument.type === "Identifier") { + if (node.argument.name === "undefined") { + context.report(node, "Do not throw undefined."); + } } - } - } + } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-trailing-spaces.js b/tools/eslint/lib/rules/no-trailing-spaces.js index af30610f94e759..a08907fc95f343 100644 --- a/tools/eslint/lib/rules/no-trailing-spaces.js +++ b/tools/eslint/lib/rules/no-trailing-spaces.js @@ -1,7 +1,6 @@ /** * @fileoverview Disallow trailing spaces at the end of lines. * @author Nodeca Team - * @copyright 2015 Greg Cochard */ "use strict"; @@ -9,103 +8,128 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - var BLANK_CLASS = "[ \t\u00a0\u2000-\u200b\u2028\u2029\u3000]", - SKIP_BLANK = "^" + BLANK_CLASS + "*$", - NONBLANK = BLANK_CLASS + "+$"; - - var options = context.options[0] || {}, - skipBlankLines = options.skipBlankLines || false; - - /** - * Report the error message - * @param {ASTNode} node node to report - * @param {int[]} location range information - * @param {int[]} fixRange Range based on the whole program - * @returns {void} - */ - function report(node, location, fixRange) { - - /* - * Passing node is a bit dirty, because message data will contain big - * text in `source`. But... who cares :) ? - * One more kludge will not make worse the bloody wizardry of this - * plugin. - */ - context.report({ - node: node, - loc: location, - message: "Trailing spaces not allowed.", - fix: function(fixer) { - return fixer.removeRange(fixRange); - } - }); - } - - - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- +module.exports = { + meta: { + docs: { + description: "disallow trailing whitespace at the end of lines", + category: "Stylistic Issues", + recommended: false + }, - return { + fixable: "whitespace", - "Program": function checkTrailingSpaces(node) { + schema: [ + { + type: "object", + properties: { + skipBlankLines: { + type: "boolean" + } + }, + additionalProperties: false + } + ] + }, - // Let's hack. Since Espree does not return whitespace nodes, - // fetch the source code and do matching via regexps. + create: function(context) { + var sourceCode = context.getSourceCode(); - var src = context.getSource(), - re = new RegExp(NONBLANK), - skipMatch = new RegExp(SKIP_BLANK), - matches, - lines = src.split(/\r?\n/), - linebreaks = context.getSource().match(/\r\n|\r|\n|\u2028|\u2029/g), - location, - totalLength = 0, - fixRange = []; + var BLANK_CLASS = "[ \t\u00a0\u2000-\u200b\u2028\u2029\u3000]", + SKIP_BLANK = "^" + BLANK_CLASS + "*$", + NONBLANK = BLANK_CLASS + "+$"; - for (var i = 0, ii = lines.length; i < ii; i++) { - matches = re.exec(lines[i]); + var options = context.options[0] || {}, + skipBlankLines = options.skipBlankLines || false; - // Always add linebreak length to line length to accommodate for line break (\n or \r\n) - // Because during the fix time they also reserve one spot in the array. - // Usually linebreak length is 2 for \r\n (CRLF) and 1 for \n (LF) - var linebreakLength = linebreaks && linebreaks[i] ? linebreaks[i].length : 1; - var lineLength = lines[i].length + linebreakLength; + /** + * Report the error message + * @param {ASTNode} node node to report + * @param {int[]} location range information + * @param {int[]} fixRange Range based on the whole program + * @returns {void} + */ + function report(node, location, fixRange) { + + /* + * Passing node is a bit dirty, because message data will contain big + * text in `source`. But... who cares :) ? + * One more kludge will not make worse the bloody wizardry of this + * plugin. + */ + context.report({ + node: node, + loc: location, + message: "Trailing spaces not allowed.", + fix: function(fixer) { + return fixer.removeRange(fixRange); + } + }); + } - if (matches) { - // If the line has only whitespace, and skipBlankLines - // is true, don't report it - if (skipBlankLines && skipMatch.test(lines[i])) { - continue; + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + return { + + Program: function checkTrailingSpaces(node) { + + // Let's hack. Since Espree does not return whitespace nodes, + // fetch the source code and do matching via regexps. + + var re = new RegExp(NONBLANK), + skipMatch = new RegExp(SKIP_BLANK), + matches, + lines = sourceCode.lines, + linebreaks = sourceCode.getText().match(/\r\n|\r|\n|\u2028|\u2029/g), + location, + totalLength = 0, + rangeStart, + rangeEnd, + fixRange = [], + containingNode; + + for (var i = 0, ii = lines.length; i < ii; i++) { + matches = re.exec(lines[i]); + + // Always add linebreak length to line length to accommodate for line break (\n or \r\n) + // Because during the fix time they also reserve one spot in the array. + // Usually linebreak length is 2 for \r\n (CRLF) and 1 for \n (LF) + var linebreakLength = linebreaks && linebreaks[i] ? linebreaks[i].length : 1; + var lineLength = lines[i].length + linebreakLength; + + if (matches) { + location = { + line: i + 1, + column: matches.index + }; + + rangeStart = totalLength + location.column; + rangeEnd = totalLength + lineLength - linebreakLength; + containingNode = sourceCode.getNodeByRangeIndex(rangeStart); + + if (containingNode && containingNode.type === "TemplateElement" && + rangeStart > containingNode.parent.range[0] && + rangeEnd < containingNode.parent.range[1]) { + totalLength += lineLength; + continue; + } + + // If the line has only whitespace, and skipBlankLines + // is true, don't report it + if (skipBlankLines && skipMatch.test(lines[i])) { + continue; + } + + fixRange = [rangeStart, rangeEnd]; + report(node, location, fixRange); } - location = { - line: i + 1, - column: matches.index - }; - - fixRange = [totalLength + location.column, totalLength + lineLength - linebreakLength]; - report(node, location, fixRange); + totalLength += lineLength; } - - totalLength += lineLength; } - } - }; -}; - -module.exports.schema = [ - { - "type": "object", - "properties": { - "skipBlankLines": { - "type": "boolean" - } - }, - "additionalProperties": false + }; } -]; +}; diff --git a/tools/eslint/lib/rules/no-undef-init.js b/tools/eslint/lib/rules/no-undef-init.js index 1348c641e362a8..8622e45701f0a1 100644 --- a/tools/eslint/lib/rules/no-undef-init.js +++ b/tools/eslint/lib/rules/no-undef-init.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to flag when initializing to undefined * @author Ilya Volodin - * @copyright 2013 Ilya Volodin. All rights reserved. - * See LICENSE in root directory for full license. */ "use strict"; @@ -11,20 +9,30 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow initializing variables to `undefined`", + category: "Variables", + recommended: false + }, - return { + schema: [] + }, - "VariableDeclarator": function(node) { - var name = node.id.name, - init = node.init && node.init.name; + create: function(context) { - if (init === "undefined" && node.parent.kind !== "const") { - context.report(node, "It's not necessary to initialize '{{name}}' to undefined.", { name: name }); + return { + + VariableDeclarator: function(node) { + var name = node.id.name, + init = node.init && node.init.name; + + if (init === "undefined" && node.parent.kind !== "const") { + context.report(node, "It's not necessary to initialize '{{name}}' to undefined.", { name: name }); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-undef.js b/tools/eslint/lib/rules/no-undef.js index c3a88725678e75..b76ce4bb5bfefc 100644 --- a/tools/eslint/lib/rules/no-undef.js +++ b/tools/eslint/lib/rules/no-undef.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to flag references to undeclared variables. * @author Mark Macdonald - * @copyright 2015 Nicholas C. Zakas. All rights reserved. - * @copyright 2013 Mark Macdonald. All rights reserved. */ "use strict"; @@ -25,39 +23,49 @@ function hasTypeOfOperator(node) { // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var options = context.options[0]; - var considerTypeOf = options && options.typeof === true || false; +module.exports = { + meta: { + docs: { + description: "disallow the use of undeclared variables unless mentioned in `/*global */` comments", + category: "Variables", + recommended: true + }, - return { - "Program:exit": function(/* node */) { - var globalScope = context.getScope(); + schema: [ + { + type: "object", + properties: { + typeof: { + type: "boolean" + } + }, + additionalProperties: false + } + ] + }, - globalScope.through.forEach(function(ref) { - var identifier = ref.identifier; + create: function(context) { + var options = context.options[0]; + var considerTypeOf = options && options.typeof === true || false; - if (!considerTypeOf && hasTypeOfOperator(identifier)) { - return; - } + return { + "Program:exit": function(/* node */) { + var globalScope = context.getScope(); - context.report({ - node: identifier, - message: "'{{name}}' is not defined.", - data: identifier - }); - }); - } - }; -}; + globalScope.through.forEach(function(ref) { + var identifier = ref.identifier; -module.exports.schema = [ - { - "type": "object", - "properties": { - "typeof": { - "type": "boolean" + if (!considerTypeOf && hasTypeOfOperator(identifier)) { + return; + } + + context.report({ + node: identifier, + message: "'{{name}}' is not defined.", + data: identifier + }); + }); } - }, - "additionalProperties": false + }; } -]; +}; diff --git a/tools/eslint/lib/rules/no-undefined.js b/tools/eslint/lib/rules/no-undefined.js index a44eabf1b1fa82..3ad2128b4efb0c 100644 --- a/tools/eslint/lib/rules/no-undefined.js +++ b/tools/eslint/lib/rules/no-undefined.js @@ -8,21 +8,31 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow the use of `undefined` as an identifier", + category: "Variables", + recommended: false + }, - return { + schema: [] + }, - "Identifier": function(node) { - if (node.name === "undefined") { - var parent = context.getAncestors().pop(); + create: function(context) { - if (!parent || parent.type !== "MemberExpression" || node !== parent.property || parent.computed) { - context.report(node, "Unexpected use of undefined."); + return { + + Identifier: function(node) { + if (node.name === "undefined") { + var parent = context.getAncestors().pop(); + + if (!parent || parent.type !== "MemberExpression" || node !== parent.property || parent.computed) { + context.report(node, "Unexpected use of undefined."); + } } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-underscore-dangle.js b/tools/eslint/lib/rules/no-underscore-dangle.js index 6401e93e3780b2..4217f8adc53b96 100644 --- a/tools/eslint/lib/rules/no-underscore-dangle.js +++ b/tools/eslint/lib/rules/no-underscore-dangle.js @@ -9,136 +9,146 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - var options = context.options[0] || {}; - var ALLOWED_VARIABLES = options.allow ? options.allow : []; - var allowAfterThis = typeof options.allowAfterThis !== "undefined" ? options.allowAfterThis : false; - - //------------------------------------------------------------------------- - // Helpers - //------------------------------------------------------------------------- - - /** - * Check if identifier is present inside the allowed option - * @param {string} identifier name of the node - * @returns {boolean} true if its is present - * @private - */ - function isAllowed(identifier) { - return ALLOWED_VARIABLES.some(function(ident) { - return ident === identifier; - }); - } +module.exports = { + meta: { + docs: { + description: "disallow dangling underscores in identifiers", + category: "Stylistic Issues", + recommended: false + }, - /** - * Check if identifier has a underscore at the end - * @param {ASTNode} identifier node to evaluate - * @returns {boolean} true if its is present - * @private - */ - function hasTrailingUnderscore(identifier) { - var len = identifier.length; + schema: [ + { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string" + } + }, + allowAfterThis: { + type: "boolean" + } + }, + additionalProperties: false + } + ] + }, + + create: function(context) { + + var options = context.options[0] || {}; + var ALLOWED_VARIABLES = options.allow ? options.allow : []; + var allowAfterThis = typeof options.allowAfterThis !== "undefined" ? options.allowAfterThis : false; + + //------------------------------------------------------------------------- + // Helpers + //------------------------------------------------------------------------- + + /** + * Check if identifier is present inside the allowed option + * @param {string} identifier name of the node + * @returns {boolean} true if its is present + * @private + */ + function isAllowed(identifier) { + return ALLOWED_VARIABLES.some(function(ident) { + return ident === identifier; + }); + } - return identifier !== "_" && (identifier[0] === "_" || identifier[len - 1] === "_"); - } + /** + * Check if identifier has a underscore at the end + * @param {ASTNode} identifier node to evaluate + * @returns {boolean} true if its is present + * @private + */ + function hasTrailingUnderscore(identifier) { + var len = identifier.length; - /** - * Check if identifier is a special case member expression - * @param {ASTNode} identifier node to evaluate - * @returns {boolean} true if its is a special case - * @private - */ - function isSpecialCaseIdentifierForMemberExpression(identifier) { - return identifier === "__proto__"; - } + return identifier !== "_" && (identifier[0] === "_" || identifier[len - 1] === "_"); + } - /** - * Check if identifier is a special case variable expression - * @param {ASTNode} identifier node to evaluate - * @returns {boolean} true if its is a special case - * @private - */ - function isSpecialCaseIdentifierInVariableExpression(identifier) { + /** + * Check if identifier is a special case member expression + * @param {ASTNode} identifier node to evaluate + * @returns {boolean} true if its is a special case + * @private + */ + function isSpecialCaseIdentifierForMemberExpression(identifier) { + return identifier === "__proto__"; + } - // Checks for the underscore library usage here - return identifier === "_"; - } + /** + * Check if identifier is a special case variable expression + * @param {ASTNode} identifier node to evaluate + * @returns {boolean} true if its is a special case + * @private + */ + function isSpecialCaseIdentifierInVariableExpression(identifier) { - /** - * Check if function has a underscore at the end - * @param {ASTNode} node node to evaluate - * @returns {void} - * @private - */ - function checkForTrailingUnderscoreInFunctionDeclaration(node) { - if (node.id) { - var identifier = node.id.name; + // Checks for the underscore library usage here + return identifier === "_"; + } - if (typeof identifier !== "undefined" && hasTrailingUnderscore(identifier) && !isAllowed(identifier)) { - context.report(node, "Unexpected dangling '_' in '" + identifier + "'."); + /** + * Check if function has a underscore at the end + * @param {ASTNode} node node to evaluate + * @returns {void} + * @private + */ + function checkForTrailingUnderscoreInFunctionDeclaration(node) { + if (node.id) { + var identifier = node.id.name; + + if (typeof identifier !== "undefined" && hasTrailingUnderscore(identifier) && !isAllowed(identifier)) { + context.report(node, "Unexpected dangling '_' in '" + identifier + "'."); + } } } - } - /** - * Check if variable expression has a underscore at the end - * @param {ASTNode} node node to evaluate - * @returns {void} - * @private - */ - function checkForTrailingUnderscoreInVariableExpression(node) { - var identifier = node.id.name; - - if (typeof identifier !== "undefined" && hasTrailingUnderscore(identifier) && - !isSpecialCaseIdentifierInVariableExpression(identifier) && !isAllowed(identifier)) { - context.report(node, "Unexpected dangling '_' in '" + identifier + "'."); - } - } + /** + * Check if variable expression has a underscore at the end + * @param {ASTNode} node node to evaluate + * @returns {void} + * @private + */ + function checkForTrailingUnderscoreInVariableExpression(node) { + var identifier = node.id.name; - /** - * Check if member expression has a underscore at the end - * @param {ASTNode} node node to evaluate - * @returns {void} - * @private - */ - function checkForTrailingUnderscoreInMemberExpression(node) { - var identifier = node.property.name, - isMemberOfThis = node.object.type === "ThisExpression"; - - if (typeof identifier !== "undefined" && hasTrailingUnderscore(identifier) && - !(isMemberOfThis && allowAfterThis) && - !isSpecialCaseIdentifierForMemberExpression(identifier) && !isAllowed(identifier)) { - context.report(node, "Unexpected dangling '_' in '" + identifier + "'."); + if (typeof identifier !== "undefined" && hasTrailingUnderscore(identifier) && + !isSpecialCaseIdentifierInVariableExpression(identifier) && !isAllowed(identifier)) { + context.report(node, "Unexpected dangling '_' in '" + identifier + "'."); + } } - } - //-------------------------------------------------------------------------- - // Public API - //-------------------------------------------------------------------------- + /** + * Check if member expression has a underscore at the end + * @param {ASTNode} node node to evaluate + * @returns {void} + * @private + */ + function checkForTrailingUnderscoreInMemberExpression(node) { + var identifier = node.property.name, + isMemberOfThis = node.object.type === "ThisExpression"; + + if (typeof identifier !== "undefined" && hasTrailingUnderscore(identifier) && + !(isMemberOfThis && allowAfterThis) && + !isSpecialCaseIdentifierForMemberExpression(identifier) && !isAllowed(identifier)) { + context.report(node, "Unexpected dangling '_' in '" + identifier + "'."); + } + } - return { - "FunctionDeclaration": checkForTrailingUnderscoreInFunctionDeclaration, - "VariableDeclarator": checkForTrailingUnderscoreInVariableExpression, - "MemberExpression": checkForTrailingUnderscoreInMemberExpression - }; + //-------------------------------------------------------------------------- + // Public API + //-------------------------------------------------------------------------- -}; + return { + FunctionDeclaration: checkForTrailingUnderscoreInFunctionDeclaration, + VariableDeclarator: checkForTrailingUnderscoreInVariableExpression, + MemberExpression: checkForTrailingUnderscoreInMemberExpression + }; -module.exports.schema = [ - { - "type": "object", - "properties": { - "allow": { - "type": "array", - "items": { - "type": "string" - } - }, - "allowAfterThis": { - "type": "boolean" - } - }, - "additionalProperties": false } -]; +}; diff --git a/tools/eslint/lib/rules/no-unexpected-multiline.js b/tools/eslint/lib/rules/no-unexpected-multiline.js index 312376a334ac30..c066673301a81c 100644 --- a/tools/eslint/lib/rules/no-unexpected-multiline.js +++ b/tools/eslint/lib/rules/no-unexpected-multiline.js @@ -1,70 +1,79 @@ /** * @fileoverview Rule to spot scenarios where a newline looks like it is ending a statement, but is not. * @author Glen Mailer - * @copyright 2015 Glen Mailer */ "use strict"; //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow confusing multiline expressions", + category: "Possible Errors", + recommended: true + }, - var FUNCTION_MESSAGE = "Unexpected newline between function and ( of function call."; - var PROPERTY_MESSAGE = "Unexpected newline between object and [ of property access."; - var TAGGED_TEMPLATE_MESSAGE = "Unexpected newline between template tag and template literal."; + schema: [] + }, - /** - * Check to see if there is a newline between the node and the following open bracket - * line's expression - * @param {ASTNode} node The node to check. - * @param {string} msg The error message to use. - * @returns {void} - * @private - */ - function checkForBreakAfter(node, msg) { - var nodeExpressionEnd = node; - var openParen = context.getTokenAfter(node); + create: function(context) { - // Move along until the end of the wrapped expression - while (openParen.value === ")") { - nodeExpressionEnd = openParen; - openParen = context.getTokenAfter(nodeExpressionEnd); - } + var FUNCTION_MESSAGE = "Unexpected newline between function and ( of function call."; + var PROPERTY_MESSAGE = "Unexpected newline between object and [ of property access."; + var TAGGED_TEMPLATE_MESSAGE = "Unexpected newline between template tag and template literal."; - if (openParen.loc.start.line !== nodeExpressionEnd.loc.end.line) { - context.report(node, openParen.loc.start, msg, { char: openParen.value }); + /** + * Check to see if there is a newline between the node and the following open bracket + * line's expression + * @param {ASTNode} node The node to check. + * @param {string} msg The error message to use. + * @returns {void} + * @private + */ + function checkForBreakAfter(node, msg) { + var nodeExpressionEnd = node; + var openParen = context.getTokenAfter(node); + + // Move along until the end of the wrapped expression + while (openParen.value === ")") { + nodeExpressionEnd = openParen; + openParen = context.getTokenAfter(nodeExpressionEnd); + } + + if (openParen.loc.start.line !== nodeExpressionEnd.loc.end.line) { + context.report(node, openParen.loc.start, msg, { char: openParen.value }); + } } - } - //-------------------------------------------------------------------------- - // Public API - //-------------------------------------------------------------------------- + //-------------------------------------------------------------------------- + // Public API + //-------------------------------------------------------------------------- - return { + return { - "MemberExpression": function(node) { - if (!node.computed) { - return; - } - checkForBreakAfter(node.object, PROPERTY_MESSAGE); - }, + MemberExpression: function(node) { + if (!node.computed) { + return; + } + checkForBreakAfter(node.object, PROPERTY_MESSAGE); + }, - "TaggedTemplateExpression": function(node) { - if (node.tag.loc.end.line === node.quasi.loc.start.line) { - return; - } - context.report(node, node.loc.start, TAGGED_TEMPLATE_MESSAGE); - }, + TaggedTemplateExpression: function(node) { + if (node.tag.loc.end.line === node.quasi.loc.start.line) { + return; + } + context.report(node, node.loc.start, TAGGED_TEMPLATE_MESSAGE); + }, - "CallExpression": function(node) { - if (node.arguments.length === 0) { - return; + CallExpression: function(node) { + if (node.arguments.length === 0) { + return; + } + checkForBreakAfter(node.callee, FUNCTION_MESSAGE); } - checkForBreakAfter(node.callee, FUNCTION_MESSAGE); - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-unmodified-loop-condition.js b/tools/eslint/lib/rules/no-unmodified-loop-condition.js index 47a0e3885a38e1..ed49b5996ef641 100644 --- a/tools/eslint/lib/rules/no-unmodified-loop-condition.js +++ b/tools/eslint/lib/rules/no-unmodified-loop-condition.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to disallow use of unmodified expressions in loop conditions * @author Toru Nagashima - * @copyright 2015 Toru Nagashima. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; @@ -245,115 +243,125 @@ function updateModifiedFlag(conditions, modifiers) { // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var groupMap = null; - - /** - * Reports a given condition info. - * - * @param {LoopConditionInfo} condition - A loop condition info to report. - * @returns {void} - */ - function report(condition) { - var node = condition.reference.identifier; - - context.report({ - node: node, - message: "'{{name}}' is not modified in this loop.", - data: node - }); - } +module.exports = { + meta: { + docs: { + description: "disallow unmodified loop conditions", + category: "Best Practices", + recommended: false + }, + + schema: [] + }, + + create: function(context) { + var groupMap = null; + + /** + * Reports a given condition info. + * + * @param {LoopConditionInfo} condition - A loop condition info to report. + * @returns {void} + */ + function report(condition) { + var node = condition.reference.identifier; + + context.report({ + node: node, + message: "'{{name}}' is not modified in this loop.", + data: node + }); + } - /** - * Registers given conditions to the group the condition belongs to. - * - * @param {LoopConditionInfo[]} conditions - A loop condition info to - * register. - * @returns {void} - */ - function registerConditionsToGroup(conditions) { - for (var i = 0; i < conditions.length; ++i) { - var condition = conditions[i]; - - if (condition.group) { - var group = groupMap.get(condition.group); - - if (!group) { - group = []; - groupMap.set(condition.group, group); + /** + * Registers given conditions to the group the condition belongs to. + * + * @param {LoopConditionInfo[]} conditions - A loop condition info to + * register. + * @returns {void} + */ + function registerConditionsToGroup(conditions) { + for (var i = 0; i < conditions.length; ++i) { + var condition = conditions[i]; + + if (condition.group) { + var group = groupMap.get(condition.group); + + if (!group) { + group = []; + groupMap.set(condition.group, group); + } + group.push(condition); } - group.push(condition); } } - } - /** - * Reports references which are inside of unmodified groups. - * - * @param {LoopConditionInfo[]} conditions - A loop condition info to report. - * @returns {void} - */ - function checkConditionsInGroup(conditions) { - if (conditions.every(isUnmodified)) { - conditions.forEach(report); + /** + * Reports references which are inside of unmodified groups. + * + * @param {LoopConditionInfo[]} conditions - A loop condition info to report. + * @returns {void} + */ + function checkConditionsInGroup(conditions) { + if (conditions.every(isUnmodified)) { + conditions.forEach(report); + } } - } - /** - * Finds unmodified references which are inside of a loop condition. - * Then reports the references which are outside of groups. - * - * @param {escope.Variable} variable - A variable to report. - * @returns {void} - */ - function checkReferences(variable) { - - // Gets references that exist in loop conditions. - var conditions = variable - .references - .map(toLoopCondition) - .filter(Boolean); - - if (conditions.length === 0) { - return; - } + /** + * Finds unmodified references which are inside of a loop condition. + * Then reports the references which are outside of groups. + * + * @param {escope.Variable} variable - A variable to report. + * @returns {void} + */ + function checkReferences(variable) { + + // Gets references that exist in loop conditions. + var conditions = variable + .references + .map(toLoopCondition) + .filter(Boolean); + + if (conditions.length === 0) { + return; + } - // Registers the conditions to belonging groups. - registerConditionsToGroup(conditions); + // Registers the conditions to belonging groups. + registerConditionsToGroup(conditions); - // Check the conditions are modified. - var modifiers = variable.references.filter(isWriteReference); + // Check the conditions are modified. + var modifiers = variable.references.filter(isWriteReference); - if (modifiers.length > 0) { - updateModifiedFlag(conditions, modifiers); + if (modifiers.length > 0) { + updateModifiedFlag(conditions, modifiers); + } + + /* + * Reports the conditions which are not belonging to groups. + * Others will be reported after all variables are done. + */ + conditions + .filter(isUnmodifiedAndNotBelongToGroup) + .forEach(report); } - /* - * Reports the conditions which are not belonging to groups. - * Others will be reported after all variables are done. - */ - conditions - .filter(isUnmodifiedAndNotBelongToGroup) - .forEach(report); - } + return { + "Program:exit": function() { + var queue = [context.getScope()]; - return { - "Program:exit": function() { - var queue = [context.getScope()]; + groupMap = new Map(); - groupMap = new Map(); + var scope; - var scope; + while ((scope = queue.pop())) { + pushAll(queue, scope.childScopes); + scope.variables.forEach(checkReferences); + } - while ((scope = queue.pop())) { - pushAll(queue, scope.childScopes); - scope.variables.forEach(checkReferences); + groupMap.forEach(checkConditionsInGroup); + groupMap = null; } - - groupMap.forEach(checkConditionsInGroup); - groupMap = null; - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-unneeded-ternary.js b/tools/eslint/lib/rules/no-unneeded-ternary.js index fcbff265f91db0..1c344a42e615ea 100644 --- a/tools/eslint/lib/rules/no-unneeded-ternary.js +++ b/tools/eslint/lib/rules/no-unneeded-ternary.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to flag no-unneeded-ternary * @author Gyandeep Singh - * @copyright 2015 Gyandeep Singh. All rights reserved. - * @copyright 2015 Michael Ficarra. All rights reserved. */ "use strict"; @@ -11,52 +9,62 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var options = context.options[0] || {}; - var defaultAssignment = options.defaultAssignment !== false; - - /** - * Test if the node is a boolean literal - * @param {ASTNode} node - The node to report. - * @returns {boolean} True if the its a boolean literal - * @private - */ - function isBooleanLiteral(node) { - return node.type === "Literal" && typeof node.value === "boolean"; - } +module.exports = { + meta: { + docs: { + description: "disallow ternary operators when simpler alternatives exist", + category: "Stylistic Issues", + recommended: false + }, - /** - * Test if the node matches the pattern id ? id : expression - * @param {ASTNode} node - The ConditionalExpression to check. - * @returns {boolean} True if the pattern is matched, and false otherwise - * @private - */ - function matchesDefaultAssignment(node) { - return node.test.type === "Identifier" && - node.consequent.type === "Identifier" && - node.test.name === node.consequent.name; - } + schema: [ + { + type: "object", + properties: { + defaultAssignment: { + type: "boolean" + } + }, + additionalProperties: false + } + ] + }, - return { + create: function(context) { + var options = context.options[0] || {}; + var defaultAssignment = options.defaultAssignment !== false; - "ConditionalExpression": function(node) { - if (isBooleanLiteral(node.alternate) && isBooleanLiteral(node.consequent)) { - context.report(node, node.consequent.loc.start, "Unnecessary use of boolean literals in conditional expression"); - } else if (!defaultAssignment && matchesDefaultAssignment(node)) { - context.report(node, node.consequent.loc.start, "Unnecessary use of conditional expression for default assignment"); - } + /** + * Test if the node is a boolean literal + * @param {ASTNode} node - The node to report. + * @returns {boolean} True if the its a boolean literal + * @private + */ + function isBooleanLiteral(node) { + return node.type === "Literal" && typeof node.value === "boolean"; } - }; -}; -module.exports.schema = [ - { - "type": "object", - "properties": { - "defaultAssignment": { - "type": "boolean" + /** + * Test if the node matches the pattern id ? id : expression + * @param {ASTNode} node - The ConditionalExpression to check. + * @returns {boolean} True if the pattern is matched, and false otherwise + * @private + */ + function matchesDefaultAssignment(node) { + return node.test.type === "Identifier" && + node.consequent.type === "Identifier" && + node.test.name === node.consequent.name; + } + + return { + + ConditionalExpression: function(node) { + if (isBooleanLiteral(node.alternate) && isBooleanLiteral(node.consequent)) { + context.report(node, node.consequent.loc.start, "Unnecessary use of boolean literals in conditional expression"); + } else if (!defaultAssignment && matchesDefaultAssignment(node)) { + context.report(node, node.consequent.loc.start, "Unnecessary use of conditional expression for default assignment"); + } } - }, - "additionalProperties": false + }; } -]; +}; diff --git a/tools/eslint/lib/rules/no-unreachable.js b/tools/eslint/lib/rules/no-unreachable.js index ce3f4ba01fb265..c28a6d2f2fa787 100644 --- a/tools/eslint/lib/rules/no-unreachable.js +++ b/tools/eslint/lib/rules/no-unreachable.js @@ -1,8 +1,6 @@ /** * @fileoverview Checks for unreachable code due to return, throws, break, and continue. * @author Joel Feenstra - * @copyright 2015 Toru Nagashima. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; @@ -32,63 +30,73 @@ function isUnreachable(segment) { // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var currentCodePath = null; +module.exports = { + meta: { + docs: { + description: "disallow unreachable code after `return`, `throw`, `continue`, and `break` statements", + category: "Possible Errors", + recommended: true + }, + + schema: [] + }, + + create: function(context) { + var currentCodePath = null; - /** - * Reports a given node if it's unreachable. - * @param {ASTNode} node - A statement node to report. - * @returns {void} - */ - function reportIfUnreachable(node) { - if (currentCodePath.currentSegments.every(isUnreachable)) { - context.report({message: "Unreachable code.", node: node}); + /** + * Reports a given node if it's unreachable. + * @param {ASTNode} node - A statement node to report. + * @returns {void} + */ + function reportIfUnreachable(node) { + if (currentCodePath.currentSegments.every(isUnreachable)) { + context.report({message: "Unreachable code.", node: node}); + } } - } - return { + return { - // Manages the current code path. - "onCodePathStart": function(codePath) { - currentCodePath = codePath; - }, + // Manages the current code path. + onCodePathStart: function(codePath) { + currentCodePath = codePath; + }, - "onCodePathEnd": function() { - currentCodePath = currentCodePath.upper; - }, + onCodePathEnd: function() { + currentCodePath = currentCodePath.upper; + }, - // Registers for all statement nodes (excludes FunctionDeclaration). - BlockStatement: reportIfUnreachable, - BreakStatement: reportIfUnreachable, - ClassDeclaration: reportIfUnreachable, - ContinueStatement: reportIfUnreachable, - DebuggerStatement: reportIfUnreachable, - DoWhileStatement: reportIfUnreachable, - EmptyStatement: reportIfUnreachable, - ExpressionStatement: reportIfUnreachable, - ForInStatement: reportIfUnreachable, - ForOfStatement: reportIfUnreachable, - ForStatement: reportIfUnreachable, - IfStatement: reportIfUnreachable, - ImportDeclaration: reportIfUnreachable, - LabeledStatement: reportIfUnreachable, - ReturnStatement: reportIfUnreachable, - SwitchStatement: reportIfUnreachable, - ThrowStatement: reportIfUnreachable, - TryStatement: reportIfUnreachable, + // Registers for all statement nodes (excludes FunctionDeclaration). + BlockStatement: reportIfUnreachable, + BreakStatement: reportIfUnreachable, + ClassDeclaration: reportIfUnreachable, + ContinueStatement: reportIfUnreachable, + DebuggerStatement: reportIfUnreachable, + DoWhileStatement: reportIfUnreachable, + EmptyStatement: reportIfUnreachable, + ExpressionStatement: reportIfUnreachable, + ForInStatement: reportIfUnreachable, + ForOfStatement: reportIfUnreachable, + ForStatement: reportIfUnreachable, + IfStatement: reportIfUnreachable, + ImportDeclaration: reportIfUnreachable, + LabeledStatement: reportIfUnreachable, + ReturnStatement: reportIfUnreachable, + SwitchStatement: reportIfUnreachable, + ThrowStatement: reportIfUnreachable, + TryStatement: reportIfUnreachable, - VariableDeclaration: function(node) { - if (node.kind !== "var" || node.declarations.some(isInitialized)) { - reportIfUnreachable(node); - } - }, + VariableDeclaration: function(node) { + if (node.kind !== "var" || node.declarations.some(isInitialized)) { + reportIfUnreachable(node); + } + }, - WhileStatement: reportIfUnreachable, - WithStatement: reportIfUnreachable, - ExportNamedDeclaration: reportIfUnreachable, - ExportDefaultDeclaration: reportIfUnreachable, - ExportAllDeclaration: reportIfUnreachable - }; + WhileStatement: reportIfUnreachable, + WithStatement: reportIfUnreachable, + ExportNamedDeclaration: reportIfUnreachable, + ExportDefaultDeclaration: reportIfUnreachable, + ExportAllDeclaration: reportIfUnreachable + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-unsafe-finally.js b/tools/eslint/lib/rules/no-unsafe-finally.js new file mode 100644 index 00000000000000..55ea2971f88ebf --- /dev/null +++ b/tools/eslint/lib/rules/no-unsafe-finally.js @@ -0,0 +1,78 @@ +/** + * @fileoverview Rule to flag unsafe statements in finally block + * @author Onur Temizkan + */ + +"use strict"; + +//------------------------------------------------------------------------------ +// Helpers +//------------------------------------------------------------------------------ + +var SENTINEL_NODE_TYPE = /^(?:Program|(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression)$/; + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = { + meta: { + docs: { + description: "disallow control flow statements in finally blocks", + category: "Possible Errors", + recommended: false + } + }, + create: function(context) { + + /** + * Checks if the node is the finalizer of a TryStatement + * + * @param {ASTNode} node - node to check. + * @returns {Boolean} - true if the node is the finalizer of a TryStatement + */ + function isFinallyBlock(node) { + return node.parent.type === "TryStatement" && node.parent.finalizer === node; + } + + /** + * Climbs up the tree if the node is not a sentinel node + * + * @param {ASTNode} node - node to check. + * @returns {Boolean} - return whether the node is a finally block or a sentinel node + */ + function isInFinallyBlock(node) { + while (node && !SENTINEL_NODE_TYPE.test(node.type)) { + if (isFinallyBlock(node)) { + return true; + } + node = node.parent; + } + return false; + } + + /** + * Checks whether the possibly-unsafe statement is inside a finally block. + * + * @param {ASTNode} node - node to check. + * @returns {void} + */ + function check(node) { + if (isInFinallyBlock(node)) { + context.report({ + message: "Unsafe usage of " + node.type, + node: node, + line: node.loc.line, + column: node.loc.column + }); + } + } + + return { + ReturnStatement: check, + ThrowStatement: check, + BreakStatement: check, + ContinueStatement: check + }; + } +}; diff --git a/tools/eslint/lib/rules/no-unused-expressions.js b/tools/eslint/lib/rules/no-unused-expressions.js index 3da55602f02b7e..9438268ab24c33 100644 --- a/tools/eslint/lib/rules/no-unused-expressions.js +++ b/tools/eslint/lib/rules/no-unused-expressions.js @@ -1,7 +1,6 @@ /** * @fileoverview Flag expressions in statement position that do not side effect * @author Michael Ficarra - * @copyright 2013 Michael Ficarra. All rights reserved. */ "use strict"; @@ -9,100 +8,110 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var config = context.options[0] || {}, - allowShortCircuit = config.allowShortCircuit || false, - allowTernary = config.allowTernary || false; +module.exports = { + meta: { + docs: { + description: "disallow unused expressions", + category: "Best Practices", + recommended: false + }, - /** - * @param {ASTNode} node - any node - * @returns {boolean} whether the given node structurally represents a directive - */ - function looksLikeDirective(node) { - return node.type === "ExpressionStatement" && - node.expression.type === "Literal" && typeof node.expression.value === "string"; - } + schema: [ + { + type: "object", + properties: { + allowShortCircuit: { + type: "boolean" + }, + allowTernary: { + type: "boolean" + } + }, + additionalProperties: false + } + ] + }, + + create: function(context) { + var config = context.options[0] || {}, + allowShortCircuit = config.allowShortCircuit || false, + allowTernary = config.allowTernary || false; + + /** + * @param {ASTNode} node - any node + * @returns {boolean} whether the given node structurally represents a directive + */ + function looksLikeDirective(node) { + return node.type === "ExpressionStatement" && + node.expression.type === "Literal" && typeof node.expression.value === "string"; + } - /** - * @param {Function} predicate - ([a] -> Boolean) the function used to make the determination - * @param {a[]} list - the input list - * @returns {a[]} the leading sequence of members in the given list that pass the given predicate - */ - function takeWhile(predicate, list) { - for (var i = 0, l = list.length; i < l; ++i) { - if (!predicate(list[i])) { - break; + /** + * @param {Function} predicate - ([a] -> Boolean) the function used to make the determination + * @param {a[]} list - the input list + * @returns {a[]} the leading sequence of members in the given list that pass the given predicate + */ + function takeWhile(predicate, list) { + for (var i = 0, l = list.length; i < l; ++i) { + if (!predicate(list[i])) { + break; + } } + return [].slice.call(list, 0, i); } - return [].slice.call(list, 0, i); - } - /** - * @param {ASTNode} node - a Program or BlockStatement node - * @returns {ASTNode[]} the leading sequence of directive nodes in the given node's body - */ - function directives(node) { - return takeWhile(looksLikeDirective, node.body); - } + /** + * @param {ASTNode} node - a Program or BlockStatement node + * @returns {ASTNode[]} the leading sequence of directive nodes in the given node's body + */ + function directives(node) { + return takeWhile(looksLikeDirective, node.body); + } - /** - * @param {ASTNode} node - any node - * @param {ASTNode[]} ancestors - the given node's ancestors - * @returns {boolean} whether the given node is considered a directive in its current position - */ - function isDirective(node, ancestors) { - var parent = ancestors[ancestors.length - 1], - grandparent = ancestors[ancestors.length - 2]; + /** + * @param {ASTNode} node - any node + * @param {ASTNode[]} ancestors - the given node's ancestors + * @returns {boolean} whether the given node is considered a directive in its current position + */ + function isDirective(node, ancestors) { + var parent = ancestors[ancestors.length - 1], + grandparent = ancestors[ancestors.length - 2]; - return (parent.type === "Program" || parent.type === "BlockStatement" && - (/Function/.test(grandparent.type))) && - directives(parent).indexOf(node) >= 0; - } + return (parent.type === "Program" || parent.type === "BlockStatement" && + (/Function/.test(grandparent.type))) && + directives(parent).indexOf(node) >= 0; + } - /** - * Determines whether or not a given node is a valid expression. Recurses on short circuit eval and ternary nodes if enabled by flags. - * @param {ASTNode} node - any node - * @returns {boolean} whether the given node is a valid expression - */ - function isValidExpression(node) { - if (allowTernary) { + /** + * Determines whether or not a given node is a valid expression. Recurses on short circuit eval and ternary nodes if enabled by flags. + * @param {ASTNode} node - any node + * @returns {boolean} whether the given node is a valid expression + */ + function isValidExpression(node) { + if (allowTernary) { - // Recursive check for ternary and logical expressions - if (node.type === "ConditionalExpression") { - return isValidExpression(node.consequent) && isValidExpression(node.alternate); + // Recursive check for ternary and logical expressions + if (node.type === "ConditionalExpression") { + return isValidExpression(node.consequent) && isValidExpression(node.alternate); + } } - } - if (allowShortCircuit) { - if (node.type === "LogicalExpression") { - return isValidExpression(node.right); + if (allowShortCircuit) { + if (node.type === "LogicalExpression") { + return isValidExpression(node.right); + } } - } - return /^(?:Assignment|Call|New|Update|Yield)Expression$/.test(node.type) || - (node.type === "UnaryExpression" && ["delete", "void"].indexOf(node.operator) >= 0); - } - - return { - "ExpressionStatement": function(node) { - if (!isValidExpression(node.expression) && !isDirective(node, context.getAncestors())) { - context.report(node, "Expected an assignment or function call and instead saw an expression."); - } + return /^(?:Assignment|Call|New|Update|Yield)Expression$/.test(node.type) || + (node.type === "UnaryExpression" && ["delete", "void"].indexOf(node.operator) >= 0); } - }; -}; - -module.exports.schema = [ - { - "type": "object", - "properties": { - "allowShortCircuit": { - "type": "boolean" - }, - "allowTernary": { - "type": "boolean" + return { + ExpressionStatement: function(node) { + if (!isValidExpression(node.expression) && !isDirective(node, context.getAncestors())) { + context.report(node, "Expected an assignment or function call and instead saw an expression."); + } } - }, - "additionalProperties": false + }; + } -]; +}; diff --git a/tools/eslint/lib/rules/no-unused-labels.js b/tools/eslint/lib/rules/no-unused-labels.js index e53b333f2e79b3..77713fc408bca4 100644 --- a/tools/eslint/lib/rules/no-unused-labels.js +++ b/tools/eslint/lib/rules/no-unused-labels.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to disallow unused labels. * @author Toru Nagashima - * @copyright 2016 Toru Nagashima. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; @@ -11,72 +9,82 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var scopeInfo = null; +module.exports = { + meta: { + docs: { + description: "disallow unused labels", + category: "Best Practices", + recommended: true + }, - /** - * Adds a scope info to the stack. - * - * @param {ASTNode} node - A node to add. This is a LabeledStatement. - * @returns {void} - */ - function enterLabeledScope(node) { - scopeInfo = { - label: node.label.name, - used: false, - upper: scopeInfo - }; - } + schema: [] + }, + + create: function(context) { + var scopeInfo = null; - /** - * Removes the top of the stack. - * At the same time, this reports the label if it's never used. - * - * @param {ASTNode} node - A node to report. This is a LabeledStatement. - * @returns {void} - */ - function exitLabeledScope(node) { - if (!scopeInfo.used) { - context.report({ - node: node.label, - message: "'{{name}}:' is defined but never used.", - data: node.label - }); + /** + * Adds a scope info to the stack. + * + * @param {ASTNode} node - A node to add. This is a LabeledStatement. + * @returns {void} + */ + function enterLabeledScope(node) { + scopeInfo = { + label: node.label.name, + used: false, + upper: scopeInfo + }; } - scopeInfo = scopeInfo.upper; - } + /** + * Removes the top of the stack. + * At the same time, this reports the label if it's never used. + * + * @param {ASTNode} node - A node to report. This is a LabeledStatement. + * @returns {void} + */ + function exitLabeledScope(node) { + if (!scopeInfo.used) { + context.report({ + node: node.label, + message: "'{{name}}:' is defined but never used.", + data: node.label + }); + } - /** - * Marks the label of a given node as used. - * - * @param {ASTNode} node - A node to mark. This is a BreakStatement or - * ContinueStatement. - * @returns {void} - */ - function markAsUsed(node) { - if (!node.label) { - return; + scopeInfo = scopeInfo.upper; } - var label = node.label.name; - var info = scopeInfo; + /** + * Marks the label of a given node as used. + * + * @param {ASTNode} node - A node to mark. This is a BreakStatement or + * ContinueStatement. + * @returns {void} + */ + function markAsUsed(node) { + if (!node.label) { + return; + } - while (info) { - if (info.label === label) { - info.used = true; - break; + var label = node.label.name; + var info = scopeInfo; + + while (info) { + if (info.label === label) { + info.used = true; + break; + } + info = info.upper; } - info = info.upper; } - } - return { - "LabeledStatement": enterLabeledScope, - "LabeledStatement:exit": exitLabeledScope, - "BreakStatement": markAsUsed, - "ContinueStatement": markAsUsed - }; + return { + LabeledStatement: enterLabeledScope, + "LabeledStatement:exit": exitLabeledScope, + BreakStatement: markAsUsed, + ContinueStatement: markAsUsed + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-unused-vars.js b/tools/eslint/lib/rules/no-unused-vars.js index fa889d1975164e..89d43c7bfd681b 100644 --- a/tools/eslint/lib/rules/no-unused-vars.js +++ b/tools/eslint/lib/rules/no-unused-vars.js @@ -15,318 +15,328 @@ var lodash = require("lodash"); // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow unused variables", + category: "Variables", + recommended: true + }, + + schema: [ + { + oneOf: [ + { + enum: ["all", "local"] + }, + { + type: "object", + properties: { + vars: { + enum: ["all", "local"] + }, + varsIgnorePattern: { + type: "string" + }, + args: { + enum: ["all", "after-used", "none"] + }, + argsIgnorePattern: { + type: "string" + }, + caughtErrors: { + enum: ["all", "none"] + }, + caughtErrorsIgnorePattern: { + type: "string" + } + } + } + ] + } + ] + }, - var MESSAGE = "'{{name}}' is defined but never used"; + create: function(context) { - var config = { - vars: "all", - args: "after-used", - caughtErrors: "none" - }; + var MESSAGE = "'{{name}}' is defined but never used"; - var firstOption = context.options[0]; + var config = { + vars: "all", + args: "after-used", + caughtErrors: "none" + }; - if (firstOption) { - if (typeof firstOption === "string") { - config.vars = firstOption; - } else { - config.vars = firstOption.vars || config.vars; - config.args = firstOption.args || config.args; - config.caughtErrors = firstOption.caughtErrors || config.caughtErrors; + var firstOption = context.options[0]; - if (firstOption.varsIgnorePattern) { - config.varsIgnorePattern = new RegExp(firstOption.varsIgnorePattern); - } + if (firstOption) { + if (typeof firstOption === "string") { + config.vars = firstOption; + } else { + config.vars = firstOption.vars || config.vars; + config.args = firstOption.args || config.args; + config.caughtErrors = firstOption.caughtErrors || config.caughtErrors; - if (firstOption.argsIgnorePattern) { - config.argsIgnorePattern = new RegExp(firstOption.argsIgnorePattern); - } + if (firstOption.varsIgnorePattern) { + config.varsIgnorePattern = new RegExp(firstOption.varsIgnorePattern); + } + + if (firstOption.argsIgnorePattern) { + config.argsIgnorePattern = new RegExp(firstOption.argsIgnorePattern); + } - if (firstOption.caughtErrorsIgnorePattern) { - config.caughtErrorsIgnorePattern = new RegExp(firstOption.caughtErrorsIgnorePattern); + if (firstOption.caughtErrorsIgnorePattern) { + config.caughtErrorsIgnorePattern = new RegExp(firstOption.caughtErrorsIgnorePattern); + } } } - } - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- + + /** + * Determines if a given variable is being exported from a module. + * @param {Variable} variable - EScope variable object. + * @returns {boolean} True if the variable is exported, false if not. + * @private + */ + function isExported(variable) { - /** - * Determines if a given variable is being exported from a module. - * @param {Variable} variable - EScope variable object. - * @returns {boolean} True if the variable is exported, false if not. - * @private - */ - function isExported(variable) { + var definition = variable.defs[0]; - var definition = variable.defs[0]; + if (definition) { - if (definition) { + var node = definition.node; - var node = definition.node; + if (node.type === "VariableDeclarator") { + node = node.parent; + } else if (definition.type === "Parameter") { + return false; + } - if (node.type === "VariableDeclarator") { - node = node.parent; - } else if (definition.type === "Parameter") { + return node.parent.type.indexOf("Export") === 0; + } else { return false; } - - return node.parent.type.indexOf("Export") === 0; - } else { - return false; } - } - /** - * Determines if a reference is a read operation. - * @param {Reference} ref - An escope Reference - * @returns {Boolean} whether the given reference represents a read operation - * @private - */ - function isReadRef(ref) { - return ref.isRead(); - } - - /** - * Determine if an identifier is referencing an enclosing function name. - * @param {Reference} ref - The reference to check. - * @param {ASTNode[]} nodes - The candidate function nodes. - * @returns {boolean} True if it's a self-reference, false if not. - * @private - */ - function isSelfReference(ref, nodes) { - var scope = ref.from; - - while (scope) { - if (nodes.indexOf(scope.block) >= 0) { - return true; - } - - scope = scope.upper; + /** + * Determines if a reference is a read operation. + * @param {Reference} ref - An escope Reference + * @returns {Boolean} whether the given reference represents a read operation + * @private + */ + function isReadRef(ref) { + return ref.isRead(); } - return false; - } - - /** - * Determines if the variable is used. - * @param {Variable} variable - The variable to check. - * @param {Reference[]} references - The variable references to check. - * @returns {boolean} True if the variable is used - */ - function isUsedVariable(variable) { - var functionNodes = variable.defs.filter(function(def) { - return def.type === "FunctionName"; - }).map(function(def) { - return def.node; - }), - isFunctionDefinition = functionNodes.length > 0; - - return variable.references.some(function(ref) { - return isReadRef(ref) && !(isFunctionDefinition && isSelfReference(ref, functionNodes)); - }); - } - - /** - * Gets an array of variables without read references. - * @param {Scope} scope - an escope Scope object. - * @param {Variable[]} unusedVars - an array that saving result. - * @returns {Variable[]} unused variables of the scope and descendant scopes. - * @private - */ - function collectUnusedVariables(scope, unusedVars) { - var variables = scope.variables; - var childScopes = scope.childScopes; - var i, l; - - if (scope.type !== "TDZ" && (scope.type !== "global" || config.vars === "all")) { - for (i = 0, l = variables.length; i < l; ++i) { - var variable = variables[i]; - - // skip a variable of class itself name in the class scope - if (scope.type === "class" && scope.block.id === variable.identifiers[0]) { - continue; + /** + * Determine if an identifier is referencing an enclosing function name. + * @param {Reference} ref - The reference to check. + * @param {ASTNode[]} nodes - The candidate function nodes. + * @returns {boolean} True if it's a self-reference, false if not. + * @private + */ + function isSelfReference(ref, nodes) { + var scope = ref.from; + + while (scope) { + if (nodes.indexOf(scope.block) >= 0) { + return true; } - // skip function expression names and variables marked with markVariableAsUsed() - if (scope.functionExpressionScope || variable.eslintUsed) { - continue; - } + scope = scope.upper; + } - // skip implicit "arguments" variable - if (scope.type === "function" && variable.name === "arguments" && variable.identifiers.length === 0) { - continue; - } + return false; + } - // explicit global variables don't have definitions. - var def = variable.defs[0]; + /** + * Determines if the variable is used. + * @param {Variable} variable - The variable to check. + * @param {Reference[]} references - The variable references to check. + * @returns {boolean} True if the variable is used + */ + function isUsedVariable(variable) { + var functionNodes = variable.defs.filter(function(def) { + return def.type === "FunctionName"; + }).map(function(def) { + return def.node; + }), + isFunctionDefinition = functionNodes.length > 0; + + return variable.references.some(function(ref) { + return isReadRef(ref) && !(isFunctionDefinition && isSelfReference(ref, functionNodes)); + }); + } - if (def) { - var type = def.type; + /** + * Gets an array of variables without read references. + * @param {Scope} scope - an escope Scope object. + * @param {Variable[]} unusedVars - an array that saving result. + * @returns {Variable[]} unused variables of the scope and descendant scopes. + * @private + */ + function collectUnusedVariables(scope, unusedVars) { + var variables = scope.variables; + var childScopes = scope.childScopes; + var i, l; + + if (scope.type !== "TDZ" && (scope.type !== "global" || config.vars === "all")) { + for (i = 0, l = variables.length; i < l; ++i) { + var variable = variables[i]; + + // skip a variable of class itself name in the class scope + if (scope.type === "class" && scope.block.id === variable.identifiers[0]) { + continue; + } - // skip catch variables - if (type === "CatchClause") { - if (config.caughtErrors === "none") { - continue; - } + // skip function expression names and variables marked with markVariableAsUsed() + if (scope.functionExpressionScope || variable.eslintUsed) { + continue; + } - // skip ignored parameters - if (config.caughtErrorsIgnorePattern && config.caughtErrorsIgnorePattern.test(def.name.name)) { - continue; - } + // skip implicit "arguments" variable + if (scope.type === "function" && variable.name === "arguments" && variable.identifiers.length === 0) { + continue; } - if (type === "Parameter") { + // explicit global variables don't have definitions. + var def = variable.defs[0]; - // skip any setter argument - if (def.node.parent.type === "Property" && def.node.parent.kind === "set") { - continue; - } + if (def) { + var type = def.type; - // if "args" option is "none", skip any parameter - if (config.args === "none") { - continue; - } + // skip catch variables + if (type === "CatchClause") { + if (config.caughtErrors === "none") { + continue; + } - // skip ignored parameters - if (config.argsIgnorePattern && config.argsIgnorePattern.test(def.name.name)) { - continue; + // skip ignored parameters + if (config.caughtErrorsIgnorePattern && config.caughtErrorsIgnorePattern.test(def.name.name)) { + continue; + } } - // if "args" option is "after-used", skip all but the last parameter - if (config.args === "after-used" && def.index < def.node.params.length - 1) { - continue; + if (type === "Parameter") { + + // skip any setter argument + if (def.node.parent.type === "Property" && def.node.parent.kind === "set") { + continue; + } + + // if "args" option is "none", skip any parameter + if (config.args === "none") { + continue; + } + + // skip ignored parameters + if (config.argsIgnorePattern && config.argsIgnorePattern.test(def.name.name)) { + continue; + } + + // if "args" option is "after-used", skip all but the last parameter + if (config.args === "after-used" && def.index < def.node.params.length - 1) { + continue; + } + } else { + + // skip ignored variables + if (config.varsIgnorePattern && config.varsIgnorePattern.test(def.name.name)) { + continue; + } } - } else { + } - // skip ignored variables - if (config.varsIgnorePattern && config.varsIgnorePattern.test(def.name.name)) { - continue; - } + if (!isUsedVariable(variable) && !isExported(variable)) { + unusedVars.push(variable); } } + } - if (!isUsedVariable(variable) && !isExported(variable)) { - unusedVars.push(variable); - } + for (i = 0, l = childScopes.length; i < l; ++i) { + collectUnusedVariables(childScopes[i], unusedVars); } - } - for (i = 0, l = childScopes.length; i < l; ++i) { - collectUnusedVariables(childScopes[i], unusedVars); + return unusedVars; } - return unusedVars; - } - - /** - * Gets the index of a given variable name in a given comment. - * @param {escope.Variable} variable - A variable to get. - * @param {ASTNode} comment - A comment node which includes the variable name. - * @returns {number} The index of the variable name's location. - */ - function getColumnInComment(variable, comment) { - var namePattern = new RegExp("[\\s,]" + lodash.escapeRegExp(variable.name) + "(?:$|[\\s,:])", "g"); - - // To ignore the first text "global". - namePattern.lastIndex = comment.value.indexOf("global") + 6; + /** + * Gets the index of a given variable name in a given comment. + * @param {escope.Variable} variable - A variable to get. + * @param {ASTNode} comment - A comment node which includes the variable name. + * @returns {number} The index of the variable name's location. + */ + function getColumnInComment(variable, comment) { + var namePattern = new RegExp("[\\s,]" + lodash.escapeRegExp(variable.name) + "(?:$|[\\s,:])", "g"); - // Search a given variable name. - var match = namePattern.exec(comment.value); + // To ignore the first text "global". + namePattern.lastIndex = comment.value.indexOf("global") + 6; - return match ? match.index + 1 : 0; - } + // Search a given variable name. + var match = namePattern.exec(comment.value); - /** - * Creates the correct location of a given variables. - * The location is at its name string in a `/*global` comment. - * - * @param {escope.Variable} variable - A variable to get its location. - * @returns {{line: number, column: number}} The location object for the variable. - */ - function getLocation(variable) { - var comment = variable.eslintExplicitGlobalComment; - var baseLoc = comment.loc.start; - var column = getColumnInComment(variable, comment); - var prefix = comment.value.slice(0, column); - var lineInComment = (prefix.match(/\n/g) || []).length; - - if (lineInComment > 0) { - column -= 1 + prefix.lastIndexOf("\n"); - } else { - - // 2 is for `/*` - column += baseLoc.column + 2; + return match ? match.index + 1 : 0; } - return { - line: baseLoc.line + lineInComment, - column: column - }; - } - - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- - - return { - "Program:exit": function(programNode) { - var unusedVars = collectUnusedVariables(context.getScope(), []); - - for (var i = 0, l = unusedVars.length; i < l; ++i) { - var unusedVar = unusedVars[i]; - - if (unusedVar.eslintExplicitGlobal) { - context.report({ - node: programNode, - loc: getLocation(unusedVar), - message: MESSAGE, - data: unusedVar - }); - } else if (unusedVar.defs.length > 0) { - context.report({ - node: unusedVar.identifiers[0], - message: MESSAGE, - data: unusedVar - }); - } + /** + * Creates the correct location of a given variables. + * The location is at its name string in a `/*global` comment. + * + * @param {escope.Variable} variable - A variable to get its location. + * @returns {{line: number, column: number}} The location object for the variable. + */ + function getLocation(variable) { + var comment = variable.eslintExplicitGlobalComment; + var baseLoc = comment.loc.start; + var column = getColumnInComment(variable, comment); + var prefix = comment.value.slice(0, column); + var 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: column + }; } - }; -}; + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- -module.exports.schema = [ - { - "oneOf": [ - { - "enum": ["all", "local"] - }, - { - "type": "object", - "properties": { - "vars": { - "enum": ["all", "local"] - }, - "varsIgnorePattern": { - "type": "string" - }, - "args": { - "enum": ["all", "after-used", "none"] - }, - "argsIgnorePattern": { - "type": "string" - }, - "caughtErrors": { - "enum": ["all", "none"] - }, - "caughtErrorsIgnorePattern": { - "type": "string" + return { + "Program:exit": function(programNode) { + var unusedVars = collectUnusedVariables(context.getScope(), []); + + for (var i = 0, l = unusedVars.length; i < l; ++i) { + var unusedVar = unusedVars[i]; + + if (unusedVar.eslintExplicitGlobal) { + context.report({ + node: programNode, + loc: getLocation(unusedVar), + message: MESSAGE, + data: unusedVar + }); + } else if (unusedVar.defs.length > 0) { + context.report({ + node: unusedVar.identifiers[0], + message: MESSAGE, + data: unusedVar + }); } } } - ] + }; + } -]; +}; diff --git a/tools/eslint/lib/rules/no-use-before-define.js b/tools/eslint/lib/rules/no-use-before-define.js index b8f67144c579f0..889e709948259c 100644 --- a/tools/eslint/lib/rules/no-use-before-define.js +++ b/tools/eslint/lib/rules/no-use-before-define.js @@ -1,7 +1,6 @@ /** * @fileoverview Rule to flag use of variables before they are defined * @author Ilya Volodin - * @copyright 2013 Ilya Volodin. All rights reserved. */ "use strict"; @@ -124,114 +123,124 @@ function isInInitializer(variable, reference) { // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var options = parseOptions(context.options[0]); +module.exports = { + meta: { + docs: { + description: "disallow the use of variables before they are defined", + category: "Variables", + recommended: false + }, - // Defines a function which checks whether or not a reference is allowed according to the option. - var isAllowed; - - if (options.functions && options.classes) { - isAllowed = alwaysFalse; - } else if (options.functions) { - isAllowed = isOuterClass; - } else if (options.classes) { - isAllowed = isFunction; - } else { - isAllowed = isFunctionOrOuterClass; - } - - /** - * Finds and validates all variables in a given scope. - * @param {Scope} scope The scope object. - * @returns {void} - * @private - */ - function findVariablesInScope(scope) { - scope.references.forEach(function(reference) { - var variable = reference.resolved; - - // Skips when the reference is: - // - initialization's. - // - referring to an undefined variable. - // - referring to a global environment variable (there're no identifiers). - // - located preceded by the variable (except in initializers). - // - allowed by options. - if (reference.init || - !variable || - variable.identifiers.length === 0 || - (variable.identifiers[0].range[1] < reference.identifier.range[1] && !isInInitializer(variable, reference)) || - isAllowed(variable, reference) - ) { - return; + schema: [ + { + oneOf: [ + { + enum: ["nofunc"] + }, + { + type: "object", + properties: { + functions: {type: "boolean"}, + classes: {type: "boolean"} + }, + additionalProperties: false + } + ] } + ] + }, + + create: function(context) { + var options = parseOptions(context.options[0]); + + // Defines a function which checks whether or not a reference is allowed according to the option. + var isAllowed; + + if (options.functions && options.classes) { + isAllowed = alwaysFalse; + } else if (options.functions) { + isAllowed = isOuterClass; + } else if (options.classes) { + isAllowed = isFunction; + } else { + isAllowed = isFunctionOrOuterClass; + } - // Reports. - context.report({ - node: reference.identifier, - message: "'{{name}}' was used before it was defined", - data: reference.identifier + /** + * Finds and validates all variables in a given scope. + * @param {Scope} scope The scope object. + * @returns {void} + * @private + */ + function findVariablesInScope(scope) { + scope.references.forEach(function(reference) { + var variable = reference.resolved; + + // Skips when the reference is: + // - initialization's. + // - referring to an undefined variable. + // - referring to a global environment variable (there're no identifiers). + // - located preceded by the variable (except in initializers). + // - allowed by options. + if (reference.init || + !variable || + variable.identifiers.length === 0 || + (variable.identifiers[0].range[1] < reference.identifier.range[1] && !isInInitializer(variable, reference)) || + isAllowed(variable, reference) + ) { + return; + } + + // Reports. + context.report({ + node: reference.identifier, + message: "'{{name}}' was used before it was defined", + data: reference.identifier + }); }); - }); - } - - /** - * Validates variables inside of a node's scope. - * @param {ASTNode} node The node to check. - * @returns {void} - * @private - */ - function findVariables() { - var scope = context.getScope(); - - findVariablesInScope(scope); - } + } - var ruleDefinition = { - "Program:exit": function(node) { - var scope = context.getScope(), - ecmaFeatures = context.parserOptions.ecmaFeatures || {}; + /** + * Validates variables inside of a node's scope. + * @param {ASTNode} node The node to check. + * @returns {void} + * @private + */ + function findVariables() { + var scope = context.getScope(); findVariablesInScope(scope); - - // both Node.js and Modules have an extra scope - if (ecmaFeatures.globalReturn || node.sourceType === "module") { - findVariablesInScope(scope.childScopes[0]); - } } - }; - if (context.parserOptions.ecmaVersion >= 6) { - ruleDefinition["BlockStatement:exit"] = - ruleDefinition["SwitchStatement:exit"] = findVariables; + var ruleDefinition = { + "Program:exit": function(node) { + var scope = context.getScope(), + ecmaFeatures = context.parserOptions.ecmaFeatures || {}; + + findVariablesInScope(scope); - ruleDefinition["ArrowFunctionExpression:exit"] = function(node) { - if (node.body.type !== "BlockStatement") { - findVariables(node); + // both Node.js and Modules have an extra scope + if (ecmaFeatures.globalReturn || node.sourceType === "module") { + findVariablesInScope(scope.childScopes[0]); + } } }; - } else { - ruleDefinition["FunctionExpression:exit"] = - ruleDefinition["FunctionDeclaration:exit"] = - ruleDefinition["ArrowFunctionExpression:exit"] = findVariables; - } - return ruleDefinition; -}; + if (context.parserOptions.ecmaVersion >= 6) { + ruleDefinition["BlockStatement:exit"] = + ruleDefinition["SwitchStatement:exit"] = findVariables; + + ruleDefinition["ArrowFunctionExpression:exit"] = function(node) { + if (node.body.type !== "BlockStatement") { + findVariables(node); + } + }; + } else { + ruleDefinition["FunctionExpression:exit"] = + ruleDefinition["FunctionDeclaration:exit"] = + ruleDefinition["ArrowFunctionExpression:exit"] = findVariables; + } -module.exports.schema = [ - { - "oneOf": [ - { - "enum": ["nofunc"] - }, - { - "type": "object", - "properties": { - "functions": {"type": "boolean"}, - "classes": {"type": "boolean"} - }, - "additionalProperties": false - } - ] + return ruleDefinition; } -]; +}; diff --git a/tools/eslint/lib/rules/no-useless-call.js b/tools/eslint/lib/rules/no-useless-call.js index fe6afd6d2487cc..eb14f0baf94eb4 100644 --- a/tools/eslint/lib/rules/no-useless-call.js +++ b/tools/eslint/lib/rules/no-useless-call.js @@ -1,7 +1,6 @@ /** * @fileoverview A rule to disallow unnecessary `.call()` and `.apply()`. * @author Toru Nagashima - * @copyright 2015 Toru Nagashima. All rights reserved. */ "use strict"; @@ -72,25 +71,35 @@ function isValidThisArg(expectedThis, thisArg, context) { // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - return { - "CallExpression": function(node) { - if (!isCallOrNonVariadicApply(node)) { - return; - } +module.exports = { + meta: { + docs: { + description: "disallow unnecessary calls to `.call()` and `.apply()`", + category: "Best Practices", + recommended: false + }, + + schema: [] + }, + + create: function(context) { + return { + CallExpression: function(node) { + if (!isCallOrNonVariadicApply(node)) { + return; + } - var applied = node.callee.object; - var expectedThis = (applied.type === "MemberExpression") ? applied.object : null; - var thisArg = node.arguments[0]; + var applied = node.callee.object; + var expectedThis = (applied.type === "MemberExpression") ? applied.object : null; + var thisArg = node.arguments[0]; - if (isValidThisArg(expectedThis, thisArg, context)) { - context.report( - node, - "unnecessary '.{{name}}()'.", - {name: node.callee.property.name}); + if (isValidThisArg(expectedThis, thisArg, context)) { + context.report( + node, + "unnecessary '.{{name}}()'.", + {name: node.callee.property.name}); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-useless-computed-key.js b/tools/eslint/lib/rules/no-useless-computed-key.js new file mode 100644 index 00000000000000..0894fb7ca41e56 --- /dev/null +++ b/tools/eslint/lib/rules/no-useless-computed-key.js @@ -0,0 +1,37 @@ +/** + * @fileoverview Rule to disallow unnecessary computed property keys in object literals + * @author Burak Yigit Kaya + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +var MESSAGE_UNNECESSARY_COMPUTED = "Unnecessarily computed property [{{property}}] found."; + +module.exports = { + meta: { + docs: { + description: "disallow unnecessary computed property keys in object literals", + category: "ECMAScript 6", + recommended: false + } + }, + create: function(context) { + return { + Property: function(node) { + if (!node.computed) { + return; + } + + var key = node.key, + nodeType = typeof key.value; + + if (key.type === "Literal" && (nodeType === "string" || nodeType === "number")) { + context.report(node, MESSAGE_UNNECESSARY_COMPUTED, { property: context.getSource(key) }); + } + } + }; + } +}; diff --git a/tools/eslint/lib/rules/no-useless-concat.js b/tools/eslint/lib/rules/no-useless-concat.js index 96baf51a4e0ccf..ce9589d4880220 100644 --- a/tools/eslint/lib/rules/no-useless-concat.js +++ b/tools/eslint/lib/rules/no-useless-concat.js @@ -1,8 +1,6 @@ /** * @fileoverview disallow unncessary concatenation of template strings * @author Henry Zhu - * @copyright 2015 Henry Zhu. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; @@ -57,38 +55,48 @@ function getRight(node) { // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - return { - BinaryExpression: function(node) { +module.exports = { + meta: { + docs: { + description: "disallow unnecessary concatenation of literals or template literals", + category: "Best Practices", + recommended: false + }, - // check if not concatenation - if (node.operator !== "+") { - return; - } + schema: [] + }, + + create: function(context) { + return { + BinaryExpression: function(node) { - // account for the `foo + "a" + "b"` case - var left = getLeft(node); - var right = getRight(node); + // check if not concatenation + if (node.operator !== "+") { + return; + } - if (astUtils.isStringLiteral(left) && - astUtils.isStringLiteral(right) && - astUtils.isTokenOnSameLine(left, right) - ) { + // account for the `foo + "a" + "b"` case + var left = getLeft(node); + var right = getRight(node); - // move warning location to operator - var operatorToken = context.getTokenAfter(left); + if (astUtils.isStringLiteral(left) && + astUtils.isStringLiteral(right) && + astUtils.isTokenOnSameLine(left, right) + ) { - while (operatorToken.value !== "+") { - operatorToken = context.getTokenAfter(operatorToken); - } + // move warning location to operator + var operatorToken = context.getTokenAfter(left); - context.report( - node, - operatorToken.loc.start, - "Unexpected string concatenation of literals."); + while (operatorToken.value !== "+") { + operatorToken = context.getTokenAfter(operatorToken); + } + + context.report( + node, + operatorToken.loc.start, + "Unexpected string concatenation of literals."); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-useless-constructor.js b/tools/eslint/lib/rules/no-useless-constructor.js index 244f2b458f646e..b91ab4bcae5866 100644 --- a/tools/eslint/lib/rules/no-useless-constructor.js +++ b/tools/eslint/lib/rules/no-useless-constructor.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to flag the use of redundant constructors in classes. * @author Alberto Rodríguez - * @copyright 2015 Alberto Rodríguez. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; @@ -142,33 +140,43 @@ function isRedundantSuperCall(body, ctorParams) { // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - /** - * Checks whether a node is a redundant constructor - * @param {ASTNode} node - node to check - * @returns {void} - */ - function checkForConstructor(node) { - if (node.kind !== "constructor") { - return; +module.exports = { + meta: { + docs: { + description: "disallow unnecessary constructors", + category: "ECMAScript 6", + recommended: false + }, + + schema: [] + }, + + create: function(context) { + + /** + * Checks whether a node is a redundant constructor + * @param {ASTNode} node - node to check + * @returns {void} + */ + function checkForConstructor(node) { + if (node.kind !== "constructor") { + return; + } + + var body = node.value.body.body; + var ctorParams = node.value.params; + var superClass = node.parent.parent.superClass; + + if (superClass ? isRedundantSuperCall(body, ctorParams) : (body.length === 0)) { + context.report({ + node: node, + message: "Useless constructor." + }); + } } - var body = node.value.body.body; - var ctorParams = node.value.params; - var superClass = node.parent.parent.superClass; - - if (superClass ? isRedundantSuperCall(body, ctorParams) : (body.length === 0)) { - context.report({ - node: node, - message: "Useless constructor." - }); - } + return { + MethodDefinition: checkForConstructor + }; } - - return { - "MethodDefinition": checkForConstructor - }; }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-useless-escape.js b/tools/eslint/lib/rules/no-useless-escape.js index a6f5daa71c444d..036831fc394f4f 100644 --- a/tools/eslint/lib/rules/no-useless-escape.js +++ b/tools/eslint/lib/rules/no-useless-escape.js @@ -1,7 +1,6 @@ /** * @fileoverview Look for useless escapes in strings and regexes * @author Onur Temizkan - * @copyright 2016 Onur Temizkan. All rights reserved. */ "use strict"; @@ -58,51 +57,74 @@ var VALID_REGEX_ESCAPES = [ "u" ]; -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow unnecessary escape characters", + category: "Best Practices", + recommended: false + }, - /** - * Checks if the escape character in given slice is unnecessary. - * - * @private - * @param {string} elm - string slice to validate. - * @param {ASTNode} node - node to validate. - * @returns {void} - * @this escapes_quote_node - */ - function validate(elm) { - var escapeNotFound = this.escapes.indexOf(elm[1]) === -1; - var isQuoteEscape = elm[1] === this.node.raw[0]; + schema: [] + }, - if (escapeNotFound && !isQuoteEscape) { - context.report(this.node, "Unnecessary escape character: " + elm); - } - } + create: function(context) { - /** - * Checks if a node has an escape. - * - * @param {ASTNode} node - node to check. - * @returns {void} - */ - function check(node) { - var nodeEscapes; + /** + * Checks if the escape character in given slice is unnecessary. + * + * @private + * @param {string[]} escapes - list of valid escapes + * @param {ASTNode} node - node to validate. + * @param {string} elm - string slice to validate. + * @returns {void} + */ + function validate(escapes, node, elm) { + var escapeNotFound = escapes.indexOf(elm[0][1]) === -1; + var isQuoteEscape = elm[0][1] === node.raw[0]; - if (typeof node.value === "string") { - nodeEscapes = VALID_STRING_ESCAPES; - } else if (node.regex) { - nodeEscapes = VALID_REGEX_ESCAPES; - } else { - return; + if (escapeNotFound && !isQuoteEscape) { + context.report({ + node: node, + loc: { + line: node.loc.start.line, + column: node.loc.start.column + elm.index + }, + message: "Unnecessary escape character: " + elm[0] + }); + } } - (node.raw.match(/\\[^\d]/g) || []).forEach(validate, { - "escapes": nodeEscapes, - "node": node - }); + /** + * Checks if a node has an escape. + * + * @param {ASTNode} node - node to check. + * @returns {void} + */ + function check(node) { + var nodeEscapes, match; + var pattern = /\\[^\d]/g; + + if (typeof node.value === "string") { + + // JSXAttribute doesn't have any escape sequence: https://facebook.github.io/jsx/ + if (node.parent.type === "JSXAttribute") { + return; + } + + nodeEscapes = VALID_STRING_ESCAPES; + } else if (node.regex) { + nodeEscapes = VALID_REGEX_ESCAPES; + } else { + return; + } + + while ((match = pattern.exec(node.raw))) { + validate(nodeEscapes, node, match); + } + } + return { + Literal: check + }; } - return { - "Literal": check - }; }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-var.js b/tools/eslint/lib/rules/no-var.js index 05cb6e99eca58e..2e9948a330e190 100644 --- a/tools/eslint/lib/rules/no-var.js +++ b/tools/eslint/lib/rules/no-var.js @@ -1,7 +1,6 @@ /** * @fileoverview Rule to check for the usage of var. * @author Jamund Ferguson - * @copyright 2014 Jamund Ferguson. All rights reserved. */ "use strict"; @@ -10,17 +9,27 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "require `let` or `const` instead of `var`", + category: "ECMAScript 6", + recommended: false + }, - return { - "VariableDeclaration": function(node) { - if (node.kind === "var") { - context.report(node, "Unexpected var, use let or const instead."); + schema: [] + }, + + create: function(context) { + + return { + VariableDeclaration: function(node) { + if (node.kind === "var") { + context.report(node, "Unexpected var, use let or const instead."); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-void.js b/tools/eslint/lib/rules/no-void.js index 858304dd1d526e..4adae20b37bc91 100644 --- a/tools/eslint/lib/rules/no-void.js +++ b/tools/eslint/lib/rules/no-void.js @@ -1,7 +1,6 @@ /** * @fileoverview Rule to disallow use of void operator. * @author Mike Sidorov - * @copyright 2014 Mike Sidorov. All rights reserved. */ "use strict"; @@ -9,20 +8,30 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow `void` operators", + category: "Best Practices", + recommended: false + }, - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- + schema: [] + }, - return { - "UnaryExpression": function(node) { - if (node.operator === "void") { - context.report(node, "Expected 'undefined' and instead saw 'void'."); + create: function(context) { + + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + return { + UnaryExpression: function(node) { + if (node.operator === "void") { + context.report(node, "Expected 'undefined' and instead saw 'void'."); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-warning-comments.js b/tools/eslint/lib/rules/no-warning-comments.js index 02450229d9f59c..dadf231f5c39f0 100644 --- a/tools/eslint/lib/rules/no-warning-comments.js +++ b/tools/eslint/lib/rules/no-warning-comments.js @@ -11,110 +11,120 @@ var astUtils = require("../ast-utils"); // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - var configuration = context.options[0] || {}, - warningTerms = configuration.terms || ["todo", "fixme", "xxx"], - location = configuration.location || "start", - selfConfigRegEx = /\bno-warning-comments\b/, - warningRegExps; - - /** - * Convert a warning term into a RegExp which will match a comment containing that whole word in the specified - * location ("start" or "anywhere"). If the term starts or ends with non word characters, then the match will not - * require word boundaries on that side. - * - * @param {String} term A term to convert to a RegExp - * @returns {RegExp} The term converted to a RegExp - */ - function convertToRegExp(term) { - var escaped = term.replace(/[-\/\\$\^*+?.()|\[\]{}]/g, "\\$&"), - suffix, - prefix; - - /* - * If the term ends in a word character (a-z0-9_), ensure a word - * boundary at the end, so that substrings do not get falsely - * matched. eg "todo" in a string such as "mastodon". - * If the term ends in a non-word character, then \b won't match on - * the boundary to the next non-word character, which would likely - * be a space. For example `/\bFIX!\b/.test('FIX! blah') === false`. - * In these cases, use no bounding match. Same applies for the - * prefix, handled below. - */ - suffix = /\w$/.test(term) ? "\\b" : ""; +module.exports = { + meta: { + docs: { + description: "disallow specified warning terms in comments", + category: "Best Practices", + recommended: false + }, - if (location === "start") { + schema: [ + { + type: "object", + properties: { + terms: { + type: "array", + items: { + type: "string" + } + }, + location: { + enum: ["start", "anywhere"] + } + }, + additionalProperties: false + } + ] + }, + + create: function(context) { + + var configuration = context.options[0] || {}, + warningTerms = configuration.terms || ["todo", "fixme", "xxx"], + location = configuration.location || "start", + selfConfigRegEx = /\bno-warning-comments\b/, + warningRegExps; + + /** + * Convert a warning term into a RegExp which will match a comment containing that whole word in the specified + * location ("start" or "anywhere"). If the term starts or ends with non word characters, then the match will not + * require word boundaries on that side. + * + * @param {String} term A term to convert to a RegExp + * @returns {RegExp} The term converted to a RegExp + */ + function convertToRegExp(term) { + var escaped = term.replace(/[-\/\\$\^*+?.()|\[\]{}]/g, "\\$&"), + suffix, + prefix; /* - * When matching at the start, ignore leading whitespace, and - * there's no need to worry about word boundaries. + * If the term ends in a word character (a-z0-9_), ensure a word + * boundary at the end, so that substrings do not get falsely + * matched. eg "todo" in a string such as "mastodon". + * If the term ends in a non-word character, then \b won't match on + * the boundary to the next non-word character, which would likely + * be a space. For example `/\bFIX!\b/.test('FIX! blah') === false`. + * In these cases, use no bounding match. Same applies for the + * prefix, handled below. */ - prefix = "^\\s*"; - } else if (/^\w/.test(term)) { - prefix = "\\b"; - } else { - prefix = ""; - } + suffix = /\w$/.test(term) ? "\\b" : ""; + + if (location === "start") { + + /* + * When matching at the start, ignore leading whitespace, and + * there's no need to worry about word boundaries. + */ + prefix = "^\\s*"; + } else if (/^\w/.test(term)) { + prefix = "\\b"; + } else { + prefix = ""; + } - return new RegExp(prefix + escaped + suffix, "i"); - } + return new RegExp(prefix + escaped + suffix, "i"); + } - /** - * Checks the specified comment for matches of the configured warning terms and returns the matches. - * @param {String} comment The comment which is checked. - * @returns {Array} All matched warning terms for this comment. - */ - function commentContainsWarningTerm(comment) { - var matches = []; - - warningRegExps.forEach(function(regex, index) { - if (regex.test(comment)) { - matches.push(warningTerms[index]); - } - }); + /** + * Checks the specified comment for matches of the configured warning terms and returns the matches. + * @param {String} comment The comment which is checked. + * @returns {Array} All matched warning terms for this comment. + */ + function commentContainsWarningTerm(comment) { + var matches = []; - return matches; - } + warningRegExps.forEach(function(regex, index) { + if (regex.test(comment)) { + matches.push(warningTerms[index]); + } + }); - /** - * Checks the specified node for matching warning comments and reports them. - * @param {ASTNode} node The AST node being checked. - * @returns {void} undefined. - */ - function checkComment(node) { - if (astUtils.isDirectiveComment(node) && selfConfigRegEx.test(node.value)) { - return; + return matches; } - var matches = commentContainsWarningTerm(node.value); + /** + * Checks the specified node for matching warning comments and reports them. + * @param {ASTNode} node The AST node being checked. + * @returns {void} undefined. + */ + function checkComment(node) { + if (astUtils.isDirectiveComment(node) && selfConfigRegEx.test(node.value)) { + return; + } - matches.forEach(function(matchedTerm) { - context.report(node, "Unexpected '" + matchedTerm + "' comment."); - }); - } + var matches = commentContainsWarningTerm(node.value); - warningRegExps = warningTerms.map(convertToRegExp); - return { - "BlockComment": checkComment, - "LineComment": checkComment - }; -}; + matches.forEach(function(matchedTerm) { + context.report(node, "Unexpected '" + matchedTerm + "' comment."); + }); + } -module.exports.schema = [ - { - "type": "object", - "properties": { - "terms": { - "type": "array", - "items": { - "type": "string" - } - }, - "location": { - "enum": ["start", "anywhere"] - } - }, - "additionalProperties": false + warningRegExps = warningTerms.map(convertToRegExp); + return { + BlockComment: checkComment, + LineComment: checkComment + }; } -]; +}; diff --git a/tools/eslint/lib/rules/no-whitespace-before-property.js b/tools/eslint/lib/rules/no-whitespace-before-property.js index 0910f2fce42212..347c63d934f166 100644 --- a/tools/eslint/lib/rules/no-whitespace-before-property.js +++ b/tools/eslint/lib/rules/no-whitespace-before-property.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to disallow whitespace before properties * @author Kai Cataldo - * @copyright 2015 Kai Cataldo. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; @@ -12,70 +10,88 @@ var astUtils = require("../ast-utils"); // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var sourceCode = context.getSourceCode(); +module.exports = { + meta: { + docs: { + description: "disallow whitespace before properties", + category: "Stylistic Issues", + recommended: false + }, - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- + fixable: "whitespace", + schema: [] + }, - /** - * 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) { - var token = sourceCode.getTokenBefore(node.property); + create: function(context) { + var sourceCode = context.getSourceCode(); - while (token.value !== "[") { - token = sourceCode.getTokenBefore(token); - } - return token; - } + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- - /** - * Reports whitespace before property token - * @param {ASTNode} node - the node to report in the event of an error - * @returns {void} - * @private - */ - function reportError(node) { - context.report({ - node: node, - message: "Unexpected whitespace before property {{propName}}.", - data: { - propName: sourceCode.getText(node.property) + /** + * 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) { + var token = sourceCode.getTokenBefore(node.property); + + while (token.value !== "[") { + token = sourceCode.getTokenBefore(token); } - }); - } + return token; + } - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- + /** + * Reports whitespace before property token + * @param {ASTNode} node - the node to report in the event of an error + * @param {Token} leftToken - the left token + * @param {Token} rightToken - the right token + * @returns {void} + * @private + */ + function reportError(node, leftToken, rightToken) { + var replacementText = node.computed ? "" : "."; - return { - MemberExpression: function(node) { - var rightToken; - var leftToken; + context.report({ + node: node, + message: "Unexpected whitespace before property {{propName}}.", + data: { + propName: sourceCode.getText(node.property) + }, + fix: function(fixer) { + return fixer.replaceTextRange([leftToken.range[1], rightToken.range[0]], replacementText); + } + }); + } - if (!astUtils.isTokenOnSameLine(node.object, node.property)) { - return; - } + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- - if (node.computed) { - rightToken = findOpeningBracket(node); - leftToken = sourceCode.getTokenBefore(rightToken); - } else { - rightToken = sourceCode.getFirstToken(node.property); - leftToken = sourceCode.getTokenBefore(rightToken, 1); - } + return { + MemberExpression: function(node) { + var rightToken; + var leftToken; + + if (!astUtils.isTokenOnSameLine(node.object, node.property)) { + return; + } + + if (node.computed) { + rightToken = findOpeningBracket(node); + leftToken = sourceCode.getTokenBefore(rightToken); + } else { + rightToken = sourceCode.getFirstToken(node.property); + leftToken = sourceCode.getTokenBefore(rightToken, 1); + } - if (sourceCode.isSpaceBetweenTokens(leftToken, rightToken)) { - reportError(node); + if (sourceCode.isSpaceBetweenTokens(leftToken, rightToken)) { + reportError(node, leftToken, rightToken); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/no-with.js b/tools/eslint/lib/rules/no-with.js index beec2554db2cd9..df7528fdfa8487 100644 --- a/tools/eslint/lib/rules/no-with.js +++ b/tools/eslint/lib/rules/no-with.js @@ -9,14 +9,24 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "disallow `with` statements", + category: "Best Practices", + recommended: false + }, - return { - "WithStatement": function(node) { - context.report(node, "Unexpected use of 'with' statement."); - } - }; + schema: [] + }, -}; + create: function(context) { + + return { + WithStatement: function(node) { + context.report(node, "Unexpected use of 'with' statement."); + } + }; -module.exports.schema = []; + } +}; diff --git a/tools/eslint/lib/rules/object-curly-spacing.js b/tools/eslint/lib/rules/object-curly-spacing.js index 8a7b9aefeeb3aa..11224bbdd13a0a 100644 --- a/tools/eslint/lib/rules/object-curly-spacing.js +++ b/tools/eslint/lib/rules/object-curly-spacing.js @@ -1,12 +1,6 @@ /** * @fileoverview Disallows or enforces spaces inside of object literals. * @author Jamund Ferguson - * @copyright 2014 Brandyn Bennett. All rights reserved. - * @copyright 2014 Michael Ficarra. No rights reserved. - * @copyright 2014 Vignesh Anand. All rights reserved. - * @copyright 2015 Jamund Ferguson. All rights reserved. - * @copyright 2015 Toru Nagashima. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; @@ -16,265 +10,277 @@ var astUtils = require("../ast-utils"); // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var spaced = context.options[0] === "always", - sourceCode = context.getSourceCode(); - - /** - * Determines whether an option is set, relative to the spacing option. - * If spaced is "always", then check whether option is set to false. - * If spaced is "never", then check whether option is set to true. - * @param {Object} option - The option to exclude. - * @returns {boolean} Whether or not the property is excluded. - */ - function isOptionSet(option) { - return context.options[1] ? context.options[1][option] === !spaced : false; - } +module.exports = { + meta: { + docs: { + description: "enforce consistent spacing inside braces", + category: "Stylistic Issues", + recommended: false + }, - var options = { - spaced: spaced, - arraysInObjectsException: isOptionSet("arraysInObjects"), - objectsInObjectsException: isOptionSet("objectsInObjects") - }; - - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- - - /** - * Reports that there shouldn't be a space after the first token - * @param {ASTNode} node - The node to report in the event of an error. - * @param {Token} token - The token to use for the report. - * @returns {void} - */ - function reportNoBeginningSpace(node, token) { - context.report({ - node: node, - loc: token.loc.start, - message: "There should be no space after '" + token.value + "'", - fix: function(fixer) { - var nextToken = context.getSourceCode().getTokenAfter(token); - - return fixer.removeRange([token.range[1], nextToken.range[0]]); - } - }); - } + fixable: "whitespace", - /** - * Reports that there shouldn't be a space before the last token - * @param {ASTNode} node - The node to report in the event of an error. - * @param {Token} token - The token to use for the report. - * @returns {void} - */ - function reportNoEndingSpace(node, token) { - context.report({ - node: node, - loc: token.loc.start, - message: "There should be no space before '" + token.value + "'", - fix: function(fixer) { - var previousToken = context.getSourceCode().getTokenBefore(token); - - return fixer.removeRange([previousToken.range[1], token.range[0]]); - } - }); - } - - /** - * Reports that there should be a space after the first token - * @param {ASTNode} node - The node to report in the event of an error. - * @param {Token} token - The token to use for the report. - * @returns {void} - */ - function reportRequiredBeginningSpace(node, token) { - context.report({ - node: node, - loc: token.loc.start, - message: "A space is required after '" + token.value + "'", - fix: function(fixer) { - return fixer.insertTextAfter(token, " "); + schema: [ + { + enum: ["always", "never"] + }, + { + type: "object", + properties: { + arraysInObjects: { + type: "boolean" + }, + objectsInObjects: { + type: "boolean" + } + }, + additionalProperties: false } - }); - } + ] + }, - /** - * Reports that there should be a space before the last token - * @param {ASTNode} node - The node to report in the event of an error. - * @param {Token} token - The token to use for the report. - * @returns {void} - */ - function reportRequiredEndingSpace(node, token) { - context.report({ - node: node, - loc: token.loc.start, - message: "A space is required before '" + token.value + "'", - fix: function(fixer) { - return fixer.insertTextBefore(token, " "); - } - }); - } + create: function(context) { + var spaced = context.options[0] === "always", + sourceCode = context.getSourceCode(); + + /** + * Determines whether an option is set, relative to the spacing option. + * If spaced is "always", then check whether option is set to false. + * If spaced is "never", then check whether option is set to true. + * @param {Object} option - The option to exclude. + * @returns {boolean} Whether or not the property is excluded. + */ + function isOptionSet(option) { + return context.options[1] ? context.options[1][option] === !spaced : false; + } - /** - * Determines if spacing in curly braces is valid. - * @param {ASTNode} node The AST node to check. - * @param {Token} first The first token to check (should be the opening brace) - * @param {Token} second The second token to check (should be first after the opening brace) - * @param {Token} penultimate The penultimate token to check (should be last before closing brace) - * @param {Token} last The last token to check (should be closing brace) - * @returns {void} - */ - function validateBraceSpacing(node, first, second, penultimate, last) { - var shouldCheckPenultimate, - penultimateType, - closingCurlyBraceMustBeSpaced, - firstSpaced, - lastSpaced; - - if (astUtils.isTokenOnSameLine(first, second)) { - firstSpaced = sourceCode.isSpaceBetweenTokens(first, second); - if (options.spaced && !firstSpaced) { - reportRequiredBeginningSpace(node, first); - } - if (!options.spaced && firstSpaced) { - reportNoBeginningSpace(node, first); - } + var options = { + spaced: spaced, + arraysInObjectsException: isOptionSet("arraysInObjects"), + objectsInObjectsException: isOptionSet("objectsInObjects") + }; + + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- + + /** + * Reports that there shouldn't be a space after the first token + * @param {ASTNode} node - The node to report in the event of an error. + * @param {Token} token - The token to use for the report. + * @returns {void} + */ + function reportNoBeginningSpace(node, token) { + context.report({ + node: node, + loc: token.loc.start, + message: "There should be no space after '" + token.value + "'", + fix: function(fixer) { + var nextToken = context.getSourceCode().getTokenAfter(token); + + return fixer.removeRange([token.range[1], nextToken.range[0]]); + } + }); } - if (astUtils.isTokenOnSameLine(penultimate, last)) { - shouldCheckPenultimate = ( - options.arraysInObjectsException && penultimate.value === "]" || - options.objectsInObjectsException && penultimate.value === "}" - ); - penultimateType = shouldCheckPenultimate && sourceCode.getNodeByRangeIndex(penultimate.start).type; + /** + * Reports that there shouldn't be a space before the last token + * @param {ASTNode} node - The node to report in the event of an error. + * @param {Token} token - The token to use for the report. + * @returns {void} + */ + function reportNoEndingSpace(node, token) { + context.report({ + node: node, + loc: token.loc.start, + message: "There should be no space before '" + token.value + "'", + fix: function(fixer) { + var previousToken = context.getSourceCode().getTokenBefore(token); + + return fixer.removeRange([previousToken.range[1], token.range[0]]); + } + }); + } - closingCurlyBraceMustBeSpaced = ( - options.arraysInObjectsException && penultimateType === "ArrayExpression" || - options.objectsInObjectsException && penultimateType === "ObjectExpression" - ) ? !options.spaced : options.spaced; + /** + * Reports that there should be a space after the first token + * @param {ASTNode} node - The node to report in the event of an error. + * @param {Token} token - The token to use for the report. + * @returns {void} + */ + function reportRequiredBeginningSpace(node, token) { + context.report({ + node: node, + loc: token.loc.start, + message: "A space is required after '" + token.value + "'", + fix: function(fixer) { + return fixer.insertTextAfter(token, " "); + } + }); + } - lastSpaced = sourceCode.isSpaceBetweenTokens(penultimate, last); + /** + * Reports that there should be a space before the last token + * @param {ASTNode} node - The node to report in the event of an error. + * @param {Token} token - The token to use for the report. + * @returns {void} + */ + function reportRequiredEndingSpace(node, token) { + context.report({ + node: node, + loc: token.loc.start, + message: "A space is required before '" + token.value + "'", + fix: function(fixer) { + return fixer.insertTextBefore(token, " "); + } + }); + } - if (closingCurlyBraceMustBeSpaced && !lastSpaced) { - reportRequiredEndingSpace(node, last); - } - if (!closingCurlyBraceMustBeSpaced && lastSpaced) { - reportNoEndingSpace(node, last); + /** + * Determines if spacing in curly braces is valid. + * @param {ASTNode} node The AST node to check. + * @param {Token} first The first token to check (should be the opening brace) + * @param {Token} second The second token to check (should be first after the opening brace) + * @param {Token} penultimate The penultimate token to check (should be last before closing brace) + * @param {Token} last The last token to check (should be closing brace) + * @returns {void} + */ + function validateBraceSpacing(node, first, second, penultimate, last) { + var shouldCheckPenultimate, + penultimateType, + closingCurlyBraceMustBeSpaced, + firstSpaced, + lastSpaced; + + if (astUtils.isTokenOnSameLine(first, second)) { + firstSpaced = sourceCode.isSpaceBetweenTokens(first, second); + if (options.spaced && !firstSpaced) { + reportRequiredBeginningSpace(node, first); + } + if (!options.spaced && firstSpaced) { + reportNoBeginningSpace(node, first); + } } - } - } - /** - * Reports a given object node if spacing in curly braces is invalid. - * @param {ASTNode} node - An ObjectExpression or ObjectPattern node to check. - * @returns {void} - */ - function checkForObject(node) { - if (node.properties.length === 0) { - return; + if (astUtils.isTokenOnSameLine(penultimate, last)) { + shouldCheckPenultimate = ( + options.arraysInObjectsException && penultimate.value === "]" || + options.objectsInObjectsException && penultimate.value === "}" + ); + penultimateType = shouldCheckPenultimate && sourceCode.getNodeByRangeIndex(penultimate.start).type; + + closingCurlyBraceMustBeSpaced = ( + options.arraysInObjectsException && penultimateType === "ArrayExpression" || + options.objectsInObjectsException && penultimateType === "ObjectExpression" + ) ? !options.spaced : options.spaced; + + lastSpaced = sourceCode.isSpaceBetweenTokens(penultimate, last); + + if (closingCurlyBraceMustBeSpaced && !lastSpaced) { + reportRequiredEndingSpace(node, last); + } + if (!closingCurlyBraceMustBeSpaced && lastSpaced) { + reportNoEndingSpace(node, last); + } + } } - var first = sourceCode.getFirstToken(node), - last = sourceCode.getLastToken(node), - second = sourceCode.getTokenAfter(first), - penultimate = sourceCode.getTokenBefore(last); + /** + * Reports a given object node if spacing in curly braces is invalid. + * @param {ASTNode} node - An ObjectExpression or ObjectPattern node to check. + * @returns {void} + */ + function checkForObject(node) { + if (node.properties.length === 0) { + return; + } - validateBraceSpacing(node, first, second, penultimate, last); - } + var first = sourceCode.getFirstToken(node), + last = sourceCode.getLastToken(node), + second = sourceCode.getTokenAfter(first), + penultimate = sourceCode.getTokenBefore(last); - /** - * Reports a given import node if spacing in curly braces is invalid. - * @param {ASTNode} node - An ImportDeclaration node to check. - * @returns {void} - */ - function checkForImport(node) { - if (node.specifiers.length === 0) { - return; + validateBraceSpacing(node, first, second, penultimate, last); } - var firstSpecifier = node.specifiers[0], - lastSpecifier = node.specifiers[node.specifiers.length - 1]; + /** + * Reports a given import node if spacing in curly braces is invalid. + * @param {ASTNode} node - An ImportDeclaration node to check. + * @returns {void} + */ + function checkForImport(node) { + if (node.specifiers.length === 0) { + return; + } - if (lastSpecifier.type !== "ImportSpecifier") { - return; - } - if (firstSpecifier.type !== "ImportSpecifier") { - firstSpecifier = node.specifiers[1]; - } + var firstSpecifier = node.specifiers[0], + lastSpecifier = node.specifiers[node.specifiers.length - 1]; - var first = sourceCode.getTokenBefore(firstSpecifier), - last = sourceCode.getTokenAfter(lastSpecifier); + if (lastSpecifier.type !== "ImportSpecifier") { + return; + } + if (firstSpecifier.type !== "ImportSpecifier") { + firstSpecifier = node.specifiers[1]; + } - // to support a trailing comma. - if (last.value === ",") { - last = sourceCode.getTokenAfter(last); - } + var first = sourceCode.getTokenBefore(firstSpecifier), + last = sourceCode.getTokenAfter(lastSpecifier); - var second = sourceCode.getTokenAfter(first), - penultimate = sourceCode.getTokenBefore(last); + // to support a trailing comma. + if (last.value === ",") { + last = sourceCode.getTokenAfter(last); + } - validateBraceSpacing(node, first, second, penultimate, last); - } + var second = sourceCode.getTokenAfter(first), + penultimate = sourceCode.getTokenBefore(last); - /** - * Reports a given export node if spacing in curly braces is invalid. - * @param {ASTNode} node - An ExportNamedDeclaration node to check. - * @returns {void} - */ - function checkForExport(node) { - if (node.specifiers.length === 0) { - return; + validateBraceSpacing(node, first, second, penultimate, last); } - var firstSpecifier = node.specifiers[0], - lastSpecifier = node.specifiers[node.specifiers.length - 1], - first = sourceCode.getTokenBefore(firstSpecifier), - last = sourceCode.getTokenAfter(lastSpecifier); + /** + * Reports a given export node if spacing in curly braces is invalid. + * @param {ASTNode} node - An ExportNamedDeclaration node to check. + * @returns {void} + */ + function checkForExport(node) { + if (node.specifiers.length === 0) { + return; + } - // to support a trailing comma. - if (last.value === ",") { - last = sourceCode.getTokenAfter(last); - } + var firstSpecifier = node.specifiers[0], + lastSpecifier = node.specifiers[node.specifiers.length - 1], + first = sourceCode.getTokenBefore(firstSpecifier), + last = sourceCode.getTokenAfter(lastSpecifier); - var second = sourceCode.getTokenAfter(first), - penultimate = sourceCode.getTokenBefore(last); + // to support a trailing comma. + if (last.value === ",") { + last = sourceCode.getTokenAfter(last); + } - validateBraceSpacing(node, first, second, penultimate, last); - } + var second = sourceCode.getTokenAfter(first), + penultimate = sourceCode.getTokenBefore(last); - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- + validateBraceSpacing(node, first, second, penultimate, last); + } - return { + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- - // var {x} = y; - ObjectPattern: checkForObject, + return { - // var y = {x: 'y'} - ObjectExpression: checkForObject, + // var {x} = y; + ObjectPattern: checkForObject, - // import {y} from 'x'; - ImportDeclaration: checkForImport, + // var y = {x: 'y'} + ObjectExpression: checkForObject, - // export {name} from 'yo'; - ExportNamedDeclaration: checkForExport - }; + // import {y} from 'x'; + ImportDeclaration: checkForImport, -}; + // export {name} from 'yo'; + ExportNamedDeclaration: checkForExport + }; -module.exports.schema = [ - { - "enum": ["always", "never"] - }, - { - "type": "object", - "properties": { - "arraysInObjects": { - "type": "boolean" - }, - "objectsInObjects": { - "type": "boolean" - } - }, - "additionalProperties": false } -]; +}; diff --git a/tools/eslint/lib/rules/object-shorthand.js b/tools/eslint/lib/rules/object-shorthand.js index c6ffa0f8f34a72..4c7c066bcdc588 100644 --- a/tools/eslint/lib/rules/object-shorthand.js +++ b/tools/eslint/lib/rules/object-shorthand.js @@ -1,7 +1,6 @@ /** * @fileoverview Rule to enforce concise object methods and properties. * @author Jamund Ferguson - * @copyright 2015 Jamund Ferguson. All rights reserved. */ "use strict"; @@ -16,112 +15,127 @@ var OPTIONS = { //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var APPLY = context.options[0] || OPTIONS.always; - var APPLY_TO_METHODS = APPLY === OPTIONS.methods || APPLY === OPTIONS.always; - var APPLY_TO_PROPS = APPLY === OPTIONS.properties || APPLY === OPTIONS.always; - var APPLY_NEVER = APPLY === OPTIONS.never; - - var PARAMS = context.options[1] || {}; - var IGNORE_CONSTRUCTORS = PARAMS.ignoreConstructors; - - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- - - /** - * Determines if the first character of the name is a capital letter. - * @param {string} name The name of the node to evaluate. - * @returns {boolean} True if the first character of the property name is a capital letter, false if not. - * @private - */ - function isConstructor(name) { - var firstChar = name.charAt(0); - - return firstChar === firstChar.toUpperCase(); - } +module.exports = { + meta: { + docs: { + description: "require or disallow method and property shorthand syntax for object literals", + category: "ECMAScript 6", + recommended: false + }, - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- + schema: { + anyOf: [ + { + type: "array", + items: [ + { + enum: ["always", "methods", "properties", "never"] + } + ], + minItems: 0, + maxItems: 1 + }, + { + type: "array", + items: [ + { + enum: ["always", "methods"] + }, + { + type: "object", + properties: { + ignoreConstructors: { + type: "boolean" + } + }, + additionalProperties: false + } + ], + minItems: 0, + maxItems: 2 + } + ] + } + }, + + create: function(context) { + var APPLY = context.options[0] || OPTIONS.always; + var APPLY_TO_METHODS = APPLY === OPTIONS.methods || APPLY === OPTIONS.always; + var APPLY_TO_PROPS = APPLY === OPTIONS.properties || APPLY === OPTIONS.always; + var APPLY_NEVER = APPLY === OPTIONS.never; + + var PARAMS = context.options[1] || {}; + var IGNORE_CONSTRUCTORS = PARAMS.ignoreConstructors; + + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- + + /** + * Determines if the first character of the name is a capital letter. + * @param {string} name The name of the node to evaluate. + * @returns {boolean} True if the first character of the property name is a capital letter, false if not. + * @private + */ + function isConstructor(name) { + var firstChar = name.charAt(0); + + return firstChar === firstChar.toUpperCase(); + } - return { - "Property": function(node) { - var isConciseProperty = node.method || node.shorthand, - type; + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- - // Ignore destructuring assignment - if (node.parent.type === "ObjectPattern") { - return; - } + return { + Property: function(node) { + var isConciseProperty = node.method || node.shorthand, + type; - // if we're "never" and concise we should warn now - if (APPLY_NEVER && isConciseProperty) { - type = node.method ? "method" : "property"; - context.report(node, "Expected longform " + type + " syntax."); - } + // Ignore destructuring assignment + if (node.parent.type === "ObjectPattern") { + return; + } - // at this point if we're concise or if we're "never" we can leave - if (APPLY_NEVER || isConciseProperty) { - return; - } + // if we're "never" and concise we should warn now + if (APPLY_NEVER && isConciseProperty) { + type = node.method ? "method" : "property"; + context.report(node, "Expected longform " + type + " syntax."); + } - // getters, setters and computed properties are ignored - if (node.kind === "get" || node.kind === "set" || node.computed) { - return; - } + // at this point if we're concise or if we're "never" we can leave + if (APPLY_NEVER || isConciseProperty) { + return; + } - if (node.value.type === "FunctionExpression" && !node.value.id && APPLY_TO_METHODS) { - if (IGNORE_CONSTRUCTORS && isConstructor(node.key.name)) { + // only computed methods can fail the following checks + if (!APPLY_TO_METHODS && node.computed) { return; } - // {x: function(){}} should be written as {x() {}} - context.report(node, "Expected method shorthand."); - } else if (node.value.type === "Identifier" && node.key.name === node.value.name && APPLY_TO_PROPS) { + // getters and setters are ignored + if (node.kind === "get" || node.kind === "set") { + return; + } - // {x: x} should be written as {x} - context.report(node, "Expected property shorthand."); - } else if (node.value.type === "Identifier" && node.key.type === "Literal" && node.key.value === node.value.name && APPLY_TO_PROPS) { + if (node.value.type === "FunctionExpression" && !node.value.id && APPLY_TO_METHODS) { + if (IGNORE_CONSTRUCTORS && isConstructor(node.key.name)) { + return; + } - // {"x": x} should be written as {x} - context.report(node, "Expected property shorthand."); - } - } - }; + // {x: function(){}} should be written as {x() {}} + context.report(node, "Expected method shorthand."); + } else if (node.value.type === "Identifier" && node.key.name === node.value.name && APPLY_TO_PROPS) { -}; + // {x: x} should be written as {x} + context.report(node, "Expected property shorthand."); + } else if (node.value.type === "Identifier" && node.key.type === "Literal" && node.key.value === node.value.name && APPLY_TO_PROPS) { -module.exports.schema = { - "anyOf": [ - { - "type": "array", - "items": [ - { - "enum": ["always", "methods", "properties", "never"] + // {"x": x} should be written as {x} + context.report(node, "Expected property shorthand."); } - ], - "minItems": 0, - "maxItems": 1 - }, - { - "type": "array", - "items": [ - { - "enum": ["always", "methods"] - }, - { - "type": "object", - "properties": { - "ignoreConstructors": { - "type": "boolean" - } - }, - "additionalProperties": false - } - ], - "minItems": 0, - "maxItems": 2 - } - ] + } + }; + + } }; diff --git a/tools/eslint/lib/rules/one-var-declaration-per-line.js b/tools/eslint/lib/rules/one-var-declaration-per-line.js index 2f763485d7e3f9..f4cdb84b187fa2 100644 --- a/tools/eslint/lib/rules/one-var-declaration-per-line.js +++ b/tools/eslint/lib/rules/one-var-declaration-per-line.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to check multiple var declarations per line * @author Alberto Rodríguez - * @copyright 2016 Alberto Rodríguez. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; @@ -10,66 +8,76 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "require or disallow newlines around `var` declarations", + category: "Stylistic Issues", + recommended: false + }, - var ERROR_MESSAGE = "Expected variable declaration to be on a new line."; - var always = context.options[0] === "always"; + schema: [ + { + enum: ["always", "initializations"] + } + ] + }, - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- + create: function(context) { + var ERROR_MESSAGE = "Expected variable declaration to be on a new line."; + var always = context.options[0] === "always"; - /** - * Determine if provided keyword is a variant of for specifiers - * @private - * @param {string} keyword - keyword to test - * @returns {boolean} True if `keyword` is a variant of for specifier - */ - function isForTypeSpecifier(keyword) { - return keyword === "ForStatement" || keyword === "ForInStatement" || keyword === "ForOfStatement"; - } + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- - /** - * Checks newlines around variable declarations. - * @private - * @param {ASTNode} node - `VariableDeclaration` node to test - * @returns {void} - */ - function checkForNewLine(node) { - if (isForTypeSpecifier(node.parent.type)) { - return; - } - var declarations = node.declarations; - var prev; + /** + * Determine if provided keyword is a variant of for specifiers + * @private + * @param {string} keyword - keyword to test + * @returns {boolean} True if `keyword` is a variant of for specifier + */ + function isForTypeSpecifier(keyword) { + return keyword === "ForStatement" || keyword === "ForInStatement" || keyword === "ForOfStatement"; + } - declarations.forEach(function(current) { - if (prev && prev.loc.end.line === current.loc.start.line) { - if (always || prev.init || current.init) { - context.report({ - node: node, - message: ERROR_MESSAGE, - loc: current.loc.start - }); - } + /** + * Checks newlines around variable declarations. + * @private + * @param {ASTNode} node - `VariableDeclaration` node to test + * @returns {void} + */ + function checkForNewLine(node) { + if (isForTypeSpecifier(node.parent.type)) { + return; } - prev = current; - }); - } - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- + var declarations = node.declarations; + var prev; - return { - "VariableDeclaration": checkForNewLine - }; + declarations.forEach(function(current) { + if (prev && prev.loc.end.line === current.loc.start.line) { + if (always || prev.init || current.init) { + context.report({ + node: node, + message: ERROR_MESSAGE, + loc: current.loc.start + }); + } + } + prev = current; + }); + } -}; + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + return { + VariableDeclaration: checkForNewLine + }; -module.exports.schema = [ - { - "enum": ["always", "initializations"] } -]; +}; diff --git a/tools/eslint/lib/rules/one-var.js b/tools/eslint/lib/rules/one-var.js index d7cccbfe9da09f..805cec3654dd0c 100644 --- a/tools/eslint/lib/rules/one-var.js +++ b/tools/eslint/lib/rules/one-var.js @@ -1,10 +1,6 @@ /** * @fileoverview A rule to control the use of single variable declarations. * @author Ian Christian Myers - * @copyright 2015 Ian VanSchooten. All rights reserved. - * @copyright 2015 Joey Baker. All rights reserved. - * @copyright 2015 Danny Fritz. All rights reserved. - * @copyright 2013 Ian Christian Myers. All rights reserved. */ "use strict"; @@ -13,311 +9,321 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "enforce variables to be declared either together or separately in functions", + category: "Stylistic Issues", + recommended: false + }, - var MODE_ALWAYS = "always", - MODE_NEVER = "never"; + schema: [ + { + oneOf: [ + { + enum: ["always", "never"] + }, + { + type: "object", + properties: { + var: { + enum: ["always", "never"] + }, + let: { + enum: ["always", "never"] + }, + const: { + enum: ["always", "never"] + } + }, + additionalProperties: false + }, + { + type: "object", + properties: { + initialized: { + enum: ["always", "never"] + }, + uninitialized: { + enum: ["always", "never"] + } + }, + additionalProperties: false + } + ] + } + ] + }, - var mode = context.options[0] || MODE_ALWAYS; + create: function(context) { - var options = { - }; + var MODE_ALWAYS = "always", + MODE_NEVER = "never"; - if (typeof mode === "string") { // simple options configuration with just a string - options.var = { uninitialized: mode, initialized: mode}; - options.let = { uninitialized: mode, initialized: mode}; - options.const = { uninitialized: mode, initialized: mode}; - } else if (typeof mode === "object") { // options configuration is an object - if (mode.hasOwnProperty("var") && typeof mode.var === "string") { - options.var = { uninitialized: mode.var, initialized: mode.var}; - } - if (mode.hasOwnProperty("let") && typeof mode.let === "string") { - options.let = { uninitialized: mode.let, initialized: mode.let}; - } - if (mode.hasOwnProperty("const") && typeof mode.const === "string") { - options.const = { uninitialized: mode.const, initialized: mode.const}; - } - if (mode.hasOwnProperty("uninitialized")) { - if (!options.var) { - options.var = {}; - } - if (!options.let) { - options.let = {}; + var mode = context.options[0] || MODE_ALWAYS; + + var options = { + }; + + if (typeof mode === "string") { // simple options configuration with just a string + options.var = { uninitialized: mode, initialized: mode}; + options.let = { uninitialized: mode, initialized: mode}; + options.const = { uninitialized: mode, initialized: mode}; + } else if (typeof mode === "object") { // options configuration is an object + if (mode.hasOwnProperty("var") && typeof mode.var === "string") { + options.var = { uninitialized: mode.var, initialized: mode.var}; } - if (!options.const) { - options.const = {}; + if (mode.hasOwnProperty("let") && typeof mode.let === "string") { + options.let = { uninitialized: mode.let, initialized: mode.let}; } - options.var.uninitialized = mode.uninitialized; - options.let.uninitialized = mode.uninitialized; - options.const.uninitialized = mode.uninitialized; - } - if (mode.hasOwnProperty("initialized")) { - if (!options.var) { - options.var = {}; + if (mode.hasOwnProperty("const") && typeof mode.const === "string") { + options.const = { uninitialized: mode.const, initialized: mode.const}; } - if (!options.let) { - options.let = {}; + if (mode.hasOwnProperty("uninitialized")) { + if (!options.var) { + options.var = {}; + } + if (!options.let) { + options.let = {}; + } + if (!options.const) { + options.const = {}; + } + options.var.uninitialized = mode.uninitialized; + options.let.uninitialized = mode.uninitialized; + options.const.uninitialized = mode.uninitialized; } - if (!options.const) { - options.const = {}; + if (mode.hasOwnProperty("initialized")) { + if (!options.var) { + options.var = {}; + } + if (!options.let) { + options.let = {}; + } + if (!options.const) { + options.const = {}; + } + options.var.initialized = mode.initialized; + options.let.initialized = mode.initialized; + options.const.initialized = mode.initialized; } - options.var.initialized = mode.initialized; - options.let.initialized = mode.initialized; - options.const.initialized = mode.initialized; } - } - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- - - var functionStack = []; - var blockStack = []; - - /** - * Increments the blockStack counter. - * @returns {void} - * @private - */ - function startBlock() { - blockStack.push({ - let: {initialized: false, uninitialized: false}, - const: {initialized: false, uninitialized: false} - }); - } + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- + + var functionStack = []; + var blockStack = []; + + /** + * Increments the blockStack counter. + * @returns {void} + * @private + */ + function startBlock() { + blockStack.push({ + let: {initialized: false, uninitialized: false}, + const: {initialized: false, uninitialized: false} + }); + } - /** - * Increments the functionStack counter. - * @returns {void} - * @private - */ - function startFunction() { - functionStack.push({initialized: false, uninitialized: false}); - startBlock(); - } + /** + * Increments the functionStack counter. + * @returns {void} + * @private + */ + function startFunction() { + functionStack.push({initialized: false, uninitialized: false}); + startBlock(); + } - /** - * Decrements the blockStack counter. - * @returns {void} - * @private - */ - function endBlock() { - blockStack.pop(); - } + /** + * Decrements the blockStack counter. + * @returns {void} + * @private + */ + function endBlock() { + blockStack.pop(); + } - /** - * Decrements the functionStack counter. - * @returns {void} - * @private - */ - function endFunction() { - functionStack.pop(); - endBlock(); - } + /** + * Decrements the functionStack counter. + * @returns {void} + * @private + */ + function endFunction() { + functionStack.pop(); + endBlock(); + } - /** - * Records whether initialized or uninitialized variables are defined in current scope. - * @param {string} statementType node.kind, one of: "var", "let", or "const" - * @param {ASTNode[]} declarations List of declarations - * @param {Object} currentScope The scope being investigated - * @returns {void} - * @private - */ - function recordTypes(statementType, declarations, currentScope) { - for (var i = 0; i < declarations.length; i++) { - if (declarations[i].init === null) { - if (options[statementType] && options[statementType].uninitialized === MODE_ALWAYS) { - currentScope.uninitialized = true; - } - } else { - if (options[statementType] && options[statementType].initialized === MODE_ALWAYS) { - currentScope.initialized = true; + /** + * Records whether initialized or uninitialized variables are defined in current scope. + * @param {string} statementType node.kind, one of: "var", "let", or "const" + * @param {ASTNode[]} declarations List of declarations + * @param {Object} currentScope The scope being investigated + * @returns {void} + * @private + */ + function recordTypes(statementType, declarations, currentScope) { + for (var i = 0; i < declarations.length; i++) { + if (declarations[i].init === null) { + if (options[statementType] && options[statementType].uninitialized === MODE_ALWAYS) { + currentScope.uninitialized = true; + } + } else { + if (options[statementType] && options[statementType].initialized === MODE_ALWAYS) { + currentScope.initialized = true; + } } } } - } - /** - * Determines the current scope (function or block) - * @param {string} statementType node.kind, one of: "var", "let", or "const" - * @returns {Object} The scope associated with statementType - */ - function getCurrentScope(statementType) { - var currentScope; - - if (statementType === "var") { - currentScope = functionStack[functionStack.length - 1]; - } else if (statementType === "let") { - currentScope = blockStack[blockStack.length - 1].let; - } else if (statementType === "const") { - currentScope = blockStack[blockStack.length - 1].const; + /** + * Determines the current scope (function or block) + * @param {string} statementType node.kind, one of: "var", "let", or "const" + * @returns {Object} The scope associated with statementType + */ + function getCurrentScope(statementType) { + var currentScope; + + if (statementType === "var") { + currentScope = functionStack[functionStack.length - 1]; + } else if (statementType === "let") { + currentScope = blockStack[blockStack.length - 1].let; + } else if (statementType === "const") { + currentScope = blockStack[blockStack.length - 1].const; + } + return currentScope; } - return currentScope; - } - /** - * Counts the number of initialized and uninitialized declarations in a list of declarations - * @param {ASTNode[]} declarations List of declarations - * @returns {Object} Counts of 'uninitialized' and 'initialized' declarations - * @private - */ - function countDeclarations(declarations) { - var counts = { uninitialized: 0, initialized: 0 }; - - for (var i = 0; i < declarations.length; i++) { - if (declarations[i].init === null) { - counts.uninitialized++; - } else { - counts.initialized++; + /** + * Counts the number of initialized and uninitialized declarations in a list of declarations + * @param {ASTNode[]} declarations List of declarations + * @returns {Object} Counts of 'uninitialized' and 'initialized' declarations + * @private + */ + function countDeclarations(declarations) { + var counts = { uninitialized: 0, initialized: 0 }; + + for (var i = 0; i < declarations.length; i++) { + if (declarations[i].init === null) { + counts.uninitialized++; + } else { + counts.initialized++; + } } + return counts; } - return counts; - } - /** - * Determines if there is more than one var statement in the current scope. - * @param {string} statementType node.kind, one of: "var", "let", or "const" - * @param {ASTNode[]} declarations List of declarations - * @returns {boolean} Returns true if it is the first var declaration, false if not. - * @private - */ - function hasOnlyOneStatement(statementType, declarations) { - - var declarationCounts = countDeclarations(declarations); - var currentOptions = options[statementType] || {}; - var currentScope = getCurrentScope(statementType); - - if (currentOptions.uninitialized === MODE_ALWAYS && currentOptions.initialized === MODE_ALWAYS) { - if (currentScope.uninitialized || currentScope.initialized) { - return false; + /** + * Determines if there is more than one var statement in the current scope. + * @param {string} statementType node.kind, one of: "var", "let", or "const" + * @param {ASTNode[]} declarations List of declarations + * @returns {boolean} Returns true if it is the first var declaration, false if not. + * @private + */ + function hasOnlyOneStatement(statementType, declarations) { + + var declarationCounts = countDeclarations(declarations); + var currentOptions = options[statementType] || {}; + var currentScope = getCurrentScope(statementType); + + if (currentOptions.uninitialized === MODE_ALWAYS && currentOptions.initialized === MODE_ALWAYS) { + if (currentScope.uninitialized || currentScope.initialized) { + return false; + } } - } - if (declarationCounts.uninitialized > 0) { - if (currentOptions.uninitialized === MODE_ALWAYS && currentScope.uninitialized) { - return false; + if (declarationCounts.uninitialized > 0) { + if (currentOptions.uninitialized === MODE_ALWAYS && currentScope.uninitialized) { + return false; + } } - } - if (declarationCounts.initialized > 0) { - if (currentOptions.initialized === MODE_ALWAYS && currentScope.initialized) { - return false; + if (declarationCounts.initialized > 0) { + if (currentOptions.initialized === MODE_ALWAYS && currentScope.initialized) { + return false; + } } + recordTypes(statementType, declarations, currentScope); + return true; } - recordTypes(statementType, declarations, currentScope); - return true; - } - - //-------------------------------------------------------------------------- - // Public API - //-------------------------------------------------------------------------- - - return { - "Program": startFunction, - "FunctionDeclaration": startFunction, - "FunctionExpression": startFunction, - "ArrowFunctionExpression": startFunction, - "BlockStatement": startBlock, - "ForStatement": startBlock, - "ForInStatement": startBlock, - "ForOfStatement": startBlock, - "SwitchStatement": startBlock, - - "VariableDeclaration": function(node) { - var parent = node.parent, - type, declarations, declarationCounts; - - type = node.kind; - if (!options[type]) { - return; - } - declarations = node.declarations; - declarationCounts = countDeclarations(declarations); + //-------------------------------------------------------------------------- + // Public API + //-------------------------------------------------------------------------- + + return { + Program: startFunction, + FunctionDeclaration: startFunction, + FunctionExpression: startFunction, + ArrowFunctionExpression: startFunction, + BlockStatement: startBlock, + ForStatement: startBlock, + ForInStatement: startBlock, + ForOfStatement: startBlock, + SwitchStatement: startBlock, + + VariableDeclaration: function(node) { + var parent = node.parent, + type, declarations, declarationCounts; + + type = node.kind; + if (!options[type]) { + return; + } - // always - if (!hasOnlyOneStatement(type, declarations)) { - if (options[type].initialized === MODE_ALWAYS && options[type].uninitialized === MODE_ALWAYS) { - context.report(node, "Combine this with the previous '" + type + "' statement."); - } else { - if (options[type].initialized === MODE_ALWAYS) { - context.report(node, "Combine this with the previous '" + type + "' statement with initialized variables."); - } - if (options[type].uninitialized === MODE_ALWAYS) { - context.report(node, "Combine this with the previous '" + type + "' statement with uninitialized variables."); + declarations = node.declarations; + declarationCounts = countDeclarations(declarations); + + // always + if (!hasOnlyOneStatement(type, declarations)) { + if (options[type].initialized === MODE_ALWAYS && options[type].uninitialized === MODE_ALWAYS) { + context.report(node, "Combine this with the previous '" + type + "' statement."); + } else { + if (options[type].initialized === MODE_ALWAYS) { + context.report(node, "Combine this with the previous '" + type + "' statement with initialized variables."); + } + if (options[type].uninitialized === MODE_ALWAYS) { + context.report(node, "Combine this with the previous '" + type + "' statement with uninitialized variables."); + } } } - } - // never - if (parent.type !== "ForStatement" || parent.init !== node) { - var totalDeclarations = declarationCounts.uninitialized + declarationCounts.initialized; + // never + if (parent.type !== "ForStatement" || parent.init !== node) { + var totalDeclarations = declarationCounts.uninitialized + declarationCounts.initialized; - if (totalDeclarations > 1) { + if (totalDeclarations > 1) { - if (options[type].initialized === MODE_NEVER && options[type].uninitialized === MODE_NEVER) { + if (options[type].initialized === MODE_NEVER && options[type].uninitialized === MODE_NEVER) { - // both initialized and uninitialized - context.report(node, "Split '" + type + "' declarations into multiple statements."); - } else if (options[type].initialized === MODE_NEVER && declarationCounts.initialized > 0) { + // both initialized and uninitialized + context.report(node, "Split '" + type + "' declarations into multiple statements."); + } else if (options[type].initialized === MODE_NEVER && declarationCounts.initialized > 0) { - // initialized - context.report(node, "Split initialized '" + type + "' declarations into multiple statements."); - } else if (options[type].uninitialized === MODE_NEVER && declarationCounts.uninitialized > 0) { + // initialized + context.report(node, "Split initialized '" + type + "' declarations into multiple statements."); + } else if (options[type].uninitialized === MODE_NEVER && declarationCounts.uninitialized > 0) { - // uninitialized - context.report(node, "Split uninitialized '" + type + "' declarations into multiple statements."); + // uninitialized + context.report(node, "Split uninitialized '" + type + "' declarations into multiple statements."); + } } } - } - }, + }, - "ForStatement:exit": endBlock, - "ForOfStatement:exit": endBlock, - "ForInStatement:exit": endBlock, - "SwitchStatement:exit": endBlock, - "BlockStatement:exit": endBlock, - "Program:exit": endFunction, - "FunctionDeclaration:exit": endFunction, - "FunctionExpression:exit": endFunction, - "ArrowFunctionExpression:exit": endFunction - }; + "ForStatement:exit": endBlock, + "ForOfStatement:exit": endBlock, + "ForInStatement:exit": endBlock, + "SwitchStatement:exit": endBlock, + "BlockStatement:exit": endBlock, + "Program:exit": endFunction, + "FunctionDeclaration:exit": endFunction, + "FunctionExpression:exit": endFunction, + "ArrowFunctionExpression:exit": endFunction + }; -}; - -module.exports.schema = [ - { - "oneOf": [ - { - "enum": ["always", "never"] - }, - { - "type": "object", - "properties": { - "var": { - "enum": ["always", "never"] - }, - "let": { - "enum": ["always", "never"] - }, - "const": { - "enum": ["always", "never"] - } - }, - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "initialized": { - "enum": ["always", "never"] - }, - "uninitialized": { - "enum": ["always", "never"] - } - }, - "additionalProperties": false - } - ] } -]; +}; diff --git a/tools/eslint/lib/rules/operator-assignment.js b/tools/eslint/lib/rules/operator-assignment.js index 9656846019d3a0..7e60c9efd40801 100644 --- a/tools/eslint/lib/rules/operator-assignment.js +++ b/tools/eslint/lib/rules/operator-assignment.js @@ -1,7 +1,6 @@ /** * @fileoverview Rule to replace assignment expressions with operator assignment * @author Brandon Mills - * @copyright 2014 Brandon Mills. All rights reserved. */ "use strict"; @@ -71,54 +70,64 @@ function same(a, b) { } } -module.exports = function(context) { - - /** - * Ensures that an assignment uses the shorthand form where possible. - * @param {ASTNode} node An AssignmentExpression node. - * @returns {void} - */ - function verify(node) { - var expr, left, operator; +module.exports = { + meta: { + docs: { + description: "require or disallow assignment operator shorthand where possible", + category: "Stylistic Issues", + recommended: false + }, + + schema: [ + { + enum: ["always", "never"] + } + ] + }, - if (node.operator !== "=" || node.right.type !== "BinaryExpression") { - return; - } + create: function(context) { - left = node.left; - expr = node.right; - operator = expr.operator; + /** + * Ensures that an assignment uses the shorthand form where possible. + * @param {ASTNode} node An AssignmentExpression node. + * @returns {void} + */ + function verify(node) { + var expr, left, operator; - if (isCommutativeOperatorWithShorthand(operator)) { - if (same(left, expr.left) || same(left, expr.right)) { - context.report(node, "Assignment can be replaced with operator assignment."); + if (node.operator !== "=" || node.right.type !== "BinaryExpression") { + return; } - } else if (isNonCommutativeOperatorWithShorthand(operator)) { - if (same(left, expr.left)) { - context.report(node, "Assignment can be replaced with operator assignment."); + + left = node.left; + expr = node.right; + operator = expr.operator; + + if (isCommutativeOperatorWithShorthand(operator)) { + if (same(left, expr.left) || same(left, expr.right)) { + context.report(node, "Assignment can be replaced with operator assignment."); + } + } else if (isNonCommutativeOperatorWithShorthand(operator)) { + if (same(left, expr.left)) { + context.report(node, "Assignment can be replaced with operator assignment."); + } } } - } - /** - * Warns if an assignment expression uses operator assignment shorthand. - * @param {ASTNode} node An AssignmentExpression node. - * @returns {void} - */ - function prohibit(node) { - if (node.operator !== "=") { - context.report(node, "Unexpected operator assignment shorthand."); + /** + * Warns if an assignment expression uses operator assignment shorthand. + * @param {ASTNode} node An AssignmentExpression node. + * @returns {void} + */ + function prohibit(node) { + if (node.operator !== "=") { + context.report(node, "Unexpected operator assignment shorthand."); + } } - } - return { - "AssignmentExpression": context.options[0] !== "never" ? verify : prohibit - }; + return { + AssignmentExpression: context.options[0] !== "never" ? verify : prohibit + }; -}; - -module.exports.schema = [ - { - "enum": ["always", "never"] } -]; +}; diff --git a/tools/eslint/lib/rules/operator-linebreak.js b/tools/eslint/lib/rules/operator-linebreak.js index aa3c03692839ba..85f90b908feca7 100644 --- a/tools/eslint/lib/rules/operator-linebreak.js +++ b/tools/eslint/lib/rules/operator-linebreak.js @@ -1,7 +1,6 @@ /** * @fileoverview Operator linebreak - enforces operator linebreak style of two types: after and before * @author Benoît Zugmeyer - * @copyright 2015 Benoît Zugmeyer. All rights reserved. */ "use strict"; @@ -13,136 +12,146 @@ var lodash = require("lodash"), // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "enforce consistent linebreak style for operators", + category: "Stylistic Issues", + recommended: false + }, - var usedDefaultGlobal = !context.options[0]; - var globalStyle = context.options[0] || "after"; - var options = context.options[1] || {}; - var styleOverrides = options.overrides ? lodash.assign({}, options.overrides) : {}; + schema: [ + { + enum: ["after", "before", "none", null] + }, + { + type: "object", + properties: { + overrides: { + type: "object", + properties: { + anyOf: { + type: "string", + enum: ["after", "before", "none", "ignore"] + } + } + } + }, + additionalProperties: false + } + ] + }, - if (usedDefaultGlobal && !styleOverrides["?"]) { - styleOverrides["?"] = "before"; - } + create: function(context) { - if (usedDefaultGlobal && !styleOverrides[":"]) { - styleOverrides[":"] = "before"; - } + var usedDefaultGlobal = !context.options[0]; + var globalStyle = context.options[0] || "after"; + var options = context.options[1] || {}; + var styleOverrides = options.overrides ? lodash.assign({}, options.overrides) : {}; - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- - - /** - * Checks the operator placement - * @param {ASTNode} node The node to check - * @param {ASTNode} leftSide The node that comes before the operator in `node` - * @private - * @returns {void} - */ - function validateNode(node, leftSide) { - var leftToken = context.getLastToken(leftSide); - var operatorToken = context.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 = context.getTokenAfter(operatorToken); + if (usedDefaultGlobal && !styleOverrides["?"]) { + styleOverrides["?"] = "before"; } - var rightToken = context.getTokenAfter(operatorToken); - var operator = operatorToken.value; - var operatorStyleOverride = styleOverrides[operator]; - var style = operatorStyleOverride || globalStyle; + if (usedDefaultGlobal && !styleOverrides[":"]) { + styleOverrides[":"] = "before"; + } - // if single line - if (astUtils.isTokenOnSameLine(leftToken, operatorToken) && - astUtils.isTokenOnSameLine(operatorToken, rightToken)) { + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- + + /** + * Checks the operator placement + * @param {ASTNode} node The node to check + * @param {ASTNode} leftSide The node that comes before the operator in `node` + * @private + * @returns {void} + */ + function validateNode(node, leftSide) { + var leftToken = context.getLastToken(leftSide); + var operatorToken = context.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 = context.getTokenAfter(operatorToken); + } - return; + var rightToken = context.getTokenAfter(operatorToken); + var operator = operatorToken.value; + var operatorStyleOverride = styleOverrides[operator]; + var style = operatorStyleOverride || globalStyle; - } else if (operatorStyleOverride !== "ignore" && !astUtils.isTokenOnSameLine(leftToken, operatorToken) && - !astUtils.isTokenOnSameLine(operatorToken, rightToken)) { + // if single line + if (astUtils.isTokenOnSameLine(leftToken, operatorToken) && + astUtils.isTokenOnSameLine(operatorToken, rightToken)) { - // lone operator - context.report(node, { - line: operatorToken.loc.end.line, - column: operatorToken.loc.end.column - }, "Bad line breaking before and after '" + operator + "'."); + return; - } else if (style === "before" && astUtils.isTokenOnSameLine(leftToken, operatorToken)) { + } else if (operatorStyleOverride !== "ignore" && !astUtils.isTokenOnSameLine(leftToken, operatorToken) && + !astUtils.isTokenOnSameLine(operatorToken, rightToken)) { - context.report(node, { - line: operatorToken.loc.end.line, - column: operatorToken.loc.end.column - }, "'" + operator + "' should be placed at the beginning of the line."); + // lone operator + context.report(node, { + line: operatorToken.loc.end.line, + column: operatorToken.loc.end.column + }, "Bad line breaking before and after '" + operator + "'."); - } else if (style === "after" && astUtils.isTokenOnSameLine(operatorToken, rightToken)) { + } else if (style === "before" && astUtils.isTokenOnSameLine(leftToken, operatorToken)) { - context.report(node, { - line: operatorToken.loc.end.line, - column: operatorToken.loc.end.column - }, "'" + operator + "' should be placed at the end of the line."); + context.report(node, { + line: operatorToken.loc.end.line, + column: operatorToken.loc.end.column + }, "'" + operator + "' should be placed at the beginning of the line."); - } else if (style === "none") { + } else if (style === "after" && astUtils.isTokenOnSameLine(operatorToken, rightToken)) { - context.report(node, { - line: operatorToken.loc.end.line, - column: operatorToken.loc.end.column - }, "There should be no line break before or after '" + operator + "'"); + context.report(node, { + line: operatorToken.loc.end.line, + column: operatorToken.loc.end.column + }, "'" + operator + "' should be placed at the end of the line."); - } - } + } else if (style === "none") { - /** - * Validates a binary expression using `validateNode` - * @param {BinaryExpression|LogicalExpression|AssignmentExpression} node node to be validated - * @returns {void} - */ - function validateBinaryExpression(node) { - validateNode(node, node.left); - } + context.report(node, { + line: operatorToken.loc.end.line, + column: operatorToken.loc.end.column + }, "There should be no line break before or after '" + operator + "'"); - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- - - return { - "BinaryExpression": validateBinaryExpression, - "LogicalExpression": validateBinaryExpression, - "AssignmentExpression": validateBinaryExpression, - "VariableDeclarator": function(node) { - if (node.init) { - validateNode(node, node.id); } - }, - "ConditionalExpression": function(node) { - validateNode(node, node.test); - validateNode(node, node.consequent); } - }; -}; -module.exports.schema = [ - { - "enum": ["after", "before", "none", null] - }, - { - "type": "object", - "properties": { - "overrides": { - "type": "object", - "properties": { - "anyOf": { - "type": "string", - "enum": ["after", "before", "none", "ignore"] - } + /** + * Validates a binary expression using `validateNode` + * @param {BinaryExpression|LogicalExpression|AssignmentExpression} node node to be validated + * @returns {void} + */ + function validateBinaryExpression(node) { + validateNode(node, node.left); + } + + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + return { + BinaryExpression: validateBinaryExpression, + LogicalExpression: validateBinaryExpression, + AssignmentExpression: validateBinaryExpression, + VariableDeclarator: function(node) { + if (node.init) { + validateNode(node, node.id); } + }, + ConditionalExpression: function(node) { + validateNode(node, node.test); + validateNode(node, node.consequent); } - }, - "additionalProperties": false + }; } -]; +}; diff --git a/tools/eslint/lib/rules/padded-blocks.js b/tools/eslint/lib/rules/padded-blocks.js index f245a858f072e6..39a2b07c8d862c 100644 --- a/tools/eslint/lib/rules/padded-blocks.js +++ b/tools/eslint/lib/rules/padded-blocks.js @@ -1,7 +1,6 @@ /** * @fileoverview A rule to ensure blank lines within blocks. * @author Mathias Schreck - * @copyright 2014 Mathias Schreck. All rights reserved. */ "use strict"; @@ -10,209 +9,219 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var options = {}; - var config = context.options[0] || "always"; +module.exports = { + meta: { + docs: { + description: "require or disallow padding within blocks", + category: "Stylistic Issues", + recommended: false + }, - if (typeof config === "string") { - options.blocks = config === "always"; - } else { - if (config.hasOwnProperty("blocks")) { - options.blocks = config.blocks === "always"; - } - if (config.hasOwnProperty("switches")) { - options.switches = config.switches === "always"; - } - if (config.hasOwnProperty("classes")) { - options.classes = config.classes === "always"; + schema: [ + { + oneOf: [ + { + enum: ["always", "never"] + }, + { + type: "object", + properties: { + blocks: { + enum: ["always", "never"] + }, + switches: { + enum: ["always", "never"] + }, + classes: { + enum: ["always", "never"] + } + }, + additionalProperties: false, + minProperties: 1 + } + ] + } + ] + }, + + create: function(context) { + var options = {}; + var config = context.options[0] || "always"; + + if (typeof config === "string") { + options.blocks = config === "always"; + } else { + if (config.hasOwnProperty("blocks")) { + options.blocks = config.blocks === "always"; + } + if (config.hasOwnProperty("switches")) { + options.switches = config.switches === "always"; + } + if (config.hasOwnProperty("classes")) { + options.classes = config.classes === "always"; + } } - } - var ALWAYS_MESSAGE = "Block must be padded by blank lines.", - NEVER_MESSAGE = "Block must not be padded by blank lines."; + var ALWAYS_MESSAGE = "Block must be padded by blank lines.", + NEVER_MESSAGE = "Block must not be padded by blank lines."; - var sourceCode = context.getSourceCode(); + var sourceCode = context.getSourceCode(); - /** - * Gets the open brace token from a given node. - * @param {ASTNode} node - A BlockStatement or SwitchStatement node from which to get the open brace. - * @returns {Token} The token of the open brace. - */ - function getOpenBrace(node) { - if (node.type === "SwitchStatement") { - return sourceCode.getTokenBefore(node.cases[0]); + /** + * Gets the open brace token from a given node. + * @param {ASTNode} node - A BlockStatement or SwitchStatement node from which to get the open brace. + * @returns {Token} The token of the open brace. + */ + function getOpenBrace(node) { + if (node.type === "SwitchStatement") { + return sourceCode.getTokenBefore(node.cases[0]); + } + return sourceCode.getFirstToken(node); } - return sourceCode.getFirstToken(node); - } - - /** - * Checks if the given parameter is a comment node - * @param {ASTNode|Token} node An AST node or token - * @returns {boolean} True if node is a comment - */ - function isComment(node) { - return node.type === "Line" || node.type === "Block"; - } - /** - * 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) { - var tokenStartLine = token.loc.start.line, - expectedFirstLine = tokenStartLine + 2, - first, - firstLine; - - first = token; - do { - first = sourceCode.getTokenOrCommentAfter(first); - } while (isComment(first) && first.loc.start.line === tokenStartLine); - - firstLine = first.loc.start.line; - return expectedFirstLine <= firstLine; - } + /** + * Checks if the given parameter is a comment node + * @param {ASTNode|Token} node An AST node or token + * @returns {boolean} True if node is a comment + */ + function isComment(node) { + return node.type === "Line" || node.type === "Block"; + } - /** - * Checks if the given token is preceeded by a blank line. - * @param {Token} token The token to check - * @returns {boolean} Whether or not the token is preceeded by a blank line - */ - function isTokenBottomPadded(token) { - var blockEnd = token.loc.end.line, - expectedLastLine = blockEnd - 2, - last, - lastLine; - - last = token; - do { - last = sourceCode.getTokenOrCommentBefore(last); - } while (isComment(last) && last.loc.end.line === blockEnd); - - lastLine = last.loc.end.line; - return lastLine <= expectedLastLine; - } + /** + * 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) { + var tokenStartLine = token.loc.start.line, + expectedFirstLine = tokenStartLine + 2, + first, + firstLine; + + first = token; + do { + first = sourceCode.getTokenOrCommentAfter(first); + } while (isComment(first) && first.loc.start.line === tokenStartLine); + + firstLine = first.loc.start.line; + return expectedFirstLine <= firstLine; + } - /** - * Checks if a node should be padded, according to the rule config. - * @param {ASTNode} node The AST node to check. - * @returns {boolean} True if the node should be padded, false otherwise. - */ - function requirePaddingFor(node) { - switch (node.type) { - case "BlockStatement": - return options.blocks; - case "SwitchStatement": - return options.switches; - case "ClassBody": - return options.classes; - - /* istanbul ignore next */ - default: - throw new Error("unreachable"); + /** + * Checks if the given token is preceeded by a blank line. + * @param {Token} token The token to check + * @returns {boolean} Whether or not the token is preceeded by a blank line + */ + function isTokenBottomPadded(token) { + var blockEnd = token.loc.end.line, + expectedLastLine = blockEnd - 2, + last, + lastLine; + + last = token; + do { + last = sourceCode.getTokenOrCommentBefore(last); + } while (isComment(last) && last.loc.end.line === blockEnd); + + lastLine = last.loc.end.line; + return lastLine <= expectedLastLine; } - } - /** - * Checks the given BlockStatement node to be padded if the block is not empty. - * @param {ASTNode} node The AST node of a BlockStatement. - * @returns {void} undefined. - */ - function checkPadding(node) { - var openBrace = getOpenBrace(node), - closeBrace = sourceCode.getLastToken(node), - blockHasTopPadding = isTokenTopPadded(openBrace), - blockHasBottomPadding = isTokenBottomPadded(closeBrace); - - if (requirePaddingFor(node)) { - if (!blockHasTopPadding) { - context.report({ - node: node, - loc: { line: openBrace.loc.start.line, column: openBrace.loc.start.column }, - message: ALWAYS_MESSAGE - }); - } - if (!blockHasBottomPadding) { - context.report({ - node: node, - loc: {line: closeBrace.loc.end.line, column: closeBrace.loc.end.column - 1 }, - message: ALWAYS_MESSAGE - }); - } - } else { - if (blockHasTopPadding) { - context.report({ - node: node, - loc: { line: openBrace.loc.start.line, column: openBrace.loc.start.column }, - message: NEVER_MESSAGE - }); + /** + * Checks if a node should be padded, according to the rule config. + * @param {ASTNode} node The AST node to check. + * @returns {boolean} True if the node should be padded, false otherwise. + */ + function requirePaddingFor(node) { + switch (node.type) { + case "BlockStatement": + return options.blocks; + case "SwitchStatement": + return options.switches; + case "ClassBody": + return options.classes; + + /* istanbul ignore next */ + default: + throw new Error("unreachable"); } + } - if (blockHasBottomPadding) { - context.report({ - node: node, - loc: {line: closeBrace.loc.end.line, column: closeBrace.loc.end.column - 1 }, - message: NEVER_MESSAGE - }); + /** + * Checks the given BlockStatement node to be padded if the block is not empty. + * @param {ASTNode} node The AST node of a BlockStatement. + * @returns {void} undefined. + */ + function checkPadding(node) { + var openBrace = getOpenBrace(node), + closeBrace = sourceCode.getLastToken(node), + blockHasTopPadding = isTokenTopPadded(openBrace), + blockHasBottomPadding = isTokenBottomPadded(closeBrace); + + if (requirePaddingFor(node)) { + if (!blockHasTopPadding) { + context.report({ + node: node, + loc: { line: openBrace.loc.start.line, column: openBrace.loc.start.column }, + message: ALWAYS_MESSAGE + }); + } + if (!blockHasBottomPadding) { + context.report({ + node: node, + loc: {line: closeBrace.loc.end.line, column: closeBrace.loc.end.column - 1 }, + message: ALWAYS_MESSAGE + }); + } + } else { + if (blockHasTopPadding) { + context.report({ + node: node, + loc: { line: openBrace.loc.start.line, column: openBrace.loc.start.column }, + message: NEVER_MESSAGE + }); + } + + if (blockHasBottomPadding) { + context.report({ + node: node, + loc: {line: closeBrace.loc.end.line, column: closeBrace.loc.end.column - 1 }, + message: NEVER_MESSAGE + }); + } } } - } - - var rule = {}; - if (options.hasOwnProperty("switches")) { - rule.SwitchStatement = function(node) { - if (node.cases.length === 0) { - return; - } - checkPadding(node); - }; - } + var rule = {}; - if (options.hasOwnProperty("blocks")) { - rule.BlockStatement = function(node) { - if (node.body.length === 0) { - return; - } - checkPadding(node); - }; - } + if (options.hasOwnProperty("switches")) { + rule.SwitchStatement = function(node) { + if (node.cases.length === 0) { + return; + } + checkPadding(node); + }; + } - if (options.hasOwnProperty("classes")) { - rule.ClassBody = function(node) { - if (node.body.length === 0) { - return; - } - checkPadding(node); - }; - } + if (options.hasOwnProperty("blocks")) { + rule.BlockStatement = function(node) { + if (node.body.length === 0) { + return; + } + checkPadding(node); + }; + } - return rule; -}; + if (options.hasOwnProperty("classes")) { + rule.ClassBody = function(node) { + if (node.body.length === 0) { + return; + } + checkPadding(node); + }; + } -module.exports.schema = [ - { - "oneOf": [ - { - "enum": ["always", "never"] - }, - { - "type": "object", - "properties": { - "blocks": { - "enum": ["always", "never"] - }, - "switches": { - "enum": ["always", "never"] - }, - "classes": { - "enum": ["always", "never"] - } - }, - "additionalProperties": false, - "minProperties": 1 - } - ] + return rule; } -]; +}; diff --git a/tools/eslint/lib/rules/prefer-arrow-callback.js b/tools/eslint/lib/rules/prefer-arrow-callback.js index a51fa6026e30e3..4c4c2e6f2b10b6 100644 --- a/tools/eslint/lib/rules/prefer-arrow-callback.js +++ b/tools/eslint/lib/rules/prefer-arrow-callback.js @@ -1,7 +1,6 @@ /** * @fileoverview A rule to suggest using arrow functions as callbacks. * @author Toru Nagashima - * @copyright 2015 Toru Nagashima. All rights reserved. */ "use strict"; @@ -27,11 +26,6 @@ function isFunctionName(variable) { * @returns {boolean} `true` if the node is the specific value. */ function checkMetaProperty(node, metaName, propertyName) { - - // TODO: Remove this if block after https://github.com/eslint/espree/issues/206 was fixed. - if (typeof node.meta === "string") { - return node.meta === metaName && node.property === propertyName; - } return node.meta.name === metaName && node.property.name === propertyName; } @@ -125,104 +119,136 @@ function getCallbackInfo(node) { // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - /* - * {Array<{this: boolean, super: boolean, meta: boolean}>} - * - this - A flag which shows there are one or more ThisExpression. - * - super - A flag which shows there are one or more Super. - * - meta - A flag which shows there are one or more MethProperty. - */ - var stack = []; - - /** - * Pushes new function scope with all `false` flags. - * @returns {void} - */ - function enterScope() { - stack.push({this: false, super: false, meta: false}); - } +module.exports = { + meta: { + docs: { + description: "require arrow functions as callbacks", + category: "ECMAScript 6", + recommended: false + }, - /** - * Pops a function scope from the stack. - * @returns {{this: boolean, super: boolean, meta: boolean}} The information of the last scope. - */ - function exitScope() { - return stack.pop(); - } + schema: [ + { + type: "object", + properties: { + allowNamedFunctions: { + type: "boolean" + }, + allowUnboundThis: { + type: "boolean" + } + }, + additionalProperties: false + } + ] + }, + + create: function(context) { + var options = context.options[0] || {}; + + var allowUnboundThis = options.allowUnboundThis !== false; // default to true + var allowNamedFunctions = options.allowNamedFunctions; + + /* + * {Array<{this: boolean, super: boolean, meta: boolean}>} + * - this - A flag which shows there are one or more ThisExpression. + * - super - A flag which shows there are one or more Super. + * - meta - A flag which shows there are one or more MethProperty. + */ + var stack = []; + + /** + * Pushes new function scope with all `false` flags. + * @returns {void} + */ + function enterScope() { + stack.push({this: false, super: false, meta: false}); + } - return { + /** + * Pops a function scope from the stack. + * @returns {{this: boolean, super: boolean, meta: boolean}} The information of the last scope. + */ + function exitScope() { + return stack.pop(); + } - // Reset internal state. - Program: function() { - stack = []; - }, + return { - // If there are below, it cannot replace with arrow functions merely. - ThisExpression: function() { - var info = stack[stack.length - 1]; + // Reset internal state. + Program: function() { + stack = []; + }, - if (info) { - info.this = true; - } - }, + // If there are below, it cannot replace with arrow functions merely. + ThisExpression: function() { + var info = stack[stack.length - 1]; - Super: function() { - var info = stack[stack.length - 1]; + if (info) { + info.this = true; + } + }, - if (info) { - info.super = true; - } - }, + Super: function() { + var info = stack[stack.length - 1]; - MetaProperty: function(node) { - var info = stack[stack.length - 1]; + if (info) { + info.super = true; + } + }, - if (info && checkMetaProperty(node, "new", "target")) { - info.meta = true; - } - }, + MetaProperty: function(node) { + var info = stack[stack.length - 1]; - // To skip nested scopes. - FunctionDeclaration: enterScope, - "FunctionDeclaration:exit": exitScope, + if (info && checkMetaProperty(node, "new", "target")) { + info.meta = true; + } + }, - // Main. - FunctionExpression: enterScope, - "FunctionExpression:exit": function(node) { - var scopeInfo = exitScope(); + // To skip nested scopes. + FunctionDeclaration: enterScope, + "FunctionDeclaration:exit": exitScope, - // Skip generators. - if (node.generator) { - return; - } + // Main. + FunctionExpression: enterScope, + "FunctionExpression:exit": function(node) { + var scopeInfo = exitScope(); - // Skip recursive functions. - var nameVar = context.getDeclaredVariables(node)[0]; + // Skip named function expressions + if (allowNamedFunctions && node.id && node.id.name) { + return; + } - if (isFunctionName(nameVar) && nameVar.references.length > 0) { - return; - } + // Skip generators. + if (node.generator) { + return; + } - // Skip if it's using arguments. - var variable = getVariableOfArguments(context.getScope()); + // Skip recursive functions. + var nameVar = context.getDeclaredVariables(node)[0]; - if (variable && variable.references.length > 0) { - return; - } + if (isFunctionName(nameVar) && nameVar.references.length > 0) { + return; + } - // Reports if it's a callback which can replace with arrows. - var callbackInfo = getCallbackInfo(node); + // Skip if it's using arguments. + var variable = getVariableOfArguments(context.getScope()); - if (callbackInfo.isCallback && - (!scopeInfo.this || callbackInfo.isLexicalThis) && - !scopeInfo.super && - !scopeInfo.meta - ) { - context.report(node, "Unexpected function expression."); + if (variable && variable.references.length > 0) { + return; + } + + // Reports if it's a callback which can replace with arrows. + var callbackInfo = getCallbackInfo(node); + + if (callbackInfo.isCallback && + (!allowUnboundThis || !scopeInfo.this || callbackInfo.isLexicalThis) && + !scopeInfo.super && + !scopeInfo.meta + ) { + context.report(node, "Unexpected function expression."); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/prefer-const.js b/tools/eslint/lib/rules/prefer-const.js index ae55b516450756..668453520fc29d 100644 --- a/tools/eslint/lib/rules/prefer-const.js +++ b/tools/eslint/lib/rules/prefer-const.js @@ -1,7 +1,6 @@ /** * @fileoverview A rule to suggest using of const declaration for variables that are never reassigned after declared. * @author Toru Nagashima - * @copyright 2015 Toru Nagashima. All rights reserved. */ "use strict"; @@ -179,90 +178,100 @@ function groupByDestructuring(variables) { // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var options = context.options[0] || {}; - var checkingMixedDestructuring = options.destructuring !== "all"; - var variables = null; - - /** - * Reports a given reference. - * - * @param {escope.Reference} reference - A reference to report. - * @returns {void} - */ - function report(reference) { - var id = reference.identifier; - - context.report({ - node: id, - message: "'{{name}}' is never reassigned, use 'const' instead.", - data: id - }); - } +module.exports = { + meta: { + docs: { + description: "require `const` declarations for variables that are never reassigned after declared", + category: "ECMAScript 6", + recommended: false + }, - /** - * Reports a given variable if the variable should be declared as const. - * - * @param {escope.Variable} variable - A variable to report. - * @returns {void} - */ - function checkVariable(variable) { - var writer = getWriteReferenceIfShouldBeConst(variable); + schema: [ + { + type: "object", + properties: { + destructuring: {enum: ["any", "all"]} + }, + additionalProperties: false + } + ] + }, + + create: function(context) { + var options = context.options[0] || {}; + var checkingMixedDestructuring = options.destructuring !== "all"; + var variables = null; + + /** + * Reports a given reference. + * + * @param {escope.Reference} reference - A reference to report. + * @returns {void} + */ + function report(reference) { + var id = reference.identifier; - if (writer) { - report(writer); + context.report({ + node: id, + message: "'{{name}}' is never reassigned, use 'const' instead.", + data: id + }); } - } - /** - * Reports given references if all of the reference should be declared as - * const. - * - * The argument 'writers' is an array of references. - * This reference is the result of - * 'getWriteReferenceIfShouldBeConst(variable)', so it's nullable. - * In simple declaration or assignment cases, the length of the array is 1. - * In destructuring cases, the length of the array can be 2 or more. - * - * @param {(escope.Reference|null)[]} writers - References which are grouped - * by destructuring to report. - * @returns {void} - */ - function checkGroup(writers) { - if (writers.every(Boolean)) { - writers.forEach(report); + /** + * Reports a given variable if the variable should be declared as const. + * + * @param {escope.Variable} variable - A variable to report. + * @returns {void} + */ + function checkVariable(variable) { + var writer = getWriteReferenceIfShouldBeConst(variable); + + if (writer) { + report(writer); + } } - } - return { - "Program": function() { - variables = []; - }, - - "Program:exit": function() { - if (checkingMixedDestructuring) { - variables.forEach(checkVariable); - } else { - groupByDestructuring(variables).forEach(checkGroup); + /** + * Reports given references if all of the reference should be declared as + * const. + * + * The argument 'writers' is an array of references. + * This reference is the result of + * 'getWriteReferenceIfShouldBeConst(variable)', so it's nullable. + * In simple declaration or assignment cases, the length of the array is 1. + * In destructuring cases, the length of the array can be 2 or more. + * + * @param {(escope.Reference|null)[]} writers - References which are grouped + * by destructuring to report. + * @returns {void} + */ + function checkGroup(writers) { + if (writers.every(Boolean)) { + writers.forEach(report); } + } - variables = null; - }, + return { + Program: function() { + variables = []; + }, - "VariableDeclaration": function(node) { - if (node.kind === "let" && !isInitOfForStatement(node)) { - pushAll(variables, context.getDeclaredVariables(node)); - } - } - }; -}; + "Program:exit": function() { + if (checkingMixedDestructuring) { + variables.forEach(checkVariable); + } else { + groupByDestructuring(variables).forEach(checkGroup); + } -module.exports.schema = [ - { - type: "object", - properties: { - destructuring: {enum: ["any", "all"]} - }, - additionalProperties: false + variables = null; + }, + + VariableDeclaration: function(node) { + if (node.kind === "let" && !isInitOfForStatement(node)) { + pushAll(variables, context.getDeclaredVariables(node)); + } + } + }; } -]; +}; diff --git a/tools/eslint/lib/rules/prefer-reflect.js b/tools/eslint/lib/rules/prefer-reflect.js index 83b805a30d99b9..38bb093ba6f509 100644 --- a/tools/eslint/lib/rules/prefer-reflect.js +++ b/tools/eslint/lib/rules/prefer-reflect.js @@ -1,7 +1,6 @@ /** * @fileoverview Rule to suggest using "Reflect" api over Function/Object methods * @author Keith Cirkel - * @copyright 2015 Keith Cirkel. All rights reserved. */ "use strict"; @@ -9,94 +8,104 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var existingNames = { - "apply": "Function.prototype.apply", - "call": "Function.prototype.call", - "defineProperty": "Object.defineProperty", - "getOwnPropertyDescriptor": "Object.getOwnPropertyDescriptor", - "getPrototypeOf": "Object.getPrototypeOf", - "setPrototypeOf": "Object.setPrototypeOf", - "isExtensible": "Object.isExtensible", - "getOwnPropertyNames": "Object.getOwnPropertyNames", - "preventExtensions": "Object.preventExtensions" - }; +module.exports = { + meta: { + docs: { + description: "require `Reflect` methods where applicable", + category: "ECMAScript 6", + recommended: false + }, - var reflectSubsitutes = { - "apply": "Reflect.apply", - "call": "Reflect.apply", - "defineProperty": "Reflect.defineProperty", - "getOwnPropertyDescriptor": "Reflect.getOwnPropertyDescriptor", - "getPrototypeOf": "Reflect.getPrototypeOf", - "setPrototypeOf": "Reflect.setPrototypeOf", - "isExtensible": "Reflect.isExtensible", - "getOwnPropertyNames": "Reflect.getOwnPropertyNames", - "preventExtensions": "Reflect.preventExtensions" - }; + schema: [ + { + type: "object", + properties: { + exceptions: { + type: "array", + items: { + enum: [ + "apply", + "call", + "delete", + "defineProperty", + "getOwnPropertyDescriptor", + "getPrototypeOf", + "setPrototypeOf", + "isExtensible", + "getOwnPropertyNames", + "preventExtensions" + ] + }, + uniqueItems: true + } + }, + additionalProperties: false + } + ] + }, - var exceptions = (context.options[0] || {}).exceptions || []; + create: function(context) { + var existingNames = { + apply: "Function.prototype.apply", + call: "Function.prototype.call", + defineProperty: "Object.defineProperty", + getOwnPropertyDescriptor: "Object.getOwnPropertyDescriptor", + getPrototypeOf: "Object.getPrototypeOf", + setPrototypeOf: "Object.setPrototypeOf", + isExtensible: "Object.isExtensible", + getOwnPropertyNames: "Object.getOwnPropertyNames", + preventExtensions: "Object.preventExtensions" + }; - /** - * Reports the Reflect violation based on the `existing` and `substitute` - * @param {Object} node The node that violates the rule. - * @param {string} existing The existing method name that has been used. - * @param {string} substitute The Reflect substitute that should be used. - * @returns {void} - */ - function report(node, existing, substitute) { - context.report(node, "Avoid using {{existing}}, instead use {{substitute}}", { - existing: existing, - substitute: substitute - }); - } + var reflectSubsitutes = { + apply: "Reflect.apply", + call: "Reflect.apply", + defineProperty: "Reflect.defineProperty", + getOwnPropertyDescriptor: "Reflect.getOwnPropertyDescriptor", + getPrototypeOf: "Reflect.getPrototypeOf", + setPrototypeOf: "Reflect.setPrototypeOf", + isExtensible: "Reflect.isExtensible", + getOwnPropertyNames: "Reflect.getOwnPropertyNames", + preventExtensions: "Reflect.preventExtensions" + }; - return { - "CallExpression": function(node) { - var methodName = (node.callee.property || {}).name; - var isReflectCall = (node.callee.object || {}).name === "Reflect"; - var hasReflectSubsitute = reflectSubsitutes.hasOwnProperty(methodName); - var userConfiguredException = exceptions.indexOf(methodName) !== -1; - - if (hasReflectSubsitute && !isReflectCall && !userConfiguredException) { - report(node, existingNames[methodName], reflectSubsitutes[methodName]); - } - }, - "UnaryExpression": function(node) { - var isDeleteOperator = node.operator === "delete"; - var targetsIdentifier = node.argument.type === "Identifier"; - var userConfiguredException = exceptions.indexOf("delete") !== -1; + var exceptions = (context.options[0] || {}).exceptions || []; - if (isDeleteOperator && !targetsIdentifier && !userConfiguredException) { - report(node, "the delete keyword", "Reflect.deleteProperty"); - } + /** + * Reports the Reflect violation based on the `existing` and `substitute` + * @param {Object} node The node that violates the rule. + * @param {string} existing The existing method name that has been used. + * @param {string} substitute The Reflect substitute that should be used. + * @returns {void} + */ + function report(node, existing, substitute) { + context.report(node, "Avoid using {{existing}}, instead use {{substitute}}", { + existing: existing, + substitute: substitute + }); } - }; -}; + return { + CallExpression: function(node) { + var methodName = (node.callee.property || {}).name; + var isReflectCall = (node.callee.object || {}).name === "Reflect"; + var hasReflectSubsitute = reflectSubsitutes.hasOwnProperty(methodName); + var userConfiguredException = exceptions.indexOf(methodName) !== -1; -module.exports.schema = [ - { - "type": "object", - "properties": { - "exceptions": { - "type": "array", - "items": { - "enum": [ - "apply", - "call", - "delete", - "defineProperty", - "getOwnPropertyDescriptor", - "getPrototypeOf", - "setPrototypeOf", - "isExtensible", - "getOwnPropertyNames", - "preventExtensions" - ] - }, - "uniqueItems": true + if (hasReflectSubsitute && !isReflectCall && !userConfiguredException) { + report(node, existingNames[methodName], reflectSubsitutes[methodName]); + } + }, + UnaryExpression: function(node) { + var isDeleteOperator = node.operator === "delete"; + var targetsIdentifier = node.argument.type === "Identifier"; + var userConfiguredException = exceptions.indexOf("delete") !== -1; + + if (isDeleteOperator && !targetsIdentifier && !userConfiguredException) { + report(node, "the delete keyword", "Reflect.deleteProperty"); + } } - }, - "additionalProperties": false + }; + } -]; +}; diff --git a/tools/eslint/lib/rules/prefer-rest-params.js b/tools/eslint/lib/rules/prefer-rest-params.js index d52c1164cbf7d4..0ce1d8a1220b28 100644 --- a/tools/eslint/lib/rules/prefer-rest-params.js +++ b/tools/eslint/lib/rules/prefer-rest-params.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to * @author Toru Nagashima - * @copyright 2015 Toru Nagashima. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; @@ -38,38 +36,48 @@ function getVariableOfArguments(scope) { // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "require rest parameters instead of `arguments`", + category: "ECMAScript 6", + recommended: false + }, - /** - * Reports a given reference. - * - * @param {escope.Reference} reference - A reference to report. - * @returns {void} - */ - function report(reference) { - context.report({ - node: reference.identifier, - message: "Use the rest parameters instead of 'arguments'." - }); - } + schema: [] + }, - /** - * Reports references of the implicit `arguments` variable if exist. - * - * @returns {void} - */ - function checkForArguments() { - var argumentsVar = getVariableOfArguments(context.getScope()); + create: function(context) { - if (argumentsVar) { - argumentsVar.references.forEach(report); + /** + * Reports a given reference. + * + * @param {escope.Reference} reference - A reference to report. + * @returns {void} + */ + function report(reference) { + context.report({ + node: reference.identifier, + message: "Use the rest parameters instead of 'arguments'." + }); } - } - return { - FunctionDeclaration: checkForArguments, - FunctionExpression: checkForArguments - }; -}; + /** + * Reports references of the implicit `arguments` variable if exist. + * + * @returns {void} + */ + function checkForArguments() { + var argumentsVar = getVariableOfArguments(context.getScope()); -module.exports.schema = []; + if (argumentsVar) { + argumentsVar.references.forEach(report); + } + } + + return { + FunctionDeclaration: checkForArguments, + FunctionExpression: checkForArguments + }; + } +}; diff --git a/tools/eslint/lib/rules/prefer-spread.js b/tools/eslint/lib/rules/prefer-spread.js index de0cbbe5320498..79c7eb0243bd45 100644 --- a/tools/eslint/lib/rules/prefer-spread.js +++ b/tools/eslint/lib/rules/prefer-spread.js @@ -1,7 +1,6 @@ /** * @fileoverview A rule to suggest using of the spread operator instead of `.apply()`. * @author Toru Nagashima - * @copyright 2015 Toru Nagashima. All rights reserved. */ "use strict"; @@ -71,22 +70,32 @@ function isValidThisArg(expectedThis, thisArg, context) { // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - return { - "CallExpression": function(node) { - if (!isVariadicApplyCalling(node)) { - return; - } +module.exports = { + meta: { + docs: { + description: "require spread operators instead of `.apply()`", + category: "ECMAScript 6", + recommended: false + }, + + schema: [] + }, + + create: function(context) { + return { + CallExpression: function(node) { + if (!isVariadicApplyCalling(node)) { + return; + } - var applied = node.callee.object; - var expectedThis = (applied.type === "MemberExpression") ? applied.object : null; - var thisArg = node.arguments[0]; + var applied = node.callee.object; + var expectedThis = (applied.type === "MemberExpression") ? applied.object : null; + var thisArg = node.arguments[0]; - if (isValidThisArg(expectedThis, thisArg, context)) { - context.report(node, "use the spread operator instead of the '.apply()'."); + if (isValidThisArg(expectedThis, thisArg, context)) { + context.report(node, "use the spread operator instead of the '.apply()'."); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/prefer-template.js b/tools/eslint/lib/rules/prefer-template.js index 19b3d10c0ab7a6..0165aaecd65d8c 100644 --- a/tools/eslint/lib/rules/prefer-template.js +++ b/tools/eslint/lib/rules/prefer-template.js @@ -1,7 +1,6 @@ /** * @fileoverview A rule to suggest using template literals instead of string concatenation. * @author Toru Nagashima - * @copyright 2015 Toru Nagashima. All rights reserved. */ "use strict"; @@ -55,43 +54,53 @@ function hasNonStringLiteral(node) { // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var done = Object.create(null); - - /** - * Reports if a given node is string concatenation with non string literals. - * - * @param {ASTNode} node - A node to check. - * @returns {void} - */ - function checkForStringConcat(node) { - if (!astUtils.isStringLiteral(node) || !isConcatenation(node.parent)) { - return; - } - - var topBinaryExpr = getTopConcatBinaryExpression(node.parent); +module.exports = { + meta: { + docs: { + description: "require template literals instead of string concatenation", + category: "ECMAScript 6", + recommended: false + }, - // Checks whether or not this node had been checked already. - if (done[topBinaryExpr.range[0]]) { - return; + schema: [] + }, + + create: function(context) { + var done = Object.create(null); + + /** + * Reports if a given node is string concatenation with non string literals. + * + * @param {ASTNode} node - A node to check. + * @returns {void} + */ + function checkForStringConcat(node) { + if (!astUtils.isStringLiteral(node) || !isConcatenation(node.parent)) { + return; + } + + var topBinaryExpr = getTopConcatBinaryExpression(node.parent); + + // Checks whether or not this node had been checked already. + if (done[topBinaryExpr.range[0]]) { + return; + } + done[topBinaryExpr.range[0]] = true; + + if (hasNonStringLiteral(topBinaryExpr)) { + context.report( + topBinaryExpr, + "Unexpected string concatenation."); + } } - done[topBinaryExpr.range[0]] = true; - if (hasNonStringLiteral(topBinaryExpr)) { - context.report( - topBinaryExpr, - "Unexpected string concatenation."); - } - } + return { + Program: function() { + done = Object.create(null); + }, - return { - Program: function() { - done = Object.create(null); - }, - - Literal: checkForStringConcat, - TemplateLiteral: checkForStringConcat - }; + Literal: checkForStringConcat, + TemplateLiteral: checkForStringConcat + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/quote-props.js b/tools/eslint/lib/rules/quote-props.js index f3453adb063af2..1fd2e74a5a34c4 100644 --- a/tools/eslint/lib/rules/quote-props.js +++ b/tools/eslint/lib/rules/quote-props.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to flag non-quoted property names in object literals. * @author Mathias Bynens - * @copyright 2014 Brandon Mills. All rights reserved. - * @copyright 2015 Tomasz Olędzki. All rights reserved. */ "use strict"; @@ -17,207 +15,217 @@ var espree = require("espree"), // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - var MODE = context.options[0], - KEYWORDS = context.options[1] && context.options[1].keywords, - CHECK_UNNECESSARY = !context.options[1] || context.options[1].unnecessary !== false, - NUMBERS = context.options[1] && context.options[1].numbers, - - MESSAGE_UNNECESSARY = "Unnecessarily quoted property '{{property}}' found.", - MESSAGE_UNQUOTED = "Unquoted property '{{property}}' found.", - MESSAGE_NUMERIC = "Unquoted number literal '{{property}}' used as key.", - MESSAGE_RESERVED = "Unquoted reserved word '{{property}}' used as key."; - - - /** - * Checks whether a certain string constitutes an ES3 token - * @param {string} tokenStr - The string to be checked. - * @returns {boolean} `true` if it is an ES3 token. - */ - function isKeyword(tokenStr) { - return keywords.indexOf(tokenStr) >= 0; - } - - /** - * Checks if an espree-tokenized key has redundant quotes (i.e. whether quotes are unnecessary) - * @param {string} rawKey The raw key value from the source - * @param {espreeTokens} tokens The espree-tokenized node key - * @param {boolean} [skipNumberLiterals=false] Indicates whether number literals should be checked - * @returns {boolean} Whether or not a key has redundant quotes. - * @private - */ - function areQuotesRedundant(rawKey, tokens, skipNumberLiterals) { - return tokens.length === 1 && tokens[0].start === 0 && tokens[0].end === rawKey.length && - (["Identifier", "Keyword", "Null", "Boolean"].indexOf(tokens[0].type) >= 0 || - (tokens[0].type === "Numeric" && !skipNumberLiterals && "" + +tokens[0].value === tokens[0].value)); - } +module.exports = { + meta: { + docs: { + description: "require quotes around object literal property names", + category: "Stylistic Issues", + recommended: false + }, - /** - * Ensures that a property's key is quoted only when necessary - * @param {ASTNode} node Property AST node - * @returns {void} - */ - function checkUnnecessaryQuotes(node) { - var key = node.key, - isKeywordToken, - tokens; - - if (node.method || node.computed || node.shorthand) { - return; + schema: { + anyOf: [ + { + type: "array", + items: [ + { + enum: ["always", "as-needed", "consistent", "consistent-as-needed"] + } + ], + minItems: 0, + maxItems: 1 + }, + { + type: "array", + items: [ + { + enum: ["always", "as-needed", "consistent", "consistent-as-needed"] + }, + { + type: "object", + properties: { + keywords: { + type: "boolean" + }, + unnecessary: { + type: "boolean" + }, + numbers: { + type: "boolean" + } + }, + additionalProperties: false + } + ], + minItems: 0, + maxItems: 2 + } + ] } + }, - if (key.type === "Literal" && typeof key.value === "string") { - try { - tokens = espree.tokenize(key.value); - } catch (e) { - return; - } + create: function(context) { - if (tokens.length !== 1) { - return; - } + var MODE = context.options[0], + KEYWORDS = context.options[1] && context.options[1].keywords, + CHECK_UNNECESSARY = !context.options[1] || context.options[1].unnecessary !== false, + NUMBERS = context.options[1] && context.options[1].numbers, - isKeywordToken = isKeyword(tokens[0].value); + MESSAGE_UNNECESSARY = "Unnecessarily quoted property '{{property}}' found.", + MESSAGE_UNQUOTED = "Unquoted property '{{property}}' found.", + MESSAGE_NUMERIC = "Unquoted number literal '{{property}}' used as key.", + MESSAGE_RESERVED = "Unquoted reserved word '{{property}}' used as key."; - if (isKeywordToken && KEYWORDS) { - return; - } - if (CHECK_UNNECESSARY && areQuotesRedundant(key.value, tokens, NUMBERS)) { - context.report(node, MESSAGE_UNNECESSARY, {property: key.value}); - } - } else if (KEYWORDS && key.type === "Identifier" && isKeyword(key.name)) { - context.report(node, MESSAGE_RESERVED, {property: key.name}); - } else if (NUMBERS && key.type === "Literal" && typeof key.value === "number") { - context.report(node, MESSAGE_NUMERIC, {property: key.value}); + /** + * Checks whether a certain string constitutes an ES3 token + * @param {string} tokenStr - The string to be checked. + * @returns {boolean} `true` if it is an ES3 token. + */ + function isKeyword(tokenStr) { + return keywords.indexOf(tokenStr) >= 0; } - } - /** - * Ensures that a property's key is quoted - * @param {ASTNode} node Property AST node - * @returns {void} - */ - function checkOmittedQuotes(node) { - var key = node.key; - - if (!node.method && !node.computed && !node.shorthand && !(key.type === "Literal" && typeof key.value === "string")) { - context.report(node, MESSAGE_UNQUOTED, { - property: key.name || key.value - }); + /** + * Checks if an espree-tokenized key has redundant quotes (i.e. whether quotes are unnecessary) + * @param {string} rawKey The raw key value from the source + * @param {espreeTokens} tokens The espree-tokenized node key + * @param {boolean} [skipNumberLiterals=false] Indicates whether number literals should be checked + * @returns {boolean} Whether or not a key has redundant quotes. + * @private + */ + function areQuotesRedundant(rawKey, tokens, skipNumberLiterals) { + return tokens.length === 1 && tokens[0].start === 0 && tokens[0].end === rawKey.length && + (["Identifier", "Keyword", "Null", "Boolean"].indexOf(tokens[0].type) >= 0 || + (tokens[0].type === "Numeric" && !skipNumberLiterals && "" + +tokens[0].value === tokens[0].value)); } - } - /** - * Ensures that an object's keys are consistently quoted, optionally checks for redundancy of quotes - * @param {ASTNode} node Property AST node - * @param {boolean} checkQuotesRedundancy Whether to check quotes' redundancy - * @returns {void} - */ - function checkConsistency(node, checkQuotesRedundancy) { - var quotes = false, - lackOfQuotes = false, - necessaryQuotes = false; - - node.properties.forEach(function(property) { - var key = property.key, + /** + * Ensures that a property's key is quoted only when necessary + * @param {ASTNode} node Property AST node + * @returns {void} + */ + function checkUnnecessaryQuotes(node) { + var key = node.key, + isKeywordToken, tokens; - if (!key || property.method || property.computed || property.shorthand) { + if (node.method || node.computed || node.shorthand) { return; } if (key.type === "Literal" && typeof key.value === "string") { + try { + tokens = espree.tokenize(key.value); + } catch (e) { + return; + } - quotes = true; + if (tokens.length !== 1) { + return; + } - if (checkQuotesRedundancy) { - try { - tokens = espree.tokenize(key.value); - } catch (e) { - necessaryQuotes = true; - return; - } + isKeywordToken = isKeyword(tokens[0].value); - necessaryQuotes = necessaryQuotes || !areQuotesRedundant(key.value, tokens) || KEYWORDS && isKeyword(tokens[0].value); + if (isKeywordToken && KEYWORDS) { + return; } - } else if (KEYWORDS && checkQuotesRedundancy && key.type === "Identifier" && isKeyword(key.name)) { - necessaryQuotes = true; - context.report(node, "Properties should be quoted as '{{property}}' is a reserved word.", {property: key.name}); - } else { - lackOfQuotes = true; - } - if (quotes && lackOfQuotes) { - context.report(node, "Inconsistently quoted property '{{key}}' found.", { - key: key.name || key.value - }); + if (CHECK_UNNECESSARY && areQuotesRedundant(key.value, tokens, NUMBERS)) { + context.report(node, MESSAGE_UNNECESSARY, {property: key.value}); + } + } else if (KEYWORDS && key.type === "Identifier" && isKeyword(key.name)) { + context.report(node, MESSAGE_RESERVED, {property: key.name}); + } else if (NUMBERS && key.type === "Literal" && typeof key.value === "number") { + context.report(node, MESSAGE_NUMERIC, {property: key.value}); } - }); - - if (checkQuotesRedundancy && quotes && !necessaryQuotes) { - context.report(node, "Properties shouldn't be quoted as all quotes are redundant."); } - } - return { - "Property": function(node) { - if (MODE === "always" || !MODE) { - checkOmittedQuotes(node); - } - if (MODE === "as-needed") { - checkUnnecessaryQuotes(node); - } - }, - "ObjectExpression": function(node) { - if (MODE === "consistent") { - checkConsistency(node, false); - } - if (MODE === "consistent-as-needed") { - checkConsistency(node, true); + /** + * Ensures that a property's key is quoted + * @param {ASTNode} node Property AST node + * @returns {void} + */ + function checkOmittedQuotes(node) { + var key = node.key; + + if (!node.method && !node.computed && !node.shorthand && !(key.type === "Literal" && typeof key.value === "string")) { + context.report(node, MESSAGE_UNQUOTED, { + property: key.name || key.value + }); } } - }; - -}; -module.exports.schema = { - "anyOf": [ - { - "type": "array", - "items": [ - { - "enum": ["always", "as-needed", "consistent", "consistent-as-needed"] + /** + * Ensures that an object's keys are consistently quoted, optionally checks for redundancy of quotes + * @param {ASTNode} node Property AST node + * @param {boolean} checkQuotesRedundancy Whether to check quotes' redundancy + * @returns {void} + */ + function checkConsistency(node, checkQuotesRedundancy) { + var quotes = false, + lackOfQuotes = false, + necessaryQuotes = false; + + node.properties.forEach(function(property) { + var key = property.key, + tokens; + + if (!key || property.method || property.computed || property.shorthand) { + return; } - ], - "minItems": 0, - "maxItems": 1 - }, - { - "type": "array", - "items": [ - { - "enum": ["always", "as-needed", "consistent", "consistent-as-needed"] - }, - { - "type": "object", - "properties": { - "keywords": { - "type": "boolean" - }, - "unnecessary": { - "type": "boolean" - }, - "numbers": { - "type": "boolean" + + if (key.type === "Literal" && typeof key.value === "string") { + + quotes = true; + + if (checkQuotesRedundancy) { + try { + tokens = espree.tokenize(key.value); + } catch (e) { + necessaryQuotes = true; + return; } - }, - "additionalProperties": false + + necessaryQuotes = necessaryQuotes || !areQuotesRedundant(key.value, tokens) || KEYWORDS && isKeyword(tokens[0].value); + } + } else if (KEYWORDS && checkQuotesRedundancy && key.type === "Identifier" && isKeyword(key.name)) { + necessaryQuotes = true; + context.report(node, "Properties should be quoted as '{{property}}' is a reserved word.", {property: key.name}); + } else { + lackOfQuotes = true; + } + + if (quotes && lackOfQuotes) { + context.report(node, "Inconsistently quoted property '{{key}}' found.", { + key: key.name || key.value + }); } - ], - "minItems": 0, - "maxItems": 2 + }); + + if (checkQuotesRedundancy && quotes && !necessaryQuotes) { + context.report(node, "Properties shouldn't be quoted as all quotes are redundant."); + } } - ] + + return { + Property: function(node) { + if (MODE === "always" || !MODE) { + checkOmittedQuotes(node); + } + if (MODE === "as-needed") { + checkUnnecessaryQuotes(node); + } + }, + ObjectExpression: function(node) { + if (MODE === "consistent") { + checkConsistency(node, false); + } + if (MODE === "consistent-as-needed") { + checkConsistency(node, true); + } + } + }; + + } }; diff --git a/tools/eslint/lib/rules/quotes.js b/tools/eslint/lib/rules/quotes.js index b5cce4bbfea2d9..d4e9203811cf7f 100644 --- a/tools/eslint/lib/rules/quotes.js +++ b/tools/eslint/lib/rules/quotes.js @@ -1,8 +1,6 @@ /** * @fileoverview A rule to choose between single and double quote marks * @author Matt DuVall , Brandon Payton - * @copyright 2013 Matt DuVall. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; @@ -18,17 +16,17 @@ var astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ var QUOTE_SETTINGS = { - "double": { + double: { quote: "\"", alternateQuote: "'", description: "doublequote" }, - "single": { + single: { quote: "'", alternateQuote: "\"", description: "singlequote" }, - "backtick": { + backtick: { quote: "`", alternateQuote: "\"", description: "backtick" @@ -74,154 +72,189 @@ var AVOID_ESCAPE = "avoid-escape", // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - var quoteOption = context.options[0], - settings = QUOTE_SETTINGS[quoteOption || "double"], - avoidEscape = context.options[1] === AVOID_ESCAPE, - sourceCode = context.getSourceCode(); - - /** - * Determines if a given node is part of JSX syntax. - * @param {ASTNode} node The node to check. - * @returns {boolean} True if the node is a JSX node, false if not. - * @private - */ - function isJSXElement(node) { - return node.type.indexOf("JSX") === 0; - } +module.exports = { + meta: { + docs: { + description: "enforce the consistent use of either backticks, double, or single quotes", + category: "Stylistic Issues", + recommended: false + }, - /** - * Checks whether or not a given node is a directive. - * The directive is a `ExpressionStatement` which has only a string literal. - * @param {ASTNode} node - A node to check. - * @returns {boolean} Whether or not the node is a directive. - * @private - */ - function isDirective(node) { - return ( - node.type === "ExpressionStatement" && - node.expression.type === "Literal" && - typeof node.expression.value === "string" - ); - } + fixable: "code", + + schema: [ + { + enum: ["single", "double", "backtick"] + }, + { + anyOf: [ + { + enum: ["avoid-escape"] + }, + { + type: "object", + properties: { + avoidEscape: { + type: "boolean" + }, + allowTemplateLiterals: { + type: "boolean" + } + }, + additionalProperties: false + } + ] + } + ] + }, - /** - * Checks whether or not a given node is a part of directive prologues. - * See also: http://www.ecma-international.org/ecma-262/6.0/#sec-directive-prologues-and-the-use-strict-directive - * @param {ASTNode} node - A node to check. - * @returns {boolean} Whether or not the node is a part of directive prologues. - * @private - */ - function isPartOfDirectivePrologue(node) { - var block = node.parent.parent; - - if (block.type !== "Program" && (block.type !== "BlockStatement" || !FUNCTION_TYPE.test(block.parent.type))) { - return false; + create: function(context) { + + var quoteOption = context.options[0], + settings = QUOTE_SETTINGS[quoteOption || "double"], + options = context.options[1], + avoidEscape = options && options.avoidEscape === true, + allowTemplateLiterals = options && options.allowTemplateLiterals === true, + sourceCode = context.getSourceCode(); + + // deprecated + if (options === AVOID_ESCAPE) { + avoidEscape = true; + } + + /** + * Determines if a given node is part of JSX syntax. + * @param {ASTNode} node The node to check. + * @returns {boolean} True if the node is a JSX node, false if not. + * @private + */ + function isJSXElement(node) { + return node.type.indexOf("JSX") === 0; } - // Check the node is at a prologue. - for (var i = 0; i < block.body.length; ++i) { - var statement = block.body[i]; + /** + * Checks whether or not a given node is a directive. + * The directive is a `ExpressionStatement` which has only a string literal. + * @param {ASTNode} node - A node to check. + * @returns {boolean} Whether or not the node is a directive. + * @private + */ + function isDirective(node) { + return ( + node.type === "ExpressionStatement" && + node.expression.type === "Literal" && + typeof node.expression.value === "string" + ); + } - if (statement === node.parent) { - return true; + /** + * Checks whether or not a given node is a part of directive prologues. + * See also: http://www.ecma-international.org/ecma-262/6.0/#sec-directive-prologues-and-the-use-strict-directive + * @param {ASTNode} node - A node to check. + * @returns {boolean} Whether or not the node is a part of directive prologues. + * @private + */ + function isPartOfDirectivePrologue(node) { + var block = node.parent.parent; + + if (block.type !== "Program" && (block.type !== "BlockStatement" || !FUNCTION_TYPE.test(block.parent.type))) { + return false; } - if (!isDirective(statement)) { - break; + + // Check the node is at a prologue. + for (var i = 0; i < block.body.length; ++i) { + var statement = block.body[i]; + + if (statement === node.parent) { + return true; + } + if (!isDirective(statement)) { + break; + } } - } - return false; - } + return false; + } - /** - * Checks whether or not a given node is allowed as non backtick. - * @param {ASTNode} node - A node to check. - * @returns {boolean} Whether or not the node is allowed as non backtick. - * @private - */ - function isAllowedAsNonBacktick(node) { - var parent = node.parent; - - switch (parent.type) { - - // Directive Prologues. - case "ExpressionStatement": - return isPartOfDirectivePrologue(node); - - // LiteralPropertyName. - case "Property": - return parent.key === node && !parent.computed; - - // ModuleSpecifier. - case "ImportDeclaration": - case "ExportNamedDeclaration": - case "ExportAllDeclaration": - return parent.source === node; - - // Others don't allow. - default: - return false; + /** + * Checks whether or not a given node is allowed as non backtick. + * @param {ASTNode} node - A node to check. + * @returns {boolean} Whether or not the node is allowed as non backtick. + * @private + */ + function isAllowedAsNonBacktick(node) { + var parent = node.parent; + + switch (parent.type) { + + // Directive Prologues. + case "ExpressionStatement": + return isPartOfDirectivePrologue(node); + + // LiteralPropertyName. + case "Property": + return parent.key === node && !parent.computed; + + // ModuleSpecifier. + case "ImportDeclaration": + case "ExportNamedDeclaration": + case "ExportAllDeclaration": + return parent.source === node; + + // Others don't allow. + default: + return false; + } } - } - return { + return { + + Literal: function(node) { + var val = node.value, + rawVal = node.raw, + isValid; - "Literal": function(node) { - var val = node.value, - rawVal = node.raw, - isValid; + if (settings && typeof val === "string") { + isValid = (quoteOption === "backtick" && isAllowedAsNonBacktick(node)) || + isJSXElement(node.parent) || + astUtils.isSurroundedBy(rawVal, settings.quote); - if (settings && typeof val === "string") { - isValid = (quoteOption === "backtick" && isAllowedAsNonBacktick(node)) || - isJSXElement(node.parent) || - astUtils.isSurroundedBy(rawVal, settings.quote); + if (!isValid && avoidEscape) { + isValid = astUtils.isSurroundedBy(rawVal, settings.alternateQuote) && rawVal.indexOf(settings.quote) >= 0; + } - if (!isValid && avoidEscape) { - isValid = astUtils.isSurroundedBy(rawVal, settings.alternateQuote) && rawVal.indexOf(settings.quote) >= 0; + if (!isValid) { + context.report({ + node: node, + message: "Strings must use " + settings.description + ".", + fix: function(fixer) { + return fixer.replaceText(node, settings.convert(node.raw)); + } + }); + } } + }, + + TemplateLiteral: function(node) { - if (!isValid) { + // 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") { + return; + } + + var shouldWarn = node.quasis.length === 1 && (node.quasis[0].value.cooked.indexOf("\n") === -1); + + if (shouldWarn) { context.report({ node: node, message: "Strings must use " + settings.description + ".", fix: function(fixer) { - return fixer.replaceText(node, settings.convert(node.raw)); + return fixer.replaceText(node, settings.convert(sourceCode.getText(node))); } }); } } - }, - - "TemplateLiteral": function(node) { - - // If backticks are expected or it's a tagged template, then this shouldn't throw an errors - if (quoteOption === "backtick" || node.parent.type === "TaggedTemplateExpression") { - return; - } - - var shouldWarn = node.quasis.length === 1 && (node.quasis[0].value.cooked.indexOf("\n") === -1); + }; - if (shouldWarn) { - context.report({ - node: node, - message: "Strings must use " + settings.description + ".", - fix: function(fixer) { - return fixer.replaceText(node, settings.convert(sourceCode.getText(node))); - } - }); - } - } - }; - -}; - -module.exports.schema = [ - { - "enum": ["single", "double", "backtick"] - }, - { - "enum": ["avoid-escape"] } -]; +}; diff --git a/tools/eslint/lib/rules/radix.js b/tools/eslint/lib/rules/radix.js index 23a2f71d445409..05a1c130a9f4df 100644 --- a/tools/eslint/lib/rules/radix.js +++ b/tools/eslint/lib/rules/radix.js @@ -76,86 +76,96 @@ function isDefaultRadix(radix) { // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var mode = context.options[0] || MODE_ALWAYS; - - /** - * Checks the arguments of a given CallExpression node and reports it if it - * offends this rule. - * - * @param {ASTNode} node - A CallExpression node to check. - * @returns {void} - */ - function checkArguments(node) { - var args = node.arguments; - - switch (args.length) { - case 0: - context.report({ - node: node, - message: "Missing parameters." - }); - break; - - case 1: - if (mode === MODE_ALWAYS) { - context.report({ - node: node, - message: "Missing radix parameter." - }); - } - break; - - default: - if (mode === MODE_AS_NEEDED && isDefaultRadix(args[1])) { - context.report({ - node: node, - message: "Redundant radix parameter." - }); - } else if (!isValidRadix(args[1])) { +module.exports = { + meta: { + docs: { + description: "enforce the consistent use of the radix argument when using `parseInt()`", + category: "Best Practices", + recommended: false + }, + + schema: [ + { + enum: ["always", "as-needed"] + } + ] + }, + + create: function(context) { + var mode = context.options[0] || MODE_ALWAYS; + + /** + * Checks the arguments of a given CallExpression node and reports it if it + * offends this rule. + * + * @param {ASTNode} node - A CallExpression node to check. + * @returns {void} + */ + function checkArguments(node) { + var args = node.arguments; + + switch (args.length) { + case 0: context.report({ node: node, - message: "Invalid radix parameter." + message: "Missing parameters." }); - } - break; + break; + + case 1: + if (mode === MODE_ALWAYS) { + context.report({ + node: node, + message: "Missing radix parameter." + }); + } + break; + + default: + if (mode === MODE_AS_NEEDED && isDefaultRadix(args[1])) { + context.report({ + node: node, + message: "Redundant radix parameter." + }); + } else if (!isValidRadix(args[1])) { + context.report({ + node: node, + message: "Invalid radix parameter." + }); + } + break; + } } - } - return { - "Program:exit": function() { - var scope = context.getScope(); - var variable; + return { + "Program:exit": function() { + var scope = context.getScope(); + var variable; - // Check `parseInt()` - variable = astUtils.getVariableByName(scope, "parseInt"); - if (!isShadowed(variable)) { - variable.references.forEach(function(reference) { - var node = reference.identifier; + // Check `parseInt()` + variable = astUtils.getVariableByName(scope, "parseInt"); + if (!isShadowed(variable)) { + variable.references.forEach(function(reference) { + var node = reference.identifier; - if (astUtils.isCallee(node)) { - checkArguments(node.parent); - } - }); - } + if (astUtils.isCallee(node)) { + checkArguments(node.parent); + } + }); + } - // Check `Number.parseInt()` - variable = astUtils.getVariableByName(scope, "Number"); - if (!isShadowed(variable)) { - variable.references.forEach(function(reference) { - var node = reference.identifier.parent; + // Check `Number.parseInt()` + variable = astUtils.getVariableByName(scope, "Number"); + if (!isShadowed(variable)) { + variable.references.forEach(function(reference) { + var node = reference.identifier.parent; - if (isParseIntMethod(node) && astUtils.isCallee(node)) { - checkArguments(node.parent); - } - }); + if (isParseIntMethod(node) && astUtils.isCallee(node)) { + checkArguments(node.parent); + } + }); + } } - } - }; -}; - -module.exports.schema = [ - { - "enum": ["always", "as-needed"] + }; } -]; +}; diff --git a/tools/eslint/lib/rules/require-jsdoc.js b/tools/eslint/lib/rules/require-jsdoc.js index bac4475e9efa1b..083e79b1f55ccb 100644 --- a/tools/eslint/lib/rules/require-jsdoc.js +++ b/tools/eslint/lib/rules/require-jsdoc.js @@ -1,97 +1,106 @@ /** * @fileoverview Rule to check for jsdoc presence. * @author Gyandeep Singh - * @copyright 2015 Gyandeep Singh. All rights reserved. */ "use strict"; var lodash = require("lodash"); -module.exports = function(context) { - var source = context.getSourceCode(); - var DEFAULT_OPTIONS = { - "FunctionDeclaration": true, - "MethodDefinition": false, - "ClassDeclaration": false - }; - var options = lodash.assign(DEFAULT_OPTIONS, context.options[0] && context.options[0].require || {}); +module.exports = { + meta: { + docs: { + description: "require JSDoc comments", + category: "Stylistic Issues", + recommended: false + }, - /** - * Report the error message - * @param {ASTNode} node node to report - * @returns {void} - */ - function report(node) { - context.report(node, "Missing JSDoc comment."); - } + schema: [ + { + type: "object", + properties: { + require: { + type: "object", + properties: { + ClassDeclaration: { + type: "boolean" + }, + MethodDefinition: { + type: "boolean" + }, + FunctionDeclaration: { + type: "boolean" + } + }, + additionalProperties: false + } + }, + additionalProperties: false + } + ] + }, - /** - * Check if the jsdoc comment is present for class methods - * @param {ASTNode} node node to examine - * @returns {void} - */ - function checkClassMethodJsDoc(node) { - if (node.parent.type === "MethodDefinition") { - var jsdocComment = source.getJSDocComment(node); + create: function(context) { + var source = context.getSourceCode(); + var DEFAULT_OPTIONS = { + FunctionDeclaration: true, + MethodDefinition: false, + ClassDeclaration: false + }; + var options = lodash.assign(DEFAULT_OPTIONS, context.options[0] && context.options[0].require || {}); - if (!jsdocComment) { - report(node); - } + /** + * Report the error message + * @param {ASTNode} node node to report + * @returns {void} + */ + function report(node) { + context.report(node, "Missing JSDoc comment."); } - } - /** - * Check if the jsdoc comment is present or not. - * @param {ASTNode} node node to examine - * @returns {void} - */ - function checkJsDoc(node) { - var jsdocComment = source.getJSDocComment(node); + /** + * Check if the jsdoc comment is present for class methods + * @param {ASTNode} node node to examine + * @returns {void} + */ + function checkClassMethodJsDoc(node) { + if (node.parent.type === "MethodDefinition") { + var jsdocComment = source.getJSDocComment(node); - if (!jsdocComment) { - report(node); + if (!jsdocComment) { + report(node); + } + } } - } - return { - "FunctionDeclaration": function(node) { - if (options.FunctionDeclaration) { - checkJsDoc(node); - } - }, - "FunctionExpression": function(node) { - if (options.MethodDefinition) { - checkClassMethodJsDoc(node); - } - }, - "ClassDeclaration": function(node) { - if (options.ClassDeclaration) { - checkJsDoc(node); + /** + * Check if the jsdoc comment is present or not. + * @param {ASTNode} node node to examine + * @returns {void} + */ + function checkJsDoc(node) { + var jsdocComment = source.getJSDocComment(node); + + if (!jsdocComment) { + report(node); } } - }; -}; -module.exports.schema = [ - { - "type": "object", - "properties": { - "require": { - "type": "object", - "properties": { - "ClassDeclaration": { - "type": "boolean" - }, - "MethodDefinition": { - "type": "boolean" - }, - "FunctionDeclaration": { - "type": "boolean" - } - }, - "additionalProperties": false + return { + FunctionDeclaration: function(node) { + if (options.FunctionDeclaration) { + checkJsDoc(node); + } + }, + FunctionExpression: function(node) { + if (options.MethodDefinition) { + checkClassMethodJsDoc(node); + } + }, + ClassDeclaration: function(node) { + if (options.ClassDeclaration) { + checkJsDoc(node); + } } - }, - "additionalProperties": false + }; } -]; +}; diff --git a/tools/eslint/lib/rules/require-yield.js b/tools/eslint/lib/rules/require-yield.js index b293ee4c9e1875..441d354ed80f4e 100644 --- a/tools/eslint/lib/rules/require-yield.js +++ b/tools/eslint/lib/rules/require-yield.js @@ -1,7 +1,6 @@ /** * @fileoverview Rule to flag the generator functions that does not have yield. * @author Toru Nagashima - * @copyright 2015 Toru Nagashima. All rights reserved. */ "use strict"; @@ -10,55 +9,65 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var stack = []; +module.exports = { + meta: { + docs: { + description: "require generator functions to contain `yield`", + category: "ECMAScript 6", + recommended: false + }, - /** - * If the node is a generator function, start counting `yield` keywords. - * @param {Node} node - A function node to check. - * @returns {void} - */ - function beginChecking(node) { - if (node.generator) { - stack.push(0); - } - } + schema: [] + }, + + create: function(context) { + var stack = []; - /** - * If the node is a generator function, end counting `yield` keywords, then - * reports result. - * @param {Node} node - A function node to check. - * @returns {void} - */ - function endChecking(node) { - if (!node.generator) { - return; + /** + * If the node is a generator function, start counting `yield` keywords. + * @param {Node} node - A function node to check. + * @returns {void} + */ + function beginChecking(node) { + if (node.generator) { + stack.push(0); + } } - var countYield = stack.pop(); + /** + * If the node is a generator function, end counting `yield` keywords, then + * reports result. + * @param {Node} node - A function node to check. + * @returns {void} + */ + function endChecking(node) { + if (!node.generator) { + return; + } + + var countYield = stack.pop(); - if (countYield === 0 && node.body.body.length > 0) { - context.report( - node, - "This generator function does not have 'yield'."); + if (countYield === 0 && node.body.body.length > 0) { + context.report( + node, + "This generator function does not have 'yield'."); + } } - } - return { - "FunctionDeclaration": beginChecking, - "FunctionDeclaration:exit": endChecking, - "FunctionExpression": beginChecking, - "FunctionExpression:exit": endChecking, + return { + FunctionDeclaration: beginChecking, + "FunctionDeclaration:exit": endChecking, + FunctionExpression: beginChecking, + "FunctionExpression:exit": endChecking, - // Increases the count of `yield` keyword. - "YieldExpression": function() { + // Increases the count of `yield` keyword. + YieldExpression: function() { - /* istanbul ignore else */ - if (stack.length > 0) { - stack[stack.length - 1] += 1; + /* istanbul ignore else */ + if (stack.length > 0) { + stack[stack.length - 1] += 1; + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/semi-spacing.js b/tools/eslint/lib/rules/semi-spacing.js index 37fbc6f3c5cc0c..ea43e9243dfb7a 100644 --- a/tools/eslint/lib/rules/semi-spacing.js +++ b/tools/eslint/lib/rules/semi-spacing.js @@ -1,7 +1,6 @@ /** * @fileoverview Validates spacing before and after semicolon * @author Mathias Schreck - * @copyright 2015 Mathias Schreck */ "use strict"; @@ -12,200 +11,212 @@ var astUtils = require("../ast-utils"); // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "enforce consistent spacing before and after semicolons", + category: "Stylistic Issues", + recommended: false + }, + + fixable: "whitespace", + + schema: [ + { + type: "object", + properties: { + before: { + type: "boolean" + }, + after: { + type: "boolean" + } + }, + additionalProperties: false + } + ] + }, - var config = context.options[0], - requireSpaceBefore = false, - requireSpaceAfter = true, - sourceCode = context.getSourceCode(); + create: function(context) { - if (typeof config === "object") { - if (config.hasOwnProperty("before")) { - requireSpaceBefore = config.before; - } - if (config.hasOwnProperty("after")) { - requireSpaceAfter = config.after; + var config = context.options[0], + requireSpaceBefore = false, + requireSpaceAfter = true, + sourceCode = context.getSourceCode(); + + if (typeof config === "object") { + if (config.hasOwnProperty("before")) { + requireSpaceBefore = config.before; + } + if (config.hasOwnProperty("after")) { + requireSpaceAfter = config.after; + } } - } - /** - * Checks if a given token has leading whitespace. - * @param {Object} token The token to check. - * @returns {boolean} True if the given token has leading space, false if not. - */ - function hasLeadingSpace(token) { - var tokenBefore = context.getTokenBefore(token); + /** + * Checks if a given token has leading whitespace. + * @param {Object} token The token to check. + * @returns {boolean} True if the given token has leading space, false if not. + */ + function hasLeadingSpace(token) { + var tokenBefore = context.getTokenBefore(token); - return tokenBefore && astUtils.isTokenOnSameLine(tokenBefore, token) && sourceCode.isSpaceBetweenTokens(tokenBefore, token); - } + return tokenBefore && astUtils.isTokenOnSameLine(tokenBefore, token) && sourceCode.isSpaceBetweenTokens(tokenBefore, token); + } - /** - * Checks if a given token has trailing whitespace. - * @param {Object} token The token to check. - * @returns {boolean} True if the given token has trailing space, false if not. - */ - function hasTrailingSpace(token) { - var tokenAfter = context.getTokenAfter(token); + /** + * Checks if a given token has trailing whitespace. + * @param {Object} token The token to check. + * @returns {boolean} True if the given token has trailing space, false if not. + */ + function hasTrailingSpace(token) { + var tokenAfter = context.getTokenAfter(token); - return tokenAfter && astUtils.isTokenOnSameLine(token, tokenAfter) && sourceCode.isSpaceBetweenTokens(token, tokenAfter); - } + return tokenAfter && astUtils.isTokenOnSameLine(token, tokenAfter) && sourceCode.isSpaceBetweenTokens(token, tokenAfter); + } - /** - * Checks if the given token is the last token in its line. - * @param {Token} token The token to check. - * @returns {boolean} Whether or not the token is the last in its line. - */ - function isLastTokenInCurrentLine(token) { - var tokenAfter = context.getTokenAfter(token); + /** + * Checks if the given token is the last token in its line. + * @param {Token} token The token to check. + * @returns {boolean} Whether or not the token is the last in its line. + */ + function isLastTokenInCurrentLine(token) { + var tokenAfter = context.getTokenAfter(token); - return !(tokenAfter && astUtils.isTokenOnSameLine(token, tokenAfter)); - } + return !(tokenAfter && astUtils.isTokenOnSameLine(token, tokenAfter)); + } - /** - * Checks if the given token is the first token in its line - * @param {Token} token The token to check. - * @returns {boolean} Whether or not the token is the first in its line. - */ - function isFirstTokenInCurrentLine(token) { - var tokenBefore = context.getTokenBefore(token); + /** + * Checks if the given token is the first token in its line + * @param {Token} token The token to check. + * @returns {boolean} Whether or not the token is the first in its line. + */ + function isFirstTokenInCurrentLine(token) { + var tokenBefore = context.getTokenBefore(token); - return !(tokenBefore && astUtils.isTokenOnSameLine(token, tokenBefore)); - } + return !(tokenBefore && astUtils.isTokenOnSameLine(token, tokenBefore)); + } - /** - * Checks if the next token of a given token is a closing parenthesis. - * @param {Token} token The token to check. - * @returns {boolean} Whether or not the next token of a given token is a closing parenthesis. - */ - function isBeforeClosingParen(token) { - var nextToken = context.getTokenAfter(token); - - return ( - nextToken && - nextToken.type === "Punctuator" && - (nextToken.value === "}" || nextToken.value === ")") - ); - } + /** + * Checks if the next token of a given token is a closing parenthesis. + * @param {Token} token The token to check. + * @returns {boolean} Whether or not the next token of a given token is a closing parenthesis. + */ + function isBeforeClosingParen(token) { + var nextToken = context.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 === ";"; - } + /** + * 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 === ";"; + } - /** - * Reports if the given token has invalid spacing. - * @param {Token} token The semicolon token to check. - * @param {ASTNode} node The corresponding node of the token. - * @returns {void} - */ - function checkSemicolonSpacing(token, node) { - var location; - - if (isSemicolon(token)) { - location = token.loc.start; - - if (hasLeadingSpace(token)) { - if (!requireSpaceBefore) { - context.report({ - node: node, - loc: location, - message: "Unexpected whitespace before semicolon.", - fix: function(fixer) { - var tokenBefore = context.getTokenBefore(token); - - return fixer.removeRange([tokenBefore.range[1], token.range[0]]); - } - }); - } - } else { - if (requireSpaceBefore) { - context.report({ - node: node, - loc: location, - message: "Missing whitespace before semicolon.", - fix: function(fixer) { - return fixer.insertTextBefore(token, " "); - } - }); - } - } + /** + * Reports if the given token has invalid spacing. + * @param {Token} token The semicolon token to check. + * @param {ASTNode} node The corresponding node of the token. + * @returns {void} + */ + function checkSemicolonSpacing(token, node) { + var location; + + if (isSemicolon(token)) { + location = token.loc.start; - if (!isFirstTokenInCurrentLine(token) && !isLastTokenInCurrentLine(token) && !isBeforeClosingParen(token)) { - if (hasTrailingSpace(token)) { - if (!requireSpaceAfter) { + if (hasLeadingSpace(token)) { + if (!requireSpaceBefore) { context.report({ node: node, loc: location, - message: "Unexpected whitespace after semicolon.", + message: "Unexpected whitespace before semicolon.", fix: function(fixer) { - var tokenAfter = context.getTokenAfter(token); + var tokenBefore = context.getTokenBefore(token); - return fixer.removeRange([token.range[1], tokenAfter.range[0]]); + return fixer.removeRange([tokenBefore.range[1], token.range[0]]); } }); } } else { - if (requireSpaceAfter) { + if (requireSpaceBefore) { context.report({ node: node, loc: location, - message: "Missing whitespace after semicolon.", + message: "Missing whitespace before semicolon.", fix: function(fixer) { - return fixer.insertTextAfter(token, " "); + return fixer.insertTextBefore(token, " "); } }); } } + + if (!isFirstTokenInCurrentLine(token) && !isLastTokenInCurrentLine(token) && !isBeforeClosingParen(token)) { + if (hasTrailingSpace(token)) { + if (!requireSpaceAfter) { + context.report({ + node: node, + loc: location, + message: "Unexpected whitespace after semicolon.", + fix: function(fixer) { + var tokenAfter = context.getTokenAfter(token); + + return fixer.removeRange([token.range[1], tokenAfter.range[0]]); + } + }); + } + } else { + if (requireSpaceAfter) { + context.report({ + node: node, + loc: location, + message: "Missing whitespace after semicolon.", + fix: function(fixer) { + return fixer.insertTextAfter(token, " "); + } + }); + } + } + } } } - } - /** - * Checks the spacing of the semicolon with the assumption that the last token is the semicolon. - * @param {ASTNode} node The node to check. - * @returns {void} - */ - function checkNode(node) { - var token = context.getLastToken(node); + /** + * Checks the spacing of the semicolon with the assumption that the last token is the semicolon. + * @param {ASTNode} node The node to check. + * @returns {void} + */ + function checkNode(node) { + var token = context.getLastToken(node); - checkSemicolonSpacing(token, node); - } - - return { - "VariableDeclaration": checkNode, - "ExpressionStatement": checkNode, - "BreakStatement": checkNode, - "ContinueStatement": checkNode, - "DebuggerStatement": checkNode, - "ReturnStatement": checkNode, - "ThrowStatement": checkNode, - "ForStatement": function(node) { - if (node.init) { - checkSemicolonSpacing(context.getTokenAfter(node.init), node); - } - - if (node.test) { - checkSemicolonSpacing(context.getTokenAfter(node.test), node); - } + checkSemicolonSpacing(token, node); } - }; -}; -module.exports.schema = [ - { - "type": "object", - "properties": { - "before": { - "type": "boolean" - }, - "after": { - "type": "boolean" + return { + VariableDeclaration: checkNode, + ExpressionStatement: checkNode, + BreakStatement: checkNode, + ContinueStatement: checkNode, + DebuggerStatement: checkNode, + ReturnStatement: checkNode, + ThrowStatement: checkNode, + ForStatement: function(node) { + if (node.init) { + checkSemicolonSpacing(context.getTokenAfter(node.init), node); + } + + if (node.test) { + checkSemicolonSpacing(context.getTokenAfter(node.test), node); + } } - }, - "additionalProperties": false + }; } -]; +}; diff --git a/tools/eslint/lib/rules/semi.js b/tools/eslint/lib/rules/semi.js index 2986f406e64b13..e386084faf2317 100644 --- a/tools/eslint/lib/rules/semi.js +++ b/tools/eslint/lib/rules/semi.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to flag missing semicolons. * @author Nicholas C. Zakas - * @copyright 2013 Nicholas C. Zakas. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; @@ -10,207 +8,219 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - var OPT_OUT_PATTERN = /[\[\(\/\+\-]/; // One of [(/+- - var options = context.options[1]; - var never = context.options[0] === "never", - exceptOneLine = options && options.omitLastInOneLineBlock === true, - sourceCode = context.getSourceCode(); - - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- - - /** - * Reports a semicolon error with appropriate location and message. - * @param {ASTNode} node The node with an extra or missing semicolon. - * @param {boolean} missing True if the semicolon is missing. - * @returns {void} - */ - function report(node, missing) { - var message, - fix, - lastToken = sourceCode.getLastToken(node), - loc = lastToken.loc; - - if (!missing) { - message = "Missing semicolon."; - loc = loc.end; - fix = function(fixer) { - return fixer.insertTextAfter(lastToken, ";"); - }; - } else { - message = "Extra semicolon."; - loc = loc.start; - fix = function(fixer) { - return fixer.remove(lastToken); - }; - } +module.exports = { + meta: { + docs: { + description: "require or disallow semicolons instead of ASI", + category: "Stylistic Issues", + recommended: false + }, - context.report({ - node: node, - loc: loc, - message: message, - fix: fix - }); + fixable: "code", - } + schema: { + anyOf: [ + { + type: "array", + items: [ + { + enum: ["never"] + } + ], + minItems: 0, + maxItems: 1 + }, + { + type: "array", + items: [ + { + enum: ["always"] + }, + { + type: "object", + properties: { + omitLastInOneLineBlock: {type: "boolean"} + }, + additionalProperties: false + } + ], + minItems: 0, + maxItems: 2 + } + ] + } + }, + + create: function(context) { + + var OPT_OUT_PATTERN = /[\[\(\/\+\-]/; // One of [(/+- + var options = context.options[1]; + var never = context.options[0] === "never", + exceptOneLine = options && options.omitLastInOneLineBlock === true, + sourceCode = context.getSourceCode(); + + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- + + /** + * Reports a semicolon error with appropriate location and message. + * @param {ASTNode} node The node with an extra or missing semicolon. + * @param {boolean} missing True if the semicolon is missing. + * @returns {void} + */ + function report(node, missing) { + var message, + fix, + lastToken = sourceCode.getLastToken(node), + loc = lastToken.loc; + + if (!missing) { + message = "Missing semicolon."; + loc = loc.end; + fix = function(fixer) { + return fixer.insertTextAfter(lastToken, ";"); + }; + } else { + message = "Extra semicolon."; + loc = loc.start; + fix = function(fixer) { + return fixer.remove(lastToken); + }; + } - /** - * 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 === ";"); - } + context.report({ + node: node, + loc: loc, + message: message, + fix: fix + }); - /** - * 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 - * - next token is a valid statement divider - * @param {Token} lastToken last token of current node. - * @returns {boolean} whether the semicolon is unnecessary. - */ - function isUnnecessarySemicolon(lastToken) { - var isDivider, isOptOutToken, lastTokenLine, nextToken, nextTokenLine; - - if (!isSemicolon(lastToken)) { - return false; } - nextToken = context.getTokenAfter(lastToken); - - if (!nextToken) { - return true; + /** + * 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 === ";"); } - lastTokenLine = lastToken.loc.end.line; - nextTokenLine = nextToken.loc.start.line; - isOptOutToken = OPT_OUT_PATTERN.test(nextToken.value); - isDivider = (nextToken.value === "}" || nextToken.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 + * - next token is a valid statement divider + * @param {Token} lastToken last token of current node. + * @returns {boolean} whether the semicolon is unnecessary. + */ + function isUnnecessarySemicolon(lastToken) { + var isDivider, isOptOutToken, lastTokenLine, nextToken, nextTokenLine; - return (lastTokenLine !== nextTokenLine && !isOptOutToken) || isDivider; - } + if (!isSemicolon(lastToken)) { + return false; + } - /** - * Checks a node to see if it's in a one-liner block statement. - * @param {ASTNode} node The node to check. - * @returns {boolean} whether the node is in a one-liner block statement. - */ - function isOneLinerBlock(node) { - var nextToken = context.getTokenAfter(node); + nextToken = context.getTokenAfter(lastToken); - if (!nextToken || nextToken.value !== "}") { - return false; - } + if (!nextToken) { + return true; + } - var parent = node.parent; + lastTokenLine = lastToken.loc.end.line; + nextTokenLine = nextToken.loc.start.line; + isOptOutToken = OPT_OUT_PATTERN.test(nextToken.value); + isDivider = (nextToken.value === "}" || nextToken.value === ";"); - return parent && parent.type === "BlockStatement" && - parent.loc.start.line === parent.loc.end.line; - } + return (lastTokenLine !== nextTokenLine && !isOptOutToken) || isDivider; + } + + /** + * Checks a node to see if it's in a one-liner block statement. + * @param {ASTNode} node The node to check. + * @returns {boolean} whether the node is in a one-liner block statement. + */ + function isOneLinerBlock(node) { + var nextToken = context.getTokenAfter(node); - /** - * Checks a node to see if it's followed by a semicolon. - * @param {ASTNode} node The node to check. - * @returns {void} - */ - function checkForSemicolon(node) { - var lastToken = context.getLastToken(node); - - if (never) { - if (isUnnecessarySemicolon(lastToken)) { - report(node, true); + if (!nextToken || nextToken.value !== "}") { + return false; } - } else { - if (!isSemicolon(lastToken)) { - if (!exceptOneLine || !isOneLinerBlock(node)) { - report(node); + + var parent = node.parent; + + return parent && parent.type === "BlockStatement" && + parent.loc.start.line === parent.loc.end.line; + } + + /** + * Checks a node to see if it's followed by a semicolon. + * @param {ASTNode} node The node to check. + * @returns {void} + */ + function checkForSemicolon(node) { + var lastToken = context.getLastToken(node); + + if (never) { + if (isUnnecessarySemicolon(lastToken)) { + report(node, true); } } else { - if (exceptOneLine && isOneLinerBlock(node)) { - report(node, true); + if (!isSemicolon(lastToken)) { + if (!exceptOneLine || !isOneLinerBlock(node)) { + report(node); + } + } else { + if (exceptOneLine && isOneLinerBlock(node)) { + report(node, true); + } } } } - } - - /** - * Checks to see if there's a semicolon after a variable declaration. - * @param {ASTNode} node The node to check. - * @returns {void} - */ - function checkForSemicolonForVariableDeclaration(node) { - var ancestors = context.getAncestors(), - parentIndex = ancestors.length - 1, - parent = ancestors[parentIndex]; - - if ((parent.type !== "ForStatement" || parent.init !== node) && - (!/^For(?:In|Of)Statement/.test(parent.type) || parent.left !== node) - ) { - checkForSemicolon(node); - } - } - //-------------------------------------------------------------------------- - // Public API - //-------------------------------------------------------------------------- - - return { - "VariableDeclaration": checkForSemicolonForVariableDeclaration, - "ExpressionStatement": checkForSemicolon, - "ReturnStatement": checkForSemicolon, - "ThrowStatement": checkForSemicolon, - "DoWhileStatement": checkForSemicolon, - "DebuggerStatement": checkForSemicolon, - "BreakStatement": checkForSemicolon, - "ContinueStatement": checkForSemicolon, - "ImportDeclaration": checkForSemicolon, - "ExportAllDeclaration": checkForSemicolon, - "ExportNamedDeclaration": function(node) { - if (!node.declaration) { - checkForSemicolon(node); - } - }, - "ExportDefaultDeclaration": function(node) { - if (!/(?:Class|Function)Declaration/.test(node.declaration.type)) { + /** + * Checks to see if there's a semicolon after a variable declaration. + * @param {ASTNode} node The node to check. + * @returns {void} + */ + function checkForSemicolonForVariableDeclaration(node) { + var ancestors = context.getAncestors(), + parentIndex = ancestors.length - 1, + parent = ancestors[parentIndex]; + + if ((parent.type !== "ForStatement" || parent.init !== node) && + (!/^For(?:In|Of)Statement/.test(parent.type) || parent.left !== node) + ) { checkForSemicolon(node); } } - }; -}; - -module.exports.schema = { - "anyOf": [ - { - "type": "array", - "items": [ - { - "enum": ["never"] + //-------------------------------------------------------------------------- + // Public API + //-------------------------------------------------------------------------- + + return { + VariableDeclaration: checkForSemicolonForVariableDeclaration, + ExpressionStatement: checkForSemicolon, + ReturnStatement: checkForSemicolon, + ThrowStatement: checkForSemicolon, + DoWhileStatement: checkForSemicolon, + DebuggerStatement: checkForSemicolon, + BreakStatement: checkForSemicolon, + ContinueStatement: checkForSemicolon, + ImportDeclaration: checkForSemicolon, + ExportAllDeclaration: checkForSemicolon, + ExportNamedDeclaration: function(node) { + if (!node.declaration) { + checkForSemicolon(node); } - ], - "minItems": 0, - "maxItems": 1 - }, - { - "type": "array", - "items": [ - { - "enum": ["always"] - }, - { - "type": "object", - "properties": { - "omitLastInOneLineBlock": {"type": "boolean"} - }, - "additionalProperties": false + }, + ExportDefaultDeclaration: function(node) { + if (!/(?:Class|Function)Declaration/.test(node.declaration.type)) { + checkForSemicolon(node); } - ], - "minItems": 0, - "maxItems": 2 - } - ] + } + }; + + } }; diff --git a/tools/eslint/lib/rules/sort-imports.js b/tools/eslint/lib/rules/sort-imports.js index 4e8807cedb725e..18b34f86a09659 100644 --- a/tools/eslint/lib/rules/sort-imports.js +++ b/tools/eslint/lib/rules/sort-imports.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to require sorting of import declarations * @author Christian Schuller - * @copyright 2015 Christian Schuller. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; @@ -11,157 +9,167 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - var configuration = context.options[0] || {}, - ignoreCase = configuration.ignoreCase || false, - ignoreMemberSort = configuration.ignoreMemberSort || false, - memberSyntaxSortOrder = configuration.memberSyntaxSortOrder || ["none", "all", "multiple", "single"], - previousDeclaration = null; - - /** - * Gets the used member syntax style. - * - * import "my-module.js" --> none - * import * as myModule from "my-module.js" --> all - * import {myMember} from "my-module.js" --> single - * import {foo, bar} from "my-module.js" --> multiple - * - * @param {ASTNode} node - the ImportDeclaration node. - * @returns {string} used member parameter style, ["all", "multiple", "single"] - */ - function usedMemberSyntax(node) { - if (node.specifiers.length === 0) { - return "none"; - } else if (node.specifiers[0].type === "ImportNamespaceSpecifier") { - return "all"; - } else if (node.specifiers.length === 1) { - return "single"; - } else { - return "multiple"; +module.exports = { + meta: { + docs: { + description: "enforce sorted import declarations within modules", + category: "ECMAScript 6", + recommended: false + }, + + schema: [ + { + type: "object", + properties: { + ignoreCase: { + type: "boolean" + }, + memberSyntaxSortOrder: { + type: "array", + items: { + enum: ["none", "all", "multiple", "single"] + }, + uniqueItems: true, + minItems: 4, + maxItems: 4 + }, + ignoreMemberSort: { + type: "boolean" + } + }, + additionalProperties: false + } + ] + }, + + create: function(context) { + + var configuration = context.options[0] || {}, + ignoreCase = configuration.ignoreCase || false, + ignoreMemberSort = configuration.ignoreMemberSort || false, + memberSyntaxSortOrder = configuration.memberSyntaxSortOrder || ["none", "all", "multiple", "single"], + previousDeclaration = null; + + /** + * Gets the used member syntax style. + * + * import "my-module.js" --> none + * import * as myModule from "my-module.js" --> all + * import {myMember} from "my-module.js" --> single + * import {foo, bar} from "my-module.js" --> multiple + * + * @param {ASTNode} node - the ImportDeclaration node. + * @returns {string} used member parameter style, ["all", "multiple", "single"] + */ + function usedMemberSyntax(node) { + if (node.specifiers.length === 0) { + return "none"; + } else if (node.specifiers[0].type === "ImportNamespaceSpecifier") { + return "all"; + } else if (node.specifiers.length === 1) { + return "single"; + } else { + return "multiple"; + } } - } - /** - * Gets the group by member parameter index for given declaration. - * @param {ASTNode} node - the ImportDeclaration node. - * @returns {number} the declaration group by member index. - */ - function getMemberParameterGroupIndex(node) { - return memberSyntaxSortOrder.indexOf(usedMemberSyntax(node)); - } + /** + * Gets the group by member parameter index for given declaration. + * @param {ASTNode} node - the ImportDeclaration node. + * @returns {number} the declaration group by member index. + */ + function getMemberParameterGroupIndex(node) { + return memberSyntaxSortOrder.indexOf(usedMemberSyntax(node)); + } - /** - * Gets the local name of the first imported module. - * @param {ASTNode} node - the ImportDeclaration node. - * @returns {?string} the local name of the first imported module. - */ - function getFirstLocalMemberName(node) { - if (node.specifiers[0]) { - return node.specifiers[0].local.name; - } else { - return null; + /** + * Gets the local name of the first imported module. + * @param {ASTNode} node - the ImportDeclaration node. + * @returns {?string} the local name of the first imported module. + */ + function getFirstLocalMemberName(node) { + if (node.specifiers[0]) { + return node.specifiers[0].local.name; + } else { + return null; + } } - } - return { - "ImportDeclaration": function(node) { - if (previousDeclaration) { - var currentLocalMemberName = getFirstLocalMemberName(node), - currentMemberSyntaxGroupIndex = getMemberParameterGroupIndex(node), - previousLocalMemberName = getFirstLocalMemberName(previousDeclaration), - previousMemberSyntaxGroupIndex = getMemberParameterGroupIndex(previousDeclaration); - - if (ignoreCase) { - previousLocalMemberName = previousLocalMemberName && previousLocalMemberName.toLowerCase(); - currentLocalMemberName = currentLocalMemberName && currentLocalMemberName.toLowerCase(); - } + return { + ImportDeclaration: function(node) { + if (previousDeclaration) { + var currentLocalMemberName = getFirstLocalMemberName(node), + currentMemberSyntaxGroupIndex = getMemberParameterGroupIndex(node), + previousLocalMemberName = getFirstLocalMemberName(previousDeclaration), + previousMemberSyntaxGroupIndex = getMemberParameterGroupIndex(previousDeclaration); - // When the current declaration uses a different member syntax, - // then check if the ordering is correct. - // Otherwise, make a default string compare (like rule sort-vars to be consistent) of the first used local member name. - if (currentMemberSyntaxGroupIndex !== previousMemberSyntaxGroupIndex) { - if (currentMemberSyntaxGroupIndex < previousMemberSyntaxGroupIndex) { - context.report({ - node: node, - message: "Expected '{{syntaxA}}' syntax before '{{syntaxB}}' syntax.", - data: { - syntaxA: memberSyntaxSortOrder[currentMemberSyntaxGroupIndex], - syntaxB: memberSyntaxSortOrder[previousMemberSyntaxGroupIndex] - } - }); + if (ignoreCase) { + previousLocalMemberName = previousLocalMemberName && previousLocalMemberName.toLowerCase(); + currentLocalMemberName = currentLocalMemberName && currentLocalMemberName.toLowerCase(); } - } else { - if (previousLocalMemberName && - currentLocalMemberName && - currentLocalMemberName < previousLocalMemberName - ) { - context.report({ - node: node, - message: "Imports should be sorted alphabetically." - }); + + // When the current declaration uses a different member syntax, + // then check if the ordering is correct. + // Otherwise, make a default string compare (like rule sort-vars to be consistent) of the first used local member name. + if (currentMemberSyntaxGroupIndex !== previousMemberSyntaxGroupIndex) { + if (currentMemberSyntaxGroupIndex < previousMemberSyntaxGroupIndex) { + context.report({ + node: node, + message: "Expected '{{syntaxA}}' syntax before '{{syntaxB}}' syntax.", + data: { + syntaxA: memberSyntaxSortOrder[currentMemberSyntaxGroupIndex], + syntaxB: memberSyntaxSortOrder[previousMemberSyntaxGroupIndex] + } + }); + } + } else { + if (previousLocalMemberName && + currentLocalMemberName && + currentLocalMemberName < previousLocalMemberName + ) { + context.report({ + node: node, + message: "Imports should be sorted alphabetically." + }); + } } } - } - // Multiple members of an import declaration should also be sorted alphabetically. - if (!ignoreMemberSort && node.specifiers.length > 1) { - var previousSpecifier = null; - var previousSpecifierName = null; + // Multiple members of an import declaration should also be sorted alphabetically. + if (!ignoreMemberSort && node.specifiers.length > 1) { + var previousSpecifier = null; + var previousSpecifierName = null; - for (var i = 0; i < node.specifiers.length; ++i) { - var currentSpecifier = node.specifiers[i]; + for (var i = 0; i < node.specifiers.length; ++i) { + var currentSpecifier = node.specifiers[i]; - if (currentSpecifier.type !== "ImportSpecifier") { - continue; - } + if (currentSpecifier.type !== "ImportSpecifier") { + continue; + } - var currentSpecifierName = currentSpecifier.local.name; + var currentSpecifierName = currentSpecifier.local.name; - if (ignoreCase) { - currentSpecifierName = currentSpecifierName.toLowerCase(); - } + if (ignoreCase) { + currentSpecifierName = currentSpecifierName.toLowerCase(); + } - if (previousSpecifier && currentSpecifierName < previousSpecifierName) { - context.report({ - node: currentSpecifier, - message: "Member '{{memberName}}' of the import declaration should be sorted alphabetically.", - data: { - memberName: currentSpecifier.local.name - } - }); - } + if (previousSpecifier && currentSpecifierName < previousSpecifierName) { + context.report({ + node: currentSpecifier, + message: "Member '{{memberName}}' of the import declaration should be sorted alphabetically.", + data: { + memberName: currentSpecifier.local.name + } + }); + } - previousSpecifier = currentSpecifier; - previousSpecifierName = currentSpecifierName; + previousSpecifier = currentSpecifier; + previousSpecifierName = currentSpecifierName; + } } - } - previousDeclaration = node; - } - }; -}; - -module.exports.schema = [ - { - "type": "object", - "properties": { - "ignoreCase": { - "type": "boolean" - }, - "memberSyntaxSortOrder": { - "type": "array", - "items": { - "enum": ["none", "all", "multiple", "single"] - }, - "uniqueItems": true, - "minItems": 4, - "maxItems": 4 - }, - "ignoreMemberSort": { - "type": "boolean" + previousDeclaration = node; } - }, - "additionalProperties": false + }; } -]; +}; diff --git a/tools/eslint/lib/rules/sort-vars.js b/tools/eslint/lib/rules/sort-vars.js index 9aa85c8cbd09e2..8a7b0e710a7524 100644 --- a/tools/eslint/lib/rules/sort-vars.js +++ b/tools/eslint/lib/rules/sort-vars.js @@ -9,45 +9,55 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - var configuration = context.options[0] || {}, - ignoreCase = configuration.ignoreCase || false; - - return { - "VariableDeclaration": function(node) { - node.declarations.reduce(function(memo, decl) { - if (decl.id.type === "ObjectPattern" || decl.id.type === "ArrayPattern") { - return memo; - } - - var lastVariableName = memo.id.name, - currenVariableName = decl.id.name; - - if (ignoreCase) { - lastVariableName = lastVariableName.toLowerCase(); - currenVariableName = currenVariableName.toLowerCase(); - } - - if (currenVariableName < lastVariableName) { - context.report(decl, "Variables within the same declaration block should be sorted alphabetically"); - return memo; - } else { - return decl; - } - }, node.declarations[0]); - } - }; -}; +module.exports = { + meta: { + docs: { + description: "require variables within the same declaration block to be sorted", + category: "Stylistic Issues", + recommended: false + }, -module.exports.schema = [ - { - "type": "object", - "properties": { - "ignoreCase": { - "type": "boolean" + schema: [ + { + type: "object", + properties: { + ignoreCase: { + type: "boolean" + } + }, + additionalProperties: false } - }, - "additionalProperties": false + ] + }, + + create: function(context) { + + var configuration = context.options[0] || {}, + ignoreCase = configuration.ignoreCase || false; + + return { + VariableDeclaration: function(node) { + node.declarations.reduce(function(memo, decl) { + if (decl.id.type === "ObjectPattern" || decl.id.type === "ArrayPattern") { + return memo; + } + + var lastVariableName = memo.id.name, + currenVariableName = decl.id.name; + + if (ignoreCase) { + lastVariableName = lastVariableName.toLowerCase(); + currenVariableName = currenVariableName.toLowerCase(); + } + + if (currenVariableName < lastVariableName) { + context.report(decl, "Variables within the same declaration block should be sorted alphabetically"); + return memo; + } else { + return decl; + } + }, node.declarations[0]); + } + }; } -]; +}; diff --git a/tools/eslint/lib/rules/space-before-blocks.js b/tools/eslint/lib/rules/space-before-blocks.js index c7fbec83316172..7fb9d5cddcc9c5 100644 --- a/tools/eslint/lib/rules/space-before-blocks.js +++ b/tools/eslint/lib/rules/space-before-blocks.js @@ -1,7 +1,6 @@ /** * @fileoverview A rule to ensure whitespace before blocks. * @author Mathias Schreck - * @copyright 2014 Mathias Schreck. All rights reserved. */ "use strict"; @@ -12,129 +11,141 @@ var astUtils = require("../ast-utils"); // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var config = context.options[0], - sourceCode = context.getSourceCode(), - checkFunctions = true, - checkKeywords = true, - checkClasses = true; - - if (typeof config === "object") { - checkFunctions = config.functions !== "never"; - checkKeywords = config.keywords !== "never"; - checkClasses = config.classes !== "never"; - } else if (config === "never") { - checkFunctions = false; - checkKeywords = false; - checkClasses = false; - } +module.exports = { + meta: { + docs: { + description: "enforce consistent spacing before blocks", + category: "Stylistic Issues", + recommended: false + }, - /** - * Checks whether or not a given token is an arrow operator (=>) or a keyword - * in order to avoid to conflict with `arrow-spacing` and `keyword-spacing`. - * - * @param {Token} token - A token to check. - * @returns {boolean} `true` if the token is an arrow operator. - */ - function isConflicted(token) { - return (token.type === "Punctuator" && token.value === "=>") || token.type === "Keyword"; - } + fixable: "whitespace", - /** - * Checks the given BlockStatement node has a preceding space if it doesn’t start on a new line. - * @param {ASTNode|Token} node The AST node of a BlockStatement. - * @returns {void} undefined. - */ - function checkPrecedingSpace(node) { - var precedingToken = context.getTokenBefore(node), - hasSpace, - parent, - requireSpace; - - if (precedingToken && !isConflicted(precedingToken) && astUtils.isTokenOnSameLine(precedingToken, node)) { - hasSpace = sourceCode.isSpaceBetweenTokens(precedingToken, node); - parent = context.getAncestors().pop(); - if (parent.type === "FunctionExpression" || parent.type === "FunctionDeclaration") { - requireSpace = checkFunctions; - } else if (node.type === "ClassBody") { - requireSpace = checkClasses; - } else { - requireSpace = checkKeywords; + schema: [ + { + oneOf: [ + { + enum: ["always", "never"] + }, + { + type: "object", + properties: { + keywords: { + enum: ["always", "never"] + }, + functions: { + enum: ["always", "never"] + }, + classes: { + enum: ["always", "never"] + } + }, + additionalProperties: false + } + ] } + ] + }, + + create: function(context) { + var config = context.options[0], + sourceCode = context.getSourceCode(), + checkFunctions = true, + checkKeywords = true, + checkClasses = true; - if (requireSpace) { - if (!hasSpace) { - context.report({ - node: node, - message: "Missing space before opening brace.", - fix: function(fixer) { - return fixer.insertTextBefore(node, " "); - } - }); + if (typeof config === "object") { + checkFunctions = config.functions !== "never"; + checkKeywords = config.keywords !== "never"; + checkClasses = config.classes !== "never"; + } else if (config === "never") { + checkFunctions = false; + checkKeywords = false; + checkClasses = false; + } + + /** + * Checks whether or not a given token is an arrow operator (=>) or a keyword + * in order to avoid to conflict with `arrow-spacing` and `keyword-spacing`. + * + * @param {Token} token - A token to check. + * @returns {boolean} `true` if the token is an arrow operator. + */ + function isConflicted(token) { + return (token.type === "Punctuator" && token.value === "=>") || token.type === "Keyword"; + } + + /** + * Checks the given BlockStatement node has a preceding space if it doesn’t start on a new line. + * @param {ASTNode|Token} node The AST node of a BlockStatement. + * @returns {void} undefined. + */ + function checkPrecedingSpace(node) { + var precedingToken = context.getTokenBefore(node), + hasSpace, + parent, + requireSpace; + + if (precedingToken && !isConflicted(precedingToken) && astUtils.isTokenOnSameLine(precedingToken, node)) { + hasSpace = sourceCode.isSpaceBetweenTokens(precedingToken, node); + parent = context.getAncestors().pop(); + if (parent.type === "FunctionExpression" || parent.type === "FunctionDeclaration") { + requireSpace = checkFunctions; + } else if (node.type === "ClassBody") { + requireSpace = checkClasses; + } else { + requireSpace = checkKeywords; } - } else { - if (hasSpace) { - context.report({ - node: node, - message: "Unexpected space before opening brace.", - fix: function(fixer) { - return fixer.removeRange([precedingToken.range[1], node.range[0]]); - } - }); + + if (requireSpace) { + if (!hasSpace) { + context.report({ + node: node, + message: "Missing space before opening brace.", + fix: function(fixer) { + return fixer.insertTextBefore(node, " "); + } + }); + } + } else { + if (hasSpace) { + context.report({ + node: node, + message: "Unexpected space before opening brace.", + fix: function(fixer) { + return fixer.removeRange([precedingToken.range[1], node.range[0]]); + } + }); + } } } } - } - /** - * Checks if the CaseBlock of an given SwitchStatement node has a preceding space. - * @param {ASTNode} node The node of a SwitchStatement. - * @returns {void} undefined. - */ - function checkSpaceBeforeCaseBlock(node) { - var cases = node.cases, - firstCase, - openingBrace; - - if (cases.length > 0) { - firstCase = cases[0]; - openingBrace = context.getTokenBefore(firstCase); - } else { - openingBrace = context.getLastToken(node, 1); - } + /** + * Checks if the CaseBlock of an given SwitchStatement node has a preceding space. + * @param {ASTNode} node The node of a SwitchStatement. + * @returns {void} undefined. + */ + function checkSpaceBeforeCaseBlock(node) { + var cases = node.cases, + firstCase, + openingBrace; - checkPrecedingSpace(openingBrace); - } + if (cases.length > 0) { + firstCase = cases[0]; + openingBrace = context.getTokenBefore(firstCase); + } else { + openingBrace = context.getLastToken(node, 1); + } - return { - "BlockStatement": checkPrecedingSpace, - "ClassBody": checkPrecedingSpace, - "SwitchStatement": checkSpaceBeforeCaseBlock - }; + checkPrecedingSpace(openingBrace); + } -}; + return { + BlockStatement: checkPrecedingSpace, + ClassBody: checkPrecedingSpace, + SwitchStatement: checkSpaceBeforeCaseBlock + }; -module.exports.schema = [ - { - "oneOf": [ - { - "enum": ["always", "never"] - }, - { - "type": "object", - "properties": { - "keywords": { - "enum": ["always", "never"] - }, - "functions": { - "enum": ["always", "never"] - }, - "classes": { - "enum": ["always", "never"] - } - }, - "additionalProperties": false - } - ] } -]; +}; diff --git a/tools/eslint/lib/rules/space-before-function-paren.js b/tools/eslint/lib/rules/space-before-function-paren.js index b96acb6678c42e..d96cb4a6085021 100644 --- a/tools/eslint/lib/rules/space-before-function-paren.js +++ b/tools/eslint/lib/rules/space-before-function-paren.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to validate spacing before function paren. * @author Mathias Schreck - * @copyright 2015 Mathias Schreck - * See LICENSE in root directory for full license. */ "use strict"; @@ -10,115 +8,135 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "enforce consistent spacing before `function` definition opening parenthesis", + category: "Stylistic Issues", + recommended: false + }, - var configuration = context.options[0], - sourceCode = context.getSourceCode(), - requireAnonymousFunctionSpacing = true, - requireNamedFunctionSpacing = true; + fixable: "whitespace", - if (typeof configuration === "object") { - requireAnonymousFunctionSpacing = configuration.anonymous !== "never"; - requireNamedFunctionSpacing = configuration.named !== "never"; - } else if (configuration === "never") { - requireAnonymousFunctionSpacing = false; - requireNamedFunctionSpacing = false; - } + schema: [ + { + oneOf: [ + { + enum: ["always", "never"] + }, + { + type: "object", + properties: { + anonymous: { + enum: ["always", "never", "ignore"] + }, + named: { + enum: ["always", "never", "ignore"] + } + }, + additionalProperties: false + } + ] + } + ] + }, + + create: function(context) { - /** - * Determines whether a function has a name. - * @param {ASTNode} node The function node. - * @returns {boolean} Whether the function has a name. - */ - function isNamedFunction(node) { - var parent; + var configuration = context.options[0], + sourceCode = context.getSourceCode(), + requireAnonymousFunctionSpacing = true, + forbidAnonymousFunctionSpacing = false, + requireNamedFunctionSpacing = true, + forbidNamedFunctionSpacing = false; - if (node.id) { - return true; + if (typeof configuration === "object") { + requireAnonymousFunctionSpacing = ( + !configuration.anonymous || configuration.anonymous === "always"); + forbidAnonymousFunctionSpacing = configuration.anonymous === "never"; + requireNamedFunctionSpacing = ( + !configuration.named || configuration.named === "always"); + forbidNamedFunctionSpacing = configuration.named === "never"; + } else if (configuration === "never") { + requireAnonymousFunctionSpacing = false; + forbidAnonymousFunctionSpacing = true; + requireNamedFunctionSpacing = false; + forbidNamedFunctionSpacing = true; } - parent = node.parent; - return parent.type === "MethodDefinition" || - (parent.type === "Property" && - ( - parent.kind === "get" || - parent.kind === "set" || - parent.method - ) - ); - } + /** + * Determines whether a function has a name. + * @param {ASTNode} node The function node. + * @returns {boolean} Whether the function has a name. + */ + function isNamedFunction(node) { + var parent; - /** - * Validates the spacing before function parentheses. - * @param {ASTNode} node The node to be validated. - * @returns {void} - */ - function validateSpacingBeforeParentheses(node) { - var isNamed = isNamedFunction(node), - leftToken, - rightToken, - location; + if (node.id) { + return true; + } - if (node.generator && !isNamed) { - return; + parent = node.parent; + return parent.type === "MethodDefinition" || + (parent.type === "Property" && + ( + parent.kind === "get" || + parent.kind === "set" || + parent.method + ) + ); } - rightToken = sourceCode.getFirstToken(node); - while (rightToken.value !== "(") { - rightToken = sourceCode.getTokenAfter(rightToken); - } - leftToken = context.getTokenBefore(rightToken); - location = leftToken.loc.end; + /** + * Validates the spacing before function parentheses. + * @param {ASTNode} node The node to be validated. + * @returns {void} + */ + function validateSpacingBeforeParentheses(node) { + var isNamed = isNamedFunction(node), + leftToken, + rightToken, + location; - if (sourceCode.isSpaceBetweenTokens(leftToken, rightToken)) { - if ((isNamed && !requireNamedFunctionSpacing) || (!isNamed && !requireAnonymousFunctionSpacing)) { - context.report({ - node: node, - loc: location, - message: "Unexpected space before function parentheses.", - fix: function(fixer) { - return fixer.removeRange([leftToken.range[1], rightToken.range[0]]); - } - }); - } - } else { - if ((isNamed && requireNamedFunctionSpacing) || (!isNamed && requireAnonymousFunctionSpacing)) { - context.report({ - node: node, - loc: location, - message: "Missing space before function parentheses.", - fix: function(fixer) { - return fixer.insertTextAfter(leftToken, " "); - } - }); + if (node.generator && !isNamed) { + return; } - } - } - return { - "FunctionDeclaration": validateSpacingBeforeParentheses, - "FunctionExpression": validateSpacingBeforeParentheses - }; -}; + rightToken = sourceCode.getFirstToken(node); + while (rightToken.value !== "(") { + rightToken = sourceCode.getTokenAfter(rightToken); + } + leftToken = context.getTokenBefore(rightToken); + location = leftToken.loc.end; -module.exports.schema = [ - { - "oneOf": [ - { - "enum": ["always", "never"] - }, - { - "type": "object", - "properties": { - "anonymous": { - "enum": ["always", "never"] - }, - "named": { - "enum": ["always", "never"] - } - }, - "additionalProperties": false + if (sourceCode.isSpaceBetweenTokens(leftToken, rightToken)) { + if ((isNamed && forbidNamedFunctionSpacing) || (!isNamed && forbidAnonymousFunctionSpacing)) { + context.report({ + node: node, + loc: location, + message: "Unexpected space before function parentheses.", + fix: function(fixer) { + return fixer.removeRange([leftToken.range[1], rightToken.range[0]]); + } + }); + } + } else { + if ((isNamed && requireNamedFunctionSpacing) || (!isNamed && requireAnonymousFunctionSpacing)) { + context.report({ + node: node, + loc: location, + message: "Missing space before function parentheses.", + fix: function(fixer) { + return fixer.insertTextAfter(leftToken, " "); + } + }); + } } - ] + } + + return { + FunctionDeclaration: validateSpacingBeforeParentheses, + FunctionExpression: validateSpacingBeforeParentheses + }; } -]; +}; diff --git a/tools/eslint/lib/rules/space-in-parens.js b/tools/eslint/lib/rules/space-in-parens.js index bd15a41f3c66ba..11361aec1202f3 100644 --- a/tools/eslint/lib/rules/space-in-parens.js +++ b/tools/eslint/lib/rules/space-in-parens.js @@ -1,8 +1,6 @@ /** * @fileoverview Disallows or enforces spaces inside of parentheses. * @author Jonathan Rajavuori - * @copyright 2014 David Clark. All rights reserved. - * @copyright 2014 Jonathan Rajavuori. All rights reserved. */ "use strict"; @@ -12,260 +10,272 @@ var astUtils = require("../ast-utils"); // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - var MISSING_SPACE_MESSAGE = "There must be a space inside this paren.", - REJECTED_SPACE_MESSAGE = "There should be no spaces inside this paren.", - ALWAYS = context.options[0] === "always", - - exceptionsArrayOptions = (context.options.length === 2) ? context.options[1].exceptions : [], - options = {}, - exceptions; +module.exports = { + meta: { + docs: { + description: "enforce consistent spacing inside parentheses", + category: "Stylistic Issues", + recommended: false + }, - if (exceptionsArrayOptions.length) { - options.braceException = exceptionsArrayOptions.indexOf("{}") !== -1; - options.bracketException = exceptionsArrayOptions.indexOf("[]") !== -1; - options.parenException = exceptionsArrayOptions.indexOf("()") !== -1; - options.empty = exceptionsArrayOptions.indexOf("empty") !== -1; - } + fixable: "whitespace", + + schema: [ + { + enum: ["always", "never"] + }, + { + type: "object", + properties: { + exceptions: { + type: "array", + items: { + enum: ["{}", "[]", "()", "empty"] + }, + uniqueItems: true + } + }, + additionalProperties: false + } + ] + }, - /** - * Produces an object with the opener and closer exception values - * @param {Object} opts The exception options - * @returns {Object} `openers` and `closers` exception values - * @private - */ - function getExceptions() { - var openers = [], - closers = []; - - if (options.braceException) { - openers.push("{"); - closers.push("}"); - } + create: function(context) { - if (options.bracketException) { - openers.push("["); - closers.push("]"); - } + var MISSING_SPACE_MESSAGE = "There must be a space inside this paren.", + REJECTED_SPACE_MESSAGE = "There should be no spaces inside this paren.", + ALWAYS = context.options[0] === "always", - if (options.parenException) { - openers.push("("); - closers.push(")"); - } + exceptionsArrayOptions = (context.options.length === 2) ? context.options[1].exceptions : [], + options = {}, + exceptions; - if (options.empty) { - openers.push(")"); - closers.push("("); + if (exceptionsArrayOptions.length) { + options.braceException = exceptionsArrayOptions.indexOf("{}") !== -1; + options.bracketException = exceptionsArrayOptions.indexOf("[]") !== -1; + options.parenException = exceptionsArrayOptions.indexOf("()") !== -1; + options.empty = exceptionsArrayOptions.indexOf("empty") !== -1; } - return { - openers: openers, - closers: closers - }; - } - - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- - var sourceCode = context.getSourceCode(); - - /** - * Determines if a token is one of the exceptions for the opener paren - * @param {Object} token The token to check - * @returns {boolean} True if the token is one of the exceptions for the opener paren - */ - function isOpenerException(token) { - return token.type === "Punctuator" && exceptions.openers.indexOf(token.value) >= 0; - } - - /** - * Determines if a token is one of the exceptions for the closer paren - * @param {Object} token The token to check - * @returns {boolean} True if the token is one of the exceptions for the closer paren - */ - function isCloserException(token) { - return token.type === "Punctuator" && exceptions.closers.indexOf(token.value) >= 0; - } - - /** - * Determines if an opener paren should have a missing space after it - * @param {Object} left The paren token - * @param {Object} right The token after it - * @returns {boolean} True if the paren should have a space - */ - function shouldOpenerHaveSpace(left, right) { - if (sourceCode.isSpaceBetweenTokens(left, right)) { - return false; - } + /** + * Produces an object with the opener and closer exception values + * @param {Object} opts The exception options + * @returns {Object} `openers` and `closers` exception values + * @private + */ + function getExceptions() { + var openers = [], + closers = []; + + if (options.braceException) { + openers.push("{"); + closers.push("}"); + } - if (ALWAYS) { - if (right.type === "Punctuator" && right.value === ")") { - return false; + if (options.bracketException) { + openers.push("["); + closers.push("]"); } - return !isOpenerException(right); - } else { - return isOpenerException(right); - } - } - /** - * Determines if an closer paren should have a missing space after it - * @param {Object} left The token before the paren - * @param {Object} right The paren token - * @returns {boolean} True if the paren should have a space - */ - function shouldCloserHaveSpace(left, right) { - if (left.type === "Punctuator" && left.value === "(") { - return false; - } + if (options.parenException) { + openers.push("("); + closers.push(")"); + } - if (sourceCode.isSpaceBetweenTokens(left, right)) { - return false; - } + if (options.empty) { + openers.push(")"); + closers.push("("); + } - if (ALWAYS) { - return !isCloserException(left); - } else { - return isCloserException(left); + return { + openers: openers, + closers: closers + }; } - } - /** - * Determines if an opener paren should not have an existing space after it - * @param {Object} left The paren token - * @param {Object} right The token after it - * @returns {boolean} True if the paren should reject the space - */ - function shouldOpenerRejectSpace(left, right) { - if (right.type === "Line") { - return false; + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- + var sourceCode = context.getSourceCode(); + + /** + * Determines if a token is one of the exceptions for the opener paren + * @param {Object} token The token to check + * @returns {boolean} True if the token is one of the exceptions for the opener paren + */ + function isOpenerException(token) { + return token.type === "Punctuator" && exceptions.openers.indexOf(token.value) >= 0; } - if (!astUtils.isTokenOnSameLine(left, right)) { - return false; + /** + * Determines if a token is one of the exceptions for the closer paren + * @param {Object} token The token to check + * @returns {boolean} True if the token is one of the exceptions for the closer paren + */ + function isCloserException(token) { + return token.type === "Punctuator" && exceptions.closers.indexOf(token.value) >= 0; } - if (!sourceCode.isSpaceBetweenTokens(left, right)) { - return false; - } + /** + * Determines if an opener paren should have a missing space after it + * @param {Object} left The paren token + * @param {Object} right The token after it + * @returns {boolean} True if the paren should have a space + */ + function shouldOpenerHaveSpace(left, right) { + if (sourceCode.isSpaceBetweenTokens(left, right)) { + return false; + } - if (ALWAYS) { - return isOpenerException(right); - } else { - return !isOpenerException(right); + if (ALWAYS) { + if (right.type === "Punctuator" && right.value === ")") { + return false; + } + return !isOpenerException(right); + } else { + return isOpenerException(right); + } } - } - /** - * Determines if an closer paren should not have an existing space after it - * @param {Object} left The token before the paren - * @param {Object} right The paren token - * @returns {boolean} True if the paren should reject the space - */ - function shouldCloserRejectSpace(left, right) { - if (left.type === "Punctuator" && left.value === "(") { - return false; - } + /** + * Determines if an closer paren should have a missing space after it + * @param {Object} left The token before the paren + * @param {Object} right The paren token + * @returns {boolean} True if the paren should have a space + */ + function shouldCloserHaveSpace(left, right) { + if (left.type === "Punctuator" && left.value === "(") { + return false; + } - if (!astUtils.isTokenOnSameLine(left, right)) { - return false; - } + if (sourceCode.isSpaceBetweenTokens(left, right)) { + return false; + } - if (!sourceCode.isSpaceBetweenTokens(left, right)) { - return false; + if (ALWAYS) { + return !isCloserException(left); + } else { + return isCloserException(left); + } } - if (ALWAYS) { - return isCloserException(left); - } else { - return !isCloserException(left); - } - } + /** + * Determines if an opener paren should not have an existing space after it + * @param {Object} left The paren token + * @param {Object} right The token after it + * @returns {boolean} True if the paren should reject the space + */ + function shouldOpenerRejectSpace(left, right) { + if (right.type === "Line") { + return false; + } - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- + if (!astUtils.isTokenOnSameLine(left, right)) { + return false; + } - return { - "Program": function checkParenSpaces(node) { - var tokens, prevToken, nextToken; + if (!sourceCode.isSpaceBetweenTokens(left, right)) { + return false; + } - exceptions = getExceptions(); - tokens = sourceCode.tokensAndComments; + if (ALWAYS) { + return isOpenerException(right); + } else { + return !isOpenerException(right); + } + } - tokens.forEach(function(token, i) { - prevToken = tokens[i - 1]; - nextToken = tokens[i + 1]; + /** + * Determines if an closer paren should not have an existing space after it + * @param {Object} left The token before the paren + * @param {Object} right The paren token + * @returns {boolean} True if the paren should reject the space + */ + function shouldCloserRejectSpace(left, right) { + if (left.type === "Punctuator" && left.value === "(") { + return false; + } - if (token.type !== "Punctuator") { - return; - } + if (!astUtils.isTokenOnSameLine(left, right)) { + return false; + } - if (token.value !== "(" && token.value !== ")") { - return; - } + if (!sourceCode.isSpaceBetweenTokens(left, right)) { + return false; + } - if (token.value === "(" && shouldOpenerHaveSpace(token, nextToken)) { - context.report({ - node: node, - loc: token.loc.start, - message: MISSING_SPACE_MESSAGE, - fix: function(fixer) { - return fixer.insertTextAfter(token, " "); - } - }); - } else if (token.value === "(" && shouldOpenerRejectSpace(token, nextToken)) { - context.report({ - node: node, - loc: token.loc.start, - message: REJECTED_SPACE_MESSAGE, - fix: function(fixer) { - return fixer.removeRange([token.range[1], nextToken.range[0]]); - } - }); - } else if (token.value === ")" && shouldCloserHaveSpace(prevToken, token)) { - - // context.report(node, token.loc.start, MISSING_SPACE_MESSAGE); - context.report({ - node: node, - loc: token.loc.start, - message: MISSING_SPACE_MESSAGE, - fix: function(fixer) { - return fixer.insertTextBefore(token, " "); - } - }); - } else if (token.value === ")" && shouldCloserRejectSpace(prevToken, token)) { - context.report({ - node: node, - loc: token.loc.start, - message: REJECTED_SPACE_MESSAGE, - fix: function(fixer) { - return fixer.removeRange([prevToken.range[1], token.range[0]]); - } - }); - } - }); + if (ALWAYS) { + return isCloserException(left); + } else { + return !isCloserException(left); + } } - }; -}; + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- -module.exports.schema = [ - { - "enum": ["always", "never"] - }, - { - "type": "object", - "properties": { - "exceptions": { - "type": "array", - "items": { - "enum": ["{}", "[]", "()", "empty"] - }, - "uniqueItems": true + return { + Program: function checkParenSpaces(node) { + var tokens, prevToken, nextToken; + + exceptions = getExceptions(); + tokens = sourceCode.tokensAndComments; + + tokens.forEach(function(token, i) { + prevToken = tokens[i - 1]; + nextToken = tokens[i + 1]; + + if (token.type !== "Punctuator") { + return; + } + + if (token.value !== "(" && token.value !== ")") { + return; + } + + if (token.value === "(" && shouldOpenerHaveSpace(token, nextToken)) { + context.report({ + node: node, + loc: token.loc.start, + message: MISSING_SPACE_MESSAGE, + fix: function(fixer) { + return fixer.insertTextAfter(token, " "); + } + }); + } else if (token.value === "(" && shouldOpenerRejectSpace(token, nextToken)) { + context.report({ + node: node, + loc: token.loc.start, + message: REJECTED_SPACE_MESSAGE, + fix: function(fixer) { + return fixer.removeRange([token.range[1], nextToken.range[0]]); + } + }); + } else if (token.value === ")" && shouldCloserHaveSpace(prevToken, token)) { + + // context.report(node, token.loc.start, MISSING_SPACE_MESSAGE); + context.report({ + node: node, + loc: token.loc.start, + message: MISSING_SPACE_MESSAGE, + fix: function(fixer) { + return fixer.insertTextBefore(token, " "); + } + }); + } else if (token.value === ")" && shouldCloserRejectSpace(prevToken, token)) { + context.report({ + node: node, + loc: token.loc.start, + message: REJECTED_SPACE_MESSAGE, + fix: function(fixer) { + return fixer.removeRange([prevToken.range[1], token.range[0]]); + } + }); + } + }); } - }, - "additionalProperties": false + }; + } -]; +}; diff --git a/tools/eslint/lib/rules/space-infix-ops.js b/tools/eslint/lib/rules/space-infix-ops.js index dee07ee31ae75f..862ff66fb5e6ae 100644 --- a/tools/eslint/lib/rules/space-infix-ops.js +++ b/tools/eslint/lib/rules/space-infix-ops.js @@ -8,141 +8,153 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var int32Hint = context.options[0] ? context.options[0].int32Hint === true : false; - - var OPERATORS = [ - "*", "/", "%", "+", "-", "<<", ">>", ">>>", "<", "<=", ">", ">=", "in", - "instanceof", "==", "!=", "===", "!==", "&", "^", "|", "&&", "||", "=", - "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=", "&=", "^=", "|=", - "?", ":", ",", "**" - ]; - - /** - * Returns the first token which violates the rule - * @param {ASTNode} left - The left node of the main node - * @param {ASTNode} right - The right node of the main node - * @returns {object} The violator token or null - * @private - */ - function getFirstNonSpacedToken(left, right) { - var op, - tokens = context.getTokensBetween(left, right, 1); - - for (var i = 1, l = tokens.length - 1; i < l; ++i) { - op = tokens[i]; - if ( - op.type === "Punctuator" && - OPERATORS.indexOf(op.value) >= 0 && - (tokens[i - 1].range[1] >= op.range[0] || op.range[1] >= tokens[i + 1].range[0]) - ) { - return op; +module.exports = { + meta: { + docs: { + description: "require spacing around operators", + category: "Stylistic Issues", + recommended: false + }, + + fixable: "whitespace", + + schema: [ + { + type: "object", + properties: { + int32Hint: { + type: "boolean" + } + }, + additionalProperties: false + } + ] + }, + + create: function(context) { + var int32Hint = context.options[0] ? context.options[0].int32Hint === true : false; + + var OPERATORS = [ + "*", "/", "%", "+", "-", "<<", ">>", ">>>", "<", "<=", ">", ">=", "in", + "instanceof", "==", "!=", "===", "!==", "&", "^", "|", "&&", "||", "=", + "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=", "&=", "^=", "|=", + "?", ":", ",", "**" + ]; + + /** + * Returns the first token which violates the rule + * @param {ASTNode} left - The left node of the main node + * @param {ASTNode} right - The right node of the main node + * @returns {object} The violator token or null + * @private + */ + function getFirstNonSpacedToken(left, right) { + var op, + tokens = context.getTokensBetween(left, right, 1); + + for (var i = 1, l = tokens.length - 1; i < l; ++i) { + op = tokens[i]; + if ( + op.type === "Punctuator" && + OPERATORS.indexOf(op.value) >= 0 && + (tokens[i - 1].range[1] >= op.range[0] || op.range[1] >= tokens[i + 1].range[0]) + ) { + return op; + } } + return null; } - return null; - } - /** - * Reports an AST node as a rule violation - * @param {ASTNode} mainNode - The node to report - * @param {object} culpritToken - The token which has a problem - * @returns {void} - * @private - */ - function report(mainNode, culpritToken) { - context.report({ - node: mainNode, - loc: culpritToken.loc.start, - message: "Infix operators must be spaced.", - fix: function(fixer) { - var previousToken = context.getTokenBefore(culpritToken); - var afterToken = context.getTokenAfter(culpritToken); - var fixString = ""; - - if (culpritToken.range[0] - previousToken.range[1] === 0) { - fixString = " "; + /** + * Reports an AST node as a rule violation + * @param {ASTNode} mainNode - The node to report + * @param {object} culpritToken - The token which has a problem + * @returns {void} + * @private + */ + function report(mainNode, culpritToken) { + context.report({ + node: mainNode, + loc: culpritToken.loc.start, + message: "Infix operators must be spaced.", + fix: function(fixer) { + var previousToken = context.getTokenBefore(culpritToken); + var afterToken = context.getTokenAfter(culpritToken); + var fixString = ""; + + if (culpritToken.range[0] - previousToken.range[1] === 0) { + fixString = " "; + } + + fixString += culpritToken.value; + + if (afterToken.range[0] - culpritToken.range[1] === 0) { + fixString += " "; + } + + return fixer.replaceText(culpritToken, fixString); } + }); + } - fixString += culpritToken.value; + /** + * Check if the node is binary then report + * @param {ASTNode} node node to evaluate + * @returns {void} + * @private + */ + function checkBinary(node) { + var nonSpacedNode = getFirstNonSpacedToken(node.left, node.right); - if (afterToken.range[0] - culpritToken.range[1] === 0) { - fixString += " "; + if (nonSpacedNode) { + if (!(int32Hint && context.getSource(node).substr(-2) === "|0")) { + report(node, nonSpacedNode); } - - return fixer.replaceText(culpritToken, fixString); - } - }); - } - - /** - * Check if the node is binary then report - * @param {ASTNode} node node to evaluate - * @returns {void} - * @private - */ - function checkBinary(node) { - var nonSpacedNode = getFirstNonSpacedToken(node.left, node.right); - - if (nonSpacedNode) { - if (!(int32Hint && context.getSource(node).substr(-2) === "|0")) { - report(node, nonSpacedNode); } } - } - /** - * Check if the node is conditional - * @param {ASTNode} node node to evaluate - * @returns {void} - * @private - */ - function checkConditional(node) { - var nonSpacedConsequesntNode = getFirstNonSpacedToken(node.test, node.consequent); - var nonSpacedAlternateNode = getFirstNonSpacedToken(node.consequent, node.alternate); - - if (nonSpacedConsequesntNode) { - report(node, nonSpacedConsequesntNode); - } else if (nonSpacedAlternateNode) { - report(node, nonSpacedAlternateNode); + /** + * Check if the node is conditional + * @param {ASTNode} node node to evaluate + * @returns {void} + * @private + */ + function checkConditional(node) { + var nonSpacedConsequesntNode = getFirstNonSpacedToken(node.test, node.consequent); + var nonSpacedAlternateNode = getFirstNonSpacedToken(node.consequent, node.alternate); + + if (nonSpacedConsequesntNode) { + report(node, nonSpacedConsequesntNode); + } else if (nonSpacedAlternateNode) { + report(node, nonSpacedAlternateNode); + } } - } - /** - * Check if the node is a variable - * @param {ASTNode} node node to evaluate - * @returns {void} - * @private - */ - function checkVar(node) { - var nonSpacedNode; - - if (node.init) { - nonSpacedNode = getFirstNonSpacedToken(node.id, node.init); - if (nonSpacedNode) { - report(node, nonSpacedNode); + /** + * Check if the node is a variable + * @param {ASTNode} node node to evaluate + * @returns {void} + * @private + */ + function checkVar(node) { + var nonSpacedNode; + + if (node.init) { + nonSpacedNode = getFirstNonSpacedToken(node.id, node.init); + if (nonSpacedNode) { + report(node, nonSpacedNode); + } } } - } - return { - "AssignmentExpression": checkBinary, - "AssignmentPattern": checkBinary, - "BinaryExpression": checkBinary, - "LogicalExpression": checkBinary, - "ConditionalExpression": checkConditional, - "VariableDeclarator": checkVar - }; + return { + AssignmentExpression: checkBinary, + AssignmentPattern: checkBinary, + BinaryExpression: checkBinary, + LogicalExpression: checkBinary, + ConditionalExpression: checkConditional, + VariableDeclarator: checkVar + }; -}; - -module.exports.schema = [ - { - "type": "object", - "properties": { - "int32Hint": { - "type": "boolean" - } - }, - "additionalProperties": false } -]; +}; diff --git a/tools/eslint/lib/rules/space-unary-ops.js b/tools/eslint/lib/rules/space-unary-ops.js index d5412e36f3abde..0bb92af1e68d6c 100644 --- a/tools/eslint/lib/rules/space-unary-ops.js +++ b/tools/eslint/lib/rules/space-unary-ops.js @@ -1,7 +1,6 @@ /** * @fileoverview This rule shoud require or disallow spaces before or after unary operations. * @author Marcin Kumorek - * @copyright 2014 Marcin Kumorek. All rights reserved. */ "use strict"; @@ -9,259 +8,271 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var options = context.options && Array.isArray(context.options) && context.options[0] || { words: true, nonwords: false }; +module.exports = { + meta: { + docs: { + description: "enforce consistent spacing before or after unary operators", + category: "Stylistic Issues", + recommended: false + }, - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- + fixable: "whitespace", - /** - * Check if the node is the first "!" in a "!!" convert to Boolean expression - * @param {ASTnode} node AST node - * @returns {boolean} Whether or not the node is first "!" in "!!" - */ - function isFirstBangInBangBangExpression(node) { - return node && node.type === "UnaryExpression" && node.argument.operator === "!" && - node.argument && node.argument.type === "UnaryExpression" && node.argument.operator === "!"; - } + schema: [ + { + type: "object", + properties: { + words: { + type: "boolean" + }, + nonwords: { + type: "boolean" + }, + overrides: { + type: "object", + additionalProperties: { + type: "boolean" + } + } + }, + additionalProperties: false + } + ] + }, - /** - * Check if the node's child argument is an "ObjectExpression" - * @param {ASTnode} node AST node - * @returns {boolean} Whether or not the argument's type is "ObjectExpression" - */ - function isArgumentObjectExpression(node) { - return node.argument && node.argument.type && node.argument.type === "ObjectExpression"; - } + create: function(context) { + var options = context.options && Array.isArray(context.options) && context.options[0] || { words: true, nonwords: false }; - /** - * Checks if an override exists for a given operator. - * @param {ASTnode} node AST node - * @param {string} operator Operator - * @returns {boolean} Whether or not an override has been provided for the operator - */ - function overrideExistsForOperator(node, operator) { - return options.overrides && options.overrides.hasOwnProperty(operator); - } + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- - /** - * Gets the value that the override was set to for this operator - * @param {ASTnode} node AST node - * @param {string} operator Operator - * @returns {boolean} Whether or not an override enforces a space with this operator - */ - function overrideEnforcesSpaces(node, operator) { - return options.overrides[operator]; - } + /** + * Check if the node is the first "!" in a "!!" convert to Boolean expression + * @param {ASTnode} node AST node + * @returns {boolean} Whether or not the node is first "!" in "!!" + */ + function isFirstBangInBangBangExpression(node) { + return node && node.type === "UnaryExpression" && node.argument.operator === "!" && + node.argument && node.argument.type === "UnaryExpression" && node.argument.operator === "!"; + } - /** - * Verify Unary Word Operator has spaces after the word operator - * @param {ASTnode} node AST node - * @param {object} firstToken first token from the AST node - * @param {object} secondToken second token from the AST node - * @param {string} word The word to be used for reporting - * @returns {void} - */ - function verifyWordHasSpaces(node, firstToken, secondToken, word) { - if (secondToken.range[0] === firstToken.range[1]) { - context.report({ - node: node, - message: "Unary word operator '" + word + "' must be followed by whitespace.", - fix: function(fixer) { - return fixer.insertTextAfter(firstToken, " "); - } - }); + /** + * Check if the node's child argument is an "ObjectExpression" + * @param {ASTnode} node AST node + * @returns {boolean} Whether or not the argument's type is "ObjectExpression" + */ + function isArgumentObjectExpression(node) { + return node.argument && node.argument.type && node.argument.type === "ObjectExpression"; + } + + /** + * Checks if an override exists for a given operator. + * @param {ASTnode} node AST node + * @param {string} operator Operator + * @returns {boolean} Whether or not an override has been provided for the operator + */ + function overrideExistsForOperator(node, operator) { + return options.overrides && options.overrides.hasOwnProperty(operator); + } + + /** + * Gets the value that the override was set to for this operator + * @param {ASTnode} node AST node + * @param {string} operator Operator + * @returns {boolean} Whether or not an override enforces a space with this operator + */ + function overrideEnforcesSpaces(node, operator) { + return options.overrides[operator]; } - } - /** - * Verify Unary Word Operator doesn't have spaces after the word operator - * @param {ASTnode} node AST node - * @param {object} firstToken first token from the AST node - * @param {object} secondToken second token from the AST node - * @param {string} word The word to be used for reporting - * @returns {void} - */ - function verifyWordDoesntHaveSpaces(node, firstToken, secondToken, word) { - if (isArgumentObjectExpression(node)) { - if (secondToken.range[0] > firstToken.range[1]) { + /** + * Verify Unary Word Operator has spaces after the word operator + * @param {ASTnode} node AST node + * @param {object} firstToken first token from the AST node + * @param {object} secondToken second token from the AST node + * @param {string} word The word to be used for reporting + * @returns {void} + */ + function verifyWordHasSpaces(node, firstToken, secondToken, word) { + if (secondToken.range[0] === firstToken.range[1]) { context.report({ node: node, - message: "Unexpected space after unary word operator '" + word + "'.", + message: "Unary word operator '" + word + "' must be followed by whitespace.", fix: function(fixer) { - return fixer.removeRange([firstToken.range[1], secondToken.range[0]]); + return fixer.insertTextAfter(firstToken, " "); } }); } } - } - /** - * Check Unary Word Operators for spaces after the word operator - * @param {ASTnode} node AST node - * @param {object} firstToken first token from the AST node - * @param {object} secondToken second token from the AST node - * @param {string} word The word to be used for reporting - * @returns {void} - */ - function checkUnaryWordOperatorForSpaces(node, firstToken, secondToken, word) { - word = word || firstToken.value; + /** + * Verify Unary Word Operator doesn't have spaces after the word operator + * @param {ASTnode} node AST node + * @param {object} firstToken first token from the AST node + * @param {object} secondToken second token from the AST node + * @param {string} word The word to be used for reporting + * @returns {void} + */ + function verifyWordDoesntHaveSpaces(node, firstToken, secondToken, word) { + if (isArgumentObjectExpression(node)) { + if (secondToken.range[0] > firstToken.range[1]) { + context.report({ + node: node, + message: "Unexpected space after unary word operator '" + word + "'.", + fix: function(fixer) { + return fixer.removeRange([firstToken.range[1], secondToken.range[0]]); + } + }); + } + } + } + + /** + * Check Unary Word Operators for spaces after the word operator + * @param {ASTnode} node AST node + * @param {object} firstToken first token from the AST node + * @param {object} secondToken second token from the AST node + * @param {string} word The word to be used for reporting + * @returns {void} + */ + function checkUnaryWordOperatorForSpaces(node, firstToken, secondToken, word) { + word = word || firstToken.value; - if (overrideExistsForOperator(node, word)) { - if (overrideEnforcesSpaces(node, word)) { + if (overrideExistsForOperator(node, word)) { + if (overrideEnforcesSpaces(node, word)) { + verifyWordHasSpaces(node, firstToken, secondToken, word); + } else { + verifyWordDoesntHaveSpaces(node, firstToken, secondToken, word); + } + } else if (options.words) { verifyWordHasSpaces(node, firstToken, secondToken, word); } else { verifyWordDoesntHaveSpaces(node, firstToken, secondToken, word); } - } else if (options.words) { - verifyWordHasSpaces(node, firstToken, secondToken, word); - } else { - verifyWordDoesntHaveSpaces(node, firstToken, secondToken, word); } - } - /** - * Verifies YieldExpressions satisfy spacing requirements - * @param {ASTnode} node AST node - * @returns {void} - */ - function checkForSpacesAfterYield(node) { - var tokens = context.getFirstTokens(node, 3), - word = "yield"; + /** + * Verifies YieldExpressions satisfy spacing requirements + * @param {ASTnode} node AST node + * @returns {void} + */ + function checkForSpacesAfterYield(node) { + var tokens = context.getFirstTokens(node, 3), + word = "yield"; - if (!node.argument || node.delegate) { - return; - } - - checkUnaryWordOperatorForSpaces(node, tokens[0], tokens[1], word); - } - - /** - * Verifies UnaryExpression, UpdateExpression and NewExpression have spaces before or after the operator - * @param {ASTnode} node AST node - * @param {object} firstToken First token in the expression - * @param {object} secondToken Second token in the expression - * @returns {void} - */ - function verifyNonWordsHaveSpaces(node, firstToken, secondToken) { - if (node.prefix) { - if (isFirstBangInBangBangExpression(node)) { + if (!node.argument || node.delegate) { return; } - if (firstToken.range[1] === secondToken.range[0]) { - context.report({ - node: node, - message: "Unary operator '" + firstToken.value + "' must be followed by whitespace.", - fix: function(fixer) { - return fixer.insertTextAfter(firstToken, " "); - } - }); - } - } else { - if (firstToken.range[1] === secondToken.range[0]) { - context.report({ - node: node, - message: "Space is required before unary expressions '" + secondToken.value + "'.", - fix: function(fixer) { - return fixer.insertTextBefore(secondToken, " "); - } - }); - } + + checkUnaryWordOperatorForSpaces(node, tokens[0], tokens[1], word); } - } - /** - * Verifies UnaryExpression, UpdateExpression and NewExpression don't have spaces before or after the operator - * @param {ASTnode} node AST node - * @param {object} firstToken First token in the expression - * @param {object} secondToken Second token in the expression - * @returns {void} - */ - function verifyNonWordsDontHaveSpaces(node, firstToken, secondToken) { - if (node.prefix) { - if (secondToken.range[0] > firstToken.range[1]) { - context.report({ - node: node, - message: "Unexpected space after unary operator '" + firstToken.value + "'.", - fix: function(fixer) { - return fixer.removeRange([firstToken.range[1], secondToken.range[0]]); - } - }); + /** + * Verifies UnaryExpression, UpdateExpression and NewExpression have spaces before or after the operator + * @param {ASTnode} node AST node + * @param {object} firstToken First token in the expression + * @param {object} secondToken Second token in the expression + * @returns {void} + */ + function verifyNonWordsHaveSpaces(node, firstToken, secondToken) { + if (node.prefix) { + if (isFirstBangInBangBangExpression(node)) { + return; + } + if (firstToken.range[1] === secondToken.range[0]) { + context.report({ + node: node, + message: "Unary operator '" + firstToken.value + "' must be followed by whitespace.", + fix: function(fixer) { + return fixer.insertTextAfter(firstToken, " "); + } + }); + } + } else { + if (firstToken.range[1] === secondToken.range[0]) { + context.report({ + node: node, + message: "Space is required before unary expressions '" + secondToken.value + "'.", + fix: function(fixer) { + return fixer.insertTextBefore(secondToken, " "); + } + }); + } } - } else { - if (secondToken.range[0] > firstToken.range[1]) { - context.report({ - node: node, - message: "Unexpected space before unary operator '" + secondToken.value + "'.", - fix: function(fixer) { - return fixer.removeRange([firstToken.range[1], secondToken.range[0]]); - } - }); + } + + /** + * Verifies UnaryExpression, UpdateExpression and NewExpression don't have spaces before or after the operator + * @param {ASTnode} node AST node + * @param {object} firstToken First token in the expression + * @param {object} secondToken Second token in the expression + * @returns {void} + */ + function verifyNonWordsDontHaveSpaces(node, firstToken, secondToken) { + if (node.prefix) { + if (secondToken.range[0] > firstToken.range[1]) { + context.report({ + node: node, + message: "Unexpected space after unary operator '" + firstToken.value + "'.", + fix: function(fixer) { + return fixer.removeRange([firstToken.range[1], secondToken.range[0]]); + } + }); + } + } else { + if (secondToken.range[0] > firstToken.range[1]) { + context.report({ + node: node, + message: "Unexpected space before unary operator '" + secondToken.value + "'.", + fix: function(fixer) { + return fixer.removeRange([firstToken.range[1], secondToken.range[0]]); + } + }); + } } } - } - /** - * Verifies UnaryExpression, UpdateExpression and NewExpression satisfy spacing requirements - * @param {ASTnode} node AST node - * @returns {void} - */ - function checkForSpaces(node) { - var tokens = context.getFirstTokens(node, 2), - firstToken = tokens[0], - secondToken = tokens[1]; + /** + * Verifies UnaryExpression, UpdateExpression and NewExpression satisfy spacing requirements + * @param {ASTnode} node AST node + * @returns {void} + */ + function checkForSpaces(node) { + var tokens = context.getFirstTokens(node, 2), + firstToken = tokens[0], + secondToken = tokens[1]; - if ((node.type === "NewExpression" || node.prefix) && firstToken.type === "Keyword") { - checkUnaryWordOperatorForSpaces(node, firstToken, secondToken); - return; - } + if ((node.type === "NewExpression" || node.prefix) && firstToken.type === "Keyword") { + checkUnaryWordOperatorForSpaces(node, firstToken, secondToken); + return; + } - var operator = node.prefix ? tokens[0].value : tokens[1].value; + var operator = node.prefix ? tokens[0].value : tokens[1].value; - if (overrideExistsForOperator(node, operator)) { - if (overrideEnforcesSpaces(node, operator)) { + if (overrideExistsForOperator(node, operator)) { + if (overrideEnforcesSpaces(node, operator)) { + verifyNonWordsHaveSpaces(node, firstToken, secondToken); + } else { + verifyNonWordsDontHaveSpaces(node, firstToken, secondToken); + } + } else if (options.nonwords) { verifyNonWordsHaveSpaces(node, firstToken, secondToken); } else { verifyNonWordsDontHaveSpaces(node, firstToken, secondToken); } - } else if (options.nonwords) { - verifyNonWordsHaveSpaces(node, firstToken, secondToken); - } else { - verifyNonWordsDontHaveSpaces(node, firstToken, secondToken); } - } - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- - return { - "UnaryExpression": checkForSpaces, - "UpdateExpression": checkForSpaces, - "NewExpression": checkForSpaces, - "YieldExpression": checkForSpacesAfterYield - }; - -}; + return { + UnaryExpression: checkForSpaces, + UpdateExpression: checkForSpaces, + NewExpression: checkForSpaces, + YieldExpression: checkForSpacesAfterYield + }; -module.exports.schema = [ - { - "type": "object", - "properties": { - "words": { - "type": "boolean" - }, - "nonwords": { - "type": "boolean" - }, - "overrides": { - "type": "object", - "additionalProperties": { - "type": "boolean" - } - } - }, - "additionalProperties": false } -]; +}; diff --git a/tools/eslint/lib/rules/spaced-comment.js b/tools/eslint/lib/rules/spaced-comment.js index 73f0861c8f39c9..149862024c2b3c 100644 --- a/tools/eslint/lib/rules/spaced-comment.js +++ b/tools/eslint/lib/rules/spaced-comment.js @@ -1,9 +1,6 @@ /** * @fileoverview Source code for spaced-comments rule * @author Gyandeep Singh - * @copyright 2015 Toru Nagashima. All rights reserved. - * @copyright 2015 Gyandeep Singh. All rights reserved. - * @copyright 2014 Greg Cochard. All rights reserved. */ "use strict"; @@ -140,166 +137,178 @@ function createNeverStylePattern(markers) { // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "enforce consistent spacing after the `//` or `/*` in a comment", + category: "Stylistic Issues", + recommended: false + }, - // Unless the first option is never, require a space - var requireSpace = context.options[0] !== "never"; + fixable: "whitespace", - /* - * Parse the second options. - * If markers don't include `"*"`, it's added automatically for JSDoc - * comments. - */ - var config = context.options[1] || {}; - var styleRules = ["block", "line"].reduce(function(rule, type) { - var markers = parseMarkersOption(config[type] && config[type].markers || config.markers); - var exceptions = config[type] && config[type].exceptions || config.exceptions || []; - - // Create RegExp object for valid patterns. - rule[type] = { - regex: requireSpace ? createAlwaysStylePattern(markers, exceptions) : createNeverStylePattern(markers), - hasExceptions: exceptions.length > 0, - markers: new RegExp("^(" + markers.map(escape).join("|") + ")") - }; - - return rule; - }, {}); + schema: [ + { + enum: ["always", "never"] + }, + { + type: "object", + properties: { + exceptions: { + type: "array", + items: { + type: "string" + } + }, + markers: { + type: "array", + items: { + type: "string" + } + }, + line: { + type: "object", + properties: { + exceptions: { + type: "array", + items: { + type: "string" + } + }, + markers: { + type: "array", + items: { + type: "string" + } + } + }, + additionalProperties: false + }, + block: { + type: "object", + properties: { + exceptions: { + type: "array", + items: { + type: "string" + } + }, + markers: { + type: "array", + items: { + type: "string" + } + } + }, + additionalProperties: false + } + }, + additionalProperties: false + } + ] + }, - /** - * Reports a spacing error with an appropriate message. - * @param {ASTNode} node - A comment node to check. - * @param {string} message - An error message to report - * @param {Array} match - An array of match results for markers. - * @returns {void} - */ - function report(node, message, match) { - var type = node.type.toLowerCase(), - commentIdentifier = type === "block" ? "/*" : "//"; - - context.report({ - node: node, - fix: function(fixer) { - var start = node.range[0], - end = start + 2; - - if (requireSpace) { - if (match) { + create: function(context) { + + // Unless the first option is never, require a space + var requireSpace = context.options[0] !== "never"; + + /* + * Parse the second options. + * If markers don't include `"*"`, it's added automatically for JSDoc + * comments. + */ + var config = context.options[1] || {}; + var styleRules = ["block", "line"].reduce(function(rule, type) { + var markers = parseMarkersOption(config[type] && config[type].markers || config.markers); + var exceptions = config[type] && config[type].exceptions || config.exceptions || []; + + // Create RegExp object for valid patterns. + rule[type] = { + regex: requireSpace ? createAlwaysStylePattern(markers, exceptions) : createNeverStylePattern(markers), + hasExceptions: exceptions.length > 0, + markers: new RegExp("^(" + markers.map(escape).join("|") + ")") + }; + + return rule; + }, {}); + + /** + * Reports a spacing error with an appropriate message. + * @param {ASTNode} node - A comment node to check. + * @param {string} message - An error message to report + * @param {Array} match - An array of match results for markers. + * @returns {void} + */ + function report(node, message, match) { + var type = node.type.toLowerCase(), + commentIdentifier = type === "block" ? "/*" : "//"; + + context.report({ + node: node, + fix: function(fixer) { + var start = node.range[0], + end = start + 2; + + if (requireSpace) { + if (match) { + end += match[0].length; + } + return fixer.insertTextAfterRange([start, end], " "); + } else { end += match[0].length; + return fixer.replaceTextRange([start, end], commentIdentifier + (match[1] ? match[1] : "")); } - return fixer.insertTextAfterRange([start, end], " "); - } else { - end += match[0].length; - return fixer.replaceTextRange([start, end], commentIdentifier + (match[1] ? match[1] : "")); - } - }, - message: message - }); - } - - /** - * Reports a given comment if it's invalid. - * @param {ASTNode} node - a comment node to check. - * @returns {void} - */ - function checkCommentForSpace(node) { - var type = node.type.toLowerCase(), - rule = styleRules[type], - commentIdentifier = type === "block" ? "/*" : "//"; - - // Ignores empty comments. - if (node.value.length === 0) { - return; + }, + message: message + }); } - // Checks. - if (requireSpace) { - if (!rule.regex.test(node.value)) { - var hasMarker = rule.markers.exec(node.value); - var marker = hasMarker ? commentIdentifier + hasMarker[0] : commentIdentifier; - - if (rule.hasExceptions) { - report(node, "Expected exception block, space or tab after '" + marker + "' in comment.", hasMarker); - } else { - report(node, "Expected space or tab after '" + marker + "' in comment.", hasMarker); - } + /** + * Reports a given comment if it's invalid. + * @param {ASTNode} node - a comment node to check. + * @returns {void} + */ + function checkCommentForSpace(node) { + var type = node.type.toLowerCase(), + rule = styleRules[type], + commentIdentifier = type === "block" ? "/*" : "//"; + + // Ignores empty comments. + if (node.value.length === 0) { + return; } - } else { - var matched = rule.regex.exec(node.value); - if (matched) { - if (!matched[1]) { - report(node, "Unexpected space or tab after '" + commentIdentifier + "' in comment.", matched); - } else { - report(node, "Unexpected space or tab after marker (" + matched[1] + ") in comment.", matched); + // Checks. + if (requireSpace) { + if (!rule.regex.test(node.value)) { + var hasMarker = rule.markers.exec(node.value); + var marker = hasMarker ? commentIdentifier + hasMarker[0] : commentIdentifier; + + if (rule.hasExceptions) { + report(node, "Expected exception block, space or tab after '" + marker + "' in comment.", hasMarker); + } else { + report(node, "Expected space or tab after '" + marker + "' in comment.", hasMarker); + } + } + } else { + var matched = rule.regex.exec(node.value); + + if (matched) { + if (!matched[1]) { + report(node, "Unexpected space or tab after '" + commentIdentifier + "' in comment.", matched); + } else { + report(node, "Unexpected space or tab after marker (" + matched[1] + ") in comment.", matched); + } } } } - } - return { + return { - "LineComment": checkCommentForSpace, - "BlockComment": checkCommentForSpace + LineComment: checkCommentForSpace, + BlockComment: checkCommentForSpace - }; -}; - -module.exports.schema = [ - { - "enum": ["always", "never"] - }, - { - "type": "object", - "properties": { - "exceptions": { - "type": "array", - "items": { - "type": "string" - } - }, - "markers": { - "type": "array", - "items": { - "type": "string" - } - }, - "line": { - "type": "object", - "properties": { - "exceptions": { - "type": "array", - "items": { - "type": "string" - } - }, - "markers": { - "type": "array", - "items": { - "type": "string" - } - } - }, - "additionalProperties": false - }, - "block": { - "type": "object", - "properties": { - "exceptions": { - "type": "array", - "items": { - "type": "string" - } - }, - "markers": { - "type": "array", - "items": { - "type": "string" - } - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false + }; } -]; +}; diff --git a/tools/eslint/lib/rules/strict.js b/tools/eslint/lib/rules/strict.js index 81f1cfbf8caffd..4097a327931781 100644 --- a/tools/eslint/lib/rules/strict.js +++ b/tools/eslint/lib/rules/strict.js @@ -1,9 +1,6 @@ /** * @fileoverview Rule to control usage of strict mode directives. * @author Brandon Mills - * @copyright 2015 Brandon Mills. All rights reserved. - * @copyright 2013-2014 Nicholas C. Zakas. All rights reserved. - * @copyright 2013 Ian Christian Myers. All rights reserved. */ "use strict"; @@ -60,155 +57,165 @@ function getUseStrictDirectives(statements) { // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "require or disallow strict mode directives", + category: "Strict Mode", + recommended: false + }, - var mode = context.options[0] || "safe", - ecmaFeatures = context.parserOptions.ecmaFeatures || {}, - scopes = [], - classScopes = [], - rule; + schema: [ + { + enum: ["never", "global", "function", "safe"] + } + ] + }, - if (ecmaFeatures.impliedStrict) { - mode = "implied"; - } else if (mode === "safe") { - mode = ecmaFeatures.globalReturn ? "global" : "function"; - } + create: function(context) { - /** - * Report a slice of an array of nodes with a given message. - * @param {ASTNode[]} nodes Nodes. - * @param {string} start Index to start from. - * @param {string} end Index to end before. - * @param {string} message Message to display. - * @returns {void} - */ - function reportSlice(nodes, start, end, message) { - var i; - - for (i = start; i < end; i++) { - context.report(nodes[i], message); - } - } + var mode = context.options[0] || "safe", + ecmaFeatures = context.parserOptions.ecmaFeatures || {}, + scopes = [], + classScopes = [], + rule; - /** - * Report all nodes in an array with a given message. - * @param {ASTNode[]} nodes Nodes. - * @param {string} message Message to display. - * @returns {void} - */ - function reportAll(nodes, message) { - reportSlice(nodes, 0, nodes.length, message); - } - - /** - * Report all nodes in an array, except the first, with a given message. - * @param {ASTNode[]} nodes Nodes. - * @param {string} message Message to display. - * @returns {void} - */ - function reportAllExceptFirst(nodes, message) { - reportSlice(nodes, 1, nodes.length, message); - } + if (ecmaFeatures.impliedStrict) { + mode = "implied"; + } else if (mode === "safe") { + mode = ecmaFeatures.globalReturn ? "global" : "function"; + } - /** - * Entering a function in 'function' mode pushes a new nested scope onto the - * stack. The new scope is true if the nested function is strict mode code. - * @param {ASTNode} node The function declaration or expression. - * @param {ASTNode[]} useStrictDirectives The Use Strict Directives of the node. - * @returns {void} - */ - function enterFunctionInFunctionMode(node, useStrictDirectives) { - var isInClass = classScopes.length > 0, - isParentGlobal = scopes.length === 0 && classScopes.length === 0, - isParentStrict = scopes.length > 0 && scopes[scopes.length - 1], - isStrict = useStrictDirectives.length > 0; - - if (isStrict) { - if (isParentStrict) { - context.report(useStrictDirectives[0], messages.unnecessary); - } else if (isInClass) { - context.report(useStrictDirectives[0], messages.unnecessaryInClasses); + /** + * Report a slice of an array of nodes with a given message. + * @param {ASTNode[]} nodes Nodes. + * @param {string} start Index to start from. + * @param {string} end Index to end before. + * @param {string} message Message to display. + * @returns {void} + */ + function reportSlice(nodes, start, end, message) { + var i; + + for (i = start; i < end; i++) { + context.report(nodes[i], message); } + } - reportAllExceptFirst(useStrictDirectives, messages.multiple); - } else if (isParentGlobal) { - context.report(node, messages.function); + /** + * Report all nodes in an array with a given message. + * @param {ASTNode[]} nodes Nodes. + * @param {string} message Message to display. + * @returns {void} + */ + function reportAll(nodes, message) { + reportSlice(nodes, 0, nodes.length, message); } - scopes.push(isParentStrict || isStrict); - } + /** + * Report all nodes in an array, except the first, with a given message. + * @param {ASTNode[]} nodes Nodes. + * @param {string} message Message to display. + * @returns {void} + */ + function reportAllExceptFirst(nodes, message) { + reportSlice(nodes, 1, nodes.length, message); + } - /** - * Exiting a function in 'function' mode pops its scope off the stack. - * @returns {void} - */ - function exitFunctionInFunctionMode() { - scopes.pop(); - } + /** + * Entering a function in 'function' mode pushes a new nested scope onto the + * stack. The new scope is true if the nested function is strict mode code. + * @param {ASTNode} node The function declaration or expression. + * @param {ASTNode[]} useStrictDirectives The Use Strict Directives of the node. + * @returns {void} + */ + function enterFunctionInFunctionMode(node, useStrictDirectives) { + var isInClass = classScopes.length > 0, + isParentGlobal = scopes.length === 0 && classScopes.length === 0, + isParentStrict = scopes.length > 0 && scopes[scopes.length - 1], + isStrict = useStrictDirectives.length > 0; + + if (isStrict) { + if (isParentStrict) { + context.report(useStrictDirectives[0], messages.unnecessary); + } else if (isInClass) { + context.report(useStrictDirectives[0], messages.unnecessaryInClasses); + } - /** - * Enter a function and either: - * - Push a new nested scope onto the stack (in 'function' mode). - * - Report all the Use Strict Directives (in the other modes). - * @param {ASTNode} node The function declaration or expression. - * @returns {void} - */ - function enterFunction(node) { - var isBlock = node.body.type === "BlockStatement", - useStrictDirectives = isBlock ? - getUseStrictDirectives(node.body.body) : []; + reportAllExceptFirst(useStrictDirectives, messages.multiple); + } else if (isParentGlobal) { + context.report(node, messages.function); + } - if (mode === "function") { - enterFunctionInFunctionMode(node, useStrictDirectives); - } else { - reportAll(useStrictDirectives, messages[mode]); + scopes.push(isParentStrict || isStrict); } - } - - rule = { - "Program": function(node) { - var useStrictDirectives = getUseStrictDirectives(node.body); - if (node.sourceType === "module") { - mode = "module"; - } + /** + * Exiting a function in 'function' mode pops its scope off the stack. + * @returns {void} + */ + function exitFunctionInFunctionMode() { + scopes.pop(); + } - if (mode === "global") { - if (node.body.length > 0 && useStrictDirectives.length === 0) { - context.report(node, messages.global); - } - reportAllExceptFirst(useStrictDirectives, messages.multiple); + /** + * Enter a function and either: + * - Push a new nested scope onto the stack (in 'function' mode). + * - Report all the Use Strict Directives (in the other modes). + * @param {ASTNode} node The function declaration or expression. + * @returns {void} + */ + function enterFunction(node) { + var isBlock = node.body.type === "BlockStatement", + useStrictDirectives = isBlock ? + getUseStrictDirectives(node.body.body) : []; + + if (mode === "function") { + enterFunctionInFunctionMode(node, useStrictDirectives); } else { reportAll(useStrictDirectives, messages[mode]); } - }, - "FunctionDeclaration": enterFunction, - "FunctionExpression": enterFunction, - "ArrowFunctionExpression": enterFunction - }; + } - if (mode === "function") { - lodash.assign(rule, { + rule = { + Program: function(node) { + var useStrictDirectives = getUseStrictDirectives(node.body); - // Inside of class bodies are always strict mode. - "ClassBody": function() { - classScopes.push(true); - }, - "ClassBody:exit": function() { - classScopes.pop(); - }, + if (node.sourceType === "module") { + mode = "module"; + } - "FunctionDeclaration:exit": exitFunctionInFunctionMode, - "FunctionExpression:exit": exitFunctionInFunctionMode, - "ArrowFunctionExpression:exit": exitFunctionInFunctionMode - }); - } + if (mode === "global") { + if (node.body.length > 0 && useStrictDirectives.length === 0) { + context.report(node, messages.global); + } + reportAllExceptFirst(useStrictDirectives, messages.multiple); + } else { + reportAll(useStrictDirectives, messages[mode]); + } + }, + FunctionDeclaration: enterFunction, + FunctionExpression: enterFunction, + ArrowFunctionExpression: enterFunction + }; - return rule; -}; + if (mode === "function") { + lodash.assign(rule, { + + // Inside of class bodies are always strict mode. + ClassBody: function() { + classScopes.push(true); + }, + "ClassBody:exit": function() { + classScopes.pop(); + }, + + "FunctionDeclaration:exit": exitFunctionInFunctionMode, + "FunctionExpression:exit": exitFunctionInFunctionMode, + "ArrowFunctionExpression:exit": exitFunctionInFunctionMode + }); + } -module.exports.schema = [ - { - "enum": ["never", "global", "function", "safe"] + return rule; } -]; +}; diff --git a/tools/eslint/lib/rules/template-curly-spacing.js b/tools/eslint/lib/rules/template-curly-spacing.js index 4f5f9e1a4187c0..144a03536907a0 100644 --- a/tools/eslint/lib/rules/template-curly-spacing.js +++ b/tools/eslint/lib/rules/template-curly-spacing.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to enforce spacing around embedded expressions of template strings * @author Toru Nagashima - * @copyright 2016 Toru Nagashima. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; @@ -24,82 +22,94 @@ var CLOSE_PAREN = /^\}/; // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var sourceCode = context.getSourceCode(); - var always = context.options[0] === "always"; - var prefix = always ? "Expected" : "Unexpected"; - - /** - * Checks spacing before `}` of a given token. - * @param {Token} token - A token to check. This is a Template token. - * @returns {void} - */ - function checkSpacingBefore(token) { - var prevToken = sourceCode.getTokenBefore(token); - - if (prevToken && - CLOSE_PAREN.test(token.value) && - astUtils.isTokenOnSameLine(prevToken, token) && - sourceCode.isSpaceBetweenTokens(prevToken, token) !== always - ) { - context.report({ - loc: token.loc.start, - message: prefix + " space(s) before '}'.", - fix: function(fixer) { - if (always) { - return fixer.insertTextBefore(token, " "); +module.exports = { + meta: { + docs: { + description: "require or disallow spacing around embedded expressions of template strings", + category: "ECMAScript 6", + recommended: false + }, + + fixable: "whitespace", + + schema: [ + {enum: ["always", "never"]} + ] + }, + + create: function(context) { + var sourceCode = context.getSourceCode(); + var always = context.options[0] === "always"; + var prefix = always ? "Expected" : "Unexpected"; + + /** + * Checks spacing before `}` of a given token. + * @param {Token} token - A token to check. This is a Template token. + * @returns {void} + */ + function checkSpacingBefore(token) { + var prevToken = sourceCode.getTokenBefore(token); + + if (prevToken && + CLOSE_PAREN.test(token.value) && + astUtils.isTokenOnSameLine(prevToken, token) && + sourceCode.isSpaceBetweenTokens(prevToken, token) !== always + ) { + context.report({ + loc: token.loc.start, + message: prefix + " space(s) before '}'.", + fix: function(fixer) { + if (always) { + return fixer.insertTextBefore(token, " "); + } + return fixer.removeRange([ + prevToken.range[1], + token.range[0] + ]); } - return fixer.removeRange([ - prevToken.range[1], - token.range[0] - ]); - } - }); + }); + } } - } - /** - * Checks spacing after `${` of a given token. - * @param {Token} token - A token to check. This is a Template token. - * @returns {void} - */ - function checkSpacingAfter(token) { - var nextToken = sourceCode.getTokenAfter(token); - - if (nextToken && - OPEN_PAREN.test(token.value) && - astUtils.isTokenOnSameLine(token, nextToken) && - sourceCode.isSpaceBetweenTokens(token, nextToken) !== always - ) { - context.report({ - loc: { - line: token.loc.end.line, - column: token.loc.end.column - 2 - }, - message: prefix + " space(s) after '${'.", - fix: function(fixer) { - if (always) { - return fixer.insertTextAfter(token, " "); + /** + * Checks spacing after `${` of a given token. + * @param {Token} token - A token to check. This is a Template token. + * @returns {void} + */ + function checkSpacingAfter(token) { + var nextToken = sourceCode.getTokenAfter(token); + + if (nextToken && + OPEN_PAREN.test(token.value) && + astUtils.isTokenOnSameLine(token, nextToken) && + sourceCode.isSpaceBetweenTokens(token, nextToken) !== always + ) { + context.report({ + loc: { + line: token.loc.end.line, + column: token.loc.end.column - 2 + }, + message: prefix + " space(s) after '${'.", + fix: function(fixer) { + if (always) { + return fixer.insertTextAfter(token, " "); + } + return fixer.removeRange([ + token.range[1], + nextToken.range[0] + ]); } - return fixer.removeRange([ - token.range[1], - nextToken.range[0] - ]); - } - }); + }); + } } - } - return { - TemplateElement: function(node) { - var token = sourceCode.getFirstToken(node); + return { + TemplateElement: function(node) { + var token = sourceCode.getFirstToken(node); - checkSpacingBefore(token); - checkSpacingAfter(token); - } - }; + checkSpacingBefore(token); + checkSpacingAfter(token); + } + }; + } }; - -module.exports.schema = [ - {enum: ["always", "never"]} -]; diff --git a/tools/eslint/lib/rules/use-isnan.js b/tools/eslint/lib/rules/use-isnan.js index 7d65f9c0d85921..10f7b71c8bd42b 100644 --- a/tools/eslint/lib/rules/use-isnan.js +++ b/tools/eslint/lib/rules/use-isnan.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to flag comparisons to the value NaN * @author James Allardice - * @copyright 2014 Jordan Harband. All rights reserved. - * @copyright 2013 James Allardice. All rights reserved. */ "use strict"; @@ -11,16 +9,26 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "require calls to `isNaN()` when checking for `NaN`", + category: "Possible Errors", + recommended: true + }, - return { - "BinaryExpression": function(node) { - if (/^(?:[<>]|[!=]=)=?$/.test(node.operator) && (node.left.name === "NaN" || node.right.name === "NaN")) { - context.report(node, "Use the isNaN function to compare with NaN."); + schema: [] + }, + + create: function(context) { + + return { + BinaryExpression: function(node) { + if (/^(?:[<>]|[!=]=)=?$/.test(node.operator) && (node.left.name === "NaN" || node.right.name === "NaN")) { + context.report(node, "Use the isNaN function to compare with NaN."); + } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/valid-jsdoc.js b/tools/eslint/lib/rules/valid-jsdoc.js index 299095064dc4c2..e7d6fdeadf8813 100644 --- a/tools/eslint/lib/rules/valid-jsdoc.js +++ b/tools/eslint/lib/rules/valid-jsdoc.js @@ -1,7 +1,6 @@ /** * @fileoverview Validates JSDoc comments are syntactically correct * @author Nicholas C. Zakas - * @copyright 2014 Nicholas C. Zakas. All rights reserved. */ "use strict"; @@ -15,367 +14,383 @@ var doctrine = require("doctrine"); // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - var options = context.options[0] || {}, - prefer = options.prefer || {}, - sourceCode = context.getSourceCode(), - - // these both default to true, so you have to explicitly make them false - requireReturn = options.requireReturn !== false, - requireParamDescription = options.requireParamDescription !== false, - requireReturnDescription = options.requireReturnDescription !== false, - requireReturnType = options.requireReturnType !== false, - preferType = options.preferType || {}, - checkPreferType = Object.keys(preferType).length !== 0; - - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- - - // Using a stack to store if a function returns or not (handling nested functions) - var fns = []; - - /** - * Check if node type is a Class - * @param {ASTNode} node node to check. - * @returns {boolean} True is its a class - * @private - */ - function isTypeClass(node) { - return node.type === "ClassExpression" || node.type === "ClassDeclaration"; - } - - /** - * When parsing a new function, store it in our function stack. - * @param {ASTNode} node A function node to check. - * @returns {void} - * @private - */ - function startFunction(node) { - fns.push({ - returnPresent: (node.type === "ArrowFunctionExpression" && node.body.type !== "BlockStatement") || - isTypeClass(node) - }); - } +module.exports = { + meta: { + docs: { + description: "enforce valid JSDoc comments", + category: "Possible Errors", + recommended: false + }, - /** - * Indicate that return has been found in the current function. - * @param {ASTNode} node The return node. - * @returns {void} - * @private - */ - function addReturn(node) { - var functionState = fns[fns.length - 1]; - - if (functionState && node.argument !== null) { - functionState.returnPresent = true; + schema: [ + { + type: "object", + properties: { + prefer: { + type: "object", + additionalProperties: { + type: "string" + } + }, + preferType: { + type: "object", + additionalProperties: { + type: "string" + } + }, + requireReturn: { + type: "boolean" + }, + requireParamDescription: { + type: "boolean" + }, + requireReturnDescription: { + type: "boolean" + }, + matchDescription: { + type: "string" + }, + requireReturnType: { + type: "boolean" + } + }, + additionalProperties: false + } + ] + }, + + create: function(context) { + + var options = context.options[0] || {}, + prefer = options.prefer || {}, + sourceCode = context.getSourceCode(), + + // these both default to true, so you have to explicitly make them false + requireReturn = options.requireReturn !== false, + requireParamDescription = options.requireParamDescription !== false, + requireReturnDescription = options.requireReturnDescription !== false, + requireReturnType = options.requireReturnType !== false, + preferType = options.preferType || {}, + checkPreferType = Object.keys(preferType).length !== 0; + + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- + + // Using a stack to store if a function returns or not (handling nested functions) + var fns = []; + + /** + * Check if node type is a Class + * @param {ASTNode} node node to check. + * @returns {boolean} True is its a class + * @private + */ + function isTypeClass(node) { + return node.type === "ClassExpression" || node.type === "ClassDeclaration"; } - } - /** - * Check if return tag type is void or undefined - * @param {Object} tag JSDoc tag - * @returns {boolean} True if its of type void or undefined - * @private - */ - function isValidReturnType(tag) { - return tag.type === null || tag.type.name === "void" || tag.type.type === "UndefinedLiteral"; - } - - /** - * Check if type should be validated based on some exceptions - * @param {Object} type JSDoc tag - * @returns {boolean} True if it can be validated - * @private - */ - function canTypeBeValidated(type) { - return type !== "UndefinedLiteral" && // {undefined} as there is no name property available. - type !== "NullLiteral" && // {null} - type !== "NullableLiteral" && // {?} - type !== "FunctionType" && // {function(a)} - type !== "AllLiteral"; // {*} - } - - /** - * Extract the current and expected type based on the input type object - * @param {Object} type JSDoc tag - * @returns {Object} current and expected type object - * @private - */ - function getCurrentExpectedTypes(type) { - var currentType; - var expectedType; - - if (type.name) { - currentType = type.name; - } else if (type.expression) { - currentType = type.expression.name; + /** + * When parsing a new function, store it in our function stack. + * @param {ASTNode} node A function node to check. + * @returns {void} + * @private + */ + function startFunction(node) { + fns.push({ + returnPresent: (node.type === "ArrowFunctionExpression" && node.body.type !== "BlockStatement") || + isTypeClass(node) + }); } - expectedType = currentType && preferType[currentType]; - - return { - currentType: currentType, - expectedType: expectedType - }; - } + /** + * Indicate that return has been found in the current function. + * @param {ASTNode} node The return node. + * @returns {void} + * @private + */ + function addReturn(node) { + var functionState = fns[fns.length - 1]; + + if (functionState && node.argument !== null) { + functionState.returnPresent = true; + } + } - /** - * Check if return tag type is void or undefined - * @param {Object} jsdocNode JSDoc node - * @param {Object} type JSDoc tag - * @returns {void} - * @private - */ - function validateType(jsdocNode, type) { - if (!type || !canTypeBeValidated(type.type)) { - return; + /** + * Check if return tag type is void or undefined + * @param {Object} tag JSDoc tag + * @returns {boolean} True if its of type void or undefined + * @private + */ + function isValidReturnType(tag) { + return tag.type === null || tag.type.name === "void" || tag.type.type === "UndefinedLiteral"; } - var typesToCheck = []; - var elements = []; - - switch (type.type) { - case "TypeApplication": // {Array.} - elements = type.applications[0].type === "UnionType" ? type.applications[0].elements : type.applications; - typesToCheck.push(getCurrentExpectedTypes(type)); - break; - case "RecordType": // {{20:String}} - elements = type.fields; - break; - case "UnionType": // {String|number|Test} - case "ArrayType": // {[String, number, Test]} - elements = type.elements; - break; - case "FieldType": // Array.<{count: number, votes: number}> - typesToCheck.push(getCurrentExpectedTypes(type.value)); - break; - default: - typesToCheck.push(getCurrentExpectedTypes(type)); + /** + * Check if type should be validated based on some exceptions + * @param {Object} type JSDoc tag + * @returns {boolean} True if it can be validated + * @private + */ + function canTypeBeValidated(type) { + return type !== "UndefinedLiteral" && // {undefined} as there is no name property available. + type !== "NullLiteral" && // {null} + type !== "NullableLiteral" && // {?} + type !== "FunctionType" && // {function(a)} + type !== "AllLiteral"; // {*} } - elements.forEach(validateType.bind(null, jsdocNode)); - - typesToCheck.forEach(function(typeToCheck) { - if (typeToCheck.expectedType && - typeToCheck.expectedType !== typeToCheck.currentType) { - context.report({ - node: jsdocNode, - message: "Use '{{expectedType}}' instead of '{{currentType}}'.", - data: { - currentType: typeToCheck.currentType, - expectedType: typeToCheck.expectedType - } - }); + /** + * Extract the current and expected type based on the input type object + * @param {Object} type JSDoc tag + * @returns {Object} current and expected type object + * @private + */ + function getCurrentExpectedTypes(type) { + var currentType; + var expectedType; + + if (type.name) { + currentType = type.name; + } else if (type.expression) { + currentType = type.expression.name; } - }); - } - /** - * Validate the JSDoc node and output warnings if anything is wrong. - * @param {ASTNode} node The AST node to check. - * @returns {void} - * @private - */ - function checkJSDoc(node) { - var jsdocNode = sourceCode.getJSDocComment(node), - functionData = fns.pop(), - hasReturns = false, - hasConstructor = false, - isInterface = false, - isOverride = false, - params = Object.create(null), - jsdoc; - - // make sure only to validate JSDoc comments - if (jsdocNode) { - - try { - jsdoc = doctrine.parse(jsdocNode.value, { - strict: true, - unwrap: true, - sloppy: true - }); - } catch (ex) { + expectedType = currentType && preferType[currentType]; - if (/braces/i.test(ex.message)) { - context.report(jsdocNode, "JSDoc type missing brace."); - } else { - context.report(jsdocNode, "JSDoc syntax error."); - } + return { + currentType: currentType, + expectedType: expectedType + }; + } + /** + * Check if return tag type is void or undefined + * @param {Object} jsdocNode JSDoc node + * @param {Object} type JSDoc tag + * @returns {void} + * @private + */ + function validateType(jsdocNode, type) { + if (!type || !canTypeBeValidated(type.type)) { return; } - jsdoc.tags.forEach(function(tag) { - - switch (tag.title.toLowerCase()) { + var typesToCheck = []; + var elements = []; + + switch (type.type) { + case "TypeApplication": // {Array.} + elements = type.applications[0].type === "UnionType" ? type.applications[0].elements : type.applications; + typesToCheck.push(getCurrentExpectedTypes(type)); + break; + case "RecordType": // {{20:String}} + elements = type.fields; + break; + case "UnionType": // {String|number|Test} + case "ArrayType": // {[String, number, Test]} + elements = type.elements; + break; + case "FieldType": // Array.<{count: number, votes: number}> + typesToCheck.push(getCurrentExpectedTypes(type.value)); + break; + default: + typesToCheck.push(getCurrentExpectedTypes(type)); + } - case "param": - case "arg": - case "argument": - if (!tag.type) { - context.report(jsdocNode, "Missing JSDoc parameter type for '{{name}}'.", { name: tag.name }); + elements.forEach(validateType.bind(null, jsdocNode)); + + typesToCheck.forEach(function(typeToCheck) { + if (typeToCheck.expectedType && + typeToCheck.expectedType !== typeToCheck.currentType) { + context.report({ + node: jsdocNode, + message: "Use '{{expectedType}}' instead of '{{currentType}}'.", + data: { + currentType: typeToCheck.currentType, + expectedType: typeToCheck.expectedType } + }); + } + }); + } - if (!tag.description && requireParamDescription) { - context.report(jsdocNode, "Missing JSDoc parameter description for '{{name}}'.", { name: tag.name }); - } + /** + * Validate the JSDoc node and output warnings if anything is wrong. + * @param {ASTNode} node The AST node to check. + * @returns {void} + * @private + */ + function checkJSDoc(node) { + var jsdocNode = sourceCode.getJSDocComment(node), + functionData = fns.pop(), + hasReturns = false, + hasConstructor = false, + isInterface = false, + isOverride = false, + isAbstract = false, + params = Object.create(null), + jsdoc; + + // make sure only to validate JSDoc comments + if (jsdocNode) { + + try { + jsdoc = doctrine.parse(jsdocNode.value, { + strict: true, + unwrap: true, + sloppy: true + }); + } catch (ex) { + + if (/braces/i.test(ex.message)) { + context.report(jsdocNode, "JSDoc type missing brace."); + } else { + context.report(jsdocNode, "JSDoc syntax error."); + } - if (params[tag.name]) { - context.report(jsdocNode, "Duplicate JSDoc parameter '{{name}}'.", { name: tag.name }); - } else if (tag.name.indexOf(".") === -1) { - params[tag.name] = 1; - } - break; + return; + } - case "return": - case "returns": - hasReturns = true; + jsdoc.tags.forEach(function(tag) { - if (!requireReturn && !functionData.returnPresent && (tag.type === null || !isValidReturnType(tag))) { - context.report(jsdocNode, "Unexpected @" + tag.title + " tag; function has no return statement."); - } else { - if (requireReturnType && !tag.type) { - context.report(jsdocNode, "Missing JSDoc return type."); + switch (tag.title.toLowerCase()) { + + case "param": + case "arg": + case "argument": + if (!tag.type) { + context.report(jsdocNode, "Missing JSDoc parameter type for '{{name}}'.", { name: tag.name }); } - if (!isValidReturnType(tag) && !tag.description && requireReturnDescription) { - context.report(jsdocNode, "Missing JSDoc return description."); + if (!tag.description && requireParamDescription) { + context.report(jsdocNode, "Missing JSDoc parameter description for '{{name}}'.", { name: tag.name }); } - } - break; + if (params[tag.name]) { + context.report(jsdocNode, "Duplicate JSDoc parameter '{{name}}'.", { name: tag.name }); + } else if (tag.name.indexOf(".") === -1) { + params[tag.name] = 1; + } + break; + + case "return": + case "returns": + hasReturns = true; + + if (!requireReturn && !functionData.returnPresent && (tag.type === null || !isValidReturnType(tag)) && !isAbstract) { + context.report(jsdocNode, "Unexpected @" + tag.title + " tag; function has no return statement."); + } else { + if (requireReturnType && !tag.type) { + context.report(jsdocNode, "Missing JSDoc return type."); + } + + if (!isValidReturnType(tag) && !tag.description && requireReturnDescription) { + context.report(jsdocNode, "Missing JSDoc return description."); + } + } - case "constructor": - case "class": - hasConstructor = true; - break; + break; - case "override": - case "inheritdoc": - isOverride = true; - break; + case "constructor": + case "class": + hasConstructor = true; + break; - case "interface": - isInterface = true; - break; + case "override": + case "inheritdoc": + isOverride = true; + break; - // no default - } + case "abstract": + case "virtual": + isAbstract = true; + break; - // check tag preferences - if (prefer.hasOwnProperty(tag.title) && tag.title !== prefer[tag.title]) { - context.report(jsdocNode, "Use @{{name}} instead.", { name: prefer[tag.title] }); - } + case "interface": + isInterface = true; + break; - // validate the types - if (checkPreferType && tag.type) { - validateType(jsdocNode, tag.type); - } - }); + // no default + } - // check for functions missing @returns - if (!isOverride && !hasReturns && !hasConstructor && !isInterface && - node.parent.kind !== "get" && node.parent.kind !== "constructor" && - node.parent.kind !== "set" && !isTypeClass(node)) { - if (requireReturn || functionData.returnPresent) { - context.report(jsdocNode, "Missing JSDoc @" + (prefer.returns || "returns") + " for function."); + // check tag preferences + if (prefer.hasOwnProperty(tag.title) && tag.title !== prefer[tag.title]) { + context.report(jsdocNode, "Use @{{name}} instead.", { name: prefer[tag.title] }); + } + + // validate the types + if (checkPreferType && tag.type) { + validateType(jsdocNode, tag.type); + } + }); + + // check for functions missing @returns + if (!isOverride && !hasReturns && !hasConstructor && !isInterface && + node.parent.kind !== "get" && node.parent.kind !== "constructor" && + node.parent.kind !== "set" && !isTypeClass(node)) { + if (requireReturn || functionData.returnPresent) { + context.report(jsdocNode, "Missing JSDoc @" + (prefer.returns || "returns") + " for function."); + } } - } - // check the parameters - var jsdocParams = Object.keys(params); + // check the parameters + var jsdocParams = Object.keys(params); - if (node.params) { - node.params.forEach(function(param, i) { - var name = param.name; + if (node.params) { + node.params.forEach(function(param, i) { + var name = param.name; - if (param.type === "AssignmentPattern") { - name = param.left.name; - } + if (param.type === "AssignmentPattern") { + name = param.left.name; + } - // TODO(nzakas): Figure out logical things to do with destructured, default, rest params - if (param.type === "Identifier" || param.type === "AssignmentPattern") { - if (jsdocParams[i] && (name !== jsdocParams[i])) { - context.report(jsdocNode, "Expected JSDoc for '{{name}}' but found '{{jsdocName}}'.", { - name: name, - jsdocName: jsdocParams[i] - }); - } else if (!params[name] && !isOverride) { - context.report(jsdocNode, "Missing JSDoc for parameter '{{name}}'.", { - name: name - }); + // TODO(nzakas): Figure out logical things to do with destructured, default, rest params + if (param.type === "Identifier" || param.type === "AssignmentPattern") { + if (jsdocParams[i] && (name !== jsdocParams[i])) { + context.report(jsdocNode, "Expected JSDoc for '{{name}}' but found '{{jsdocName}}'.", { + name: name, + jsdocName: jsdocParams[i] + }); + } else if (!params[name] && !isOverride) { + context.report(jsdocNode, "Missing JSDoc for parameter '{{name}}'.", { + name: name + }); + } } - } - }); - } + }); + } - if (options.matchDescription) { - var regex = new RegExp(options.matchDescription); + if (options.matchDescription) { + var regex = new RegExp(options.matchDescription); - if (!regex.test(jsdoc.description)) { - context.report(jsdocNode, "JSDoc description does not satisfy the regex pattern."); + if (!regex.test(jsdoc.description)) { + context.report(jsdocNode, "JSDoc description does not satisfy the regex pattern."); + } } + } } - } - - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- - - return { - "ArrowFunctionExpression": startFunction, - "FunctionExpression": startFunction, - "FunctionDeclaration": startFunction, - "ClassExpression": startFunction, - "ClassDeclaration": startFunction, - "ArrowFunctionExpression:exit": checkJSDoc, - "FunctionExpression:exit": checkJSDoc, - "FunctionDeclaration:exit": checkJSDoc, - "ClassExpression:exit": checkJSDoc, - "ClassDeclaration:exit": checkJSDoc, - "ReturnStatement": addReturn - }; + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- -}; + return { + ArrowFunctionExpression: startFunction, + FunctionExpression: startFunction, + FunctionDeclaration: startFunction, + ClassExpression: startFunction, + ClassDeclaration: startFunction, + "ArrowFunctionExpression:exit": checkJSDoc, + "FunctionExpression:exit": checkJSDoc, + "FunctionDeclaration:exit": checkJSDoc, + "ClassExpression:exit": checkJSDoc, + "ClassDeclaration:exit": checkJSDoc, + ReturnStatement: addReturn + }; -module.exports.schema = [ - { - "type": "object", - "properties": { - "prefer": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "preferType": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "requireReturn": { - "type": "boolean" - }, - "requireParamDescription": { - "type": "boolean" - }, - "requireReturnDescription": { - "type": "boolean" - }, - "matchDescription": { - "type": "string" - }, - "requireReturnType": { - "type": "boolean" - } - }, - "additionalProperties": false } -]; +}; diff --git a/tools/eslint/lib/rules/valid-typeof.js b/tools/eslint/lib/rules/valid-typeof.js index d67a46bf3dd7ce..289375a88bac3b 100644 --- a/tools/eslint/lib/rules/valid-typeof.js +++ b/tools/eslint/lib/rules/valid-typeof.js @@ -8,35 +8,45 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "enforce comparing `typeof` expressions against valid strings", + category: "Possible Errors", + recommended: true + }, - var VALID_TYPES = ["symbol", "undefined", "object", "boolean", "number", "string", "function"], - OPERATORS = ["==", "===", "!=", "!=="]; + schema: [] + }, - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- + create: function(context) { - return { + var VALID_TYPES = ["symbol", "undefined", "object", "boolean", "number", "string", "function"], + OPERATORS = ["==", "===", "!=", "!=="]; - "UnaryExpression": function(node) { - var parent, sibling; + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- - if (node.operator === "typeof") { - parent = context.getAncestors().pop(); + return { - if (parent.type === "BinaryExpression" && OPERATORS.indexOf(parent.operator) !== -1) { - sibling = parent.left === node ? parent.right : parent.left; + UnaryExpression: function(node) { + var parent, sibling; - if (sibling.type === "Literal" && VALID_TYPES.indexOf(sibling.value) === -1) { - context.report(sibling, "Invalid typeof comparison value"); + if (node.operator === "typeof") { + parent = context.getAncestors().pop(); + + if (parent.type === "BinaryExpression" && OPERATORS.indexOf(parent.operator) !== -1) { + sibling = parent.left === node ? parent.right : parent.left; + + if (sibling.type === "Literal" && VALID_TYPES.indexOf(sibling.value) === -1) { + context.report(sibling, "Invalid typeof comparison value"); + } } } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/vars-on-top.js b/tools/eslint/lib/rules/vars-on-top.js index ae009f85ad4c27..b44f77eb3fa695 100644 --- a/tools/eslint/lib/rules/vars-on-top.js +++ b/tools/eslint/lib/rules/vars-on-top.js @@ -2,8 +2,6 @@ * @fileoverview Rule to enforce var declarations are only at the top of a function. * @author Danny Fritz * @author Gyandeep Singh - * @copyright 2014 Danny Fritz. All rights reserved. - * @copyright 2014 Gyandeep Singh. All rights reserved. */ "use strict"; @@ -11,116 +9,126 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var errorMessage = "All 'var' declarations must be at the top of the function scope."; - - //-------------------------------------------------------------------------- - // Helpers - //-------------------------------------------------------------------------- - - /** - * @param {ASTNode} node - any node - * @returns {Boolean} whether the given node structurally represents a directive - */ - function looksLikeDirective(node) { - return node.type === "ExpressionStatement" && - node.expression.type === "Literal" && typeof node.expression.value === "string"; - } - - /** - * Check to see if its a ES6 import declaration - * @param {ASTNode} node - any node - * @returns {Boolean} whether the given node represents a import declaration - */ - function looksLikeImport(node) { - return node.type === "ImportDeclaration" || node.type === "ImportSpecifier" || - node.type === "ImportDefaultSpecifier" || node.type === "ImportNamespaceSpecifier"; - } +module.exports = { + meta: { + docs: { + description: "require `var` declarations be placed at the top of their containing scope", + category: "Best Practices", + recommended: false + }, + + schema: [] + }, + + create: function(context) { + var errorMessage = "All 'var' declarations must be at the top of the function scope."; + + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- + + /** + * @param {ASTNode} node - any node + * @returns {Boolean} whether the given node structurally represents a directive + */ + function looksLikeDirective(node) { + return node.type === "ExpressionStatement" && + node.expression.type === "Literal" && typeof node.expression.value === "string"; + } - /** - * Checks whether this variable is on top of the block body - * @param {ASTNode} node - The node to check - * @param {ASTNode[]} statements - collection of ASTNodes for the parent node block - * @returns {Boolean} True if var is on top otherwise false - */ - function isVarOnTop(node, statements) { - var i = 0, - l = statements.length; - - // skip over directives - for (; i < l; ++i) { - if (!looksLikeDirective(statements[i]) && !looksLikeImport(statements[i])) { - break; - } + /** + * Check to see if its a ES6 import declaration + * @param {ASTNode} node - any node + * @returns {Boolean} whether the given node represents a import declaration + */ + function looksLikeImport(node) { + return node.type === "ImportDeclaration" || node.type === "ImportSpecifier" || + node.type === "ImportDefaultSpecifier" || node.type === "ImportNamespaceSpecifier"; } - for (; i < l; ++i) { - if (statements[i].type !== "VariableDeclaration" && - (statements[i].type !== "ExportNamedDeclaration" || - statements[i].declaration.type !== "VariableDeclaration")) { - return false; - } - if (statements[i] === node) { - return true; + /** + * Checks whether this variable is on top of the block body + * @param {ASTNode} node - The node to check + * @param {ASTNode[]} statements - collection of ASTNodes for the parent node block + * @returns {Boolean} True if var is on top otherwise false + */ + function isVarOnTop(node, statements) { + var i = 0, + l = statements.length; + + // skip over directives + for (; i < l; ++i) { + if (!looksLikeDirective(statements[i]) && !looksLikeImport(statements[i])) { + break; + } } - } - return false; - } + for (; i < l; ++i) { + if (statements[i].type !== "VariableDeclaration" && + (statements[i].type !== "ExportNamedDeclaration" || + statements[i].declaration.type !== "VariableDeclaration")) { + return false; + } + if (statements[i] === node) { + return true; + } + } - /** - * Checks whether variable is on top at the global level - * @param {ASTNode} node - The node to check - * @param {ASTNode} parent - Parent of the node - * @returns {void} - */ - function globalVarCheck(node, parent) { - if (!isVarOnTop(node, parent.body)) { - context.report(node, errorMessage); + return false; } - } - /** - * Checks whether variable is on top at functional block scope level - * @param {ASTNode} node - The node to check - * @param {ASTNode} parent - Parent of the node - * @param {ASTNode} grandParent - Parent of the node's parent - * @returns {void} - */ - function blockScopeVarCheck(node, parent, grandParent) { - if (!(/Function/.test(grandParent.type) && - parent.type === "BlockStatement" && - isVarOnTop(node, parent.body))) { - context.report(node, errorMessage); + /** + * Checks whether variable is on top at the global level + * @param {ASTNode} node - The node to check + * @param {ASTNode} parent - Parent of the node + * @returns {void} + */ + function globalVarCheck(node, parent) { + if (!isVarOnTop(node, parent.body)) { + context.report(node, errorMessage); + } } - } - //-------------------------------------------------------------------------- - // Public API - //-------------------------------------------------------------------------- - - return { - "VariableDeclaration": function(node) { - var ancestors = context.getAncestors(); - var parent = ancestors.pop(); - var grandParent = ancestors.pop(); - - if (node.kind === "var") { // check variable is `var` type and not `let` or `const` - if (parent.type === "ExportNamedDeclaration") { - node = parent; - parent = grandParent; - grandParent = ancestors.pop(); - } + /** + * Checks whether variable is on top at functional block scope level + * @param {ASTNode} node - The node to check + * @param {ASTNode} parent - Parent of the node + * @param {ASTNode} grandParent - Parent of the node's parent + * @returns {void} + */ + function blockScopeVarCheck(node, parent, grandParent) { + if (!(/Function/.test(grandParent.type) && + parent.type === "BlockStatement" && + isVarOnTop(node, parent.body))) { + context.report(node, errorMessage); + } + } - if (parent.type === "Program") { // That means its a global variable - globalVarCheck(node, parent); - } else { - blockScopeVarCheck(node, parent, grandParent); + //-------------------------------------------------------------------------- + // Public API + //-------------------------------------------------------------------------- + + return { + VariableDeclaration: function(node) { + var ancestors = context.getAncestors(); + var parent = ancestors.pop(); + var grandParent = ancestors.pop(); + + if (node.kind === "var") { // check variable is `var` type and not `let` or `const` + if (parent.type === "ExportNamedDeclaration") { + node = parent; + parent = grandParent; + grandParent = ancestors.pop(); + } + + if (parent.type === "Program") { // That means its a global variable + globalVarCheck(node, parent); + } else { + blockScopeVarCheck(node, parent, grandParent); + } } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/wrap-iife.js b/tools/eslint/lib/rules/wrap-iife.js index ac5c8a45f02a01..1dd1a0c5af84d1 100644 --- a/tools/eslint/lib/rules/wrap-iife.js +++ b/tools/eslint/lib/rules/wrap-iife.js @@ -1,7 +1,6 @@ /** * @fileoverview Rule to flag when IIFE is not wrapped in parens * @author Ilya Volodin - * @copyright 2013 Ilya Volodin. All rights reserved. */ "use strict"; @@ -10,46 +9,56 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { +module.exports = { + meta: { + docs: { + description: "require parentheses around immediate `function` invocations", + category: "Best Practices", + recommended: false + }, - var style = context.options[0] || "outside"; + schema: [ + { + enum: ["outside", "inside", "any"] + } + ] + }, - /** - * Check if the node is wrapped in () - * @param {ASTNode} node node to evaluate - * @returns {boolean} True if it is wrapped - * @private - */ - function wrapped(node) { - var previousToken = context.getTokenBefore(node), - nextToken = context.getTokenAfter(node); + create: function(context) { - return previousToken && previousToken.value === "(" && - nextToken && nextToken.value === ")"; - } + var style = context.options[0] || "outside"; + + /** + * Check if the node is wrapped in () + * @param {ASTNode} node node to evaluate + * @returns {boolean} True if it is wrapped + * @private + */ + function wrapped(node) { + var previousToken = context.getTokenBefore(node), + nextToken = context.getTokenAfter(node); + + return previousToken && previousToken.value === "(" && + nextToken && nextToken.value === ")"; + } - return { + return { - "CallExpression": function(node) { - if (node.callee.type === "FunctionExpression") { - var callExpressionWrapped = wrapped(node), - functionExpressionWrapped = wrapped(node.callee); + CallExpression: function(node) { + if (node.callee.type === "FunctionExpression") { + var callExpressionWrapped = wrapped(node), + functionExpressionWrapped = wrapped(node.callee); - if (!callExpressionWrapped && !functionExpressionWrapped) { - context.report(node, "Wrap an immediate function invocation in parentheses."); - } else if (style === "inside" && !functionExpressionWrapped) { - context.report(node, "Wrap only the function expression in parens."); - } else if (style === "outside" && !callExpressionWrapped) { - context.report(node, "Move the invocation into the parens that contain the function."); + if (!callExpressionWrapped && !functionExpressionWrapped) { + context.report(node, "Wrap an immediate function invocation in parentheses."); + } else if (style === "inside" && !functionExpressionWrapped) { + context.report(node, "Wrap only the function expression in parens."); + } else if (style === "outside" && !callExpressionWrapped) { + context.report(node, "Move the invocation into the parens that contain the function."); + } } } - } - }; - -}; + }; -module.exports.schema = [ - { - "enum": ["outside", "inside", "any"] } -]; +}; diff --git a/tools/eslint/lib/rules/wrap-regex.js b/tools/eslint/lib/rules/wrap-regex.js index f2625cc2b98187..96df3304c8b627 100644 --- a/tools/eslint/lib/rules/wrap-regex.js +++ b/tools/eslint/lib/rules/wrap-regex.js @@ -9,30 +9,40 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - return { - - "Literal": function(node) { - var token = context.getFirstToken(node), - nodeType = token.type, - source, - grandparent, - ancestors; - - if (nodeType === "RegularExpression") { - source = context.getTokenBefore(node); - ancestors = context.getAncestors(); - grandparent = ancestors[ancestors.length - 1]; - - if (grandparent.type === "MemberExpression" && grandparent.object === node && - (!source || source.value !== "(")) { - context.report(node, "Wrap the regexp literal in parens to disambiguate the slash."); +module.exports = { + meta: { + docs: { + description: "require parenthesis around regex literals", + category: "Stylistic Issues", + recommended: false + }, + + schema: [] + }, + + create: function(context) { + + return { + + Literal: function(node) { + var token = context.getFirstToken(node), + nodeType = token.type, + source, + grandparent, + ancestors; + + if (nodeType === "RegularExpression") { + source = context.getTokenBefore(node); + ancestors = context.getAncestors(); + grandparent = ancestors[ancestors.length - 1]; + + if (grandparent.type === "MemberExpression" && grandparent.object === node && + (!source || source.value !== "(")) { + context.report(node, "Wrap the regexp literal in parens to disambiguate the slash."); + } } } - } - }; + }; + } }; - -module.exports.schema = []; diff --git a/tools/eslint/lib/rules/yield-star-spacing.js b/tools/eslint/lib/rules/yield-star-spacing.js index c69594ae15a7d2..e2911b7200524c 100644 --- a/tools/eslint/lib/rules/yield-star-spacing.js +++ b/tools/eslint/lib/rules/yield-star-spacing.js @@ -1,7 +1,6 @@ /** * @fileoverview Rule to check the spacing around the * in yield* expressions. * @author Bryan Smith - * @copyright 2015 Bryan Smith. All rights reserved. */ "use strict"; @@ -10,93 +9,105 @@ // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - var sourceCode = context.getSourceCode(); +module.exports = { + meta: { + docs: { + description: "require or disallow spacing around the `*` in `yield*` expressions", + category: "ECMAScript 6", + recommended: false + }, - var mode = (function(option) { - if (!option || typeof option === "string") { - return { - before: { before: true, after: false }, - after: { before: false, after: true }, - both: { before: true, after: true }, - neither: { before: false, after: false } - }[option || "after"]; - } - return option; - }(context.options[0])); + fixable: "whitespace", + + schema: [ + { + oneOf: [ + { + enum: ["before", "after", "both", "neither"] + }, + { + type: "object", + properties: { + before: {type: "boolean"}, + after: {type: "boolean"} + }, + additionalProperties: false + } + ] + } + ] + }, - /** - * Checks the spacing between two tokens before or after the star token. - * @param {string} side Either "before" or "after". - * @param {Token} leftToken `function` keyword token if side is "before", or - * star token if side is "after". - * @param {Token} rightToken Star token if side is "before", or identifier - * token if side is "after". - * @returns {void} - */ - function checkSpacing(side, leftToken, rightToken) { - if (sourceCode.isSpaceBetweenTokens(leftToken, rightToken) !== mode[side]) { - var after = leftToken.value === "*"; - var spaceRequired = mode[side]; - var node = after ? leftToken : rightToken; - var type = spaceRequired ? "Missing" : "Unexpected"; - var message = type + " space " + side + " *."; + create: function(context) { + var sourceCode = context.getSourceCode(); - context.report({ - node: node, - message: message, - fix: function(fixer) { - if (spaceRequired) { - if (after) { - return fixer.insertTextAfter(node, " "); + var mode = (function(option) { + if (!option || typeof option === "string") { + return { + before: { before: true, after: false }, + after: { before: false, after: true }, + both: { before: true, after: true }, + neither: { before: false, after: false } + }[option || "after"]; + } + return option; + }(context.options[0])); + + /** + * Checks the spacing between two tokens before or after the star token. + * @param {string} side Either "before" or "after". + * @param {Token} leftToken `function` keyword token if side is "before", or + * star token if side is "after". + * @param {Token} rightToken Star token if side is "before", or identifier + * token if side is "after". + * @returns {void} + */ + function checkSpacing(side, leftToken, rightToken) { + if (sourceCode.isSpaceBetweenTokens(leftToken, rightToken) !== mode[side]) { + var after = leftToken.value === "*"; + var spaceRequired = mode[side]; + var node = after ? leftToken : rightToken; + var type = spaceRequired ? "Missing" : "Unexpected"; + var message = type + " space " + side + " *."; + + context.report({ + node: node, + message: message, + fix: function(fixer) { + if (spaceRequired) { + if (after) { + return fixer.insertTextAfter(node, " "); + } + return fixer.insertTextBefore(node, " "); } - return fixer.insertTextBefore(node, " "); + return fixer.removeRange([leftToken.range[1], rightToken.range[0]]); } - return fixer.removeRange([leftToken.range[1], rightToken.range[0]]); - } - }); - } - } - - /** - * Enforces the spacing around the star if node is a yield* expression. - * @param {ASTNode} node A yield expression node. - * @returns {void} - */ - function checkExpression(node) { - if (!node.delegate) { - return; + }); + } } - var tokens = sourceCode.getFirstTokens(node, 3); - var yieldToken = tokens[0]; - var starToken = tokens[1]; - var nextToken = tokens[2]; + /** + * Enforces the spacing around the star if node is a yield* expression. + * @param {ASTNode} node A yield expression node. + * @returns {void} + */ + function checkExpression(node) { + if (!node.delegate) { + return; + } - checkSpacing("before", yieldToken, starToken); - checkSpacing("after", starToken, nextToken); - } + var tokens = sourceCode.getFirstTokens(node, 3); + var yieldToken = tokens[0]; + var starToken = tokens[1]; + var nextToken = tokens[2]; - return { - "YieldExpression": checkExpression - }; + checkSpacing("before", yieldToken, starToken); + checkSpacing("after", starToken, nextToken); + } -}; + return { + YieldExpression: checkExpression + }; -module.exports.schema = [ - { - "oneOf": [ - { - "enum": ["before", "after", "both", "neither"] - }, - { - "type": "object", - "properties": { - "before": {"type": "boolean"}, - "after": {"type": "boolean"} - }, - "additionalProperties": false - } - ] } -]; +}; diff --git a/tools/eslint/lib/rules/yoda.js b/tools/eslint/lib/rules/yoda.js index a5ff4a962632c4..ce2709ec9a4c39 100644 --- a/tools/eslint/lib/rules/yoda.js +++ b/tools/eslint/lib/rules/yoda.js @@ -1,8 +1,6 @@ /** * @fileoverview Rule to require or disallow yoda comparisons * @author Nicholas C. Zakas - * @copyright 2014 Nicholas C. Zakas. All rights reserved. - * @copyright 2014 Brandon Mills. All rights reserved. */ "use strict"; @@ -119,129 +117,139 @@ function same(a, b) { // Rule Definition //------------------------------------------------------------------------------ -module.exports = function(context) { - - // Default to "never" (!always) if no option - var always = (context.options[0] === "always"); - var exceptRange = (context.options[1] && context.options[1].exceptRange); - var onlyEquality = (context.options[1] && context.options[1].onlyEquality); - - /** - * Determines whether node represents a range test. - * A range test is a "between" test like `(0 <= x && x < 1)` or an "outside" - * test like `(x < 0 || 1 <= x)`. It must be wrapped in parentheses, and - * both operators must be `<` or `<=`. Finally, the literal on the left side - * must be less than or equal to the literal on the right side so that the - * test makes any sense. - * @param {ASTNode} node LogicalExpression node to test. - * @returns {Boolean} Whether node is a range test. - */ - function isRangeTest(node) { - var left = node.left, - right = node.right; +module.exports = { + meta: { + docs: { + description: "require or disallow \"Yoda\" conditions", + category: "Best Practices", + recommended: false + }, - /** - * Determines whether node is of the form `0 <= x && x < 1`. - * @returns {Boolean} Whether node is a "between" range test. - */ - function isBetweenTest() { - var leftLiteral, rightLiteral; - - return (node.operator === "&&" && - (leftLiteral = getNormalizedLiteral(left.left)) && - (rightLiteral = getNormalizedLiteral(right.right)) && - leftLiteral.value <= rightLiteral.value && - same(left.right, right.left)); - } + schema: [ + { + enum: ["always", "never"] + }, + { + type: "object", + properties: { + exceptRange: { + type: "boolean" + }, + onlyEquality: { + type: "boolean" + } + }, + additionalProperties: false + } + ] + }, - /** - * Determines whether node is of the form `x < 0 || 1 <= x`. - * @returns {Boolean} Whether node is an "outside" range test. - */ - function isOutsideTest() { - var leftLiteral, rightLiteral; - - return (node.operator === "||" && - (leftLiteral = getNormalizedLiteral(left.right)) && - (rightLiteral = getNormalizedLiteral(right.left)) && - leftLiteral.value <= rightLiteral.value && - same(left.left, right.right)); - } + create: function(context) { + + // Default to "never" (!always) if no option + var always = (context.options[0] === "always"); + var exceptRange = (context.options[1] && context.options[1].exceptRange); + var onlyEquality = (context.options[1] && context.options[1].onlyEquality); /** - * Determines whether node is wrapped in parentheses. - * @returns {Boolean} Whether node is preceded immediately by an open - * paren token and followed immediately by a close - * paren token. + * Determines whether node represents a range test. + * A range test is a "between" test like `(0 <= x && x < 1)` or an "outside" + * test like `(x < 0 || 1 <= x)`. It must be wrapped in parentheses, and + * both operators must be `<` or `<=`. Finally, the literal on the left side + * must be less than or equal to the literal on the right side so that the + * test makes any sense. + * @param {ASTNode} node LogicalExpression node to test. + * @returns {Boolean} Whether node is a range test. */ - function isParenWrapped() { - var tokenBefore, tokenAfter; - - return ((tokenBefore = context.getTokenBefore(node)) && - tokenBefore.value === "(" && - (tokenAfter = context.getTokenAfter(node)) && - tokenAfter.value === ")"); - } - - return (node.type === "LogicalExpression" && - left.type === "BinaryExpression" && - right.type === "BinaryExpression" && - isRangeTestOperator(left.operator) && - isRangeTestOperator(right.operator) && - (isBetweenTest() || isOutsideTest()) && - isParenWrapped()); - } + function isRangeTest(node) { + var left = node.left, + right = node.right; + + /** + * Determines whether node is of the form `0 <= x && x < 1`. + * @returns {Boolean} Whether node is a "between" range test. + */ + function isBetweenTest() { + var leftLiteral, rightLiteral; + + return (node.operator === "&&" && + (leftLiteral = getNormalizedLiteral(left.left)) && + (rightLiteral = getNormalizedLiteral(right.right)) && + leftLiteral.value <= rightLiteral.value && + same(left.right, right.left)); + } - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- - - return { - "BinaryExpression": always ? function(node) { - - // Comparisons must always be yoda-style: if ("blue" === color) - if ( - (node.right.type === "Literal" || looksLikeLiteral(node.right)) && - !(node.left.type === "Literal" || looksLikeLiteral(node.left)) && - !(!isEqualityOperator(node.operator) && onlyEquality) && - isComparisonOperator(node.operator) && - !(exceptRange && isRangeTest(context.getAncestors().pop())) - ) { - context.report(node, "Expected literal to be on the left side of " + node.operator + "."); + /** + * Determines whether node is of the form `x < 0 || 1 <= x`. + * @returns {Boolean} Whether node is an "outside" range test. + */ + function isOutsideTest() { + var leftLiteral, rightLiteral; + + return (node.operator === "||" && + (leftLiteral = getNormalizedLiteral(left.right)) && + (rightLiteral = getNormalizedLiteral(right.left)) && + leftLiteral.value <= rightLiteral.value && + same(left.left, right.right)); } - } : function(node) { - - // Comparisons must never be yoda-style (default) - if ( - (node.left.type === "Literal" || looksLikeLiteral(node.left)) && - !(node.right.type === "Literal" || looksLikeLiteral(node.right)) && - !(!isEqualityOperator(node.operator) && onlyEquality) && - isComparisonOperator(node.operator) && - !(exceptRange && isRangeTest(context.getAncestors().pop())) - ) { - context.report(node, "Expected literal to be on the right side of " + node.operator + "."); + /** + * Determines whether node is wrapped in parentheses. + * @returns {Boolean} Whether node is preceded immediately by an open + * paren token and followed immediately by a close + * paren token. + */ + function isParenWrapped() { + var tokenBefore, tokenAfter; + + return ((tokenBefore = context.getTokenBefore(node)) && + tokenBefore.value === "(" && + (tokenAfter = context.getTokenAfter(node)) && + tokenAfter.value === ")"); } + return (node.type === "LogicalExpression" && + left.type === "BinaryExpression" && + right.type === "BinaryExpression" && + isRangeTestOperator(left.operator) && + isRangeTestOperator(right.operator) && + (isBetweenTest() || isOutsideTest()) && + isParenWrapped()); } - }; -}; + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + return { + BinaryExpression: always ? function(node) { + + // Comparisons must always be yoda-style: if ("blue" === color) + if ( + (node.right.type === "Literal" || looksLikeLiteral(node.right)) && + !(node.left.type === "Literal" || looksLikeLiteral(node.left)) && + !(!isEqualityOperator(node.operator) && onlyEquality) && + isComparisonOperator(node.operator) && + !(exceptRange && isRangeTest(context.getAncestors().pop())) + ) { + context.report(node, "Expected literal to be on the left side of " + node.operator + "."); + } + + } : function(node) { + + // Comparisons must never be yoda-style (default) + if ( + (node.left.type === "Literal" || looksLikeLiteral(node.left)) && + !(node.right.type === "Literal" || looksLikeLiteral(node.right)) && + !(!isEqualityOperator(node.operator) && onlyEquality) && + isComparisonOperator(node.operator) && + !(exceptRange && isRangeTest(context.getAncestors().pop())) + ) { + context.report(node, "Expected literal to be on the right side of " + node.operator + "."); + } -module.exports.schema = [ - { - "enum": ["always", "never"] - }, - { - "type": "object", - "properties": { - "exceptRange": { - "type": "boolean" - }, - "onlyEquality": { - "type": "boolean" } - }, - "additionalProperties": false + }; + } -]; +}; diff --git a/tools/eslint/lib/testers/event-generator-tester.js b/tools/eslint/lib/testers/event-generator-tester.js index c275a74b7607e9..00b2d03307a883 100644 --- a/tools/eslint/lib/testers/event-generator-tester.js +++ b/tools/eslint/lib/testers/event-generator-tester.js @@ -1,8 +1,6 @@ /** * @fileoverview Helpers to test EventGenerator interface. * @author Toru Nagashima - * @copyright 2015 Toru Nagashima. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; diff --git a/tools/eslint/lib/testers/rule-tester.js b/tools/eslint/lib/testers/rule-tester.js index ce4ca1c4ba8a84..4485e0d5fcc7f8 100644 --- a/tools/eslint/lib/testers/rule-tester.js +++ b/tools/eslint/lib/testers/rule-tester.js @@ -1,10 +1,6 @@ /** * @fileoverview Mocha test wrapper * @author Ilya Volodin - * @copyright 2015 Kevin Partington. All rights reserved. - * @copyright 2015 Nicholas C. Zakas. All rights reserved. - * @copyright 2014 Ilya Volodin. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; diff --git a/tools/eslint/lib/timing.js b/tools/eslint/lib/timing.js index c1346480fd8a30..6dfffc19d979eb 100644 --- a/tools/eslint/lib/timing.js +++ b/tools/eslint/lib/timing.js @@ -1,7 +1,6 @@ /** * @fileoverview Tracks performance of individual rules. * @author Brandon Mills - * @copyright 2014 Brandon Mills. All rights reserved. */ "use strict"; @@ -102,7 +101,7 @@ function display(data) { return ALIGN[index](":", w + 1, "-"); }).join("|")); - console.log(table.join("\n")); + console.log(table.join("\n")); // eslint-disable-line no-console } /* istanbul ignore next */ diff --git a/tools/eslint/lib/token-store.js b/tools/eslint/lib/token-store.js index 91409b7eedde19..0262b69a521107 100644 --- a/tools/eslint/lib/token-store.js +++ b/tools/eslint/lib/token-store.js @@ -1,8 +1,6 @@ /** * @fileoverview Object to handle access and retrieval of tokens. * @author Brandon Mills - * @copyright 2014 Nicholas C. Zakas. All rights reserved. - * @copyright 2014 Brandon Mills. All rights reserved. */ "use strict"; diff --git a/tools/eslint/lib/util/comment-event-generator.js b/tools/eslint/lib/util/comment-event-generator.js index 90bbfe9f2f444e..2989f4ee26ae39 100644 --- a/tools/eslint/lib/util/comment-event-generator.js +++ b/tools/eslint/lib/util/comment-event-generator.js @@ -1,8 +1,6 @@ /** * @fileoverview The event generator for comments. * @author Toru Nagashima - * @copyright 2015 Toru Nagashima. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; diff --git a/tools/eslint/lib/util/glob-util.js b/tools/eslint/lib/util/glob-util.js index 9a704d6308b833..dadefbd9665eb4 100644 --- a/tools/eslint/lib/util/glob-util.js +++ b/tools/eslint/lib/util/glob-util.js @@ -1,8 +1,6 @@ /** * @fileoverview Utilities for working with globs and the filesystem. * @author Ian VanSchooten - * @copyright 2015 Ian VanSchooten. All rights reserved. - * See LICENSE in root directory for full license. */ "use strict"; diff --git a/tools/eslint/lib/util/hash.js b/tools/eslint/lib/util/hash.js index b0271bbf03dcbb..9f3b734c278e73 100644 --- a/tools/eslint/lib/util/hash.js +++ b/tools/eslint/lib/util/hash.js @@ -1,8 +1,6 @@ /** * @fileoverview Defining the hashing function in one place. * @author Michael Ficarra - * @copyright 2016 Michael Ficarra. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; diff --git a/tools/eslint/lib/util/keywords.js b/tools/eslint/lib/util/keywords.js index dde29c6b76c06a..3fbb77771df5c9 100644 --- a/tools/eslint/lib/util/keywords.js +++ b/tools/eslint/lib/util/keywords.js @@ -1,7 +1,6 @@ /** * @fileoverview A shared list of ES3 keywords. * @author Josh Perez - * @copyright 2015 Jose Roberto Vidal. All rights reserved. */ "use strict"; diff --git a/tools/eslint/lib/util/module-resolver.js b/tools/eslint/lib/util/module-resolver.js index 9df544cf2b6840..251292280dd3d8 100644 --- a/tools/eslint/lib/util/module-resolver.js +++ b/tools/eslint/lib/util/module-resolver.js @@ -1,8 +1,6 @@ /** * @fileoverview Implements the Node.js require.resolve algorithm * @author Nicholas C. Zakas - * @copyright 2016 Nicholas C. Zakas. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; @@ -24,8 +22,11 @@ var DEFAULT_OPTIONS = { * module.paths is an array of paths to search for resolving things relative * to this file. Module.globalPaths contains all of the special Node.js * directories that can also be searched for modules. + * + * Need to check for existence of module.paths because Jest seems not to + * include it. See https://github.com/eslint/eslint/issues/5791. */ - lookupPaths: module.paths.concat(Module.globalPaths) + lookupPaths: module.paths ? module.paths.concat(Module.globalPaths) : Module.globalPaths.concat() }; /** diff --git a/tools/eslint/lib/util/node-event-generator.js b/tools/eslint/lib/util/node-event-generator.js index 002bd29dfe3ed0..92253f6ca23b6e 100644 --- a/tools/eslint/lib/util/node-event-generator.js +++ b/tools/eslint/lib/util/node-event-generator.js @@ -1,8 +1,6 @@ /** * @fileoverview The event generator for AST nodes. * @author Toru Nagashima - * @copyright 2015 Toru Nagashima. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; diff --git a/tools/eslint/lib/util/npm-util.js b/tools/eslint/lib/util/npm-util.js index c45f0790115347..fd081307fd3cd5 100644 --- a/tools/eslint/lib/util/npm-util.js +++ b/tools/eslint/lib/util/npm-util.js @@ -1,8 +1,6 @@ /** * @fileoverview Utility for executing npm commands. * @author Ian VanSchooten - * @copyright 2016 Ilya Volodin. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; diff --git a/tools/eslint/lib/util/path-util.js b/tools/eslint/lib/util/path-util.js index d1c8197adfb1f2..ddc0b60625acaa 100644 --- a/tools/eslint/lib/util/path-util.js +++ b/tools/eslint/lib/util/path-util.js @@ -1,8 +1,6 @@ /** * @fileoverview Common helpers for operations on filenames and paths * @author Ian VanSchooten - * @copyright 2016 Ian VanSchooten. All rights reserved. - * See LICENSE in root directory for full license. */ "use strict"; diff --git a/tools/eslint/lib/util/rule-fixer.js b/tools/eslint/lib/util/rule-fixer.js index 0f9ef9adf3c73f..91f1033e4260af 100644 --- a/tools/eslint/lib/util/rule-fixer.js +++ b/tools/eslint/lib/util/rule-fixer.js @@ -1,8 +1,6 @@ /** * @fileoverview An object that creates fix commands for rules. * @author Nicholas C. Zakas - * @copyright 2015 Nicholas C. Zakas. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; diff --git a/tools/eslint/lib/util/source-code-fixer.js b/tools/eslint/lib/util/source-code-fixer.js index 0ea68d382b2e36..e8c440d7c21e39 100644 --- a/tools/eslint/lib/util/source-code-fixer.js +++ b/tools/eslint/lib/util/source-code-fixer.js @@ -1,8 +1,6 @@ /** * @fileoverview An object that caches and applies source code fixes. * @author Nicholas C. Zakas - * @copyright 2015 Nicholas C. Zakas. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; diff --git a/tools/eslint/lib/util/source-code-util.js b/tools/eslint/lib/util/source-code-util.js index b12b095f17d0cd..e51c1c124c798f 100644 --- a/tools/eslint/lib/util/source-code-util.js +++ b/tools/eslint/lib/util/source-code-util.js @@ -1,8 +1,6 @@ /** * @fileoverview Tools for obtaining SourceCode objects. * @author Ian VanSchooten - * @copyright 2016 Ian VanSchooten. All rights reserved. - * See LICENSE in root directory for full license. */ "use strict"; diff --git a/tools/eslint/lib/util/source-code.js b/tools/eslint/lib/util/source-code.js index a79bd5b531bcab..adf4df93a6b3ae 100644 --- a/tools/eslint/lib/util/source-code.js +++ b/tools/eslint/lib/util/source-code.js @@ -1,8 +1,6 @@ /** * @fileoverview Abstraction of JavaScript source code. * @author Nicholas C. Zakas - * @copyright 2015 Nicholas C. Zakas. All rights reserved. - * See LICENSE file in root directory for full license. */ "use strict"; diff --git a/tools/eslint/lib/util/traverser.js b/tools/eslint/lib/util/traverser.js index 74cfbec2b2371c..7a538355cf8a4d 100644 --- a/tools/eslint/lib/util/traverser.js +++ b/tools/eslint/lib/util/traverser.js @@ -1,8 +1,6 @@ /** * @fileoverview Wrapper around estraverse * @author Nicholas C. Zakas - * @copyright 2016 Nicholas C. Zakas. All rights reserved. - * See LICENSE in root directory for full license. */ "use strict"; diff --git a/tools/eslint/node_modules/.bin/eslint b/tools/eslint/node_modules/.bin/eslint new file mode 120000 index 00000000000000..810e4bcb32af34 --- /dev/null +++ b/tools/eslint/node_modules/.bin/eslint @@ -0,0 +1 @@ +../eslint/bin/eslint.js \ No newline at end of file diff --git a/tools/eslint/node_modules/acorn-jsx/README.md b/tools/eslint/node_modules/acorn-jsx/README.md index 6b3826d3fcbdb5..cd9674c0b38b03 100644 --- a/tools/eslint/node_modules/acorn-jsx/README.md +++ b/tools/eslint/node_modules/acorn-jsx/README.md @@ -37,6 +37,28 @@ var ast = acorn.parse(code, { }); ``` +Note that official spec doesn't support mix of XML namespaces and object-style access in tag names (#27) like in ``, so it was deprecated in `acorn-jsx@3.0`. If you still want to opt-in to support of such constructions, you can pass the following option: + +```javascript +var ast = acorn.parse(code, { + plugins: { + jsx: { allowNamespacedObjects: true } + } +}); +``` + +Also, since most apps use pure React transformer, a new option was introduced that allows to prohibit namespaces completely: + +```javascript +var ast = acorn.parse(code, { + plugins: { + jsx: { allowNamespaces: false } + } +}); +``` + +Note that by default `allowNamespaces` is enabled for spec compliancy. + ## License This plugin is issued under the [MIT license](./LICENSE). diff --git a/tools/eslint/node_modules/acorn-jsx/inject.js b/tools/eslint/node_modules/acorn-jsx/inject.js index bfe0358097d3d2..2bc4e9fd3986f3 100644 --- a/tools/eslint/node_modules/acorn-jsx/inject.js +++ b/tools/eslint/node_modules/acorn-jsx/inject.js @@ -198,7 +198,7 @@ module.exports = function(acorn) { pp.jsx_parseNamespacedName = function() { var startPos = this.start, startLoc = this.startLoc; var name = this.jsx_parseIdentifier(); - if (!this.eat(tt.colon)) return name; + if (!this.options.plugins.jsx.allowNamespaces || !this.eat(tt.colon)) return name; var node = this.startNodeAt(startPos, startLoc); node.namespace = name; node.name = this.jsx_parseIdentifier(); @@ -211,6 +211,9 @@ module.exports = function(acorn) { pp.jsx_parseElementName = function() { var startPos = this.start, startLoc = this.startLoc; var node = this.jsx_parseNamespacedName(); + if (this.type === tt.dot && node.type === 'JSXNamespacedName' && !this.options.plugins.jsx.allowNamespacedObjects) { + this.unexpected(); + } while (this.eat(tt.dot)) { var newNode = this.startNodeAt(startPos, startLoc); newNode.object = node; @@ -356,7 +359,20 @@ module.exports = function(acorn) { return this.jsx_parseElementAt(startPos, startLoc); }; - acorn.plugins.jsx = function(instance) { + acorn.plugins.jsx = function(instance, opts) { + if (!opts) { + return; + } + + if (typeof opts !== 'object') { + opts = {}; + } + + instance.options.plugins.jsx = { + allowNamespaces: opts.allowNamespaces !== false, + allowNamespacedObjects: !!opts.allowNamespacedObjects + }; + instance.extend('parseExprAtom', function(inner) { return function(refShortHandDefaultPos) { if (this.type === tt.jsxText) diff --git a/tools/eslint/node_modules/acorn-jsx/node_modules/.bin/acorn b/tools/eslint/node_modules/acorn-jsx/node_modules/.bin/acorn deleted file mode 120000 index cf76760386200f..00000000000000 --- a/tools/eslint/node_modules/acorn-jsx/node_modules/.bin/acorn +++ /dev/null @@ -1 +0,0 @@ -../acorn/bin/acorn \ No newline at end of file diff --git a/tools/eslint/node_modules/acorn-jsx/node_modules/acorn/.tern-project b/tools/eslint/node_modules/acorn-jsx/node_modules/acorn/.tern-project deleted file mode 100644 index 6718ce07e1c8a0..00000000000000 --- a/tools/eslint/node_modules/acorn-jsx/node_modules/acorn/.tern-project +++ /dev/null @@ -1,6 +0,0 @@ -{ - "plugins": { - "node": true, - "es_modules": true - } -} \ No newline at end of file diff --git a/tools/eslint/node_modules/acorn-jsx/node_modules/acorn/AUTHORS b/tools/eslint/node_modules/acorn-jsx/node_modules/acorn/AUTHORS deleted file mode 100644 index 0e8f48b695eaa7..00000000000000 --- a/tools/eslint/node_modules/acorn-jsx/node_modules/acorn/AUTHORS +++ /dev/null @@ -1,43 +0,0 @@ -List of Acorn contributors. Updated before every release. - -Adrian Rakovsky -Alistair Braidwood -Andres Suarez -Aparajita Fishman -Arian Stolwijk -Artem Govorov -Brandon Mills -Charles Hughes -Conrad Irwin -David Bonnet -ForbesLindesay -Forbes Lindesay -Gilad Peleg -impinball -Ingvar Stepanyan -Jesse McCarthy -Jiaxing Wang -Joel Kemp -Johannes Herr -Jürg Lehni -keeyipchan -Kevin Kwok -krator -Marijn Haverbeke -Martin Carlberg -Mathias Bynens -Mathieu 'p01' Henri -Max Schaefer -Max Zerzouri -Mihai Bazon -Mike Rennie -Nick Fitzgerald -Oskar Schöldström -Paul Harper -Peter Rust -PlNG -r-e-d -Rich Harris -Sebastian McKenzie -Timothy Gu -zsjforcn diff --git a/tools/eslint/node_modules/acorn-jsx/node_modules/acorn/LICENSE b/tools/eslint/node_modules/acorn-jsx/node_modules/acorn/LICENSE deleted file mode 100644 index d4c7fc583804df..00000000000000 --- a/tools/eslint/node_modules/acorn-jsx/node_modules/acorn/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (C) 2012-2014 by various contributors (see AUTHORS) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/tools/eslint/node_modules/acorn-jsx/node_modules/acorn/README.md b/tools/eslint/node_modules/acorn-jsx/node_modules/acorn/README.md deleted file mode 100644 index 12680abf6b3cc7..00000000000000 --- a/tools/eslint/node_modules/acorn-jsx/node_modules/acorn/README.md +++ /dev/null @@ -1,396 +0,0 @@ -# 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) -[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. - -## Community - -Acorn is open source software released under an -[MIT license](https://github.com/ternjs/acorn/blob/master/LICENSE). - -You are welcome to -[report bugs](https://github.com/ternjs/acorn/issues) or create pull -requests on [github](https://github.com/ternjs/acorn). For questions -and discussion, please use the -[Tern discussion forum](https://discuss.ternjs.net). - -## Installation - -The easiest way to install acorn is with [`npm`][npm]. - -[npm]: https://www.npmjs.com/ - -```sh -npm install acorn -``` - -Alternately, download the source. - -```sh -git clone https://github.com/ternjs/acorn.git -``` - -## Components - -When run in a CommonJS (node.js) or AMD environment, exported values -appear in the interfaces exposed by the individual files, as usual. -When loaded in the browser (Acorn works in any JS-enabled browser more -recent than IE5) without any kind of module management, a single -global object `acorn` will be defined, and all the exported properties -will be added to that. - -### Main parser - -This is implemented in `dist/acorn.js`, and is what you get when you -`require("acorn")` in node.js. - -**parse**`(input, options)` is used to parse a JavaScript program. -The `input` parameter is a string, `options` can be undefined or an -object setting some of the options listed below. The return value will -be an abstract syntax tree object as specified by the -[ESTree spec][estree]. - -When encountering a syntax error, the parser will raise a -`SyntaxError` object with a meaningful message. The error object will -have a `pos` property that indicates the character offset at which the -error occurred, and a `loc` object that contains a `{line, column}` -object referring to that same position. - -[estree]: https://github.com/estree/estree - -- **ecmaVersion**: Indicates the ECMAScript version to parse. Must be - either 3, 5, or 6. This influences support for strict mode, the set - of reserved words, and support for new syntax features. Default is 5. - -- **sourceType**: Indicate the mode the code should be parsed in. Can be - either `"script"` or `"module"`. - -- **onInsertedSemicolon**: If given a callback, that callback will be - called whenever a missing semicolon is inserted by the parser. The - callback will be given the character offset of the point where the - semicolon is inserted as argument, and if `locations` is on, also a - `{line, column}` object representing this position. - -- **onTrailingComma**: Like `onInsertedSemicolon`, but for trailing - commas. - -- **allowReserved**: If `false`, using a reserved word will generate - an error. Defaults to `true` for `ecmaVersion` 3, `false` for higher - versions. When given the value `"never"`, reserved words and - keywords can also not be used as property names (as in Internet - Explorer's old parser). - -- **allowReturnOutsideFunction**: By default, a return statement at - the top level raises an error. Set this to `true` to accept such - code. - -- **allowImportExportEverywhere**: By default, `import` and `export` - declarations can only appear at a program's top level. Setting this - option to `true` allows them anywhere where a statement is allowed. - -- **allowHashBang**: When this is enabled (off by default), if the - code starts with the characters `#!` (as in a shellscript), the - first line will be treated as a comment. - -- **locations**: When `true`, each node has a `loc` object attached - with `start` and `end` subobjects, each of which contains the - one-based line and zero-based column numbers in `{line, column}` - form. Default is `false`. - -- **onToken**: If a function is passed for this option, each found - token will be passed in same format as tokens returned from - `tokenizer().getToken()`. - - If array is passed, each found token is pushed to it. - - Note that you are not allowed to call the parser from the - callback—that will corrupt its internal state. - -- **onComment**: If a function is passed for this option, whenever a - comment is encountered the function will be called with the - following parameters: - - - `block`: `true` if the comment is a block comment, false if it - is a line comment. - - `text`: The content of the comment. - - `start`: Character offset of the start of the comment. - - `end`: Character offset of the end of the comment. - - When the `locations` options is on, the `{line, column}` locations - of the comment’s start and end are passed as two additional - parameters. - - If array is passed for this option, each found comment is pushed - to it as object in Esprima format: - - ```javascript - { - "type": "Line" | "Block", - "value": "comment text", - "start": Number, - "end": Number, - // If `locations` option is on: - "loc": { - "start": {line: Number, column: Number} - "end": {line: Number, column: Number} - }, - // If `ranges` option is on: - "range": [Number, Number] - } - ``` - - Note that you are not allowed to call the parser from the - callback—that will corrupt its internal state. - -- **ranges**: Nodes have their start and end characters offsets - recorded in `start` and `end` properties (directly on the node, - rather than the `loc` object, which holds line/column data. To also - add a [semi-standardized][range] `range` property holding a - `[start, end]` array with the same numbers, set the `ranges` option - to `true`. - -- **program**: It is possible to parse multiple files into a single - AST by passing the tree produced by parsing the first file as the - `program` option in subsequent parses. This will add the toplevel - forms of the parsed file to the "Program" (top) node of an existing - parse tree. - -- **sourceFile**: When the `locations` option is `true`, you can pass - this option to add a `source` attribute in every node’s `loc` - object. Note that the contents of this option are not examined or - processed in any way; you are free to use whatever format you - choose. - -- **directSourceFile**: Like `sourceFile`, but a `sourceFile` property - will be added directly to the nodes, rather than the `loc` object. - -- **preserveParens**: If this option is `true`, parenthesized expressions - are represented by (non-standard) `ParenthesizedExpression` nodes - that have a single `expression` property containing the expression - inside parentheses. - -[range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678 - -**parseExpressionAt**`(input, offset, options)` will parse a single -expression in a string, and return its AST. It will not complain if -there is more of the string left after the expression. - -**getLineInfo**`(input, offset)` can be used to get a `{line, -column}` object for a given program string and character offset. - -**tokenizer**`(input, options)` returns an object with a `getToken` -method that can be called repeatedly to get the next token, a `{start, -end, type, value}` object (with added `loc` property when the -`locations` option is enabled and `range` property when the `ranges` -option is enabled). When the token's type is `tokTypes.eof`, you -should stop calling the method, since it will keep returning that same -token forever. - -In ES6 environment, returned result can be used as any other -protocol-compliant iterable: - -```javascript -for (let token of acorn.tokenizer(str)) { - // iterate over the tokens -} - -// transform code to array of tokens: -var tokens = [...acorn.tokenizer(str)]; -``` - -**tokTypes** holds an object mapping names to the token type objects -that end up in the `type` properties of tokens. - -#### Note on using with [Escodegen][escodegen] - -Escodegen supports generating comments from AST, attached in -Esprima-specific format. In order to simulate same format in -Acorn, consider following example: - -```javascript -var comments = [], tokens = []; - -var ast = acorn.parse('var x = 42; // answer', { - // collect ranges for each node - ranges: true, - // collect comments in Esprima's format - onComment: comments, - // collect token ranges - onToken: tokens -}); - -// attach comments using collected information -escodegen.attachComments(ast, comments, tokens); - -// generate code -console.log(escodegen.generate(ast, {comment: true})); -// > 'var x = 42; // answer' -``` - -[escodegen]: https://github.com/estools/escodegen - -### dist/acorn_loose.js ### - -This file implements an error-tolerant parser. It exposes a single -function. The loose parser is accessible in node.js via `require("acorn/dist/acorn_loose")`. - -**parse_dammit**`(input, options)` takes the same arguments and -returns the same syntax tree as the `parse` function in `acorn.js`, -but never raises an error, and will do its best to parse syntactically -invalid code in as meaningful a way as it can. It'll insert identifier -nodes with name `"✖"` as placeholders in places where it can't make -sense of the input. Depends on `acorn.js`, because it uses the same -tokenizer. - -### dist/walk.js ### - -Implements an abstract syntax tree walker. Will store its interface in -`acorn.walk` when loaded without a module system. - -**simple**`(node, visitors, base, state)` does a 'simple' walk over -a tree. `node` should be the AST node to walk, and `visitors` an -object with properties whose names correspond to node types in the -[ESTree spec][estree]. The properties should contain functions -that will be called with the node object and, if applicable the state -at that point. The last two arguments are optional. `base` is a walker -algorithm, and `state` is a start state. The default walker will -simply visit all statements and expressions and not produce a -meaningful state. (An example of a use of state is to track scope at -each point in the tree.) - -**ancestor**`(node, visitors, base, state)` does a 'simple' walk over -a tree, building up an array of ancestor nodes (including the current node) -and passing the array to callbacks in the `state` parameter. - -**recursive**`(node, state, functions, base)` does a 'recursive' -walk, where the walker functions are responsible for continuing the -walk on the child nodes of their target node. `state` is the start -state, and `functions` should contain an object that maps node types -to walker functions. Such functions are called with `(node, state, c)` -arguments, and can cause the walk to continue on a sub-node by calling -the `c` argument on it with `(node, state)` arguments. The optional -`base` argument provides the fallback walker functions for node types -that aren't handled in the `functions` object. If not given, the -default walkers will be used. - -**make**`(functions, base)` builds a new walker object by using the -walker functions in `functions` and filling in the missing ones by -taking defaults from `base`. - -**findNodeAt**`(node, start, end, test, base, state)` tries to -locate a node in a tree at the given start and/or end offsets, which -satisfies the predicate `test`. `start` and `end` can be either `null` -(as wildcard) or a number. `test` may be a string (indicating a node -type) or a function that takes `(nodeType, node)` arguments and -returns a boolean indicating whether this node is interesting. `base` -and `state` are optional, and can be used to specify a custom walker. -Nodes are tested from inner to outer, so if two nodes match the -boundaries, the inner one will be preferred. - -**findNodeAround**`(node, pos, test, base, state)` is a lot like -`findNodeAt`, but will match any node that exists 'around' (spanning) -the given position. - -**findNodeAfter**`(node, pos, test, base, state)` is similar to -`findNodeAround`, but will match all nodes *after* the given position -(testing outer nodes before inner nodes). - -## Command line interface - -The `bin/acorn` utility can be used to parse a file from the command -line. It accepts as arguments its input file and the following -options: - -- `--ecma3|--ecma5|--ecma6`: Sets the ECMAScript version to parse. Default is - version 5. - -- `--module`: Sets the parsing mode to `"module"`. Is set to `"script"` otherwise. - -- `--locations`: Attaches a "loc" object to each node with "start" and - "end" subobjects, each of which contains the one-based line and - zero-based column numbers in `{line, column}` form. - -- `--allow-hash-bang`: If the code starts with the characters #! (as in a shellscript), the first line will be treated as a comment. - -- `--compact`: No whitespace is used in the AST output. - -- `--silent`: Do not output the AST, just return the exit status. - -- `--help`: Print the usage information and quit. - -The utility spits out the syntax tree as JSON data. - -## Build system - -Acorn is written in ECMAScript 6, as a set of small modules, in the -project's `src` directory, and compiled down to bigger ECMAScript 3 -files in `dist` using [Browserify](http://browserify.org) and -[Babel](http://babeljs.io/). If you are already using Babel, you can -consider including the modules directly. - -The command-line test runner (`npm test`) uses the ES6 modules. The -browser-based test page (`test/index.html`) uses the compiled modules. -The `bin/build-acorn.js` script builds the latter from the former. - -If you are working on Acorn, you'll probably want to try the code out -directly, without an intermediate build step. In your scripts, you can -register the Babel require shim like this: - - require("babel-core/register") - -That will allow you to directly `require` the ES6 modules. - -## Plugins - -Acorn is designed support allow plugins which, within reasonable -bounds, redefine the way the parser works. Plugins can add new token -types and new tokenizer contexts (if necessary), and extend methods in -the parser object. This is not a clean, elegant API—using it requires -an understanding of Acorn's internals, and plugins are likely to break -whenever those internals are significantly changed. But still, it is -_possible_, in this way, to create parsers for JavaScript dialects -without forking all of Acorn. And in principle it is even possible to -combine such plugins, so that if you have, for example, a plugin for -parsing types and a plugin for parsing JSX-style XML literals, you -could load them both and parse code with both JSX tags and types. - -A plugin should register itself by adding a property to -`acorn.plugins`, which holds a function. Calling `acorn.parse`, a -`plugins` option can be passed, holding an object mapping plugin names -to configuration values (or just `true` for plugins that don't take -options). After the parser object has been created, the initialization -functions for the chosen plugins are called with `(parser, -configValue)` arguments. They are expected to use the `parser.extend` -method to extend parser methods. For example, the `readToken` method -could be extended like this: - -```javascript -parser.extend("readToken", function(nextMethod) { - return function(code) { - console.log("Reading a token!") - return nextMethod.call(this, code) - } -}) -``` - -The `nextMethod` argument passed to `extend`'s second argument is the -previous value of this method, and should usually be called through to -whenever the extended method does not handle the call itself. - -Similarly, the loose parser allows plugins to register themselves via -`acorn.pluginsLoose`. The extension mechanism is the same as for the -normal parser: - -```javascript -looseParser.extend("readToken", function(nextMethod) { - return function() { - console.log("Reading a token in the loose parser!") - return nextMethod.call(this) - } -}) -``` - -There is a proof-of-concept JSX plugin in the [`acorn-jsx`](https://github.com/RReverser/acorn-jsx) project. diff --git a/tools/eslint/node_modules/acorn-jsx/node_modules/acorn/bin/acorn b/tools/eslint/node_modules/acorn-jsx/node_modules/acorn/bin/acorn deleted file mode 100755 index db079096d3749a..00000000000000 --- a/tools/eslint/node_modules/acorn-jsx/node_modules/acorn/bin/acorn +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env node -"use strict"; - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj["default"] = obj; return newObj; } } - -var _path = require("path"); - -var _fs = require("fs"); - -var _distAcornJs = require("../dist/acorn.js"); - -var acorn = _interopRequireWildcard(_distAcornJs); - -var infile = undefined, - forceFile = undefined, - silent = false, - compact = false, - tokenize = false; -var options = {}; - -function help(status) { - var print = status == 0 ? console.log : console.error; - print("usage: " + (0, _path.basename)(process.argv[1]) + " [--ecma3|--ecma5|--ecma6]"); - print(" [--tokenize] [--locations] [---allow-hash-bang] [--compact] [--silent] [--module] [--help] [--] [infile]"); - process.exit(status); -} - -for (var i = 2; i < process.argv.length; ++i) { - var arg = process.argv[i]; - if ((arg == "-" || arg[0] != "-") && !infile) infile = arg;else if (arg == "--" && !infile && i + 2 == process.argv.length) forceFile = infile = process.argv[++i];else if (arg == "--ecma3") options.ecmaVersion = 3;else if (arg == "--ecma5") options.ecmaVersion = 5;else if (arg == "--ecma6") options.ecmaVersion = 6;else if (arg == "--locations") options.locations = true;else if (arg == "--allow-hash-bang") options.allowHashBang = true;else if (arg == "--silent") silent = true;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 help(1); -} - -function run(code) { - var result = undefined; - 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 = undefined; - 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; - } - } - if (!silent) console.log(JSON.stringify(result, null, compact ? null : 2)); -} - -if (forceFile || infile && infile != "-") { - run((0, _fs.readFileSync)(infile, "utf8")); -} else { - (function () { - var code = ""; - process.stdin.resume(); - process.stdin.on("data", function (chunk) { - return code += chunk; - }); - process.stdin.on("end", function () { - return run(code); - }); - })(); -} \ No newline at end of file diff --git a/tools/eslint/node_modules/acorn-jsx/node_modules/acorn/bin/build-acorn.js b/tools/eslint/node_modules/acorn-jsx/node_modules/acorn/bin/build-acorn.js deleted file mode 100644 index 71f2cf941f5b4d..00000000000000 --- a/tools/eslint/node_modules/acorn-jsx/node_modules/acorn/bin/build-acorn.js +++ /dev/null @@ -1,82 +0,0 @@ -var fs = require("fs"), path = require("path") -var stream = require("stream") - -var browserify = require("browserify") -var babel = require('babel-core') -var babelify = require("babelify").configure({loose: "all"}) - -process.chdir(path.resolve(__dirname, "..")) - -browserify({standalone: "acorn"}) - .plugin(require('browserify-derequire')) - .transform(babelify) - .require("./src/index.js", {entry: true}) - .bundle() - .on("error", function (err) { console.log("Error: " + err.message) }) - .pipe(fs.createWriteStream("dist/acorn.js")) - -var ACORN_PLACEHOLDER = "this_function_call_should_be_replaced_with_a_call_to_load_acorn()"; -function acornShimPrepare(file) { - var tr = new stream.Transform - if (file == path.resolve(__dirname, "../src/index.js")) { - var sent = false - tr._transform = function(chunk, _, callback) { - if (!sent) { - sent = true - callback(null, ACORN_PLACEHOLDER); - } else { - callback() - } - } - } else { - tr._transform = function(chunk, _, callback) { callback(null, chunk) } - } - return tr -} -function acornShimComplete() { - var tr = new stream.Transform - var buffer = ""; - tr._transform = function(chunk, _, callback) { - buffer += chunk.toString("utf8"); - callback(); - }; - tr._flush = function (callback) { - tr.push(buffer.replace(ACORN_PLACEHOLDER, "module.exports = typeof acorn != 'undefined' ? acorn : require(\"./acorn\")")); - callback(null); - }; - return tr; -} - -browserify({standalone: "acorn.loose"}) - .plugin(require('browserify-derequire')) - .transform(acornShimPrepare) - .transform(babelify) - .require("./src/loose/index.js", {entry: true}) - .bundle() - .on("error", function (err) { console.log("Error: " + err.message) }) - .pipe(acornShimComplete()) - .pipe(fs.createWriteStream("dist/acorn_loose.js")) - -browserify({standalone: "acorn.walk"}) - .plugin(require('browserify-derequire')) - .transform(acornShimPrepare) - .transform(babelify) - .require("./src/walk/index.js", {entry: true}) - .bundle() - .on("error", function (err) { console.log("Error: " + err.message) }) - .pipe(acornShimComplete()) - .pipe(fs.createWriteStream("dist/walk.js")) - -babel.transformFile("./src/bin/acorn.js", function (err, result) { - if (err) return console.log("Error: " + err.message) - fs.writeFile("bin/acorn", result.code, function (err) { - if (err) return console.log("Error: " + err.message) - - // Make bin/acorn executable - if (process.platform === 'win32') - return - var stat = fs.statSync("bin/acorn") - var newPerm = stat.mode | parseInt('111', 8) - fs.chmodSync("bin/acorn", newPerm) - }) -}) diff --git a/tools/eslint/node_modules/acorn-jsx/node_modules/acorn/bin/generate-identifier-regex.js b/tools/eslint/node_modules/acorn-jsx/node_modules/acorn/bin/generate-identifier-regex.js deleted file mode 100644 index 0d7c50fc384ee5..00000000000000 --- a/tools/eslint/node_modules/acorn-jsx/node_modules/acorn/bin/generate-identifier-regex.js +++ /dev/null @@ -1,47 +0,0 @@ -// Note: run `npm install unicode-7.0.0` first. - -// Which Unicode version should be used? -var version = '7.0.0'; - -var start = require('unicode-' + version + '/properties/ID_Start/code-points') - .filter(function(ch) { return ch > 127; }); -var cont = [0x200c, 0x200d].concat(require('unicode-' + version + '/properties/ID_Continue/code-points') - .filter(function(ch) { return ch > 127 && start.indexOf(ch) == -1; })); - -function pad(str, width) { - while (str.length < width) str = "0" + str; - return str; -} - -function esc(code) { - var hex = code.toString(16); - if (hex.length <= 2) return "\\x" + pad(hex, 2); - else return "\\u" + pad(hex, 4); -} - -function generate(chars) { - var astral = [], re = ""; - for (var i = 0, at = 0x10000; i < chars.length; i++) { - var from = chars[i], to = from; - while (i < chars.length - 1 && chars[i + 1] == to + 1) { - i++; - to++; - } - if (to <= 0xffff) { - if (from == to) re += esc(from); - else if (from + 1 == to) re += esc(from) + esc(to); - else re += esc(from) + "-" + esc(to); - } else { - astral.push(from - at, to - from); - at = to; - } - } - return {nonASCII: re, astral: astral}; -} - -var startData = generate(start), contData = generate(cont); - -console.log(" var nonASCIIidentifierStartChars = \"" + startData.nonASCII + "\";"); -console.log(" var nonASCIIidentifierChars = \"" + contData.nonASCII + "\";"); -console.log(" var astralIdentifierStartCodes = " + JSON.stringify(startData.astral) + ";"); -console.log(" var astralIdentifierCodes = " + JSON.stringify(contData.astral) + ";"); diff --git a/tools/eslint/node_modules/acorn-jsx/node_modules/acorn/bin/update_authors.sh b/tools/eslint/node_modules/acorn-jsx/node_modules/acorn/bin/update_authors.sh deleted file mode 100755 index 466c8db5867cba..00000000000000 --- a/tools/eslint/node_modules/acorn-jsx/node_modules/acorn/bin/update_authors.sh +++ /dev/null @@ -1,6 +0,0 @@ -# Combine existing list of authors with everyone known in git, sort, add header. -tail --lines=+3 AUTHORS > AUTHORS.tmp -git log --format='%aN' | grep -v abraidwood >> AUTHORS.tmp -echo -e "List of Acorn contributors. Updated before every release.\n" > AUTHORS -sort -u AUTHORS.tmp >> AUTHORS -rm -f AUTHORS.tmp diff --git a/tools/eslint/node_modules/acorn-jsx/node_modules/acorn/dist/.keep b/tools/eslint/node_modules/acorn-jsx/node_modules/acorn/dist/.keep deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/tools/eslint/node_modules/acorn-jsx/node_modules/acorn/dist/acorn.js b/tools/eslint/node_modules/acorn-jsx/node_modules/acorn/dist/acorn.js deleted file mode 100644 index 9419f862ae779e..00000000000000 --- a/tools/eslint/node_modules/acorn-jsx/node_modules/acorn/dist/acorn.js +++ /dev/null @@ -1,3340 +0,0 @@ -(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.acorn = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= 6 && (prop.computed || prop.method || prop.shorthand)) return; - var key = prop.key;var name = undefined; - switch (key.type) { - case "Identifier": - name = key.name;break; - case "Literal": - name = String(key.value);break; - default: - return; - } - var kind = prop.kind; - - if (this.options.ecmaVersion >= 6) { - if (name === "__proto__" && kind === "init") { - if (propHash.proto) this.raise(key.start, "Redefinition of __proto__ property"); - propHash.proto = true; - } - return; - } - name = "$" + name; - var other = propHash[name]; - if (other) { - var isGetSet = kind !== "init"; - if ((this.strict || isGetSet) && other[kind] || !(isGetSet ^ other.init)) this.raise(key.start, "Redefinition of property"); - } else { - other = propHash[name] = { - init: false, - get: false, - set: false - }; - } - other[kind] = true; -}; - -// ### Expression parsing - -// These nest, from the most general expression type at the top to -// 'atomic', nondivisible expression types at the bottom. Most of -// the functions will simply let the function(s) below them parse, -// and, *if* the syntactic construct they handle is present, wrap -// the AST node that the inner parser gave them in another node. - -// Parse a full expression. The optional arguments are used to -// forbid the `in` operator (in for loops initalization expressions) -// and provide reference for storing '=' operator inside shorthand -// property assignment in contexts where both object expression -// and object pattern might appear (so it's possible to raise -// delayed syntax error at correct position). - -pp.parseExpression = function (noIn, refDestructuringErrors) { - var startPos = this.start, - startLoc = this.startLoc; - var expr = this.parseMaybeAssign(noIn, refDestructuringErrors); - if (this.type === _tokentype.types.comma) { - var node = this.startNodeAt(startPos, startLoc); - node.expressions = [expr]; - while (this.eat(_tokentype.types.comma)) node.expressions.push(this.parseMaybeAssign(noIn, refDestructuringErrors)); - return this.finishNode(node, "SequenceExpression"); - } - return expr; -}; - -// Parse an assignment expression. This includes applications of -// operators like `+=`. - -pp.parseMaybeAssign = function (noIn, refDestructuringErrors, afterLeftParse) { - if (this.type == _tokentype.types._yield && this.inGenerator) return this.parseYield(); - - var validateDestructuring = false; - if (!refDestructuringErrors) { - refDestructuringErrors = { shorthandAssign: 0, trailingComma: 0 }; - validateDestructuring = true; - } - var startPos = this.start, - startLoc = this.startLoc; - if (this.type == _tokentype.types.parenL || this.type == _tokentype.types.name) this.potentialArrowAt = this.start; - var left = this.parseMaybeConditional(noIn, refDestructuringErrors); - if (afterLeftParse) left = afterLeftParse.call(this, left, startPos, startLoc); - if (this.type.isAssign) { - if (validateDestructuring) this.checkPatternErrors(refDestructuringErrors, true); - var node = this.startNodeAt(startPos, startLoc); - node.operator = this.value; - node.left = this.type === _tokentype.types.eq ? this.toAssignable(left) : left; - refDestructuringErrors.shorthandAssign = 0; // reset because shorthand default was used correctly - this.checkLVal(left); - this.next(); - node.right = this.parseMaybeAssign(noIn); - return this.finishNode(node, "AssignmentExpression"); - } else { - if (validateDestructuring) this.checkExpressionErrors(refDestructuringErrors, true); - } - return left; -}; - -// Parse a ternary conditional (`?:`) operator. - -pp.parseMaybeConditional = function (noIn, refDestructuringErrors) { - var startPos = this.start, - startLoc = this.startLoc; - var expr = this.parseExprOps(noIn, refDestructuringErrors); - if (this.checkExpressionErrors(refDestructuringErrors)) return expr; - if (this.eat(_tokentype.types.question)) { - var node = this.startNodeAt(startPos, startLoc); - node.test = expr; - node.consequent = this.parseMaybeAssign(); - this.expect(_tokentype.types.colon); - node.alternate = this.parseMaybeAssign(noIn); - return this.finishNode(node, "ConditionalExpression"); - } - return expr; -}; - -// Start the precedence parser. - -pp.parseExprOps = function (noIn, refDestructuringErrors) { - var startPos = this.start, - startLoc = this.startLoc; - var expr = this.parseMaybeUnary(refDestructuringErrors); - if (this.checkExpressionErrors(refDestructuringErrors)) return expr; - return this.parseExprOp(expr, startPos, startLoc, -1, noIn); -}; - -// Parse binary operators with the operator precedence parsing -// algorithm. `left` is the left-hand side of the operator. -// `minPrec` provides context that allows the function to stop and -// defer further parser to one of its callers when it encounters an -// operator that has a lower precedence than the set it is parsing. - -pp.parseExprOp = function (left, leftStartPos, leftStartLoc, minPrec, noIn) { - var prec = this.type.binop; - if (prec != null && (!noIn || this.type !== _tokentype.types._in)) { - if (prec > minPrec) { - var node = this.startNodeAt(leftStartPos, leftStartLoc); - node.left = left; - node.operator = this.value; - var op = this.type; - this.next(); - var startPos = this.start, - startLoc = this.startLoc; - node.right = this.parseExprOp(this.parseMaybeUnary(), startPos, startLoc, prec, noIn); - this.finishNode(node, op === _tokentype.types.logicalOR || op === _tokentype.types.logicalAND ? "LogicalExpression" : "BinaryExpression"); - return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, noIn); - } - } - return left; -}; - -// Parse unary operators, both prefix and postfix. - -pp.parseMaybeUnary = function (refDestructuringErrors) { - if (this.type.prefix) { - var node = this.startNode(), - update = this.type === _tokentype.types.incDec; - node.operator = this.value; - node.prefix = true; - this.next(); - node.argument = this.parseMaybeUnary(); - this.checkExpressionErrors(refDestructuringErrors, true); - if (update) this.checkLVal(node.argument);else if (this.strict && node.operator === "delete" && node.argument.type === "Identifier") this.raise(node.start, "Deleting local variable in strict mode"); - return this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression"); - } - var startPos = this.start, - startLoc = this.startLoc; - var expr = this.parseExprSubscripts(refDestructuringErrors); - if (this.checkExpressionErrors(refDestructuringErrors)) return expr; - while (this.type.postfix && !this.canInsertSemicolon()) { - var node = this.startNodeAt(startPos, startLoc); - node.operator = this.value; - node.prefix = false; - node.argument = expr; - this.checkLVal(expr); - this.next(); - expr = this.finishNode(node, "UpdateExpression"); - } - return expr; -}; - -// Parse call, dot, and `[]`-subscript expressions. - -pp.parseExprSubscripts = function (refDestructuringErrors) { - var startPos = this.start, - startLoc = this.startLoc; - 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); -}; - -pp.parseSubscripts = function (base, startPos, startLoc, noCalls) { - for (;;) { - if (this.eat(_tokentype.types.dot)) { - var 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(_tokentype.types.bracketL)) { - var node = this.startNodeAt(startPos, startLoc); - node.object = base; - node.property = this.parseExpression(); - node.computed = true; - this.expect(_tokentype.types.bracketR); - base = this.finishNode(node, "MemberExpression"); - } else if (!noCalls && this.eat(_tokentype.types.parenL)) { - var node = this.startNodeAt(startPos, startLoc); - node.callee = base; - node.arguments = this.parseExprList(_tokentype.types.parenR, false); - base = this.finishNode(node, "CallExpression"); - } else if (this.type === _tokentype.types.backQuote) { - var node = this.startNodeAt(startPos, startLoc); - node.tag = base; - node.quasi = this.parseTemplate(); - base = this.finishNode(node, "TaggedTemplateExpression"); - } else { - return base; - } - } -}; - -// Parse an atomic expression — either a single token that is an -// expression, an expression started by a keyword like `function` or -// `new`, or an expression wrapped in punctuation like `()`, `[]`, -// or `{}`. - -pp.parseExprAtom = function (refDestructuringErrors) { - var node = undefined, - canBeArrow = this.potentialArrowAt == this.start; - switch (this.type) { - case _tokentype.types._super: - if (!this.inFunction) this.raise(this.start, "'super' outside of function or class"); - case _tokentype.types._this: - var type = this.type === _tokentype.types._this ? "ThisExpression" : "Super"; - node = this.startNode(); - this.next(); - return this.finishNode(node, type); - - case _tokentype.types._yield: - if (this.inGenerator) this.unexpected(); - - case _tokentype.types.name: - var startPos = this.start, - startLoc = this.startLoc; - var id = this.parseIdent(this.type !== _tokentype.types.name); - if (canBeArrow && !this.canInsertSemicolon() && this.eat(_tokentype.types.arrow)) return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id]); - return id; - - case _tokentype.types.regexp: - var value = this.value; - node = this.parseLiteral(value.value); - node.regex = { pattern: value.pattern, flags: value.flags }; - return node; - - case _tokentype.types.num:case _tokentype.types.string: - return this.parseLiteral(this.value); - - case _tokentype.types._null:case _tokentype.types._true:case _tokentype.types._false: - node = this.startNode(); - node.value = this.type === _tokentype.types._null ? null : this.type === _tokentype.types._true; - node.raw = this.type.keyword; - this.next(); - return this.finishNode(node, "Literal"); - - case _tokentype.types.parenL: - return this.parseParenAndDistinguishExpression(canBeArrow); - - case _tokentype.types.bracketL: - node = this.startNode(); - this.next(); - // check whether this is array comprehension or regular array - if (this.options.ecmaVersion >= 7 && this.type === _tokentype.types._for) { - return this.parseComprehension(node, false); - } - node.elements = this.parseExprList(_tokentype.types.bracketR, true, true, refDestructuringErrors); - return this.finishNode(node, "ArrayExpression"); - - case _tokentype.types.braceL: - return this.parseObj(false, refDestructuringErrors); - - case _tokentype.types._function: - node = this.startNode(); - this.next(); - return this.parseFunction(node, false); - - case _tokentype.types._class: - return this.parseClass(this.startNode(), false); - - case _tokentype.types._new: - return this.parseNew(); - - case _tokentype.types.backQuote: - return this.parseTemplate(); - - default: - this.unexpected(); - } -}; - -pp.parseLiteral = function (value) { - var node = this.startNode(); - node.value = value; - node.raw = this.input.slice(this.start, this.end); - this.next(); - return this.finishNode(node, "Literal"); -}; - -pp.parseParenExpression = function () { - this.expect(_tokentype.types.parenL); - var val = this.parseExpression(); - this.expect(_tokentype.types.parenR); - return val; -}; - -pp.parseParenAndDistinguishExpression = function (canBeArrow) { - var startPos = this.start, - startLoc = this.startLoc, - val = undefined; - if (this.options.ecmaVersion >= 6) { - this.next(); - - if (this.options.ecmaVersion >= 7 && this.type === _tokentype.types._for) { - return this.parseComprehension(this.startNodeAt(startPos, startLoc), true); - } - - var innerStartPos = this.start, - innerStartLoc = this.startLoc; - var exprList = [], - first = true; - var refDestructuringErrors = { shorthandAssign: 0, trailingComma: 0 }, - spreadStart = undefined, - innerParenStart = undefined; - while (this.type !== _tokentype.types.parenR) { - first ? first = false : this.expect(_tokentype.types.comma); - if (this.type === _tokentype.types.ellipsis) { - spreadStart = this.start; - exprList.push(this.parseParenItem(this.parseRest())); - break; - } else { - if (this.type === _tokentype.types.parenL && !innerParenStart) { - innerParenStart = this.start; - } - exprList.push(this.parseMaybeAssign(false, refDestructuringErrors, this.parseParenItem)); - } - } - var innerEndPos = this.start, - innerEndLoc = this.startLoc; - this.expect(_tokentype.types.parenR); - - if (canBeArrow && !this.canInsertSemicolon() && this.eat(_tokentype.types.arrow)) { - this.checkPatternErrors(refDestructuringErrors, true); - if (innerParenStart) this.unexpected(innerParenStart); - return this.parseParenArrowList(startPos, startLoc, exprList); - } - - if (!exprList.length) this.unexpected(this.lastTokStart); - if (spreadStart) this.unexpected(spreadStart); - this.checkExpressionErrors(refDestructuringErrors, true); - - if (exprList.length > 1) { - val = this.startNodeAt(innerStartPos, innerStartLoc); - val.expressions = exprList; - this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc); - } else { - val = exprList[0]; - } - } else { - val = this.parseParenExpression(); - } - - if (this.options.preserveParens) { - var par = this.startNodeAt(startPos, startLoc); - par.expression = val; - return this.finishNode(par, "ParenthesizedExpression"); - } else { - return val; - } -}; - -pp.parseParenItem = function (item) { - return item; -}; - -pp.parseParenArrowList = function (startPos, startLoc, exprList) { - return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList); -}; - -// New's precedence is slightly tricky. It must allow its argument to -// be a `[]` or dot subscript expression, but not a call — at least, -// not without wrapping it in parentheses. Thus, it uses the noCalls -// argument to parseSubscripts to prevent it from consuming the -// argument list. - -var empty = []; - -pp.parseNew = function () { - var node = this.startNode(); - var meta = this.parseIdent(true); - if (this.options.ecmaVersion >= 6 && this.eat(_tokentype.types.dot)) { - node.meta = meta; - node.property = this.parseIdent(true); - if (node.property.name !== "target") this.raise(node.property.start, "The only valid meta property for new is new.target"); - if (!this.inFunction) this.raise(node.start, "new.target can only be used in functions"); - return this.finishNode(node, "MetaProperty"); - } - var startPos = this.start, - startLoc = this.startLoc; - node.callee = this.parseSubscripts(this.parseExprAtom(), startPos, startLoc, true); - if (this.eat(_tokentype.types.parenL)) node.arguments = this.parseExprList(_tokentype.types.parenR, false);else node.arguments = empty; - return this.finishNode(node, "NewExpression"); -}; - -// Parse template expression. - -pp.parseTemplateElement = function () { - var elem = this.startNode(); - elem.value = { - raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, '\n'), - cooked: this.value - }; - this.next(); - elem.tail = this.type === _tokentype.types.backQuote; - return this.finishNode(elem, "TemplateElement"); -}; - -pp.parseTemplate = function () { - var node = this.startNode(); - this.next(); - node.expressions = []; - var curElt = this.parseTemplateElement(); - node.quasis = [curElt]; - while (!curElt.tail) { - this.expect(_tokentype.types.dollarBraceL); - node.expressions.push(this.parseExpression()); - this.expect(_tokentype.types.braceR); - node.quasis.push(curElt = this.parseTemplateElement()); - } - this.next(); - return this.finishNode(node, "TemplateLiteral"); -}; - -// Parse an object literal or binding pattern. - -pp.parseObj = function (isPattern, refDestructuringErrors) { - var node = this.startNode(), - first = true, - propHash = {}; - node.properties = []; - this.next(); - while (!this.eat(_tokentype.types.braceR)) { - if (!first) { - this.expect(_tokentype.types.comma); - if (this.afterTrailingComma(_tokentype.types.braceR)) break; - } else first = false; - - var prop = this.startNode(), - isGenerator = undefined, - startPos = undefined, - startLoc = undefined; - if (this.options.ecmaVersion >= 6) { - prop.method = false; - prop.shorthand = false; - if (isPattern || refDestructuringErrors) { - startPos = this.start; - startLoc = this.startLoc; - } - if (!isPattern) isGenerator = this.eat(_tokentype.types.star); - } - this.parsePropertyName(prop); - this.parsePropertyValue(prop, isPattern, isGenerator, startPos, startLoc, refDestructuringErrors); - this.checkPropClash(prop, propHash); - node.properties.push(this.finishNode(prop, "Property")); - } - return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression"); -}; - -pp.parsePropertyValue = function (prop, isPattern, isGenerator, startPos, startLoc, refDestructuringErrors) { - if (this.eat(_tokentype.types.colon)) { - prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refDestructuringErrors); - prop.kind = "init"; - } else if (this.options.ecmaVersion >= 6 && this.type === _tokentype.types.parenL) { - if (isPattern) this.unexpected(); - prop.kind = "init"; - prop.method = true; - prop.value = this.parseMethod(isGenerator); - } else if (this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" && (prop.key.name === "get" || prop.key.name === "set") && (this.type != _tokentype.types.comma && this.type != _tokentype.types.braceR)) { - if (isGenerator || isPattern) this.unexpected(); - prop.kind = prop.key.name; - this.parsePropertyName(prop); - prop.value = this.parseMethod(false); - var paramCount = prop.kind === "get" ? 0 : 1; - if (prop.value.params.length !== paramCount) { - var start = prop.value.start; - if (prop.kind === "get") this.raise(start, "getter should have no params");else this.raise(start, "setter should have exactly one param"); - } - if (prop.kind === "set" && prop.value.params[0].type === "RestElement") this.raise(prop.value.params[0].start, "Setter cannot use rest params"); - } else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") { - prop.kind = "init"; - if (isPattern) { - if (this.keywords.test(prop.key.name) || (this.strict ? this.reservedWordsStrictBind : this.reservedWords).test(prop.key.name)) this.raise(prop.key.start, "Binding " + prop.key.name); - prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key); - } else if (this.type === _tokentype.types.eq && refDestructuringErrors) { - if (!refDestructuringErrors.shorthandAssign) refDestructuringErrors.shorthandAssign = this.start; - prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key); - } else { - prop.value = prop.key; - } - prop.shorthand = true; - } else this.unexpected(); -}; - -pp.parsePropertyName = function (prop) { - if (this.options.ecmaVersion >= 6) { - if (this.eat(_tokentype.types.bracketL)) { - prop.computed = true; - prop.key = this.parseMaybeAssign(); - this.expect(_tokentype.types.bracketR); - return prop.key; - } else { - prop.computed = false; - } - } - return prop.key = this.type === _tokentype.types.num || this.type === _tokentype.types.string ? this.parseExprAtom() : this.parseIdent(true); -}; - -// Initialize empty function node. - -pp.initFunction = function (node) { - node.id = null; - if (this.options.ecmaVersion >= 6) { - node.generator = false; - node.expression = false; - } -}; - -// Parse object or class method. - -pp.parseMethod = function (isGenerator) { - var node = this.startNode(); - this.initFunction(node); - this.expect(_tokentype.types.parenL); - node.params = this.parseBindingList(_tokentype.types.parenR, false, false); - if (this.options.ecmaVersion >= 6) node.generator = isGenerator; - this.parseFunctionBody(node, false); - return this.finishNode(node, "FunctionExpression"); -}; - -// Parse arrow function expression with given parameters. - -pp.parseArrowExpression = function (node, params) { - this.initFunction(node); - node.params = this.toAssignableList(params, true); - this.parseFunctionBody(node, true); - return this.finishNode(node, "ArrowFunctionExpression"); -}; - -// Parse function body and check parameters. - -pp.parseFunctionBody = function (node, isArrowFunction) { - var isExpression = isArrowFunction && this.type !== _tokentype.types.braceL; - - if (isExpression) { - node.body = this.parseMaybeAssign(); - node.expression = true; - } else { - // Start a new scope with regard to labels and the `inFunction` - // flag (restore them to their old value afterwards). - var oldInFunc = this.inFunction, - oldInGen = this.inGenerator, - oldLabels = this.labels; - this.inFunction = true;this.inGenerator = node.generator;this.labels = []; - node.body = this.parseBlock(true); - node.expression = false; - this.inFunction = oldInFunc;this.inGenerator = oldInGen;this.labels = oldLabels; - } - - // 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 (this.strict || !isExpression && node.body.body.length && this.isUseStrict(node.body.body[0])) { - 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.checkParams(node); - } -}; - -// Checks function params for various disallowed patterns such as using "eval" -// or "arguments" and duplicate parameters. - -pp.checkParams = function (node) { - var nameHash = {}; - for (var i = 0; i < node.params.length; i++) { - this.checkLVal(node.params[i], true, nameHash); - } -}; - -// Parses a comma-separated list of expressions, and returns them as -// an array. `close` is the token type that ends the list, and -// `allowEmpty` can be turned on to allow subsequent commas with -// nothing in between them to be parsed as `null` (which is needed -// for array literals). - -pp.parseExprList = function (close, allowTrailingComma, allowEmpty, refDestructuringErrors) { - var elts = [], - first = true; - while (!this.eat(close)) { - if (!first) { - this.expect(_tokentype.types.comma); - if (this.type === close && refDestructuringErrors && !refDestructuringErrors.trailingComma) { - refDestructuringErrors.trailingComma = this.lastTokStart; - } - if (allowTrailingComma && this.afterTrailingComma(close)) break; - } else first = false; - - var elt = undefined; - if (allowEmpty && this.type === _tokentype.types.comma) elt = null;else if (this.type === _tokentype.types.ellipsis) elt = this.parseSpread(refDestructuringErrors);else elt = this.parseMaybeAssign(false, refDestructuringErrors); - elts.push(elt); - } - return elts; -}; - -// Parse the next token as an identifier. If `liberal` is true (used -// when parsing properties), it will also convert keywords into -// identifiers. - -pp.parseIdent = function (liberal) { - var node = this.startNode(); - if (liberal && this.options.allowReserved == "never") liberal = false; - if (this.type === _tokentype.types.name) { - if (!liberal && (this.strict ? this.reservedWordsStrict : this.reservedWords).test(this.value) && (this.options.ecmaVersion >= 6 || this.input.slice(this.start, this.end).indexOf("\\") == -1)) this.raise(this.start, "The keyword '" + this.value + "' is reserved"); - node.name = this.value; - } else if (liberal && this.type.keyword) { - node.name = this.type.keyword; - } else { - this.unexpected(); - } - this.next(); - return this.finishNode(node, "Identifier"); -}; - -// Parses yield expression inside generator. - -pp.parseYield = function () { - var node = this.startNode(); - this.next(); - if (this.type == _tokentype.types.semi || this.canInsertSemicolon() || this.type != _tokentype.types.star && !this.type.startsExpr) { - node.delegate = false; - node.argument = null; - } else { - node.delegate = this.eat(_tokentype.types.star); - node.argument = this.parseMaybeAssign(); - } - return this.finishNode(node, "YieldExpression"); -}; - -// Parses array and generator comprehensions. - -pp.parseComprehension = function (node, isGenerator) { - node.blocks = []; - while (this.type === _tokentype.types._for) { - var block = this.startNode(); - this.next(); - this.expect(_tokentype.types.parenL); - block.left = this.parseBindingAtom(); - this.checkLVal(block.left, true); - this.expectContextual("of"); - block.right = this.parseExpression(); - this.expect(_tokentype.types.parenR); - node.blocks.push(this.finishNode(block, "ComprehensionBlock")); - } - node.filter = this.eat(_tokentype.types._if) ? this.parseParenExpression() : null; - node.body = this.parseExpression(); - this.expect(isGenerator ? _tokentype.types.parenR : _tokentype.types.bracketR); - node.generator = isGenerator; - return this.finishNode(node, "ComprehensionExpression"); -}; - -},{"./state":10,"./tokentype":14}],2:[function(_dereq_,module,exports){ -// This is a trick taken from Esprima. It turns out that, on -// non-Chrome browsers, to check whether a string is in a set, a -// predicate containing a big ugly `switch` statement is faster than -// a regular expression, and on Chrome the two are about on par. -// This function uses `eval` (non-lexical) to produce such a -// predicate from a space-separated string of words. -// -// It starts by sorting the words by length. - -// Reserved word lists for various dialects of the language - -"use strict"; - -exports.__esModule = true; -exports.isIdentifierStart = isIdentifierStart; -exports.isIdentifierChar = isIdentifierChar; -var reservedWords = { - 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" -}; - -exports.reservedWords = 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"; - -var keywords = { - 5: ecma5AndLessKeywords, - 6: ecma5AndLessKeywords + " let const class extends export import yield super" -}; - -exports.keywords = keywords; -// ## Character categories - -// Big ugly regular expressions that match characters in the -// whitespace, identifier, and identifier-start categories. These -// are only applied when a character is found to actually have a -// code point above 128. -// Generated by `bin/generate-identifier-regex.js`. - -var nonASCIIidentifierStartChars = "ªµºÀ-ÖØ-öø-ˁˆ-ˑˠ-ˤˬˮͰ-ʹͶͷͺ-ͽͿΆΈ-ΊΌΎ-ΡΣ-ϵϷ-ҁҊ-ԯԱ-Ֆՙա-ևא-תװ-ײؠ-يٮٯٱ-ۓەۥۦۮۯۺ-ۼۿܐܒ-ܯݍ-ޥޱߊ-ߪߴߵߺࠀ-ࠕࠚࠤࠨࡀ-ࡘࢠ-ࢲऄ-हऽॐक़-ॡॱ-ঀঅ-ঌএঐও-নপ-রলশ-হঽৎড়ঢ়য়-ৡৰৱਅ-ਊਏਐਓ-ਨਪ-ਰਲਲ਼ਵਸ਼ਸਹਖ਼-ੜਫ਼ੲ-ੴઅ-ઍએ-ઑઓ-નપ-રલળવ-હઽૐૠૡଅ-ଌଏଐଓ-ନପ-ରଲଳଵ-ହଽଡ଼ଢ଼ୟ-ୡୱஃஅ-ஊஎ-ஐஒ-கஙசஜஞடணதந-பம-ஹௐఅ-ఌఎ-ఐఒ-నప-హఽౘౙౠౡಅ-ಌಎ-ಐಒ-ನಪ-ಳವ-ಹಽೞೠೡೱೲഅ-ഌഎ-ഐഒ-ഺഽൎൠൡൺ-ൿඅ-ඖක-නඳ-රලව-ෆก-ะาำเ-ๆກຂຄງຈຊຍດ-ທນ-ຟມ-ຣລວສຫອ-ະາຳຽເ-ໄໆໜ-ໟༀཀ-ཇཉ-ཬྈ-ྌက-ဪဿၐ-ၕၚ-ၝၡၥၦၮ-ၰၵ-ႁႎႠ-ჅჇჍა-ჺჼ-ቈቊ-ቍቐ-ቖቘቚ-ቝበ-ኈኊ-ኍነ-ኰኲ-ኵኸ-ኾዀዂ-ዅወ-ዖዘ-ጐጒ-ጕጘ-ፚᎀ-ᎏᎠ-Ᏼᐁ-ᙬᙯ-ᙿᚁ-ᚚᚠ-ᛪᛮ-ᛸᜀ-ᜌᜎ-ᜑᜠ-ᜱᝀ-ᝑᝠ-ᝬᝮ-ᝰក-ឳៗៜᠠ-ᡷᢀ-ᢨᢪᢰ-ᣵᤀ-ᤞᥐ-ᥭᥰ-ᥴᦀ-ᦫᧁ-ᧇᨀ-ᨖᨠ-ᩔᪧᬅ-ᬳᭅ-ᭋᮃ-ᮠᮮᮯᮺ-ᯥᰀ-ᰣᱍ-ᱏᱚ-ᱽᳩ-ᳬᳮ-ᳱᳵᳶᴀ-ᶿḀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙὛὝὟ-ώᾀ-ᾴᾶ-ᾼιῂ-ῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲ-ῴῶ-ῼⁱⁿₐ-ₜℂℇℊ-ℓℕ℘-ℝℤΩℨK-ℹℼ-ℿⅅ-ⅉⅎⅠ-ↈⰀ-Ⱞⰰ-ⱞⱠ-ⳤⳫ-ⳮⳲⳳⴀ-ⴥⴧⴭⴰ-ⵧⵯⶀ-ⶖⶠ-ⶦⶨ-ⶮⶰ-ⶶⶸ-ⶾⷀ-ⷆⷈ-ⷎⷐ-ⷖⷘ-ⷞ々-〇〡-〩〱-〵〸-〼ぁ-ゖ゛-ゟァ-ヺー-ヿㄅ-ㄭㄱ-ㆎㆠ-ㆺㇰ-ㇿ㐀-䶵一-鿌ꀀ-ꒌꓐ-ꓽꔀ-ꘌꘐ-ꘟꘪꘫꙀ-ꙮꙿ-ꚝꚠ-ꛯꜗ-ꜟꜢ-ꞈꞋ-ꞎꞐ-ꞭꞰꞱꟷ-ꠁꠃ-ꠅꠇ-ꠊꠌ-ꠢꡀ-ꡳꢂ-ꢳꣲ-ꣷꣻꤊ-ꤥꤰ-ꥆꥠ-ꥼꦄ-ꦲꧏꧠ-ꧤꧦ-ꧯꧺ-ꧾꨀ-ꨨꩀ-ꩂꩄ-ꩋꩠ-ꩶꩺꩾ-ꪯꪱꪵꪶꪹ-ꪽꫀꫂꫛ-ꫝꫠ-ꫪꫲ-ꫴꬁ-ꬆꬉ-ꬎꬑ-ꬖꬠ-ꬦꬨ-ꬮꬰ-ꭚꭜ-ꭟꭤꭥꯀ-ꯢ가-힣ힰ-ퟆퟋ-ퟻ豈-舘並-龎ff-stﬓ-ﬗיִײַ-ﬨשׁ-זּטּ-לּמּנּסּףּפּצּ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷻﹰ-ﹴﹶ-ﻼA-Za-zヲ-하-ᅦᅧ-ᅬᅭ-ᅲᅳ-ᅵ"; -var nonASCIIidentifierChars = "‌‍·̀-ͯ·҃-֑҇-ׇֽֿׁׂׅׄؐ-ًؚ-٩ٰۖ-ۜ۟-۪ۤۧۨ-ۭ۰-۹ܑܰ-݊ަ-ް߀-߉߫-߳ࠖ-࠙ࠛ-ࠣࠥ-ࠧࠩ-࡙࠭-࡛ࣤ-ःऺ-़ा-ॏ॑-ॗॢॣ०-९ঁ-ঃ়া-ৄেৈো-্ৗৢৣ০-৯ਁ-ਃ਼ਾ-ੂੇੈੋ-੍ੑ੦-ੱੵઁ-ઃ઼ા-ૅે-ૉો-્ૢૣ૦-૯ଁ-ଃ଼ା-ୄେୈୋ-୍ୖୗୢୣ୦-୯ஂா-ூெ-ைொ-்ௗ௦-௯ఀ-ఃా-ౄె-ైొ-్ౕౖౢౣ౦-౯ಁ-ಃ಼ಾ-ೄೆ-ೈೊ-್ೕೖೢೣ೦-೯ഁ-ഃാ-ൄെ-ൈൊ-്ൗൢൣ൦-൯ංඃ්ා-ුූෘ-ෟ෦-෯ෲෳัิ-ฺ็-๎๐-๙ັິ-ູົຼ່-ໍ໐-໙༘༙༠-༩༹༵༷༾༿ཱ-྄྆྇ྍ-ྗྙ-ྼ࿆ါ-ှ၀-၉ၖ-ၙၞ-ၠၢ-ၤၧ-ၭၱ-ၴႂ-ႍႏ-ႝ፝-፟፩-፱ᜒ-᜔ᜲ-᜴ᝒᝓᝲᝳ឴-៓៝០-៩᠋-᠍᠐-᠙ᢩᤠ-ᤫᤰ-᤻᥆-᥏ᦰ-ᧀᧈᧉ᧐-᧚ᨗ-ᨛᩕ-ᩞ᩠-᩿᩼-᪉᪐-᪙᪰-᪽ᬀ-ᬄ᬴-᭄᭐-᭙᭫-᭳ᮀ-ᮂᮡ-ᮭ᮰-᮹᯦-᯳ᰤ-᰷᱀-᱉᱐-᱙᳐-᳔᳒-᳨᳭ᳲ-᳴᳸᳹᷀-᷵᷼-᷿‿⁀⁔⃐-⃥⃜⃡-⃰⳯-⵿⳱ⷠ-〪ⷿ-゙゚〯꘠-꘩꙯ꙴ-꙽ꚟ꛰꛱ꠂ꠆ꠋꠣ-ꠧꢀꢁꢴ-꣄꣐-꣙꣠-꣱꤀-꤉ꤦ-꤭ꥇ-꥓ꦀ-ꦃ꦳-꧀꧐-꧙ꧥ꧰-꧹ꨩ-ꨶꩃꩌꩍ꩐-꩙ꩻ-ꩽꪰꪲ-ꪴꪷꪸꪾ꪿꫁ꫫ-ꫯꫵ꫶ꯣ-ꯪ꯬꯭꯰-꯹ﬞ︀-️︠-︭︳︴﹍-﹏0-9_"; - -var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]"); -var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]"); - -nonASCIIidentifierStartChars = nonASCIIidentifierChars = null; - -// These are a run-length and offset encoded representation of the -// >0xffff code points that are a valid part of identifiers. The -// 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 tools/generate-identifier-regex.js -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, 99, 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, 98, 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, 955, 52, 76, 44, 33, 24, 27, 35, 42, 34, 4, 0, 13, 47, 15, 3, 22, 0, 38, 17, 2, 24, 133, 46, 39, 7, 3, 1, 3, 21, 2, 6, 2, 1, 2, 4, 4, 0, 32, 4, 287, 47, 21, 1, 2, 0, 185, 46, 82, 47, 21, 0, 60, 42, 502, 63, 32, 0, 449, 56, 1288, 920, 104, 110, 2962, 1070, 13266, 568, 8, 30, 114, 29, 19, 47, 17, 3, 32, 20, 6, 18, 881, 68, 12, 0, 67, 12, 16481, 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, 1340, 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, 16355, 541]; -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, 16, 9, 83, 11, 168, 11, 6, 9, 8, 2, 57, 0, 2, 6, 3, 1, 3, 2, 10, 0, 11, 1, 3, 6, 4, 4, 316, 19, 13, 9, 214, 6, 3, 8, 112, 16, 16, 9, 82, 12, 9, 9, 535, 9, 20855, 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, 4305, 6, 792618, 239]; - -// This has a complexity linear to the value of the code. The -// assumption is that looking up astral identifier characters is -// rare. -function isInAstralSet(code, set) { - var pos = 0x10000; - for (var i = 0; i < set.length; i += 2) { - pos += set[i]; - if (pos > code) return false; - pos += set[i + 1]; - if (pos >= code) return true; - } -} - -// Test whether a given character code starts an identifier. - -function isIdentifierStart(code, astral) { - if (code < 65) return code === 36; - if (code < 91) return true; - if (code < 97) return code === 95; - if (code < 123) return true; - if (code <= 0xffff) return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)); - if (astral === false) return false; - return isInAstralSet(code, astralIdentifierStartCodes); -} - -// Test whether a given character is part of an identifier. - -function isIdentifierChar(code, astral) { - if (code < 48) return code === 36; - if (code < 58) return true; - if (code < 65) return false; - if (code < 91) return true; - if (code < 97) return code === 95; - if (code < 123) return true; - if (code <= 0xffff) return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)); - if (astral === false) return false; - return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes); -} - -},{}],3:[function(_dereq_,module,exports){ -// Acorn is a tiny, fast JavaScript parser written in JavaScript. -// -// Acorn was written by Marijn Haverbeke, Ingvar Stepanyan, and -// various contributors and released under an MIT license. -// -// Git repositories for Acorn are available at -// -// http://marijnhaverbeke.nl/git/acorn -// https://github.com/ternjs/acorn.git -// -// Please use the [github bug tracker][ghbt] to report issues. -// -// [ghbt]: https://github.com/ternjs/acorn/issues -// -// This file defines the main parser interface. The library also comes -// with a [error-tolerant parser][dammit] and an -// [abstract syntax tree walker][walk], defined in other files. -// -// [dammit]: acorn_loose.js -// [walk]: util/walk.js - -"use strict"; - -exports.__esModule = true; -exports.parse = parse; -exports.parseExpressionAt = parseExpressionAt; -exports.tokenizer = tokenizer; - -var _state = _dereq_("./state"); - -_dereq_("./parseutil"); - -_dereq_("./statement"); - -_dereq_("./lval"); - -_dereq_("./expression"); - -_dereq_("./location"); - -exports.Parser = _state.Parser; -exports.plugins = _state.plugins; - -var _options = _dereq_("./options"); - -exports.defaultOptions = _options.defaultOptions; - -var _locutil = _dereq_("./locutil"); - -exports.Position = _locutil.Position; -exports.SourceLocation = _locutil.SourceLocation; -exports.getLineInfo = _locutil.getLineInfo; - -var _node = _dereq_("./node"); - -exports.Node = _node.Node; - -var _tokentype = _dereq_("./tokentype"); - -exports.TokenType = _tokentype.TokenType; -exports.tokTypes = _tokentype.types; - -var _tokencontext = _dereq_("./tokencontext"); - -exports.TokContext = _tokencontext.TokContext; -exports.tokContexts = _tokencontext.types; - -var _identifier = _dereq_("./identifier"); - -exports.isIdentifierChar = _identifier.isIdentifierChar; -exports.isIdentifierStart = _identifier.isIdentifierStart; - -var _tokenize = _dereq_("./tokenize"); - -exports.Token = _tokenize.Token; - -var _whitespace = _dereq_("./whitespace"); - -exports.isNewLine = _whitespace.isNewLine; -exports.lineBreak = _whitespace.lineBreak; -exports.lineBreakG = _whitespace.lineBreakG; -var version = "2.7.0"; - -exports.version = version; -// The main exported interface (under `self.acorn` when in the -// browser) is a `parse` function that takes a code string and -// returns an abstract syntax tree as specified by [Mozilla parser -// API][api]. -// -// [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API - -function parse(input, options) { - return new _state.Parser(options, input).parse(); -} - -// This function tries to parse a single expression at a given -// offset in a string. Useful for parsing mixed-language formats -// that embed JavaScript expressions. - -function parseExpressionAt(input, pos, options) { - var p = new _state.Parser(options, input, pos); - p.nextToken(); - return p.parseExpression(); -} - -// Acorn is organized as a tokenizer and a recursive-descent parser. -// The `tokenizer` export provides an interface to the tokenizer. - -function tokenizer(input, options) { - return new _state.Parser(options, input); -} - -},{"./expression":1,"./identifier":2,"./location":4,"./locutil":5,"./lval":6,"./node":7,"./options":8,"./parseutil":9,"./state":10,"./statement":11,"./tokencontext":12,"./tokenize":13,"./tokentype":14,"./whitespace":16}],4:[function(_dereq_,module,exports){ -"use strict"; - -var _state = _dereq_("./state"); - -var _locutil = _dereq_("./locutil"); - -var pp = _state.Parser.prototype; - -// This function is used to raise exceptions on parse errors. It -// takes an offset integer (into the current `input`) to indicate -// the location of the error, attaches the position to the end -// of the error message, and then raises a `SyntaxError` with that -// message. - -pp.raise = function (pos, message) { - var loc = _locutil.getLineInfo(this.input, pos); - message += " (" + loc.line + ":" + loc.column + ")"; - var err = new SyntaxError(message); - err.pos = pos;err.loc = loc;err.raisedAt = this.pos; - throw err; -}; - -pp.curPosition = function () { - if (this.options.locations) { - return new _locutil.Position(this.curLine, this.pos - this.lineStart); - } -}; - -},{"./locutil":5,"./state":10}],5:[function(_dereq_,module,exports){ -"use strict"; - -exports.__esModule = true; -exports.getLineInfo = getLineInfo; - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var _whitespace = _dereq_("./whitespace"); - -// These are used when `options.locations` is on, for the -// `startLoc` and `endLoc` properties. - -var Position = (function () { - function Position(line, col) { - _classCallCheck(this, Position); - - this.line = line; - this.column = col; - } - - Position.prototype.offset = function offset(n) { - return new Position(this.line, this.column + n); - }; - - return Position; -})(); - -exports.Position = Position; - -var SourceLocation = function SourceLocation(p, start, end) { - _classCallCheck(this, SourceLocation); - - this.start = start; - this.end = end; - if (p.sourceFile !== null) this.source = p.sourceFile; -} - -// The `getLineInfo` function is mostly useful when the -// `locations` option is off (for performance reasons) and you -// want to find the line/column position for a given character -// offset. `input` should be the code string that the offset refers -// into. - -; - -exports.SourceLocation = SourceLocation; - -function getLineInfo(input, offset) { - for (var line = 1, cur = 0;;) { - _whitespace.lineBreakG.lastIndex = cur; - var match = _whitespace.lineBreakG.exec(input); - if (match && match.index < offset) { - ++line; - cur = match.index + match[0].length; - } else { - return new Position(line, offset - cur); - } - } -} - -},{"./whitespace":16}],6:[function(_dereq_,module,exports){ -"use strict"; - -var _tokentype = _dereq_("./tokentype"); - -var _state = _dereq_("./state"); - -var _util = _dereq_("./util"); - -var pp = _state.Parser.prototype; - -// Convert existing expression atom to assignable pattern -// if possible. - -pp.toAssignable = function (node, isBinding) { - if (this.options.ecmaVersion >= 6 && node) { - switch (node.type) { - case "Identifier": - case "ObjectPattern": - case "ArrayPattern": - break; - - case "ObjectExpression": - node.type = "ObjectPattern"; - for (var i = 0; i < node.properties.length; i++) { - var prop = node.properties[i]; - if (prop.kind !== "init") this.raise(prop.key.start, "Object pattern can't contain getter or setter"); - this.toAssignable(prop.value, isBinding); - } - break; - - case "ArrayExpression": - node.type = "ArrayPattern"; - this.toAssignableList(node.elements, isBinding); - break; - - case "AssignmentExpression": - if (node.operator === "=") { - node.type = "AssignmentPattern"; - delete node.operator; - // falls through to AssignmentPattern - } else { - this.raise(node.left.end, "Only '=' operator can be used for specifying default value."); - break; - } - - case "AssignmentPattern": - if (node.right.type === "YieldExpression") this.raise(node.right.start, "Yield expression cannot be a default value"); - break; - - case "ParenthesizedExpression": - node.expression = this.toAssignable(node.expression, isBinding); - break; - - case "MemberExpression": - if (!isBinding) break; - - default: - this.raise(node.start, "Assigning to rvalue"); - } - } - return node; -}; - -// Convert list of expression atoms to binding list. - -pp.toAssignableList = function (exprList, isBinding) { - var end = exprList.length; - if (end) { - var last = exprList[end - 1]; - if (last && last.type == "RestElement") { - --end; - } else if (last && last.type == "SpreadElement") { - last.type = "RestElement"; - var arg = last.argument; - this.toAssignable(arg, isBinding); - if (arg.type !== "Identifier" && arg.type !== "MemberExpression" && arg.type !== "ArrayPattern") this.unexpected(arg.start); - --end; - } - - if (isBinding && last.type === "RestElement" && last.argument.type !== "Identifier") this.unexpected(last.argument.start); - } - for (var i = 0; i < end; i++) { - var elt = exprList[i]; - if (elt) this.toAssignable(elt, isBinding); - } - return exprList; -}; - -// Parses spread element. - -pp.parseSpread = function (refDestructuringErrors) { - var node = this.startNode(); - this.next(); - node.argument = this.parseMaybeAssign(refDestructuringErrors); - return this.finishNode(node, "SpreadElement"); -}; - -pp.parseRest = function (allowNonIdent) { - var node = this.startNode(); - this.next(); - - // RestElement inside of a function parameter must be an identifier - if (allowNonIdent) node.argument = this.type === _tokentype.types.name ? this.parseIdent() : this.unexpected();else node.argument = this.type === _tokentype.types.name || this.type === _tokentype.types.bracketL ? this.parseBindingAtom() : this.unexpected(); - - return this.finishNode(node, "RestElement"); -}; - -// Parses lvalue (assignable) atom. - -pp.parseBindingAtom = function () { - if (this.options.ecmaVersion < 6) return this.parseIdent(); - switch (this.type) { - case _tokentype.types.name: - return this.parseIdent(); - - case _tokentype.types.bracketL: - var node = this.startNode(); - this.next(); - node.elements = this.parseBindingList(_tokentype.types.bracketR, true, true); - return this.finishNode(node, "ArrayPattern"); - - case _tokentype.types.braceL: - return this.parseObj(true); - - default: - this.unexpected(); - } -}; - -pp.parseBindingList = function (close, allowEmpty, allowTrailingComma, allowNonIdent) { - var elts = [], - first = true; - while (!this.eat(close)) { - if (first) first = false;else this.expect(_tokentype.types.comma); - if (allowEmpty && this.type === _tokentype.types.comma) { - elts.push(null); - } else if (allowTrailingComma && this.afterTrailingComma(close)) { - break; - } else if (this.type === _tokentype.types.ellipsis) { - var rest = this.parseRest(allowNonIdent); - this.parseBindingListItem(rest); - elts.push(rest); - this.expect(close); - break; - } else { - var elem = this.parseMaybeDefault(this.start, this.startLoc); - this.parseBindingListItem(elem); - elts.push(elem); - } - } - return elts; -}; - -pp.parseBindingListItem = function (param) { - return param; -}; - -// Parses assignment pattern around given atom if possible. - -pp.parseMaybeDefault = function (startPos, startLoc, left) { - left = left || this.parseBindingAtom(); - if (this.options.ecmaVersion < 6 || !this.eat(_tokentype.types.eq)) return left; - var node = this.startNodeAt(startPos, startLoc); - node.left = left; - node.right = this.parseMaybeAssign(); - return this.finishNode(node, "AssignmentPattern"); -}; - -// Verify that a node is an lval — something that can be assigned -// to. - -pp.checkLVal = function (expr, isBinding, checkClashes) { - switch (expr.type) { - case "Identifier": - if (this.strict && this.reservedWordsStrictBind.test(expr.name)) this.raise(expr.start, (isBinding ? "Binding " : "Assigning to ") + expr.name + " in strict mode"); - if (checkClashes) { - if (_util.has(checkClashes, expr.name)) this.raise(expr.start, "Argument name clash"); - checkClashes[expr.name] = true; - } - break; - - case "MemberExpression": - if (isBinding) this.raise(expr.start, (isBinding ? "Binding" : "Assigning to") + " member expression"); - break; - - case "ObjectPattern": - for (var i = 0; i < expr.properties.length; i++) { - this.checkLVal(expr.properties[i].value, isBinding, checkClashes); - }break; - - case "ArrayPattern": - for (var i = 0; i < expr.elements.length; i++) { - var elem = expr.elements[i]; - if (elem) this.checkLVal(elem, isBinding, checkClashes); - } - break; - - case "AssignmentPattern": - this.checkLVal(expr.left, isBinding, checkClashes); - break; - - case "RestElement": - this.checkLVal(expr.argument, isBinding, checkClashes); - break; - - case "ParenthesizedExpression": - this.checkLVal(expr.expression, isBinding, checkClashes); - break; - - default: - this.raise(expr.start, (isBinding ? "Binding" : "Assigning to") + " rvalue"); - } -}; - -},{"./state":10,"./tokentype":14,"./util":15}],7:[function(_dereq_,module,exports){ -"use strict"; - -exports.__esModule = true; - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var _state = _dereq_("./state"); - -var _locutil = _dereq_("./locutil"); - -var Node = function Node(parser, pos, loc) { - _classCallCheck(this, Node); - - this.type = ""; - this.start = pos; - this.end = 0; - if (parser.options.locations) this.loc = new _locutil.SourceLocation(parser, loc); - if (parser.options.directSourceFile) this.sourceFile = parser.options.directSourceFile; - if (parser.options.ranges) this.range = [pos, 0]; -} - -// Start an AST node, attaching a start offset. - -; - -exports.Node = Node; -var pp = _state.Parser.prototype; - -pp.startNode = function () { - return new Node(this, this.start, this.startLoc); -}; - -pp.startNodeAt = function (pos, loc) { - return new Node(this, pos, loc); -}; - -// Finish an AST node, adding `type` and `end` properties. - -function finishNodeAt(node, type, pos, loc) { - node.type = type; - node.end = pos; - if (this.options.locations) node.loc.end = loc; - if (this.options.ranges) node.range[1] = pos; - return node; -} - -pp.finishNode = function (node, type) { - return finishNodeAt.call(this, node, type, this.lastTokEnd, this.lastTokEndLoc); -}; - -// Finish node at given position - -pp.finishNodeAt = function (node, type, pos, loc) { - return finishNodeAt.call(this, node, type, pos, loc); -}; - -},{"./locutil":5,"./state":10}],8:[function(_dereq_,module,exports){ -"use strict"; - -exports.__esModule = true; -exports.getOptions = getOptions; - -var _util = _dereq_("./util"); - -var _locutil = _dereq_("./locutil"); - -// A second optional argument can be given to further configure -// the parser process. These options are recognized: - -var defaultOptions = { - // `ecmaVersion` indicates the ECMAScript version to parse. Must - // be either 3, or 5, or 6. This influences support for strict - // mode, the set of reserved words, support for getters and - // setters and other features. - ecmaVersion: 5, - // Source type ("script" or "module") for different semantics - sourceType: "script", - // `onInsertedSemicolon` can be a callback that will be called - // when a semicolon is automatically inserted. It will be passed - // th position of the comma as an offset, and if `locations` is - // enabled, it is given the location as a `{line, column}` object - // as second argument. - onInsertedSemicolon: null, - // `onTrailingComma` is similar to `onInsertedSemicolon`, but for - // trailing commas. - onTrailingComma: null, - // By default, reserved words are only enforced if ecmaVersion >= 5. - // Set `allowReserved` to a boolean value to explicitly turn this on - // an off. When this option has the value "never", reserved words - // and keywords can also not be used as property names. - allowReserved: null, - // When enabled, a return at the top level is not considered an - // error. - allowReturnOutsideFunction: false, - // When enabled, import/export statements are not constrained to - // appearing at the top of the program. - allowImportExportEverywhere: false, - // When enabled, hashbang directive in the beginning of file - // is allowed and treated as a line comment. - allowHashBang: false, - // When `locations` is on, `loc` properties holding objects with - // `start` and `end` properties in `{line, column}` form (with - // line being 1-based and column 0-based) will be attached to the - // nodes. - locations: false, - // A function can be passed as `onToken` option, which will - // cause Acorn to call that function with object in the same - // format as tokens returned from `tokenizer().getToken()`. Note - // that you are not allowed to call the parser from the - // callback—that will corrupt its internal state. - onToken: null, - // A function can be passed as `onComment` option, which will - // cause Acorn to call that function with `(block, text, start, - // end)` parameters whenever a comment is skipped. `block` is a - // boolean indicating whether this is a block (`/* */`) comment, - // `text` is the content of the comment, and `start` and `end` are - // character offsets that denote the start and end of the comment. - // When the `locations` option is on, two more parameters are - // passed, the full `{line, column}` locations of the start and - // end of the comments. Note that you are not allowed to call the - // parser from the callback—that will corrupt its internal state. - onComment: null, - // Nodes have their start and end characters offsets recorded in - // `start` and `end` properties (directly on the node, rather than - // the `loc` object, which holds line/column data. To also add a - // [semi-standardized][range] `range` property holding a `[start, - // end]` array with the same numbers, set the `ranges` option to - // `true`. - // - // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678 - ranges: false, - // It is possible to parse multiple files into a single AST by - // passing the tree produced by parsing the first file as - // `program` option in subsequent parses. This will add the - // toplevel forms of the parsed file to the `Program` (top) node - // of an existing parse tree. - program: null, - // When `locations` is on, you can pass this to record the source - // file in every node's `loc` object. - sourceFile: null, - // This value, if given, is stored in every node, whether - // `locations` is on or off. - directSourceFile: null, - // When enabled, parenthesized expressions are represented by - // (non-standard) ParenthesizedExpression nodes - preserveParens: false, - plugins: {} -}; - -exports.defaultOptions = defaultOptions; -// Interpret and default an options object - -function getOptions(opts) { - var options = {}; - for (var opt in defaultOptions) { - options[opt] = opts && _util.has(opts, opt) ? opts[opt] : defaultOptions[opt]; - }if (options.allowReserved == null) options.allowReserved = options.ecmaVersion < 5; - - if (_util.isArray(options.onToken)) { - (function () { - var tokens = options.onToken; - options.onToken = function (token) { - return tokens.push(token); - }; - })(); - } - if (_util.isArray(options.onComment)) options.onComment = pushComment(options, options.onComment); - - return options; -} - -function pushComment(options, array) { - return function (block, text, start, end, startLoc, endLoc) { - var comment = { - type: block ? 'Block' : 'Line', - value: text, - start: start, - end: end - }; - if (options.locations) comment.loc = new _locutil.SourceLocation(this, startLoc, endLoc); - if (options.ranges) comment.range = [start, end]; - array.push(comment); - }; -} - -},{"./locutil":5,"./util":15}],9:[function(_dereq_,module,exports){ -"use strict"; - -var _tokentype = _dereq_("./tokentype"); - -var _state = _dereq_("./state"); - -var _whitespace = _dereq_("./whitespace"); - -var pp = _state.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"; -}; - -// Predicate that tests whether the next token is of the given -// type, and if yes, consumes it as a side effect. - -pp.eat = function (type) { - if (this.type === type) { - this.next(); - return true; - } else { - return false; - } -}; - -// Tests whether parsed token is a contextual keyword. - -pp.isContextual = function (name) { - return this.type === _tokentype.types.name && this.value === name; -}; - -// Consumes contextual keyword if possible. - -pp.eatContextual = function (name) { - return this.value === name && this.eat(_tokentype.types.name); -}; - -// Asserts that following token is given contextual keyword. - -pp.expectContextual = function (name) { - if (!this.eatContextual(name)) this.unexpected(); -}; - -// Test whether a semicolon can be inserted at the current position. - -pp.canInsertSemicolon = function () { - return this.type === _tokentype.types.eof || this.type === _tokentype.types.braceR || _whitespace.lineBreak.test(this.input.slice(this.lastTokEnd, this.start)); -}; - -pp.insertSemicolon = function () { - if (this.canInsertSemicolon()) { - if (this.options.onInsertedSemicolon) this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc); - return true; - } -}; - -// Consume a semicolon, or, failing that, see if we are allowed to -// pretend that there is a semicolon at this position. - -pp.semicolon = function () { - if (!this.eat(_tokentype.types.semi) && !this.insertSemicolon()) this.unexpected(); -}; - -pp.afterTrailingComma = function (tokType) { - if (this.type == tokType) { - if (this.options.onTrailingComma) this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc); - this.next(); - return true; - } -}; - -// Expect a token of a given type. If found, consume it, otherwise, -// raise an unexpected token error. - -pp.expect = function (type) { - this.eat(type) || this.unexpected(); -}; - -// Raise an unexpected token error. - -pp.unexpected = function (pos) { - this.raise(pos != null ? pos : this.start, "Unexpected token"); -}; - -pp.checkPatternErrors = function (refDestructuringErrors, andThrow) { - var pos = refDestructuringErrors && refDestructuringErrors.trailingComma; - if (!andThrow) return !!pos; - if (pos) this.raise(pos, "Trailing comma is not permitted in destructuring patterns"); -}; - -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"); -}; - -},{"./state":10,"./tokentype":14,"./whitespace":16}],10:[function(_dereq_,module,exports){ -"use strict"; - -exports.__esModule = true; - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var _identifier = _dereq_("./identifier"); - -var _tokentype = _dereq_("./tokentype"); - -var _whitespace = _dereq_("./whitespace"); - -var _options = _dereq_("./options"); - -// Registered plugins -var plugins = {}; - -exports.plugins = plugins; -function keywordRegexp(words) { - return new RegExp("^(" + words.replace(/ /g, "|") + ")$"); -} - -var Parser = (function () { - function Parser(options, input, startPos) { - _classCallCheck(this, Parser); - - this.options = options = _options.getOptions(options); - this.sourceFile = options.sourceFile; - this.keywords = keywordRegexp(_identifier.keywords[options.ecmaVersion >= 6 ? 6 : 5]); - var reserved = options.allowReserved ? "" : _identifier.reservedWords[options.ecmaVersion] + (options.sourceType == "module" ? " await" : ""); - this.reservedWords = keywordRegexp(reserved); - var reservedStrict = (reserved ? reserved + " " : "") + _identifier.reservedWords.strict; - this.reservedWordsStrict = keywordRegexp(reservedStrict); - this.reservedWordsStrictBind = keywordRegexp(reservedStrict + " " + _identifier.reservedWords.strictBind); - this.input = String(input); - - // Used to signal to callers of `readWord1` whether the word - // contained any escape sequences. This is needed because words with - // escape sequences must not be interpreted as keywords. - this.containsEsc = false; - - // Load plugins - this.loadPlugins(options.plugins); - - // Set up token state - - // The current position of the tokenizer in the input. - if (startPos) { - this.pos = startPos; - this.lineStart = Math.max(0, this.input.lastIndexOf("\n", startPos)); - this.curLine = this.input.slice(0, this.lineStart).split(_whitespace.lineBreak).length; - } else { - this.pos = this.lineStart = 0; - this.curLine = 1; - } - - // Properties of the current token: - // Its type - this.type = _tokentype.types.eof; - // For tokens that include more information than their type, the value - this.value = null; - // Its start and end offset - this.start = this.end = this.pos; - // And, if locations are used, the {line, column} object - // corresponding to those offsets - this.startLoc = this.endLoc = this.curPosition(); - - // Position information for the previous token - this.lastTokEndLoc = this.lastTokStartLoc = null; - this.lastTokStart = this.lastTokEnd = this.pos; - - // The context stack is used to superficially track syntactic - // context to predict whether a regular expression is allowed in a - // given position. - this.context = this.initialContext(); - this.exprAllowed = true; - - // Figure out if it's a module code. - this.strict = this.inModule = options.sourceType === "module"; - - // Used to signify the start of a potential arrow function - this.potentialArrowAt = -1; - - // Flags to track whether we are in a function, a generator. - this.inFunction = this.inGenerator = false; - // Labels in scope. - this.labels = []; - - // If enabled, skip leading hashbang line. - if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === '#!') this.skipLineComment(2); - } - - // DEPRECATED Kept for backwards compatibility until 3.0 in case a plugin uses them - - Parser.prototype.isKeyword = function isKeyword(word) { - return this.keywords.test(word); - }; - - Parser.prototype.isReservedWord = function isReservedWord(word) { - return this.reservedWords.test(word); - }; - - Parser.prototype.extend = function extend(name, f) { - this[name] = f(this[name]); - }; - - Parser.prototype.loadPlugins = function loadPlugins(pluginConfigs) { - for (var _name in pluginConfigs) { - var plugin = plugins[_name]; - if (!plugin) throw new Error("Plugin '" + _name + "' not found"); - plugin(this, pluginConfigs[_name]); - } - }; - - Parser.prototype.parse = function parse() { - var node = this.options.program || this.startNode(); - this.nextToken(); - return this.parseTopLevel(node); - }; - - return Parser; -})(); - -exports.Parser = Parser; - -},{"./identifier":2,"./options":8,"./tokentype":14,"./whitespace":16}],11:[function(_dereq_,module,exports){ -"use strict"; - -var _tokentype = _dereq_("./tokentype"); - -var _state = _dereq_("./state"); - -var _whitespace = _dereq_("./whitespace"); - -var pp = _state.Parser.prototype; - -// ### Statement parsing - -// Parse a program. Initializes the parser, reads any number of -// statements, and wraps them in a Program node. Optionally takes a -// `program` argument. If present, the statements will be appended -// to its body instead of creating a new node. - -pp.parseTopLevel = function (node) { - var first = true; - if (!node.body) node.body = []; - while (this.type !== _tokentype.types.eof) { - var stmt = this.parseStatement(true, true); - node.body.push(stmt); - if (first) { - if (this.isUseStrict(stmt)) this.setStrict(true); - first = false; - } - } - this.next(); - if (this.options.ecmaVersion >= 6) { - node.sourceType = this.options.sourceType; - } - return this.finishNode(node, "Program"); -}; - -var loopLabel = { kind: "loop" }, - switchLabel = { kind: "switch" }; - -// Parse a single statement. -// -// If expecting a statement and finding a slash operator, parse a -// regular expression literal. This is to handle cases like -// `if (foo) /blah/.exec(foo)`, where looking at the previous token -// does not help. - -pp.parseStatement = function (declaration, topLevel) { - var starttype = this.type, - node = this.startNode(); - - // Most types of statements are recognized by the keyword they - // start with. Many are trivial to parse, some require a bit of - // complexity. - - switch (starttype) { - case _tokentype.types._break:case _tokentype.types._continue: - return this.parseBreakContinueStatement(node, starttype.keyword); - case _tokentype.types._debugger: - return this.parseDebuggerStatement(node); - case _tokentype.types._do: - return this.parseDoStatement(node); - case _tokentype.types._for: - return this.parseForStatement(node); - case _tokentype.types._function: - if (!declaration && this.options.ecmaVersion >= 6) this.unexpected(); - return this.parseFunctionStatement(node); - case _tokentype.types._class: - if (!declaration) this.unexpected(); - return this.parseClass(node, true); - case _tokentype.types._if: - return this.parseIfStatement(node); - case _tokentype.types._return: - return this.parseReturnStatement(node); - case _tokentype.types._switch: - return this.parseSwitchStatement(node); - case _tokentype.types._throw: - return this.parseThrowStatement(node); - case _tokentype.types._try: - return this.parseTryStatement(node); - case _tokentype.types._let:case _tokentype.types._const: - if (!declaration) this.unexpected(); // NOTE: falls through to _var - case _tokentype.types._var: - return this.parseVarStatement(node, starttype); - case _tokentype.types._while: - return this.parseWhileStatement(node); - case _tokentype.types._with: - return this.parseWithStatement(node); - case _tokentype.types.braceL: - return this.parseBlock(); - case _tokentype.types.semi: - return this.parseEmptyStatement(node); - case _tokentype.types._export: - case _tokentype.types._import: - if (!this.options.allowImportExportEverywhere) { - if (!topLevel) this.raise(this.start, "'import' and 'export' may only appear at the top level"); - if (!this.inModule) this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'"); - } - return starttype === _tokentype.types._import ? this.parseImport(node) : this.parseExport(node); - - // If the statement does not start with a statement keyword or a - // brace, it's an ExpressionStatement or LabeledStatement. We - // simply start parsing an expression, and afterwards, if the - // next token is a colon and the expression was a simple - // Identifier node, we switch to interpreting it as a label. - default: - var maybeName = this.value, - expr = this.parseExpression(); - if (starttype === _tokentype.types.name && expr.type === "Identifier" && this.eat(_tokentype.types.colon)) return this.parseLabeledStatement(node, maybeName, expr);else return this.parseExpressionStatement(node, expr); - } -}; - -pp.parseBreakContinueStatement = function (node, keyword) { - var isBreak = keyword == "break"; - this.next(); - if (this.eat(_tokentype.types.semi) || this.insertSemicolon()) node.label = null;else if (this.type !== _tokentype.types.name) this.unexpected();else { - node.label = this.parseIdent(); - this.semicolon(); - } - - // Verify that there is an actual destination to break or - // continue to. - for (var i = 0; i < this.labels.length; ++i) { - var lab = this.labels[i]; - if (node.label == null || lab.name === node.label.name) { - if (lab.kind != null && (isBreak || lab.kind === "loop")) break; - if (node.label && isBreak) break; - } - } - if (i === this.labels.length) this.raise(node.start, "Unsyntactic " + keyword); - return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement"); -}; - -pp.parseDebuggerStatement = function (node) { - this.next(); - this.semicolon(); - return this.finishNode(node, "DebuggerStatement"); -}; - -pp.parseDoStatement = function (node) { - this.next(); - this.labels.push(loopLabel); - node.body = this.parseStatement(false); - this.labels.pop(); - this.expect(_tokentype.types._while); - node.test = this.parseParenExpression(); - if (this.options.ecmaVersion >= 6) this.eat(_tokentype.types.semi);else this.semicolon(); - return this.finishNode(node, "DoWhileStatement"); -}; - -// Disambiguating between a `for` and a `for`/`in` or `for`/`of` -// loop is non-trivial. Basically, we have to parse the init `var` -// statement or expression, disallowing the `in` operator (see -// the second parameter to `parseExpression`), and then check -// whether the next token is `in` or `of`. When there is no init -// part (semicolon immediately after the opening parenthesis), it -// is a regular `for` loop. - -pp.parseForStatement = function (node) { - this.next(); - this.labels.push(loopLabel); - this.expect(_tokentype.types.parenL); - if (this.type === _tokentype.types.semi) return this.parseFor(node, null); - if (this.type === _tokentype.types._var || this.type === _tokentype.types._let || this.type === _tokentype.types._const) { - var _init = this.startNode(), - varKind = this.type; - this.next(); - this.parseVar(_init, true, varKind); - this.finishNode(_init, "VariableDeclaration"); - if ((this.type === _tokentype.types._in || this.options.ecmaVersion >= 6 && this.isContextual("of")) && _init.declarations.length === 1 && !(varKind !== _tokentype.types._var && _init.declarations[0].init)) return this.parseForIn(node, _init); - return this.parseFor(node, _init); - } - var refDestructuringErrors = { shorthandAssign: 0, trailingComma: 0 }; - var init = this.parseExpression(true, refDestructuringErrors); - if (this.type === _tokentype.types._in || this.options.ecmaVersion >= 6 && this.isContextual("of")) { - this.checkPatternErrors(refDestructuringErrors, true); - this.toAssignable(init); - this.checkLVal(init); - return this.parseForIn(node, init); - } else { - this.checkExpressionErrors(refDestructuringErrors, true); - } - return this.parseFor(node, init); -}; - -pp.parseFunctionStatement = function (node) { - this.next(); - return this.parseFunction(node, true); -}; - -pp.parseIfStatement = function (node) { - this.next(); - node.test = this.parseParenExpression(); - node.consequent = this.parseStatement(false); - node.alternate = this.eat(_tokentype.types._else) ? this.parseStatement(false) : null; - return this.finishNode(node, "IfStatement"); -}; - -pp.parseReturnStatement = function (node) { - if (!this.inFunction && !this.options.allowReturnOutsideFunction) this.raise(this.start, "'return' outside of function"); - this.next(); - - // In `return` (and `break`/`continue`), the keywords with - // optional arguments, we eagerly look for a semicolon or the - // possibility to insert one. - - if (this.eat(_tokentype.types.semi) || this.insertSemicolon()) node.argument = null;else { - node.argument = this.parseExpression();this.semicolon(); - } - return this.finishNode(node, "ReturnStatement"); -}; - -pp.parseSwitchStatement = function (node) { - this.next(); - node.discriminant = this.parseParenExpression(); - node.cases = []; - this.expect(_tokentype.types.braceL); - this.labels.push(switchLabel); - - // 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 != _tokentype.types.braceR;) { - if (this.type === _tokentype.types._case || this.type === _tokentype.types._default) { - var isCase = this.type === _tokentype.types._case; - if (cur) this.finishNode(cur, "SwitchCase"); - node.cases.push(cur = this.startNode()); - cur.consequent = []; - this.next(); - if (isCase) { - cur.test = this.parseExpression(); - } else { - if (sawDefault) this.raise(this.lastTokStart, "Multiple default clauses"); - sawDefault = true; - cur.test = null; - } - this.expect(_tokentype.types.colon); - } else { - if (!cur) this.unexpected(); - cur.consequent.push(this.parseStatement(true)); - } - } - if (cur) this.finishNode(cur, "SwitchCase"); - this.next(); // Closing brace - this.labels.pop(); - return this.finishNode(node, "SwitchStatement"); -}; - -pp.parseThrowStatement = function (node) { - this.next(); - if (_whitespace.lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) this.raise(this.lastTokEnd, "Illegal newline after throw"); - node.argument = this.parseExpression(); - this.semicolon(); - return this.finishNode(node, "ThrowStatement"); -}; - -// Reused empty array added for node fields that are always empty. - -var empty = []; - -pp.parseTryStatement = function (node) { - this.next(); - node.block = this.parseBlock(); - node.handler = null; - if (this.type === _tokentype.types._catch) { - var clause = this.startNode(); - this.next(); - this.expect(_tokentype.types.parenL); - clause.param = this.parseBindingAtom(); - this.checkLVal(clause.param, true); - this.expect(_tokentype.types.parenR); - clause.body = this.parseBlock(); - node.handler = this.finishNode(clause, "CatchClause"); - } - node.finalizer = this.eat(_tokentype.types._finally) ? this.parseBlock() : null; - if (!node.handler && !node.finalizer) this.raise(node.start, "Missing catch or finally clause"); - return this.finishNode(node, "TryStatement"); -}; - -pp.parseVarStatement = function (node, kind) { - this.next(); - this.parseVar(node, false, kind); - this.semicolon(); - return this.finishNode(node, "VariableDeclaration"); -}; - -pp.parseWhileStatement = function (node) { - this.next(); - node.test = this.parseParenExpression(); - this.labels.push(loopLabel); - node.body = this.parseStatement(false); - this.labels.pop(); - return this.finishNode(node, "WhileStatement"); -}; - -pp.parseWithStatement = function (node) { - if (this.strict) this.raise(this.start, "'with' in strict mode"); - this.next(); - node.object = this.parseParenExpression(); - node.body = this.parseStatement(false); - return this.finishNode(node, "WithStatement"); -}; - -pp.parseEmptyStatement = function (node) { - this.next(); - return this.finishNode(node, "EmptyStatement"); -}; - -pp.parseLabeledStatement = function (node, maybeName, expr) { - for (var i = 0; i < this.labels.length; ++i) { - if (this.labels[i].name === maybeName) this.raise(expr.start, "Label '" + maybeName + "' is already declared"); - }var kind = this.type.isLoop ? "loop" : this.type === _tokentype.types._switch ? "switch" : null; - for (var i = this.labels.length - 1; i >= 0; i--) { - var label = this.labels[i]; - if (label.statementStart == node.start) { - label.statementStart = this.start; - label.kind = kind; - } else break; - } - this.labels.push({ name: maybeName, kind: kind, statementStart: this.start }); - node.body = this.parseStatement(true); - this.labels.pop(); - node.label = expr; - return this.finishNode(node, "LabeledStatement"); -}; - -pp.parseExpressionStatement = function (node, expr) { - node.expression = expr; - this.semicolon(); - return this.finishNode(node, "ExpressionStatement"); -}; - -// Parse a semicolon-enclosed block of statements, handling `"use -// strict"` declarations when `allowStrict` is true (used for -// function bodies). - -pp.parseBlock = function (allowStrict) { - var node = this.startNode(), - first = true, - oldStrict = undefined; - node.body = []; - this.expect(_tokentype.types.braceL); - while (!this.eat(_tokentype.types.braceR)) { - var 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); - return this.finishNode(node, "BlockStatement"); -}; - -// Parse a regular `for` loop. The disambiguation code in -// `parseStatement` will already have parsed the init statement or -// expression. - -pp.parseFor = function (node, init) { - node.init = init; - this.expect(_tokentype.types.semi); - node.test = this.type === _tokentype.types.semi ? null : this.parseExpression(); - this.expect(_tokentype.types.semi); - node.update = this.type === _tokentype.types.parenR ? null : this.parseExpression(); - this.expect(_tokentype.types.parenR); - node.body = this.parseStatement(false); - this.labels.pop(); - return this.finishNode(node, "ForStatement"); -}; - -// Parse a `for`/`in` and `for`/`of` loop, which are almost -// same from parser's perspective. - -pp.parseForIn = function (node, init) { - var type = this.type === _tokentype.types._in ? "ForInStatement" : "ForOfStatement"; - this.next(); - node.left = init; - node.right = this.parseExpression(); - this.expect(_tokentype.types.parenR); - node.body = this.parseStatement(false); - this.labels.pop(); - return this.finishNode(node, type); -}; - -// Parse a list of variable declarations. - -pp.parseVar = function (node, isFor, kind) { - node.declarations = []; - node.kind = kind.keyword; - for (;;) { - var decl = this.startNode(); - this.parseVarId(decl); - if (this.eat(_tokentype.types.eq)) { - decl.init = this.parseMaybeAssign(isFor); - } else if (kind === _tokentype.types._const && !(this.type === _tokentype.types._in || this.options.ecmaVersion >= 6 && this.isContextual("of"))) { - this.unexpected(); - } else if (decl.id.type != "Identifier" && !(isFor && (this.type === _tokentype.types._in || this.isContextual("of")))) { - this.raise(this.lastTokEnd, "Complex binding patterns require an initialization value"); - } else { - decl.init = null; - } - node.declarations.push(this.finishNode(decl, "VariableDeclarator")); - if (!this.eat(_tokentype.types.comma)) break; - } - return node; -}; - -pp.parseVarId = function (decl) { - decl.id = this.parseBindingAtom(); - this.checkLVal(decl.id, true); -}; - -// Parse a function declaration or literal (depending on the -// `isStatement` parameter). - -pp.parseFunction = function (node, isStatement, allowExpressionBody) { - this.initFunction(node); - if (this.options.ecmaVersion >= 6) node.generator = this.eat(_tokentype.types.star); - if (isStatement || this.type === _tokentype.types.name) node.id = this.parseIdent(); - this.parseFunctionParams(node); - this.parseFunctionBody(node, allowExpressionBody); - return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression"); -}; - -pp.parseFunctionParams = function (node) { - this.expect(_tokentype.types.parenL); - node.params = this.parseBindingList(_tokentype.types.parenR, false, false, true); -}; - -// Parse a class declaration or literal (depending on the -// `isStatement` parameter). - -pp.parseClass = function (node, isStatement) { - this.next(); - this.parseClassId(node, isStatement); - this.parseClassSuper(node); - var classBody = this.startNode(); - var hadConstructor = false; - classBody.body = []; - this.expect(_tokentype.types.braceL); - while (!this.eat(_tokentype.types.braceR)) { - if (this.eat(_tokentype.types.semi)) continue; - var method = this.startNode(); - var isGenerator = this.eat(_tokentype.types.star); - var isMaybeStatic = this.type === _tokentype.types.name && this.value === "static"; - this.parsePropertyName(method); - method["static"] = isMaybeStatic && this.type !== _tokentype.types.parenL; - if (method["static"]) { - if (isGenerator) this.unexpected(); - isGenerator = this.eat(_tokentype.types.star); - this.parsePropertyName(method); - } - method.kind = "method"; - var isGetSet = false; - if (!method.computed) { - var key = method.key; - - if (!isGenerator && key.type === "Identifier" && this.type !== _tokentype.types.parenL && (key.name === "get" || key.name === "set")) { - isGetSet = true; - method.kind = key.name; - key = this.parsePropertyName(method); - } - if (!method["static"] && (key.type === "Identifier" && key.name === "constructor" || key.type === "Literal" && key.value === "constructor")) { - if (hadConstructor) this.raise(key.start, "Duplicate constructor in the same class"); - if (isGetSet) this.raise(key.start, "Constructor can't have get/set modifier"); - if (isGenerator) this.raise(key.start, "Constructor can't be a generator"); - method.kind = "constructor"; - hadConstructor = true; - } - } - this.parseClassMethod(classBody, method, isGenerator); - if (isGetSet) { - var paramCount = method.kind === "get" ? 0 : 1; - if (method.value.params.length !== paramCount) { - var start = method.value.start; - if (method.kind === "get") this.raise(start, "getter should have no params");else this.raise(start, "setter should have exactly one param"); - } - if (method.kind === "set" && method.value.params[0].type === "RestElement") this.raise(method.value.params[0].start, "Setter cannot use rest params"); - } - } - node.body = this.finishNode(classBody, "ClassBody"); - return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression"); -}; - -pp.parseClassMethod = function (classBody, method, isGenerator) { - method.value = this.parseMethod(isGenerator); - classBody.body.push(this.finishNode(method, "MethodDefinition")); -}; - -pp.parseClassId = function (node, isStatement) { - node.id = this.type === _tokentype.types.name ? this.parseIdent() : isStatement ? this.unexpected() : null; -}; - -pp.parseClassSuper = function (node) { - node.superClass = this.eat(_tokentype.types._extends) ? this.parseExprSubscripts() : null; -}; - -// Parses module export declaration. - -pp.parseExport = function (node) { - this.next(); - // export * from '...' - if (this.eat(_tokentype.types.star)) { - this.expectContextual("from"); - node.source = this.type === _tokentype.types.string ? this.parseExprAtom() : this.unexpected(); - this.semicolon(); - return this.finishNode(node, "ExportAllDeclaration"); - } - if (this.eat(_tokentype.types._default)) { - // export default ... - var expr = this.parseMaybeAssign(); - var needsSemi = true; - if (expr.type == "FunctionExpression" || expr.type == "ClassExpression") { - needsSemi = false; - if (expr.id) { - expr.type = expr.type == "FunctionExpression" ? "FunctionDeclaration" : "ClassDeclaration"; - } - } - node.declaration = expr; - if (needsSemi) this.semicolon(); - return this.finishNode(node, "ExportDefaultDeclaration"); - } - // export var|const|let|function|class ... - if (this.shouldParseExportStatement()) { - node.declaration = this.parseStatement(true); - node.specifiers = []; - node.source = null; - } else { - // export { x, y as z } [from '...'] - node.declaration = null; - node.specifiers = this.parseExportSpecifiers(); - if (this.eatContextual("from")) { - node.source = this.type === _tokentype.types.string ? this.parseExprAtom() : this.unexpected(); - } else { - // check for keywords used as local names - for (var i = 0; i < node.specifiers.length; i++) { - if (this.keywords.test(node.specifiers[i].local.name) || this.reservedWords.test(node.specifiers[i].local.name)) { - this.unexpected(node.specifiers[i].local.start); - } - } - - node.source = null; - } - this.semicolon(); - } - return this.finishNode(node, "ExportNamedDeclaration"); -}; - -pp.shouldParseExportStatement = function () { - return this.type.keyword; -}; - -// Parses a comma-separated list of module exports. - -pp.parseExportSpecifiers = function () { - var nodes = [], - first = true; - // export { x, y as z } [from '...'] - this.expect(_tokentype.types.braceL); - while (!this.eat(_tokentype.types.braceR)) { - if (!first) { - this.expect(_tokentype.types.comma); - if (this.afterTrailingComma(_tokentype.types.braceR)) break; - } else first = false; - - var node = this.startNode(); - node.local = this.parseIdent(this.type === _tokentype.types._default); - node.exported = this.eatContextual("as") ? this.parseIdent(true) : node.local; - nodes.push(this.finishNode(node, "ExportSpecifier")); - } - return nodes; -}; - -// Parses import declaration. - -pp.parseImport = function (node) { - this.next(); - // import '...' - if (this.type === _tokentype.types.string) { - node.specifiers = empty; - node.source = this.parseExprAtom(); - } else { - node.specifiers = this.parseImportSpecifiers(); - this.expectContextual("from"); - node.source = this.type === _tokentype.types.string ? this.parseExprAtom() : this.unexpected(); - } - this.semicolon(); - return this.finishNode(node, "ImportDeclaration"); -}; - -// Parses a comma-separated list of module imports. - -pp.parseImportSpecifiers = function () { - var nodes = [], - first = true; - if (this.type === _tokentype.types.name) { - // import defaultObj, { x, y as z } from '...' - var node = this.startNode(); - node.local = this.parseIdent(); - this.checkLVal(node.local, true); - nodes.push(this.finishNode(node, "ImportDefaultSpecifier")); - if (!this.eat(_tokentype.types.comma)) return nodes; - } - if (this.type === _tokentype.types.star) { - var node = this.startNode(); - this.next(); - this.expectContextual("as"); - node.local = this.parseIdent(); - this.checkLVal(node.local, true); - nodes.push(this.finishNode(node, "ImportNamespaceSpecifier")); - return nodes; - } - this.expect(_tokentype.types.braceL); - while (!this.eat(_tokentype.types.braceR)) { - if (!first) { - this.expect(_tokentype.types.comma); - if (this.afterTrailingComma(_tokentype.types.braceR)) break; - } else first = false; - - var node = this.startNode(); - node.imported = this.parseIdent(true); - if (this.eatContextual("as")) { - node.local = this.parseIdent(); - } else { - node.local = node.imported; - if (this.isKeyword(node.local.name)) this.unexpected(node.local.start); - if (this.reservedWordsStrict.test(node.local.name)) this.raise(node.local.start, "The keyword '" + node.local.name + "' is reserved"); - } - this.checkLVal(node.local, true); - nodes.push(this.finishNode(node, "ImportSpecifier")); - } - return nodes; -}; - -},{"./state":10,"./tokentype":14,"./whitespace":16}],12:[function(_dereq_,module,exports){ -// The algorithm used to determine whether a regexp can appear at a -// given point in the program is loosely based on sweet.js' approach. -// See https://github.com/mozilla/sweet.js/wiki/design - -"use strict"; - -exports.__esModule = true; - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var _state = _dereq_("./state"); - -var _tokentype = _dereq_("./tokentype"); - -var _whitespace = _dereq_("./whitespace"); - -var TokContext = function TokContext(token, isExpr, preserveSpace, override) { - _classCallCheck(this, TokContext); - - this.token = token; - this.isExpr = !!isExpr; - this.preserveSpace = !!preserveSpace; - this.override = override; -}; - -exports.TokContext = TokContext; -var types = { - b_stat: new TokContext("{", false), - b_expr: new TokContext("{", true), - b_tmpl: new TokContext("${", true), - 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) -}; - -exports.types = types; -var pp = _state.Parser.prototype; - -pp.initialContext = function () { - return [types.b_stat]; -}; - -pp.braceIsBlock = function (prevType) { - if (prevType === _tokentype.types.colon) { - var _parent = this.curContext(); - if (_parent === types.b_stat || _parent === types.b_expr) return !_parent.isExpr; - } - if (prevType === _tokentype.types._return) return _whitespace.lineBreak.test(this.input.slice(this.lastTokEnd, this.start)); - if (prevType === _tokentype.types._else || prevType === _tokentype.types.semi || prevType === _tokentype.types.eof || prevType === _tokentype.types.parenR) return true; - if (prevType == _tokentype.types.braceL) return this.curContext() === types.b_stat; - return !this.exprAllowed; -}; - -pp.updateContext = function (prevType) { - var update = undefined, - type = this.type; - if (type.keyword && prevType == _tokentype.types.dot) this.exprAllowed = false;else if (update = type.updateContext) update.call(this, prevType);else this.exprAllowed = type.beforeExpr; -}; - -// Token-specific context update code - -_tokentype.types.parenR.updateContext = _tokentype.types.braceR.updateContext = function () { - if (this.context.length == 1) { - this.exprAllowed = true; - return; - } - var out = this.context.pop(); - if (out === types.b_stat && this.curContext() === types.f_expr) { - this.context.pop(); - this.exprAllowed = false; - } else if (out === types.b_tmpl) { - this.exprAllowed = true; - } else { - this.exprAllowed = !out.isExpr; - } -}; - -_tokentype.types.braceL.updateContext = function (prevType) { - this.context.push(this.braceIsBlock(prevType) ? types.b_stat : types.b_expr); - this.exprAllowed = true; -}; - -_tokentype.types.dollarBraceL.updateContext = function () { - this.context.push(types.b_tmpl); - this.exprAllowed = true; -}; - -_tokentype.types.parenL.updateContext = function (prevType) { - var statementParens = prevType === _tokentype.types._if || prevType === _tokentype.types._for || prevType === _tokentype.types._with || prevType === _tokentype.types._while; - this.context.push(statementParens ? types.p_stat : types.p_expr); - this.exprAllowed = true; -}; - -_tokentype.types.incDec.updateContext = function () { - // tokExprAllowed stays unchanged -}; - -_tokentype.types._function.updateContext = function () { - if (this.curContext() !== types.b_stat) this.context.push(types.f_expr); - this.exprAllowed = false; -}; - -_tokentype.types.backQuote.updateContext = function () { - if (this.curContext() === types.q_tmpl) this.context.pop();else this.context.push(types.q_tmpl); - this.exprAllowed = false; -}; - -},{"./state":10,"./tokentype":14,"./whitespace":16}],13:[function(_dereq_,module,exports){ -"use strict"; - -exports.__esModule = true; - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var _identifier = _dereq_("./identifier"); - -var _tokentype = _dereq_("./tokentype"); - -var _state = _dereq_("./state"); - -var _locutil = _dereq_("./locutil"); - -var _whitespace = _dereq_("./whitespace"); - -// 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. - -var Token = function Token(p) { - _classCallCheck(this, Token); - - this.type = p.type; - this.value = p.value; - this.start = p.start; - this.end = p.end; - if (p.options.locations) this.loc = new _locutil.SourceLocation(p, p.startLoc, p.endLoc); - if (p.options.ranges) this.range = [p.start, p.end]; -} - -// ## Tokenizer - -; - -exports.Token = Token; -var pp = _state.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.next = function () { - if (this.options.onToken) this.options.onToken(new Token(this)); - - this.lastTokEnd = this.end; - this.lastTokStart = this.start; - this.lastTokEndLoc = this.endLoc; - this.lastTokStartLoc = this.startLoc; - this.nextToken(); -}; - -pp.getToken = function () { - this.next(); - return new Token(this); -}; - -// If we're in an ES6 environment, make parsers iterable -if (typeof Symbol !== "undefined") pp[Symbol.iterator] = function () { - var self = this; - return { next: function next() { - var token = self.getToken(); - return { - done: token.type === _tokentype.types.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 !== _tokentype.types.num && this.type !== _tokentype.types.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]; -}; - -// Read a single token, updating the parser object's token-related -// properties. - -pp.nextToken = function () { - var curContext = this.curContext(); - if (!curContext || !curContext.preserveSpace) this.skipSpace(); - - this.start = this.pos; - if (this.options.locations) this.startLoc = this.curPosition(); - if (this.pos >= this.input.length) return this.finishToken(_tokentype.types.eof); - - if (curContext.override) return curContext.override(this);else this.readToken(this.fullCharCodeAtPos()); -}; - -pp.readToken = function (code) { - // Identifier or keyword. '\uXXXX' sequences are allowed in - // identifiers, so '\' also dispatches to that. - if (_identifier.isIdentifierStart(code, this.options.ecmaVersion >= 6) || code === 92 /* '\' */) return this.readWord(); - - return this.getTokenFromCode(code); -}; - -pp.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.skipBlockComment = function () { - var startLoc = this.options.onComment && this.curPosition(); - var start = this.pos, - end = this.input.indexOf("*/", this.pos += 2); - if (end === -1) this.raise(this.pos - 2, "Unterminated comment"); - this.pos = end + 2; - if (this.options.locations) { - _whitespace.lineBreakG.lastIndex = start; - var match = undefined; - while ((match = _whitespace.lineBreakG.exec(this.input)) && match.index < this.pos) { - ++this.curLine; - this.lineStart = match.index + match[0].length; - } - } - if (this.options.onComment) this.options.onComment(true, this.input.slice(start + 2, end), start, this.pos, startLoc, this.curPosition()); -}; - -pp.skipLineComment = function (startSkip) { - var start = this.pos; - var startLoc = this.options.onComment && this.curPosition(); - var 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); - } - if (this.options.onComment) this.options.onComment(false, this.input.slice(start + startSkip, this.pos), start, this.pos, startLoc, this.curPosition()); -}; - -// Called at the start of the parse and after every token. Skips -// whitespace and comments, and. - -pp.skipSpace = function () { - loop: while (this.pos < this.input.length) { - var 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: - ++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: - this.skipLineComment(2); - break; - default: - break loop; - } - break; - default: - if (ch > 8 && ch < 14 || ch >= 5760 && _whitespace.nonASCIIwhitespace.test(String.fromCharCode(ch))) { - ++this.pos; - } else { - break loop; - } - } - } -}; - -// Called at the end of every token. Sets `end`, `val`, and -// maintains `context` and `exprAllowed`, and skips the space after -// the token, so that the next one's `start` will point at the -// right position. - -pp.finishToken = function (type, val) { - this.end = this.pos; - if (this.options.locations) this.endLoc = this.curPosition(); - var prevType = this.type; - this.type = type; - this.value = val; - - this.updateContext(prevType); -}; - -// ### Token reading - -// This is the function that is called to fetch the next token. It -// is somewhat obscure, because it works in character codes rather -// than characters, and because operator parsing has been inlined -// into it. -// -// All in the name of speed. -// -pp.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); - if (this.options.ecmaVersion >= 6 && next === 46 && next2 === 46) { - // 46 = dot '.' - this.pos += 3; - return this.finishToken(_tokentype.types.ellipsis); - } else { - ++this.pos; - return this.finishToken(_tokentype.types.dot); - } -}; - -pp.readToken_slash = function () { - // '/' - var next = this.input.charCodeAt(this.pos + 1); - if (this.exprAllowed) { - ++this.pos;return this.readRegexp(); - } - if (next === 61) return this.finishOp(_tokentype.types.assign, 2); - return this.finishOp(_tokentype.types.slash, 1); -}; - -pp.readToken_mult_modulo = function (code) { - // '%*' - var next = this.input.charCodeAt(this.pos + 1); - if (next === 61) return this.finishOp(_tokentype.types.assign, 2); - return this.finishOp(code === 42 ? _tokentype.types.star : _tokentype.types.modulo, 1); -}; - -pp.readToken_pipe_amp = function (code) { - // '|&' - var next = this.input.charCodeAt(this.pos + 1); - if (next === code) return this.finishOp(code === 124 ? _tokentype.types.logicalOR : _tokentype.types.logicalAND, 2); - if (next === 61) return this.finishOp(_tokentype.types.assign, 2); - return this.finishOp(code === 124 ? _tokentype.types.bitwiseOR : _tokentype.types.bitwiseAND, 1); -}; - -pp.readToken_caret = function () { - // '^' - var next = this.input.charCodeAt(this.pos + 1); - if (next === 61) return this.finishOp(_tokentype.types.assign, 2); - return this.finishOp(_tokentype.types.bitwiseXOR, 1); -}; - -pp.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 && _whitespace.lineBreak.test(this.input.slice(this.lastTokEnd, this.pos))) { - // A `-->` line comment - this.skipLineComment(3); - this.skipSpace(); - return this.nextToken(); - } - return this.finishOp(_tokentype.types.incDec, 2); - } - if (next === 61) return this.finishOp(_tokentype.types.assign, 2); - return this.finishOp(_tokentype.types.plusMin, 1); -}; - -pp.readToken_lt_gt = function (code) { - // '<>' - var next = this.input.charCodeAt(this.pos + 1); - var size = 1; - if (next === code) { - size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2; - if (this.input.charCodeAt(this.pos + size) === 61) return this.finishOp(_tokentype.types.assign, size + 1); - return this.finishOp(_tokentype.types.bitShift, size); - } - if (next == 33 && code == 60 && this.input.charCodeAt(this.pos + 2) == 45 && this.input.charCodeAt(this.pos + 3) == 45) { - if (this.inModule) this.unexpected(); - // `` line comment - this.skipLineComment(3) - this.skipSpace() - return this.nextToken() - } - return this.finishOp(tt.incDec, 2) - } - if (next === 61) return this.finishOp(tt.assign, 2) - return this.finishOp(tt.plusMin, 1) -} - -pp.readToken_lt_gt = function(code) { // '<>' - let next = this.input.charCodeAt(this.pos + 1) - let size = 1 - if (next === code) { - size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2 - if (this.input.charCodeAt(this.pos + size) === 61) return this.finishOp(tt.assign, size + 1) - return this.finishOp(tt.bitShift, size) - } - if (next == 33 && code == 60 && this.input.charCodeAt(this.pos + 2) == 45 && - this.input.charCodeAt(this.pos + 3) == 45) { - if (this.inModule) this.unexpected() - // `