diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000000000..ca97ab47dfea49 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,39 @@ +root = true + +[*] +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true + +[vcbuild.bat] +end_of_line = crlf + +[*.{md,markdown}] +trim_trailing_whitespace = false + +[{lib,src,test}/**.js] +indent_style = space +indent_size = 2 + +[src/**.{h,cc}] +indent_style = space +indent_size = 2 + +[test/*.py] +indent_style = space +indent_size = 2 + +[configure] +indent_style = space +indent_size = 2 + +[Makefile] +indent_style = tab +indent_size = 8 + +[{deps,tools}/**] +indent_style = ignore +indent_size = ignore +end_of_line = ignore +trim_trailing_whitespace = ignore +charset = ignore diff --git a/.eslintrc b/.eslintrc index cf1f7682cdcf91..33a7919d88c9ef 100644 --- a/.eslintrc +++ b/.eslintrc @@ -70,6 +70,11 @@ rules: # require space after keywords, eg 'for (..)' space-after-keywords: 2 + # ECMAScript 6 + # list: http://eslint.org/docs/rules/#ecmascript-6 + ## Suggest using 'const' wherever possible + prefer-const: 2 + # Strict Mode # list: https://github.com/eslint/eslint/tree/master/docs/rules#strict-mode ## 'use strict' on top @@ -79,9 +84,13 @@ rules: # list: https://github.com/eslint/eslint/tree/master/docs/rules#variables ## disallow use of undefined variables (globals) no-undef: 2 + ## disallow declaration of variables that are not used in the code + no-unused-vars: [2, {"args": "none"}] # Custom rules in tools/eslint-rules require-buffer: 2 + new-with-error: [2, "Error", "RangeError", "TypeError", "SyntaxError", "ReferenceError"] + # Global scoped method and vars globals: diff --git a/.gitignore b/.gitignore index a3e3a28b07dc96..5cf2cd0a71cbdf 100644 --- a/.gitignore +++ b/.gitignore @@ -43,6 +43,7 @@ ipch/ /config.mk /config.gypi +/config_fips.gypi *-nodegyp* /gyp-mac-tool /dist-osx diff --git a/.mailmap b/.mailmap index 8400b36a6c90d6..78da54872c0f9c 100644 --- a/.mailmap +++ b/.mailmap @@ -6,6 +6,7 @@ Alexey Kupershtokh Alexis Campailla Alexis Sellier Alexis Sellier +Andy Bettisworth Aria Stewart Arlo Breault Artem Zaytsev @@ -19,15 +20,20 @@ Bert Belder Brandon Benvie Brian White Brian White +Caleb Boyd +Charles Chew Choon Keat Charles Rudolph +Claudio Rodriguez Colin Ihrig Christopher Lenz +Dan Kaplun Daniel Berger Daniel Chcouri <333222@gmail.com> Daniel Gröber Daniel Gröber Daniel Pihlström +Danny Nemer Dave Pacheco David Siegel Domenic Denicola @@ -37,6 +43,8 @@ Einar Otto Stangvik Elliott Cable EungJun Yi Evan Larkin +Evan Lucas +Evan Lucas Farid Neshat Fedor Indutny Felix Böhm @@ -48,23 +56,29 @@ Gabriel de Perthuis Gil Pedersen Henry Chin Herbert Vojčík +Icer Liang Igor Soarez Igor Zinkovsky Isaac Z. Schlueter Isaac Z. Schlueter Jake Verbaten James Hartig +Jan Krems Jered Schmidt Jeremiah Senkpiel +Jerry Chin Joe Shaw Johan Bergström Johan Dahlberg Johann Hofmann Jonas Pfenniger Jonathan Ong +Jonathan Persson Jonathan Rentzsch Josh Erickson Joshua S. Weinstein +Junliang Yan +Junliang Yan Jérémy Lal Jérémy Lal Kai Sasaki Lewuathe @@ -81,6 +95,8 @@ Malte-Thorben Bruns Malte-Thorben Bruns Marcin Cieślak Marcin Cieślak +Marti Martz +Martial James Jefferson Mathias Pettersson Matthew Lye Michael Bernstein @@ -95,16 +111,20 @@ Nicholas Kinsey Nikolai Vavilov Onne Gorter Paul Querna +Peter Flannery +Phillip Johnsen Ray Morgan Ray Solomon Raymond Feng Rick Olson Roman Klauke Roman Reiss +Ron Korving Ryan Dahl Ryan Emery Sakthipriyan Vairamani Sam Mikes +Sam P Gallagher-Bishop Sam Shull Sam Shull Sambasiva Suda diff --git a/AUTHORS b/AUTHORS index 3e80bf26e550ca..5ab61aebf20966 100644 --- a/AUTHORS +++ b/AUTHORS @@ -517,7 +517,7 @@ Cam Swords Paul Loyd Benjamin Waters Lev Gimelfarb -pflannery +Peter Flannery Tuğrul Topuz Lorenz Leutgeb ayanamist @@ -565,7 +565,7 @@ Feross Aboukhadijeh Refael Ackermann Taojie Greg Sabia Tucker -Dan Kaplun +Dan Kaplun Colin Ihrig Greg Sabia Tucker Mark Stosberg @@ -580,7 +580,7 @@ Roman Klauke Xavi Magrinyà Euan Ed Morley -Charles +Charles Jan Krems Fred K. Schott Chris Dickinson @@ -648,7 +648,7 @@ Bryce Kahle The Gitter Badger Brendan Ashworth Jose Luis Rivas -Evan Lucas +Evan Lucas Vincent Weevers Tyler Kellen Evan Torrie @@ -669,7 +669,6 @@ Calvin Metcalf Eric Mill pkcs James M Snell -Evan Lucas Cydox Steven Rockarts Vladimir Guguiev @@ -690,7 +689,7 @@ Glen Keane Xiaowei Li <446240525@qq.com> toastynerd Todd Kennedy -Icer Liang +Icer Liang Stephen Belanger Jeremiah Senkpiel Brendan Ashworth @@ -794,7 +793,7 @@ Oleksandr Chekhovskyi Tristian Flanagan Mike Tunnicliffe Ionică Bizău -Danny Nemer +Danny Nemer Sven Slootweg Dmitry Vasilyev Malcolm Ahoy @@ -810,5 +809,64 @@ Michał Gołębiowski Johann Hofmann Charles Rudolph Dave Eddy +Justin Chase +Jeremy Whitlock +Rod Machen +Martial James Jefferson +Doug Shamoo +Junliang Yan +Dave Hodder +Jason Karns +Balázs Galambosi +David Boivin +Liang-Chi Hsieh +Timothy Gu +Fábio Santos +Myles Borins +Jonas Dohse +Коренберг Марк +Caleb Boyd +Yuval Brik +Claudio Rodriguez +Ido Ben-Yair +Kyle Smith +Marti Martz +Stefan Budeanu +Emily Aviva Kapor-Mater +Sam P Gallagher-Bishop +David Woods +Ashok Suthar +Ömer Fadıl Usta +Jerry Chin +Hemanth.HM +Hugues Malphettes +Tyler Henkel +Zheng Chaoping +Ashley Williams +Bryan English +Devin Nakamura +Vladimir Varankin +Manuel B +Jesse McCarthy +Craig Cavalier +Michael Cornacchia +Markus Tzoe +Martin Forsberg +Carl Lei +Lewis Cowper +Bryon Leung +Chunyang Dai +Jonathan Persson +Dave +Luigi Pinca +Peter A. Bigot +Zirak +Scott Buchanan +Rebecca Turner +Bryce Baril +Super Zheng +Rafał Pocztarski +Michael Ruddy +Andy Bettisworth # Generated by tools/update-authors.sh diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f8d56f2daa4cb7..20b012697e6629 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -51,23 +51,26 @@ and built upon. The rules for the master branch are less strict; consult the [stability index](./doc/api/documentation.markdown#stability-index) for details. -In a nutshell, modules are at varying levels of API stability. Bug fixes are +In a nutshell, modules are at varying levels of API stability. Bug fixes are always welcome but API or behavioral changes to modules at stability level 3 (Locked) are off-limits. #### Dependencies Node.js has several bundled dependencies in the *deps/* and the *tools/* -directories that are not part of the project proper. Any changes to files +directories that are not part of the project proper. Any changes to files in those directories or its subdirectories should be sent to their respective -projects. Do not send your patch to us, we cannot accept it. +projects. Do not send your patch to us, we cannot accept it. In case of doubt, open an issue in the [issue tracker](https://github.com/nodejs/node/issues/) or contact one of the [project Collaborators](https://github.com/nodejs/node/#current-project-team-members). -([IRC](http://webchat.freenode.net/?channels=io.js) is often the best medium.) Especially do so if you plan to work on something big. Nothing is more + +Especially do so if you plan to work on something big. Nothing is more frustrating than seeing your hard work go to waste because your vision -does not align with the project team. +does not align with the project team. Node.js has two IRC channels, +[#Node.js](http://webchat.freenode.net/?channels=node.js) for general help and questions, and +[#Node-dev](http://webchat.freenode.net/?channels=node-dev) for development of node core specifically. ### Step 2: Branch @@ -87,8 +90,8 @@ $ git config --global user.name "J. Random User" $ git config --global user.email "j.random.user@example.com" ``` -Writing good commit logs is important. A commit log should describe what -changed and why. Follow these guidelines when writing one: +Writing good commit logs is important. A commit log should describe what +changed and why. Follow these guidelines when writing one: 1. The first line should be 50 characters or less and contain a short description of the change prefixed with the name of the changed @@ -130,15 +133,15 @@ $ git rebase upstream/master ### Step 5: Test -Bug fixes and features **should come with tests**. Add your tests in the -test/parallel/ directory. Look at other tests to see how they should be +Bug fixes and features **should come with tests**. Add your tests in the +test/parallel/ directory. Look at other tests to see how they should be structured (license boilerplate, common includes, etc.). ```text $ ./configure && make -j8 test ``` -Make sure the linter is happy and that all tests pass. Please, do not submit +Make sure the linter is happy and that all tests pass. Please, do not submit patches that fail either check. If you are updating tests and just want to run a single test to check it, you @@ -166,9 +169,9 @@ $ git push origin my-feature-branch Go to https://github.com/yourusername/node and select your feature branch. Click the 'Pull Request' button and fill out the form. -Pull requests are usually reviewed within a few days. If there are comments +Pull requests are usually reviewed within a few days. If there are comments 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 +feature branch. Post a comment in the pull request afterwards; GitHub does not send out notifications when you add commits. diff --git a/Makefile b/Makefile index 02619fac98ddd7..94eb41995367ed 100644 --- a/Makefile +++ b/Makefile @@ -74,7 +74,7 @@ clean: distclean: -rm -rf out - -rm -f config.gypi icu_config.gypi + -rm -f config.gypi icu_config.gypi config_fips.gypi -rm -f config.mk -rm -rf $(NODE_EXE) $(NODE_G_EXE) -rm -rf node_modules @@ -493,6 +493,9 @@ bench-url: all bench-events: all @$(NODE) benchmark/common.js events +bench-util: all + @$(NODE) benchmark/common.js util + bench-all: bench bench-misc bench-array bench-buffer bench-url bench-events bench: bench-net bench-http bench-fs bench-tls diff --git a/README.md b/README.md index 633e44493d431a..c534c64fbe29a7 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,11 @@ Node.js [![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/nodejs/node?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine. Node.js +uses an event-driven, non-blocking I/O model that makes it lightweight and +efficient. The Node.js package ecosystem, npm, is the largest ecosystem of open +source libraries in the world. + The Node.js project is supported by the [Node.js Foundation](https://nodejs.org/en/foundation/). Contributions, policies and releases are managed under an @@ -49,8 +54,8 @@ Binaries, installers, and source tarballs 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 -line is available in the form: latest-lts-_codename_. For example: - +line is available in the form: latest-_codename_. For example: + **Nightly** builds are available at , listed under their version @@ -147,7 +152,7 @@ $ man doc/node.1 To test if Node.js was built correctly: ``` -$ node -e "console.log('Hello from node.js ' + process.version)" +$ node -e "console.log('Hello from Node.js ' + process.version)" ``` ### Windows @@ -174,7 +179,7 @@ To run the tests: To test if Node.js was built correctly: ``` -$ node -e "console.log('Hello from node.js ' + process.version)" +$ node -e "console.log('Hello from Node.js ' + process.version)" ``` ### Android / Android based devices, aka. Firefox OS @@ -329,7 +334,9 @@ Instructions: Appendix A in the [security policy] (http://csrc.nist.gov/groups/STM/cmvp/documents/140-1/140sp/140sp1747.pdf). The only exception is that `./config no-asm` can be - used in place of `./config` ) + used in place of `./config`, and the FIPSDIR environment variable + may be used to specify a non-standard install folder for the + validated module, as per User Guide sections 4.2.1, 4.2.2, and 4.2.3. 6. Get into Node.js checkout folder 7. `./configure --openssl-fips=/path/to/openssl-fips/installdir` For example on ubuntu 12 the installation directory was @@ -342,13 +349,13 @@ Instructions: * [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md) * [CONTRIBUTING.md](./CONTRIBUTING.md) * [GOVERNANCE.md](./GOVERNANCE.md) -* IRC: - [#io.js on Freenode.net](http://webchat.freenode.net?channels=io.js&uio=d4) +* IRC (general questions): [#node.js on Freenode.net](http://webchat.freenode.net?channels=node.js&uio=d4) +* IRC (node core development): [#node-dev on Freenode.net](http://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 +All security bugs in Node.js are taken seriously and should be reported by emailing security@nodejs.org. This will be delivered to a subset of the project team who handle security issues. Please don't disclose security bugs publicly until they have been handled by the security team. @@ -383,15 +390,19 @@ information about the governance of the Node.js project, see ### Collaborators * [brendanashworth](https://github.com/brendanashworth) - **Brendan Ashworth** <brendan.ashworth@me.com> +* [calvinmetcalf](https://github.com/calvinmetcalf) - **Calvin Metcalf** <calvin.metcalf@gmail.com> * [ChALkeR](https://github.com/ChALkeR) - **Сковорода Никита Андреевич** <chalkerx@gmail.com> * [domenic](https://github.com/domenic) - **Domenic Denicola** <d@domenic.me> * [evanlucas](https://github.com/evanlucas) - **Evan Lucas** <evanlucas@me.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> * [jbergstroem](https://github.com/jbergstroem) - **Johan Bergström** <bugs@bergstroem.nu> * [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> * [lxe](https://github.com/lxe) - **Aleksey Smolenchuk** <lxe@lxe.co> +* [mcollina](https://github.com/mcollina) - **Matteo Collina** <matteo.collina@gmail.com> * [mhdawson](https://github.com/mhdawson) - **Michael Dawson** <michael_dawson@ca.ibm.com> * [micnic](https://github.com/micnic) - **Nicu Micleușanu** <micnic90@gmail.com> * [mikeal](https://github.com/mikeal) - **Mikeal Rogers** <mikeal.rogers@gmail.com> @@ -401,6 +412,7 @@ information about the governance of the Node.js project, see * [petkaantonov](https://github.com/petkaantonov) - **Petka Antonov** <petka_antonov@hotmail.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> * [saghul](https://github.com/saghul) - **Saúl Ibarra Corretgé** <saghul@gmail.com> @@ -417,6 +429,7 @@ information about the governance of the Node.js project, see * [tunniclm](https://github.com/tunniclm) - **Mike Tunnicliffe** <m.j.tunnicliffe@gmail.com> * [vkurchatkin](https://github.com/vkurchatkin) - **Vladimir Kurchatkin** <vladimir.kurchatkin@gmail.com> * [yosuke-furukawa](https://github.com/yosuke-furukawa) - **Yosuke Furukawa** <yosuke.furukawa@gmail.com> +* [zkat](https://github.com/zkat) - **Kat Marchán** <kzm@sykosomatic.org> Collaborators & TSC members follow the [COLLABORATOR_GUIDE.md](./COLLABORATOR_GUIDE.md) in maintaining the Node.js project. @@ -431,6 +444,8 @@ Releases of Node.js and io.js will be signed with one of the following GPG keys: * **Jeremiah Senkpiel** <fishrock@keybase.io> `FD3A5288F042B6850C66B31F09FE44734EB7990E` * **James M Snell** <jasnell@keybase.io> `71DCFD284A79C3B38668286BC97EC7A07EDE3FC1` * **Rod Vagg** <rod@vagg.org> `DD8F2338BAE7501E3DD5AC78C273792F7D83545D` +* **Myles Borins** <myles.borins@gmail.com> `C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8` +* **Evan Lucas** <evanlucas@me.com> `B9AE9905FFD7803F25714661B63B535A4C206CA9` The full set of trusted release keys can be imported by running: @@ -441,6 +456,8 @@ gpg --keyserver pool.sks-keyservers.net --recv-keys 0034A06D9D9B0064CE8ADF6BF174 gpg --keyserver pool.sks-keyservers.net --recv-keys FD3A5288F042B6850C66B31F09FE44734EB7990E gpg --keyserver pool.sks-keyservers.net --recv-keys 71DCFD284A79C3B38668286BC97EC7A07EDE3FC1 gpg --keyserver pool.sks-keyservers.net --recv-keys DD8F2338BAE7501E3DD5AC78C273792F7D83545D +gpg --keyserver pool.sks-keyservers.net --recv-keys C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 +gpg --keyserver pool.sks-keyservers.net --recv-keys B9AE9905FFD7803F25714661B63B535A4C206CA9 ``` See the section above on [Verifying Binaries](#verifying-binaries) for diff --git a/WORKING_GROUPS.md b/WORKING_GROUPS.md index aa573844b790a9..9d518db1351acc 100644 --- a/WORKING_GROUPS.md +++ b/WORKING_GROUPS.md @@ -452,40 +452,13 @@ By making a contribution to this project, I certify that: * (c) The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it. +### Moderation Policy + +The [Node.js Moderation Policy] applies to this WG. ### Code of Conduct -This Code of Conduct is adapted from [Rust's wonderful -CoC](https://github.com/rust-lang/rust/wiki/Note-development-policy#conduct). - -* We are committed to providing a friendly, safe and welcoming - environment for all, regardless of gender, sexual orientation, - disability, ethnicity, religion, or similar personal characteristic. -* Please avoid using overtly sexual nicknames or other nicknames that - might detract from a friendly, safe and welcoming environment for - all. -* Please be kind and courteous. There's no need to be mean or rude. -* Respect that people have differences of opinion and that every - design or implementation choice carries a trade-off and numerous - costs. There is seldom a right answer. -* Please keep unstructured critique to a minimum. If you have solid - ideas you want to experiment with, make a fork and see how it works. -* We will exclude you from interaction if you insult, demean or harass - anyone. That is not welcome behaviour. We interpret the term - "harassment" as including the definition in the [Citizen Code of - Conduct](http://citizencodeofconduct.org/); if you have any lack of - clarity about what might be included in that concept, please read - their definition. In particular, we don't tolerate behavior that - excludes people in socially marginalized groups. -* Private harassment is also unacceptable. No matter who you are, if - you feel you have been or are being harassed or made uncomfortable - by a community member, please contact one of the channel ops or any - of the TC members immediately with a capture (log, photo, email) of - the harassment if possible. Whether you're a regular contributor or - a newcomer, we care about making this community a safe place for you - and we've got your back. -* Likewise any spamming, trolling, flaming, baiting or other - attention-stealing behaviour is not welcome. -* Avoid the use of personal pronouns in code comments or - documentation. There is no need to address persons when explaining - code (e.g. "When the developer") +The [Node.js Code of Conduct][] applies to this WG. + +[Node.js Code of Conduct]: https://github.com/nodejs/node/blob/master/CODE_OF_CONDUCT.md +[Node.js Moderation Policy]: https://github.com/nodejs/TSC/blob/master/Moderation-Policy.md diff --git a/benchmark/assert/deepequal-prims-and-objs-big-array.js b/benchmark/assert/deepequal-prims-and-objs-big-array.js new file mode 100644 index 00000000000000..d8d2b57331f7ef --- /dev/null +++ b/benchmark/assert/deepequal-prims-and-objs-big-array.js @@ -0,0 +1,37 @@ +'use strict'; +var common = require('../common.js'); +var assert = require('assert'); +var bench = common.createBenchmark(main, { + prim: [ + null, + undefined, + 'a', + 1, + true, + {0: 'a'}, + [1, 2, 3], + new Array([1, 2, 3]) + ], + n: [25] +}); + +function main(conf) { + var prim = conf.prim; + var n = +conf.n; + var primArray; + var primArrayCompare; + var x; + + primArray = new Array(); + primArrayCompare = new Array(); + for (x = 0; x < (1e5); x++) { + primArray.push(prim); + primArrayCompare.push(prim); + } + + bench.start(); + for (x = 0; x < n; x++) { + assert.deepEqual(primArray, primArrayCompare); + } + bench.end(n); +} diff --git a/benchmark/assert/deepequal-prims-and-objs-big-loop.js b/benchmark/assert/deepequal-prims-and-objs-big-loop.js new file mode 100644 index 00000000000000..5f0519bb3b45ad --- /dev/null +++ b/benchmark/assert/deepequal-prims-and-objs-big-loop.js @@ -0,0 +1,30 @@ +'use strict'; +var common = require('../common.js'); +var assert = require('assert'); +var bench = common.createBenchmark(main, { + prim: [ + null, + undefined, + 'a', + 1, + true, + {0: 'a'}, + [1, 2, 3], + new Array([1, 2, 3]) + ], + n: [1e5] +}); + +function main(conf) { + var prim = conf.prim; + var n = +conf.n; + var x; + + bench.start(); + + for (x = 0; x < n; x++) { + assert.deepEqual(new Array([prim]), new Array([prim])); + } + + bench.end(n); +} diff --git a/benchmark/assert/deepequal-typedarrays.js b/benchmark/assert/deepequal-typedarrays.js new file mode 100644 index 00000000000000..99c13206d7560a --- /dev/null +++ b/benchmark/assert/deepequal-typedarrays.js @@ -0,0 +1,22 @@ +'use strict'; +var common = require('../common.js'); +var assert = require('assert'); +var bench = common.createBenchmark(main, { + type: ('Int8Array Uint8Array Int16Array Uint16Array Int32Array Uint32Array ' + + 'Float32Array Float64Array Uint8ClampedArray').split(' '), + n: [1] +}); + +function main(conf) { + var type = conf.type; + var clazz = global[type]; + var n = +conf.n; + + bench.start(); + var actual = new clazz(n * 1e6); + var expected = new clazz(n * 1e6); + + assert.deepEqual(actual, expected); + + bench.end(n); +} diff --git a/benchmark/buffers/buffer_zero.js b/benchmark/buffers/buffer_zero.js new file mode 100644 index 00000000000000..461378758b5951 --- /dev/null +++ b/benchmark/buffers/buffer_zero.js @@ -0,0 +1,18 @@ +'use strict'; + +const common = require('../common.js'); + +const bench = common.createBenchmark(main, { + n: [1024] +}); + +const zero = new Buffer(0); + +function main(conf) { + var n = +conf.n; + bench.start(); + for (let i = 0; i < n * 1024; i++) { + new Buffer(zero); + } + bench.end(n); +} diff --git a/benchmark/util/inspect.js b/benchmark/util/inspect.js new file mode 100644 index 00000000000000..8a59e6b48e54df --- /dev/null +++ b/benchmark/util/inspect.js @@ -0,0 +1,15 @@ +var util = require('util'); + +var common = require('../common.js'); + +var bench = common.createBenchmark(main, {n: [5e6]}); + +function main(conf) { + var n = conf.n | 0; + + bench.start(); + for (var i = 0; i < n; i += 1) { + var r = util.inspect({a: 'a', b: 'b', c: 'c', d: 'd'}); + } + bench.end(n); +} diff --git a/common.gypi b/common.gypi index dc7f9b67577d03..5b8b2c09d6b4a9 100644 --- a/common.gypi +++ b/common.gypi @@ -183,7 +183,6 @@ '-fsanitize=address', '-DLEAK_SANITIZER' ], - 'cflags_cc+': [ '-gline-tables-only' ], 'cflags!': [ '-fomit-frame-pointer' ], 'ldflags': [ '-fsanitize=address' ], }], diff --git a/configure b/configure index 0e83d8a8d7cdc5..a3730bc438ef1a 100755 --- a/configure +++ b/configure @@ -30,7 +30,7 @@ valid_os = ('win', 'mac', 'solaris', 'freebsd', 'openbsd', 'linux', valid_arch = ('arm', 'arm64', 'ia32', 'mips', 'mipsel', 'ppc', 'ppc64', 'x32', 'x64', 'x86') valid_arm_float_abi = ('soft', 'softfp', 'hard') -valid_arm_fpu = ('vfp', 'vfpv2', 'vfpv3', 'vfpv3-d16', 'neon') +valid_arm_fpu = ('vfp', 'vfpv3', 'vfpv3-d16', 'neon') valid_mips_arch = ('loongson', 'r1', 'r2', 'r6', 'rx') valid_mips_fpu = ('fp32', 'fp64', 'fpxx') valid_mips_float_abi = ('soft', 'hard') @@ -84,7 +84,13 @@ parser.add_option("--fully-static", action="store_true", dest="fully_static", help="Generate an executable without external dynamic libraries. This " - "will not work on OSX when using default compilation environment") + "will not work on OSX when using the default compilation environment") + +parser.add_option("--partly-static", + action="store_true", + dest="partly_static", + help="Generate an executable with libgcc and libstdc++ libraries. This " + "will not work on OSX when using the default compilation environment") parser.add_option("--link-module", action="append", @@ -617,7 +623,7 @@ def configure_arm(o): else: arm_float_abi = 'default' - arm_fpu = 'vfpv2' + arm_fpu = 'vfp' if is_arch_armv7(): arm_fpu = 'vfpv3' @@ -670,6 +676,10 @@ def configure_node(o): elif target_arch in ('mips', 'mipsel'): configure_mips(o) + if flavor == 'aix': + o['variables']['node_core_target_name'] = 'node_base' + o['variables']['node_target_type'] = 'static_library' + if flavor in ('solaris', 'mac', 'linux', 'freebsd'): use_dtrace = not options.without_dtrace # Don't enable by default on linux and freebsd @@ -778,7 +788,7 @@ def configure_openssl(o): o['variables']['openssl_fips'] = options.openssl_fips fips_dir = os.path.join(root_dir, 'deps', 'openssl', 'fips') fips_ld = os.path.abspath(os.path.join(fips_dir, 'fipsld')) - o['make_global_settings'] = [ + o['make_fips_settings'] = [ ['LINK', fips_ld + ' <(openssl_fips)/bin/fipsld'], ] else: @@ -790,12 +800,19 @@ def configure_openssl(o): configure_library('openssl', o) -def configure_fullystatic(o): - if options.fully_static: - o['libraries'] += ['-static'] +def configure_static(o): + if options.fully_static or options.partly_static: if flavor == 'mac': print("Generation of static executable will not work on OSX " - "when using default compilation environment") + "when using the default compilation environment") + return + + if options.fully_static: + o['libraries'] += ['-static'] + elif options.partly_static: + o['libraries'] += ['-static-libgcc', '-static-libstdc++'] + if options.enable_asan: + o['libraries'] += ['-static-libasan'] def configure_winsdk(o): @@ -1093,13 +1110,22 @@ configure_v8(output) configure_openssl(output) configure_winsdk(output) configure_intl(output) -configure_fullystatic(output) +configure_static(output) # variables should be a root level element, # move everything else to target_defaults variables = output['variables'] del output['variables'] +# make_global_settings for special FIPS linking +# should not be used to compile modules in node-gyp +config_fips = { 'make_global_settings' : [] } +if 'make_fips_settings' in output: + config_fips['make_global_settings'] = output['make_fips_settings'] + del output['make_fips_settings'] + write('config_fips.gypi', do_not_edit + + pprint.pformat(config_fips, indent=2) + '\n') + # make_global_settings should be a root level element too if 'make_global_settings' in output: make_global_settings = output['make_global_settings'] diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS index b2397e2df6de5f..8dc3955cad5bf3 100644 --- a/deps/uv/AUTHORS +++ b/deps/uv/AUTHORS @@ -225,3 +225,18 @@ Colin Snover Sakthipriyan Vairamani Eli Skeggs nmushell +Gireesh Punathil +Ryan Johnston +Adam Stylinski +Nathan Corvino +Wink Saville +Angel Leon +Louis DeJardin +Imran Iqbal +Petka Antonov +Ian Kronquist +kkdaemon +Yuval Brik +Joran Dirk Greef +Andrey Mazo +sztomi diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog index 42f10352b1cb35..af0743af72c8db 100644 --- a/deps/uv/ChangeLog +++ b/deps/uv/ChangeLog @@ -1,3 +1,102 @@ +2015.12.15, Version 1.8.0 (Stable), 5467299450ecf61635657557b6e01aaaf6c3fdf4 + +Changes since version 1.7.5: + +* unix: fix memory leak in uv_interface_addresses (Jianghua Yang) + +* unix: make uv_guess_handle work properly for AIX (Gireesh Punathil) + +* fs: undo uv__req_init when uv__malloc failed (Jianghua Yang) + +* build: remove unused 'component' GYP option (Saúl Ibarra Corretgé) + +* include: remove duplicate extern declaration (Jianghua Yang) + +* win: use the MSVC provided snprintf where possible (Jason Williams) + +* win, test: fix compilation warning (Saúl Ibarra Corretgé) + +* win: fix compilation with VS < 2012 (Ryan Johnston) + +* stream: support empty uv_try_write on unix (Fedor Indutny) + +* unix: fix request handle leak in uv__udp_send (Jianghua Yang) + +* src: replace QUEUE_SPLIT with QUEUE_MOVE (Ben Noordhuis) + +* unix: use QUEUE_MOVE when iterating over lists (Ben Noordhuis) + +* unix: squelch harmless valgrind warning (Ben Noordhuis) + +* test: don't abort on setrlimit() failure (Ben Noordhuis) + +* unix: only undo fs req registration in async mode (Ben Noordhuis) + +* unix: fix uv__getiovmax return value (HungMingWu) + +* unix: make work with Solaris Studio. (Adam Stylinski) + +* test: fix fs_event_watch_file_currentdir flakiness (Santiago Gimeno) + +* unix: skip prohibited syscalls on tvOS and watchOS (Nathan Corvino) + +* test: use FQDN in getaddrinfo_fail test (Wink Saville) + +* docs: clarify documentation of uv_tcp_init_ex (Andrius Bentkus) + +* win: fix comment (Miodrag Milanovic) + +* doc: fix typo in README (Angel Leon) + +* darwin: abort() if (un)locking fs mutex fails (Ben Noordhuis) + +* pipe: enable inprocess uv_write2 on Windows (Louis DeJardin) + +* win: properly return UV_EBADF when _close() fails (Nicholas Vavilov) + +* test: skip process_title for AIX (Imran Iqbal) + +* misc: expose handle print APIs (Petka Antonov) + +* include: add stdio.h to uv.h (Saúl Ibarra Corretgé) + +* misc: remove unnecessary null pointer checks (Ian Kronquist) + +* test,freebsd: skip udp_dual_stack if not supported (Santiago Gimeno) + +* linux: don't retry dup2/dup3 on EINTR (Ben Noordhuis) + +* unix: don't retry dup2/dup3 on EINTR (Ben Noordhuis) + +* test: fix -Wtautological-pointer-compare warnings (Saúl Ibarra Corretgé) + +* win: map ERROR_BAD_PATHNAME to UV_ENOENT (Tony Kelman) + +* test: fix test/test-tty.c for AIX (Imran Iqbal) + +* android: support api level less than 21 (kkdaemon) + +* fsevents: fix race on simultaneous init+close (Fedor Indutny) + +* linux,fs: fix p{read,write}v with a 64bit offset (Saúl Ibarra Corretgé) + +* fs: add uv_fs_realpath() (Yuval Brik) + +* win: fix path for removed and renamed fs events (Joran Dirk Greef) + +* win: do not read more from stream than available (Jeremy Whitlock) + +* test: test that uv_close() doesn't corrupt QUEUE (Andrey Mazo) + +* unix: fix uv_fs_event_stop() from fs_event_cb (Andrey Mazo) + +* test: fix self-deadlocks in thread_rwlock_trylock (Ben Noordhuis) + +* src: remove non ascii character (sztomi) + +* test: fix test udp_multicast_join6 for AIX (Imran Iqbal) + + 2015.09.23, Version 1.7.5 (Stable), a8c1136de2cabf25b143021488cbaab05834daa8 Changes since version 1.7.4: diff --git a/deps/uv/Makefile.am b/deps/uv/Makefile.am index fbf9527ae93a70..0ef781ff198804 100644 --- a/deps/uv/Makefile.am +++ b/deps/uv/Makefile.am @@ -200,6 +200,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \ test/test-poll-closesocket.c \ test/test-poll.c \ test/test-process-title.c \ + test/test-queue-foreach-delete.c \ test/test-ref.c \ test/test-run-nowait.c \ test/test-run-once.c \ diff --git a/deps/uv/README.md b/deps/uv/README.md index 0ce26699716a1a..dfd24ba79d1850 100644 --- a/deps/uv/README.md +++ b/deps/uv/README.md @@ -119,7 +119,7 @@ Git tags are signed with the developer's key, they can be verified as follows: $ git verify-tag v1.6.1 Starting with libuv 1.7.0, the tarballs stored in the -[downloads site](http://dist.libuv.org/dist/) are signed and an accomanying +[downloads site](http://dist.libuv.org/dist/) are signed and an accompanying signature file sit alongside each. Once both the release tarball and the signature file are downloaded, the file can be verified as follows: diff --git a/deps/uv/appveyor.yml b/deps/uv/appveyor.yml index c9f55134e583dd..9aa63c5a5d2e73 100644 --- a/deps/uv/appveyor.yml +++ b/deps/uv/appveyor.yml @@ -1,4 +1,4 @@ -version: v1.7.5.build{build} +version: v1.8.0.build{build} install: - cinst -y nsis diff --git a/deps/uv/common.gypi b/deps/uv/common.gypi index 392c85951e1ebd..7cebcde5f89137 100644 --- a/deps/uv/common.gypi +++ b/deps/uv/common.gypi @@ -4,7 +4,6 @@ 'target_arch%': 'ia32', # set v8's target architecture 'host_arch%': 'ia32', # set v8's host architecture 'uv_library%': 'static_library', # allow override to 'shared_library' for DLL/.so builds - 'component%': 'static_library', # NB. these names match with what V8 expects 'msvs_multi_core_compile': '0', # we do enable multicore compiles, but not using the V8 way }, diff --git a/deps/uv/configure.ac b/deps/uv/configure.ac index c55a11847e255e..011bee2a891e73 100644 --- a/deps/uv/configure.ac +++ b/deps/uv/configure.ac @@ -13,7 +13,7 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. AC_PREREQ(2.57) -AC_INIT([libuv], [1.7.5], [https://github.com/libuv/libuv/issues]) +AC_INIT([libuv], [1.8.0], [https://github.com/libuv/libuv/issues]) AC_CONFIG_MACRO_DIR([m4]) m4_include([m4/libuv-extra-automake-flags.m4]) m4_include([m4/as_case.m4]) diff --git a/deps/uv/docs/src/fs.rst b/deps/uv/docs/src/fs.rst index 33c04406f14d9e..69e283f4c67fc6 100644 --- a/deps/uv/docs/src/fs.rst +++ b/deps/uv/docs/src/fs.rst @@ -279,6 +279,16 @@ API Equivalent to :man:`readlink(2)`. +.. c:function:: int uv_fs_realpath(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) + + Equivalent to :man:`realpath(3)` on Unix. Windows uses ``GetFinalPathNameByHandle()``. + + .. note:: + This function is not implemented on Windows XP and Windows Server 2003. + On these systems, UV_ENOSYS is returned. + + .. versionadded:: 1.8.0 + .. c:function:: int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb) .. c:function:: int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb) diff --git a/deps/uv/docs/src/misc.rst b/deps/uv/docs/src/misc.rst index e9ddba3db6a953..2ce0887db0c278 100644 --- a/deps/uv/docs/src/misc.rst +++ b/deps/uv/docs/src/misc.rst @@ -288,3 +288,41 @@ API .. note:: Not every platform can support nanosecond resolution; however, this value will always be in nanoseconds. + +.. c:function:: void uv_print_all_handles(uv_loop_t* loop, FILE* stream) + + Prints all handles associated with the given `loop` to the given `stream`. + + Example: + + :: + + uv_print_all_handles(uv_default_loop(), stderr); + /* + [--I] signal 0x1a25ea8 + [-AI] async 0x1a25cf0 + [R--] idle 0x1a7a8c8 + */ + + The format is `[flags] handle-type handle-address`. For `flags`: + + - `R` is printed for a handle that is referenced + - `A` is printed for a handle that is active + - `I` is printed for a handle that is internal + + .. warning:: + This function is meant for ad hoc debugging, there is no API/ABI + stability guarantees. + + .. versionadded:: 1.8.0 + +.. c:function:: void uv_print_active_handles(uv_loop_t* loop, FILE* stream) + + This is the same as :c:func:`uv_print_all_handles` except only active handles + are printed. + + .. warning:: + This function is meant for ad hoc debugging, there is no API/ABI + stability guarantees. + + .. versionadded:: 1.8.0 diff --git a/deps/uv/docs/src/tcp.rst b/deps/uv/docs/src/tcp.rst index dd18522d91d4eb..ca0c9b4ac5af4c 100644 --- a/deps/uv/docs/src/tcp.rst +++ b/deps/uv/docs/src/tcp.rst @@ -34,7 +34,7 @@ API .. c:function:: int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* handle, unsigned int flags) - Initialize the handle with the specified flags. At the moment the lower 8 bits + Initialize the handle with the specified flags. At the moment only the lower 8 bits of the `flags` parameter are used as the socket domain. A socket will be created for the given domain. If the specified domain is ``AF_UNSPEC`` no socket is created, just like :c:func:`uv_tcp_init`. diff --git a/deps/uv/gyp_uv.py b/deps/uv/gyp_uv.py index 0491ff873f1af1..39933f624d5c40 100755 --- a/deps/uv/gyp_uv.py +++ b/deps/uv/gyp_uv.py @@ -83,9 +83,6 @@ def run_gyp(args): if not any(a.startswith('-Duv_library=') for a in args): args.append('-Duv_library=static_library') - if not any(a.startswith('-Dcomponent=') for a in args): - args.append('-Dcomponent=static_library') - # Some platforms (OpenBSD for example) don't have multiprocessing.synchronize # so gyp must be run with --no-parallel if not gyp_parallel_support: diff --git a/deps/uv/include/uv-version.h b/deps/uv/include/uv-version.h index e1f26601a156c2..6e61f55ed20d85 100644 --- a/deps/uv/include/uv-version.h +++ b/deps/uv/include/uv-version.h @@ -31,8 +31,8 @@ */ #define UV_VERSION_MAJOR 1 -#define UV_VERSION_MINOR 7 -#define UV_VERSION_PATCH 5 +#define UV_VERSION_MINOR 8 +#define UV_VERSION_PATCH 0 #define UV_VERSION_IS_RELEASE 1 #define UV_VERSION_SUFFIX "" diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h index f96026b603d34e..dd3111a960e69b 100644 --- a/deps/uv/include/uv.h +++ b/deps/uv/include/uv.h @@ -48,6 +48,7 @@ extern "C" { #include "uv-errno.h" #include "uv-version.h" #include +#include #if defined(_MSC_VER) && _MSC_VER < 1600 # include "stdint-msvc2008.h" @@ -424,6 +425,10 @@ UV_EXTERN int uv_is_active(const uv_handle_t* handle); UV_EXTERN void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg); +/* Helpers for ad hoc debugging, no API/ABI stability guaranteed. */ +UV_EXTERN void uv_print_all_handles(uv_loop_t* loop, FILE* stream); +UV_EXTERN void uv_print_active_handles(uv_loop_t* loop, FILE* stream); + UV_EXTERN void uv_close(uv_handle_t* handle, uv_close_cb close_cb); UV_EXTERN int uv_send_buffer_size(uv_handle_t* handle, int* value); @@ -1083,7 +1088,8 @@ typedef enum { UV_FS_SYMLINK, UV_FS_READLINK, UV_FS_CHOWN, - UV_FS_FCHOWN + UV_FS_FCHOWN, + UV_FS_REALPATH } uv_fs_type; /* uv_fs_t is a subclass of uv_req_t. */ @@ -1235,6 +1241,10 @@ UV_EXTERN int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); +UV_EXTERN int uv_fs_realpath(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + uv_fs_cb cb); UV_EXTERN int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file file, @@ -1363,7 +1373,7 @@ UV_EXTERN int uv_chdir(const char* dir); UV_EXTERN uint64_t uv_get_free_memory(void); UV_EXTERN uint64_t uv_get_total_memory(void); -UV_EXTERN extern uint64_t uv_hrtime(void); +UV_EXTERN uint64_t uv_hrtime(void); UV_EXTERN void uv_disable_stdio_inheritance(void); diff --git a/deps/uv/src/inet.c b/deps/uv/src/inet.c index c948b2e7cfaf01..da63a688c4e424 100644 --- a/deps/uv/src/inet.c +++ b/deps/uv/src/inet.c @@ -55,11 +55,7 @@ static int inet_ntop4(const unsigned char *src, char *dst, size_t size) { char tmp[UV__INET_ADDRSTRLEN]; int l; -#ifndef _WIN32 l = snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]); -#else - l = _snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]); -#endif if (l <= 0 || (size_t) l >= size) { return UV_ENOSPC; } diff --git a/deps/uv/src/queue.h b/deps/uv/src/queue.h index 60c80000385be5..ff3540a0a51c84 100644 --- a/deps/uv/src/queue.h +++ b/deps/uv/src/queue.h @@ -30,6 +30,9 @@ typedef void *QUEUE[2]; #define QUEUE_DATA(ptr, type, field) \ ((type *) ((char *) (ptr) - offsetof(type, field))) +/* Important note: mutating the list while QUEUE_FOREACH is + * iterating over its elements results in undefined behavior. + */ #define QUEUE_FOREACH(q, h) \ for ((q) = QUEUE_NEXT(h); (q) != (h); (q) = QUEUE_NEXT(q)) @@ -66,6 +69,17 @@ typedef void *QUEUE[2]; } \ while (0) +#define QUEUE_MOVE(h, n) \ + do { \ + if (QUEUE_EMPTY(h)) \ + QUEUE_INIT(n); \ + else { \ + QUEUE* q = QUEUE_HEAD(h); \ + QUEUE_SPLIT(h, q, n); \ + } \ + } \ + while (0) + #define QUEUE_INSERT_HEAD(h, q) \ do { \ QUEUE_NEXT(q) = QUEUE_NEXT(h); \ diff --git a/deps/uv/src/threadpool.c b/deps/uv/src/threadpool.c index 15d719944f1d0c..2c5152b4200875 100644 --- a/deps/uv/src/threadpool.c +++ b/deps/uv/src/threadpool.c @@ -223,13 +223,8 @@ void uv__work_done(uv_async_t* handle) { int err; loop = container_of(handle, uv_loop_t, wq_async); - QUEUE_INIT(&wq); - uv_mutex_lock(&loop->wq_mutex); - if (!QUEUE_EMPTY(&loop->wq)) { - q = QUEUE_HEAD(&loop->wq); - QUEUE_SPLIT(&loop->wq, q, &wq); - } + QUEUE_MOVE(&loop->wq, &wq); uv_mutex_unlock(&loop->wq_mutex); while (!QUEUE_EMPTY(&wq)) { diff --git a/deps/uv/src/unix/android-ifaddrs.c b/deps/uv/src/unix/android-ifaddrs.c index 71f7290b3263e0..30f681b7d04a41 100644 --- a/deps/uv/src/unix/android-ifaddrs.c +++ b/deps/uv/src/unix/android-ifaddrs.c @@ -1,6 +1,6 @@ /* Copyright (c) 2013, Kenneth MacKay -Copyright (c) 2014, Emergya (Cloud4all, FP7/2007-2013 grant agreement n° 289016) +Copyright (c) 2014, Emergya (Cloud4all, FP7/2007-2013 grant agreement #289016) All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/deps/uv/src/unix/async.c b/deps/uv/src/unix/async.c index 9ff24aeb3d7d87..184b598126eb2c 100644 --- a/deps/uv/src/unix/async.c +++ b/deps/uv/src/unix/async.c @@ -78,12 +78,18 @@ void uv__async_close(uv_async_t* handle) { static void uv__async_event(uv_loop_t* loop, struct uv__async* w, unsigned int nevents) { + QUEUE queue; QUEUE* q; uv_async_t* h; - QUEUE_FOREACH(q, &loop->async_handles) { + QUEUE_MOVE(&loop->async_handles, &queue); + while (!QUEUE_EMPTY(&queue)) { + q = QUEUE_HEAD(&queue); h = QUEUE_DATA(q, uv_async_t, queue); + QUEUE_REMOVE(q); + QUEUE_INSERT_TAIL(&loop->async_handles, q); + if (cmpxchgi(&h->pending, 1, 0) == 0) continue; diff --git a/deps/uv/src/unix/atomic-ops.h b/deps/uv/src/unix/atomic-ops.h index 8fb157dcc61eb4..84e471838bede7 100644 --- a/deps/uv/src/unix/atomic-ops.h +++ b/deps/uv/src/unix/atomic-ops.h @@ -18,6 +18,11 @@ #include "internal.h" /* UV_UNUSED */ +#if defined(__SUNPRO_C) || defined(__SUNPRO_CC) +#include +#define __sync_val_compare_and_swap(p, o, n) atomic_cas_ptr(p, o, n) +#endif + UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)); UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval)); UV_UNUSED(static void cpu_relax(void)); diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c index e149357e076eb2..cedd86ed34a128 100644 --- a/deps/uv/src/unix/core.c +++ b/deps/uv/src/unix/core.c @@ -75,6 +75,10 @@ #include #endif +#if defined(__ANDROID_API__) && __ANDROID_API__ < 21 +# include /* for dlsym */ +#endif + static int uv__run_pending(uv_loop_t* loop); /* Verify that uv_buf_t is ABI-compatible with struct iovec. */ @@ -204,8 +208,14 @@ int uv__getiovmax(void) { return IOV_MAX; #elif defined(_SC_IOV_MAX) static int iovmax = -1; - if (iovmax == -1) + if (iovmax == -1) { iovmax = sysconf(_SC_IOV_MAX); + /* On some embedded devices (arm-linux-uclibc based ip camera), + * sysconf(_SC_IOV_MAX) can not get the correct value. The return + * value is -1 and the errno is EINPROGRESS. Degrade the value to 1. + */ + if (iovmax == -1) iovmax = 1; + } return iovmax; #else return 1024; @@ -721,9 +731,7 @@ static int uv__run_pending(uv_loop_t* loop) { if (QUEUE_EMPTY(&loop->pending_queue)) return 0; - QUEUE_INIT(&pq); - q = QUEUE_HEAD(&loop->pending_queue); - QUEUE_SPLIT(&loop->pending_queue, q, &pq); + QUEUE_MOVE(&loop->pending_queue, &pq); while (!QUEUE_EMPTY(&pq)) { q = QUEUE_HEAD(&pq); @@ -956,16 +964,12 @@ int uv__open_cloexec(const char* path, int flags) { int uv__dup2_cloexec(int oldfd, int newfd) { int r; #if defined(__FreeBSD__) && __FreeBSD__ >= 10 - do - r = dup3(oldfd, newfd, O_CLOEXEC); - while (r == -1 && errno == EINTR); + r = dup3(oldfd, newfd, O_CLOEXEC); if (r == -1) return -errno; return r; #elif defined(__FreeBSD__) && defined(F_DUP2FD_CLOEXEC) - do - r = fcntl(oldfd, F_DUP2FD_CLOEXEC, newfd); - while (r == -1 && errno == EINTR); + r = fcntl(oldfd, F_DUP2FD_CLOEXEC, newfd); if (r != -1) return r; if (errno != EINVAL) @@ -976,7 +980,7 @@ int uv__dup2_cloexec(int oldfd, int newfd) { if (!no_dup3) { do r = uv__dup3(oldfd, newfd, UV__O_CLOEXEC); - while (r == -1 && (errno == EINTR || errno == EBUSY)); + while (r == -1 && errno == EBUSY); if (r != -1) return r; if (errno != ENOSYS) @@ -990,9 +994,9 @@ int uv__dup2_cloexec(int oldfd, int newfd) { do r = dup2(oldfd, newfd); #if defined(__linux__) - while (r == -1 && (errno == EINTR || errno == EBUSY)); + while (r == -1 && errno == EBUSY); #else - while (r == -1 && errno == EINTR); + while (0); /* Never retry. */ #endif if (r == -1) @@ -1018,6 +1022,9 @@ int uv_os_homedir(char* buffer, size_t* size) { size_t len; long initsize; int r; +#if defined(__ANDROID_API__) && __ANDROID_API__ < 21 + int (*getpwuid_r)(uid_t, struct passwd*, char*, size_t, struct passwd**); +#endif if (buffer == NULL || size == NULL || *size == 0) return -EINVAL; @@ -1039,6 +1046,12 @@ int uv_os_homedir(char* buffer, size_t* size) { return 0; } +#if defined(__ANDROID_API__) && __ANDROID_API__ < 21 + getpwuid_r = dlsym(RTLD_DEFAULT, "getpwuid_r"); + if (getpwuid_r == NULL) + return -ENOSYS; +#endif + /* HOME is not set, so call getpwuid() */ initsize = sysconf(_SC_GETPW_R_SIZE_MAX); diff --git a/deps/uv/src/unix/darwin.c b/deps/uv/src/unix/darwin.c index dab6ca999d05f6..cf95da21693b9a 100644 --- a/deps/uv/src/unix/darwin.c +++ b/deps/uv/src/unix/darwin.c @@ -258,8 +258,10 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { } *addresses = uv__malloc(*count * sizeof(**addresses)); - if (!(*addresses)) + if (!(*addresses)) { + freeifaddrs(addrs); return -ENOMEM; + } address = *addresses; diff --git a/deps/uv/src/unix/dl.c b/deps/uv/src/unix/dl.c index 7c6d41c969b25f..fc1c052bb8122e 100644 --- a/deps/uv/src/unix/dl.c +++ b/deps/uv/src/unix/dl.c @@ -39,10 +39,8 @@ int uv_dlopen(const char* filename, uv_lib_t* lib) { void uv_dlclose(uv_lib_t* lib) { - if (lib->errmsg) { - uv__free(lib->errmsg); - lib->errmsg = NULL; - } + uv__free(lib->errmsg); + lib->errmsg = NULL; if (lib->handle) { /* Ignore errors. No good way to signal them without leaking memory. */ @@ -67,8 +65,7 @@ const char* uv_dlerror(const uv_lib_t* lib) { static int uv__dlerror(uv_lib_t* lib) { const char* errmsg; - if (lib->errmsg) - uv__free(lib->errmsg); + uv__free(lib->errmsg); errmsg = dlerror(); diff --git a/deps/uv/src/unix/freebsd.c b/deps/uv/src/unix/freebsd.c index c69608b139973b..b747abdf5bc46e 100644 --- a/deps/uv/src/unix/freebsd.c +++ b/deps/uv/src/unix/freebsd.c @@ -176,7 +176,7 @@ char** uv_setup_args(int argc, char** argv) { int uv_set_process_title(const char* title) { int oid[4]; - if (process_title) uv__free(process_title); + uv__free(process_title); process_title = uv__strdup(title); oid[0] = CTL_KERN; @@ -373,8 +373,10 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { } *addresses = uv__malloc(*count * sizeof(**addresses)); - if (!(*addresses)) + if (!(*addresses)) { + freeifaddrs(addrs); return -ENOMEM; + } address = *addresses; diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c index d739c282585f71..57b65be25a85ea 100644 --- a/deps/uv/src/unix/fs.c +++ b/deps/uv/src/unix/fs.c @@ -80,8 +80,10 @@ req->path = path; \ } else { \ req->path = uv__strdup(path); \ - if (req->path == NULL) \ + if (req->path == NULL) { \ + uv__req_unregister(loop, req); \ return -ENOMEM; \ + } \ } \ } \ while (0) @@ -97,8 +99,10 @@ path_len = strlen(path) + 1; \ new_path_len = strlen(new_path) + 1; \ req->path = uv__malloc(path_len + new_path_len); \ - if (req->path == NULL) \ + if (req->path == NULL) { \ + uv__req_unregister(loop, req); \ return -ENOMEM; \ + } \ req->new_path = req->path + path_len; \ memcpy((void*) req->path, path, path_len); \ memcpy((void*) req->new_path, new_path, new_path_len); \ @@ -370,20 +374,27 @@ static ssize_t uv__fs_scandir(uv_fs_t* req) { } -static ssize_t uv__fs_readlink(uv_fs_t* req) { - ssize_t len; - char* buf; +static ssize_t uv__fs_pathmax_size(const char* path) { + ssize_t pathmax; - len = pathconf(req->path, _PC_PATH_MAX); + pathmax = pathconf(path, _PC_PATH_MAX); - if (len == -1) { + if (pathmax == -1) { #if defined(PATH_MAX) - len = PATH_MAX; + return PATH_MAX; #else - len = 4096; + return 4096; #endif } + return pathmax; +} + +static ssize_t uv__fs_readlink(uv_fs_t* req) { + ssize_t len; + char* buf; + + len = uv__fs_pathmax_size(req->path); buf = uv__malloc(len + 1); if (buf == NULL) { @@ -404,6 +415,27 @@ static ssize_t uv__fs_readlink(uv_fs_t* req) { return 0; } +static ssize_t uv__fs_realpath(uv_fs_t* req) { + ssize_t len; + char* buf; + + len = uv__fs_pathmax_size(req->path); + buf = uv__malloc(len + 1); + + if (buf == NULL) { + errno = ENOMEM; + return -1; + } + + if (realpath(req->path, buf) == NULL) { + uv__free(buf); + return -1; + } + + req->ptr = buf; + + return 0; +} static ssize_t uv__fs_sendfile_emul(uv_fs_t* req) { struct pollfd pfd; @@ -626,7 +658,9 @@ static ssize_t uv__fs_write(uv_fs_t* req) { */ #if defined(__APPLE__) static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; - pthread_mutex_lock(&lock); + + if (pthread_mutex_lock(&lock)) + abort(); #endif if (req->off < 0) { @@ -683,7 +717,8 @@ static ssize_t uv__fs_write(uv_fs_t* req) { done: #if defined(__APPLE__) - pthread_mutex_unlock(&lock); + if (pthread_mutex_unlock(&lock)) + abort(); #endif return r; @@ -867,6 +902,7 @@ static void uv__fs_work(struct uv__work* w) { X(READ, uv__fs_buf_iter(req, uv__fs_read)); X(SCANDIR, uv__fs_scandir(req)); X(READLINK, uv__fs_readlink(req)); + X(REALPATH, uv__fs_realpath(req)); X(RENAME, rename(req->path, req->new_path)); X(RMDIR, rmdir(req->path)); X(SENDFILE, uv__fs_sendfile(req)); @@ -1062,8 +1098,11 @@ int uv_fs_mkdtemp(uv_loop_t* loop, uv_fs_cb cb) { INIT(MKDTEMP); req->path = uv__strdup(tpl); - if (req->path == NULL) + if (req->path == NULL) { + if (cb != NULL) + uv__req_unregister(loop, req); return -ENOMEM; + } POST; } @@ -1099,8 +1138,11 @@ int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, if (nbufs > ARRAY_SIZE(req->bufsml)) req->bufs = uv__malloc(nbufs * sizeof(*bufs)); - if (req->bufs == NULL) + if (req->bufs == NULL) { + if (cb != NULL) + uv__req_unregister(loop, req); return -ENOMEM; + } memcpy(req->bufs, bufs, nbufs * sizeof(*bufs)); @@ -1131,6 +1173,16 @@ int uv_fs_readlink(uv_loop_t* loop, } +int uv_fs_realpath(uv_loop_t* loop, + uv_fs_t* req, + const char * path, + uv_fs_cb cb) { + INIT(REALPATH); + PATH; + POST; +} + + int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path, @@ -1224,8 +1276,11 @@ int uv_fs_write(uv_loop_t* loop, if (nbufs > ARRAY_SIZE(req->bufsml)) req->bufs = uv__malloc(nbufs * sizeof(*bufs)); - if (req->bufs == NULL) + if (req->bufs == NULL) { + if (cb != NULL) + uv__req_unregister(loop, req); return -ENOMEM; + } memcpy(req->bufs, bufs, nbufs * sizeof(*bufs)); diff --git a/deps/uv/src/unix/fsevents.c b/deps/uv/src/unix/fsevents.c index 8143f7c1f018db..d331a13172675e 100644 --- a/deps/uv/src/unix/fsevents.c +++ b/deps/uv/src/unix/fsevents.c @@ -73,9 +73,16 @@ typedef struct uv__fsevents_event_s uv__fsevents_event_t; typedef struct uv__cf_loop_signal_s uv__cf_loop_signal_t; typedef struct uv__cf_loop_state_s uv__cf_loop_state_t; +enum uv__cf_loop_signal_type_e { + kUVCFLoopSignalRegular, + kUVCFLoopSignalClosing +}; +typedef enum uv__cf_loop_signal_type_e uv__cf_loop_signal_type_t; + struct uv__cf_loop_signal_s { QUEUE member; uv_fs_event_t* handle; + uv__cf_loop_signal_type_t type; }; struct uv__fsevents_event_s { @@ -98,7 +105,9 @@ struct uv__cf_loop_state_s { /* Forward declarations */ static void uv__cf_loop_cb(void* arg); static void* uv__cf_loop_runner(void* arg); -static int uv__cf_loop_signal(uv_loop_t* loop, uv_fs_event_t* handle); +static int uv__cf_loop_signal(uv_loop_t* loop, + uv_fs_event_t* handle, + uv__cf_loop_signal_type_t type); /* Lazy-loaded by uv__fsevents_global_init(). */ static CFArrayRef (*pCFArrayCreate)(CFAllocatorRef, @@ -149,11 +158,7 @@ static void (*pFSEventStreamStop)(FSEventStreamRef); int err; \ uv_mutex_lock(&(handle)->cf_mutex); \ /* Split-off all events and empty original queue */ \ - QUEUE_INIT(&events); \ - if (!QUEUE_EMPTY(&(handle)->cf_events)) { \ - q = QUEUE_HEAD(&(handle)->cf_events); \ - QUEUE_SPLIT(&(handle)->cf_events, q, &events); \ - } \ + QUEUE_MOVE(&(handle)->cf_events, &events); \ /* Get error (if any) and zero original one */ \ err = (handle)->cf_error; \ (handle)->cf_error = 0; \ @@ -387,7 +392,8 @@ static void uv__fsevents_destroy_stream(uv_loop_t* loop) { /* Runs in CF thread, when there're new fsevent handles to add to stream */ -static void uv__fsevents_reschedule(uv_fs_event_t* handle) { +static void uv__fsevents_reschedule(uv_fs_event_t* handle, + uv__cf_loop_signal_type_t type) { uv__cf_loop_state_t* state; QUEUE* q; uv_fs_event_t* curr; @@ -486,7 +492,7 @@ static void uv__fsevents_reschedule(uv_fs_event_t* handle) { * * NOTE: This is coupled with `uv_sem_wait()` in `uv__fsevents_close` */ - if (!uv__is_active(handle)) + if (type == kUVCFLoopSignalClosing) uv_sem_post(&state->fsevent_sem); } @@ -676,7 +682,7 @@ void uv__fsevents_loop_delete(uv_loop_t* loop) { if (loop->cf_state == NULL) return; - if (uv__cf_loop_signal(loop, NULL) != 0) + if (uv__cf_loop_signal(loop, NULL, kUVCFLoopSignalRegular) != 0) abort(); uv_thread_join(&loop->cf_thread); @@ -735,17 +741,14 @@ static void uv__cf_loop_cb(void* arg) { loop = arg; state = loop->cf_state; - QUEUE_INIT(&split_head); uv_mutex_lock(&loop->cf_mutex); - if (!QUEUE_EMPTY(&loop->cf_signals)) { - QUEUE* split_pos = QUEUE_HEAD(&loop->cf_signals); - QUEUE_SPLIT(&loop->cf_signals, split_pos, &split_head); - } + QUEUE_MOVE(&loop->cf_signals, &split_head); uv_mutex_unlock(&loop->cf_mutex); while (!QUEUE_EMPTY(&split_head)) { item = QUEUE_HEAD(&split_head); + QUEUE_REMOVE(item); s = QUEUE_DATA(item, uv__cf_loop_signal_t, member); @@ -753,16 +756,17 @@ static void uv__cf_loop_cb(void* arg) { if (s->handle == NULL) pCFRunLoopStop(state->loop); else - uv__fsevents_reschedule(s->handle); + uv__fsevents_reschedule(s->handle, s->type); - QUEUE_REMOVE(item); uv__free(s); } } /* Runs in UV loop to notify CF thread */ -int uv__cf_loop_signal(uv_loop_t* loop, uv_fs_event_t* handle) { +int uv__cf_loop_signal(uv_loop_t* loop, + uv_fs_event_t* handle, + uv__cf_loop_signal_type_t type) { uv__cf_loop_signal_t* item; uv__cf_loop_state_t* state; @@ -771,6 +775,7 @@ int uv__cf_loop_signal(uv_loop_t* loop, uv_fs_event_t* handle) { return -ENOMEM; item->handle = handle; + item->type = type; uv_mutex_lock(&loop->cf_mutex); QUEUE_INSERT_TAIL(&loop->cf_signals, &item->member); @@ -833,7 +838,7 @@ int uv__fsevents_init(uv_fs_event_t* handle) { /* Reschedule FSEventStream */ assert(handle != NULL); - err = uv__cf_loop_signal(handle->loop, handle); + err = uv__cf_loop_signal(handle->loop, handle, kUVCFLoopSignalRegular); if (err) goto fail_loop_signal; @@ -873,7 +878,7 @@ int uv__fsevents_close(uv_fs_event_t* handle) { /* Reschedule FSEventStream */ assert(handle != NULL); - err = uv__cf_loop_signal(handle->loop, handle); + err = uv__cf_loop_signal(handle->loop, handle, kUVCFLoopSignalClosing); if (err) return -err; diff --git a/deps/uv/src/unix/linux-core.c b/deps/uv/src/unix/linux-core.c index e6e68283d58d07..3ff6fb15e93557 100644 --- a/deps/uv/src/unix/linux-core.c +++ b/deps/uv/src/unix/linux-core.c @@ -814,8 +814,10 @@ int uv_interface_addresses(uv_interface_address_t** addresses, return 0; *addresses = uv__malloc(*count * sizeof(**addresses)); - if (!(*addresses)) + if (!(*addresses)) { + freeifaddrs(addrs); return -ENOMEM; + } address = *addresses; diff --git a/deps/uv/src/unix/linux-inotify.c b/deps/uv/src/unix/linux-inotify.c index d9ed9f4b24512b..282912115d8120 100644 --- a/deps/uv/src/unix/linux-inotify.c +++ b/deps/uv/src/unix/linux-inotify.c @@ -35,6 +35,7 @@ struct watcher_list { RB_ENTRY(watcher_list) entry; QUEUE watchers; + int iterating; char* path; int wd; }; @@ -113,6 +114,15 @@ static struct watcher_list* find_watcher(uv_loop_t* loop, int wd) { return RB_FIND(watcher_root, CAST(&loop->inotify_watchers), &w); } +static void maybe_free_watcher_list(struct watcher_list* w, uv_loop_t* loop) { + /* if the watcher_list->watchers is being iterated over, we can't free it. */ + if ((!w->iterating) && QUEUE_EMPTY(&w->watchers)) { + /* No watchers left for this path. Clean up. */ + RB_REMOVE(watcher_root, CAST(&loop->inotify_watchers), w); + uv__inotify_rm_watch(loop->inotify_fd, w->wd); + uv__free(w); + } +} static void uv__inotify_read(uv_loop_t* loop, uv__io_t* dummy, @@ -120,6 +130,7 @@ static void uv__inotify_read(uv_loop_t* loop, const struct uv__inotify_event* e; struct watcher_list* w; uv_fs_event_t* h; + QUEUE queue; QUEUE* q; const char* path; ssize_t size; @@ -159,10 +170,31 @@ static void uv__inotify_read(uv_loop_t* loop, */ path = e->len ? (const char*) (e + 1) : uv__basename_r(w->path); - QUEUE_FOREACH(q, &w->watchers) { + /* We're about to iterate over the queue and call user's callbacks. + * What can go wrong? + * A callback could call uv_fs_event_stop() + * and the queue can change under our feet. + * So, we use QUEUE_MOVE() trick to safely iterate over the queue. + * And we don't free the watcher_list until we're done iterating. + * + * First, + * tell uv_fs_event_stop() (that could be called from a user's callback) + * not to free watcher_list. + */ + w->iterating = 1; + QUEUE_MOVE(&w->watchers, &queue); + while (!QUEUE_EMPTY(&queue)) { + q = QUEUE_HEAD(&queue); h = QUEUE_DATA(q, uv_fs_event_t, watchers); + + QUEUE_REMOVE(q); + QUEUE_INSERT_TAIL(&w->watchers, q); + h->cb(h, path, events, 0); } + /* done iterating, time to (maybe) free empty watcher_list */ + w->iterating = 0; + maybe_free_watcher_list(w, loop); } } } @@ -214,6 +246,7 @@ int uv_fs_event_start(uv_fs_event_t* handle, w->wd = wd; w->path = strcpy((char*)(w + 1), path); QUEUE_INIT(&w->watchers); + w->iterating = 0; RB_INSERT(watcher_root, CAST(&handle->loop->inotify_watchers), w); no_insert: @@ -241,12 +274,7 @@ int uv_fs_event_stop(uv_fs_event_t* handle) { uv__handle_stop(handle); QUEUE_REMOVE(&handle->watchers); - if (QUEUE_EMPTY(&w->watchers)) { - /* No watchers left for this path. Clean up. */ - RB_REMOVE(watcher_root, CAST(&handle->loop->inotify_watchers), w); - uv__inotify_rm_watch(handle->loop->inotify_fd, w->wd); - uv__free(w); - } + maybe_free_watcher_list(w, handle->loop); return 0; } diff --git a/deps/uv/src/unix/linux-syscalls.c b/deps/uv/src/unix/linux-syscalls.c index 566e1f37cfed12..89998ded26b17c 100644 --- a/deps/uv/src/unix/linux-syscalls.c +++ b/deps/uv/src/unix/linux-syscalls.c @@ -444,18 +444,18 @@ int uv__utimesat(int dirfd, } -ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset) { +ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, int64_t offset) { #if defined(__NR_preadv) - return syscall(__NR_preadv, fd, iov, iovcnt, offset); + return syscall(__NR_preadv, fd, iov, iovcnt, (long)offset, (long)(offset >> 32)); #else return errno = ENOSYS, -1; #endif } -ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset) { +ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset) { #if defined(__NR_pwritev) - return syscall(__NR_pwritev, fd, iov, iovcnt, offset); + return syscall(__NR_pwritev, fd, iov, iovcnt, (long)offset, (long)(offset >> 32)); #else return errno = ENOSYS, -1; #endif diff --git a/deps/uv/src/unix/linux-syscalls.h b/deps/uv/src/unix/linux-syscalls.h index 6f249b72453675..96e79439cf07ab 100644 --- a/deps/uv/src/unix/linux-syscalls.h +++ b/deps/uv/src/unix/linux-syscalls.h @@ -151,8 +151,8 @@ int uv__utimesat(int dirfd, const char* path, const struct timespec times[2], int flags); -ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset); -ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset); +ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, int64_t offset); +ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset); int uv__dup3(int oldfd, int newfd, int flags); #endif /* UV_LINUX_SYSCALL_H_ */ diff --git a/deps/uv/src/unix/loop-watcher.c b/deps/uv/src/unix/loop-watcher.c index dc25760bd5344c..340bb0dfa11350 100644 --- a/deps/uv/src/unix/loop-watcher.c +++ b/deps/uv/src/unix/loop-watcher.c @@ -47,9 +47,14 @@ \ void uv__run_##name(uv_loop_t* loop) { \ uv_##name##_t* h; \ + QUEUE queue; \ QUEUE* q; \ - QUEUE_FOREACH(q, &loop->name##_handles) { \ + QUEUE_MOVE(&loop->name##_handles, &queue); \ + while (!QUEUE_EMPTY(&queue)) { \ + q = QUEUE_HEAD(&queue); \ h = QUEUE_DATA(q, uv_##name##_t, queue); \ + QUEUE_REMOVE(q); \ + QUEUE_INSERT_TAIL(&loop->name##_handles, q); \ h->name##_cb(h); \ } \ } \ diff --git a/deps/uv/src/unix/netbsd.c b/deps/uv/src/unix/netbsd.c index 29f2a4dec63831..ca48550f9d99d4 100644 --- a/deps/uv/src/unix/netbsd.c +++ b/deps/uv/src/unix/netbsd.c @@ -298,8 +298,10 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { *addresses = uv__malloc(*count * sizeof(**addresses)); - if (!(*addresses)) + if (!(*addresses)) { + freeifaddrs(addrs); return -ENOMEM; + } address = *addresses; diff --git a/deps/uv/src/unix/openbsd.c b/deps/uv/src/unix/openbsd.c index c8d54599386efe..6a3909a666c1d0 100644 --- a/deps/uv/src/unix/openbsd.c +++ b/deps/uv/src/unix/openbsd.c @@ -161,7 +161,7 @@ char** uv_setup_args(int argc, char** argv) { int uv_set_process_title(const char* title) { - if (process_title) uv__free(process_title); + uv__free(process_title); process_title = uv__strdup(title); setproctitle(title); return 0; @@ -313,8 +313,10 @@ int uv_interface_addresses(uv_interface_address_t** addresses, *addresses = uv__malloc(*count * sizeof(**addresses)); - if (!(*addresses)) + if (!(*addresses)) { + freeifaddrs(addrs); return -ENOMEM; + } address = *addresses; diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c index 9fa061e6bc99b6..571f8cd778c74f 100644 --- a/deps/uv/src/unix/process.c +++ b/deps/uv/src/unix/process.c @@ -270,6 +270,11 @@ static void uv__write_int(int fd, int val) { } +#if !(defined(__APPLE__) && (TARGET_OS_TV || TARGET_OS_WATCH)) +/* execvp is marked __WATCHOS_PROHIBITED __TVOS_PROHIBITED, so must be + * avoided. Since this isn't called on those targets, the function + * doesn't even need to be defined for them. + */ static void uv__process_child_init(const uv_process_options_t* options, int stdio_count, int (*pipes)[2], @@ -375,11 +380,16 @@ static void uv__process_child_init(const uv_process_options_t* options, uv__write_int(error_fd, -errno); _exit(127); } +#endif int uv_spawn(uv_loop_t* loop, uv_process_t* process, const uv_process_options_t* options) { +#if defined(__APPLE__) && (TARGET_OS_TV || TARGET_OS_WATCH) + /* fork is marked __WATCHOS_PROHIBITED __TVOS_PROHIBITED. */ + return -ENOSYS; +#else int signal_pipe[2] = { -1, -1 }; int (*pipes)[2]; int stdio_count; @@ -528,6 +538,7 @@ int uv_spawn(uv_loop_t* loop, } return err; +#endif } diff --git a/deps/uv/src/unix/signal.c b/deps/uv/src/unix/signal.c index 0b7a405c15da65..edd9085d3f352f 100644 --- a/deps/uv/src/unix/signal.c +++ b/deps/uv/src/unix/signal.c @@ -234,6 +234,8 @@ void uv__signal_loop_cleanup(uv_loop_t* loop) { /* Stop all the signal watchers that are still attached to this loop. This * ensures that the (shared) signal tree doesn't contain any invalid entries * entries, and that signal handlers are removed when appropriate. + * It's safe to use QUEUE_FOREACH here because the handles and the handle + * queue are not modified by uv__signal_stop(). */ QUEUE_FOREACH(q, &loop->handle_queue) { uv_handle_t* handle = QUEUE_DATA(q, uv_handle_t, handle_queue); diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c index 183b68cf7165b0..7d7ab2633b6f2d 100644 --- a/deps/uv/src/unix/stream.c +++ b/deps/uv/src/unix/stream.c @@ -779,9 +779,9 @@ static void uv__write(uv_stream_t* stream) { if (req->send_handle) { struct msghdr msg; - char scratch[64]; struct cmsghdr *cmsg; int fd_to_send = uv__handle_fd((uv_handle_t*) req->send_handle); + char scratch[64] = {0}; assert(fd_to_send >= 0); @@ -1471,7 +1471,7 @@ int uv_try_write(uv_stream_t* stream, uv__stream_osx_interrupt_select(stream); } - if (written == 0) + if (written == 0 && req_size != 0) return -EAGAIN; else return written; diff --git a/deps/uv/src/unix/sunos.c b/deps/uv/src/unix/sunos.c index 05b7a114031178..0c46817b446e61 100644 --- a/deps/uv/src/unix/sunos.c +++ b/deps/uv/src/unix/sunos.c @@ -693,8 +693,10 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { } *addresses = uv__malloc(*count * sizeof(**addresses)); - if (!(*addresses)) + if (!(*addresses)) { + freeifaddrs(addrs); return -ENOMEM; + } address = *addresses; diff --git a/deps/uv/src/unix/tty.c b/deps/uv/src/unix/tty.c index 54c9055a08ae12..7cc5b714ed302c 100644 --- a/deps/uv/src/unix/tty.c +++ b/deps/uv/src/unix/tty.c @@ -236,6 +236,15 @@ uv_handle_type uv_guess_handle(uv_file file) { return UV_UDP; if (type == SOCK_STREAM) { +#if defined(_AIX) + /* on AIX the getsockname call returns an empty sa structure + * for sockets of type AF_UNIX. For all other types it will + * return a properly filled in structure. + */ + if (len == 0) + return UV_NAMED_PIPE; +#endif /* defined(_AIX) */ + if (sa.sa_family == AF_INET || sa.sa_family == AF_INET6) return UV_TCP; if (sa.sa_family == AF_UNIX) diff --git a/deps/uv/src/unix/udp.c b/deps/uv/src/unix/udp.c index 66ecc4e341b913..39ade8de338afc 100644 --- a/deps/uv/src/unix/udp.c +++ b/deps/uv/src/unix/udp.c @@ -410,8 +410,10 @@ int uv__udp_send(uv_udp_send_t* req, if (nbufs > ARRAY_SIZE(req->bufsml)) req->bufs = uv__malloc(nbufs * sizeof(bufs[0])); - if (req->bufs == NULL) + if (req->bufs == NULL) { + uv__req_unregister(handle->loop, req); return -ENOMEM; + } memcpy(req->bufs, bufs, nbufs * sizeof(bufs[0])); handle->send_queue_size += uv__count_bufs(req->bufs, req->nbufs); diff --git a/deps/uv/src/uv-common.c b/deps/uv/src/uv-common.c index 675a776bf4ae1e..40ed28fec5a662 100644 --- a/deps/uv/src/uv-common.c +++ b/deps/uv/src/uv-common.c @@ -141,11 +141,7 @@ static const char* uv__unknown_err_code(int err) { char buf[32]; char* copy; -#ifndef _WIN32 snprintf(buf, sizeof(buf), "Unknown system error %d", err); -#else - _snprintf(buf, sizeof(buf), "Unknown system error %d", err); -#endif copy = uv__strdup(buf); return copy != NULL ? copy : "Unknown system error"; @@ -341,19 +337,25 @@ int uv_udp_recv_stop(uv_udp_t* handle) { void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg) { + QUEUE queue; QUEUE* q; uv_handle_t* h; - QUEUE_FOREACH(q, &loop->handle_queue) { + QUEUE_MOVE(&loop->handle_queue, &queue); + while (!QUEUE_EMPTY(&queue)) { + q = QUEUE_HEAD(&queue); h = QUEUE_DATA(q, uv_handle_t, handle_queue); + + QUEUE_REMOVE(q); + QUEUE_INSERT_TAIL(&loop->handle_queue, q); + if (h->flags & UV__HANDLE_INTERNAL) continue; walk_cb(h, arg); } } -#ifndef NDEBUG -static void uv__print_handles(uv_loop_t* loop, int only_active) { +static void uv__print_handles(uv_loop_t* loop, int only_active, FILE* stream) { const char* type; QUEUE* q; uv_handle_t* h; @@ -374,7 +376,7 @@ static void uv__print_handles(uv_loop_t* loop, int only_active) { default: type = ""; } - fprintf(stderr, + fprintf(stream, "[%c%c%c] %-8s %p\n", "R-"[!(h->flags & UV__HANDLE_REF)], "A-"[!(h->flags & UV__HANDLE_ACTIVE)], @@ -385,15 +387,14 @@ static void uv__print_handles(uv_loop_t* loop, int only_active) { } -void uv_print_all_handles(uv_loop_t* loop) { - uv__print_handles(loop, 0); +void uv_print_all_handles(uv_loop_t* loop, FILE* stream) { + uv__print_handles(loop, 0, stream); } -void uv_print_active_handles(uv_loop_t* loop) { - uv__print_handles(loop, 1); +void uv_print_active_handles(uv_loop_t* loop, FILE* stream) { + uv__print_handles(loop, 1, stream); } -#endif void uv_ref(uv_handle_t* handle) { diff --git a/deps/uv/src/uv-common.h b/deps/uv/src/uv-common.h index b348ec76bd50bd..27902fdf8645f7 100644 --- a/deps/uv/src/uv-common.h +++ b/deps/uv/src/uv-common.h @@ -41,6 +41,10 @@ #include "tree.h" #include "queue.h" +#if !defined(snprintf) && defined(_MSC_VER) && _MSC_VER < 1900 +extern int snprintf(char*, size_t, const char*, ...); +#endif + #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) #define container_of(ptr, type, member) \ diff --git a/deps/uv/src/win/error.c b/deps/uv/src/win/error.c index a265a272dced19..c512f35af979a3 100644 --- a/deps/uv/src/win/error.c +++ b/deps/uv/src/win/error.c @@ -129,6 +129,7 @@ int uv_translate_sys_error(int sys_errno) { case ERROR_NETWORK_UNREACHABLE: return UV_ENETUNREACH; case WSAENETUNREACH: return UV_ENETUNREACH; case WSAENOBUFS: return UV_ENOBUFS; + case ERROR_BAD_PATHNAME: return UV_ENOENT; case ERROR_DIRECTORY: return UV_ENOENT; case ERROR_FILE_NOT_FOUND: return UV_ENOENT; case ERROR_INVALID_NAME: return UV_ENOENT; diff --git a/deps/uv/src/win/fs-event.c b/deps/uv/src/win/fs-event.c index ba68f78c82a610..76ecfebaa24c39 100644 --- a/deps/uv/src/win/fs-event.c +++ b/deps/uv/src/win/fs-event.c @@ -381,9 +381,10 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req, if (handle->dirw) { /* - * We attempt to convert the file name to its long form for - * events that still point to valid files on disk. - * For removed and renamed events, we do not provide the file name. + * We attempt to resolve the long form of the file name explicitly. + * We only do this for file names that might still exist on disk. + * If this fails, we use the name given by ReadDirectoryChangesW. + * This may be the long form or the 8.3 short name in some cases. */ if (file_info->Action != FILE_ACTION_REMOVED && file_info->Action != FILE_ACTION_RENAMED_OLD_NAME) { @@ -438,16 +439,24 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req, } /* - * If we couldn't get the long name - just use the name - * provided by ReadDirectoryChangesW. + * We could not resolve the long form explicitly. + * We therefore use the name given by ReadDirectoryChangesW. + * This may be the long form or the 8.3 short name in some cases. */ if (!long_filenamew) { filenamew = file_info->FileName; sizew = file_info->FileNameLength / sizeof(WCHAR); } } else { - /* Removed or renamed callbacks don't provide filename. */ - filenamew = NULL; + /* + * Removed or renamed events cannot be resolved to the long form. + * We therefore use the name given by ReadDirectoryChangesW. + * This may be the long form or the 8.3 short name in some cases. + */ + if (!long_filenamew) { + filenamew = file_info->FileName; + sizew = file_info->FileNameLength / sizeof(WCHAR); + } } } else { /* We already have the long name of the file, so just use it. */ diff --git a/deps/uv/src/win/fs.c b/deps/uv/src/win/fs.c index 4a17573113ff9b..a32b0127f7e1e9 100644 --- a/deps/uv/src/win/fs.c +++ b/deps/uv/src/win/fs.c @@ -110,6 +110,9 @@ const WCHAR JUNCTION_PREFIX_LEN = 4; const WCHAR LONG_PATH_PREFIX[] = L"\\\\?\\"; const WCHAR LONG_PATH_PREFIX_LEN = 4; +const WCHAR UNC_PATH_PREFIX[] = L"\\\\?\\UNC\\"; +const WCHAR UNC_PATH_PREFIX_LEN = 8; + void uv_fs_init() { _fmode = _O_BINARY; @@ -233,14 +236,61 @@ INLINE static void uv_fs_req_init(uv_loop_t* loop, uv_fs_t* req, } +static int fs__wide_to_utf8(WCHAR* w_source_ptr, + DWORD w_source_len, + char** target_ptr, + uint64_t* target_len_ptr) { + int r; + int target_len; + char* target; + target_len = WideCharToMultiByte(CP_UTF8, + 0, + w_source_ptr, + w_source_len, + NULL, + 0, + NULL, + NULL); + + if (target_len == 0) { + return -1; + } + + if (target_len_ptr != NULL) { + *target_len_ptr = target_len; + } + + if (target_ptr == NULL) { + return 0; + } + + target = uv__malloc(target_len + 1); + if (target == NULL) { + SetLastError(ERROR_OUTOFMEMORY); + return -1; + } + + r = WideCharToMultiByte(CP_UTF8, + 0, + w_source_ptr, + w_source_len, + target, + target_len, + NULL, + NULL); + assert(r == target_len); + target[target_len] = '\0'; + *target_ptr = target; + return 0; +} + + INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr, uint64_t* target_len_ptr) { char buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; REPARSE_DATA_BUFFER* reparse_data = (REPARSE_DATA_BUFFER*) buffer; - WCHAR *w_target; + WCHAR* w_target; DWORD w_target_len; - char* target; - int target_len; DWORD bytes; if (!DeviceIoControl(handle, @@ -333,50 +383,7 @@ INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr, return -1; } - /* If needed, compute the length of the target. */ - if (target_ptr != NULL || target_len_ptr != NULL) { - /* Compute the length of the target. */ - target_len = WideCharToMultiByte(CP_UTF8, - 0, - w_target, - w_target_len, - NULL, - 0, - NULL, - NULL); - if (target_len == 0) { - return -1; - } - } - - /* If requested, allocate memory and convert to UTF8. */ - if (target_ptr != NULL) { - int r; - target = (char*) uv__malloc(target_len + 1); - if (target == NULL) { - SetLastError(ERROR_OUTOFMEMORY); - return -1; - } - - r = WideCharToMultiByte(CP_UTF8, - 0, - w_target, - w_target_len, - target, - target_len, - NULL, - NULL); - assert(r == target_len); - target[target_len] = '\0'; - - *target_ptr = target; - } - - if (target_len_ptr != NULL) { - *target_len_ptr = target_len; - } - - return 0; + return fs__wide_to_utf8(w_target, w_target_len, target_ptr, target_len_ptr); } @@ -533,7 +540,15 @@ void fs__close(uv_fs_t* req) { else result = 0; - SET_REQ_RESULT(req, result); + /* _close doesn't set _doserrno on failure, but it does always set errno + * to EBADF on failure. + */ + if (result == -1) { + assert(errno == EBADF); + SET_REQ_UV_ERROR(req, UV_EBADF, ERROR_INVALID_HANDLE); + } else { + req->result = 0; + } } @@ -1699,6 +1714,84 @@ static void fs__readlink(uv_fs_t* req) { } +static size_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) { + int r; + DWORD w_realpath_len; + WCHAR* w_realpath_ptr; + WCHAR* w_finalpath_ptr = NULL; + + w_realpath_len = pGetFinalPathNameByHandleW(handle, NULL, 0, VOLUME_NAME_DOS); + if (w_realpath_len == 0) { + return -1; + } + + w_realpath_ptr = uv__malloc((w_realpath_len + 1) * sizeof(WCHAR)); + if (w_realpath_ptr == NULL) { + SetLastError(ERROR_OUTOFMEMORY); + return -1; + } + + if (pGetFinalPathNameByHandleW(handle, + w_realpath_ptr, + w_realpath_len, + VOLUME_NAME_DOS) == 0) { + uv__free(w_realpath_ptr); + SetLastError(ERROR_INVALID_HANDLE); + return -1; + } + + /* convert UNC path to long path */ + if (wcsncmp(w_realpath_ptr, + UNC_PATH_PREFIX, + UNC_PATH_PREFIX_LEN) == 0) { + w_finalpath_ptr = w_realpath_ptr + 6; + *w_finalpath_ptr = L'\\'; + } else if (wcsncmp(w_realpath_ptr, + LONG_PATH_PREFIX, + LONG_PATH_PREFIX_LEN) == 0) { + w_finalpath_ptr = w_realpath_ptr + 4; + } else { + uv__free(w_realpath_ptr); + SetLastError(ERROR_INVALID_HANDLE); + return -1; + } + + r = fs__wide_to_utf8(w_finalpath_ptr, w_realpath_len, realpath_ptr, NULL); + uv__free(w_realpath_ptr); + return r; +} + +static void fs__realpath(uv_fs_t* req) { + HANDLE handle; + + if (!pGetFinalPathNameByHandleW) { + SET_REQ_UV_ERROR(req, UV_ENOSYS, ERROR_NOT_SUPPORTED); + return; + } + + handle = CreateFileW(req->file.pathw, + 0, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, + NULL); + if (handle == INVALID_HANDLE_VALUE) { + SET_REQ_WIN32_ERROR(req, GetLastError()); + return; + } + + if (fs__realpath_handle(handle, (char**) &req->ptr) == -1) { + CloseHandle(handle); + SET_REQ_WIN32_ERROR(req, GetLastError()); + return; + } + + CloseHandle(handle); + req->flags |= UV_FS_FREE_PTR; + SET_REQ_RESULT(req, 0); +} + static void fs__chown(uv_fs_t* req) { req->result = 0; @@ -1743,6 +1836,7 @@ static void uv__fs_work(struct uv__work* w) { XX(LINK, link) XX(SYMLINK, symlink) XX(READLINK, readlink) + XX(REALPATH, realpath) XX(CHOWN, chown) XX(FCHOWN, fchown); default: @@ -2067,6 +2161,31 @@ int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path, } +int uv_fs_realpath(uv_loop_t* loop, uv_fs_t* req, const char* path, + uv_fs_cb cb) { + int err; + + if (!req || !path) { + return UV_EINVAL; + } + + uv_fs_req_init(loop, req, UV_FS_REALPATH, cb); + + err = fs__capture_path(req, path, NULL, cb != NULL); + if (err) { + return uv_translate_sys_error(err); + } + + if (cb) { + QUEUE_FS_TP_JOB(loop, req); + return 0; + } else { + fs__realpath(req); + return req->result; + } +} + + int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb) { int err; diff --git a/deps/uv/src/win/getaddrinfo.c b/deps/uv/src/win/getaddrinfo.c index 3d23660e884c5d..ceed3b7638b457 100644 --- a/deps/uv/src/win/getaddrinfo.c +++ b/deps/uv/src/win/getaddrinfo.c @@ -109,10 +109,8 @@ static void uv__getaddrinfo_done(struct uv__work* w, int status) { req = container_of(w, uv_getaddrinfo_t, work_req); /* release input parameter memory */ - if (req->alloc != NULL) { - uv__free(req->alloc); - req->alloc = NULL; - } + uv__free(req->alloc); + req->alloc = NULL; if (status == UV_ECANCELED) { assert(req->retcode == 0); @@ -219,9 +217,7 @@ void uv_freeaddrinfo(struct addrinfo* ai) { char* alloc_ptr = (char*)ai; /* release copied result memory */ - if (alloc_ptr != NULL) { - uv__free(alloc_ptr); - } + uv__free(alloc_ptr); } @@ -354,8 +350,9 @@ int uv_getaddrinfo(uv_loop_t* loop, } error: - if (req != NULL && req->alloc != NULL) { + if (req != NULL) { uv__free(req->alloc); + req->alloc = NULL; } return uv_translate_sys_error(err); } diff --git a/deps/uv/src/win/internal.h b/deps/uv/src/win/internal.h index 8d4081bdb51ccf..783f21af0fe9f1 100644 --- a/deps/uv/src/win/internal.h +++ b/deps/uv/src/win/internal.h @@ -327,6 +327,7 @@ void uv__util_init(); uint64_t uv__hrtime(double scale); int uv_parent_pid(); +int uv_current_pid(); __declspec(noreturn) void uv_fatal_error(const int errorno, const char* syscall); diff --git a/deps/uv/src/win/pipe.c b/deps/uv/src/win/pipe.c index 8312b1ceb958c3..bcce80c77e5d57 100644 --- a/deps/uv/src/win/pipe.c +++ b/deps/uv/src/win/pipe.c @@ -85,7 +85,7 @@ static void eof_timer_close_cb(uv_handle_t* handle); static void uv_unique_pipe_name(char* ptr, char* name, size_t size) { - _snprintf(name, size, "\\\\?\\pipe\\uv\\%p-%u", ptr, GetCurrentProcessId()); + snprintf(name, size, "\\\\?\\pipe\\uv\\%p-%u", ptr, GetCurrentProcessId()); } @@ -1246,6 +1246,10 @@ static int uv_pipe_write_impl(uv_loop_t* loop, if (send_handle) { tcp_send_handle = (uv_tcp_t*)send_handle; + if (handle->pipe.conn.ipc_pid == 0) { + handle->pipe.conn.ipc_pid = uv_current_pid(); + } + err = uv_tcp_duplicate_socket(tcp_send_handle, handle->pipe.conn.ipc_pid, &ipc_frame.socket_info_ex.socket_info); if (err) { @@ -1629,7 +1633,7 @@ void uv_process_pipe_read_req(uv_loop_t* loop, uv_pipe_t* handle, if (ReadFile(handle->handle, buf.base, - buf.len, + min(buf.len, avail), &bytes, NULL)) { /* Successful read */ diff --git a/deps/uv/src/win/snprintf.c b/deps/uv/src/win/snprintf.c new file mode 100644 index 00000000000000..776c0e39217585 --- /dev/null +++ b/deps/uv/src/win/snprintf.c @@ -0,0 +1,42 @@ +/* Copyright the libuv project contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#if defined(_MSC_VER) && _MSC_VER < 1900 + +#include +#include + +/* Emulate snprintf() on MSVC<2015, _snprintf() doesn't zero-terminate the buffer + * on overflow... + */ +int snprintf(char* buf, size_t len, const char* fmt, ...) { + int n; + va_list ap; + va_start(ap, fmt); + + n = _vscprintf(fmt, ap); + vsnprintf_s(buf, len, _TRUNCATE, fmt, ap); + + va_end(ap); + return n; +} + +#endif diff --git a/deps/uv/src/win/tty.c b/deps/uv/src/win/tty.c index b40bb42710ae7b..d87cc699097cf7 100644 --- a/deps/uv/src/win/tty.c +++ b/deps/uv/src/win/tty.c @@ -208,7 +208,7 @@ static void uv_tty_capture_initial_style(CONSOLE_SCREEN_BUFFER_INFO* info) { static int style_captured = 0; /* Only do this once. - /* Assumption: Caller has acquired uv_tty_output_lock. */ + Assumption: Caller has acquired uv_tty_output_lock. */ if (style_captured) return; diff --git a/deps/uv/src/win/util.c b/deps/uv/src/win/util.c index a0d1307f8a2590..cb247513046351 100644 --- a/deps/uv/src/win/util.c +++ b/deps/uv/src/win/util.c @@ -59,6 +59,10 @@ static char *process_title; static CRITICAL_SECTION process_title_lock; +/* Cached copy of the process id, written once. */ +static DWORD current_pid = 0; + + /* Interval (in seconds) of the high-resolution clock. */ static double hrtime_interval_ = 0; @@ -359,6 +363,14 @@ int uv_parent_pid() { } +int uv_current_pid() { + if (current_pid == 0) { + current_pid = GetCurrentProcessId(); + } + return current_pid; +} + + char** uv_setup_args(int argc, char** argv) { return argv; } diff --git a/deps/uv/src/win/winapi.c b/deps/uv/src/win/winapi.c index b0b7fd825fb64e..26bd0648668742 100644 --- a/deps/uv/src/win/winapi.c +++ b/deps/uv/src/win/winapi.c @@ -46,6 +46,7 @@ sSleepConditionVariableSRW pSleepConditionVariableSRW; sWakeAllConditionVariable pWakeAllConditionVariable; sWakeConditionVariable pWakeConditionVariable; sCancelSynchronousIo pCancelSynchronousIo; +sGetFinalPathNameByHandleW pGetFinalPathNameByHandleW; void uv_winapi_init() { @@ -139,4 +140,7 @@ void uv_winapi_init() { pCancelSynchronousIo = (sCancelSynchronousIo) GetProcAddress(kernel32_module, "CancelSynchronousIo"); + + pGetFinalPathNameByHandleW = (sGetFinalPathNameByHandleW) + GetProcAddress(kernel32_module, "GetFinalPathNameByHandleW"); } diff --git a/deps/uv/src/win/winapi.h b/deps/uv/src/win/winapi.h index 5bc79bcab27dbb..122198a6d481ac 100644 --- a/deps/uv/src/win/winapi.h +++ b/deps/uv/src/win/winapi.h @@ -4678,6 +4678,12 @@ typedef VOID (WINAPI* sWakeConditionVariable) typedef BOOL (WINAPI* sCancelSynchronousIo) (HANDLE hThread); +typedef DWORD (WINAPI* sGetFinalPathNameByHandleW) + (HANDLE hFile, + LPWSTR lpszFilePath, + DWORD cchFilePath, + DWORD dwFlags); + /* Ntdll function pointers */ extern sRtlNtStatusToDosError pRtlNtStatusToDosError; extern sNtDeviceIoControlFile pNtDeviceIoControlFile; @@ -4699,5 +4705,6 @@ extern sSleepConditionVariableSRW pSleepConditionVariableSRW; extern sWakeAllConditionVariable pWakeAllConditionVariable; extern sWakeConditionVariable pWakeConditionVariable; extern sCancelSynchronousIo pCancelSynchronousIo; +extern sGetFinalPathNameByHandleW pGetFinalPathNameByHandleW; #endif /* UV_WIN_WINAPI_H_ */ diff --git a/deps/uv/test/runner-win.h b/deps/uv/test/runner-win.h index c94b89bd5ec712..8cc4c16eb22eac 100644 --- a/deps/uv/test/runner-win.h +++ b/deps/uv/test/runner-win.h @@ -19,9 +19,6 @@ * IN THE SOFTWARE. */ -/* Don't complain about _snprintf being insecure. */ -#define _CRT_SECURE_NO_WARNINGS - /* Don't complain about write(), fileno() etc. being deprecated. */ #pragma warning(disable : 4996) @@ -30,10 +27,9 @@ #include #include - -/* Windows has no snprintf, only _snprintf. */ -#define snprintf _snprintf - +#if !defined(snprintf) && defined(_MSC_VER) && _MSC_VER < 1900 +extern int snprintf(char*, size_t, const char*, ...); +#endif typedef struct { HANDLE process; diff --git a/deps/uv/test/runner.c b/deps/uv/test/runner.c index e094defc7e7de5..c616d176445db1 100644 --- a/deps/uv/test/runner.c +++ b/deps/uv/test/runner.c @@ -210,6 +210,8 @@ int run_test(const char* test, #ifndef _WIN32 /* Clean up stale socket from previous run. */ remove(TEST_PIPENAME); + remove(TEST_PIPENAME_2); + remove(TEST_PIPENAME_3); #endif /* If it's a helper the user asks for, start it directly. */ diff --git a/deps/uv/test/task.h b/deps/uv/test/task.h index e736763802f610..d18c1daa364702 100644 --- a/deps/uv/test/task.h +++ b/deps/uv/test/task.h @@ -50,9 +50,11 @@ #ifdef _WIN32 # define TEST_PIPENAME "\\\\?\\pipe\\uv-test" # define TEST_PIPENAME_2 "\\\\?\\pipe\\uv-test2" +# define TEST_PIPENAME_3 "\\\\?\\pipe\\uv-test3" #else # define TEST_PIPENAME "/tmp/uv-test-sock" # define TEST_PIPENAME_2 "/tmp/uv-test-sock2" +# define TEST_PIPENAME_3 "/tmp/uv-test-sock3" #endif #ifdef _WIN32 @@ -174,40 +176,8 @@ enum test_status { #endif - -#if defined _WIN32 && ! defined __GNUC__ - -#include - -/* Define inline for MSVC<2015 */ -# if defined(_MSC_VER) && _MSC_VER < 1900 -# define inline __inline -# endif - -# if defined(_MSC_VER) && _MSC_VER < 1900 -/* Emulate snprintf() on MSVC<2015, _snprintf() doesn't zero-terminate the buffer - * on overflow... - */ -inline int snprintf(char* buf, size_t len, const char* fmt, ...) { - va_list ap; - int n; - - va_start(ap, fmt); - n = _vsprintf_p(buf, len, fmt, ap); - va_end(ap); - - /* It's a sad fact of life that no one ever checks the return value of - * snprintf(). Zero-terminating the buffer hopefully reduces the risk - * of gaping security holes. - */ - if (n < 0) - if (len > 0) - buf[0] = '\0'; - - return n; -} -# endif - +#if !defined(snprintf) && defined(_MSC_VER) && _MSC_VER < 1900 +extern int snprintf(char*, size_t, const char*, ...); #endif #if defined(__clang__) || \ diff --git a/deps/uv/test/test-emfile.c b/deps/uv/test/test-emfile.c index 453bfe4cf5ff55..dd35f785b46352 100644 --- a/deps/uv/test/test-emfile.c +++ b/deps/uv/test/test-emfile.c @@ -25,7 +25,6 @@ #include "task.h" #include -#include #include #include @@ -45,6 +44,13 @@ TEST_IMPL(emfile) { uv_loop_t* loop; int first_fd; + /* Lower the file descriptor limit and use up all fds save one. */ + limits.rlim_cur = limits.rlim_max = maxfd + 1; + if (setrlimit(RLIMIT_NOFILE, &limits)) { + ASSERT(errno == EPERM); /* Valgrind blocks the setrlimit() call. */ + RETURN_SKIP("setrlimit(RLIMIT_NOFILE) failed, running under valgrind?"); + } + loop = uv_default_loop(); ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); ASSERT(0 == uv_tcp_init(loop, &server_handle)); @@ -52,13 +58,6 @@ TEST_IMPL(emfile) { ASSERT(0 == uv_tcp_bind(&server_handle, (const struct sockaddr*) &addr, 0)); ASSERT(0 == uv_listen((uv_stream_t*) &server_handle, 8, connection_cb)); - /* Lower the file descriptor limit and use up all fds save one. */ - limits.rlim_cur = limits.rlim_max = maxfd + 1; - if (setrlimit(RLIMIT_NOFILE, &limits)) { - perror("setrlimit(RLIMIT_NOFILE)"); - ASSERT(0); - } - /* Remember the first one so we can clean up afterwards. */ do first_fd = dup(0); diff --git a/deps/uv/test/test-fs-event.c b/deps/uv/test/test-fs-event.c index a0908ce575bd42..e02ff2fda5e5d9 100644 --- a/deps/uv/test/test-fs-event.c +++ b/deps/uv/test/test-fs-event.c @@ -115,7 +115,11 @@ static void fs_event_cb_dir(uv_fs_event_t* handle, const char* filename, ASSERT(handle == &fs_event); ASSERT(status == 0); ASSERT(events == UV_RENAME); + #if defined(__APPLE__) || defined(_WIN32) || defined(__linux__) + ASSERT(strcmp(filename, "file1") == 0); + #else ASSERT(filename == NULL || strcmp(filename, "file1") == 0); + #endif ASSERT(0 == uv_fs_event_stop(handle)); uv_close((uv_handle_t*)handle, close_cb); } @@ -178,8 +182,12 @@ static void fs_event_cb_dir_multi_file(uv_fs_event_t* handle, ASSERT(handle == &fs_event); ASSERT(status == 0); ASSERT(events == UV_CHANGE || UV_RENAME); + #if defined(__APPLE__) || defined(_WIN32) || defined(__linux__) + ASSERT(strncmp(filename, file_prefix, sizeof(file_prefix) - 1) == 0); + #else ASSERT(filename == NULL || strncmp(filename, file_prefix, sizeof(file_prefix) - 1) == 0); + #endif if (fs_event_created + fs_event_removed == fs_event_file_count) { /* Once we've processed all create events, delete all files */ @@ -250,8 +258,16 @@ static void fs_event_cb_dir_multi_file_in_subdir(uv_fs_event_t* handle, ASSERT(handle == &fs_event); ASSERT(status == 0); ASSERT(events == UV_CHANGE || UV_RENAME); + #if defined(__APPLE__) || defined(_WIN32) || defined(__linux__) + ASSERT(strncmp(filename, + file_prefix_in_subdir, + sizeof(file_prefix_in_subdir) - 1) == 0); + #else ASSERT(filename == NULL || - strncmp(filename, file_prefix_in_subdir, sizeof(file_prefix_in_subdir) - 1) == 0); + strncmp(filename, + file_prefix_in_subdir, + sizeof(file_prefix_in_subdir) - 1) == 0); + #endif if (fs_event_created + fs_event_removed == fs_event_file_count) { /* Once we've processed all create events, delete all files */ @@ -270,7 +286,11 @@ static void fs_event_cb_file(uv_fs_event_t* handle, const char* filename, ASSERT(handle == &fs_event); ASSERT(status == 0); ASSERT(events == UV_CHANGE); + #if defined(__APPLE__) || defined(_WIN32) || defined(__linux__) + ASSERT(strcmp(filename, "file2") == 0); + #else ASSERT(filename == NULL || strcmp(filename, "file2") == 0); + #endif ASSERT(0 == uv_fs_event_stop(handle)); uv_close((uv_handle_t*)handle, close_cb); } @@ -293,7 +313,11 @@ static void fs_event_cb_file_current_dir(uv_fs_event_t* handle, ASSERT(handle == &fs_event); ASSERT(status == 0); ASSERT(events == UV_CHANGE); + #if defined(__APPLE__) || defined(_WIN32) || defined(__linux__) + ASSERT(strcmp(filename, "watch_file") == 0); + #else ASSERT(filename == NULL || strcmp(filename, "watch_file") == 0); + #endif /* Regression test for SunOS: touch should generate just one event. */ { @@ -487,7 +511,7 @@ TEST_IMPL(fs_event_watch_file_current_dir) { r = uv_timer_init(loop, &timer); ASSERT(r == 0); - r = uv_timer_start(&timer, timer_cb_touch, 1, 0); + r = uv_timer_start(&timer, timer_cb_touch, 10, 0); ASSERT(r == 0); ASSERT(timer_cb_touch_called == 0); diff --git a/deps/uv/test/test-fs.c b/deps/uv/test/test-fs.c index 90572ca6147150..cf37ac4909ca12 100644 --- a/deps/uv/test/test-fs.c +++ b/deps/uv/test/test-fs.c @@ -83,6 +83,7 @@ static int fchown_cb_count; static int link_cb_count; static int symlink_cb_count; static int readlink_cb_count; +static int realpath_cb_count; static int utime_cb_count; static int futime_cb_count; @@ -168,6 +169,35 @@ static void readlink_cb(uv_fs_t* req) { } +static void realpath_cb(uv_fs_t* req) { + char test_file_abs_buf[PATHMAX]; + size_t test_file_abs_size = sizeof(test_file_abs_buf); + ASSERT(req->fs_type == UV_FS_REALPATH); +#ifdef _WIN32 + /* + * Windows XP and Server 2003 don't support GetFinalPathNameByHandleW() + */ + if (req->result == UV_ENOSYS) { + realpath_cb_count++; + uv_fs_req_cleanup(req); + return; + } +#endif + ASSERT(req->result == 0); + + uv_cwd(test_file_abs_buf, &test_file_abs_size); +#ifdef _WIN32 + strcat(test_file_abs_buf, "\\test_file"); + ASSERT(stricmp(req->ptr, test_file_abs_buf) == 0); +#else + strcat(test_file_abs_buf, "/test_file"); + ASSERT(strcmp(req->ptr, test_file_abs_buf) == 0); +#endif + realpath_cb_count++; + uv_fs_req_cleanup(req); +} + + static void access_cb(uv_fs_t* req) { ASSERT(req->fs_type == UV_FS_ACCESS); access_cb_count++; @@ -1565,11 +1595,43 @@ TEST_IMPL(fs_readlink) { } +TEST_IMPL(fs_realpath) { + uv_fs_t req; + + loop = uv_default_loop(); + ASSERT(0 == uv_fs_realpath(loop, &req, "no_such_file", dummy_cb)); + ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); + ASSERT(dummy_cb_count == 1); + ASSERT(req.ptr == NULL); +#ifdef _WIN32 + /* + * Windows XP and Server 2003 don't support GetFinalPathNameByHandleW() + */ + if (req.result == UV_ENOSYS) { + uv_fs_req_cleanup(&req); + RETURN_SKIP("realpath is not supported on Windows XP"); + } +#endif + ASSERT(req.result == UV_ENOENT); + uv_fs_req_cleanup(&req); + + ASSERT(UV_ENOENT == uv_fs_realpath(NULL, &req, "no_such_file", NULL)); + ASSERT(req.ptr == NULL); + ASSERT(req.result == UV_ENOENT); + uv_fs_req_cleanup(&req); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + TEST_IMPL(fs_symlink) { int r; uv_fs_t req; uv_file file; uv_file link; + char test_file_abs_buf[PATHMAX]; + size_t test_file_abs_size; /* Setup. */ unlink("test_file"); @@ -1577,6 +1639,14 @@ TEST_IMPL(fs_symlink) { unlink("test_file_symlink2"); unlink("test_file_symlink_symlink"); unlink("test_file_symlink2_symlink"); + test_file_abs_size = sizeof(test_file_abs_buf); +#ifdef _WIN32 + uv_cwd(test_file_abs_buf, &test_file_abs_size); + strcat(test_file_abs_buf, "\\test_file"); +#else + uv_cwd(test_file_abs_buf, &test_file_abs_size); + strcat(test_file_abs_buf, "/test_file"); +#endif loop = uv_default_loop(); @@ -1647,6 +1717,24 @@ TEST_IMPL(fs_symlink) { ASSERT(strcmp(req.ptr, "test_file_symlink") == 0); uv_fs_req_cleanup(&req); + r = uv_fs_realpath(NULL, &req, "test_file_symlink_symlink", NULL); +#ifdef _WIN32 + /* + * Windows XP and Server 2003 don't support GetFinalPathNameByHandleW() + */ + if (r == UV_ENOSYS) { + uv_fs_req_cleanup(&req); + RETURN_SKIP("realpath is not supported on Windows XP"); + } +#endif + ASSERT(r == 0); +#ifdef _WIN32 + ASSERT(stricmp(req.ptr, test_file_abs_buf) == 0); +#else + ASSERT(strcmp(req.ptr, test_file_abs_buf) == 0); +#endif + uv_fs_req_cleanup(&req); + /* async link */ r = uv_fs_symlink(loop, &req, @@ -1687,6 +1775,20 @@ TEST_IMPL(fs_symlink) { uv_run(loop, UV_RUN_DEFAULT); ASSERT(readlink_cb_count == 1); + r = uv_fs_realpath(loop, &req, "test_file", realpath_cb); +#ifdef _WIN32 + /* + * Windows XP and Server 2003 don't support GetFinalPathNameByHandleW() + */ + if (r == UV_ENOSYS) { + uv_fs_req_cleanup(&req); + RETURN_SKIP("realpath is not supported on Windows XP"); + } +#endif + ASSERT(r == 0); + uv_run(loop, UV_RUN_DEFAULT); + ASSERT(realpath_cb_count == 1); + /* * Run the loop just to check we don't have make any extraneous uv_ref() * calls. This should drop out immediately. @@ -1710,12 +1812,15 @@ TEST_IMPL(fs_symlink_dir) { int r; char* test_dir; uv_dirent_t dent; + static char test_dir_abs_buf[PATHMAX]; + size_t test_dir_abs_size; /* set-up */ unlink("test_dir/file1"); unlink("test_dir/file2"); rmdir("test_dir"); rmdir("test_dir_symlink"); + test_dir_abs_size = sizeof(test_dir_abs_buf); loop = uv_default_loop(); @@ -1723,16 +1828,16 @@ TEST_IMPL(fs_symlink_dir) { uv_fs_req_cleanup(&req); #ifdef _WIN32 - { - static char src_path_buf[PATHMAX]; - size_t size; - size = sizeof(src_path_buf); - strcpy(src_path_buf, "\\\\?\\"); - uv_cwd(src_path_buf + 4, &size); - strcat(src_path_buf, "\\test_dir\\"); - test_dir = src_path_buf; - } + strcpy(test_dir_abs_buf, "\\\\?\\"); + uv_cwd(test_dir_abs_buf + 4, &test_dir_abs_size); + test_dir_abs_size += 4; + strcat(test_dir_abs_buf, "\\test_dir\\"); + test_dir_abs_size += strlen("\\test_dir\\"); + test_dir = test_dir_abs_buf; #else + uv_cwd(test_dir_abs_buf, &test_dir_abs_size); + strcat(test_dir_abs_buf, "/test_dir"); + test_dir_abs_size += strlen("/test_dir"); test_dir = "test_dir"; #endif @@ -1767,6 +1872,25 @@ TEST_IMPL(fs_symlink_dir) { #endif uv_fs_req_cleanup(&req); + r = uv_fs_realpath(NULL, &req, "test_dir_symlink", NULL); +#ifdef _WIN32 + /* + * Windows XP and Server 2003 don't support GetFinalPathNameByHandleW() + */ + if (r == UV_ENOSYS) { + uv_fs_req_cleanup(&req); + RETURN_SKIP("realpath is not supported on Windows XP"); + } +#endif + ASSERT(r == 0); +#ifdef _WIN32 + ASSERT(strlen(req.ptr) == test_dir_abs_size - 5); + ASSERT(strnicmp(req.ptr, test_dir + 4, test_dir_abs_size - 5) == 0); +#else + ASSERT(strcmp(req.ptr, test_dir_abs_buf) == 0); +#endif + uv_fs_req_cleanup(&req); + r = uv_fs_open(NULL, &open_req1, "test_dir/file1", O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR, NULL); ASSERT(r >= 0); diff --git a/deps/uv/test/test-get-loadavg.c b/deps/uv/test/test-get-loadavg.c index 7465e18b91e9c7..4762e47576d064 100644 --- a/deps/uv/test/test-get-loadavg.c +++ b/deps/uv/test/test-get-loadavg.c @@ -24,10 +24,9 @@ TEST_IMPL(get_loadavg) { - double avg[3]; + double avg[3] = {-1, -1, -1}; uv_loadavg(avg); - ASSERT(avg != NULL); ASSERT(avg[0] >= 0); ASSERT(avg[1] >= 0); ASSERT(avg[2] >= 0); diff --git a/deps/uv/test/test-getaddrinfo.c b/deps/uv/test/test-getaddrinfo.c index 45813c313af2c2..6b644a8d442a3a 100644 --- a/deps/uv/test/test-getaddrinfo.c +++ b/deps/uv/test/test-getaddrinfo.c @@ -83,10 +83,11 @@ static void getaddrinfo_cuncurrent_cb(uv_getaddrinfo_t* handle, TEST_IMPL(getaddrinfo_fail) { uv_getaddrinfo_t req; + /* Use a FQDN by ending in a period */ ASSERT(0 == uv_getaddrinfo(uv_default_loop(), &req, getaddrinfo_fail_cb, - "xyzzy.xyzzy.xyzzy", + "xyzzy.xyzzy.xyzzy.", NULL, NULL)); ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); @@ -100,10 +101,11 @@ TEST_IMPL(getaddrinfo_fail) { TEST_IMPL(getaddrinfo_fail_sync) { uv_getaddrinfo_t req; + /* Use a FQDN by ending in a period */ ASSERT(0 > uv_getaddrinfo(uv_default_loop(), &req, NULL, - "xyzzy.xyzzy.xyzzy", + "xyzzy.xyzzy.xyzzy.", NULL, NULL)); uv_freeaddrinfo(req.addrinfo); diff --git a/deps/uv/test/test-getnameinfo.c b/deps/uv/test/test-getnameinfo.c index ebe9246699dbd0..b1391616d13e54 100644 --- a/deps/uv/test/test-getnameinfo.c +++ b/deps/uv/test/test-getnameinfo.c @@ -73,8 +73,8 @@ TEST_IMPL(getnameinfo_basic_ip4_sync) { NULL, (const struct sockaddr*)&addr4, 0)); - ASSERT(req.host != NULL); - ASSERT(req.service != NULL); + ASSERT(req.host[0] != '\0'); + ASSERT(req.service[0] != '\0'); MAKE_VALGRIND_HAPPY(); return 0; diff --git a/deps/uv/test/test-ipc-send-recv.c b/deps/uv/test/test-ipc-send-recv.c index d9b913339d3d50..c445483fa089e3 100644 --- a/deps/uv/test/test-ipc-send-recv.c +++ b/deps/uv/test/test-ipc-send-recv.c @@ -30,6 +30,8 @@ void spawn_helper(uv_pipe_t* channel, uv_process_t* process, const char* helper); +void ipc_send_recv_helper_threadproc(void* arg); + union handles { uv_handle_t handle; uv_stream_t stream; @@ -38,16 +40,37 @@ union handles { uv_tty_t tty; }; -struct echo_ctx { +struct test_ctx { uv_pipe_t channel; + uv_connect_t connect_req; uv_write_t write_req; + uv_write_t write_req2; uv_handle_type expected_type; union handles send; + union handles send2; + union handles recv; + union handles recv2; +}; + +struct echo_ctx { + uv_pipe_t listen; + uv_pipe_t channel; + uv_write_t write_req; + uv_write_t write_req2; + uv_handle_type expected_type; union handles recv; + union handles recv2; }; -static struct echo_ctx ctx; -static int num_recv_handles; +static struct test_ctx ctx; +static struct echo_ctx ctx2; + +/* Used in write2_cb to decide if we need to cleanup or not */ +static int is_child_process; +static int is_in_process; +static int read_cb_called; +static int recv_cb_called; +static int write2_cb_called; static void alloc_cb(uv_handle_t* handle, @@ -66,39 +89,55 @@ static void recv_cb(uv_stream_t* handle, uv_handle_type pending; uv_pipe_t* pipe; int r; + union handles* recv; + + if (++recv_cb_called == 1) { + recv = &ctx.recv; + } else { + recv = &ctx.recv2; + } pipe = (uv_pipe_t*) handle; ASSERT(pipe == &ctx.channel); - ASSERT(nread >= 0); - ASSERT(1 == uv_pipe_pending_count(pipe)); - - pending = uv_pipe_pending_type(pipe); - ASSERT(pending == ctx.expected_type); - - if (pending == UV_NAMED_PIPE) - r = uv_pipe_init(ctx.channel.loop, &ctx.recv.pipe, 0); - else if (pending == UV_TCP) - r = uv_tcp_init(ctx.channel.loop, &ctx.recv.tcp); - else - abort(); - ASSERT(r == 0); - r = uv_accept(handle, &ctx.recv.stream); - ASSERT(r == 0); - - uv_close((uv_handle_t*)&ctx.channel, NULL); - uv_close(&ctx.send.handle, NULL); - uv_close(&ctx.recv.handle, NULL); - num_recv_handles++; + /* Depending on the OS, the final recv_cb can be called after the child + * process has terminated which can result in nread being UV_EOF instead of + * the number of bytes read. Since the other end of the pipe has closed this + * UV_EOF is an acceptable value. */ + if (nread == UV_EOF) { + /* UV_EOF is only acceptable for the final recv_cb call */ + ASSERT(recv_cb_called == 2); + } else { + ASSERT(nread >= 0); + ASSERT(1 == uv_pipe_pending_count(pipe)); + + pending = uv_pipe_pending_type(pipe); + ASSERT(pending == ctx.expected_type); + + if (pending == UV_NAMED_PIPE) + r = uv_pipe_init(ctx.channel.loop, &recv->pipe, 0); + else if (pending == UV_TCP) + r = uv_tcp_init(ctx.channel.loop, &recv->tcp); + else + abort(); + ASSERT(r == 0); + + r = uv_accept(handle, &recv->stream); + ASSERT(r == 0); + } + + /* Close after two writes received */ + if (recv_cb_called == 2) { + uv_close((uv_handle_t*)&ctx.channel, NULL); + } } - -static int run_test(void) { - uv_process_t process; - uv_buf_t buf; +static void connect_cb(uv_connect_t* req, int status) { int r; + uv_buf_t buf; - spawn_helper(&ctx.channel, &process, "ipc_send_recv_helper"); + ASSERT(req == &ctx.connect_req); + ASSERT(status == 0); buf = uv_buf_init(".", 1); r = uv_write2(&ctx.write_req, @@ -108,19 +147,56 @@ static int run_test(void) { NULL); ASSERT(r == 0); + /* Perform two writes to the same pipe to make sure that on Windows we are + * not running into issue 505: + * https://github.com/libuv/libuv/issues/505 */ + buf = uv_buf_init(".", 1); + r = uv_write2(&ctx.write_req2, + (uv_stream_t*)&ctx.channel, + &buf, 1, + &ctx.send2.stream, + NULL); + ASSERT(r == 0); + r = uv_read_start((uv_stream_t*)&ctx.channel, alloc_cb, recv_cb); ASSERT(r == 0); +} + +static int run_test(int inprocess) { + uv_process_t process; + uv_thread_t tid; + int r; + + if (inprocess) { + r = uv_thread_create(&tid, ipc_send_recv_helper_threadproc, (void *) 42); + ASSERT(r == 0); + + uv_sleep(1000); + + r = uv_pipe_init(uv_default_loop(), &ctx.channel, 1); + ASSERT(r == 0); + + uv_pipe_connect(&ctx.connect_req, &ctx.channel, TEST_PIPENAME_3, connect_cb); + } else { + spawn_helper(&ctx.channel, &process, "ipc_send_recv_helper"); + + connect_cb(&ctx.connect_req, 0); + } r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); ASSERT(r == 0); - ASSERT(num_recv_handles == 1); + ASSERT(recv_cb_called == 2); + + if (inprocess) { + r = uv_thread_join(&tid); + ASSERT(r == 0); + } return 0; } - -TEST_IMPL(ipc_send_recv_pipe) { +static int run_ipc_send_recv_pipe(int inprocess) { int r; ctx.expected_type = UV_NAMED_PIPE; @@ -131,15 +207,28 @@ TEST_IMPL(ipc_send_recv_pipe) { r = uv_pipe_bind(&ctx.send.pipe, TEST_PIPENAME); ASSERT(r == 0); - r = run_test(); + r = uv_pipe_init(uv_default_loop(), &ctx.send2.pipe, 1); + ASSERT(r == 0); + + r = uv_pipe_bind(&ctx.send2.pipe, TEST_PIPENAME_2); + ASSERT(r == 0); + + r = run_test(inprocess); ASSERT(r == 0); MAKE_VALGRIND_HAPPY(); return 0; } +TEST_IMPL(ipc_send_recv_pipe) { + return run_ipc_send_recv_pipe(0); +} -TEST_IMPL(ipc_send_recv_tcp) { +TEST_IMPL(ipc_send_recv_pipe_inprocess) { + return run_ipc_send_recv_pipe(1); +} + +static int run_ipc_send_recv_tcp(int inprocess) { struct sockaddr_in addr; int r; @@ -150,25 +239,45 @@ TEST_IMPL(ipc_send_recv_tcp) { r = uv_tcp_init(uv_default_loop(), &ctx.send.tcp); ASSERT(r == 0); + r = uv_tcp_init(uv_default_loop(), &ctx.send2.tcp); + ASSERT(r == 0); + r = uv_tcp_bind(&ctx.send.tcp, (const struct sockaddr*) &addr, 0); ASSERT(r == 0); - r = run_test(); + r = uv_tcp_bind(&ctx.send2.tcp, (const struct sockaddr*) &addr, 0); + ASSERT(r == 0); + + r = run_test(inprocess); ASSERT(r == 0); MAKE_VALGRIND_HAPPY(); return 0; } +TEST_IMPL(ipc_send_recv_tcp) { + return run_ipc_send_recv_tcp(0); +} + +TEST_IMPL(ipc_send_recv_tcp_inprocess) { + return run_ipc_send_recv_tcp(1); +} + -/* Everything here runs in a child process. */ +/* Everything here runs in a child process or second thread. */ static void write2_cb(uv_write_t* req, int status) { ASSERT(status == 0); - uv_close(&ctx.recv.handle, NULL); - uv_close((uv_handle_t*)&ctx.channel, NULL); -} + /* After two successful writes in the child process, allow the child + * process to be closed. */ + if (++write2_cb_called == 2 && (is_child_process || is_in_process)) { + uv_close(&ctx2.recv.handle, NULL); + uv_close(&ctx2.recv2.handle, NULL); + uv_close((uv_handle_t*)&ctx2.channel, NULL); + uv_close((uv_handle_t*)&ctx2.listen, NULL); + } +} static void read_cb(uv_stream_t* handle, ssize_t nread, @@ -177,37 +286,102 @@ static void read_cb(uv_stream_t* handle, uv_pipe_t* pipe; uv_handle_type pending; int r; + union handles* recv; + uv_write_t* write_req; + + if (nread == UV__EOF || nread == UV__ECONNABORTED) { + return; + } + + if (++read_cb_called == 2) { + recv = &ctx2.recv; + write_req = &ctx2.write_req; + } else { + recv = &ctx2.recv2; + write_req = &ctx2.write_req2; + } pipe = (uv_pipe_t*) handle; - ASSERT(pipe == &ctx.channel); + ASSERT(pipe == &ctx2.channel); ASSERT(nread >= 0); ASSERT(1 == uv_pipe_pending_count(pipe)); pending = uv_pipe_pending_type(pipe); ASSERT(pending == UV_NAMED_PIPE || pending == UV_TCP); - wrbuf = uv_buf_init(".", 1); - if (pending == UV_NAMED_PIPE) - r = uv_pipe_init(ctx.channel.loop, &ctx.recv.pipe, 0); + r = uv_pipe_init(ctx2.channel.loop, &recv->pipe, 0); else if (pending == UV_TCP) - r = uv_tcp_init(ctx.channel.loop, &ctx.recv.tcp); + r = uv_tcp_init(ctx2.channel.loop, &recv->tcp); else abort(); ASSERT(r == 0); - r = uv_accept(handle, &ctx.recv.stream); + r = uv_accept(handle, &recv->stream); ASSERT(r == 0); - r = uv_write2(&ctx.write_req, - (uv_stream_t*)&ctx.channel, + wrbuf = uv_buf_init(".", 1); + r = uv_write2(write_req, + (uv_stream_t*)&ctx2.channel, &wrbuf, 1, - &ctx.recv.stream, + &recv->stream, write2_cb); ASSERT(r == 0); } +static void send_recv_start() { + int r; + ASSERT(1 == uv_is_readable((uv_stream_t*)&ctx2.channel)); + ASSERT(1 == uv_is_writable((uv_stream_t*)&ctx2.channel)); + ASSERT(0 == uv_is_closing((uv_handle_t*)&ctx2.channel)); + + r = uv_read_start((uv_stream_t*)&ctx2.channel, alloc_cb, read_cb); + ASSERT(r == 0); +} + +static void listen_cb(uv_stream_t* handle, int status) { + int r; + ASSERT(handle == (uv_stream_t*)&ctx2.listen); + ASSERT(status == 0); + + r = uv_accept((uv_stream_t*)&ctx2.listen, (uv_stream_t*)&ctx2.channel); + ASSERT(r == 0); + + send_recv_start(); +} + +int run_ipc_send_recv_helper(uv_loop_t* loop, int inprocess) { + int r; + + is_in_process = inprocess; + + memset(&ctx2, 0, sizeof(ctx2)); + + r = uv_pipe_init(loop, &ctx2.listen, 0); + ASSERT(r == 0); + + r = uv_pipe_init(loop, &ctx2.channel, 1); + ASSERT(r == 0); + + if (inprocess) { + r = uv_pipe_bind(&ctx2.listen, TEST_PIPENAME_3); + ASSERT(r == 0); + + r = uv_listen((uv_stream_t*)&ctx2.listen, SOMAXCONN, listen_cb); + ASSERT(r == 0); + } else { + r = uv_pipe_open(&ctx2.channel, 0); + ASSERT(r == 0); + + send_recv_start(); + } + + r = uv_run(loop, UV_RUN_DEFAULT); + ASSERT(r == 0); + + return 0; +} /* stdin is a duplex channel over which a handle is sent. * We receive it and send it back where it came from. @@ -215,22 +389,23 @@ static void read_cb(uv_stream_t* handle, int ipc_send_recv_helper(void) { int r; - memset(&ctx, 0, sizeof(ctx)); - - r = uv_pipe_init(uv_default_loop(), &ctx.channel, 1); + r = run_ipc_send_recv_helper(uv_default_loop(), 0); ASSERT(r == 0); - uv_pipe_open(&ctx.channel, 0); - ASSERT(1 == uv_is_readable((uv_stream_t*)&ctx.channel)); - ASSERT(1 == uv_is_writable((uv_stream_t*)&ctx.channel)); - ASSERT(0 == uv_is_closing((uv_handle_t*)&ctx.channel)); + MAKE_VALGRIND_HAPPY(); + return 0; +} - r = uv_read_start((uv_stream_t*)&ctx.channel, alloc_cb, read_cb); +void ipc_send_recv_helper_threadproc(void* arg) { + int r; + uv_loop_t loop; + + r = uv_loop_init(&loop); ASSERT(r == 0); - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); + r = run_ipc_send_recv_helper(&loop, 1); ASSERT(r == 0); - MAKE_VALGRIND_HAPPY(); - return 0; + r = uv_loop_close(&loop); + ASSERT(r == 0); } diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index 8ee74391afaeb7..858a20af49c291 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -50,8 +50,10 @@ TEST_DECLARE (ipc_listen_before_write) TEST_DECLARE (ipc_listen_after_write) #ifndef _WIN32 TEST_DECLARE (ipc_send_recv_pipe) +TEST_DECLARE (ipc_send_recv_pipe_inprocess) #endif TEST_DECLARE (ipc_send_recv_tcp) +TEST_DECLARE (ipc_send_recv_tcp_inprocess) TEST_DECLARE (ipc_tcp_connection) TEST_DECLARE (tcp_ping_pong) TEST_DECLARE (tcp_ping_pong_v6) @@ -252,6 +254,7 @@ TEST_DECLARE (fs_unlink_readonly) TEST_DECLARE (fs_chown) TEST_DECLARE (fs_link) TEST_DECLARE (fs_readlink) +TEST_DECLARE (fs_realpath) TEST_DECLARE (fs_symlink) TEST_DECLARE (fs_symlink_dir) TEST_DECLARE (fs_utime) @@ -334,6 +337,7 @@ HELPER_DECLARE (tcp6_echo_server) HELPER_DECLARE (udp4_echo_server) HELPER_DECLARE (pipe_echo_server) +TEST_DECLARE (queue_foreach_delete) TASK_LIST_START TEST_ENTRY_CUSTOM (platform_output, 0, 1, 5000) @@ -380,8 +384,10 @@ TASK_LIST_START TEST_ENTRY (ipc_listen_after_write) #ifndef _WIN32 TEST_ENTRY (ipc_send_recv_pipe) + TEST_ENTRY (ipc_send_recv_pipe_inprocess) #endif TEST_ENTRY (ipc_send_recv_tcp) + TEST_ENTRY (ipc_send_recv_tcp_inprocess) TEST_ENTRY (ipc_tcp_connection) TEST_ENTRY (tcp_ping_pong) @@ -671,6 +677,7 @@ TASK_LIST_START TEST_ENTRY (fs_utime) TEST_ENTRY (fs_futime) TEST_ENTRY (fs_readlink) + TEST_ENTRY (fs_realpath) TEST_ENTRY (fs_symlink) TEST_ENTRY (fs_symlink_dir) TEST_ENTRY (fs_stat_missing_path) @@ -714,6 +721,9 @@ TASK_LIST_START TEST_ENTRY (dlerror) TEST_ENTRY (ip4_addr) TEST_ENTRY (ip6_addr_link_local) + + TEST_ENTRY (queue_foreach_delete) + #if 0 /* These are for testing the test runner. */ TEST_ENTRY (fail_always) diff --git a/deps/uv/test/test-mutexes.c b/deps/uv/test/test-mutexes.c index 4aeac73b4c1571..af5e4e88a22f30 100644 --- a/deps/uv/test/test-mutexes.c +++ b/deps/uv/test/test-mutexes.c @@ -25,6 +25,10 @@ #include #include +static uv_cond_t condvar; +static uv_mutex_t mutex; +static uv_rwlock_t rwlock; +static int step; /* The mutex and rwlock tests are really poor. * They're very basic sanity checks and nothing more. @@ -63,60 +67,96 @@ TEST_IMPL(thread_rwlock) { } -TEST_IMPL(thread_rwlock_trylock) { - uv_rwlock_t rwlock; - int r; - - r = uv_rwlock_init(&rwlock); - ASSERT(r == 0); - - /* No locks held. */ +/* Call when holding |mutex|. */ +static void synchronize_nowait(void) { + step += 1; + uv_cond_signal(&condvar); +} - r = uv_rwlock_trywrlock(&rwlock); - ASSERT(r == 0); - /* Write lock held. */ +/* Call when holding |mutex|. */ +static void synchronize(void) { + int current; - r = uv_rwlock_tryrdlock(&rwlock); - ASSERT(r == UV_EBUSY); - r = uv_rwlock_trywrlock(&rwlock); - ASSERT(r == UV_EBUSY); + synchronize_nowait(); + /* Wait for the other thread. Guard against spurious wakeups. */ + for (current = step; current == step; uv_cond_wait(&condvar, &mutex)); + ASSERT(step == current + 1); +} - uv_rwlock_wrunlock(&rwlock); - /* No locks held. */ +static void thread_rwlock_trylock_peer(void* unused) { + (void) &unused; - r = uv_rwlock_tryrdlock(&rwlock); - ASSERT(r == 0); + uv_mutex_lock(&mutex); - /* One read lock held. */ + /* Write lock held by other thread. */ + ASSERT(UV_EBUSY == uv_rwlock_tryrdlock(&rwlock)); + ASSERT(UV_EBUSY == uv_rwlock_trywrlock(&rwlock)); + synchronize(); - r = uv_rwlock_tryrdlock(&rwlock); - ASSERT(r == 0); + /* Read lock held by other thread. */ + ASSERT(0 == uv_rwlock_tryrdlock(&rwlock)); + uv_rwlock_rdunlock(&rwlock); + ASSERT(UV_EBUSY == uv_rwlock_trywrlock(&rwlock)); + synchronize(); - /* Two read locks held. */ + /* Acquire write lock. */ + ASSERT(0 == uv_rwlock_trywrlock(&rwlock)); + synchronize(); - r = uv_rwlock_trywrlock(&rwlock); - ASSERT(r == UV_EBUSY); + /* Release write lock and acquire read lock. */ + uv_rwlock_wrunlock(&rwlock); + ASSERT(0 == uv_rwlock_tryrdlock(&rwlock)); + synchronize(); uv_rwlock_rdunlock(&rwlock); + synchronize_nowait(); /* Signal main thread we're going away. */ + uv_mutex_unlock(&mutex); +} - /* One read lock held. */ - uv_rwlock_rdunlock(&rwlock); +TEST_IMPL(thread_rwlock_trylock) { + uv_thread_t thread; - /* No read locks held. */ + ASSERT(0 == uv_cond_init(&condvar)); + ASSERT(0 == uv_mutex_init(&mutex)); + ASSERT(0 == uv_rwlock_init(&rwlock)); - r = uv_rwlock_trywrlock(&rwlock); - ASSERT(r == 0); + uv_mutex_lock(&mutex); + ASSERT(0 == uv_thread_create(&thread, thread_rwlock_trylock_peer, NULL)); - /* Write lock held. */ + /* Hold write lock. */ + ASSERT(0 == uv_rwlock_trywrlock(&rwlock)); + synchronize(); /* Releases the mutex to the other thread. */ + /* Release write lock and acquire read lock. Pthreads doesn't support + * the notion of upgrading or downgrading rwlocks, so neither do we. + */ uv_rwlock_wrunlock(&rwlock); + ASSERT(0 == uv_rwlock_tryrdlock(&rwlock)); + synchronize(); + + /* Release read lock. */ + uv_rwlock_rdunlock(&rwlock); + synchronize(); - /* No locks held. */ + /* Write lock held by other thread. */ + ASSERT(UV_EBUSY == uv_rwlock_tryrdlock(&rwlock)); + ASSERT(UV_EBUSY == uv_rwlock_trywrlock(&rwlock)); + synchronize(); + /* Read lock held by other thread. */ + ASSERT(0 == uv_rwlock_tryrdlock(&rwlock)); + uv_rwlock_rdunlock(&rwlock); + ASSERT(UV_EBUSY == uv_rwlock_trywrlock(&rwlock)); + synchronize(); + + ASSERT(0 == uv_thread_join(&thread)); uv_rwlock_destroy(&rwlock); + uv_mutex_unlock(&mutex); + uv_mutex_destroy(&mutex); + uv_cond_destroy(&condvar); return 0; } diff --git a/deps/uv/test/test-process-title.c b/deps/uv/test/test-process-title.c index 29be20749bea9d..42ade44160416f 100644 --- a/deps/uv/test/test-process-title.c +++ b/deps/uv/test/test-process-title.c @@ -42,7 +42,7 @@ static void set_title(const char* title) { TEST_IMPL(process_title) { -#if defined(__sun) +#if defined(__sun) || defined(_AIX) RETURN_SKIP("uv_(get|set)_process_title is not implemented."); #else /* Check for format string vulnerabilities. */ diff --git a/deps/uv/test/test-queue-foreach-delete.c b/deps/uv/test/test-queue-foreach-delete.c new file mode 100644 index 00000000000000..45da225381f51f --- /dev/null +++ b/deps/uv/test/test-queue-foreach-delete.c @@ -0,0 +1,200 @@ +/* Copyright The libuv project and contributors. All rights reserved. + * + * 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. + */ + +#include "uv.h" +#include "task.h" + +#include + + +/* + * The idea behind the test is as follows. + * Certain handle types are stored in a queue internally. + * Extra care should be taken for removal of a handle from the queue while iterating over the queue. + * (i.e., QUEUE_REMOVE() called within QUEUE_FOREACH()) + * This usually happens when someone closes or stops a handle from within its callback. + * So we need to check that we haven't screwed the queue on close/stop. + * To do so we do the following (for each handle type): + * 1. Create and start 3 handles (#0, #1, and #2). + * + * The queue after the start() calls: + * ..=> [queue head] <=> [handle] <=> [handle #1] <=> [handle] <=.. + * + * 2. Trigger handles to fire (for uv_idle_t, uv_prepare_t, and uv_check_t there is nothing to do). + * + * 3. In the callback for the first-executed handle (#0 or #2 depending on handle type) + * stop the handle and the next one (#1). + * (for uv_idle_t, uv_prepare_t, and uv_check_t callbacks are executed in the reverse order as they are start()'ed, + * so callback for handle #2 will be called first) + * + * The queue after the stop() calls: + * correct foreach "next" | + * \/ + * ..=> [queue head] <==============================> [handle] <=.. + * [ ] <- [handle] <=> [handle #1] -> [ ] + * /\ + * wrong foreach "next" | + * + * 4. The callback for handle #1 shouldn't be called because the handle #1 is stopped in the previous step. + * However, if QUEUE_REMOVE() is not handled properly within QUEUE_FOREACH(), the callback _will_ be called. + */ + +static const unsigned first_handle_number_idle = 2; +static const unsigned first_handle_number_prepare = 2; +static const unsigned first_handle_number_check = 2; +#ifdef __linux__ +static const unsigned first_handle_number_fs_event = 0; +#endif + + +#define DEFINE_GLOBALS_AND_CBS(name) \ + static uv_##name##_t (name)[3]; \ + static unsigned name##_cb_calls[3]; \ + \ + static void name##2_cb(uv_##name##_t* handle) { \ + ASSERT(handle == &(name)[2]); \ + if (first_handle_number_##name == 2) { \ + uv_close((uv_handle_t*)&(name)[2], NULL); \ + uv_close((uv_handle_t*)&(name)[1], NULL); \ + } \ + name##_cb_calls[2]++; \ + } \ + \ + static void name##1_cb(uv_##name##_t* handle) { \ + ASSERT(handle == &(name)[1]); \ + ASSERT(0 && "Shouldn't be called" && (&name[0])); \ + } \ + \ + static void name##0_cb(uv_##name##_t* handle) { \ + ASSERT(handle == &(name)[0]); \ + if (first_handle_number_##name == 0) { \ + uv_close((uv_handle_t*)&(name)[0], NULL); \ + uv_close((uv_handle_t*)&(name)[1], NULL); \ + } \ + name##_cb_calls[0]++; \ + } \ + \ + static const uv_##name##_cb name##_cbs[] = { \ + (uv_##name##_cb)name##0_cb, \ + (uv_##name##_cb)name##1_cb, \ + (uv_##name##_cb)name##2_cb, \ + }; + +#define INIT_AND_START(name, loop) \ + do { \ + size_t i; \ + for (i = 0; i < ARRAY_SIZE(name); i++) { \ + int r; \ + r = uv_##name##_init((loop), &(name)[i]); \ + ASSERT(r == 0); \ + \ + r = uv_##name##_start(&(name)[i], name##_cbs[i]); \ + ASSERT(r == 0); \ + } \ + } while (0) + +#define END_ASSERTS(name) \ + do { \ + ASSERT(name##_cb_calls[0] == 1); \ + ASSERT(name##_cb_calls[1] == 0); \ + ASSERT(name##_cb_calls[2] == 1); \ + } while (0) + +DEFINE_GLOBALS_AND_CBS(idle) +DEFINE_GLOBALS_AND_CBS(prepare) +DEFINE_GLOBALS_AND_CBS(check) + +#ifdef __linux__ +DEFINE_GLOBALS_AND_CBS(fs_event) + +static const char watched_dir[] = "."; +static uv_timer_t timer; +static unsigned helper_timer_cb_calls; + + +static void init_and_start_fs_events(uv_loop_t* loop) { + size_t i; + for (i = 0; i < ARRAY_SIZE(fs_event); i++) { + int r; + r = uv_fs_event_init(loop, &fs_event[i]); + ASSERT(r == 0); + + r = uv_fs_event_start(&fs_event[i], + (uv_fs_event_cb)fs_event_cbs[i], + watched_dir, + 0); + ASSERT(r == 0); + } +} + +static void helper_timer_cb(uv_timer_t* thandle) { + int r; + uv_fs_t fs_req; + + /* fire all fs_events */ + r = uv_fs_utime(thandle->loop, &fs_req, watched_dir, 0, 0, NULL); + ASSERT(r == 0); + ASSERT(fs_req.result == 0); + ASSERT(fs_req.fs_type == UV_FS_UTIME); + ASSERT(strcmp(fs_req.path, watched_dir) == 0); + uv_fs_req_cleanup(&fs_req); + + helper_timer_cb_calls++; +} +#endif + + +TEST_IMPL(queue_foreach_delete) { + uv_loop_t* loop; + int r; + + loop = uv_default_loop(); + + INIT_AND_START(idle, loop); + INIT_AND_START(prepare, loop); + INIT_AND_START(check, loop); + +#ifdef __linux__ + init_and_start_fs_events(loop); + + /* helper timer to trigger async and fs_event callbacks */ + r = uv_timer_init(loop, &timer); + ASSERT(r == 0); + + r = uv_timer_start(&timer, helper_timer_cb, 0, 0); + ASSERT(r == 0); +#endif + + r = uv_run(loop, UV_RUN_NOWAIT); + ASSERT(r == 1); + + END_ASSERTS(idle); + END_ASSERTS(prepare); + END_ASSERTS(check); + +#ifdef __linux__ + ASSERT(helper_timer_cb_calls == 1); +#endif + + MAKE_VALGRIND_HAPPY(); + + return 0; +} diff --git a/deps/uv/test/test-spawn.c b/deps/uv/test/test-spawn.c index e71f0f7d53d344..eba54ae7054976 100644 --- a/deps/uv/test/test-spawn.c +++ b/deps/uv/test/test-spawn.c @@ -960,11 +960,11 @@ TEST_IMPL(spawn_detect_pipe_name_collisions_on_windows) { options.stdio_count = 2; /* Create a pipe that'll cause a collision. */ - _snprintf(name, - sizeof(name), - "\\\\.\\pipe\\uv\\%p-%d", - &out, - GetCurrentProcessId()); + snprintf(name, + sizeof(name), + "\\\\.\\pipe\\uv\\%p-%d", + &out, + GetCurrentProcessId()); pipe_handle = CreateNamedPipeA(name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, diff --git a/deps/uv/test/test-tcp-try-write.c b/deps/uv/test/test-tcp-try-write.c index 8a60136b64e9aa..97a1d6e3d5794f 100644 --- a/deps/uv/test/test-tcp-try-write.c +++ b/deps/uv/test/test-tcp-try-write.c @@ -58,6 +58,11 @@ static void connect_cb(uv_connect_t* req, int status) { break; } } while (1); + + do { + buf = uv_buf_init("", 0); + r = uv_try_write((uv_stream_t*) &client, &buf, 1); + } while (r != 0); uv_close((uv_handle_t*) &client, close_cb); } diff --git a/deps/uv/test/test-tcp-write-fail.c b/deps/uv/test/test-tcp-write-fail.c index 2840d8161032be..5256a9f4a790aa 100644 --- a/deps/uv/test/test-tcp-write-fail.c +++ b/deps/uv/test/test-tcp-write-fail.c @@ -43,7 +43,7 @@ static void close_socket(uv_tcp_t* sock) { r = uv_fileno((uv_handle_t*)sock, &fd); ASSERT(r == 0); #ifdef _WIN32 - r = closesocket(fd); + r = closesocket((uv_os_sock_t)fd); #else r = close(fd); #endif diff --git a/deps/uv/test/test-threadpool-cancel.c b/deps/uv/test/test-threadpool-cancel.c index cb456224516823..784c1739f6d47e 100644 --- a/deps/uv/test/test-threadpool-cancel.c +++ b/deps/uv/test/test-threadpool-cancel.c @@ -276,7 +276,7 @@ TEST_IMPL(threadpool_cancel_work) { TEST_IMPL(threadpool_cancel_fs) { struct cancel_info ci; - uv_fs_t reqs[25]; + uv_fs_t reqs[26]; uv_loop_t* loop; unsigned n; uv_buf_t iov; @@ -305,6 +305,7 @@ TEST_IMPL(threadpool_cancel_fs) { ASSERT(0 == uv_fs_read(loop, reqs + n++, 0, &iov, 1, 0, fs_cb)); ASSERT(0 == uv_fs_scandir(loop, reqs + n++, "/", 0, fs_cb)); ASSERT(0 == uv_fs_readlink(loop, reqs + n++, "/", fs_cb)); + ASSERT(0 == uv_fs_realpath(loop, reqs + n++, "/", fs_cb)); ASSERT(0 == uv_fs_rename(loop, reqs + n++, "/", "/", fs_cb)); ASSERT(0 == uv_fs_mkdir(loop, reqs + n++, "/", 0, fs_cb)); ASSERT(0 == uv_fs_sendfile(loop, reqs + n++, 0, 0, 0, 0, fs_cb)); diff --git a/deps/uv/test/test-tty.c b/deps/uv/test/test-tty.c index 81e612c1d6ae1c..b844959d526340 100644 --- a/deps/uv/test/test-tty.c +++ b/deps/uv/test/test-tty.c @@ -153,11 +153,14 @@ TEST_IMPL(tty_file) { ASSERT(0 == close(fd)); } +/* Bug on AIX where '/dev/random' returns 1 from isatty() */ +#ifndef _AIX fd = open("/dev/random", O_RDONLY); if (fd != -1) { ASSERT(UV_EINVAL == uv_tty_init(&loop, &tty, fd, 1)); ASSERT(0 == close(fd)); } +#endif /* _AIX */ fd = open("/dev/zero", O_RDONLY); if (fd != -1) { diff --git a/deps/uv/test/test-udp-ipv6.c b/deps/uv/test/test-udp-ipv6.c index 1d5720ce73162a..1b0db78b8efcea 100644 --- a/deps/uv/test/test-udp-ipv6.c +++ b/deps/uv/test/test-udp-ipv6.c @@ -26,6 +26,10 @@ #include #include +#ifdef __FreeBSD__ +#include +#endif + #define CHECK_HANDLE(handle) \ ASSERT((uv_udp_t*)(handle) == &server \ || (uv_udp_t*)(handle) == &client \ @@ -43,6 +47,18 @@ static int send_cb_called; static int recv_cb_called; static int close_cb_called; +#ifdef __FreeBSD__ +static int can_ipv6_ipv4_dual() { + int v6only; + size_t size = sizeof(int); + + if (sysctlbyname("net.inet6.ip6.v6only", &v6only, &size, NULL, 0)) + return 0; + + return v6only != 1; +} +#endif + static void alloc_cb(uv_handle_t* handle, size_t suggested_size, @@ -150,6 +166,11 @@ TEST_IMPL(udp_dual_stack) { if (!can_ipv6()) RETURN_SKIP("IPv6 not supported"); +#ifdef __FreeBSD__ + if (!can_ipv6_ipv4_dual()) + RETURN_SKIP("IPv6-IPv4 dual stack not supported"); +#endif + do_test(ipv6_recv_ok, 0); ASSERT(recv_cb_called == 1); diff --git a/deps/uv/test/test-udp-multicast-join6.c b/deps/uv/test/test-udp-multicast-join6.c index 873cb6d811d749..f635bdb9e14ee2 100644 --- a/deps/uv/test/test-udp-multicast-join6.c +++ b/deps/uv/test/test-udp-multicast-join6.c @@ -119,7 +119,7 @@ TEST_IMPL(udp_multicast_join6) { ASSERT(r == 0); /* join the multicast channel */ -#if defined(__APPLE__) +#if defined(__APPLE__) || defined(_AIX) r = uv_udp_set_membership(&client, "ff02::1", "::1%lo0", UV_JOIN_GROUP); #else r = uv_udp_set_membership(&client, "ff02::1", NULL, UV_JOIN_GROUP); diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp index 8049faa7a66929..635a234ea6eee8 100644 --- a/deps/uv/uv.gyp +++ b/deps/uv/uv.gyp @@ -104,6 +104,13 @@ 'src/win/winsock.c', 'src/win/winsock.h', ], + 'conditions': [ + ['MSVS_VERSION < "2015"', { + 'sources': [ + 'src/win/snprintf.c' + ] + }] + ], 'link_settings': { 'libraries': [ '-ladvapi32', @@ -340,6 +347,7 @@ 'test/test-poll-close-doesnt-corrupt-stack.c', 'test/test-poll-closesocket.c', 'test/test-process-title.c', + 'test/test-queue-foreach-delete.c', 'test/test-ref.c', 'test/test-run-nowait.c', 'test/test-run-once.c', diff --git a/deps/v8/src/ast-value-factory.cc b/deps/v8/src/ast-value-factory.cc index 68cf015200365c..fbcde8b45703fc 100644 --- a/deps/v8/src/ast-value-factory.cc +++ b/deps/v8/src/ast-value-factory.cc @@ -29,6 +29,7 @@ #include "src/api.h" #include "src/objects.h" +#include "src/utils.h" namespace v8 { namespace internal { @@ -379,11 +380,32 @@ AstRawString* AstValueFactory::GetString(uint32_t hash, bool is_one_byte, bool AstValueFactory::AstRawStringCompare(void* a, void* b) { const AstRawString* lhs = static_cast(a); const AstRawString* rhs = static_cast(b); - if (lhs->is_one_byte() != rhs->is_one_byte()) return false; + if (lhs->length() != rhs->length()) return false; if (lhs->hash() != rhs->hash()) return false; - int len = lhs->byte_length(); - if (rhs->byte_length() != len) return false; - return memcmp(lhs->raw_data(), rhs->raw_data(), len) == 0; + const unsigned char* l = lhs->raw_data(); + const unsigned char* r = rhs->raw_data(); + size_t length = rhs->length(); + if (lhs->is_one_byte()) { + if (rhs->is_one_byte()) { + return CompareCharsUnsigned(reinterpret_cast(l), + reinterpret_cast(r), + length) == 0; + } else { + return CompareCharsUnsigned(reinterpret_cast(l), + reinterpret_cast(r), + length) == 0; + } + } else { + if (rhs->is_one_byte()) { + return CompareCharsUnsigned(reinterpret_cast(l), + reinterpret_cast(r), + length) == 0; + } else { + return CompareCharsUnsigned(reinterpret_cast(l), + reinterpret_cast(r), + length) == 0; + } + } } } // namespace internal } // namespace v8 diff --git a/deps/v8/src/elements.cc b/deps/v8/src/elements.cc index e830d7c4650052..f2ae31863a28ea 100644 --- a/deps/v8/src/elements.cc +++ b/deps/v8/src/elements.cc @@ -1100,13 +1100,18 @@ class FastElementsAccessor } int num_used = 0; for (int i = 0; i < backing_store->length(); ++i) { - if (!backing_store->is_the_hole(i)) ++num_used; - // Bail out early if more than 1/4 is used. - if (4 * num_used > backing_store->length()) break; - } - if (4 * num_used <= backing_store->length()) { - JSObject::NormalizeElements(obj); + if (!backing_store->is_the_hole(i)) { + ++num_used; + // Bail out if a number dictionary wouldn't be able to save at least + // 75% space. + if (4 * SeededNumberDictionary::ComputeCapacity(num_used) * + SeededNumberDictionary::kEntrySize > + backing_store->length()) { + return; + } + } } + JSObject::NormalizeElements(obj); } } diff --git a/deps/v8/src/objects.cc b/deps/v8/src/objects.cc index 5c863855f89d79..e7d4844ad05329 100644 --- a/deps/v8/src/objects.cc +++ b/deps/v8/src/objects.cc @@ -12459,6 +12459,8 @@ static bool ShouldConvertToFastElements(JSObject* object, uint32_t dictionary_size = static_cast(dictionary->Capacity()) * SeededNumberDictionary::kEntrySize; + + // Turn fast if the dictionary only saves 50% space. return 2 * dictionary_size >= *new_capacity; } diff --git a/deps/v8/test/mjsunit/regress/regress-4450.js b/deps/v8/test/mjsunit/regress/regress-4450.js new file mode 100644 index 00000000000000..31ff4f19c26d77 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-4450.js @@ -0,0 +1,8 @@ +// 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. + +({})['foobar\u2653'.slice(0, 6)] = null; +var x; +eval('x = function foobar() { return foobar };'); +x(); diff --git a/doc/api/addons.markdown b/doc/api/addons.markdown index 28a5457cca7c72..aa343d73192ce8 100644 --- a/doc/api/addons.markdown +++ b/doc/api/addons.markdown @@ -1,6 +1,6 @@ # Addons -Addons are dynamically linked shared objects. They can provide glue to C and +Addons are dynamically-linked shared objects. They can provide glue to C and C++ libraries. The API (at the moment) is rather complex, involving knowledge of several libraries: @@ -11,11 +11,11 @@ knowledge of several libraries: - [libuv][], C event loop library. Anytime one needs to wait for a file descriptor to become readable, wait for a timer, or wait for a signal - to be received one will need to interface with libuv. That is, if you + to be received, one will need to interface with libuv. That is, if you perform any I/O, libuv will need to be used. - - Internal Node.js libraries. Most importantly is the `node::ObjectWrap` - class which you will likely want to derive from. + - Internal Node.js libraries. The most important class is `node::ObjectWrap` + which you will likely want to derive from. - Others. Look in `deps/` for what else is available. @@ -28,7 +28,7 @@ be used as a starting-point for your own Addon. ## Hello world -To get started let's make a small Addon which is the C++ equivalent of +To get started, let's make a small Addon which is the C++ equivalent of the following JavaScript code: module.exports.hello = function() { return 'world'; }; @@ -68,11 +68,11 @@ Note that all Node.js addons must export an initialization function: There is no semi-colon after `NODE_MODULE` as it's not a function (see `node.h`). -The `module_name` needs to match the filename of the final binary (minus the -.node suffix). +The `module_name` needs to match the filename of the final binary (excluding +the .node suffix). The source code needs to be built into `addon.node`, the binary Addon. To -do this we create a file called `binding.gyp` which describes the configuration +do this, we create a file called `binding.gyp` which describes the configuration to build your module in a JSON-like format. This file gets compiled by [node-gyp][]. @@ -89,17 +89,17 @@ The next step is to generate the appropriate project build files for the current platform. Use `node-gyp configure` for that. Now you will have either a `Makefile` (on Unix platforms) or a `vcxproj` file -(on Windows) in the `build/` directory. Next invoke the `node-gyp build` +(on Windows) in the `build/` directory. Next, invoke the `node-gyp build` command. Now you have your compiled `.node` bindings file! The compiled bindings end up in `build/Release/`. -You can now use the binary addon in an Node.js project `hello.js` by pointing +You can now use the binary addon in a Node.js project `hello.js` by pointing `require` to the recently built `hello.node` module: // hello.js - var addon = require('./build/Release/addon'); + const addon = require('./build/Release/addon'); console.log(addon.hello()); // 'world' @@ -114,7 +114,7 @@ Below are some addon patterns to help you get started. Consult the online [Embedder's Guide][] for an explanation of several concepts used such as handles, scopes, function templates, etc. -In order to use these examples you need to compile them using `node-gyp`. +In order to use these examples, you need to compile them using `node-gyp`. Create the following `binding.gyp` file: { @@ -127,7 +127,7 @@ Create the following `binding.gyp` file: } In cases where there is more than one `.cc` file, simply add the file name to -the `sources` array, e.g.: +the `sources` array. For example: "sources": ["addon.cc", "myexample.cc"] @@ -189,7 +189,7 @@ function calls and return a result. This is the main and only needed source You can test it with the following JavaScript snippet: // test.js - var addon = require('./build/Release/addon'); + const addon = require('./build/Release/addon'); console.log( 'This should be eight:', addon.add(3,5) ); @@ -234,10 +234,10 @@ the full `module` object as the second argument. This allows the addon to completely overwrite `exports` with a single function instead of adding the function as a property of `exports`. -To test it run the following JavaScript snippet: +To test it, run the following JavaScript snippet: // test.js - var addon = require('./build/Release/addon'); + const addon = require('./build/Release/addon'); addon(function(msg){ console.log(msg); // 'hello world' @@ -282,7 +282,7 @@ the string passed to `createObject()`: To test it in JavaScript: // test.js - var addon = require('./build/Release/addon'); + const addon = require('./build/Release/addon'); var obj1 = addon('hello'); var obj2 = addon('world'); @@ -336,7 +336,7 @@ wraps a C++ function: To test: // test.js - var addon = require('./build/Release/addon'); + const addon = require('./build/Release/addon'); var fn = addon(); console.log(fn()); // 'hello world' @@ -344,8 +344,8 @@ To test: ### Wrapping C++ objects -Here we will create a wrapper for a C++ object/class `MyObject` that can be -instantiated in JavaScript through the `new` operator. First prepare the main +Here, we will create a wrapper for a C++ object/class `MyObject` that can be +instantiated in JavaScript through the `new` operator. First, prepare the main module `addon.cc`: // addon.cc @@ -365,7 +365,7 @@ module `addon.cc`: } // namespace demo -Then in `myobject.h` make your wrapper inherit from `node::ObjectWrap`: +Then, in `myobject.h`, make your wrapper inherit from `node::ObjectWrap`: // myobject.h #ifndef MYOBJECT_H @@ -394,7 +394,7 @@ Then in `myobject.h` make your wrapper inherit from `node::ObjectWrap`: #endif -And in `myobject.cc` implement the various methods that you want to expose. +And in `myobject.cc`, implement the various methods that you want to expose. Here we expose the method `plusOne` by adding it to the constructor's prototype: @@ -470,7 +470,7 @@ prototype: Test it with: // test.js - var addon = require('./build/Release/addon'); + const addon = require('./build/Release/addon'); var obj = new addon.MyObject(10); console.log( obj.plusOne() ); // 11 @@ -480,7 +480,8 @@ Test it with: ### Factory of wrapped objects This is useful when you want to be able to create native objects without -explicitly instantiating them with the `new` operator in JavaScript, e.g. +explicitly instantiating them with the `new` operator in JavaScript. For +example: var obj = addon.createObject(); // instead of: @@ -515,8 +516,9 @@ Let's register our `createObject` method in `addon.cc`: } // namespace demo -In `myobject.h` we now introduce the static method `NewInstance` that takes -care of instantiating the object (i.e. it does the job of `new` in JavaScript): +In `myobject.h`, we now introduce the static method `NewInstance` that takes +care of instantiating the object. In other words, it does the job of `new` in +JavaScript: // myobject.h #ifndef MYOBJECT_H @@ -628,7 +630,7 @@ The implementation is similar to the above in `myobject.cc`: Test it with: // test.js - var createObject = require('./build/Release/addon'); + const createObject = require('./build/Release/addon'); var obj = createObject(10); console.log( obj.plusOne() ); // 11 @@ -644,9 +646,9 @@ Test it with: ### Passing wrapped objects around In addition to wrapping and returning C++ objects, you can pass them around -by unwrapping them with Node.js's `node::ObjectWrap::Unwrap` helper function. -In the following `addon.cc` we introduce a function `add()` that can take on two -`MyObject` objects: +by unwrapping them with the Node.js helper function `node::ObjectWrap::Unwrap`. +In the following `addon.cc`, we introduce a function `add()` that can take on +two `MyObject` objects: // addon.cc #include @@ -690,7 +692,7 @@ In the following `addon.cc` we introduce a function `add()` that can take on two } // namespace demo -To make things interesting we introduce a public method in `myobject.h` so we +To make things interesting, we introduce a public method in `myobject.h` so we can probe private values after unwrapping the object: // myobject.h @@ -721,7 +723,7 @@ can probe private values after unwrapping the object: #endif -The implementation of `myobject.cc` is similar as before: +The implementation of `myobject.cc` is similar to before: // myobject.cc #include @@ -790,7 +792,7 @@ The implementation of `myobject.cc` is similar as before: Test it with: // test.js - var addon = require('./build/Release/addon'); + const addon = require('./build/Release/addon'); var obj1 = addon.createObject(10); var obj2 = addon.createObject(20); @@ -804,10 +806,10 @@ Test it with: * `callback`: `void (*)(void*)` - A pointer to the function to call at exit. * `args`: `void*` - A pointer to pass to the callback at exit. -Registers exit hooks that run after the event loop has ended, but before the VM +Registers exit hooks that run after the event loop has ended but before the VM is killed. -Callbacks are run in last-in, first-out order. AtExit takes two parameters: +Callbacks are run in last-in first-out order. AtExit takes two parameters: a pointer to a callback function to run at exit, and a pointer to untyped context data to be passed to that callback. @@ -864,11 +866,11 @@ The file `addon.cc` implements AtExit below: Test in JavaScript by running: // test.js - var addon = require('./build/Release/addon'); + const addon = require('./build/Release/addon'); [online]: https://v8docs.nodesource.com/ [libuv]: https://github.com/libuv/libuv -[download]: https://github.com/rvagg/node-addon-examples +[download]: https://github.com/nodejs/node-addon-examples [node-gyp]: https://github.com/nodejs/node-gyp [v8 reference]: http://izs.me/v8-docs/main.html -[Embedder's Guide]: http://code.google.com/apis/v8/embed.html +[Embedder's Guide]: https://code.google.com/apis/v8/embed.html diff --git a/doc/api/assert.markdown b/doc/api/assert.markdown index 6ea4071b79cc14..cf710c6ed4ced0 100644 --- a/doc/api/assert.markdown +++ b/doc/api/assert.markdown @@ -2,115 +2,343 @@ Stability: 3 - Locked -This module is used so that Node.js can test itself. It can be accessed with -`require('assert')`. However, it is recommended that a userland assertion -library be used instead. +The `assert` module provides a simple set of assertion tests that can be used to +test invariants. The module is intended for internal use by Node.js, but can be +used in application code via `require('assert')`. However, `assert` is not a +testing framework, and is not intended to be used as a general purpose assertion +library. + +The API for the `assert` module is [Locked][]. This means that there will be no +additions or changes to any of the methods implemented and exposed by +the module. ## assert(value[, message]), assert.ok(value[, message]) -Tests if value is truthy. It is equivalent to +Tests if `value` is truthy. It is equivalent to `assert.equal(!!value, true, message)`. +If `value` is not truthy, an `AssertionError` is thrown with a `message` +property set equal to the value of the `message` parameter. If the `message` +parameter is `undefined`, a default error message is assigned. + + const assert = require('assert'); + + assert(true); // OK + assert(1); // OK + assert(false); + // throws "AssertionError: false == true" + assert(0); + // throws "AssertionError: 0 == true" + assert(false, 'it\'s false'); + // throws "AssertionError: it's false" + + assert.ok(true); // OK + assert.ok(1); // OK + assert.ok(false); + // throws "AssertionError: false == true" + assert.ok(0); + // throws "AssertionError: 0 == true" + assert.ok(false, 'it\'s false'); + // throws "AssertionError: it's false" + ## assert.deepEqual(actual, expected[, message]) -Tests for deep equality. Primitive values are compared with the equal -comparison operator ( `==` ). +Tests for deep equality between the `actual` and `expected` parameters. +Primitive values are compared with the equal comparison operator ( `==` ). -This only considers enumerable properties. It does not test object prototypes, -attached symbols, or non-enumerable properties. This can lead to some -potentially surprising results. For example, this does not throw an -`AssertionError` because the properties on the `Error` object are -non-enumerable: +Only enumerable "own" properties are considered. The `deepEqual()` +implementation does not test object prototypes, attached symbols, or +non-enumerable properties. This can lead to some potentially surprising +results. For example, the following example does not throw an `AssertionError` +because the properties on the [`Error`][] object are non-enumerable: // WARNING: This does not throw an AssertionError! assert.deepEqual(Error('a'), Error('b')); +"Deep" equality means that the enumerable "own" properties of child objects +are evaluated also: + + const assert = require('assert'); + + const obj1 = { + a : { + b : 1 + } + }; + const obj2 = { + a : { + b : 2 + } + }; + const obj3 = { + a : { + b : 1 + } + } + const obj4 = Object.create(obj1); + + assert.deepEqual(obj1, obj1); + // OK, object is equal to itself + + assert.deepEqual(obj1, obj2); + // AssertionError: { a: { b: 1 } } deepEqual { a: { b: 2 } } + // values of b are different + + assert.deepEqual(obj1, obj3); + // OK, objects are equal + + assert.deepEqual(obj1, obj4); + // AssertionError: { a: { b: 1 } } deepEqual {} + // Prototypes are ignored + +If the values are not equal, an `AssertionError` is thrown with a `message` +property set equal to the value of the `message` parameter. If the `message` +parameter is undefined, a default error message is assigned. + ## assert.deepStrictEqual(actual, expected[, message]) -Tests for deep equality. Primitive values are compared with the strict equality -operator ( `===` ). +Generally identical to `assert.deepEqual` with the exception that primitive +values are compared using the strict equality operator ( `===` ). + + const assert = require('assert'); + + assert.deepEqual({a:1}, {a:'1'}); + // OK, because 1 == '1' + + assert.deepStrictEqual({a:1}, {a:'1'}); + // AssertionError: { a: 1 } deepStrictEqual { a: '1' } + // because 1 !== '1' using strict equality + +If the values are not equal, an `AssertionError` is thrown with a `message` +property set equal to the value of the `message` parameter. If the `message` +parameter is undefined, a default error message is assigned. ## assert.doesNotThrow(block[, error][, message]) -Expects `block` not to throw an error. See [assert.throws()][] for more details. +Asserts that the function `block` does not throw an error. See +[`assert.throws()`][] for more details. -If `block` throws an error and if it is of a different type from `error`, the -thrown error will get propagated back to the caller. The following call will -throw the `TypeError`, since we're not matching the error types in the -assertion. +When `assert.doesNotThrow()` is called, it will immediately call the `block` +function. + +If an error is thrown and it is the same type as that specified by the `error` +parameter, then an `AssertionError` is thrown. If the error is of a different +type, or if the `error` parameter is undefined, the error is propagated back +to the caller. + +The following, for instance, will throw the [`TypeError`][] because there is no +matching error type in the assertion: assert.doesNotThrow( function() { - throw new TypeError("Wrong value"); + throw new TypeError('Wrong value'); }, SyntaxError ); -In case `error` matches with the error thrown by `block`, an `AssertionError` -is thrown instead. +However, the following will result in an `AssertionError` with the message +'Got unwanted exception (TypeError)..': assert.doesNotThrow( function() { - throw new TypeError("Wrong value"); + throw new TypeError('Wrong value'); }, TypeError ); +If an `AssertionError` is thrown and a value is provided for the `message` +parameter, the value of `message` will be appended to the `AssertionError` +message: + + assert.doesNotThrow( + function() { + throw new TypeError('Wrong value'); + }, + TypeError, + 'Whoops' + ); + // Throws: AssertionError: Got unwanted exception (TypeError). Whoops + ## assert.equal(actual, expected[, message]) -Tests shallow, coercive equality with the equal comparison operator ( `==` ). +Tests shallow, coercive equality between the `actual` and `expected` parameters +using the equal comparison operator ( `==` ). + + const assert = require('assert'); + + assert.equal(1, 1); + // OK, 1 == 1 + assert.equal(1, '1'); + // OK, 1 == '1' + + assert.equal(1, 2); + // AssertionError: 1 == 2 + assert.equal({a: {b: 1}}, {a: {b: 1}}); + //AssertionError: { a: { b: 1 } } == { a: { b: 1 } } + +If the values are not equal, an `AssertionError` is thrown with a `message` +property set equal to the value of the `message` parameter. If the `message` +parameter is undefined, a default error message is assigned. ## assert.fail(actual, expected, message, operator) -Throws an exception that displays the values for `actual` and `expected` -separated by the provided operator. +Throws an `AssertionError`. If `message` is falsy, the error message is set as +the values of `actual` and `expected` separated by the provided `operator`. +Otherwise, the error message is the value of `message`. + + const assert = require('assert'); + + assert.fail(1, 2, undefined, '>'); + // AssertionError: 1 > 2 + + assert.fail(1, 2, 'whoops', '>'); + // AssertionError: whoops ## assert.ifError(value) Throws `value` if `value` is truthy. This is useful when testing the `error` argument in callbacks. + const assert = require('assert'); + + assert.ifError(0); // OK + assert.ifError(1); // Throws 1 + assert.ifError('error') // Throws 'error' + assert.ifError(new Error()); // Throws Error + ## assert.notDeepEqual(actual, expected[, message]) -Tests for any deep inequality. Opposite of `assert.deepEqual`. +Tests for any deep inequality. Opposite of [`assert.deepEqual`][]. + + const assert = require('assert'); + + const obj1 = { + a : { + b : 1 + } + }; + const obj2 = { + a : { + b : 2 + } + }; + const obj3 = { + a : { + b : 1 + } + } + const obj4 = Object.create(obj1); + + assert.deepEqual(obj1, obj1); + AssertionError: { a: { b: 1 } } notDeepEqual { a: { b: 1 } } + + assert.deepEqual(obj1, obj2); + // OK, obj1 and obj2 are not deeply equal + + assert.deepEqual(obj1, obj3); + // AssertionError: { a: { b: 1 } } notDeepEqual { a: { b: 1 } } + + assert.deepEqual(obj1, obj4); + // OK, obj1 and obj2 are not deeply equal + +If the values are deeply equal, an `AssertionError` is thrown with a `message` +property set equal to the value of the `message` parameter. If the `message` +parameter is undefined, a default error message is assigned. ## assert.notDeepStrictEqual(actual, expected[, message]) -Tests for deep inequality. Opposite of `assert.deepStrictEqual`. +Tests for deep strict inequality. Opposite of [`assert.deepStrictEqual`][]. + + const assert = require('assert'); + + assert.notDeepEqual({a:1}, {a:'1'}); + // AssertionError: { a: 1 } notDeepEqual { a: '1' } + + assert.notDeepStrictEqual({a:1}, {a:'1'}); + // OK + +If the values are deeply and strictly equal, an `AssertionError` is thrown +with a `message` property set equal to the value of the `message` parameter. If +the `message` parameter is undefined, a default error message is assigned. ## assert.notEqual(actual, expected[, message]) Tests shallow, coercive inequality with the not equal comparison operator ( `!=` ). + const assert = require('assert'); + + assert.notEqual(1, 2); + // OK + + assert.notEqual(1, 1); + // AssertionError: 1 != 1 + + assert.notEqual(1, '1'); + // AssertionError: 1 != '1' + +If the values are equal, an `AssertionError` is thrown with a `message` +property set equal to the value of the `message` parameter. If the `message` +parameter is undefined, a default error message is assigned. + ## assert.notStrictEqual(actual, expected[, message]) Tests strict inequality as determined by the strict not equal operator ( `!==` ). + const assert = require('assert'); + + assert.notStrictEqual(1, 2); + // OK + + assert.notStrictEqual(1, 1); + // AssertionError: 1 != 1 + + assert.notStrictEqual(1, '1'); + // OK + +If the values are strictly equal, an `AssertionError` is thrown with a +`message` property set equal to the value of the `message` parameter. If the +`message` parameter is undefined, a default error message is assigned. + ## assert.strictEqual(actual, expected[, message]) Tests strict equality as determined by the strict equality operator ( `===` ). + const assert = require('assert'); + + assert.strictEqual(1, 2); + // AssertionError: 1 === 2 + + assert.strictEqual(1, 1); + // OK + + assert.strictEqual(1, '1'); + // AssertionError: 1 === '1' + +If the values are not strictly equal, an `AssertionError` is thrown with a +`message` property set equal to the value of the `message` parameter. If the +`message` parameter is undefined, a default error message is assigned. + ## assert.throws(block[, error][, message]) -Expects `block` to throw an error. `error` can be a constructor, `RegExp`, or -validation function. +Expects the function `block` to throw an error. If specified, `error` can be a +constructor, [`RegExp`][], or validation function. Validate instanceof using constructor: assert.throws( function() { - throw new Error("Wrong value"); + throw new Error('Wrong value'); }, Error ); -Validate error message using RegExp: +Validate error message using [`RegExp`][]: assert.throws( function() { - throw new Error("Wrong value"); + throw new Error('Wrong value'); }, /value/ ); @@ -119,14 +347,20 @@ Custom error validation: assert.throws( function() { - throw new Error("Wrong value"); + throw new Error('Wrong value'); }, function(err) { if ( (err instanceof Error) && /value/.test(err) ) { return true; } }, - "unexpected error" + 'unexpected error' ); -[assert.throws()]: #assert_assert_throws_block_error_message +[Locked]: documentation.html#documentation_stability_index +[`assert.deepEqual`]: #assert_assert_deepequal_actual_expected_message +[`assert.deepStrictEqual`]: #assert_assert_deepstrictequal_actual_expected_message +[`assert.throws()`]: #assert_assert_throws_block_error_message +[`Error`]: errors.html#errors_class_error +[`RegExp`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions +[`TypeError`]: errors.html#errors_class_typeerror diff --git a/doc/api/buffer.markdown b/doc/api/buffer.markdown index 52c57010e5ba71..6fa7f7c9946965 100644 --- a/doc/api/buffer.markdown +++ b/doc/api/buffer.markdown @@ -2,7 +2,7 @@ Stability: 2 - Stable -Pure JavaScript is Unicode friendly but not nice to binary data. When +Pure JavaScript is Unicode-friendly but not nice to binary data. When dealing with TCP streams or the file system, it's necessary to handle octet streams. Node.js has several strategies for manipulating, creating, and consuming octet streams. @@ -15,23 +15,23 @@ The `Buffer` class is a global, making it very rare that one would need to ever `require('buffer')`. Converting between Buffers and JavaScript string objects requires an explicit -encoding method. Here are the different string encodings. +encoding method. The different string encodings are: -* `'ascii'` - for 7 bit ASCII data only. This encoding method is very fast, and +* `'ascii'` - for 7-bit ASCII data only. This encoding method is very fast and will strip the high bit if set. * `'utf8'` - Multibyte encoded Unicode characters. Many web pages and other document formats use UTF-8. -* `'utf16le'` - 2 or 4 bytes, little endian encoded Unicode characters. +* `'utf16le'` - 2 or 4 bytes, little-endian encoded Unicode characters. Surrogate pairs (U+10000 to U+10FFFF) are supported. * `'ucs2'` - Alias of `'utf16le'`. * `'base64'` - Base64 string encoding. -* `'binary'` - A way of encoding the buffer into a one-byte (i.e. `latin-1`) - encoded string. The string `'latin-1'` is not supported. Instead simply pass +* `'binary'` - A way of encoding the buffer into a one-byte (`latin-1`) + encoded string. The string `'latin-1'` is not supported. Instead, pass `'binary'` to use `'latin-1'` encoding. * `'hex'` - Encode each byte as two hexadecimal characters. @@ -45,12 +45,12 @@ Creating a typed array from a `Buffer` works with the following caveats: with elements `[1,2,3,4]`, not a `Uint32Array` with a single element `[0x1020304]` or `[0x4030201]`. -NOTE: Node.js v0.8 simply retained a reference to the buffer in `array.buffer` -instead of cloning it. +NOTE: Node.js v0.8 retained a reference to the buffer in `array.buffer` instead +of cloning it. While more efficient, it introduces subtle incompatibilities with the typed arrays specification. `ArrayBuffer#slice()` makes a copy of the slice while -`Buffer#slice()` creates a view. +[`Buffer#slice()`][] creates a view. ## Class: Buffer @@ -74,13 +74,13 @@ Copies the passed `buffer` data onto a new `Buffer` instance. * `size` Number Allocates a new buffer of `size` bytes. `size` must be less than -1,073,741,824 bytes (1 GB) on 32 bits architectures or -2,147,483,648 bytes (2 GB) on 64 bits architectures, -otherwise a `RangeError` is thrown. +1,073,741,824 bytes (1 GB) on 32-bit architectures or +2,147,483,648 bytes (2 GB) on 64-bit architectures. +Otherwise, a [`RangeError`][] is thrown. Unlike `ArrayBuffers`, the underlying memory for buffers is not initialized. So the contents of a newly created `Buffer` are unknown and could contain -sensitive data. Use `buf.fill(0)` to initialize a buffer to zeroes. +sensitive data. Use [`buf.fill(0)`][] to initialize a buffer to zeroes. ### new Buffer(str[, encoding]) @@ -97,15 +97,15 @@ Allocates a new buffer containing the given `str`. * Return: Number Gives the actual byte length of a string. `encoding` defaults to `'utf8'`. -This is not the same as `String.prototype.length` since that returns the +This is not the same as [`String.prototype.length`][] since that returns the number of *characters* in a string. Example: str = '\u00bd + \u00bc = \u00be'; - console.log(str + ": " + str.length + " characters, " + - Buffer.byteLength(str, 'utf8') + " bytes"); + console.log(`${str}: ${str.length} characters, ` + + `${Buffer.byteLength(str, 'utf8')} bytes`); // ½ + ¼ = ¾: 9 characters, 12 bytes @@ -208,14 +208,11 @@ Example: copy an ASCII string into a buffer, one byte at a time: // Node.js -Returns a boolean of whether `this` and `otherBuffer` have the same -bytes. - ### buf.compare(otherBuffer) * `otherBuffer` {Buffer} -Returns a number indicating whether `this` comes before or after or is +Returns a number indicating whether `this` comes before, after, or is the same as the `otherBuffer` in sort order. @@ -227,7 +224,7 @@ the same as the `otherBuffer` in sort order. * `sourceEnd` Number, Optional, Default: `buffer.length` Copies data from a region of this buffer to a region in the target buffer even -if the target memory region overlaps with the source. If `undefined` the +if the target memory region overlaps with the source. If `undefined`, the `targetStart` and `sourceStart` parameters default to `0` while `sourceEnd` defaults to `buffer.length`. @@ -267,6 +264,8 @@ region in the same buffer * `otherBuffer` {Buffer} +Returns a boolean indicating whether `this` and `otherBuffer` have the same bytes. + ### buf.fill(value[, offset][, end]) * `value` @@ -278,7 +277,7 @@ and `end` (defaults to `buffer.length`) are not given it will fill the entire buffer. var b = new Buffer(50); - b.fill("h"); + b.fill('h'); ### buf.indexOf(value[, byteOffset]) @@ -286,9 +285,9 @@ buffer. * `byteOffset` Number, Optional, Default: 0 * Return: Number -Operates similar to [Array#indexOf()][]. Accepts a String, Buffer or Number. +Operates similar to [`Array#indexOf()`][]. Accepts a String, Buffer or Number. Strings are interpreted as UTF8. Buffers will use the entire buffer. So in order -to compare a partial Buffer use `Buffer#slice()`. Numbers can range from 0 to +to compare a partial Buffer use [`Buffer#slice()`][]. Numbers can range from 0 to 255. ### buf.length @@ -302,7 +301,7 @@ buffer object. It does not change when the contents of the buffer are changed. buf = new Buffer(1234); console.log(buf.length); - buf.write("some string", 0, "ascii"); + buf.write('some string', 0, 'ascii'); console.log(buf.length); // 1234 @@ -311,10 +310,10 @@ buffer object. It does not change when the contents of the buffer are changed. While the `length` property is not immutable, changing the value of `length` can result in undefined and inconsistent behavior. Applications that wish to modify the length of a buffer should therefore treat `length` as read-only and -use `buf.slice` to create a new buffer. +use [`buf.slice`][] to create a new buffer. buf = new Buffer(10); - buf.write("abcdefghj", 0, "ascii"); + buf.write('abcdefghj', 0, 'ascii'); console.log(buf.length); // 10 buf = buf.slice(0,5); console.log(buf.length); // 5 @@ -326,7 +325,7 @@ use `buf.slice` to create a new buffer. * `noAssert` Boolean, Optional, Default: false * Return: Number -Reads a 64 bit double from the buffer at the specified offset with specified +Reads a 64-bit double from the buffer at the specified offset with specified endian format. Set `noAssert` to true to skip validation of `offset`. This means that `offset` @@ -356,7 +355,7 @@ Example: * `noAssert` Boolean, Optional, Default: false * Return: Number -Reads a 32 bit float from the buffer at the specified offset with specified +Reads a 32-bit float from the buffer at the specified offset with specified endian format. Set `noAssert` to true to skip validation of `offset`. This means that `offset` @@ -381,7 +380,7 @@ Example: * `noAssert` Boolean, Optional, Default: false * Return: Number -Reads a signed 8 bit integer from the buffer at the specified offset. +Reads a signed 8-bit integer from the buffer at the specified offset. Set `noAssert` to true to skip validation of `offset`. This means that `offset` may be beyond the end of the buffer. Defaults to `false`. @@ -396,7 +395,7 @@ complement signed values. * `noAssert` Boolean, Optional, Default: false * Return: Number -Reads a signed 16 bit integer from the buffer at the specified offset with +Reads a signed 16-bit integer from the buffer at the specified offset with specified endian format. Set `noAssert` to true to skip validation of `offset`. This means that `offset` @@ -412,7 +411,7 @@ complement signed values. * `noAssert` Boolean, Optional, Default: false * Return: Number -Reads a signed 32 bit integer from the buffer at the specified offset with +Reads a signed 32-bit integer from the buffer at the specified offset with specified endian format. Set `noAssert` to true to skip validation of `offset`. This means that `offset` @@ -447,7 +446,7 @@ may be beyond the end of the buffer. Defaults to `false`. * `noAssert` Boolean, Optional, Default: false * Return: Number -Reads an unsigned 8 bit integer from the buffer at the specified offset. +Reads an unsigned 8-bit integer from the buffer at the specified offset. Set `noAssert` to true to skip validation of `offset`. This means that `offset` may be beyond the end of the buffer. Defaults to `false`. @@ -477,7 +476,7 @@ Example: * `noAssert` Boolean, Optional, Default: false * Return: Number -Reads an unsigned 16 bit integer from the buffer at the specified offset with +Reads an unsigned 16-bit integer from the buffer at the specified offset with specified endian format. Set `noAssert` to true to skip validation of `offset`. This means that `offset` @@ -513,7 +512,7 @@ Example: * `noAssert` Boolean, Optional, Default: false * Return: Number -Reads an unsigned 32 bit integer from the buffer at the specified offset with +Reads an unsigned 32-bit integer from the buffer at the specified offset with specified endian format. Set `noAssert` to true to skip validation of `offset`. This means that `offset` @@ -599,12 +598,12 @@ defaults to `'utf8'`. The `start` and `end` parameters default to `0` and buf.toString('utf8',0,5); // outputs: abcde buf.toString(undefined,0,5); // encoding defaults to 'utf8', outputs abcde -See `buffer.write()` example, above. +See `buf.write()` example, below. ### buf.toJSON() -Returns a JSON-representation of the Buffer instance. `JSON.stringify` +Returns a JSON representation of the Buffer instance. `JSON.stringify` implicitly calls this function when stringifying a Buffer instance. Example: @@ -640,7 +639,7 @@ The method will not write partial characters. buf = new Buffer(256); len = buf.write('\u00bd + \u00bc = \u00be', 0); - console.log(len + " bytes: " + buf.toString('utf8', 0, len)); + console.log(`${len} bytes: ${buf.toString('utf8', 0, len)}`); ### buf.writeDoubleBE(value, offset[, noAssert]) ### buf.writeDoubleLE(value, offset[, noAssert]) @@ -650,7 +649,7 @@ The method will not write partial characters. * `noAssert` Boolean, Optional, Default: false Writes `value` to the buffer at the specified offset with specified endian -format. Note, `value` must be a valid 64 bit double. +format. `value` must be a valid 64-bit double. Set `noAssert` to true to skip validation of `value` and `offset`. This means that `value` may be too large for the specific function and `offset` may be @@ -679,7 +678,7 @@ Example: * `noAssert` Boolean, Optional, Default: false Writes `value` to the buffer at the specified offset with specified endian -format. Note, behavior is unspecified if `value` is not a 32 bit float. +format. Behavior is unspecified if `value` is not a 32-bit float. Set `noAssert` to true to skip validation of `value` and `offset`. This means that `value` may be too large for the specific function and `offset` may be @@ -706,8 +705,8 @@ Example: * `offset` Number * `noAssert` Boolean, Optional, Default: false -Writes `value` to the buffer at the specified offset. Note, `value` must be a -valid signed 8 bit integer. +Writes `value` to the buffer at the specified offset. `value` must be a +valid signed 8-bit integer. Set `noAssert` to true to skip validation of `value` and `offset`. This means that `value` may be too large for the specific function and `offset` may be @@ -725,7 +724,7 @@ signed integer into `buffer`. * `noAssert` Boolean, Optional, Default: false Writes `value` to the buffer at the specified offset with specified endian -format. Note, `value` must be a valid signed 16 bit integer. +format. `value` must be a valid signed 16-bit integer. Set `noAssert` to true to skip validation of `value` and `offset`. This means that `value` may be too large for the specific function and `offset` may be @@ -743,7 +742,7 @@ complement signed integer into `buffer`. * `noAssert` Boolean, Optional, Default: false Writes `value` to the buffer at the specified offset with specified endian -format. Note, `value` must be a valid signed 32 bit integer. +format. `value` must be a valid signed 32-bit integer. Set `noAssert` to true to skip validation of `value` and `offset`. This means that `value` may be too large for the specific function and `offset` may be @@ -778,8 +777,8 @@ to `false`. * `offset` Number * `noAssert` Boolean, Optional, Default: false -Writes `value` to the buffer at the specified offset. Note, `value` must be a -valid unsigned 8 bit integer. +Writes `value` to the buffer at the specified offset. `value` must be a +valid unsigned 8-bit integer. Set `noAssert` to true to skip validation of `value` and `offset`. This means that `value` may be too large for the specific function and `offset` may be @@ -806,7 +805,7 @@ Example: * `noAssert` Boolean, Optional, Default: false Writes `value` to the buffer at the specified offset with specified endian -format. Note, `value` must be a valid unsigned 16 bit integer. +format. `value` must be a valid unsigned 16-bit integer. Set `noAssert` to true to skip validation of `value` and `offset`. This means that `value` may be too large for the specific function and `offset` may be @@ -837,7 +836,7 @@ Example: * `noAssert` Boolean, Optional, Default: false Writes `value` to the buffer at the specified offset with specified endian -format. Note, `value` must be a valid unsigned 32 bit integer. +format. `value` must be a valid unsigned 32-bit integer. Set `noAssert` to true to skip validation of `value` and `offset`. This means that `value` may be too large for the specific function and `offset` may be @@ -882,11 +881,11 @@ to `false`. * Number, Default: 50 How many bytes will be returned when `buffer.inspect()` is called. This can -be overridden by user modules. See [util.inspect()][] for more details on +be overridden by user modules. See [`util.inspect()`][] for more details on `buffer.inspect()` behavior. Note that this is a property on the buffer module returned by -`require('buffer')`, not on the Buffer global, or a buffer instance. +`require('buffer')`, not on the Buffer global or a buffer instance. ## ES6 iteration @@ -901,7 +900,7 @@ Buffers can be iterated over using `for..of` syntax: // 2 // 3 -Additionally, `buffer.values()`, `buffer.keys()` and `buffer.entries()` +Additionally, the `buffer.values()`, `buffer.keys()`, and `buffer.entries()` methods can be used to create iterators. ## Class: SlowBuffer @@ -914,7 +913,7 @@ larger allocated object. This approach improves both performance and memory usage since v8 does not need to track and cleanup as many `Persistent` objects. In the case where a developer may need to retain a small chunk of memory from a -pool for an indeterminate amount of time it may be appropriate to create an +pool for an indeterminate amount of time, it may be appropriate to create an un-pooled Buffer instance using SlowBuffer and copy out the relevant bits. // need to keep around a few small chunks of memory @@ -929,9 +928,14 @@ un-pooled Buffer instance using SlowBuffer and copy out the relevant bits. store.push(sb); }); -Though this should be used sparingly and only be a last resort *after* a developer -has actively observed undue memory retention in their applications. +This should be used only as a last resort *after* a developer has observed +undue memory retention in their applications. +[`Array#indexOf()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf +[`buf.fill(0)`]: #buffer_buf_fill_value_offset_end +[`buf.slice`]: #buffer_buf_slice_start_end [`buf1.compare(buf2)`]: #buffer_buf_compare_otherbuffer -[Array#indexOf()]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf -[util.inspect()]: util.html#util_util_inspect_object_options +[`Buffer#slice()`]: #buffer_buf_slice_start_end +[`RangeError`]: errors.html#errors_class_rangeerror +[`String.prototype.length`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/length +[`util.inspect()`]: util.html#util_util_inspect_object_options diff --git a/doc/api/child_process.markdown b/doc/api/child_process.markdown index d52d974f74c41f..1ab53227fdc1ee 100644 --- a/doc/api/child_process.markdown +++ b/doc/api/child_process.markdown @@ -10,25 +10,25 @@ It is possible to stream data through a child's `stdin`, `stdout`, and line-buffered I/O internally. That doesn't affect Node.js but it means data you send to the child process may not be immediately consumed.) -To create a child process use `require('child_process').spawn()` or +To create a child process, use `require('child_process').spawn()` or `require('child_process').fork()`. The semantics of each are slightly -different, and explained [below][]. +different as explained [below][]. For scripting purposes you may find the [synchronous counterparts][] more convenient. ## Class: ChildProcess -`ChildProcess` is an [EventEmitter][]. +`ChildProcess` is an [`EventEmitter`][]. Child processes always have three streams associated with them. `child.stdin`, `child.stdout`, and `child.stderr`. These may be shared with the stdio streams of the parent process, or they may be separate stream objects which can be piped to and from. -The ChildProcess class is not intended to be used directly. Use the -`spawn()`, `exec()`, `execFile()`, or `fork()` methods to create a Child -Process instance. +The `ChildProcess` class is not intended to be used directly. Use the +[`spawn()`][], [`exec()`][], [`execFile()`][], or [`fork()`][] methods to create +an instance of `ChildProcess`. ### Event: 'close' @@ -37,7 +37,7 @@ Process instance. was killed by the parent. This event is emitted when the stdio streams of a child process have all -terminated. This is distinct from 'exit', since multiple processes +terminated. This is distinct from `'exit'`, since multiple processes might share the same stdio streams. ### Event: 'disconnect' @@ -54,11 +54,11 @@ Emitted when: 1. The process could not be spawned, or 2. The process could not be killed, or -3. Sending a message to the child process failed for whatever reason. +3. Sending a message to the child process failed. -Note that the `exit`-event may or may not fire after an error has occurred. If -you are listening on both events to fire a function, remember to guard against -calling your function twice. +Note that the `'exit'` event may or may not fire after an error has occurred. +If you are listening on both events to fire a function, remember to guard +against calling your function twice. See also [`ChildProcess#kill()`][] and [`ChildProcess#send()`][]. @@ -75,20 +75,19 @@ of the signal, otherwise `null`. Note that the child process stdio streams might still be open. -Also, note that Node.js establishes signal handlers for `'SIGINT'` and -`'SIGTERM`', so it will not terminate due to receipt of those signals, -it will exit. +Also, note that Node.js establishes signal handlers for `SIGINT` and +`SIGTERM`. It will not terminate due to receipt of those signals. It will exit. See `waitpid(2)`. ### Event: 'message' * `message` {Object} a parsed JSON object or primitive value. -* `sendHandle` {Handle object} a [net.Socket][] or [net.Server][] object, or +* `sendHandle` {Handle object} a [`net.Socket`][] or [`net.Server`][] object, or undefined. Messages sent by `.send(message, [sendHandle])` are obtained using the -`message` event. +`'message'` event. ### child.connected @@ -103,11 +102,11 @@ gracefully once there are no other connections keeping it alive. After calling this method the `.connected` flag will be set to `false` in both the parent and child, and it is no longer possible to send messages. -The 'disconnect' event will be emitted when there are no messages in the process -of being received, most likely immediately. +The `'disconnect'` event will be emitted when there are no messages in the +process of being received, most likely immediately. Note that you can also call `process.disconnect()` in the child process when the -child process has any open IPC channels with the parent (i.e `fork()`). +child process has any open IPC channels with the parent (i.e [`fork()`][]). ### child.kill([signal]) @@ -116,11 +115,12 @@ child process has any open IPC channels with the parent (i.e `fork()`). Send a signal to the child process. If no argument is given, the process will be sent `'SIGTERM'`. See `signal(7)` for a list of available signals. - var spawn = require('child_process').spawn, - grep = spawn('grep', ['ssh']); + const spawn = require('child_process').spawn; + const grep = spawn('grep', ['ssh']); - grep.on('close', function (code, signal) { - console.log('child process terminated due to receipt of signal ' + signal); + grep.on('close', (code, signal) => { + console.log( + `child process terminated due to receipt of signal ${signal}`); }); // send SIGHUP to process @@ -128,9 +128,9 @@ be sent `'SIGTERM'`. See `signal(7)` for a list of available signals. May emit an `'error'` event when the signal cannot be delivered. Sending a signal to a child process that has already exited is not an error but may -have unforeseen consequences: if the PID (the process ID) has been reassigned -to another process, the signal will be delivered to that process instead. -What happens next is anyone's guess. +have unforeseen consequences. Specifically, if the process identifier (PID) has +been reassigned to another process, the signal will be delivered to that +process instead. What happens next is anyone's guess. Note that while the function is called `kill`, the signal delivered to the child process may not actually kill it. `kill` really just sends a signal @@ -142,14 +142,14 @@ See `kill(2)` * {Integer} -The PID of the child process. +The process identifier (PID) of the child process. Example: - var spawn = require('child_process').spawn, - grep = spawn('grep', ['ssh']); + const spawn = require('child_process').spawn; + const grep = spawn('grep', ['ssh']); - console.log('Spawned child pid: ' + grep.pid); + console.log(`Spawned child pid: ${grep.pid}`); grep.stdin.end(); ### child.send(message[, sendHandle][, callback]) @@ -165,11 +165,10 @@ a `'message'` event on the child. For example: - var cp = require('child_process'); + const cp = require('child_process'); + const n = cp.fork(`${__dirname}/sub.js`); - var n = cp.fork(__dirname + '/sub.js'); - - n.on('message', function(m) { + n.on('message', (m) => { console.log('PARENT got message:', m); }); @@ -177,28 +176,28 @@ For example: And then the child script, `'sub.js'` might look like this: - process.on('message', function(m) { + process.on('message', (m) => { console.log('CHILD got message:', m); }); process.send({ foo: 'bar' }); -In the child the `process` object will have a `send()` method, and `process` +In the child, the `process` object will have a `send()` method, and `process` will emit objects each time it receives a message on its channel. There is a special case when sending a `{cmd: 'NODE_foo'}` message. All messages containing a `NODE_` prefix in its `cmd` property will not be emitted in -the `message` event, since they are internal messages used by Node.js core. -Messages containing the prefix are emitted in the `internalMessage` event. +the `'message'` event, since they are internal messages used by Node.js core. +Messages containing the prefix are emitted in the `'internalMessage'` event. Avoid using this feature; it is subject to change without notice. The `sendHandle` option to `child.send()` is for sending a TCP server or socket object to another process. The child will receive the object as its -second argument to the `message` event. +second argument to the `'message'` event. The `callback` option is a function that is invoked after the message is sent but before the target may have received it. It is called with a single -argument: `null` on success, or an `Error` object on failure. +argument: `null` on success, or an [`Error`][] object on failure. `child.send()` emits an `'error'` event if no callback was given and the message cannot be sent, for example because the child process has already exited. @@ -211,22 +210,22 @@ Use the callback mechanism to implement flow control. Here is an example of sending a server: - var child = require('child_process').fork('child.js'); + const child = require('child_process').fork('child.js'); // Open up the server object and send the handle. - var server = require('net').createServer(); - server.on('connection', function (socket) { + const server = require('net').createServer(); + server.on('connection', (socket) => { socket.end('handled by parent'); }); - server.listen(1337, function() { + server.listen(1337, () => { child.send('server', server); }); And the child would then receive the server object as: - process.on('message', function(m, server) { + process.on('message', (m, server) => { if (m === 'server') { - server.on('connection', function (socket) { + server.on('connection', (socket) => { socket.end('handled by child'); }); } @@ -236,7 +235,7 @@ Note that the server is now shared between the parent and child, this means that some connections will be handled by the parent and some by the child. For `dgram` servers the workflow is exactly the same. Here you listen on -a `message` event instead of `connection` and use `server.bind` instead of +a `'message'` event instead of `'connection'` and use `server.bind` instead of `server.listen`. (Currently only supported on UNIX platforms.) #### Example: sending socket object @@ -246,12 +245,12 @@ connections with the remote address `74.125.127.100` as VIP by sending the socket to a "special" child process. Other sockets will go to a "normal" process. - var normal = require('child_process').fork('child.js', ['normal']); - var special = require('child_process').fork('child.js', ['special']); + const normal = require('child_process').fork('child.js', ['normal']); + const special = require('child_process').fork('child.js', ['special']); // Open up the server and send sockets to child - var server = require('net').createServer(); - server.on('connection', function (socket) { + const server = require('net').createServer(); + server.on('connection', (socket) => { // if this is a VIP if (socket.remoteAddress === '74.125.127.100') { @@ -265,9 +264,9 @@ process. The `child.js` could look like this: - process.on('message', function(m, socket) { + process.on('message', (m, socket) => { if (m === 'socket') { - socket.end('You were handled as a ' + process.argv[2] + ' person'); + socket.end(`You were handled as a ${process.argv[2]} person`); } }); @@ -307,7 +306,7 @@ to the same object, or null. * {Array} A sparse array of pipes to the child process, corresponding with positions in -the [stdio][] option to [spawn][] that have been set to `'pipe'`. +the [`stdio`][] option to [`spawn()`][] that have been set to `'pipe'`. Note that streams 0-2 are also available as ChildProcess.stdin, ChildProcess.stdout, and ChildProcess.stderr, respectively. @@ -315,11 +314,11 @@ In the following example, only the child's fd `1` is setup as a pipe, so only the parent's `child.stdio[1]` is a stream, all other values in the array are `null`. - var assert = require('assert'); - var fs = require('fs'); - var child_process = require('child_process'); + const assert = require('assert'); + const fs = require('fs'); + const child_process = require('child_process'); - child = child_process.spawn('ls', { + const child = child_process.spawn('ls', { stdio: [ 0, // use parents stdin for child 'pipe', // pipe child's stdout to parent @@ -378,20 +377,18 @@ callback or returning an EventEmitter). Runs a command in a shell and buffers the output. - var exec = require('child_process').exec, - child; - - child = exec('cat *.js bad_file | wc -l', - function (error, stdout, stderr) { - console.log('stdout: ' + stdout); - console.log('stderr: ' + stderr); + 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); + console.log(`exec error: ${error}`); } }); The callback gets the arguments `(error, stdout, stderr)`. On success, `error` -will be `null`. On error, `error` will be an instance of `Error` and `error.code` +will be `null`. On error, `error` will be an instance of [`Error`][] and `error.code` will be the exit code of the child process, and `error.signal` will be set to the signal that terminated the process. @@ -451,7 +448,7 @@ leaner than [`child_process.exec()`][]. It has the same options. (Default: `process.execArgv`) * `silent` {Boolean} If true, stdin, stdout, and stderr of the child will be piped to the parent, otherwise they will be inherited from the parent, see - the "pipe" and "inherit" options for `spawn()`'s `stdio` for more details + the `'pipe'` and `'inherit'` options for [`spawn()`][]'s [`stdio`][] for more details (default is false) * `uid` {Number} Sets the user identity of the process. (See setuid(2).) * `gid` {Number} Sets the group identity of the process. (See setgid(2).) @@ -472,7 +469,7 @@ done with care and by default will talk over the fd represented an environmental variable `NODE_CHANNEL_FD` on the child process. The input and output on this fd is expected to be line delimited JSON objects. -*Note: Unlike the `fork()` POSIX system call, `child_process.fork()` does not clone the +*Note: Unlike the `fork()` POSIX system call, [`child_process.fork()`][] does not clone the current process.* ### child_process.spawn(command[, args][, options]) @@ -508,64 +505,64 @@ process, the default is `process.env`. Example of running `ls -lh /usr`, capturing `stdout`, `stderr`, and the exit code: - var spawn = require('child_process').spawn, - ls = spawn('ls', ['-lh', '/usr']); + const spawn = require('child_process').spawn; + const ls = spawn('ls', ['-lh', '/usr']); - ls.stdout.on('data', function (data) { - console.log('stdout: ' + data); + ls.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); }); - ls.stderr.on('data', function (data) { - console.log('stderr: ' + data); + ls.stderr.on('data', (data) => { + console.log(`stderr: ${data}`); }); - ls.on('close', function (code) { - console.log('child process exited with code ' + code); + ls.on('close', (code) => { + console.log(`child process exited with code ${code}`); }); Example: A very elaborate way to run 'ps ax | grep ssh' - var spawn = require('child_process').spawn, - ps = spawn('ps', ['ax']), - grep = spawn('grep', ['ssh']); + const spawn = require('child_process').spawn; + const ps = spawn('ps', ['ax']); + const grep = spawn('grep', ['ssh']); - ps.stdout.on('data', function (data) { + ps.stdout.on('data', (data) => { grep.stdin.write(data); }); - ps.stderr.on('data', function (data) { - console.log('ps stderr: ' + data); + ps.stderr.on('data', (data) => { + console.log(`ps stderr: ${data}`); }); - ps.on('close', function (code) { + ps.on('close', (code) => { if (code !== 0) { - console.log('ps process exited with code ' + code); + console.log(`ps process exited with code ${code}`); } grep.stdin.end(); }); - grep.stdout.on('data', function (data) { - console.log('' + data); + grep.stdout.on('data', (data) => { + console.log(`${data}`); }); - grep.stderr.on('data', function (data) { - console.log('grep stderr: ' + data); + grep.stderr.on('data', (data) => { + console.log(`grep stderr: ${data}`); }); - grep.on('close', function (code) { + grep.on('close', (code) => { if (code !== 0) { - console.log('grep process exited with code ' + code); + console.log(`grep process exited with code ${code}`); } }); Example of checking for failed exec: - var spawn = require('child_process').spawn, - child = spawn('bad_command'); + const spawn = require('child_process').spawn; + const child = spawn('bad_command'); - child.on('error', function (err) { + child.on('error', (err) => { console.log('Failed to start child process.'); }); @@ -587,12 +584,12 @@ and the parent's event loop will not include the child in its reference count. Example of detaching a long-running process and redirecting its output to a file: - var fs = require('fs'), - spawn = require('child_process').spawn, - out = fs.openSync('./out.log', 'a'), - err = fs.openSync('./out.log', 'a'); + const fs = require('fs'); + const spawn = require('child_process').spawn; + const out = fs.openSync('./out.log', 'a'); + const err = fs.openSync('./out.log', 'a'); - var child = spawn('prg', [], { + const child = spawn('prg', [], { detached: true, stdio: [ 'ignore', out, err ] }); @@ -613,7 +610,7 @@ As a shorthand, the `stdio` argument may be one of the following strings: * `'ignore'` - `['ignore', 'ignore', 'ignore']` * `'inherit'` - `[process.stdin, process.stdout, process.stderr]` or `[0,1,2]` -Otherwise, the 'stdio' option to `child_process.spawn()` is an array where each +Otherwise, the `'stdio'` option to [`child_process.spawn()`][] is an array where each index corresponds to a fd in the child. The value is one of the following: 1. `'pipe'` - Create a pipe between the child process and the parent process. @@ -646,7 +643,7 @@ index corresponds to a fd in the child. The value is one of the following: Example: - var spawn = require('child_process').spawn; + const spawn = require('child_process').spawn; // Child will use parent's stdios spawn('prg', [], { stdio: 'inherit' }); @@ -697,7 +694,7 @@ the `SIGTERM` signal and doesn't exit, your process will wait until the child process has exited. If the process times out, or has a non-zero exit code, this method ***will*** -throw. The `Error` object will contain the entire result from +throw. The [`Error`][] object will contain the entire result from [`child_process.spawnSync()`][] ### child_process.execSync(command[, options]) @@ -731,7 +728,7 @@ the `SIGTERM` signal and doesn't exit, your process will wait until the child process has exited. If the process times out, or has a non-zero exit code, this method ***will*** -throw. The `Error` object will contain the entire result from +throw. The [`Error`][] object will contain the entire result from [`child_process.spawnSync()`][] ### child_process.spawnSync(command[, args][, options]) @@ -766,16 +763,20 @@ until the process has completely exited. That is to say, if the process handles the `SIGTERM` signal and doesn't exit, your process will wait until the child process has exited. -[below]: #child_process_asynchronous_process_creation -[synchronous counterparts]: #child_process_synchronous_process_creation -[EventEmitter]: events.html#events_class_events_eventemitter -[`ChildProcess#kill()`]: #child_process_child_kill_signal -[`ChildProcess#send()`]: #child_process_child_send_message_sendhandle_callback -[net.Server]: net.html#net_class_net_server -[net.Socket]: net.html#net_class_net_socket -[`child_process.fork()`]: #child_process_child_process_fork_modulepath_args_options -[stdio]: #child_process_options_stdio -[spawn]: #child_process_child_process_spawn_command_args_options [`child_process.exec()`]: #child_process_child_process_exec_command_options_callback +[`child_process.fork()`]: #child_process_child_process_fork_modulepath_args_options [`child_process.spawn()`]: #child_process_child_process_spawn_command_args_options [`child_process.spawnSync()`]: #child_process_child_process_spawnsync_command_args_options +[`ChildProcess#kill()`]: #child_process_child_kill_signal +[`ChildProcess#send()`]: #child_process_child_send_message_sendhandle_callback +[`Error`]: errors.html#errors_class_error +[`EventEmitter`]: events.html#events_class_events_eventemitter +[`exec()`]: #child_process_child_process_exec_command_options_callback +[`execFile()`]: #child_process_child_process_execfile_file_args_options_callback +[`fork()`]: #child_process_child_process_fork_modulepath_args_options +[`net.Server`]: net.html#net_class_net_server +[`net.Socket`]: net.html#net_class_net_socket +[`spawn()`]: #child_process_child_process_spawn_command_args_options +[`stdio`]: #child_process_options_stdio +[below]: #child_process_asynchronous_process_creation +[synchronous counterparts]: #child_process_synchronous_process_creation diff --git a/doc/api/cluster.markdown b/doc/api/cluster.markdown index 702ef4ede79b3a..b29c13694b00fd 100644 --- a/doc/api/cluster.markdown +++ b/doc/api/cluster.markdown @@ -9,9 +9,9 @@ processes to handle the load. The cluster module allows you to easily create child processes that all share server ports. - var cluster = require('cluster'); - var http = require('http'); - var numCPUs = require('os').cpus().length; + const cluster = require('cluster'); + const http = require('http'); + const numCPUs = require('os').cpus().length; if (cluster.isMaster) { // Fork workers. @@ -19,15 +19,15 @@ all share server ports. cluster.fork(); } - cluster.on('exit', function(worker, code, signal) { - console.log('worker ' + worker.process.pid + ' died'); + cluster.on('exit', (worker, code, signal) => { + console.log(`worker ${worker.process.pid} died`); }); } else { // Workers can share any TCP connection // In this case it is an HTTP server - http.createServer(function(req, res) { + http.createServer((req, res) => { res.writeHead(200); - res.end("hello world\n"); + res.end('hello world\n'); }).listen(8000); } @@ -46,7 +46,7 @@ server in a worker. -The worker processes are spawned using the `child_process.fork` method, +The worker processes are spawned using the [`child_process.fork`][] method, so that they can communicate with the parent via IPC and pass server handles back and forth. @@ -113,13 +113,13 @@ it can be obtained using `cluster.worker`. Similar to the `cluster.on('disconnect')` event, but specific to this worker. - cluster.fork().on('disconnect', function() { + cluster.fork().on('disconnect', () => { // Worker has disconnected }); ### Event: 'error' -This event is the same as the one provided by `child_process.fork()`. +This event is the same as the one provided by [`child_process.fork()`][]. In a worker you can also use `process.on('error')`. @@ -131,14 +131,14 @@ In a worker you can also use `process.on('error')`. Similar to the `cluster.on('exit')` event, but specific to this worker. - var worker = cluster.fork(); - worker.on('exit', function(code, signal) { + const worker = cluster.fork(); + worker.on('exit', (code, signal) => { if( signal ) { - console.log("worker was killed by signal: "+signal); + console.log(`worker was killed by signal: ${signal}`); } else if( code !== 0 ) { - console.log("worker exited with error code: "+code); + console.log(`worker exited with error code: ${code}`); } else { - console.log("worker success!"); + console.log('worker success!'); } }); @@ -148,7 +148,7 @@ Similar to the `cluster.on('exit')` event, but specific to this worker. Similar to the `cluster.on('listening')` event, but specific to this worker. - cluster.fork().on('listening', function(address) { + cluster.fork().on('listening', (address) => { // Worker is listening }); @@ -160,22 +160,22 @@ It is not emitted in the worker. Similar to the `cluster.on('message')` event, but specific to this worker. -This event is the same as the one provided by `child_process.fork()`. +This event is the same as the one provided by [`child_process.fork()`][]. In a worker you can also use `process.on('message')`. As an example, here is a cluster that keeps count of the number of requests in the master process using the message system: - var cluster = require('cluster'); - var http = require('http'); + const cluster = require('cluster'); + const http = require('http'); if (cluster.isMaster) { // Keep track of http requests var numReqs = 0; - setInterval(function() { - console.log("numReqs =", numReqs); + setInterval(() => { + console.log('numReqs =', numReqs); }, 1000); // Count requests @@ -186,21 +186,21 @@ in the master process using the message system: } // Start workers and listen for messages containing notifyRequest - var numCPUs = require('os').cpus().length; + const numCPUs = require('os').cpus().length; for (var i = 0; i < numCPUs; i++) { cluster.fork(); } - Object.keys(cluster.workers).forEach(function(id) { + Object.keys(cluster.workers).forEach((id) => { cluster.workers[id].on('message', messageHandler); }); } else { // Worker processes have a http server. - http.Server(function(req, res) { + http.Server((req, res) => { res.writeHead(200); - res.end("hello world\n"); + res.end('hello world\n'); // notify master about the request process.send({ cmd: 'notifyRequest' }); @@ -211,7 +211,7 @@ in the master process using the message system: Similar to the `cluster.on('online')` event, but specific to this worker. - cluster.fork().on('online', function() { + cluster.fork().on('online', () => { // Worker is online }); @@ -219,7 +219,7 @@ It is not emitted in the worker. ### worker.disconnect() -In a worker, this function will close all servers, wait for the 'close' event on +In a worker, this function will close all servers, wait for the `'close'` event on those servers, and then disconnect the IPC channel. In the master, an internal message is sent to the worker causing it to call @@ -238,38 +238,38 @@ automatically closed by workers, and disconnect does not wait for them to close before exiting. Note that in a worker, `process.disconnect` exists, but it is not this function, -it is [disconnect][]. +it is [`disconnect`][]. Because long living server connections may block workers from disconnecting, it may be useful to send a message, so application specific actions may be taken to close them. It also may be useful to implement a timeout, killing a worker if -the `disconnect` event has not been emitted after some time. +the `'disconnect'` event has not been emitted after some time. if (cluster.isMaster) { var worker = cluster.fork(); var timeout; - worker.on('listening', function(address) { + worker.on('listening', (address) => { worker.send('shutdown'); worker.disconnect(); - timeout = setTimeout(function() { + timeout = setTimeout(() => { worker.kill(); }, 2000); }); - worker.on('disconnect', function() { + worker.on('disconnect', () => { clearTimeout(timeout); }); } else if (cluster.isWorker) { - var net = require('net'); - var server = net.createServer(function(socket) { + const net = require('net'); + var server = net.createServer((socket) => { // connections never end }); server.listen(8000); - process.on('message', function(msg) { + process.on('message', (msg) => { if(msg === 'shutdown') { // initiate graceful close of any connections to server } @@ -290,7 +290,7 @@ cluster.workers This function returns `true` if the worker is connected to its master via its IPC channel, `false` otherwise. A worker is connected to its master after it's been -created. It is disconnected after the `disconnect` event is emitted. +created. It is disconnected after the `'disconnect'` event is emitted. ### worker.isDead() @@ -311,13 +311,13 @@ Causes `.suicide` to be set. This method is aliased as `worker.destroy()` for backwards compatibility. Note that in a worker, `process.kill()` exists, but it is not this function, -it is [kill][]. +it is [`kill`][]. ### worker.process * {ChildProcess object} -All workers are created using `child_process.fork()`, the returned object +All workers are created using [`child_process.fork()`][], the returned object from this function is stored as `.process`. In a worker, the global `process` is stored. @@ -337,7 +337,7 @@ disconnection. Send a message to a worker or master, optionally with a handle. In the master this sends a message to a specific worker. It is identical to -[ChildProcess.send()][]. +[`ChildProcess.send()`][]. In a worker this sends a message to the master. It is identical to `process.send()`. @@ -349,7 +349,7 @@ This example will echo back all messages from the master: worker.send('hi there'); } else if (cluster.isWorker) { - process.on('message', function(msg) { + process.on('message', (msg) => { process.send(msg); }); } @@ -363,7 +363,7 @@ Set by calling `.kill()` or `.disconnect()`, until then it is `undefined`. The boolean `worker.suicide` lets you distinguish between voluntary and accidental exit, the master may choose not to respawn a worker based on this value. - cluster.on('exit', function(worker, code, signal) { + cluster.on('exit', (worker, code, signal) => { if (worker.suicide === true) { console.log('Oh, it was just suicide\' – no need to worry'). } @@ -380,12 +380,12 @@ Emitted after the worker IPC channel has disconnected. This can occur when a worker exits gracefully, is killed, or is disconnected manually (such as with worker.disconnect()). -There may be a delay between the `disconnect` and `exit` events. These events +There may be a delay between the `'disconnect'` and `'exit'` events. These events can be used to detect if the process is stuck in a cleanup or if there are long-living connections. - cluster.on('disconnect', function(worker) { - console.log('The worker #' + worker.id + ' has disconnected'); + cluster.on('disconnect', (worker) => { + console.log(`The worker #${worker.id} has disconnected`); }); ## Event: 'exit' @@ -395,11 +395,11 @@ long-living connections. * `signal` {String} the name of the signal (eg. `'SIGHUP'`) that caused the process to be killed. -When any of the workers die the cluster module will emit the 'exit' event. +When any of the workers die the cluster module will emit the `'exit'` event. This can be used to restart the worker by calling `.fork()` again. - cluster.on('exit', function(worker, code, signal) { + cluster.on('exit', (worker, code, signal) => { console.log('worker %d died (%s). restarting...', worker.process.pid, signal || code); cluster.fork(); @@ -411,21 +411,21 @@ See [child_process event: 'exit'][]. * `worker` {Worker object} -When a new worker is forked the cluster module will emit a 'fork' event. +When a new worker is forked the cluster module will emit a `'fork'` event. This can be used to log worker activity, and create your own timeout. var timeouts = []; function errorMsg() { - console.error("Something must be wrong with the connection ..."); + console.error('Something must be wrong with the connection ...'); } - cluster.on('fork', function(worker) { + cluster.on('fork', (worker) => { timeouts[worker.id] = setTimeout(errorMsg, 2000); }); - cluster.on('listening', function(worker, address) { + cluster.on('listening', (worker, address) => { clearTimeout(timeouts[worker.id]); }); - cluster.on('exit', function(worker, code, signal) { + cluster.on('exit', (worker, code, signal) => { clearTimeout(timeouts[worker.id]); errorMsg(); }); @@ -435,16 +435,17 @@ This can be used to log worker activity, and create your own timeout. * `worker` {Worker object} * `address` {Object} -After calling `listen()` from a worker, when the 'listening' event is emitted on -the server, a listening event will also be emitted on `cluster` in the master. +After calling `listen()` from a worker, when the `'listening'` event is emitted on +the server, a `'listening'` event will also be emitted on `cluster` in the master. The event handler is executed with two arguments, the `worker` contains the worker object and the `address` object contains the following connection properties: `address`, `port` and `addressType`. This is very useful if the worker is listening on more than one address. - cluster.on('listening', function(worker, address) { - console.log("A worker is now connected to " + address.address + ":" + address.port); + cluster.on('listening', (worker, address) => { + console.log( + `A worker is now connected to ${address.address}:${address.port}`); }); The `addressType` is one of: @@ -469,11 +470,11 @@ See [child_process event: 'message'][]. After forking a new worker, the worker should respond with an online message. When the master receives an online message it will emit this event. -The difference between 'fork' and 'online' is that fork is emitted when the +The difference between `'fork'` and `'online'` is that fork is emitted when the master forks a worker, and 'online' is emitted when the worker is running. - cluster.on('online', function(worker) { - console.log("Yay, the worker responded after it was forked"); + cluster.on('online', (worker) => { + console.log('Yay, the worker responded after it was forked'); }); ## Event: 'setup' @@ -584,7 +585,7 @@ Note that: Example: - var cluster = require('cluster'); + const cluster = require('cluster'); cluster.setupMaster({ exec: 'worker.js', args: ['--use', 'https'], @@ -604,14 +605,14 @@ This can only be called from the master process. A reference to the current worker object. Not available in the master process. - var cluster = require('cluster'); + const cluster = require('cluster'); if (cluster.isMaster) { console.log('I am master'); cluster.fork(); cluster.fork(); } else if (cluster.isWorker) { - console.log('I am worker #' + cluster.worker.id); + console.log(`I am worker #${cluster.worker.id}`); } ## cluster.workers @@ -633,21 +634,22 @@ before last `'disconnect'` or `'exit'` event is emitted. callback(cluster.workers[id]); } } - eachWorker(function(worker) { + eachWorker((worker) => { worker.send('big announcement to all workers'); }); Should you wish to reference a worker over a communication channel, using the worker's unique id is the easiest way to find the worker. - socket.on('data', function(id) { + socket.on('data', (id) => { var worker = cluster.workers[id]; }); -[server.close()]: net.html#net_event_close -[disconnect]: child_process.html#child_process_child_disconnect -[kill]: process.html#process_process_kill_pid_signal +[`child_process.fork()`]: child_process.html#child_process_child_process_fork_modulepath_args_options +[`ChildProcess.send()`]: child_process.html#child_process_child_send_message_sendhandle_callback +[`disconnect`]: child_process.html#child_process_child_disconnect +[`kill`]: process.html#process_process_kill_pid_signal +[`server.close()`]: net.html#net_event_close [Child Process module]: child_process.html#child_process_child_process_fork_modulepath_args_options -[ChildProcess.send()]: child_process.html#child_process_child_send_message_sendhandle_callback [child_process event: 'exit']: child_process.html#child_process_event_exit [child_process event: 'message']: child_process.html#child_process_event_message diff --git a/doc/api/console.markdown b/doc/api/console.markdown index 824b1947996f1f..c0cc060ec14995 100644 --- a/doc/api/console.markdown +++ b/doc/api/console.markdown @@ -2,124 +2,176 @@ Stability: 2 - Stable -The module defines a `Console` class and exports a `console` object. +The `console` module provides a simple debugging console that is similar to the +JavaScript console mechanism provided by web browsers. -The `console` object is a special instance of `Console` whose output is -sent to stdout or stderr. +The module exports two specific components: -For ease of use, `console` is defined as a global object and can be used -directly without `require`. +* A `Console` class with methods such as `console.log()`, `console.error()` and + `console.warn()` that can be used to write to any Node.js stream. +* A global `console` instance configured to write to `stdout` and `stderr`. + Because this object is global, it can be used without calling + `require('console')`. + +Example using the global `console`: + + console.log('hello world'); + // Prints: hello world, to stdout + console.log('hello %s', 'world'); + // Prints: hello world, to stdout + console.error(new Error('Whoops, something bad happened')); + // Prints: [Error: Whoops, something bad happened], to stderr + + const name = 'Will Robinson'; + console.warn(`Danger ${name}! Danger!`); + // Prints: Danger Will Robinson! Danger!, to stderr + +Example using the `Console` class: + + const out = getStreamSomehow(); + const err = getStreamSomehow(); + const myConsole = new console.Console(out, err); + + myConsole.log('hello world'); + // Prints: hello world, to out + myConsole.log('hello %s', 'world'); + // Prints: hello world, to out + myConsole.error(new Error('Whoops, something bad happened')); + // Prints: [Error: Whoops, something bad happened], to err + + const name = 'Will Robinson'; + myConsole.warn(`Danger ${name}! Danger!`); + // Prints: Danger Will Robinson! Danger!, to err + +While the API for the `Console` class is designed fundamentally around the +Web browser `console` object, the `Console` is Node.js is *not* intended to +duplicate the browsers functionality exactly. + +## Asynchronous vs Synchronous Consoles + +The console functions are synchronous when the destination is a terminal or +a file (to avoid lost messages in case of premature exit) and asynchronous +when the destination is a pipe (to avoid blocking for long periods of time). + +In the following example, stdout is non-blocking while stderr is blocking: + + $ node script.js 2> error.log | tee info.log + +Typically, the distinction between blocking/non-blocking is not important +unless an application is logging significant amounts of data. High volume +logging *should* use a `Console` instance that writes to a pipe. ## Class: Console -Use `require('console').Console` or `console.Console` to access this class. - - var Console = require('console').Console; - var Console = console.Console; +The `Console` class can be used to create a simple logger with configurable +output streams and can be accessed using either `require('console').Console` +or `console.Console`: -You can use `Console` class to custom simple logger like `console`, but with -different output streams. + const Console = require('console').Console; + const Console = console.Console; ### new Console(stdout[, stderr]) -Create a new `Console` by passing one or two writable stream instances. +Creates a new `Console` by passing one or two writable stream instances. `stdout` is a writable stream to print log or info output. `stderr` is used for warning or error output. If `stderr` isn't passed, the warning and error output will be sent to the `stdout`. - var output = fs.createWriteStream('./stdout.log'); - var errorOutput = fs.createWriteStream('./stderr.log'); + const output = fs.createWriteStream('./stdout.log'); + const errorOutput = fs.createWriteStream('./stderr.log'); // custom simple logger - var logger = new Console(output, errorOutput); + const logger = new Console(output, errorOutput); // use it like console var count = 5; logger.log('count: %d', count); // in stdout.log: count 5 The global `console` is a special `Console` whose output is sent to -`process.stdout` and `process.stderr`: +`process.stdout` and `process.stderr`. It is equivalent to calling: new Console(process.stdout, process.stderr); -## console - -* {Object} - - - -For printing to stdout and stderr. Similar to the console object functions -provided by most web browsers, here the output is sent to stdout or stderr. - -The console functions are synchronous when the destination is a terminal or -a file (to avoid lost messages in case of premature exit) and asynchronous -when it's a pipe (to avoid blocking for long periods of time). - -That is, in the following example, stdout is non-blocking while stderr -is blocking: - - $ node script.js 2> error.log | tee info.log - -In daily use, the blocking/non-blocking dichotomy is not something you -should worry about unless you log huge amounts of data. - ### console.assert(value[, message][, ...]) -Similar to [assert.ok()][], but the error message is formatted as -`util.format(message...)`. +A simple assertion test that verifies whether `value` is truthy. If it is not, +an `AssertionError` is throw. If provided, the error `message` is formatted +using [`util.format()`][] and used as the error message. + + console.assert(true, 'does nothing'); + // OK + console.assert(false, 'Whoops %s', 'didn\'t work'); + // AssertionError: Whoops didn't work ### console.dir(obj[, options]) -Uses `util.inspect` on `obj` and prints resulting string to stdout. This function -bypasses any custom `inspect()` function on `obj`. An optional *options* object -may be passed that alters certain aspects of the formatted string: +Uses [`util.inspect()`][] on `obj` and prints the resulting string to stdout. +This function bypasses any custom `inspect()` function defined on `obj`. An +optional `options` object may be passed that alters certain aspects of the +formatted string: - `showHidden` - if `true` then the object's non-enumerable and symbol properties will be shown too. Defaults to `false`. - `depth` - tells `inspect` how many times to recurse while formatting the object. This is useful for inspecting large complicated objects. Defaults to -`2`. To make it recurse indefinitely pass `null`. +`2`. To make it recurse indefinitely, pass `null`. - `colors` - if `true`, then the output will be styled with ANSI color codes. -Defaults to `false`. Colors are customizable, see [customizing util.inspect colors][]. +Defaults to `false`. Colors are customizable; see +[customizing `util.inspect()` colors][]. ### console.error([data][, ...]) -Same as `console.log` but prints to stderr. +Prints to stderr with newline. Multiple arguments can be passed, with the first +used as the primary message and all additional used as substitution +values similar to `printf()` (the arguments are all passed to +[`util.format()`][]). + + const code = 5; + console.error('error #%d', code); + // Prints: error #5, to stderr + console.error('error', code); + // Prints: error 5, to stderr + +If formatting elements (e.g. `%d`) are not found in the first string then +[`util.inspect()`][] is called on each argument and the resulting string +values are concatenated. See [`util.format()`][] for more information. ### console.info([data][, ...]) -Same as `console.log`. +The `console.info()` function is an alias for [`console.log()`][]. ### console.log([data][, ...]) -Prints to stdout with newline. This function can take multiple arguments in a -`printf()`-like way. Example: +Prints to stdout with newline. Multiple arguments can be passed, with the first +used as the primary message and all additional used as substitution +values similar to `printf()` (the arguments are all passed to +[`util.format()`][]). var count = 5; console.log('count: %d', count); - // prints 'count: 5' + // Prints: count: 5, to stdout + console.log('count: ', count); + // Prints: count: 5, to stdout -If formatting elements are not found in the first string then `util.inspect` -is used on each argument. See [util.format()][] for more information. +If formatting elements (e.g. `%d`) are not found in the first string then +[`util.inspect()`][] is called on each argument and the resulting string +values are concatenated. See [`util.format()`][] for more information. ### console.time(label) Used to calculate the duration of a specific operation. To start a timer, call -the `console.time()` method, giving it a name as only parameter. To stop the +the `console.time()` method, giving it a unique `label` as the only parameter. To stop the timer, and to get the elapsed time in milliseconds, just call the [`console.timeEnd()`][] method, again passing the -timer's name as the parameter. +timer's unique `label` as the parameter. ### console.timeEnd(label) -Stops a timer that was previously started by calling -[`console.time()`][] and prints the result to the -console. - -Example: +Stops a timer that was previously started by calling [`console.time()`][] and +prints the result to stdout: console.time('100-elements'); for (var i = 0; i < 100; i++) { @@ -130,15 +182,30 @@ Example: ### console.trace(message[, ...]) -Print to stderr `'Trace :'`, followed by the formatted message and stack trace -to the current position. +Prints to stderr the string `'Trace :'`, followed by the [`util.format()`][] +formatted message and stack trace to the current position in the code. + + console.trace('Show me'); + // Prints: (stack trace will vary based on where trace is called) + // Trace: Show me + // at repl:2:9 + // at REPLServer.defaultEval (repl.js:248:27) + // at bound (domain.js:287:14) + // at REPLServer.runBound [as eval] (domain.js:300:12) + // at REPLServer. (repl.js:412:12) + // at emitOne (events.js:82:20) + // at REPLServer.emit (events.js:169:7) + // at REPLServer.Interface._onLine (readline.js:210:10) + // at REPLServer.Interface._line (readline.js:549:8) + // at REPLServer.Interface._ttyWrite (readline.js:826:14) ### console.warn([data][, ...]) -Same as `console.error`. +The `console.warn()` function is an alias for [`console.error()`][]. -[assert.ok()]: assert.html#assert_assert_value_message_assert_ok_value_message -[customizing util.inspect colors]: util.html#util_customizing_util_inspect_colors -[util.format()]: util.html#util_util_format_format -[`console.timeEnd()`]: #console_console_timeend_label +[`console.error()`]: #console_console_error_data +[`console.log()`]: #console_console_log_data [`console.time()`]: #console_console_time_label +[`console.timeEnd()`]: #console_console_timeend_label +[`util.format()`]: util.html#util_util_format_format +[`util.inspect()`]: util.html#util_util_inspect_object_options diff --git a/doc/api/crypto.markdown b/doc/api/crypto.markdown index 60231b17072692..d98365842423ff 100644 --- a/doc/api/crypto.markdown +++ b/doc/api/crypto.markdown @@ -14,7 +14,7 @@ decipher, sign and verify methods. The class used for working with signed public key & challenges. The most common usage for this series of functions is when dealing with the `` -element. http://www.openssl.org/docs/apps/spkac.html +element. https://www.openssl.org/docs/apps/spkac.html Returned by `crypto.Certificate`. @@ -89,7 +89,7 @@ data as it is streamed. Class for decrypting data. -Returned by `crypto.createDecipher` and `crypto.createDecipheriv`. +Returned by [`crypto.createDecipher`][] and [`crypto.createDecipheriv`][]. Decipher objects are [streams][] that are both readable and writable. The written enciphered data is used to produce the plain-text data on @@ -125,7 +125,7 @@ You can disable auto padding if the data has been encrypted without standard block padding to prevent `decipher.final` from checking and removing it. This will only work if the input data's length is a multiple of the ciphers block size. You must call this before streaming data to -`decipher.update`. +[`decipher.update`][]. ### decipher.update(data[, input_encoding][, output_encoding]) @@ -264,15 +264,15 @@ expected. Example (obtaining a shared secret): - var crypto = require('crypto'); - var alice = crypto.createECDH('secp256k1'); - var bob = crypto.createECDH('secp256k1'); + const crypto = require('crypto'); + const alice = crypto.createECDH('secp256k1'); + const bob = crypto.createECDH('secp256k1'); alice.generateKeys(); bob.generateKeys(); - var alice_secret = alice.computeSecret(bob.getPublicKey(), null, 'hex'); - var bob_secret = bob.computeSecret(alice.getPublicKey(), null, 'hex'); + const alice_secret = alice.computeSecret(bob.getPublicKey(), null, 'hex'); + const bob_secret = bob.computeSecret(alice.getPublicKey(), null, 'hex'); /* alice_secret and bob_secret should be the same */ console.log(alice_secret == bob_secret); @@ -426,15 +426,15 @@ is used to compute the hash. Once the writable side of the stream is ended, use the `read()` method to get the enciphered contents. The legacy `update` and `final` methods are also supported. -Note: `createCipher` derives keys with the OpenSSL function [EVP_BytesToKey][] +Note: `createCipher` derives keys with the OpenSSL function [`EVP_BytesToKey`][] with the digest algorithm set to MD5, one iteration, and no salt. The lack of salt allows dictionary attacks as the same password always creates the same key. The low iteration count and non-cryptographically secure hash algorithm allow passwords to be tested very rapidly. -In line with OpenSSL's recommendation to use pbkdf2 instead of EVP_BytesToKey it -is recommended you derive a key and iv yourself with [crypto.pbkdf2][] and to -then use [createCipheriv()][] to create the cipher stream. +In line with OpenSSL's recommendation to use pbkdf2 instead of [`EVP_BytesToKey`][] it +is recommended you derive a key and iv yourself with [`crypto.pbkdf2`][] and to +then use [`createCipheriv()`][] to create the cipher stream. ## crypto.createCipheriv(algorithm, key, iv) @@ -448,7 +448,7 @@ the raw key used by the algorithm. `iv` is an [initialization vector][]. ## crypto.createCredentials(details) - Stability: 0 - Deprecated: Use [tls.createSecureContext][] instead. + Stability: 0 - Deprecated: Use [`tls.createSecureContext`][] instead. Creates a credentials object, with the optional details being a dictionary with keys: @@ -464,7 +464,7 @@ dictionary with keys: (Certificate Revocation List) * `ciphers`: A string describing the ciphers to use or exclude. Consult - + for details on the format. If no 'ca' details are given, then Node.js will use the default @@ -474,12 +474,12 @@ publicly trusted list of CAs as given in ## crypto.createDecipher(algorithm, password) Creates and returns a decipher object, with the given algorithm and -key. This is the mirror of the [createCipher()][] above. +key. This is the mirror of the [`createCipher()`][] above. ## crypto.createDecipheriv(algorithm, key, iv) Creates and returns a decipher object, with the given algorithm, key -and iv. This is the mirror of the [createCipheriv()][] above. +and iv. This is the mirror of the [`createCipheriv()`][] above. ## crypto.createDiffieHellman(prime[, prime_encoding][, generator][, generator_encoding]) @@ -500,7 +500,7 @@ If no `generator` is specified, then `2` is used. ## crypto.createECDH(curve_name) Creates an Elliptic Curve (EC) Diffie-Hellman key exchange object using a -predefined curve specified by the `curve_name` string. Use [getCurves()][] to +predefined curve specified by the `curve_name` string. Use [`getCurves()`][] to obtain a list of available curve names. On recent releases, `openssl ecparam -list_curves` will also display the name and description of each available elliptic curve. @@ -518,20 +518,20 @@ algorithms. Example: this program that takes the sha256 sum of a file - var filename = process.argv[2]; - var crypto = require('crypto'); - var fs = require('fs'); + const filename = process.argv[2]; + const crypto = require('crypto'); + const fs = require('fs'); - var shasum = crypto.createHash('sha256'); + const shasum = crypto.createHash('sha256'); - var s = fs.ReadStream(filename); - s.on('data', function(d) { + const s = fs.ReadStream(filename); + s.on('data', (d) => { shasum.update(d); }); - s.on('end', function() { + s.on('end', () => { var d = shasum.digest('hex'); - console.log(d + ' ' + filename); + console.log(`${d} ${filename}`); }); ## crypto.createHmac(algorithm, key) @@ -564,7 +564,7 @@ Returns an array with the names of the supported ciphers. Example: - var ciphers = crypto.getCiphers(); + const ciphers = crypto.getCiphers(); console.log(ciphers); // ['aes-128-cbc', 'aes-128-ccm', ...] ## crypto.getCurves() @@ -573,7 +573,7 @@ Returns an array with the names of the supported elliptic curves. Example: - var curves = crypto.getCurves(); + const curves = crypto.getCurves(); console.log(curves); // ['secp256k1', 'secp384r1', ...] ## crypto.getDiffieHellman(group_name) @@ -583,23 +583,23 @@ supported groups are: `'modp1'`, `'modp2'`, `'modp5'` (defined in [RFC 2412][], but see [Caveats][]) and `'modp14'`, `'modp15'`, `'modp16'`, `'modp17'`, `'modp18'` (defined in [RFC 3526][]). The returned object mimics the interface of objects created by -[crypto.createDiffieHellman()][] above, but will not allow changing -the keys (with [diffieHellman.setPublicKey()][] for example). The +[`crypto.createDiffieHellman()`][] above, but will not allow changing +the keys (with [`diffieHellman.setPublicKey()`][] for example). The advantage of using this routine is that the parties do not have to generate nor exchange group modulus beforehand, saving both processor and communication time. Example (obtaining a shared secret): - var crypto = require('crypto'); - var alice = crypto.getDiffieHellman('modp14'); - var bob = crypto.getDiffieHellman('modp14'); + const crypto = require('crypto'); + const alice = crypto.getDiffieHellman('modp14'); + const bob = crypto.getDiffieHellman('modp14'); alice.generateKeys(); bob.generateKeys(); - var alice_secret = alice.computeSecret(bob.getPublicKey(), null, 'hex'); - var bob_secret = bob.computeSecret(alice.getPublicKey(), null, 'hex'); + const alice_secret = alice.computeSecret(bob.getPublicKey(), null, 'hex'); + const bob_secret = bob.computeSecret(alice.getPublicKey(), null, 'hex'); /* alice_secret and bob_secret should be the same */ console.log(alice_secret == bob_secret); @@ -610,7 +610,7 @@ Returns an array with the names of the supported hash algorithms. Example: - var hashes = crypto.getHashes(); + const hashes = crypto.getHashes(); console.log(hashes); // ['sha', 'sha1', 'sha1WithRSAEncryption', ...] ## crypto.pbkdf2(password, salt, iterations, keylen[, digest], callback) @@ -635,7 +635,7 @@ Example: console.log(key.toString('hex')); // 'c5e478d...1469e50' }); -You can get a list of supported digest functions with [crypto.getHashes()][]. +You can get a list of supported digest functions with [`crypto.getHashes()`][]. ## crypto.pbkdf2Sync(password, salt, iterations, keylen[, digest]) @@ -694,7 +694,7 @@ NOTE: All paddings are defined in `constants` module. Generates cryptographically strong pseudo-random data. Usage: // async - crypto.randomBytes(256, function(ex, buf) { + crypto.randomBytes(256, (ex, buf) => { if (ex) throw ex; console.log('Have %d bytes of random data: %s', buf.length, buf); }); @@ -782,22 +782,25 @@ Based on the recommendations of [NIST SP 800-131A]: See the reference for other recommendations and details. -[stream]: stream.html -[streams]: stream.html +[`createCipher()`]: #crypto_crypto_createcipher_algorithm_password +[`createCipheriv()`]: #crypto_crypto_createcipheriv_algorithm_key_iv +[`crypto.createDecipher`]: #crypto_crypto_createdecipher_algorithm_password +[`crypto.createDecipheriv`]: #crypto_crypto_createdecipheriv_algorithm_key_iv +[`crypto.createDiffieHellman()`]: #crypto_crypto_creatediffiehellman_prime_prime_encoding_generator_generator_encoding +[`crypto.getHashes()`]: #crypto_crypto_gethashes +[`crypto.pbkdf2`]: #crypto_crypto_pbkdf2_password_salt_iterations_keylen_digest_callback +[`decipher.update`]: #crypto_decipher_update_data_input_encoding_output_encoding +[`diffieHellman.setPublicKey()`]: #crypto_diffiehellman_setpublickey_public_key_encoding +[`EVP_BytesToKey`]: https://www.openssl.org/docs/crypto/EVP_BytesToKey.html +[`getCurves()`]: #crypto_crypto_getcurves +[`tls.createSecureContext`]: tls.html#tls_tls_createsecurecontext_details [buffer]: buffer.html [buffers]: buffer.html -[createCipher()]: #crypto_crypto_createcipher_algorithm_password -[createCipheriv()]: #crypto_crypto_createcipheriv_algorithm_key_iv -[getCurves()]: #crypto_crypto_getcurves -[crypto.createDiffieHellman()]: #crypto_crypto_creatediffiehellman_prime_prime_encoding_generator_generator_encoding -[tls.createSecureContext]: tls.html#tls_tls_createsecurecontext_details -[diffieHellman.setPublicKey()]: #crypto_diffiehellman_setpublickey_public_key_encoding -[RFC 2412]: http://www.rfc-editor.org/rfc/rfc2412.txt -[RFC 3526]: http://www.rfc-editor.org/rfc/rfc3526.txt -[crypto.pbkdf2]: #crypto_crypto_pbkdf2_password_salt_iterations_keylen_digest_callback -[EVP_BytesToKey]: https://www.openssl.org/docs/crypto/EVP_BytesToKey.html -[NIST SP 800-132]: http://csrc.nist.gov/publications/nistpubs/800-132/nist-sp800-132.pdf -[NIST SP 800-131A]: http://csrc.nist.gov/publications/nistpubs/800-131A/sp800-131A.pdf -[initialization vector]: http://en.wikipedia.org/wiki/Initialization_vector [Caveats]: #crypto_caveats -[crypto.getHashes()]: #crypto_crypto_gethashes +[initialization vector]: https://en.wikipedia.org/wiki/Initialization_vector +[NIST SP 800-131A]: http://csrc.nist.gov/publications/nistpubs/800-131A/sp800-131A.pdf +[NIST SP 800-132]: http://csrc.nist.gov/publications/nistpubs/800-132/nist-sp800-132.pdf +[RFC 2412]: https://www.rfc-editor.org/rfc/rfc2412.txt +[RFC 3526]: https://www.rfc-editor.org/rfc/rfc3526.txt +[stream]: stream.html +[streams]: stream.html diff --git a/doc/api/debugger.markdown b/doc/api/debugger.markdown index 224f53eb45e2ba..11d31477d41717 100644 --- a/doc/api/debugger.markdown +++ b/doc/api/debugger.markdown @@ -4,9 +4,10 @@ -V8 comes with an extensive debugger which is accessible out-of-process via a -simple [TCP protocol][]. Node.js has a built-in client for this debugger. To -use this, start Node.js with the `debug` argument; a prompt will appear: +Node.js includes a full-featured out-of-process debugging utility accessible +via a simple [TCP-based protocol][] and built-in debugging client. To use it, +start Node.js with the `debug` argument followed by the path to the script to +debug; a prompt will be displayed indicating successful launch of the debugger: % node debug myscript.js < debugger listening on port 5858 @@ -17,21 +18,23 @@ use this, start Node.js with the `debug` argument; a prompt will appear: 3 debugger; debug> -Node.js's debugger client doesn't support the full range of commands, but -simple step and inspection is possible. By putting the statement `debugger;` -into the source code of your script, you will enable a breakpoint. +Node.js's debugger client does not yet support the full range of commands, but +simple step and inspection are possible. -For example, suppose `myscript.js` looked like this: +Inserting the statement `debugger;` into the source code of a script will +enable a breakpoint at that position in the code. + +For example, suppose `myscript.js` is written as: // myscript.js x = 5; setTimeout(function () { debugger; - console.log("world"); + console.log('world'); }, 1000); - console.log("hello"); + console.log('hello'); -Then once the debugger is run, it will break on line 4. +Once the debugger is run, a breakpoint will occur at line 4: % node debug myscript.js < debugger listening on port 5858 @@ -46,15 +49,15 @@ Then once the debugger is run, it will break on line 4. 1 x = 5; 2 setTimeout(function () { 3 debugger; - 4 console.log("world"); + 4 console.log('world'); 5 }, 1000); debug> next break in /home/indutny/Code/git/indutny/myscript.js:4 2 setTimeout(function () { 3 debugger; - 4 console.log("world"); + 4 console.log('world'); 5 }, 1000); - 6 console.log("hello"); + 6 console.log('hello'); debug> repl Press Ctrl + C to leave debug repl > x @@ -65,28 +68,28 @@ Then once the debugger is run, it will break on line 4. < world break in /home/indutny/Code/git/indutny/myscript.js:5 3 debugger; - 4 console.log("world"); + 4 console.log('world'); 5 }, 1000); - 6 console.log("hello"); + 6 console.log('hello'); 7 debug> quit % -The `repl` command allows you to evaluate code remotely. The `next` command -steps over to the next line. There are a few other commands available and more -to come. Type `help` to see others. +The `repl` command allows code to be evaluated remotely. The `next` command +steps over to the next line. Type `help` to see what other commands are +available. ## Watchers -You can watch expression and variable values while debugging your code. -On every breakpoint each expression from the watchers list will be evaluated -in the current context and displayed just before the breakpoint's source code -listing. +It is possible to watch expression and variable values while debugging. On +every breakpoint, each expression from the watchers list will be evaluated +in the current context and displayed immediately before the breakpoint's +source code listing. -To start watching an expression, type `watch("my_expression")`. `watchers` -prints the active watchers. To remove a watcher, type -`unwatch("my_expression")`. +To begin watching an expression, type `watch('my_expression')`. The command +`watchers` will print the active watchers. To remove a watcher, type +`unwatch('my_expression')`. ## Commands reference @@ -153,19 +156,20 @@ breakpoint) ### Various * `scripts` - List all loaded scripts -* `version` - Display v8's version +* `version` - Display V8's version ## Advanced Usage -The V8 debugger can be enabled and accessed either by starting Node.js with -the `--debug` command-line flag or by signaling an existing Node.js process -with `SIGUSR1`. +An alternative way of enabling and accessing the debugger is to start +Node.js with the `--debug` command-line flag or by signaling an existing +Node.js process with `SIGUSR1`. -Once a process has been set in debug mode with this it can be connected to -with the Node.js debugger. Either connect to the `pid` or the URI to the -debugger. The syntax is: +Once a process has been set in debug mode this way, it can be connected to +using the Node.js debugger by either connecting to the `pid` of the running +process or via URI reference to the listening debugger: * `node debug -p ` - Connects to the process via the `pid` -* `node debug ` - Connects to the process via the URI such as localhost:5858 +* `node debug ` - Connects to the process via the URI such as +localhost:5858 -[TCP protocol]: http://code.google.com/p/v8/wiki/DebuggerProtocol +[TCP-based protocol]: https://github.com/v8/v8/wiki/Debugging-Protocol diff --git a/doc/api/dgram.markdown b/doc/api/dgram.markdown index 3db13305281f5a..78bf3c2210bfca 100644 --- a/doc/api/dgram.markdown +++ b/doc/api/dgram.markdown @@ -4,52 +4,64 @@ -Datagram sockets are available through `require('dgram')`. +The `dgram` module provides an implementation of UDP Datagram sockets. -Important note: the behavior of `dgram.Socket#bind()` has changed in v0.10 -and is always asynchronous now. If you have code that looks like this: + const dgram = require('dgram'); + const server = dgram.createSocket('udp4'); - var s = dgram.createSocket('udp4'); - s.bind(1234); - s.addMembership('224.0.0.114'); + server.on('error', (err) => { + console.log(`server error:\n${err.stack}`); + server.close(); + }); -You have to change it to this: + server.on('message', (msg, rinfo) => { + console.log(`server got: ${msg} from ${rinfo.address}:${rinfo.port}`); + }); - var s = dgram.createSocket('udp4'); - s.bind(1234, function() { - s.addMembership('224.0.0.114'); + server.on('listening', () => { + var address = server.address(); + console.log(`server listening ${address.address}:${address.port}`); }); + server.bind(41234); + // server listening 0.0.0.0:41234 + ## Class: dgram.Socket -The dgram Socket class encapsulates the datagram functionality. It -should be created via `dgram.createSocket(...)` +The `dgram.Socket` object is an [`EventEmitter`][] that encapsulates the +datagram functionality. + +New instances of `dgram.Socket` are created using [`dgram.createSocket()`][]. +The `new` keyword is not to be used to create `dgram.Socket` instances. ### Event: 'close' -Emitted after a socket is closed with `close()`. No new `message` events will be emitted -on this socket. +The `'close'` event is emitted after a socket is closed with [`close()`][]. +Once triggered, no new `'message'` events will be emitted on this socket. ### Event: 'error' * `exception` Error object -Emitted when an error occurs. +The `'error'` event is emitted whenever any error occurs. The event handler +function is passed a single Error object. ### Event: 'listening' -Emitted when a socket starts listening for datagrams. This happens as soon as UDP sockets -are created. +The `'listening'` event is emitted whenever a socket begins listening for +datagram messages. This occurs as soon as UDP sockets are created. ### Event: 'message' * `msg` Buffer object. The message * `rinfo` Object. Remote address information -Emitted when a new datagram is available on a socket. `msg` is a `Buffer` and -`rinfo` is an object with the sender's address information: +The `'message'` event is emitted when a new datagram is available on a socket. +The event handler function is passed two arguments: `msg` and `rinfo`. The +`msg` argument is a [`Buffer`][] and `rinfo` is an object with the sender's +address information provided by the `address`, `family` and `port` properties: - socket.on('message', function(msg, rinfo) { + socket.on('message', (msg, rinfo) => { console.log('Received %d bytes from %s:%d\n', msg.length, rinfo.address, rinfo.port); }); @@ -59,57 +71,58 @@ Emitted when a new datagram is available on a socket. `msg` is a `Buffer` and * `multicastAddress` String * `multicastInterface` String, Optional -Tells the kernel to join a multicast group with `IP_ADD_MEMBERSHIP` socket option. - -If `multicastInterface` is not specified, the OS will try to add membership to all valid -interfaces. +Tells the kernel to join a multicast group at the given `multicastAddress` +using the `IP_ADD_MEMBERSHIP` socket option. If the `multicastInterface` +argument is not specified, the operating system will try to add membership to +all valid networking interfaces. ### socket.address() -Returns an object containing the address information for a socket. For UDP sockets, -this object will contain `address` , `family` and `port`. +Returns an object containing the address information for a socket. +For UDP sockets, this object will contain `address`, `family` and `port` +properties. -### socket.bind([port][, address][, callback]) +### [socket.bind([port][, address][, callback])] * `port` Integer, Optional * `address` String, Optional -* `callback` Function with no parameters, Optional. Callback when - binding is done. - -For UDP sockets, listen for datagrams on a named `port` and optional -`address`. If `port` is not specified, the OS will try to bind to a random -port. If `address` is not specified, the OS will try to listen on -all addresses. After binding is done, a "listening" event is emitted -and the `callback`(if specified) is called. Specifying both a -"listening" event listener and `callback` is not harmful but not very +* `callback` Function with no parameters, Optional. Called when + binding is complete. + +For UDP sockets, causes the `dgram.Socket` to listen for datagram messages on a +named `port` and optional `address`. If `port` is not specified, the operating +system will attempt to bind to a random port. If `address` is not specified, +the operating system will attempt to listen on all addresses. Once binding is +complete, a `'listening'` event is emitted and the optional `callback` function +is called. + +Note that specifying both a `'listening'` event listener and passing a +`callback` to the `socket.bind()` method is not harmful but not very useful. A bound datagram socket keeps the Node.js process running to receive -datagrams. +datagram messages. -If binding fails, an "error" event is generated. In rare case (e.g. -binding a closed socket), an `Error` may be thrown by this method. +If binding fails, an `'error'` event is generated. In rare case (e.g. +attempting to bind with a closed socket), an [`Error`][] may be thrown. Example of a UDP server listening on port 41234: - var dgram = require("dgram"); + const dgram = require('dgram'); + const server = dgram.createSocket('udp4'); - var server = dgram.createSocket("udp4"); - - server.on("error", function (err) { - console.log("server error:\n" + err.stack); + server.on('error', (err) => { + console.log(`server error:\n${err.stack}`); server.close(); }); - server.on("message", function (msg, rinfo) { - console.log("server got: " + msg + " from " + - rinfo.address + ":" + rinfo.port); + server.on('message', (msg, rinfo) => { + console.log(`server got: ${msg} from ${rinfo.address}:${rinfo.port}`); }); - server.on("listening", function () { + server.on('listening', () => { var address = server.address(); - console.log("server listening " + - address.address + ":" + address.port); + console.log(`server listening ${address.address}:${address.port}`); }); server.bind(41234); @@ -123,16 +136,22 @@ Example of a UDP server listening on port 41234: * `exclusive` {Boolean} - Optional. * `callback` {Function} - Optional. -The `port` and `address` properties of `options`, as well as the optional -callback function, behave as they do on a call to -[socket.bind(port, \[address\], \[callback\]) -](#dgram_socket_bind_port_address_callback). +For UDP sockets, causes the `dgram.Socket` to listen for datagram messages on a +named `port` and optional `address` that are passed as properties of an +`options` object passed as the first argument. If `port` is not specified, the +operating system will attempt to bind to a random port. If `address` is not +specified, the operating system will attempt to listen on all addresses. Once +binding is complete, a `'listening'` event is emitted and the optional +`callback` function is called. + +The `options` object may contain an additional `exclusive` property that is +use when using `dgram.Socket` objects with the [`cluster`] module. When +`exclusive` is set to `false` (the default), cluster workers will use the same +underlying socket handle allowing connection handling duties to be shared. +When `exclusive` is `true`, however, the handle is not shared and attempted +port sharing results in an error. -If `exclusive` is `false` (default), then cluster workers will use the same -underlying handle, allowing connection handling duties to be shared. When -`exclusive` is `true`, the handle is not shared, and attempted port sharing -results in an error. An example which listens on an exclusive port is -shown below. +An example socket listening on an exclusive port is shown below. socket.bind({ address: 'localhost', @@ -143,20 +162,20 @@ shown below. ### socket.close([callback]) Close the underlying socket and stop listening for data on it. If a callback is -provided, it is added as a listener for the ['close'][] event. +provided, it is added as a listener for the [`'close'`][] event. ### socket.dropMembership(multicastAddress[, multicastInterface]) * `multicastAddress` String * `multicastInterface` String, Optional -Opposite of `addMembership` - tells the kernel to leave a multicast group with -`IP_DROP_MEMBERSHIP` socket option. This is automatically called by the kernel -when the socket is closed or process terminates, so most apps will never need to call -this. +Instructs the kernel to leave a multicast group at `multicastAddress` using the +`IP_DROP_MEMBERSHIP` socket option. This method is automatically called by the +kernel when the socket is closed or the process terminates, so most apps will +never have reason to call this. -If `multicastInterface` is not specified, the OS will try to drop membership to all valid -interfaces. +If `multicastInterface` is not specified, the operating system will attempt to +drop membership on all valid interfaces. ### socket.send(buf, offset, length, port, address[, callback]) @@ -167,152 +186,206 @@ interfaces. * `address` String. Destination hostname or IP address. * `callback` Function. Called when the message has been sent. Optional. -For UDP sockets, the destination port and address must be specified. A string -may be supplied for the `address` parameter, and it will be resolved with DNS. +Broadcasts a datagram on the socket. The destination `port` and `address` must +be specified. -If the address is omitted or is an empty string, `'0.0.0.0'` or `'::0'` is used -instead. Depending on the network configuration, those defaults may or may not -work; it's best to be explicit about the destination address. +The `buf` argument is a [`Buffer`] object containing the message. The `offset` +and `length` specify the offset within the `Buffer` where the message begins +and the number of bytes in the message, respectively. With messages that +contain multi-byte characters, `offset` and `length` will be calculated with +respect to [byte length][] and not the character position. -If the socket has not been previously bound with a call to `bind`, it gets -assigned a random port number and is bound to the "all interfaces" address +The `address` argument is a string. If the value of `address` is a host name, +DNS will be used to resolve the address of the host. If the `address` is not +specified or is an empty string, `'0.0.0.0'` or `'::0'` will be used instead. +It is possible, depending on the network configuration, that these defaults +may not work; accordingly, it is best to be explicit about the destination +address. + +If the socket has not been previously bound with a call to `bind`, the socket +is assigned a random port number and is bound to the "all interfaces" address (`'0.0.0.0'` for `udp4` sockets, `'::0'` for `udp6` sockets.) -An optional callback may be specified to detect DNS errors or for determining -when it's safe to reuse the `buf` object. Note that DNS lookups delay the time -to send for at least one tick. The only way to know for sure that the datagram -has been sent is by using a callback. If an error occurs and a callback is -given, the error will be the first argument to the callback. If a callback is -not given, the error is emitted as an `'error'` event on the `socket` object. +An optional `callback` function may be specified to as a way of reporting +DNS errors or for determining when it is safe to reuse the `buf` object. +Note that DNS lookups delay the time to send for at least one tick of the +Node.js event loop. -With consideration for multi-byte characters, `offset` and `length` will -be calculated with respect to [byte length][] and not the character position. +The only way to know for sure that the datagram has been sent is by using a +`callback`. If an error occurs and a `callback` is given, the error will be +passed as the first argument to the `callback`. If a `callback` is not given, +the error is emitted as an `'error'` event on the `socket` object. Example of sending a UDP packet to a random port on `localhost`; - var dgram = require('dgram'); - var message = new Buffer("Some bytes"); - var client = dgram.createSocket("udp4"); - client.send(message, 0, message.length, 41234, "localhost", function(err) { + const dgram = require('dgram'); + const message = new Buffer('Some bytes'); + const client = dgram.createSocket('udp4'); + client.send(message, 0, message.length, 41234, 'localhost', (err) => { client.close(); }); **A Note about UDP datagram size** -The maximum size of an `IPv4/v6` datagram depends on the `MTU` (_Maximum Transmission Unit_) -and on the `Payload Length` field size. +The maximum size of an `IPv4/v6` datagram depends on the `MTU` +(_Maximum Transmission Unit_) and on the `Payload Length` field size. -- The `Payload Length` field is `16 bits` wide, which means that a normal payload - cannot be larger than 64K octets including internet header and data +- The `Payload Length` field is `16 bits` wide, which means that a normal + payload exceed 64K octets _including_ the internet header and data (65,507 bytes = 65,535 − 8 bytes UDP header − 20 bytes IP header); - this is generally true for loopback interfaces, but such long datagrams - are impractical for most hosts and networks. + this is generally true for loopback interfaces, but such long datagram + messages are impractical for most hosts and networks. -- The `MTU` is the largest size a given link layer technology can support for datagrams. - For any link, `IPv4` mandates a minimum `MTU` of `68` octets, while the recommended `MTU` - for IPv4 is `576` (typically recommended as the `MTU` for dial-up type applications), - whether they arrive whole or in fragments. +- The `MTU` is the largest size a given link layer technology can support for + datagram messages. For any link, `IPv4` mandates a minimum `MTU` of `68` + octets, while the recommended `MTU` for IPv4 is `576` (typically recommended + as the `MTU` for dial-up type applications), whether they arrive whole or in + fragments. For `IPv6`, the minimum `MTU` is `1280` octets, however, the mandatory minimum - fragment reassembly buffer size is `1500` octets. - The value of `68` octets is very small, since most current link layer technologies have - a minimum `MTU` of `1500` (like Ethernet). + fragment reassembly buffer size is `1500` octets. The value of `68` octets is + very small, since most current link layer technologies, like Ethernet, have a + minimum `MTU` of `1500`. -Note that it's impossible to know in advance the MTU of each link through which -a packet might travel, and that generally sending a datagram greater than -the (receiver) `MTU` won't work (the packet gets silently dropped, without -informing the source that the data did not reach its intended recipient). +It is impossible to know in advance the MTU of each link through which +a packet might travel. Sending a datagram greater than the receiver `MTU` will +not work because the packet will get silently dropped without informing the +source that the data did not reach its intended recipient. ### socket.setBroadcast(flag) * `flag` Boolean -Sets or clears the `SO_BROADCAST` socket option. When this option is set, UDP packets -may be sent to a local interface's broadcast address. +Sets or clears the `SO_BROADCAST` socket option. When set to `true`, UDP +packets may be sent to a local interface's broadcast address. ### socket.setMulticastLoopback(flag) * `flag` Boolean -Sets or clears the `IP_MULTICAST_LOOP` socket option. When this option is set, multicast -packets will also be received on the local interface. +Sets or clears the `IP_MULTICAST_LOOP` socket option. When set to `true`, +multicast packets will also be received on the local interface. ### socket.setMulticastTTL(ttl) * `ttl` Integer -Sets the `IP_MULTICAST_TTL` socket option. TTL stands for "Time to Live," but in this -context it specifies the number of IP hops that a packet is allowed to go through, -specifically for multicast traffic. Each router or gateway that forwards a packet -decrements the TTL. If the TTL is decremented to 0 by a router, it will not be forwarded. +Sets the `IP_MULTICAST_TTL` socket option. While TTL generally stands for +"Time to Live", in this context it specifies the number of IP hops that a +packet is allowed to travel through, specifically for multicast traffic. Each +router or gateway that forwards a packet decrements the TTL. If the TTL is +decremented to 0 by a router, it will not be forwarded. -The argument to `setMulticastTTL()` is a number of hops between 0 and 255. The default on most -systems is 1. +The argument passed to to `socket.setMulticastTTL()` is a number of hops +between 0 and 255. The default on most systems is `1` but can vary. ### socket.setTTL(ttl) * `ttl` Integer -Sets the `IP_TTL` socket option. TTL stands for "Time to Live," but in this context it -specifies the number of IP hops that a packet is allowed to go through. Each router or -gateway that forwards a packet decrements the TTL. If the TTL is decremented to 0 by a -router, it will not be forwarded. Changing TTL values is typically done for network -probes or when multicasting. +Sets the `IP_TTL` socket option. While TTL generally stands for "Time to Live", +in this context it specifies the number of IP hops that a packet is allowed to +travel through. Each router or gateway that forwards a packet decrements the +TTL. If the TTL is decremented to 0 by a router, it will not be forwarded. +Changing TTL values is typically done for network probes or when multicasting. -The argument to `setTTL()` is a number of hops between 1 and 255. The default -on most systems is 64. +The argument to `socket.setTTL()` is a number of hops between 1 and 255. +The default on most systems is 64 but can vary. ### socket.ref() -Opposite of `unref`, calling `ref` on a previously `unref`d socket will *not* -let the program exit if it's the only socket left (the default behavior). If -the socket is `ref`d calling `ref` again will have no effect. +By default, binding a socket will cause it to block the Node.js process from +exiting as long as the socket is open. The `socket.unref()` method can be used +to exclude the socket from the reference counting that keeps the Node.js +process active. The `socket.ref()` method adds the socket back to the reference +counting and restores the default behavior. + +Calling `socket.ref()` multiples times will have no additional effect. -Returns `socket`. +The `socket.ref()` method returns a reference to the socket so calls can be +chained. ### socket.unref() -Calling `unref` on a socket will allow the program to exit if this is the only -active socket in the event system. If the socket is already `unref`d calling -`unref` again will have no effect. +By default, binding a socket will cause it to block the Node.js process from +exiting as long as the socket is open. The `socket.unref()` method can be used +to exclude the socket from the reference counting that keeps the Node.js +process active, allowing the process to exit even if the socket is still +listening. -Returns `socket`. +Calling `socket.unref()` multiple times will have no addition effect. -## dgram.createSocket(options[, callback]) +The `socket.unref()` method returns a reference to the socket so calls can be +chained. + +### Change to asynchronous `socket.bind()` behavior + +As of Node.js v0.10, [`dgram.Socket#bind()`][] changed to an asynchronous +execution model. Legacy code that assumes synchronous behavior, as in the +following example: + + const s = dgram.createSocket('udp4'); + s.bind(1234); + s.addMembership('224.0.0.114'); + +Must be changed to pass a callback function to the [`dgram.Socket#bind()`][] +function: + + const s = dgram.createSocket('udp4'); + s.bind(1234, () => { + s.addMembership('224.0.0.114'); + }); + +## `dgram` module functions + +### dgram.createSocket(options[, callback]) * `options` Object -* `callback` Function. Attached as a listener to `message` events. +* `callback` Function. Attached as a listener to `'message'` events. * Returns: Socket object -The `options` object should contain a `type` field of either `udp4` or `udp6` -and an optional boolean `reuseAddr` field. +Creates a `dgram.Socket` object. The `options` argument is an object that +should contain a `type` field of either `udp4` or `udp6` and an optional +boolean `reuseAddr` field. -When `reuseAddr` is `true` `socket.bind()` will reuse the address, even if +When `reuseAddr` is `true` [`socket.bind()`][] will reuse the address, even if another process has already bound a socket on it. `reuseAddr` defaults to -`false`. - -Takes an optional callback which is added as a listener for `message` events. +`false`. An optional `callback` function can be passed specified which is added +as a listener for `'message'` events. -Call `socket.bind()` if you want to receive datagrams. `socket.bind()` will -bind to the "all interfaces" address on a random port (it does the right thing -for both `udp4` and `udp6` sockets). You can then retrieve the address and port -with `socket.address().address` and `socket.address().port`. +Once the socket is created, calling [`socket.bind()`][] will instruct the +socket to begin listening for datagram messages. When `address` and `port` are +not passed to [`socket.bind()`][] the method will bind the socket to the "all +interfaces" address on a random port (it does the right thing for both `udp4` +and `udp6` sockets). The bound address and port can be retrieved using +[`socket.address().address`][] and [`socket.address().port`][]. ## dgram.createSocket(type[, callback]) * `type` String. Either 'udp4' or 'udp6' -* `callback` Function. Attached as a listener to `message` events. +* `callback` Function. Attached as a listener to `'message'` events. Optional * Returns: Socket object -Creates a datagram Socket of the specified types. Valid types are `udp4` -and `udp6`. - -Takes an optional callback which is added as a listener for `message` events. - -Call `socket.bind()` if you want to receive datagrams. `socket.bind()` will -bind to the "all interfaces" address on a random port (it does the right thing -for both `udp4` and `udp6` sockets). You can then retrieve the address and port -with `socket.address().address` and `socket.address().port`. - -['close']: #dgram_event_close +Creates a `dgram.Socket` object of the specified `type`. The `type` argument +can be either `udp4` or `udp6`. An optional `callback` function can be passed +which is added as a listener for `'message'` events. + +Once the socket is created, calling [`socket.bind()`][] will instruct the +socket to begin listening for datagram messages. When `address` and `port` are +not passed to [`socket.bind()`][] the method will bind the socket to the "all +interfaces" address on a random port (it does the right thing for both `udp4` +and `udp6` sockets). The bound address and port can be retrieved using +[`socket.address().address`][] and [`socket.address().port`][]. + +[`EventEmitter`]: events.html +[`Buffer`]: buffer.html +[`'close'`]: #dgram_event_close +[`addMembership()`]: #dgram_socket_addmembership_multicastaddress_multicastinterface +[`close()`]: #dgram_socket_close_callback +[`dgram.createSocket()`]: #dgram_dgram_createsocket_options_callback +[`dgram.Socket#bind()`]: #dgram_socket_bind_options_callback +[`Error`]: errors.html#errors_class_error +[`socket.address().address`]: #dgram_socket_address +[`socket.address().port`]: #dgram_socket_address +[`socket.bind()`]: #dgram_socket_bind_port_address_callback [byte length]: buffer.html#buffer_class_method_buffer_bytelength_string_encoding diff --git a/doc/api/dns.markdown b/doc/api/dns.markdown index e7b9fbb7987b93..86bee216487683 100644 --- a/doc/api/dns.markdown +++ b/doc/api/dns.markdown @@ -2,67 +2,63 @@ Stability: 2 - Stable -Use `require('dns')` to access this module. - -This module contains functions that belong to two different categories: +The `dns` module contains functions belonging to two different categories: 1) Functions that use the underlying operating system facilities to perform -name resolution, and that do not necessarily do any network communication. -This category contains only one function: `dns.lookup()`. __Developers looking -to perform name resolution in the same way that other applications on the same -operating system behave should use [`dns.lookup()`][].__ +name resolution, and that do not necessarily perform any network communication. +This category contains only one function: [`dns.lookup()`][]. __Developers +looking to perform name resolution in the same way that other applications on +the same operating system behave should use [`dns.lookup()`][].__ -Here is an example that does a lookup of `www.google.com`. +For example, looking up `nodejs.org`. - var dns = require('dns'); + const dns = require('dns'); - dns.lookup('www.google.com', function onLookup(err, addresses, family) { + dns.lookup('nodejs.org', (err, addresses, family) => { console.log('addresses:', addresses); }); 2) Functions that connect to an actual DNS server to perform name resolution, and that _always_ use the network to perform DNS queries. This category -contains all functions in the `dns` module but [`dns.lookup()`][]. These functions -do not use the same set of configuration files than what [`dns.lookup()`][] uses. -For instance, _they do not use the configuration from `/etc/hosts`_. These -functions should be used by developers who do not want to use the underlying -operating system's facilities for name resolution, and instead want to -_always_ perform DNS queries. +contains all functions in the `dns` module _except_ [`dns.lookup()`][]. These +functions do not use the same set of configuration files used by +[`dns.lookup()`][] (e.g. `/etc/hosts`). These functions should be used by +developers who do not want to use the underlying operating system's facilities +for name resolution, and instead want to _always_ perform DNS queries. -Here is an example which resolves `'www.google.com'` then reverse -resolves the IP addresses which are returned. +Below is an example that resolves `'nodejs.org'` then reverse resolves the IP +addresses that are returned. - var dns = require('dns'); + const dns = require('dns'); - dns.resolve4('www.google.com', function (err, addresses) { + dns.resolve4('nodejs.org', (err, addresses) => { if (err) throw err; - console.log('addresses: ' + JSON.stringify(addresses)); + console.log(`addresses: ${JSON.stringify(addresses)}`); - addresses.forEach(function (a) { - dns.reverse(a, function (err, hostnames) { + addresses.forEach((a) => { + dns.reverse(a, (err, hostnames) => { if (err) { throw err; } - - console.log('reverse for ' + a + ': ' + JSON.stringify(hostnames)); + console.log(`reverse for ${a}: ${JSON.stringify(hostnames)}`); }); }); }); -There are subtle consequences in choosing one or another, please consult the -[Implementation considerations section][] for more information. +There are subtle consequences in choosing one over the other, please consult +the [Implementation considerations section][] for more information. ## dns.getServers() -Returns an array of IP addresses as strings that are currently being used for -resolution +Returns an array of IP address strings that are being used for name +resolution. ## dns.lookup(hostname[, options], callback) -Resolves a hostname (e.g. `'google.com'`) into the first found A (IPv4) or +Resolves a hostname (e.g. `'nodejs.org'`) into the first found A (IPv4) or AAAA (IPv6) record. `options` can be an object or integer. If `options` is -not provided, then IP v4 and v6 addresses are both valid. If `options` is +not provided, then IPv4 and IPv6 addresses are both valid. If `options` is an integer, then it must be `4` or `6`. Alternatively, `options` can be an object containing these properties: @@ -80,153 +76,193 @@ Alternatively, `options` can be an object containing these properties: All properties are optional. An example usage of options is shown below. -``` -{ - family: 4, - hints: dns.ADDRCONFIG | dns.V4MAPPED, - all: false -} -``` + { + family: 4, + hints: dns.ADDRCONFIG | dns.V4MAPPED, + all: false + } -The callback has arguments `(err, address, family)`. `address` is a string -representation of an IP v4 or v6 address. `family` is either the integer 4 or 6 -and denotes the family of `address` (not necessarily the value initially passed -to `lookup`). +The `callback` function has arguments `(err, address, family)`. `address` is a +string representation of an IPv4 or IPv6 address. `family` is either the +integer `4` or `6` and denotes the family of `address` (not necessarily the +value initially passed to `lookup`). -With the `all` option set, the arguments change to `(err, addresses)`, with -`addresses` being an array of objects with the properties `address` and -`family`. +With the `all` option set to `true`, the arguments change to +`(err, addresses)`, with `addresses` being an array of objects with the +properties `address` and `family`. -On error, `err` is an `Error` object, where `err.code` is the error code. +On error, `err` is an [`Error`][] object, where `err.code` is the error code. Keep in mind that `err.code` will be set to `'ENOENT'` not only when the hostname does not exist but also when the lookup fails in other ways such as no available file descriptors. -`dns.lookup()` doesn't necessarily have anything to do with the DNS protocol. -It's only an operating system facility that can associate name with addresses, -and vice versa. +`dns.lookup()` does not necessarily have anything to do with the DNS protocol. +The implementation uses an operating system facility that can associate names +with addresses, and vice versa. This implementation can have subtle but +important consequences on the behavior of any Node.js program. Please take some +time to consult the [Implementation considerations section][] before using +`dns.lookup()`. + +### Supported getaddrinfo flags -Its implementation can have subtle but important consequences on the behavior -of any Node.js program. Please take some time to consult the [Implementation -considerations section][] before using it. +The following flags can be passed as hints to [`dns.lookup()`][]. + +- `dns.ADDRCONFIG`: Returned address types are determined by the types +of addresses supported by the current system. For example, IPv4 addresses +are only returned if the current system has at least one IPv4 address +configured. Loopback addresses are not considered. +- `dns.V4MAPPED`: If the IPv6 family was specified, but no IPv6 addresses were +found, then return IPv4 mapped IPv6 addresses. Note that it is not supported +on some operating systems (e.g FreeBSD 10.1). ## dns.lookupService(address, port, callback) -Resolves the given address and port into a hostname and service using -`getnameinfo`. +Resolves the given `address` and `port` into a hostname and service using +the operating system's underlying `getnameinfo` implementation. The callback has arguments `(err, hostname, service)`. The `hostname` and `service` arguments are strings (e.g. `'localhost'` and `'http'` respectively). -On error, `err` is an `Error` object, where `err.code` is the error code. +On error, `err` is an [`Error`][] object, where `err.code` is the error code. + const dns = require('dns'); + dns.lookupService('127.0.0.1', 22, (err, hostname, service) => { + console.log(hostname, service); + // Prints: localhost ssh + }); ## dns.resolve(hostname[, rrtype], callback) -Resolves a hostname (e.g. `'google.com'`) into an array of the record types -specified by rrtype. +Uses the DNS protocol to resolve a hostname (e.g. `'nodejs.org'`) into an +array of the record types specified by `rrtype`. -Valid rrtypes are: +Valid values for `rrtype` are: - * `'A'` (IPV4 addresses, default) - * `'AAAA'` (IPV6 addresses) - * `'MX'` (mail exchange records) - * `'TXT'` (text records) - * `'SRV'` (SRV records) - * `'PTR'` (used for reverse IP lookups) - * `'NS'` (name server records) - * `'CNAME'` (canonical name records) - * `'SOA'` (start of authority record) + * `'A'` - IPV4 addresses, default + * `'AAAA'` - IPV6 addresses + * `'MX'` - mail exchange records + * `'TXT'` - text records + * `'SRV'` - SRV records + * `'PTR'` - used for reverse IP lookups + * `'NS'` - name server records + * `'CNAME'` - canonical name records + * `'SOA'` - start of authority record -The callback has arguments `(err, addresses)`. The type of each item -in `addresses` is determined by the record type, and described in the -documentation for the corresponding lookup methods below. +The `callback` function has arguments `(err, addresses)`. When successful, +`addresses` will be an array. The type of each item in `addresses` is +determined by the record type, and described in the documentation for the +corresponding lookup methods below. -On error, `err` is an `Error` object, where `err.code` is +On error, `err` is an [`Error`][] object, where `err.code` is one of the error codes listed below. - ## dns.resolve4(hostname, callback) -The same as [`dns.resolve()`][], but only for IPv4 queries (`A` records). -`addresses` is an array of IPv4 addresses (e.g. +Uses the DNS protocol to resolve a IPv4 addresses (`A` records) for the +`hostname`. The `addresses` argument passed to the `callback` function +will contain an array of IPv4 addresses (e.g. `['74.125.79.104', '74.125.79.105', '74.125.79.106']`). ## dns.resolve6(hostname, callback) -The same as [`dns.resolve4()`][] except for IPv6 queries (an `AAAA` query). +Uses the DNS protocol to resolve a IPv6 addresses (`AAAA` records) for the +`hostname`. The `addresses` argument passed to the `callback` function +will contain an array of IPv6 addresses. ## dns.resolveCname(hostname, callback) -The same as [`dns.resolve()`][], but only for canonical name records (`CNAME` -records). `addresses` is an array of the canonical name records available for -`hostname` (e.g., `['bar.example.com']`). +Uses the DNS protocol to resolve `CNAME` records for the `hostname`. The +`addresses` argument passed to the `callback` function +will contain an of canonical name records available for the `hostname` +(e.g. `['bar.example.com']`). ## dns.resolveMx(hostname, callback) -The same as [`dns.resolve()`][], but only for mail exchange queries (`MX` records). - -`addresses` is an array of MX records, each with a priority and an exchange -attribute (e.g. `[{'priority': 10, 'exchange': 'mx.example.com'},...]`). +Uses the DNS protocol to resolve mail exchange records (`MX` records) for the +`hostname`. The `addresses` argument passed to the `callback` function will +contain an array of objects containing both a `priority` and `exchange` +property (e.g. `[{priority: 10, exchange: 'mx.example.com'}, ...]`). ## dns.resolveNs(hostname, callback) -The same as [`dns.resolve()`][], but only for name server records (`NS` records). -`addresses` is an array of the name server records available for `hostname` +Uses the DNS protocol to resolve name server records (`NS` records) for the +`hostname`. The `addresses` argument passed to the `callback` function will +contain an array of name server records available for `hostname` (e.g., `['ns1.example.com', 'ns2.example.com']`). ## dns.resolveSoa(hostname, callback) -The same as [`dns.resolve()`][], but only for start of authority record queries -(`SOA` record). +Uses the DNS protocol to resolve a start of authority record (`SOA` record) for +the `hostname`. The `addresses` argument passed to the `callback` function will +be an object with the following properties: + +* `nsname` +* `hostmaster` +* `serial` +* `refresh` +* `retry` +* `expire` +* `minttl` + + { + nsname: 'ns.example.com', + hostmaster: 'root.example.com', + serial: 2013101809, + refresh: 10000, + retry: 2400, + expire: 604800, + minttl: 3600 + } -`addresses` is an object with the following structure: +## dns.resolveSrv(hostname, callback) -``` -{ - nsname: 'ns.example.com', - hostmaster: 'root.example.com', - serial: 2013101809, - refresh: 10000, - retry: 2400, - expire: 604800, - minttl: 3600 -} -``` +Uses the DNS protocol to resolve service records (`SRV` records) for the +`hostname`. The `addresses` argument passed to the `callback` function will +be an array of objects with the following properties: -## dns.resolveSrv(hostname, callback) +* `priority` +* `weight` +* `port` +* `name` -The same as [`dns.resolve()`][], but only for service records (`SRV` records). -`addresses` is an array of the SRV records available for `hostname`. Properties -of SRV records are priority, weight, port, and name (e.g., -`[{'priority': 10, 'weight': 5, 'port': 21223, 'name': 'service.example.com'}, ...]`). + { + priority: 10, + weight: 5, + port: 21223, + name: 'service.example.com' + } ## dns.resolveTxt(hostname, callback) -The same as [`dns.resolve()`][], but only for text queries (`TXT` records). -`addresses` is a 2-d array of the text records available for `hostname` (e.g., +Uses the DNS protocol to resolve text queries (`TXT` records) for the +`hostname`. The `addresses` argument passed to the `callback` function is +is a two-dimentional array of the text records available for `hostname` (e.g., `[ ['v=spf1 ip4:0.0.0.0 ', '~all' ] ]`). Each sub-array contains TXT chunks of -one record. Depending on the use case, the could be either joined together or +one record. Depending on the use case, these could be either joined together or treated separately. ## dns.reverse(ip, callback) -Reverse resolves an ip address to an array of hostnames. +Performs a reverse DNS query that resolves an IPv4 or IPv6 address to an +array of hostnames. -The callback has arguments `(err, hostnames)`. +The `callback` function has arguments `(err, hostnames)`, where `hostnames` +is an array of resolved hostnames for the given `ip`. -On error, `err` is an `Error` object, where `err.code` is +On error, `err` is an [`Error`][] object, where `err.code` is one of the error codes listed below. ## dns.setServers(servers) -Given an array of IP addresses as strings, set them as the servers to use for -resolving +Sets the IP addresses of the servers to be used when resolving. The `servers` +argument is an array of IPv4 or IPv6 addresses. + +If a port specified on the address it will be removed. -If you specify a port with the address it will be stripped, as the underlying -library doesn't support that. +An error will be thrown if an invalid address is provided. -This will throw if you pass invalid input. +The `dns.setServers()` method must not be called while a DNS query is in +progress. ## Error codes @@ -257,63 +293,52 @@ Each DNS query can return one of the following error codes: - `dns.ADDRGETNETWORKPARAMS`: Could not find GetNetworkParams function. - `dns.CANCELLED`: DNS query cancelled. -## Supported getaddrinfo flags - -The following flags can be passed as hints to `dns.lookup()`. - -- `dns.ADDRCONFIG`: Returned address types are determined by the types -of addresses supported by the current system. For example, IPv4 addresses -are only returned if the current system has at least one IPv4 address -configured. Loopback addresses are not considered. -- `dns.V4MAPPED`: If the IPv6 family was specified, but no IPv6 addresses were -found, then return IPv4 mapped IPv6 addresses. Note that it is not supported -on some operating systems (e.g FreeBSD 10.1). - ## Implementation considerations -Although `dns.lookup()` and `dns.resolve*()/dns.reverse()` functions have the same -goal of associating a network name with a network address (or vice versa), -their behavior is quite different. These differences can have subtle but -significant consequences on the behavior of Node.js programs. - -### dns.lookup - -Under the hood, `dns.lookup()` uses the same operating system facilities as most -other programs. For instance, `dns.lookup()` will almost always resolve a given -name the same way as the `ping` command. On most POSIX-like operating systems, -the behavior of the `dns.lookup()` function can be tweaked by changing settings -in `nsswitch.conf(5)` and/or `resolv.conf(5)`, but be careful that changing -these files will change the behavior of all other programs running on the same -operating system. - -Though the call will be asynchronous from JavaScript's perspective, it is -implemented as a synchronous call to `getaddrinfo(3)` that runs on libuv's -threadpool. Because libuv's threadpool has a fixed size, it means that if for -whatever reason the call to `getaddrinfo(3)` takes a long time, other -operations that could run on libuv's threadpool (such as filesystem +Although [`dns.lookup()`][] and the various `dns.resolve*()/dns.reverse()` +functions have the same goal of associating a network name with a network +address (or vice versa), their behavior is quite different. These differences +can have subtle but significant consequences on the behavior of Node.js +programs. + +### `dns.lookup()` + +Under the hood, [`dns.lookup()`][] uses the same operating system facilities +as most other programs. For instance, [`dns.lookup()`][] will almost always +resolve a given name the same way as the `ping` command. On most POSIX-like +operating systems, the behavior of the [`dns.lookup()`][] function can be +modified by changing settings in `nsswitch.conf(5)` and/or `resolv.conf(5)`, +but note that changing these files will change the behavior of _all other +programs running on the same operating system_. + +Though the call to `dns.lookup()` will be asynchronous from JavaScript's +perspective, it is implemented as a synchronous call to `getaddrinfo(3)` that +runs on libuv's threadpool. Because libuv's threadpool has a fixed size, it +means that if for whatever reason the call to `getaddrinfo(3)` takes a long +time, other operations that could run on libuv's threadpool (such as filesystem operations) will experience degraded performance. In order to mitigate this issue, one potential solution is to increase the size of libuv's threadpool by -setting the 'UV_THREADPOOL_SIZE' environment variable to a value greater than -4 (its current default value). For more information on libuv's threadpool, see +setting the `'UV_THREADPOOL_SIZE'` environment variable to a value greater than +`4` (its current default value). For more information on libuv's threadpool, see [the official libuv documentation][]. -### dns.resolve, functions starting with dns.resolve and dns.reverse +### `dns.resolve()`, `dns.resolve*()` and `dns.reverse()` -These functions are implemented quite differently than `dns.lookup()`. They do -not use `getaddrinfo(3)` and they _always_ perform a DNS query on the network. -This network communication is always done asynchronously, and does not use -libuv's threadpool. +These functions are implemented quite differently than [`dns.lookup()`][]. They +do not use `getaddrinfo(3)` and they _always_ perform a DNS query on the +network. This network communication is always done asynchronously, and does not +use libuv's threadpool. As a result, these functions cannot have the same negative impact on other -processing that happens on libuv's threadpool that `dns.lookup()` can have. +processing that happens on libuv's threadpool that [`dns.lookup()`][] can have. -They do not use the same set of configuration files than what `dns.lookup()` +They do not use the same set of configuration files than what [`dns.lookup()`][] uses. For instance, _they do not use the configuration from `/etc/hosts`_. -[Implementation considerations section]: #dns_implementation_considerations -[supported `getaddrinfo` flags]: #dns_supported_getaddrinfo_flags +[`dns.lookup()`]: #dns_dns_lookup_hostname_options_callback [`dns.resolve()`]: #dns_dns_resolve_hostname_rrtype_callback [`dns.resolve4()`]: #dns_dns_resolve4_hostname_callback +[`Error`]: errors.html#errors_class_error +[Implementation considerations section]: #dns_implementation_considerations +[supported `getaddrinfo` flags]: #dns_supported_getaddrinfo_flags [the official libuv documentation]: http://docs.libuv.org/en/latest/threadpool.html -[`dns.lookup()`]: #dns_dns_lookup_hostname_options_callback - diff --git a/doc/api/domain.markdown b/doc/api/domain.markdown index c62b8555f035c4..410a74498ddeaa 100644 --- a/doc/api/domain.markdown +++ b/doc/api/domain.markdown @@ -11,7 +11,7 @@ in the future. Domains provide a way to handle multiple different IO operations as a single group. If any of the event emitters or callbacks registered to a -domain emit an `error` event, or throw an error, then the domain object +domain emit an `'error'` event, or throw an error, then the domain object will be notified, rather than losing the context of the error in the `process.on('uncaughtException')` handler, or causing the program to exit immediately with an error code. @@ -23,7 +23,7 @@ exit immediately with an error code. Domain error handlers are not a substitute for closing down your process when an error occurs. -By the very nature of how `throw` works in JavaScript, there is almost +By the very nature of how [`throw`][] works in JavaScript, there is almost never any way to safely "pick up where you left off", without leaking references, or creating some other sort of undefined brittle state. @@ -48,15 +48,15 @@ For example, this is not a good idea: // XXX WARNING! BAD IDEA! var d = require('domain').create(); -d.on('error', function(er) { +d.on('error', (er) => { // The error won't crash the process, but what it does is worse! // Though we've prevented abrupt process restarting, we are leaking // resources like crazy if this ever happens. // This is no better than process.on('uncaughtException')! console.log('error, but oh well', er.message); }); -d.run(function() { - require('http').createServer(function(req, res) { +d.run(() => { + require('http').createServer((req, res) => { handleRequest(req, res); }).listen(PORT); }); @@ -69,8 +69,8 @@ appropriately, and handle errors with much greater safety. ```javascript // Much better! -var cluster = require('cluster'); -var PORT = +process.env.PORT || 1337; +const cluster = require('cluster'); +const PORT = +process.env.PORT || 1337; if (cluster.isMaster) { // In real life, you'd probably use more than just 2 workers, @@ -88,7 +88,7 @@ if (cluster.isMaster) { cluster.fork(); cluster.fork(); - cluster.on('disconnect', function(worker) { + cluster.on('disconnect', (worker) => { console.error('disconnect!'); cluster.fork(); }); @@ -98,14 +98,14 @@ if (cluster.isMaster) { // // This is where we put our bugs! - var domain = require('domain'); + const domain = require('domain'); // See the cluster documentation for more details about using // worker processes to serve requests. How it works, caveats, etc. - var server = require('http').createServer(function(req, res) { + const server = require('http').createServer((req, res) => { var d = domain.create(); - d.on('error', function(er) { + d.on('error', (er) => { console.error('error', er.stack); // Note: we're in dangerous territory! @@ -115,7 +115,7 @@ if (cluster.isMaster) { try { // make sure we close down within 30 seconds - var killtimer = setTimeout(function() { + var killtimer = setTimeout(() => { process.exit(1); }, 30000); // But don't keep the process open just for that! @@ -146,7 +146,7 @@ if (cluster.isMaster) { d.add(res); // Now run the handler function in the domain. - d.run(function() { + d.run(() => { handleRequest(req, res); }); }); @@ -159,7 +159,7 @@ function handleRequest(req, res) { switch(req.url) { case '/error': // We do some async stuff, and then... - setTimeout(function() { + setTimeout(() => { // Whoops! flerb.bark(); }); @@ -174,11 +174,11 @@ function handleRequest(req, res) { -Any time an Error object is routed through a domain, a few extra fields +Any time an `Error` object is routed through a domain, a few extra fields are added to it. * `error.domain` The domain that first handled the error. -* `error.domainEmitter` The event emitter that emitted an 'error' event +* `error.domainEmitter` The event emitter that emitted an `'error'` event with the error object. * `error.domainBound` The callback function which was bound to the domain, and passed an error as its first argument. @@ -207,8 +207,8 @@ If you *want* to nest Domain objects as children of a parent Domain, then you must explicitly add them. Implicit binding routes thrown errors and `'error'` events to the -Domain's `error` event, but does not register the EventEmitter on the -Domain, so `domain.dispose()` will not shut down the EventEmitter. +Domain's `'error'` event, but does not register the EventEmitter on the +Domain, so [`domain.dispose()`][] will not shut down the EventEmitter. Implicit binding only takes care of thrown errors and `'error'` events. ## Explicit Binding @@ -229,18 +229,20 @@ For example: ``` // create a top-level domain for the server -var serverDomain = domain.create(); +const domain = require('domain'); +const http = require('http'); +const serverDomain = domain.create(); -serverDomain.run(function() { +serverDomain.run(() => { // server is created in the scope of serverDomain - http.createServer(function(req, res) { + http.createServer((req, res) => { // req and res are also created in the scope of serverDomain // however, we'd prefer to have a separate domain for each request. // create it first thing, and add req and res to it. var reqd = domain.create(); reqd.add(req); reqd.add(res); - reqd.on('error', function(er) { + reqd.on('error', (er) => { console.error('Error', er, req.url); try { res.writeHead(500); @@ -264,8 +266,8 @@ Returns a new Domain object. The Domain class encapsulates the functionality of routing errors and uncaught exceptions to the active Domain object. -Domain is a child class of [EventEmitter][]. To handle the errors that it -catches, listen to its `error` event. +Domain is a child class of [`EventEmitter`][]. To handle the errors that it +catches, listen to its `'error'` event. ### domain.run(fn[, arg][, ...]) @@ -281,14 +283,16 @@ This is the most basic way to use a domain. Example: ``` -var d = domain.create(); -d.on('error', function(er) { +const domain = require('domain'); +const fs = require('fs'); +const d = domain.create(); +d.on('error', (er) => { console.error('Caught error!', er); }); -d.run(function() { - process.nextTick(function() { - setTimeout(function() { // simulating some various async stuff - fs.open('non-existent file', 'r', function(er, fd) { +d.run(() => { + process.nextTick(() => { + setTimeout(() => { // simulating some various async stuff + fs.open('non-existent file', 'r', (er, fd) => { if (er) throw er; // proceed... }); @@ -312,12 +316,12 @@ to the domain. * `emitter` {EventEmitter | Timer} emitter or timer to be added to the domain Explicitly adds an emitter to the domain. If any event handlers called by -the emitter throw an error, or if the emitter emits an `error` event, it -will be routed to the domain's `error` event, just like with implicit +the emitter throw an error, or if the emitter emits an `'error'` event, it +will be routed to the domain's `'error'` event, just like with implicit binding. -This also works with timers that are returned from `setInterval` and -`setTimeout`. If their callback function throws, it will be caught by +This also works with timers that are returned from [`setInterval()`][] and +[`setTimeout()`][]. If their callback function throws, it will be caught by the domain 'error' handler. If the Timer or EventEmitter was already bound to a domain, it is removed @@ -327,7 +331,7 @@ from that one, and bound to this one instead. * `emitter` {EventEmitter | Timer} emitter or timer to be removed from the domain -The opposite of `domain.add(emitter)`. Removes domain handling from the +The opposite of [`domain.add(emitter)`][]. Removes domain handling from the specified emitter. ### domain.bind(callback) @@ -337,11 +341,11 @@ specified emitter. The returned function will be a wrapper around the supplied callback function. When the returned function is called, any errors that are -thrown will be routed to the domain's `error` event. +thrown will be routed to the domain's `'error'` event. #### Example - var d = domain.create(); + const d = domain.create(); function readSomeFile(filename, cb) { fs.readFile(filename, 'utf8', d.bind(function(er, data) { @@ -350,7 +354,7 @@ thrown will be routed to the domain's `error` event. })); } - d.on('error', function(er) { + d.on('error', (er) => { // an error occurred somewhere. // if we throw it now, it will crash the program // with the normal line number and stack message. @@ -361,16 +365,16 @@ thrown will be routed to the domain's `error` event. * `callback` {Function} The callback function * return: {Function} The intercepted function -This method is almost identical to `domain.bind(callback)`. However, in -addition to catching thrown errors, it will also intercept `Error` +This method is almost identical to [`domain.bind(callback)`][]. However, in +addition to catching thrown errors, it will also intercept [`Error`][] objects sent as the first argument to the function. -In this way, the common `if (er) return callback(er);` pattern can be replaced +In this way, the common `if (err) return callback(err);` pattern can be replaced with a single error handler in a single place. #### Example - var d = domain.create(); + const d = domain.create(); function readSomeFile(filename, cb) { fs.readFile(filename, 'utf8', d.intercept(function(data) { @@ -386,7 +390,7 @@ with a single error handler in a single place. })); } - d.on('error', function(er) { + d.on('error', (er) => { // an error occurred somewhere. // if we throw it now, it will crash the program // with the normal line number and stack message. @@ -397,12 +401,12 @@ with a single error handler in a single place. The `enter` method is plumbing used by the `run`, `bind`, and `intercept` methods to set the active domain. It sets `domain.active` and `process.domain` to the domain, and implicitly pushes the domain onto the domain stack managed -by the domain module (see `domain.exit()` for details on the domain stack). The +by the domain module (see [`domain.exit()`][] for details on the domain stack). The call to `enter` delimits the beginning of a chain of asynchronous calls and I/O operations bound to a domain. Calling `enter` changes only the active domain, and does not alter the domain -itself. `Enter` and `exit` can be called an arbitrary number of times on a +itself. `enter` and `exit` can be called an arbitrary number of times on a single domain. If the domain on which `enter` is called has been disposed, `enter` will return @@ -420,7 +424,7 @@ If there are multiple, nested domains bound to the current execution context, `exit` will exit any domains nested within this domain. Calling `exit` changes only the active domain, and does not alter the domain -itself. `Enter` and `exit` can be called an arbitrary number of times on a +itself. `enter` and `exit` can be called an arbitrary number of times on a single domain. If the domain on which `exit` is called has been disposed, `exit` will return @@ -432,7 +436,15 @@ without exiting the domain. explicitly via error event handlers set on the domain. Once `dispose` has been called, the domain will no longer be used by callbacks -bound into the domain via `run`, `bind`, or `intercept`, and a `dispose` event +bound into the domain via `run`, `bind`, or `intercept`, and a `'dispose'` event is emitted. -[EventEmitter]: events.html#events_class_events_eventemitter +[`domain.add(emitter)`]: #domain_domain_add_emitter +[`domain.bind(callback)`]: #domain_domain_bind_callback +[`domain.dispose()`]: #domain_domain_dispose +[`domain.exit()`]: #domain_domain_exit +[`Error`]: errors.html#errors_class_error +[`EventEmitter`]: events.html#events_class_events_eventemitter +[`setInterval()`]: timers.html#timers_setinterval_callback_delay_arg +[`setTimeout()`]: timers.html#timers_settimeout_callback_delay_arg +[`throw`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/throw diff --git a/doc/api/errors.markdown b/doc/api/errors.markdown index d2c09f2e6b7788..823e9361901cb1 100644 --- a/doc/api/errors.markdown +++ b/doc/api/errors.markdown @@ -2,222 +2,257 @@ -Errors generated by Node.js fall into two categories: JavaScript errors and system -errors. All errors inherit from or are instances of JavaScript's [Error][] -class and are guaranteed to provide *at least* the attributes available on that -class. - -When an operation is not permitted due to language-syntax or -language-runtime-level reasons, a **JavaScript error** is generated and thrown -as an **exception**. If an operation is not allowed due to system-level -restrictions, a **system error** is generated. Client code is then given the -opportunity to **intercept** this error based on how the API **propagates** it. - -The style of API called determines how generated errors are handed back, or -**propagated**, to client code, which in turn informs how the client may **intercept** -the error. Exceptions can be intercepted using the `try / catch` construct; -other propagation strategies are covered [below][]. +Applications running in Node.js will generally experience four categories of +errors: + +- Standard JavaScript errors such as: + - [`EvalError`][]: thrown when a call to `eval()` fails. + - [`SyntaxError`][]: thrown in response to improper JavaScript language + syntax. + - [`RangeError`][]: thrown when a value is not within an expected range + - [`ReferenceError`][]: thrown when using undefined variables + - [`TypeError`][]: thrown when passing arguments of the wrong type + - [`URIError`][]: thrown when a global URI handling function is misused. +- System errors triggered by underlying operating system constraints such + as attempting to open a file that does not exist, attempting to send data + over a closed socket, etc; +- And User-specified errors triggered by application code. +- Assertion Errors are a special class of error that can be triggered whenever + Node.js detects an exceptional logic violation that should never occur. These + are raised typically by the `assert` module. + +All JavaScript and System errors raised by Node.js inherit from, or are +instances of, the standard JavaScript [`Error`][] class and are guaranteed +to provide *at least* the properties available on that class. ## Error Propagation and Interception -All Node.js APIs will treat invalid arguments as exceptional -- that is, if passed -invalid arguments, they will *immediately* generate and throw the error as an -exception, even if they are an otherwise asynchronous API. - -Synchronous APIs (like [fs.readFileSync][]) will throw the error. The act of -*throwing* a value (in this case, the error) turns the value into an **exception**. -Exceptions may be caught using the `try { } catch(err) { }` construct. +Node.js supports several mechanisms for propagating and handling errors that +occur while an application is running. How these errors are reported and +handled depends entirely on the type of Error and the style of the API that is +called. + +All JavaScript errors are handled as exceptions that *immediately* generate +and throw an error using the standard JavaScript `throw` mechanism. These +are handled using the [`try / catch` construct][] provided by the JavaScript +language. + + // Throws with a ReferenceError because z is undefined + try { + const m = 1; + const n = m + z; + } catch (err) { + // Handle the error here. + } -Asynchronous APIs have **two** mechanisms for error propagation; one mechanism -for APIs that represent a single operation, and one for APIs that represent -multiple operations over time. +Any use of the JavaScript `throw` mechanism will raise an exception that +*must* be handled using `try / catch` or the Node.js process will exit +immediately. -### Error events +With few exceptions, _Synchronous_ APIs (any blocking method that does not +accept a `callback` function, such as [`fs.readFileSync`][]), will use `throw` +to report errors. - +Errors that occur within _Asynchronous APIs_ may be reported in multiple ways: -The other mechanism for providing errors is the "error" event. This is -typically used by [stream-based][] and [event emitter-based][] APIs, which -themselves represent a series of asynchronous operations over time (versus a -single operation that may pass or fail). If no "error" event handler is -attached to the source of the error, the error will be thrown. At this point, -it will crash the process as an unhandled exception unless [domains][] are -employed appropriately or [process.on('uncaughtException')][] has a handler. +- Most asynchronous methods that accept a `callback` function will accept an + `Error` object passed as the first argument to that function. If that first + argument is not `null` and is an instance of `Error`, then an error occurred + that should be handled. -```javascript -var net = require('net'); + ``` + const fs = require('fs'); + fs.readFile('a file that does not exist', (err, data) => { + if (err) { + console.error('There was an error reading the file!', err); + return; + } + // Otherwise handle the data + }); + ``` +- When an asynchronous method is called on an object that is an `EventEmitter`, + errors can be routed to that object's `'error'` event. + + ``` + const net = require('net'); + const connection = net.connect('localhost'); + + // Adding an 'error' event handler to a stream: + connection.on('error', (err) => { + // If the connection is reset by the server, or if it can't + // connect at all, or on any sort of error encountered by + // the connection, the error will be sent here. + console.error(err); + }); -var connection = net.connect('localhost'); + connection.pipe(process.stdout); + ``` -// adding an "error" event handler to a stream: -connection.on('error', function(err) { - // if the connection is reset by the server, or if it can't - // connect at all, or on any sort of error encountered by - // the connection, the error will be sent here. - console.error(err); -}); +- A handful of typically asynchronous methods in the Node.js API may still + use the `throw` mechanism to raise exceptions that must be handled using + `try / catch`. There is no comprehensive list of such methods; please + refer to the documentation of each method to determine the appropriate + error handling mechanism required. -connection.pipe(process.stdout); -``` +The use of the `'error'` event mechanism is most common for [stream-based][] +and [event emitter-based][] APIs, which themselves represent a series of +asynchronous operations over time (as opposed to a single operation that may +pass or fail). -The "throw when no error handlers are attached behavior" is not limited to APIs -provided by Node.js -- even user created event emitters and streams will throw -errors when no error handlers are attached. An example: +For *all* `EventEmitter` objects, if an `'error'` event handler is not +provided, the error will be thrown, causing the Node.js process to report an +unhandled exception and crash unless either: The [`domain`][] module is used +appropriately or a handler has been registered for the +[`process.on('uncaughtException')`][] event. -```javascript -var EventEmitter = require('events'); + const EventEmitter = require('events'); + const ee = new EventEmitter(); -var ee = new EventEmitter(); + setImmediate(() => { + // This will crash the process because no 'error' event + // handler has been added. + ee.emit('error', new Error('This will crash')); + }); -setImmediate(function() { - // this will crash the process because no "error" event - // handler has been added. - ee.emit('error', new Error('This will crash')); -}); -``` +Errors generated in this way *cannot* be intercepted using `try / catch` as +they are thrown *after* the calling code has already exited. -As with node style callbacks, errors generated this way *cannot* be intercepted -by `try { } catch(err) { }` -- they happen *after* the calling code has already -exited. +Developers must refer to the documentation for each method to determine +exactly how errors raised by those methods are propagated. -### Node style callbacks +### Node.js style callbacks -Single operation APIs take "node style callbacks" -- a -function provided to the API as an argument. The node style callback takes -at least **one** argument -- `error` -- that will either be `null` (if no error -was encountered) or an `Error` instance. For instance: - -```javascript -var fs = require('fs'); - -fs.readFile('/some/file/that/does-not-exist', function nodeStyleCallback(err, data) { - console.log(err) // Error: ENOENT - console.log(data) // undefined / null -}); - -fs.readFile('/some/file/that/does-exist', function(err, data) { - console.log(err) // null - console.log(data) // -}) -``` - -Note that `try { } catch(err) { }` **cannot** intercept errors generated by -asynchronous APIs. A common mistake for beginners is to try to use `throw` -inside their node style callback: - -```javascript -// THIS WILL NOT WORK: -var fs = require('fs'); - -try { - fs.readFile('/some/file/that/does-not-exist', function(err, data) { - // mistaken assumption: throwing here... - if (err) { - throw err; +Most asynchronous methods exposed by the Node.js core API follow an idiomatic +pattern referred to as a "Node.js style callback". With this pattern, a +callback function is passed to the method as an argument. When the operation +either completes or an error is raised, the callback function is called with +the Error object (if any) passed as the first argument. If no error was raised, +the first argument will be passed as `null`. + + const fs = require('fs'); + + function nodeStyleCallback(err, data) { + if (err) { + console.error('There was an error', err); + return; + } + console.log(data); } - }); -} catch(err) { - // ... will be caught here -- this is incorrect! - console.log(err); // Error: ENOENT -} -``` - -This will not work! By the time the node style callback has been called, the -surrounding code (including the `try { } catch(err) { }` will have already -exited. Throwing an error inside a node style callback **will crash the process** in most cases. -If [domains][] are enabled, they may intercept the thrown error; similarly, if a -handler has been added to `process.on('uncaughtException')`, it will intercept -the error. -## JavaScript Errors - - + fs.readFile('/some/file/that/does-not-exist', nodeStyleCallback); + fs.readFile('/some/file/that/does-exist', nodeStyleCallback) + +The JavaScript `try / catch` mechanism **cannot** be used to intercept errors +generated by asynchronous APIs. A common mistake for beginners is to try to +use `throw` inside a Node.js style callback: + + // THIS WILL NOT WORK: + const fs = require('fs'); + + try { + fs.readFile('/some/file/that/does-not-exist', (err, data) => { + // mistaken assumption: throwing here... + if (err) { + throw err; + } + }); + } catch(err) { + // This will not catch the throw! + console.log(err); + } -JavaScript errors typically denote that an API is being used incorrectly, or that -there is a problem with the program as written. +This will not work because the callback function passed to `fs.readFile()` is +called asynchronously. By the time the callback has been called, the +surrounding code (including the `try { } catch(err) { }` block will have +already exited. Throwing an error inside the callback **can crash the Node.js +process** in most cases. If [domains][] are enabled, or a handler has been +registered with `process.on('uncaughtException')`, such errors can be +intercepted. -### Class: Error +## Class: Error -A general error object. Unlike other error objects, `Error` instances do not -denote any specific circumstance of why the error occurred. Errors capture a -"stack trace" detailing the point in the program at which they were -instantiated, and may provide a description of the error. +A generic JavaScript `Error` object that does not denote any specific +circumstance of why the error occurred. `Error` objects capture a "stack trace" +detailing the point in the code at which the `Error` was instantiated, and may +provide a text description of the error. -**Note**: Node.js will generate this class of error to encapsulate system -errors as well as plain JavaScript errors. +All errors generated by Node.js, including all System and JavaScript errors, +will either be instances of, or inherit from, the `Error` class. -#### new Error(message) +### new Error(message) -Instantiates a new Error object and sets its `.message` property to the provided -message. Its `.stack` will represent the point in the program at which `new Error` -was called. Stack traces are subject to [V8's stack trace API][]. -Stack traces only extend to the beginning of synchronous code execution, *or* a number of frames given by -`Error.stackTraceLimit`, whichever is smaller. +Creates a new `Error` object and sets the `error.message` property to the +provided text message. If an object is passed as `message`, the text message +is generated by calling `message.toString()`. The `error.stack` property will +represent the point in the code at which `new Error()` was called. Stack traces +are dependent on [V8's stack trace API][]. Stack traces extend only to either +(a) the beginning of *synchronous code execution*, or (b) the number of frames +given by the property `Error.stackTraceLimit`, whichever is smaller. -#### Error.captureStackTrace(targetObject[, constructorOpt]) +### Error.captureStackTrace(targetObject[, constructorOpt]) Creates a `.stack` property on `targetObject`, which when accessed returns -a string representing the location in the program at which `Error.captureStackTrace` -was called. - -```javascript -var myObject = {}; - -Error.captureStackTrace(myObject); +a string representing the location in the code at which +`Error.captureStackTrace()` was called. -myObject.stack // similar to `new Error().stack` -``` + const myObject = {}; + Error.captureStackTrace(myObject); + myObject.stack // similar to `new Error().stack` The first line of the trace, instead of being prefixed with `ErrorType: -message`, will be the result of `targetObject.toString()`. +message`, will be the result of calling `targetObject.toString()`. -`constructorOpt` optionally accepts a function. If given, all frames above -`constructorOpt`, including `constructorOpt`, will be omitted from the generated -stack trace. +The optional `constructorOpt` argument accepts a function. If given, all frames +above `constructorOpt`, including `constructorOpt`, will be omitted from the +generated stack trace. -This is useful for hiding implementation details of error generation from the -end user. A common way of using this parameter is to pass the current Error -constructor to it: +The `constructorOpt` argument is useful for hiding implementation +details of error generation from an end user. For instance: -```javascript - -function MyError() { - Error.captureStackTrace(this, MyError); -} + function MyError() { + Error.captureStackTrace(this, MyError); + } -// without passing MyError to captureStackTrace, the MyError -// frame would should up in the .stack property. by passing -// the constructor, we omit that frame and all frames above it. -new MyError().stack + // Without passing MyError to captureStackTrace, the MyError + // frame would should up in the .stack property. by passing + // the constructor, we omit that frame and all frames above it. + new MyError().stack -``` +### Error.stackTraceLimit -#### Error.stackTraceLimit +The `Error.stackTraceLimit` property specifies the number of stack frames +collected by a stack trace (whether generated by `new Error().stack` or +`Error.captureStackTrace(obj)`). -Property that determines the number of stack frames collected by a stack trace -(whether generated by `new Error().stack` or `Error.captureStackTrace(obj)`). +The default value is `10` but may be set to any valid JavaScript number. Changes +will affect any stack trace captured *after* the value has been changed. -The initial value is `10`. It may be set to any valid JavaScript number, which -will affect any stack trace captured *after* the value has been changed. If set -to a non-number value, stack traces will not capture any frames and will report -`undefined` on access. +If set to a non-number value, or set to a negative number, stack traces will +not capture any frames. #### error.message -A string of the value passed to `Error()` upon instantiation. The message will -also appear in the first line of the stack trace of the error. Changing this -property *may not* change the first line of the stack trace. +Returns the string description of error as set by calling `new Error(message)`. +The `message` passed to the constructor will also appear in the first line of +the stack trace of the `Error`, however changing this property after the +`Error` object is created *may not* change the first line of the stack trace. + + const err = new Error('The message'); + console.log(err.message); + // Prints: The message #### error.stack -A property that, when **accessed**, returns a string representing the point in the program -at which this error was instantiated. An example stacktrace follows: +Returns a string describing the point in the code at which the `Error` was +instantiated. + +For example: Error: Things keep happening! at /home/gbusey/file.js:525:2 @@ -225,264 +260,259 @@ at which this error was instantiated. An example stacktrace follows: at Actor. (/home/gbusey/actors.js:400:8) at increaseSynergy (/home/gbusey/actors.js:701:6) -The first line is formatted as `: `, and it is followed -by a series of stack frames (each line beginning with "at "). Each frame describes -a call site in the program that lead to the error being generated. V8 attempts to -display a name for each function (by variable name, function name, or object -method name), but occasionally it will not be able to find a suitable name. If -V8 cannot determine a name for the function, only location information will be -displayed for that frame. Otherwise, the determined function name will be displayed -with location information appended in parentheses. - -Frames are **only** generated for JavaScript functions. If, for example, execution -synchronously passes through a C++ addon function called `cheetahify`, which itself -calls a JavaScript function, the frame representing the `cheetahify` call will **not** -be present in stacktraces: - -```javascript -var cheetahify = require('./native-binding.node'); - -function makeFaster() { - // cheetahify *synchronously* calls speedy. - cheetahify(function speedy() { - throw new Error('oh no!'); - }); -} - -makeFaster(); // will throw: -// /home/gbusey/file.js:6 -// throw new Error('oh no!'); -// ^ -// Error: oh no! -// at speedy (/home/gbusey/file.js:6:11) -// at makeFaster (/home/gbusey/file.js:5:3) -// at Object. (/home/gbusey/file.js:10:1) -// at Module._compile (module.js:456:26) -// at Object.Module._extensions..js (module.js:474:10) -// at Module.load (module.js:356:32) -// at Function.Module._load (module.js:312:12) -// at Function.Module.runMain (module.js:497:10) -// at startup (node.js:119:16) -// at node.js:906:3 -``` +The first line is formatted as `: `, and +is followed by a series of stack frames (each line beginning with "at "). +Each frame describes a call site within the code that lead to the error being +generated. V8 attempts to display a name for each function (by variable name, +function name, or object method name), but occasionally it will not be able to +find a suitable name. If V8 cannot determine a name for the function, only +location information will be displayed for that frame. Otherwise, the +determined function name will be displayed with location information appended +in parentheses. + +It is important to note that frames are **only** generated for JavaScript +functions. If, for example, execution synchronously passes through a C++ addon +function called `cheetahify`, which itself calls a JavaScript function, the +frame representing the `cheetahify` call will **not** be present in the stack +traces: + + const cheetahify = require('./native-binding.node'); + + function makeFaster() { + // cheetahify *synchronously* calls speedy. + cheetahify(function speedy() { + throw new Error('oh no!'); + }); + } + + makeFaster(); // will throw: + // /home/gbusey/file.js:6 + // throw new Error('oh no!'); + // ^ + // Error: oh no! + // at speedy (/home/gbusey/file.js:6:11) + // at makeFaster (/home/gbusey/file.js:5:3) + // at Object. (/home/gbusey/file.js:10:1) + // at Module._compile (module.js:456:26) + // at Object.Module._extensions..js (module.js:474:10) + // at Module.load (module.js:356:32) + // at Function.Module._load (module.js:312:12) + // at Function.Module.runMain (module.js:497:10) + // at startup (node.js:119:16) + // at node.js:906:3 The location information will be one of: * `native`, if the frame represents a call internal to V8 (as in `[].forEach`). -* `plain-filename.js:line:column`, if the frame represents a call internal to Node.js. -* `/absolute/path/to/file.js:line:column`, if the frame represents a call in a user program, or its dependencies. +* `plain-filename.js:line:column`, if the frame represents a call internal + to Node.js. +* `/absolute/path/to/file.js:line:column`, if the frame represents a call in + a user program, or its dependencies. -It is important to note that the string representing the stacktrace is only -generated on **access**: it is lazily generated. +The string representing the stack trace is lazily generated when the +`error.stack` property is **accessed**. The number of frames captured by the stack trace is bounded by the smaller of `Error.stackTraceLimit` or the number of available frames on the current event loop tick. -System-level errors are generated as augmented Error instances, which are detailed -[below](#errors_system_errors). +System-level errors are generated as augmented `Error` instances, which are +detailed [below](#errors_system_errors). + +## Class: RangeError -### Class: RangeError +A subclass of `Error` that indicates that a provided argument was not within the +set or range of acceptable values for a function; whether that is a numeric +range, or outside the set of options for a given function parameter. -A subclass of Error that indicates that a provided argument was not within the -set or range of acceptable values for a function; whether that be a numeric -range, or outside the set of options for a given function parameter. An example: +For example: -```javascript -require('net').connect(-1); // throws RangeError, port should be > 0 && < 65536 -``` + require('net').connect(-1); + // throws RangeError, port should be > 0 && < 65536 -Node.js will generate and throw RangeError instances *immediately* -- they are a form +Node.js will generate and throw `RangeError` instances *immediately* as a form of argument validation. -### Class: ReferenceError +## Class: ReferenceError -A subclass of Error that indicates that an attempt is being made to access a variable -that is not defined. Most commonly it indicates a typo, or an otherwise broken program. -While client code may generate and propagate these errors, in practice only V8 will do -so. +A subclass of `Error` that indicates that an attempt is being made to access a +variable that is not defined. Such errors commonly indicate typos in code, or +an otherwise broken program. -```javascript -doesNotExist; // throws ReferenceError, doesNotExist is not a variable in this program. -``` +While client code may generate and propagate these errors, in practice, only V8 +will do so. -ReferenceError instances will have an `.arguments` member that is an array containing -one element -- a string representing the variable that was not defined. + doesNotExist; + // throws ReferenceError, doesNotExist is not a variable in this program. -```javascript -try { - doesNotExist; -} catch(err) { - err.arguments[0] === 'doesNotExist'; -} -``` +`ReferenceError` instances will have an `error.arguments` property whose value +is an array containing a single element: a string representing the variable +that was not defined. + + const assert = require('assert'); + try { + doesNotExist; + } catch(err) { + assert(err.arguments[0], 'doesNotExist'); + } -Unless the userland program is dynamically generating and running code, -ReferenceErrors should always be considered a bug in the program, or its -dependencies. +Unless an application is dynamically generating and running code, +`ReferenceError` instances should always be considered a bug in the code +or its dependencies. -### Class: SyntaxError +## Class: SyntaxError -A subclass of Error that indicates that a program is not valid JavaScript. +A subclass of `Error` that indicates that a program is not valid JavaScript. These errors may only be generated and propagated as a result of code evaluation. Code evaluation may happen as a result of `eval`, `Function`, `require`, or [vm][]. These errors are almost always indicative of a broken program. -```javascript -try { - require("vm").runInThisContext("binary ! isNotOk"); -} catch(err) { - // err will be a SyntaxError -} -``` + try { + require('vm').runInThisContext('binary ! isNotOk'); + } catch(err) { + // err will be a SyntaxError + } -SyntaxErrors are unrecoverable from the context that created them – they may only be caught -by other contexts. +`SyntaxError` instances are unrecoverable in the context that created them – +they may only be caught by other contexts. -### Class: TypeError +## Class: TypeError -A subclass of Error that indicates that a provided argument is not an allowable -type. For example, passing a function to a parameter which expects a string would -be considered a TypeError. +A subclass of `Error` that indicates that a provided argument is not an +allowable type. For example, passing a function to a parameter which expects a +string would be considered a TypeError. -```javascript -require('url').parse(function() { }); // throws TypeError, since it expected a string -``` + require('url').parse(function() { }); + // throws TypeError, since it expected a string -Node.js will generate and throw TypeError instances *immediately* -- they are a form +Node.js will generate and throw `TypeError` instances *immediately* as a form of argument validation. -### Exceptions vs. Errors +## Exceptions vs. Errors -A JavaScript exception is a value that is thrown as a result of an invalid operation or -as the target of a `throw` statement. While it is not required that these values are instances of -`Error` or classes which inherit from `Error`, all exceptions thrown by Node.js or the JavaScript -runtime *will* be instances of Error. +A JavaScript exception is a value that is thrown as a result of an invalid +operation or as the target of a `throw` statement. While it is not required +that these values are instances of `Error` or classes which inherit from +`Error`, all exceptions thrown by Node.js or the JavaScript runtime *will* be +instances of Error. -Some exceptions are *unrecoverable* at the JavaScript layer. These exceptions will always bring -down the process. These are usually failed `assert()` checks or `abort()` calls in the C++ layer. +Some exceptions are *unrecoverable* at the JavaScript layer. Such exceptions +will *always* cause the Node.js process to crash. Examples include `assert()` +checks or `abort()` calls in the C++ layer. ## System Errors -System errors are generated in response to a program's runtime environment. -Ideally, they represent operational errors that the program needs to be able to -react to. They are generated at the syscall level: an exhaustive list of error -codes and their meanings is available by running `man 2 intro` or `man 3 errno` -on most Unices; or [online][]. +System errors are generated when exceptions occur within the program's +runtime environment. Typically, these are operational errors that occur +when an application violates an operating system constraint such as attempting +to read a file that does not exist or when the user does not have sufficient +permissions. + +System errors are typically generated at the syscall level: an exhaustive list +of error codes and their meanings is available by running `man 2 intro` or +`man 3 errno` on most Unices; or [online][]. -In Node.js, system errors are represented as augmented Error objects -- not full -subclasses, but instead an error instance with added members. +In Node.js, system errors are represented as augmented `Error` objects with +added properties. ### Class: System Error #### error.code #### error.errno -A string representing the error code, which is always `E` followed by capital -letters, and may be referenced in `man 2 intro`. +Returns a string representing the error code, which is always `E` followed by +a sequence of capital letters, and may be referenced in `man 2 intro`. + +The properties `error.code` and `error.errno` are aliases of one another and +return the same value. #### error.syscall -A string representing the [syscall][] that failed. +Returns a string describing the [syscall][] that failed. ### Common System Errors -This list is **not exhaustive**, but enumerates many of the common system errors when -writing a Node.js program. An exhaustive list may be found [here][online]. - -#### EACCES: Permission denied - -An attempt was made to access a file in a way forbidden by its file access -permissions. - -#### EADDRINUSE: Address already in use - -An attempt to bind a server ([net][], [http][], or [https][]) to a local -address failed due to another server on the local system already occupying -that address. - -#### ECONNREFUSED: Connection refused - -No connection could be made because the target machine actively refused -it. This usually results from trying to connect to a service that is inactive -on the foreign host. - -#### ECONNRESET: Connection reset by peer - -A connection was forcibly closed by a peer. This normally results -from a loss of the connection on the remote socket due to a timeout -or reboot. Commonly encountered via the [http][] and [net][] modules. - -#### EEXIST: File exists - -An existing file was the target of an operation that required that the target -not exist. - -#### EISDIR: Is a directory - -An operation expected a file, but the given pathname was a directory. - -#### EMFILE: Too many open files in system - -Maximum number of [file descriptors][] allowable on the system has -been reached, and requests for another descriptor cannot be fulfilled until -at least one has been closed. - -Commonly encountered when opening many files at once in parallel, especially -on systems (in particular, OS X) where there is a low file descriptor limit -for processes. To remedy a low limit, run `ulimit -n 2048` in the same shell -that will run the Node.js process. - -#### ENOENT: No such file or directory - -Commonly raised by [fs][] operations; a component of the specified pathname -does not exist -- no entity (file or directory) could be found by the given path. - -#### ENOTDIR: Not a directory - -A component of the given pathname existed, but was not a directory as expected. -Commonly raised by [fs.readdir][]. - -#### ENOTEMPTY: Directory not empty - -A directory with entries was the target of an operation that requires -an empty directory -- usually [fs.unlink][]. - -#### EPERM: Operation not permitted - -An attempt was made to perform an operation that requires appropriate -privileges. - -#### EPIPE: Broken pipe - -A write on a pipe, socket, or FIFO for which there is no process to read the -data. Commonly encountered at the [net][] and [http][] layers, indicative that -the remote side of the stream being written to has been closed. - -#### ETIMEDOUT: Operation timed out - -A connect or send request failed because the connected party did not properly -respond after a period of time. Usually encountered by [http][] or [net][] -- -often a sign that a connected socket was not `.end()`'d appropriately. - -[Error]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error +This list is **not exhaustive**, but enumerates many of the common system +errors encountered when writing a Node.js program. An exhaustive list may be +found [here][online]. + +- `EACCES` (Permission denied): An attempt was made to access a file in a way + forbidden by its file access permissions. + +- `EADDRINUSE` (Address already in use): An attempt to bind a server + ([`net`][], [`http`][], or [`https`][]) to a local address failed due to + another server on the local system already occupying that address. + +- `ECONNREFUSED` (Connection refused): No connection could be made because the + target machine actively refused it. This usually results from trying to + connect to a service that is inactive on the foreign host. + +- `ECONNRESET` (Connection reset by peer): A connection was forcibly closed by + a peer. This normally results from a loss of the connection on the remote + socket due to a timeout or reboot. Commonly encountered via the [`http`][] + and [`net`][] modules. + +- `EEXIST` (File exists): An existing file was the target of an operation that + required that the target not exist. + +- `EISDIR` (Is a directory): An operation expected a file, but the given + pathname was a directory. + +- `EMFILE` (Too many open files in system): Maximum number of + [file descriptors][] allowable on the system has been reached, and + requests for another descriptor cannot be fulfilled until at least one + has been closed. This is encountered when opening many files at once in + parallel, especially on systems (in particular, OS X) where there is a low + file descriptor limit for processes. To remedy a low limit, run + `ulimit -n 2048` in the same shell that will run the Node.js process. + +- `ENOENT` (No such file or directory): Commonly raised by [`fs`][] operations + to indicate that a component of the specified pathname does not exist -- no + entity (file or directory) could be found by the given path. + +- `ENOTDIR` (Not a directory): A component of the given pathname existed, but + was not a directory as expected. Commonly raised by [`fs.readdir`][]. + +- `ENOTEMPTY` (Directory not empty): A directory with entries was the target + of an operation that requires an empty directory -- usually [`fs.unlink`][]. + +- `EPERM` (Operation not permitted): An attempt was made to perform an + operation that requires elevated privileges. + +- `EPIPE` (Broken pipe): A write on a pipe, socket, or FIFO for which there is + no process to read the data. Commonly encountered at the [`net`][] and + [`http`][] layers, indicative that the remote side of the stream being + written to has been closed. + +- `ETIMEDOUT` (Operation timed out): A connect or send request failed because + the connected party did not properly respond after a period of time. Usually + encountered by [`http`][] or [`net`][] -- often a sign that a `socket.end()` + was not properly called. + +[`Error`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error +[`fs.readdir`]: fs.html#fs_fs_readdir_path_callback +[`fs.readFileSync`]: fs.html#fs_fs_readfilesync_file_options +[`fs.unlink`]: fs.html#fs_fs_unlink_path_callback +[`fs`]: fs.html +[`http`]: http.html +[`https`]: https.html +[`net`]: net.html +[`process.on('uncaughtException')`]: process.html#process_event_uncaughtexception +[`try / catch` construct]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch +[`try { } catch(err) { }`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch [below]: #errors_error_propagation_and_interception -[fs.readFileSync]: fs.html#fs_fs_readfilesync_file_options -[stream-based]: stream.html -[event emitter-based]: events.html#events_class_events_eventemitter [domains]: domain.html -[process.on('uncaughtException')]: process.html#process_event_uncaughtexception -[V8's stack trace API]: https://code.google.com/p/v8-wiki/wiki/JavaScriptStackTraceApi -[vm]: vm.html +[event emitter-based]: events.html#events_class_events_eventemitter +[file descriptors]: https://en.wikipedia.org/wiki/File_descriptor [online]: http://man7.org/linux/man-pages/man3/errno.3.html +[stream-based]: stream.html [syscall]: http://man7.org/linux/man-pages/man2/syscall.2.html -[net]: net.html -[http]: http.html -[https]: https.html -[file descriptors]: http://en.wikipedia.org/wiki/File_descriptor -[fs]: fs.html -[fs.readdir]: fs.html#fs_fs_readdir_path_callback -[fs.unlink]: fs.html#fs_fs_unlink_path_callback +[V8's stack trace API]: https://github.com/v8/v8/wiki/Stack-Trace-API +[vm]: vm.html +[`SyntaxError`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SyntaxError +[`ReferenceError`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ReferenceError +[`TypeError`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypeError +[`domain`]: domain.html diff --git a/doc/api/events.markdown b/doc/api/events.markdown index 2d17ca2f83b6b8..0fdfc078749046 100644 --- a/doc/api/events.markdown +++ b/doc/api/events.markdown @@ -4,87 +4,257 @@ -Many objects in Node.js emit events: a [`net.Server`][] emits an event each -time a peer connects to it, a [`fs.ReadStream`][] emits an event when the file -is opened. All objects which emit events are instances of `events.EventEmitter`. -You can access this module by doing: `require("events");` +Much of the Node.js core API is built around an idiomatic asynchronous +event-driven architecture in which certain kinds of objects (called "emitters") +periodically emit named events that cause Function objects ("listeners") to be +called. -Typically, event names are represented by a camel-cased string, however, -there aren't any strict restrictions on that, as any string will be accepted. +For instance: a [`net.Server`][] object emits an event each time a peer +connects to it; a [`fs.ReadStream`][] emits an event when the file is opened; +a [stream][] emits an event whenever data is available to be read. -Functions can then be attached to objects, to be executed when an event -is emitted. These functions are called _listeners_. Inside a listener -function, `this` refers to the `EventEmitter` that the listener was -attached to. +All objects that emit events are instances of the `EventEmitter` class. These +objects expose an `eventEmitter.on()` function that allows one or more +Functions to be attached to named events emitted by the object. Typically, +event names are camel-cased strings but any valid JavaScript property key +can be used. +When the `EventEmitter` object emits an event, all of the Functions attached +to that specific event are called _synchronously_. Any values returned by the +called listeners are _ignored_ and will be discarded. -## Class: events.EventEmitter +The following example shows a simple `EventEmitter` instance with a single +listener. The `eventEmitter.on()` method is used to register listeners, while +the `eventEmitter.emit()` method is used to trigger the event. -Use `require('events')` to access the EventEmitter class. + const EventEmitter = require('events'); + const util = require('util'); + + function MyEmitter() { + EventEmitter.call(this); + } + util.inherits(MyEmitter, EventEmitter); -```javascript -var EventEmitter = require('events'); -``` + const myEmitter = new MyEmitter(); + myEmitter.on('event', function() { + console.log('an event occurred!'); + }); + myEmitter.emit('event'); -When an `EventEmitter` instance experiences an error, the typical action is -to emit an `'error'` event. Error events are treated as a special case in -Node.js. If there is no listener for it, then the default action is to print -a stack trace and exit the program. +Any object can become an `EventEmitter` through inheritance. The example above +uses the traditional Node.js style prototypical inheritance using +the `util.inherits()` method. It is, however, possible to use ES6 classes as +well: -All EventEmitters emit the event `'newListener'` when new listeners are -added and `'removeListener'` when a listener is removed. + const EventEmitter = require('events'); -### Inheriting from 'EventEmitter' + class MyEmitter extends EventEmitter {} -Inheriting from `EventEmitter` is no different from inheriting from any other -constructor function. For example: + const myEmitter = new MyEmitter(); + myEmitter.on('event', function() { + console.log('an event occurred!'); + }); + myEmitter.emit('event'); + +## Passing arguments and `this` to listeners + +The `eventEmitter.emit()` method allows an arbitrary set of arguments to be +passed to the listener functions. It is important to keep in mind that when an +ordinary listener function is called by the `EventEmitter`, the standard `this` +keyword is intentionally set to reference the `EventEmitter` to which the +listener is attached. + + const myEmitter = new MyEmitter(); + myEmitter.on('event', function(a, b) { + console.log(a, b, this); + // Prints: + // a b MyEmitter { + // domain: null, + // _events: { event: [Function] }, + // _eventsCount: 1, + // _maxListeners: undefined } + }); + myEmitter.emit('event', 'a', 'b'); - 'use strict'; - const util = require('util'); - const EventEmitter = require('events'); +It is possible to use ES6 Arrow Functions as listeners, however, when doing so, +the `this` keyword will no longer reference the `EventEmitter` instance: - function MyEventEmitter() { - // Initialize necessary properties from `EventEmitter` in this instance - EventEmitter.call(this); - } + const myEmitter = new MyEmitter(); + myEmitter.on('event', (a, b) => { + console.log(a, b, this); + // Prints: a b {} + }); + myEmitter.emit('event', 'a', 'b'); + +## Asynchronous vs. Synchronous + +The `EventListener` calls all listeners synchronously in the order in which +they were registered. This is important to ensure the proper sequencing of +events and to avoid race conditions or logic errors. When appropriate, +listener functions can switch to an asynchronous mode of operation using +the `setImmediate()` or `process.nextTick()` methods: + + const myEmitter = new MyEmitter(); + myEmitter.on('event', (a, b) => { + setImmediate(() => { + console.log('this happens asynchronously'); + }); + }); + myEmitter.emit('event', 'a', 'b'); + +## Handling events only once + +When a listener is registered using the `eventEmitter.on()` method, that +listener will be invoked _every time_ the named event is emitted. + + const myEmitter = new MyEmitter(); + var m = 0; + myEmitter.on('event', () => { + console.log(++m); + }); + myEmitter.emit('event'); + // Prints: 1 + myEmitter.emit('event'); + // Prints: 2 + +Using the `eventEmitter.once()` method, it is possible to register a listener +that is immediately unregistered after it is called. + + const myEmitter = new MyEmitter(); + var m = 0; + myEmitter.once('event', () => { + console.log(++m); + }); + myEmitter.emit('event'); + // Prints: 1 + myEmitter.emit('event'); + // Ignored + +## Error events + +When an error occurs within an `EventEmitter` instance, the typical action is +for an `'error'` event to be emitted. These are treated as a special case +within Node.js. + +If an `EventEmitter` does _not_ have at least one listener registered for the +`'error'` event, and an `'error'` event is emitted, the error is thrown, a +stack trace is printed, and the Node.js process exits. + + const myEmitter = new MyEmitter(); + myEmitter.emit('error', new Error('whoops!')); + // Throws and crashes Node.js + +To guard against crashing the Node.js process, developers can either register +a listener for the `process.on('uncaughtException')` event or use the +[`domain`][] module (_Note, however, that the `domain` module has been +deprecated_). + + const myEmitter = new MyEmitter(); - // Inherit functions from `EventEmitter`'s prototype - util.inherits(MyEventEmitter, EventEmitter); + process.on('uncaughtException', (err) => { + console.log('whoops! there was an error'); + }); + + myEmitter.emit('error', new Error('whoops!')); + // Prints: whoops! there was an error + +As a best practice, developers should always register listeners for the +`'error'` event: + + const myEmitter = new MyEmitter(); + myEmitter.on('error', (err) => { + console.log('whoops! there was an error'); + }); + myEmitter.emit('error', new Error('whoops!')); + // Prints: whoops! there was an error + +## Class: EventEmitter -### Class Method: EventEmitter.listenerCount(emitter, event) +The `EventEmitter` class is defined and exposed by the `events` module: - Stability: 0 - Deprecated: Use [emitter.listenerCount][] instead. + const EventEmitter = require('events'); -Returns the number of listeners for a given event. +All EventEmitters emit the event `'newListener'` when new listeners are +added and `'removeListener'` when a listener is removed. ### Event: 'newListener' -* `event` {String} The event name +* `event` {String|Symbol} The event name * `listener` {Function} The event handler function -This event is emitted *before* a listener is added. When this event is -triggered, the listener has not been added to the array of listeners for the -`event`. Any listeners added to the event `name` in the newListener event -callback will be added *before* the listener that is in the process of being -added. +The `EventEmitter` instance will emit it's own `'newListener'` event *before* +a listener is added to it's internal array of listeners. + +Listeners registered for the `'newListener'` event will be passed the event +name and a reference to the listener being added. + +The fact that the event is triggered before adding the listener has a subtle +but important side effect: any *additional* listeners registered to the same +`name` *within* the `'newListener'` callback will be inserted *before* the +listener that is in the process of being added. + + const myEmitter = new MyEmitter(); + // Only do this once so we don't loop forever + myEmitter.once('newListener', (event, listener) => { + if (event === 'event') { + // Insert a new listener in front + myEmitter.on('event', () => { + console.log('B'); + }); + } + }); + myEmitter.on('event', () => { + console.log('A'); + }); + myEmitter.emit('event'); + // Prints: + // B + // A ### Event: 'removeListener' -* `event` {String} The event name +* `event` {String|Symbol} The event name * `listener` {Function} The event handler function -This event is emitted *after* a listener is removed. When this event is -triggered, the listener has been removed from the array of listeners for the -`event`. +The `'removeListener'` event is emitted *after* a listener is removed. + +### EventEmitter.listenerCount(emitter, event) + + Stability: 0 - Deprecated: Use [`emitter.listenerCount()`][] instead. + +A class method that returns the number of listeners for the given `event` +registered on the given `emitter`. + + const myEmitter = new MyEmitter(); + myEmitter.on('event', () => {}); + myEmitter.on('event', () => {}); + console.log(EventEmitter.listenerCount(myEmitter, 'event')); + // Prints: 2 ### EventEmitter.defaultMaxListeners -[`emitter.setMaxListeners(n)`][] sets the maximum on a per-instance basis. -This class property lets you set it for *all* `EventEmitter` instances, -current and future, effective immediately. Use with care. +By default, a maximum of `10` listeners can be registered for any single +event. This limit can be changed for individual `EventEmitter` instances +using the [`emitter.setMaxListeners(n)`][] method. To change the default +for *all* `EventEmitter` instances, the `EventEmitter.defaultMaxListeners` +property can be used. -Note that [`emitter.setMaxListeners(n)`][] still has precedence over -`EventEmitter.defaultMaxListeners`. +Take caution when setting the `EventEmitter.defaultMaxListeners` because the +change effects *all* `EventEmitter` instances, including those created before +the change is made. However, calling [`emitter.setMaxListeners(n)`][] still has +precedence over `EventEmitter.defaultMaxListeners`. + +Note that this is not a hard limit. The `EventEmitter` instance will allow +more listeners to be added but will output a trace warning to stderr indicating +that a `possible EventEmitter memory leak` has been detected. For any single +`EventEmitter`, the `emitter.getMaxListeners()` and `emitter.setMaxListeners()` +methods can be used to temporarily avoid this warning: + + emitter.setMaxListeners(emitter.getMaxListeners() + 1); + emitter.once('event', () => { + // do stuff + emitter.setMaxListeners(Math.max(emitter.getMaxListeners() - 1, 0)); + }); ### emitter.addListener(event, listener) @@ -92,77 +262,72 @@ Alias for `emitter.on(event, listener)`. ### emitter.emit(event[, arg1][, arg2][, ...]) -Calls each of the listeners in order with the supplied arguments. +Synchronously calls each of the listeners registered for `event`, in the order +they were registered, passing the supplied arguments to each. Returns `true` if event had listeners, `false` otherwise. ### emitter.getMaxListeners() -Returns the current max listener value for the emitter which is either set by -[`emitter.setMaxListeners(n)`][] or defaults to +Returns the current max listener value for the `EventEmitter` which is either +set by [`emitter.setMaxListeners(n)`][] or defaults to [`EventEmitter.defaultMaxListeners`][]. -This can be useful to increment/decrement max listeners to avoid the warning -while not being irresponsible and setting a too big number. +### emitter.listenerCount(event) - emitter.setMaxListeners(emitter.getMaxListeners() + 1); - emitter.once('event', function () { - // do stuff - emitter.setMaxListeners(Math.max(emitter.getMaxListeners() - 1, 0)); - }); - -### emitter.listenerCount(type) - -* `type` {Value} The type of event +* `event` {Value} The type of event -Returns the number of listeners listening to the `type` of event. +Returns the number of listeners listening to the `event` type. ### emitter.listeners(event) -Returns a copy of the array of listeners for the specified event. +Returns a copy of the array of listeners for the specified `event`. - server.on('connection', function (stream) { + server.on('connection', (stream) => { console.log('someone connected!'); }); - console.log(util.inspect(server.listeners('connection'))); // [ [Function] ] + console.log(util.inspect(server.listeners('connection'))); + // Prints: [ [Function] ] ### emitter.on(event, listener) -Adds a listener to the end of the listeners array for the specified `event`. -No checks are made to see if the `listener` has already been added. Multiple -calls passing the same combination of `event` and `listener` will result in the -`listener` being added multiple times. +Adds the `listener` function to the end of the listeners array for the +specified `event`. No checks are made to see if the `listener` has already +been added. Multiple calls passing the same combination of `event` and +`listener` will result in the `listener` being added, and called, multiple +times. - server.on('connection', function (stream) { + server.on('connection', (stream) => { console.log('someone connected!'); }); -Returns emitter, so calls can be chained. +Returns a reference to the `EventEmitter` so calls can be chained. ### emitter.once(event, listener) -Adds a **one time** listener for the event. This listener is -invoked only the next time the event is fired, after which -it is removed. +Adds a **one time** `listener` function for the `event`. This listener is +invoked only the next time `event` is triggered, after which it is removed. - server.once('connection', function (stream) { + server.once('connection', (stream) => { console.log('Ah, we have our first user!'); }); -Returns emitter, so calls can be chained. +Returns a reference to the `EventEmitter` so calls can be chained. ### emitter.removeAllListeners([event]) -Removes all listeners, or those of the specified event. It's not a good idea to -remove listeners that were added elsewhere in the code, especially when it's on -an emitter that you didn't create (e.g. sockets or file streams). +Removes all listeners, or those of the specified `event`. -Returns emitter, so calls can be chained. +Note that it is bad practice to remove listeners added elsewhere in the code, +particularly when the `EventEmitter` instance was created by some other +component or module (e.g. sockets or file streams). + +Returns a reference to the `EventEmitter` so calls can be chained. ### emitter.removeListener(event, listener) -Removes a listener from the listener array for the specified event. -**Caution**: changes array indices in the listener array behind the listener. +Removes the specified `listener` from the listener array for the specified +`event`. var callback = function(stream) { console.log('someone connected!'); @@ -176,19 +341,29 @@ listener array. If any single listener has been added multiple times to the listener array for the specified `event`, then `removeListener` must be called multiple times to remove each instance. -Returns emitter, so calls can be chained. +Because listeners are managed using an internal array, calling this will +change the position indices of any listener registered *after* the listener +being removed. This will not impact the order in which listeners are called, +but it will means that any copies of the listener array as returned by +the `emitter.listeners()` method will need to be recreated. + +Returns a reference to the `EventEmitter` so calls can be chained. ### emitter.setMaxListeners(n) -By default EventEmitters will print a warning if more than 10 listeners are -added for a particular event. This is a useful default which helps finding -memory leaks. Obviously not all Emitters should be limited to 10. This function -allows that to be increased. Set to `Infinity` (or `0`) for unlimited. +By default EventEmitters will print a warning if more than `10` listeners are +added for a particular event. This is a useful default that helps finding +memory leaks. Obviously, not all events should be limited to just 10 listeners. +The `emitter.setMaxListeners()` method allows the limit to be modified for this +specific `EventEmitter` instance. The value can be set to `Infinity` (or `0`) +for to indicate an unlimited number of listeners. -Returns emitter, so calls can be chained. +Returns a reference to the `EventEmitter` so calls can be chained. [`net.Server`]: net.html#net_class_net_server [`fs.ReadStream`]: fs.html#fs_class_fs_readstream [`emitter.setMaxListeners(n)`]: #events_emitter_setmaxlisteners_n [`EventEmitter.defaultMaxListeners`]: #events_eventemitter_defaultmaxlisteners -[emitter.listenerCount]: #events_emitter_listenercount_type +[`emitter.listenerCount()`]: #events_emitter_listenercount_event +[`domain`]: domain.html +[stream]: stream.html diff --git a/doc/api/fs.markdown b/doc/api/fs.markdown index 97903dbd469dae..6b505dcadfa313 100644 --- a/doc/api/fs.markdown +++ b/doc/api/fs.markdown @@ -18,16 +18,16 @@ You can use try/catch to handle exceptions or allow them to bubble up. Here is an example of the asynchronous version: - var fs = require('fs'); + const fs = require('fs'); - fs.unlink('/tmp/hello', function (err) { + fs.unlink('/tmp/hello', (err) => { if (err) throw err; console.log('successfully deleted /tmp/hello'); }); Here is the synchronous version: - var fs = require('fs'); + const fs = require('fs'); fs.unlinkSync('/tmp/hello'); console.log('successfully deleted /tmp/hello'); @@ -35,23 +35,23 @@ Here is the synchronous version: With the asynchronous methods there is no guaranteed ordering. So the following is prone to error: - fs.rename('/tmp/hello', '/tmp/world', function (err) { + fs.rename('/tmp/hello', '/tmp/world', (err) => { if (err) throw err; console.log('renamed complete'); }); - fs.stat('/tmp/world', function (err, stats) { + fs.stat('/tmp/world', (err, stats) => { if (err) throw err; - console.log('stats: ' + JSON.stringify(stats)); + console.log(`stats: ${JSON.stringify(stats)}`); }); It could be that `fs.stat` is executed before `fs.rename`. The correct way to do this is to chain the callbacks. - fs.rename('/tmp/hello', '/tmp/world', function (err) { + fs.rename('/tmp/hello', '/tmp/world', (err) => { if (err) throw err; - fs.stat('/tmp/world', function (err, stats) { + fs.stat('/tmp/world', (err, stats) => { if (err) throw err; - console.log('stats: ' + JSON.stringify(stats)); + console.log(`stats: ${JSON.stringify(stats)}`); }); }); @@ -64,7 +64,7 @@ will be relative to `process.cwd()`. Most fs functions let you omit the callback argument. If you do, a default callback is used that rethrows errors. To get a trace to the original call -site, set the NODE_DEBUG environment variable: +site, set the `NODE_DEBUG` environment variable: $ cat script.js function bad() { @@ -94,7 +94,7 @@ Objects returned from `fs.watch()` are of this type. * `filename` {String} The filename that changed (if relevant/available) Emitted when something changes in a watched directory or file. -See more details in [fs.watch][]. +See more details in [`fs.watch()`][]. ### Event: 'error' @@ -118,18 +118,18 @@ Emitted when the ReadStream's file is opened. ## Class: fs.Stats -Objects returned from `fs.stat()`, `fs.lstat()` and `fs.fstat()` and their +Objects returned from [`fs.stat()`][], [`fs.lstat()`][] and [`fs.fstat()`][] and their synchronous counterparts are of this type. - `stats.isFile()` - `stats.isDirectory()` - `stats.isBlockDevice()` - `stats.isCharacterDevice()` - - `stats.isSymbolicLink()` (only valid with `fs.lstat()`) + - `stats.isSymbolicLink()` (only valid with [`fs.lstat()`][]) - `stats.isFIFO()` - `stats.isSocket()` -For a regular file `util.inspect(stats)` would return a string very +For a regular file [`util.inspect(stats)`][] would return a string very similar to this: { dev: 2114, @@ -148,9 +148,9 @@ similar to this: birthtime: Mon, 10 Oct 2011 23:24:11 GMT } Please note that `atime`, `mtime`, `birthtime`, and `ctime` are -instances of [Date][MDN-Date] object and to compare the values of +instances of [`Date`][MDN-Date] object and to compare the values of these objects you should use appropriate methods. For most general -uses [getTime()][MDN-Date-getTime] will return the number of +uses [`getTime()`][MDN-Date-getTime] will return the number of milliseconds elapsed since _1 January 1970 00:00:00 UTC_ and this integer should be sufficient for any comparison, however there are additional methods which can be used for displaying fuzzy information. @@ -222,7 +222,7 @@ argument will be populated. The following example checks if the file ## fs.accessSync(path[, mode]) -Synchronous version of `fs.access`. This throws if any accessibility checks +Synchronous version of [`fs.access()`][]. This throws if any accessibility checks fail, and does nothing otherwise. ## fs.appendFile(file, data[, options], callback) @@ -240,7 +240,7 @@ Asynchronously append data to a file, creating the file if it does not yet exist Example: - fs.appendFile('message.txt', 'data to append', function (err) { + fs.appendFile('message.txt', 'data to append', (err) => { if (err) throw err; console.log('The "data to append" was appended to file!'); }); @@ -255,7 +255,7 @@ _Note: Specified file descriptors will not be closed automatically._ ## fs.appendFileSync(file, data[, options]) -The synchronous version of `fs.appendFile`. Returns `undefined`. +The synchronous version of [`fs.appendFile()`][]. Returns `undefined`. ## fs.chmod(path, mode, callback) @@ -286,7 +286,7 @@ Synchronous close(2). Returns `undefined`. ## fs.createReadStream(path[, options]) -Returns a new ReadStream object (See `Readable Stream`). +Returns a new [`ReadStream`][] object. (See [Readable Stream][]). Be aware that, unlike the default value set for `highWaterMark` on a readable stream (16 kb), the stream returned by this method has a @@ -303,12 +303,12 @@ default value of 64 kb for the same parameter. `options` can include `start` and `end` values to read a range of bytes from the file instead of the entire file. Both `start` and `end` are inclusive and -start at 0. The `encoding` can be any one of those accepted by [Buffer][]. +start at 0. The `encoding` can be any one of those accepted by [`Buffer`][]. If `fd` is specified, `ReadStream` will ignore the `path` argument and will use -the specified file descriptor. This means that no `open` event will be emitted. +the specified file descriptor. This means that no `'open'` event will be emitted. Note that `fd` should be blocking; non-blocking `fd`s should be passed to -`net.Socket`. +[`net.Socket`][]. If `autoClose` is false, then the file descriptor won't be closed, even if there's an error. It is your responsibility to close it and make sure @@ -327,7 +327,7 @@ If `options` is a string, then it specifies the encoding. ## fs.createWriteStream(path[, options]) -Returns a new WriteStream object (See `Writable Stream`). +Returns a new [`WriteStream`][] object. (See [Writable Stream][]). `options` is an object or string with the following defaults: @@ -339,24 +339,24 @@ Returns a new WriteStream object (See `Writable Stream`). `options` may also include a `start` option to allow writing data at some position past the beginning of the file. Modifying a file rather than replacing it may require a `flags` mode of `r+` rather than the -default mode `w`. The `defaultEncoding` can be any one of those accepted by [Buffer][]. +default mode `w`. The `defaultEncoding` can be any one of those accepted by [`Buffer`][]. -Like `ReadStream` above, if `fd` is specified, `WriteStream` will ignore the +Like [`ReadStream`][], if `fd` is specified, `WriteStream` will ignore the `path` argument and will use the specified file descriptor. This means that no -`open` event will be emitted. Note that `fd` should be blocking; non-blocking -`fd`s should be passed to `net.Socket`. +`'open'` event will be emitted. Note that `fd` should be blocking; non-blocking +`fd`s should be passed to [`net.Socket`][]. If `options` is a string, then it specifies the encoding. ## fs.exists(path, callback) - Stability: 0 - Deprecated: Use [fs.stat][] or [fs.access][] instead. + Stability: 0 - Deprecated: Use [`fs.stat()`][] or [`fs.access()`][] instead. Test whether or not the given path exists by checking with the file system. Then call the `callback` argument with either true or false. Example: - fs.exists('/etc/passwd', function (exists) { - console.log(exists ? "it's there" : 'no passwd!'); + fs.exists('/etc/passwd', (exists) => { + console.log(exists ? 'it\'s there' : 'no passwd!'); }); `fs.exists()` should not be used to check if a file exists before calling @@ -367,10 +367,10 @@ non-existent. ## fs.existsSync(path) -Synchronous version of [`fs.exists`][]. -Returns `true` if the file exists, `false` otherwise. + Stability: 0 - Deprecated: Use [`fs.statSync()`][] or [`fs.accessSync()`][] instead. - Stability: 0 - Deprecated: Use [fs.statSync][] or [fs.accessSync][] instead. +Synchronous version of [`fs.exists()`][]. +Returns `true` if the file exists, `false` otherwise. ## fs.fchmod(fd, mode, callback) @@ -393,7 +393,7 @@ Synchronous fchown(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 +`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) @@ -425,7 +425,7 @@ descriptor. ## fs.futimesSync(fd, atime, mtime) -Synchronous version of `fs.futimes()`. Returns `undefined`. +Synchronous version of [`fs.futimes()`][]. Returns `undefined`. ## fs.lchmod(path, mode, callback) @@ -540,7 +540,7 @@ the end of the file. ## fs.openSync(path, flags[, mode]) -Synchronous version of `fs.open()`. Returns an integer representing the file +Synchronous version of [`fs.open()`][]. Returns an integer representing the file descriptor. ## fs.read(fd, buffer, offset, length, position, callback) @@ -579,7 +579,7 @@ Synchronous readdir(3). Returns an array of filenames excluding `'.'` and Asynchronously reads the entire contents of a file. Example: - fs.readFile('/etc/passwd', function (err, data) { + fs.readFile('/etc/passwd', (err, data) => { if (err) throw err; console.log(data); }); @@ -599,7 +599,7 @@ _Note: Specified file descriptors will not be closed automatically._ ## fs.readFileSync(file[, options]) -Synchronous version of `fs.readFile`. Returns the contents of the `file`. +Synchronous version of [`fs.readFile`][]. Returns the contents of the `file`. If the `encoding` option is specified then this function returns a string. Otherwise it returns a buffer. @@ -623,18 +623,20 @@ resolution or avoid additional `fs.stat` calls for known real paths. Example: var cache = {'/etc':'/private/etc'}; - fs.realpath('/etc/passwd', cache, function (err, resolvedPath) { + fs.realpath('/etc/passwd', cache, (err, resolvedPath) => { if (err) throw err; console.log(resolvedPath); }); ## fs.readSync(fd, buffer, offset, length, position) -Synchronous version of `fs.read`. Returns the number of `bytesRead`. +Synchronous version of [`fs.read()`][]. Returns the number of `bytesRead`. ## fs.realpathSync(path[, cache]) -Synchronous realpath(2). Returns the resolved path. +Synchronous realpath(2). Returns the resolved path. `cache` is an +object literal of mapped paths that can be used to force a specific path +resolution or avoid additional `fs.stat` calls for known real paths. ## fs.rename(oldPath, newPath, callback) @@ -657,23 +659,29 @@ Synchronous rmdir(2). Returns `undefined`. ## fs.stat(path, callback) Asynchronous stat(2). The callback gets two arguments `(err, stats)` where -`stats` is a [fs.Stats][] object. See the [fs.Stats][] section below for more +`stats` is a [`fs.Stats`][] object. See the [`fs.Stats`][] section below for more information. ## fs.statSync(path) -Synchronous stat(2). Returns an instance of `fs.Stats`. +Synchronous stat(2). Returns an instance of [`fs.Stats`][]. -## fs.symlink(destination, path[, type], callback) +## fs.symlink(target, path[, type], callback) Asynchronous symlink(2). No arguments other than a possible exception are given to the completion callback. The `type` argument can be set to `'dir'`, `'file'`, or `'junction'` (default is `'file'`) and is only available on Windows (ignored on other platforms). Note that Windows junction points require the destination path to be absolute. When using -`'junction'`, the `destination` argument will automatically be normalized to absolute path. +`'junction'`, the `target` argument will automatically be normalized to absolute path. + +Here is an example below: + + fs.symlink('./foo', './new-port'); + +It would create a symlic link named with "new-port" that points to "foo". -## fs.symlinkSync(destination, path[, type]) +## fs.symlinkSync(target, path[, type]) Synchronous symlink(2). Returns `undefined`. @@ -705,8 +713,8 @@ have effectively stopped watching `filename`. Calling `fs.unwatchFile()` with a filename that is not being watched is a no-op, not an error. -_Note: `fs.watch` is more efficient than `fs.watchFile` and `fs.unwatchFile`. -`fs.watch` should be used instead of `fs.watchFile` and `fs.unwatchFile` +_Note: [`fs.watch()`][] is more efficient than `fs.watchFile()` and `fs.unwatchFile()`. +`fs.watch()` should be used instead of `fs.watchFile()` and `fs.unwatchFile()` when possible._ ## fs.utimes(path, atime, mtime, callback) @@ -716,19 +724,19 @@ Change file timestamps of the file referenced by the supplied path. Note: the arguments `atime` and `mtime` of the following related functions does follow the below rules: -- If the value is a numberable string like "123456789", the value would get +- If the value is a numberable string like `'123456789'`, the value would get converted to corresponding number. - If the value is `NaN` or `Infinity`, the value would get converted to `Date.now()`. ## fs.utimesSync(path, atime, mtime) -Synchronous version of `fs.utimes()`. Returns `undefined`. +Synchronous version of [`fs.utimes()`][]. Returns `undefined`. ## fs.watch(filename[, options][, listener]) Watch for changes on `filename`, where `filename` is either a file or a -directory. The returned object is a [fs.FSWatcher][]. +directory. The returned object is a [`fs.FSWatcher`][]. The second argument is optional. The `options` if provided should be an object. The supported boolean members are `persistent` and `recursive`. `persistent` @@ -740,7 +748,7 @@ on supported platforms (See Caveats below). The default is `{ persistent: true, recursive: false }`. The listener callback gets two arguments `(event, filename)`. `event` is either -'rename' or 'change', and `filename` is the name of the file which triggered +`'rename'` or `'change'`, and `filename` is the name of the file which triggered the event. ### Caveats @@ -782,10 +790,10 @@ Windows. Even on supported platforms, `filename` is not always guaranteed to be provided. Therefore, don't assume that `filename` argument is always provided in the callback, and have some fallback logic if it is null. - fs.watch('somedir', function (event, filename) { - console.log('event is: ' + event); + fs.watch('somedir', (event, filename) => { + console.log(`event is: ${event}`); if (filename) { - console.log('filename provided: ' + filename); + console.log(`filename provided: ${filename}`); } else { console.log('filename not provided'); } @@ -806,9 +814,9 @@ target should be polled in milliseconds. The default is The `listener` gets two arguments the current stat object and the previous stat object: - fs.watchFile('message.text', function (curr, prev) { - console.log('the current mtime is: ' + curr.mtime); - console.log('the previous mtime was: ' + prev.mtime); + fs.watchFile('message.text', (curr, prev) => { + console.log(`the current mtime is: ${curr.mtime}`); + console.log(`the previous mtime was: ${prev.mtime}`); }); These stat objects are instances of `fs.Stat`. @@ -822,7 +830,7 @@ _Note: when an `fs.watchFile` operation results in an `ENOENT` error, it will of zero. If the file is created later on, the listener will be called again, with the latest stat objects. This is a change in functionality since v0.10._ -_Note: `fs.watch` is more efficient than `fs.watchFile` and `fs.unwatchFile`. +_Note: [`fs.watch()`][] is more efficient than `fs.watchFile` and `fs.unwatchFile`. `fs.watch` should be used instead of `fs.watchFile` and `fs.unwatchFile` when possible._ @@ -860,7 +868,7 @@ the current position. See pwrite(2). The callback will receive the arguments `(err, written, string)` where `written` specifies how many _bytes_ the passed string required to be written. Note that -bytes written is not the same as string characters. See [Buffer.byteLength][]. +bytes written is not the same as string characters. See [`Buffer.byteLength`][]. Unlike when writing `buffer`, the entire string must be written. No substring may be specified. This is because the byte offset of the resulting data may not @@ -892,7 +900,7 @@ to `'utf8'`. Example: - fs.writeFile('message.txt', 'Hello Node.js', function (err) { + fs.writeFile('message.txt', 'Hello Node.js', (err) => { if (err) throw err; console.log('It\'s saved!'); }); @@ -911,25 +919,40 @@ _Note: Specified file descriptors will not be closed automatically._ ## fs.writeFileSync(file, data[, options]) -The synchronous version of `fs.writeFile`. Returns `undefined`. +The synchronous version of [`fs.writeFile()`][]. Returns `undefined`. ## fs.writeSync(fd, buffer, offset, length[, position]) ## fs.writeSync(fd, data[, position[, encoding]]) -Synchronous versions of `fs.write()`. Returns the number of bytes written. - -[fs.watch]: #fs_fs_watch_filename_options_listener -[Readable Stream]: stream.html#stream_class_stream_readable -[MDN-Date]: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date +Synchronous versions of [`fs.write()`][]. Returns the number of bytes written. + +[`Buffer.byteLength`]: buffer.html#buffer_class_method_buffer_bytelength_string_encoding +[`Buffer`]: buffer.html#buffer_buffer +[`fs.access()`]: #fs_fs_access_path_mode_callback +[`fs.accessSync()`]: #fs_fs_accesssync_path_mode +[`fs.appendFile()`]: fs.html#fs_fs_appendfile_file_data_options_callback +[`fs.exists()`]: fs.html#fs_fs_exists_path_callback +[`fs.fstat()`]: #fs_fs_fstat_fd_callback +[`fs.FSWatcher`]: #fs_class_fs_fswatcher +[`fs.futimes()`]: #fs_fs_futimes_fd_atime_mtime_callback +[`fs.lstat()`]: #fs_fs_lstat_path_callback +[`fs.open()`]: #fs_fs_open_path_flags_mode_callback +[`fs.read()`]: #fs_fs_read_fd_buffer_offset_length_position_callback +[`fs.readFile`]: #fs_fs_readfile_file_options_callback +[`fs.stat()`]: #fs_fs_stat_path_callback +[`fs.Stats`]: #fs_class_fs_stats +[`fs.statSync()`]: #fs_fs_statsync_path +[`fs.utimes()`]: #fs_fs_futimes_fd_atime_mtime_callback +[`fs.watch()`]: #fs_fs_watch_filename_options_listener +[`fs.write()`]: #fs_fs_write_fd_buffer_offset_length_position_callback +[`fs.writeFile()`]: #fs_fs_writefile_file_data_options_callback +[`net.Socket`]: net.html#net_class_net_socket +[`ReadStream`]: #fs_class_fs_readstream +[`stat()`]: fs.html#fs_fs_stat_path_callback +[`util.inspect(stats)`]: util.html#util_util_inspect_object_options +[`WriteStream`]: #fs_class_fs_writestream [MDN-Date-getTime]: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/getTime +[MDN-Date]: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date +[Readable Stream]: stream.html#stream_class_stream_readable [Writable Stream]: stream.html#stream_class_stream_writable -[fs.stat]: #fs_fs_stat_path_callback -[`fs.exists`]: fs.html#fs_fs_exists_path_callback -[fs.access]: #fs_fs_access_path_mode_callback -[fs.statSync]: #fs_fs_statsync_path -[fs.accessSync]: #fs_fs_accesssync_path_mode -[fs.Stats]: #fs_class_fs_stats -[Buffer]: buffer.html#buffer_buffer -[fs.FSWatcher]: #fs_class_fs_fswatcher -[Buffer.byteLength]: buffer.html#buffer_class_method_buffer_bytelength_string_encoding diff --git a/doc/api/globals.markdown b/doc/api/globals.markdown index dd675c90664c49..5ac7bd9a0c3aa9 100644 --- a/doc/api/globals.markdown +++ b/doc/api/globals.markdown @@ -11,7 +11,7 @@ actually in the global scope but in the module scope - this will be noted. * {Function} -Used to handle binary data. See the [buffer section][] +Used to handle binary data. See the [buffer section][]. ## __dirname @@ -48,7 +48,7 @@ Example: running `node example.js` from `/Users/mjr` ## clearInterval(t) -Stop a timer that was previously created with `setInterval()`. The callback +Stop a timer that was previously created with [`setInterval()`][]. The callback will not execute. @@ -57,7 +57,7 @@ The timer functions are global variables. See the [timers][] section. ## clearTimeout(t) -Stop a timer that was previously created with `setTimeout()`. The callback will +Stop a timer that was previously created with [`setTimeout()`][]. The callback will not execute. ## console @@ -66,7 +66,7 @@ not execute. * {Object} -Used to print to stdout and stderr. See the [console][] section. +Used to print to stdout and stderr. See the [`console`][] section. ## exports @@ -111,7 +111,7 @@ See the [module system documentation][] for more information. * {Object} -The process object. See the [process object][] section. +The process object. See the [`process` object][] section. ## require() @@ -179,9 +179,11 @@ cannot span more than 24.8 days. Returns an opaque value that represents the timer. +[`console`]: console.html +[`process` object]: process.html#process_process +[`setInterval()`]: #globals_setinterval_cb_ms +[`setTimeout()`]: #globals_settimeout_cb_ms [buffer section]: buffer.html [module system documentation]: modules.html [Modules]: modules.html#modules_modules -[process object]: process.html#process_process -[console]: console.html [timers]: timers.html diff --git a/doc/api/http.markdown b/doc/api/http.markdown index 154580a8946b2b..56d3595ed12ca3 100644 --- a/doc/api/http.markdown +++ b/doc/api/http.markdown @@ -25,7 +25,7 @@ HTTP API is very low-level. It deals with stream handling and message parsing only. It parses a message into headers and body but it does not parse the actual headers or the body. -See [message.headers][] for details on how duplicate headers are handled. +See [`message.headers`][] for details on how duplicate headers are handled. The raw headers as they were received are retained in the `rawHeaders` property, which is an array of `[key, value, key2, value2, ...]`. For @@ -60,14 +60,14 @@ agents when they are no longer in use, so that the Sockets will be shut down. Sockets are removed from the agent's pool when the socket emits either -a "close" event or a special "agentRemove" event. This means that if +a `'close'` event or a special `'agentRemove'` event. This means that if you intend to keep one HTTP request open for a long time and don't want it to stay in the pool you can do something along the lines of: - http.get(options, function(res) { + http.get(options, (res) => { // Do stuff - }).on("socket", function (socket) { - socket.emit("agentRemove"); + }).on('socket', (socket) => { + socket.emit('agentRemove'); }); Alternatively, you could just opt out of pooling entirely using @@ -78,7 +78,7 @@ Alternatively, you could just opt out of pooling entirely using port: 80, path: '/', agent: false // create a new agent just for this one request - }, function (res) { + }, (res) => { // Do stuff with response }) @@ -97,13 +97,13 @@ Alternatively, you could just opt out of pooling entirely using in a free state. Only relevant if `keepAlive` is set to `true`. Default = `256`. -The default `http.globalAgent` that is used by `http.request` has all +The default [`http.globalAgent`][] that is used by [`http.request()`][] has all of these values set to their respective defaults. -To configure any of them, you must create your own `Agent` object. +To configure any of them, you must create your own [`http.Agent`][] object. ```javascript -var http = require('http'); +const http = require('http'); var keepAliveAgent = new http.Agent({ keepAlive: true }); options.agent = keepAliveAgent; http.request(options, onResponseCallback); @@ -156,7 +156,7 @@ Agent. Do not modify. ## Class: http.ClientRequest -This object is created internally and returned from `http.request()`. It +This object is created internally and returned from [`http.request()`][]. It represents an _in-progress_ request whose header has already been queued. The header is still mutable using the `setHeader(name, value)`, `getHeader(name)`, `removeHeader(name)` API. The actual header will be sent along with the first @@ -165,7 +165,7 @@ data chunk or when closing the connection. To get the response, add a listener for `'response'` to the request object. `'response'` will be emitted from the request object when the response headers have been received. The `'response'` event is executed with one -argument which is an instance of [http.IncomingMessage][]. +argument which is an instance of [`http.IncomingMessage`][]. During the `'response'` event, one can add listeners to the response object; particularly to listen for the `'data'` event. @@ -183,7 +183,7 @@ Note: Node.js does not check whether Content-Length and the length of the body which has been transmitted are equal or not. The request implements the [Writable Stream][] interface. This is an -[EventEmitter][] with the following events: +[`EventEmitter`][] with the following events: ### Event: 'abort' @@ -196,25 +196,25 @@ emitted on the first call to `abort()`. `function (response, socket, head) { }` -Emitted each time a server responds to a request with a CONNECT method. If this -event isn't being listened for, clients receiving a CONNECT method will have +Emitted each time a server responds to a request with a `CONNECT` method. If this +event isn't being listened for, clients receiving a `CONNECT` method will have their connections closed. -A client server pair that show you how to listen for the `connect` event. +A client server pair that show you how to listen for the `'connect'` event. - var http = require('http'); - var net = require('net'); - var url = require('url'); + const http = require('http'); + const net = require('net'); + const url = require('url'); // Create an HTTP tunneling proxy - var proxy = http.createServer(function (req, res) { + var proxy = http.createServer( (req, res) => { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('okay'); }); - proxy.on('connect', function(req, cltSocket, head) { + proxy.on('connect', (req, cltSocket, head) => { // connect to an origin server - var srvUrl = url.parse('http://' + req.url); - var srvSocket = net.connect(srvUrl.port, srvUrl.hostname, function() { + var srvUrl = url.parse(`http://${req.url}`); + var srvSocket = net.connect(srvUrl.port, srvUrl.hostname, () => { cltSocket.write('HTTP/1.1 200 Connection Established\r\n' + 'Proxy-agent: Node.js-Proxy\r\n' + '\r\n'); @@ -225,7 +225,7 @@ A client server pair that show you how to listen for the `connect` event. }); // now that proxy is running - proxy.listen(1337, '127.0.0.1', function() { + proxy.listen(1337, '127.0.0.1', () => { // make a request to a tunneling proxy var options = { @@ -238,7 +238,7 @@ A client server pair that show you how to listen for the `connect` event. var req = http.request(options); req.end(); - req.on('connect', function(res, socket, head) { + req.on('connect', (res, socket, head) => { console.log('got connected!'); // make a request over an HTTP tunnel @@ -246,10 +246,10 @@ A client server pair that show you how to listen for the `connect` event. 'Host: www.google.com:80\r\n' + 'Connection: close\r\n' + '\r\n'); - socket.on('data', function(chunk) { + socket.on('data', (chunk) => { console.log(chunk.toString()); }); - socket.on('end', function() { + socket.on('end', () => { proxy.close(); }); }); @@ -268,7 +268,7 @@ the client should send the request body. `function (response) { }` Emitted when a response is received to this request. This event is emitted only -once. The `response` argument will be an instance of [http.IncomingMessage][]. +once. The `response` argument will be an instance of [`http.IncomingMessage`][]. Options: @@ -290,16 +290,16 @@ Emitted each time a server responds to a request with an upgrade. If this event isn't being listened for, clients receiving an upgrade header will have their connections closed. -A client server pair that show you how to listen for the `upgrade` event. +A client server pair that show you how to listen for the `'upgrade'` event. - var http = require('http'); + const http = require('http'); // Create an HTTP server - var srv = http.createServer(function (req, res) { + var srv = http.createServer( (req, res) => { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('okay'); }); - srv.on('upgrade', function(req, socket, head) { + srv.on('upgrade', (req, socket, head) => { socket.write('HTTP/1.1 101 Web Socket Protocol Handshake\r\n' + 'Upgrade: WebSocket\r\n' + 'Connection: Upgrade\r\n' + @@ -309,7 +309,7 @@ A client server pair that show you how to listen for the `upgrade` event. }); // now that server is running - srv.listen(1337, '127.0.0.1', function() { + srv.listen(1337, '127.0.0.1', () => { // make a request var options = { @@ -324,7 +324,7 @@ A client server pair that show you how to listen for the `upgrade` event. var req = http.request(options); req.end(); - req.on('upgrade', function(res, socket, upgradeHead) { + req.on('upgrade', (res, socket, upgradeHead) => { console.log('got upgraded!'); socket.end(); process.exit(0); @@ -343,7 +343,7 @@ unsent, it will flush them to the stream. If the request is chunked, this will send the terminating `'0\r\n\r\n'`. If `data` is specified, it is equivalent to calling -`request.write(data, encoding)` followed by `request.end(callback)`. +[`response.write(data, encoding)`][] followed by `request.end(callback)`. If `callback` is specified, it will be called when the request stream is finished. @@ -363,17 +363,20 @@ the optimization and kickstart the request. ### request.setNoDelay([noDelay]) Once a socket is assigned to this request and is connected -[socket.setNoDelay()][] will be called. +[`socket.setNoDelay()`][] will be called. ### request.setSocketKeepAlive([enable][, initialDelay]) Once a socket is assigned to this request and is connected -[socket.setKeepAlive()][] will be called. +[`socket.setKeepAlive()`][] will be called. ### request.setTimeout(timeout[, callback]) Once a socket is assigned to this request and is connected -[socket.setTimeout()][] will be called. +[`socket.setTimeout()`][] will be called. + +* `timeout` {Number} Milliseconds before a request is considered to be timed out. +* `callback` {Function} Optional function to be called when a timeout occurs. Same as binding to the `timeout` event. ### request.write(chunk[, encoding][, callback]) @@ -383,7 +386,7 @@ server--in that case it is suggested to use the `['Transfer-Encoding', 'chunked']` header line when creating the request. -The `chunk` argument should be a [Buffer][] or a string. +The `chunk` argument should be a [`Buffer`][] or a string. The `encoding` argument is optional and only applies when `chunk` is a string. Defaults to `'utf8'`. @@ -395,7 +398,7 @@ Returns `request`. ## Class: http.Server -This is an [EventEmitter][] with the following events: +This is an [`EventEmitter`][] with the following events: ### Event: 'checkContinue' @@ -405,21 +408,21 @@ Emitted each time a request with an http Expect: 100-continue is received. If this event isn't listened for, the server will automatically respond with a 100 Continue as appropriate. -Handling this event involves calling [response.writeContinue()][] if the client +Handling this event involves calling [`response.writeContinue()`][] if the client should continue to send the request body, or generating an appropriate HTTP response (e.g., 400 Bad Request) if the client should not continue to send the request body. -Note that when this event is emitted and handled, the `request` event will +Note that when this event is emitted and handled, the `'request'` event will not be emitted. ### Event: 'clientError' `function (exception, socket) { }` -If a client connection emits an 'error' event, it will be forwarded here. +If a client connection emits an `'error'` event, it will be forwarded here. -`socket` is the `net.Socket` object that the error originated from. +`socket` is the [`net.Socket`][] object that the error originated from. ### Event: 'close' @@ -431,8 +434,8 @@ Emitted when the server closes. `function (request, socket, head) { }` -Emitted each time a client requests a http CONNECT method. If this event isn't -listened for, then clients requesting a CONNECT method will have their +Emitted each time a client requests a http `CONNECT` method. If this event isn't +listened for, then clients requesting a `CONNECT` method will have their connections closed. * `request` is the arguments for the http request, as it is in the request @@ -441,7 +444,7 @@ connections closed. * `head` is an instance of Buffer, the first packet of the tunneling stream, this may be empty. -After this event is emitted, the request's socket will not have a `data` +After this event is emitted, the request's socket will not have a `'data'` event listener, meaning you will need to bind to it in order to handle data sent to the server on that socket. @@ -450,8 +453,8 @@ sent to the server on that socket. `function (socket) { }` When a new TCP stream is established. `socket` is an object of type -`net.Socket`. Usually users will not want to access this event. In -particular, the socket will not emit `readable` events because of how +[`net.Socket`][]. Usually users will not want to access this event. In +particular, the socket will not emit `'readable'` events because of how the protocol parser attaches to the socket. The `socket` can also be accessed at `request.connection`. @@ -461,8 +464,8 @@ accessed at `request.connection`. Emitted each time there is a request. Note that there may be multiple requests per connection (in the case of keep-alive connections). - `request` is an instance of [http.IncomingMessage][] and `response` is -an instance of [http.ServerResponse][]. + `request` is an instance of [`http.IncomingMessage`][] and `response` is +an instance of [`http.ServerResponse`][]. ### Event: 'upgrade' @@ -478,13 +481,13 @@ closed. * `head` is an instance of Buffer, the first packet of the upgraded stream, this may be empty. -After this event is emitted, the request's socket will not have a `data` +After this event is emitted, the request's socket will not have a `'data'` event listener, meaning you will need to bind to it in order to handle data sent to the server on that socket. ### server.close([callback]) -Stops the server from accepting new connections. See [net.Server.close()][]. +Stops the server from accepting new connections. See [`net.Server.close()`][]. ### server.listen(handle[, callback]) @@ -501,14 +504,16 @@ already been bound to a port or domain socket. Listening on a file descriptor is not supported on Windows. This function is asynchronous. The last parameter `callback` will be added as -a listener for the ['listening'][] event. See also [net.Server.listen()][]. +a listener for the `'listening'` event. See also [`net.Server.listen()`][]. + +Returns `server`. ### server.listen(path[, callback]) Start a UNIX socket server listening for connections on the given `path`. This function is asynchronous. The last parameter `callback` will be added as -a listener for the ['listening'][] event. See also [net.Server.listen(path)][]. +a listener for the `'listening'` event. See also [`net.Server.listen(path)`][]. ### server.listen(port[, hostname][, backlog][, callback]) @@ -525,7 +530,7 @@ The actual length will be determined by your OS through sysctl settings such as parameter is 511 (not 512). This function is asynchronous. The last parameter `callback` will be added as -a listener for the ['listening'][] event. See also [net.Server.listen(port)][]. +a listener for the `'listening'` event. See also [`net.Server.listen(port)`][]. ### server.maxHeadersCount @@ -571,14 +576,14 @@ This object is created internally by a HTTP server--not by the user. It is passed as the second parameter to the `'request'` event. The response implements the [Writable Stream][] interface. This is an -[EventEmitter][] with the following events: +[`EventEmitter`][] with the following events: ### Event: 'close' `function () { }` Indicates that the underlying connection was terminated before -[response.end()][] was called or able to flush. +[`response.end()`][] was called or able to flush. ### Event: 'finish' @@ -606,21 +611,20 @@ emit trailers, with a list of the header fields in its value. E.g., response.writeHead(200, { 'Content-Type': 'text/plain', 'Trailer': 'Content-MD5' }); response.write(fileData); - response.addTrailers({'Content-MD5': "7895bf4b8828b55ceaf47747b4bca667"}); + response.addTrailers({'Content-MD5': '7895bf4b8828b55ceaf47747b4bca667'}); response.end(); Attempting to set a trailer field name that contains invalid characters will -result in a `TypeError` being thrown. +result in a [`TypeError`][] being thrown. ### response.end([data][, encoding][, callback]) This method signals to the server that all of the response headers and body have been sent; that server should consider this message complete. -The method, `response.end()`, MUST be called on each -response. +The method, `response.end()`, MUST be called on each response. If `data` is specified, it is equivalent to calling -`response.write(data, encoding)` followed by `response.end(callback)`. +[`response.write(data, encoding)`][] followed by `response.end(callback)`. If `callback` is specified, it will be called when the response stream is finished. @@ -628,7 +632,7 @@ is finished. ### response.finished Boolean value that indicates whether the response has completed. Starts -as `false`. After `response.end()` executes, the value will be `true`. +as `false`. After [`response.end()`][] executes, the value will be `true`. ### response.getHeader(name) @@ -650,7 +654,7 @@ Removes a header that's queued for implicit sending. Example: - response.removeHeader("Content-Encoding"); + response.removeHeader('Content-Encoding'); ### response.sendDate @@ -668,14 +672,14 @@ here if you need to send multiple headers with the same name. Example: - response.setHeader("Content-Type", "text/html"); + response.setHeader('Content-Type', 'text/html'); or - response.setHeader("Set-Cookie", ["type=ninja", "language=javascript"]); + response.setHeader('Set-Cookie', ['type=ninja', 'language=javascript']); Attempting to set a header field name that contains invalid characters will -result in a `TypeError` being thrown. +result in a [`TypeError`][] being thrown. ### response.setTimeout(msecs, callback) @@ -696,7 +700,7 @@ Returns `response`. ### response.statusCode -When using implicit headers (not calling [response.writeHead()][] explicitly), +When using implicit headers (not calling [`response.writeHead()`][] explicitly), this property controls the status code that will be sent to the client when the headers get flushed. @@ -709,7 +713,7 @@ status code which was sent out. ### response.statusMessage -When using implicit headers (not calling `response.writeHead()` explicitly), this property +When using implicit headers (not calling [`response.writeHead()`][] explicitly), this property controls the status message that will be sent to the client when the headers get flushed. If this is left as `undefined` then the standard message for the status code will be used. @@ -723,7 +727,7 @@ status message which was sent out. ### response.write(chunk[, encoding][, callback]) -If this method is called and [response.writeHead()][] has not been called, +If this method is called and [`response.writeHead()`][] has not been called, it will switch to implicit header mode and flush the implicit headers. This sends a chunk of the response body. This method may @@ -737,9 +741,9 @@ will be called when this chunk of data is flushed. **Note**: This is the raw HTTP body and has nothing to do with higher-level multi-part body encodings that may be used. -The first time `response.write()` is called, it will send the buffered +The first time [`response.write()`][] is called, it will send the buffered header information and the first body to the client. The second time -`response.write()` is called, Node.js assumes you're going to be streaming +[`response.write()`][] is called, Node.js assumes you're going to be streaming data, and sends that separately. That is, the response is buffered up to the first chunk of body. @@ -750,7 +754,7 @@ buffer. Returns `false` if all or part of the data was queued in user memory. ### response.writeContinue() Sends a HTTP/1.1 100 Continue message to the client, indicating that -the request body should be sent. See the ['checkContinue'][] event on `Server`. +the request body should be sent. See the [`'checkContinue'`][] event on `Server`. ### response.writeHead(statusCode[, statusMessage][, headers]) @@ -767,9 +771,9 @@ Example: 'Content-Type': 'text/plain' }); This method must only be called once on a message and it must -be called before [response.end()][] is called. +be called before [`response.end()`][] is called. -If you call [response.write()][] or [response.end()][] before calling this, the +If you call [`response.write()`][] or [`response.end()`][] before calling this, the implicit/mutable headers will be calculated and call this function for you. Note that Content-Length is given in bytes not characters. The above example @@ -779,10 +783,10 @@ should be used to determine the number of bytes in a given encoding. And Node.js does not check whether Content-Length and the length of the body which has been transmitted are equal or not. -## http.IncomingMessage +## Class: http.IncomingMessage -An `IncomingMessage` object is created by [http.Server][] or -[http.ClientRequest][] and passed as the first argument to the `'request'` +An `IncomingMessage` object is created by [`http.Server`][] or +[`http.ClientRequest`][] and passed as the first argument to the `'request'` and `'response'` event respectively. It may be used to access response status, headers and data. @@ -831,7 +835,7 @@ Also `response.httpVersionMajor` is the first integer and ### message.method -**Only valid for request obtained from [http.Server][].** +**Only valid for request obtained from [`http.Server`][].** The request method as a string. Read only. Example: `'GET'`, `'DELETE'`. @@ -861,7 +865,7 @@ Header names are not lowercased, and duplicates are not merged. ### message.rawTrailers The raw request/response trailer keys and values exactly as they were -received. Only populated at the 'end' event. +received. Only populated at the `'end'` event. ### message.setTimeout(msecs, callback) @@ -874,30 +878,30 @@ Returns `message`. ### message.statusCode -**Only valid for response obtained from `http.ClientRequest`.** +**Only valid for response obtained from [`http.ClientRequest`][].** The 3-digit HTTP response status code. E.G. `404`. ### message.statusMessage -**Only valid for response obtained from `http.ClientRequest`.** +**Only valid for response obtained from [`http.ClientRequest`][].** ### message.socket -The `net.Socket` object associated with the connection. +The [`net.Socket`][] object associated with the connection. -With HTTPS support, use [request.socket.getPeerCertificate()][] to obtain the +With HTTPS support, use [`request.socket.getPeerCertificate()`][] to obtain the client's authentication details. The HTTP response status message (reason phrase). E.G. `OK` or `Internal Server Error`. ### message.trailers -The request/response trailers object. Only populated at the 'end' event. +The request/response trailers object. Only populated at the `'end'` event. ### message.url -**Only valid for request obtained from [http.Server][].** +**Only valid for request obtained from [`http.Server`][].** Request URL string. This contains only the URL that is present in the actual HTTP request. If the request is: @@ -945,14 +949,14 @@ Found'`. ## http.createClient([port][, host]) - Stability: 0 - Deprecated: Use [http.request][] instead. + Stability: 0 - Deprecated: Use [`http.request()`][] instead. Constructs a new HTTP client. `port` and `host` refer to the server to be connected to. ## http.createServer([requestListener]) -Returns a new instance of [http.Server][]. +Returns a new instance of [`http.Server`][]. The `requestListener` is a function which is automatically added to the `'request'` event. @@ -960,15 +964,17 @@ added to the `'request'` event. ## http.get(options[, callback]) Since most requests are GET requests without bodies, Node.js provides this -convenience method. The only difference between this method and `http.request()` +convenience method. The only difference between this method and [`http.request()`][] is that it sets the method to GET and calls `req.end()` automatically. Example: - http.get("http://www.google.com/index.html", function(res) { - console.log("Got response: " + res.statusCode); - }).on('error', function(e) { - console.log("Got error: " + e.message); + http.get('http://www.google.com/index.html', (res) => { + console.log(`Got response: ${res.statusCode}`); + // consume response body + res.resume(); + }).on('error', (e) => { + console.log(`Got error: ${e.message}`); }); ## http.globalAgent @@ -982,14 +988,14 @@ Node.js maintains several connections per server to make HTTP requests. This function allows one to transparently issue requests. `options` can be an object or a string. If `options` is a string, it is -automatically parsed with [url.parse()][]. +automatically parsed with [`url.parse()`][]. Options: -- `protocol`: Protocol to use. Defaults to `'http'`. +- `protocol`: Protocol to use. Defaults to `'http:'`. - `host`: A domain name or IP address of the server to issue the request to. Defaults to `'localhost'`. -- `hostname`: Alias for `host`. To support `url.parse()` `hostname` is +- `hostname`: Alias for `host`. To support [`url.parse()`][] `hostname` is preferred over `host`. - `family`: IP address family to use when resolving `host` and `hostname`. Valid values are `4` or `6`. When unspecified, both IP v4 and v6 will be @@ -1005,17 +1011,17 @@ Options: - `headers`: An object containing request headers. - `auth`: Basic authentication i.e. `'user:password'` to compute an Authorization header. -- `agent`: Controls [Agent][] behavior. When an Agent is used request will +- `agent`: Controls [`Agent`][] behavior. When an Agent is used request will default to `Connection: keep-alive`. Possible values: - - `undefined` (default): use [globalAgent][] for this host and port. + - `undefined` (default): use [`http.globalAgent`][] for this host and port. - `Agent` object: explicitly use the passed in `Agent`. - `false`: opts out of connection pooling with an Agent, defaults request to `Connection: close`. The optional `callback` parameter will be added as a one time listener for -the ['response'][] event. +the `'response'` event. -`http.request()` returns an instance of the [http.ClientRequest][] +`http.request()` returns an instance of the [`http.ClientRequest`][] class. The `ClientRequest` instance is a writable stream. If one needs to upload a file with a POST request, then write to the `ClientRequest` object. @@ -1036,20 +1042,20 @@ Example: } }; - var req = http.request(options, function(res) { - console.log('STATUS: ' + res.statusCode); - console.log('HEADERS: ' + JSON.stringify(res.headers)); + var req = http.request(options, (res) => { + console.log(`STATUS: ${res.statusCode}`); + console.log(`HEADERS: ${JSON.stringify(res.headers)}`); res.setEncoding('utf8'); - res.on('data', function (chunk) { - console.log('BODY: ' + chunk); + res.on('data', (chunk) => { + console.log(`BODY: ${chunk}`); }); - res.on('end', function() { + res.on('end', () => { console.log('No more data in response.') }) }); - req.on('error', function(e) { - console.log('problem with request: ' + e.message); + req.on('error', (e) => { + console.log(`problem with request: ${e.message}`); }); // write data to request body @@ -1062,7 +1068,8 @@ even if there is no data being written to the request body. If any error is encountered during the request (be that with DNS resolution, TCP level errors, or actual HTTP parse errors) an `'error'` event is emitted -on the returned request object. +on the returned request object. As with all `'error'` events, if no listeners +are registered the error will be thrown. There are a few special headers that should be noted. @@ -1073,41 +1080,44 @@ There are a few special headers that should be noted. * Sending an 'Expect' header will immediately send the request headers. Usually, when sending 'Expect: 100-continue', you should both set a timeout - and listen for the `continue` event. See RFC2616 Section 8.2.3 for more + and listen for the `'continue'` event. See RFC2616 Section 8.2.3 for more information. * Sending an Authorization header will override using the `auth` option to compute basic authentication. -[message.headers][]: #http_message_headers -[constructor options]: #http_new_agent_options +[`'checkContinue'`]: #http_event_checkcontinue +[`'listening'`]: net.html#net_event_listening +[`'response'`]: #http_event_response +[`Agent`]: #http_class_http_agent +[`Buffer`]: buffer.html#buffer_buffer [`destroy()`]: #http_agent_destroy -['checkContinue']: #http_event_checkcontinue -['listening']: net.html#net_event_listening -['response']: #http_event_response -[Agent]: #http_class_http_agent -[Buffer]: buffer.html#buffer_buffer -[EventEmitter]: events.html#events_class_events_eventemitter +[`EventEmitter`]: events.html#events_class_events_eventemitter +[`http.Agent`]: #http_class_http_agent +[`http.ClientRequest`]: #http_class_http_clientrequest +[`http.globalAgent`]: #http_http_globalagent +[`http.IncomingMessage`]: #http_http_incomingmessage +[`http.request()`]: #http_http_request_options_callback +[`http.Server`]: #http_class_http_server +[`http.ServerResponse`]: #http_class_http_serverresponse +[`message.headers`]: #http_message_headers +[`net.Server.close()`]: net.html#net_server_close_callback +[`net.Server.listen()`]: net.html#net_server_listen_handle_callback +[`net.Server.listen(path)`]: net.html#net_server_listen_path_callback +[`net.Server.listen(port)`]: net.html#net_server_listen_port_hostname_backlog_callback +[`net.Socket`]: net.html#net_class_net_socket +[`request.socket.getPeerCertificate()`]: tls.html#tls_tlssocket_getpeercertificate_detailed +[`response.end()`]: #http_response_end_data_encoding_callback +[`response.write()`]: #http_response_write_chunk_encoding_callback +[`response.write(data, encoding)`]: #http_response_write_chunk_encoding_callback +[`response.writeContinue()`]: #http_response_writecontinue +[`response.writeHead()`]: #http_response_writehead_statuscode_statusmessage_headers +[`socket.setKeepAlive()`]: net.html#net_socket_setkeepalive_enable_initialdelay +[`socket.setNoDelay()`]: net.html#net_socket_setnodelay_nodelay +[`socket.setTimeout()`]: net.html#net_socket_settimeout_timeout_callback +[`stream.setEncoding()`]: stream.html#stream_stream_setencoding_encoding +[`TypeError`]: errors.html#errors_class_typeerror +[`url.parse()`]: url.html#url_url_parse_urlstr_parsequerystring_slashesdenotehost +[constructor options]: #http_new_agent_options [Readable Stream]: stream.html#stream_class_stream_readable [Writable Stream]: stream.html#stream_class_stream_writable -[globalAgent]: #http_http_globalagent -[http.ClientRequest]: #http_class_http_clientrequest -[http.IncomingMessage]: #http_http_incomingmessage -[http.ServerResponse]: #http_class_http_serverresponse -[http.Server]: #http_class_http_server -[http.request]: #http_http_request_options_callback -[net.Server.close()]: net.html#net_server_close_callback -['listening']: net.html#net_event_listening -[net.Server.listen(path)]: net.html#net_server_listen_path_callback -[net.Server.listen(port)]: net.html#net_server_listen_port_hostname_backlog_callback -[net.Server.listen()]: net.html#net_server_listen_handle_callback -[response.end()]: #http_response_end_data_encoding_callback -[response.write()]: #http_response_write_chunk_encoding_callback -[response.writeContinue()]: #http_response_writecontinue -[response.writeHead()]: #http_response_writehead_statuscode_statusmessage_headers -[socket.setKeepAlive()]: net.html#net_socket_setkeepalive_enable_initialdelay -[socket.setNoDelay()]: net.html#net_socket_setnodelay_nodelay -[socket.setTimeout()]: net.html#net_socket_settimeout_timeout_callback -[request.socket.getPeerCertificate()]: tls.html#tls_tlssocket_getpeercertificate_detailed -[stream.setEncoding()]: stream.html#stream_stream_setencoding_encoding -[url.parse()]: url.html#url_url_parse_urlstr_parsequerystring_slashesdenotehost diff --git a/doc/api/https.markdown b/doc/api/https.markdown index 8a916311fc664f..93416633747fb4 100644 --- a/doc/api/https.markdown +++ b/doc/api/https.markdown @@ -7,107 +7,107 @@ separate module. ## Class: https.Agent -An Agent object for HTTPS similar to [http.Agent][]. See [https.request()][] +An Agent object for HTTPS similar to [`http.Agent`][]. See [`https.request()`][] for more information. ## Class: https.Server This class is a subclass of `tls.Server` and emits events same as -`http.Server`. See `http.Server` for more information. +[`http.Server`][]. See [`http.Server`][] for more information. ### server.setTimeout(msecs, callback) -See [http.Server#setTimeout()][]. +See [`http.Server#setTimeout()`][]. ### server.timeout -See [http.Server#timeout][]. +See [`http.Server#timeout`][]. ## https.createServer(options[, requestListener]) Returns a new HTTPS web server object. The `options` is similar to -[tls.createServer()][]. The `requestListener` is a function which is +[`tls.createServer()`][]. The `requestListener` is a function which is automatically added to the `'request'` event. Example: // curl -k https://localhost:8000/ - var https = require('https'); - var fs = require('fs'); + const https = require('https'); + const fs = require('fs'); - var options = { + const options = { key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'), cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem') }; - https.createServer(options, function (req, res) { + https.createServer(options, (req, res) => { res.writeHead(200); - res.end("hello world\n"); + res.end('hello world\n'); }).listen(8000); Or - var https = require('https'); - var fs = require('fs'); + const https = require('https'); + const fs = require('fs'); - var options = { + const options = { pfx: fs.readFileSync('server.pfx') }; - https.createServer(options, function (req, res) { + https.createServer(options, (req, res) => { res.writeHead(200); - res.end("hello world\n"); + res.end('hello world\n'); }).listen(8000); ### server.close([callback]) -See [http.close()][] for details. +See [`http.close()`][] for details. ### server.listen(handle[, callback]) ### server.listen(path[, callback]) ### server.listen(port[, host][, backlog][, callback]) -See [http.listen()][] for details. +See [`http.listen()`][] for details. ## https.get(options, callback) -Like `http.get()` but for HTTPS. +Like [`http.get()`][] but for HTTPS. `options` can be an object or a string. If `options` is a string, it is -automatically parsed with [url.parse()][]. +automatically parsed with [`url.parse()`][]. Example: - var https = require('https'); + const https = require('https'); - https.get('https://encrypted.google.com/', function(res) { - console.log("statusCode: ", res.statusCode); - console.log("headers: ", res.headers); + https.get('https://encrypted.google.com/', (res) => { + console.log('statusCode: ', res.statusCode); + console.log('headers: ', res.headers); - res.on('data', function(d) { + res.on('data', (d) => { process.stdout.write(d); }); - }).on('error', function(e) { + }).on('error', (e) => { console.error(e); }); ## https.globalAgent -Global instance of [https.Agent][] for all HTTPS client requests. +Global instance of [`https.Agent`][] for all HTTPS client requests. ## https.request(options, callback) Makes a request to a secure web server. `options` can be an object or a string. If `options` is a string, it is -automatically parsed with [url.parse()][]. +automatically parsed with [`url.parse()`][]. -All options from [http.request()][] are valid. +All options from [`http.request()`][] are valid. Example: - var https = require('https'); + const https = require('https'); var options = { hostname: 'encrypted.google.com', @@ -116,17 +116,17 @@ Example: method: 'GET' }; - var req = https.request(options, function(res) { - console.log("statusCode: ", res.statusCode); - console.log("headers: ", res.headers); + var req = https.request(options, (res) => { + console.log('statusCode: ', res.statusCode); + console.log('headers: ', res.headers); - res.on('data', function(d) { + res.on('data', (d) => { process.stdout.write(d); }); }); req.end(); - req.on('error', function(e) { + req.on('error', (e) => { console.error(e); }); @@ -150,24 +150,25 @@ The options argument has the following options - `headers`: An object containing request headers. - `auth`: Basic authentication i.e. `'user:password'` to compute an Authorization header. -- `agent`: Controls [Agent][] behavior. When an Agent is used request will +- `agent`: Controls [`Agent`][] behavior. When an Agent is used request will default to `Connection: keep-alive`. Possible values: - - `undefined` (default): use [globalAgent][] for this host and port. + - `undefined` (default): use [`globalAgent`][] for this host and port. - `Agent` object: explicitly use the passed in `Agent`. - `false`: opts out of connection pooling with an Agent, defaults request to `Connection: close`. -The following options from [tls.connect()][] can also be specified. However, a -[globalAgent][] silently ignores these. +The following options from [`tls.connect()`][] can also be specified. However, a +[`globalAgent`][] silently ignores these. - `pfx`: Certificate, Private key and CA certificates to use for SSL. Default `null`. - `key`: Private key to use for SSL. Default `null`. - `passphrase`: A string of passphrase for the private key or pfx. Default `null`. - `cert`: Public x509 certificate to use. Default `null`. -- `ca`: An authority certificate or array of authority certificates to check - the remote host against. +- `ca`: A string, `Buffer` or array of strings or `Buffer`s of trusted + certificates in PEM format. If this is omitted several well known "root" + CAs will be used, like VeriSign. These are used to authorize connections. - `ciphers`: A string describing the ciphers to use or exclude. Consult - for + for details on the format. - `rejectUnauthorized`: If `true`, the server certificate is verified against the list of supplied CAs. An `'error'` event is emitted if verification @@ -175,9 +176,9 @@ The following options from [tls.connect()][] can also be specified. However, a request is sent. Default `true`. - `secureProtocol`: The SSL method to use, e.g. `SSLv3_method` to force SSL version 3. The possible values depend on your installation of - OpenSSL and are defined in the constant [SSL_METHODS][]. + OpenSSL and are defined in the constant [`SSL_METHODS`][]. -In order to specify these options, use a custom `Agent`. +In order to specify these options, use a custom [`Agent`][]. Example: @@ -191,7 +192,7 @@ Example: }; options.agent = new https.Agent(options); - var req = https.request(options, function(res) { + var req = https.request(options, (res) => { ... } @@ -209,21 +210,23 @@ Example: agent: false }; - var req = https.request(options, function(res) { + var req = https.request(options, (res) => { ... } -[http.Server#setTimeout()]: http.html#http_server_settimeout_msecs_callback -[http.Server#timeout]: http.html#http_server_timeout -[Agent]: #https_class_https_agent -[globalAgent]: #https_https_globalagent -[http.listen()]: http.html#http_server_listen_port_hostname_backlog_callback -[url.parse()]: url.html#url_url_parse_urlstr_parsequerystring_slashesdenotehost -[http.close()]: http.html#http_server_close_callback -[http.Agent]: http.html#http_class_http_agent -[http.request()]: http.html#http_http_request_options_callback -[https.Agent]: #https_class_https_agent -[https.request()]: #https_https_request_options_callback -[tls.connect()]: tls.html#tls_tls_connect_options_callback -[tls.createServer()]: tls.html#tls_tls_createserver_options_secureconnectionlistener -[SSL_METHODS]: http://www.openssl.org/docs/ssl/ssl.html#DEALING_WITH_PROTOCOL_METHODS +[`Agent`]: #https_class_https_agent +[`globalAgent`]: #https_https_globalagent +[`http.Agent`]: http.html#http_class_http_agent +[`http.close()`]: http.html#http_server_close_callback +[`http.get()`]: http.html#http_http_get_options_callback +[`http.listen()`]: http.html#http_server_listen_port_hostname_backlog_callback +[`http.request()`]: http.html#http_http_request_options_callback +[`http.Server#setTimeout()`]: http.html#http_server_settimeout_msecs_callback +[`http.Server#timeout`]: http.html#http_server_timeout +[`http.Server`]: http.html#http_class_http_server +[`https.Agent`]: #https_class_https_agent +[`https.request()`]: #https_https_request_options_callback +[`SSL_METHODS`]: https://www.openssl.org/docs/ssl/ssl.html#DEALING_WITH_PROTOCOL_METHODS +[`tls.connect()`]: tls.html#tls_tls_connect_options_callback +[`tls.createServer()`]: tls.html#tls_tls_createserver_options_secureconnectionlistener +[`url.parse()`]: url.html#url_url_parse_urlstr_parsequerystring_slashesdenotehost diff --git a/doc/api/modules.markdown b/doc/api/modules.markdown index ceab37d536ca3a..aa1f0b074e5043 100644 --- a/doc/api/modules.markdown +++ b/doc/api/modules.markdown @@ -10,13 +10,12 @@ in one-to-one correspondence. As an example, `foo.js` loads the module The contents of `foo.js`: - var circle = require('./circle.js'); - console.log( 'The area of a circle of radius 4 is ' - + circle.area(4)); + const circle = require('./circle.js'); + console.log( `The area of a circle of radius 4 is ${circle.area(4)}`); The contents of `circle.js`: - var PI = Math.PI; + const PI = Math.PI; exports.area = function (r) { return PI * r * r; @@ -40,9 +39,9 @@ instead of `exports`. Below, `bar.js` makes use of the `square` module, which exports a constructor: - var square = require('./square.js'); + const square = require('./square.js'); var mySquare = square(2); - console.log('The area of my square is ' + mySquare.area()); + console.log(`The area of my square is ${mySquare.area()}`); The `square` module is defined in `square.js`: @@ -233,7 +232,7 @@ Consider this situation: console.log('a starting'); exports.done = false; - var b = require('./b.js'); + const b = require('./b.js'); console.log('in a, b.done = %j', b.done); exports.done = true; console.log('a done'); @@ -242,7 +241,7 @@ Consider this situation: console.log('b starting'); exports.done = false; - var a = require('./a.js'); + const a = require('./a.js'); console.log('in b, a.done = %j', a.done); exports.done = true; console.log('b done'); @@ -250,8 +249,8 @@ Consider this situation: `main.js`: console.log('main starting'); - var a = require('./a.js'); - var b = require('./b.js'); + const a = require('./a.js'); + const b = require('./b.js'); console.log('in main, a.done=%j, b.done=%j', a.done, b.done); When `main.js` loads `a.js`, then `a.js` in turn loads `b.js`. At that @@ -299,7 +298,7 @@ A required module prefixed with `'./'` is relative to the file calling Without a leading '/', './', or '../' to indicate a file, the module must either be a core module or is loaded from a `node_modules` folder. -If the given path does not exist, `require()` will throw an Error with its +If the given path does not exist, `require()` will throw an [`Error`][] with its `code` property set to `'MODULE_NOT_FOUND'`. ## Folders as Modules @@ -425,20 +424,20 @@ which is probably not what you want to do. For example suppose we were making a module called `a.js` - var EventEmitter = require('events'); + const EventEmitter = require('events'); module.exports = new EventEmitter(); // Do some work, and after some time emit // the 'ready' event from the module itself. - setTimeout(function() { + setTimeout(() => { module.exports.emit('ready'); }, 1000); Then in another file we could do - var a = require('./a'); - a.on('ready', function() { + const a = require('./a'); + a.on('ready', () => { console.log('module a is ready'); }); @@ -448,13 +447,13 @@ done in any callbacks. This does not work: x.js: - setTimeout(function() { - module.exports = { a: "hello" }; + setTimeout(() => { + module.exports = { a: 'hello' }; }, 0); y.js: - var x = require('./x'); + const x = require('./x'); console.log(x.a); #### exports alias @@ -519,4 +518,5 @@ object. Since `require()` returns the `module.exports`, and the `module` is typically *only* available within a specific module's code, it must be explicitly exported in order to be used. -[module resolution]: https://nodejs.org/api/modules.html#modules_all_together +[`Error`]: errors.html#errors_class_error +[module resolution]: #modules_all_together diff --git a/doc/api/net.markdown b/doc/api/net.markdown index 0a44c6535b3dec..7e898596f5a18e 100644 --- a/doc/api/net.markdown +++ b/doc/api/net.markdown @@ -10,7 +10,7 @@ this module with `require('net');`. This class is used to create a TCP or local server. -`net.Server` is an [EventEmitter][] with the following events: +`net.Server` is an [`EventEmitter`][] with the following events: ### Event: 'close' @@ -28,7 +28,7 @@ Emitted when a new connection is made. `socket` is an instance of * {Error Object} -Emitted when an error occurs. The ['close'][] event will be called directly +Emitted when an error occurs. The [`'close'`][] event will be called directly following this event. See example in discussion of `server.listen`. ### Event: 'listening' @@ -45,14 +45,14 @@ Returns an object with three properties, e.g. Example: - var server = net.createServer(function (socket) { - socket.end("goodbye\n"); + var server = net.createServer((socket) => { + socket.end('goodbye\n'); }); // grab a random port. - server.listen(function() { + server.listen(() => { address = server.address(); - console.log("opened server on %j", address); + console.log('opened server on %j', address); }); Don't call `server.address()` until the `'listening'` event has been emitted. @@ -61,19 +61,19 @@ Don't call `server.address()` until the `'listening'` event has been emitted. Stops the server from accepting new connections and keeps existing connections. This function is asynchronous, the server is finally -closed when all connections are ended and the server emits a ['close'][] event. +closed when all connections are ended and the server emits a [`'close'`][] event. The optional `callback` will be called once the `'close'` event occurs. Unlike that event, it will be called with an Error as its only argument if the server was not open when it was closed. ### server.connections - Stability: 0 - Deprecated: Use [server.getConnections][] instead. + Stability: 0 - Deprecated: Use [`server.getConnections`][] instead. The number of concurrent connections on the server. This becomes `null` when sending a socket to a child with -`child_process.fork()`. To poll forks and get current number of active +[`child_process.fork()`][]. To poll forks and get current number of active connections use asynchronous `server.getConnections` instead. ### server.getConnections(callback) @@ -83,9 +83,10 @@ when sockets were sent to forks. Callback should take two arguments `err` and `count`. -### server.listen(handle[, callback]) +### server.listen(handle[, backlog][, callback]) * `handle` {Object} +* `backlog` {Number} * `callback` {Function} The `handle` object can be set to either a server or socket (anything @@ -98,9 +99,12 @@ already been bound to a port or domain socket. Listening on a file descriptor is not supported on Windows. This function is asynchronous. When the server has been bound, -['listening'][] event will be emitted. +[`'listening'`][] event will be emitted. The last parameter `callback` will be added as a listener for the -['listening'][] event. +[`'listening'`][] event. + +The parameter `backlog` behaves the same as in +[`server.listen(port, \[host\], \[backlog\], \[callback\])`][]. ### server.listen(options[, callback]) @@ -114,9 +118,8 @@ The last parameter `callback` will be added as a listener for the The `port`, `host`, and `backlog` properties of `options`, as well as the optional callback function, behave as they do on a call to -[server.listen(port, \[host\], \[backlog\], \[callback\]) -](#net_server_listen_port_hostname_backlog_callback). Alternatively, the `path` -option can be used to specify a UNIX socket. +[`server.listen(port, \[host\], \[backlog\], \[callback\])`][]. Alternatively, +the `path` option can be used to specify a UNIX socket. If `exclusive` is `false` (default), then cluster workers will use the same underlying handle, allowing connection handling duties to be shared. When @@ -130,16 +133,17 @@ shown below. exclusive: true }); -### server.listen(path[, callback]) +### server.listen(path[, backlog][, callback]) * `path` {String} +* `backlog` {Number} * `callback` {Function} Start a local socket server listening for connections on the given `path`. This function is asynchronous. When the server has been bound, -['listening'][] event will be emitted. The last parameter `callback` -will be added as a listener for the ['listening'][] event. +[`'listening'`][] event will be emitted. The last parameter `callback` +will be added as a listener for the [`'listening'`][] event. On UNIX, the local domain is usually known as the UNIX domain. The path is a filesystem path name. It is subject to the same naming conventions and @@ -157,6 +161,9 @@ double-backslashes, such as: net.createServer().listen( path.join('\\\\?\\pipe', process.cwd(), 'myctl')) +The parameter `backlog` behaves the same as in +[`server.listen(port, \[host\], \[backlog\], \[callback\])`][]. + ### server.listen(port[, hostname][, backlog][, callback]) Begin accepting connections on the specified `port` and `hostname`. If the @@ -170,17 +177,17 @@ The actual length will be determined by your OS through sysctl settings such as parameter is 511 (not 512). This function is asynchronous. When the server has been bound, -['listening'][] event will be emitted. The last parameter `callback` -will be added as a listener for the ['listening'][] event. +[`'listening'`][] event will be emitted. The last parameter `callback` +will be added as a listener for the [`'listening'`][] event. One issue some users run into is getting `EADDRINUSE` errors. This means that another server is already running on the requested port. One way of handling this would be to wait a second and then try again. This can be done with - server.on('error', function (e) { + server.on('error', (e) => { if (e.code == 'EADDRINUSE') { console.log('Address in use, retrying...'); - setTimeout(function () { + setTimeout(() => { server.close(); server.listen(PORT, HOST); }, 1000); @@ -195,7 +202,7 @@ Set this property to reject connections when the server's connection count gets high. It is not recommended to use this option once a socket has been sent to a child -with `child_process.fork()`. +with [`child_process.fork()`][]. ### server.ref() @@ -217,7 +224,7 @@ Returns `server`. This object is an abstraction of a TCP or local socket. `net.Socket` instances implement a duplex Stream interface. They can be created by the -user and used as a client (with `connect()`) or they can be created by Node.js +user and used as a client (with [`connect()`][]) or they can be created by Node.js and passed to the user through the `'connection'` event of a server. ### new net.Socket([options]) @@ -237,7 +244,7 @@ Set `readable` and/or `writable` to `true` to allow reads and/or writes on this socket (NOTE: Works only when `fd` is passed). About `allowHalfOpen`, refer to `createServer()` and `'end'` event. -`net.Socket` instances are [EventEmitter][] with the following events: +`net.Socket` instances are [`EventEmitter`][] with the following events: ### Event: 'close' @@ -249,7 +256,7 @@ which says if the socket was closed due to a transmission error. ### Event: 'connect' Emitted when a socket connection is successfully established. -See `connect()`. +See [`connect()`][]. ### Event: 'data' @@ -290,16 +297,16 @@ following this event. Emitted after resolving the hostname but before connecting. Not applicable to UNIX sockets. -* `err` {Error | Null} The error object. See [dns.lookup()][]. +* `err` {Error | Null} The error object. See [`dns.lookup()`][]. * `address` {String} The IP address. -* `family` {String | Null} The address type. See [dns.lookup()][]. +* `family` {String | Null} The address type. See [`dns.lookup()`][]. ### Event: 'timeout' Emitted if the socket times out from inactivity. This is only to notify that the socket has been idle. The user must manually close the connection. -See also: `socket.setTimeout()` +See also: [`socket.setTimeout()`][] ### socket.address() @@ -324,7 +331,7 @@ written, but the buffer may contain strings, and the strings are lazily encoded, so the exact number of bytes is not known.) Users who experience large or growing `bufferSize` should attempt to -"throttle" the data flows in their program with `pause()` and `resume()`. +"throttle" the data flows in their program with [`pause()`][] and [`resume()`][]. ### socket.bytesRead @@ -360,17 +367,17 @@ specifies: Normally this method is not needed, as `net.createConnection` opens the socket. Use this only if you are implementing a custom Socket. -This function is asynchronous. When the ['connect'][] event is emitted the +This function is asynchronous. When the [`'connect'`][] event is emitted the socket is established. If there is a problem connecting, the `'connect'` event -will not be emitted, the `'error'` event will be emitted with the exception. +will not be emitted, the [`'error'`][] event will be emitted with the exception. The `connectListener` parameter will be added as a listener for the -['connect'][] event. +[`'connect'`][] event. ### socket.connect(path[, connectListener]) ### socket.connect(port[, host][, connectListener]) -As [socket.connect(options[, connectListener])](#net_socket_connect_options_connectlistener), +As [`socket.connect(options\[, connectListener\])`][], with options either as either `{port: port, host: host}` or `{path: path}`. ### socket.destroy() @@ -399,7 +406,7 @@ The numeric representation of the local port. For example, ### socket.pause() -Pauses the reading of data. That is, `'data'` events will not be emitted. +Pauses the reading of data. That is, [`'data'`][] events will not be emitted. Useful to throttle back an upload. ### socket.ref() @@ -413,7 +420,8 @@ Returns `socket`. ### socket.remoteAddress The string representation of the remote IP address. For example, -`'74.125.127.100'` or `'2001:4860:a005::68'`. +`'74.125.127.100'` or `'2001:4860:a005::68'`. Value may be `undefined` if +the socket is destroyed (for example, if the client disconnected). ### socket.remoteFamily @@ -426,12 +434,12 @@ The numeric representation of the remote port. For example, ### socket.resume() -Resumes reading after a call to `pause()`. +Resumes reading after a call to [`pause()`][]. ### socket.setEncoding([encoding]) -Set the encoding for the socket as a Readable Stream. See -[stream.setEncoding()][] for more information. +Set the encoding for the socket as a [Readable Stream][]. See +[`stream.setEncoding()`][] for more information. ### socket.setKeepAlive([enable][, initialDelay]) @@ -460,14 +468,14 @@ Returns `socket`. Sets the socket to timeout after `timeout` milliseconds of inactivity on the socket. By default `net.Socket` do not have a timeout. -When an idle timeout is triggered the socket will receive a `'timeout'` -event but the connection will not be severed. The user must manually `end()` -or `destroy()` the socket. +When an idle timeout is triggered the socket will receive a [`'timeout'`][] +event but the connection will not be severed. The user must manually [`end()`][] +or [`destroy()`][] the socket. If `timeout` is 0, then the existing idle timeout is disabled. The optional `callback` parameter will be added as a one time listener for the -`'timeout'` event. +[`'timeout'`][] event. Returns `socket`. @@ -486,115 +494,114 @@ case of a string--it defaults to UTF8 encoding. Returns `true` if the entire data was flushed successfully to the kernel buffer. Returns `false` if all or part of the data was queued in user memory. -`'drain'` will be emitted when the buffer is again free. +[`'drain'`][] will be emitted when the buffer is again free. The optional `callback` parameter will be executed when the data is finally written out - this may not be immediately. ## net.connect(options[, connectListener]) -A factory function, which returns a new ['net.Socket'][] and automatically +A factory function, which returns a new [`net.Socket`][] and automatically connects with the supplied `options`. -The options are passed to both the ['net.Socket'][] constructor and the -['socket.connect'][] method. +The options are passed to both the [`net.Socket`][] constructor and the +[`socket.connect`][] method. The `connectListener` parameter will be added as a listener for the -['connect'][] event once. +[`'connect'`][] event once. Here is an example of a client of the previously described echo server: - var net = require('net'); - var client = net.connect({port: 8124}, - function() { //'connect' listener + const net = require('net'); + const client = net.connect({port: 8124}, () => { //'connect' listener console.log('connected to server!'); client.write('world!\r\n'); }); - client.on('data', function(data) { + client.on('data', (data) => { console.log(data.toString()); client.end(); }); - client.on('end', function() { + client.on('end', () => { console.log('disconnected from server'); }); To connect on the socket `/tmp/echo.sock` the second line would just be changed to - var client = net.connect({path: '/tmp/echo.sock'}); + const client = net.connect({path: '/tmp/echo.sock'}); ## net.connect(path[, connectListener]) -A factory function, which returns a new unix ['net.Socket'][] and automatically +A factory function, which returns a new unix [`net.Socket`][] and automatically connects to the supplied `path`. The `connectListener` parameter will be added as a listener for the -['connect'][] event once. +[`'connect'`][] event once. ## net.connect(port[, host][, connectListener]) -A factory function, which returns a new ['net.Socket'][] and automatically +A factory function, which returns a new [`net.Socket`][] and automatically connects to the supplied `port` and `host`. If `host` is omitted, `'localhost'` will be assumed. The `connectListener` parameter will be added as a listener for the -['connect'][] event once. +[`'connect'`][] event once. ## net.createConnection(options[, connectListener]) -A factory function, which returns a new ['net.Socket'][] and automatically +A factory function, which returns a new [`net.Socket`][] and automatically connects with the supplied `options`. -The options are passed to both the ['net.Socket'][] constructor and the -['socket.connect'][] method. +The options are passed to both the [`net.Socket`][] constructor and the +[`socket.connect`][] method. The `connectListener` parameter will be added as a listener for the -['connect'][] event once. +[`'connect'`][] event once. Here is an example of a client of the previously described echo server: - var net = require('net'); - var client = net.connect({port: 8124}, - function() { //'connect' listener + const net = require('net'); + const client = net.connect({port: 8124}, + () => { //'connect' listener console.log('connected to server!'); client.write('world!\r\n'); }); - client.on('data', function(data) { + client.on('data', (data) => { console.log(data.toString()); client.end(); }); - client.on('end', function() { + client.on('end', () => { console.log('disconnected from server'); }); To connect on the socket `/tmp/echo.sock` the second line would just be changed to - var client = net.connect({path: '/tmp/echo.sock'}); + const client = net.connect({path: '/tmp/echo.sock'}); ## net.createConnection(path[, connectListener]) -A factory function, which returns a new unix ['net.Socket'][] and automatically +A factory function, which returns a new unix [`net.Socket`][] and automatically connects to the supplied `path`. The `connectListener` parameter will be added as a listener for the -['connect'][] event once. +[`'connect'`][] event once. ## net.createConnection(port[, host][, connectListener]) -A factory function, which returns a new ['net.Socket'][] and automatically +A factory function, which returns a new [`net.Socket`][] and automatically connects to the supplied `port` and `host`. If `host` is omitted, `'localhost'` will be assumed. The `connectListener` parameter will be added as a listener for the -['connect'][] event once. +[`'connect'`][] event once. ## net.createServer([options][, connectionListener]) Creates a new server. The `connectionListener` argument is -automatically set as a listener for the ['connection'][] event. +automatically set as a listener for the [`'connection'`][] event. `options` is an object with the following defaults: @@ -605,27 +612,27 @@ automatically set as a listener for the ['connection'][] event. If `allowHalfOpen` is `true`, then the socket won't automatically send a FIN packet when the other end of the socket sends a FIN packet. The socket becomes -non-readable, but still writable. You should call the `end()` method explicitly. -See ['end'][] event for more information. +non-readable, but still writable. You should call the [`end()`][] method explicitly. +See [`'end'`][] event for more information. If `pauseOnConnect` is `true`, then the socket associated with each incoming connection will be paused, and no data will be read from its handle. This allows connections to be passed between processes without any data being read by the -original process. To begin reading data from a paused socket, call `resume()`. +original process. To begin reading data from a paused socket, call [`resume()`][]. Here is an example of an echo server which listens for connections on port 8124: - var net = require('net'); - var server = net.createServer(function(c) { //'connection' listener + const net = require('net'); + const server = net.createServer((c) => { //'connection' listener console.log('client connected'); - c.on('end', function() { + c.on('end', () => { console.log('client disconnected'); }); c.write('hello\r\n'); c.pipe(c); }); - server.listen(8124, function() { //'listening' listener + server.listen(8124, () => { //'listening' listener console.log('server bound'); }); @@ -636,7 +643,7 @@ Test this by using `telnet`: To listen on the socket `/tmp/echo.sock` the third line from the last would just be changed to - server.listen('/tmp/echo.sock', function() { //'listening' listener + server.listen('/tmp/echo.sock', () => { //'listening' listener Use `nc` to connect to a UNIX domain socket server: @@ -657,15 +664,28 @@ Returns true if input is a version 4 IP address, otherwise returns false. Returns true if input is a version 6 IP address, otherwise returns false. -['close']: #net_event_close -['connect']: #net_event_connect -['connection']: #net_event_connection -['end']: #net_event_end -[EventEmitter]: events.html#events_class_events_eventemitter -['listening']: #net_event_listening -[server.getConnections]: #net_server_getconnections_callback +[`'close'`]: #net_event_close +[`'connect'`]: #net_event_connect +[`'connection'`]: #net_event_connection +[`'data'`]: #net_event_data +[`'drain'`]: #net_event_drain +[`'end'`]: #net_event_end +[`'error'`]: #net_event_error_1 +[`'listening'`]: #net_event_listening +[`'timeout'`]: #net_event_timeout +[`child_process.fork()`]: child_process.html#child_process_child_process_fork_modulepath_args_options +[`connect()`]: #net_socket_connect_options_connectlistener +[`destroy()`]: #net_socket_destroy +[`dns.lookup()`]: dns.html#dns_dns_lookup_hostname_options_callback +[`end()`]: #net_socket_end_data_encoding +[`EventEmitter`]: events.html#events_class_events_eventemitter +[`net.Socket`]: #net_class_net_socket +[`pause()`]: #net_socket_pause +[`resume()`]: #net_socket_resume +[`server.getConnections`]: #net_server_getconnections_callback +[`server.listen(port, \[host\], \[backlog\], \[callback\])`]: #net_server_listen_port_hostname_backlog_callback +[`socket.connect(options\[, connectListener\])`]: #net_socket_connect_options_connectlistener +[`socket.connect`]: #net_socket_connect_options_connectlistener +[`socket.setTimeout()`]: #net_socket_settimeout_timeout_callback +[`stream.setEncoding()`]: stream.html#stream_readable_setencoding_encoding [Readable Stream]: stream.html#stream_class_stream_readable -[stream.setEncoding()]: stream.html#stream_readable_setencoding_encoding -['net.Socket']: #net_class_net_socket -[dns.lookup()]: dns.html#dns_dns_lookup_hostname_options_callback -['socket.connect']: #net_socket_connect_options_connectlistener diff --git a/doc/api/process.markdown b/doc/api/process.markdown index 444a4c703ccd3d..d954f4c9ab843e 100644 --- a/doc/api/process.markdown +++ b/doc/api/process.markdown @@ -3,22 +3,22 @@ The `process` object is a global object and can be accessed from anywhere. -It is an instance of [EventEmitter][]. +It is an instance of [`EventEmitter`][]. ## Event: 'beforeExit' This event is emitted when Node.js empties its event loop and has nothing else to schedule. Normally, Node.js exits when there is no work scheduled, but a listener -for 'beforeExit' can make asynchronous calls, and cause Node.js to continue. +for `'beforeExit'` can make asynchronous calls, and cause Node.js to continue. -'beforeExit' is not emitted for conditions causing explicit termination, such as -`process.exit()` or uncaught exceptions, and should not be used as an -alternative to the 'exit' event unless the intention is to schedule more work. +`'beforeExit'` is not emitted for conditions causing explicit termination, such as +[`process.exit()`][] or uncaught exceptions, and should not be used as an +alternative to the `'exit'` event unless the intention is to schedule more work. ## Event: 'exit' Emitted when the process is about to exit. There is no way to prevent the -exiting of the event loop at this point, and once all `exit` listeners have +exiting of the event loop at this point, and once all `'exit'` listeners have finished running the process will exit. Therefore you **must** only perform **synchronous** operations in this handler. This is a good hook to perform checks on the module's state (like for unit tests). The callback takes one @@ -27,11 +27,11 @@ argument, the code the process is exiting with. This event is only emitted when Node.js exits explicitly by process.exit() or implicitly by the event loop draining. -Example of listening for `exit`: +Example of listening for `'exit'`: - process.on('exit', function(code) { + process.on('exit', (code) => { // do *NOT* do this - setTimeout(function() { + setTimeout(() => { console.log('This will not run'); }, 0); console.log('About to exit with code:', code); @@ -40,10 +40,10 @@ Example of listening for `exit`: ## Event: 'message' * `message` {Object} a parsed JSON object or primitive value -* `sendHandle` {Handle object} a [net.Socket][] or [net.Server][] object, or +* `sendHandle` {Handle object} a [`net.Socket`][] or [`net.Server`][] object, or undefined. -Messages sent by [ChildProcess.send()][] are obtained using the `'message'` +Messages sent by [`ChildProcess.send()`][] are obtained using the `'message'` event on the child's process object. ## Event: 'rejectionHandled' @@ -63,19 +63,19 @@ event loop turn it takes for the `'unhandledRejection'` event to be emitted. Another way of stating this is that, unlike in synchronous code where there is an ever-growing list of unhandled exceptions, with promises there is a growing-and-shrinking list of unhandled rejections. In synchronous code, the -'uncaughtException' event tells you when the list of unhandled exceptions +`'uncaughtException'` event tells you when the list of unhandled exceptions grows. And in asynchronous code, the `'unhandledRejection'` event tells you -when the list of unhandled rejections grows, while the 'rejectionHandled' +when the list of unhandled rejections grows, while the `'rejectionHandled'` event tells you when the list of unhandled rejections shrinks. For example using the rejection detection hooks in order to keep a map of all the rejected promise reasons at a given time: - var unhandledRejections = new Map(); - process.on('unhandledRejection', function(reason, p) { + const unhandledRejections = new Map(); + process.on('unhandledRejection', (reason, p) => { unhandledRejections.set(p, reason); }); - process.on('rejectionHandled', function(p) { + process.on('rejectionHandled', (p) => { unhandledRejections.delete(p); }); @@ -91,13 +91,13 @@ Emitted when an exception bubbles all the way back to the event loop. If a listener is added for this exception, the default action (which is to print a stack trace and exit) will not occur. -Example of listening for `uncaughtException`: +Example of listening for `'uncaughtException'`: - process.on('uncaughtException', function(err) { - console.log('Caught exception: ' + err); + process.on('uncaughtException', (err) => { + console.log(`Caught exception: ${err}`); }); - setTimeout(function() { + setTimeout(() => { console.log('This will still run.'); }, 500); @@ -105,7 +105,7 @@ Example of listening for `uncaughtException`: nonexistentFunc(); console.log('This will not run.'); -Note that `uncaughtException` is a very crude mechanism for exception +Note that `'uncaughtException'` is a very crude mechanism for exception handling. Do *not* use it as the Node.js equivalent of `On Error Resume Next`. An @@ -115,9 +115,9 @@ is in an undefined state. Blindly resuming means *anything* could happen. Think of resuming as pulling the power cord when you are upgrading your system. Nine out of ten times nothing happens - but the 10th time, your system is bust. -`uncaughtException` should be used to perform synchronous cleanup before +`'uncaughtException'` should be used to perform synchronous cleanup before shutting down the process. It is not safe to resume normal operation after -`uncaughtException`. If you do use it, restart your application after every +`'uncaughtException'`. If you do use it, restart your application after every unhandled exception! You have been warned. @@ -127,18 +127,18 @@ You have been warned. Emitted whenever a `Promise` is rejected and no error handler is attached to the promise within a turn of the event loop. When programming with promises exceptions are encapsulated as rejected promises. Such promises can be caught -and handled using `promise.catch(...)` and rejections are propagated through +and handled using [`promise.catch(...)`][] and rejections are propagated through a promise chain. This event is useful for detecting and keeping track of promises that were rejected whose rejections were not handled yet. This event is emitted with the following arguments: - - `reason` the object with which the promise was rejected (usually an `Error` + - `reason` the object with which the promise was rejected (usually an [`Error`][] instance). - `p` the promise that was rejected. Here is an example that logs every unhandled rejection to the console - process.on('unhandledRejection', function(reason, p) { + process.on('unhandledRejection', (reason, p) => { console.log("Unhandled Rejection at: Promise ", p, " reason: ", reason); // application specific logging, throwing an error, or other logic here }); @@ -146,8 +146,8 @@ Here is an example that logs every unhandled rejection to the console For example, here is a rejection that will trigger the `'unhandledRejection'` event: - somePromise.then(function(res) { - return reportToUser(JSON.pasre(res)); // note the typo + somePromise.then((res) => { + return reportToUser(JSON.parse(res)); // note the typo }); // no `.catch` or `.then` Here is an example of a coding pattern that will also trigger @@ -175,7 +175,7 @@ operations are pending. The following status codes are used in other cases: * `1` **Uncaught Fatal Exception** - There was an uncaught exception, - and it was not handled by a domain or an `uncaughtException` event + and it was not handled by a domain or an `'uncaughtException'` event handler. * `2` - Unused (reserved by Bash for builtin misuse) * `3` **Internal JavaScript Parse Error** - The JavaScript source code @@ -219,14 +219,14 @@ cases: Emitted when the processes receives a signal. See sigaction(2) for a list of -standard POSIX signal names such as SIGINT, SIGHUP, etc. +standard POSIX signal names such as `SIGINT`, `SIGHUP`, etc. Example of listening for `SIGINT`: // Start reading from stdin so we don't exit. process.stdin.resume(); - process.on('SIGINT', function() { + process.on('SIGINT', () => { console.log('Got SIGINT. Press Control-D to exit.'); }); @@ -285,8 +285,8 @@ An array containing the command line arguments. The first element will be next elements will be any additional command line arguments. // print process.argv - process.argv.forEach(function(val, index, array) { - console.log(index + ': ' + val); + process.argv.forEach((val, index, array) => { + console.log(`${index}: ${val}`); }); This will generate: @@ -302,20 +302,20 @@ This will generate: Changes the current working directory of the process or throws an exception if that fails. - console.log('Starting directory: ' + process.cwd()); + console.log(`Starting directory: ${process.cwd()}`); try { process.chdir('/tmp'); - console.log('New directory: ' + process.cwd()); + console.log(`New directory: ${process.cwd()}`); } catch (err) { - console.log('chdir: ' + err); + console.log(`chdir: ${err}`); } ## process.config An Object containing the JavaScript representation of the configure options that were used to compile the current Node.js executable. This is the same as -the "config.gypi" file that was produced when running the `./configure` script. +the `config.gypi` file that was produced when running the `./configure` script. An example of the possible output looks like: @@ -350,14 +350,14 @@ If `process.connected` is false, it is no longer possible to send messages. Returns the current working directory of the process. - console.log('Current directory: ' + process.cwd()); + console.log(`Current directory: ${process.cwd()}`); ## process.disconnect() Close the IPC channel to the parent process, allowing this child to exit gracefully once there are no other connections keeping it alive. -Identical to the parent process's [ChildProcess.disconnect()][]. +Identical to the parent process's [`ChildProcess.disconnect()`][]. If Node.js was not spawned with an IPC channel, `process.disconnect()` will be undefined. @@ -434,7 +434,7 @@ The shell that executed Node.js should see the exit code as 1. ## process.exitCode A number which will be the process exit code, when the process either -exits gracefully, or is exited via `process.exit()` without specifying +exits gracefully, or is exited via [`process.exit()`][] without specifying a code. Specifying a code to `process.exit(code)` will override any previous @@ -450,7 +450,7 @@ Gets the effective group identity of the process. (See getegid(2).) This is the numerical group id, not the group name. if (process.getegid) { - console.log('Current gid: ' + process.getegid()); + console.log(`Current gid: ${process.getegid()}`); } @@ -463,7 +463,7 @@ Gets the effective user identity of the process. (See geteuid(2).) This is the numerical userid, not the username. if (process.geteuid) { - console.log('Current uid: ' + process.geteuid()); + console.log(`Current uid: ${process.geteuid()}`); } ## process.getgid() @@ -475,7 +475,7 @@ Gets the group identity of the process. (See getgid(2).) This is the numerical group id, not the group name. if (process.getgid) { - console.log('Current gid: ' + process.getgid()); + console.log(`Current gid: ${process.getgid()}`); } ## process.getgroups() @@ -495,7 +495,7 @@ Gets the user identity of the process. (See getuid(2).) This is the numerical userid, not the username. if (process.getuid) { - console.log('Current uid: ' + process.getuid()); + console.log(`Current uid: ${process.getuid()}`); } ## process.hrtime() @@ -511,7 +511,7 @@ a diff reading, useful for benchmarks and measuring intervals: var time = process.hrtime(); // [ 1800216, 25 ] - setTimeout(function() { + setTimeout(() => { var diff = process.hrtime(time); // [ 1, 552 ] @@ -527,7 +527,7 @@ Android) Reads /etc/group and initializes the group access list, using all groups of which the user is a member. This is a privileged operation, meaning you need -to be root or have the CAP_SETGID capability. +to be root or have the `CAP_SETGID` capability. `user` is a user name or user ID. `extra_group` is a group name or group ID. @@ -543,11 +543,12 @@ Some care needs to be taken when dropping privileges. Example: Send a signal to a process. `pid` is the process id and `signal` is the string describing the signal to send. Signal names are strings like -'SIGINT' or 'SIGHUP'. If omitted, the signal will be 'SIGTERM'. +`SIGINT` or `SIGHUP`. If omitted, the signal will be `SIGTERM`. See [Signal Events][] and kill(2) for more information. Will throw an error if target does not exist, and as a special case, a signal -of `0` can be used to test for the existence of a process. +of `0` can be used to test for the existence of a process. Windows platforms +will throw an error if the `pid` is used to kill a process group. Note that even though the name of this function is `process.kill`, it is really just a signal sender, like the `kill` system call. The signal sent may do @@ -555,11 +556,11 @@ something other than kill the target process. Example of sending a signal to yourself: - process.on('SIGHUP', function() { + process.on('SIGHUP', () => { console.log('Got SIGHUP signal.'); }); - setTimeout(function() { + setTimeout(() => { console.log('Exiting.'); process.exit(0); }, 100); @@ -583,7 +584,7 @@ As with `require.main`, it will be `undefined` if there was no entry script. Returns an object describing the memory usage of the Node.js process measured in bytes. - var util = require('util'); + const util = require('util'); console.log(util.inspect(process.memoryUsage())); @@ -603,12 +604,12 @@ This will generate: Once the current event loop turn runs to completion, call the callback function. -This is *not* a simple alias to `setTimeout(fn, 0)`, it's much more +This is *not* a simple alias to [`setTimeout(fn, 0)`][], it's much more efficient. It runs before any additional I/O events (including timers) fire in subsequent ticks of the event loop. console.log('start'); - process.nextTick(function() { + process.nextTick(() => { console.log('nextTick callback'); }); console.log('scheduled'); @@ -624,7 +625,7 @@ but before any I/O has occurred. function MyThing(options) { this.setupOptions(options); - process.nextTick(function() { + process.nextTick(() => { this.startDoingStuff(); }.bind(this)); } @@ -676,14 +677,14 @@ happening, just like a `while(true);` loop. The PID of the process. - console.log('This process is pid ' + process.pid); + console.log(`This process is pid ${process.pid}`); ## process.platform What platform you're running on: `'darwin'`, `'freebsd'`, `'linux'`, `'sunos'` or `'win32'` - console.log('This platform is ' + process.platform); + console.log(`This platform is ${process.platform}`); ## process.release @@ -692,8 +693,8 @@ for the source tarball and headers-only tarball. `process.release` contains the following properties: -* `name`: a string with a value that will always be `"node"` for Node.js. For - legacy io.js releases, this will be `"io.js"`. +* `name`: a string with a value that will always be `'node'` for Node.js. For + legacy io.js releases, this will be `'io.js'`. * `sourceUrl`: a complete URL pointing to a _.tar.gz_ file containing the source of the current release. * `headersUrl`: a complete URL pointing to a _.tar.gz_ file containing only @@ -723,7 +724,7 @@ relied upon to exist. When Node.js is spawned with an IPC channel attached, it can send messages to its parent process using `process.send()`. Each will be received as a -['message'][] event on the parent's `ChildProcess` object. +[`'message'`][] event on the parent's `ChildProcess` object. If Node.js was not spawned with an IPC channel, `process.send()` will be undefined. @@ -737,13 +738,13 @@ This accepts either a numerical ID or a groupname string. If a groupname is specified, this method blocks while resolving it to a numerical ID. if (process.getegid && process.setegid) { - console.log('Current gid: ' + process.getegid()); + console.log(`Current gid: ${process.getegid()}`); try { process.setegid(501); - console.log('New gid: ' + process.getegid()); + console.log(`New gid: ${process.getegid()}`); } catch (err) { - console.log('Failed to set gid: ' + err); + console.log(`Failed to set gid: ${err}`); } } @@ -757,13 +758,13 @@ This accepts either a numerical ID or a username string. If a username is specified, this method blocks while resolving it to a numerical ID. if (process.geteuid && process.seteuid) { - console.log('Current uid: ' + process.geteuid()); + console.log(`Current uid: ${process.geteuid()}`); try { process.seteuid(501); - console.log('New uid: ' + process.geteuid()); + console.log(`New uid: ${process.geteuid()}`); } catch (err) { - console.log('Failed to set uid: ' + err); + console.log(`Failed to set uid: ${err}`); } } @@ -777,13 +778,13 @@ a numerical ID or a groupname string. If a groupname is specified, this method blocks while resolving it to a numerical ID. if (process.getgid && process.setgid) { - console.log('Current gid: ' + process.getgid()); + console.log(`Current gid: ${process.getgid()}`); try { process.setgid(501); - console.log('New gid: ' + process.getgid()); + console.log(`New gid: ${process.getgid()}`); } catch (err) { - console.log('Failed to set gid: ' + err); + console.log(`Failed to set gid: ${err}`); } } @@ -793,7 +794,7 @@ Note: this function is only available on POSIX platforms (i.e. not Windows, Android) Sets the supplementary group IDs. This is a privileged operation, meaning you -need to be root or have the CAP_SETGID capability. +need to be root or have the `CAP_SETGID` capability. The list can contain group IDs, group names or both. @@ -807,13 +808,13 @@ a numerical ID or a username string. If a username is specified, this method blocks while resolving it to a numerical ID. if (process.getuid && process.setuid) { - console.log('Current uid: ' + process.getuid()); + console.log(`Current uid: ${process.getuid()}`); try { process.setuid(501); - console.log('New uid: ' + process.getuid()); + console.log(`New uid: ${process.getuid()}`); } catch (err) { - console.log('Failed to set uid: ' + err); + console.log(`Failed to set uid: ${err}`); } } @@ -835,14 +836,14 @@ Example of opening standard input and listening for both events: process.stdin.setEncoding('utf8'); - process.stdin.on('readable', function() { + process.stdin.on('readable', () => { var chunk = process.stdin.read(); if (chunk !== null) { - process.stdout.write('data: ' + chunk); + process.stdout.write(`data: ${chunk}`); } }); - process.stdin.on('end', function() { + process.stdin.on('end', () => { process.stdout.write('end'); }); @@ -864,11 +865,11 @@ A `Writable Stream` to `stdout` (on fd `1`). For example, a `console.log` equivalent could look like this: console.log = function(msg) { - process.stdout.write(msg + '\n'); + process.stdout.write(`${msg}\n`); }; `process.stderr` and `process.stdout` are unlike other streams in Node.js in -that they cannot be closed (`end()` will throw), they never emit the `finish` +that they cannot be closed (`end()` will throw), they never emit the `'finish'` event and that writes can block when output is redirected to a file (although disks are fast and operating systems normally employ write-back caching so it should be a very rare occurrence indeed.) @@ -890,7 +891,7 @@ See [the tty docs][] for more information. ## process.title -Getter/setter to set what is displayed in 'ps'. +Getter/setter to set what is displayed in `ps`. When used as a setter, the maximum length is platform-specific and probably short. @@ -908,11 +909,11 @@ Sets or reads the process's file mode creation mask. Child processes inherit the mask from the parent process. Returns the old mask if `mask` argument is given, otherwise returns the current mask. - var oldmask, newmask = 0022; - - oldmask = process.umask(newmask); - console.log('Changed umask from: ' + oldmask.toString(8) + - ' to ' + newmask.toString(8)); + const newmask = 0o022; + const oldmask = process.umask(newmask); + console.log( + `Changed umask from ${oldmask.toString(8)} to ${newmask.toString(8)}` + ); ## process.uptime() @@ -923,7 +924,7 @@ Number of seconds Node.js has been running. A compiled-in property that exposes `NODE_VERSION`. - console.log('Version: ' + process.version); + console.log(`Version: ${process.version}`); ## process.versions @@ -943,13 +944,17 @@ Will print something like: icu: '55.1', openssl: '1.0.1k' } -[ChildProcess.disconnect()]: child_process.html#child_process_child_disconnect -[ChildProcess.send()]: child_process.html#child_process_child_send_message_sendhandle_callback -[Signal Events]: #process_signal_events -[EventEmitter]: events.html#events_class_events_eventemitter -[net.Server]: net.html#net_class_net_server -[net.Socket]: net.html#net_class_net_socket +[`'message'`]: child_process.html#child_process_event_message +[`ChildProcess.disconnect()`]: child_process.html#child_process_child_disconnect +[`ChildProcess.send()`]: child_process.html#child_process_child_send_message_sendhandle_callback +[`Error`]: errors.html#errors_class_error +[`EventEmitter`]: events.html#events_class_events_eventemitter +[`net.Server`]: net.html#net_class_net_server +[`net.Socket`]: net.html#net_class_net_socket +[`process.exit()`]: #process_process_exit_code +[`promise.catch(...)`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch [`require.main`]: modules.html#modules_accessing_the_main_module -['message']: child_process.html#child_process_event_message +[`setTimeout(fn, 0)`]: timers.html#timers_settimeout_callback_delay_arg +[Signal Events]: #process_signal_events [Stream compatibility]: stream.html#stream_compatibility_with_older_node_js_versions [the tty docs]: tty.html#tty_tty diff --git a/doc/api/punycode.markdown b/doc/api/punycode.markdown index c54a981fedb45b..0b3f49d9ba69a3 100644 --- a/doc/api/punycode.markdown +++ b/doc/api/punycode.markdown @@ -67,4 +67,4 @@ Creates a string based on an array of numeric code point values. A string representing the current Punycode.js version number. [Punycode.js]: https://mths.be/punycode -[JavaScript uses UCS-2 internally]: http://mathiasbynens.be/notes/javascript-encoding +[JavaScript uses UCS-2 internally]: https://mathiasbynens.be/notes/javascript-encoding diff --git a/doc/api/readline.markdown b/doc/api/readline.markdown index ac5c61fa1cc9cf..a83b492b0b5621 100644 --- a/doc/api/readline.markdown +++ b/doc/api/readline.markdown @@ -3,22 +3,22 @@ Stability: 2 - Stable To use this module, do `require('readline')`. Readline allows reading of a -stream (such as `process.stdin`) on a line-by-line basis. +stream (such as [`process.stdin`][]) on a line-by-line basis. Note that once you've invoked this module, your Node.js program will not terminate until you've closed the interface. Here's how to allow your program to gracefully exit: - var readline = require('readline'); + const readline = require('readline'); - var rl = readline.createInterface({ + const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); - rl.question("What do you think of Node.js? ", function(answer) { + rl.question('What do you think of Node.js? ', (answer) => { // TODO: Log the answer in a database - console.log("Thank you for your valuable feedback:", answer); + console.log('Thank you for your valuable feedback:', answer); rl.close(); }); @@ -31,13 +31,14 @@ stream. ### rl.close() Closes the `Interface` instance, relinquishing control on the `input` and -`output` streams. The "close" event will also be emitted. +`output` streams. The `'close'` event will also be emitted. ### rl.pause() Pauses the readline `input` stream, allowing it to be resumed later if needed. -Note that this doesn't immediately pause the stream of events. Several events may be emitted after calling `pause`, including `line`. +Note that this doesn't immediately pause the stream of events. Several events may +be emitted after calling `pause`, including `line`. ### rl.prompt([preserveCursor]) @@ -65,8 +66,8 @@ nothing is displayed. Example usage: - interface.question('What is your favorite food?', function(answer) { - console.log('Oh, so your favorite food is ' + answer); + interface.question('What is your favorite food?', (answer) => { + console.log(`Oh, so your favorite food is ${answer}`); }); ### rl.resume() @@ -76,7 +77,7 @@ Resumes the readline `input` stream. ### rl.setPrompt(prompt) Sets the prompt, for example when you run `node` on the command line, you see -`> `, which is node.js's prompt. +`> `, which is Node.js's prompt. ### rl.write(data[, key]) @@ -100,7 +101,7 @@ Example: Emitted when `close()` is called. -Also emitted when the `input` stream receives its "end" event. The `Interface` +Also emitted when the `input` stream receives its `'end'` event. The `Interface` instance should be considered "finished" once this is emitted. For example, when the `input` stream receives `^D`, respectively known as `EOT`. @@ -114,10 +115,10 @@ the `input` stream receives a `^C`, respectively known as `SIGINT`. Emitted whenever the `input` stream receives a `\n`, usually received when the user hits enter, or return. This is a good hook to listen for user input. -Example of listening for `line`: +Example of listening for `'line'`: - rl.on('line', function (cmd) { - console.log('You just typed: '+cmd); + rl.on('line', (cmd) => { + console.log(`You just typed: ${cmd}`); }); ### Event: 'pause' @@ -129,9 +130,9 @@ Emitted whenever the `input` stream is paused. Also emitted whenever the `input` stream is not paused and receives the `SIGCONT` event. (See events `SIGTSTP` and `SIGCONT`) -Example of listening for `pause`: +Example of listening for `'pause'`: - rl.on('pause', function() { + rl.on('pause', () => { console.log('Readline paused.'); }); @@ -141,9 +142,9 @@ Example of listening for `pause`: Emitted whenever the `input` stream is resumed. -Example of listening for `resume`: +Example of listening for `'resume'`: - rl.on('resume', function() { + rl.on('resume', () => { console.log('Readline resumed.'); }); @@ -160,7 +161,7 @@ background. Example of listening for `SIGCONT`: - rl.on('SIGCONT', function() { + rl.on('SIGCONT', () => { // `prompt` will automatically resume the stream rl.prompt(); }); @@ -175,8 +176,8 @@ stream receives a `SIGINT`, `pause` will be triggered. Example of listening for `SIGINT`: - rl.on('SIGINT', function() { - rl.question('Are you sure you want to exit?', function(answer) { + rl.on('SIGINT', () => { + rl.question('Are you sure you want to exit?', (answer) => { if (answer.match(/^y(es)?$/i)) rl.pause(); }); }); @@ -191,15 +192,15 @@ Emitted whenever the `input` stream receives a `^Z`, respectively known as `SIGTSTP`. If there is no `SIGTSTP` event listener present when the `input` stream receives a `SIGTSTP`, the program will be sent to the background. -When the program is resumed with `fg`, the `pause` and `SIGCONT` events will be +When the program is resumed with `fg`, the `'pause'` and `SIGCONT` events will be emitted. You can use either to resume the stream. -The `pause` and `SIGCONT` events will not be triggered if the stream was paused +The `'pause'` and `SIGCONT` events will not be triggered if the stream was paused before the program was sent to the background. Example of listening for `SIGTSTP`: - rl.on('SIGTSTP', function() { + rl.on('SIGTSTP', () => { // This will override SIGTSTP and prevent the program from going to the // background. console.log('Caught SIGTSTP.'); @@ -210,13 +211,13 @@ Example of listening for `SIGTSTP`: Here's an example of how to use all these together to craft a tiny command line interface: - var readline = require('readline'), - rl = readline.createInterface(process.stdin, process.stdout); + const readline = require('readline'); + const rl = readline.createInterface(process.stdin, process.stdout); rl.setPrompt('OHAI> '); rl.prompt(); - rl.on('line', function(line) { + rl.on('line', (line) => { switch(line.trim()) { case 'hello': console.log('world!'); @@ -226,11 +227,27 @@ line interface: break; } rl.prompt(); - }).on('close', function() { + }).on('close', () => { console.log('Have a great day!'); process.exit(0); }); +## Example: Read File Stream Line-by-Line + +A common case for `readline`'s `input` option is to pass a filesystem readable +stream to it. This is how one could craft line-by-line parsing of a file: + + const readline = require('readline'); + const fs = require('fs'); + + const rl = readline.createInterface({ + input: fs.createReadStream('sample.txt') + }); + + rl.on('line', function (line) { + console.log('Line from file:', line); + }); + ## readline.clearLine(stream, dir) Clears current line of given TTY stream in a specified direction. @@ -246,7 +263,7 @@ Clears the screen from the current position of the cursor down. ## readline.createInterface(options) -Creates a readline `Interface` instance. Accepts an "options" Object that takes +Creates a readline `Interface` instance. Accepts an `options` Object that takes the following values: - `input` - the readable stream to listen to (Required). @@ -276,7 +293,7 @@ Example: function completer(line) { var completions = '.help .error .exit .quit .q'.split(' ') - var hits = completions.filter(function(c) { return c.indexOf(line) == 0 }) + var hits = completions.filter((c) => { return c.indexOf(line) == 0 }) // show all completions if none found return [hits.length ? hits : completions, line] } @@ -287,22 +304,22 @@ Also `completer` can be run in async mode if it accepts two arguments: callback(null, [['123'], linePartial]); } -`createInterface` is commonly used with `process.stdin` and -`process.stdout` in order to accept user input: +`createInterface` is commonly used with [`process.stdin`][] and +[`process.stdout`][] in order to accept user input: - var readline = require('readline'); - var rl = readline.createInterface({ + const readline = require('readline'); + const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); Once you have a readline instance, you most commonly listen for the -`"line"` event. +`'line'` event. If `terminal` is `true` for this instance then the `output` stream will get the best compatibility if it defines an `output.columns` property, and fires -a `"resize"` event on the `output` if/when the columns ever change -(`process.stdout` does this automatically when it is a TTY). +a `'resize'` event on the `output` if/when the columns ever change +([`process.stdout`][] does this automatically when it is a TTY). ## readline.cursorTo(stream, x, y) @@ -311,3 +328,6 @@ Move cursor to the specified position in a given TTY stream. ## readline.moveCursor(stream, dx, dy) Move cursor relative to it's current position in a given TTY stream. + +[`process.stdin`]: process.html#process_process_stdin +[`process.stdout`]: process.html#process_process_stdout diff --git a/doc/api/repl.markdown b/doc/api/repl.markdown index 8961bb3fb54215..99e9d0e26d8720 100644 --- a/doc/api/repl.markdown +++ b/doc/api/repl.markdown @@ -85,8 +85,8 @@ a variable to the REPL explicitly by assigning it to the `context` object associated with each `REPLServer`. For example: // repl_test.js - var repl = require('repl'), - msg = 'message'; + const repl = require('repl'); + var msg = 'message'; repl.start('> ').context.m = msg; @@ -120,7 +120,7 @@ The following key combinations in the REPL have these special effects: ### Customizing Object displays in the REPL The REPL module internally uses -[util.inspect()][], when printing values. However, `util.inspect` delegates the +[`util.inspect()`][], when printing values. However, `util.inspect` delegates the call to the object's `inspect()` function, if it has one. You can read more about this delegation [here][]. @@ -147,12 +147,12 @@ This inherits from [Readline Interface][] with the following events: `function () {}` Emitted when the user exits the REPL in any of the defined ways. Namely, typing -`.exit` at the repl, pressing Ctrl+C twice to signal SIGINT, or pressing Ctrl+D -to signal "end" on the `input` stream. +`.exit` at the repl, pressing Ctrl+C twice to signal `SIGINT`, or pressing Ctrl+D +to signal `'end'` on the `input` stream. Example of listening for `exit`: - replServer.on('exit', function () { + replServer.on('exit', () => { console.log('Got "exit" event from repl!'); process.exit(); }); @@ -173,7 +173,7 @@ Example of listening for `reset`: someExtension.extend(r.context); // When a new context is created extend it as well. - replServer.on('reset', function (context) { + replServer.on('reset', (context) => { console.log('repl has a new context'); someExtension.extend(context); }); @@ -196,13 +196,13 @@ If a function is provided instead of an object for `cmd`, it is treated as the Example of defining a command: // repl_test.js - var repl = require('repl'); + const repl = require('repl'); var replServer = repl.start(); replServer.defineCommand('sayhello', { help: 'Say hello', action: function(name) { - this.write('Hello, ' + name + '!\n'); + this.write(`Hello, ${name}!\n'); this.displayPrompt(); } }); @@ -216,8 +216,8 @@ Example of invoking that command from the REPL: * `preserveCursor` {Boolean} -Like [readline.prompt][] except also adding indents with ellipses when inside -blocks. The `preserveCursor` argument is passed to [readline.prompt][]. This is +Like [`readline.prompt`][] except also adding indents with ellipses when inside +blocks. The `preserveCursor` argument is passed to [`readline.prompt`][]. This is used primarily with `defineCommand`. It's also used internally to render each prompt line. @@ -277,9 +277,9 @@ will share the same global object but will have unique I/O. Here is an example that starts a REPL on stdin, a Unix socket, and a TCP socket: - var net = require('net'), - repl = require('repl'), - connections = 0; + const net = require('net'); + const repl = require('repl'); + var connections = 0; repl.start({ prompt: 'Node.js via stdin> ', @@ -287,24 +287,24 @@ Here is an example that starts a REPL on stdin, a Unix socket, and a TCP socket: output: process.stdout }); - net.createServer(function (socket) { + net.createServer((socket) => { connections += 1; repl.start({ prompt: 'Node.js via Unix socket> ', input: socket, output: socket - }).on('exit', function() { + }).on('exit', () => { socket.end(); }) }).listen('/tmp/node-repl-sock'); - net.createServer(function (socket) { + net.createServer((socket) => { connections += 1; repl.start({ prompt: 'Node.js via TCP socket> ', input: socket, output: socket - }).on('exit', function() { + }).on('exit', () => { socket.end(); }); }).listen(5001); @@ -323,7 +323,7 @@ a `net.Server` and `net.Socket` instance, see: https://gist.github.com/2209310 For an example of running a REPL instance over `curl(1)`, see: https://gist.github.com/2053342 -[Readline Interface]: readline.html#readline_class_interface -[readline.prompt]: readline.html#readline_rl_prompt_preservecursor -[util.inspect()]: util.html#util_util_inspect_object_options +[`readline.prompt`]: readline.html#readline_rl_prompt_preservecursor +[`util.inspect()`]: util.html#util_util_inspect_object_options [here]: util.html#util_custom_inspect_function_on_objects +[Readline Interface]: readline.html#readline_class_interface diff --git a/doc/api/stream.markdown b/doc/api/stream.markdown index caf9daeaf21362..a0fcb81e9fab0b 100644 --- a/doc/api/stream.markdown +++ b/doc/api/stream.markdown @@ -4,26 +4,24 @@ 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][] +[`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 @@ -50,9 +48,9 @@ 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'); +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: @@ -126,7 +124,7 @@ 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. +* 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][]. @@ -134,7 +132,7 @@ 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 pipe destinations, by removing any [`'data'`][] event handlers, and removing all pipe destinations by calling the [`unpipe()`][] method. @@ -153,7 +151,7 @@ Examples of readable streams include: * [crypto streams][] * [tcp sockets][] * [child process stdout and stderr][] -* [process.stdin][] +* [`process.stdin`][] #### Event: 'close' @@ -161,13 +159,13 @@ 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. -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. @@ -176,7 +174,7 @@ possible, this is the best way to do so. ```javascript var readable = getReadableStreamSomehow(); -readable.on('data', function(chunk) { +readable.on('data', (chunk) => { console.log('got %d bytes of data', chunk.length); }); ``` @@ -185,16 +183,16 @@ 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 +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. ```javascript 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 +214,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: ```javascript -var fs = require('fs'); +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'); }); ``` @@ -275,16 +273,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 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); @@ -335,7 +333,7 @@ end. ```javascript reader.pipe(writer, { end: false }); -reader.on('end', function() { +reader.on('end', () => { writer.end('Goodbye\n'); }); ``` @@ -366,7 +364,7 @@ drained. ```javascript 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,9 +373,9 @@ 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 +Note that calling `readable.read([size])` after the `'end'` event has been triggered will return `null`. No runtime error will be raised. #### readable.resume() @@ -389,13 +387,13 @@ events. 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 +its `'end'` event, you can call [`readable.resume()`][] to open the flow of data. ```javascript var readable = getReadableStreamSomehow(); readable.resume(); -readable.on('end', function() { +readable.on('end', () => { console.log('got to the end, but did not read anything'); }); ``` @@ -420,7 +418,7 @@ as strings, always use this method. ```javascript 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); }); @@ -443,7 +441,7 @@ 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'); @@ -460,7 +458,7 @@ 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 @@ -471,7 +469,7 @@ for Stream Implementors, below.) // 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); @@ -528,12 +526,12 @@ 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); +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. }); ``` @@ -565,11 +563,11 @@ Examples of writable streams include: * [crypto streams][] * [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` +If a [`writable.write(chunk)`][] call returns false, then the `'drain'` event will indicate when it is appropriate to begin writing more data to the stream. @@ -615,10 +613,10 @@ 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.'); }); ``` @@ -633,7 +631,7 @@ stream, adding this writable to its set of destinations. ```javascript 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); }); @@ -650,7 +648,7 @@ readable stream, removing this writable from its set of destinations. ```javascript 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); }); @@ -671,7 +669,7 @@ Buffered data will be flushed either at `.uncork()` or at `.end()` call. * `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. +supplied, the callback is attached as a listener on the `'finish'` event. Calling [`write()`][] after calling [`end()`][] will raise an error. @@ -710,7 +708,7 @@ If the data had to be buffered internally, then it will return 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. +the `'drain'` event before writing more data. ## API for Stream Implementors @@ -723,7 +721,7 @@ To implement any sort of stream, the pattern is the same: [`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: @@ -761,7 +759,7 @@ of stream class you are writing:

[Writable](#stream_class_stream_writable_1)

-

[_write][], _writev

+

[_write][], [_writev][]

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

[Duplex](#stream_class_stream_duplex_1)

-

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

+

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

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

[Transform](#stream_class_stream_transform_1)

-

_transform, _flush

+

[_transform][], [_flush][]

@@ -907,7 +905,7 @@ 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. +when the `'readable'` event fires. 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 @@ -955,8 +953,8 @@ 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'); +const Readable = require('stream').Readable; +const util = require('util'); util.inherits(Counter, Readable); function Counter(opt) { @@ -995,8 +993,8 @@ below for a better implementation. // 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 +1010,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); }); @@ -1118,8 +1116,8 @@ 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 +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. @@ -1210,8 +1208,8 @@ 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) { @@ -1467,7 +1465,7 @@ var writable = new stream.Writable({ Both Writable and Readable streams will buffer data on an internal -object which can be retrieved from `_writableState.getBuffer()` or +object which can be retrieved from `_writableState.getBuffer()` or `_readableState.buffer`, respectively. The amount of data that will potentially be buffered depends on the @@ -1510,7 +1508,7 @@ no longer have to worry about losing `'data'` chunks. Most programs will continue to function normally. However, this introduces an edge case in the following conditions: -* No [`'data'` event][] handler is added. +* No [`'data'`][] event handler is added. * The [`resume()`][] method is never called. * The stream is not piped to any writable destination. @@ -1518,10 +1516,10 @@ For example, consider the following code: ```javascript // 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'); }); @@ -1538,9 +1536,9 @@ start the flow of data: ```javascript // 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'); }); @@ -1589,9 +1587,9 @@ 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; +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 @@ -1671,60 +1669,69 @@ code) will know when to check again, by calling `stream.read(0)`. 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]: http.html#http_http_incomingmessage -[EventEmitter]: events.html#events_class_events_eventemitter -[Object mode]: #stream_object_mode +[_read]: #stream_readable_read_size_1 +[_write]: #stream_writable_write_chunk_encoding_callback_1 +[`'data'`]: #stream_event_data +[`'end'`]: #stream_event_end +[`'finish'`]: #stream_event_finish +[`_read()`]: #stream_readable_read_size_1 +[`_read(size)`]: #stream_readable_read_size_1 +[`_write()`]: #stream_writable_write_chunk_encoding_callback_1 +[`_write(chunk, encoding, callback)`]: #stream_writable_write_chunk_encoding_callback_1 +[`end()`]: #stream_writable_end_chunk_encoding_callback +[`EventEmitter`]: events.html#events_class_events_eventemitter +[`pause()`]: #stream_readable_pause +[`pipe()`]: #stream_readable_pipe_destination_options +[`process.stderr`]: process.html#process_process_stderr +[`process.stdin`]: process.html#process_process_stdin +[`process.stdout`]: process.html#process_process_stdout +[`readable.resume()`]: #stream_readable_resume +[`resume()`]: #stream_readable_resume +[`stdout`]: process.html#process_process_stdout +[`stream.push()`]: #stream_readable_push_chunk_encoding [`stream.push(chunk)`]: #stream_readable_push_chunk_encoding [`stream.push(null)`]: #stream_readable_push_chunk_encoding -[`stream.push()`]: #stream_readable_push_chunk_encoding +[`stream.write(chunk)`]: #stream_writable_write_chunk_encoding_callback +[`tls.CryptoStream`]: tls.html#tls_class_cryptostream [`unpipe()`]: #stream_readable_unpipe_destination -[unpiped]: #stream_readable_unpipe_destination -[tcp sockets]: net.html#net_class_net_socket -[http responses, on the client]: http.html#http_http_incomingmessage -[http requests, on the server]: http.html#http_http_incomingmessage -[http requests, on the client]: http.html#http_class_http_clientrequest -[http responses, on the server]: http.html#http_class_http_serverresponse -[fs read streams]: fs.html#fs_class_fs_readstream -[fs write streams]: fs.html#fs_class_fs_writestream -[zlib streams]: zlib.html -[zlib]: zlib.html -[crypto streams]: crypto.html -[crypto]: crypto.html -[tls.CryptoStream]: tls.html#tls_class_cryptostream -[process.stdin]: process.html#process_process_stdin -[stdout]: process.html#process_process_stdout -[process.stdout]: process.html#process_process_stdout -[process.stderr]: process.html#process_process_stderr -[child process stdout and stderr]: child_process.html#child_process_child_stdout -[child process stdin]: child_process.html#child_process_child_stdin +[`unpipe()`]: #stream_readable_unpipe_destination +[`util.inherits`]: util.html#util_util_inherits_constructor_superconstructor +[`writable.write(chunk)`]: #stream_writable_write_chunk_encoding_callback +[`write()`]: #stream_writable_write_chunk_encoding_callback +[`write(chunk, encoding, callback)`]: #stream_writable_write_chunk_encoding_callback [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]: child_process.html#child_process_child_stdin +[child process stdout and stderr]: child_process.html#child_process_child_stdout +[crypto streams]: crypto.html +[crypto]: crypto.html [Duplex]: #stream_class_stream_duplex +[fs read streams]: fs.html#fs_class_fs_readstream +[fs write streams]: fs.html#fs_class_fs_writestream +[http requests, on the client]: http.html#http_class_http_clientrequest +[http requests, on the server]: http.html#http_http_incomingmessage +[http responses, on the client]: http.html#http_http_incomingmessage +[http responses, on the server]: http.html#http_class_http_serverresponse +[Object mode]: #stream_object_mode +[Readable]: #stream_class_stream_readable +[request to an HTTP server]: http.html#http_http_incomingmessage +[tcp sockets]: 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`]: 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 +[unpiped]: #stream_readable_unpipe_destination +[Writable]: #stream_class_stream_writable +[zlib streams]: zlib.html +[zlib]: zlib.html +[_transform]: #stream_transform_transform_chunk_encoding_callback +[`_transform()`]: #stream_transform_transform_chunk_encoding_callback +[`_transform(chunk, encoding, callback)`]: #stream_transform_transform_chunk_encoding_callback +[_flush]: #stream_transform_flush_callback +[`_flush()`]: #stream_transform_flush_callback +[`_flush(callback)`]: #stream_transform_flush_callback +[_writev]: #stream_writable_writev_chunks_callback +[`_writev()`]: #stream_writable_writev_chunks_callback +[`_writev(chunks, callback)`]: #stream_writable_writev_chunks_callback diff --git a/doc/api/string_decoder.markdown b/doc/api/string_decoder.markdown index 885af7745a23a0..8bcba2cfbd51e9 100644 --- a/doc/api/string_decoder.markdown +++ b/doc/api/string_decoder.markdown @@ -6,18 +6,18 @@ To use this module, do `require('string_decoder')`. StringDecoder decodes a buffer to a string. It is a simple interface to `buffer.toString()` but provides additional support for utf8. - var StringDecoder = require('string_decoder').StringDecoder; - var decoder = new StringDecoder('utf8'); + const StringDecoder = require('string_decoder').StringDecoder; + const decoder = new StringDecoder('utf8'); - var cent = new Buffer([0xC2, 0xA2]); + const cent = new Buffer([0xC2, 0xA2]); console.log(decoder.write(cent)); - var euro = new Buffer([0xE2, 0x82, 0xAC]); + const euro = new Buffer([0xE2, 0x82, 0xAC]); console.log(decoder.write(euro)); ## Class: StringDecoder -Accepts a single argument, `encoding` which defaults to `utf8`. +Accepts a single argument, `encoding` which defaults to `'utf8'`. ### decoder.end() diff --git a/doc/api/synopsis.markdown b/doc/api/synopsis.markdown index f9e8b19ed6fcfe..4a051013c4a6e1 100644 --- a/doc/api/synopsis.markdown +++ b/doc/api/synopsis.markdown @@ -3,11 +3,11 @@ An example of a [web server][] written with Node.js which responds with -'Hello World': +`'Hello World'`: - var http = require('http'); + const http = require('http'); - http.createServer(function (request, response) { + http.createServer( (request, response) => { response.writeHead(200, {'Content-Type': 'text/plain'}); response.end('Hello World\n'); }).listen(8124); diff --git a/doc/api/timers.markdown b/doc/api/timers.markdown index 3a087be76a5cf2..4d5caf2e0ee0e5 100644 --- a/doc/api/timers.markdown +++ b/doc/api/timers.markdown @@ -28,7 +28,7 @@ Returns the timer. ## setImmediate(callback[, arg][, ...]) To schedule the "immediate" execution of `callback` after I/O events -callbacks and before `setTimeout` and `setInterval` . Returns an +callbacks and before [`setTimeout`][] and [`setInterval`][]. Returns an `immediateObject` for possible use with `clearImmediate()`. Optionally you can also pass arguments to the callback. @@ -64,7 +64,7 @@ immediately, as if the `delay` was set to 1. ## unref() -The opaque value returned by `setTimeout` and `setInterval` also has the method +The opaque value returned by [`setTimeout`][] and [`setInterval`][] also has the method `timer.unref()` which will allow you to create a timer that is active but if it is the only item left in the event loop, it won't keep the program running. If the timer is already `unref`d calling `unref` again will have no effect. @@ -74,3 +74,6 @@ will wakeup the event loop, creating too many of these may adversely effect event loop performance -- use wisely. Returns the timer. + +[`setInterval`]: timers.html#timers_setinterval_callback_delay_arg +[`setTimeout`]: timers.html#timers_settimeout_callback_delay_arg diff --git a/doc/api/tls.markdown b/doc/api/tls.markdown index a0261bf1e59539..469b0d64733be2 100644 --- a/doc/api/tls.markdown +++ b/doc/api/tls.markdown @@ -164,7 +164,7 @@ Returned by tls.createSecurePair. The event is emitted from the SecurePair once the pair has successfully established a secure connection. -Similarly to the checking for the server 'secureConnection' event, +Similarly to the checking for the server `'secureConnection'` event, pair.cleartext.authorized should be checked to confirm whether the certificate used properly authorized. @@ -179,7 +179,7 @@ connections using TLS or SSL. `function (exception, tlsSocket) { }` -When a client connection emits an 'error' event before secure connection is +When a client connection emits an `'error'` event before secure connection is established - it will be forwarded here. `tlsSocket` is the [tls.TLSSocket][] that the error originated from. @@ -213,9 +213,9 @@ Calling `callback(err)` will result in a `socket.destroy(err)` call. Typical flow: -1. Client connects to server and sends `OCSPRequest` to it (via status info +1. Client connects to server and sends `'OCSPRequest'` to it (via status info extension in ClientHello.) -2. Server receives request and invokes `OCSPRequest` event listener if present +2. Server receives request and invokes `'OCSPRequest'` event listener if present 3. Server grabs OCSP url from either `certificate` or `issuer` and performs an [OCSP request] to the CA 4. Server receives `OCSPResponse` from CA and sends it back to client via @@ -249,11 +249,11 @@ established after addition of event listener. Here's an example for using TLS session resumption: var tlsSessionStore = {}; - server.on('newSession', function(id, data, cb) { + server.on('newSession', (id, data, cb) => { tlsSessionStore[id.toString('hex')] = data; cb(); }); - server.on('resumeSession', function(id, cb) { + server.on('resumeSession', (id, cb) => { cb(null, tlsSessionStore[id.toString('hex')] || null); }); @@ -333,7 +333,7 @@ or currently pending server connections will use previous keys. ## Class: tls.TLSSocket -This is a wrapped version of [net.Socket][] that does transparent encryption +This is a wrapped version of [`net.Socket`][] that does transparent encryption of written data and all required TLS negotiation. This instance implements a duplex [Stream][] interfaces. It has all the @@ -346,7 +346,7 @@ only return data while the connection is open. Construct a new TLSSocket object from existing TCP socket. -`socket` is an instance of [net.Socket][] +`socket` is an instance of [`net.Socket`][] `options` is an optional object that might contain following properties: @@ -356,7 +356,7 @@ Construct a new TLSSocket object from existing TCP socket. - `isServer`: If `true` - TLS socket will be instantiated in server-mode. Default: `false` - - `server`: An optional [net.Server][] instance + - `server`: An optional [`net.Server`][] instance - `requestCert`: Optional, see [tls.createSecurePair][] @@ -369,7 +369,7 @@ Construct a new TLSSocket object from existing TCP socket. - `session`: Optional, a `Buffer` instance, containing TLS session - `requestOCSP`: Optional, if `true` - OCSP status request extension would - be added to client hello, and `OCSPResponse` event will be emitted on socket + be added to client hello, and `'OCSPResponse'` event will be emitted on socket before establishing secure communication ### Event: 'OCSPResponse' @@ -422,7 +422,7 @@ Example: { name: 'AES256-SHA', version: 'TLSv1/SSLv3' } See SSL_CIPHER_get_name() and SSL_CIPHER_get_version() in -http://www.openssl.org/docs/ssl/ssl.html#DEALING_WITH_CIPHERS for more +https://www.openssl.org/docs/ssl/ssl.html#DEALING_WITH_CIPHERS for more information. ### tlsSocket.getPeerCertificate([ detailed ]) @@ -546,9 +546,9 @@ Creates a new client connection to the given `port` and `host` (old API) or - `cert`: A string or `Buffer` containing the certificate key of the client in PEM format. (Could be an array of certs). - - `ca`: An array of strings or `Buffer`s of trusted certificates in PEM - format. If this is omitted several well known "root" CAs will be used, - like VeriSign. These are used to authorize connections. + - `ca`: A string, `Buffer` or array of strings or `Buffer`s of trusted + certificates in PEM format. If this is omitted several well known "root" + CAs will be used, like VeriSign. These are used to authorize connections. - `ciphers`: A string describing the ciphers to use or exclude, separated by `:`. Uses the same default cipher suite as `tls.createServer`. @@ -575,16 +575,16 @@ Creates a new client connection to the given `port` and `host` (old API) or - `session`: A `Buffer` instance, containing TLS session. The `callback` parameter will be added as a listener for the -['secureConnect'][] event. +[`'secureConnect'`][] event. `tls.connect()` returns a [tls.TLSSocket][] object. Here is an example of a client of echo server as described previously: - var tls = require('tls'); - var fs = require('fs'); + const tls = require('tls'); + const fs = require('fs'); - var options = { + const options = { // These are necessary only if using the client certificate authentication key: fs.readFileSync('client-key.pem'), cert: fs.readFileSync('client-cert.pem'), @@ -593,40 +593,40 @@ Here is an example of a client of echo server as described previously: ca: [ fs.readFileSync('server-cert.pem') ] }; - var socket = tls.connect(8000, options, function() { + var socket = tls.connect(8000, options, () => { console.log('client connected', socket.authorized ? 'authorized' : 'unauthorized'); process.stdin.pipe(socket); process.stdin.resume(); }); socket.setEncoding('utf8'); - socket.on('data', function(data) { + socket.on('data', (data) => { console.log(data); }); - socket.on('end', function() { + socket.on('end', () => { server.close(); }); Or - var tls = require('tls'); - var fs = require('fs'); + const tls = require('tls'); + const fs = require('fs'); - var options = { + const options = { pfx: fs.readFileSync('client.pfx') }; - var socket = tls.connect(8000, options, function() { + var socket = tls.connect(8000, options, () => { console.log('client connected', socket.authorized ? 'authorized' : 'unauthorized'); process.stdin.pipe(socket); process.stdin.resume(); }); socket.setEncoding('utf8'); - socket.on('data', function(data) { + socket.on('data', (data) => { console.log(data); }); - socket.on('end', function() { + socket.on('end', () => { server.close(); }); @@ -643,13 +643,14 @@ dictionary with keys: objects in the format `{pem: key, passphrase: passphrase}`. (Required) * `passphrase` : A string of passphrase for the private key or pfx * `cert` : A string holding the PEM encoded certificate -* `ca` : Either a string or list of strings of PEM encoded CA - certificates to trust. +* `ca`: A string, `Buffer` or array of strings or `Buffer`s of trusted + certificates in PEM format. If this is omitted several well known "root" + CAs will be used, like VeriSign. These are used to authorize connections. * `crl` : Either a string or list of strings of PEM encoded CRLs (Certificate Revocation List) * `ciphers`: A string describing the ciphers to use or exclude. Consult - + for details on the format. * `honorCipherOrder` : When choosing a cipher, use the server's preferences instead of the client preferences. For further details see `tls` module @@ -687,7 +688,7 @@ NOTE: `cleartext` has the same APIs as [tls.TLSSocket][] ## tls.createServer(options[, secureConnectionListener]) Creates a new [tls.Server][]. The `connectionListener` argument is -automatically set as a listener for the [secureConnection][] event. The +automatically set as a listener for the [`'secureConnection'`][] event. The `options` object has these possibilities: - `pfx`: A string or `Buffer` containing the private key, certificate and @@ -704,9 +705,9 @@ automatically set as a listener for the [secureConnection][] event. The - `cert`: A string or `Buffer` containing the certificate key of the server in PEM format. (Could be an array of certs). (Required) - - `ca`: An array of strings or `Buffer`s of trusted certificates in PEM - format. If this is omitted several well known "root" CAs will be used, - like VeriSign. These are used to authorize connections. + - `ca`: A string, `Buffer` or array of strings or `Buffer`s of trusted + certificates in PEM format. If this is omitted several well known "root" + CAs will be used, like VeriSign. These are used to authorize connections. - `crl` : Either a string or list of strings of PEM encoded CRLs (Certificate Revocation List) @@ -813,10 +814,10 @@ automatically set as a listener for the [secureConnection][] event. The Here is a simple example echo server: - var tls = require('tls'); - var fs = require('fs'); + const tls = require('tls'); + const fs = require('fs'); - var options = { + const options = { key: fs.readFileSync('server-key.pem'), cert: fs.readFileSync('server-cert.pem'), @@ -827,23 +828,23 @@ Here is a simple example echo server: ca: [ fs.readFileSync('client-cert.pem') ] }; - var server = tls.createServer(options, function(socket) { + var server = tls.createServer(options, (socket) => { console.log('server connected', socket.authorized ? 'authorized' : 'unauthorized'); - socket.write("welcome!\n"); + socket.write('welcome!\n'); socket.setEncoding('utf8'); socket.pipe(socket); }); - server.listen(8000, function() { + server.listen(8000, () => { console.log('server bound'); }); Or - var tls = require('tls'); - var fs = require('fs'); + const tls = require('tls'); + const fs = require('fs'); - var options = { + const options = { pfx: fs.readFileSync('server.pfx'), // This is necessary only if using the client certificate authentication. @@ -851,14 +852,14 @@ Or }; - var server = tls.createServer(options, function(socket) { + var server = tls.createServer(options, (socket) => { console.log('server connected', socket.authorized ? 'authorized' : 'unauthorized'); - socket.write("welcome!\n"); + socket.write('welcome!\n'); socket.setEncoding('utf8'); socket.pipe(socket); }); - server.listen(8000, function() { + server.listen(8000, () => { console.log('server bound'); }); You can test this server by connecting to it with `openssl s_client`: @@ -875,29 +876,29 @@ Example: var ciphers = tls.getCiphers(); console.log(ciphers); // ['AES128-SHA', 'AES256-SHA', ...] -[OpenSSL cipher list format documentation]: http://www.openssl.org/docs/apps/ciphers.html#CIPHER_LIST_FORMAT -[Chrome's 'modern cryptography' setting]: http://www.chromium.org/Home/chromium-security/education/tls#TOC-Deprecation-of-TLS-Features-Algorithms-in-Chrome +[OpenSSL cipher list format documentation]: https://www.openssl.org/docs/apps/ciphers.html#CIPHER_LIST_FORMAT +[Chrome's 'modern cryptography' setting]: https://www.chromium.org/Home/chromium-security/education/tls#TOC-Deprecation-of-TLS-Features-Algorithms-in-Chrome [specific attacks affecting larger AES key sizes]: https://www.schneier.com/blog/archives/2009/07/another_new_aes.html -[BEAST attacks]: http://blog.ivanristic.com/2011/10/mitigating-the-beast-attack-on-tls.html +[BEAST attacks]: https://blog.ivanristic.com/2011/10/mitigating-the-beast-attack-on-tls.html [crypto.getCurves()]: crypto.html#crypto_crypto_getcurves [tls.createServer]: #tls_tls_createserver_options_secureconnectionlistener [tls.createSecurePair]: #tls_tls_createsecurepair_context_isserver_requestcert_rejectunauthorized_options [tls.TLSSocket]: #tls_class_tls_tlssocket -[net.Server]: net.html#net_class_net_server -[net.Socket]: net.html#net_class_net_socket +[`net.Server`]: net.html#net_class_net_server +[`net.Socket`]: net.html#net_class_net_socket [net.Server.address()]: net.html#net_server_address -['secureConnect']: #tls_event_secureconnect -[secureConnection]: #tls_event_secureconnection +[`'secureConnect'`]: #tls_event_secureconnect +[`'secureConnection'`]: #tls_event_secureconnection [Stream]: stream.html#stream_stream -[SSL_METHODS]: http://www.openssl.org/docs/ssl/ssl.html#DEALING_WITH_PROTOCOL_METHODS +[SSL_METHODS]: https://www.openssl.org/docs/ssl/ssl.html#DEALING_WITH_PROTOCOL_METHODS [tls.Server]: #tls_class_tls_server -[SSL_CTX_set_timeout]: http://www.openssl.org/docs/ssl/SSL_CTX_set_timeout.html -[RFC 4492]: http://www.rfc-editor.org/rfc/rfc4492.txt -[Forward secrecy]: http://en.wikipedia.org/wiki/Perfect_forward_secrecy +[SSL_CTX_set_timeout]: https://www.openssl.org/docs/ssl/SSL_CTX_set_timeout.html +[RFC 4492]: https://www.rfc-editor.org/rfc/rfc4492.txt +[Forward secrecy]: https://en.wikipedia.org/wiki/Perfect_forward_secrecy [DHE]: https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange [ECDHE]: https://en.wikipedia.org/wiki/Elliptic_curve_Diffie%E2%80%93Hellman -[asn1.js]: http://npmjs.org/package/asn1.js -[OCSP request]: http://en.wikipedia.org/wiki/OCSP_stapling +[asn1.js]: https://npmjs.org/package/asn1.js +[OCSP request]: https://en.wikipedia.org/wiki/OCSP_stapling [TLS recommendations]: https://wiki.mozilla.org/Security/Server_Side_TLS [TLS Session Tickets]: https://www.ietf.org/rfc/rfc5077.txt [getPeerCertificate]: #tls_tlssocket_getpeercertificate_detailed diff --git a/doc/api/tty.markdown b/doc/api/tty.markdown index 279a1dd0b9440e..f01cedd702da9a 100644 --- a/doc/api/tty.markdown +++ b/doc/api/tty.markdown @@ -45,20 +45,20 @@ ever created (and only when `isatty(1)` is true). Emitted by `refreshSize()` when either of the `columns` or `rows` properties has changed. - process.stdout.on('resize', function() { + process.stdout.on('resize', () => { console.log('screen size has changed!'); - console.log(process.stdout.columns + 'x' + process.stdout.rows); + console.log(`${process.stdout.columns}x${process.stdout.rows}`); }); ### ws.columns A `Number` that gives the number of columns the TTY currently has. This property -gets updated on "resize" events. +gets updated on `'resize'` events. ### ws.rows A `Number` that gives the number of rows the TTY currently has. This property -gets updated on "resize" events. +gets updated on `'resize'` events. ## tty.isatty(fd) diff --git a/doc/api/url.markdown b/doc/api/url.markdown index 8c8cd5bf1b85bf..c6a4b2351b0227 100644 --- a/doc/api/url.markdown +++ b/doc/api/url.markdown @@ -87,12 +87,12 @@ Here's how the formatting process works: * `path` will be ignored. * `protocol` is treated the same with or without the trailing `:` (colon). * The protocols `http`, `https`, `ftp`, `gopher`, `file` will be - postfixed with `://` (colon-slash-slash). + postfixed with `://` (colon-slash-slash) as long as `host`/`hostname` are present. * All other protocols `mailto`, `xmpp`, `aim`, `sftp`, `foo`, etc will be postfixed with `:` (colon). * `slashes` set to `true` if the protocol requires `://` (colon-slash-slash) * Only needs to be set for protocols not previously listed as requiring - slashes, such as `mongodb://localhost:8000/`. + slashes, such as `mongodb://localhost:8000/`, or if `host`/`hostname` are absent. * `auth` will be used if present. * `hostname` will only be used if `host` is absent. * `port` will only be used if `host` is absent. diff --git a/doc/api/util.markdown b/doc/api/util.markdown index e4a85cafba3854..4574ae452b231b 100644 --- a/doc/api/util.markdown +++ b/doc/api/util.markdown @@ -5,12 +5,12 @@ These functions are in the module `'util'`. Use `require('util')` to access them. -The `util` module is primarily designed to support the needs of node.js's +The `util` module is primarily designed to support the needs of Node.js's internal APIs. Many of these utilities are useful for your own programs. If you find that these functions are lacking for your purposes, however, you are encouraged to write your own utilities. We are not interested in any future additions to the `util` module that -are unnecessary for node.js's internal functionality. +are unnecessary for Node.js's internal functionality. ## util.debug(string) @@ -53,7 +53,7 @@ comma. For example, `NODE_DEBUG=fs,net,tls`. Marks that a method should not be used any more. - var util = require('util'); + const util = require('util'); exports.puts = util.deprecate(function() { for (var i = 0, len = arguments.length; i < len; ++i) { @@ -123,8 +123,8 @@ prototype of `constructor` will be set to a new object created from As an additional convenience, `superConstructor` will be accessible through the `constructor.super_` property. - var util = require("util"); - var EventEmitter = require("events"); + const util = require('util'); + const EventEmitter = require('events'); function MyStream() { EventEmitter.call(this); @@ -133,7 +133,7 @@ through the `constructor.super_` property. util.inherits(MyStream, EventEmitter); MyStream.prototype.write = function(data) { - this.emit("data", data); + this.emit('data', data); } var stream = new MyStream(); @@ -141,10 +141,10 @@ through the `constructor.super_` property. console.log(stream instanceof EventEmitter); // true console.log(MyStream.super_ === EventEmitter); // true - stream.on("data", function(data) { - console.log('Received data: "' + data + '"'); + stream.on('data', (data) => { + console.log(`Received data: "${data}"`); }) - stream.write("It works!"); // Received data: "It works!" + stream.write('It works!'); // Received data: "It works!" ## util.inspect(object[, options]) @@ -168,7 +168,7 @@ formatted string: Example of inspecting all properties of the `util` object: - var util = require('util'); + const util = require('util'); console.log(util.inspect(util, { showHidden: true, depth: null })); @@ -207,11 +207,11 @@ There are also `bold`, `italic`, `underline` and `inverse` codes. Objects also may define their own `inspect(depth)` function which `util.inspect()` will invoke and use the result of when inspecting the object: - var util = require('util'); + const util = require('util'); var obj = { name: 'nate' }; obj.inspect = function(depth) { - return '{' + this.name + '}'; + return `{${this.name}}`; }; util.inspect(obj); @@ -233,11 +233,11 @@ formatted according to the returned Object. This is similar to how Stability: 0 - Deprecated -Internal alias for Array.isArray. +Internal alias for [`Array.isArray`][]. Returns `true` if the given "object" is an `Array`. `false` otherwise. - var util = require('util'); + const util = require('util'); util.isArray([]) // true @@ -252,7 +252,7 @@ Returns `true` if the given "object" is an `Array`. `false` otherwise. Returns `true` if the given "object" is a `Boolean`. `false` otherwise. - var util = require('util'); + const util = require('util'); util.isBoolean(1) // false @@ -269,7 +269,7 @@ Use `Buffer.isBuffer()` instead. Returns `true` if the given "object" is a `Buffer`. `false` otherwise. - var util = require('util'); + const util = require('util'); util.isBuffer({ length: 0 }) // false @@ -284,7 +284,7 @@ Returns `true` if the given "object" is a `Buffer`. `false` otherwise. Returns `true` if the given "object" is a `Date`. `false` otherwise. - var util = require('util'); + const util = require('util'); util.isDate(new Date()) // true @@ -297,9 +297,9 @@ Returns `true` if the given "object" is a `Date`. `false` otherwise. Stability: 0 - Deprecated -Returns `true` if the given "object" is an `Error`. `false` otherwise. +Returns `true` if the given "object" is an [`Error`][]. `false` otherwise. - var util = require('util'); + const util = require('util'); util.isError(new Error()) // true @@ -314,7 +314,7 @@ Returns `true` if the given "object" is an `Error`. `false` otherwise. Returns `true` if the given "object" is a `Function`. `false` otherwise. - var util = require('util'); + const util = require('util'); function Foo() {} var Bar = function() {}; @@ -332,7 +332,7 @@ Returns `true` if the given "object" is a `Function`. `false` otherwise. Returns `true` if the given "object" is strictly `null`. `false` otherwise. - var util = require('util'); + const util = require('util'); util.isNull(0) // false @@ -347,7 +347,7 @@ Returns `true` if the given "object" is strictly `null`. `false` otherwise. Returns `true` if the given "object" is `null` or `undefined`. `false` otherwise. - var util = require('util'); + const util = require('util'); util.isNullOrUndefined(0) // false @@ -362,7 +362,7 @@ Returns `true` if the given "object" is `null` or `undefined`. `false` otherwise Returns `true` if the given "object" is a `Number`. `false` otherwise. - var util = require('util'); + const util = require('util'); util.isNumber(false) // false @@ -380,7 +380,7 @@ Returns `true` if the given "object" is a `Number`. `false` otherwise. Returns `true` if the given "object" is strictly an `Object` __and__ not a `Function`. `false` otherwise. - var util = require('util'); + const util = require('util'); util.isObject(5) // false @@ -397,7 +397,7 @@ Returns `true` if the given "object" is strictly an `Object` __and__ not a Returns `true` if the given "object" is a primitive type. `false` otherwise. - var util = require('util'); + const util = require('util'); util.isPrimitive(5) // true @@ -424,7 +424,7 @@ Returns `true` if the given "object" is a primitive type. `false` otherwise. Returns `true` if the given "object" is a `RegExp`. `false` otherwise. - var util = require('util'); + const util = require('util'); util.isRegExp(/some regexp/) // true @@ -439,7 +439,7 @@ Returns `true` if the given "object" is a `RegExp`. `false` otherwise. Returns `true` if the given "object" is a `String`. `false` otherwise. - var util = require('util'); + const util = require('util'); util.isString('') // true @@ -456,7 +456,7 @@ Returns `true` if the given "object" is a `String`. `false` otherwise. Returns `true` if the given "object" is a `Symbol`. `false` otherwise. - var util = require('util'); + const util = require('util'); util.isSymbol(5) // false @@ -471,7 +471,7 @@ Returns `true` if the given "object" is a `Symbol`. `false` otherwise. Returns `true` if the given "object" is `undefined`. `false` otherwise. - var util = require('util'); + const util = require('util'); var foo; util.isUndefined(5) @@ -505,4 +505,6 @@ Deprecated predecessor of `stream.pipe()`. Deprecated predecessor of `console.log`. +[`Array.isArray`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray [constructor]: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/constructor +[`Error`]: errors.html#errors_class_error diff --git a/doc/api/v8.markdown b/doc/api/v8.markdown index ea0d04d25b7efd..70abd6c6473f24 100644 --- a/doc/api/v8.markdown +++ b/doc/api/v8.markdown @@ -3,7 +3,7 @@ Stability: 2 - Stable This module exposes events and interfaces specific to the version of [V8][] -built with node.js. These interfaces are subject to change by upstream and are +built with Node.js. These interfaces are subject to change by upstream and are therefore not covered under the stability index. ## getHeapStatistics() @@ -27,7 +27,7 @@ Set additional V8 command line flags. Use with care; changing settings after the VM has started may result in unpredictable behavior, including crashes and data loss. Or it may simply do nothing. -The V8 options available for a version of node.js may be determined by running +The V8 options available for a version of Node.js may be determined by running `node --v8-options`. An unofficial, community-maintained list of options and their effects is available [here][]. @@ -35,7 +35,7 @@ Usage: ``` // Print GC events to stdout for one minute. -var v8 = require('v8'); +const v8 = require('v8'); v8.setFlagsFromString('--trace_gc'); setTimeout(function() { v8.setFlagsFromString('--notrace_gc'); }, 60e3); ``` diff --git a/doc/api/vm.markdown b/doc/api/vm.markdown index 870a9551215abf..07e99ac735677c 100644 --- a/doc/api/vm.markdown +++ b/doc/api/vm.markdown @@ -6,7 +6,7 @@ You can access this module with: - var vm = require('vm'); + const vm = require('vm'); JavaScript code can be compiled and run immediately or compiled, saved, and run later. @@ -26,10 +26,16 @@ The options when creating a script are: - `filename`: allows you to control the filename that shows up in any stack traces produced from this script. +- `lineOffset`: allows you to add an offset to the line number that is + displayed in stack traces +- `columnOffset`: allows you to add an offset to the column number that is + displayed in stack traces - `displayErrors`: whether or not to print any errors to stderr, with the line of code that caused them highlighted, before throwing an exception. Applies only to syntax errors compiling the code; errors while running the code are controlled by the options to the script's methods. +- `timeout`: a number of milliseconds to execute `code` before terminating + execution. If execution is terminated, an [`Error`][] will be thrown. ### script.runInContext(contextifiedSandbox[, options]) @@ -42,8 +48,8 @@ and returns the result. Running code does not have access to local scope. Example: compile code that increments a global variable and sets one, then execute the code multiple times. These globals are contained in the sandbox. - var util = require('util'); - var vm = require('vm'); + const util = require('util'); + const vm = require('vm'); var sandbox = { animal: 'cat', @@ -79,14 +85,14 @@ Example: compile code that sets a global variable, then execute the code multiple times in different contexts. These globals are set on and contained in the sandboxes. - var util = require('util'); - var vm = require('vm'); + const util = require('util'); + const vm = require('vm'); - var sandboxes = [{}, {}, {}]; + const sandboxes = [{}, {}, {}]; - var script = new vm.Script('globalVar = "set"'); + const script = new vm.Script('globalVar = "set"'); - sandboxes.forEach(function (sandbox) { + sandboxes.forEach((sandbox) => { script.runInNewContext(sandbox); }); @@ -108,11 +114,11 @@ current `global` object. Example of using `script.runInThisContext` to compile code once and run it multiple times: - var vm = require('vm'); + const vm = require('vm'); global.globalVar = 0; - var script = new vm.Script('globalVar += 1', { filename: 'myfile.vm' }); + const script = new vm.Script('globalVar += 1', { filename: 'myfile.vm' }); for (var i = 0; i < 1000; ++i) { script.runInThisContext(); @@ -124,12 +130,18 @@ multiple times: The options for running a script are: -- `displayErrors`: whether or not to print any runtime errors to stderr, with - the line of code that caused them highlighted, before throwing an exception. +- `filename`: allows you to control the filename that shows up in any stack + traces produced. +- `lineOffset`: allows you to add an offset to the line number that is + displayed in stack traces +- `columnOffset`: allows you to add an offset to the column number that is + displayed in stack traces +- `displayErrors`: whether or not to print any errors to stderr, with the + line of code that caused them highlighted, before throwing an exception. Applies only to runtime errors executing the code; it is impossible to create a `Script` instance with syntax errors, as the constructor will throw. - `timeout`: a number of milliseconds to execute the script before terminating - execution. If execution is terminated, an `Error` will be thrown. + execution. If execution is terminated, an [`Error`][] will be thrown. ## vm.createContext([sandbox]) @@ -164,10 +176,10 @@ returns the result. Running code does not have access to local scope. The Example: compile and execute different scripts in a single existing context. - var util = require('util'); - var vm = require('vm'); + const util = require('util'); + const vm = require('vm'); - var sandbox = { globalVar: 1 }; + const sandbox = { globalVar: 1 }; vm.createContext(sandbox); for (var i = 0; i < 10; ++i) { @@ -186,7 +198,7 @@ separate process. `vm.runInDebugContext` compiles and executes `code` inside the V8 debug context. The primary use case is to get access to the V8 debug object: - var Debug = vm.runInDebugContext('Debug'); + const Debug = vm.runInDebugContext('Debug'); Debug.scripts().forEach(function(script) { console.log(script.name); }); Note that the debug context and object are intrinsically tied to V8's debugger @@ -205,10 +217,10 @@ the sandbox as the global object and returns the result. Example: compile and execute code that increments a global variable and sets a new one. These globals are contained in the sandbox. - var util = require('util'); - var vm = require('vm'); + const util = require('util'); + const vm = require('vm'); - var sandbox = { + const sandbox = { animal: 'cat', count: 2 }; @@ -230,14 +242,14 @@ code does not have access to local scope, but does have access to the current Example of using `vm.runInThisContext` and `eval` to run the same code: - var vm = require('vm'); + const vm = require('vm'); var localVar = 'initial value'; - var vmResult = vm.runInThisContext('localVar = "vm";'); + const vmResult = vm.runInThisContext('localVar = "vm";'); console.log('vmResult: ', vmResult); console.log('localVar: ', localVar); - var evalResult = eval('localVar = "eval";'); + const evalResult = eval('localVar = "eval";'); console.log('evalResult: ', evalResult); console.log('localVar: ', localVar); @@ -252,12 +264,17 @@ e.g. `(0,eval)('code')`. However, it also has the following additional options: - `filename`: allows you to control the filename that shows up in any stack traces produced. +- `lineOffset`: allows you to add an offset to the line number that is + displayed in stack traces +- `columnOffset`: allows you to add an offset to the column number that is + displayed in stack traces - `displayErrors`: whether or not to print any errors to stderr, with the line of code that caused them highlighted, before throwing an exception. Will capture both syntax errors from compiling `code` and runtime errors thrown by executing the compiled code. Defaults to `true`. - `timeout`: a number of milliseconds to execute `code` before terminating - execution. If execution is terminated, an `Error` will be thrown. + execution. If execution is terminated, an [`Error`][] will be thrown. -[indirect `eval` call]: http://es5.github.io/#x10.4.2 -[global object]: http://es5.github.io/#x15.1 +[indirect `eval` call]: https://es5.github.io/#x10.4.2 +[global object]: https://es5.github.io/#x15.1 +[`Error`]: errors.html#errors_class_error diff --git a/doc/api/zlib.markdown b/doc/api/zlib.markdown index 8d4d7e87e3918f..5f238be5bff8d8 100644 --- a/doc/api/zlib.markdown +++ b/doc/api/zlib.markdown @@ -4,7 +4,7 @@ You can access this module with: - var zlib = require('zlib'); + const zlib = require('zlib'); This provides bindings to Gzip/Gunzip, Deflate/Inflate, and DeflateRaw/InflateRaw classes. Each class takes the same options, and @@ -15,24 +15,24 @@ is a readable/writable Stream. Compressing or decompressing a file can be done by piping an fs.ReadStream into a zlib stream, then into an fs.WriteStream. - var gzip = zlib.createGzip(); - var fs = require('fs'); - var inp = fs.createReadStream('input.txt'); - var out = fs.createWriteStream('input.txt.gz'); + const gzip = zlib.createGzip(); + const fs = require('fs'); + const inp = fs.createReadStream('input.txt'); + const out = fs.createWriteStream('input.txt.gz'); inp.pipe(gzip).pipe(out); Compressing or decompressing data in one step can be done by using the convenience methods. - var input = '.................................'; + const input = '.................................'; zlib.deflate(input, function(err, buffer) { if (!err) { console.log(buffer.toString('base64')); } }); - var buffer = new Buffer('eJzT0yMAAGTvBe8=', 'base64'); + const buffer = new Buffer('eJzT0yMAAGTvBe8=', 'base64'); zlib.unzip(buffer, function(err, buffer) { if (!err) { console.log(buffer.toString()); @@ -48,14 +48,14 @@ ought to be cached. See [Memory Usage Tuning][] below for more information on the speed/memory/compression tradeoffs involved in zlib usage. // client request example - var zlib = require('zlib'); - var http = require('http'); - var fs = require('fs'); - var request = http.get({ host: 'izs.me', + const zlib = require('zlib'); + const http = require('http'); + const fs = require('fs'); + const request = http.get({ host: 'izs.me', path: '/', port: 80, headers: { 'accept-encoding': 'gzip,deflate' } }); - request.on('response', function(response) { + request.on('response', (response) => { var output = fs.createWriteStream('izs.me_index.html'); switch (response.headers['content-encoding']) { @@ -75,10 +75,10 @@ on the speed/memory/compression tradeoffs involved in zlib usage. // server example // Running a gzip operation on every request is quite expensive. // It would be much more efficient to cache the compressed buffer. - var zlib = require('zlib'); - var http = require('http'); - var fs = require('fs'); - http.createServer(function(request, response) { + const zlib = require('zlib'); + const http = require('http'); + const fs = require('fs'); + http.createServer((request, response) => { var raw = fs.createReadStream('index.html'); var acceptEncoding = request.headers['accept-encoding']; if (!acceptEncoding) { @@ -356,8 +356,8 @@ Decompress a raw Buffer with Inflate. Decompress a raw Buffer with Unzip. -[accept-encoding]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3 -[content-encoding]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.11 +[accept-encoding]: https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3 +[content-encoding]: https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.11 [Memory Usage Tuning]: #zlib_memory_usage_tuning [zlib documentation]: http://zlib.net/manual.html#Constants [options]: #zlib_class_options diff --git a/doc/api_assets/style.css b/doc/api_assets/style.css index 6f26c3a0c71075..4c8d64ab5579c3 100644 --- a/doc/api_assets/style.css +++ b/doc/api_assets/style.css @@ -11,26 +11,28 @@ body { font-size: 62.5%; margin: 0; padding: 0; - color: #3a3a3a; - background: #fcfefa; + color: #333; + background: #fff; } #content { font-size: 1.8em; } -a { - color: #FE5210; +a, +a:link, +a:active { + color: #80bd01; text-decoration: none; -} - -a:visited { - color: #FE7110; + border-radius: 2px; + padding: .1em .2em; + margin: -.1em 0; } a:hover, a:focus { - color: #FFA158; + color: #fff; + background-color: #80bd01; } strong { @@ -170,7 +172,6 @@ dd + dt.pre { } h1, h2, h3, h4, h5, h6 { - color: #301004; text-rendering: optimizeLegibility; font-weight: 700; position: relative; @@ -280,7 +281,7 @@ code.pre { } #intro a { - color: #333; + color: #ddd; font-size: 1.25em; font-weight: bold; } @@ -296,7 +297,6 @@ hr { } #toc h2 { - color: #C73E09; margin-top: 0; font-size: 1.0em; line-height: 0; @@ -339,12 +339,14 @@ p code, li code { font-size: 0.9em; color: #040404; - background-color: #f2f5f0; - padding: 0.2em 0.4em; + background-color: #f0f0f0; + padding: .1em .2em; + border-radius: 2px; } a code { color: inherit; + background: inherit; } span.type { @@ -360,12 +362,13 @@ span.type { #column1.interior { width: 702px; - border-left: 234px solid #f2f5f0; + margin-left: 234px; padding-left: 2.0em; } #column2.interior { width: 234px; + background: #333; position: fixed; height: 100%; overflow-y: scroll; @@ -377,8 +380,8 @@ span.type { bottom: 0; left: 0; width: 234px; - height: 5em; - background: linear-gradient(rgba(242,245,240, 0), rgba(242,245,240, 1)); + height: 4em; + background: linear-gradient(rgba(242,245,240, 0), rgba(51, 51, 51, 1)); pointer-events: none; } @@ -386,9 +389,9 @@ span.type { list-style: none; margin-left: 0em; margin-top: 1.25em; - background: #f2f5f0; + background: #333; margin-bottom: 0; - padding-bottom: 4em; + padding-bottom: 3em; } #column2 ul li { @@ -403,19 +406,24 @@ span.type { } #column2 ul li a { - color: #7a7a7a; + color: #ccc; + border-radius: 0; } -#column2 ul li a.active { - color: #533; - border-bottom: 1px solid #533; +#column2 ul li a.active, +#column2 ul li a.active:hover, +#column2 ul li a.active:focus { + color: #80bd01; + border-radius: 0; + border-bottom: 1px solid #80bd01; + background: none; } -#footer { - padding: 0; - min-height: 24px; - background: #333; - color: white; +#intro a:hover, +#column2 ul li a:hover, +#column2 ul li a:focus { + color: #fff; + background: none; } span > .mark, @@ -455,7 +463,7 @@ td > *:last-child { font-size: 2.1em; } #column1.interior { - border-left: 0; + margin-left: 0; padding-left: 0.5em; padding-right: 0.5em; width: auto; @@ -473,7 +481,7 @@ td > *:last-child { font-size: 2.4em; } #column1.interior { - border-left: 0; + margin-left: 0; padding-left: 0.5em; padding-right: 0.5em; width: auto; diff --git a/doc/ctc-meetings/2015-10-28.md b/doc/ctc-meetings/2015-10-28.md new file mode 100644 index 00000000000000..5efe94454ad3f8 --- /dev/null +++ b/doc/ctc-meetings/2015-10-28.md @@ -0,0 +1,276 @@ +# Node Foundation CTC Meeting 2015-10-28 + +## Links + +* **Audio Recording**: https://soundcloud.com/node-foundation/ctc-meeting-2015-10-28 +* **GitHub Issue**: https://github.com/nodejs/node/issues/3561 +* **Minutes Google Doc**: +* _Previous Minutes Google Doc: _ + +## Present + +* Rod Vagg (CTC) +* Brian White (CTC) +* James Snell (CTC) +* Chris Dickinson (CTC) +* Ben Noordhuis (CTC) +* Jeremiah Senkpiel (CTC) +* Trevor Norris (CTC) +* Alexis Campailla (CTC) +* Mikeal Rogers (observer) +* Shigeki Ohtsu (CTC) +* Seth Thompson (observer) +* Bert Belder (CTC) +* Fedor Indutny (CTC) +* Ben Noordhuis (CTC) +* Colin Ihrig (CTC) + +## Agenda + +Extracted from **tsc-agenda** labelled issues and pull requests in the nodejs org prior to meeting. + +### nodejs/node + +* Load JSON-LD in the same way as JSON [#3502](https://github.com/nodejs/node/pull/3502) +* fs: decode filenames using UTF-8 in fs.watch [#3401](https://github.com/nodejs/node/pull/3401) +* WG: Considering a new HTTP WG [#3214](https://github.com/nodejs/node/issues/3214) + +## Minutes + +### Review of previous meeting + +* governance: add new collaborators #VIII [#3472](https://github.com/nodejs/node/issues/3472) +* detect "full-icu" module [#3460](https://github.com/nodejs/node/issues/3460) +* WG: Considering a new HTTP WG [#3214](https://github.com/nodejs/node/issues/3214) +* node: deprecate public access to `process.binding` [#2768](https://github.com/nodejs/node/pull/2768) +* node: make listen address configurable [#3316](https://github.com/nodejs/node/pull/3316) + +### Standup + +* Rod Vagg (CTC): Traveling, rc for v5.x, going to put another rc out today, comfortable with it getting released tomorrow. If it slips we’ll put it off until next week. Just need to do more smoke testing on this. +* Brian White (CTC): Not a whole lot this week — triaging, responding to issues. +* James Snell (CTC): Getting HTTP parser up to v2.6; getting 4.2.2 LTS update ready to go. open issue on LTS repo, would love eyes on it, to verify that the commits going into 4.2.2 look good. (https://github.com/nodejs/LTS/issues/50) working with Miles on getting CITGM updated. +* Chris Dickinson (CTC): Some silly build stuff +* Jeremiah Senkpiel (CTC): Not much — computer was dead since last Friday, ): but repaired now. +* Trevor Norris (CTC): Bugs and issues — couple of outstanding PRs around asyncwrap, one done at Fedor’s request to make AsyncWrap public, in order to make JSStream class public +* Alexis Campailla (CTC): Meetings; first API WG meeting, defining scope of the work for the WG, we want to address engine abstraction and native module API and some performance issues; small work in CI to add diagnostics; progress on module build service, going to post finding soon to get feedback +* Mikeal Rogers (observer): getting a lot of interest on a certification program for node, for alternative implementations, looking at notes for API WG (thanks for taking great notes! that was awesome) I reached out to a few people that may contribute as well +* Seth Thompson (observer): No updates this week. +* Bert Belder (CTC): nothing noteworthy +* Ben Noordhuis (CTC): Fixed debugger bugs, reviewed a lot of pull requests. +* Colin Ihrig (CTC): Trying to help out with issue tracker, anticipate in another week ½ I should have significantly more time to work on core. + +### Load JSON-LD in the same way as JSON [#3502](https://github.com/nodejs/node/pull/3502) + +* adds .jsonld files to require.extensions so that they’d load using json loader + +Rod: I raised this to CTC. I see this as a slippery slope, adding anything more to require.extensions. I don’t see how this won’t turn into XML — turns into bloat in formats that folks want to support. My preference would be to let the ecosystem figure this out and let folks write their own JSON loaders. + +Jeremiah: also probably belongs in npm + +James: .jsonld is just a json file with a special syntax internally. I have a module that loads it. It’s very easy to work around. Rename the file to use a json extension. I don’t see the harm in landing it, but if we don’t want to go that route, + +Mikeal: is the patch to add the extension or to give you your own serializer (extension) + +Bert: It seems harmless, but 6 months from now what if someone shows up and says “hey you’re not validating it properly” and then we have to add a validator … I’m very sensitive to slippery slope argument + +Alexis: Is it a different syntax? + +Bert: is every json document a valid jsonld document? + +James: no. + +Mikeal: we’re using a parser from npm, are we going to get a war between parsers, swapping them out? + +James: this doesn’t do any special parsing for jsonld, it just aliases json and uses the existing process. + +Trevor: the problem is what it opens us up to. invariably this leads to more PRs. this patch I don’t have a problem with, but I have a problem with this kind of patch in the future + +Bert: I think we’re reaching consensus here, which is: reject this patch. is anyone here strongly in favor. + +Ben: not in favor. one argument is jsonld is now a standard. but I too am sensitive to the slippery slope argument, so I’m perfectly fine with rejecting it. + +James: when rejecting it, it would be worthwhile to note how to work around it. I can do this. + +Jeremiah: require.extensions is not going to change anytime soon, so folks can write their own. + +Bert: I think we can go to the next issue. + +### fs: decode filenames using UTF-8 in fs.watch [#3401](https://github.com/nodejs/node/pull/3401) + +See also [#3519](https://github.com/nodejs/node/issues/3519) + +Bert: this is Ben’s issue. + +Ben: I wouldn’t say it’s my issue, but I’ve been involved +the thing is that filenames are frequently (but not always) utf8, the problem is now that node in one or two places it doesn’t encode utf8 [Ben, post meeting addition: For background: I thought we had some file logic baked into node::Environment and the dtrace/etw/lttng/systemtap subsystems but turns out that's not the case.] + +Bert: where else are we encoding differently? + +Ben: I can answer this in a few seconds. At least, I think there are more places. Maybe I’m mistaken, also a possibility! + +Jeremiah: I think someone else said it was only fs.watch too. + +Bert: I’ve seen the discussion but I haven’t commented. I think there’s a problem with assuming that all files are all utf8, but it seems inconsequential to assume this everywhere but this one place + +Ben: this is not the best issue to link to, I agree it’s inconsistent to do utf8 in most places and latin1 in only one place. There’s a link to another issue 3519. my beef with the PR is not that it’s a terrible fix, it’s more that decoding to utf8 is not always the right thing to do because not all fs are utf-8. If we’re going to do this it has to be a semver major, and if we’re going to do a semver major, then it may as well be a full fix, which I’ve outlined in 3519. + +Bert: there’s actually some discussions we need to have around these things. Your suggestion is to not land this PR, and instead fix this the right way. Do you think it’s likely that 3519 will see attention any time soon? + +Ben: It’s on my todo list. I should mention that the way node deals with file names has been a thorn in my side for a long time now, I’ve been planning to do something about it for a long time, so take this as you will. + +Bert: my question is: do we take this PR now, ahead of + +Bert: customizable decoding + +Mikeal: is the other one going to be a breaking change? + +Ben: yes + +Bert: or it could be a bugfix? + +Mikeal: so it would make sense to buffer as many changes around that as possible. + +Jeremiah: we could land the semver-major fix on master which would go into 6.x, then if we have time before 6.x we could do the proper fix. maybe that keeps us from fixing it entirely though? + +Ben: that’s my problem, it’s a bandaid that lets us truck on for a another couple of years. + +James?: I don’t really like quick fixes, but … + +Trevor: on the fs doc page, a lot of those calls reference the system level call, on unix do those use utf8 + +Ben: how do you mean? + +Trevor: for example, stat, first arg is char* pathname, if i were to take a utf8 string and read that in… what encoding does it use? + +Ben: syscall is agnostic. kernel treats as string of bytes. in node, we call fs.stat in javascript, string is decoded to utf8, then passed on to the kernel. + +Trevor: if i have a file that’s latin1, I’d have to turn that into a buffer as a binary buffer then tostring it to a utf8 string in order for the file to be open? + +[multiple people are talking] + +Ben: yes. + +Ben: sometimes it’s not possible to open files with funny characters in their names. + +Trevor: if there were a file with invalid utf8 characters it’d be impossible to open those, right? + +Ben: yep. + +James: I’m not a fan of the quick fix. I am okay with incremental so long as the larger task gets done, but … + +Bert: I am in favor of the quick fix, it restores consistency in the way node does things. practically speaking, almost all fs are going to be utf-8. it fixes the problem where fs.watch tells you “hey a file changed” but you go to look and the file’s not there due to the encoding scheme. I’d like to make a little improvement. the problem has been known since at least 2011, and we’ve never gotten around to it. I would not be surprised if it takes another 4 years for someone to take a stab at it. + +Brian: is it possible to get the user’s LOCALE and convert to that before sending it off? + +Ben: that’s worse than what we have now. + +James: the LOCALE often lies. + +Bert: are we going to land the patch to fs.watch? I’d like to have a quick references. + +Trevor: it’s not going to land in 5, we could leave it open until near v6 and land it then if no one is able to get around to the full fix. there’s 5-6 months between 5 and 6… + +Rod: that sounds like a nice compromise. + +### WG: Considering a new HTTP WG [#3214](https://github.com/nodejs/node/issues/3214) + +Rod: I left this on because I thought it’d be nice to get a report from the WG on how it went. + +James: [cd: I am missing folk here]: Jeremiah, Eran Hammer, Doug Wilson, Myles Borins Brian White, Patrick Mueller, and myself. + +We talked about the charter. Looking into what improvements can be made to better support the ecosystem. Making existing impl hookable so that modules could swap out parts of the implementation with their own. Like replacing the parser, or header specific handling. The charter covers that aspect of it, but emphasizes that existing systems are not broken. We have a number of issues that we’ve created to start discussing these. I’ll get these into the doc. + +That’s the short version. Still really early to tell what all will come of it and what kind of schedule it’ll be on. 5th, at [cd: TIME?] +We’ll be drawing up a charter and bringing it back to this group. + +Any other questions? + +Rod: could we get a report on the API WG? + +Trevor: the discussion was mainly around the native api. it went in a direction I wasn’t expecting. I explained my JS API proposal, then it went into a module discussion. ABI compat is straight out, it went in the direction of NAN (API compat, but occasional recompiles). Some discussion arose around abstracting node, like v8 completely. to replace with another VM. How do you handle specific difference like features that are available in one vm or another? or JS features that are/aren’t available between VMs. To target all vms, you end up having to use ES5. I was kind of losing where they were going with it. there are a lot of smart people. We’ll just have to have a discussion about feasibility. + +Ben: Was there any talk about who’s going to do the actual work? + +Trevor: No — it was more theoretical. It was more like the ES committee — develop features then say “go make these.” IF I bring it up I’m sure I can get some solid answers. + +Alexis: I’m trying to push for the Chakra folks to do some of this work. + +Mikeal: [cd: sorry, I missed this.] + +Rod: What companies are involved? Did MS show up? + +Trevor: Yes, I think so. JXCore, IBM was there, can’t remember offhand. + +Bert: JXCore is also secretly MS? + +Alexis: Not a secret! They’re on contract for an industrial IoT project. + +Alexis: IBM was there, Nodesource. + +Mikeal: Looking for someone from samsung’s jerryscript team to join. + +Trevor: My initial proposal was to get something usable. I’ll be out of there if it turns into WASM — if it blows up in size. + +Mikeal: The whole point is to be smaller than the current API, right? + +Bert: Well, not smaller, but … let’s not talk about technical issues + +Alexis: We’ve discussed multiple approaches, and we can tackle the problem from multiple sides. Trevor is tackling it by reducing the size of core. The approach I want to take is FFI interface into native modules. All of these approaches can help us tackle this huge beast into a manageable problem. They’re not competing solutions. + +Bert: We want to avoid scope creep. If the WG comes up with a HUGE proposal with 20 points of view, then no one will ever go do it. + +Trevor: I want to simplify the JS API, and get it to a point where all of the existing api can sit on top of it. If someone wants to do the work of replacing V8, they’ll have a clean entry point into the JS. And then write a set of compliance tests that specify what every entry point does. Writing a bunch for native code without JS tests to back it up would be futile. + +Bert: Restricting it to API design, that in theory, the sort of design goal, is for the API to be sufficient for Node to use. + +Alexis: This would include the native module api? + +Rod: It sounds like HTTP attacked charter first, maybe the API WG needs to do the same, to combat growth of scope. Maybe anyone else on this call that wants to could join and try to define scope? Is there another call scheduled, Trevor? + +Trevor: we’re still collecting times. I’ll mention the ctc in the issue. + +Rod: we should make a new @ctc GH group. + +Bert: which is going to be more fun? + +Rod: The CTC + +Bert: when are we going to split up? + +Rod: Mikeal is organizing another meeting. + +Mikeal: It’s tomorrow at this time slot. + +### node-gyp: Windows users are not happy. [node-gyp#629](https://github.com/nodejs/node-gyp/issues/629) + + +Jeremiah: Do we want to talk about the windows issue? + +Rod?: it kind of contains all of the windows problems. + +Alexis: I was asking about guidance on this. + +Rod: there’s a strategy of giving folks a place to vent, keeping it from spilling over elsewhere. Without this issue, it might explode into a bunch more issues. + +Alexis: We’re working on a module build service. The other thing is that MS is going to release a smaller SKU of the compiler, that might be able to be included with node-gyp. + +Rod: Next visual studio is going to be shipping with clang. + +Trevor: Yes for AST stuff. [cd: might have gotten this wrong] + +Rod: Alexis, you should post in there, but I think it’s going to always catch folks googling for the problem. I’m not sure you can resolve it by closing or locking it. Folks will go there and not see a proper resolution. + +Mikeal: make sure there are issues for everything in the thread, then close and lock. Make sure there are resolutions (even if it’s “move hte conversation”). + +Rod: I’m happy for Alexis to take the lead on this. + +Rod: Maybe change the title to “Windows users are happy?” + +Alexis: Maybe change to “Unix users are unhappy.” + +Rod: that’d be an epic troll. + +## Next Meeting + +November 4, 2015 diff --git a/doc/node.1 b/doc/node.1 index a352a6821186d1..685f039e4ccc37 100644 --- a/doc/node.1 +++ b/doc/node.1 @@ -773,4 +773,6 @@ See the website for documentation https://nodejs.org/ Mailing list: http://groups.google.com/group/nodejs -IRC: irc.freenode.net #io.js +IRC (general questions): irc.freenode.net #node.js + +IRC (node core development): irc.freenode.net #node-dev diff --git a/doc/releases.md b/doc/releases.md index 2adbdcbcd2d77f..daa325b0bce351 100644 --- a/doc/releases.md +++ b/doc/releases.md @@ -1,11 +1,11 @@ Node.js Release Process ===================== -This document describes the technical aspects of the node.js release process. The intended audience is those who have been authorized by the Node.js Foundation Technical Steering Committee (TSC) to create, promote and sign official release builds for node.js, hosted on . +This document describes the technical aspects of the Node.js release process. The intended audience is those who have been authorized by the Node.js Foundation Technical Steering Committee (TSC) to create, promote, and sign official release builds for Node.js, hosted on . ## Who can make a release? -Release authorization is given by the node.js TSC. Once authorized, an individual must be have the following: +Release authorization is given by the Node.js TSC. Once authorized, an individual must be have the following: ### 1. Jenkins Release Access @@ -17,23 +17,23 @@ There are three relevant Jenkins jobs that should be used for a release flow: **c.** **Release builds:** **[iojs+release](https://ci.nodejs.org/job/iojs+release/)** does all of the work to build all required release assets. Promotion of the release files is a manual step once they are ready (see below). -The [Node.js build team](https://github.com/nodejs/build) is able to provide this access to individuals authorized by the TC. +The [Node.js build team](https://github.com/nodejs/build) is able to provide this access to individuals authorized by the TSC. ### 2. Access -The _dist_ user on nodejs.org controls the assets available in (note that is an alias for ). +The _dist_ user on nodejs.org controls the assets available in . is an alias for . -The Jenkins release build slaves upload their artifacts to the web server as the _staging_ user, the _dist_ user has access to move these assets to public access (the _staging_ user does not, for security purposes). +The Jenkins release build slaves upload their artifacts to the web server as the _staging_ user. The _dist_ user has access to move these assets to public access while, for security, the _staging_ user does not. Nightly builds are promoted automatically on the server by a cron task for the _dist_ user. -Release builds require manual promotion by an individual with SSH access to the server as the _dist_ user. The [Node.js build team](https://github.com/nodejs/build) is able to provide this access to individuals authorized by the TC. +Release builds require manual promotion by an individual with SSH access to the server as the _dist_ user. The [Node.js build team](https://github.com/nodejs/build) is able to provide this access to individuals authorized by the TSC. ### 3. A Publicly Listed GPG Key -A SHASUMS256.txt file is produced for every promoted build, nightly and releases. Additionally for releases, this file is signed by the individual responsible for that release. In order to be able to verify downloaded binaries, the public should be able to check that the SHASUMS256.txt file has been signed by someone who has been authorized to create a release. +A SHASUMS256.txt file is produced for every promoted build, nightly, and releases. Additionally for releases, this file is signed by the individual responsible for that release. In order to be able to verify downloaded binaries, the public should be able to check that the SHASUMS256.txt file has been signed by someone who has been authorized to create a release. -The GPG keys should be fetchable from a known third-party keyserver, currently the SKS Keyservers at are recommended. Use the [submission](https://sks-keyservers.net/i/#submit) form to submit a new GPG key. Keys should be fetchable via: +The GPG keys should be fetchable from a known third-party keyserver. The SKS Keyservers at are recommended. Use the [submission](https://sks-keyservers.net/i/#submit) form to submit a new GPG key. Keys should be fetchable via: ``` gpg --keyserver pool.sks-keyservers.net --recv-keys @@ -48,21 +48,50 @@ Additionally, full GPG key fingerprints for individuals authorized to release sh Notes: - Dates listed below as _"YYYY-MM-DD"_ should be the date of the release **as UTC**. Use `date -u +'%Y-%m-%d'` to find out what this is. - - Version strings are listed below as _"vx.y.z"_, substitute for the release version. + - Version strings are listed below as _"vx.y.z"_. Substitute for the release version. -### 1. Ensure that HEAD Is Stable +### 1. Cherry-picking from `master` and other branches -Run a **[node-test-pull-request](https://ci.nodejs.org/job/node-test-pull-request/)** test run to ensure that the build is stable and the HEAD commit is ready for release. +Create a new branch named _"vx.y.z-proposal"_, or something similar. Using `git cherry-pick`, bring the appropriate commits into your new branch. To determine the relevant commits, use [`branch-diff`](https://github.com/rvagg/branch-diff) and [`changelog-maker`](https://github.com/rvagg/changelog-maker/) (both are available on npm and should be installed globally). These tools depend on our commit metadata, as well as the `semver-minor` and `semver-major` GitHub labels. One drawback is that when the `PR-URL` metadata is accidentally omitted from a commit, the commit will show up because it's unsure if it's a duplicate or not. -### 2. Produce a Nightly Build _(optional)_ +For a list of commits that could be landed in a patch release on v5.x -If there is a reason to produce a test release for the purpose of having others try out installers or specifics of builds, produce a nightly build using **[iojs+release](https://ci.nodejs.org/job/iojs+release/)** and wait for it to drop in . Follow the directions and enter a proper length commit sha, a date string and select "nightly" for "disttype". +``` +$ branch-diff v5.x master --exclude-label semver-major,semver-minor,dont-land-on-v5.x --simple +``` -This is particularly recommended if there has been recent work relating to the OS X or Windows installers as they are not tested in any way by CI. +Carefully review the list of commits looking for errors (incorrect `PR-URL`, incorrect semver, etc.). Commits labeled as semver minor or semver major should only be cherry-picked when appropriate for the type of release being made. Previous release commits and version bumps do not need to be cherry-picked. -### 3. Update the _CHANGELOG.md_ +### 2. Update `src/node_version.h` -Collect a formatted list of commits since the last release. Use [changelog-maker](https://github.com/rvagg/changelog-maker) (available from npm: `npm install changelog-maker -g`) to do this. +Set the version for the proposed release using the following macros, which are already defined in `src/node_version.h`: + +``` +#define NODE_MAJOR_VERSION x +#define NODE_MINOR_VERSION y +#define NODE_PATCH_VERSION z +``` + +Set the `NODE_VERSION_IS_RELEASE` macro value to `1`. This causes the build to be produced with a version string that does not have a trailing pre-release tag: + +``` +#define NODE_VERSION_IS_RELEASE 1 +``` + +**Also consider whether to bump `NODE_MODULE_VERSION`**: + +This macro is used to signal an ABI version for native addons. It currently has two common uses in the community: + +* Determining what API to work against for compiling native addons, e.g. [NAN](https://github.com/rvagg/nan) uses it to form a compatibility-layer for much of what it wraps. +* Determining the ABI for downloading pre-built binaries of native addons, e.g. [node-pre-gyp](https://github.com/mapbox/node-pre-gyp) uses this value as exposed via `process.versions.modules` to help determine the appropriate binary to download at install-time. + +The general rule is to bump this version when there are _breaking ABI_ changes and also if there are non-trivial API changes. The rules are not yet strictly defined, so if in doubt, please confer with someone that will have a more informed perspective, such as a member of the NAN team. + +**Note** that it is current TSC policy to bump major version when ABI changes. If you see a need to bump `NODE_MODULE_VERSION` then you should consult the TSC. Commits may need to be reverted or a major version bump may need to happen. + +### 3. Update `CHANGELOG.md` + +Collect a formatted list of commits since the last release. Use [`changelog-maker`](https://github.com/rvagg/changelog-maker) to do this. ``` $ changelog-maker --group @@ -74,10 +103,10 @@ Note that changelog-maker counts commits since the last tag and if the last tag $ changelog-maker --group --start-ref v2.3.1 ``` -The _CHANGELOG.md_ entry should take the following form: +The `CHANGELOG.md` entry should take the following form: ``` -## YYYY-MM-DD, Version x.y.z, @releaser +## YYYY-MM-DD, Version x.y.z (Release Type), @releaser ### Notable changes @@ -95,129 +124,154 @@ See https://github.com/nodejs/node/labels/confirmed-bug for complete and current ### Commits -* Include the full list of commits since the last release here +* Include the full list of commits since the last release here. Do not include "Working on X.Y.Z+1" commits. ``` -### 4. Update _src/node_version.h_ +The release type should be either Stable, LTS, or Maintenance, depending on the type of release being produced. -The following macros should already be set for the release since they will have been updated directly following the last release. They shouldn't require changing: - -``` -#define NODE_MAJOR_VERSION x -#define NODE_MINOR_VERSION y -#define NODE_PATCH_VERSION z -``` +### 4. Create Release Commit -However, the `NODE_VERSION_IS_RELEASE` macro needs to be set to `1` for the build to be produced with a version string that does not have a trailing pre-release tag: +The `CHANGELOG.md` and `src/node_version.h` changes should be the final commit that will be tagged for the release. When committing these to git, use the following message format: ``` -#define NODE_VERSION_IS_RELEASE 1 -``` +YYYY-MM-DD, Version x.y.z (Release Type) -**Also consider whether to bump `NODE_MODULE_VERSION`**: +Notable changes: -This macro is used to signal an ABI version for native addons. It currently has two common uses in the community: +* Copy the notable changes list here, reformatted for plain-text +``` -* Determining what API to work against for compiling native addons, e.g. [NAN](https://github.com/rvagg/nan) uses it to form a compatibility-layer for much of what it wraps. -* Determining the ABI for downloading pre-built binaries of native addons, e.g. [node-pre-gyp](https://github.com/mapbox/node-pre-gyp) uses this value as exposed via `process.versions.modules` to help determine the appropriate binary to download at install-time. +### 5. Propose Release on GitHub -The general rule is to bump this version when there are _breaking ABI_ changes and also if there are non-trivial API changes. The rules are not yet strictly defined, so if in doubt, please confer with someone that will have a more informed perspective, such as a member of the NAN team. +Push the release branch to `nodejs/node`, not to your own fork. This allows release branches to more easily be passed between members of the release team if necessary. -**Note** that it is current TSC policy to bump major version when ABI changes. If you see a need to bump `NODE_MODULE_VERSION` then you should consult the TSC, commits may need to be reverted or a major version bump may need to happen. +Create a pull request targeting the correct release line. For example, a v5.3.0-proposal PR should target v5.x, not master. Paste the CHANGELOG modifications into the body of the PR so that collaborators can see what is changing. These PRs should be left open for at least 24 hours, and can be updated as new commits land. -### 5. Create Release Commit +If you need any additional information about any of the commits, this PR is a good place to @-mention the relevant contributors. -The _CHANGELOG.md_ and _src/node_version.h_ changes should be the final commit that will be tagged for the release. +This is also a good time to update the release commit to include `PR-URL` metadata. -When committing these to git, use the following message format: +### 6. Ensure that the Release Branch is Stable -``` -YYYY-MM-DD node.js vx.y.z Release +Run a **[node-test-pull-request](https://ci.nodejs.org/job/node-test-pull-request/)** test run to ensure that the build is stable and the HEAD commit is ready for release. -Notable changes: +Perform some smoke-testing. We have [citgm](https://github.com/nodejs/citgm) for this. You can also manually test important modules from the ecosystem. Remember that node-gyp and npm both take a `--nodedir` flag to point to your local repository so that you can test unreleased versions without needing node-gyp to download headers for you. -* Copy the notable changes list here, reformatted for plain-text -``` +### 7. Produce a Nightly Build _(optional)_ -### 6. Push to GitHub +If there is a reason to produce a test release for the purpose of having others try out installers or specifics of builds, produce a nightly build using **[iojs+release](https://ci.nodejs.org/job/iojs+release/)** and wait for it to drop in . Follow the directions and enter a proper length commit SHA, enter a date string, and select "nightly" for "disttype". -Note that it is not essential that the release builds be created from the Node.js repository, they may be created from your own fork if you desire. It is preferable, but not essential that the commits remain the same between that used to build and the tagged commit in the Node.js repository. +This is particularly recommended if there has been recent work relating to the OS X or Windows installers as they are not tested in any way by CI. -### 7. Produce Release Builds +### 8. Produce Release Builds Use **[iojs+release](https://ci.nodejs.org/job/iojs+release/)** to produce release artifacts. Enter the commit that you want to build from and select "release" for "disttype". Artifacts from each slave are uploaded to Jenkins and are available if further testing is required. Use this opportunity particularly to test OS X and Windows installers if there are any concerns. Click through to the individual slaves for a run to find the artifacts. -All release slaves should achieve "SUCCESS" (and be green, not red). A release with failures should not be promoted, there are likely problems to be investigated. +All release slaves should achieve "SUCCESS" (and be green, not red). A release with failures should not be promoted as there are likely problems to be investigated. You can rebuild the release as many times as you need prior to promoting them if you encounter problems. -Note that you do not have to wait for the ARM builds if they are take longer than the others. It is only necessary to have the main Linux (x64 and x86), OS X .pkg and .tar.gz, Windows (x64 and x86) .msi and .exe, source, headers and docs (both produced currently by an OS X slave). i.e. the slaves with "arm" in their name don't need to have finished to progress to the next step. However, **if you promote builds _before_ ARM builds have finished, you must repeat the promotion step for the ARM builds when they are ready**. +If you have an error on Windows and need to start again, be aware that you'll get immediate failure unless you wait up to 2 minutes for the linker to stop from previous jobs. i.e. if a build fails after having started compiling, that slave will still have a linker process that's running for another couple of minutes which will prevent Jenkins from clearing the workspace to start a new one. This isn't a big deal, it's just a hassle because it'll result in another failed build if you start again! + +ARMv7 takes the longest to compile. Unfortunately ccache isn't as effective on release builds, I think it's because of the additional macro settings that go in to a release build that nullify previous builds. Also most of the release build machines are separate to the test build machines so they don't get any benefit from ongoing compiles between releases. You can expect 1.5 hours for the ARMv7 builder to complete and you should normally wait for this to finish. It is possible to rush a release out if you want and add additional builds later but we normally provide ARMv7 from initial promotion. -### 8. Tag and Sign the Release Commit +You do not have to wait for the ARMv6 / Raspberry PI builds if they take longer than the others. It is only necessary to have the main Linux (x64 and x86), OS X .pkg and .tar.gz, Windows (x64 and x86) .msi and .exe, source, headers and docs (both produced currently by an OS X slave). **If you promote builds _before_ ARM builds have finished, you must repeat the promotion step for the ARM builds when they are ready**. -Tag the release as vx.y.z and sign **using the same GPG key that will be used to sign SHASUMS256.txt**. +### 9. Test the Build + +Jenkins collects the artifacts from the builds, allowing you to download and install the new build. Make sure that the build appears correct. Check the version numbers, and perform some basic checks to confirm that all is well with the build before moving forward. + +### 10. Tag and Sign the Release Commit + +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`. + +Create a tag using the following command: ``` -$ git tag -sm 'YYYY-MM-DD node.js vz.y.x Release' +$ git tag -sm 'YYYY-MM-DD Node.js vx.y.z (Release Type) Release' ``` -Push the tag to GitHub. +The tag **must** be signed using the GPG key that's listed for you on the project README. + +Push the tag to the repo before you promote the builds. If you haven't pushed your tag first, then build promotion won't work properly. Push the tag using the following command: ``` -$ git push origin +$ git push ``` -### 9. Set Up For the Next Release +### 11. Set Up For the Next Release -Edit _src/node_version.h_ again and: +On release proposal branch, edit `src/node_version.h` again and: * Increment `NODE_PATCH_VERSION` by one * Change `NODE_VERSION_IS_RELEASE` back to `0` -Commit this change with: +Commit this change with the following commit message format: ``` -$ git commit -am 'Working on vx.y.z' # where 'z' is the incremented patch number +Working on vx.y.z # where 'z' is the incremented patch number + +PR-URL: ``` This sets up the branch so that nightly builds are produced with the next version number _and_ a pre-release tag. -### 10. Promote and Sign the Release Builds +Merge your release branch into the stable branch that you are releasing from (not master). -**It is important that the same individual who signed the release tag be the one to promote the builds as the SHASUMS256.txt file needs to be signed with the same GPG key!** +Cherry-pick the release commit to `master`. After cherry-picking, edit `src/node_version.h` to ensure the version macros contain whatever values were previously on `master`. `NODE_VERSION_IS_RELEASE` should be `0`. -When you are confident that the build slaves have properly produced usable artifacts and uploaded them to the web server you can promote them to release status. This is done by interacting with the web server via the _dist_ user. +### 12. Promote and Sign the Release Builds -The _tools/release.sh_ script should be used to promote and sign the build. When run, it will perform the following actions: +**It is important that the same individual who signed the release tag be the one to promote the builds as the SHASUMS256.txt file needs to be signed with the same GPG key!** + +Use `tools/release.sh` to promote and sign the build. When run, it will perform the following actions: -**a.** Select a GPG key from your private keys, it will use a command similar to: `gpg --list-secret-keys` to list your keys. If you don't have any keys, it will bail (why are you releasing? Your tag should be signed!). If you have only one key, it will use that. If you have more than one key it will ask you to select one from the list. Be sure to use the same key that you signed your git tag with. +**a.** Select a GPG key from your private keys. It will use a command similar to: `gpg --list-secret-keys` to list your keys. If you don't have any keys, it will bail. (Why are you releasing? Your tag should be signed!) If you have only one key, it will use that. If you have more than one key it will ask you to select one from the list. Be sure to use the same key that you signed your git tag with. **b.** Log in to the server via SSH and check for releases that can be promoted, along with the list of artifacts. It will use the `dist-promotable` command on the server to find these. You will be asked, for each promotable release, whether you want to proceed. If there is more than one release to promote (there shouldn't be), be sure to only promote the release you are responsible for. **c.** Log in to the server via SSH and run the promote script for the given release. The command on the server will be similar to: `dist-promote vx.y.z`. After this step, the release artifacts will be available for download and a SHASUMS256.txt file will be present. The release will still be unsigned, however. -**d.** Download SHASUMS256.txt to your computer using SCP into a temporary directory. +**d.** Use `scp` to download SHASUMS256.txt to a temporary directory on your computer. + +**e.** Sign the SHASUMS256.txt file using a command similar to: `gpg --default-key YOURKEY --clearsign /path/to/SHASUMS256.txt`. You will be prompted by GPG for your password. The signed file will be named SHASUMS256.txt.asc. + +**f.** Output an ASCII armored version of your public GPG key using a command similar to: `gpg --default-key YOURKEY --armor --export --output /path/to/SHASUMS256.txt.gpg`. This does not require your password and is mainly a convenience for users, although not the recommended way to get a copy of your key. + +**g.** Upload the SHASUMS256.txt files back to the server into the release directory. + +If you didn't wait for ARM builds in the previous step before promoting the release, you should re-run `tools/release.sh` after the ARM builds have finished. That will move the ARM artifacts into the correct location. You will be prompted to re-sign SHASUMS256.txt. + +### 13. Check the Release + +Your release should be available at and . Check that the appropriate files are in place. You may want to check that the binaries are working as appropriate and have the right internal version strings. Check that the API docs are available at . Check that the release catalog files are correct at and . -**e.** Sign the SHASUMS256.txt file using a command similar to: `gpg --default-key YOURKEY --clearsign /path/to/SHASUMS256.txt`. You will be prompted by GPG for your password for this to work. The signed file will be named SHASUMS256.txt.asc. +### 14. Create a Blog Post -**f.** Output an ASCII armored version of your public GPG key, using a command similar to: `gpg --default-key YOURKEY --armor --export --output /path/to/SHASUMS256.txt.gpg`. This does not require your password and is mainly a convenience for users although not the recommended way to get a copy of your key. +There is an automatic build that is kicked off when you promote new builds, so within a few minutes nodejs.org will be listing your new version as the latest release. However, the blog post is not yet fully automatic. -**g.** Upload the SHASUMS256.txt\* files back to the server into the release directory. +Create a new blog post by running the [nodejs.org release-post.js script](https://github.com/nodejs/nodejs.org/blob/master/scripts/release-post.js). This script will use the promoted builds and changelog to generate the post. Run `npm run serve` to preview the post locally before pushing to the [nodejs.org](https://github.com/nodejs/nodejs.org) repo. -If you didn't wait for ARM builds in the previous step before promoting the release, you should re-run _tools/release.sh_ after the ARM builds have finished and it will move the ARM artifacts into the correct location and you will be prompted to re-sign SHASUMS256.txt. +* You can add a short blurb just under the main heading if you want to say something important, otherwise the text should be publication ready. +* The links to the download files won't be complete unless you waited for the ARMv6 builds. Any downloads that are missing will have `*Coming soon*` next to them. It's your responsibility to manually update these later when you have the outstanding builds. +* The SHASUMS256.txt.asc content is at the bottom of the post. When you update the list of tarballs you'll need to copy/paste the new contents of this file to reflect those changes. +* Always use pull-requests on the nodejs.org repo. Be respectful of that working group, but you shouldn't have to wait for PR sign-off. Opening a PR and merging it immediately _should_ be fine. +* Changes to `master` on the nodejs.org repo will trigger a new build of nodejs.org so your changes should appear in a few minutes after pushing. -### 11. Check the Release +### 15. Announce -Your release should be available at and also . Check that the appropriate files are in place, you may also want to check that the binaries are working as appropriate and have the right internal version strings. Check that the API docs are available at . Check that the release catalog files are correct at and . +The nodejs.org website will automatically rebuild and include the new version. You simply need to announce the build, preferably via Twitter with a message such as: -### 12. Announce +> v5.3.0 of @nodejs is out @ https://nodejs.org/dist/latest/ changelog @ https://github.com/nodejs/node/blob/master/CHANGELOG.md#2015-12-16-version-530-stable-cjihrig … something here about notable changes -The nodejs.org website will automatically rebuild and include the new version. You simply need to announce the build, preferably via twitter with a message such as: +### 16. Cleanup -> v2.3.2 of @official_iojs is out @ https://nodejs.org/dist/latest/ changelog @ https://github.com/nodejs/node/blob/master/CHANGELOG.md#2015-07-01-version-232-rvagg … something here about notable changes +Close your release proposal PR and remove the proposal branch. -### 13. Celebrate +### 17. Celebrate _In whatever form you do this..._ diff --git a/doc/template.html b/doc/template.html index f9f27d0dc267b4..dec3f50670226e 100644 --- a/doc/template.html +++ b/doc/template.html @@ -42,9 +42,6 @@

Table of Contents

- - diff --git a/doc/tsc-meetings/2015-09-30.md b/doc/tsc-meetings/2015-09-30.md new file mode 100644 index 00000000000000..c10b9e75bc2ad9 --- /dev/null +++ b/doc/tsc-meetings/2015-09-30.md @@ -0,0 +1,161 @@ +# Node Foundation TSC Meeting 2015-09-30 + +## Links + +* **Audio Recording**: https://soundcloud.com/node-foundation/tsc-meeting-2015-09-30 +* **GitHub Issue**: https://github.com/nodejs/node/issues/3126 +* **Minutes Google Doc**: https://docs.google.com/document/d/1RkLAWTIrhD3BTB2rs9_FahWI0C7lt9F8xnQXaueJPIE +* _Previous Minutes Google Doc: _ + +## Present + +* Rod Vagg (TSC) +* Brian White (TSC) +* Chris Dickinson (TSC) +* James Snell (TSC) +* Michael Dawson +* Ben Noordhuis (TSC) +* Steven R Loomis +* Bert Belder (TSC) +* Alexis Campailla (TSC) +* Domenic Denicola +* Seth Thompson + +## Agenda + +Extracted from **tsc-agenda** labelled issues and pull requests in the nodejs org prior to meeting. + +### nodejs/node + +* Discussion: LTS & v5 release planning [#3000](https://github.com/nodejs/node/issues/3000) +* Inspecting Node.js with Chrome DevTools [#2546](https://github.com/nodejs/node/issues/2546) + +### nodejs/TSC + +* Umbrella Program [#2](https://github.com/nodejs/TSC/pull/2) + +## Minutes + +### Standup + +* Rod Vagg (TSC) - Lots! Pass. +* Brian White (TSC) - DNS PR (querying NSS modules like mDNS works now, continuing work on other getnameinfo/getaddrinfo compat issues) +* Chris Dickinson (TSC) - Static Analysis +* James Snell (TSC) - Review of the HTTP module, going in depth with spec compliance +* Michael Dawson - AIX, contributing changes from IBM repos, node-gyp, all related to getting native modules working on AIX, submitted PR to core, benchmarking — bare metal machine for benchmarking group, backporting test fix to 0.12, FIPS-compat work on the test suite, getting hooked into v8 security reporting +* Ben Noordhuis (TSC) - Review PRs, bug reports, fixed 1-2 bugs, sent a few patches upstream to V8 and gyp, fixed a few bugs in node-gyp. +* Steven R Loomis - Review PRs, bug reports. Looking into alternatives to packaging full ICU data. Might be able to `npm install` ICU data. +* Bert Belder (TSC) - +* Alexis Campailla (TSC) - working on Node-serialport on Windows in Jenkins, looking into native module build service +* Domenic Denicola - v8-extras are starting to appear in Chrome, maybe use them in Node for startup performance. + +### Review of previous meeting + +* Deprecate Array#values() in 0.12.x [#25877](https://github.com/nodejs/node-v0.x-archive/issues/25877) +* Deprecate smalloc in v0.12 [#25784](https://github.com/nodejs/node-v0.x-archive/issues/25784) +* Inspecting Node.js with Chrome DevTools [#2546](https://github.com/nodejs/node/issues/2546) +* util: Remove p, has been deprecated for years [#2529](https://github.com/nodejs/node/pull/2529) + +### Discussion: LTS & v5 release planning [#3000](https://github.com/nodejs/node/issues/3000) + +(Chris: apologies, I did a bad job here.) + +Ben: Plan is to ship the first LTS release with v8 4.5, not 4.6 + +Rod: Yes. + +Ben: Is there a pressing reason to do so? + +Rod: LTS comes off the v4.x branch, we committed to not bump V8 in stable releases. + +Ben: It basically means that the first LTS release is going to ship with an outdated release. + +James: Yes, we knew this was a strong possibility. + +Michael: The model is that we give the community time to catch up. In the future that’s 6 months, so we’re never going to be on a supported version. + +Ben: V8 moves quickly. If we stick with 4.5, we’re going to have to manage a bigger delta between our copy and upstream. + +James: Yes, this was always going to be the case. We’re committed to supporting the V8 for 36 months. + +Ben: Yes, my point is that we could be starting with a smaller delta. + +Rod: One of the reasons we had this LTS delay on 4 is to shake out some of these concerns, like the buffer changes. Normally this shakeout will be 6 months, but this time it’s only been a month. + +Alexis: Is v5 going to be LTS also? + +Rod: We are having discussions about the overlap between v5 and v6, whether there’ll be a strict cutoff or some overlap. No decision yet. That’ll happen in April. It sounds like most folks are leaning towards +making the two releases (v4 LTS + v5) independent — option 1 [here](https://github.com/nodejs/node/issues/3000#issuecomment-144026295). + +Ben: We still haven’t come up with a way to maintain V8 going forward. + +James: We do need a good process there, you are absolutely right about that. + +Rod: I vote for IBM to hire someone dedicated to this. (Laughter) + +Michael: I can’t promise that at this point. + +Rod: As the delta increases between versions this becomes more concerning. + +James: make sure this is on the LTS WG agenda for next week. + +Rod: We tried to tackle this once before, came up with job description but nothing concrete. + +Michael: We stopped short of telling the foundation that this is a position that we need to staff. + +James: I would agree. We’re at the point where bringing someone in at the foundation level is probably a good idea. + +Rod: Noted. OK. We’ve got resolution there. + +Michael: James: Make sure it’s on the LTS agenda for going back to the foundation for resources. + +Rod: LTS is meeting this Monday (issue 43 on the repo). There’s some discussion around codenames and how to expose LTS info. We’ve committed to first week of October for LTS releases, so timing is going to be a little awkward with 4.1.2 coming out monday. Version 5 will be shipping when we have a stable V8, presumably mid-to-late october (1-3 weeks with no stable release line.) + +Rod: We’ll be pulling in semver minor and patch changes, we’ll continue to have bugfix releases for version 4, + +### Inspecting Node.js with Chrome DevTools [#2546](https://github.com/nodejs/node/issues/2546) + +Rod: Trevor is lead on this, but isn’t present. Does anyone else have any updates? + +Ben: Wasn’t the last contentious issue putting WS in core? I think we agreed that if it’s not exposed to user-land, it's fine. + +Alexis: (discussion of another WS issue) + +Bert: we decided on this + +Ben: We agreed that if it was internal, non-exposed to core, + +(Talk about native deps for WS, buffer-util can be ) + +Ben: if this is a private dependency, we don’t need it to be fast, so we don’t necessarily need the native deps. + +Chris: (Hopped into discussion from minute-taking, hence the bad minutes) +https://github.com/nodejs/node/pull/1202 - add mask/unmask +https://github.com/nodejs/node/pull/1319 - add utf8 validator + +### Umbrella Program [#2](https://github.com/nodejs/TSC/pull/2) + +Ben: it’s basically a template for describing projects that are under the umbrella of the node foundation. It doesn’t look that controversial to me. + +Rod: it also doesn’t look that complete. + +Ben: Indeed. I suggest we discuss next week when mikeal is on the call. Seems like a rubber-stamp LGTM to me. + +Rod: We should think about what projects we want to introduce to the organization, including what happens to competition in the ecosystem when we pull in things (like build tools) +Domenic: This is for things like libuv, yes? + +Rod: There are already npm projects knocking on the door. One such project is request. It has its own org right now, but could work under the auspices of the node foundation. However it exists in an ecosystem where there is competition — is it okay for us to bless one project over others? NAN is sort of in the same position, it _could_ have competition. Another example is the npm client possibly. If the foundation were in a position to take npm would we even want it? + +### renaming of “language groups” from iojs-\* to nodejs-\* [#2525](https://github.com/nodejs/node/issues/2525) + +Steven: Looking for buyoff on this. + +Ben: Seen the approach and it looks good. + +Rod: You should take this as “you have authority to move ahead”. + +Steven: Will do. + +### Next Meeting + +October 7th diff --git a/doc/tsc-meetings/2015-10-07.md b/doc/tsc-meetings/2015-10-07.md new file mode 100644 index 00000000000000..6cb8813a5cac02 --- /dev/null +++ b/doc/tsc-meetings/2015-10-07.md @@ -0,0 +1,102 @@ +# Node Foundation TSC Meeting 2015-10-07 + +## Links + +* **Audio Recording**: https://soundcloud.com/node-foundation/tsc-meeting-2015-10-07 +* **GitHub Issue**: https://github.com/nodejs/node/issues/3126 +* **Minutes Google Doc**: https://docs.google.com/document/d/1LIrTCdTUjKtb_GGecrJ3Es0rPOpVdpkV5kefJ_p5FGU +* _Previous Minutes Google Doc: _ + +## Present + +* Rod Vagg (TSC) +* Brian White (TSC) +* Steven Loomis (observer) +* Trevor Norris (TSC) +* Shigeki Ohtsu (TSC) +* Ben Noordhuis (TSC) +* Mikeal Rogers (observer) +* Michael Dawson (observer) +* Seth Thompson (observer) +* Jeremiah Senkpiel (TSC) + +## Agenda + +Extracted from **tsc-agenda** labelled issues and pull requests in the nodejs org prior to meeting. + +### nodejs/node + +* WG: Considering a new HTTP WG [#3214](https://github.com/nodejs/node/issues/3214) +* lib,test: deprecate _linklist [#3078](https://github.com/nodejs/node/pull/3078) +* Discussion: LTS & v5 release planning [#3000](https://github.com/nodejs/node/issues/3000) +* Compiling node v4.0.0 with OpenSSL 1.0.1 fails [#2783](https://github.com/nodejs/node/issues/2783) +* Inspecting Node.js with Chrome DevTools [#2546](https://github.com/nodejs/node/issues/2546) + +### nodejs/TSC + +* Umbrella Program [#2](https://github.com/nodejs/TSC/pull/2) + +## Minutes + +### Standup + +* Rod Vagg: 4.1.2 release, security procedures surrounding that +* Brian White: Working on javascript dns resolver, regular PR + Issue work. +* Steven Loomis: Working on ICU 56 Release. TC 39 & emca spec work for Intl WG. Working on Intl build issues. +* Trevor Norris: Focused on fixing async_wrap, writing tests and preparing for it to become more official +* Shigeki Ohtsu: No works for node project, I spent all time to my internal works. +* Ben Noordhuis: Nothing to report—the usual +* Mikeal Rogers: Looking into stalled Wgs and seeing how to help out. Working on the umbrella program. Lots of conference things. +* Michael Dawson: Added a benchmarking machine to the CI, working on some tests issues. Working on PPC for the CI. +* Seth Thompson: Working on v8 4.7, scheduled soon +* Jeremiah Senkpiel: vacation, some issue catch-up + +### Review of previous meeting + +* Discussion: LTS & v5 release planning [#3000](https://github.com/nodejs/node/issues/3000) +* Inspecting Node.js with Chrome DevTools [#2546](https://github.com/nodejs/node/issues/2546) +* Umbrella Program [#2](https://github.com/nodejs/TSC/pull/2) +* renaming of “language groups” from iojs-\* to nodejs-\* [#2525](https://github.com/nodejs/node/issues/2525) + + +### WG: Considering a new HTTP WG [#3214](https://github.com/nodejs/node/issues/3214) + +* Discussed the HTTP WG based on James’ comments @ https://github.com/nodejs/node/issues/3234#issuecomment-146293038 +* Generally positive, only concerns are regarding decision making power—TSC may not want to hand that off as this is not quite like Streams (in that few people grok the code!) and there are philosophical questions to be resolved about HTTP that the TSC should be involved in. + +### lib,test: deprecate _linklist [#3078](https://github.com/nodejs/node/pull/3078) + +* Userland modules exist that could be used instead +* Ben suggested straight removal, Jeramiah raised the matter of process that we have committed to adding a warning before removal, so we could remove in v6 but probably shouldn’t in v5 +* No disagreement with moving forward for deprecation + +### Discussion: LTS & v5 release planning [#3000](https://github.com/nodejs/node/issues/3000) + +* Recap of the latest LTS meeting [LTS#43](https://github.com/nodejs/LTS/issues/43) +* Aim to have LTS / v4.2.0 out tomorrow, backup date of Monday if we miss that. LTS starts then for v4.x, v5.x has to wait until V8 4.6 to be stable mid to late October. + +### Compiling node v4.0.0 with OpenSSL 1.0.1 fails [#2783](https://github.com/nodejs/node/issues/2783) + +* Shigeki, Ben: It would be quite hard to support 1.0.1 since we are using 1.0.2 APIs. + +* Discussion on the possible difficulty of using 1.0.2 on varied Linux distros + +* ubuntu wily (not released) seems to use 1.0.2 - work has been done to package. 1.0.2 is only in Wily - https://launchpad.net/ubuntu/+source/openssl/1.0.2d-0ubuntu1 - https://answers.launchpad.net/ubuntu/+source/openssl/+question/263725 - “My guess is that we will see openssl 1.0.2 from Ubuntu 15.10 onwards (or eventually only starting with 16.04)” + +* Concern that allowing 1.0.1 would result in a substandard (insecure?) & untested binary. + +* Some discussion about the fact that we don’t test building with shared / static dependencies + +* feedback to issue: No appetite to do the work from the TSC, maybe someone could do it but we wouldn’t support. + +### Inspecting Node.js with Chrome DevTools [#2546](https://github.com/nodejs/node/issues/2546) + +_skipped discussion_ + +### Umbrella Program [#2](https://github.com/nodejs/TSC/pull/2) + +_skipped discussion_ + +## Next Meeting + +October 14th, 2015 diff --git a/doc/tsc-meetings/2015-10-14.md b/doc/tsc-meetings/2015-10-14.md new file mode 100644 index 00000000000000..65a0f467cdffb3 --- /dev/null +++ b/doc/tsc-meetings/2015-10-14.md @@ -0,0 +1,121 @@ +# Node Foundation TSC Meeting 2015-10-14 + +## Links + +* **Audio Recording**: https://soundcloud.com/node-foundation/tsc-meeting-2015-10-14 +* **GitHub Issue**: https://github.com/nodejs/node/issues/3363 +* **Minutes Google Doc**: +* _Previous Minutes Google Doc: _ + +## Present + +* Rod Vagg (TSC) +* Domenic Denicola (observer) +* Brian White (TSC) +* Steven Loomis (observer) +* James Snell (TSC) +* Michael Dawson (observer) +* Ben Noordhuis (TSC) +* Jeremiah Senkpiel (TSC) +* Trevor Norris (TSC) +* Alexis Campailla (TSC) +* Mikeal Rogers (observer) + +## Agenda + +Extracted from **tsc-agenda** labelled issues and pull requests in the nodejs org prior to meeting. + +### nodejs/node + +* V8 security reporting [#3348](https://github.com/nodejs/node/issues/3348) +* doc: add information about Assert behavior and maintenance [#3330](https://github.com/nodejs/node/pull/3330) +* WG: Considering a new HTTP WG [#3214](https://github.com/nodejs/node/issues/3214) +* Discussion: LTS & v5 release planning [#3000](https://github.com/nodejs/node/issues/3000) +* Compiling node v4.0.0 with OpenSSL 1.0.1 fails [#2783](https://github.com/nodejs/node/issues/2783) + +### nodejs/TSC + +* Umbrella Program [#2](https://github.com/nodejs/TSC/pull/2) + + +## Minutes + +### Standup + +* Rod Vagg: Not quite as involved, took a bit of time off. Getting back up to speed on build +* Domenic: Nothing this week +* Brian: PRs & Issues +* Steven: Worked on getting ICU 56.1 out and into v4.2.0 LTS, working on making the ICU [install better](https://github.com/nodejs/node-v0.x-archive/issues/8996#issuecomment-89411193). Also shepherding iojs-* rename to nodejs-* [#2525](https://github.com/nodejs/node/issues/2525) +* James: Worked on the 4.2.0 and 4.2.1 releases. Working on the cgitm smoke-testing tool and http WG. +* Michael: Worked on adding pLinux to the CI. Looking into running the tests on fips-compliant mode. Investigated some AIX issues. +* Ben: PRs & Issues, doing some work on the debugger and memory bugs in libuv +* Jeremiah: PRs & Issues, working on resolving the timers in beforeExit bug: https://github.com/nodejs/node/pull/2795 +* Trevor: Helped Jeremiah with the beforeExit thing, worked on PRs and Issues. Looking into AsyncWrap improvements. +* Alexis: Looking into a native module build service. Worked on the Ci a bit. +* Mikeal: Worked on the Umbrella Program proposal. Helping set up the Node.js Interactive conference. + + +### Review of previous meeting + +* WG: Considering a new HTTP WG [#3214](https://github.com/nodejs/node/issues/3214) +* lib,test: deprecate _linklist [#3078](https://github.com/nodejs/node/pull/3078) +* Discussion: LTS & v5 release planning [#3000](https://github.com/nodejs/node/issues/3000) +* Compiling node v4.0.0 with OpenSSL 1.0.1 fails [#2783](https://github.com/nodejs/node/issues/2783) +* Inspecting Node.js with Chrome DevTools [#2546](https://github.com/nodejs/node/issues/2546) +* Umbrella Program [#2](https://github.com/nodejs/TSC/pull/2) + + +### V8 security reporting [#3348](https://github.com/nodejs/node/issues/3348) + +Michael: Proposal is to add one or more TSC members to the V8 security list. Not all issues will actually be V8 issues, but there shouldn’t be too many. + +* Concerns about too many issues + +Michael: Let’s go back and ask if a handfull means only 4-5 a week. + +Mikeal: Part of the Umbrella Program is to make a top-level security group that all security issues are funneled through. This group may not need to be TSC members. + +Ben: How would this group know an issue is relevant to us? + +Rod: We are talking about a Chromium security list, so we would probably need someone with enough knowledge to filter out which issues affect us. + +Mikeal: They would only be an initial filter. + +Rod: Some chromium issues will not be recognizable as V8 issues without prior understanding. + +Rod & others: Suggest to add Ben and Fedor to add to the Chromium/V8 security list. + +Discussion about the current Security repo / group, and current mailing lists + +### doc: add information about Assert behavior and maintenance [#3330](https://github.com/nodejs/node/pull/3330) + +Discussion about what assert is intended to do, and how we want to deal with additions and breaking changes in the future. + +Discussion about the stability index in the docs. + +Resolution: Lock the assert module. Possibly re-evaluate in the future. Close existing open PRs/issues against it after landing doc change. + + +### WG: Considering a new HTTP WG [#3214](https://github.com/nodejs/node/issues/3214) + +James: having scheduling problems for an initial hangout but are getting a lot of interest from outside of core, including Doug Wilson and Eran Hammer. + +Discussion about the WG’s goals and how we should possibly think about handing over authority of the http module to this WG in the future. (At charter time or later on) + +### Discussion: LTS & v5 release planning [#3000](https://github.com/nodejs/node/issues/3000) + +James: recommended that we adopt a general rule that commits must go through at least one stable release before going into an LTS. Exceptions to this are security problems and changes that can’t go on to stable. + +### Compiling node v4.0.0 with OpenSSL 1.0.1 fails [#2783](https://github.com/nodejs/node/issues/2783) + +Conclusion was that this would be difficult and would result in a build that had some features disabled. The TSC is not going to undertake this work and would have reservations officially supporting a build that cripples some crypto features. However, pull requests for this work are welcome and would be considered. + +### Umbrella Program [#2](https://github.com/nodejs/TSC/pull/2) + +Mikeal sought a vote from the TSC to adopt the Project Lifecycle document and the Core TLP document. + +Resolution: there were no abstentions from voting and no disagreement amongst TSC members present, additional TSC members have registered their +1 on the PR so the motion is passed. + +## Next Meeting + +October 21st, 2015 diff --git a/doc/tsc-meetings/2015-10-21.md b/doc/tsc-meetings/2015-10-21.md new file mode 100644 index 00000000000000..5aad511600bb88 --- /dev/null +++ b/doc/tsc-meetings/2015-10-21.md @@ -0,0 +1,214 @@ +# Node Foundation Core Technical Committee (CTC) Meeting 2015-10-21 + +## Links + +* **Audio Recording**: https://soundcloud.com/node-foundation/tsc-meeting-2015-10-21 +* **GitHub Issue**: https://github.com/nodejs/node/issues/3464 +* **Minutes Google Doc**: +* _Previous Minutes Google Doc: _ + +## Present + +* Rod Vagg (CTC) +* Brian White (CTC) +* Steven R. Loomis (observer) +* James Snell (CTC) +* Michael Dawson (observer) +* Chris Dickinson (CTC) +* Ben Noordhuis (CTC) +* Jeremiah Senkpiel (CTC) +* Trevor Norris (CTC) +* Alexis Campailla (CTC) +* Mikeal Rogers (observer) +* Shigeki Ohtsu (CTC) +* Seth Thompson (observer) +* Bert Belder (CTC) +* Fedor Indutny (CTC) +## Agenda + +Extracted from **tsc-agenda** labelled issues and pull requests in the nodejs org prior to meeting. + +### nodejs/node + +* governance: add new collaborators #VIII [#3472](https://github.com/nodejs/node/issues/3472) +* detect "full-icu" module [#3460](https://github.com/nodejs/node/issues/3460) +* WG: Considering a new HTTP WG [#3214](https://github.com/nodejs/node/issues/3214) +* node: deprecate public access to `process.binding` [#2768](https://github.com/nodejs/node/pull/2768) + +## Minutes + +### Review of previous meeting + +* V8 security reporting [#3348](https://github.com/nodejs/node/issues/3348) +* doc: add information about Assert behavior and maintenance [#3330](https://github.com/nodejs/node/pull/3330) +* WG: Considering a new HTTP WG [#3214](https://github.com/nodejs/node/issues/3214) +* Discussion: LTS & v5 release planning [#3000](https://github.com/nodejs/node/issues/3000) +* Compiling node v4.0.0 with OpenSSL 1.0.1 fails [#2783](https://github.com/nodejs/node/issues/2783) +* Umbrella Program [#2](https://github.com/nodejs/TSC/pull/2) + +### Standup + +* Rod Vagg: index.tab and index.json updates (nodejs.org/dist/index.*) including an “lts” field, also made consistent directories for ancient Node tarballs with shasums files so nvm and other tools can simplify their access. v5 and other build yak shaving. +* Brian White: usual triaging and PR and Issues commenting, not much else +* Steven R. Loomis: Intl meeting, "full-icu" npm module [will be away until Nov 11 meeting, Unicode conf/Unicode-TC] +* James Snell: Working on localization for the node runtime [#3413](https://github.com/nodejs/node/pull/3413) +* Michael Dawson: Working through PPC and AIX PRs and issues, LTS WG discussions, Benchmarking WG, working with Stefan on agenda items for API WG meeting. +* Chris Dickinson: was busy with vacation and conferences, but looking into the WhatWG Streams spec, next up is static analysis server +* Ben Noordhuis: The usual. Looking into make the debugger better. The test suite is in bad shape +* Jeremiah Senkpiel: issue and PR work — going back through the backlog now, helping with v5 release + npm@3 +* Trevor Norris: flurry of AsyncWrap PRs, trying to get it to a point where people could more reliably use it, it can’t be hidden forever. +* Alexis Campailla: Sick, traveling; CI progress on flakiness, some progress on native module build service +* Mikeal Rogers: Foundation resources for v5 release: PR folks wrote a blog post, expectation setting, make sure enterprises are still using LTS, if you’re a dev here’s what to be excited about, etc. +* Shigeki Ohtsu: Worked semver-major fix to limit DH key size [#1831] (https://github.com/nodejs/node/pull/1831) and some works for root certs. +* Seth Thompson: Security mailing list stuff went through this week, working on v8 side of things to create a new version of the octane benchmark, excited about the benchmarking WG +* Bert Belder: nothing +* Fedor Indutny: reviewing PRs, helped fix a beforeExit bug, fixing yet another V8’s ArrayBuffer issue + - Discussed the ArrayBuffer issue in detail + +* (Aside: Shigeki and Fedor were asked to look at [#3406](https://github.com/nodejs/node/issues/3406) - “p1/p2” issue ) + +### governance: add new collaborators #VIII [#3472](https://github.com/nodejs/node/issues/3472) + +- Discussed onboarding. + +- Action: Jeremiah to schedule and run another onaboarding, Chris to tune in. + +### detect "full-icu" module [#3460](https://github.com/nodejs/node/issues/3460) + +Stems from conversation from the 0.X days about whether Node should ship other languages separately. + +This is a module published on npm as an alternative to shipping with Node proper. + +Whether node can detect a full-icu install in a special place (node_modules/full-icu, global/node_modules/full-icu) + +Nathan7 commented with a concern about coupling npm to node + +Currently have to start node with ICU_DATA_PATH=some/path/to/file + +Rod: Couple it to `execPath` + +James: globally installed could install into a well known global location + +Rod: Does this have to be done at startup? + +Stephen: Yes. V8 has to have the data available before starting. + +James: Happens right after parsing args + +Rod: Could use HOME? + +Stephen: Could use NODE_PATH? + +Rod: Trying to move away from NODE_PATH + +Ben: Might just bite the bullet and include ICU? + +Stephen: I would like that, but I am sympathetic to folks running on OpenWRT + +Ben: I can see that, but all this installing in special paths leaves a lot of margin for error. + +James: Full ICU will double the size of the Node binary. Hard pill to swallow. + +Rod: We could offer alternative downloads? + +Stephen: Two downloads would work as well. We could do this all from build infra. + +Bert: I would not be in favor of that. We end up with “oh my module doesn’t work” “oh you didn’t download the right flavor of Node” + +Jeremiah: It’s going to make it confusing no matter what + +... [I missed this] + +Chris: could we offer better error messages? + +Rod: it peeks through in a lot of places — the ICU object, strings, etc. Maybe best to leave to module authors? Include a process.versions.icu object? + +James: small-icu is the default build running locally — CI doesn’t run with ICU enabled? + +Trevor: even if small-icu is there, it means less data, but not less build time. I would like to see how that affects the raspberry pi’s build time. + +Ben: we could avoid rebuilding ICU on rasppis + +Stephen: or use a precompiled ICU + +Jeremiah: Assumes an internet connected machine + +Rod: If we go with small-icu we should make it available + +Ben: should we add it to the repo? + +Alexis: I think so, it’s causing problems + +[???]: It’s about 80mb + +Rod: How big is it? + +Stephen: The source size & binary size was comparable to Node. +We could have a non-standard source checked in. + +Mikeal: we could use the large file storage stuff GH just added. +Stephen: 25mb uncompressed, 130mb for source tree + +Mikeal: if we say “you need ICU to build” we need to make it available + +Trevor: How’s this going to work with bouncing between branches? + +Alexis: What about keeping it as text? + +Ben: + +Steven: We have a 25mb compressed zip of source, that itself contains a 25mb compressed zip. We could strip that down — what would it take to delete the tests, etc — a subset + +Mikeal: so could we just install this 25mb file? + +Rod: This adds a dep on Git LFS + +Mikeal: Let’s try to solve one problem at a time — fix downloading, not making the default + +Rod: I’m happy with how the CI does it + +… + +Stephen: The first time you hit something ICU-based it loads it. + +Rod: I’m just wondering if this could be turned into a proper npm module. + +Stephen: I’m not sure — it looks pretty deeply enmeshed into V8 + +Seth: I don’t have answers off the top of my head on that one, I responded on the thread; we don’t currently have a priority to mess +around with localization. If there’s a design doc that proposes cleaning things up we’d be interested + +James: Resource bundle mechanism — [Note: didn’t get all of this] “using the same startup sequence as Intl.. so needs to be configured at start time” (https://github.com/nodejs/node/pull/3413 uses ICU’s resource bundle mechanism, which uses the same init path as the core data. ICU does not allow multiple initializations. + +Alexis: If the only reason we’re trying to package it is to use npm to install it, maybe we’re complicating this unnecessarily + +Rod: On the iojs side we decided not to go with ICU. It’s in core because it has to be initialized before v8 is started, my question is this something that could be changed upstream in v8? Ideally this should not be in core. + +Steven: It didn’t look like it could be split off easily. + +Chris: JS proxies + +Steven: Possible, but _very_ tricky + +[Moving conversation to GH] + + +### WG: Considering a new HTTP WG [#3214](https://github.com/nodejs/node/issues/3214) + +HTTP WG first meeting is tomorrow at 1pm Pacific, nothing to discuss yet + +### node: deprecate public access to `process.binding` [#2768](https://github.com/nodejs/node/pull/2768) + +Lots of discussion, focused on `process.binding('natives')`. Summary: We should at least try to make it read-only first. Ben said he would follow up with a PR. + +### node: make listen address configurable [#3316](https://github.com/nodejs/node/pull/3316) + +Fedor: Ben suggested commandline argument to submit hostname and port. Fedor concerned about the amout of code required to parse and separate the two parts of the option. Would be better to have a separate argument for hostname. + +Discussion about usability vs simplicity of code. + +Quick vote on whether to move forward with the PR in its current form, no objections. + +## Next Meeting + +October 28th, 2015 diff --git a/lib/_debugger.js b/lib/_debugger.js index 9f8fa26f2189c3..ad7ee6295bee2a 100644 --- a/lib/_debugger.js +++ b/lib/_debugger.js @@ -5,7 +5,7 @@ const path = require('path'); const net = require('net'); const vm = require('vm'); const Module = require('module'); -const repl = Module.requireRepl(); +const repl = require('repl'); const inherits = util.inherits; const assert = require('assert'); const spawn = require('child_process').spawn; @@ -45,7 +45,7 @@ exports.port = 5858; // // Parser/Serializer for V8 debugger protocol -// http://code.google.com/p/v8/wiki/DebuggerProtocol +// https://github.com/v8/v8/wiki/Debugging-Protocol // // Usage: // p = new Protocol(); @@ -1546,8 +1546,7 @@ Interface.prototype.repl = function() { var listeners = this.repl.rli.listeners('SIGINT').slice(0); this.repl.rli.removeAllListeners('SIGINT'); - // Exit debug repl on Ctrl + C - this.repl.rli.once('SIGINT', function() { + function exitDebugRepl() { // Restore all listeners process.nextTick(function() { listeners.forEach(function(listener) { @@ -1557,7 +1556,16 @@ Interface.prototype.repl = function() { // Exit debug repl self.exitRepl(); - }); + + self.repl.rli.removeListener('SIGINT', exitDebugRepl); + self.repl.removeListener('exit', exitDebugRepl); + } + + // Exit debug repl on SIGINT + this.repl.rli.on('SIGINT', exitDebugRepl); + + // Exit debug repl on repl exit + this.repl.on('exit', exitDebugRepl); // Set new this.repl.eval = this.debugEval.bind(this); diff --git a/lib/_http_agent.js b/lib/_http_agent.js index 305baa2cbd2f03..ddb1c5bfff9b63 100644 --- a/lib/_http_agent.js +++ b/lib/_http_agent.js @@ -58,7 +58,7 @@ function Agent(options) { if (req && req.shouldKeepAlive && !socket.destroyed && - self.options.keepAlive) { + self.keepAlive) { var freeSockets = self.freeSockets[name]; var freeLen = freeSockets ? freeSockets.length : 0; var count = freeLen; @@ -66,7 +66,6 @@ function Agent(options) { count += self.sockets[name].length; if (count > self.maxSockets || freeLen >= self.maxFreeSockets) { - self.removeSocket(socket, options); socket.destroy(); } else { freeSockets = freeSockets || []; @@ -78,7 +77,6 @@ function Agent(options) { freeSockets.push(socket); } } else { - self.removeSocket(socket, options); socket.destroy(); } } diff --git a/lib/_http_client.js b/lib/_http_client.js index aef05eb8fa2299..db1db7bcc3ab60 100644 --- a/lib/_http_client.js +++ b/lib/_http_client.js @@ -3,7 +3,6 @@ const util = require('util'); const net = require('net'); const url = require('url'); -const EventEmitter = require('events'); const HTTPParser = process.binding('http_parser').HTTPParser; const assert = require('assert').ok; const common = require('_http_common'); diff --git a/lib/_http_outgoing.js b/lib/_http_outgoing.js index d130246b84dc58..8a6f76a357d40d 100644 --- a/lib/_http_outgoing.js +++ b/lib/_http_outgoing.js @@ -560,7 +560,7 @@ OutgoingMessage.prototype.end = function(data, encoding, callback) { var ret; if (data) { // Normal body write. - ret = this.write(data, encoding); + this.write(data, encoding); } if (this._hasBody && this.chunkedEncoding) { diff --git a/lib/assert.js b/lib/assert.js index 6b99098c5fda35..3e52ab45f66127 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -170,6 +170,11 @@ function _deepEqual(actual, expected, strict) { (expected === null || typeof expected !== 'object')) { return strict ? actual === expected : actual == expected; + // If both values are instances of typed arrays, wrap them in + // a Buffer each to increase performance + } else if (ArrayBuffer.isView(actual) && ArrayBuffer.isView(expected)) { + return compare(new Buffer(actual), new Buffer(expected)) === 0; + // 7.5 For all other Object pairs, including Array objects, equivalence is // determined by having the same number of owned properties (as verified // with Object.prototype.hasOwnProperty.call), the same set of keys @@ -278,6 +283,10 @@ function expectedException(actual, expected) { // Ignore. The instanceof check doesn't work for arrow functions. } + if (Error.isPrototypeOf(expected)) { + return false; + } + return expected.call({}, actual) === true; } diff --git a/lib/buffer.js b/lib/buffer.js index f6f28294e3c3c7..9c6b6c94162833 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -19,13 +19,17 @@ binding.setupBufferJS(Buffer.prototype, bindingObj); const flags = bindingObj.flags; const kNoZeroFill = 0; +function createBuffer(size) { + const ui8 = new Uint8Array(size); + Object.setPrototypeOf(ui8, Buffer.prototype); + return ui8; +} function createPool() { poolSize = Buffer.poolSize; if (poolSize > 0) flags[kNoZeroFill] = 1; - allocPool = new Uint8Array(poolSize); - Object.setPrototypeOf(allocPool, Buffer.prototype); + allocPool = createBuffer(poolSize); poolOffset = 0; } createPool(); @@ -40,7 +44,7 @@ function alignPool() { } -function Buffer(arg) { +function Buffer(arg, encoding) { // Common case. if (typeof arg === 'number') { // If less than zero, or NaN. @@ -51,7 +55,7 @@ function Buffer(arg) { // Slightly less common case. if (typeof arg === 'string') { - return fromString(arg, arguments[1]); + return fromString(arg, encoding); } // Unusual. @@ -67,9 +71,7 @@ function SlowBuffer(length) { length = 0; if (length > 0) flags[kNoZeroFill] = 1; - const ui8 = new Uint8Array(+length); - Object.setPrototypeOf(ui8, Buffer.prototype); - return ui8; + return createBuffer(+length); } Object.setPrototypeOf(SlowBuffer.prototype, Uint8Array.prototype); @@ -78,9 +80,7 @@ Object.setPrototypeOf(SlowBuffer, Uint8Array); function allocate(size) { if (size === 0) { - const ui8 = new Uint8Array(size); - Object.setPrototypeOf(ui8, Buffer.prototype); - return ui8; + return createBuffer(size); } if (size < (Buffer.poolSize >>> 1)) { if (size > (poolSize - poolOffset)) @@ -95,9 +95,7 @@ function allocate(size) { // being zero filled. if (size > 0) flags[kNoZeroFill] = 1; - const ui8 = new Uint8Array(size); - Object.setPrototypeOf(ui8, Buffer.prototype); - return ui8; + return createBuffer(size); } } @@ -123,6 +121,10 @@ function fromString(string, encoding) { function fromObject(obj) { if (obj instanceof Buffer) { var b = allocate(obj.length); + + if (b.length === 0) + return b; + obj.copy(b, 0, 0, obj.length); return b; } @@ -276,6 +278,7 @@ function byteLength(string, encoding) { case 'utf8': case 'utf-8': + case undefined: return binding.byteLengthUtf8(string); case 'ucs2': diff --git a/lib/cluster.js b/lib/cluster.js index c4c2c0d9ac4c93..f202f25cdd522a 100644 --- a/lib/cluster.js +++ b/lib/cluster.js @@ -291,7 +291,7 @@ function masterInit() { var match = execArgv[i].match(/^(--debug|--debug-(brk|port))(=\d+)?$/); if (match) { - let debugPort = process.debugPort + debugPortOffset; + const debugPort = process.debugPort + debugPortOffset; ++debugPortOffset; execArgv[i] = match[1] + '=' + debugPort; } diff --git a/lib/dgram.js b/lib/dgram.js index eaf84272d16284..161f908eae547e 100644 --- a/lib/dgram.js +++ b/lib/dgram.js @@ -252,8 +252,7 @@ Socket.prototype.send = function(buffer, if (typeof buffer === 'string') buffer = new Buffer(buffer); - - if (!(buffer instanceof Buffer)) + else if (!(buffer instanceof Buffer)) throw new TypeError('First argument must be a buffer or string.'); offset = offset | 0; diff --git a/lib/dns.js b/lib/dns.js index 71d20bdca403df..782cdfa3f79df4 100644 --- a/lib/dns.js +++ b/lib/dns.js @@ -330,7 +330,6 @@ exports.NOTFOUND = 'ENOTFOUND'; exports.NOTIMP = 'ENOTIMP'; exports.REFUSED = 'EREFUSED'; exports.BADQUERY = 'EBADQUERY'; -exports.ADNAME = 'EADNAME'; exports.BADNAME = 'EBADNAME'; exports.BADFAMILY = 'EBADFAMILY'; exports.BADRESP = 'EBADRESP'; diff --git a/lib/fs.js b/lib/fs.js index cd39cc9d83fcc1..57e9220a149f28 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -872,29 +872,29 @@ function preprocessSymlinkDestination(path, type, linkPath) { } } -fs.symlink = function(destination, path, type_, callback_) { +fs.symlink = function(target, path, type_, callback_) { var type = (typeof type_ === 'string' ? type_ : null); var callback = makeCallback(arguments[arguments.length - 1]); - if (!nullCheck(destination, callback)) return; + if (!nullCheck(target, callback)) return; if (!nullCheck(path, callback)) return; var req = new FSReqWrap(); req.oncomplete = callback; - binding.symlink(preprocessSymlinkDestination(destination, type, path), + binding.symlink(preprocessSymlinkDestination(target, type, path), pathModule._makeLong(path), type, req); }; -fs.symlinkSync = function(destination, path, type) { +fs.symlinkSync = function(target, path, type) { type = (typeof type === 'string' ? type : null); - nullCheck(destination); + nullCheck(target); nullCheck(path); - return binding.symlink(preprocessSymlinkDestination(destination, type, path), + return binding.symlink(preprocessSymlinkDestination(target, type, path), pathModule._makeLong(path), type); }; diff --git a/lib/https.js b/lib/https.js index abe4a20907dfdd..f13c1ffea96be8 100644 --- a/lib/https.js +++ b/lib/https.js @@ -123,6 +123,10 @@ Agent.prototype.getName = function(options) { if (options.rejectUnauthorized !== undefined) name += options.rejectUnauthorized; + name += ':'; + if (options.servername && options.servername !== options.host) + name += options.servername; + return name; }; diff --git a/lib/internal/child_process.js b/lib/internal/child_process.js index 8c1abc5f746fc8..b4365fb8c067f7 100644 --- a/lib/internal/child_process.js +++ b/lib/internal/child_process.js @@ -217,7 +217,7 @@ util.inherits(ChildProcess, EventEmitter); function flushStdio(subprocess) { if (subprocess.stdio == null) return; subprocess.stdio.forEach(function(stream, fd, stdio) { - if (!stream || !stream.readable || stream._consuming) + if (!stream || !stream.readable) return; stream.resume(); }); @@ -675,6 +675,9 @@ function setupChannel(target, channel) { const INTERNAL_PREFIX = 'NODE_'; function handleMessage(target, message, handle) { + if (!target._channel) + return; + var eventName = 'message'; if (message !== null && typeof message === 'object' && diff --git a/lib/internal/module.js b/lib/internal/module.js index 7f3a39e539424a..ef55aa64bd5642 100644 --- a/lib/internal/module.js +++ b/lib/internal/module.js @@ -1,6 +1,30 @@ 'use strict'; -module.exports.stripBOM = stripBOM; +module.exports = { makeRequireFunction, stripBOM }; + +// Invoke with makeRequireFunction.call(module) where |module| is the +// Module object to use as the context for the require() function. +function makeRequireFunction() { + const Module = this.constructor; + const self = this; + + function require(path) { + return self.require(path); + } + + require.resolve = function(request) { + return Module._resolveFilename(request, self); + }; + + require.main = process.mainModule; + + // Enable support to add extra extension types. + require.extensions = Module._extensions; + + require.cache = Module._cache; + + return require; +} /** * Remove byte order marker. This catches EF BB BF (the UTF-8 BOM) diff --git a/lib/internal/repl.js b/lib/internal/repl.js index 1a62414a49e95d..e6b41fbdd89b65 100644 --- a/lib/internal/repl.js +++ b/lib/internal/repl.js @@ -14,12 +14,6 @@ module.exports.createInternalRepl = createRepl; // The debounce is to guard against code pasted into the REPL. const kDebounceHistoryMS = 15; -// XXX(chrisdickinson): hack to make sure that the internal debugger -// uses the original repl. -function replStart() { - return REPL.start.apply(REPL, arguments); -} - function createRepl(env, opts, cb) { if (typeof opts === 'function') { cb = opts; @@ -120,7 +114,15 @@ function setupHistory(repl, historyPath, oldHistoryPath, ready) { if (data) { repl.history = data.split(/[\n\r]+/, repl.historySize); - } else if (oldHistoryPath) { + } else if (oldHistoryPath === historyPath) { + // If pre-v3.0, the user had set NODE_REPL_HISTORY_FILE to + // ~/.node_repl_history, warn the user about it and proceed. + repl._writeToOutput( + '\nThe old repl history file has the same name and location as ' + + `the new one i.e., ${historyPath} and is empty.\nUsing it as is.\n`); + repl._refreshLine(); + + } else if (oldHistoryPath) { // Grab data from the older pre-v3.0 JSON NODE_REPL_HISTORY_FILE format. repl._writeToOutput( '\nConverting old JSON repl history to line-separated history.\n' + @@ -128,7 +130,13 @@ function setupHistory(repl, historyPath, oldHistoryPath, ready) { repl._refreshLine(); try { - repl.history = JSON.parse(fs.readFileSync(oldHistoryPath, 'utf8')); + // Pre-v3.0, repl history was stored as JSON. + // Try and convert it to line separated history. + const oldReplJSONHistory = fs.readFileSync(oldHistoryPath, 'utf8'); + + // Only attempt to use the history if there was any. + if (oldReplJSONHistory) repl.history = JSON.parse(oldReplJSONHistory); + if (!Array.isArray(repl.history)) { throw new Error('Expected array, got ' + typeof repl.history); } diff --git a/lib/internal/util.js b/lib/internal/util.js index a31f22e6e9f186..c34682ed1b3809 100644 --- a/lib/internal/util.js +++ b/lib/internal/util.js @@ -1,7 +1,10 @@ 'use strict'; +const binding = process.binding('util'); const prefix = '(node) '; +exports.getHiddenValue = binding.getHiddenValue; + // All the internal deprecations have to use this function only, as this will // prepend the prefix to the actual message. exports.deprecate = function(fn, msg) { @@ -54,3 +57,21 @@ exports._deprecate = function(fn, msg) { return deprecated; }; + +exports.decorateErrorStack = function decorateErrorStack(err) { + if (!(exports.isError(err) && err.stack)) + return; + + const arrow = exports.getHiddenValue(err, 'arrowMessage'); + + if (arrow) + err.stack = arrow + err.stack; +}; + +exports.isError = function isError(e) { + return exports.objectToString(e) === '[object Error]' || e instanceof Error; +}; + +exports.objectToString = function objectToString(o) { + return Object.prototype.toString.call(o); +}; diff --git a/lib/module.js b/lib/module.js index 2d660c4b23d1d0..1d937f8baa2aa8 100644 --- a/lib/module.js +++ b/lib/module.js @@ -47,7 +47,6 @@ Module.wrapper = NativeModule.wrapper; Module.wrap = NativeModule.wrap; Module._debug = util.debuglog('module'); - // We use this alias for the preprocessor that filters it out const debug = Module._debug; @@ -275,17 +274,6 @@ Module._load = function(request, parent, isMain) { debug('Module._load REQUEST %s parent: %s', request, parent.id); } - // REPL is a special case, because it needs the real require. - if (request === 'internal/repl' || request === 'repl') { - if (Module._cache[request]) { - return Module._cache[request]; - } - var replModule = new Module(request); - replModule._compile(NativeModule.getSource(request), `${request}.js`); - NativeModule._cache[request] = replModule; - return replModule.exports; - } - var filename = Module._resolveFilename(request, parent); var cachedModule = Module._cache[filename]; @@ -377,41 +365,14 @@ var resolvedArgv; // the file. // Returns exception, if any. Module.prototype._compile = function(content, filename) { - var self = this; // remove shebang content = content.replace(shebangRe, ''); - function require(path) { - return self.require(path); - } - - require.resolve = function(request) { - return Module._resolveFilename(request, self); - }; - - Object.defineProperty(require, 'paths', { get: function() { - throw new Error('require.paths is removed. Use ' + - 'node_modules folders, or the NODE_PATH ' + - 'environment variable instead.'); - }}); - - require.main = process.mainModule; - - // Enable support to add extra extension types - require.extensions = Module._extensions; - require.registerExtension = function() { - throw new Error('require.registerExtension() removed. Use ' + - 'require.extensions instead.'); - }; - - require.cache = Module._cache; - - var dirname = path.dirname(filename); - // create wrapper function var wrapper = Module.wrap(content); - var compiledWrapper = runInThisContext(wrapper, { filename: filename }); + var compiledWrapper = runInThisContext(wrapper, + { filename: filename, lineOffset: 0 }); if (global.v8debug) { if (!resolvedArgv) { // we enter the repl if we're not given a filename argument. @@ -431,8 +392,22 @@ Module.prototype._compile = function(content, filename) { global.v8debug.Debug.setBreakPoint(compiledWrapper, 0, 0); } } - var args = [self.exports, require, self, filename, dirname]; - return compiledWrapper.apply(self.exports, args); + const dirname = path.dirname(filename); + const require = internalModule.makeRequireFunction.call(this); + + Object.defineProperty(require, 'paths', { get: function() { + throw new Error('require.paths is removed. Use ' + + 'node_modules folders, or the NODE_PATH ' + + 'environment variable instead.'); + }}); + + require.registerExtension = function() { + throw new Error('require.registerExtension() removed. Use ' + + 'require.extensions instead.'); + }; + + const args = [this.exports, require, this, filename, dirname]; + return compiledWrapper.apply(this.exports, args); }; @@ -498,10 +473,10 @@ Module._initPaths = function() { Module.globalPaths = modulePaths.slice(0); }; -// bootstrap repl -Module.requireRepl = function() { - return Module._load('internal/repl', '.'); -}; +// TODO(bnoordhuis) Unused, remove in the future. +Module.requireRepl = internalUtil.deprecate(function() { + return NativeModule.require('internal/repl'); +}, 'Module.requireRepl is deprecated.'); Module._preloadModules = function(requests) { if (!Array.isArray(requests)) diff --git a/lib/net.js b/lib/net.js index 58c9a3bc34c737..f778043572362e 100644 --- a/lib/net.js +++ b/lib/net.js @@ -1081,7 +1081,6 @@ function Server(options, connectionListener) { EventEmitter.call(this); var self = this; - var options; if (typeof options === 'function') { connectionListener = options; diff --git a/lib/os.js b/lib/os.js index 2d537f53840a35..ddf7cee9d48791 100644 --- a/lib/os.js +++ b/lib/os.js @@ -1,7 +1,6 @@ 'use strict'; const binding = process.binding('os'); -const util = require('util'); const internalUtil = require('internal/util'); const isWindows = process.platform === 'win32'; diff --git a/lib/repl.js b/lib/repl.js index ef641a89c4012e..9c80ee59bd53d2 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -21,6 +21,8 @@ 'use strict'; +const internalModule = require('internal/module'); +const internalUtil = require('internal/util'); const util = require('util'); const inherits = util.inherits; const Stream = require('stream'); @@ -29,9 +31,11 @@ const path = require('path'); const fs = require('fs'); const rl = require('readline'); const Console = require('console').Console; +const Module = require('module'); const domain = require('domain'); const debug = util.debuglog('repl'); +const parentModule = module; const replMap = new WeakMap(); try { @@ -274,6 +278,7 @@ function REPLServer(prompt, self._domain.on('error', function(e) { debug('domain error'); const top = replMap.get(self); + internalUtil.decorateErrorStack(e); top.outputStream.write((e.stack || e) + '\n'); top.lineParser.reset(); top.bufferedCommand = ''; @@ -507,6 +512,10 @@ REPLServer.prototype.createContext = function() { context.global.global = context; } + const module = new Module(''); + module.paths = Module._resolveLookupPaths('', parentModule)[1]; + + const require = internalModule.makeRequireFunction.call(module); context.module = module; context.require = require; @@ -545,7 +554,8 @@ REPLServer.prototype.displayPrompt = function(preserveCursor) { var prompt = this._initialPrompt; if (this.bufferedCommand.length) { prompt = '...'; - var levelInd = new Array(this.lines.level.length).join('..'); + const len = this.lines.level.length ? this.lines.level.length - 1 : 0; + const levelInd = '..'.repeat(len); prompt += levelInd + ' '; } @@ -646,7 +656,7 @@ REPLServer.prototype.complete = function(line, callback) { completionGroupsLoaded(); } else if (match = line.match(requireRE)) { // require('...') - var exts = Object.keys(require.extensions); + const exts = Object.keys(this.context.require.extensions); var indexRe = new RegExp('^index(' + exts.map(regexpEscape).join('|') + ')$'); @@ -897,7 +907,8 @@ REPLServer.prototype.memory = function memory(cmd) { // save the line so I can do magic later if (cmd) { // TODO should I tab the level? - self.lines.push(new Array(self.lines.level.length).join(' ') + cmd); + const len = self.lines.level.length ? self.lines.level.length - 1 : 0; + self.lines.push(' '.repeat(len) + cmd); } else { // I don't want to not change the format too much... self.lines.push(''); @@ -1059,6 +1070,9 @@ function defineDefaultCommands(repl) { self.write(line + '\n'); } }); + } else { + this.outputStream.write('Failed to load:' + file + + ' is not a valid file\n'); } } catch (e) { this.outputStream.write('Failed to load:' + file + '\n'); diff --git a/lib/timers.js b/lib/timers.js index e4b27fdc54adb6..8cfd1cb42e1af2 100644 --- a/lib/timers.js +++ b/lib/timers.js @@ -192,21 +192,21 @@ exports.setTimeout = function(callback, after) { case 2: break; case 3: - ontimeout = callback.bind(timer, arguments[2]); + ontimeout = () => callback.call(timer, arguments[2]); break; case 4: - ontimeout = callback.bind(timer, arguments[2], arguments[3]); + ontimeout = () => callback.call(timer, arguments[2], arguments[3]); break; case 5: ontimeout = - callback.bind(timer, arguments[2], arguments[3], arguments[4]); + () => callback.call(timer, arguments[2], arguments[3], arguments[4]); break; // slow case default: var args = new Array(length - 2); for (var i = 2; i < length; i++) args[i - 2] = arguments[i]; - ontimeout = callback.apply.bind(callback, timer, args); + ontimeout = () => callback.apply(timer, args); break; } timer._onTimeout = ontimeout; @@ -247,20 +247,20 @@ exports.setInterval = function(callback, repeat) { case 2: break; case 3: - ontimeout = callback.bind(timer, arguments[2]); + ontimeout = () => callback.call(timer, arguments[2]); break; case 4: - ontimeout = callback.bind(timer, arguments[2], arguments[3]); + ontimeout = () => callback.call(timer, arguments[2], arguments[3]); break; case 5: ontimeout = - callback.bind(timer, arguments[2], arguments[3], arguments[4]); + () => callback.call(timer, arguments[2], arguments[3], arguments[4]); break; default: var args = new Array(length - 2); for (var i = 2; i < length; i += 1) args[i - 2] = arguments[i]; - ontimeout = callback.apply.bind(callback, timer, args); + ontimeout = () => callback.apply(timer, args); break; } timer._onTimeout = wrapper; @@ -272,7 +272,7 @@ exports.setInterval = function(callback, repeat) { return timer; function wrapper() { - timer._repeat.call(this); + timer._repeat(); // Timer might be closed - no point in restarting it if (!timer._repeat) diff --git a/lib/url.js b/lib/url.js index 45155fee936bbf..6489d6327d0e29 100644 --- a/lib/url.js +++ b/lib/url.js @@ -586,7 +586,7 @@ Url.prototype.resolveObject = function(relative) { // Put this after the other two cases because it simplifies the booleans if (psychotic) { result.hostname = result.host = srcPath.shift(); - //occationaly the auth can get stuck only in host + //occasionally the auth can get stuck only in host //this especially happens in cases like //url.resolveObject('mailto:local1@domain1', 'local2@domain2') var authInHost = result.host && result.host.indexOf('@') > 0 ? @@ -668,7 +668,7 @@ Url.prototype.resolveObject = function(relative) { if (psychotic) { result.hostname = result.host = isAbsolute ? '' : srcPath.length ? srcPath.shift() : ''; - //occationaly the auth can get stuck only in host + //occasionally the auth can get stuck only in host //this especially happens in cases like //url.resolveObject('mailto:local1@domain1', 'local2@domain2') var authInHost = result.host && result.host.indexOf('@') > 0 ? diff --git a/lib/util.js b/lib/util.js index a6231c8acf56da..6f8d841dd438f7 100644 --- a/lib/util.js +++ b/lib/util.js @@ -5,6 +5,8 @@ const Buffer = require('buffer').Buffer; const internalUtil = require('internal/util'); const binding = process.binding('util'); +const isError = internalUtil.isError; + var Debug; const formatRegExp = /%[sdj%]/g; @@ -161,9 +163,10 @@ function stylizeNoColor(str, styleType) { function arrayToHash(array) { var hash = {}; - array.forEach(function(val, idx) { + for (var i = 0; i < array.length; i++) { + var val = array[i]; hash[val] = true; - }); + } return hash; } @@ -195,6 +198,7 @@ function ensureDebugIsInitialized() { function inspectPromise(p) { ensureDebugIsInitialized(); + // Only create a mirror if the object is a Promise. if (!binding.isPromise(p)) return null; const mirror = Debug.MakeMirror(p, true); @@ -289,16 +293,19 @@ function formatValue(ctx, value, recurseTimes) { var constructor = getConstructorOf(value); var base = '', empty = false, braces, formatter; + // We can't compare constructors for various objects using a comparison like + // `constructor === Array` because the object could have come from a different + // context and thus the constructor won't match. Instead we check the + // constructor names (including those up the prototype chain where needed) to + // determine object types. if (Array.isArray(value)) { - // We can't use `constructor === Array` because this could - // have come from a Debug context. - // Otherwise, an Array will print "Array [...]". + // Unset the constructor to prevent "Array [...]" for ordinary arrays. if (constructor && constructor.name === 'Array') constructor = null; braces = ['[', ']']; empty = value.length === 0; formatter = formatArray; - } else if (value instanceof Set) { + } else if (binding.isSet(value)) { braces = ['{', '}']; // With `showHidden`, `length` will display as a hidden property for // arrays. For consistency's sake, do the same for `size`, even though this @@ -307,7 +314,7 @@ function formatValue(ctx, value, recurseTimes) { keys.unshift('size'); empty = value.size === 0; formatter = formatSet; - } else if (value instanceof Map) { + } else if (binding.isMap(value)) { braces = ['{', '}']; // Ditto. if (ctx.showHidden) @@ -315,8 +322,7 @@ function formatValue(ctx, value, recurseTimes) { empty = value.size === 0; formatter = formatMap; } else { - // Only create a mirror if the object superficially looks like a Promise. - var promiseInternals = value instanceof Promise && inspectPromise(value); + var promiseInternals = inspectPromise(value); if (promiseInternals) { braces = ['{', '}']; formatter = formatPromise; @@ -332,7 +338,8 @@ function formatValue(ctx, value, recurseTimes) { empty = false; formatter = formatCollectionIterator; } else { - if (constructor === Object) + // Unset the constructor to prevent "Object {...}" for ordinary objects. + if (constructor && constructor.name === 'Object') constructor = null; braces = ['{', '}']; empty = true; // No other data than keys. @@ -517,7 +524,7 @@ function formatCollectionIterator(ctx, value, recurseTimes, visibleKeys, keys) { var nextRecurseTimes = recurseTimes === null ? null : recurseTimes - 1; var vals = mirror.preview(); var output = []; - for (let o of vals) { + for (const o of vals) { output.push(formatValue(ctx, o, nextRecurseTimes)); } return output; @@ -666,7 +673,7 @@ function isUndefined(arg) { exports.isUndefined = isUndefined; function isRegExp(re) { - return objectToString(re) === '[object RegExp]'; + return binding.isRegExp(re); } exports.isRegExp = isRegExp; @@ -676,13 +683,10 @@ function isObject(arg) { exports.isObject = isObject; function isDate(d) { - return objectToString(d) === '[object Date]'; + return binding.isDate(d); } exports.isDate = isDate; -function isError(e) { - return objectToString(e) === '[object Error]' || e instanceof Error; -} exports.isError = isError; function isFunction(arg) { @@ -698,10 +702,6 @@ exports.isPrimitive = isPrimitive; exports.isBuffer = Buffer.isBuffer; -function objectToString(o) { - return Object.prototype.toString.call(o); -} - function pad(n) { return n < 10 ? '0' + n.toString(10) : n.toString(10); diff --git a/node.gyp b/node.gyp index a587edc926945e..778162119a0006 100644 --- a/node.gyp +++ b/node.gyp @@ -13,6 +13,7 @@ 'node_shared_openssl%': 'false', 'node_v8_options%': '', 'node_target_type%': 'executable', + 'node_core_target_name%': 'node', 'library_files': [ 'src/node.js', 'lib/_debug_agent.js', @@ -81,7 +82,7 @@ 'targets': [ { - 'target_name': 'node', + 'target_name': '<(node_core_target_name)', 'type': '<(node_target_type)', 'dependencies': [ @@ -673,5 +674,53 @@ 'test/cctest/util.cc', ], } - ] # end targets + ], # end targets + + 'conditions': [ + ['OS=="aix"', { + 'targets': [ + { + 'target_name': 'node', + 'type': 'executable', + 'dependencies': ['<(node_core_target_name)', 'node_exp'], + + 'include_dirs': [ + 'src', + 'deps/v8/include', + ], + + 'sources': [ + 'src/node_main.cc', + '<@(library_files)', + # node.gyp is added to the project by default. + 'common.gypi', + ], + + 'ldflags': ['-Wl,-bbigtoc,-bE:<(PRODUCT_DIR)/node.exp'], + }, + { + 'target_name': 'node_exp', + 'type': 'none', + 'dependencies': [ + '<(node_core_target_name)', + ], + 'actions': [ + { + 'action_name': 'expfile', + 'inputs': [ + '<(OBJ_DIR)' + ], + 'outputs': [ + '<(PRODUCT_DIR)/node.exp' + ], + 'action': [ + 'sh', 'tools/create_expfile.sh', + '<@(_inputs)', '<@(_outputs)' + ], + } + ] + } + ], # end targets + }], # end aix section + ], # end conditions block } diff --git a/src/async-wrap-inl.h b/src/async-wrap-inl.h index cac8175889dfbf..1d9ebe27e45bef 100644 --- a/src/async-wrap-inl.h +++ b/src/async-wrap-inl.h @@ -17,7 +17,8 @@ inline AsyncWrap::AsyncWrap(Environment* env, v8::Local object, ProviderType provider, AsyncWrap* parent) - : BaseObject(env, object), bits_(static_cast(provider) << 1) { + : BaseObject(env, object), bits_(static_cast(provider) << 1), + uid_(env->get_async_wrap_uid()) { CHECK_NE(provider, PROVIDER_NONE); CHECK_GE(object->InternalFieldCount(), 1); @@ -40,11 +41,12 @@ inline AsyncWrap::AsyncWrap(Environment* env, v8::Local argv[] = { v8::Int32::New(env->isolate(), provider), + v8::Integer::New(env->isolate(), get_uid()), Null(env->isolate()) }; if (parent != nullptr) - argv[1] = parent->object(); + argv[2] = parent->object(); v8::MaybeLocal ret = init_fn->Call(env->context(), object, ARRAY_SIZE(argv), argv); @@ -56,6 +58,22 @@ inline AsyncWrap::AsyncWrap(Environment* env, } +inline AsyncWrap::~AsyncWrap() { + if (!ran_init_callback()) + return; + + v8::Local fn = env()->async_hooks_destroy_function(); + if (!fn.IsEmpty()) { + v8::HandleScope scope(env()->isolate()); + v8::Local uid = v8::Integer::New(env()->isolate(), get_uid()); + v8::MaybeLocal ret = + fn->Call(env()->context(), v8::Null(env()->isolate()), 1, &uid); + if (ret.IsEmpty()) + FatalError("node::AsyncWrap::~AsyncWrap", "destroy hook threw"); + } +} + + inline bool AsyncWrap::ran_init_callback() const { return static_cast(bits_ & 1); } @@ -66,6 +84,11 @@ inline AsyncWrap::ProviderType AsyncWrap::provider_type() const { } +inline int64_t AsyncWrap::get_uid() const { + return uid_; +} + + inline v8::Local AsyncWrap::MakeCallback( const v8::Local symbol, int argc, diff --git a/src/async-wrap.cc b/src/async-wrap.cc index 4f27e5116dca8d..c9f5caad1e4ea8 100644 --- a/src/async-wrap.cc +++ b/src/async-wrap.cc @@ -103,6 +103,9 @@ RetainedObjectInfo* WrapperInfo(uint16_t class_id, Local wrapper) { static void EnableHooksJS(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); + Local init_fn = env->async_hooks_init_function(); + if (init_fn.IsEmpty() || !init_fn->IsFunction()) + return env->ThrowTypeError("init callback is not assigned to a function"); env->async_hooks()->set_enable_callbacks(1); } @@ -116,13 +119,20 @@ static void DisableHooksJS(const FunctionCallbackInfo& args) { static void SetupHooks(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); - CHECK(args[0]->IsFunction()); - CHECK(args[1]->IsFunction()); - CHECK(args[2]->IsFunction()); + if (env->async_hooks()->callbacks_enabled()) + return env->ThrowError("hooks should not be set while also enabled"); + + if (!args[0]->IsFunction()) + return env->ThrowTypeError("init callback must be a function"); env->set_async_hooks_init_function(args[0].As()); - env->set_async_hooks_pre_function(args[1].As()); - env->set_async_hooks_post_function(args[2].As()); + + if (args[1]->IsFunction()) + env->set_async_hooks_pre_function(args[1].As()); + if (args[2]->IsFunction()) + env->set_async_hooks_post_function(args[2].As()); + if (args[3]->IsFunction()) + env->set_async_hooks_destroy_function(args[3].As()); } @@ -148,6 +158,7 @@ static void Initialize(Local target, env->set_async_hooks_init_function(Local()); env->set_async_hooks_pre_function(Local()); env->set_async_hooks_post_function(Local()); + env->set_async_hooks_destroy_function(Local()); } diff --git a/src/async-wrap.h b/src/async-wrap.h index 330f3454f42d2c..5db29600bcd180 100644 --- a/src/async-wrap.h +++ b/src/async-wrap.h @@ -51,10 +51,12 @@ class AsyncWrap : public BaseObject { ProviderType provider, AsyncWrap* parent = nullptr); - inline virtual ~AsyncWrap() override = default; + inline virtual ~AsyncWrap(); inline ProviderType provider_type() const; + inline int64_t get_uid() const; + // Only call these within a valid HandleScope. v8::Local MakeCallback(const v8::Local cb, int argc, @@ -76,6 +78,7 @@ class AsyncWrap : public BaseObject { // expected the context object will receive a _asyncQueue object property // that will be used to call pre/post in MakeCallback. uint32_t bits_; + const int64_t uid_; }; void LoadAsyncWrapperInfo(Environment* env); diff --git a/src/env-inl.h b/src/env-inl.h index 2d965f9a519232..f73e9c6ba2000a 100644 --- a/src/env-inl.h +++ b/src/env-inl.h @@ -210,6 +210,7 @@ inline Environment::Environment(v8::Local context, using_domains_(false), printed_error_(false), trace_sync_io_(false), + async_wrap_uid_(0), debugger_agent_(this), http_parser_buffer_(nullptr), context_(context->GetIsolate(), context) { @@ -359,6 +360,10 @@ inline void Environment::set_trace_sync_io(bool value) { trace_sync_io_ = value; } +inline int64_t Environment::get_async_wrap_uid() { + return ++async_wrap_uid_; +} + inline uint32_t* Environment::heap_statistics_buffer() const { CHECK_NE(heap_statistics_buffer_, nullptr); return heap_statistics_buffer_; diff --git a/src/env.h b/src/env.h index 185cc17294ec05..ea5e8fea6edf62 100644 --- a/src/env.h +++ b/src/env.h @@ -231,6 +231,7 @@ namespace node { V(async_hooks_init_function, v8::Function) \ V(async_hooks_pre_function, v8::Function) \ V(async_hooks_post_function, v8::Function) \ + V(async_hooks_destroy_function, v8::Function) \ V(binding_cache_object, v8::Object) \ V(buffer_constructor_function, v8::Function) \ V(buffer_prototype_object, v8::Object) \ @@ -442,6 +443,8 @@ class Environment { void PrintSyncTrace() const; inline void set_trace_sync_io(bool value); + inline int64_t get_async_wrap_uid(); + bool KickNextTick(); inline uint32_t* heap_statistics_buffer() const; @@ -537,6 +540,7 @@ class Environment { bool using_domains_; bool printed_error_; bool trace_sync_io_; + int64_t async_wrap_uid_; debugger::Agent debugger_agent_; HandleWrapQueue handle_wrap_queue_; diff --git a/src/node.cc b/src/node.cc index cdbcc8b9f471d1..65afc8c1fe02f2 100644 --- a/src/node.cc +++ b/src/node.cc @@ -64,9 +64,8 @@ #if defined(_MSC_VER) #include #include -#include #define strcasecmp _stricmp -#define getpid _getpid +#define getpid GetCurrentProcessId #define umask _umask typedef int mode_t; #else @@ -1482,8 +1481,6 @@ void AppendExceptionLine(Environment* env, arrow[off + 1] = '\0'; Local arrow_str = String::NewFromUtf8(env->isolate(), arrow); - Local msg; - Local stack; // Allocation failed, just print it out if (arrow_str.IsEmpty() || err_obj.IsEmpty() || !err_obj->IsNativeError()) @@ -1548,8 +1545,10 @@ static void ReportException(Environment* env, name.IsEmpty() || name->IsUndefined()) { // Not an error object. Just print as-is. - node::Utf8Value message(env->isolate(), er); - PrintErrorString("%s\n", *message); + String::Utf8Value message(er); + + PrintErrorString("%s\n", *message ? *message : + ""); } else { node::Utf8Value name_string(env->isolate(), name); node::Utf8Value message_string(env->isolate(), message); diff --git a/src/node.h b/src/node.h index b5941ff06b27bd..ef1f629d20aa0e 100644 --- a/src/node.h +++ b/src/node.h @@ -96,7 +96,7 @@ NODE_EXTERN v8::Local UVException(v8::Isolate* isolate, const char* path, const char* dest); -NODE_DEPRECATED("Use UVException(isolate, ...)", +NODE_DEPRECATED("Use ErrnoException(isolate, ...)", inline v8::Local ErrnoException( int errorno, const char* syscall = NULL, diff --git a/src/node.js b/src/node.js index 5a4496e43350c5..b38594f7c09274 100644 --- a/src/node.js +++ b/src/node.js @@ -142,7 +142,7 @@ // If -i or --interactive were passed, or stdin is a TTY. if (process._forceRepl || NativeModule.require('tty').isatty(0)) { // REPL - var cliRepl = Module.requireRepl(); + var cliRepl = NativeModule.require('internal/repl'); cliRepl.createInternalRepl(process.env, function(err, repl) { if (err) { throw err; @@ -345,20 +345,20 @@ // callback invocation with small numbers of arguments to avoid the // performance hit associated with using `fn.apply()` if (args === undefined) { - doNTCallback0(callback); + nextTickCallbackWith0Args(callback); } else { switch (args.length) { case 1: - doNTCallback1(callback, args[0]); + nextTickCallbackWith1Arg(callback, args[0]); break; case 2: - doNTCallback2(callback, args[0], args[1]); + nextTickCallbackWith2Args(callback, args[0], args[1]); break; case 3: - doNTCallback3(callback, args[0], args[1], args[2]); + nextTickCallbackWith3Args(callback, args[0], args[1], args[2]); break; default: - doNTCallbackMany(callback, args); + nextTickCallbackWithManyArgs(callback, args); } } if (1e4 < tickInfo[kIndex]) @@ -386,20 +386,20 @@ // callback invocation with small numbers of arguments to avoid the // performance hit associated with using `fn.apply()` if (args === undefined) { - doNTCallback0(callback); + nextTickCallbackWith0Args(callback); } else { switch (args.length) { case 1: - doNTCallback1(callback, args[0]); + nextTickCallbackWith1Arg(callback, args[0]); break; case 2: - doNTCallback2(callback, args[0], args[1]); + nextTickCallbackWith2Args(callback, args[0], args[1]); break; case 3: - doNTCallback3(callback, args[0], args[1], args[2]); + nextTickCallbackWith3Args(callback, args[0], args[1], args[2]); break; default: - doNTCallbackMany(callback, args); + nextTickCallbackWithManyArgs(callback, args); } } if (1e4 < tickInfo[kIndex]) @@ -413,7 +413,7 @@ } while (tickInfo[kLength] !== 0); } - function doNTCallback0(callback) { + function nextTickCallbackWith0Args(callback) { var threw = true; try { callback(); @@ -424,7 +424,7 @@ } } - function doNTCallback1(callback, arg1) { + function nextTickCallbackWith1Arg(callback, arg1) { var threw = true; try { callback(arg1); @@ -435,7 +435,7 @@ } } - function doNTCallback2(callback, arg1, arg2) { + function nextTickCallbackWith2Args(callback, arg1, arg2) { var threw = true; try { callback(arg1, arg2); @@ -446,7 +446,7 @@ } } - function doNTCallback3(callback, arg1, arg2, arg3) { + function nextTickCallbackWith3Args(callback, arg1, arg2, arg3) { var threw = true; try { callback(arg1, arg2, arg3); @@ -457,7 +457,7 @@ } } - function doNTCallbackMany(callback, args) { + function nextTickCallbackWithManyArgs(callback, args) { var threw = true; try { callback.apply(null, args); @@ -950,7 +950,10 @@ var source = NativeModule.getSource(this.id); source = NativeModule.wrap(source); - var fn = runInThisContext(source, { filename: this.filename }); + var fn = runInThisContext(source, { + filename: this.filename, + lineOffset: 0 + }); fn(this.exports, NativeModule.require, this, this.filename); this.loaded = true; diff --git a/src/node_contextify.cc b/src/node_contextify.cc index 8880439c8a7e3f..bfd45a22862a06 100644 --- a/src/node_contextify.cc +++ b/src/node_contextify.cc @@ -504,13 +504,15 @@ class ContextifyScript : public BaseObject { TryCatch try_catch; Local code = args[0]->ToString(env->isolate()); Local filename = GetFilenameArg(args, 1); + Local lineOffset = GetLineOffsetArg(args, 1); + Local columnOffset = GetColumnOffsetArg(args, 1); bool display_errors = GetDisplayErrorsArg(args, 1); if (try_catch.HasCaught()) { try_catch.ReThrow(); return; } - ScriptOrigin origin(filename); + ScriptOrigin origin(filename, lineOffset, columnOffset); ScriptCompiler::Source source(code, origin); Local v8_script = ScriptCompiler::CompileUnbound(env->isolate(), &source); @@ -675,6 +677,39 @@ class ContextifyScript : public BaseObject { } + static Local GetLineOffsetArg( + const FunctionCallbackInfo& args, + const int i) { + Local defaultLineOffset = Integer::New(args.GetIsolate(), 0); + + if (!args[i]->IsObject()) { + return defaultLineOffset; + } + + Local key = FIXED_ONE_BYTE_STRING(args.GetIsolate(), "lineOffset"); + Local value = args[i].As()->Get(key); + + return value->IsUndefined() ? defaultLineOffset : value->ToInteger(); + } + + + static Local GetColumnOffsetArg( + const FunctionCallbackInfo& args, + const int i) { + Local defaultColumnOffset = Integer::New(args.GetIsolate(), 0); + + if (!args[i]->IsObject()) { + return defaultColumnOffset; + } + + Local key = FIXED_ONE_BYTE_STRING(args.GetIsolate(), + "columnOffset"); + Local value = args[i].As()->Get(key); + + return value->IsUndefined() ? defaultColumnOffset : value->ToInteger(); + } + + static bool EvalMachine(Environment* env, const int64_t timeout, const bool display_errors, diff --git a/src/node_crypto.cc b/src/node_crypto.cc index b03e6444ff8a3b..7911ce9e612816 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -116,14 +116,6 @@ static X509_NAME *cnnic_ev_name = d2i_X509_NAME(nullptr, &cnnic_ev_p, sizeof(CNNIC_EV_ROOT_CA_SUBJECT_DATA)-1); -// Forcibly clear OpenSSL's error stack on return. This stops stale errors -// from popping up later in the lifecycle of crypto operations where they -// would cause spurious failures. It's a rather blunt method, though. -// ERR_clear_error() isn't necessarily cheap either. -struct ClearErrorOnReturn { - ~ClearErrorOnReturn() { ERR_clear_error(); } -}; - static uv_mutex_t* locks; const char* const root_certs[] = { @@ -519,46 +511,35 @@ int SSL_CTX_get_issuer(SSL_CTX* ctx, X509* cert, X509** issuer) { } -// Read a file that contains our certificate in "PEM" format, -// possibly followed by a sequence of CA certificates that should be -// sent to the peer in the Certificate message. -// -// Taken from OpenSSL - editted for style. int SSL_CTX_use_certificate_chain(SSL_CTX* ctx, - BIO* in, + X509* x, + STACK_OF(X509)* extra_certs, X509** cert, X509** issuer) { - int ret = 0; - X509* x = nullptr; - - x = PEM_read_bio_X509_AUX(in, nullptr, CryptoPemCallback, nullptr); + CHECK_EQ(*issuer, nullptr); + CHECK_EQ(*cert, nullptr); - if (x == nullptr) { - SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_PEM_LIB); - goto end; - } - - ret = SSL_CTX_use_certificate(ctx, x); + int ret = SSL_CTX_use_certificate(ctx, x); if (ret) { // If we could set up our certificate, now proceed to // the CA certificates. - X509 *ca; int r; - unsigned long err; if (ctx->extra_certs != nullptr) { sk_X509_pop_free(ctx->extra_certs, X509_free); ctx->extra_certs = nullptr; } - while ((ca = PEM_read_bio_X509(in, nullptr, CryptoPemCallback, nullptr))) { + for (int i = 0; i < sk_X509_num(extra_certs); i++) { + X509* ca = sk_X509_value(extra_certs, i); + // NOTE: Increments reference count on `ca` r = SSL_CTX_add1_chain_cert(ctx, ca); if (!r) { - X509_free(ca); ret = 0; + *issuer = nullptr; goto end; } // Note that we must not free r if it was successfully @@ -569,17 +550,8 @@ int SSL_CTX_use_certificate_chain(SSL_CTX* ctx, // Find issuer if (*issuer != nullptr || X509_check_issued(ca, x) != X509_V_OK) continue; - *issuer = ca; - } - // When the while loop ends, it's usually just EOF. - err = ERR_peek_last_error(); - if (ERR_GET_LIB(err) == ERR_LIB_PEM && - ERR_GET_REASON(err) == PEM_R_NO_START_LINE) { - ERR_clear_error(); - } else { - // some real error - ret = 0; + *issuer = ca; } } @@ -592,13 +564,88 @@ int SSL_CTX_use_certificate_chain(SSL_CTX* ctx, // no need to free `store` } else { // Increment issuer reference count - CRYPTO_add(&(*issuer)->references, 1, CRYPTO_LOCK_X509); + *issuer = X509_dup(*issuer); + if (*issuer == nullptr) { + ret = 0; + goto end; + } } } end: + if (ret && x != nullptr) { + *cert = X509_dup(x); + if (*cert == nullptr) + ret = 0; + } + return ret; +} + + +// Read a file that contains our certificate in "PEM" format, +// possibly followed by a sequence of CA certificates that should be +// sent to the peer in the Certificate message. +// +// Taken from OpenSSL - edited for style. +int SSL_CTX_use_certificate_chain(SSL_CTX* ctx, + BIO* in, + X509** cert, + X509** issuer) { + X509* x = nullptr; + + // Just to ensure that `ERR_peek_last_error` below will return only errors + // that we are interested in + ERR_clear_error(); + + x = PEM_read_bio_X509_AUX(in, nullptr, CryptoPemCallback, nullptr); + + if (x == nullptr) { + SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_PEM_LIB); + return 0; + } + + X509* extra = nullptr; + int ret = 0; + unsigned long err = 0; + + // Read extra certs + STACK_OF(X509)* extra_certs = sk_X509_new_null(); + if (extra_certs == nullptr) { + SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_MALLOC_FAILURE); + goto done; + } + + while ((extra = PEM_read_bio_X509(in, nullptr, CryptoPemCallback, nullptr))) { + if (sk_X509_push(extra_certs, extra)) + continue; + + // Failure, free all certs + goto done; + } + extra = nullptr; + + // When the while loop ends, it's usually just EOF. + err = ERR_peek_last_error(); + if (ERR_GET_LIB(err) == ERR_LIB_PEM && + ERR_GET_REASON(err) == PEM_R_NO_START_LINE) { + ERR_clear_error(); + } else { + // some real error + goto done; + } + + ret = SSL_CTX_use_certificate_chain(ctx, x, extra_certs, cert, issuer); + if (!ret) + goto done; + + done: + if (extra_certs != nullptr) + sk_X509_pop_free(extra_certs, X509_free); + if (extra != nullptr) + X509_free(extra); if (x != nullptr) - *cert = x; + X509_free(x); + return ret; } @@ -616,6 +663,16 @@ void SecureContext::SetCert(const FunctionCallbackInfo& args) { if (!bio) return; + // Free previous certs + if (sc->issuer_ != nullptr) { + X509_free(sc->issuer_); + sc->issuer_ = nullptr; + } + if (sc->cert_ != nullptr) { + X509_free(sc->cert_); + sc->cert_ = nullptr; + } + int rv = SSL_CTX_use_certificate_chain(sc->ctx_, bio, &sc->cert_, @@ -887,7 +944,7 @@ void SecureContext::LoadPKCS12(const FunctionCallbackInfo& args) { PKCS12* p12 = nullptr; EVP_PKEY* pkey = nullptr; X509* cert = nullptr; - STACK_OF(X509)* extraCerts = nullptr; + STACK_OF(X509)* extra_certs = nullptr; char* pass = nullptr; bool ret = false; @@ -912,28 +969,33 @@ void SecureContext::LoadPKCS12(const FunctionCallbackInfo& args) { pass[passlen] = '\0'; } + // Free previous certs + if (sc->issuer_ != nullptr) { + X509_free(sc->issuer_); + sc->issuer_ = nullptr; + } + if (sc->cert_ != nullptr) { + X509_free(sc->cert_); + sc->cert_ = nullptr; + } + if (d2i_PKCS12_bio(in, &p12) && - PKCS12_parse(p12, pass, &pkey, &cert, &extraCerts) && - SSL_CTX_use_certificate(sc->ctx_, cert) && + PKCS12_parse(p12, pass, &pkey, &cert, &extra_certs) && + SSL_CTX_use_certificate_chain(sc->ctx_, + cert, + extra_certs, + &sc->cert_, + &sc->issuer_) && SSL_CTX_use_PrivateKey(sc->ctx_, pkey)) { - // set extra certs - while (X509* x509 = sk_X509_pop(extraCerts)) { - if (!sc->ca_store_) { - sc->ca_store_ = X509_STORE_new(); - SSL_CTX_set_cert_store(sc->ctx_, sc->ca_store_); - } - - X509_STORE_add_cert(sc->ca_store_, x509); - SSL_CTX_add_client_CA(sc->ctx_, x509); - X509_free(x509); - } + ret = true; + } + if (pkey != nullptr) EVP_PKEY_free(pkey); + if (cert != nullptr) X509_free(cert); - sk_X509_free(extraCerts); - - ret = true; - } + if (extra_certs != nullptr) + sk_X509_free(extra_certs); PKCS12_free(p12); BIO_free_all(in); @@ -2866,6 +2928,11 @@ void CipherBase::Init(const char* cipher_type, int key_buf_len) { HandleScope scope(env()->isolate()); +#ifdef NODE_FIPS_MODE + return env()->ThrowError( + "crypto.createCipher() is not supported in FIPS mode."); +#endif // NODE_FIPS_MODE + CHECK_EQ(cipher_, nullptr); cipher_ = EVP_get_cipherbyname(cipher_type); if (cipher_ == nullptr) { diff --git a/src/node_crypto.h b/src/node_crypto.h index 3bec02c38ebdec..e009fc1da63b01 100644 --- a/src/node_crypto.h +++ b/src/node_crypto.h @@ -41,6 +41,21 @@ namespace node { namespace crypto { +// Forcibly clear OpenSSL's error stack on return. This stops stale errors +// from popping up later in the lifecycle of crypto operations where they +// would cause spurious failures. It's a rather blunt method, though. +// ERR_clear_error() isn't necessarily cheap either. +struct ClearErrorOnReturn { + ~ClearErrorOnReturn() { ERR_clear_error(); } +}; + +// Pop errors from OpenSSL's error stack that were added +// between when this was constructed and destructed. +struct MarkPopErrorOnReturn { + MarkPopErrorOnReturn() { ERR_set_mark(); } + ~MarkPopErrorOnReturn() { ERR_pop_to_mark(); } +}; + enum CheckResult { CHECK_CERT_REVOKED = 0, CHECK_OK = 1 diff --git a/src/node_file.cc b/src/node_file.cc index b84e0e44c442b0..b6ef7d5b78f70e 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -580,15 +580,15 @@ static void Symlink(const FunctionCallbackInfo& args) { int len = args.Length(); if (len < 1) - return TYPE_ERROR("dest path required"); + return TYPE_ERROR("target path required"); if (len < 2) return TYPE_ERROR("src path required"); if (!args[0]->IsString()) - return TYPE_ERROR("dest path must be a string"); + return TYPE_ERROR("target path must be a string"); if (!args[1]->IsString()) return TYPE_ERROR("src path must be a string"); - node::Utf8Value dest(env->isolate(), args[0]); + node::Utf8Value target(env->isolate(), args[0]); node::Utf8Value path(env->isolate(), args[1]); int flags = 0; @@ -604,9 +604,9 @@ static void Symlink(const FunctionCallbackInfo& args) { } if (args[3]->IsObject()) { - ASYNC_DEST_CALL(symlink, args[3], *path, *dest, *path, flags) + ASYNC_DEST_CALL(symlink, args[3], *path, *target, *path, flags) } else { - SYNC_DEST_CALL(symlink, *dest, *path, *dest, *path, flags) + SYNC_DEST_CALL(symlink, *target, *path, *target, *path, flags) } } diff --git a/src/node_os.cc b/src/node_os.cc index a1000907485519..92f53a9c407fae 100644 --- a/src/node_os.cc +++ b/src/node_os.cc @@ -200,7 +200,7 @@ static void GetInterfaceAddresses(const FunctionCallbackInfo& args) { ret = Object::New(env->isolate()); if (err == UV_ENOSYS) { - args.GetReturnValue().Set(ret); + return args.GetReturnValue().Set(ret); } else if (err) { return env->ThrowUVException(err, "uv_interface_addresses"); } diff --git a/src/node_util.cc b/src/node_util.cc index 19c3e3240a52af..1e0f214ae4470a 100644 --- a/src/node_util.cc +++ b/src/node_util.cc @@ -10,31 +10,59 @@ using v8::Context; using v8::FunctionCallbackInfo; using v8::Local; using v8::Object; +using v8::String; using v8::Value; -static void IsMapIterator(const FunctionCallbackInfo& args) { - CHECK_EQ(1, args.Length()); - args.GetReturnValue().Set(args[0]->IsMapIterator()); -} +#define VALUE_METHOD_MAP(V) \ + V(isArrayBuffer, IsArrayBuffer) \ + V(isDataView, IsDataView) \ + V(isDate, IsDate) \ + V(isMap, IsMap) \ + V(isMapIterator, IsMapIterator) \ + V(isPromise, IsPromise) \ + V(isRegExp, IsRegExp) \ + V(isSet, IsSet) \ + V(isSetIterator, IsSetIterator) \ + V(isTypedArray, IsTypedArray) -static void IsSetIterator(const FunctionCallbackInfo& args) { - CHECK_EQ(1, args.Length()); - args.GetReturnValue().Set(args[0]->IsSetIterator()); -} -static void IsPromise(const FunctionCallbackInfo& args) { - CHECK_EQ(1, args.Length()); - args.GetReturnValue().Set(args[0]->IsPromise()); +#define V(_, ucname) \ + static void ucname(const FunctionCallbackInfo& args) { \ + CHECK_EQ(1, args.Length()); \ + args.GetReturnValue().Set(args[0]->ucname()); \ + } + + VALUE_METHOD_MAP(V) +#undef V + + +static void GetHiddenValue(const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args); + + if (!args[0]->IsObject()) + return env->ThrowTypeError("obj must be an object"); + + if (!args[1]->IsString()) + return env->ThrowTypeError("name must be a string"); + + Local obj = args[0].As(); + Local name = args[1].As(); + + args.GetReturnValue().Set(obj->GetHiddenValue(name)); } + void Initialize(Local target, Local unused, Local context) { Environment* env = Environment::GetCurrent(context); - env->SetMethod(target, "isMapIterator", IsMapIterator); - env->SetMethod(target, "isSetIterator", IsSetIterator); - env->SetMethod(target, "isPromise", IsPromise); + +#define V(lcname, ucname) env->SetMethod(target, #lcname, ucname); + VALUE_METHOD_MAP(V) +#undef V + + env->SetMethod(target, "getHiddenValue", GetHiddenValue); } } // namespace util diff --git a/src/tls_wrap.cc b/src/tls_wrap.cc index fc00893b77f84f..1bdd4b7df947fe 100644 --- a/src/tls_wrap.cc +++ b/src/tls_wrap.cc @@ -31,16 +31,15 @@ using v8::Object; using v8::String; using v8::Value; - TLSWrap::TLSWrap(Environment* env, Kind kind, StreamBase* stream, SecureContext* sc) - : SSLWrap(env, sc, kind), - StreamBase(env), - AsyncWrap(env, + : AsyncWrap(env, env->tls_wrap_constructor_function()->NewInstance(), AsyncWrap::PROVIDER_TLSWRAP), + SSLWrap(env, sc, kind), + StreamBase(env), sc_(sc), stream_(stream), enc_in_(nullptr), @@ -401,6 +400,8 @@ void TLSWrap::ClearOut() { if (ssl_ == nullptr) return; + crypto::MarkPopErrorOnReturn mark_pop_error_on_return; + char out[kClearOutChunkSize]; int read; for (;;) { @@ -409,6 +410,7 @@ void TLSWrap::ClearOut() { if (read <= 0) break; + char* current = out; while (read > 0) { int avail = read; @@ -416,10 +418,11 @@ void TLSWrap::ClearOut() { OnAlloc(avail, &buf); if (static_cast(buf.len) < avail) avail = buf.len; - memcpy(buf.base, out, avail); + memcpy(buf.base, current, avail); OnRead(avail, &buf); read -= avail; + current += avail; } } @@ -460,6 +463,8 @@ bool TLSWrap::ClearIn() { if (ssl_ == nullptr) return false; + crypto::MarkPopErrorOnReturn mark_pop_error_on_return; + int written = 0; while (clear_in_->Length() > 0) { size_t avail = 0; @@ -587,6 +592,8 @@ int TLSWrap::DoWrite(WriteWrap* w, if (ssl_ == nullptr) return UV_EPROTO; + crypto::MarkPopErrorOnReturn mark_pop_error_on_return; + int written = 0; for (i = 0; i < count; i++) { written = SSL_write(ssl_, bufs[i].base, bufs[i].len); @@ -702,8 +709,11 @@ void TLSWrap::DoRead(ssize_t nread, int TLSWrap::DoShutdown(ShutdownWrap* req_wrap) { + crypto::MarkPopErrorOnReturn mark_pop_error_on_return; + if (ssl_ != nullptr && SSL_shutdown(ssl_) == 0) SSL_shutdown(ssl_); + shutdown_ = true; EncOut(); return stream_->DoShutdown(req_wrap); diff --git a/src/tls_wrap.h b/src/tls_wrap.h index 47cbf27fe288e5..31d19523a62d08 100644 --- a/src/tls_wrap.h +++ b/src/tls_wrap.h @@ -21,9 +21,9 @@ namespace crypto { class SecureContext; } -class TLSWrap : public crypto::SSLWrap, - public StreamBase, - public AsyncWrap { +class TLSWrap : public AsyncWrap, + public crypto::SSLWrap, + public StreamBase { public: ~TLSWrap() override; diff --git a/test/addons/at-exit/test.js b/test/addons/at-exit/test.js index 32264a6604eeb6..c94453cb3b05a4 100644 --- a/test/addons/at-exit/test.js +++ b/test/addons/at-exit/test.js @@ -1,3 +1,3 @@ 'use strict'; require('../../common'); -var binding = require('./build/Release/binding'); +require('./build/Release/binding'); diff --git a/test/addons/buffer-free-callback/test.js b/test/addons/buffer-free-callback/test.js index 6ee328d5222049..a70931d81e8977 100644 --- a/test/addons/buffer-free-callback/test.js +++ b/test/addons/buffer-free-callback/test.js @@ -2,7 +2,6 @@ // Flags: --expose-gc require('../../common'); -var assert = require('assert'); var binding = require('./build/Release/binding'); function check(size) { diff --git a/test/addons/make-callback/test.js b/test/addons/make-callback/test.js index 80ea0db796ab30..f3c98770ef335a 100644 --- a/test/addons/make-callback/test.js +++ b/test/addons/make-callback/test.js @@ -40,7 +40,7 @@ assert.strictEqual(42, makeCallback(recv, 'two', 1337)); const target = vm.runInNewContext(` (function($Object) { if (Object === $Object) - throw Error('bad'); + throw new Error('bad'); return Object; }) `); @@ -55,7 +55,7 @@ const forward = vm.runInNewContext(` // Runs in outer context. const endpoint = function($Object) { if (Object === $Object) - throw Error('bad'); + throw new Error('bad'); return Object; }; assert.strictEqual(Object, makeCallback(process, forward, endpoint)); diff --git a/test/addons/repl-domain-abort/test.js b/test/addons/repl-domain-abort/test.js index bbd0c737eeba49..5591b4f2b38e90 100644 --- a/test/addons/repl-domain-abort/test.js +++ b/test/addons/repl-domain-abort/test.js @@ -46,4 +46,4 @@ var options = { }; // Run commands from fake REPL. -var dummy = repl.start(options); +repl.start(options); diff --git a/test/common.js b/test/common.js index b5e3c2a13b331d..bb7a3652f38a02 100644 --- a/test/common.js +++ b/test/common.js @@ -5,7 +5,11 @@ var fs = require('fs'); var assert = require('assert'); var os = require('os'); var child_process = require('child_process'); +const stream = require('stream'); +const util = require('util'); +const testRoot = path.resolve(process.env.NODE_TEST_DIR || + path.dirname(__filename)); exports.testDir = path.dirname(__filename); exports.fixturesDir = path.join(exports.testDir, 'fixtures'); @@ -20,6 +24,8 @@ exports.isLinuxPPCBE = (process.platform === 'linux') && exports.isSunOS = process.platform === 'sunos'; exports.isFreeBSD = process.platform === 'freebsd'; +exports.enoughTestMem = os.totalmem() > 0x20000000; /* 512MB */ + function rimrafSync(p) { try { var st = fs.lstatSync(p); @@ -65,18 +71,28 @@ exports.refreshTmpDir = function() { }; if (process.env.TEST_THREAD_ID) { - // Distribute ports in parallel tests - if (!process.env.NODE_COMMON_PORT) - exports.PORT += +process.env.TEST_THREAD_ID * 100; - + exports.PORT += process.env.TEST_THREAD_ID * 100; exports.tmpDirName += '.' + process.env.TEST_THREAD_ID; } -exports.tmpDir = path.join(exports.testDir, exports.tmpDirName); +exports.tmpDir = path.join(testRoot, exports.tmpDirName); var opensslCli = null; var inFreeBSDJail = null; var localhostIPv4 = null; +exports.localIPv6Hosts = [ + // Debian/Ubuntu + 'ip6-localhost', + 'ip6-loopback', + + // SUSE + 'ipv6-localhost', + 'ipv6-loopback', + + // Typically universal + 'localhost', +]; + Object.defineProperty(exports, 'inFreeBSDJail', { get: function() { if (inFreeBSDJail !== null) return inFreeBSDJail; @@ -151,21 +167,13 @@ Object.defineProperty(exports, 'hasFipsCrypto', { if (exports.isWindows) { exports.PIPE = '\\\\.\\pipe\\libuv-test'; + if (process.env.TEST_THREAD_ID) { + exports.PIPE += '.' + process.env.TEST_THREAD_ID; + } } else { exports.PIPE = exports.tmpDir + '/test.sock'; } -if (process.env.NODE_COMMON_PIPE) { - exports.PIPE = process.env.NODE_COMMON_PIPE; - // Remove manually, the test runner won't do it - // for us like it does for files in test/tmp. - try { - fs.unlinkSync(exports.PIPE); - } catch (e) { - // Ignore. - } -} - if (exports.isWindows) { exports.faketimeCli = false; } else { @@ -238,13 +246,21 @@ exports.spawnPwd = function(options) { }; exports.platformTimeout = function(ms) { + if (process.config.target_defaults.default_configuration === 'Debug') + ms = 2 * ms; + if (process.arch !== 'arm') return ms; - if (process.config.variables.arm_version === '6') + const armv = process.config.variables.arm_version; + + if (armv === '6') return 7 * ms; // ARMv6 - return 2 * ms; // ARMv7 and up. + if (armv === '7') + return 2 * ms; // ARMv7 + + return ms; // ARMv8+ }; var knownGlobals = [setTimeout, @@ -483,3 +499,20 @@ exports.nodeProcessAborted = function nodeProcessAborted(exitCode, signal) { return expectedExitCodes.indexOf(exitCode) > -1; } }; + +// A stream to push an array into a REPL +function ArrayStream() { + this.run = function(data) { + data.forEach(line => { + this.emit('data', line + '\n'); + }); + }; +} + +util.inherits(ArrayStream, stream.Stream); +exports.ArrayStream = ArrayStream; +ArrayStream.prototype.readable = true; +ArrayStream.prototype.writable = true; +ArrayStream.prototype.pause = function() {}; +ArrayStream.prototype.resume = function() {}; +ArrayStream.prototype.write = function() {}; diff --git a/test/debugger/test-debugger-pid.js b/test/debugger/test-debugger-pid.js index 14a281ab3ce4cc..6a977d7cfa72e8 100644 --- a/test/debugger/test-debugger-pid.js +++ b/test/debugger/test-debugger-pid.js @@ -1,16 +1,9 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var spawn = require('child_process').spawn; -var port = common.PORT + 1337; var buffer = ''; -var expected = []; -var scriptToDebug = common.fixturesDir + '/empty.js'; - -function fail() { - assert(0); // `--debug-brk script.js` should not quit -} // connect to debug agent var interfacer = spawn(process.execPath, ['debug', '-p', '655555']); diff --git a/test/debugger/test-debugger-remote.js b/test/debugger/test-debugger-remote.js index 81ed8b41ab0198..f5232dce9c8df4 100644 --- a/test/debugger/test-debugger-remote.js +++ b/test/debugger/test-debugger-remote.js @@ -3,9 +3,7 @@ var common = require('../common'); var assert = require('assert'); var spawn = require('child_process').spawn; -var port = common.PORT + 1337; var buffer = ''; -var expected = []; var scriptToDebug = common.fixturesDir + '/empty.js'; function fail() { diff --git a/test/fixtures/.empty-repl-history-file b/test/fixtures/.empty-repl-history-file new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/test/fixtures/exports-function-with-param.js b/test/fixtures/exports-function-with-param.js new file mode 100644 index 00000000000000..263b9064422108 --- /dev/null +++ b/test/fixtures/exports-function-with-param.js @@ -0,0 +1 @@ +module.exports = function foo(arg) { return arg; } diff --git a/test/fixtures/keys/Makefile b/test/fixtures/keys/Makefile index 143986274a6b93..1148e529cd9595 100644 --- a/test/fixtures/keys/Makefile +++ b/test/fixtures/keys/Makefile @@ -79,6 +79,14 @@ agent1-cert.pem: agent1-csr.pem ca1-cert.pem ca1-key.pem -CAcreateserial \ -out agent1-cert.pem +agent1-pfx.pem: agent1-cert.pem agent1-key.pem ca1-cert.pem + openssl pkcs12 -export \ + -in agent1-cert.pem \ + -inkey agent1-key.pem \ + -certfile ca1-cert.pem \ + -out agent1-pfx.pem \ + -password pass:sample + agent1-verify: agent1-cert.pem ca1-cert.pem openssl verify -CAfile ca1-cert.pem agent1-cert.pem diff --git a/test/fixtures/keys/agent1-pfx.pem b/test/fixtures/keys/agent1-pfx.pem new file mode 100644 index 00000000000000..a36e746a72e06e Binary files /dev/null and b/test/fixtures/keys/agent1-pfx.pem differ diff --git a/test/fixtures/node_modules/baz/index.js b/test/fixtures/node_modules/baz/index.js index 346f068ec52a2b..859ea0924d6fb7 100644 --- a/test/fixtures/node_modules/baz/index.js +++ b/test/fixtures/node_modules/baz/index.js @@ -6,3 +6,5 @@ assert.equal(require('bar'), require('../bar.js')); // this should work, and get the one in ./node_modules/asdf.js assert.equal(require('asdf'), require('./node_modules/asdf.js')); + +module.exports = 'eye catcher'; diff --git a/test/fixtures/test-error-first-line-offset.js b/test/fixtures/test-error-first-line-offset.js new file mode 100644 index 00000000000000..8276753746b12b --- /dev/null +++ b/test/fixtures/test-error-first-line-offset.js @@ -0,0 +1 @@ +error diff --git a/test/fixtures/throws_error7.js b/test/fixtures/throws_error7.js new file mode 100644 index 00000000000000..f730bc6def1ba9 --- /dev/null +++ b/test/fixtures/throws_error7.js @@ -0,0 +1,5 @@ +throw { + toString: function() { + throw this; + } +}; diff --git a/test/gc/test-http-client-onerror.js b/test/gc/test-http-client-onerror.js index 98d046e180f11b..7e50683c6633e5 100644 --- a/test/gc/test-http-client-onerror.js +++ b/test/gc/test-http-client-onerror.js @@ -22,7 +22,7 @@ console.log('We should do ' + todo + ' requests'); var http = require('http'); var server = http.createServer(serverHandler); -server.listen(PORT, getall); +server.listen(PORT, runTest); function getall() { if (count >= todo) @@ -51,8 +51,10 @@ function getall() { setImmediate(getall); } -for (var i = 0; i < 10; i++) - getall(); +function runTest() { + for (var i = 0; i < 10; i++) + getall(); +} function afterGC() { countGC ++; diff --git a/test/internet/test-dgram-multicast-multi-process.js b/test/internet/test-dgram-multicast-multi-process.js index 0bef2e1dc028c1..f72402eef64147 100644 --- a/test/internet/test-dgram-multicast-multi-process.js +++ b/test/internet/test-dgram-multicast-multi-process.js @@ -1,30 +1,122 @@ 'use strict'; -var common = require('../common'), - assert = require('assert'), - dgram = require('dgram'), - util = require('util'), - Buffer = require('buffer').Buffer, - fork = require('child_process').fork, - LOCAL_BROADCAST_HOST = '224.0.0.114', - TIMEOUT = common.platformTimeout(5000), - messages = [ - new Buffer('First message to send'), - new Buffer('Second message to send'), - new Buffer('Third message to send'), - new Buffer('Fourth message to send') - ]; +const common = require('../common'); +const assert = require('assert'); +const dgram = require('dgram'); +const fork = require('child_process').fork; +const LOCAL_BROADCAST_HOST = '224.0.0.114'; +const TIMEOUT = common.platformTimeout(5000); +const messages = [ + new Buffer('First message to send'), + new Buffer('Second message to send'), + new Buffer('Third message to send'), + new Buffer('Fourth message to send') +]; +const workers = {}; +const listeners = 3; + + +// Skip test in FreeBSD jails. +if (common.inFreeBSDJail) { + console.log('1..0 # Skipped: In a FreeBSD jail'); + return; +} + +function launchChildProcess(index) { + const worker = fork(__filename, ['child']); + workers[worker.pid] = worker; + + worker.messagesReceived = []; + + // Handle the death of workers. + worker.on('exit', function(code, signal) { + // Don't consider this the true death if the worker has finished + // successfully or if the exit code is 0. + if (worker.isDone || code === 0) { + return; + } + + dead += 1; + console.error('[PARENT] Worker %d died. %d dead of %d', + worker.pid, + dead, + listeners); + + if (dead === listeners) { + console.error('[PARENT] All workers have died.'); + console.error('[PARENT] Fail'); + process.exit(1); + } + }); + + worker.on('message', function(msg) { + if (msg.listening) { + listening += 1; + + if (listening === listeners) { + // All child process are listening, so start sending. + sendSocket.sendNext(); + } + return; + } + if (msg.message) { + worker.messagesReceived.push(msg.message); + + if (worker.messagesReceived.length === messages.length) { + done += 1; + worker.isDone = true; + console.error('[PARENT] %d received %d messages total.', + worker.pid, + worker.messagesReceived.length); + } + + if (done === listeners) { + console.error('[PARENT] All workers have received the ' + + 'required number of messages. Will now compare.'); + + Object.keys(workers).forEach(function(pid) { + const worker = workers[pid]; + + var count = 0; + + worker.messagesReceived.forEach(function(buf) { + for (var i = 0; i < messages.length; ++i) { + if (buf.toString() === messages[i].toString()) { + count++; + break; + } + } + }); + + console.error('[PARENT] %d received %d matching messages.', + worker.pid, count); + + assert.strictEqual(count, messages.length, + 'A worker received an invalid multicast message'); + }); + + clearTimeout(timer); + console.error('[PARENT] Success'); + killChildren(workers); + } + } + }); +} + +function killChildren(children) { + Object.keys(children).forEach(function(key) { + const child = children[key]; + child.kill(); + }); +} if (process.argv[2] !== 'child') { - var workers = {}, - listeners = 3, - listening = 0, - dead = 0, - i = 0, - done = 0, - timer = null; - - //exit the test if it doesn't succeed within TIMEOUT - timer = setTimeout(function() { + var listening = 0; + var dead = 0; + var i = 0; + var done = 0; + + // Exit the test if it doesn't succeed within TIMEOUT. + var timer = setTimeout(function() { console.error('[PARENT] Responses were not received within %d ms.', TIMEOUT); console.error('[PARENT] Fail'); @@ -34,101 +126,18 @@ if (process.argv[2] !== 'child') { process.exit(1); }, TIMEOUT); - //launch child processes + // Launch child processes. for (var x = 0; x < listeners; x++) { - (function() { - var worker = fork(process.argv[1], ['child']); - workers[worker.pid] = worker; - - worker.messagesReceived = []; - - //handle the death of workers - worker.on('exit', function(code, signal) { - // don't consider this the true death if the - // worker has finished successfully - - // or if the exit code is 0 - if (worker.isDone || code === 0) { - return; - } - - dead += 1; - console.error('[PARENT] Worker %d died. %d dead of %d', - worker.pid, - dead, - listeners); - - if (dead === listeners) { - console.error('[PARENT] All workers have died.'); - console.error('[PARENT] Fail'); - - killChildren(workers); - - process.exit(1); - } - }); - - worker.on('message', function(msg) { - if (msg.listening) { - listening += 1; - - if (listening === listeners) { - //all child process are listening, so start sending - sendSocket.sendNext(); - } - } - else if (msg.message) { - worker.messagesReceived.push(msg.message); - - if (worker.messagesReceived.length === messages.length) { - done += 1; - worker.isDone = true; - console.error('[PARENT] %d received %d messages total.', - worker.pid, - worker.messagesReceived.length); - } - - if (done === listeners) { - console.error('[PARENT] All workers have received the ' + - 'required number of messages. Will now compare.'); - - Object.keys(workers).forEach(function(pid) { - var worker = workers[pid]; - - var count = 0; - - worker.messagesReceived.forEach(function(buf) { - for (var i = 0; i < messages.length; ++i) { - if (buf.toString() === messages[i].toString()) { - count++; - break; - } - } - }); - - console.error('[PARENT] %d received %d matching messages.', - worker.pid, count); - - assert.equal(count, messages.length, - 'A worker received an invalid multicast message'); - }); - - clearTimeout(timer); - console.error('[PARENT] Success'); - killChildren(workers); - } - } - }); - })(x); + launchChildProcess(x); } var sendSocket = dgram.createSocket('udp4'); - // FIXME a libuv limitation makes it necessary to bind() - // before calling any of the set*() functions - the bind() - // call is what creates the actual socket... + // FIXME: a libuv limitation makes it necessary to bind() + // before calling any of the set*() functions. The bind() + // call is what creates the actual socket. sendSocket.bind(); - // The socket is actually created async now + // The socket is actually created async now. sendSocket.on('listening', function() { sendSocket.setTTL(1); sendSocket.setBroadcast(true); @@ -141,7 +150,7 @@ if (process.argv[2] !== 'child') { }); sendSocket.sendNext = function() { - var buf = messages[i++]; + const buf = messages[i++]; if (!buf) { try { sendSocket.close(); } catch (e) {} @@ -151,61 +160,51 @@ if (process.argv[2] !== 'child') { sendSocket.send(buf, 0, buf.length, common.PORT, LOCAL_BROADCAST_HOST, function(err) { if (err) throw err; - console.error('[PARENT] sent %s to %s:%s', - util.inspect(buf.toString()), + console.error('[PARENT] sent "%s" to %s:%s', + buf.toString(), LOCAL_BROADCAST_HOST, common.PORT); process.nextTick(sendSocket.sendNext); }); }; - - function killChildren(children) { - Object.keys(children).forEach(function(key) { - var child = children[key]; - child.kill(); - }); - } } if (process.argv[2] === 'child') { - var receivedMessages = []; - var listenSocket = dgram.createSocket({ + const receivedMessages = []; + const listenSocket = dgram.createSocket({ type: 'udp4', reuseAddr: true }); - listenSocket.on('message', function(buf, rinfo) { - console.error('[CHILD] %s received %s from %j', process.pid, - util.inspect(buf.toString()), rinfo); + listenSocket.on('listening', function() { + listenSocket.addMembership(LOCAL_BROADCAST_HOST); - receivedMessages.push(buf); + listenSocket.on('message', function(buf, rinfo) { + console.error('[CHILD] %s received "%s" from %j', process.pid, + buf.toString(), rinfo); - process.send({ message: buf.toString() }); + receivedMessages.push(buf); - if (receivedMessages.length == messages.length) { - // .dropMembership() not strictly needed but here as a sanity check - listenSocket.dropMembership(LOCAL_BROADCAST_HOST); - process.nextTick(function() { - listenSocket.close(); - }); - } - }); + process.send({ message: buf.toString() }); - listenSocket.on('close', function() { - //HACK: Wait to exit the process to ensure that the parent - //process has had time to receive all messages via process.send() - //This may be indicitave of some other issue. - setTimeout(function() { - process.exit(); - }, 1000); - }); + if (receivedMessages.length == messages.length) { + // .dropMembership() not strictly needed but here as a sanity check. + listenSocket.dropMembership(LOCAL_BROADCAST_HOST); + process.nextTick(function() { + listenSocket.close(); + }); + } + }); - listenSocket.on('listening', function() { + listenSocket.on('close', function() { + // HACK: Wait to exit the process to ensure that the parent + // process has had time to receive all messages via process.send() + // This may be indicative of some other issue. + setTimeout(function() { + process.exit(); + }, common.platformTimeout(1000)); + }); process.send({ listening: true }); }); listenSocket.bind(common.PORT); - - listenSocket.on('listening', function() { - listenSocket.addMembership(LOCAL_BROADCAST_HOST); - }); } diff --git a/test/internet/test-dns-ipv4.js b/test/internet/test-dns-ipv4.js index 04befca6370e1e..bdca60d1b4fd5d 100644 --- a/test/internet/test-dns-ipv4.js +++ b/test/internet/test-dns-ipv4.js @@ -3,9 +3,7 @@ var common = require('../common'); var assert = require('assert'), dns = require('dns'), net = require('net'), - isIP = net.isIP, isIPv4 = net.isIPv4; -var util = require('util'); var expected = 0, completed = 0, diff --git a/test/internet/test-dns-ipv6.js b/test/internet/test-dns-ipv6.js index 27547edcd84b46..d7c50a1e86b656 100644 --- a/test/internet/test-dns-ipv6.js +++ b/test/internet/test-dns-ipv6.js @@ -3,9 +3,7 @@ var common = require('../common'); var assert = require('assert'), dns = require('dns'), net = require('net'), - isIP = net.isIP, isIPv6 = net.isIPv6; -var util = require('util'); var expected = 0, completed = 0, diff --git a/test/internet/test-dns-txt-sigsegv.js b/test/internet/test-dns-txt-sigsegv.js index eba5c66c464981..4c2f12f7a97c28 100644 --- a/test/internet/test-dns-txt-sigsegv.js +++ b/test/internet/test-dns-txt-sigsegv.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var dns = require('dns'); diff --git a/test/internet/test-dns.js b/test/internet/test-dns.js index 2a423f97dee7b0..6448ad7c76b07b 100644 --- a/test/internet/test-dns.js +++ b/test/internet/test-dns.js @@ -1,9 +1,8 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'), dns = require('dns'), net = require('net'), - isIP = net.isIP, isIPv4 = net.isIPv4, isIPv6 = net.isIPv6; var util = require('util'); @@ -48,7 +47,7 @@ TEST(function test_reverse_bogus(done) { var error; try { - var req = dns.reverse('bogus ip', function() { + dns.reverse('bogus ip', function() { assert.ok(false); }); } catch (e) { @@ -369,7 +368,7 @@ console.log('looking up nodejs.org...'); var cares = process.binding('cares_wrap'); var req = new cares.GetAddrInfoReqWrap(); -var err = cares.getaddrinfo(req, 'nodejs.org', 4); +cares.getaddrinfo(req, 'nodejs.org', 4); req.oncomplete = function(err, domains) { assert.strictEqual(err, 0); diff --git a/test/internet/test-http-dns-fail.js b/test/internet/test-http-dns-fail.js index 151597de14cb0e..7e2f8cd402d658 100644 --- a/test/internet/test-http-dns-fail.js +++ b/test/internet/test-http-dns-fail.js @@ -4,7 +4,7 @@ * should trigger the error event after each attempt. */ -var common = require('../common'); +require('../common'); var assert = require('assert'); var http = require('http'); diff --git a/test/internet/test-net-connect-timeout.js b/test/internet/test-net-connect-timeout.js index b92d234852967e..fd78a2936bd88b 100644 --- a/test/internet/test-net-connect-timeout.js +++ b/test/internet/test-net-connect-timeout.js @@ -3,7 +3,7 @@ // https://groups.google.com/forum/#!topic/nodejs/UE0ZbfLt6t8 // https://groups.google.com/forum/#!topic/nodejs-dev/jR7-5UDqXkw -var common = require('../common'); +require('../common'); var net = require('net'); var assert = require('assert'); diff --git a/test/internet/test-net-connect-unref.js b/test/internet/test-net-connect-unref.js index a712490d31f566..ad24683b34d49e 100644 --- a/test/internet/test-net-connect-unref.js +++ b/test/internet/test-net-connect-unref.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var net = require('net'); diff --git a/test/message/2100bytes.js b/test/message/2100bytes.js index b05f5e9e1d7168..0f696806be03fe 100644 --- a/test/message/2100bytes.js +++ b/test/message/2100bytes.js @@ -1,7 +1,5 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); -var util = require('util'); +require('../common'); console.log([ '_______________________________________________50', diff --git a/test/message/core_line_numbers.js b/test/message/core_line_numbers.js new file mode 100644 index 00000000000000..221001ed8952d0 --- /dev/null +++ b/test/message/core_line_numbers.js @@ -0,0 +1,11 @@ +'use strict'; +require('../common'); +const punycode = require('punycode'); + +// This test verifies that line numbers in core modules are reported correctly. +// The punycode module was chosen for testing because it changes infrequently. +// If this test begins failing, it is likely due to a punycode update, and the +// test's assertions simply need to be updated to reflect the changes. If a +// punycode update was not made, and this test begins failing, then line numbers +// are probably actually broken. +punycode.decode('x'); diff --git a/test/message/core_line_numbers.out b/test/message/core_line_numbers.out new file mode 100644 index 00000000000000..c4909774a0e6ec --- /dev/null +++ b/test/message/core_line_numbers.out @@ -0,0 +1,15 @@ +punycode.js:67 + throw new RangeError(errors[type]); + ^ + +RangeError: Invalid input + at error (punycode.js:67:*) + at Object.decode (punycode.js:*:*) + at Object. (*test*message*core_line_numbers.js:*:*) + at Module._compile (module.js:*:*) + at Object.Module._extensions..js (module.js:*:*) + at Module.load (module.js:*:*) + at Function.Module._load (module.js:*:*) + at Function.Module.runMain (module.js:*:*) + at startup (node.js:*:*) + at node.js:*:* diff --git a/test/message/error_exit.js b/test/message/error_exit.js index 7805fd21935377..18d9dfb4ee998c 100644 --- a/test/message/error_exit.js +++ b/test/message/error_exit.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); process.on('exit', function(code) { diff --git a/test/message/eval_messages.js b/test/message/eval_messages.js index 0b17bf5f97ae52..bb1569601c889f 100644 --- a/test/message/eval_messages.js +++ b/test/message/eval_messages.js @@ -1,7 +1,6 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); +require('../common'); var spawn = require('child_process').spawn; diff --git a/test/message/eval_messages.out b/test/message/eval_messages.out index b02da9b2808087..4fb3c7f56d5859 100644 --- a/test/message/eval_messages.out +++ b/test/message/eval_messages.out @@ -7,7 +7,7 @@ SyntaxError: Strict mode code may not include a with statement at Object. ([eval]-wrapper:*:*) at Module._compile (module.js:*:*) at node.js:*:* - at doNTCallback0 (node.js:*:*) + at nextTickCallbackWith0Args (node.js:*:*) at process._tickCallback (node.js:*:*) 42 42 @@ -20,7 +20,7 @@ Error: hello at Object. ([eval]-wrapper:*:*) at Module._compile (module.js:*:*) at node.js:*:* - at doNTCallback0 (node.js:*:*) + at nextTickCallbackWith0Args (node.js:*:*) at process._tickCallback (node.js:*:*) [eval]:1 throw new Error("hello") @@ -31,7 +31,7 @@ Error: hello at Object. ([eval]-wrapper:*:*) at Module._compile (module.js:*:*) at node.js:*:* - at doNTCallback0 (node.js:*:*) + at nextTickCallbackWith0Args (node.js:*:*) at process._tickCallback (node.js:*:*) 100 [eval]:1 @@ -43,7 +43,7 @@ ReferenceError: y is not defined at Object. ([eval]-wrapper:*:*) at Module._compile (module.js:*:*) at node.js:*:* - at doNTCallback0 (node.js:*:*) + at nextTickCallbackWith0Args (node.js:*:*) at process._tickCallback (node.js:*:*) [eval]:1 var ______________________________________________; throw 10 diff --git a/test/message/hello_world.js b/test/message/hello_world.js index 1e6b030393c6cf..187bbd2cfcf7f7 100644 --- a/test/message/hello_world.js +++ b/test/message/hello_world.js @@ -1,5 +1,4 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); +require('../common'); console.log('hello world'); diff --git a/test/message/max_tick_depth.js b/test/message/max_tick_depth.js index cacd795810605a..1d2ec175c5d957 100644 --- a/test/message/max_tick_depth.js +++ b/test/message/max_tick_depth.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); process.maxTickDepth = 10; var i = 20; diff --git a/test/message/nexttick_throw.js b/test/message/nexttick_throw.js index 3c0e2d8e379fd9..22f61a36f947df 100644 --- a/test/message/nexttick_throw.js +++ b/test/message/nexttick_throw.js @@ -1,6 +1,5 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); +require('../common'); process.nextTick(function() { process.nextTick(function() { diff --git a/test/message/nexttick_throw.out b/test/message/nexttick_throw.out index 1dd60694a892b8..1e03f6de84b90a 100644 --- a/test/message/nexttick_throw.out +++ b/test/message/nexttick_throw.out @@ -4,7 +4,7 @@ ^ ReferenceError: undefined_reference_error_maker is not defined at *test*message*nexttick_throw.js:*:* - at doNTCallback0 (node.js:*:*) + at nextTickCallbackWith0Args (node.js:*:*) at process._tickCallback (node.js:*:*) at Function.Module.runMain (module.js:*:*) at startup (node.js:*:*) diff --git a/test/message/stack_overflow.js b/test/message/stack_overflow.js index 7d1033c3ab2b1a..cef53bfb3d35c5 100644 --- a/test/message/stack_overflow.js +++ b/test/message/stack_overflow.js @@ -1,6 +1,5 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); +require('../common'); Error.stackTraceLimit = 0; diff --git a/test/message/stdin_messages.js b/test/message/stdin_messages.js index e99c08553a916d..6e1ced4124f2a6 100644 --- a/test/message/stdin_messages.js +++ b/test/message/stdin_messages.js @@ -1,7 +1,6 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); +require('../common'); var spawn = require('child_process').spawn; diff --git a/test/message/stdin_messages.out b/test/message/stdin_messages.out index 94a55c79aba043..57908426079e15 100644 --- a/test/message/stdin_messages.out +++ b/test/message/stdin_messages.out @@ -8,7 +8,7 @@ SyntaxError: Strict mode code may not include a with statement at Object. ([stdin]-wrapper:*:*) at Module._compile (module.js:*:*) at node.js:*:* - at doNTCallback0 (node.js:*:*) + at nextTickCallbackWith0Args (node.js:*:*) at process._tickCallback (node.js:*:*) 42 42 @@ -22,7 +22,7 @@ Error: hello at Object. ([stdin]-wrapper:*:*) at Module._compile (module.js:*:*) at node.js:*:* - at doNTCallback0 (node.js:*:*) + at nextTickCallbackWith0Args (node.js:*:*) at process._tickCallback (node.js:*:*) [stdin]:1 @@ -34,7 +34,7 @@ Error: hello at Object. ([stdin]-wrapper:*:*) at Module._compile (module.js:*:*) at node.js:*:* - at doNTCallback0 (node.js:*:*) + at nextTickCallbackWith0Args (node.js:*:*) at process._tickCallback (node.js:*:*) 100 @@ -47,7 +47,7 @@ ReferenceError: y is not defined at Object. ([stdin]-wrapper:*:*) at Module._compile (module.js:*:*) at node.js:*:* - at doNTCallback0 (node.js:*:*) + at nextTickCallbackWith0Args (node.js:*:*) at process._tickCallback (node.js:*:*) [stdin]:1 diff --git a/test/message/throw_custom_error.js b/test/message/throw_custom_error.js index bb5dae05a9b03a..8866ca8514de7d 100644 --- a/test/message/throw_custom_error.js +++ b/test/message/throw_custom_error.js @@ -1,6 +1,5 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); +require('../common'); // custom error throwing throw ({ name: 'MyCustomError', message: 'This is a custom message' }); diff --git a/test/message/throw_custom_error.out b/test/message/throw_custom_error.out index ef73c52c889dff..401581f31d5caf 100644 --- a/test/message/throw_custom_error.out +++ b/test/message/throw_custom_error.out @@ -1,4 +1,4 @@ -*test*message*throw_custom_error.js:6 +*test*message*throw_custom_error.js:5 throw ({ name: 'MyCustomError', message: 'This is a custom message' }); ^ MyCustomError: This is a custom message diff --git a/test/message/throw_in_line_with_tabs.js b/test/message/throw_in_line_with_tabs.js index 50c69ca681019d..3bb403feb3221b 100644 --- a/test/message/throw_in_line_with_tabs.js +++ b/test/message/throw_in_line_with_tabs.js @@ -1,7 +1,6 @@ /* eslint-disable indent */ 'use strict'; -var common = require('../common'); -var assert = require('assert'); +require('../common'); console.error('before'); diff --git a/test/message/throw_in_line_with_tabs.out b/test/message/throw_in_line_with_tabs.out index e83b05768433b8..d245cca4941ab5 100644 --- a/test/message/throw_in_line_with_tabs.out +++ b/test/message/throw_in_line_with_tabs.out @@ -1,5 +1,5 @@ before -*test*message*throw_in_line_with_tabs.js:10 +*test*message*throw_in_line_with_tabs.js:9 throw ({ foo: 'bar' }); ^ [object Object] diff --git a/test/message/throw_non_error.js b/test/message/throw_non_error.js index a1046b725e93a4..d4dae642af882b 100644 --- a/test/message/throw_non_error.js +++ b/test/message/throw_non_error.js @@ -1,6 +1,5 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); +require('../common'); // custom error throwing throw ({ foo: 'bar' }); diff --git a/test/message/throw_non_error.out b/test/message/throw_non_error.out index 15f95fcc11699a..b98edc46ae2a6e 100644 --- a/test/message/throw_non_error.out +++ b/test/message/throw_non_error.out @@ -1,4 +1,4 @@ -*test*message*throw_non_error.js:6 +*test*message*throw_non_error.js:5 throw ({ foo: 'bar' }); ^ [object Object] diff --git a/test/message/throw_null.js b/test/message/throw_null.js index ab8fb565a61e54..9b17aa68f186e4 100644 --- a/test/message/throw_null.js +++ b/test/message/throw_null.js @@ -1,5 +1,4 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); +require('../common'); throw null; diff --git a/test/message/throw_null.out b/test/message/throw_null.out index eb3eeb1294e727..5d2c677240d1a7 100644 --- a/test/message/throw_null.out +++ b/test/message/throw_null.out @@ -1,5 +1,5 @@ -*test*message*throw_null.js:5 +*test*message*throw_null.js:4 throw null; ^ null diff --git a/test/message/throw_undefined.js b/test/message/throw_undefined.js index f855cdd2f7dabd..18c27dbac87799 100644 --- a/test/message/throw_undefined.js +++ b/test/message/throw_undefined.js @@ -1,5 +1,4 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); +require('../common'); throw undefined; diff --git a/test/message/throw_undefined.out b/test/message/throw_undefined.out index c23dac051fa5f1..32a71f0486e47e 100644 --- a/test/message/throw_undefined.out +++ b/test/message/throw_undefined.out @@ -1,5 +1,5 @@ -*test*message*throw_undefined.js:5 +*test*message*throw_undefined.js:4 throw undefined; ^ undefined diff --git a/test/message/timeout_throw.js b/test/message/timeout_throw.js index aaf3fbc8d2f48f..5c345ac8c0c376 100644 --- a/test/message/timeout_throw.js +++ b/test/message/timeout_throw.js @@ -1,6 +1,5 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); +require('../common'); setTimeout(function() { undefined_reference_error_maker; diff --git a/test/message/undefined_reference_in_new_context.js b/test/message/undefined_reference_in_new_context.js index 7256c0d8e36088..73821ae53d4f5f 100644 --- a/test/message/undefined_reference_in_new_context.js +++ b/test/message/undefined_reference_in_new_context.js @@ -1,6 +1,5 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); +require('../common'); var vm = require('vm'); console.error('before'); diff --git a/test/message/vm_display_runtime_error.js b/test/message/vm_display_runtime_error.js index d01ab0b540b3cb..a7ca9907444181 100644 --- a/test/message/vm_display_runtime_error.js +++ b/test/message/vm_display_runtime_error.js @@ -1,6 +1,5 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); +require('../common'); var vm = require('vm'); console.error('beginning'); diff --git a/test/message/vm_display_syntax_error.js b/test/message/vm_display_syntax_error.js index 179263478b84b8..23525c14d822fb 100644 --- a/test/message/vm_display_syntax_error.js +++ b/test/message/vm_display_syntax_error.js @@ -1,6 +1,5 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); +require('../common'); var vm = require('vm'); console.error('beginning'); diff --git a/test/message/vm_dont_display_runtime_error.js b/test/message/vm_dont_display_runtime_error.js index 6b4c824cbe5eff..19d0120a90abfd 100644 --- a/test/message/vm_dont_display_runtime_error.js +++ b/test/message/vm_dont_display_runtime_error.js @@ -1,6 +1,5 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); +require('../common'); var vm = require('vm'); console.error('beginning'); diff --git a/test/message/vm_dont_display_syntax_error.js b/test/message/vm_dont_display_syntax_error.js index 42b1ab14cba76f..bff0433a144b09 100644 --- a/test/message/vm_dont_display_syntax_error.js +++ b/test/message/vm_dont_display_syntax_error.js @@ -1,6 +1,5 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); +require('../common'); var vm = require('vm'); console.error('beginning'); diff --git a/test/parallel/parallel.status b/test/parallel/parallel.status index 56a0ab21b0a0b7..ced1680ef9d66b 100644 --- a/test/parallel/parallel.status +++ b/test/parallel/parallel.status @@ -7,14 +7,13 @@ prefix parallel [true] # This section applies to all platforms [$system==win32] +test-child-process-fork-regr-gh-2847 : PASS,FLAKY test-cluster-net-send : PASS,FLAKY +test-cluster-shared-leak : PASS,FLAKY +test-debug-no-context : PASS,FLAKY test-tls-ticket-cluster : PASS,FLAKY -test-child-process-fork-regr-gh-2847 : PASS,FLAKY [$system==linux] -test-http-client-timeout-event : PASS,FLAKY -test-child-process-buffering : PASS,FLAKY -test-child-process-exit-code : PASS,FLAKY [$system==macos] @@ -22,4 +21,3 @@ test-child-process-exit-code : PASS,FLAKY test-debug-signal-cluster : PASS,FLAKY [$system==freebsd] -test-net-socket-local-address : PASS,FLAKY diff --git a/test/parallel/test-assert-typedarray-deepequal.js b/test/parallel/test-assert-typedarray-deepequal.js new file mode 100644 index 00000000000000..68edefdc175317 --- /dev/null +++ b/test/parallel/test-assert-typedarray-deepequal.js @@ -0,0 +1,41 @@ +'use strict'; + +require('../common'); +const assert = require('assert'); +const a = require('assert'); + +function makeBlock(f) { + var args = Array.prototype.slice.call(arguments, 1); + return function() { + return f.apply(this, args); + }; +} + +const equalArrayPairs = [ + [new Uint8Array(1e5), new Uint8Array(1e5)], + [new Uint16Array(1e5), new Uint16Array(1e5)], + [new Uint32Array(1e5), new Uint32Array(1e5)], + [new Uint8ClampedArray(1e5), new Uint8ClampedArray(1e5)], + [new Int8Array(1e5), new Int8Array(1e5)], + [new Int16Array(1e5), new Int16Array(1e5)], + [new Int32Array(1e5), new Int32Array(1e5)], + [new Float32Array(1e5), new Float32Array(1e5)], + [new Float64Array(1e5), new Float64Array(1e5)] +]; + +const notEqualArrayPairs = [ + [new Uint8Array(2), new Uint8Array(3)], + [new Uint8Array([1, 2, 3]), new Uint8Array([4, 5, 6])], + [new Uint8ClampedArray([300, 2, 3]), new Uint8Array([300, 2, 3])] +]; + +equalArrayPairs.forEach((arrayPair) => { + assert.deepEqual(arrayPair[0], arrayPair[1]); +}); + +notEqualArrayPairs.forEach((arrayPair) => { + assert.throws( + makeBlock(a.deepEqual, arrayPair[0], arrayPair[1]), + a.AssertionError + ); +}); diff --git a/test/parallel/test-assert.js b/test/parallel/test-assert.js index db36abc184b024..e9c01fda773d9e 100644 --- a/test/parallel/test-assert.js +++ b/test/parallel/test-assert.js @@ -271,8 +271,6 @@ assert.throws(makeBlock(a.deepStrictEqual, new Boolean(true), {}), function thrower(errorConstructor) { throw new errorConstructor('test'); } -var aethrow = makeBlock(thrower, a.AssertionError); -aethrow = makeBlock(thrower, a.AssertionError); // the basic calls work assert.throws(makeBlock(thrower, a.AssertionError), @@ -344,9 +342,28 @@ a.throws(makeBlock(thrower, TypeError), function(err) { } }); +// https://github.com/nodejs/node/issues/3188 +threw = false; -// GH-207. Make sure deepEqual doesn't loop forever on circular refs +try { + var ES6Error = class extends Error {}; + + var AnotherErrorType = class extends Error {}; + const functionThatThrows = function() { + throw new AnotherErrorType('foo'); + }; + + assert.throws(functionThatThrows, ES6Error); +} catch (e) { + threw = true; + assert(e instanceof AnotherErrorType, + `expected AnotherErrorType, received ${e}`); +} + +assert.ok(threw); + +// GH-207. Make sure deepEqual doesn't loop forever on circular refs var b = {}; b.b = b; @@ -465,6 +482,6 @@ testBlockTypeError(assert.doesNotThrow, undefined); // https://github.com/nodejs/node/issues/3275 assert.throws(() => { throw 'error'; }, err => err === 'error'); -assert.throws(() => { throw Error(); }, err => err instanceof Error); +assert.throws(() => { throw new Error(); }, err => err instanceof Error); console.log('All OK'); diff --git a/test/parallel/test-async-wrap-check-providers.js b/test/parallel/test-async-wrap-check-providers.js index 2d7d318885eb16..45dd8d4f24048b 100644 --- a/test/parallel/test-async-wrap-check-providers.js +++ b/test/parallel/test-async-wrap-check-providers.js @@ -73,16 +73,17 @@ process.on('SIGINT', () => process.exit()); // Run from closed net server above. function checkTLS() { - let options = { + const options = { key: fs.readFileSync(common.fixturesDir + '/keys/ec-key.pem'), cert: fs.readFileSync(common.fixturesDir + '/keys/ec-cert.pem') }; - let server = tls.createServer(options, noop).listen(common.PORT, function() { - tls.connect(common.PORT, { rejectUnauthorized: false }, function() { - this.destroy(); - server.close(); + const server = tls.createServer(options, noop) + .listen(common.PORT, function() { + tls.connect(common.PORT, { rejectUnauthorized: false }, function() { + this.destroy(); + server.close(); + }); }); - }); } zlib.createGzip(); diff --git a/test/parallel/test-async-wrap-disabled-propagate-parent.js b/test/parallel/test-async-wrap-disabled-propagate-parent.js index de36071524c4fe..70d82befe72a63 100644 --- a/test/parallel/test-async-wrap-disabled-propagate-parent.js +++ b/test/parallel/test-async-wrap-disabled-propagate-parent.js @@ -10,7 +10,7 @@ let cntr = 0; let server; let client; -function init(type, parent) { +function init(type, id, parent) { if (parent) { cntr++; // Cannot assert in init callback or will abort. diff --git a/test/parallel/test-async-wrap-propagate-parent.js b/test/parallel/test-async-wrap-propagate-parent.js index 8074b0062e0db2..beeb27ba7866a9 100644 --- a/test/parallel/test-async-wrap-propagate-parent.js +++ b/test/parallel/test-async-wrap-propagate-parent.js @@ -9,7 +9,7 @@ let cntr = 0; let server; let client; -function init(type, parent) { +function init(type, id, parent) { if (parent) { cntr++; // Cannot assert in init callback or will abort. diff --git a/test/parallel/test-async-wrap-throw-no-init.js b/test/parallel/test-async-wrap-throw-no-init.js new file mode 100644 index 00000000000000..768e38e8eff389 --- /dev/null +++ b/test/parallel/test-async-wrap-throw-no-init.js @@ -0,0 +1,22 @@ +'use strict'; + +require('../common'); +const assert = require('assert'); +const async_wrap = process.binding('async_wrap'); + + +assert.throws(function() { + async_wrap.setupHooks(null); +}, /init callback must be a function/); + +assert.throws(function() { + async_wrap.enable(); +}, /init callback is not assigned to a function/); + +// Should not throw +async_wrap.setupHooks(() => {}); +async_wrap.enable(); + +assert.throws(function() { + async_wrap.setupHooks(() => {}); +}, /hooks should not be set while also enabled/); diff --git a/test/parallel/test-beforeexit-event.js b/test/parallel/test-beforeexit-event.js index f3bd127b408b08..8e5d66f5f5d7c7 100644 --- a/test/parallel/test-beforeexit-event.js +++ b/test/parallel/test-beforeexit-event.js @@ -1,7 +1,6 @@ 'use strict'; var assert = require('assert'); var net = require('net'); -var util = require('util'); var common = require('../common'); var revivals = 0; var deaths = 0; diff --git a/test/parallel/test-buffer-arraybuffer.js b/test/parallel/test-buffer-arraybuffer.js index c25de262ea9779..522d97ece196c1 100644 --- a/test/parallel/test-buffer-arraybuffer.js +++ b/test/parallel/test-buffer-arraybuffer.js @@ -1,6 +1,6 @@ 'use strict'; -const common = require('../common'); +require('../common'); const assert = require('assert'); const Buffer = require('buffer').Buffer; diff --git a/test/parallel/test-buffer-ascii.js b/test/parallel/test-buffer-ascii.js index efc3a72c662595..94ba85a22761dd 100644 --- a/test/parallel/test-buffer-ascii.js +++ b/test/parallel/test-buffer-ascii.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); // ASCII conversion in node.js simply masks off the high bits, diff --git a/test/parallel/test-buffer-bytelength.js b/test/parallel/test-buffer-bytelength.js index c136c62808e8fc..91f18afcb3f5c3 100644 --- a/test/parallel/test-buffer-bytelength.js +++ b/test/parallel/test-buffer-bytelength.js @@ -1,6 +1,6 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var Buffer = require('buffer').Buffer; diff --git a/test/parallel/test-buffer-concat.js b/test/parallel/test-buffer-concat.js index 8d0c0eebbd14e6..07f763a76dc419 100644 --- a/test/parallel/test-buffer-concat.js +++ b/test/parallel/test-buffer-concat.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var zero = []; diff --git a/test/parallel/test-buffer-fakes.js b/test/parallel/test-buffer-fakes.js index d473d16e92159f..1a1d9c0c494b84 100644 --- a/test/parallel/test-buffer-fakes.js +++ b/test/parallel/test-buffer-fakes.js @@ -1,9 +1,8 @@ 'use strict'; -const common = require('../common'); +require('../common'); const assert = require('assert'); const Buffer = require('buffer').Buffer; -const Bp = Buffer.prototype; function FakeBuffer() { } FakeBuffer.__proto__ = Buffer; diff --git a/test/parallel/test-buffer-indexof.js b/test/parallel/test-buffer-indexof.js index d358749f8efc01..aac5b18f718cb3 100644 --- a/test/parallel/test-buffer-indexof.js +++ b/test/parallel/test-buffer-indexof.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var Buffer = require('buffer').Buffer; diff --git a/test/parallel/test-buffer-inheritance.js b/test/parallel/test-buffer-inheritance.js index eb2f4a531d0b38..ea61e50bf5f04a 100644 --- a/test/parallel/test-buffer-inheritance.js +++ b/test/parallel/test-buffer-inheritance.js @@ -1,6 +1,6 @@ 'use strict'; -const common = require('../common'); +require('../common'); const assert = require('assert'); diff --git a/test/parallel/test-buffer-inspect.js b/test/parallel/test-buffer-inspect.js index 35da378631aee8..6d44389de735a2 100644 --- a/test/parallel/test-buffer-inspect.js +++ b/test/parallel/test-buffer-inspect.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var util = require('util'); diff --git a/test/parallel/test-buffer-iterator.js b/test/parallel/test-buffer-iterator.js index 05371d6d793fed..ad135a9113627d 100644 --- a/test/parallel/test-buffer-iterator.js +++ b/test/parallel/test-buffer-iterator.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var buffer = new Buffer([1, 2, 3, 4, 5]); diff --git a/test/parallel/test-buffer-slow.js b/test/parallel/test-buffer-slow.js index d7b4f486e21422..cf1a3fd8eb200d 100644 --- a/test/parallel/test-buffer-slow.js +++ b/test/parallel/test-buffer-slow.js @@ -1,6 +1,6 @@ 'use strict'; -const common = require('../common'); +require('../common'); const assert = require('assert'); const buffer = require('buffer'); const Buffer = buffer.Buffer; diff --git a/test/parallel/test-buffer-zero-fill-reset.js b/test/parallel/test-buffer-zero-fill-reset.js index 52203a997e89f5..56fb77818a1284 100644 --- a/test/parallel/test-buffer-zero-fill-reset.js +++ b/test/parallel/test-buffer-zero-fill-reset.js @@ -14,6 +14,6 @@ function testUint8Array(ui) { for (let i = 0; i < 100; i++) { new Buffer(0); - let ui = new Uint8Array(65); + const ui = new Uint8Array(65); assert.ok(testUint8Array(ui), 'Uint8Array is not zero-filled'); } diff --git a/test/parallel/test-child-process-buffering.js b/test/parallel/test-child-process-buffering.js index a37e1dbbbd7574..1efa5a65f9cea8 100644 --- a/test/parallel/test-child-process-buffering.js +++ b/test/parallel/test-child-process-buffering.js @@ -2,8 +2,6 @@ var common = require('../common'); var assert = require('assert'); -var spawn = require('child_process').spawn; - var pwd_called = false; var childClosed = false; var childExited = false; diff --git a/test/parallel/test-child-process-constructor.js b/test/parallel/test-child-process-constructor.js index 89db9cf81fddc7..6980810485c964 100644 --- a/test/parallel/test-child-process-constructor.js +++ b/test/parallel/test-child-process-constructor.js @@ -1,7 +1,7 @@ 'use strict'; +require('../common'); var assert = require('assert'); -var common = require('../common'); var child_process = require('child_process'); var ChildProcess = child_process.ChildProcess; assert.equal(typeof ChildProcess, 'function'); diff --git a/test/parallel/test-child-process-cwd.js b/test/parallel/test-child-process-cwd.js index e0e83b6007a815..f13da684fbdfe4 100644 --- a/test/parallel/test-child-process-cwd.js +++ b/test/parallel/test-child-process-cwd.js @@ -1,8 +1,6 @@ 'use strict'; var common = require('../common'); var assert = require('assert'); -var spawn = require('child_process').spawn; -var path = require('path'); var returns = 0; diff --git a/test/parallel/test-child-process-detached.js b/test/parallel/test-child-process-detached.js index 25b811a8caa991..711c5d227d6b07 100644 --- a/test/parallel/test-child-process-detached.js +++ b/test/parallel/test-child-process-detached.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var path = require('path'); diff --git a/test/parallel/test-child-process-exec-buffer.js b/test/parallel/test-child-process-exec-buffer.js index 0ab05080a2cb87..a381af9631e0d8 100644 --- a/test/parallel/test-child-process-exec-buffer.js +++ b/test/parallel/test-child-process-exec-buffer.js @@ -9,7 +9,7 @@ var success_count = 0; var str = 'hello'; // default encoding -var child = exec('echo ' + str, function(err, stdout, stderr) { +exec('echo ' + str, function(err, stdout, stderr) { assert.ok('string', typeof(stdout), 'Expected stdout to be a string'); assert.ok('string', typeof(stderr), 'Expected stderr to be a string'); assert.equal(str + os.EOL, stdout); @@ -18,7 +18,7 @@ var child = exec('echo ' + str, function(err, stdout, stderr) { }); // no encoding (Buffers expected) -var child = exec('echo ' + str, { +exec('echo ' + str, { encoding: null }, function(err, stdout, stderr) { assert.ok(stdout instanceof Buffer, 'Expected stdout to be a Buffer'); diff --git a/test/parallel/test-child-process-exec-cwd.js b/test/parallel/test-child-process-exec-cwd.js index e253399b96ac30..c259ffffda3dee 100644 --- a/test/parallel/test-child-process-exec-cwd.js +++ b/test/parallel/test-child-process-exec-cwd.js @@ -16,7 +16,7 @@ if (common.isWindows) { dir = '/dev'; } -var child = exec(pwdcommand, {cwd: dir}, function(err, stdout, stderr) { +exec(pwdcommand, {cwd: dir}, function(err, stdout, stderr) { if (err) { error_count++; console.log('error!: ' + err.code); diff --git a/test/parallel/test-child-process-flush-stdio.js b/test/parallel/test-child-process-flush-stdio.js new file mode 100644 index 00000000000000..5fd7eb3bc99922 --- /dev/null +++ b/test/parallel/test-child-process-flush-stdio.js @@ -0,0 +1,17 @@ +'use strict'; +const cp = require('child_process'); +const common = require('../common'); +const assert = require('assert'); + +const p = cp.spawn('echo'); + +p.on('close', common.mustCall(function(code, signal) { + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); +})); + +p.stdout.read(); + +setTimeout(function() { + p.kill(); +}, 100); diff --git a/test/parallel/test-child-process-fork-and-spawn.js b/test/parallel/test-child-process-fork-and-spawn.js index d5255bf83ca8e0..5766dc865bc975 100644 --- a/test/parallel/test-child-process-fork-and-spawn.js +++ b/test/parallel/test-child-process-fork-and-spawn.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var spawn = require('child_process').spawn; var fork = require('child_process').fork; diff --git a/test/parallel/test-child-process-fork-dgram.js b/test/parallel/test-child-process-fork-dgram.js index f700960490cbaa..86cd6576c73b98 100644 --- a/test/parallel/test-child-process-fork-dgram.js +++ b/test/parallel/test-child-process-fork-dgram.js @@ -25,7 +25,6 @@ if (common.isWindows) { } if (process.argv[2] === 'child') { - var childCollected = 0; var server; process.on('message', function removeMe(msg, clusterServer) { diff --git a/test/parallel/test-child-process-fork-exec-path.js b/test/parallel/test-child-process-fork-exec-path.js index 6a61bddd8a19a4..35a730b0da6c42 100644 --- a/test/parallel/test-child-process-fork-exec-path.js +++ b/test/parallel/test-child-process-fork-exec-path.js @@ -1,6 +1,5 @@ 'use strict'; var assert = require('assert'); -var cp = require('child_process'); var fs = require('fs'); var path = require('path'); var common = require('../common'); diff --git a/test/parallel/test-child-process-fork-net2.js b/test/parallel/test-child-process-fork-net2.js index 95ec26a88d0de2..dd89557b61121d 100644 --- a/test/parallel/test-child-process-fork-net2.js +++ b/test/parallel/test-child-process-fork-net2.js @@ -117,47 +117,29 @@ if (process.argv[2] === 'child') { }); var closeEmitted = false; - server.on('close', function() { - console.error('[m] server close'); + server.on('close', common.mustCall(function() { closeEmitted = true; - console.error('[m] killing child processes'); child1.kill(); child2.kill(); child3.kill(); - }); + })); server.listen(common.PORT, '127.0.0.1'); - var timeElapsed = 0; var closeServer = function() { - console.error('[m] closeServer'); - var startTime = Date.now(); - server.on('close', function() { - console.error('[m] emit(close)'); - timeElapsed = Date.now() - startTime; - }); - - console.error('[m] calling server.close'); server.close(); setTimeout(function() { assert(!closeEmitted); - console.error('[m] sending close to children'); child1.send('close'); child2.send('close'); child3.disconnect(); }, 200); }; - var min = 190; - var max = common.platformTimeout(2000); process.on('exit', function() { assert.equal(disconnected, count); assert.equal(connected, count); - assert.ok(closeEmitted); - assert.ok(timeElapsed >= min && timeElapsed <= max, - `timeElapsed was not between ${min} and ${max} ms:` + - `${timeElapsed}`); }); } diff --git a/test/parallel/test-child-process-fork-ref.js b/test/parallel/test-child-process-fork-ref.js index b4066641bae970..de34f3eb8ae9c3 100644 --- a/test/parallel/test-child-process-fork-ref.js +++ b/test/parallel/test-child-process-fork-ref.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var fork = require('child_process').fork; diff --git a/test/parallel/test-child-process-fork-ref2.js b/test/parallel/test-child-process-fork-ref2.js index 8bc7e4c35541b2..42c43ed8882b78 100644 --- a/test/parallel/test-child-process-fork-ref2.js +++ b/test/parallel/test-child-process-fork-ref2.js @@ -1,6 +1,5 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); +require('../common'); var fork = require('child_process').fork; if (process.argv[2] === 'child') { diff --git a/test/parallel/test-child-process-fork-regr-gh-2847.js b/test/parallel/test-child-process-fork-regr-gh-2847.js index 27b4d72d2fc612..f035b7fdc89eb8 100644 --- a/test/parallel/test-child-process-fork-regr-gh-2847.js +++ b/test/parallel/test-child-process-fork-regr-gh-2847.js @@ -5,7 +5,6 @@ const assert = require('assert'); const cluster = require('cluster'); const net = require('net'); -const util = require('util'); var connectcount = 0; var sendcount = 0; diff --git a/test/parallel/test-child-process-internal.js b/test/parallel/test-child-process-internal.js index c39dc93293aa8b..03ea340236ad34 100644 --- a/test/parallel/test-child-process-internal.js +++ b/test/parallel/test-child-process-internal.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); //messages diff --git a/test/parallel/test-child-process-set-blocking.js b/test/parallel/test-child-process-set-blocking.js index 3f09388265b89a..6cdfbbc9a24c71 100644 --- a/test/parallel/test-child-process-set-blocking.js +++ b/test/parallel/test-child-process-set-blocking.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var ch = require('child_process'); diff --git a/test/parallel/test-child-process-silent.js b/test/parallel/test-child-process-silent.js index 3714d3758d0f22..c3705ab2a4d7e0 100644 --- a/test/parallel/test-child-process-silent.js +++ b/test/parallel/test-child-process-silent.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var childProcess = require('child_process'); diff --git a/test/parallel/test-child-process-spawn-error.js b/test/parallel/test-child-process-spawn-error.js index 1398dac165319c..4eaa45ee7aefb0 100644 --- a/test/parallel/test-child-process-spawn-error.js +++ b/test/parallel/test-child-process-spawn-error.js @@ -1,6 +1,5 @@ 'use strict'; var common = require('../common'); -var fs = require('fs'); var spawn = require('child_process').spawn; var assert = require('assert'); diff --git a/test/parallel/test-child-process-spawnsync-env.js b/test/parallel/test-child-process-spawnsync-env.js index 646097f9454c5c..4455b867e30108 100644 --- a/test/parallel/test-child-process-spawnsync-env.js +++ b/test/parallel/test-child-process-spawnsync-env.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var cp = require('child_process'); diff --git a/test/parallel/test-child-process-spawnsync-timeout.js b/test/parallel/test-child-process-spawnsync-timeout.js index 34c69a1fc597d2..122a65825949df 100644 --- a/test/parallel/test-child-process-spawnsync-timeout.js +++ b/test/parallel/test-child-process-spawnsync-timeout.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var spawnSync = require('child_process').spawnSync; diff --git a/test/parallel/test-child-process-stdin-ipc.js b/test/parallel/test-child-process-stdin-ipc.js index d2347849dd5b9b..79e60f333b9d6b 100644 --- a/test/parallel/test-child-process-stdin-ipc.js +++ b/test/parallel/test-child-process-stdin-ipc.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var spawn = require('child_process').spawn; diff --git a/test/parallel/test-child-process-stdin.js b/test/parallel/test-child-process-stdin.js index c12b24579375dc..4a371b83fb045b 100644 --- a/test/parallel/test-child-process-stdin.js +++ b/test/parallel/test-child-process-stdin.js @@ -18,30 +18,20 @@ var response = ''; var exitStatus = -1; var closed = false; -var gotStdoutEOF = false; - cat.stdout.setEncoding('utf8'); cat.stdout.on('data', function(chunk) { console.log('stdout: ' + chunk); response += chunk; }); -cat.stdout.on('end', function() { - gotStdoutEOF = true; -}); - - -var gotStderrEOF = false; +cat.stdout.on('end', common.mustCall(function() {})); cat.stderr.on('data', function(chunk) { // shouldn't get any stderr output assert.ok(false); }); -cat.stderr.on('end', function(chunk) { - gotStderrEOF = true; -}); - +cat.stderr.on('end', common.mustCall(function() {})); cat.on('exit', function(status) { console.log('exit event'); diff --git a/test/parallel/test-child-process-stdio-big-write-end.js b/test/parallel/test-child-process-stdio-big-write-end.js index 5ae85acc54d9dd..bc414938b581e3 100644 --- a/test/parallel/test-child-process-stdio-big-write-end.js +++ b/test/parallel/test-child-process-stdio-big-write-end.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var BUFSIZE = 1024; diff --git a/test/parallel/test-child-process-stdio-inherit.js b/test/parallel/test-child-process-stdio-inherit.js index 8cf08a7bd5fa71..409c0af7ca0d31 100644 --- a/test/parallel/test-child-process-stdio-inherit.js +++ b/test/parallel/test-child-process-stdio-inherit.js @@ -31,5 +31,5 @@ function grandparent() { function parent() { // should not immediately exit. - var child = common.spawnCat({ stdio: 'inherit' }); + common.spawnCat({ stdio: 'inherit' }); } diff --git a/test/parallel/test-child-process-stdio.js b/test/parallel/test-child-process-stdio.js index 1ff6e4d914f7ec..d5fe6d43b64d5c 100644 --- a/test/parallel/test-child-process-stdio.js +++ b/test/parallel/test-child-process-stdio.js @@ -1,7 +1,6 @@ 'use strict'; var common = require('../common'); var assert = require('assert'); -var spawn = require('child_process').spawn; var options = {stdio: ['pipe']}; var child = common.spawnPwd(options); diff --git a/test/parallel/test-child-process-stdout-flush-exit.js b/test/parallel/test-child-process-stdout-flush-exit.js index 577a33a05082f2..b76a7cb5e5a8e2 100644 --- a/test/parallel/test-child-process-stdout-flush-exit.js +++ b/test/parallel/test-child-process-stdout-flush-exit.js @@ -1,7 +1,6 @@ 'use strict'; var common = require('../common'); var assert = require('assert'); -var path = require('path'); // if child process output to console and exit if (process.argv[2] === 'child') { diff --git a/test/parallel/test-child-process-validate-stdio.js b/test/parallel/test-child-process-validate-stdio.js index 289323002da4bd..0a12e4f54c5306 100644 --- a/test/parallel/test-child-process-validate-stdio.js +++ b/test/parallel/test-child-process-validate-stdio.js @@ -1,8 +1,8 @@ 'use strict'; // Flags: --expose_internals +require('../common'); var assert = require('assert'); -var common = require('../common'); var _validateStdio = require('internal/child_process')._validateStdio; // should throw if string and not ignore, pipe, or inherit diff --git a/test/parallel/test-cluster-debug-port.js b/test/parallel/test-cluster-debug-port.js index 1a42850e9b2bc1..076a59108b09de 100644 --- a/test/parallel/test-cluster-debug-port.js +++ b/test/parallel/test-cluster-debug-port.js @@ -1,5 +1,5 @@ 'use strict'; -const common = require('../common'); +require('../common'); const assert = require('assert'); const cluster = require('cluster'); diff --git a/test/parallel/test-cluster-dgram-2.js b/test/parallel/test-cluster-dgram-2.js index 0253cafcf49766..6426e1c224beb7 100644 --- a/test/parallel/test-cluster-dgram-2.js +++ b/test/parallel/test-cluster-dgram-2.js @@ -2,7 +2,6 @@ var NUM_WORKERS = 4; var PACKETS_PER_WORKER = 10; -var assert = require('assert'); var cluster = require('cluster'); var common = require('../common'); var dgram = require('dgram'); diff --git a/test/parallel/test-cluster-disconnect-handles.js b/test/parallel/test-cluster-disconnect-handles.js index a6a79ef6a2ae45..f35f101dbd1879 100644 --- a/test/parallel/test-cluster-disconnect-handles.js +++ b/test/parallel/test-cluster-disconnect-handles.js @@ -23,6 +23,7 @@ cluster.schedulingPolicy = cluster.SCHED_RR; // is to make sure the connection is still sitting in the master's // pending handle queue. if (cluster.isMaster) { + let isKilling = false; const handles = require('internal/cluster').handles; // FIXME(bnoordhuis) lib/cluster.js scans the execArgv arguments for // debugger flags and renumbers any port numbers it sees starting @@ -68,11 +69,30 @@ if (cluster.isMaster) { })); })); process.on('exit', () => assert.deepStrictEqual(handles, {})); + process.on('uncaughtException', function(ex) { + // Make sure we clean up so as not to leave a stray worker process running + // if we encounter a connection or other error + if (!worker.isDead()) { + if (!isKilling) { + isKilling = true; + worker.once('exit', function() { + throw ex; + }); + worker.process.kill(); + } + return; + } + throw ex; + }); } else { const server = net.createServer(socket => socket.pipe(socket)); - server.listen(() => { + const cb = () => { process.send(['listening', server.address()]); debugger; - }); + }; + if (common.hasIPv6) + server.listen(cb); + else + server.listen(0, common.localhostIPv4, cb); process.on('disconnect', process.exit); } diff --git a/test/parallel/test-cluster-disconnect-race.js b/test/parallel/test-cluster-disconnect-race.js new file mode 100644 index 00000000000000..97d55a20b1ac51 --- /dev/null +++ b/test/parallel/test-cluster-disconnect-race.js @@ -0,0 +1,39 @@ +'use strict'; + +// This code triggers an AssertionError on Linux in Node.js 5.3.0 and earlier. +// Ref: https://github.com/nodejs/node/issues/4205 + +const common = require('../common'); +const assert = require('assert'); +const net = require('net'); +const cluster = require('cluster'); + +if (common.isWindows) { + console.log('1..0 # Skipped: This test does not apply to Windows.'); + return; +} + +cluster.schedulingPolicy = cluster.SCHED_NONE; + +if (cluster.isMaster) { + var worker1, worker2; + + worker1 = cluster.fork(); + worker1.on('message', common.mustCall(function() { + worker2 = cluster.fork(); + worker1.disconnect(); + worker2.on('online', common.mustCall(worker2.disconnect)); + })); + + cluster.on('exit', common.mustCall(function(worker, code) { + assert.strictEqual(code, 0, 'worker exited with error'); + }, 2)); + + return; +} + +var server = net.createServer(); + +server.listen(common.PORT, function() { + process.send('listening'); +}); diff --git a/test/parallel/test-cluster-eaddrinuse.js b/test/parallel/test-cluster-eaddrinuse.js index 6ff68252d9d867..3821551f00a32c 100644 --- a/test/parallel/test-cluster-eaddrinuse.js +++ b/test/parallel/test-cluster-eaddrinuse.js @@ -5,7 +5,6 @@ var common = require('../common'); var assert = require('assert'); -var cluster = require('cluster'); var fork = require('child_process').fork; var net = require('net'); diff --git a/test/parallel/test-cluster-fork-env.js b/test/parallel/test-cluster-fork-env.js index 7749e42f608c60..fb58daee0cffdb 100644 --- a/test/parallel/test-cluster-fork-env.js +++ b/test/parallel/test-cluster-fork-env.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var cluster = require('cluster'); diff --git a/test/parallel/test-cluster-http-pipe.js b/test/parallel/test-cluster-http-pipe.js index 4c6dee347bb8e9..cb9b090f08e801 100644 --- a/test/parallel/test-cluster-http-pipe.js +++ b/test/parallel/test-cluster-http-pipe.js @@ -34,7 +34,6 @@ http.createServer(function(req, res) { res.writeHead(200); res.end('OK'); }).listen(common.PIPE, function() { - var self = this; http.get({ socketPath: common.PIPE, path: '/' }, function(res) { res.resume(); res.on('end', function(err) { diff --git a/test/parallel/test-cluster-rr-ref.js b/test/parallel/test-cluster-rr-ref.js index 474e4d69f225c6..95d121df875bb8 100644 --- a/test/parallel/test-cluster-rr-ref.js +++ b/test/parallel/test-cluster-rr-ref.js @@ -1,7 +1,6 @@ 'use strict'; const common = require('../common'); -const assert = require('assert'); const cluster = require('cluster'); const net = require('net'); diff --git a/test/parallel/test-cluster-setup-master-cumulative.js b/test/parallel/test-cluster-setup-master-cumulative.js index 0376546d286b51..f0f98fbdbfb3a6 100644 --- a/test/parallel/test-cluster-setup-master-cumulative.js +++ b/test/parallel/test-cluster-setup-master-cumulative.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var cluster = require('cluster'); diff --git a/test/parallel/test-cluster-setup-master-emit.js b/test/parallel/test-cluster-setup-master-emit.js index 8b463ec97bff45..ad15c084c5924d 100644 --- a/test/parallel/test-cluster-setup-master-emit.js +++ b/test/parallel/test-cluster-setup-master-emit.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var cluster = require('cluster'); diff --git a/test/parallel/test-cluster-setup-master-multiple.js b/test/parallel/test-cluster-setup-master-multiple.js index 8ee6d091cd524a..5ceff2bddfaf9d 100644 --- a/test/parallel/test-cluster-setup-master-multiple.js +++ b/test/parallel/test-cluster-setup-master-multiple.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var cluster = require('cluster'); diff --git a/test/parallel/test-cluster-setup-master.js b/test/parallel/test-cluster-setup-master.js index c32b3ea6d3b18b..561371afb027a3 100644 --- a/test/parallel/test-cluster-setup-master.js +++ b/test/parallel/test-cluster-setup-master.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var cluster = require('cluster'); diff --git a/test/parallel/test-cluster-uncaught-exception.js b/test/parallel/test-cluster-uncaught-exception.js index ec42773ef55856..04eac2e8ce63d4 100644 --- a/test/parallel/test-cluster-uncaught-exception.js +++ b/test/parallel/test-cluster-uncaught-exception.js @@ -3,7 +3,7 @@ // one that the cluster module installs. // https://github.com/joyent/node/issues/2556 -var common = require('../common'); +require('../common'); var assert = require('assert'); var cluster = require('cluster'); var fork = require('child_process').fork; diff --git a/test/parallel/test-cluster-worker-constructor.js b/test/parallel/test-cluster-worker-constructor.js index e29dc01561903d..2a96d24a8a3459 100644 --- a/test/parallel/test-cluster-worker-constructor.js +++ b/test/parallel/test-cluster-worker-constructor.js @@ -2,7 +2,7 @@ // test-cluster-worker-constructor.js // validates correct behavior of the cluster.Worker constructor -var common = require('../common'); +require('../common'); var assert = require('assert'); var cluster = require('cluster'); var worker; diff --git a/test/parallel/test-cluster-worker-death.js b/test/parallel/test-cluster-worker-death.js index 88a0f887cc2cab..65da9865b0dd2d 100644 --- a/test/parallel/test-cluster-worker-death.js +++ b/test/parallel/test-cluster-worker-death.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var cluster = require('cluster'); diff --git a/test/parallel/test-cluster-worker-forced-exit.js b/test/parallel/test-cluster-worker-forced-exit.js index 76f5cc69a9f716..ef9f7728bad3a2 100644 --- a/test/parallel/test-cluster-worker-forced-exit.js +++ b/test/parallel/test-cluster-worker-forced-exit.js @@ -2,7 +2,6 @@ require('../common'); var assert = require('assert'); var cluster = require('cluster'); -var net = require('net'); var SENTINEL = 42; diff --git a/test/parallel/test-cluster-worker-init.js b/test/parallel/test-cluster-worker-init.js index 38886af5279a6d..41f73e1255a7c5 100644 --- a/test/parallel/test-cluster-worker-init.js +++ b/test/parallel/test-cluster-worker-init.js @@ -3,7 +3,7 @@ // verifies that, when a child process is forked, the cluster.worker // object can receive messages as expected -var common = require('../common'); +require('../common'); var assert = require('assert'); var cluster = require('cluster'); var msg = 'foo'; diff --git a/test/parallel/test-cluster-worker-isconnected.js b/test/parallel/test-cluster-worker-isconnected.js index eb3c5892bb5e21..985d15ce6475e6 100644 --- a/test/parallel/test-cluster-worker-isconnected.js +++ b/test/parallel/test-cluster-worker-isconnected.js @@ -2,7 +2,6 @@ require('../common'); var cluster = require('cluster'); var assert = require('assert'); -var util = require('util'); if (cluster.isMaster) { var worker = cluster.fork(); diff --git a/test/parallel/test-console-instance.js b/test/parallel/test-console-instance.js index a80c6e57e4b151..1ab038df48e432 100644 --- a/test/parallel/test-console-instance.js +++ b/test/parallel/test-console-instance.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var Stream = require('stream'); var Console = require('console').Console; diff --git a/test/parallel/test-console-not-call-toString.js b/test/parallel/test-console-not-call-toString.js index 7846dbf2778b9c..f152e33e98f087 100644 --- a/test/parallel/test-console-not-call-toString.js +++ b/test/parallel/test-console-not-call-toString.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var func = function() {}; diff --git a/test/parallel/test-console.js b/test/parallel/test-console.js index 982c83851f072a..b906d837562ef9 100644 --- a/test/parallel/test-console.js +++ b/test/parallel/test-console.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); assert.ok(process.stdout.writable); diff --git a/test/parallel/test-crypto-authenticated.js b/test/parallel/test-crypto-authenticated.js index 2cc36278332c9b..fa9a78c26e5b59 100644 --- a/test/parallel/test-crypto-authenticated.js +++ b/test/parallel/test-crypto-authenticated.js @@ -93,32 +93,44 @@ for (var i in TEST_CASES) { (function() { if (!test.password) return; - var encrypt = crypto.createCipher(test.algo, test.password); - if (test.aad) - encrypt.setAAD(new Buffer(test.aad, 'hex')); - var hex = encrypt.update(test.plain, 'ascii', 'hex'); - hex += encrypt.final('hex'); - var auth_tag = encrypt.getAuthTag(); - // only test basic encryption run if output is marked as tampered. - if (!test.tampered) { - assert.equal(hex.toUpperCase(), test.ct); - assert.equal(auth_tag.toString('hex').toUpperCase(), test.tag); + if (common.hasFipsCrypto) { + assert.throws(function() + { crypto.createCipher(test.algo, test.password); }, + /not supported in FIPS mode/); + } else { + var encrypt = crypto.createCipher(test.algo, test.password); + if (test.aad) + encrypt.setAAD(new Buffer(test.aad, 'hex')); + var hex = encrypt.update(test.plain, 'ascii', 'hex'); + hex += encrypt.final('hex'); + var auth_tag = encrypt.getAuthTag(); + // only test basic encryption run if output is marked as tampered. + if (!test.tampered) { + assert.equal(hex.toUpperCase(), test.ct); + assert.equal(auth_tag.toString('hex').toUpperCase(), test.tag); + } } })(); (function() { if (!test.password) return; - var decrypt = crypto.createDecipher(test.algo, test.password); - decrypt.setAuthTag(new Buffer(test.tag, 'hex')); - if (test.aad) - decrypt.setAAD(new Buffer(test.aad, 'hex')); - var msg = decrypt.update(test.ct, 'hex', 'ascii'); - if (!test.tampered) { - msg += decrypt.final('ascii'); - assert.equal(msg, test.plain); + if (common.hasFipsCrypto) { + assert.throws(function() + { crypto.createDecipher(test.algo, test.password); }, + /not supported in FIPS mode/); } else { - // assert that final throws if input data could not be verified! - assert.throws(function() { decrypt.final('ascii'); }, / auth/); + var decrypt = crypto.createDecipher(test.algo, test.password); + decrypt.setAuthTag(new Buffer(test.tag, 'hex')); + if (test.aad) + decrypt.setAAD(new Buffer(test.aad, 'hex')); + var msg = decrypt.update(test.ct, 'hex', 'ascii'); + if (!test.tampered) { + msg += decrypt.final('ascii'); + assert.equal(msg, test.plain); + } else { + // assert that final throws if input data could not be verified! + assert.throws(function() { decrypt.final('ascii'); }, / auth/); + } } })(); diff --git a/test/parallel/test-crypto-binary-default.js b/test/parallel/test-crypto-binary-default.js index 6299c869087a6e..c4b8990beb2ec2 100644 --- a/test/parallel/test-crypto-binary-default.js +++ b/test/parallel/test-crypto-binary-default.js @@ -20,7 +20,6 @@ var fs = require('fs'); var path = require('path'); // Test Certificates -var caPem = fs.readFileSync(common.fixturesDir + '/test_ca.pem', 'ascii'); var certPem = fs.readFileSync(common.fixturesDir + '/test_cert.pem', 'ascii'); var certPfx = fs.readFileSync(common.fixturesDir + '/test_cert.pfx'); var keyPem = fs.readFileSync(common.fixturesDir + '/test_key.pem', 'ascii'); @@ -496,12 +495,13 @@ function testCipher4(key, iv) { assert.equal(txt, plaintext, 'encryption and decryption with key and iv'); } +if (!common.hasFipsCrypto) { + testCipher1('MySecretKey123'); + testCipher1(new Buffer('MySecretKey123')); -testCipher1('MySecretKey123'); -testCipher1(new Buffer('MySecretKey123')); - -testCipher2('0123456789abcdef'); -testCipher2(new Buffer('0123456789abcdef')); + testCipher2('0123456789abcdef'); + testCipher2(new Buffer('0123456789abcdef')); +} testCipher3('0123456789abcd0123456789', '12345678'); testCipher3('0123456789abcd0123456789', new Buffer('12345678')); diff --git a/test/parallel/test-crypto-certificate.js b/test/parallel/test-crypto-certificate.js index 8286d58d1e44ca..9814b395552e9f 100644 --- a/test/parallel/test-crypto-certificate.js +++ b/test/parallel/test-crypto-certificate.js @@ -11,7 +11,6 @@ var crypto = require('crypto'); crypto.DEFAULT_ENCODING = 'buffer'; var fs = require('fs'); -var path = require('path'); // Test Certificates var spkacValid = fs.readFileSync(common.fixturesDir + '/spkac.valid'); diff --git a/test/parallel/test-crypto-cipher-decipher.js b/test/parallel/test-crypto-cipher-decipher.js index f33ea5482c8c3a..5f867739abe7ed 100644 --- a/test/parallel/test-crypto-cipher-decipher.js +++ b/test/parallel/test-crypto-cipher-decipher.js @@ -6,6 +6,10 @@ if (!common.hasCrypto) { console.log('1..0 # Skipped: missing crypto'); return; } +if (common.hasFipsCrypto) { + console.log('1..0 # Skipped: not supported in FIPS mode'); + return; +} var crypto = require('crypto'); function testCipher1(key) { @@ -62,71 +66,12 @@ function testCipher2(key) { assert.equal(txt, plaintext, 'encryption and decryption with Base64'); } - -function testCipher3(key, iv) { - // Test encyrption and decryption with explicit key and iv - var plaintext = - '32|RmVZZkFUVmpRRkp0TmJaUm56ZU9qcnJkaXNNWVNpTTU*|iXmckfRWZBGWWELw' + - 'eCBsThSsfUHLeRe0KCsK8ooHgxie0zOINpXxfZi/oNG7uq9JWFVCk70gfzQH8ZUJ' + - 'jAfaFg**'; - var cipher = crypto.createCipheriv('des-ede3-cbc', key, iv); - var ciph = cipher.update(plaintext, 'utf8', 'hex'); - ciph += cipher.final('hex'); - - var decipher = crypto.createDecipheriv('des-ede3-cbc', key, iv); - var txt = decipher.update(ciph, 'hex', 'utf8'); - txt += decipher.final('utf8'); - - assert.equal(txt, plaintext, 'encryption and decryption with key and iv'); - - // streaming cipher interface - // NB: In real life, it's not guaranteed that you can get all of it - // in a single read() like this. But in this case, we know it's - // quite small, so there's no harm. - var cStream = crypto.createCipheriv('des-ede3-cbc', key, iv); - cStream.end(plaintext); - ciph = cStream.read(); - - var dStream = crypto.createDecipheriv('des-ede3-cbc', key, iv); - dStream.end(ciph); - txt = dStream.read().toString('utf8'); - - assert.equal(txt, plaintext, 'streaming cipher iv'); -} - - -function testCipher4(key, iv) { - // Test encyrption and decryption with explicit key and iv - var plaintext = - '32|RmVZZkFUVmpRRkp0TmJaUm56ZU9qcnJkaXNNWVNpTTU*|iXmckfRWZBGWWELw' + - 'eCBsThSsfUHLeRe0KCsK8ooHgxie0zOINpXxfZi/oNG7uq9JWFVCk70gfzQH8ZUJ' + - 'jAfaFg**'; - var cipher = crypto.createCipheriv('des-ede3-cbc', key, iv); - var ciph = cipher.update(plaintext, 'utf8', 'buffer'); - ciph = Buffer.concat([ciph, cipher.final('buffer')]); - - var decipher = crypto.createDecipheriv('des-ede3-cbc', key, iv); - var txt = decipher.update(ciph, 'buffer', 'utf8'); - txt += decipher.final('utf8'); - - assert.equal(txt, plaintext, 'encryption and decryption with key and iv'); -} - - testCipher1('MySecretKey123'); testCipher1(new Buffer('MySecretKey123')); testCipher2('0123456789abcdef'); testCipher2(new Buffer('0123456789abcdef')); -testCipher3('0123456789abcd0123456789', '12345678'); -testCipher3('0123456789abcd0123456789', new Buffer('12345678')); -testCipher3(new Buffer('0123456789abcd0123456789'), '12345678'); -testCipher3(new Buffer('0123456789abcd0123456789'), new Buffer('12345678')); - -testCipher4(new Buffer('0123456789abcd0123456789'), new Buffer('12345678')); - - // Base64 padding regression test, see #4837. (function() { var c = crypto.createCipher('aes-256-cbc', 'secret'); diff --git a/test/parallel/test-crypto-cipheriv-decipheriv.js b/test/parallel/test-crypto-cipheriv-decipheriv.js new file mode 100644 index 00000000000000..d325c0facf7e54 --- /dev/null +++ b/test/parallel/test-crypto-cipheriv-decipheriv.js @@ -0,0 +1,65 @@ +'use strict'; +var common = require('../common'); +var assert = require('assert'); + +if (!common.hasCrypto) { + console.log('1..0 # Skipped: missing crypto'); + return; +} +var crypto = require('crypto'); + +function testCipher1(key, iv) { + // Test encyrption and decryption with explicit key and iv + var plaintext = + '32|RmVZZkFUVmpRRkp0TmJaUm56ZU9qcnJkaXNNWVNpTTU*|iXmckfRWZBGWWELw' + + 'eCBsThSsfUHLeRe0KCsK8ooHgxie0zOINpXxfZi/oNG7uq9JWFVCk70gfzQH8ZUJ' + + 'jAfaFg**'; + var cipher = crypto.createCipheriv('des-ede3-cbc', key, iv); + var ciph = cipher.update(plaintext, 'utf8', 'hex'); + ciph += cipher.final('hex'); + + var decipher = crypto.createDecipheriv('des-ede3-cbc', key, iv); + var txt = decipher.update(ciph, 'hex', 'utf8'); + txt += decipher.final('utf8'); + + assert.equal(txt, plaintext, 'encryption and decryption with key and iv'); + + // streaming cipher interface + // NB: In real life, it's not guaranteed that you can get all of it + // in a single read() like this. But in this case, we know it's + // quite small, so there's no harm. + var cStream = crypto.createCipheriv('des-ede3-cbc', key, iv); + cStream.end(plaintext); + ciph = cStream.read(); + + var dStream = crypto.createDecipheriv('des-ede3-cbc', key, iv); + dStream.end(ciph); + txt = dStream.read().toString('utf8'); + + assert.equal(txt, plaintext, 'streaming cipher iv'); +} + + +function testCipher2(key, iv) { + // Test encyrption and decryption with explicit key and iv + var plaintext = + '32|RmVZZkFUVmpRRkp0TmJaUm56ZU9qcnJkaXNNWVNpTTU*|iXmckfRWZBGWWELw' + + 'eCBsThSsfUHLeRe0KCsK8ooHgxie0zOINpXxfZi/oNG7uq9JWFVCk70gfzQH8ZUJ' + + 'jAfaFg**'; + var cipher = crypto.createCipheriv('des-ede3-cbc', key, iv); + var ciph = cipher.update(plaintext, 'utf8', 'buffer'); + ciph = Buffer.concat([ciph, cipher.final('buffer')]); + + var decipher = crypto.createDecipheriv('des-ede3-cbc', key, iv); + var txt = decipher.update(ciph, 'buffer', 'utf8'); + txt += decipher.final('utf8'); + + assert.equal(txt, plaintext, 'encryption and decryption with key and iv'); +} + +testCipher1('0123456789abcd0123456789', '12345678'); +testCipher1('0123456789abcd0123456789', new Buffer('12345678')); +testCipher1(new Buffer('0123456789abcd0123456789'), '12345678'); +testCipher1(new Buffer('0123456789abcd0123456789'), new Buffer('12345678')); + +testCipher2(new Buffer('0123456789abcd0123456789'), new Buffer('12345678')); diff --git a/test/parallel/test-crypto-dh.js b/test/parallel/test-crypto-dh.js index 322b5d1c70a073..93224416ed9754 100644 --- a/test/parallel/test-crypto-dh.js +++ b/test/parallel/test-crypto-dh.js @@ -58,7 +58,7 @@ assert.equal(secret1, secret3); // Run this one twice to make sure that the dh3 clears its error properly (function() { - var c = crypto.createDecipher('aes-128-ecb', ''); + var c = crypto.createDecipheriv('aes-128-ecb', crypto.randomBytes(16), ''); assert.throws(function() { c.final('utf8'); }, /wrong final block length/); })(); @@ -67,7 +67,7 @@ assert.throws(function() { }, /key is too small/i); (function() { - var c = crypto.createDecipher('aes-128-ecb', ''); + var c = crypto.createDecipheriv('aes-128-ecb', crypto.randomBytes(16), ''); assert.throws(function() { c.final('utf8'); }, /wrong final block length/); })(); @@ -171,7 +171,7 @@ var ecdh3 = crypto.createECDH('secp256k1'); var key3 = ecdh3.generateKeys(); assert.throws(function() { - var secret3 = ecdh2.computeSecret(key3, 'binary', 'buffer'); + ecdh2.computeSecret(key3, 'binary', 'buffer'); }); // ECDH should allow .setPrivateKey()/.setPublicKey() diff --git a/test/parallel/test-crypto-verify-failure.js b/test/parallel/test-crypto-verify-failure.js index f315aed1a9f139..2bc4ce5433739d 100644 --- a/test/parallel/test-crypto-verify-failure.js +++ b/test/parallel/test-crypto-verify-failure.js @@ -1,6 +1,5 @@ 'use strict'; var common = require('../common'); -var assert = require('assert'); if (!common.hasCrypto) { console.log('1..0 # Skipped: missing crypto'); @@ -20,8 +19,6 @@ var options = { cert: fs.readFileSync(common.fixturesDir + '/keys/agent1-cert.pem') }; -var canSend = true; - var server = tls.Server(options, function(socket) { setImmediate(function() { console.log('sending'); @@ -32,17 +29,15 @@ var server = tls.Server(options, function(socket) { }); }); -var client; - function verify() { console.log('verify'); - var verified = crypto.createVerify('RSA-SHA1') - .update('Test') - .verify(certPem, 'asdfasdfas', 'base64'); + crypto.createVerify('RSA-SHA1') + .update('Test') + .verify(certPem, 'asdfasdfas', 'base64'); } server.listen(common.PORT, function() { - client = tls.connect({ + tls.connect({ port: common.PORT, rejectUnauthorized: false }, function() { diff --git a/test/parallel/test-crypto.js b/test/parallel/test-crypto.js index e5fe8db58c132e..df59fd9bded726 100644 --- a/test/parallel/test-crypto.js +++ b/test/parallel/test-crypto.js @@ -93,11 +93,11 @@ assertSorted(crypto.getCurves()); // throw, not assert in C++ land. assert.throws(function() { crypto.createCipher('aes192', 'test').update('0', 'hex'); -}, /Bad input string/); +}, common.hasFipsCrypto ? /not supported in FIPS mode/ : /Bad input string/); assert.throws(function() { crypto.createDecipher('aes192', 'test').update('0', 'hex'); -}, /Bad input string/); +}, common.hasFipsCrypto ? /not supported in FIPS mode/ : /Bad input string/); assert.throws(function() { crypto.createHash('sha1').update('0', 'hex'); diff --git a/test/parallel/test-debug-port-cluster.js b/test/parallel/test-debug-port-cluster.js index 5bec9dc720599e..912f06d6dc6dd5 100644 --- a/test/parallel/test-debug-port-cluster.js +++ b/test/parallel/test-debug-port-cluster.js @@ -3,47 +3,25 @@ var common = require('../common'); var assert = require('assert'); var spawn = require('child_process').spawn; -var port = common.PORT + 1337; +const PORT_MIN = common.PORT + 1337; +const PORT_MAX = PORT_MIN + 2; var args = [ - '--debug=' + port, + '--debug=' + PORT_MIN, common.fixturesDir + '/clustered-server/app.js' ]; -var child = spawn(process.execPath, args); -var outputLines = []; +const child = spawn(process.execPath, args); +child.stderr.setEncoding('utf8'); -child.stderr.on('data', function(data) { - var lines = data.toString().replace(/\r/g, '').trim().split('\n'); - var line = lines[0]; - - lines.forEach(function(ln) { console.log('> ' + ln); } ); - - if (line === 'all workers are running') { - assertOutputLines(); - process.exit(); - } else { - outputLines = outputLines.concat(lines); - } -}); - -process.on('exit', function onExit() { - child.kill(); +let stderr = ''; +child.stderr.on('data', data => { + stderr += data; + if (child.killed !== true && stderr.includes('all workers are running')) + child.kill(); }); -var assertOutputLines = common.mustCall(function() { - var expectedLines = [ - 'Debugger listening on port ' + port, - 'Debugger listening on port ' + (port + 1), - 'Debugger listening on port ' + (port + 2), - ]; - - // Do not assume any particular order of output messages, - // since workers can take different amout of time to - // start up - outputLines.sort(); - - assert.equal(outputLines.length, expectedLines.length); - for (var i = 0; i < expectedLines.length; i++) - assert.equal(outputLines[i], expectedLines[i]); +process.on('exit', () => { + for (let port = PORT_MIN; port <= PORT_MAX; port += 1) + assert(stderr.includes(`Debugger listening on port ${port}`)); }); diff --git a/test/parallel/test-debug-signal-cluster.js b/test/parallel/test-debug-signal-cluster.js index 6572ef50afe845..7a950458b87271 100644 --- a/test/parallel/test-debug-signal-cluster.js +++ b/test/parallel/test-debug-signal-cluster.js @@ -10,7 +10,6 @@ var options = { stdio: ['inherit', 'inherit', 'pipe', 'ipc'] }; var child = spawn(process.execPath, args, options); var outputLines = []; -var outputTimerId; var waitingForDebuggers = false; var pids = null; diff --git a/test/parallel/test-delayed-require.js b/test/parallel/test-delayed-require.js index 5fa82f236c1dd9..7376e70ba780e2 100644 --- a/test/parallel/test-delayed-require.js +++ b/test/parallel/test-delayed-require.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var a; diff --git a/test/parallel/test-dgram-bind.js b/test/parallel/test-dgram-bind.js index 6d35534cb5eb56..0bca97fb294f79 100644 --- a/test/parallel/test-dgram-bind.js +++ b/test/parallel/test-dgram-bind.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var dgram = require('dgram'); diff --git a/test/parallel/test-dgram-bytes-length.js b/test/parallel/test-dgram-bytes-length.js index 9f8c39eb04daaf..c68b2fab70aff5 100644 --- a/test/parallel/test-dgram-bytes-length.js +++ b/test/parallel/test-dgram-bytes-length.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var dgram = require('dgram'); diff --git a/test/parallel/test-dgram-empty-packet.js b/test/parallel/test-dgram-empty-packet.js index ba6faa62d86cec..66cdbb92ac8f1b 100644 --- a/test/parallel/test-dgram-empty-packet.js +++ b/test/parallel/test-dgram-empty-packet.js @@ -1,8 +1,6 @@ 'use strict'; var common = require('../common'); -var assert = require('assert'); -var fs = require('fs'); var dgram = require('dgram'); var callbacks = 0; var client; diff --git a/test/parallel/test-dgram-error-message-address.js b/test/parallel/test-dgram-error-message-address.js index e307a23e2451db..005695654f9542 100644 --- a/test/parallel/test-dgram-error-message-address.js +++ b/test/parallel/test-dgram-error-message-address.js @@ -20,7 +20,6 @@ socket_ipv4.bind(common.PORT, '1.1.1.1'); // IPv6 Test var socket_ipv6 = dgram.createSocket('udp6'); -var family_ipv6 = 'IPv6'; socket_ipv6.on('listening', common.fail); diff --git a/test/parallel/test-dgram-listen-after-bind.js b/test/parallel/test-dgram-listen-after-bind.js index 2aac7ae9cf7588..498a17a0e5b053 100644 --- a/test/parallel/test-dgram-listen-after-bind.js +++ b/test/parallel/test-dgram-listen-after-bind.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var dgram = require('dgram'); diff --git a/test/parallel/test-dgram-pingpong.js b/test/parallel/test-dgram-pingpong.js index 29ab92757bd817..883085a9cdaab2 100644 --- a/test/parallel/test-dgram-pingpong.js +++ b/test/parallel/test-dgram-pingpong.js @@ -11,7 +11,6 @@ function pingPongTest(port, host) { var callbacks = 0; var N = 500; var count = 0; - var sent_final_ping = false; var server = dgram.createSocket('udp4', function(msg, rinfo) { if (debug) console.log('server got: ' + msg + @@ -48,7 +47,6 @@ function pingPongTest(port, host) { if (count < N) { client.send(buf, 0, buf.length, port, 'localhost'); } else { - sent_final_ping = true; client.send(buf, 0, buf.length, port, 'localhost', function() { client.close(); }); diff --git a/test/parallel/test-dgram-ref.js b/test/parallel/test-dgram-ref.js index d689a45e36dfa2..6505ce9b1ec886 100644 --- a/test/parallel/test-dgram-ref.js +++ b/test/parallel/test-dgram-ref.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var dgram = require('dgram'); // should not hang, see #1282 diff --git a/test/parallel/test-dgram-regress-4496.js b/test/parallel/test-dgram-regress-4496.js index fcb8d026bc547e..4bdd0d6520d7dc 100644 --- a/test/parallel/test-dgram-regress-4496.js +++ b/test/parallel/test-dgram-regress-4496.js @@ -1,7 +1,7 @@ 'use strict'; // Remove this test once we support sending strings. -var common = require('../common'); +require('../common'); var assert = require('assert'); var dgram = require('dgram'); diff --git a/test/parallel/test-dgram-send-bad-arguments.js b/test/parallel/test-dgram-send-bad-arguments.js index ccd10e00555384..ddaa162c8bff10 100644 --- a/test/parallel/test-dgram-send-bad-arguments.js +++ b/test/parallel/test-dgram-send-bad-arguments.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var dgram = require('dgram'); diff --git a/test/parallel/test-dgram-send-callback-buffer-length.js b/test/parallel/test-dgram-send-callback-buffer-length.js index a34c5e2eb6b8db..80c2d23e42ef55 100644 --- a/test/parallel/test-dgram-send-callback-buffer-length.js +++ b/test/parallel/test-dgram-send-callback-buffer-length.js @@ -2,9 +2,7 @@ var common = require('../common'); var assert = require('assert'); -var fs = require('fs'); var dgram = require('dgram'); -var callbacks = 0; var client, timer, buf, len, offset; diff --git a/test/parallel/test-dgram-send-empty-buffer.js b/test/parallel/test-dgram-send-empty-buffer.js index 11f3d38d2ed046..a8ab4339d8a398 100644 --- a/test/parallel/test-dgram-send-empty-buffer.js +++ b/test/parallel/test-dgram-send-empty-buffer.js @@ -1,10 +1,7 @@ 'use strict'; var common = require('../common'); -var assert = require('assert'); -var fs = require('fs'); var dgram = require('dgram'); -var callbacks = 0; var client, timer, buf; if (process.platform === 'darwin') { diff --git a/test/parallel/test-dgram-udp4.js b/test/parallel/test-dgram-udp4.js index f81dec398f72d1..58c8b69839ffe6 100644 --- a/test/parallel/test-dgram-udp4.js +++ b/test/parallel/test-dgram-udp4.js @@ -2,8 +2,7 @@ var common = require('../common'); var assert = require('assert'); -var fs = require('fs'), - dgram = require('dgram'), server, client, +var dgram = require('dgram'), server, client, server_port = common.PORT, message_to_send = 'A message to send', timer; @@ -52,4 +51,4 @@ server.bind(server_port); timer = setTimeout(function() { throw new Error('Timeout'); -}, 200); +}, common.platformTimeout(200)); diff --git a/test/parallel/test-dgram-unref.js b/test/parallel/test-dgram-unref.js index 2add3d28c49760..083dab6d29589c 100644 --- a/test/parallel/test-dgram-unref.js +++ b/test/parallel/test-dgram-unref.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var dgram = require('dgram'); diff --git a/test/parallel/test-dh-padding.js b/test/parallel/test-dh-padding.js index cdb1fc75f94215..7d482b78f63a7c 100644 --- a/test/parallel/test-dh-padding.js +++ b/test/parallel/test-dh-padding.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); try { diff --git a/test/parallel/test-dns-cares-domains.js b/test/parallel/test-dns-cares-domains.js index cb651c5f5afb86..a1aa18a10f88ec 100644 --- a/test/parallel/test-dns-cares-domains.js +++ b/test/parallel/test-dns-cares-domains.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var dns = require('dns'); var domain = require('domain'); diff --git a/test/parallel/test-dns-lookup-cb-error.js b/test/parallel/test-dns-lookup-cb-error.js index 330dfb5d57092a..4a3dd2694121f8 100644 --- a/test/parallel/test-dns-lookup-cb-error.js +++ b/test/parallel/test-dns-lookup-cb-error.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var cares = process.binding('cares_wrap'); diff --git a/test/parallel/test-dns-regress-7070.js b/test/parallel/test-dns-regress-7070.js index 1fbd7f07a9d520..e696327d4d5f66 100644 --- a/test/parallel/test-dns-regress-7070.js +++ b/test/parallel/test-dns-regress-7070.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var dns = require('dns'); diff --git a/test/parallel/test-dns.js b/test/parallel/test-dns.js index abc7edbf598097..3362e8c534eaab 100644 --- a/test/parallel/test-dns.js +++ b/test/parallel/test-dns.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var dns = require('dns'); diff --git a/test/parallel/test-domain-exit-dispose-again.js b/test/parallel/test-domain-exit-dispose-again.js index 6fe9f25fb0d887..e5b1affc0afb55 100644 --- a/test/parallel/test-domain-exit-dispose-again.js +++ b/test/parallel/test-domain-exit-dispose-again.js @@ -1,39 +1,76 @@ 'use strict'; -const common = require('../common'); -const assert = require('assert'); -const domain = require('domain'); -// Use the same timeout value so that both timers' callbacks are called during -// the same invocation of the underlying native timer's callback (listOnTimeout -// in lib/timers.js). -setTimeout(err, 50); -setTimeout(common.mustCall(secondTimer), 50); +// This test makes sure that when a domain is disposed, timers that are +// attached to that domain are not fired, but timers that are _not_ attached +// to that domain, including those whose callbacks are called from within +// the same invocation of listOnTimeout, _are_ called. -function err() { +require('../common'); +var assert = require('assert'); +var domain = require('domain'); +var disposalFailed = false; + +// Repeatedly schedule a timer with a delay different than the timers attached +// to a domain that will eventually be disposed to make sure that they are +// called, regardless of what happens with those timers attached to domains +// that will eventually be disposed. +var a = 0; +log(); +function log() { + console.log(a++, process.domain); + if (a < 10) setTimeout(log, 20); +} + +var secondTimerRan = false; + +// Use the same timeout duration for both "firstTimer" and "secondTimer" +// callbacks so that they are called during the same invocation of the +// underlying native timer's callback (listOnTimeout in lib/timers.js). +const TIMEOUT_DURATION = 50; + +setTimeout(function firstTimer() { const d = domain.create(); - d.on('error', handleDomainError); - d.run(err2); - function err2() { - // this function doesn't exist, and throws an error as a result. + d.on('error', function handleError(err) { + // Dispose the domain on purpose, so that we can test that nestedTimer + // is not called since it's associated to this domain and a timer whose + // domain is diposed should not run. + d.dispose(); + console.error(err); + console.error('in domain error handler', + process.domain, process.domain === d); + }); + + d.run(function() { + // Create another nested timer that is by definition associated to the + // domain "d". Because an error is thrown before the timer's callback + // is called, and because the domain's error handler disposes the domain, + // this timer's callback should never run. + setTimeout(function nestedTimer() { + console.error('Nested timer should not run, because it is attached to ' + + 'a domain that should be disposed.'); + disposalFailed = true; + process.exit(1); + }); + + // Make V8 throw an unreferenced error. As a result, the domain's error + // handler is called, which disposes the domain "d" and should prevent the + // nested timer that is attached to it from running. err3(); - } + }); +}, TIMEOUT_DURATION); - function handleDomainError(e) { - // In the domain's error handler, the current active domain should be the - // domain within which the error was thrown. - assert.equal(process.domain, d); - } -} +// This timer expires in the same invocation of listOnTimeout than firstTimer, +// but because it's not attached to any domain, it must run regardless of +// domain "d" being disposed. +setTimeout(function secondTimer() { + console.log('In second timer'); + secondTimerRan = true; +}, TIMEOUT_DURATION); -function secondTimer() { - // secondTimer was scheduled before any domain had been created, so its - // callback should not have any active domain set when it runs. - // 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. - if (process.domain !== null) { - console.log('process.domain should be null, but instead is:', - process.domain); - process.exit(1); - } -} +process.on('exit', function() { + assert.equal(a, 10); + assert.equal(disposalFailed, false); + assert(secondTimerRan); + console.log('ok'); +}); diff --git a/test/parallel/test-domain-exit-dispose.js b/test/parallel/test-domain-exit-dispose.js index 90e7210ce21aea..2bddb01cbd8ca5 100644 --- a/test/parallel/test-domain-exit-dispose.js +++ b/test/parallel/test-domain-exit-dispose.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var domain = require('domain'); var disposalFailed = false; diff --git a/test/parallel/test-domain-from-timer.js b/test/parallel/test-domain-from-timer.js index 93661b419b0bbf..f0115018ec1879 100644 --- a/test/parallel/test-domain-from-timer.js +++ b/test/parallel/test-domain-from-timer.js @@ -1,7 +1,7 @@ 'use strict'; // Simple tests of most basic domain functionality. -var common = require('../common'); +require('../common'); var assert = require('assert'); // timeouts call the callback directly from cc, so need to make sure the diff --git a/test/parallel/test-domain-http-server.js b/test/parallel/test-domain-http-server.js index 99dbf413e3a4f8..37dbc30f4234d7 100644 --- a/test/parallel/test-domain-http-server.js +++ b/test/parallel/test-domain-http-server.js @@ -9,7 +9,6 @@ objects.baz.asdf = objects; var serverCaught = 0; var clientCaught = 0; -var disposeEmit = 0; var server = http.createServer(function(req, res) { var dom = domain.create(); diff --git a/test/parallel/test-domain-implicit-fs.js b/test/parallel/test-domain-implicit-fs.js index fd21dcafe0858f..d0a468419b923e 100644 --- a/test/parallel/test-domain-implicit-fs.js +++ b/test/parallel/test-domain-implicit-fs.js @@ -1,15 +1,13 @@ 'use strict'; // Simple tests of most basic domain functionality. -var common = require('../common'); +require('../common'); var assert = require('assert'); var domain = require('domain'); -var events = require('events'); var caught = 0; var expectCaught = 1; var d = new domain.Domain(); -var e = new events.EventEmitter(); d.on('error', function(er) { console.error('caught', er); diff --git a/test/parallel/test-domain-multi.js b/test/parallel/test-domain-multi.js index e5f9f6748b178e..ac01d66deee544 100644 --- a/test/parallel/test-domain-multi.js +++ b/test/parallel/test-domain-multi.js @@ -4,7 +4,6 @@ var common = require('../common'); var assert = require('assert'); var domain = require('domain'); -var events = require('events'); var caughtA = false; var caughtB = false; diff --git a/test/parallel/test-domain-nested-throw.js b/test/parallel/test-domain-nested-throw.js index 0fba3001b543fb..69a80b7ab104d0 100644 --- a/test/parallel/test-domain-nested-throw.js +++ b/test/parallel/test-domain-nested-throw.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var domain = require('domain'); diff --git a/test/parallel/test-domain-stack.js b/test/parallel/test-domain-stack.js index f9b5648a6619a7..e30d3b21f3af57 100644 --- a/test/parallel/test-domain-stack.js +++ b/test/parallel/test-domain-stack.js @@ -1,10 +1,8 @@ 'use strict'; // Make sure that the domain stack doesn't get out of hand. -var common = require('../common'); -var assert = require('assert'); +require('../common'); var domain = require('domain'); -var events = require('events'); var a = domain.create(); a.name = 'a'; diff --git a/test/parallel/test-domain-timers.js b/test/parallel/test-domain-timers.js index 7530c9edba40b1..a97b300da02d31 100644 --- a/test/parallel/test-domain-timers.js +++ b/test/parallel/test-domain-timers.js @@ -1,7 +1,7 @@ 'use strict'; +require('../common'); var domain = require('domain'); var assert = require('assert'); -var common = require('../common'); var timeout_err, timeout, immediate_err; diff --git a/test/parallel/test-domain-top-level-error-handler-throw.js b/test/parallel/test-domain-top-level-error-handler-throw.js index 2b9e704e43c32b..4bde30d17cb8c8 100644 --- a/test/parallel/test-domain-top-level-error-handler-throw.js +++ b/test/parallel/test-domain-top-level-error-handler-throw.js @@ -7,7 +7,7 @@ * top-level error handler, not the one from the previous error. */ -const common = require('../common'); +require('../common'); const domainErrHandlerExMessage = 'exception from domain error handler'; const internalExMessage = 'You should NOT see me'; @@ -36,10 +36,12 @@ if (process.argv[2] === 'child') { stderrOutput += data.toString(); }); - child.on('exit', function onChildExited(exitCode, signal) { + child.on('close', function onChildClosed() { assert(stderrOutput.indexOf(domainErrHandlerExMessage) !== -1); assert(stderrOutput.indexOf(internalExMessage) === -1); + }); + child.on('exit', function onChildExited(exitCode, signal) { var expectedExitCode = 7; var expectedSignal = null; diff --git a/test/parallel/test-domain-uncaught-exception.js b/test/parallel/test-domain-uncaught-exception.js index 8792eb1ce5459f..35632dbf537202 100644 --- a/test/parallel/test-domain-uncaught-exception.js +++ b/test/parallel/test-domain-uncaught-exception.js @@ -13,8 +13,6 @@ const assert = require('assert'); const domain = require('domain'); const child_process = require('child_process'); -const uncaughtExceptions = {}; - const tests = []; function test1() { diff --git a/test/parallel/test-domain-with-abort-on-uncaught-exception.js b/test/parallel/test-domain-with-abort-on-uncaught-exception.js index 130778038bf072..3158274ea181a9 100644 --- a/test/parallel/test-domain-with-abort-on-uncaught-exception.js +++ b/test/parallel/test-domain-with-abort-on-uncaught-exception.js @@ -31,7 +31,6 @@ const domainErrHandlerExMessage = 'exception from domain error handler'; if (process.argv[2] === 'child') { var domain = require('domain'); var d = domain.create(); - var triggeredProcessUncaughtException = false; process.on('uncaughtException', function onUncaughtException() { // The process' uncaughtException event must not be emitted when @@ -116,13 +115,6 @@ if (process.argv[2] === 'child') { var child = exec(cmdToExec); if (child) { - var childTriggeredOnUncaughtExceptionHandler = false; - child.on('message', function onChildMsg(msg) { - if (msg === 'triggeredProcessUncaughtEx') { - childTriggeredOnUncaughtExceptionHandler = true; - } - }); - child.on('exit', function onChildExited(exitCode, signal) { // When throwing errors from the top-level domain error handler // outside of a try/catch block, the process should not exit gracefully diff --git a/test/parallel/test-domain.js b/test/parallel/test-domain.js index 918e3288e8dc91..bef5e942e057a1 100644 --- a/test/parallel/test-domain.js +++ b/test/parallel/test-domain.js @@ -1,7 +1,7 @@ 'use strict'; // Simple tests of most basic domain functionality. -var common = require('../common'); +require('../common'); var assert = require('assert'); var domain = require('domain'); var events = require('events'); diff --git a/test/parallel/test-dsa-fips-invalid-key.js b/test/parallel/test-dsa-fips-invalid-key.js index 0b5773411ee592..2d30ef6891008a 100644 --- a/test/parallel/test-dsa-fips-invalid-key.js +++ b/test/parallel/test-dsa-fips-invalid-key.js @@ -12,8 +12,6 @@ var fs = require('fs'); var input = 'hello'; -var dsapub = fs.readFileSync(common.fixturesDir + - '/keys/dsa_public_1025.pem'); var dsapri = fs.readFileSync(common.fixturesDir + '/keys/dsa_private_1025.pem'); var sign = crypto.createSign('DSS1'); diff --git a/test/parallel/test-error-reporting.js b/test/parallel/test-error-reporting.js index 88ef5d306e3e37..b5b70eeb3b2add 100644 --- a/test/parallel/test-error-reporting.js +++ b/test/parallel/test-error-reporting.js @@ -24,8 +24,6 @@ function errExec(script, callback) { // Count the tests exits++; - - console.log('.'); }); } @@ -64,6 +62,11 @@ errExec('throws_error6.js', function(err, stdout, stderr) { assert.ok(/SyntaxError/.test(stderr)); }); +// Object that throws in toString() doesn't print garbage +errExec('throws_error7.js', function(err, stdout, stderr) { + assert.ok(/ ../tmp/node-test-realpath-d1/foo - /tmp/node-test-realpath-d1 -> ../node-test-realpath-d2 - /tmp/node-test-realpath-d2/foo -> ../node-test-realpath-f2 + /tmp/node-test-realpath-f1 -> $tmpDir/node-test-realpath-d1/foo + /tmp/node-test-realpath-d1 -> $tmpDir/node-test-realpath-d2 + /tmp/node-test-realpath-d2/foo -> $tmpDir/node-test-realpath-f2 /tmp/node-test-realpath-f2 - -> /node/test/fixtures/nested-index/one/realpath-c - /node/test/fixtures/nested-index/one/realpath-c - -> /node/test/fixtures/nested-index/two/realpath-c - /node/test/fixtures/nested-index/two/realpath-c -> ../../cycles/root.js - /node/test/fixtures/cycles/root.js (hard) + -> $tmpDir/targets/nested-index/one/realpath-c + $tmpDir/targets/nested-index/one/realpath-c + -> $tmpDir/targets/nested-index/two/realpath-c + $tmpDir/targets/nested-index/two/realpath-c -> $tmpDir/cycles/root.js + $tmpDir/targets/cycles/root.js (hard) */ var entry = tmp('node-test-realpath-f1'); try { fs.unlinkSync(tmp('node-test-realpath-d2/foo')); } catch (e) {} @@ -289,16 +292,16 @@ function test_deep_symlink_mix(callback) { fs.mkdirSync(tmp('node-test-realpath-d2'), 0o700); try { [ - [entry, '../' + common.tmpDirName + '/node-test-realpath-d1/foo'], + [entry, common.tmpDir + '/node-test-realpath-d1/foo'], [tmp('node-test-realpath-d1'), - '../' + common.tmpDirName + '/node-test-realpath-d2'], + common.tmpDir + '/node-test-realpath-d2'], [tmp('node-test-realpath-d2/foo'), '../node-test-realpath-f2'], - [tmp('node-test-realpath-f2'), fixturesAbsDir + - '/nested-index/one/realpath-c'], - [fixturesAbsDir + '/nested-index/one/realpath-c', fixturesAbsDir + - '/nested-index/two/realpath-c'], - [fixturesAbsDir + '/nested-index/two/realpath-c', - '../../../' + common.tmpDirName + '/cycles/root.js'] + [tmp('node-test-realpath-f2'), targetsAbsDir + + '/nested-index/one/realpath-c'], + [targetsAbsDir + '/nested-index/one/realpath-c', targetsAbsDir + + '/nested-index/two/realpath-c'], + [targetsAbsDir + '/nested-index/two/realpath-c', + common.tmpDir + '/cycles/root.js'] ].forEach(function(t) { try { fs.unlinkSync(t[0]); } catch (e) {} fs.symlinkSync(t[1], t[0]); diff --git a/test/parallel/test-fs-stat.js b/test/parallel/test-fs-stat.js index 123d6608b4bb4f..1affdec6260c0d 100644 --- a/test/parallel/test-fs-stat.js +++ b/test/parallel/test-fs-stat.js @@ -1,5 +1,5 @@ /* eslint-disable strict */ -var common = require('../common'); +require('../common'); var assert = require('assert'); var fs = require('fs'); var got_error = false; diff --git a/test/parallel/test-fs-symlink-dir-junction-relative.js b/test/parallel/test-fs-symlink-dir-junction-relative.js index dcc4e989cc1ef2..cb3e5a464faba9 100644 --- a/test/parallel/test-fs-symlink-dir-junction-relative.js +++ b/test/parallel/test-fs-symlink-dir-junction-relative.js @@ -11,7 +11,7 @@ var expected_tests = 2; var linkPath1 = path.join(common.tmpDir, 'junction1'); var linkPath2 = path.join(common.tmpDir, 'junction2'); var linkTarget = path.join(common.fixturesDir); -var linkData = '../fixtures'; +var linkData = path.join(common.fixturesDir); common.refreshTmpDir(); @@ -42,4 +42,3 @@ function verifyLink(linkPath) { process.on('exit', function() { assert.equal(completed, expected_tests); }); - diff --git a/test/parallel/test-fs-sync-fd-leak.js b/test/parallel/test-fs-sync-fd-leak.js index 5f2b63125a1d0f..f7cfd25f4b9b4c 100644 --- a/test/parallel/test-fs-sync-fd-leak.js +++ b/test/parallel/test-fs-sync-fd-leak.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var fs = require('fs'); diff --git a/test/parallel/test-fs-utimes.js b/test/parallel/test-fs-utimes.js index 49746bfbfb8bb5..5d5cb40ec1eede 100644 --- a/test/parallel/test-fs-utimes.js +++ b/test/parallel/test-fs-utimes.js @@ -23,7 +23,7 @@ function check_mtime(resource, mtime) { var real_mtime = fs._toUnixTimestamp(stats.mtime); // check up to single-second precision // sub-second precision is OS and fs dependant - return Math.floor(mtime) == Math.floor(real_mtime); + return mtime - real_mtime < 2; } function expect_errno(syscall, resource, err, errno) { @@ -48,7 +48,7 @@ function expect_ok(syscall, resource, err, atime, mtime) { // would be even better though (node doesn't have such functionality yet) function runTest(atime, mtime, callback) { - var fd, err; + var fd; // // test synchronized code paths, these functions throw on failure // diff --git a/test/parallel/test-fs-write-file-sync.js b/test/parallel/test-fs-write-file-sync.js index 37373404daf20e..5f51878cbd8340 100644 --- a/test/parallel/test-fs-write-file-sync.js +++ b/test/parallel/test-fs-write-file-sync.js @@ -15,7 +15,7 @@ fs._closeSync = fs.closeSync; fs.closeSync = closeSync; // Reset the umask for testing -var mask = process.umask(0o000); +process.umask(0o000); // On Windows chmod is only able to manipulate read-only bit. Test if creating // the file in read-only mode works. diff --git a/test/parallel/test-fs-write-no-fd.js b/test/parallel/test-fs-write-no-fd.js index 5b38ce6ba814c4..eb0ed5caeb6612 100644 --- a/test/parallel/test-fs-write-no-fd.js +++ b/test/parallel/test-fs-write-no-fd.js @@ -1,5 +1,5 @@ 'use strict'; -const common = require('../common'); +require('../common'); const fs = require('fs'); const assert = require('assert'); diff --git a/test/parallel/test-handle-wrap-close-abort.js b/test/parallel/test-handle-wrap-close-abort.js index 8e2388fa84d809..8572668f666864 100644 --- a/test/parallel/test-handle-wrap-close-abort.js +++ b/test/parallel/test-handle-wrap-close-abort.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); process.on('uncaughtException', function() { }); diff --git a/test/parallel/test-http-1.0-keep-alive.js b/test/parallel/test-http-1.0-keep-alive.js index eac0fe51e2206a..516a02031ef247 100644 --- a/test/parallel/test-http-1.0-keep-alive.js +++ b/test/parallel/test-http-1.0-keep-alive.js @@ -1,6 +1,5 @@ 'use strict'; var common = require('../common'); -var assert = require('assert'); var http = require('http'); var net = require('net'); diff --git a/test/parallel/test-http-1.0.js b/test/parallel/test-http-1.0.js index 9989c9b969b879..f9c865f3e630a0 100644 --- a/test/parallel/test-http-1.0.js +++ b/test/parallel/test-http-1.0.js @@ -19,7 +19,7 @@ function test(handler, request_generator, response_validator) { server.close(); response_validator(server_response, client_got_eof, true); } - var timer = setTimeout(cleanup, 1000); + var timer = setTimeout(cleanup, common.platformTimeout(1000)); process.on('exit', cleanup); server.listen(port); diff --git a/test/parallel/test-http-304.js b/test/parallel/test-http-304.js index 06fd60f5572ba2..6ac1c68d0d3665 100644 --- a/test/parallel/test-http-304.js +++ b/test/parallel/test-http-304.js @@ -1,6 +1,5 @@ 'use strict'; var common = require('../common'); -var assert = require('assert'); var http = require('http'); var childProcess = require('child_process'); diff --git a/test/parallel/test-http-abort-client.js b/test/parallel/test-http-abort-client.js index e24ded11d1a7ec..4d7a32c1dfb26b 100644 --- a/test/parallel/test-http-abort-client.js +++ b/test/parallel/test-http-abort-client.js @@ -14,7 +14,7 @@ var server = http.Server(function(req, res) { var responseClose = false; server.listen(common.PORT, function() { - var client = http.get({ + http.get({ port: common.PORT, headers: { connection: 'keep-alive' } diff --git a/test/parallel/test-http-after-connect.js b/test/parallel/test-http-after-connect.js index edd03b2178b2ba..ed18def8608820 100644 --- a/test/parallel/test-http-after-connect.js +++ b/test/parallel/test-http-after-connect.js @@ -45,7 +45,7 @@ server.listen(common.PORT, function() { }); function doRequest(i) { - var req = http.get({ + http.get({ port: common.PORT, path: '/request' + i }, function(res) { diff --git a/test/parallel/test-http-agent-false.js b/test/parallel/test-http-agent-false.js index ad8de89f2038e9..96606028bf7a45 100644 --- a/test/parallel/test-http-agent-false.js +++ b/test/parallel/test-http-agent-false.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var http = require('http'); diff --git a/test/parallel/test-http-agent-getname.js b/test/parallel/test-http-agent-getname.js index d8d30a8ddbc25c..1b80b5c36e1e64 100644 --- a/test/parallel/test-http-agent-getname.js +++ b/test/parallel/test-http-agent-getname.js @@ -1,8 +1,8 @@ 'use strict'; +require('../common'); var assert = require('assert'); var http = require('http'); -var common = require('../common'); var agent = new http.Agent(); diff --git a/test/parallel/test-http-agent-keepalive.js b/test/parallel/test-http-agent-keepalive.js index ef9553c8316841..6800e893e329da 100644 --- a/test/parallel/test-http-agent-keepalive.js +++ b/test/parallel/test-http-agent-keepalive.js @@ -1,27 +1,26 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); -var http = require('http'); -var Agent = require('_http_agent').Agent; -var EventEmitter = require('events').EventEmitter; +const common = require('../common'); +const assert = require('assert'); +const http = require('http'); +const Agent = require('_http_agent').Agent; -var agent = new Agent({ +const agent = new Agent({ keepAlive: true, keepAliveMsecs: 1000, maxSockets: 5, maxFreeSockets: 5 }); -var server = http.createServer(function(req, res) { +const server = http.createServer(function(req, res) { if (req.url === '/error') { res.destroy(); return; } else if (req.url === '/remote_close') { - // cache the socket, close it after 100ms - var socket = res.connection; - setTimeout(function() { + // cache the socket, close it after a short delay + const socket = res.connection; + setImmediate(function() { socket.end(); - }, 100); + }); } res.end('hello world'); }); @@ -35,7 +34,7 @@ function get(path, callback) { }, callback); } -var name = 'localhost:' + common.PORT + ':'; +const name = 'localhost:' + common.PORT + ':'; function checkDataAndSockets(body) { assert.equal(body.toString(), 'hello world'); @@ -77,7 +76,7 @@ function remoteClose() { assert.equal(agent.freeSockets[name], undefined, 'freeSockets is not empty'); remoteError(); - }, 200); + }, common.platformTimeout(200)); }); }); }); @@ -85,7 +84,7 @@ function remoteClose() { function remoteError() { // remove server will destroy ths socket - var req = get('/error', function(res) { + const req = get('/error', function(res) { throw new Error('should not call this function'); }); req.on('error', function(err) { @@ -98,7 +97,7 @@ function remoteError() { assert.equal(agent.sockets[name], undefined); assert.equal(agent.freeSockets[name], undefined); done(); - }, 1); + }, common.platformTimeout(1)); }); } diff --git a/test/parallel/test-http-agent-maxsockets-regress-4050.js b/test/parallel/test-http-agent-maxsockets-regress-4050.js new file mode 100644 index 00000000000000..1cbe37cf0cc443 --- /dev/null +++ b/test/parallel/test-http-agent-maxsockets-regress-4050.js @@ -0,0 +1,43 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const http = require('http'); + +const MAX_SOCKETS = 2; + +const agent = new http.Agent({ + keepAlive: true, + keepAliveMsecs: 1000, + maxSockets: MAX_SOCKETS, + maxFreeSockets: 2 +}); + +const server = http.createServer(function(req, res) { + res.end('hello world'); +}); + +function get(path, callback) { + return http.get({ + host: 'localhost', + port: common.PORT, + agent: agent, + path: path + }, callback); +} + +server.listen(common.PORT, function() { + var finished = 0; + const num_requests = 6; + for (var i = 0; i < num_requests; i++) { + const request = get('/1', function() { + }); + request.on('response', function() { + request.abort(); + const sockets = agent.sockets[Object.keys(agent.sockets)[0]]; + assert(sockets.length <= MAX_SOCKETS); + if (++finished === num_requests) { + server.close(); + } + }); + } +}); diff --git a/test/parallel/test-http-agent-null.js b/test/parallel/test-http-agent-null.js index e118738f664083..29961ff3a5e84b 100644 --- a/test/parallel/test-http-agent-null.js +++ b/test/parallel/test-http-agent-null.js @@ -2,7 +2,6 @@ var common = require('../common'); var assert = require('assert'); var http = require('http'); -var net = require('net'); var request = 0; var response = 0; diff --git a/test/parallel/test-http-buffer-sanity.js b/test/parallel/test-http-buffer-sanity.js index 4b120311d7dac9..98ce0f75b916a8 100644 --- a/test/parallel/test-http-buffer-sanity.js +++ b/test/parallel/test-http-buffer-sanity.js @@ -2,7 +2,6 @@ var common = require('../common'); var assert = require('assert'); var http = require('http'); -var util = require('util'); var bufferSize = 5 * 1024 * 1024; var measuredSize = 0; diff --git a/test/parallel/test-http-byteswritten.js b/test/parallel/test-http-byteswritten.js index 974f446dd436b4..fdc407aec667ba 100644 --- a/test/parallel/test-http-byteswritten.js +++ b/test/parallel/test-http-byteswritten.js @@ -1,7 +1,6 @@ 'use strict'; var common = require('../common'); var assert = require('assert'); -var fs = require('fs'); var http = require('http'); var body = 'hello world\n'; diff --git a/test/parallel/test-http-client-abort2.js b/test/parallel/test-http-client-abort2.js index 3f7ae98fa25820..477d12b25827b2 100644 --- a/test/parallel/test-http-client-abort2.js +++ b/test/parallel/test-http-client-abort2.js @@ -1,6 +1,5 @@ 'use strict'; var common = require('../common'); -var assert = require('assert'); var http = require('http'); var server = http.createServer(function(req, res) { diff --git a/test/parallel/test-http-client-encoding.js b/test/parallel/test-http-client-encoding.js index dd696f4dff608a..baaef855b1e6e0 100644 --- a/test/parallel/test-http-client-encoding.js +++ b/test/parallel/test-http-client-encoding.js @@ -1,6 +1,5 @@ 'use strict'; var common = require('../common'); -var assert = require('assert'); var http = require('http'); diff --git a/test/parallel/test-http-client-pipe-end.js b/test/parallel/test-http-client-pipe-end.js index efe241419397e4..715f8ccf79df92 100644 --- a/test/parallel/test-http-client-pipe-end.js +++ b/test/parallel/test-http-client-pipe-end.js @@ -2,7 +2,6 @@ // see https://github.com/joyent/node/issues/3257 var common = require('../common'); -var assert = require('assert'); var http = require('http'); var server = http.createServer(function(req, res) { diff --git a/test/parallel/test-http-client-readable.js b/test/parallel/test-http-client-readable.js index ba9fdd658c3864..8328afb01c6478 100644 --- a/test/parallel/test-http-client-readable.js +++ b/test/parallel/test-http-client-readable.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var http = require('http'); var util = require('util'); diff --git a/test/parallel/test-http-client-timeout-with-data.js b/test/parallel/test-http-client-timeout-with-data.js index 0aefe62ef45055..673908fe6d465f 100644 --- a/test/parallel/test-http-client-timeout-with-data.js +++ b/test/parallel/test-http-client-timeout-with-data.js @@ -1,7 +1,7 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); -var http = require('http'); +const common = require('../common'); +const assert = require('assert'); +const http = require('http'); var ntimeouts = 0; var nchunks = 0; @@ -11,21 +11,21 @@ process.on('exit', function() { assert.equal(nchunks, 2); }); -var options = { +const options = { method: 'GET', port: common.PORT, host: '127.0.0.1', path: '/' }; -var server = http.createServer(function(req, res) { +const server = http.createServer(function(req, res) { res.writeHead(200, {'Content-Length':'2'}); res.write('*'); - setTimeout(function() { res.end('*'); }, 100); + setTimeout(function() { res.end('*'); }, common.platformTimeout(100)); }); server.listen(options.port, options.host, function() { - var req = http.request(options, onresponse); + const req = http.request(options, onresponse); req.end(); function onresponse(res) { diff --git a/test/parallel/test-http-default-port.js b/test/parallel/test-http-default-port.js index 457424ecfa9397..e403b401fb603f 100644 --- a/test/parallel/test-http-default-port.js +++ b/test/parallel/test-http-default-port.js @@ -57,7 +57,7 @@ if (common.hasCrypto) { res.end('ok'); this.close(); }).listen(SSLPORT, function() { - var req = https.get({ + https.get({ host: 'localhost', rejectUnauthorized: false, headers: { diff --git a/test/parallel/test-http-destroyed-socket-write2.js b/test/parallel/test-http-destroyed-socket-write2.js index 5bbb3bbc946f7d..9065939ccbd798 100644 --- a/test/parallel/test-http-destroyed-socket-write2.js +++ b/test/parallel/test-http-destroyed-socket-write2.js @@ -6,7 +6,6 @@ var assert = require('assert'); // where the server has ended the socket. var http = require('http'); -var net = require('net'); var server = http.createServer(function(req, res) { setImmediate(function() { res.destroy(); diff --git a/test/parallel/test-http-eof-on-connect.js b/test/parallel/test-http-eof-on-connect.js index e676643bab4911..fc7dd1d9fe88ce 100644 --- a/test/parallel/test-http-eof-on-connect.js +++ b/test/parallel/test-http-eof-on-connect.js @@ -1,6 +1,5 @@ 'use strict'; var common = require('../common'); -var assert = require('assert'); var net = require('net'); var http = require('http'); diff --git a/test/parallel/test-http-exceptions.js b/test/parallel/test-http-exceptions.js index dc2d5583ddbaf9..922dc2095714be 100644 --- a/test/parallel/test-http-exceptions.js +++ b/test/parallel/test-http-exceptions.js @@ -1,6 +1,5 @@ 'use strict'; var common = require('../common'); -var assert = require('assert'); var http = require('http'); var server = http.createServer(function(req, res) { @@ -11,9 +10,8 @@ var server = http.createServer(function(req, res) { }); server.listen(common.PORT, function() { - var req; for (var i = 0; i < 4; i += 1) { - req = http.get({ port: common.PORT, path: '/busy/' + i }); + http.get({ port: common.PORT, path: '/busy/' + i }); } }); diff --git a/test/parallel/test-http-flush-headers.js b/test/parallel/test-http-flush-headers.js index e3c9761cff5d34..5e91a4643a9019 100644 --- a/test/parallel/test-http-flush-headers.js +++ b/test/parallel/test-http-flush-headers.js @@ -10,7 +10,7 @@ server.on('request', function(req, res) { server.close(); }); server.listen(common.PORT, '127.0.0.1', function() { - let req = http.request({ + const req = http.request({ method: 'GET', host: '127.0.0.1', port: common.PORT, diff --git a/test/parallel/test-http-flush.js b/test/parallel/test-http-flush.js index cac1caf752bee6..8dc7ba7418dc88 100644 --- a/test/parallel/test-http-flush.js +++ b/test/parallel/test-http-flush.js @@ -1,6 +1,5 @@ 'use strict'; var common = require('../common'); -var assert = require('assert'); var http = require('http'); http.createServer(function(req, res) { diff --git a/test/parallel/test-http-head-request.js b/test/parallel/test-http-head-request.js index 5a6f90507cf303..faf2168e36d0be 100644 --- a/test/parallel/test-http-head-request.js +++ b/test/parallel/test-http-head-request.js @@ -2,7 +2,6 @@ var common = require('../common'); var assert = require('assert'); var http = require('http'); -var util = require('util'); var body = 'hello world\n'; diff --git a/test/parallel/test-http-incoming-pipelined-socket-destroy.js b/test/parallel/test-http-incoming-pipelined-socket-destroy.js index 21cd3e69dfd746..1e5a910424d737 100644 --- a/test/parallel/test-http-incoming-pipelined-socket-destroy.js +++ b/test/parallel/test-http-incoming-pipelined-socket-destroy.js @@ -1,6 +1,5 @@ 'use strict'; var common = require('../common'); -var assert = require('assert'); var http = require('http'); var net = require('net'); diff --git a/test/parallel/test-http-keep-alive-close-on-header.js b/test/parallel/test-http-keep-alive-close-on-header.js index 9ed6077b943aa8..83a0d0684cf637 100644 --- a/test/parallel/test-http-keep-alive-close-on-header.js +++ b/test/parallel/test-http-keep-alive-close-on-header.js @@ -2,7 +2,6 @@ var common = require('../common'); var assert = require('assert'); var http = require('http'); -var util = require('util'); var body = 'hello world\n'; var headers = {'connection': 'keep-alive'}; diff --git a/test/parallel/test-http-keep-alive.js b/test/parallel/test-http-keep-alive.js index f89f7698c46ebd..0d30bbe1da3069 100644 --- a/test/parallel/test-http-keep-alive.js +++ b/test/parallel/test-http-keep-alive.js @@ -11,7 +11,6 @@ var server = http.createServer(function(req, res) { res.end(); }); -var connectCount = 0; var agent = new http.Agent({maxSockets: 1}); var headers = {'connection': 'keep-alive'}; var name = agent.getName({ port: common.PORT }); diff --git a/test/parallel/test-http-localaddress-bind-error.js b/test/parallel/test-http-localaddress-bind-error.js index 9a4bde26cd22d6..adaeba2b9459ea 100644 --- a/test/parallel/test-http-localaddress-bind-error.js +++ b/test/parallel/test-http-localaddress-bind-error.js @@ -17,7 +17,7 @@ var server = http.createServer(function(req, res) { }); server.listen(common.PORT, '127.0.0.1', function() { - var req = http.request({ + http.request({ host: 'localhost', port: common.PORT, path: '/', diff --git a/test/parallel/test-http-many-ended-pipelines.js b/test/parallel/test-http-many-ended-pipelines.js index 4e0bc7e8ff736f..c415af64f9dcd6 100644 --- a/test/parallel/test-http-many-ended-pipelines.js +++ b/test/parallel/test-http-many-ended-pipelines.js @@ -1,6 +1,5 @@ 'use strict'; var common = require('../common'); -var assert = require('assert'); // no warnings should happen! var trace = console.trace; @@ -13,15 +12,19 @@ var http = require('http'); var net = require('net'); var numRequests = 20; -var done = 0; +var first = false; var server = http.createServer(function(req, res) { - res.end('ok'); + if (!first) { + first = true; + req.socket.on('close', function() { + server.close(); + }); + } + res.end('ok'); // Oh no! The connection died! req.socket.destroy(); - if (++done == numRequests) - server.close(); }); server.listen(common.PORT); diff --git a/test/parallel/test-http-methods.js b/test/parallel/test-http-methods.js index 348fd2e519ef64..62a4187841bdbc 100644 --- a/test/parallel/test-http-methods.js +++ b/test/parallel/test-http-methods.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var http = require('http'); var util = require('util'); diff --git a/test/parallel/test-http-mutable-headers.js b/test/parallel/test-http-mutable-headers.js index 2a60117328c580..af8fd6d7e8f938 100644 --- a/test/parallel/test-http-mutable-headers.js +++ b/test/parallel/test-http-mutable-headers.js @@ -110,7 +110,7 @@ function nextTest() { break; default: - throw Error('?'); + throw new Error('?'); } response.setEncoding('utf8'); diff --git a/test/parallel/test-http-no-content-length.js b/test/parallel/test-http-no-content-length.js index 5752e5e924cd1b..7a205dc07df3ca 100644 --- a/test/parallel/test-http-no-content-length.js +++ b/test/parallel/test-http-no-content-length.js @@ -10,7 +10,7 @@ var server = net.createServer(function(socket) { // Neither Content-Length nor Connection socket.end('HTTP/1.1 200 ok\r\n\r\nHello'); }).listen(common.PORT, function() { - var req = http.get({port: common.PORT}, function(res) { + http.get({port: common.PORT}, function(res) { res.setEncoding('utf8'); res.on('data', function(chunk) { body += chunk; diff --git a/test/parallel/test-http-parser-bad-ref.js b/test/parallel/test-http-parser-bad-ref.js index d409dc62d008d9..545a9c1fef11c4 100644 --- a/test/parallel/test-http-parser-bad-ref.js +++ b/test/parallel/test-http-parser-bad-ref.js @@ -4,7 +4,7 @@ // Flags: --expose_gc -var common = require('../common'); +require('../common'); var assert = require('assert'); var HTTPParser = process.binding('http_parser').HTTPParser; diff --git a/test/parallel/test-http-parser.js b/test/parallel/test-http-parser.js index bb004f864cf468..f10f3ac26b4b10 100644 --- a/test/parallel/test-http-parser.js +++ b/test/parallel/test-http-parser.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var HTTPParser = process.binding('http_parser').HTTPParser; diff --git a/test/parallel/test-http-pipeline-regr-3508.js b/test/parallel/test-http-pipeline-regr-3508.js index 05639a2a42c5a7..74fe7586726cbd 100644 --- a/test/parallel/test-http-pipeline-regr-3508.js +++ b/test/parallel/test-http-pipeline-regr-3508.js @@ -1,6 +1,5 @@ 'use strict'; const common = require('../common'); -const assert = require('assert'); const http = require('http'); const net = require('net'); diff --git a/test/parallel/test-http-proxy.js b/test/parallel/test-http-proxy.js index fc8a753f2485ce..8a579cd69aa5b4 100644 --- a/test/parallel/test-http-proxy.js +++ b/test/parallel/test-http-proxy.js @@ -25,7 +25,7 @@ var backend = http.createServer(function(req, res) { var proxy = http.createServer(function(req, res) { console.error('proxy req headers: ' + JSON.stringify(req.headers)); - var proxy_req = http.get({ + http.get({ port: BACKEND_PORT, path: url.parse(req.url).pathname }, function(proxy_res) { @@ -56,7 +56,7 @@ function startReq() { nlistening++; if (nlistening < 2) return; - var client = http.get({ + http.get({ port: PROXY_PORT, path: '/test' }, function(res) { diff --git a/test/parallel/test-http-raw-headers.js b/test/parallel/test-http-raw-headers.js index 7ecaaa93cfb04e..2042c0262a95ed 100644 --- a/test/parallel/test-http-raw-headers.js +++ b/test/parallel/test-http-raw-headers.js @@ -54,14 +54,6 @@ http.createServer(function(req, res) { ]); res.end('x f o o'); }).listen(common.PORT, function() { - var expectRawHeaders = [ - 'Date', - 'Tue, 06 Aug 2013 01:31:54 GMT', - 'Connection', - 'close', - 'Transfer-Encoding', - 'chunked' - ]; var req = http.request({ port: common.PORT, path: '/' }); req.addTrailers([ ['x-bAr', 'yOyOyOy'], diff --git a/test/parallel/test-http-regr-gh-2821.js b/test/parallel/test-http-regr-gh-2821.js index 4fdef2369bb168..8725111324a869 100644 --- a/test/parallel/test-http-regr-gh-2821.js +++ b/test/parallel/test-http-regr-gh-2821.js @@ -1,6 +1,5 @@ 'use strict'; const common = require('../common'); -const assert = require('assert'); const http = require('http'); const server = http.createServer(function(req, res) { diff --git a/test/parallel/test-http-res-write-after-end.js b/test/parallel/test-http-res-write-after-end.js index c8b3bf26e0804b..206f4273ec70c7 100644 --- a/test/parallel/test-http-res-write-after-end.js +++ b/test/parallel/test-http-res-write-after-end.js @@ -18,7 +18,7 @@ var server = http.Server(function(req, res) { }); server.listen(common.PORT, function() { - var req = http.get({port: common.PORT}, function(res) { + http.get({port: common.PORT}, function(res) { server.close(); }); }); diff --git a/test/parallel/test-http-server-stale-close.js b/test/parallel/test-http-server-stale-close.js index a866d39c2cc735..349e869c1a4fbc 100644 --- a/test/parallel/test-http-server-stale-close.js +++ b/test/parallel/test-http-server-stale-close.js @@ -1,6 +1,5 @@ 'use strict'; var common = require('../common'); -var assert = require('assert'); var http = require('http'); var util = require('util'); var fork = require('child_process').fork; diff --git a/test/parallel/test-http-timeout.js b/test/parallel/test-http-timeout.js index aab903420f0acc..f459961517852b 100644 --- a/test/parallel/test-http-timeout.js +++ b/test/parallel/test-http-timeout.js @@ -1,6 +1,5 @@ 'use strict'; var common = require('../common'); -var assert = require('assert'); var http = require('http'); diff --git a/test/parallel/test-http-unix-socket.js b/test/parallel/test-http-unix-socket.js index 98ed839241c2c6..bdac0566c33a42 100644 --- a/test/parallel/test-http-unix-socket.js +++ b/test/parallel/test-http-unix-socket.js @@ -1,7 +1,6 @@ 'use strict'; var common = require('../common'); var assert = require('assert'); -var fs = require('fs'); var http = require('http'); var status_ok = false; // status code == 200? diff --git a/test/parallel/test-http-url.parse-https.request.js b/test/parallel/test-http-url.parse-https.request.js index 10c40ec0310708..df01ae64f81dba 100644 --- a/test/parallel/test-http-url.parse-https.request.js +++ b/test/parallel/test-http-url.parse-https.request.js @@ -10,7 +10,6 @@ var https = require('https'); var url = require('url'); var fs = require('fs'); -var clientRequest; // https options var httpsOptions = { diff --git a/test/parallel/test-http-url.parse-only-support-http-https-protocol.js b/test/parallel/test-http-url.parse-only-support-http-https-protocol.js index fd52a0b62d11de..0e997694aa7459 100644 --- a/test/parallel/test-http-url.parse-only-support-http-https-protocol.js +++ b/test/parallel/test-http-url.parse-only-support-http-https-protocol.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var http = require('http'); var url = require('url'); diff --git a/test/parallel/test-https-agent-servername.js b/test/parallel/test-https-agent-servername.js index 2be40836a04ea2..f7d5e5a40d8679 100644 --- a/test/parallel/test-https-agent-servername.js +++ b/test/parallel/test-https-agent-servername.js @@ -1,6 +1,5 @@ 'use strict'; var common = require('../common'); -var assert = require('assert'); if (!common.hasCrypto) { console.log('1..0 # Skipped: missing crypto'); diff --git a/test/parallel/test-https-agent-sni.js b/test/parallel/test-https-agent-sni.js new file mode 100644 index 00000000000000..117075f68264b4 --- /dev/null +++ b/test/parallel/test-https-agent-sni.js @@ -0,0 +1,52 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); + +if (!common.hasCrypto) { + console.log('1..0 # Skipped: missing crypto'); + return; +} +const https = require('https'); + +const fs = require('fs'); + +const options = { + key: fs.readFileSync(common.fixturesDir + '/keys/agent1-key.pem'), + cert: fs.readFileSync(common.fixturesDir + '/keys/agent1-cert.pem') +}; + +const TOTAL = 4; +var waiting = TOTAL; + +const server = https.Server(options, function(req, res) { + if (--waiting === 0) server.close(); + + res.writeHead(200, { + 'x-sni': req.socket.servername + }); + res.end('hello world'); +}); + +server.listen(common.PORT, function() { + function expectResponse(id) { + return common.mustCall(function(res) { + res.resume(); + assert.equal(res.headers['x-sni'], 'sni.' + id); + }); + } + + var agent = new https.Agent({ + maxSockets: 1 + }); + for (var j = 0; j < TOTAL; j++) { + https.get({ + agent: agent, + + path: '/', + port: common.PORT, + host: '127.0.0.1', + servername: 'sni.' + j, + rejectUnauthorized: false + }, expectResponse(j)); + } +}); diff --git a/test/parallel/test-https-byteswritten.js b/test/parallel/test-https-byteswritten.js index 5163eccc262ffa..beef89b25ccb98 100644 --- a/test/parallel/test-https-byteswritten.js +++ b/test/parallel/test-https-byteswritten.js @@ -2,7 +2,6 @@ var common = require('../common'); var assert = require('assert'); var fs = require('fs'); -var http = require('http'); if (!common.hasCrypto) { console.log('1..0 # Skipped: missing crypto'); diff --git a/test/parallel/test-https-eof-for-eom.js b/test/parallel/test-https-eof-for-eom.js index 0445625bace642..50d909373ff5b0 100644 --- a/test/parallel/test-https-eof-for-eom.js +++ b/test/parallel/test-https-eof-for-eom.js @@ -53,7 +53,7 @@ var bodyBuffer = ''; server.listen(common.PORT, function() { console.log('1) Making Request'); - var req = https.get({ + https.get({ port: common.PORT, rejectUnauthorized: false }, function(res) { diff --git a/test/parallel/test-https-localaddress-bind-error.js b/test/parallel/test-https-localaddress-bind-error.js index 66551a780aed9e..f5bb1f84c310b3 100644 --- a/test/parallel/test-https-localaddress-bind-error.js +++ b/test/parallel/test-https-localaddress-bind-error.js @@ -28,7 +28,7 @@ var server = https.createServer(options, function(req, res) { }); server.listen(common.PORT, '127.0.0.1', function() { - var req = https.request({ + https.request({ host: 'localhost', port: common.PORT, path: '/', diff --git a/test/parallel/test-https-socket-options.js b/test/parallel/test-https-socket-options.js index 44e179f27a800c..2adf8c798dff65 100644 --- a/test/parallel/test-https-socket-options.js +++ b/test/parallel/test-https-socket-options.js @@ -1,6 +1,5 @@ 'use strict'; var common = require('../common'); -var assert = require('assert'); if (!common.hasCrypto) { console.log('1..0 # Skipped: missing crypto'); @@ -9,7 +8,6 @@ if (!common.hasCrypto) { var https = require('https'); var fs = require('fs'); -var exec = require('child_process').exec; var http = require('http'); diff --git a/test/parallel/test-https-strict.js b/test/parallel/test-https-strict.js index 65ebfabde2bcdd..04561959de130f 100644 --- a/test/parallel/test-https-strict.js +++ b/test/parallel/test-https-strict.js @@ -110,7 +110,7 @@ function makeReq(path, port, error, host, ca) { path: path, ca: ca }; - var whichCa = 0; + if (!ca) { options.agent = agent0; } else { diff --git a/test/parallel/test-https-timeout-server-2.js b/test/parallel/test-https-timeout-server-2.js index df605958cf42df..a195ce1938b9cd 100644 --- a/test/parallel/test-https-timeout-server-2.js +++ b/test/parallel/test-https-timeout-server-2.js @@ -9,7 +9,6 @@ if (!common.hasCrypto) { } var https = require('https'); -var net = require('net'); var tls = require('tls'); var fs = require('fs'); diff --git a/test/parallel/test-https-timeout-server.js b/test/parallel/test-https-timeout-server.js index ba175ecf763ecf..f6d5d75a88abbe 100644 --- a/test/parallel/test-https-timeout-server.js +++ b/test/parallel/test-https-timeout-server.js @@ -9,7 +9,6 @@ if (!common.hasCrypto) { var https = require('https'); var net = require('net'); -var tls = require('tls'); var fs = require('fs'); var clientErrors = 0; diff --git a/test/parallel/test-https-timeout.js b/test/parallel/test-https-timeout.js index 7f34c18bec0897..2b41dadaec7857 100644 --- a/test/parallel/test-https-timeout.js +++ b/test/parallel/test-https-timeout.js @@ -1,6 +1,5 @@ 'use strict'; var common = require('../common'); -var assert = require('assert'); if (!common.hasCrypto) { console.log('1..0 # Skipped: missing crypto'); @@ -9,7 +8,6 @@ if (!common.hasCrypto) { var https = require('https'); var fs = require('fs'); -var exec = require('child_process').exec; var options = { key: fs.readFileSync(common.fixturesDir + '/keys/agent1-key.pem'), diff --git a/test/parallel/test-https-truncate.js b/test/parallel/test-https-truncate.js index e77bf29ed25454..83506c65d6f3cc 100644 --- a/test/parallel/test-https-truncate.js +++ b/test/parallel/test-https-truncate.js @@ -9,7 +9,6 @@ if (!common.hasCrypto) { var https = require('https'); var fs = require('fs'); -var path = require('path'); var key = fs.readFileSync(common.fixturesDir + '/keys/agent1-key.pem'); var cert = fs.readFileSync(common.fixturesDir + '/keys/agent1-cert.pem'); diff --git a/test/parallel/test-internal-modules-expose.js b/test/parallel/test-internal-modules-expose.js index 4ece1d0c7b6f29..ed3cecb6f29719 100644 --- a/test/parallel/test-internal-modules-expose.js +++ b/test/parallel/test-internal-modules-expose.js @@ -1,7 +1,7 @@ 'use strict'; // Flags: --expose_internals -var common = require('../common'); +require('../common'); var assert = require('assert'); assert.equal(typeof require('internal/freelist').FreeList, 'function'); diff --git a/test/parallel/test-internal-modules.js b/test/parallel/test-internal-modules.js index 011b6f7132e9bf..5d93a381c7acdf 100644 --- a/test/parallel/test-internal-modules.js +++ b/test/parallel/test-internal-modules.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); assert.throws(function() { diff --git a/test/parallel/test-intl.js b/test/parallel/test-intl.js index 7288febf9e6bfd..1219c330386ca5 100644 --- a/test/parallel/test-intl.js +++ b/test/parallel/test-intl.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); // does node think that i18n was enabled? diff --git a/test/parallel/test-js-stream-call-properties.js b/test/parallel/test-js-stream-call-properties.js index c6b1adb3cb7a7a..280e5d9dabee66 100644 --- a/test/parallel/test-js-stream-call-properties.js +++ b/test/parallel/test-js-stream-call-properties.js @@ -1,6 +1,6 @@ 'use strict'; -const common = require('../common'); +require('../common'); const util = require('util'); const JSStream = process.binding('js_stream').JSStream; diff --git a/test/parallel/test-listen-fd-cluster.js b/test/parallel/test-listen-fd-cluster.js index f6d00c72a0f78c..c321f699d7a89d 100644 --- a/test/parallel/test-listen-fd-cluster.js +++ b/test/parallel/test-listen-fd-cluster.js @@ -4,7 +4,6 @@ var assert = require('assert'); var http = require('http'); var net = require('net'); var PORT = common.PORT; -var spawn = require('child_process').spawn; var cluster = require('cluster'); console.error('Cluster listen fd test', process.argv[2] || 'runner'); diff --git a/test/parallel/test-listen-fd-server.js b/test/parallel/test-listen-fd-server.js index d51d51ee8eb4de..3e0fa521f75334 100644 --- a/test/parallel/test-listen-fd-server.js +++ b/test/parallel/test-listen-fd-server.js @@ -4,7 +4,6 @@ var assert = require('assert'); var http = require('http'); var net = require('net'); var PORT = common.PORT; -var spawn = require('child_process').spawn; if (common.isWindows) { console.log('1..0 # Skipped: This test is disabled on windows.'); diff --git a/test/parallel/test-memory-usage.js b/test/parallel/test-memory-usage.js index 8394fc16599ef3..9b39601e2e20b3 100644 --- a/test/parallel/test-memory-usage.js +++ b/test/parallel/test-memory-usage.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var r = process.memoryUsage(); diff --git a/test/parallel/test-microtask-queue-integration-domain.js b/test/parallel/test-microtask-queue-integration-domain.js index 7a4ad77cd321e3..f0d0196ac2f9a7 100644 --- a/test/parallel/test-microtask-queue-integration-domain.js +++ b/test/parallel/test-microtask-queue-integration-domain.js @@ -1,7 +1,13 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); -var domain = require('domain'); + +// Requiring the domain module here changes the function that is used by node to +// call process.nextTick's callbacks to a variant that specifically handles +// domains. We want to test this specific variant in this test, and so even if +// the domain module is not used, this require call is needed and must not be +// removed. +require('domain'); var implementations = [ function(fn) { diff --git a/test/parallel/test-microtask-queue-integration.js b/test/parallel/test-microtask-queue-integration.js index 37de5ee33b1477..fe873d27c91447 100644 --- a/test/parallel/test-microtask-queue-integration.js +++ b/test/parallel/test-microtask-queue-integration.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var implementations = [ diff --git a/test/parallel/test-microtask-queue-run-domain.js b/test/parallel/test-microtask-queue-run-domain.js index 77534920ff1451..fb5139f71d65aa 100644 --- a/test/parallel/test-microtask-queue-run-domain.js +++ b/test/parallel/test-microtask-queue-run-domain.js @@ -1,7 +1,13 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); -var domain = require('domain'); + +// Requiring the domain module here changes the function that is used by node to +// call process.nextTick's callbacks to a variant that specifically handles +// domains. We want to test this specific variant in this test, and so even if +// the domain module is not used, this require call is needed and must not be +// removed. +require('domain'); function enqueueMicrotask(fn) { Promise.resolve().then(fn); diff --git a/test/parallel/test-microtask-queue-run-immediate-domain.js b/test/parallel/test-microtask-queue-run-immediate-domain.js index 2dea0a76cc1bf4..4a7729ab98a062 100644 --- a/test/parallel/test-microtask-queue-run-immediate-domain.js +++ b/test/parallel/test-microtask-queue-run-immediate-domain.js @@ -1,7 +1,13 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); -var domain = require('domain'); + +// Requiring the domain module here changes the function that is used by node to +// call process.nextTick's callbacks to a variant that specifically handles +// domains. We want to test this specific variant in this test, and so even if +// the domain module is not used, this require call is needed and must not be +// removed. +require('domain'); function enqueueMicrotask(fn) { Promise.resolve().then(fn); diff --git a/test/parallel/test-microtask-queue-run-immediate.js b/test/parallel/test-microtask-queue-run-immediate.js index cfd9cd3659ef00..479062ad4710f4 100644 --- a/test/parallel/test-microtask-queue-run-immediate.js +++ b/test/parallel/test-microtask-queue-run-immediate.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); function enqueueMicrotask(fn) { diff --git a/test/parallel/test-microtask-queue-run.js b/test/parallel/test-microtask-queue-run.js index ca758546c2bcfd..ce743d93003249 100644 --- a/test/parallel/test-microtask-queue-run.js +++ b/test/parallel/test-microtask-queue-run.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); function enqueueMicrotask(fn) { diff --git a/test/parallel/test-module-loading-error.js b/test/parallel/test-module-loading-error.js index 5f9195d7736549..072a6aadcb8c62 100644 --- a/test/parallel/test-module-loading-error.js +++ b/test/parallel/test-module-loading-error.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); console.error('load test-module-loading-error.js'); @@ -7,7 +7,8 @@ console.error('load test-module-loading-error.js'); var error_desc = { win32: ['%1 is not a valid Win32 application'], linux: ['file too short', 'Exec format error'], - sunos: ['unknown file type', 'not an ELF file'] + sunos: ['unknown file type', 'not an ELF file'], + darwin: ['file too short'] }; var dlerror_msg = error_desc[process.platform]; diff --git a/test/parallel/test-net-connect-options-ipv6.js b/test/parallel/test-net-connect-options-ipv6.js index f0f7bc65b3c7eb..8b11612a1286f2 100644 --- a/test/parallel/test-net-connect-options-ipv6.js +++ b/test/parallel/test-net-connect-options-ipv6.js @@ -1,57 +1,56 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); -var net = require('net'); -var dns = require('dns'); +const common = require('../common'); +const assert = require('assert'); +const net = require('net'); if (!common.hasIPv6) { console.log('1..0 # Skipped: no IPv6 support'); return; } -var serverGotEnd = false; -var clientGotEnd = false; +const hosts = common.localIPv6Hosts; +var hostIdx = 0; +var host = hosts[hostIdx]; +var localhostTries = 10; -dns.lookup('localhost', 6, function(err) { - if (err) { - console.error('Looks like IPv6 is not really supported'); - console.error(err); - return; - } +const server = net.createServer({allowHalfOpen: true}, function(socket) { + socket.resume(); + socket.on('end', common.mustCall(function() {})); + socket.end(); +}); - var server = net.createServer({allowHalfOpen: true}, function(socket) { - socket.resume(); - socket.on('end', function() { - serverGotEnd = true; - }); - socket.end(); - }); +server.listen(common.PORT, '::1', tryConnect); - server.listen(common.PORT, '::1', function() { - var client = net.connect({ - host: 'localhost', - port: common.PORT, - family: 6, - allowHalfOpen: true - }, function() { - console.error('client connect cb'); - client.resume(); - client.on('end', function() { - clientGotEnd = true; - setTimeout(function() { - assert(client.writable); - client.end(); - }, 10); - }); - client.on('close', function() { - server.close(); - }); +function tryConnect() { + const client = net.connect({ + host: host, + port: common.PORT, + family: 6, + allowHalfOpen: true + }, function() { + console.error('client connect cb'); + client.resume(); + client.on('end', common.mustCall(function() { + setTimeout(function() { + assert(client.writable); + client.end(); + }, 10); + })); + client.on('close', function() { + server.close(); }); + }).on('error', function(err) { + if (err.syscall === 'getaddrinfo' && err.code === 'ENOTFOUND') { + if (host !== 'localhost' || --localhostTries === 0) + host = hosts[++hostIdx]; + if (host) + tryConnect(); + else { + console.log('1..0 # Skipped: no IPv6 localhost support'); + server.close(); + } + return; + } + throw err; }); - - process.on('exit', function() { - console.error('exit', serverGotEnd, clientGotEnd); - assert(serverGotEnd); - assert(clientGotEnd); - }); -}); +} diff --git a/test/parallel/test-net-create-connection.js b/test/parallel/test-net-create-connection.js index c245ddc2ae7860..38452be6e6a954 100644 --- a/test/parallel/test-net-create-connection.js +++ b/test/parallel/test-net-create-connection.js @@ -22,7 +22,7 @@ server.listen(tcpPort, 'localhost', function() { function fail(opts, errtype, msg) { assert.throws(function() { - var client = net.createConnection(opts, cb); + net.createConnection(opts, cb); }, function(err) { return err instanceof errtype && msg === err.message; }); diff --git a/test/parallel/test-net-dns-custom-lookup.js b/test/parallel/test-net-dns-custom-lookup.js index 008e831c61fc9c..a2ce3966ae1237 100644 --- a/test/parallel/test-net-dns-custom-lookup.js +++ b/test/parallel/test-net-dns-custom-lookup.js @@ -2,7 +2,6 @@ var common = require('../common'); var assert = require('assert'); var net = require('net'); -var dns = require('dns'); var ok = false; function check(addressType, cb) { diff --git a/test/parallel/test-net-dns-error.js b/test/parallel/test-net-dns-error.js index 17f251cec3b6af..fc27eb1b9b0751 100644 --- a/test/parallel/test-net-dns-error.js +++ b/test/parallel/test-net-dns-error.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var net = require('net'); diff --git a/test/parallel/test-net-dns-lookup-skip.js b/test/parallel/test-net-dns-lookup-skip.js index b293196ad45c7e..9b3ae15fc393ae 100644 --- a/test/parallel/test-net-dns-lookup-skip.js +++ b/test/parallel/test-net-dns-lookup-skip.js @@ -1,6 +1,5 @@ 'use strict'; var common = require('../common'); -var assert = require('assert'); var net = require('net'); function check(addressType) { diff --git a/test/parallel/test-net-end-without-connect.js b/test/parallel/test-net-end-without-connect.js index 2911591f9f486d..69abf486316ff2 100644 --- a/test/parallel/test-net-end-without-connect.js +++ b/test/parallel/test-net-end-without-connect.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var net = require('net'); var sock = new net.Socket(); diff --git a/test/parallel/test-net-error-twice.js b/test/parallel/test-net-error-twice.js index af92ca93206f18..28e90ddd611ba9 100644 --- a/test/parallel/test-net-error-twice.js +++ b/test/parallel/test-net-error-twice.js @@ -1,16 +1,24 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); -var net = require('net'); +const common = require('../common'); +const assert = require('assert'); +const net = require('net'); -var buf = new Buffer(10 * 1024 * 1024); +const buf = new Buffer(10 * 1024 * 1024); buf.fill(0x62); -var errs = []; +const errs = []; +var clientSocket; +var serverSocket; + +function ready() { + if (clientSocket && serverSocket) { + clientSocket.destroy(); + serverSocket.write(buf); + } +} var srv = net.createServer(function onConnection(conn) { - conn.write(buf); conn.on('error', function(err) { errs.push(err); if (errs.length > 1 && errs[0] === errs[1]) @@ -19,11 +27,14 @@ var srv = net.createServer(function onConnection(conn) { conn.on('close', function() { srv.unref(); }); + serverSocket = conn; + ready(); }).listen(common.PORT, function() { var client = net.connect({ port: common.PORT }); client.on('connect', function() { - client.destroy(); + clientSocket = client; + ready(); }); }); diff --git a/test/parallel/test-net-isip.js b/test/parallel/test-net-isip.js index 96177122b7ba21..76432ed3488240 100644 --- a/test/parallel/test-net-isip.js +++ b/test/parallel/test-net-isip.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var net = require('net'); diff --git a/test/parallel/test-net-listen-close-server.js b/test/parallel/test-net-listen-close-server.js index 144ca58bbbe2b9..9cde6df1645d01 100644 --- a/test/parallel/test-net-listen-close-server.js +++ b/test/parallel/test-net-listen-close-server.js @@ -2,7 +2,6 @@ var common = require('../common'); var assert = require('assert'); var net = require('net'); -var gotError = false; var server = net.createServer(function(socket) { }); diff --git a/test/parallel/test-net-listen-error.js b/test/parallel/test-net-listen-error.js index 79cfc7da6c9255..4c4d27d703a9a6 100644 --- a/test/parallel/test-net-listen-error.js +++ b/test/parallel/test-net-listen-error.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var net = require('net'); var gotError = false; diff --git a/test/parallel/test-net-local-address-port.js b/test/parallel/test-net-local-address-port.js index aa28d180dae6ff..728993ee1bb023 100644 --- a/test/parallel/test-net-local-address-port.js +++ b/test/parallel/test-net-local-address-port.js @@ -3,7 +3,7 @@ var common = require('../common'); var assert = require('assert'); var net = require('net'); -var conns = 0, conns_closed = 0; +var conns = 0; var server = net.createServer(function(socket) { conns++; diff --git a/test/parallel/test-net-localerror.js b/test/parallel/test-net-localerror.js index 45ec1fc9099955..ed7c9471e0397f 100644 --- a/test/parallel/test-net-localerror.js +++ b/test/parallel/test-net-localerror.js @@ -17,6 +17,6 @@ connect({ function connect(opts, msg) { assert.throws(function() { - var client = net.connect(opts); + net.connect(opts); }, msg); } diff --git a/test/parallel/test-net-pipe-connect-errors.js b/test/parallel/test-net-pipe-connect-errors.js index 81ad90ef829c07..dbc7967fec9e63 100644 --- a/test/parallel/test-net-pipe-connect-errors.js +++ b/test/parallel/test-net-pipe-connect-errors.js @@ -42,7 +42,8 @@ var notSocketClient = net.createConnection(emptyTxt, function() { }); notSocketClient.on('error', function(err) { - assert(err.code === 'ENOTSOCK' || err.code === 'ECONNREFUSED'); + assert(err.code === 'ENOTSOCK' || err.code === 'ECONNREFUSED', + `received ${err.code} instead of ENOTSOCK or ECONNREFUSED`); notSocketErrorFired = true; }); diff --git a/test/parallel/test-net-reconnect.js b/test/parallel/test-net-reconnect.js index b2e8f6ea8b4e3f..f8cdcbdc4e76dd 100644 --- a/test/parallel/test-net-reconnect.js +++ b/test/parallel/test-net-reconnect.js @@ -5,7 +5,6 @@ var assert = require('assert'); var net = require('net'); var N = 50; -var c = 0; var client_recv_count = 0; var client_end_count = 0; var disconnect_count = 0; diff --git a/test/parallel/test-net-server-connections.js b/test/parallel/test-net-server-connections.js index 138a78defb260d..ae89d9aac7b3f7 100644 --- a/test/parallel/test-net-server-connections.js +++ b/test/parallel/test-net-server-connections.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var net = require('net'); diff --git a/test/parallel/test-net-server-unref-persistent.js b/test/parallel/test-net-server-unref-persistent.js index a071b625ef26d7..8e8f45f5fd7d20 100644 --- a/test/parallel/test-net-server-unref-persistent.js +++ b/test/parallel/test-net-server-unref-persistent.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var net = require('net'); var closed = false; diff --git a/test/parallel/test-net-socket-local-address.js b/test/parallel/test-net-socket-local-address.js index 502c2d226d54b8..7e90bd2f79ba47 100644 --- a/test/parallel/test-net-socket-local-address.js +++ b/test/parallel/test-net-socket-local-address.js @@ -15,7 +15,7 @@ var serverRemotePorts = []; const server = net.createServer(function(socket) { serverRemotePorts.push(socket.remotePort); - conns++; + testConnect(); }); const client = new net.Socket(); @@ -29,7 +29,12 @@ server.on('close', common.mustCall(function() { server.listen(common.PORT, common.localhostIPv4, testConnect); function testConnect() { - if (conns == 2) { + if (conns > serverRemotePorts.length || conns > clientLocalPorts.length) { + // We're waiting for a callback to fire. + return; + } + + if (conns === 2) { return server.close(); } client.connect(common.PORT, common.localhostIPv4, function() { @@ -37,4 +42,5 @@ function testConnect() { this.once('close', testConnect); this.destroy(); }); + conns++; } diff --git a/test/parallel/test-next-tick-domain.js b/test/parallel/test-next-tick-domain.js index 4d53bba6c4f5cc..8f9d9bb4aa50f7 100644 --- a/test/parallel/test-next-tick-domain.js +++ b/test/parallel/test-next-tick-domain.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var origNextTick = process.nextTick; diff --git a/test/parallel/test-next-tick-errors.js b/test/parallel/test-next-tick-errors.js index eccd7a43a0825f..7c511b8d5e18ab 100644 --- a/test/parallel/test-next-tick-errors.js +++ b/test/parallel/test-next-tick-errors.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var order = [], diff --git a/test/parallel/test-next-tick-intentional-starvation.js b/test/parallel/test-next-tick-intentional-starvation.js index d4a8a1b7481329..414524e5405ecc 100644 --- a/test/parallel/test-next-tick-intentional-starvation.js +++ b/test/parallel/test-next-tick-intentional-starvation.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); // this is the inverse of test-next-tick-starvation. diff --git a/test/parallel/test-next-tick-ordering.js b/test/parallel/test-next-tick-ordering.js index c2b936a1061d52..63f8d37828e53c 100644 --- a/test/parallel/test-next-tick-ordering.js +++ b/test/parallel/test-next-tick-ordering.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var i; diff --git a/test/parallel/test-next-tick-ordering2.js b/test/parallel/test-next-tick-ordering2.js index 4252d623679f65..70f7611dbaddae 100644 --- a/test/parallel/test-next-tick-ordering2.js +++ b/test/parallel/test-next-tick-ordering2.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var order = []; diff --git a/test/parallel/test-next-tick.js b/test/parallel/test-next-tick.js index 54e7b88cf022ca..8b45e8c705fc84 100644 --- a/test/parallel/test-next-tick.js +++ b/test/parallel/test-next-tick.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var complete = 0; diff --git a/test/parallel/test-path-zero-length-strings.js b/test/parallel/test-path-zero-length-strings.js index 083eb3e7ac03c6..07de030aa0b323 100644 --- a/test/parallel/test-path-zero-length-strings.js +++ b/test/parallel/test-path-zero-length-strings.js @@ -5,7 +5,7 @@ // directory. This test makes sure that the behaviour is intact between commits. // See: https://github.com/nodejs/node/pull/2106 -const common = require('../common'); +require('../common'); const assert = require('assert'); const path = require('path'); const pwd = process.cwd(); diff --git a/test/parallel/test-pipe-return-val.js b/test/parallel/test-pipe-return-val.js index 718d052cd24c27..eab5db8f70cf92 100644 --- a/test/parallel/test-pipe-return-val.js +++ b/test/parallel/test-pipe-return-val.js @@ -1,10 +1,9 @@ 'use strict'; // This test ensures SourceStream.pipe(DestStream) returns DestStream -var common = require('../common'); +require('../common'); var Stream = require('stream').Stream; var assert = require('assert'); -var util = require('util'); var sourceStream = new Stream(); var destStream = new Stream(); diff --git a/test/parallel/test-preload.js b/test/parallel/test-preload.js index b4a3af78d8df3b..f30ad1d218e645 100644 --- a/test/parallel/test-preload.js +++ b/test/parallel/test-preload.js @@ -1,6 +1,6 @@ 'use strict'; -var common = require('../common'), - assert = require('assert'), +require('../common'); +var assert = require('assert'), path = require('path'), child_process = require('child_process'); @@ -82,7 +82,6 @@ child_process.exec(nodeBinary + ' ' }); // https://github.com/nodejs/node/issues/1691 -var originalCwd = process.cwd(); process.chdir(path.join(__dirname, '../fixtures/')); child_process.exec(nodeBinary + ' ' + '--expose_debug_as=v8debug ' diff --git a/test/parallel/test-process-before-exit.js b/test/parallel/test-process-before-exit.js index eff96da98e4729..5d8855869a8e4a 100644 --- a/test/parallel/test-process-before-exit.js +++ b/test/parallel/test-process-before-exit.js @@ -1,6 +1,6 @@ 'use strict'; +require('../common'); var assert = require('assert'); -var common = require('../common'); var N = 5; var n = 0; diff --git a/test/parallel/test-process-config.js b/test/parallel/test-process-config.js index 4fc3bcaa98afc8..cedd773dfbeaeb 100644 --- a/test/parallel/test-process-config.js +++ b/test/parallel/test-process-config.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var fs = require('fs'); var path = require('path'); diff --git a/test/parallel/test-process-env.js b/test/parallel/test-process-env.js index 7e927d09bae668..932bae3f8ff095 100644 --- a/test/parallel/test-process-env.js +++ b/test/parallel/test-process-env.js @@ -4,7 +4,7 @@ // first things first, set the timezone; see tzset(3) process.env.TZ = 'Europe/Amsterdam'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var spawn = require('child_process').spawn; diff --git a/test/parallel/test-process-exit-code.js b/test/parallel/test-process-exit-code.js index fea8c2d4fcdc5d..8d657528d05561 100644 --- a/test/parallel/test-process-exit-code.js +++ b/test/parallel/test-process-exit-code.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); switch (process.argv[2]) { diff --git a/test/parallel/test-process-exit.js b/test/parallel/test-process-exit.js index 999eefc1eff518..0ea36f158eaf9b 100644 --- a/test/parallel/test-process-exit.js +++ b/test/parallel/test-process-exit.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); // calling .exit() from within "exit" should not overflow the call stack diff --git a/test/parallel/test-process-getgroups.js b/test/parallel/test-process-getgroups.js index b18b5a0f2f90d4..08eab8d5a8afe2 100644 --- a/test/parallel/test-process-getgroups.js +++ b/test/parallel/test-process-getgroups.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var exec = require('child_process').exec; diff --git a/test/parallel/test-process-hrtime.js b/test/parallel/test-process-hrtime.js index 0e2c5b110e9292..ad186a3507d1e7 100644 --- a/test/parallel/test-process-hrtime.js +++ b/test/parallel/test-process-hrtime.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); // the default behavior, return an Array "tuple" of numbers diff --git a/test/parallel/test-process-kill-null.js b/test/parallel/test-process-kill-null.js index 65dab752f12e6d..2516773f08786a 100644 --- a/test/parallel/test-process-kill-null.js +++ b/test/parallel/test-process-kill-null.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var spawn = require('child_process').spawn; diff --git a/test/parallel/test-process-kill-pid.js b/test/parallel/test-process-kill-pid.js index f193e979166da7..5c11be2903c4a7 100644 --- a/test/parallel/test-process-kill-pid.js +++ b/test/parallel/test-process-kill-pid.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); // test variants of pid diff --git a/test/parallel/test-process-next-tick.js b/test/parallel/test-process-next-tick.js index e7b5f8f3fe886e..6b20cfbe93377b 100644 --- a/test/parallel/test-process-next-tick.js +++ b/test/parallel/test-process-next-tick.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var N = 2; var tickCount = 0; diff --git a/test/parallel/test-process-raw-debug.js b/test/parallel/test-process-raw-debug.js index f849457d643894..ab461902911a93 100644 --- a/test/parallel/test-process-raw-debug.js +++ b/test/parallel/test-process-raw-debug.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var os = require('os'); diff --git a/test/parallel/test-process-release.js b/test/parallel/test-process-release.js index af21daf78b61b2..aac7009f2e90b8 100644 --- a/test/parallel/test-process-release.js +++ b/test/parallel/test-process-release.js @@ -1,5 +1,5 @@ 'use strict'; -const common = require('../common'); +require('../common'); const assert = require('assert'); const versionParts = process.versions.node.split('.'); diff --git a/test/parallel/test-process-wrap.js b/test/parallel/test-process-wrap.js index bf3dfe4e8b1651..b5d4dc35e4fe00 100644 --- a/test/parallel/test-process-wrap.js +++ b/test/parallel/test-process-wrap.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var Process = process.binding('process_wrap').Process; var Pipe = process.binding('pipe_wrap').Pipe; diff --git a/test/parallel/test-promises-unhandled-rejections.js b/test/parallel/test-promises-unhandled-rejections.js index e229bada3a10e2..5e7739daa5b406 100644 --- a/test/parallel/test-promises-unhandled-rejections.js +++ b/test/parallel/test-promises-unhandled-rejections.js @@ -185,12 +185,11 @@ asyncTest('When re-throwing new errors in a promise catch, only the' + asyncTest('Test params of unhandledRejection for a synchronously-rejected' + 'promise', function(done) { var e = new Error(); - var e2 = new Error(); onUnhandledSucceed(done, function(reason, promise) { assert.strictEqual(e, reason); assert.strictEqual(promise, promise); }); - var promise = Promise.reject(e); + Promise.reject(e); }); asyncTest('When re-throwing new errors in a promise catch, only the ' + @@ -629,7 +628,7 @@ asyncTest('Promise unhandledRejection handler does not interfere with domain' + assert.strictEqual(domainReceivedError, domainError); d.dispose(); }); - var a = Promise.reject(e); + Promise.reject(e); process.nextTick(function() { throw domainError; }); diff --git a/test/parallel/test-punycode.js b/test/parallel/test-punycode.js index 179bca51ec2fe0..42927549eae395 100644 --- a/test/parallel/test-punycode.js +++ b/test/parallel/test-punycode.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var punycode = require('punycode'); var assert = require('assert'); diff --git a/test/parallel/test-querystring-multichar-separator.js b/test/parallel/test-querystring-multichar-separator.js index 257492659bdfde..488b5ac56aefa0 100644 --- a/test/parallel/test-querystring-multichar-separator.js +++ b/test/parallel/test-querystring-multichar-separator.js @@ -1,5 +1,5 @@ 'use strict'; -const common = require('../common'); +require('../common'); const assert = require('assert'); const qs = require('querystring'); diff --git a/test/parallel/test-querystring.js b/test/parallel/test-querystring.js index 66497ac2d3b6db..bb3c361f882a14 100644 --- a/test/parallel/test-querystring.js +++ b/test/parallel/test-querystring.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); // test using assert diff --git a/test/parallel/test-readdouble.js b/test/parallel/test-readdouble.js index c0dab8956593fe..6c55a65007aa88 100644 --- a/test/parallel/test-readdouble.js +++ b/test/parallel/test-readdouble.js @@ -2,7 +2,7 @@ /* * Tests to verify we're reading in doubles correctly */ -var common = require('../common'); +require('../common'); var ASSERT = require('assert'); /* diff --git a/test/parallel/test-readfloat.js b/test/parallel/test-readfloat.js index 5572bbf18e291b..468faf76029613 100644 --- a/test/parallel/test-readfloat.js +++ b/test/parallel/test-readfloat.js @@ -2,7 +2,7 @@ /* * Tests to verify we're reading in floats correctly */ -var common = require('../common'); +require('../common'); var ASSERT = require('assert'); /* diff --git a/test/parallel/test-readint.js b/test/parallel/test-readint.js index 233128d792d068..b3997f74f17721 100644 --- a/test/parallel/test-readint.js +++ b/test/parallel/test-readint.js @@ -2,7 +2,7 @@ /* * Tests to verify we're reading in signed integers correctly */ -var common = require('../common'); +require('../common'); var ASSERT = require('assert'); /* diff --git a/test/parallel/test-readline-keys.js b/test/parallel/test-readline-keys.js index 5cac38a1d7db42..e026c0b583cd9e 100644 --- a/test/parallel/test-readline-keys.js +++ b/test/parallel/test-readline-keys.js @@ -1,6 +1,5 @@ 'use strict'; require('../common'); -var EventEmitter = require('events').EventEmitter; var PassThrough = require('stream').PassThrough; var assert = require('assert'); var inherits = require('util').inherits; @@ -16,7 +15,7 @@ inherits(FakeInput, PassThrough); var fi = new FakeInput(); var fo = new FakeInput(); -var rli = new Interface({ input: fi, output: fo, terminal: true }); +new Interface({ input: fi, output: fo, terminal: true }); var keys = []; fi.on('keypress', function(s, k) { diff --git a/test/parallel/test-readline-undefined-columns.js b/test/parallel/test-readline-undefined-columns.js index 73945af8bc52b9..24f138f46bce11 100644 --- a/test/parallel/test-readline-undefined-columns.js +++ b/test/parallel/test-readline-undefined-columns.js @@ -11,7 +11,7 @@ const readline = require('readline'); const iStream = new PassThrough(); const oStream = new PassThrough(); -const rli = readline.createInterface({ +readline.createInterface({ terminal: true, input: iStream, output: oStream, diff --git a/test/parallel/test-readuint.js b/test/parallel/test-readuint.js index b984541bfe9eb0..154af1841a98cd 100644 --- a/test/parallel/test-readuint.js +++ b/test/parallel/test-readuint.js @@ -3,7 +3,7 @@ * A battery of tests to help us read a series of uints */ -var common = require('../common'); +require('../common'); var ASSERT = require('assert'); /* diff --git a/test/parallel/test-ref-unref-return.js b/test/parallel/test-ref-unref-return.js index a82a433ab1af05..89ac52d2bcaa50 100644 --- a/test/parallel/test-ref-unref-return.js +++ b/test/parallel/test-ref-unref-return.js @@ -1,8 +1,8 @@ 'use strict'; +require('../common'); var assert = require('assert'); var net = require('net'); var dgram = require('dgram'); -var common = require('../common'); assert.ok((new net.Server()).ref() instanceof net.Server); assert.ok((new net.Server()).unref() instanceof net.Server); diff --git a/test/parallel/test-regress-GH-4256.js b/test/parallel/test-regress-GH-4256.js index 1a4a78b3c0781d..a312fb277fdad5 100644 --- a/test/parallel/test-regress-GH-4256.js +++ b/test/parallel/test-regress-GH-4256.js @@ -1,6 +1,6 @@ 'use strict'; require('../common'); process.domain = null; -var timer = setTimeout(function() { +setTimeout(function() { console.log('this console.log statement should not make node crash'); }, 1); diff --git a/test/parallel/test-regress-GH-6235.js b/test/parallel/test-regress-GH-6235.js index 2f2f17d9698fc9..0bf9b8965d1184 100644 --- a/test/parallel/test-regress-GH-6235.js +++ b/test/parallel/test-regress-GH-6235.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); assert.doesNotThrow(function() { diff --git a/test/parallel/test-regress-GH-7511.js b/test/parallel/test-regress-GH-7511.js index 0e5c4ded011a43..03813dea003eaf 100644 --- a/test/parallel/test-regress-GH-7511.js +++ b/test/parallel/test-regress-GH-7511.js @@ -1,6 +1,6 @@ 'use strict'; -var common = require('../common'), - assert = require('assert'), +require('../common'); +var assert = require('assert'), vm = require('vm'); assert.doesNotThrow(function() { diff --git a/test/parallel/test-regress-GH-897.js b/test/parallel/test-regress-GH-897.js index 4b7ba61f9ceca9..1b46994dc37d94 100644 --- a/test/parallel/test-regress-GH-897.js +++ b/test/parallel/test-regress-GH-897.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var t = Date.now(); diff --git a/test/parallel/test-repl-.save.load.js b/test/parallel/test-repl-.save.load.js index f63b61bf41e15b..6d28015b385e15 100644 --- a/test/parallel/test-repl-.save.load.js +++ b/test/parallel/test-repl-.save.load.js @@ -1,6 +1,5 @@ 'use strict'; var assert = require('assert'); -var util = require('util'); var join = require('path').join; var fs = require('fs'); var common = require('../common'); @@ -9,24 +8,9 @@ common.refreshTmpDir(); var repl = require('repl'); -// A stream to push an array into a REPL -function ArrayStream() { - this.run = function(data) { - var self = this; - data.forEach(function(line) { - self.emit('data', line + '\n'); - }); - }; -} -util.inherits(ArrayStream, require('stream').Stream); -ArrayStream.prototype.readable = true; -ArrayStream.prototype.writable = true; -ArrayStream.prototype.resume = function() {}; -ArrayStream.prototype.write = function() {}; - var works = [['inner.one'], 'inner.o']; -var putIn = new ArrayStream(); +const putIn = new common.ArrayStream(); var testMe = repl.start('', putIn); @@ -76,6 +60,14 @@ putIn.write = function(data) { }; putIn.run(['.load ' + loadFile]); +// throw error on loading directory +loadFile = common.tmpDir; +putIn.write = function(data) { + assert.equal(data, 'Failed to load:' + loadFile + ' is not a valid file\n'); + putIn.write = function() {}; +}; +putIn.run(['.load ' + loadFile]); + // clear the REPL putIn.run(['.clear']); diff --git a/test/parallel/test-repl-autolibs.js b/test/parallel/test-repl-autolibs.js index e37f2d036ece4d..15f779d3b12269 100644 --- a/test/parallel/test-repl-autolibs.js +++ b/test/parallel/test-repl-autolibs.js @@ -1,26 +1,14 @@ -/* eslint-disable required-modules */ 'use strict'; +const common = require('../common'); var assert = require('assert'); var util = require('util'); var repl = require('repl'); -// A stream to push an array into a REPL -function ArrayStream() { - this.run = function(data) { - var self = this; - data.forEach(function(line) { - self.emit('data', line + '\n'); - }); - }; -} -util.inherits(ArrayStream, require('stream').Stream); -ArrayStream.prototype.readable = true; -ArrayStream.prototype.writable = true; -ArrayStream.prototype.resume = function() {}; -ArrayStream.prototype.write = function() {}; +// This test adds global variables +common.globalCheck = false; -var putIn = new ArrayStream(); -var testMe = repl.start('', putIn, null, true); +const putIn = new common.ArrayStream(); +repl.start('', putIn, null, true); test1(); diff --git a/test/parallel/test-repl-console.js b/test/parallel/test-repl-console.js index e66fcb1621adc5..fe737d841e1651 100644 --- a/test/parallel/test-repl-console.js +++ b/test/parallel/test-repl-console.js @@ -1,13 +1,10 @@ 'use strict'; var common = require('../common'), assert = require('assert'), - Stream = require('stream'), repl = require('repl'); -// create a dummy stream that does nothing -var stream = new Stream(); -stream.write = stream.pause = stream.resume = function() {}; -stream.readable = stream.writable = true; +// Create a dummy stream that does nothing +const stream = new common.ArrayStream(); var r = repl.start({ input: stream, diff --git a/test/parallel/test-repl-domain.js b/test/parallel/test-repl-domain.js index 7528f502878f63..adc8478beef4af 100644 --- a/test/parallel/test-repl-domain.js +++ b/test/parallel/test-repl-domain.js @@ -1,27 +1,10 @@ 'use strict'; -var assert = require('assert'); var common = require('../common'); -var util = require('util'); var repl = require('repl'); -// A stream to push an array into a REPL -function ArrayStream() { - this.run = function(data) { - var self = this; - data.forEach(function(line) { - self.emit('data', line + '\n'); - }); - }; -} -util.inherits(ArrayStream, require('stream').Stream); -ArrayStream.prototype.readable = true; -ArrayStream.prototype.writable = true; -ArrayStream.prototype.resume = function() {}; -ArrayStream.prototype.write = function() {}; - -var putIn = new ArrayStream(); -var testMe = repl.start('', putIn); +const putIn = new common.ArrayStream(); +repl.start('', putIn); putIn.write = function(data) { // Don't use assert for this because the domain might catch it, and diff --git a/test/parallel/test-repl-end-emits-exit.js b/test/parallel/test-repl-end-emits-exit.js index e4bc4da78c142d..2c18b413d68c0f 100644 --- a/test/parallel/test-repl-end-emits-exit.js +++ b/test/parallel/test-repl-end-emits-exit.js @@ -1,15 +1,12 @@ 'use strict'; var common = require('../common'), assert = require('assert'), - Stream = require('stream'), repl = require('repl'), terminalExit = 0, regularExit = 0; -// create a dummy stream that does nothing -var stream = new Stream(); -stream.write = stream.pause = stream.resume = function() {}; -stream.readable = stream.writable = true; +// Create a dummy stream that does nothing +const stream = new common.ArrayStream(); function testTerminalMode() { var r1 = repl.start({ diff --git a/test/parallel/test-repl-envvars.js b/test/parallel/test-repl-envvars.js index 6073144085843d..2c34bbf2da86fa 100644 --- a/test/parallel/test-repl-envvars.js +++ b/test/parallel/test-repl-envvars.js @@ -2,7 +2,7 @@ // Flags: --expose-internals -const common = require('../common'); +require('../common'); const stream = require('stream'); const REPL = require('internal/repl'); const assert = require('assert'); diff --git a/test/parallel/test-repl-harmony.js b/test/parallel/test-repl-harmony.js index 6bc5cb57aa1187..a5928800381cfe 100644 --- a/test/parallel/test-repl-harmony.js +++ b/test/parallel/test-repl-harmony.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var spawn = require('child_process').spawn; diff --git a/test/parallel/test-repl-options.js b/test/parallel/test-repl-options.js index 5bc37d2d7117f3..ec3b144ec0ef77 100644 --- a/test/parallel/test-repl-options.js +++ b/test/parallel/test-repl-options.js @@ -1,15 +1,12 @@ 'use strict'; var common = require('../common'), assert = require('assert'), - Stream = require('stream'), repl = require('repl'); common.globalCheck = false; -// create a dummy stream that does nothing -var stream = new Stream(); -stream.write = stream.pause = stream.resume = function() {}; -stream.readable = stream.writable = true; +// Create a dummy stream that does nothing +const stream = new common.ArrayStream(); // 1, mostly defaults var r1 = repl.start({ diff --git a/test/sequential/test-repl-persistent-history.js b/test/parallel/test-repl-persistent-history.js similarity index 92% rename from test/sequential/test-repl-persistent-history.js rename to test/parallel/test-repl-persistent-history.js index 10e0dedf53ec3e..7571527b73800d 100644 --- a/test/sequential/test-repl-persistent-history.js +++ b/test/parallel/test-repl-persistent-history.js @@ -7,7 +7,6 @@ const stream = require('stream'); const REPL = require('internal/repl'); const assert = require('assert'); const fs = require('fs'); -const util = require('util'); const path = require('path'); const os = require('os'); @@ -66,6 +65,10 @@ const homedirErr = '\nError: Could not get the home directory.\n' + 'REPL session history will not be persisted.\n'; const replFailedRead = '\nError: Could not open history file.\n' + 'REPL session history will not be persisted.\n'; +const sameHistoryFilePaths = '\nThe old repl history file has the same name ' + + 'and location as the new one i.e., ' + + path.join(common.tmpDir, '.node_repl_history') + + ' and is empty.\nUsing it as is.\n'; // File paths const fixtures = path.join(common.testDir, 'fixtures'); const historyFixturePath = path.join(fixtures, '.node_repl_history'); @@ -73,9 +76,9 @@ const historyPath = path.join(common.tmpDir, '.fixture_copy_repl_history'); const historyPathFail = path.join(common.tmpDir, '.node_repl\u0000_history'); const oldHistoryPath = path.join(fixtures, 'old-repl-history-file.json'); const enoentHistoryPath = path.join(fixtures, 'enoent-repl-history-file.json'); +const emptyHistoryPath = path.join(fixtures, '.empty-repl-history-file'); const defaultHistoryPath = path.join(common.tmpDir, '.node_repl_history'); - const tests = [{ env: { NODE_REPL_HISTORY: '' }, test: [UP], @@ -93,6 +96,16 @@ const tests = [{ test: [UP], expected: [prompt, replDisabled, prompt] }, +{ + env: { NODE_REPL_HISTORY_FILE: emptyHistoryPath }, + test: [UP], + expected: [prompt, convertMsg, prompt] +}, +{ + env: { NODE_REPL_HISTORY_FILE: defaultHistoryPath }, + test: [UP], + expected: [prompt, sameHistoryFilePaths, prompt] +}, { env: { NODE_REPL_HISTORY: historyPath }, test: [UP, CLEAR], diff --git a/test/parallel/test-repl-require-cache.js b/test/parallel/test-repl-require-cache.js index d9b4d71d484640..c5f317ac268e2f 100644 --- a/test/parallel/test-repl-require-cache.js +++ b/test/parallel/test-repl-require-cache.js @@ -1,6 +1,6 @@ 'use strict'; -var common = require('../common'), - assert = require('assert'), +require('../common'); +var assert = require('assert'), repl = require('repl'); // https://github.com/joyent/node/issues/3226 diff --git a/test/parallel/test-repl-require.js b/test/parallel/test-repl-require.js new file mode 100644 index 00000000000000..e8e5e34190c464 --- /dev/null +++ b/test/parallel/test-repl-require.js @@ -0,0 +1,33 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const net = require('net'); + +process.chdir(common.fixturesDir); +const repl = require('repl'); + +const server = net.createServer(conn => { + repl.start('', conn).on('exit', () => { + conn.destroy(); + server.close(); + }); +}); + +const host = common.localhostIPv4; +const port = common.PORT; +const options = { host, port }; + +var answer = ''; +server.listen(options, function() { + const conn = net.connect(options); + conn.setEncoding('utf8'); + conn.on('data', data => answer += data); + conn.write('require("baz")\n.exit\n'); +}); + +process.on('exit', function() { + assert.strictEqual(false, /Cannot find module/.test(answer)); + assert.strictEqual(false, /Error/.test(answer)); + assert.strictEqual(true, /eye catcher/.test(answer)); +}); diff --git a/test/parallel/test-repl-reset-event.js b/test/parallel/test-repl-reset-event.js index e6d4eed1385b10..0bd43dcd6c370e 100644 --- a/test/parallel/test-repl-reset-event.js +++ b/test/parallel/test-repl-reset-event.js @@ -4,12 +4,9 @@ common.globalCheck = false; var assert = require('assert'); var repl = require('repl'); -var Stream = require('stream'); -// create a dummy stream that does nothing -var dummy = new Stream(); -dummy.write = dummy.pause = dummy.resume = function() {}; -dummy.readable = dummy.writable = true; +// Create a dummy stream that does nothing +const dummy = new common.ArrayStream(); function testReset(cb) { var r = repl.start({ diff --git a/test/parallel/test-repl-setprompt.js b/test/parallel/test-repl-setprompt.js index f2c65583b3656b..2708a3e6af5448 100644 --- a/test/parallel/test-repl-setprompt.js +++ b/test/parallel/test-repl-setprompt.js @@ -1,5 +1,5 @@ 'use strict'; -const common = require('../common'); +require('../common'); const assert = require('assert'); const spawn = require('child_process').spawn; const os = require('os'); diff --git a/test/parallel/test-repl-syntax-error-handling.js b/test/parallel/test-repl-syntax-error-handling.js index 66e8fb6b352c56..10166b4f06a692 100644 --- a/test/parallel/test-repl-syntax-error-handling.js +++ b/test/parallel/test-repl-syntax-error-handling.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); switch (process.argv[2]) { diff --git a/test/parallel/test-repl-syntax-error-stack.js b/test/parallel/test-repl-syntax-error-stack.js new file mode 100644 index 00000000000000..ebf0b2e4d8aed1 --- /dev/null +++ b/test/parallel/test-repl-syntax-error-stack.js @@ -0,0 +1,26 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const path = require('path'); +const repl = require('repl'); +let found = false; + +process.on('exit', () => { + assert.strictEqual(found, true); +}); + +common.ArrayStream.prototype.write = function(output) { + if (/var foo bar;/.test(output)) + found = true; +}; + +const putIn = new common.ArrayStream(); +repl.start('', putIn); +let file = path.resolve(__dirname, '../fixtures/syntax/bad_syntax'); + +if (common.isWindows) + file = file.replace(/\\/g, '\\\\'); + +putIn.run(['.clear']); +putIn.run([`require('${file}');`]); diff --git a/test/parallel/test-repl-tab-complete-crash.js b/test/parallel/test-repl-tab-complete-crash.js index 85ab0577eb8601..ce283757438192 100644 --- a/test/parallel/test-repl-tab-complete-crash.js +++ b/test/parallel/test-repl-tab-complete-crash.js @@ -1,32 +1,18 @@ 'use strict'; -require('../common'); +const common = require('../common'); const assert = require('assert'); -const util = require('util'); const repl = require('repl'); var referenceErrorCount = 0; -// A stream to push an array into a REPL -function ArrayStream() { - this.run = function(data) { - const self = this; - data.forEach(function(line) { - self.emit('data', line + '\n'); - }); - }; -} -util.inherits(ArrayStream, require('stream').Stream); -ArrayStream.prototype.readable = true; -ArrayStream.prototype.writable = true; -ArrayStream.prototype.resume = function() {}; -ArrayStream.prototype.write = function(msg) { +common.ArrayStream.prototype.write = function(msg) { if (msg.startsWith('ReferenceError: ')) { referenceErrorCount++; } }; -const putIn = new ArrayStream(); +const putIn = new common.ArrayStream(); const testMe = repl.start('', putIn); // https://github.com/nodejs/node/issues/3346 diff --git a/test/parallel/test-repl-tab-complete.js b/test/parallel/test-repl-tab-complete.js index 1cb6e7791d3c2b..86a0444c953d27 100644 --- a/test/parallel/test-repl-tab-complete.js +++ b/test/parallel/test-repl-tab-complete.js @@ -4,7 +4,6 @@ var common = require('../common'); var assert = require('assert'); -var util = require('util'); var repl = require('repl'); var referenceErrors = 0; var expectedReferenceErrors = 0; @@ -20,23 +19,8 @@ process.on('exit', function() { assert.strictEqual(referenceErrors, expectedReferenceErrors); }); -// A stream to push an array into a REPL -function ArrayStream() { - this.run = function(data) { - var self = this; - data.forEach(function(line) { - self.emit('data', line + '\n'); - }); - }; -} -util.inherits(ArrayStream, require('stream').Stream); -ArrayStream.prototype.readable = true; -ArrayStream.prototype.writable = true; -ArrayStream.prototype.resume = function() {}; -ArrayStream.prototype.write = function() {}; - var works = [['inner.one'], 'inner.o']; -var putIn = new ArrayStream(); +const putIn = new common.ArrayStream(); var testMe = repl.start('', putIn); // Some errors are passed to the domain, but do not callback diff --git a/test/parallel/test-repl-tab.js b/test/parallel/test-repl-tab.js index 1ab3b4743913bd..6474d8e4088167 100644 --- a/test/parallel/test-repl-tab.js +++ b/test/parallel/test-repl-tab.js @@ -1,7 +1,6 @@ 'use strict'; require('../common'); var assert = require('assert'); -var util = require('util'); var repl = require('repl'); var zlib = require('zlib'); diff --git a/test/parallel/test-repl-unexpected-token-recoverable.js b/test/parallel/test-repl-unexpected-token-recoverable.js index 4cfaa5136b6a55..84668c8657c453 100644 --- a/test/parallel/test-repl-unexpected-token-recoverable.js +++ b/test/parallel/test-repl-unexpected-token-recoverable.js @@ -2,7 +2,7 @@ /* * This is a regression test for https://github.com/joyent/node/issues/8874. */ -var common = require('../common'); +require('../common'); var assert = require('assert'); var spawn = require('child_process').spawn; diff --git a/test/parallel/test-repl.js b/test/parallel/test-repl.js index 4d65a1e9d084b4..0d05de9bc1863d 100644 --- a/test/parallel/test-repl.js +++ b/test/parallel/test-repl.js @@ -278,6 +278,10 @@ function error_test() { expect: 'undefined\n' + prompt_unix }, { client: client_unix, send: '/* \'\n"\n\'"\'\n*/', expect: 'undefined\n' + prompt_unix }, + // REPL should get a normal require() function, not one that allows + // access to internal modules without the --expose_internals flag. + { client: client_unix, send: 'require("internal/repl")', + expect: /^Error: Cannot find module 'internal\/repl'/ }, ]); } diff --git a/test/parallel/test-require-cache.js b/test/parallel/test-require-cache.js index f2245345e3e4bd..7ea68dd0515799 100644 --- a/test/parallel/test-require-cache.js +++ b/test/parallel/test-require-cache.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); (function testInjectFakeModule() { diff --git a/test/parallel/test-require-extensions-main.js b/test/parallel/test-require-extensions-main.js index 198fa6a8c52d37..0376082262dd78 100644 --- a/test/parallel/test-require-extensions-main.js +++ b/test/parallel/test-require-extensions-main.js @@ -1,5 +1,4 @@ 'use strict'; var common = require('../common'); -var assert = require('assert'); require(common.fixturesDir + '/require-bin/bin/req.js'); diff --git a/test/parallel/test-require-long-path.js b/test/parallel/test-require-long-path.js index 1f7e28cba2960c..c30a76a5a9e099 100644 --- a/test/parallel/test-require-long-path.js +++ b/test/parallel/test-require-long-path.js @@ -3,6 +3,11 @@ const common = require('../common'); const fs = require('fs'); const path = require('path'); +if (!common.isWindows) { + console.log('1..0 # Skipped: this test is Windows-specific.'); + return; +} + // make a path that is more than 260 chars long. const dirNameLen = Math.max(260 - common.tmpDir.length, 1); const dirName = path.join(common.tmpDir, 'x'.repeat(dirNameLen)); diff --git a/test/parallel/test-signal-safety.js b/test/parallel/test-signal-safety.js index 549c26662f717a..7938ae04d6591b 100644 --- a/test/parallel/test-signal-safety.js +++ b/test/parallel/test-signal-safety.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var Signal = process.binding('signal_wrap').Signal; diff --git a/test/parallel/test-stdin-hang.js b/test/parallel/test-stdin-hang.js index 4818a9ee952026..bb43d52506e5dc 100644 --- a/test/parallel/test-stdin-hang.js +++ b/test/parallel/test-stdin-hang.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); // This test *only* verifies that invoking the stdin getter does not // cause node to hang indefinitely. diff --git a/test/parallel/test-stdio-readable-writable.js b/test/parallel/test-stdio-readable-writable.js index f8a8923498cb03..7b9b69d309aec5 100644 --- a/test/parallel/test-stdio-readable-writable.js +++ b/test/parallel/test-stdio-readable-writable.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); assert(process.stdout.writable); diff --git a/test/parallel/test-stdout-close-unref.js b/test/parallel/test-stdout-close-unref.js index 12a031562bf6f0..37ab4987eebcaa 100644 --- a/test/parallel/test-stdout-close-unref.js +++ b/test/parallel/test-stdout-close-unref.js @@ -1,6 +1,6 @@ 'use strict'; +require('../common'); var assert = require('assert'); -var common = require('../common'); var errs = 0; diff --git a/test/parallel/test-stream-big-packet.js b/test/parallel/test-stream-big-packet.js index a9f6064c7e7277..67bb32847bd7f7 100644 --- a/test/parallel/test-stream-big-packet.js +++ b/test/parallel/test-stream-big-packet.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var util = require('util'); var stream = require('stream'); diff --git a/test/parallel/test-stream-big-push.js b/test/parallel/test-stream-big-push.js index e02ff98d3c7454..b46665efc94ff5 100644 --- a/test/parallel/test-stream-big-push.js +++ b/test/parallel/test-stream-big-push.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var stream = require('stream'); var str = 'asdfasdfasdfasdfasdf'; diff --git a/test/parallel/test-stream-duplex.js b/test/parallel/test-stream-duplex.js index 0e8789d6bf5555..200de24877bf79 100644 --- a/test/parallel/test-stream-duplex.js +++ b/test/parallel/test-stream-duplex.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var Duplex = require('stream').Transform; diff --git a/test/parallel/test-stream-end-paused.js b/test/parallel/test-stream-end-paused.js index 585d6c327fd592..9cc32db880ea88 100644 --- a/test/parallel/test-stream-end-paused.js +++ b/test/parallel/test-stream-end-paused.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var gotEnd = false; diff --git a/test/parallel/test-stream-ispaused.js b/test/parallel/test-stream-ispaused.js index 8112dc733a7205..38f8da3fd512e4 100644 --- a/test/parallel/test-stream-ispaused.js +++ b/test/parallel/test-stream-ispaused.js @@ -1,6 +1,6 @@ 'use strict'; +require('../common'); var assert = require('assert'); -var common = require('../common'); var stream = require('stream'); diff --git a/test/parallel/test-stream-pipe-after-end.js b/test/parallel/test-stream-pipe-after-end.js index 4bead73f68ce5b..258c9330a96018 100644 --- a/test/parallel/test-stream-pipe-after-end.js +++ b/test/parallel/test-stream-pipe-after-end.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var Readable = require('_stream_readable'); diff --git a/test/parallel/test-stream-pipe-cleanup-pause.js b/test/parallel/test-stream-pipe-cleanup-pause.js index b38f57a4ff0ba1..332930c813a3dd 100644 --- a/test/parallel/test-stream-pipe-cleanup-pause.js +++ b/test/parallel/test-stream-pipe-cleanup-pause.js @@ -1,6 +1,5 @@ 'use strict'; const common = require('../common'); -const assert = require('assert'); const stream = require('stream'); const reader = new stream.Readable(); diff --git a/test/parallel/test-stream-pipe-cleanup.js b/test/parallel/test-stream-pipe-cleanup.js index 08da96f92c3a0f..251695c9f723ab 100644 --- a/test/parallel/test-stream-pipe-cleanup.js +++ b/test/parallel/test-stream-pipe-cleanup.js @@ -2,7 +2,7 @@ // This test asserts that Stream.prototype.pipe does not leave listeners // hanging on the source or dest. -var common = require('../common'); +require('../common'); var stream = require('stream'); var assert = require('assert'); var util = require('util'); diff --git a/test/parallel/test-stream-pipe-error-handling.js b/test/parallel/test-stream-pipe-error-handling.js index 031a0da7e395db..88a70fb58e2cf1 100644 --- a/test/parallel/test-stream-pipe-error-handling.js +++ b/test/parallel/test-stream-pipe-error-handling.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var Stream = require('stream').Stream; @@ -38,7 +38,6 @@ var Stream = require('stream').Stream; })(); (function testErrorWithRemovedListenerThrows() { - var EE = require('events').EventEmitter; var R = Stream.Readable; var W = Stream.Writable; @@ -73,7 +72,6 @@ var Stream = require('stream').Stream; })(); (function testErrorWithRemovedListenerThrows() { - var EE = require('events').EventEmitter; var R = Stream.Readable; var W = Stream.Writable; diff --git a/test/parallel/test-stream-pipe-event.js b/test/parallel/test-stream-pipe-event.js index 0d10533b0c496a..d8601dd04a4d8e 100644 --- a/test/parallel/test-stream-pipe-event.js +++ b/test/parallel/test-stream-pipe-event.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var stream = require('stream'); var assert = require('assert'); var util = require('util'); diff --git a/test/parallel/test-stream-push-order.js b/test/parallel/test-stream-push-order.js index d67233aff7a498..f09cf95f370bce 100644 --- a/test/parallel/test-stream-push-order.js +++ b/test/parallel/test-stream-push-order.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var Readable = require('stream').Readable; var assert = require('assert'); @@ -21,7 +21,7 @@ s._read = function(n) { } }; -var v = s.read(0); +s.read(0); // ACTUALLY [1, 3, 5, 6, 4, 2] diff --git a/test/parallel/test-stream-push-strings.js b/test/parallel/test-stream-push-strings.js index 0d9c0653c0dc66..21621ff3fd114f 100644 --- a/test/parallel/test-stream-push-strings.js +++ b/test/parallel/test-stream-push-strings.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var Readable = require('stream').Readable; diff --git a/test/parallel/test-stream-readable-constructor-set-methods.js b/test/parallel/test-stream-readable-constructor-set-methods.js index 928ce31a8ebe7b..fb2114f44dad19 100644 --- a/test/parallel/test-stream-readable-constructor-set-methods.js +++ b/test/parallel/test-stream-readable-constructor-set-methods.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var Readable = require('stream').Readable; diff --git a/test/parallel/test-stream-readable-event.js b/test/parallel/test-stream-readable-event.js index 965fc82c05a1d9..10d314f4eec254 100644 --- a/test/parallel/test-stream-readable-event.js +++ b/test/parallel/test-stream-readable-event.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var Readable = require('stream').Readable; diff --git a/test/parallel/test-stream-readable-flow-recursion.js b/test/parallel/test-stream-readable-flow-recursion.js index 07edd579f1deea..57e295e5383550 100644 --- a/test/parallel/test-stream-readable-flow-recursion.js +++ b/test/parallel/test-stream-readable-flow-recursion.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); // this test verifies that passing a huge number to read(size) diff --git a/test/parallel/test-stream-transform-constructor-set-methods.js b/test/parallel/test-stream-transform-constructor-set-methods.js index c24c273b6f20e1..bf76b93690c840 100644 --- a/test/parallel/test-stream-transform-constructor-set-methods.js +++ b/test/parallel/test-stream-transform-constructor-set-methods.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var Transform = require('stream').Transform; diff --git a/test/parallel/test-stream-transform-objectmode-falsey-value.js b/test/parallel/test-stream-transform-objectmode-falsey-value.js index 762f0500ad3e60..eeb3d3f4ccc692 100644 --- a/test/parallel/test-stream-transform-objectmode-falsey-value.js +++ b/test/parallel/test-stream-transform-objectmode-falsey-value.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var stream = require('stream'); diff --git a/test/parallel/test-stream-transform-split-objectmode.js b/test/parallel/test-stream-transform-split-objectmode.js index 24833ece051e9e..4e33028da2f7de 100644 --- a/test/parallel/test-stream-transform-split-objectmode.js +++ b/test/parallel/test-stream-transform-split-objectmode.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var Transform = require('stream').Transform; diff --git a/test/parallel/test-stream-unshift-empty-chunk.js b/test/parallel/test-stream-unshift-empty-chunk.js index a7dcad425310b1..0da979e337486e 100644 --- a/test/parallel/test-stream-unshift-empty-chunk.js +++ b/test/parallel/test-stream-unshift-empty-chunk.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); // This test verifies that stream.unshift(Buffer(0)) or diff --git a/test/parallel/test-stream-unshift-read-race.js b/test/parallel/test-stream-unshift-read-race.js index 90f519b5b5d738..8239a380def66c 100644 --- a/test/parallel/test-stream-unshift-read-race.js +++ b/test/parallel/test-stream-unshift-read-race.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); // This test verifies that: @@ -13,7 +13,6 @@ var stream = require('stream'); var hwm = 10; var r = stream.Readable({ highWaterMark: hwm }); var chunks = 10; -var t = (chunks * 5); var data = new Buffer(chunks * hwm + Math.ceil(hwm / 2)); for (var i = 0; i < data.length; i++) { diff --git a/test/parallel/test-stream-wrap.js b/test/parallel/test-stream-wrap.js index e7a7ecddd2385d..5a8b75d4dc1f19 100644 --- a/test/parallel/test-stream-wrap.js +++ b/test/parallel/test-stream-wrap.js @@ -1,5 +1,5 @@ 'use strict'; -const common = require('../common'); +require('../common'); const assert = require('assert'); const StreamWrap = require('_stream_wrap'); diff --git a/test/parallel/test-stream-writable-change-default-encoding.js b/test/parallel/test-stream-writable-change-default-encoding.js index a6fcda3e62a517..d8193123d6f3af 100644 --- a/test/parallel/test-stream-writable-change-default-encoding.js +++ b/test/parallel/test-stream-writable-change-default-encoding.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var stream = require('stream'); diff --git a/test/parallel/test-stream-writable-constructor-set-methods.js b/test/parallel/test-stream-writable-constructor-set-methods.js index 47fc458ce9713b..4a5f90216070c5 100644 --- a/test/parallel/test-stream-writable-constructor-set-methods.js +++ b/test/parallel/test-stream-writable-constructor-set-methods.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var Writable = require('stream').Writable; diff --git a/test/parallel/test-stream-writable-decoded-encoding.js b/test/parallel/test-stream-writable-decoded-encoding.js index b637838c0c65be..b5f1b4f6b73f49 100644 --- a/test/parallel/test-stream-writable-decoded-encoding.js +++ b/test/parallel/test-stream-writable-decoded-encoding.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var stream = require('stream'); diff --git a/test/parallel/test-stream-writev.js b/test/parallel/test-stream-writev.js index f73270f2ff53ba..5b07dd11198e1a 100644 --- a/test/parallel/test-stream-writev.js +++ b/test/parallel/test-stream-writev.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var stream = require('stream'); @@ -30,11 +30,9 @@ function test(decode, uncork, multi, next) { function cnt(msg) { expectCount++; var expect = expectCount; - var called = false; return function(er) { if (er) throw er; - called = true; counter++; assert.equal(counter, expect); }; diff --git a/test/parallel/test-stream2-base64-single-char-read-end.js b/test/parallel/test-stream2-base64-single-char-read-end.js index 2d60877de83662..900e090921b712 100644 --- a/test/parallel/test-stream2-base64-single-char-read-end.js +++ b/test/parallel/test-stream2-base64-single-char-read-end.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var R = require('_stream_readable'); var W = require('_stream_writable'); var assert = require('assert'); diff --git a/test/parallel/test-stream2-compatibility.js b/test/parallel/test-stream2-compatibility.js index 9eab7b713bf167..1ee47c03cf0e01 100644 --- a/test/parallel/test-stream2-compatibility.js +++ b/test/parallel/test-stream2-compatibility.js @@ -1,10 +1,9 @@ 'use strict'; -var common = require('../common'); +require('../common'); var R = require('_stream_readable'); var assert = require('assert'); var util = require('util'); -var EE = require('events').EventEmitter; var ondataCalled = 0; @@ -25,7 +24,7 @@ TestReader.prototype._read = function(n) { this._buffer = new Buffer(0); }; -var reader = new TestReader(); +new TestReader(); setImmediate(function() { assert.equal(ondataCalled, 1); console.log('ok'); diff --git a/test/parallel/test-stream2-finish-pipe.js b/test/parallel/test-stream2-finish-pipe.js index 913bb7b0b4db09..63c78759cab60d 100644 --- a/test/parallel/test-stream2-finish-pipe.js +++ b/test/parallel/test-stream2-finish-pipe.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var stream = require('stream'); var Buffer = require('buffer').Buffer; diff --git a/test/parallel/test-stream2-large-read-stall.js b/test/parallel/test-stream2-large-read-stall.js index 4cd89599fee730..6a38baac5dacbc 100644 --- a/test/parallel/test-stream2-large-read-stall.js +++ b/test/parallel/test-stream2-large-read-stall.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); // If everything aligns so that you do a read(n) of exactly the @@ -53,9 +53,6 @@ function push() { setTimeout(push); } -// start the flow -var ret = r.read(0); - process.on('exit', function() { assert.equal(pushes, PUSHCOUNT + 1); assert(endEmitted); diff --git a/test/parallel/test-stream2-objects.js b/test/parallel/test-stream2-objects.js index a2f554a0b8a004..e67359eff2b29e 100644 --- a/test/parallel/test-stream2-objects.js +++ b/test/parallel/test-stream2-objects.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var Readable = require('_stream_readable'); var Writable = require('_stream_writable'); var assert = require('assert'); @@ -167,8 +167,6 @@ test('read(0) for object streams', function(t) { r.push('foobar'); r.push(null); - var v = r.read(0); - r.pipe(toArray(function(array) { assert.deepEqual(array, ['foobar']); diff --git a/test/parallel/test-stream2-pipe-error-handling.js b/test/parallel/test-stream2-pipe-error-handling.js index 9eddbdd90d00c3..7d7cfb6b2b3307 100644 --- a/test/parallel/test-stream2-pipe-error-handling.js +++ b/test/parallel/test-stream2-pipe-error-handling.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var stream = require('stream'); diff --git a/test/parallel/test-stream2-pipe-error-once-listener.js b/test/parallel/test-stream2-pipe-error-once-listener.js index f2ecb87ce97a75..d046c5ea55e498 100644 --- a/test/parallel/test-stream2-pipe-error-once-listener.js +++ b/test/parallel/test-stream2-pipe-error-once-listener.js @@ -1,6 +1,5 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); +require('../common'); var util = require('util'); var stream = require('stream'); diff --git a/test/parallel/test-stream2-push.js b/test/parallel/test-stream2-push.js index b58bce143585f4..99b73d7277aa52 100644 --- a/test/parallel/test-stream2-push.js +++ b/test/parallel/test-stream2-push.js @@ -1,11 +1,10 @@ 'use strict'; -var common = require('../common'); +require('../common'); var stream = require('stream'); var Readable = stream.Readable; var Writable = stream.Writable; var assert = require('assert'); -var util = require('util'); var EE = require('events').EventEmitter; diff --git a/test/parallel/test-stream2-read-sync-stack.js b/test/parallel/test-stream2-read-sync-stack.js index e912e1039ff558..4bce87ffb9dffd 100644 --- a/test/parallel/test-stream2-read-sync-stack.js +++ b/test/parallel/test-stream2-read-sync-stack.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var Readable = require('stream').Readable; var r = new Readable(); diff --git a/test/parallel/test-stream2-readable-empty-buffer-no-eof.js b/test/parallel/test-stream2-readable-empty-buffer-no-eof.js index 8e4001f8022f1c..18012df3a41d89 100644 --- a/test/parallel/test-stream2-readable-empty-buffer-no-eof.js +++ b/test/parallel/test-stream2-readable-empty-buffer-no-eof.js @@ -1,14 +1,14 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); +const common = require('../common'); +const assert = require('assert'); -var Readable = require('stream').Readable; +const Readable = require('stream').Readable; test1(); test2(); function test1() { - var r = new Readable(); + const r = new Readable(); // should not end when we get a Buffer(0) or '' as the _read result // that just means that there is *temporarily* no data, but to go @@ -20,9 +20,9 @@ function test1() { // r.read(0) again later, otherwise there is no more work being done // and the process just exits. - var buf = new Buffer(5); - buf.fill('x'); - var reads = 5; + const buf = Buffer(5).fill('x'); + let reads = 5; + const timeout = common.platformTimeout(50); r._read = function(n) { switch (reads--) { case 0: @@ -30,15 +30,15 @@ function test1() { case 1: return r.push(buf); case 2: - setTimeout(r.read.bind(r, 0), 50); + setTimeout(r.read.bind(r, 0), timeout); return r.push(new Buffer(0)); // Not-EOF! case 3: - setTimeout(r.read.bind(r, 0), 50); + setTimeout(r.read.bind(r, 0), timeout); return process.nextTick(function() { return r.push(new Buffer(0)); }); case 4: - setTimeout(r.read.bind(r, 0), 50); + setTimeout(r.read.bind(r, 0), timeout); return setTimeout(function() { return r.push(new Buffer(0)); }); @@ -51,9 +51,9 @@ function test1() { } }; - var results = []; + const results = []; function flow() { - var chunk; + let chunk; while (null !== (chunk = r.read())) results.push(chunk + ''); } diff --git a/test/parallel/test-stream2-readable-from-list.js b/test/parallel/test-stream2-readable-from-list.js index a8d9fb38f25090..ab9d9c5d72cae1 100644 --- a/test/parallel/test-stream2-readable-from-list.js +++ b/test/parallel/test-stream2-readable-from-list.js @@ -1,6 +1,6 @@ 'use strict'; +require('../common'); var assert = require('assert'); -var common = require('../common'); var fromList = require('_stream_readable')._fromList; // tiny node-tap lookalike. @@ -39,8 +39,6 @@ process.nextTick(run); test('buffers', function(t) { - // have a length - var len = 16; var list = [ new Buffer('foog'), new Buffer('bark'), new Buffer('bazy'), @@ -69,8 +67,6 @@ test('buffers', function(t) { }); test('strings', function(t) { - // have a length - var len = 16; var list = [ 'foog', 'bark', 'bazy', diff --git a/test/parallel/test-stream2-readable-legacy-drain.js b/test/parallel/test-stream2-readable-legacy-drain.js index 4218bace2b878f..399771e46a11ed 100644 --- a/test/parallel/test-stream2-readable-legacy-drain.js +++ b/test/parallel/test-stream2-readable-legacy-drain.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var Stream = require('stream'); diff --git a/test/parallel/test-stream2-readable-non-empty-end.js b/test/parallel/test-stream2-readable-non-empty-end.js index 46d6f92f2b9df2..1953503ef9be2e 100644 --- a/test/parallel/test-stream2-readable-non-empty-end.js +++ b/test/parallel/test-stream2-readable-non-empty-end.js @@ -1,6 +1,6 @@ 'use strict'; +require('../common'); var assert = require('assert'); -var common = require('../common'); var Readable = require('_stream_readable'); var len = 0; diff --git a/test/parallel/test-stream2-readable-wrap-empty.js b/test/parallel/test-stream2-readable-wrap-empty.js index 60417ca893300d..d2bf8f3f306f6d 100644 --- a/test/parallel/test-stream2-readable-wrap-empty.js +++ b/test/parallel/test-stream2-readable-wrap-empty.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var Readable = require('_stream_readable'); diff --git a/test/parallel/test-stream2-readable-wrap.js b/test/parallel/test-stream2-readable-wrap.js index 8e3e04b966010f..acf1cfdb030439 100644 --- a/test/parallel/test-stream2-readable-wrap.js +++ b/test/parallel/test-stream2-readable-wrap.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var Readable = require('_stream_readable'); diff --git a/test/parallel/test-stream2-set-encoding.js b/test/parallel/test-stream2-set-encoding.js index ea9a315cb1a6e1..40e09035a98e90 100644 --- a/test/parallel/test-stream2-set-encoding.js +++ b/test/parallel/test-stream2-set-encoding.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var R = require('_stream_readable'); var util = require('util'); diff --git a/test/parallel/test-stream2-transform.js b/test/parallel/test-stream2-transform.js index e45c913c94f559..11ee45915c8395 100644 --- a/test/parallel/test-stream2-transform.js +++ b/test/parallel/test-stream2-transform.js @@ -1,6 +1,6 @@ 'use strict'; +require('../common'); var assert = require('assert'); -var common = require('../common'); var PassThrough = require('_stream_passthrough'); var Transform = require('_stream_transform'); @@ -303,13 +303,10 @@ test('passthrough event emission', function(t) { var pt = new PassThrough(); var emits = 0; pt.on('readable', function() { - var state = pt._readableState; console.error('>>> emit readable %d', emits); emits++; }); - var i = 0; - pt.write(new Buffer('foog')); console.error('need emit 0'); diff --git a/test/parallel/test-stream2-unpipe-leak.js b/test/parallel/test-stream2-unpipe-leak.js index 15b510e7f643cc..3b529bac1f2e9c 100644 --- a/test/parallel/test-stream2-unpipe-leak.js +++ b/test/parallel/test-stream2-unpipe-leak.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var stream = require('stream'); diff --git a/test/parallel/test-stream2-writable.js b/test/parallel/test-stream2-writable.js index 1d87d7f920c052..81e57d06eb3bec 100644 --- a/test/parallel/test-stream2-writable.js +++ b/test/parallel/test-stream2-writable.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var W = require('_stream_writable'); var D = require('_stream_duplex'); var assert = require('assert'); diff --git a/test/parallel/test-stream3-pause-then-read.js b/test/parallel/test-stream3-pause-then-read.js index 135629a243d66c..e4e33738b33206 100644 --- a/test/parallel/test-stream3-pause-then-read.js +++ b/test/parallel/test-stream3-pause-then-read.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var stream = require('stream'); diff --git a/test/parallel/test-string-decoder.js b/test/parallel/test-string-decoder.js index 0b22d3dd04efc9..9d0034e2fc9c7d 100644 --- a/test/parallel/test-string-decoder.js +++ b/test/parallel/test-string-decoder.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var StringDecoder = require('string_decoder').StringDecoder; diff --git a/test/parallel/test-stringbytes-external-at-max.js b/test/parallel/test-stringbytes-external-at-max.js index 6678e5355224b3..31f476d66b18ba 100644 --- a/test/parallel/test-stringbytes-external-at-max.js +++ b/test/parallel/test-stringbytes-external-at-max.js @@ -1,22 +1,32 @@ 'use strict'; +// Flags: --expose-gc -require('../common'); +const common = require('../common'); const assert = require('assert'); // v8 fails silently if string length > v8::String::kMaxLength // 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'; +if (!common.enoughTestMem) { + console.log(skipMessage); + return; +} +assert(typeof gc === 'function', 'Run this test with --expose-gc'); + try { - new Buffer(kStringMaxLength * 3); + var buf = new Buffer(kStringMaxLength); + // Try to allocate memory first then force gc so future allocations succeed. + new Buffer(2 * kStringMaxLength); + gc(); } catch(e) { - assert.equal(e.message, 'Invalid array buffer length'); - console.log( - '1..0 # Skipped: intensive toString tests due to memory confinements'); + // If the exception is not due to memory confinement then rethrow it. + if (e.message !== 'Invalid array buffer length') throw (e); + console.log(skipMessage); return; } -const buf = new Buffer(kStringMaxLength); - const maxString = buf.toString('binary'); assert.equal(maxString.length, kStringMaxLength); diff --git a/test/parallel/test-stringbytes-external-exceed-max-by-1-ascii.js b/test/parallel/test-stringbytes-external-exceed-max-by-1-ascii.js index e982cf9eb092fd..4789089d5e0040 100644 --- a/test/parallel/test-stringbytes-external-exceed-max-by-1-ascii.js +++ b/test/parallel/test-stringbytes-external-exceed-max-by-1-ascii.js @@ -1,23 +1,33 @@ 'use strict'; +// Flags: --expose-gc -require('../common'); +const common = require('../common'); const assert = require('assert'); +const skipMessage = + '1..0 # Skipped: intensive toString tests due to memory confinements'; +if (!common.enoughTestMem) { + console.log(skipMessage); + return; +} +assert(typeof gc === 'function', 'Run this test with --expose-gc'); + // v8 fails silently if string length > v8::String::kMaxLength // v8::String::kMaxLength defined in v8.h const kStringMaxLength = process.binding('buffer').kStringMaxLength; try { - new Buffer(kStringMaxLength * 3); + var buf = new Buffer(kStringMaxLength + 1); + // Try to allocate memory first then force gc so future allocations succeed. + new Buffer(2 * kStringMaxLength); + gc(); } catch(e) { - assert.equal(e.message, 'Invalid array buffer length'); - console.log( - '1..0 # Skipped: intensive toString tests due to memory confinements'); + // If the exception is not due to memory confinement then rethrow it. + if (e.message !== 'Invalid array buffer length') throw (e); + console.log(skipMessage); return; } -const buf = new Buffer(kStringMaxLength + 1); - assert.throws(function() { buf.toString('ascii'); }, /toString failed/); diff --git a/test/parallel/test-stringbytes-external-exceed-max-by-1-base64.js b/test/parallel/test-stringbytes-external-exceed-max-by-1-base64.js index 43a3358759e249..8f52d6ac30dd9f 100644 --- a/test/parallel/test-stringbytes-external-exceed-max-by-1-base64.js +++ b/test/parallel/test-stringbytes-external-exceed-max-by-1-base64.js @@ -1,23 +1,33 @@ 'use strict'; +// Flags: --expose-gc -require('../common'); +const common = require('../common'); const assert = require('assert'); +const skipMessage = + '1..0 # Skipped: intensive toString tests due to memory confinements'; +if (!common.enoughTestMem) { + console.log(skipMessage); + return; +} +assert(typeof gc === 'function', 'Run this test with --expose-gc'); + // v8 fails silently if string length > v8::String::kMaxLength // v8::String::kMaxLength defined in v8.h const kStringMaxLength = process.binding('buffer').kStringMaxLength; try { - new Buffer(kStringMaxLength * 3); + var buf = new Buffer(kStringMaxLength + 1); + // Try to allocate memory first then force gc so future allocations succeed. + new Buffer(2 * kStringMaxLength); + gc(); } catch(e) { - assert.equal(e.message, 'Invalid array buffer length'); - console.log( - '1..0 # Skipped: intensive toString tests due to memory confinements'); + // If the exception is not due to memory confinement then rethrow it. + if (e.message !== 'Invalid array buffer length') throw (e); + console.log(skipMessage); return; } -const buf = new Buffer(kStringMaxLength + 1); - assert.throws(function() { buf.toString('base64'); }, /toString failed/); diff --git a/test/parallel/test-stringbytes-external-exceed-max-by-1-binary.js b/test/parallel/test-stringbytes-external-exceed-max-by-1-binary.js index 9d0d2c3e897057..79dac9cc41dcf0 100644 --- a/test/parallel/test-stringbytes-external-exceed-max-by-1-binary.js +++ b/test/parallel/test-stringbytes-external-exceed-max-by-1-binary.js @@ -1,23 +1,33 @@ 'use strict'; +// Flags: --expose-gc -require('../common'); +const common = require('../common'); const assert = require('assert'); +const skipMessage = + '1..0 # Skipped: intensive toString tests due to memory confinements'; +if (!common.enoughTestMem) { + console.log(skipMessage); + return; +} +assert(typeof gc === 'function', 'Run this test with --expose-gc'); + // v8 fails silently if string length > v8::String::kMaxLength // v8::String::kMaxLength defined in v8.h const kStringMaxLength = process.binding('buffer').kStringMaxLength; try { - new Buffer(kStringMaxLength * 3); + var buf = new Buffer(kStringMaxLength + 1); + // Try to allocate memory first then force gc so future allocations succeed. + new Buffer(2 * kStringMaxLength); + gc(); } catch(e) { - assert.equal(e.message, 'Invalid array buffer length'); - console.log( - '1..0 # Skipped: intensive toString tests due to memory confinements'); + // If the exception is not due to memory confinement then rethrow it. + if (e.message !== 'Invalid array buffer length') throw (e); + console.log(skipMessage); return; } -const buf = new Buffer(kStringMaxLength + 1); - assert.throws(function() { buf.toString('binary'); }, /toString failed/); diff --git a/test/parallel/test-stringbytes-external-exceed-max-by-1-hex.js b/test/parallel/test-stringbytes-external-exceed-max-by-1-hex.js index 2937b4aab85813..50d0dad5829160 100644 --- a/test/parallel/test-stringbytes-external-exceed-max-by-1-hex.js +++ b/test/parallel/test-stringbytes-external-exceed-max-by-1-hex.js @@ -1,23 +1,33 @@ 'use strict'; +// Flags: --expose-gc -require('../common'); +const common = require('../common'); const assert = require('assert'); +const skipMessage = + '1..0 # Skipped: intensive toString tests due to memory confinements'; +if (!common.enoughTestMem) { + console.log(skipMessage); + return; +} +assert(typeof gc === 'function', 'Run this test with --expose-gc'); + // v8 fails silently if string length > v8::String::kMaxLength // v8::String::kMaxLength defined in v8.h const kStringMaxLength = process.binding('buffer').kStringMaxLength; try { - new Buffer(kStringMaxLength * 3); + var buf = new Buffer(kStringMaxLength + 1); + // Try to allocate memory first then force gc so future allocations succeed. + new Buffer(2 * kStringMaxLength); + gc(); } catch(e) { - assert.equal(e.message, 'Invalid array buffer length'); - console.log( - '1..0 # Skipped: intensive toString tests due to memory confinements'); + // If the exception is not due to memory confinement then rethrow it. + if (e.message !== 'Invalid array buffer length') throw (e); + console.log(skipMessage); return; } -const buf = new Buffer(kStringMaxLength + 1); - assert.throws(function() { buf.toString('hex'); }, /toString failed/); diff --git a/test/parallel/test-stringbytes-external-exceed-max-by-1-utf8.js b/test/parallel/test-stringbytes-external-exceed-max-by-1-utf8.js index ee297a880dacbd..ecd6eaf954e191 100644 --- a/test/parallel/test-stringbytes-external-exceed-max-by-1-utf8.js +++ b/test/parallel/test-stringbytes-external-exceed-max-by-1-utf8.js @@ -1,23 +1,33 @@ 'use strict'; +// Flags: --expose-gc -require('../common'); +const common = require('../common'); const assert = require('assert'); +const skipMessage = + '1..0 # Skipped: intensive toString tests due to memory confinements'; +if (!common.enoughTestMem) { + console.log(skipMessage); + return; +} +assert(typeof gc === 'function', 'Run this test with --expose-gc'); + // v8 fails silently if string length > v8::String::kMaxLength // v8::String::kMaxLength defined in v8.h const kStringMaxLength = process.binding('buffer').kStringMaxLength; try { - new Buffer(kStringMaxLength * 3); + var buf = new Buffer(kStringMaxLength + 1); + // Try to allocate memory first then force gc so future allocations succeed. + new Buffer(2 * kStringMaxLength); + gc(); } catch(e) { - assert.equal(e.message, 'Invalid array buffer length'); - console.log( - '1..0 # Skipped: intensive toString tests due to memory confinements'); + // If the exception is not due to memory confinement then rethrow it. + if (e.message !== 'Invalid array buffer length') throw (e); + console.log(skipMessage); return; } -const buf = new Buffer(kStringMaxLength + 1); - assert.throws(function() { buf.toString(); }, /toString failed|Invalid array buffer length/); diff --git a/test/parallel/test-stringbytes-external-exceed-max-by-2.js b/test/parallel/test-stringbytes-external-exceed-max-by-2.js index 879e4ae91dfb60..8350c4532eafdc 100644 --- a/test/parallel/test-stringbytes-external-exceed-max-by-2.js +++ b/test/parallel/test-stringbytes-external-exceed-max-by-2.js @@ -1,22 +1,32 @@ 'use strict'; +// Flags: --expose-gc -require('../common'); +const common = require('../common'); const assert = require('assert'); +const skipMessage = + '1..0 # Skipped: intensive toString tests due to memory confinements'; +if (!common.enoughTestMem) { + console.log(skipMessage); + return; +} +assert(typeof gc === 'function', 'Run this test with --expose-gc'); + // v8 fails silently if string length > v8::String::kMaxLength // v8::String::kMaxLength defined in v8.h const kStringMaxLength = process.binding('buffer').kStringMaxLength; try { - new Buffer(kStringMaxLength * 3); + var buf = new Buffer(kStringMaxLength + 2); + // Try to allocate memory first then force gc so future allocations succeed. + new Buffer(2 * kStringMaxLength); + gc(); } catch(e) { - assert.equal(e.message, 'Invalid array buffer length'); - console.log( - '1..0 # Skipped: intensive toString tests due to memory confinements'); + // If the exception is not due to memory confinement then rethrow it. + if (e.message !== 'Invalid array buffer length') throw (e); + console.log(skipMessage); return; } -const buf2 = new Buffer(kStringMaxLength + 2); - -const maxString = buf2.toString('utf16le'); +const maxString = buf.toString('utf16le'); assert.equal(maxString.length, (kStringMaxLength + 2) / 2); diff --git a/test/parallel/test-stringbytes-external-exceed-max.js b/test/parallel/test-stringbytes-external-exceed-max.js index 0a6f585b66f3ad..fd19cfb9e20697 100644 --- a/test/parallel/test-stringbytes-external-exceed-max.js +++ b/test/parallel/test-stringbytes-external-exceed-max.js @@ -1,23 +1,33 @@ 'use strict'; +// Flags: --expose-gc -require('../common'); +const common = require('../common'); const assert = require('assert'); +const skipMessage = + '1..0 # Skipped: intensive toString tests due to memory confinements'; +if (!common.enoughTestMem) { + console.log(skipMessage); + return; +} +assert(typeof gc === 'function', 'Run this test with --expose-gc'); + // v8 fails silently if string length > v8::String::kMaxLength // v8::String::kMaxLength defined in v8.h const kStringMaxLength = process.binding('buffer').kStringMaxLength; try { - new Buffer(kStringMaxLength * 3); + var buf = new Buffer(kStringMaxLength * 2 + 2); + // Try to allocate memory first then force gc so future allocations succeed. + new Buffer(2 * kStringMaxLength); + gc(); } catch(e) { - assert.equal(e.message, 'Invalid array buffer length'); - console.log( - '1..0 # Skipped: intensive toString tests due to memory confinements'); + // If the exception is not due to memory confinement then rethrow it. + if (e.message !== 'Invalid array buffer length') throw (e); + console.log(skipMessage); return; } -const buf0 = new Buffer(kStringMaxLength * 2 + 2); - assert.throws(function() { - buf0.toString('utf16le'); + buf.toString('utf16le'); }, /toString failed/); diff --git a/test/parallel/test-stringbytes-external.js b/test/parallel/test-stringbytes-external.js index ba3f0c5d1d9ade..1f03e2be42f577 100644 --- a/test/parallel/test-stringbytes-external.js +++ b/test/parallel/test-stringbytes-external.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); // minimum string size to overflow into external string space var EXTERN_APEX = 0xFBEE9; diff --git a/test/parallel/test-timers-active.js b/test/parallel/test-timers-active.js index acddc2f41a45e8..d8faa1f5a33483 100644 --- a/test/parallel/test-timers-active.js +++ b/test/parallel/test-timers-active.js @@ -1,5 +1,5 @@ 'use strict'; -const common = require('../common'); +require('../common'); const assert = require('assert'); const active = require('timers').active; diff --git a/test/parallel/test-timers-args.js b/test/parallel/test-timers-args.js index abb785ea0fc79c..ae11e35ba2784d 100644 --- a/test/parallel/test-timers-args.js +++ b/test/parallel/test-timers-args.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); function range(n) { diff --git a/test/parallel/test-timers-immediate-queue.js b/test/parallel/test-timers-immediate-queue.js index a71472d46442ab..62482d510a6608 100644 --- a/test/parallel/test-timers-immediate-queue.js +++ b/test/parallel/test-timers-immediate-queue.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); // setImmediate should run clear its queued cbs once per event loop turn diff --git a/test/parallel/test-timers-immediate.js b/test/parallel/test-timers-immediate.js index bcfc4616ac6264..9486465602ce9b 100644 --- a/test/parallel/test-timers-immediate.js +++ b/test/parallel/test-timers-immediate.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var immediateA = false, diff --git a/test/parallel/test-timers-linked-list.js b/test/parallel/test-timers-linked-list.js index 00b2129d126c4a..cc81e8721f13e2 100644 --- a/test/parallel/test-timers-linked-list.js +++ b/test/parallel/test-timers-linked-list.js @@ -1,8 +1,7 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); -var L = require('_linklist'); - +require('../common'); +const assert = require('assert'); +const L = require('_linklist'); var list = { name: 'list' }; var A = { name: 'A' }; diff --git a/test/parallel/test-timers-non-integer-delay.js b/test/parallel/test-timers-non-integer-delay.js index 97b2c0734f60d5..b42053db3b1895 100644 --- a/test/parallel/test-timers-non-integer-delay.js +++ b/test/parallel/test-timers-non-integer-delay.js @@ -16,7 +16,6 @@ */ require('../common'); -var assert = require('assert'); var TIMEOUT_DELAY = 1.1; var NB_TIMEOUTS_FIRED = 50; diff --git a/test/parallel/test-timers-now.js b/test/parallel/test-timers-now.js index 466bd064b8decf..8a47e397ce97a8 100644 --- a/test/parallel/test-timers-now.js +++ b/test/parallel/test-timers-now.js @@ -1,6 +1,6 @@ 'use strict'; -const common = require('../common'); +require('../common'); const assert = require('assert'); // Return value of Timer.now() should easily fit in a SMI right after start-up. diff --git a/test/parallel/test-timers-ordering.js b/test/parallel/test-timers-ordering.js index 730a78a072c663..cef91e58e78c3d 100644 --- a/test/parallel/test-timers-ordering.js +++ b/test/parallel/test-timers-ordering.js @@ -1,15 +1,12 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var Timer = process.binding('timer_wrap').Timer; -var i; - var N = 30; var last_i = 0; var last_ts = 0; -var start = Timer.now(); var f = function(i) { if (i <= N) { diff --git a/test/parallel/test-timers-reset-process-domain-on-throw.js b/test/parallel/test-timers-reset-process-domain-on-throw.js new file mode 100644 index 00000000000000..f72530b5423886 --- /dev/null +++ b/test/parallel/test-timers-reset-process-domain-on-throw.js @@ -0,0 +1,45 @@ +'use strict'; + +// This test makes sure that when throwing from within a timer's callback, +// its active domain at the time of the throw is not the process' active domain +// for the next timers that need to be processed on the same turn of the event +// loop. + +const common = require('../common'); +const assert = require('assert'); +const domain = require('domain'); + +// Use the same timeout value so that both timers' callbacks are called during +// the same invocation of the underlying native timer's callback (listOnTimeout +// in lib/timers.js). +setTimeout(err, 50); +setTimeout(common.mustCall(secondTimer), 50); + +function err() { + const d = domain.create(); + d.on('error', handleDomainError); + d.run(err2); + + function err2() { + // this function doesn't exist, and throws an error as a result. + err3(); + } + + function handleDomainError(e) { + // In the domain's error handler, the current active domain should be the + // domain within which the error was thrown. + assert.equal(process.domain, d); + } +} + +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); + // 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-timers-socket-timeout-removes-other-socket-unref-timer.js b/test/parallel/test-timers-socket-timeout-removes-other-socket-unref-timer.js index 081688cfa5e812..c9ca3eafd64ebf 100644 --- a/test/parallel/test-timers-socket-timeout-removes-other-socket-unref-timer.js +++ b/test/parallel/test-timers-socket-timeout-removes-other-socket-unref-timer.js @@ -5,7 +5,6 @@ */ const common = require('../common'); -const assert = require('assert'); const net = require('net'); const clients = []; diff --git a/test/parallel/test-timers-uncaught-exception.js b/test/parallel/test-timers-uncaught-exception.js index 794b3b923be1df..6b6dc583715849 100644 --- a/test/parallel/test-timers-uncaught-exception.js +++ b/test/parallel/test-timers-uncaught-exception.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var exceptions = 0; diff --git a/test/parallel/test-timers-unref-active.js b/test/parallel/test-timers-unref-active.js index 08f28b0153fecb..ad72ac4047747b 100644 --- a/test/parallel/test-timers-unref-active.js +++ b/test/parallel/test-timers-unref-active.js @@ -15,7 +15,7 @@ * all 10 timeouts had the time to expire. */ -const common = require('../common'); +require('../common'); const timers = require('timers'); const assert = require('assert'); diff --git a/test/parallel/test-timers-unref-call.js b/test/parallel/test-timers-unref-call.js index b348330d200d65..edd5865e8f610b 100644 --- a/test/parallel/test-timers-unref-call.js +++ b/test/parallel/test-timers-unref-call.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var Timer = process.binding('timer_wrap').Timer; Timer.now = function() { return ++Timer.now.ticks; }; diff --git a/test/parallel/test-timers-unref-remove-other-unref-timers-only-one-fires.js b/test/parallel/test-timers-unref-remove-other-unref-timers-only-one-fires.js index aead4a4e7def64..971c485a4cf986 100644 --- a/test/parallel/test-timers-unref-remove-other-unref-timers-only-one-fires.js +++ b/test/parallel/test-timers-unref-remove-other-unref-timers-only-one-fires.js @@ -10,7 +10,7 @@ * This behavior is a private implementation detail and should not be * considered public interface. */ -const common = require('../common'); +require('../common'); const timers = require('timers'); const assert = require('assert'); diff --git a/test/parallel/test-timers-unref-remove-other-unref-timers.js b/test/parallel/test-timers-unref-remove-other-unref-timers.js index 8c1864f1a7da01..dcc50a5171ad28 100644 --- a/test/parallel/test-timers-unref-remove-other-unref-timers.js +++ b/test/parallel/test-timers-unref-remove-other-unref-timers.js @@ -7,7 +7,6 @@ * considered public interface. */ const common = require('../common'); -const assert = require('assert'); const timers = require('timers'); const foo = { diff --git a/test/parallel/test-timers-unref.js b/test/parallel/test-timers-unref.js index c0b24a4275be86..671c676e350e3a 100644 --- a/test/parallel/test-timers-unref.js +++ b/test/parallel/test-timers-unref.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var interval_fired = false, diff --git a/test/parallel/test-timers-unrefd-interval-still-fires.js b/test/parallel/test-timers-unrefd-interval-still-fires.js index 98bd278b451613..8f26d28816b60c 100644 --- a/test/parallel/test-timers-unrefd-interval-still-fires.js +++ b/test/parallel/test-timers-unrefd-interval-still-fires.js @@ -2,19 +2,26 @@ /* * This test is a regression test for joyent/node#8900. */ -require('../common'); -var assert = require('assert'); +const common = require('../common'); -var N = 5; +const TEST_DURATION = common.platformTimeout(100); +const N = 5; var nbIntervalFired = 0; -var timer = setInterval(function() { + +const keepOpen = setTimeout(() => { + console.error('[FAIL] Interval fired %d/%d times.', nbIntervalFired, N); + throw new Error('Test timed out. keepOpen was not canceled.'); +}, TEST_DURATION); + +const timer = setInterval(() => { ++nbIntervalFired; - if (nbIntervalFired === N) + if (nbIntervalFired === N) { clearInterval(timer); + timer._onTimeout = () => { + throw new Error('Unrefd interval fired after being cleared.'); + }; + setImmediate(() => clearTimeout(keepOpen)); + } }, 1); timer.unref(); - -setTimeout(function onTimeout() { - assert.strictEqual(nbIntervalFired, N); -}, 100); diff --git a/test/parallel/test-timers-zero-timeout.js b/test/parallel/test-timers-zero-timeout.js index 1c84814363a641..ab0c38f6084277 100644 --- a/test/parallel/test-timers-zero-timeout.js +++ b/test/parallel/test-timers-zero-timeout.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); // https://github.com/joyent/node/issues/2079 - zero timeout drops extra args @@ -7,7 +7,7 @@ var assert = require('assert'); var ncalled = 0; setTimeout(f, 0, 'foo', 'bar', 'baz'); - var timer = setTimeout(function() {}, 0); + setTimeout(function() {}, 0); function f(a, b, c) { assert.equal(a, 'foo'); diff --git a/test/parallel/test-timers.js b/test/parallel/test-timers.js index e784e262959d97..0b379e0eb45ad0 100644 --- a/test/parallel/test-timers.js +++ b/test/parallel/test-timers.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var inputs = [ diff --git a/test/parallel/test-tls-0-dns-altname.js b/test/parallel/test-tls-0-dns-altname.js index 61458142bc0115..95ceb1aa59aaea 100644 --- a/test/parallel/test-tls-0-dns-altname.js +++ b/test/parallel/test-tls-0-dns-altname.js @@ -9,7 +9,6 @@ if (!common.hasCrypto) { var tls = require('tls'); var fs = require('fs'); -var net = require('net'); var common = require('../common'); 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 ea40205bfff06f..d89a4e9930ca6a 100644 --- a/test/parallel/test-tls-async-cb-after-socket-end.js +++ b/test/parallel/test-tls-async-cb-after-socket-end.js @@ -2,7 +2,6 @@ var common = require('../common'); -var assert = require('assert'); var path = require('path'); var fs = require('fs'); var constants = require('constants'); diff --git a/test/parallel/test-tls-client-default-ciphers.js b/test/parallel/test-tls-client-default-ciphers.js index e38671fd6f9de1..9905fc45bdcd24 100644 --- a/test/parallel/test-tls-client-default-ciphers.js +++ b/test/parallel/test-tls-client-default-ciphers.js @@ -19,7 +19,7 @@ function test1() { }; try { - var s = tls.connect(common.PORT); + tls.connect(common.PORT); } catch (e) { assert(e instanceof Done); } diff --git a/test/parallel/test-tls-close-error.js b/test/parallel/test-tls-close-error.js index 5c5a797c280a7d..bd38cb55f7a17b 100644 --- a/test/parallel/test-tls-close-error.js +++ b/test/parallel/test-tls-close-error.js @@ -10,7 +10,6 @@ if (!common.hasCrypto) { var tls = require('tls'); var fs = require('fs'); -var net = require('net'); var errorCount = 0; var closeCount = 0; diff --git a/test/parallel/test-tls-close-notify.js b/test/parallel/test-tls-close-notify.js index 5cc3021ab8dd7e..5545f4512d5f39 100644 --- a/test/parallel/test-tls-close-notify.js +++ b/test/parallel/test-tls-close-notify.js @@ -9,7 +9,6 @@ if (!common.hasCrypto) { var tls = require('tls'); var fs = require('fs'); -var net = require('net'); var ended = 0; diff --git a/test/parallel/test-tls-destroy-whilst-write.js b/test/parallel/test-tls-destroy-whilst-write.js index f42ed1d4ea7702..26c20264735926 100644 --- a/test/parallel/test-tls-destroy-whilst-write.js +++ b/test/parallel/test-tls-destroy-whilst-write.js @@ -1,5 +1,4 @@ 'use strict'; -var assert = require('assert'); var common = require('../common'); if (!common.hasCrypto) { diff --git a/test/parallel/test-tls-fast-writing.js b/test/parallel/test-tls-fast-writing.js index 009fa40b631ee5..1f65391480d59d 100644 --- a/test/parallel/test-tls-fast-writing.js +++ b/test/parallel/test-tls-fast-writing.js @@ -20,7 +20,7 @@ var server = tls.createServer(options, onconnection); var gotChunk = false; var gotDrain = false; -var timer = setTimeout(function() { +setTimeout(function() { console.log('not ok - timed out'); process.exit(1); }, common.platformTimeout(500)); diff --git a/test/parallel/test-tls-handshake-error.js b/test/parallel/test-tls-handshake-error.js index f33177455f8943..f65440ed93b1a3 100644 --- a/test/parallel/test-tls-handshake-error.js +++ b/test/parallel/test-tls-handshake-error.js @@ -10,7 +10,6 @@ if (!common.hasCrypto) { var tls = require('tls'); var fs = require('fs'); -var net = require('net'); var errorCount = 0; var closeCount = 0; diff --git a/test/parallel/test-tls-handshake-nohang.js b/test/parallel/test-tls-handshake-nohang.js index ae07551ef98088..374ac02a2f45b5 100644 --- a/test/parallel/test-tls-handshake-nohang.js +++ b/test/parallel/test-tls-handshake-nohang.js @@ -1,6 +1,5 @@ 'use strict'; var common = require('../common'); -var assert = require('assert'); if (!common.hasCrypto) { console.log('1..0 # Skipped: missing crypto'); diff --git a/test/parallel/test-tls-inception.js b/test/parallel/test-tls-inception.js index df03cf934fcef6..8946f52bdd63d4 100644 --- a/test/parallel/test-tls-inception.js +++ b/test/parallel/test-tls-inception.js @@ -12,8 +12,9 @@ var fs = require('fs'); var path = require('path'); var net = require('net'); -var options, a, b, portA, portB; -var gotHello = false; +var options, a, b; + +var body = new Buffer(400000).fill('A'); options = { key: fs.readFileSync(path.join(common.fixturesDir, 'test_key.pem')), @@ -31,18 +32,14 @@ a = tls.createServer(options, function(socket) { dest.pipe(socket); socket.pipe(dest); - dest.on('close', function() { + dest.on('end', function() { socket.destroy(); }); }); // the "target" server b = tls.createServer(options, function(socket) { - socket.end('hello'); -}); - -process.on('exit', function() { - assert(gotHello); + socket.end(body); }); a.listen(common.PORT, function() { @@ -59,14 +56,15 @@ a.listen(common.PORT, function() { rejectUnauthorized: false }); ssl.setEncoding('utf8'); - ssl.once('data', function(data) { - assert.equal('hello', data); - gotHello = true; + var buf = ''; + ssl.on('data', function(data) { + buf += data; }); - ssl.on('end', function() { + ssl.on('end', common.mustCall(function() { + assert.equal(buf, body); ssl.end(); a.close(); b.close(); - }); + })); }); }); diff --git a/test/parallel/test-tls-invoke-queued.js b/test/parallel/test-tls-invoke-queued.js index f833108ea3f9e0..efa5c0aa9aa31d 100644 --- a/test/parallel/test-tls-invoke-queued.js +++ b/test/parallel/test-tls-invoke-queued.js @@ -9,7 +9,6 @@ if (!common.hasCrypto) { var tls = require('tls'); var fs = require('fs'); -var net = require('net'); var received = ''; diff --git a/test/parallel/test-tls-key-mismatch.js b/test/parallel/test-tls-key-mismatch.js index f7919c545aefb1..2e17a4931078c7 100644 --- a/test/parallel/test-tls-key-mismatch.js +++ b/test/parallel/test-tls-key-mismatch.js @@ -14,8 +14,6 @@ var options = { cert: fs.readFileSync(common.fixturesDir + '/keys/agent2-cert.pem') }; -var cert = null; - assert.throws(function() { tls.createSecureContext(options); }); diff --git a/test/parallel/test-tls-legacy-onselect.js b/test/parallel/test-tls-legacy-onselect.js index 6f1e9a91a8344c..d3b20d5d8a4cef 100644 --- a/test/parallel/test-tls-legacy-onselect.js +++ b/test/parallel/test-tls-legacy-onselect.js @@ -9,18 +9,8 @@ if (!common.hasCrypto) { var tls = require('tls'); var net = require('net'); -var fs = require('fs'); - var success = false; -function filenamePEM(n) { - return require('path').join(common.fixturesDir, 'keys', n + '.pem'); -} - -function loadPEM(n) { - return fs.readFileSync(filenamePEM(n)); -} - var server = net.Server(function(raw) { var pair = tls.createSecurePair(null, true, false, false); pair.on('error', function() {}); diff --git a/test/parallel/test-tls-max-send-fragment.js b/test/parallel/test-tls-max-send-fragment.js index cc9413b81e78d6..8b1bf0998aad30 100644 --- a/test/parallel/test-tls-max-send-fragment.js +++ b/test/parallel/test-tls-max-send-fragment.js @@ -9,7 +9,6 @@ if (!common.hasCrypto) { var tls = require('tls'); var fs = require('fs'); -var net = require('net'); var common = require('../common'); diff --git a/test/parallel/test-tls-no-sslv3.js b/test/parallel/test-tls-no-sslv3.js index ce5a9d395d6a47..442fc3b91c25af 100644 --- a/test/parallel/test-tls-no-sslv3.js +++ b/test/parallel/test-tls-no-sslv3.js @@ -19,6 +19,8 @@ if (common.opensslCli === false) { var cert = fs.readFileSync(common.fixturesDir + '/test_cert.pem'); var key = fs.readFileSync(common.fixturesDir + '/test_key.pem'); var server = tls.createServer({ cert: cert, key: key }, common.fail); +var errors = []; +var stderr = ''; server.listen(common.PORT, '127.0.0.1', function() { var address = this.address().address + ':' + this.address().port; @@ -34,13 +36,25 @@ server.listen(common.PORT, '127.0.0.1', function() { if (common.isWindows) args.push('-no_rand_screen'); - var client = spawn(common.opensslCli, args, { stdio: 'inherit' }); + var client = spawn(common.opensslCli, args, { stdio: 'pipe' }); + client.stdout.pipe(process.stdout); + client.stderr.pipe(process.stderr); + client.stderr.setEncoding('utf8'); + client.stderr.on('data', data => stderr += data); + client.once('exit', common.mustCall(function(exitCode) { assert.equal(exitCode, 1); server.close(); })); }); -server.once('clientError', common.mustCall(function(err, conn) { - assert(/:wrong version number/.test(err.message)); -})); +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.'); + } else { + assert.equal(errors.length, 1); + assert(/:wrong version number/.test(errors[0].message)); + } +}); diff --git a/test/parallel/test-tls-ocsp-callback.js b/test/parallel/test-tls-ocsp-callback.js index d970b2ab013446..e9443f45357995 100644 --- a/test/parallel/test-tls-ocsp-callback.js +++ b/test/parallel/test-tls-ocsp-callback.js @@ -22,11 +22,7 @@ var constants = require('constants'); var fs = require('fs'); var join = require('path').join; -test({ response: false }, function() { - test({ response: 'hello world' }, function() { - test({ ocsp: false }); - }); -}); +var pfx = fs.readFileSync(join(common.fixturesDir, 'keys', 'agent1-pfx.pem')); function test(testOptions, cb) { @@ -45,7 +41,13 @@ function test(testOptions, cb) { var clientSecure = 0; var ocspCount = 0; var ocspResponse; - var session; + + if (testOptions.pfx) { + delete options.key; + delete options.cert; + options.pfx = testOptions.pfx; + options.passphrase = testOptions.passphrase; + } var server = tls.createServer(options, function(cleartext) { cleartext.on('error', function(er) { @@ -106,3 +108,23 @@ function test(testOptions, cb) { assert.equal(ocspCount, 1); }); } + +var tests = [ + { response: false }, + { response: 'hello world' }, + { ocsp: false } +]; + +if (!common.hasFipsCrypto) { + tests.push({ pfx: pfx, passphrase: 'sample', response: 'hello pfx' }); +} + +function runTests(i) { + if (i === tests.length) return; + + test(tests[i], common.mustCall(function() { + runTests(i + 1); + })); +} + +runTests(0); diff --git a/test/parallel/test-tls-parse-cert-string.js b/test/parallel/test-tls-parse-cert-string.js new file mode 100644 index 00000000000000..11128783871fe4 --- /dev/null +++ b/test/parallel/test-tls-parse-cert-string.js @@ -0,0 +1,26 @@ +'use strict'; + +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 singlesOut = tls.parseCertString(singles); +assert.deepEqual(singlesOut, { + C: 'US', + ST: 'CA', + L: 'SF', + O: 'Node.js Foundation', + OU: 'Node.js', + CN: 'ca1', + emailAddress: 'ry@clouds.org' +}); + +const doubles = 'OU=Domain Control Validated\nOU=PositiveSSL Wildcard\n' + + 'CN=*.nodejs.org'; +const doublesOut = tls.parseCertString(doubles); +assert.deepEqual(doublesOut, { + OU: [ 'Domain Control Validated', 'PositiveSSL Wildcard' ], + CN: '*.nodejs.org' +}); diff --git a/test/parallel/test-tls-peer-certificate-encoding.js b/test/parallel/test-tls-peer-certificate-encoding.js index 96cb6944ef6a97..32b1583a0c4840 100644 --- a/test/parallel/test-tls-peer-certificate-encoding.js +++ b/test/parallel/test-tls-peer-certificate-encoding.js @@ -11,7 +11,6 @@ var tls = require('tls'); var fs = require('fs'); var util = require('util'); var join = require('path').join; -var spawn = require('child_process').spawn; var options = { key: fs.readFileSync(join(common.fixturesDir, 'keys', 'agent5-key.pem')), diff --git a/test/parallel/test-tls-peer-certificate-multi-keys.js b/test/parallel/test-tls-peer-certificate-multi-keys.js index fca7a1a77dda67..50ce9037f8d755 100644 --- a/test/parallel/test-tls-peer-certificate-multi-keys.js +++ b/test/parallel/test-tls-peer-certificate-multi-keys.js @@ -11,7 +11,6 @@ var tls = require('tls'); var fs = require('fs'); var util = require('util'); var join = require('path').join; -var spawn = require('child_process').spawn; var options = { key: fs.readFileSync(join(common.fixturesDir, 'agent.key')), diff --git a/test/parallel/test-tls-peer-certificate.js b/test/parallel/test-tls-peer-certificate.js index 3cb0eef2d56268..cdf8bf5644f675 100644 --- a/test/parallel/test-tls-peer-certificate.js +++ b/test/parallel/test-tls-peer-certificate.js @@ -11,7 +11,6 @@ var tls = require('tls'); var fs = require('fs'); var util = require('util'); var join = require('path').join; -var spawn = require('child_process').spawn; var options = { key: fs.readFileSync(join(common.fixturesDir, 'keys', 'agent1-key.pem')), diff --git a/test/parallel/test-tls-request-timeout.js b/test/parallel/test-tls-request-timeout.js index a9b1c78c91a0bf..0db2a613afc9e4 100644 --- a/test/parallel/test-tls-request-timeout.js +++ b/test/parallel/test-tls-request-timeout.js @@ -29,7 +29,7 @@ var server = tls.Server(options, function(socket) { }); server.listen(common.PORT, function() { - var socket = tls.connect({ + tls.connect({ port: common.PORT, rejectUnauthorized: false }); diff --git a/test/parallel/test-tls-socket-default-options.js b/test/parallel/test-tls-socket-default-options.js index 3af03a0ba9269a..c2c6e518bbc4d8 100644 --- a/test/parallel/test-tls-socket-default-options.js +++ b/test/parallel/test-tls-socket-default-options.js @@ -9,7 +9,6 @@ if (!common.hasCrypto) { const tls = require('tls'); const fs = require('fs'); -const net = require('net'); const sent = 'hello world'; @@ -33,7 +32,7 @@ function testSocketOptions(socket, socketOptions) { setImmediate(runTests); }); }).listen(common.PORT, function() { - let c = new tls.TLSSocket(socket, socketOptions); + const c = new tls.TLSSocket(socket, socketOptions); c.connect(common.PORT, function() { c.end(sent); }); diff --git a/test/parallel/test-tls-ticket-cluster.js b/test/parallel/test-tls-ticket-cluster.js index fc0f1d5e858d00..1fd1776ca8199f 100644 --- a/test/parallel/test-tls-ticket-cluster.js +++ b/test/parallel/test-tls-ticket-cluster.js @@ -42,7 +42,6 @@ if (cluster.isMaster) { function fork() { var worker = cluster.fork(); - var workerReqCount = 0; worker.on('message', function(msg) { console.error('[master] got %j', msg); if (msg === 'reused') { diff --git a/test/parallel/test-tty-stdout-end.js b/test/parallel/test-tty-stdout-end.js index 57f9c03ec449e9..a33a2e5ed27209 100644 --- a/test/parallel/test-tty-stdout-end.js +++ b/test/parallel/test-tty-stdout-end.js @@ -1,6 +1,6 @@ 'use strict'; // Can't test this when 'make test' doesn't assign a tty to the stdout. -const common = require('../common'); +require('../common'); const assert = require('assert'); const shouldThrow = function() { diff --git a/test/parallel/test-tty-wrap.js b/test/parallel/test-tty-wrap.js index dbe7b6890fd218..5e124dc89f7b87 100644 --- a/test/parallel/test-tty-wrap.js +++ b/test/parallel/test-tty-wrap.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var TTY = process.binding('tty_wrap').TTY; diff --git a/test/parallel/test-url.js b/test/parallel/test-url.js index 5098c7e46ab6e6..cd097be24384eb 100644 --- a/test/parallel/test-url.js +++ b/test/parallel/test-url.js @@ -1,10 +1,9 @@ /* eslint-disable max-len */ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); -var url = require('url'), - util = require('util'); +var url = require('url'); // URLs to parse, and expected data // { url : parsed } @@ -1515,9 +1514,6 @@ relativeTests2.forEach(function(relativeTest) { //if format and parse are inverse operations then //resolveObject(parse(x), y) == parse(resolve(x, y)) -//host and hostname are special, in this case a '' value is important -var emptyIsImportant = {'host': true, 'hostname': ''}; - //format: [from, path, expected] relativeTests.forEach(function(relativeTest) { var actual = url.resolveObject(url.parse(relativeTest[0]), relativeTest[1]), diff --git a/test/parallel/test-utf8-scripts.js b/test/parallel/test-utf8-scripts.js index 3a891283509b9e..a9db5d10e4fde7 100644 --- a/test/parallel/test-utf8-scripts.js +++ b/test/parallel/test-utf8-scripts.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); // üäö diff --git a/test/parallel/test-util-decorate-error-stack.js b/test/parallel/test-util-decorate-error-stack.js new file mode 100644 index 00000000000000..017a5ab6afe807 --- /dev/null +++ b/test/parallel/test-util-decorate-error-stack.js @@ -0,0 +1,36 @@ +// Flags: --expose_internals +'use strict'; +require('../common'); +const assert = require('assert'); +const internalUtil = require('internal/util'); + +assert.doesNotThrow(function() { + internalUtil.decorateErrorStack(); + internalUtil.decorateErrorStack(null); + internalUtil.decorateErrorStack(1); + internalUtil.decorateErrorStack(true); +}); + +// Verify that a stack property is not added to non-Errors +const obj = {}; +internalUtil.decorateErrorStack(obj); +assert.strictEqual(obj.stack, undefined); + +// Verify that the stack is decorated when possible +let err; + +try { + require('../fixtures/syntax/bad_syntax'); +} catch (e) { + err = e; + assert(!/var foo bar;/.test(err.stack)); + internalUtil.decorateErrorStack(err); +} + +assert(/var foo bar;/.test(err.stack)); + +// Verify that the stack is unchanged when there is no arrow message +err = new Error('foo'); +const originalStack = err.stack; +internalUtil.decorateErrorStack(err); +assert.strictEqual(originalStack, err.stack); diff --git a/test/parallel/test-util-format.js b/test/parallel/test-util-format.js index 6761671e1997bd..00028ddbb74728 100644 --- a/test/parallel/test-util-format.js +++ b/test/parallel/test-util-format.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var util = require('util'); var symbol = Symbol('foo'); diff --git a/test/parallel/test-util-inspect.js b/test/parallel/test-util-inspect.js index 444c0168a42fa7..d88096765694bd 100644 --- a/test/parallel/test-util-inspect.js +++ b/test/parallel/test-util-inspect.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var util = require('util'); @@ -135,12 +135,22 @@ map.set(1, 2); var mirror = Debug.MakeMirror(map.entries(), true); var vals = mirror.preview(); var valsOutput = []; -for (let o of vals) { +for (const o of vals) { valsOutput.push(o); } assert.strictEqual(util.inspect(valsOutput), '[ [ 1, 2 ] ]'); +// test for other constructors in different context +var obj = require('vm').runInNewContext('(function(){return {}})()', {}); +assert.strictEqual(util.inspect(obj), '{}'); +obj = require('vm').runInNewContext('var m=new Map();m.set(1,2);m', {}); +assert.strictEqual(util.inspect(obj), 'Map { 1 => 2 }'); +obj = require('vm').runInNewContext('var s=new Set();s.add(1);s.add(2);s', {}); +assert.strictEqual(util.inspect(obj), 'Set { 1, 2 }'); +obj = require('vm').runInNewContext('fn=function(){};new Promise(fn,fn)', {}); +assert.strictEqual(util.inspect(obj), 'Promise { }'); + // test for property descriptors var getter = Object.create(null, { a: { diff --git a/test/parallel/test-util-internal.js b/test/parallel/test-util-internal.js new file mode 100644 index 00000000000000..b557356716a004 --- /dev/null +++ b/test/parallel/test-util-internal.js @@ -0,0 +1,32 @@ +'use strict'; +// Flags: --expose_internals + +require('../common'); +const assert = require('assert'); +const internalUtil = require('internal/util'); + +function getHiddenValue(obj, name) { + return function() { + internalUtil.getHiddenValue(obj, name); + }; +} + +assert.throws(getHiddenValue(), /obj must be an object/); +assert.throws(getHiddenValue(null, 'foo'), /obj must be an object/); +assert.throws(getHiddenValue(undefined, 'foo'), /obj must be an object/); +assert.throws(getHiddenValue('bar', 'foo'), /obj must be an object/); +assert.throws(getHiddenValue(85, 'foo'), /obj must be an object/); +assert.throws(getHiddenValue({}), /name must be a string/); +assert.throws(getHiddenValue({}, null), /name must be a string/); +assert.throws(getHiddenValue({}, []), /name must be a string/); +assert.deepEqual(internalUtil.getHiddenValue({}, 'foo'), undefined); + +let arrowMessage; + +try { + require('../fixtures/syntax/bad_syntax'); +} catch (err) { + arrowMessage = internalUtil.getHiddenValue(err, 'arrowMessage'); +} + +assert(/bad_syntax\.js:1/.test(arrowMessage)); diff --git a/test/parallel/test-util.js b/test/parallel/test-util.js index 700532bd5a397b..864361d80a6dfa 100644 --- a/test/parallel/test-util.js +++ b/test/parallel/test-util.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var util = require('util'); var context = require('vm').runInNewContext; diff --git a/test/parallel/test-v8-flag-type-check.js b/test/parallel/test-v8-flag-type-check.js index 68bf30dba3cdbc..3724944821343c 100644 --- a/test/parallel/test-v8-flag-type-check.js +++ b/test/parallel/test-v8-flag-type-check.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var v8 = require('v8'); diff --git a/test/parallel/test-v8-flags.js b/test/parallel/test-v8-flags.js index d21cbc6c2635a5..cee924d5b13068 100644 --- a/test/parallel/test-v8-flags.js +++ b/test/parallel/test-v8-flags.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var v8 = require('v8'); var vm = require('vm'); diff --git a/test/parallel/test-v8-stats.js b/test/parallel/test-v8-stats.js index fc4a6df30f8ed8..eb5566fe2bc28f 100644 --- a/test/parallel/test-v8-stats.js +++ b/test/parallel/test-v8-stats.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var v8 = require('v8'); diff --git a/test/parallel/test-vm-basic.js b/test/parallel/test-vm-basic.js index 96c615c44af10c..8f9cab90eb5a1b 100644 --- a/test/parallel/test-vm-basic.js +++ b/test/parallel/test-vm-basic.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var vm = require('vm'); diff --git a/test/parallel/test-vm-context-async-script.js b/test/parallel/test-vm-context-async-script.js index e146d48343aa60..b09eda85209807 100644 --- a/test/parallel/test-vm-context-async-script.js +++ b/test/parallel/test-vm-context-async-script.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var vm = require('vm'); diff --git a/test/parallel/test-vm-context-property-forwarding.js b/test/parallel/test-vm-context-property-forwarding.js index 5fcd64b8ba9094..4034441615ca9e 100644 --- a/test/parallel/test-vm-context-property-forwarding.js +++ b/test/parallel/test-vm-context-property-forwarding.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var vm = require('vm'); diff --git a/test/parallel/test-vm-context.js b/test/parallel/test-vm-context.js index 45e19e6638892e..3fe3cf1b66a88e 100644 --- a/test/parallel/test-vm-context.js +++ b/test/parallel/test-vm-context.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var vm = require('vm'); @@ -60,3 +60,15 @@ var ctx = {}; Object.defineProperty(ctx, 'b', { configurable: false }); ctx = vm.createContext(ctx); assert.equal(script.runInContext(ctx), false); + +// Error on the first line of a module should +// have the correct line and column number +assert.throws(function() { + vm.runInContext('throw new Error()', context, { + filename: 'expected-filename.js', + lineOffset: 32, + columnOffset: 123 + }); +}, function(err) { + return /expected-filename.js:33:130/.test(err.stack); +}, 'Expected appearance of proper offset in Error stack'); diff --git a/test/parallel/test-vm-create-and-run-in-context.js b/test/parallel/test-vm-create-and-run-in-context.js index 01df6ad4531e4a..94527598ca27b1 100644 --- a/test/parallel/test-vm-create-and-run-in-context.js +++ b/test/parallel/test-vm-create-and-run-in-context.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var vm = require('vm'); diff --git a/test/parallel/test-vm-create-context-accessors.js b/test/parallel/test-vm-create-context-accessors.js index 678cf3fbd2128e..d2e7d7bd8eacc2 100644 --- a/test/parallel/test-vm-create-context-accessors.js +++ b/test/parallel/test-vm-create-context-accessors.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var vm = require('vm'); diff --git a/test/parallel/test-vm-create-context-arg.js b/test/parallel/test-vm-create-context-arg.js index d44eeec18decd5..a0c29762330133 100644 --- a/test/parallel/test-vm-create-context-arg.js +++ b/test/parallel/test-vm-create-context-arg.js @@ -1,15 +1,15 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var vm = require('vm'); assert.throws(function() { - var ctx = vm.createContext('string is not supported'); + vm.createContext('string is not supported'); }, TypeError); assert.doesNotThrow(function() { - var ctx = vm.createContext({ a: 1 }); - ctx = vm.createContext([0, 1, 2, 3]); + vm.createContext({ a: 1 }); + vm.createContext([0, 1, 2, 3]); }); assert.doesNotThrow(function() { diff --git a/test/parallel/test-vm-create-context-circular-reference.js b/test/parallel/test-vm-create-context-circular-reference.js index cb6a90dcaef321..851bebdb088adf 100644 --- a/test/parallel/test-vm-create-context-circular-reference.js +++ b/test/parallel/test-vm-create-context-circular-reference.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var vm = require('vm'); diff --git a/test/parallel/test-vm-cross-context.js b/test/parallel/test-vm-cross-context.js index 20a3792b28578e..5674f582426f1f 100644 --- a/test/parallel/test-vm-cross-context.js +++ b/test/parallel/test-vm-cross-context.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var vm = require('vm'); diff --git a/test/parallel/test-vm-debug-context.js b/test/parallel/test-vm-debug-context.js index 2e86d136bea2fa..b648592eaea901 100644 --- a/test/parallel/test-vm-debug-context.js +++ b/test/parallel/test-vm-debug-context.js @@ -53,6 +53,24 @@ assert.strictEqual(vm.runInDebugContext(undefined), undefined); assert.equal(breaks, 1); })(); +// Can set listeners and breakpoints on a single line file +(function() { + const Debug = vm.runInDebugContext('Debug'); + const fn = require(common.fixturesDir + '/exports-function-with-param'); + let called = false; + + Debug.setListener(function(event, state, data) { + if (data.constructor.name === 'BreakEvent') { + called = true; + } + }); + + Debug.setBreakPoint(fn); + fn('foo'); + assert.strictEqual(Debug.showBreakPoints(fn), '(arg) { [B0]return arg; }'); + assert.strictEqual(called, true); +})(); + // See https://github.com/nodejs/node/issues/1190, fatal errors should not // crash the process. var script = common.fixturesDir + '/vm-run-in-debug-context.js'; diff --git a/test/parallel/test-vm-function-declaration.js b/test/parallel/test-vm-function-declaration.js index 5ff194e12dd8d8..fd41be7564aab0 100644 --- a/test/parallel/test-vm-function-declaration.js +++ b/test/parallel/test-vm-function-declaration.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var vm = require('vm'); diff --git a/test/parallel/test-vm-global-define-property.js b/test/parallel/test-vm-global-define-property.js index f7f3e4f3df7d76..71e6ae9eaa0b73 100644 --- a/test/parallel/test-vm-global-define-property.js +++ b/test/parallel/test-vm-global-define-property.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var vm = require('vm'); diff --git a/test/parallel/test-vm-global-identity.js b/test/parallel/test-vm-global-identity.js index 647edb22b44db0..7d90408b64c2c7 100644 --- a/test/parallel/test-vm-global-identity.js +++ b/test/parallel/test-vm-global-identity.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var vm = require('vm'); diff --git a/test/parallel/test-vm-harmony-proxies.js b/test/parallel/test-vm-harmony-proxies.js index 2f008615ebaf54..78ee144582741a 100644 --- a/test/parallel/test-vm-harmony-proxies.js +++ b/test/parallel/test-vm-harmony-proxies.js @@ -1,19 +1,19 @@ 'use strict'; // Flags: --harmony_proxies -var common = require('../common'); +require('../common'); var assert = require('assert'); var vm = require('vm'); // src/node_contextify.cc filters out the Proxy object from the parent // context. Make sure that the new context has a Proxy object of its own. var sandbox = {}; -var result = vm.runInNewContext('this.Proxy = Proxy', sandbox); +vm.runInNewContext('this.Proxy = Proxy', sandbox); assert(typeof sandbox.Proxy === 'object'); assert(sandbox.Proxy !== Proxy); // Unless we copy the Proxy object explicitly, of course. var sandbox = { Proxy: Proxy }; -var result = vm.runInNewContext('this.Proxy = Proxy', sandbox); +vm.runInNewContext('this.Proxy = Proxy', sandbox); assert(typeof sandbox.Proxy === 'object'); assert(sandbox.Proxy === Proxy); diff --git a/test/parallel/test-vm-harmony-symbols.js b/test/parallel/test-vm-harmony-symbols.js index 86fde1b978ffb2..e4b27c9ebb8579 100644 --- a/test/parallel/test-vm-harmony-symbols.js +++ b/test/parallel/test-vm-harmony-symbols.js @@ -1,16 +1,16 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var vm = require('vm'); // The sandbox should have its own Symbol constructor. var sandbox = {}; -var result = vm.runInNewContext('this.Symbol = Symbol', sandbox); +vm.runInNewContext('this.Symbol = Symbol', sandbox); assert(typeof sandbox.Symbol === 'function'); assert(sandbox.Symbol !== Symbol); // Unless we copy the Symbol constructor explicitly, of course. var sandbox = { Symbol: Symbol }; -var result = vm.runInNewContext('this.Symbol = Symbol', sandbox); +vm.runInNewContext('this.Symbol = Symbol', sandbox); assert(typeof sandbox.Symbol === 'function'); assert(sandbox.Symbol === Symbol); diff --git a/test/parallel/test-vm-is-context.js b/test/parallel/test-vm-is-context.js index 5a46a452b91634..cc106a15fbfc61 100644 --- a/test/parallel/test-vm-is-context.js +++ b/test/parallel/test-vm-is-context.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var vm = require('vm'); diff --git a/test/parallel/test-vm-new-script-new-context.js b/test/parallel/test-vm-new-script-new-context.js index e3cc6e91cb432a..81f9b57593ea2f 100644 --- a/test/parallel/test-vm-new-script-new-context.js +++ b/test/parallel/test-vm-new-script-new-context.js @@ -21,7 +21,6 @@ assert.throws(function() { console.error('undefined reference'); -var error; script = new Script('foo.bar = 5;'); assert.throws(function() { script.runInNewContext(); @@ -41,7 +40,9 @@ code = 'foo = 1;' + foo = 2; obj = { foo: 0, baz: 3 }; script = new Script(code); +/* eslint-disable no-unused-vars */ var baz = script.runInNewContext(obj); +/* eslint-enable no-unused-vars */ assert.equal(1, obj.foo); assert.equal(2, obj.bar); assert.equal(2, foo); diff --git a/test/parallel/test-vm-preserves-property.js b/test/parallel/test-vm-preserves-property.js index 85ce2d6e8165c8..9786ee54a7cffd 100644 --- a/test/parallel/test-vm-preserves-property.js +++ b/test/parallel/test-vm-preserves-property.js @@ -1,6 +1,6 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var vm = require('vm'); diff --git a/test/parallel/test-vm-run-in-new-context.js b/test/parallel/test-vm-run-in-new-context.js index da14a041face31..2b32eccf408ff0 100644 --- a/test/parallel/test-vm-run-in-new-context.js +++ b/test/parallel/test-vm-run-in-new-context.js @@ -29,7 +29,9 @@ code = 'foo = 1;' + 'if (baz !== 3) throw new Error(\'test fail\');'; foo = 2; obj = { foo: 0, baz: 3 }; +/* eslint-disable no-unused-vars */ var baz = vm.runInNewContext(code, obj); +/* eslint-enable no-unused-vars */ assert.equal(1, obj.foo); assert.equal(2, obj.bar); assert.equal(2, foo); diff --git a/test/parallel/test-vm-static-this.js b/test/parallel/test-vm-static-this.js index fb9cb764f8422c..a5f5ad9415a828 100644 --- a/test/parallel/test-vm-static-this.js +++ b/test/parallel/test-vm-static-this.js @@ -25,7 +25,9 @@ code = 'foo = 1;' + 'if (typeof baz !== \'undefined\') throw new Error(\'test fail\');'; foo = 2; obj = { foo: 0, baz: 3 }; +/* eslint-disable no-unused-vars */ var baz = vm.runInThisContext(code); +/* eslint-enable no-unused-vars */ assert.equal(0, obj.foo); assert.equal(2, bar); assert.equal(1, foo); diff --git a/test/parallel/test-vm-symbols.js b/test/parallel/test-vm-symbols.js index d7d0ffe3af6157..d3419af559a2f2 100644 --- a/test/parallel/test-vm-symbols.js +++ b/test/parallel/test-vm-symbols.js @@ -1,6 +1,6 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var vm = require('vm'); diff --git a/test/parallel/test-vm-syntax-error-message.js b/test/parallel/test-vm-syntax-error-message.js index 4b48b0d474a88d..75748b24e193ee 100644 --- a/test/parallel/test-vm-syntax-error-message.js +++ b/test/parallel/test-vm-syntax-error-message.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var child_process = require('child_process'); diff --git a/test/parallel/test-vm-timeout.js b/test/parallel/test-vm-timeout.js index e9511e59230a84..b4dd57bb54d234 100644 --- a/test/parallel/test-vm-timeout.js +++ b/test/parallel/test-vm-timeout.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var vm = require('vm'); diff --git a/test/parallel/test-writedouble.js b/test/parallel/test-writedouble.js index 2a9ab11107f147..4e86182137de29 100644 --- a/test/parallel/test-writedouble.js +++ b/test/parallel/test-writedouble.js @@ -2,7 +2,7 @@ /* * Tests to verify we're writing doubles correctly */ -var common = require('../common'); +require('../common'); var ASSERT = require('assert'); function test(clazz) { diff --git a/test/parallel/test-writefloat.js b/test/parallel/test-writefloat.js index 948bf4910208a5..0cb748d603d0ff 100644 --- a/test/parallel/test-writefloat.js +++ b/test/parallel/test-writefloat.js @@ -2,7 +2,7 @@ /* * Tests to verify we're writing floats correctly */ -var common = require('../common'); +require('../common'); var ASSERT = require('assert'); function test(clazz) { diff --git a/test/parallel/test-writeint.js b/test/parallel/test-writeint.js index ee981a157ad761..d05a90d48b5ac6 100644 --- a/test/parallel/test-writeint.js +++ b/test/parallel/test-writeint.js @@ -2,7 +2,7 @@ /* * Tests to verify we're writing signed integers correctly */ -var common = require('../common'); +require('../common'); var ASSERT = require('assert'); function test8(clazz) { diff --git a/test/parallel/test-writeuint.js b/test/parallel/test-writeuint.js index baa12aa57666f3..843cc423072225 100644 --- a/test/parallel/test-writeuint.js +++ b/test/parallel/test-writeuint.js @@ -2,7 +2,7 @@ /* * A battery of tests to help us read a series of uints */ -var common = require('../common'); +require('../common'); var ASSERT = require('assert'); /* diff --git a/test/parallel/test-zlib-close-after-write.js b/test/parallel/test-zlib-close-after-write.js index c02ff33fb5eb63..b47deddd8889e9 100644 --- a/test/parallel/test-zlib-close-after-write.js +++ b/test/parallel/test-zlib-close-after-write.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var zlib = require('zlib'); diff --git a/test/parallel/test-zlib-const.js b/test/parallel/test-zlib-const.js index 511eca613a5229..b7eb31d2c5f48c 100644 --- a/test/parallel/test-zlib-const.js +++ b/test/parallel/test-zlib-const.js @@ -1,5 +1,5 @@ /* eslint-disable strict */ -var common = require('../common'); +require('../common'); var assert = require('assert'); var zlib = require('zlib'); diff --git a/test/parallel/test-zlib-convenience-methods.js b/test/parallel/test-zlib-convenience-methods.js index 5808bdf04a8f14..70c102efd2862c 100644 --- a/test/parallel/test-zlib-convenience-methods.js +++ b/test/parallel/test-zlib-convenience-methods.js @@ -1,7 +1,7 @@ 'use strict'; // test convenience methods with and without options supplied -var common = require('../common'); +require('../common'); var assert = require('assert'); var zlib = require('zlib'); diff --git a/test/parallel/test-zlib-dictionary.js b/test/parallel/test-zlib-dictionary.js index 109f4273f767d0..f8ce5bfbe87df4 100644 --- a/test/parallel/test-zlib-dictionary.js +++ b/test/parallel/test-zlib-dictionary.js @@ -1,10 +1,9 @@ 'use strict'; // test compression/decompression with dictionary -var common = require('../common'); -var assert = require('assert'); -var zlib = require('zlib'); -var path = require('path'); +require('../common'); +const assert = require('assert'); +const zlib = require('zlib'); var spdyDict = new Buffer([ 'optionsgetheadpostputdeletetraceacceptaccept-charsetaccept-encodingaccept-', diff --git a/test/parallel/test-zlib-flush-drain.js b/test/parallel/test-zlib-flush-drain.js index 93966cd85d269a..f04dac9f0699ac 100644 --- a/test/parallel/test-zlib-flush-drain.js +++ b/test/parallel/test-zlib-flush-drain.js @@ -1,8 +1,7 @@ 'use strict'; -const common = require('../common'); +require('../common'); const assert = require('assert'); const zlib = require('zlib'); -const path = require('path'); const bigData = new Buffer(10240).fill('x'); diff --git a/test/parallel/test-zlib-from-string.js b/test/parallel/test-zlib-from-string.js index 49f4d139c148d9..14c747fc433692 100644 --- a/test/parallel/test-zlib-from-string.js +++ b/test/parallel/test-zlib-from-string.js @@ -1,7 +1,7 @@ 'use strict'; // test compressing and uncompressing a string with zlib -var common = require('../common'); +require('../common'); var assert = require('assert'); var zlib = require('zlib'); diff --git a/test/parallel/test-zlib-invalid-input.js b/test/parallel/test-zlib-invalid-input.js index e1e81bacc1a499..9850c6078c5320 100644 --- a/test/parallel/test-zlib-invalid-input.js +++ b/test/parallel/test-zlib-invalid-input.js @@ -1,8 +1,8 @@ 'use strict'; // test uncompressing invalid input -var common = require('../common'), - assert = require('assert'), +require('../common'); +var assert = require('assert'), zlib = require('zlib'); var nonStringInputs = [1, true, {a: 1}, ['a']]; diff --git a/test/parallel/test-zlib-write-after-close.js b/test/parallel/test-zlib-write-after-close.js index a1d9adb6d9b996..b1d35935e8ab19 100644 --- a/test/parallel/test-zlib-write-after-close.js +++ b/test/parallel/test-zlib-write-after-close.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var zlib = require('zlib'); diff --git a/test/parallel/test-zlib-write-after-flush.js b/test/parallel/test-zlib-write-after-flush.js index 4c53ca49ebf758..fa70c5f14dee6c 100644 --- a/test/parallel/test-zlib-write-after-flush.js +++ b/test/parallel/test-zlib-write-after-flush.js @@ -1,8 +1,7 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var zlib = require('zlib'); -var fs = require('fs'); var gzip = zlib.createGzip(); var gunz = zlib.createUnzip(); diff --git a/test/parallel/test-zlib-zero-byte.js b/test/parallel/test-zlib-zero-byte.js index 9aa260a7f3149d..826a9c7c79793d 100644 --- a/test/parallel/test-zlib-zero-byte.js +++ b/test/parallel/test-zlib-zero-byte.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var zlib = require('zlib'); diff --git a/test/pummel/test-dtrace-jsstack.js b/test/pummel/test-dtrace-jsstack.js index 67194a3dd77f53..2e5c8670553138 100644 --- a/test/pummel/test-dtrace-jsstack.js +++ b/test/pummel/test-dtrace-jsstack.js @@ -1,8 +1,7 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var os = require('os'); -var util = require('util'); if (os.type() != 'SunOS') { console.log('1..0 # Skipped: no DTRACE support'); @@ -13,7 +12,6 @@ if (os.type() != 'SunOS') { * Some functions to create a recognizable stack. */ var frames = [ 'stalloogle', 'bagnoogle', 'doogle' ]; -var expected; var stalloogle = function(str) { expected = str; @@ -34,8 +32,6 @@ var doogle = function() { }; var spawn = require('child_process').spawn; -var prefix = '/var/tmp/node'; -var corefile = prefix + '.' + process.pid; /* * We're going to use DTrace to stop us, gcore us, and set us running again diff --git a/test/pummel/test-fs-watch-file.js b/test/pummel/test-fs-watch-file.js index 7b57803dd4ec93..4e08e9e9d1cc9b 100644 --- a/test/pummel/test-fs-watch-file.js +++ b/test/pummel/test-fs-watch-file.js @@ -9,7 +9,6 @@ var watchSeenTwo = 0; var watchSeenThree = 0; var watchSeenFour = 0; -var startDir = process.cwd(); var testDir = common.tmpDir; var filenameOne = 'watch.txt'; diff --git a/test/pummel/test-fs-watch-non-recursive.js b/test/pummel/test-fs-watch-non-recursive.js index 2586aec59b2d94..ead7de9e28dc47 100644 --- a/test/pummel/test-fs-watch-non-recursive.js +++ b/test/pummel/test-fs-watch-non-recursive.js @@ -1,6 +1,5 @@ 'use strict'; var common = require('../common'); -var assert = require('assert'); var path = require('path'); var fs = require('fs'); diff --git a/test/pummel/test-http-client-reconnect-bug.js b/test/pummel/test-http-client-reconnect-bug.js index bd852e45f19410..12a6fecc7050e8 100644 --- a/test/pummel/test-http-client-reconnect-bug.js +++ b/test/pummel/test-http-client-reconnect-bug.js @@ -3,7 +3,6 @@ var common = require('../common'); var assert = require('assert'); var net = require('net'), - util = require('util'), http = require('http'); var errorCount = 0; diff --git a/test/pummel/test-http-upload-timeout.js b/test/pummel/test-http-upload-timeout.js index 08132e3c7594d1..d1be5311db0c00 100644 --- a/test/pummel/test-http-upload-timeout.js +++ b/test/pummel/test-http-upload-timeout.js @@ -3,7 +3,6 @@ // data in random intervals. Clients are also randomly disconnecting until there // are no more clients left. If no false timeout occurs, this test has passed. var common = require('../common'), - assert = require('assert'), http = require('http'), server = http.createServer(), connections = 0; diff --git a/test/pummel/test-https-no-reader.js b/test/pummel/test-https-no-reader.js index 753687e67a5589..d9d2b64cc73d62 100644 --- a/test/pummel/test-https-no-reader.js +++ b/test/pummel/test-https-no-reader.js @@ -18,8 +18,6 @@ var options = { }; var buf = new Buffer(1024 * 1024); -var sent = 0; -var received = 0; var server = https.createServer(options, function(req, res) { res.writeHead(200); @@ -30,7 +28,6 @@ var server = https.createServer(options, function(req, res) { }); server.listen(common.PORT, function() { - var resumed = false; var req = https.request({ method: 'POST', port: common.PORT, diff --git a/test/pummel/test-keep-alive.js b/test/pummel/test-keep-alive.js index c2ec7fd81f1691..46190555b27263 100644 --- a/test/pummel/test-keep-alive.js +++ b/test/pummel/test-keep-alive.js @@ -5,7 +5,6 @@ var common = require('../common'); var assert = require('assert'); var spawn = require('child_process').spawn; var http = require('http'); -var path = require('path'); var url = require('url'); if (common.isWindows) { diff --git a/test/pummel/test-next-tick-infinite-calls.js b/test/pummel/test-next-tick-infinite-calls.js index d4fdb3496423eb..18223885d6cc19 100644 --- a/test/pummel/test-next-tick-infinite-calls.js +++ b/test/pummel/test-next-tick-infinite-calls.js @@ -1,6 +1,5 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); +require('../common'); var complete = 0; diff --git a/test/pummel/test-process-hrtime.js b/test/pummel/test-process-hrtime.js index 4fd66c03907aac..04225bae421b1a 100644 --- a/test/pummel/test-process-hrtime.js +++ b/test/pummel/test-process-hrtime.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var start = process.hrtime(); diff --git a/test/pummel/test-process-uptime.js b/test/pummel/test-process-uptime.js index a80806c2099cb1..8d2d88b74f736f 100644 --- a/test/pummel/test-process-uptime.js +++ b/test/pummel/test-process-uptime.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); console.error(process.uptime()); diff --git a/test/pummel/test-regress-GH-814.js b/test/pummel/test-regress-GH-814.js index 4ed4b31ae28143..820903d68873e7 100644 --- a/test/pummel/test-regress-GH-814.js +++ b/test/pummel/test-regress-GH-814.js @@ -46,7 +46,7 @@ var timeToQuit = Date.now() + 8e3; //Test during no more than this seconds. } } else { - throw Error("Buffer GC'ed test -> FAIL"); + throw new Error("Buffer GC'ed test -> FAIL"); } if (Date.now() < timeToQuit) { diff --git a/test/pummel/test-regress-GH-814_2.js b/test/pummel/test-regress-GH-814_2.js index 9de1a2c3f3b86b..d7c6d947919d59 100644 --- a/test/pummel/test-regress-GH-814_2.js +++ b/test/pummel/test-regress-GH-814_2.js @@ -21,7 +21,7 @@ function tailCB(data) { console.error('[FAIL]\n DATA -> '); console.error(data); console.error('\n'); - throw Error('Buffers GC test -> FAIL'); + throw new Error('Buffers GC test -> FAIL'); } } diff --git a/test/pummel/test-regress-GH-892.js b/test/pummel/test-regress-GH-892.js index 67f9dd95aebe5f..11cab1b8b6230e 100644 --- a/test/pummel/test-regress-GH-892.js +++ b/test/pummel/test-regress-GH-892.js @@ -17,11 +17,7 @@ var https = require('https'); var fs = require('fs'); -var PORT = 8000; - - var bytesExpected = 1024 * 1024 * 32; -var gotResponse = false; var started = false; diff --git a/test/pummel/test-stream-pipe-multi.js b/test/pummel/test-stream-pipe-multi.js index 807e3c1415154e..44d6973938debe 100644 --- a/test/pummel/test-stream-pipe-multi.js +++ b/test/pummel/test-stream-pipe-multi.js @@ -2,7 +2,7 @@ // Test that having a bunch of streams piping in parallel // doesn't break anything. -var common = require('../common'); +require('../common'); var assert = require('assert'); var Stream = require('stream').Stream; var rr = []; diff --git a/test/pummel/test-stream2-basic.js b/test/pummel/test-stream2-basic.js index fe921dc0058374..564a3f7f42d5a0 100644 --- a/test/pummel/test-stream2-basic.js +++ b/test/pummel/test-stream2-basic.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var R = require('_stream_readable'); var assert = require('assert'); @@ -157,7 +157,6 @@ test('pipe', function(t) { 'xxxxx' ]; var w = new TestWriter(); - var flush = true; w.on('end', function(received) { t.same(received, expect); @@ -439,7 +438,6 @@ test('adding readable triggers data flow', function(t) { r.push(new Buffer('asdf')); }; - var called = false; r.on('readable', function() { onReadable = true; r.read(); diff --git a/test/pummel/test-timer-wrap.js b/test/pummel/test-timer-wrap.js index 62ba69d3fde033..d2e96e066d2fb1 100644 --- a/test/pummel/test-timer-wrap.js +++ b/test/pummel/test-timer-wrap.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var timeouts = 0; diff --git a/test/pummel/test-timer-wrap2.js b/test/pummel/test-timer-wrap2.js index b289a85644a068..87497b2685f5d3 100644 --- a/test/pummel/test-timer-wrap2.js +++ b/test/pummel/test-timer-wrap2.js @@ -1,9 +1,8 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); +require('../common'); // Test that allocating a timer does not increase the loop's reference // count. var Timer = process.binding('timer_wrap').Timer; -var t = new Timer(); +new Timer(); diff --git a/test/pummel/test-timers.js b/test/pummel/test-timers.js index 2225da91edcf5f..d911beb6b09288 100644 --- a/test/pummel/test-timers.js +++ b/test/pummel/test-timers.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var WINDOW = 200; // why is does this need to be so big? @@ -91,12 +91,12 @@ function t() { expectedTimeouts--; } -var w = setTimeout(t, 200); -var x = setTimeout(t, 200); +setTimeout(t, 200); +setTimeout(t, 200); var y = setTimeout(t, 200); clearTimeout(y); -var z = setTimeout(t, 200); +setTimeout(t, 200); clearTimeout(y); diff --git a/test/pummel/test-tls-securepair-client.js b/test/pummel/test-tls-securepair-client.js index aaf8e628d6a2bc..3d33ef8f21623f 100644 --- a/test/pummel/test-tls-securepair-client.js +++ b/test/pummel/test-tls-securepair-client.js @@ -17,9 +17,7 @@ var join = require('path').join; var net = require('net'); var assert = require('assert'); var fs = require('fs'); -var crypto = require('crypto'); var tls = require('tls'); -var exec = require('child_process').exec; var spawn = require('child_process').spawn; test1(); @@ -47,8 +45,6 @@ function test(keyfn, certfn, check, next) { // EADDRINUSE. var PORT = common.PORT + 5; - var connections = 0; - keyfn = join(common.fixturesDir, keyfn); var key = fs.readFileSync(keyfn).toString(); diff --git a/test/pummel/test-vm-memleak.js b/test/pummel/test-vm-memleak.js index f93f34127f9219..c6623991922da9 100644 --- a/test/pummel/test-vm-memleak.js +++ b/test/pummel/test-vm-memleak.js @@ -1,8 +1,8 @@ 'use strict'; // Flags: --max_old_space_size=32 +require('../common'); var assert = require('assert'); -var common = require('../common'); var start = Date.now(); var maxMem = 0; diff --git a/test/pummel/test-watch-file.js b/test/pummel/test-watch-file.js index 1d0ef77d543e43..b87711c7a17c45 100644 --- a/test/pummel/test-watch-file.js +++ b/test/pummel/test-watch-file.js @@ -6,7 +6,6 @@ var fs = require('fs'); var path = require('path'); var f = path.join(common.fixturesDir, 'x.txt'); -var f2 = path.join(common.fixturesDir, 'x2.txt'); console.log('watching for changes of ' + f); diff --git a/test/sequential/test-child-process-execsync.js b/test/sequential/test-child-process-execsync.js index 0bc4e02c65edb8..205485c9ebbc48 100644 --- a/test/sequential/test-child-process-execsync.js +++ b/test/sequential/test-child-process-execsync.js @@ -1,7 +1,6 @@ 'use strict'; var common = require('../common'); var assert = require('assert'); -var os = require('os'); var execSync = require('child_process').execSync; var execFileSync = require('child_process').execFileSync; diff --git a/test/sequential/test-child-process-fork-getconnections.js b/test/sequential/test-child-process-fork-getconnections.js index 934df28d7988b7..a7521f1635fb39 100644 --- a/test/sequential/test-child-process-fork-getconnections.js +++ b/test/sequential/test-child-process-fork-getconnections.js @@ -6,7 +6,7 @@ const net = require('net'); const count = 12; if (process.argv[2] === 'child') { - let sockets = []; + const sockets = []; process.on('message', function(m, socket) { function sendClosed(id) { @@ -42,7 +42,7 @@ if (process.argv[2] === 'child') { }); const server = net.createServer(); - let sockets = []; + const sockets = []; let sent = 0; server.on('connection', function(socket) { diff --git a/test/sequential/test-debug-args.js b/test/sequential/test-debug-args.js index eb1533d4418a55..cb70c185f5419b 100644 --- a/test/sequential/test-debug-args.js +++ b/test/sequential/test-debug-args.js @@ -1,7 +1,7 @@ 'use strict'; // Flags: --debugger -var common = require('../common'); +require('../common'); var assert = require('assert'); assert.notEqual(process.execArgv.indexOf('--debugger'), -1); diff --git a/test/sequential/test-deprecation-flags.js b/test/sequential/test-deprecation-flags.js index ca325654c55d80..037f40f07e0a25 100644 --- a/test/sequential/test-deprecation-flags.js +++ b/test/sequential/test-deprecation-flags.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var execFile = require('child_process').execFile; var depmod = require.resolve('../fixtures/deprecated.js'); diff --git a/test/sequential/test-memory-usage-emfile.js b/test/sequential/test-memory-usage-emfile.js index 6b439049805786..92c103669a9a85 100644 --- a/test/sequential/test-memory-usage-emfile.js +++ b/test/sequential/test-memory-usage-emfile.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var fs = require('fs'); diff --git a/test/sequential/test-module-loading.js b/test/sequential/test-module-loading.js index 94aa36240b2faf..ead3447320c50a 100644 --- a/test/sequential/test-module-loading.js +++ b/test/sequential/test-module-loading.js @@ -283,3 +283,11 @@ process.on('exit', function() { // #1440 Loading files with a byte order marker. assert.equal(42, require('../fixtures/utf8-bom.js')); assert.equal(42, require('../fixtures/utf8-bom.json')); + +// Error on the first line of a module should +// have the correct line number +assert.throws(function() { + require('../fixtures/test-error-first-line-offset.js'); +}, function(err) { + return /test-error-first-line-offset.js:1:/.test(err.stack); +}, 'Expected appearance of proper offset in Error stack'); diff --git a/test/sequential/test-net-GH-5504.js b/test/sequential/test-net-GH-5504.js index 9526993dfd12c2..179b3ae3c2e241 100644 --- a/test/sequential/test-net-GH-5504.js +++ b/test/sequential/test-net-GH-5504.js @@ -1,6 +1,5 @@ 'use strict'; var common = require('../common'); -var assert = require('assert'); // this test only fails with CentOS 6.3 using kernel version 2.6.32 // On other linuxes and darwin, the `read` call gets an ECONNRESET in diff --git a/test/sequential/test-net-listen-exclusive-random-ports.js b/test/sequential/test-net-listen-exclusive-random-ports.js index c32273a59b2a50..f46f9a01d773ce 100644 --- a/test/sequential/test-net-listen-exclusive-random-ports.js +++ b/test/sequential/test-net-listen-exclusive-random-ports.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var cluster = require('cluster'); var net = require('net'); diff --git a/test/sequential/test-pump-file2tcp.js b/test/sequential/test-pump-file2tcp.js index f5949085e0aec3..f99ae1c5d79ea6 100644 --- a/test/sequential/test-pump-file2tcp.js +++ b/test/sequential/test-pump-file2tcp.js @@ -28,7 +28,6 @@ server.listen(common.PORT, function() { }); var buffer = ''; -var count = 0; server.on('listening', function() { }); diff --git a/test/sequential/test-regress-GH-1697.js b/test/sequential/test-regress-GH-1697.js index ff5754f357dfc1..ba7f90ecf00951 100644 --- a/test/sequential/test-regress-GH-1697.js +++ b/test/sequential/test-regress-GH-1697.js @@ -1,8 +1,7 @@ 'use strict'; var common = require('../common'); var net = require('net'), - cp = require('child_process'), - util = require('util'); + cp = require('child_process'); if (process.argv[2] === 'server') { // Server diff --git a/test/sequential/test-regress-GH-1726.js b/test/sequential/test-regress-GH-1726.js index 859ab6cc5e4253..c5f0bba1335264 100644 --- a/test/sequential/test-regress-GH-1726.js +++ b/test/sequential/test-regress-GH-1726.js @@ -4,7 +4,7 @@ // exit when its child exits. // https://github.com/joyent/node/issues/1726 -var common = require('../common'); +require('../common'); var assert = require('assert'); var ch = require('child_process'); diff --git a/test/sequential/test-regress-GH-819.js b/test/sequential/test-regress-GH-819.js index e459587d97cba9..20ca75c793ce24 100644 --- a/test/sequential/test-regress-GH-819.js +++ b/test/sequential/test-regress-GH-819.js @@ -1,7 +1,6 @@ 'use strict'; -var common = require('../common'); +require('../common'); var net = require('net'); -var assert = require('assert'); // Connect to something that we need to DNS resolve var c = net.createConnection(80, 'google.com'); diff --git a/test/sequential/test-setproctitle.js b/test/sequential/test-setproctitle.js index 11395f4fdbc52f..40107f5774962f 100644 --- a/test/sequential/test-setproctitle.js +++ b/test/sequential/test-setproctitle.js @@ -7,7 +7,7 @@ if ('linux freebsd darwin'.indexOf(process.platform) === -1) { return; } -var common = require('../common'); +require('../common'); var assert = require('assert'); var exec = require('child_process').exec; var path = require('path'); diff --git a/test/sequential/test-sigint-infinite-loop.js b/test/sequential/test-sigint-infinite-loop.js index 8211aeb69ec5db..1570f9c59dd5d3 100644 --- a/test/sequential/test-sigint-infinite-loop.js +++ b/test/sequential/test-sigint-infinite-loop.js @@ -2,7 +2,7 @@ // This test is to assert that we can SIGINT a script which loops forever. // Ref(http): // groups.google.com/group/nodejs-dev/browse_thread/thread/e20f2f8df0296d3f -var common = require('../common'); +require('../common'); var assert = require('assert'); var spawn = require('child_process').spawn; diff --git a/test/sequential/test-stdin-child-proc.js b/test/sequential/test-stdin-child-proc.js index 93bf265b8b0020..0189e94d5d4c8c 100644 --- a/test/sequential/test-stdin-child-proc.js +++ b/test/sequential/test-stdin-child-proc.js @@ -1,7 +1,7 @@ 'use strict'; // This tests that pausing and resuming stdin does not hang and timeout // when done in a child process. See test/simple/test-stdin-pause-resume.js -var common = require('../common'); +require('../common'); var child_process = require('child_process'); var path = require('path'); child_process.spawn(process.execPath, diff --git a/test/sequential/test-stdin-pipe-resume.js b/test/sequential/test-stdin-pipe-resume.js index dbac78d78c5e12..cd409a1d236f53 100644 --- a/test/sequential/test-stdin-pipe-resume.js +++ b/test/sequential/test-stdin-pipe-resume.js @@ -1,6 +1,6 @@ 'use strict'; // This tests that piping stdin will cause it to resume() as well. -var common = require('../common'); +require('../common'); var assert = require('assert'); if (process.argv[2] === 'child') { diff --git a/test/sequential/test-stdin-script-child.js b/test/sequential/test-stdin-script-child.js index c5d5d6d44281e3..ad65734364e707 100644 --- a/test/sequential/test-stdin-script-child.js +++ b/test/sequential/test-stdin-script-child.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var spawn = require('child_process').spawn; diff --git a/test/sequential/test-stdout-cannot-be-closed-child-process-pipe.js b/test/sequential/test-stdout-cannot-be-closed-child-process-pipe.js index c6f5aecd40e262..a138108fae7e01 100644 --- a/test/sequential/test-stdout-cannot-be-closed-child-process-pipe.js +++ b/test/sequential/test-stdout-cannot-be-closed-child-process-pipe.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); if (process.argv[2] === 'child') diff --git a/test/sequential/test-stdout-close-catch.js b/test/sequential/test-stdout-close-catch.js index f0ecf9a7c4b725..470fa9843cb9de 100644 --- a/test/sequential/test-stdout-close-catch.js +++ b/test/sequential/test-stdout-close-catch.js @@ -3,7 +3,6 @@ var common = require('../common'); var assert = require('assert'); var path = require('path'); var child_process = require('child_process'); -var fs = require('fs'); var testScript = path.join(common.fixturesDir, 'catch-stdout-error.js'); diff --git a/test/sequential/test-stdout-stderr-reading.js b/test/sequential/test-stdout-stderr-reading.js index 82fd51cedda1de..2cc029c501c162 100644 --- a/test/sequential/test-stdout-stderr-reading.js +++ b/test/sequential/test-stdout-stderr-reading.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); // verify that stdout is never read from. diff --git a/test/sequential/test-stream2-fs.js b/test/sequential/test-stream2-fs.js index 96ab97174b2478..e775dd7c0ab690 100644 --- a/test/sequential/test-stream2-fs.js +++ b/test/sequential/test-stream2-fs.js @@ -1,6 +1,5 @@ 'use strict'; var common = require('../common'); -var R = require('_stream_readable'); var assert = require('assert'); var fs = require('fs'); @@ -41,7 +40,6 @@ var w = new TestWriter(); w.on('results', function(res) { console.error(res, w.length); assert.equal(w.length, size); - var l = 0; assert.deepEqual(res.map(function(c) { return c.length; }), expectLengths); diff --git a/test/sequential/test-stream2-stderr-sync.js b/test/sequential/test-stream2-stderr-sync.js index ccbdc55e4feaf9..c7daaa6b083205 100644 --- a/test/sequential/test-stream2-stderr-sync.js +++ b/test/sequential/test-stream2-stderr-sync.js @@ -1,11 +1,7 @@ 'use strict'; // Make sure that sync writes to stderr get processed before exiting. -var common = require('../common'); -var assert = require('assert'); -var util = require('util'); - -var errnoException = util._errnoException; +require('../common'); function parent() { var spawn = require('child_process').spawn; diff --git a/test/sequential/test-sync-fileread.js b/test/sequential/test-sync-fileread.js index 24a80d96c2601b..6208e4c619efc7 100644 --- a/test/sequential/test-sync-fileread.js +++ b/test/sequential/test-sync-fileread.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); var path = require('path'); var fs = require('fs'); diff --git a/test/sequential/test-tcp-wrap-listen.js b/test/sequential/test-tcp-wrap-listen.js index a2c07a7a9ce2a2..44254c3d3f39aa 100644 --- a/test/sequential/test-tcp-wrap-listen.js +++ b/test/sequential/test-tcp-wrap-listen.js @@ -12,7 +12,7 @@ assert.equal(0, r); server.listen(128); -var slice, sliceCount = 0, eofCount = 0; +var sliceCount = 0, eofCount = 0; var writeCount = 0; var recvCount = 0; diff --git a/test/sequential/test-util-debug.js b/test/sequential/test-util-debug.js index 02d30449a9944b..5f0306e5e01645 100644 --- a/test/sequential/test-util-debug.js +++ b/test/sequential/test-util-debug.js @@ -1,5 +1,5 @@ 'use strict'; -var common = require('../common'); +require('../common'); var assert = require('assert'); if (process.argv[2] === 'child') diff --git a/test/timers/test-timers-reliability.js b/test/timers/test-timers-reliability.js index b4332468bc2ec3..76aa6ea31afe4d 100644 --- a/test/timers/test-timers-reliability.js +++ b/test/timers/test-timers-reliability.js @@ -1,7 +1,7 @@ 'use strict'; // FaketimeFlags: --exclude-monotonic -f '2014-07-21 09:00:00' -var common = require('../common'); +require('../common'); var Timer = process.binding('timer_wrap').Timer; var assert = require('assert'); @@ -44,7 +44,7 @@ monoTimer.ontimeout = function() { monoTimer.start(300, 0); -var timer = setTimeout(function() { +setTimeout(function() { timerFired = true; }, 200); diff --git a/tools/cpplint.py b/tools/cpplint.py index 4c4f577b34c9d7..3019395d62df84 100644 --- a/tools/cpplint.py +++ b/tools/cpplint.py @@ -1,4 +1,4 @@ -#!/usr/bin/python2.4 +#!/usr/bin/env python # # Copyright (c) 2009 Google Inc. All rights reserved. # @@ -88,7 +88,8 @@ import string import sys import unicodedata - +import logging +logger = logging.getLogger('testrunner') _USAGE = """ Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...] @@ -139,6 +140,9 @@ the top-level categories like 'build' and 'whitespace' will also be printed. If 'detailed' is provided, then a count is provided for each category like 'build/class'. + + logfile=filename + Write TAP output to a logfile. """ # We categorize each error message we print. Here are the categories. @@ -541,6 +545,11 @@ def SetFilters(self, filters): raise ValueError('Every filter in --filters must start with + or -' ' (%s does not)' % filt) + def setOutputFile(self, filename): + """attempts to create a file which we write output to.""" + fh = logging.FileHandler(filename, mode='wb') + logger.addHandler(fh) + def ResetErrorCounts(self): """Sets the module's error statistic back to zero.""" self.error_count = 0 @@ -558,10 +567,11 @@ def IncrementErrorCount(self, category): def PrintErrorCounts(self): """Print a summary of errors by category, and the total.""" - for category, count in self.errors_by_category.iteritems(): - sys.stderr.write('Category \'%s\' errors found: %d\n' % - (category, count)) - sys.stderr.write('Total errors found: %d\n' % self.error_count) + if not _cpplint_state.output_format == 'tap': + for category, count in self.errors_by_category.iteritems(): + sys.stderr.write('Category \'%s\' errors found: %d\n' % + (category, count)) + sys.stderr.write('Total errors found: %d\n' % self.error_count) _cpplint_state = _CppLintState() @@ -608,6 +618,9 @@ def _SetFilters(filters): """ _cpplint_state.SetFilters(filters) +def _setOutputFile(filename): + _cpplint_state.setOutputFile(filename) + class _FunctionState(object): """Tracks current function name and the number of lines in its body.""" @@ -786,6 +799,15 @@ def Error(filename, linenum, category, confidence, message): if _cpplint_state.output_format == 'vs7': sys.stderr.write('%s(%s): %s [%s] [%d]\n' % ( filename, linenum, message, category, confidence)) + elif _cpplint_state.output_format == 'tap': + template = ('not ok %s\n' + ' ---\n' + ' message: %s\n' + ' data:\n' + ' line: %d\n' + ' ruleId: %s\n' + ' ...') + logger.info(template % (filename, message, linenum, category)) else: sys.stderr.write('%s:%s: %s [%s] [%d]\n' % ( filename, linenum, message, category, confidence)) @@ -2069,7 +2091,7 @@ def CheckStyle(filename, clean_lines, linenum, file_extension, error): initial_spaces += 1 if line and line[-1].isspace(): error(filename, linenum, 'whitespace/end_of_line', 4, - 'Line ends in whitespace. Consider deleting these extra spaces.') + 'Line ends in whitespace. Consider deleting these extra spaces.') # There are certain situations we allow one space, notably for labels elif ((initial_spaces == 1 or initial_spaces == 3) and not Match(r'\s*\w+\s*:\s*$', cleansed_line)): @@ -3002,7 +3024,8 @@ def ProcessFile(filename, vlevel): 'One or more unexpected \\r (^M) found;' 'better to use only a \\n') - sys.stderr.write('Done processing %s\n' % filename) + if not _cpplint_state.output_format == 'tap': + sys.stderr.write('Done processing %s\n' % filename) def PrintUsage(message): @@ -3041,7 +3064,8 @@ def ParseArguments(args): try: (opts, filenames) = getopt.getopt(args, '', ['help', 'output=', 'verbose=', 'counting=', - 'filter=']) + 'filter=', + 'logfile=']) except getopt.GetoptError: PrintUsage('Invalid arguments.') @@ -3049,13 +3073,14 @@ def ParseArguments(args): output_format = _OutputFormat() filters = '' counting_style = '' + output_filename = '' for (opt, val) in opts: if opt == '--help': PrintUsage(None) elif opt == '--output': - if not val in ('emacs', 'vs7'): - PrintUsage('The only allowed output formats are emacs and vs7.') + if not val in ('emacs', 'vs7', 'tap'): + PrintUsage('The only allowed output formats are emacs, vs7 and tap.') output_format = val elif opt == '--verbose': verbosity = int(val) @@ -3067,6 +3092,8 @@ def ParseArguments(args): if val not in ('total', 'toplevel', 'detailed'): PrintUsage('Valid counting options are total, toplevel, and detailed') counting_style = val + elif opt == '--logfile': + output_filename = val if not filenames: PrintUsage('No files were specified.') @@ -3075,6 +3102,8 @@ def ParseArguments(args): _SetVerboseLevel(verbosity) _SetFilters(filters) _SetCountingStyle(counting_style) + if output_filename: + _setOutputFile(output_filename) return filenames @@ -3089,6 +3118,14 @@ def main(): codecs.getwriter('utf8'), 'replace') + + ch = logging.StreamHandler(sys.stdout) + logger.addHandler(ch) + logger.setLevel(logging.INFO) + + if _cpplint_state.output_format == 'tap': + logger.info('TAP version 13') + _cpplint_state.ResetErrorCounts() for filename in filenames: ProcessFile(filename, _cpplint_state.verbose_level) diff --git a/tools/create_expfile.sh b/tools/create_expfile.sh new file mode 100755 index 00000000000000..ff4420a9e87218 --- /dev/null +++ b/tools/create_expfile.sh @@ -0,0 +1,48 @@ +#!/bin/sh +# This script writes out all the exported symbols to a file +# AIX needs this as sybmols are not exported by an +# executable by default and we need to list +# them specifically in order to export them +# so that they can be used by native add-ons +# +# The raw symbol data is objtained by using nm on +# the .a files which make up the node executable +# +# -Xany makes sure we get symbols on both +# 32 bit and 64 bit as by default we'd only get those +# for 32 bit +# +# -g selects only exported symbols +# +# -C, -B and -p ensure the output is in a format we +# can easily parse and convert into the symbol we need +# +# -C suppresses the demangling of C++ names +# -B gives us output in BSD format +# -p displays the info in a standard portable output format +# +# We only include symbols if they are of the +# following types and don't start with a dot. +# +# T - Global text symbol +# D - Global data symbol +# B - Gobal bss symbol. +# +# the final sort allows us to remove any duplicates +# +# We need to exclude gtest libraries as they are not +# linked into the node executable +# +echo "Searching $1 to write out expfile to $2" + +# this special sequence must be at the start of the exp file +echo "#!." > $2 + +# pull the symbols from the .a files +find $1 -name "*.a" | grep -v gtest \ + | xargs nm -Xany -BCpg \ + | awk '{ + if ((($2 == "T") || ($2 == "D") || ($2 == "B")) && + (substr($3,1,1) != ".")) { print $3 } + }' \ + | sort -u >> $2 diff --git a/tools/eslint-rules/new-with-error.js b/tools/eslint-rules/new-with-error.js new file mode 100644 index 00000000000000..b0f550db2ffa2c --- /dev/null +++ b/tools/eslint-rules/new-with-error.js @@ -0,0 +1,36 @@ +/** + * @fileoverview Require `throw new Error()` rather than `throw Error()` + * @author Rich Trott + */ +'use strict'; + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = function(context) { + + var errorList = context.options.length !== 0 ? context.options : ['Error']; + + return { + 'ThrowStatement': function(node) { + if (node.argument.type === 'CallExpression' && + errorList.indexOf(node.argument.callee.name) !== -1) { + context.report(node, 'Use new keyword when throwing.'); + } + } + }; +}; + +module.exports.schema = { + 'type': 'array', + 'items': [ + { + 'enum': [0, 1, 2] + } + ], + 'additionalItems': { + 'type': 'string' + }, + 'uniqueItems': true +}; diff --git a/tools/gyp_node.py b/tools/gyp_node.py index 7b495055c180c8..064abe30aa209c 100755 --- a/tools/gyp_node.py +++ b/tools/gyp_node.py @@ -30,10 +30,12 @@ def run_gyp(args): args.append(os.path.join(node_root, 'node.gyp')) common_fn = os.path.join(node_root, 'common.gypi') options_fn = os.path.join(node_root, 'config.gypi') + options_fips_fn = os.path.join(node_root, 'config_fips.gypi') else: args.append(os.path.join(os.path.abspath(node_root), 'node.gyp')) common_fn = os.path.join(os.path.abspath(node_root), 'common.gypi') options_fn = os.path.join(os.path.abspath(node_root), 'config.gypi') + options_fips_fn = os.path.join(os.path.abspath(node_root), 'config_fips.gypi') if os.path.exists(common_fn): args.extend(['-I', common_fn]) @@ -41,6 +43,9 @@ def run_gyp(args): if os.path.exists(options_fn): args.extend(['-I', options_fn]) + if os.path.exists(options_fips_fn): + args.extend(['-I', options_fips_fn]) + args.append('--depth=' + node_root) # There's a bug with windows which doesn't allow this feature. diff --git a/tools/install.py b/tools/install.py index ff460bbc0f8306..cb86c65699df88 100755 --- a/tools/install.py +++ b/tools/install.py @@ -160,6 +160,10 @@ def headers(action): 'src/node_version.h', ], 'include/node/') + # Add the expfile that is created on AIX + if sys.platform.startswith('aix'): + action(['out/Release/node.exp'], 'include/node/') + subdir_files('deps/cares/include', 'include/node/', action) subdir_files('deps/v8/include', 'include/node/', action) diff --git a/tools/test.py b/tools/test.py index 49db74727aea38..217e72b870a6f8 100755 --- a/tools/test.py +++ b/tools/test.py @@ -145,6 +145,7 @@ def RunSingle(self, parallel, thread_id): sys.platform == 'sunos5' and 'ECONNREFUSED' in output.output.stderr): output = case.Run() + output.diagnostic.append('ECONNREFUSED received, test retried') case.duration = (datetime.now() - start) except IOError, e: return @@ -255,6 +256,10 @@ def HasRun(self, output): class TapProgressIndicator(SimpleProgressIndicator): + def _printDiagnostic(self, messages): + for l in messages.splitlines(): + logger.info('# ' + l) + def Starting(self): logger.info('1..%i' % len(self.cases)) self._done = 0 @@ -270,14 +275,13 @@ def HasRun(self, output): if FLAKY in output.test.outcomes and self.flaky_tests_mode == DONTCARE: status_line = status_line + ' # TODO : Fix flaky test' logger.info(status_line) + self._printDiagnostic("\n".join(output.diagnostic)) if output.HasTimedOut(): - logger.info('# TIMEOUT') + self._printDiagnostic('TIMEOUT') - for l in output.output.stderr.splitlines(): - logger.info('#' + l) - for l in output.output.stdout.splitlines(): - logger.info('#' + l) + self._printDiagnostic(output.output.stderr) + self._printDiagnostic(output.output.stdout) else: skip = skip_regex.search(output.output.stdout) if skip: @@ -288,6 +292,7 @@ def HasRun(self, output): if FLAKY in output.test.outcomes: status_line = status_line + ' # TODO : Fix flaky test' logger.info(status_line) + self._printDiagnostic("\n".join(output.diagnostic)) duration = output.test.duration @@ -490,6 +495,7 @@ def __init__(self, test, command, output, store_unexpected_output): self.command = command self.output = output self.store_unexpected_output = store_unexpected_output + self.diagnostic = [] def UnexpectedOutput(self): if self.HasCrashed(): @@ -1304,6 +1310,8 @@ def BuildOptions(): result.add_option("-r", "--run", help="Divide the tests in m groups (interleaved) and run tests from group n (--run=n,m with n < m)", default="") + result.add_option('--temp-dir', + help='Optional path to change directory used for tests', default=False) return result @@ -1331,7 +1339,10 @@ def ProcessOptions(options): print "The test group to run (n) must be smaller than number of groups (m)." return False if options.J: - options.j = multiprocessing.cpu_count() + # inherit JOBS from environment if provided. some virtualised systems + # tends to exaggerate the number of available cpus/cores. + cores = os.environ.get('JOBS') + options.j = int(cores) if cores is not None else multiprocessing.cpu_count() if options.flaky_tests not in ["run", "skip", "dontcare"]: print "Unknown flaky-tests mode %s" % options.flaky_tests return False @@ -1532,6 +1543,16 @@ def Main(): for rule in globally_unused_rules: print "Rule for '%s' was not used." % '/'.join([str(s) for s in rule.path]) + tempdir = os.environ.get('NODE_TEST_DIR') or options.temp_dir + if tempdir: + try: + os.makedirs(tempdir) + os.environ['NODE_TEST_DIR'] = tempdir + except OSError as exception: + if exception.errno != errno.EEXIST: + print "Could not create the temporary directory", options.temp_dir + sys.exit(1) + if options.report: PrintReport(all_cases) diff --git a/vcbuild.bat b/vcbuild.bat index a9b8774a6c4dc0..4311dfdee01b23 100644 --- a/vcbuild.bat +++ b/vcbuild.bat @@ -15,8 +15,6 @@ if /i "%1"=="/?" goto help set config=Release set target=Build set target_arch=x86 -set debug_arg= -set snapshot_arg= set noprojgen= set nobuild= set nosign= @@ -28,15 +26,14 @@ set licensertf= set jslint= set buildnodeweak= set noetw= -set noetw_arg= set noetw_msi_arg= set noperfctr= -set noperfctr_arg= set noperfctr_msi_arg= set i18n_arg= set download_arg= set release_urls_arg= set build_release= +set configure_flags= :next-arg if "%1"=="" goto args-done @@ -62,7 +59,6 @@ if /i "%1"=="test-internet" set test_args=%test_args% internet&goto arg-ok if /i "%1"=="test-pummel" set test_args=%test_args% pummel&goto arg-ok if /i "%1"=="test-all" set test_args=%test_args% sequential parallel message gc internet pummel&set buildnodeweak=1&set jslint=1&goto arg-ok if /i "%1"=="jslint" set jslint=1&goto arg-ok -@rem Include small-icu support with MSI installer if /i "%1"=="msi" set msi=1&set licensertf=1&set download_arg="--download=all"&set i18n_arg=small-icu&goto arg-ok if /i "%1"=="build-release" set build_release=1&goto arg-ok if /i "%1"=="upload" set upload=1&goto arg-ok @@ -89,15 +85,18 @@ if defined build_release ( set i18n_arg=small-icu ) -if "%config%"=="Debug" set debug_arg=--debug -if defined nosnapshot set snapshot_arg=--without-snapshot -if defined noetw set noetw_arg=--without-etw& set noetw_msi_arg=/p:NoETW=1 -if defined noperfctr set noperfctr_arg=--without-perfctr& set noperfctr_msi_arg=/p:NoPerfCtr=1 -if defined RELEASE_URLBASE set release_urlbase_arg=--release-urlbase=%RELEASE_URLBASE% +if "%config%"=="Debug" set configure_flags=%configure_flags% --debug +if defined nosnapshot set configure_flags=%configure_flags% --without-snapshot +if defined noetw set configure_flags=%configure_flags% --without-etw& set noetw_msi_arg=/p:NoETW=1 +if defined noperfctr set configure_flags=%configure_flags% --without-perfctr& set noperfctr_msi_arg=/p:NoPerfCtr=1 +if defined release_urlbase set release_urlbase_arg=--release-urlbase=%release_urlbase% +if defined download_arg set configure_flags=%configure_flags% %download_arg% -if "%i18n_arg%"=="full-icu" set i18n_arg=--with-intl=full-icu -if "%i18n_arg%"=="small-icu" set i18n_arg=--with-intl=small-icu -if "%i18n_arg%"=="intl-none" set i18n_arg=--with-intl=none +if "%i18n_arg%"=="full-icu" set configure_flags=%configure_flags% --with-intl=full-icu +if "%i18n_arg%"=="small-icu" set configure_flags=%configure_flags% --with-intl=small-icu +if "%i18n_arg%"=="intl-none" set configure_flags=%configure_flags% --with-intl=none + +if defined config_flags set configure_flags=%configure_flags% %config_flags% if not exist "%~dp0deps\icu" goto no-depsicu if "%target%"=="Clean" echo deleting %~dp0deps\icu @@ -168,7 +167,8 @@ goto run if defined noprojgen goto msbuild @rem Generate the VS project. -python configure %download_arg% %i18n_arg% %debug_arg% %snapshot_arg% %noetw_arg% %noperfctr_arg% --dest-cpu=%target_arch% --tag=%TAG% +echo configure %configure_flags% --dest-cpu=%target_arch% --tag=%TAG% +python configure %configure_flags% --dest-cpu=%target_arch% --tag=%TAG% if errorlevel 1 goto create-msvs-files-failed if not exist node.sln goto create-msvs-files-failed echo Project files generated.