diff -Nru nodejs-0.11.10/.gitignore nodejs-0.11.11/.gitignore --- nodejs-0.11.10/.gitignore 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/.gitignore 2014-01-29 01:29:56.000000000 +0000 @@ -42,6 +42,7 @@ /dist-osx /npm.wxs /tools/msvs/npm.wixobj +/test/addons/doc-*/ email.md deps/v8-* ./node_modules diff -Nru nodejs-0.11.10/AUTHORS nodejs-0.11.11/AUTHORS --- nodejs-0.11.10/AUTHORS 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/AUTHORS 2014-01-29 01:29:56.000000000 +0000 @@ -514,3 +514,13 @@ Lev Gimelfarb Peter Flannery Tuğrul Topuz +ayanamist +Lorenz Leutgeb +Brandon Cheng +Alexis Campailla +Yang Tianyang +Tom Gallacher +Jo Liss +Jun Ma +Jacob Hoffman-Andrews +Keith M Wesolowski diff -Nru nodejs-0.11.10/ChangeLog nodejs-0.11.11/ChangeLog --- nodejs-0.11.10/ChangeLog 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/ChangeLog 2014-01-29 01:29:56.000000000 +0000 @@ -1,4 +1,57 @@ -2013.12.31, Version 0.11.10 (Unstable) +2014.01.29, Version 0.11.11 (Unstable) + +* v8: Upgrade to 3.22.24.19 + +* http_parser: Upgrade to 2.2.1 + +* openssl: Upgrade to 1.0.1f + +* uv: Upgrade to 0.11.18 + +* async-listener: revamp of subsystem (Trevor Norris) + +* node: do not ever close stdio (Fedor Indutny) + +* http: use writev on chunked encoding (Trevor Norris) + +* async_wrap/timers: remove Add/RemoveAsyncListener (Trevor Norris) + +* child_process: better error reporting for exec (Fedor Indutny) + +* crypto: add newline to cert and key if not present (Fedor Indutny) + +* crypto: clear error in GetPeerCertificate (Fedor Indutny) + +* crypto: honor default ciphers in client mode (Jacob Hoffman-Andrews) + +* crypto: introduce .setEngine(engine, [flags]) (Fedor Indutny) + +* crypto: support custom pbkdf2 digest methods (Ben Noordhuis) + +* domain: fix off-by-one in Domain.exit() (Ryan Graham) + +* http: concatenate duplicate headers by default (Alex Kocharin) + +* http: do not emit EOF non-readable socket (Fedor Indutny) + +* node: fix argument parsing with -p arg (Alexis Campailla) + +* path: improve POSIX path.join() performance (Jo Liss) + +* tls: emit `clientError` on early socket close (Fedor Indutny) + +* tls: introduce `.setMaxSendFragment(size)` (Fedor Indutny) + +* tls: make cert/pfx optional in tls.createServer() (Ben Noordhuis) + +* tls: process accumulated input (Fedor Indutny) + +* tls: show human-readable error messages (Ben Noordhuis) + +* util: handle escaped forward slashes correctly (Tom Gallacher) + + +2013.12.31, Version 0.11.10 (Unstable), 66931791f06207d1cdfea5ec1529edf3c94026d3 * http_parser: update to 2.2 @@ -445,6 +498,25 @@ * console: `console.dir()` bypasses inspect() methods (Nathan Rajlich) +2014.01.23, Version 0.10.25 (Stable), b0e5f195dfce3e2b99f5091373d49f6616682596 + +* uv: Upgrade to v0.10.23 + +* npm: Upgrade to v1.3.24 + +* v8: Fix enumeration for objects with lots of properties + +* child_process: fix spawn() optional arguments (Sam Roberts) + +* cluster: report more errors to workers (Fedor Indutny) + +* domains: exit() only affects active domains (Ryan Graham) + +* src: OnFatalError handler must abort() (Timothy J Fontaine) + +* stream: writes may return false but forget to emit drain (Yang Tianyang) + + 2013.12.18, Version 0.10.24 (Stable), b7fd6bc899ccb629d790c47aee06aba87e535c41 * uv: Upgrade to v0.10.21 diff -Nru nodejs-0.11.10/Makefile nodejs-0.11.11/Makefile --- nodejs-0.11.10/Makefile 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/Makefile 2014-01-29 01:29:56.000000000 +0000 @@ -100,26 +100,38 @@ --directory="$(shell pwd)/test/gc/node_modules/weak" \ --nodedir="$(shell pwd)" +build-addons: + @if [ ! -f node ]; then make all; fi + rm -rf test/addons/doc-*/ + ./node tools/doc/addon-verify.js + $(foreach dir, \ + $(sort $(dir $(wildcard test/addons/*/*.gyp))), \ + ./node deps/npm/node_modules/node-gyp/bin/node-gyp rebuild \ + --directory="$(shell pwd)/$(dir)" \ + --nodedir="$(shell pwd)" && ) echo "build done" + test-gc: all test/gc/node_modules/weak/build/Release/weakref.node $(PYTHON) tools/test.py --mode=release gc -test-all: all test/gc/node_modules/weak/build/Release/weakref.node +test-build: all build-addons + +test-all: test-build test/gc/node_modules/weak/build/Release/weakref.node $(PYTHON) tools/test.py --mode=debug,release make test-npm -test-all-http1: all +test-all-http1: test-build $(PYTHON) tools/test.py --mode=debug,release --use-http1 -test-all-valgrind: all +test-all-valgrind: test-build $(PYTHON) tools/test.py --mode=debug,release --valgrind -test-release: all +test-release: test-build $(PYTHON) tools/test.py --mode=release -test-debug: all +test-debug: test-build $(PYTHON) tools/test.py --mode=debug -test-message: all +test-message: test-build $(PYTHON) tools/test.py message test-simple: all @@ -131,12 +143,18 @@ test-internet: all $(PYTHON) tools/test.py internet +test-debugger: all + $(PYTHON) tools/test.py debugger + test-npm: node ./node deps/npm/test/run.js test-npm-publish: node npm_package_config_publishtest=true ./node deps/npm/test/run.js +test-addons: test-build + $(PYTHON) tools/test.py --mode=release addons + apidoc_sources = $(wildcard doc/api/*.markdown) apidocs = $(addprefix out/,$(apidoc_sources:.markdown=.html)) \ $(addprefix out/,$(apidoc_sources:.markdown=.json)) @@ -415,4 +433,4 @@ lint: jslint cpplint -.PHONY: lint cpplint jslint bench clean docopen docclean doc dist distclean check uninstall install install-includes install-bin all staticlib dynamiclib test test-all website-upload pkg blog blogclean tar binary release-only bench-http-simple bench-idle bench-all bench bench-misc bench-array bench-buffer bench-net bench-http bench-fs bench-tls +.PHONY: lint cpplint jslint bench clean docopen docclean doc dist distclean check uninstall install install-includes install-bin all staticlib dynamiclib test test-all test-addons build-addons website-upload pkg blog blogclean tar binary release-only bench-http-simple bench-idle bench-all bench bench-misc bench-array bench-buffer bench-net bench-http bench-fs bench-tls diff -Nru nodejs-0.11.10/benchmark/net/tcp-raw-pipe.js nodejs-0.11.11/benchmark/net/tcp-raw-pipe.js --- nodejs-0.11.10/benchmark/net/tcp-raw-pipe.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/benchmark/net/tcp-raw-pipe.js 2014-01-29 01:29:56.000000000 +0000 @@ -51,7 +51,7 @@ if (nread < 0) fail(nread, 'read'); - var writeReq = {}; + var writeReq = { async: false }; err = clientHandle.writeBuffer(writeReq, buffer); if (err) diff -Nru nodejs-0.11.10/benchmark/net/tcp-raw-s2c.js nodejs-0.11.11/benchmark/net/tcp-raw-s2c.js --- nodejs-0.11.10/benchmark/net/tcp-raw-s2c.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/benchmark/net/tcp-raw-s2c.js 2014-01-29 01:29:56.000000000 +0000 @@ -68,7 +68,7 @@ write(); function write() { - var writeReq = { oncomplete: afterWrite }; + var writeReq = { async: false, oncomplete: afterWrite }; var err; switch (type) { case 'buf': @@ -82,8 +82,13 @@ break; } - if (err) + if (err) { fail(err, 'write'); + } else if (!writeReq.async) { + process.nextTick(function() { + afterWrite(null, clientHandle, writeReq); + }); + } } function afterWrite(err, handle, req) { diff -Nru nodejs-0.11.10/common.gypi nodejs-0.11.11/common.gypi --- nodejs-0.11.10/common.gypi 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/common.gypi 2014-01-29 01:29:56.000000000 +0000 @@ -19,7 +19,14 @@ }, { 'os_posix': 1, 'v8_postmortem_support': 'true' - }] + }], + ['GENERATOR == "ninja"', { + 'OBJ_DIR': '<(PRODUCT_DIR)/obj', + 'V8_BASE': '<(PRODUCT_DIR)/libv8_base.<(target_arch).a', + }, { + 'OBJ_DIR': '<(PRODUCT_DIR)/obj.target', + 'V8_BASE': '<(PRODUCT_DIR)/obj.target/deps/v8/tools/gyp/libv8_base.<(target_arch).a', + }], ], }, @@ -103,6 +110,10 @@ }, } }, + # Forcibly disable -Werror. We support a wide range of compilers, it's + # simply not feasible to squelch all warnings, never mind that the + # libraries in deps/ are not under our control. + 'cflags!': ['-Werror'], 'msvs_settings': { 'VCCLCompilerTool': { 'StringPooling': 'true', # pool string literals diff -Nru nodejs-0.11.10/configure nodejs-0.11.11/configure --- nodejs-0.11.10/configure 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/configure 2014-01-29 01:29:56.000000000 +0000 @@ -431,7 +431,7 @@ elif is_arm_hard_float_abi(): arm_float_abi = 'hard' else: - 'default' + arm_float_abi = 'default' o['variables']['armv7'] = int(is_arch_armv7()) o['variables']['arm_fpu'] = 'vfpv3' # V8 3.18 no longer supports VFP2. o['variables']['arm_neon'] = int(is_arm_neon()) diff -Nru nodejs-0.11.10/debian/changelog nodejs-0.11.11/debian/changelog --- nodejs-0.11.10/debian/changelog 2014-01-08 23:29:25.000000000 +0000 +++ nodejs-0.11.11/debian/changelog 2014-01-29 07:25:29.000000000 +0000 @@ -1,3 +1,9 @@ +nodejs (0.11.11-1chl1~quantal1) quantal; urgency=low + + * 0.11.11 (devel) release. + + -- Chris Lea Tue, 28 Jan 2014 23:11:32 -0800 + nodejs (0.11.10-1chl1~quantal1) quantal; urgency=low * 0.11.10 (devel) release. diff -Nru nodejs-0.11.10/deps/http_parser/.gitignore nodejs-0.11.11/deps/http_parser/.gitignore --- nodejs-0.11.10/deps/http_parser/.gitignore 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/deps/http_parser/.gitignore 2014-01-29 01:29:56.000000000 +0000 @@ -12,3 +12,16 @@ *.Makefile *.so.* *.a + + +# Visual Studio uglies +*.suo +*.sln +*.vcxproj +*.vcxproj.filters +*.vcxproj.user +*.opensdf +*.ncrunchsolution* +*.sdf +*.vsp +*.psess diff -Nru nodejs-0.11.10/deps/http_parser/AUTHORS nodejs-0.11.11/deps/http_parser/AUTHORS --- nodejs-0.11.10/deps/http_parser/AUTHORS 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/deps/http_parser/AUTHORS 2014-01-29 01:29:56.000000000 +0000 @@ -45,3 +45,5 @@ Uli Köhler Charlie Somerville Fedor Indutny +runner +Alexis Campailla diff -Nru nodejs-0.11.10/deps/http_parser/Makefile nodejs-0.11.11/deps/http_parser/Makefile --- nodejs-0.11.10/deps/http_parser/Makefile 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/deps/http_parser/Makefile 2014-01-29 01:29:56.000000000 +0000 @@ -19,7 +19,7 @@ # IN THE SOFTWARE. PLATFORM ?= $(shell sh -c 'uname -s | tr "[A-Z]" "[a-z]"') -SONAME ?= libhttp_parser.so.2.2 +SONAME ?= libhttp_parser.so.2.2.1 CC?=gcc AR?=ar diff -Nru nodejs-0.11.10/deps/http_parser/http_parser.c nodejs-0.11.11/deps/http_parser/http_parser.c --- nodejs-0.11.10/deps/http_parser/http_parser.c 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/deps/http_parser/http_parser.c 2014-01-29 01:29:56.000000000 +0000 @@ -1509,8 +1509,8 @@ t *= 10; t += ch - '0'; - /* Overflow? */ - if (t < parser->content_length || t == ULLONG_MAX) { + /* Overflow? Test against a conservative limit for simplicity. */ + if ((ULLONG_MAX - 10) / 10 < parser->content_length) { SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); goto error; } @@ -1782,8 +1782,8 @@ t *= 16; t += unhex_val; - /* Overflow? */ - if (t < parser->content_length || t == ULLONG_MAX) { + /* Overflow? Test against a conservative limit for simplicity. */ + if ((ULLONG_MAX - 16) / 16 < parser->content_length) { SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); goto error; } diff -Nru nodejs-0.11.10/deps/http_parser/http_parser.h nodejs-0.11.11/deps/http_parser/http_parser.h --- nodejs-0.11.10/deps/http_parser/http_parser.h 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/deps/http_parser/http_parser.h 2014-01-29 01:29:56.000000000 +0000 @@ -27,7 +27,7 @@ /* Also update SONAME in the Makefile whenever you change these. */ #define HTTP_PARSER_VERSION_MAJOR 2 #define HTTP_PARSER_VERSION_MINOR 2 -#define HTTP_PARSER_VERSION_PATCH 0 +#define HTTP_PARSER_VERSION_PATCH 1 #include #if defined(_WIN32) && !defined(__MINGW32__) && (!defined(_MSC_VER) || _MSC_VER<1600) diff -Nru nodejs-0.11.10/deps/http_parser/test.c nodejs-0.11.11/deps/http_parser/test.c --- nodejs-0.11.10/deps/http_parser/test.c 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/deps/http_parser/test.c 2014-01-29 01:29:56.000000000 +0000 @@ -2938,7 +2938,7 @@ "HTTP/1.1 200 OK\r\n" \ "Content-Length: " #size "\r\n" \ "\r\n" - const char a[] = X(18446744073709551614); /* 2^64-2 */ + const char a[] = X(1844674407370955160); /* 2^64 / 10 - 1 */ const char b[] = X(18446744073709551615); /* 2^64-1 */ const char c[] = X(18446744073709551616); /* 2^64 */ #undef X @@ -2956,7 +2956,7 @@ "\r\n" \ #size "\r\n" \ "..." - const char a[] = X(FFFFFFFFFFFFFFFE); /* 2^64-2 */ + const char a[] = X(FFFFFFFFFFFFFFE); /* 2^64 / 16 - 1 */ const char b[] = X(FFFFFFFFFFFFFFFF); /* 2^64-1 */ const char c[] = X(10000000000000000); /* 2^64 */ #undef X diff -Nru nodejs-0.11.10/deps/npm/Makefile nodejs-0.11.11/deps/npm/Makefile --- nodejs-0.11.10/deps/npm/Makefile 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/deps/npm/Makefile 2014-01-29 01:29:56.000000000 +0000 @@ -192,9 +192,6 @@ html/doc/* \ node@npmjs.org:/home/node/npm-www/doc rsync -vazu --stats --no-implied-dirs --delete \ - html/static/webfonts/ \ - node@npmjs.org:/home/node/npm-www/static/webfonts - rsync -vazu --stats --no-implied-dirs --delete \ html/static/style.css \ node@npmjs.org:/home/node/npm-www/static/ #cleanup diff -Nru nodejs-0.11.10/deps/npm/doc/api/npm-repo.md nodejs-0.11.11/deps/npm/doc/api/npm-repo.md --- nodejs-0.11.10/deps/npm/doc/api/npm-repo.md 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/deps/npm/doc/api/npm-repo.md 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,19 @@ +npm-repo(3) -- Open package repository page in the browser +======================================================== + +## SYNOPSIS + + npm.commands.repo(package, callback) + +## DESCRIPTION + +This command tries to guess at the likely location of a package's +repository URL, and then tries to open it using the `--browser` +config param. + +Like other commands, the first parameter is an array. This command only +uses the first element, which is expected to be a package name with an +optional version number. + +This command will launch a browser, so this command may not be the most +friendly for programmatic use. diff -Nru nodejs-0.11.10/deps/npm/doc/api/repo.md nodejs-0.11.11/deps/npm/doc/api/repo.md --- nodejs-0.11.10/deps/npm/doc/api/repo.md 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/deps/npm/doc/api/repo.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -npm-repo(3) -- Open package repository page in the browser -======================================================== - -## SYNOPSIS - - npm.commands.repo(package, callback) - -## DESCRIPTION - -This command tries to guess at the likely location of a package's -repository URL, and then tries to open it using the `--browser` -config param. - -Like other commands, the first parameter is an array. This command only -uses the first element, which is expected to be a package name with an -optional version number. - -This command will launch a browser, so this command may not be the most -friendly for programmatic use. diff -Nru nodejs-0.11.10/deps/npm/doc/cli/npm-docs.md nodejs-0.11.11/deps/npm/doc/cli/npm-docs.md --- nodejs-0.11.10/deps/npm/doc/cli/npm-docs.md 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/deps/npm/doc/cli/npm-docs.md 2014-01-29 01:29:56.000000000 +0000 @@ -3,17 +3,18 @@ ## SYNOPSIS - npm docs + npm docs [ [ ...]] npm docs (with no args in a package dir) - npm home + npm home [ [ ...]] npm home (with no args in a package dir) ## DESCRIPTION This command tries to guess at the likely location of a package's documentation URL, and then tries to open it using the `--browser` -config param. If no package name is provided, it will search for -a `package.json` in the current folder and use the `name` property. +config param. You can pass multiple package names at once. If no +package name is provided, it will search for a `package.json` in +the current folder and use the `name` property. ## CONFIGURATION diff -Nru nodejs-0.11.10/deps/npm/doc/cli/npm-repo.md nodejs-0.11.11/deps/npm/doc/cli/npm-repo.md --- nodejs-0.11.10/deps/npm/doc/cli/npm-repo.md 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/deps/npm/doc/cli/npm-repo.md 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,28 @@ +npm-repo(1) -- Open package repository page in the browser +======================================================== + +## SYNOPSIS + + npm repo + npm repo (with no args in a package dir) + +## DESCRIPTION + +This command tries to guess at the likely location of a package's +repository URL, and then tries to open it using the `--browser` +config param. If no package name is provided, it will search for +a `package.json` in the current folder and use the `name` property. + +## CONFIGURATION + +### browser + +* Default: OS X: `"open"`, Windows: `"start"`, Others: `"xdg-open"` +* Type: String + +The browser that is called by the `npm repo` command to open websites. + +## SEE ALSO + +* npm-docs(1) +* npm-config(1) diff -Nru nodejs-0.11.10/deps/npm/doc/cli/npm-search.md nodejs-0.11.11/deps/npm/doc/cli/npm-search.md --- nodejs-0.11.10/deps/npm/doc/cli/npm-search.md 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/deps/npm/doc/cli/npm-search.md 2014-01-29 01:29:56.000000000 +0000 @@ -3,7 +3,7 @@ ## SYNOPSIS - npm search [search terms ...] + npm search [--long] [search terms ...] npm s [search terms ...] npm se [search terms ...] @@ -15,6 +15,18 @@ A trailing `/` will be ignored in this case. (Note that many regular expression characters must be escaped or quoted in most shells.) +## CONFIGURATION + +### long + +* Default: false +* Type: Boolean + +Display full package descriptions and other long text across multiple +lines. When disabled (default) search results are truncated to fit +neatly on a single line. Modules with extremely long names will +fall on multiple lines. + ## SEE ALSO * npm-registry(7) diff -Nru nodejs-0.11.10/deps/npm/doc/cli/repo.md nodejs-0.11.11/deps/npm/doc/cli/repo.md --- nodejs-0.11.10/deps/npm/doc/cli/repo.md 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/deps/npm/doc/cli/repo.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -npm-repo(1) -- Open package repository page in the browser -======================================================== - -## SYNOPSIS - - npm repo - npm repo (with no args in a package dir) - -## DESCRIPTION - -This command tries to guess at the likely location of a package's -repository URL, and then tries to open it using the `--browser` -config param. If no package name is provided, it will search for -a `package.json` in the current folder and use the `name` property. - -## CONFIGURATION - -### browser - -* Default: OS X: `"open"`, Windows: `"start"`, Others: `"xdg-open"` -* Type: String - -The browser that is called by the `npm repo` command to open websites. - -## SEE ALSO - -* npm-docs(1) -* npm-config(1) diff -Nru nodejs-0.11.10/deps/npm/doc/files/package.json.md nodejs-0.11.11/deps/npm/doc/files/package.json.md --- nodejs-0.11.10/deps/npm/doc/files/package.json.md 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/deps/npm/doc/files/package.json.md 2014-01-29 01:29:56.000000000 +0000 @@ -9,32 +9,6 @@ A lot of the behavior described in this document is affected by the config settings described in `npm-config(7)`. -## DEFAULT VALUES - -npm will default some values based on package contents. - -* `"scripts": {"start": "node server.js"}` - - If there is a `server.js` file in the root of your package, then npm - will default the `start` command to `node server.js`. - -* `"scripts":{"preinstall": "node-waf clean || true; node-waf configure build"}` - - If there is a `wscript` file in the root of your package, npm will - default the `preinstall` command to compile using node-waf. - -* `"scripts":{"preinstall": "node-gyp rebuild"}` - - If there is a `binding.gyp` file in the root of your package, npm will - default the `preinstall` command to compile using node-gyp. - -* `"contributors": [...]` - - If there is an `AUTHORS` file in the root of your package, npm will - treat each line as a `Name (url)` format, where email and url - are optional. Lines which start with a `#` or are blank, will be - ignored. - ## name The *most* important things in your package.json are the name and version fields. @@ -122,16 +96,8 @@ Ideally you should pick one that is [OSI](http://opensource.org/licenses/alphabetical) approved. -If you have more complex licensing terms, or you want to provide more detail -in your package.json file, you can use the more verbose plural form, like this: - - "licenses" : [ - { "type" : "MyLicense" - , "url" : "http://github.com/owner/project/path/to/license" - } - ] - -It's also a good idea to include a license file at the top level in your package. +It's also a good idea to include a LICENSE file at the top level in +your package. ## people fields: author, contributors @@ -575,6 +541,27 @@ See `npm-config(7)` to see the list of config options that can be overridden. +## DEFAULT VALUES + +npm will default some values based on package contents. + +* `"scripts": {"start": "node server.js"}` + + If there is a `server.js` file in the root of your package, then npm + will default the `start` command to `node server.js`. + +* `"scripts":{"preinstall": "node-gyp rebuild"}` + + If there is a `binding.gyp` file in the root of your package, npm will + default the `preinstall` command to compile using node-gyp. + +* `"contributors": [...]` + + If there is an `AUTHORS` file in the root of your package, npm will + treat each line as a `Name (url)` format, where email and url + are optional. Lines which start with a `#` or are blank, will be + ignored. + ## SEE ALSO * semver(7) diff -Nru nodejs-0.11.10/deps/npm/doc/misc/npm-config.md nodejs-0.11.11/deps/npm/doc/misc/npm-config.md --- nodejs-0.11.10/deps/npm/doc/misc/npm-config.md 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/deps/npm/doc/misc/npm-config.md 2014-01-29 01:29:56.000000000 +0000 @@ -480,7 +480,7 @@ * Default: false * Type: Boolean -Show extended information in `npm ls` +Show extended information in `npm ls` and `npm search`. ### message diff -Nru nodejs-0.11.10/deps/npm/doc/misc/npm-index.md nodejs-0.11.11/deps/npm/doc/misc/npm-index.md --- nodejs-0.11.10/deps/npm/doc/misc/npm-index.md 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/deps/npm/doc/misc/npm-index.md 2014-01-29 01:29:56.000000000 +0000 @@ -115,6 +115,10 @@ Rebuild a package +## npm-repo(1) + +Open package repository page in the browser + ## npm-restart(1) Start a package @@ -191,10 +195,6 @@ Display npm username -## repo(1) - -Open package repository page in the browser - # API Documentation ## npm(3) @@ -285,6 +285,10 @@ Rebuild a package +## npm-repo(3) + +Open package repository page in the browser + ## npm-restart(3) Start a package @@ -349,10 +353,6 @@ Display npm username -## repo(3) - -Open package repository page in the browser - # Files ## npm-folders(5) diff -Nru nodejs-0.11.10/deps/npm/html/doc/README.html nodejs-0.11.11/deps/npm/html/doc/README.html --- nodejs-0.11.10/deps/npm/html/doc/README.html 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/deps/npm/html/doc/README.html 2014-01-29 01:29:56.000000000 +0000 @@ -239,7 +239,7 @@ - + diff -Nru nodejs-0.11.10/deps/npm/html/doc/api/npm-restart.html nodejs-0.11.11/deps/npm/html/doc/api/npm-restart.html --- nodejs-0.11.10/deps/npm/html/doc/api/npm-restart.html 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/deps/npm/html/doc/api/npm-restart.html 2014-01-29 01:29:56.000000000 +0000 @@ -27,7 +27,7 @@ - + diff -Nru nodejs-0.11.10/deps/npm/html/doc/cli/npm-adduser.html nodejs-0.11.11/deps/npm/html/doc/cli/npm-adduser.html --- nodejs-0.11.10/deps/npm/html/doc/cli/npm-adduser.html 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/deps/npm/html/doc/cli/npm-adduser.html 2014-01-29 01:29:56.000000000 +0000 @@ -39,7 +39,7 @@ - + diff -Nru nodejs-0.11.10/deps/npm/html/doc/cli/npm-restart.html nodejs-0.11.11/deps/npm/html/doc/cli/npm-restart.html --- nodejs-0.11.10/deps/npm/html/doc/cli/npm-restart.html 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/deps/npm/html/doc/cli/npm-restart.html 2014-01-29 01:29:56.000000000 +0000 @@ -24,7 +24,7 @@ - + diff -Nru nodejs-0.11.10/deps/npm/html/doc/files/npm-folders.html nodejs-0.11.11/deps/npm/html/doc/files/npm-folders.html --- nodejs-0.11.10/deps/npm/html/doc/files/npm-folders.html 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/deps/npm/html/doc/files/npm-folders.html 2014-01-29 01:29:56.000000000 +0000 @@ -205,7 +205,7 @@ - + diff -Nru nodejs-0.11.10/doc/api/addons.html nodejs-0.11.11/doc/api/addons.html --- nodejs-0.11.10/doc/api/addons.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/addons.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - Addons Node.js v0.11.10 Manual & Documentation + Addons Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
-

Node.js v0.11.10 Manual & Documentation

+

Node.js v0.11.11 Manual & Documentation

Index | @@ -108,22 +108,22 @@

First we create a file hello.cc:

-
#include <node.h>
+
// hello.cc
+#include <node.h>
 
 using namespace v8;
 
-Handle<Value> Method(const Arguments& args) {
+void Method(const FunctionCallbackInfo<Value>& args) {
   Isolate* isolate = Isolate::GetCurrent();
   HandleScope scope(isolate);
-  return scope.Close(String::New("world"));
+  args.GetReturnValue().Set(String::NewFromUtf8(isolate, "world"));
 }
 
 void init(Handle<Object> exports) {
-  exports->Set(String::NewSymbol("hello"),
-      FunctionTemplate::New(Method)->GetFunction());
+  NODE_SET_METHOD(exports, "hello", Method);
 }
 
-NODE_MODULE(hello, init)
+NODE_MODULE(addon, init)

Note that all Node addons must export an initialization function:

@@ -137,7 +137,7 @@ .node suffix).

-

The source code needs to be built into hello.node, the binary Addon. To +

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 to build your module in a JSON-like format. This file gets compiled by node-gyp. @@ -146,7 +146,7 @@

{
   "targets": [
     {
-      "target_name": "hello",
+      "target_name": "addon",
       "sources": [ "hello.cc" ]
     }
   ]
@@ -168,7 +168,8 @@
 require to the recently built hello.node module:
 
 

-
var addon = require('./build/Release/hello');
+
// hello.js
+var addon = require('./build/Release/addon');
 
 console.log(addon.hello()); // 'world'

Please see patterns below for further information or @@ -213,40 +214,43 @@ addon.cc:

-
#include <node.h>
+
// addon.cc
+#include <node.h>
 
 using namespace v8;
 
-Handle<Value> Add(const Arguments& args) {
+void Add(const FunctionCallbackInfo<Value>& args) {
   Isolate* isolate = Isolate::GetCurrent();
   HandleScope scope(isolate);
 
   if (args.Length() < 2) {
-    ThrowException(Exception::TypeError(
-        String::New("Wrong number of arguments")));
-    return scope.Close(Undefined(isolate));
+    isolate->ThrowException(Exception::TypeError(
+        String::NewFromUtf8(isolate, "Wrong number of arguments")));
+    return;
   }
 
   if (!args[0]->IsNumber() || !args[1]->IsNumber()) {
-    ThrowException(Exception::TypeError(String::New("Wrong arguments")));
-    return scope.Close(Undefined(isolate));
+    isolate->ThrowException(Exception::TypeError(
+        String::NewFromUtf8(isolate, "Wrong arguments")));
+    return;
   }
 
   Local<Number> num = Number::New(args[0]->NumberValue() +
       args[1]->NumberValue());
-  return scope.Close(num);
+
+  args.GetReturnValue().Set(num);
 }
 
 void Init(Handle<Object> exports) {
-  exports->Set(String::NewSymbol("add"),
-      FunctionTemplate::New(Add)->GetFunction());
+  NODE_SET_METHOD(exports, "add", Add);
 }
 
 NODE_MODULE(addon, Init)

You can test it with the following JavaScript snippet:

-
var addon = require('./build/Release/addon');
+
// test.js
+var addon = require('./build/Release/addon');
 
 console.log( 'This should be eight:', addon.add(3,5) );

Callbacks#

@@ -254,25 +258,23 @@ there. Here's addon.cc:

-
#include <node.h>
+
// addon.cc
+#include <node.h>
 
 using namespace v8;
 
-Handle<Value> RunCallback(const Arguments& args) {
+void RunCallback(const FunctionCallbackInfo<Value>& args) {
   Isolate* isolate = Isolate::GetCurrent();
   HandleScope scope(isolate);
 
   Local<Function> cb = Local<Function>::Cast(args[0]);
   const unsigned argc = 1;
-  Local<Value> argv[argc] = { String::New("hello world") };
+  Local<Value> argv[argc] = { String::NewFromUtf8(isolate, "hello world") };
   cb->Call(Context::GetCurrent()->Global(), argc, argv);
-
-  return scope.Close(Undefined(isolate));
 }
 
 void Init(Handle<Object> exports, Handle<Object> module) {
-  module->Set(String::NewSymbol("exports"),
-      FunctionTemplate::New(RunCallback)->GetFunction());
+  NODE_SET_METHOD(module, "exports", RunCallback);
 }
 
 NODE_MODULE(addon, Init)
@@ -285,7 +287,8 @@

To test it run the following JavaScript snippet:

-
var addon = require('./build/Release/addon');
+
// test.js
+var addon = require('./build/Release/addon');
 
 addon(function(msg){
   console.log(msg); // 'hello world'
@@ -296,30 +299,31 @@
 the string passed to createObject():
 
 

-
#include <node.h>
+
// addon.cc
+#include <node.h>
 
 using namespace v8;
 
-Handle<Value> CreateObject(const Arguments& args) {
+void CreateObject(const FunctionCallbackInfo<Value>& args) {
   Isolate* isolate = Isolate::GetCurrent();
   HandleScope scope(isolate);
 
   Local<Object> obj = Object::New();
-  obj->Set(String::NewSymbol("msg"), args[0]->ToString());
+  obj->Set(String::NewFromUtf8(isolate, "msg"), args[0]->ToString());
 
-  return scope.Close(obj);
+  args.GetReturnValue().Set(obj);
 }
 
 void Init(Handle<Object> exports, Handle<Object> module) {
-  module->Set(String::NewSymbol("exports"),
-      FunctionTemplate::New(CreateObject)->GetFunction());
+  NODE_SET_METHOD(module, "exports", CreateObject);
 }
 
 NODE_MODULE(addon, Init)

To test it in JavaScript:

-
var addon = require('./build/Release/addon');
+
// test.js
+var addon = require('./build/Release/addon');
 
 var obj1 = addon('hello');
 var obj2 = addon('world');
@@ -329,17 +333,18 @@
 wraps a C++ function:
 
 

-
#include <node.h>
+
// addon.cc
+#include <node.h>
 
 using namespace v8;
 
-Handle<Value> MyFunction(const Arguments& args) {
+void MyFunction(const FunctionCallbackInfo<Value>& args) {
   Isolate* isolate = Isolate::GetCurrent();
   HandleScope scope(isolate);
-  return scope.Close(String::New("hello world"));
+  args.GetReturnValue().Set(String::NewFromUtf8(isolate, "hello world"));
 }
 
-Handle<Value> CreateFunction(const Arguments& args) {
+void CreateFunction(const FunctionCallbackInfo<Value>& args) {
   Isolate* isolate = Isolate::GetCurrent();
   HandleScope scope(isolate);
 
@@ -347,21 +352,21 @@
   Local<Function> fn = tpl->GetFunction();
 
   // omit this to make it anonymous
-  fn->SetName(String::NewSymbol("theFunction"));
+  fn->SetName(String::NewFromUtf8(isolate, "theFunction"));
 
-  return scope.Close(fn);
+  args.GetReturnValue().Set(fn);
 }
 
 void Init(Handle<Object> exports, Handle<Object> module) {
-  module->Set(String::NewSymbol("exports"),
-      FunctionTemplate::New(CreateFunction)->GetFunction());
+  NODE_SET_METHOD(module, "exports", CreateFunction);
 }
 
 NODE_MODULE(addon, Init)

To test:

-
var addon = require('./build/Release/addon');
+
// test.js
+var addon = require('./build/Release/addon');
 
 var fn = addon();
 console.log(fn()); // 'hello world'
@@ -371,7 +376,8 @@ module addon.cc:

-
#include <node.h>
+
// addon.cc
+#include <node.h>
 #include "myobject.h"
 
 using namespace v8;
@@ -384,10 +390,12 @@
 

Then in myobject.h make your wrapper inherit from node::ObjectWrap:

-
#ifndef MYOBJECT_H
+
// myobject.h
+#ifndef MYOBJECT_H
 #define MYOBJECT_H
 
 #include <node.h>
+#include <node_object_wrap.h>
 
 class MyObject : public node::ObjectWrap {
  public:
@@ -397,8 +405,8 @@
   explicit MyObject(double value = 0);
   ~MyObject();
 
-  static v8::Handle<v8::Value> New(const v8::Arguments& args);
-  static v8::Handle<v8::Value> PlusOne(const v8::Arguments& args);
+  static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
+  static void PlusOne(const v8::FunctionCallbackInfo<v8::Value>& args);
   static v8::Persistent<v8::Function> constructor;
   double value_;
 };
@@ -409,8 +417,7 @@
 prototype:
 
 

-
#include <node.h>
-#include <node_object_wrap.h>
+
// myobject.cc
 #include "myobject.h"
 
 using namespace v8;
@@ -428,20 +435,18 @@
 
   // Prepare constructor template
   Local<FunctionTemplate> tpl = FunctionTemplate::New(New);
-  tpl->SetClassName(String::NewSymbol("MyObject"));
+  tpl->SetClassName(String::NewFromUtf8(isolate, "MyObject"));
   tpl->InstanceTemplate()->SetInternalFieldCount(1);
 
   // Prototype
-  tpl->PrototypeTemplate()->Set(String::NewSymbol("plusOne"),
-      FunctionTemplate::New(PlusOne)->GetFunction());
-
-  Persistent<Function> constructor
-      = Persistent<Function>::New(isolate, tpl->GetFunction());
+  NODE_SET_PROTOTYPE_METHOD(tpl, "plusOne", PlusOne);
 
-  exports->Set(String::NewSymbol("MyObject"), constructor);
+  constructor.Reset(isolate, tpl->GetFunction());
+  exports->Set(String::NewFromUtf8(isolate, "MyObject"),
+               tpl->GetFunction());
 }
 
-Handle<Value> MyObject::New(const Arguments& args) {
+void MyObject::New(const FunctionCallbackInfo<Value>& args) {
   Isolate* isolate = Isolate::GetCurrent();
   HandleScope scope(isolate);
 
@@ -450,28 +455,30 @@
     double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
     MyObject* obj = new MyObject(value);
     obj->Wrap(args.This());
-    return args.This();
+    args.GetReturnValue().Set(args.This());
   } else {
     // Invoked as plain function `MyObject(...)`, turn into construct call.
     const int argc = 1;
     Local<Value> argv[argc] = { args[0] };
-    return scope.Close(constructor->NewInstance(argc, argv));
+    Local<Function> cons = Local<Function>::New(isolate, constructor);
+    args.GetReturnValue().Set(cons->NewInstance(argc, argv));
   }
 }
 
-Handle<Value> MyObject::PlusOne(const Arguments& args) {
+void MyObject::PlusOne(const FunctionCallbackInfo<Value>& args) {
   Isolate* isolate = Isolate::GetCurrent();
   HandleScope scope(isolate);
 
   MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.This());
   obj->value_ += 1;
 
-  return scope.Close(Number::New(obj->value_));
+  args.GetReturnValue().Set(Number::New(obj->value_));
 }

Test it with:

-
var addon = require('./build/Release/addon');
+
// test.js
+var addon = require('./build/Release/addon');
 
 var obj = new addon.MyObject(10);
 console.log( obj.plusOne() ); // 11
@@ -488,22 +495,22 @@
 

Let's register our createObject method in addon.cc:

-
#include <node.h>
+
// addon.cc
+#include <node.h>
 #include "myobject.h"
 
 using namespace v8;
 
-Handle<Value> CreateObject(const Arguments& args) {
+void CreateObject(const FunctionCallbackInfo<Value>& args) {
   Isolate* isolate = Isolate::GetCurrent();
   HandleScope scope(isolate);
-  return scope.Close(MyObject::NewInstance(args));
+  MyObject::NewInstance(args);
 }
 
 void InitAll(Handle<Object> exports, Handle<Object> module) {
   MyObject::Init();
 
-  module->Set(String::NewSymbol("exports"),
-      FunctionTemplate::New(CreateObject)->GetFunction());
+  NODE_SET_METHOD(module, "exports", CreateObject);
 }
 
 NODE_MODULE(addon, InitAll)
@@ -511,22 +518,24 @@ care of instantiating the object (i.e. it does the job of new in JavaScript):

-
#ifndef MYOBJECT_H
+
// myobject.h
+#ifndef MYOBJECT_H
 #define MYOBJECT_H
 
 #include <node.h>
+#include <node_object_wrap.h>
 
 class MyObject : public node::ObjectWrap {
  public:
   static void Init();
-  static v8::Handle<v8::Value> NewInstance(const v8::Arguments& args);
+  static void NewInstance(const v8::FunctionCallbackInfo<v8::Value>& args);
 
  private:
   explicit MyObject(double value = 0);
   ~MyObject();
 
-  static v8::Handle<v8::Value> New(const v8::Arguments& args);
-  static v8::Handle<v8::Value> PlusOne(const v8::Arguments& args);
+  static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
+  static void PlusOne(const v8::FunctionCallbackInfo<v8::Value>& args);
   static v8::Persistent<v8::Function> constructor;
   double value_;
 };
@@ -535,7 +544,8 @@
 

The implementation is similar to the above in myobject.cc:

-
#include <node.h>
+
// myobject.cc
+#include <node.h>
 #include "myobject.h"
 
 using namespace v8;
@@ -552,17 +562,16 @@
   Isolate* isolate = Isolate::GetCurrent();
   // Prepare constructor template
   Local<FunctionTemplate> tpl = FunctionTemplate::New(New);
-  tpl->SetClassName(String::NewSymbol("MyObject"));
+  tpl->SetClassName(String::NewFromUtf8(isolate, "MyObject"));
   tpl->InstanceTemplate()->SetInternalFieldCount(1);
 
   // Prototype
-  tpl->PrototypeTemplate()->Set(String::NewSymbol("plusOne"),
-      FunctionTemplate::New(PlusOne)->GetFunction());
+  NODE_SET_PROTOTYPE_METHOD(tpl, "plusOne", PlusOne);
 
-  constructor = Persistent<Function>::New(isolate, tpl->GetFunction());
+  constructor.Reset(isolate, tpl->GetFunction());
 }
 
-Handle<Value> MyObject::New(const Arguments& args) {
+void MyObject::New(const FunctionCallbackInfo<Value>& args) {
   Isolate* isolate = Isolate::GetCurrent();
   HandleScope scope(isolate);
 
@@ -571,39 +580,42 @@
     double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
     MyObject* obj = new MyObject(value);
     obj->Wrap(args.This());
-    return args.This();
+    args.GetReturnValue().Set(args.This());
   } else {
     // Invoked as plain function `MyObject(...)`, turn into construct call.
     const int argc = 1;
     Local<Value> argv[argc] = { args[0] };
-    return scope.Close(constructor->NewInstance(argc, argv));
+    Local<Function> cons = Local<Function>::New(isolate, constructor);
+    args.GetReturnValue().Set(cons->NewInstance(argc, argv));
   }
 }
 
-Handle<Value> MyObject::NewInstance(const Arguments& args) {
+void MyObject::NewInstance(const FunctionCallbackInfo<Value>& args) {
   Isolate* isolate = Isolate::GetCurrent();
   HandleScope scope(isolate);
 
   const unsigned argc = 1;
   Handle<Value> argv[argc] = { args[0] };
-  Local<Object> instance = constructor->NewInstance(argc, argv);
+  Local<Function> cons = Local<Function>::New(isolate, constructor);
+  Local<Object> instance = cons->NewInstance(argc, argv);
 
-  return scope.Close(instance);
+  args.GetReturnValue().Set(instance);
 }
 
-Handle<Value> MyObject::PlusOne(const Arguments& args) {
+void MyObject::PlusOne(const FunctionCallbackInfo<Value>& args) {
   Isolate* isolate = Isolate::GetCurrent();
   HandleScope scope(isolate);
 
   MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.This());
   obj->value_ += 1;
 
-  return scope.Close(Number::New(obj->value_));
+  args.GetReturnValue().Set(Number::New(obj->value_));
 }

Test it with:

-
var createObject = require('./build/Release/addon');
+
// test.js
+var createObject = require('./build/Release/addon');
 
 var obj = createObject(10);
 console.log( obj.plusOne() ); // 11
@@ -621,19 +633,20 @@
 MyObject objects:
 
 

-
#include <node.h>
+
// addon.cc
+#include <node.h>
 #include <node_object_wrap.h>
 #include "myobject.h"
 
 using namespace v8;
 
-Handle<Value> CreateObject(const Arguments& args) {
+void CreateObject(const FunctionCallbackInfo<Value>& args) {
   Isolate* isolate = Isolate::GetCurrent();
   HandleScope scope(isolate);
-  return scope.Close(MyObject::NewInstance(args));
+  MyObject::NewInstance(args);
 }
 
-Handle<Value> Add(const Arguments& args) {
+void Add(const FunctionCallbackInfo<Value>& args) {
   Isolate* isolate = Isolate::GetCurrent();
   HandleScope scope(isolate);
 
@@ -642,18 +655,15 @@
   MyObject* obj2 = node::ObjectWrap::Unwrap<MyObject>(
       args[1]->ToObject());
 
-  double sum = obj1->Value() + obj2->Value();
-  return scope.Close(Number::New(sum));
+  double sum = obj1->value() + obj2->value();
+  args.GetReturnValue().Set(Number::New(sum));
 }
 
 void InitAll(Handle<Object> exports) {
   MyObject::Init();
 
-  exports->Set(String::NewSymbol("createObject"),
-      FunctionTemplate::New(CreateObject)->GetFunction());
-
-  exports->Set(String::NewSymbol("add"),
-      FunctionTemplate::New(Add)->GetFunction());
+  NODE_SET_METHOD(exports, "createObject", CreateObject);
+  NODE_SET_METHOD(exports, "add", Add);
 }
 
 NODE_MODULE(addon, InitAll)
@@ -661,7 +671,8 @@ can probe private values after unwrapping the object:

-
#ifndef MYOBJECT_H
+
// myobject.h
+#ifndef MYOBJECT_H
 #define MYOBJECT_H
 
 #include <node.h>
@@ -670,14 +681,14 @@
 class MyObject : public node::ObjectWrap {
  public:
   static void Init();
-  static v8::Handle<v8::Value> NewInstance(const v8::Arguments& args);
-  double Value() const { return value_; }
+  static void NewInstance(const v8::FunctionCallbackInfo<v8::Value>& args);
+  inline double value() const { return value_; }
 
  private:
   explicit MyObject(double value = 0);
   ~MyObject();
 
-  static v8::Handle<v8::Value> New(const v8::Arguments& args);
+  static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
   static v8::Persistent<v8::Function> constructor;
   double value_;
 };
@@ -686,7 +697,8 @@
 

The implementation of myobject.cc is similar as before:

-
#include <node.h>
+
// myobject.cc
+#include <node.h>
 #include "myobject.h"
 
 using namespace v8;
@@ -704,13 +716,13 @@
 
   // Prepare constructor template
   Local<FunctionTemplate> tpl = FunctionTemplate::New(New);
-  tpl->SetClassName(String::NewSymbol("MyObject"));
+  tpl->SetClassName(String::NewFromUtf8(isolate, "MyObject"));
   tpl->InstanceTemplate()->SetInternalFieldCount(1);
 
-  constructor = Persistent<Function>::New(isolate, tpl->GetFunction());
+  constructor.Reset(isolate, tpl->GetFunction());
 }
 
-Handle<Value> MyObject::New(const Arguments& args) {
+void MyObject::New(const FunctionCallbackInfo<Value>& args) {
   Isolate* isolate = Isolate::GetCurrent();
   HandleScope scope(isolate);
 
@@ -719,29 +731,32 @@
     double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
     MyObject* obj = new MyObject(value);
     obj->Wrap(args.This());
-    return args.This();
+    args.GetReturnValue().Set(args.This());
   } else {
     // Invoked as plain function `MyObject(...)`, turn into construct call.
     const int argc = 1;
     Local<Value> argv[argc] = { args[0] };
-    return scope.Close(constructor->NewInstance(argc, argv));
+    Local<Function> cons = Local<Function>::New(isolate, constructor);
+    args.GetReturnValue().Set(cons->NewInstance(argc, argv));
   }
 }
 
-Handle<Value> MyObject::NewInstance(const Arguments& args) {
+void MyObject::NewInstance(const FunctionCallbackInfo<Value>& args) {
   Isolate* isolate = Isolate::GetCurrent();
   HandleScope scope(isolate);
 
   const unsigned argc = 1;
   Handle<Value> argv[argc] = { args[0] };
-  Local<Object> instance = constructor->NewInstance(argc, argv);
+  Local<Function> cons = Local<Function>::New(isolate, constructor);
+  Local<Object> instance = cons->NewInstance(argc, argv);
 
-  return scope.Close(instance);
+  args.GetReturnValue().Set(instance);
 }

Test it with:

-
var addon = require('./build/Release/addon');
+
// test.js
+var addon = require('./build/Release/addon');
 
 var obj1 = addon.createObject(10);
 var obj2 = addon.createObject(20);
@@ -767,7 +782,7 @@
             
  • -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/api/addons.json nodejs-0.11.11/doc/api/addons.json --- nodejs-0.11.10/doc/api/addons.json 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/addons.json 2014-01-29 03:26:35.000000000 +0000 @@ -9,7 +9,7 @@ { "textRaw": "Hello world", "name": "hello_world", - "desc": "

    To get started let's make a small Addon which is the C++ equivalent of\nthe following JavaScript code:\n\n

    \n
    module.exports.hello = function() { return 'world'; };
    \n

    First we create a file hello.cc:\n\n

    \n
    #include <node.h>\n\nusing namespace v8;\n\nHandle<Value> Method(const Arguments& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n  return scope.Close(String::New("world"));\n}\n\nvoid init(Handle<Object> exports) {\n  exports->Set(String::NewSymbol("hello"),\n      FunctionTemplate::New(Method)->GetFunction());\n}\n\nNODE_MODULE(hello, init)
    \n

    Note that all Node addons must export an initialization function:\n\n

    \n
    void Initialize (Handle<Object> exports);\nNODE_MODULE(module_name, Initialize)
    \n

    There is no semi-colon after NODE_MODULE as it's not a function (see\nnode.h).\n\n

    \n

    The module_name needs to match the filename of the final binary (minus the\n.node suffix).\n\n

    \n

    The source code needs to be built into hello.node, the binary Addon. To\ndo this we create a file called binding.gyp which describes the configuration\nto build your module in a JSON-like format. This file gets compiled by\nnode-gyp.\n\n

    \n
    {\n  "targets": [\n    {\n      "target_name": "hello",\n      "sources": [ "hello.cc" ]\n    }\n  ]\n}
    \n

    The next step is to generate the appropriate project build files for the\ncurrent platform. Use node-gyp configure for that.\n\n

    \n

    Now you will have either a Makefile (on Unix platforms) or a vcxproj file\n(on Windows) in the build/ directory. Next invoke the node-gyp build\ncommand.\n\n

    \n

    Now you have your compiled .node bindings file! The compiled bindings end up\nin build/Release/.\n\n

    \n

    You can now use the binary addon in a Node project hello.js by pointing\nrequire to the recently built hello.node module:\n\n

    \n
    var addon = require('./build/Release/hello');\n\nconsole.log(addon.hello()); // 'world'
    \n

    Please see patterns below for further information or\n

    \n

    https://github.com/arturadib/node-qt for an example in production.\n\n\n

    \n", + "desc": "

    To get started let's make a small Addon which is the C++ equivalent of\nthe following JavaScript code:\n\n

    \n
    module.exports.hello = function() { return 'world'; };
    \n

    First we create a file hello.cc:\n\n

    \n
    // hello.cc\n#include <node.h>\n\nusing namespace v8;\n\nvoid Method(const FunctionCallbackInfo<Value>& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n  args.GetReturnValue().Set(String::NewFromUtf8(isolate, "world"));\n}\n\nvoid init(Handle<Object> exports) {\n  NODE_SET_METHOD(exports, "hello", Method);\n}\n\nNODE_MODULE(addon, init)
    \n

    Note that all Node addons must export an initialization function:\n\n

    \n
    void Initialize (Handle<Object> exports);\nNODE_MODULE(module_name, Initialize)
    \n

    There is no semi-colon after NODE_MODULE as it's not a function (see\nnode.h).\n\n

    \n

    The module_name needs to match the filename of the final binary (minus the\n.node suffix).\n\n

    \n

    The source code needs to be built into addon.node, the binary Addon. To\ndo this we create a file called binding.gyp which describes the configuration\nto build your module in a JSON-like format. This file gets compiled by\nnode-gyp.\n\n

    \n
    {\n  "targets": [\n    {\n      "target_name": "addon",\n      "sources": [ "hello.cc" ]\n    }\n  ]\n}
    \n

    The next step is to generate the appropriate project build files for the\ncurrent platform. Use node-gyp configure for that.\n\n

    \n

    Now you will have either a Makefile (on Unix platforms) or a vcxproj file\n(on Windows) in the build/ directory. Next invoke the node-gyp build\ncommand.\n\n

    \n

    Now you have your compiled .node bindings file! The compiled bindings end up\nin build/Release/.\n\n

    \n

    You can now use the binary addon in a Node project hello.js by pointing\nrequire to the recently built hello.node module:\n\n

    \n
    // hello.js\nvar addon = require('./build/Release/addon');\n\nconsole.log(addon.hello()); // 'world'
    \n

    Please see patterns below for further information or\n

    \n

    https://github.com/arturadib/node-qt for an example in production.\n\n\n

    \n", "type": "module", "displayName": "Hello world" }, @@ -21,49 +21,49 @@ { "textRaw": "Function arguments", "name": "function_arguments", - "desc": "

    The following pattern illustrates how to read arguments from JavaScript\nfunction calls and return a result. This is the main and only needed source\naddon.cc:\n\n

    \n
    #include <node.h>\n\nusing namespace v8;\n\nHandle<Value> Add(const Arguments& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  if (args.Length() < 2) {\n    ThrowException(Exception::TypeError(\n        String::New("Wrong number of arguments")));\n    return scope.Close(Undefined(isolate));\n  }\n\n  if (!args[0]->IsNumber() || !args[1]->IsNumber()) {\n    ThrowException(Exception::TypeError(String::New("Wrong arguments")));\n    return scope.Close(Undefined(isolate));\n  }\n\n  Local<Number> num = Number::New(args[0]->NumberValue() +\n      args[1]->NumberValue());\n  return scope.Close(num);\n}\n\nvoid Init(Handle<Object> exports) {\n  exports->Set(String::NewSymbol("add"),\n      FunctionTemplate::New(Add)->GetFunction());\n}\n\nNODE_MODULE(addon, Init)
    \n

    You can test it with the following JavaScript snippet:\n\n

    \n
    var addon = require('./build/Release/addon');\n\nconsole.log( 'This should be eight:', addon.add(3,5) );
    \n", + "desc": "

    The following pattern illustrates how to read arguments from JavaScript\nfunction calls and return a result. This is the main and only needed source\naddon.cc:\n\n

    \n
    // addon.cc\n#include <node.h>\n\nusing namespace v8;\n\nvoid Add(const FunctionCallbackInfo<Value>& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  if (args.Length() < 2) {\n    isolate->ThrowException(Exception::TypeError(\n        String::NewFromUtf8(isolate, "Wrong number of arguments")));\n    return;\n  }\n\n  if (!args[0]->IsNumber() || !args[1]->IsNumber()) {\n    isolate->ThrowException(Exception::TypeError(\n        String::NewFromUtf8(isolate, "Wrong arguments")));\n    return;\n  }\n\n  Local<Number> num = Number::New(args[0]->NumberValue() +\n      args[1]->NumberValue());\n\n  args.GetReturnValue().Set(num);\n}\n\nvoid Init(Handle<Object> exports) {\n  NODE_SET_METHOD(exports, "add", Add);\n}\n\nNODE_MODULE(addon, Init)
    \n

    You can test it with the following JavaScript snippet:\n\n

    \n
    // test.js\nvar addon = require('./build/Release/addon');\n\nconsole.log( 'This should be eight:', addon.add(3,5) );
    \n", "type": "module", "displayName": "Function arguments" }, { "textRaw": "Callbacks", "name": "callbacks", - "desc": "

    You can pass JavaScript functions to a C++ function and execute them from\nthere. Here's addon.cc:\n\n

    \n
    #include <node.h>\n\nusing namespace v8;\n\nHandle<Value> RunCallback(const Arguments& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  Local<Function> cb = Local<Function>::Cast(args[0]);\n  const unsigned argc = 1;\n  Local<Value> argv[argc] = { String::New("hello world") };\n  cb->Call(Context::GetCurrent()->Global(), argc, argv);\n\n  return scope.Close(Undefined(isolate));\n}\n\nvoid Init(Handle<Object> exports, Handle<Object> module) {\n  module->Set(String::NewSymbol("exports"),\n      FunctionTemplate::New(RunCallback)->GetFunction());\n}\n\nNODE_MODULE(addon, Init)
    \n

    Note that this example uses a two-argument form of Init() that receives\nthe full module object as the second argument. This allows the addon\nto completely overwrite exports with a single function instead of\nadding the function as a property of exports.\n\n

    \n

    To test it run the following JavaScript snippet:\n\n

    \n
    var addon = require('./build/Release/addon');\n\naddon(function(msg){\n  console.log(msg); // 'hello world'\n});
    \n", + "desc": "

    You can pass JavaScript functions to a C++ function and execute them from\nthere. Here's addon.cc:\n\n

    \n
    // addon.cc\n#include <node.h>\n\nusing namespace v8;\n\nvoid RunCallback(const FunctionCallbackInfo<Value>& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  Local<Function> cb = Local<Function>::Cast(args[0]);\n  const unsigned argc = 1;\n  Local<Value> argv[argc] = { String::NewFromUtf8(isolate, "hello world") };\n  cb->Call(Context::GetCurrent()->Global(), argc, argv);\n}\n\nvoid Init(Handle<Object> exports, Handle<Object> module) {\n  NODE_SET_METHOD(module, "exports", RunCallback);\n}\n\nNODE_MODULE(addon, Init)
    \n

    Note that this example uses a two-argument form of Init() that receives\nthe full module object as the second argument. This allows the addon\nto completely overwrite exports with a single function instead of\nadding the function as a property of exports.\n\n

    \n

    To test it run the following JavaScript snippet:\n\n

    \n
    // test.js\nvar addon = require('./build/Release/addon');\n\naddon(function(msg){\n  console.log(msg); // 'hello world'\n});
    \n", "type": "module", "displayName": "Callbacks" }, { "textRaw": "Object factory", "name": "object_factory", - "desc": "

    You can create and return new objects from within a C++ function with this\naddon.cc pattern, which returns an object with property msg that echoes\nthe string passed to createObject():\n\n

    \n
    #include <node.h>\n\nusing namespace v8;\n\nHandle<Value> CreateObject(const Arguments& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  Local<Object> obj = Object::New();\n  obj->Set(String::NewSymbol("msg"), args[0]->ToString());\n\n  return scope.Close(obj);\n}\n\nvoid Init(Handle<Object> exports, Handle<Object> module) {\n  module->Set(String::NewSymbol("exports"),\n      FunctionTemplate::New(CreateObject)->GetFunction());\n}\n\nNODE_MODULE(addon, Init)
    \n

    To test it in JavaScript:\n\n

    \n
    var addon = require('./build/Release/addon');\n\nvar obj1 = addon('hello');\nvar obj2 = addon('world');\nconsole.log(obj1.msg+' '+obj2.msg); // 'hello world'
    \n", + "desc": "

    You can create and return new objects from within a C++ function with this\naddon.cc pattern, which returns an object with property msg that echoes\nthe string passed to createObject():\n\n

    \n
    // addon.cc\n#include <node.h>\n\nusing namespace v8;\n\nvoid CreateObject(const FunctionCallbackInfo<Value>& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  Local<Object> obj = Object::New();\n  obj->Set(String::NewFromUtf8(isolate, "msg"), args[0]->ToString());\n\n  args.GetReturnValue().Set(obj);\n}\n\nvoid Init(Handle<Object> exports, Handle<Object> module) {\n  NODE_SET_METHOD(module, "exports", CreateObject);\n}\n\nNODE_MODULE(addon, Init)
    \n

    To test it in JavaScript:\n\n

    \n
    // test.js\nvar addon = require('./build/Release/addon');\n\nvar obj1 = addon('hello');\nvar obj2 = addon('world');\nconsole.log(obj1.msg+' '+obj2.msg); // 'hello world'
    \n", "type": "module", "displayName": "Object factory" }, { "textRaw": "Function factory", "name": "function_factory", - "desc": "

    This pattern illustrates how to create and return a JavaScript function that\nwraps a C++ function:\n\n

    \n
    #include <node.h>\n\nusing namespace v8;\n\nHandle<Value> MyFunction(const Arguments& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n  return scope.Close(String::New("hello world"));\n}\n\nHandle<Value> CreateFunction(const Arguments& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  Local<FunctionTemplate> tpl = FunctionTemplate::New(MyFunction);\n  Local<Function> fn = tpl->GetFunction();\n\n  // omit this to make it anonymous\n  fn->SetName(String::NewSymbol("theFunction"));\n\n  return scope.Close(fn);\n}\n\nvoid Init(Handle<Object> exports, Handle<Object> module) {\n  module->Set(String::NewSymbol("exports"),\n      FunctionTemplate::New(CreateFunction)->GetFunction());\n}\n\nNODE_MODULE(addon, Init)
    \n

    To test:\n\n

    \n
    var addon = require('./build/Release/addon');\n\nvar fn = addon();\nconsole.log(fn()); // 'hello world'
    \n", + "desc": "

    This pattern illustrates how to create and return a JavaScript function that\nwraps a C++ function:\n\n

    \n
    // addon.cc\n#include <node.h>\n\nusing namespace v8;\n\nvoid MyFunction(const FunctionCallbackInfo<Value>& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n  args.GetReturnValue().Set(String::NewFromUtf8(isolate, "hello world"));\n}\n\nvoid CreateFunction(const FunctionCallbackInfo<Value>& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  Local<FunctionTemplate> tpl = FunctionTemplate::New(MyFunction);\n  Local<Function> fn = tpl->GetFunction();\n\n  // omit this to make it anonymous\n  fn->SetName(String::NewFromUtf8(isolate, "theFunction"));\n\n  args.GetReturnValue().Set(fn);\n}\n\nvoid Init(Handle<Object> exports, Handle<Object> module) {\n  NODE_SET_METHOD(module, "exports", CreateFunction);\n}\n\nNODE_MODULE(addon, Init)
    \n

    To test:\n\n

    \n
    // test.js\nvar addon = require('./build/Release/addon');\n\nvar fn = addon();\nconsole.log(fn()); // 'hello world'
    \n", "type": "module", "displayName": "Function factory" }, { "textRaw": "Wrapping C++ objects", "name": "wrapping_c++_objects", - "desc": "

    Here we will create a wrapper for a C++ object/class MyObject that can be\ninstantiated in JavaScript through the new operator. First prepare the main\nmodule addon.cc:\n\n

    \n
    #include <node.h>\n#include "myobject.h"\n\nusing namespace v8;\n\nvoid InitAll(Handle<Object> exports) {\n  MyObject::Init(exports);\n}\n\nNODE_MODULE(addon, InitAll)
    \n

    Then in myobject.h make your wrapper inherit from node::ObjectWrap:\n\n

    \n
    #ifndef MYOBJECT_H\n#define MYOBJECT_H\n\n#include <node.h>\n\nclass MyObject : public node::ObjectWrap {\n public:\n  static void Init(v8::Handle<v8::Object> exports);\n\n private:\n  explicit MyObject(double value = 0);\n  ~MyObject();\n\n  static v8::Handle<v8::Value> New(const v8::Arguments& args);\n  static v8::Handle<v8::Value> PlusOne(const v8::Arguments& args);\n  static v8::Persistent<v8::Function> constructor;\n  double value_;\n};\n\n#endif
    \n

    And in myobject.cc implement the various methods that you want to expose.\nHere we expose the method plusOne by adding it to the constructor's\nprototype:\n\n

    \n
    #include <node.h>\n#include <node_object_wrap.h>\n#include "myobject.h"\n\nusing namespace v8;\n\nPersistent<Function> MyObject::constructor;\n\nMyObject::MyObject(double value) : value_(value) {\n}\n\nMyObject::~MyObject() {\n}\n\nvoid MyObject::Init(Handle<Object> exports) {\n  Isolate* isolate = Isolate::GetCurrent();\n\n  // Prepare constructor template\n  Local<FunctionTemplate> tpl = FunctionTemplate::New(New);\n  tpl->SetClassName(String::NewSymbol("MyObject"));\n  tpl->InstanceTemplate()->SetInternalFieldCount(1);\n\n  // Prototype\n  tpl->PrototypeTemplate()->Set(String::NewSymbol("plusOne"),\n      FunctionTemplate::New(PlusOne)->GetFunction());\n\n  Persistent<Function> constructor\n      = Persistent<Function>::New(isolate, tpl->GetFunction());\n\n  exports->Set(String::NewSymbol("MyObject"), constructor);\n}\n\nHandle<Value> MyObject::New(const Arguments& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  if (args.IsConstructCall()) {\n    // Invoked as constructor: `new MyObject(...)`\n    double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();\n    MyObject* obj = new MyObject(value);\n    obj->Wrap(args.This());\n    return args.This();\n  } else {\n    // Invoked as plain function `MyObject(...)`, turn into construct call.\n    const int argc = 1;\n    Local<Value> argv[argc] = { args[0] };\n    return scope.Close(constructor->NewInstance(argc, argv));\n  }\n}\n\nHandle<Value> MyObject::PlusOne(const Arguments& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.This());\n  obj->value_ += 1;\n\n  return scope.Close(Number::New(obj->value_));\n}
    \n

    Test it with:\n\n

    \n
    var addon = require('./build/Release/addon');\n\nvar obj = new addon.MyObject(10);\nconsole.log( obj.plusOne() ); // 11\nconsole.log( obj.plusOne() ); // 12\nconsole.log( obj.plusOne() ); // 13
    \n", + "desc": "

    Here we will create a wrapper for a C++ object/class MyObject that can be\ninstantiated in JavaScript through the new operator. First prepare the main\nmodule addon.cc:\n\n

    \n
    // addon.cc\n#include <node.h>\n#include "myobject.h"\n\nusing namespace v8;\n\nvoid InitAll(Handle<Object> exports) {\n  MyObject::Init(exports);\n}\n\nNODE_MODULE(addon, InitAll)
    \n

    Then in myobject.h make your wrapper inherit from node::ObjectWrap:\n\n

    \n
    // myobject.h\n#ifndef MYOBJECT_H\n#define MYOBJECT_H\n\n#include <node.h>\n#include <node_object_wrap.h>\n\nclass MyObject : public node::ObjectWrap {\n public:\n  static void Init(v8::Handle<v8::Object> exports);\n\n private:\n  explicit MyObject(double value = 0);\n  ~MyObject();\n\n  static void New(const v8::FunctionCallbackInfo<v8::Value>& args);\n  static void PlusOne(const v8::FunctionCallbackInfo<v8::Value>& args);\n  static v8::Persistent<v8::Function> constructor;\n  double value_;\n};\n\n#endif
    \n

    And in myobject.cc implement the various methods that you want to expose.\nHere we expose the method plusOne by adding it to the constructor's\nprototype:\n\n

    \n
    // myobject.cc\n#include "myobject.h"\n\nusing namespace v8;\n\nPersistent<Function> MyObject::constructor;\n\nMyObject::MyObject(double value) : value_(value) {\n}\n\nMyObject::~MyObject() {\n}\n\nvoid MyObject::Init(Handle<Object> exports) {\n  Isolate* isolate = Isolate::GetCurrent();\n\n  // Prepare constructor template\n  Local<FunctionTemplate> tpl = FunctionTemplate::New(New);\n  tpl->SetClassName(String::NewFromUtf8(isolate, "MyObject"));\n  tpl->InstanceTemplate()->SetInternalFieldCount(1);\n\n  // Prototype\n  NODE_SET_PROTOTYPE_METHOD(tpl, "plusOne", PlusOne);\n\n  constructor.Reset(isolate, tpl->GetFunction());\n  exports->Set(String::NewFromUtf8(isolate, "MyObject"),\n               tpl->GetFunction());\n}\n\nvoid MyObject::New(const FunctionCallbackInfo<Value>& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  if (args.IsConstructCall()) {\n    // Invoked as constructor: `new MyObject(...)`\n    double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();\n    MyObject* obj = new MyObject(value);\n    obj->Wrap(args.This());\n    args.GetReturnValue().Set(args.This());\n  } else {\n    // Invoked as plain function `MyObject(...)`, turn into construct call.\n    const int argc = 1;\n    Local<Value> argv[argc] = { args[0] };\n    Local<Function> cons = Local<Function>::New(isolate, constructor);\n    args.GetReturnValue().Set(cons->NewInstance(argc, argv));\n  }\n}\n\nvoid MyObject::PlusOne(const FunctionCallbackInfo<Value>& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.This());\n  obj->value_ += 1;\n\n  args.GetReturnValue().Set(Number::New(obj->value_));\n}
    \n

    Test it with:\n\n

    \n
    // test.js\nvar addon = require('./build/Release/addon');\n\nvar obj = new addon.MyObject(10);\nconsole.log( obj.plusOne() ); // 11\nconsole.log( obj.plusOne() ); // 12\nconsole.log( obj.plusOne() ); // 13
    \n", "type": "module", "displayName": "Wrapping C++ objects" }, { "textRaw": "Factory of wrapped objects", "name": "factory_of_wrapped_objects", - "desc": "

    This is useful when you want to be able to create native objects without\nexplicitly instantiating them with the new operator in JavaScript, e.g.\n\n

    \n
    var obj = addon.createObject();\n// instead of:\n// var obj = new addon.Object();
    \n

    Let's register our createObject method in addon.cc:\n\n

    \n
    #include <node.h>\n#include "myobject.h"\n\nusing namespace v8;\n\nHandle<Value> CreateObject(const Arguments& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n  return scope.Close(MyObject::NewInstance(args));\n}\n\nvoid InitAll(Handle<Object> exports, Handle<Object> module) {\n  MyObject::Init();\n\n  module->Set(String::NewSymbol("exports"),\n      FunctionTemplate::New(CreateObject)->GetFunction());\n}\n\nNODE_MODULE(addon, InitAll)
    \n

    In myobject.h we now introduce the static method NewInstance that takes\ncare of instantiating the object (i.e. it does the job of new in JavaScript):\n\n

    \n
    #ifndef MYOBJECT_H\n#define MYOBJECT_H\n\n#include <node.h>\n\nclass MyObject : public node::ObjectWrap {\n public:\n  static void Init();\n  static v8::Handle<v8::Value> NewInstance(const v8::Arguments& args);\n\n private:\n  explicit MyObject(double value = 0);\n  ~MyObject();\n\n  static v8::Handle<v8::Value> New(const v8::Arguments& args);\n  static v8::Handle<v8::Value> PlusOne(const v8::Arguments& args);\n  static v8::Persistent<v8::Function> constructor;\n  double value_;\n};\n\n#endif
    \n

    The implementation is similar to the above in myobject.cc:\n\n

    \n
    #include <node.h>\n#include "myobject.h"\n\nusing namespace v8;\n\nPersistent<Function> MyObject::constructor;\n\nMyObject::MyObject(double value) : value_(value) {\n}\n\nMyObject::~MyObject() {\n}\n\nvoid MyObject::Init() {\n  Isolate* isolate = Isolate::GetCurrent();\n  // Prepare constructor template\n  Local<FunctionTemplate> tpl = FunctionTemplate::New(New);\n  tpl->SetClassName(String::NewSymbol("MyObject"));\n  tpl->InstanceTemplate()->SetInternalFieldCount(1);\n\n  // Prototype\n  tpl->PrototypeTemplate()->Set(String::NewSymbol("plusOne"),\n      FunctionTemplate::New(PlusOne)->GetFunction());\n\n  constructor = Persistent<Function>::New(isolate, tpl->GetFunction());\n}\n\nHandle<Value> MyObject::New(const Arguments& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  if (args.IsConstructCall()) {\n    // Invoked as constructor: `new MyObject(...)`\n    double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();\n    MyObject* obj = new MyObject(value);\n    obj->Wrap(args.This());\n    return args.This();\n  } else {\n    // Invoked as plain function `MyObject(...)`, turn into construct call.\n    const int argc = 1;\n    Local<Value> argv[argc] = { args[0] };\n    return scope.Close(constructor->NewInstance(argc, argv));\n  }\n}\n\nHandle<Value> MyObject::NewInstance(const Arguments& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  const unsigned argc = 1;\n  Handle<Value> argv[argc] = { args[0] };\n  Local<Object> instance = constructor->NewInstance(argc, argv);\n\n  return scope.Close(instance);\n}\n\nHandle<Value> MyObject::PlusOne(const Arguments& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.This());\n  obj->value_ += 1;\n\n  return scope.Close(Number::New(obj->value_));\n}
    \n

    Test it with:\n\n

    \n
    var createObject = require('./build/Release/addon');\n\nvar obj = createObject(10);\nconsole.log( obj.plusOne() ); // 11\nconsole.log( obj.plusOne() ); // 12\nconsole.log( obj.plusOne() ); // 13\n\nvar obj2 = createObject(20);\nconsole.log( obj2.plusOne() ); // 21\nconsole.log( obj2.plusOne() ); // 22\nconsole.log( obj2.plusOne() ); // 23
    \n", + "desc": "

    This is useful when you want to be able to create native objects without\nexplicitly instantiating them with the new operator in JavaScript, e.g.\n\n

    \n
    var obj = addon.createObject();\n// instead of:\n// var obj = new addon.Object();
    \n

    Let's register our createObject method in addon.cc:\n\n

    \n
    // addon.cc\n#include <node.h>\n#include "myobject.h"\n\nusing namespace v8;\n\nvoid CreateObject(const FunctionCallbackInfo<Value>& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n  MyObject::NewInstance(args);\n}\n\nvoid InitAll(Handle<Object> exports, Handle<Object> module) {\n  MyObject::Init();\n\n  NODE_SET_METHOD(module, "exports", CreateObject);\n}\n\nNODE_MODULE(addon, InitAll)
    \n

    In myobject.h we now introduce the static method NewInstance that takes\ncare of instantiating the object (i.e. it does the job of new in JavaScript):\n\n

    \n
    // myobject.h\n#ifndef MYOBJECT_H\n#define MYOBJECT_H\n\n#include <node.h>\n#include <node_object_wrap.h>\n\nclass MyObject : public node::ObjectWrap {\n public:\n  static void Init();\n  static void NewInstance(const v8::FunctionCallbackInfo<v8::Value>& args);\n\n private:\n  explicit MyObject(double value = 0);\n  ~MyObject();\n\n  static void New(const v8::FunctionCallbackInfo<v8::Value>& args);\n  static void PlusOne(const v8::FunctionCallbackInfo<v8::Value>& args);\n  static v8::Persistent<v8::Function> constructor;\n  double value_;\n};\n\n#endif
    \n

    The implementation is similar to the above in myobject.cc:\n\n

    \n
    // myobject.cc\n#include <node.h>\n#include "myobject.h"\n\nusing namespace v8;\n\nPersistent<Function> MyObject::constructor;\n\nMyObject::MyObject(double value) : value_(value) {\n}\n\nMyObject::~MyObject() {\n}\n\nvoid MyObject::Init() {\n  Isolate* isolate = Isolate::GetCurrent();\n  // Prepare constructor template\n  Local<FunctionTemplate> tpl = FunctionTemplate::New(New);\n  tpl->SetClassName(String::NewFromUtf8(isolate, "MyObject"));\n  tpl->InstanceTemplate()->SetInternalFieldCount(1);\n\n  // Prototype\n  NODE_SET_PROTOTYPE_METHOD(tpl, "plusOne", PlusOne);\n\n  constructor.Reset(isolate, tpl->GetFunction());\n}\n\nvoid MyObject::New(const FunctionCallbackInfo<Value>& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  if (args.IsConstructCall()) {\n    // Invoked as constructor: `new MyObject(...)`\n    double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();\n    MyObject* obj = new MyObject(value);\n    obj->Wrap(args.This());\n    args.GetReturnValue().Set(args.This());\n  } else {\n    // Invoked as plain function `MyObject(...)`, turn into construct call.\n    const int argc = 1;\n    Local<Value> argv[argc] = { args[0] };\n    Local<Function> cons = Local<Function>::New(isolate, constructor);\n    args.GetReturnValue().Set(cons->NewInstance(argc, argv));\n  }\n}\n\nvoid MyObject::NewInstance(const FunctionCallbackInfo<Value>& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  const unsigned argc = 1;\n  Handle<Value> argv[argc] = { args[0] };\n  Local<Function> cons = Local<Function>::New(isolate, constructor);\n  Local<Object> instance = cons->NewInstance(argc, argv);\n\n  args.GetReturnValue().Set(instance);\n}\n\nvoid MyObject::PlusOne(const FunctionCallbackInfo<Value>& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.This());\n  obj->value_ += 1;\n\n  args.GetReturnValue().Set(Number::New(obj->value_));\n}
    \n

    Test it with:\n\n

    \n
    // test.js\nvar createObject = require('./build/Release/addon');\n\nvar obj = createObject(10);\nconsole.log( obj.plusOne() ); // 11\nconsole.log( obj.plusOne() ); // 12\nconsole.log( obj.plusOne() ); // 13\n\nvar obj2 = createObject(20);\nconsole.log( obj2.plusOne() ); // 21\nconsole.log( obj2.plusOne() ); // 22\nconsole.log( obj2.plusOne() ); // 23
    \n", "type": "module", "displayName": "Factory of wrapped objects" }, { "textRaw": "Passing wrapped objects around", "name": "passing_wrapped_objects_around", - "desc": "

    In addition to wrapping and returning C++ objects, you can pass them around\nby unwrapping them with Node's node::ObjectWrap::Unwrap helper function.\nIn the following addon.cc we introduce a function add() that can take on two\nMyObject objects:\n\n

    \n
    #include <node.h>\n#include <node_object_wrap.h>\n#include "myobject.h"\n\nusing namespace v8;\n\nHandle<Value> CreateObject(const Arguments& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n  return scope.Close(MyObject::NewInstance(args));\n}\n\nHandle<Value> Add(const Arguments& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  MyObject* obj1 = node::ObjectWrap::Unwrap<MyObject>(\n      args[0]->ToObject());\n  MyObject* obj2 = node::ObjectWrap::Unwrap<MyObject>(\n      args[1]->ToObject());\n\n  double sum = obj1->Value() + obj2->Value();\n  return scope.Close(Number::New(sum));\n}\n\nvoid InitAll(Handle<Object> exports) {\n  MyObject::Init();\n\n  exports->Set(String::NewSymbol("createObject"),\n      FunctionTemplate::New(CreateObject)->GetFunction());\n\n  exports->Set(String::NewSymbol("add"),\n      FunctionTemplate::New(Add)->GetFunction());\n}\n\nNODE_MODULE(addon, InitAll)
    \n

    To make things interesting we introduce a public method in myobject.h so we\ncan probe private values after unwrapping the object:\n\n

    \n
    #ifndef MYOBJECT_H\n#define MYOBJECT_H\n\n#include <node.h>\n#include <node_object_wrap.h>\n\nclass MyObject : public node::ObjectWrap {\n public:\n  static void Init();\n  static v8::Handle<v8::Value> NewInstance(const v8::Arguments& args);\n  double Value() const { return value_; }\n\n private:\n  explicit MyObject(double value = 0);\n  ~MyObject();\n\n  static v8::Handle<v8::Value> New(const v8::Arguments& args);\n  static v8::Persistent<v8::Function> constructor;\n  double value_;\n};\n\n#endif
    \n

    The implementation of myobject.cc is similar as before:\n\n

    \n
    #include <node.h>\n#include "myobject.h"\n\nusing namespace v8;\n\nPersistent<Function> MyObject::constructor;\n\nMyObject::MyObject(double value) : value_(value) {\n}\n\nMyObject::~MyObject() {\n}\n\nvoid MyObject::Init() {\n  Isolate* isolate = Isolate::GetCurrent();\n\n  // Prepare constructor template\n  Local<FunctionTemplate> tpl = FunctionTemplate::New(New);\n  tpl->SetClassName(String::NewSymbol("MyObject"));\n  tpl->InstanceTemplate()->SetInternalFieldCount(1);\n\n  constructor = Persistent<Function>::New(isolate, tpl->GetFunction());\n}\n\nHandle<Value> MyObject::New(const Arguments& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  if (args.IsConstructCall()) {\n    // Invoked as constructor: `new MyObject(...)`\n    double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();\n    MyObject* obj = new MyObject(value);\n    obj->Wrap(args.This());\n    return args.This();\n  } else {\n    // Invoked as plain function `MyObject(...)`, turn into construct call.\n    const int argc = 1;\n    Local<Value> argv[argc] = { args[0] };\n    return scope.Close(constructor->NewInstance(argc, argv));\n  }\n}\n\nHandle<Value> MyObject::NewInstance(const Arguments& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  const unsigned argc = 1;\n  Handle<Value> argv[argc] = { args[0] };\n  Local<Object> instance = constructor->NewInstance(argc, argv);\n\n  return scope.Close(instance);\n}
    \n

    Test it with:\n\n

    \n
    var addon = require('./build/Release/addon');\n\nvar obj1 = addon.createObject(10);\nvar obj2 = addon.createObject(20);\nvar result = addon.add(obj1, obj2);\n\nconsole.log(result); // 30
    \n", + "desc": "

    In addition to wrapping and returning C++ objects, you can pass them around\nby unwrapping them with Node's node::ObjectWrap::Unwrap helper function.\nIn the following addon.cc we introduce a function add() that can take on two\nMyObject objects:\n\n

    \n
    // addon.cc\n#include <node.h>\n#include <node_object_wrap.h>\n#include "myobject.h"\n\nusing namespace v8;\n\nvoid CreateObject(const FunctionCallbackInfo<Value>& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n  MyObject::NewInstance(args);\n}\n\nvoid Add(const FunctionCallbackInfo<Value>& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  MyObject* obj1 = node::ObjectWrap::Unwrap<MyObject>(\n      args[0]->ToObject());\n  MyObject* obj2 = node::ObjectWrap::Unwrap<MyObject>(\n      args[1]->ToObject());\n\n  double sum = obj1->value() + obj2->value();\n  args.GetReturnValue().Set(Number::New(sum));\n}\n\nvoid InitAll(Handle<Object> exports) {\n  MyObject::Init();\n\n  NODE_SET_METHOD(exports, "createObject", CreateObject);\n  NODE_SET_METHOD(exports, "add", Add);\n}\n\nNODE_MODULE(addon, InitAll)
    \n

    To make things interesting we introduce a public method in myobject.h so we\ncan probe private values after unwrapping the object:\n\n

    \n
    // myobject.h\n#ifndef MYOBJECT_H\n#define MYOBJECT_H\n\n#include <node.h>\n#include <node_object_wrap.h>\n\nclass MyObject : public node::ObjectWrap {\n public:\n  static void Init();\n  static void NewInstance(const v8::FunctionCallbackInfo<v8::Value>& args);\n  inline double value() const { return value_; }\n\n private:\n  explicit MyObject(double value = 0);\n  ~MyObject();\n\n  static void New(const v8::FunctionCallbackInfo<v8::Value>& args);\n  static v8::Persistent<v8::Function> constructor;\n  double value_;\n};\n\n#endif
    \n

    The implementation of myobject.cc is similar as before:\n\n

    \n
    // myobject.cc\n#include <node.h>\n#include "myobject.h"\n\nusing namespace v8;\n\nPersistent<Function> MyObject::constructor;\n\nMyObject::MyObject(double value) : value_(value) {\n}\n\nMyObject::~MyObject() {\n}\n\nvoid MyObject::Init() {\n  Isolate* isolate = Isolate::GetCurrent();\n\n  // Prepare constructor template\n  Local<FunctionTemplate> tpl = FunctionTemplate::New(New);\n  tpl->SetClassName(String::NewFromUtf8(isolate, "MyObject"));\n  tpl->InstanceTemplate()->SetInternalFieldCount(1);\n\n  constructor.Reset(isolate, tpl->GetFunction());\n}\n\nvoid MyObject::New(const FunctionCallbackInfo<Value>& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  if (args.IsConstructCall()) {\n    // Invoked as constructor: `new MyObject(...)`\n    double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();\n    MyObject* obj = new MyObject(value);\n    obj->Wrap(args.This());\n    args.GetReturnValue().Set(args.This());\n  } else {\n    // Invoked as plain function `MyObject(...)`, turn into construct call.\n    const int argc = 1;\n    Local<Value> argv[argc] = { args[0] };\n    Local<Function> cons = Local<Function>::New(isolate, constructor);\n    args.GetReturnValue().Set(cons->NewInstance(argc, argv));\n  }\n}\n\nvoid MyObject::NewInstance(const FunctionCallbackInfo<Value>& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  const unsigned argc = 1;\n  Handle<Value> argv[argc] = { args[0] };\n  Local<Function> cons = Local<Function>::New(isolate, constructor);\n  Local<Object> instance = cons->NewInstance(argc, argv);\n\n  args.GetReturnValue().Set(instance);\n}
    \n

    Test it with:\n\n

    \n
    // test.js\nvar addon = require('./build/Release/addon');\n\nvar obj1 = addon.createObject(10);\nvar obj2 = addon.createObject(20);\nvar result = addon.add(obj1, obj2);\n\nconsole.log(result); // 30
    \n", "type": "module", "displayName": "Passing wrapped objects around" } diff -Nru nodejs-0.11.10/doc/api/addons.markdown nodejs-0.11.11/doc/api/addons.markdown --- nodejs-0.11.10/doc/api/addons.markdown 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/doc/api/addons.markdown 2014-01-29 01:29:56.000000000 +0000 @@ -38,22 +38,22 @@ First we create a file `hello.cc`: + // hello.cc #include using namespace v8; - Handle Method(const Arguments& args) { + void Method(const FunctionCallbackInfo& args) { Isolate* isolate = Isolate::GetCurrent(); HandleScope scope(isolate); - return scope.Close(String::New("world")); + args.GetReturnValue().Set(String::NewFromUtf8(isolate, "world")); } void init(Handle exports) { - exports->Set(String::NewSymbol("hello"), - FunctionTemplate::New(Method)->GetFunction()); + NODE_SET_METHOD(exports, "hello", Method); } - NODE_MODULE(hello, init) + NODE_MODULE(addon, init) Note that all Node addons must export an initialization function: @@ -66,7 +66,7 @@ The `module_name` needs to match the filename of the final binary (minus the .node suffix). -The source code needs to be built into `hello.node`, the binary Addon. To +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 to build your module in a JSON-like format. This file gets compiled by [node-gyp](https://github.com/TooTallNate/node-gyp). @@ -74,7 +74,7 @@ { "targets": [ { - "target_name": "hello", + "target_name": "addon", "sources": [ "hello.cc" ] } ] @@ -93,7 +93,8 @@ You can now use the binary addon in a Node project `hello.js` by pointing `require` to the recently built `hello.node` module: - var addon = require('./build/Release/hello'); + // hello.js + var addon = require('./build/Release/addon'); console.log(addon.hello()); // 'world' @@ -138,39 +139,42 @@ function calls and return a result. This is the main and only needed source `addon.cc`: + // addon.cc #include using namespace v8; - Handle Add(const Arguments& args) { + void Add(const FunctionCallbackInfo& args) { Isolate* isolate = Isolate::GetCurrent(); HandleScope scope(isolate); if (args.Length() < 2) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments"))); - return scope.Close(Undefined(isolate)); + isolate->ThrowException(Exception::TypeError( + String::NewFromUtf8(isolate, "Wrong number of arguments"))); + return; } if (!args[0]->IsNumber() || !args[1]->IsNumber()) { - ThrowException(Exception::TypeError(String::New("Wrong arguments"))); - return scope.Close(Undefined(isolate)); + isolate->ThrowException(Exception::TypeError( + String::NewFromUtf8(isolate, "Wrong arguments"))); + return; } Local num = Number::New(args[0]->NumberValue() + args[1]->NumberValue()); - return scope.Close(num); + + args.GetReturnValue().Set(num); } void Init(Handle exports) { - exports->Set(String::NewSymbol("add"), - FunctionTemplate::New(Add)->GetFunction()); + NODE_SET_METHOD(exports, "add", Add); } NODE_MODULE(addon, Init) You can test it with the following JavaScript snippet: + // test.js var addon = require('./build/Release/addon'); console.log( 'This should be eight:', addon.add(3,5) ); @@ -181,25 +185,23 @@ You can pass JavaScript functions to a C++ function and execute them from there. Here's `addon.cc`: + // addon.cc #include using namespace v8; - Handle RunCallback(const Arguments& args) { + void RunCallback(const FunctionCallbackInfo& args) { Isolate* isolate = Isolate::GetCurrent(); HandleScope scope(isolate); Local cb = Local::Cast(args[0]); const unsigned argc = 1; - Local argv[argc] = { String::New("hello world") }; + Local argv[argc] = { String::NewFromUtf8(isolate, "hello world") }; cb->Call(Context::GetCurrent()->Global(), argc, argv); - - return scope.Close(Undefined(isolate)); } void Init(Handle exports, Handle module) { - module->Set(String::NewSymbol("exports"), - FunctionTemplate::New(RunCallback)->GetFunction()); + NODE_SET_METHOD(module, "exports", RunCallback); } NODE_MODULE(addon, Init) @@ -211,6 +213,7 @@ To test it run the following JavaScript snippet: + // test.js var addon = require('./build/Release/addon'); addon(function(msg){ @@ -224,29 +227,30 @@ `addon.cc` pattern, which returns an object with property `msg` that echoes the string passed to `createObject()`: + // addon.cc #include using namespace v8; - Handle CreateObject(const Arguments& args) { + void CreateObject(const FunctionCallbackInfo& args) { Isolate* isolate = Isolate::GetCurrent(); HandleScope scope(isolate); Local obj = Object::New(); - obj->Set(String::NewSymbol("msg"), args[0]->ToString()); + obj->Set(String::NewFromUtf8(isolate, "msg"), args[0]->ToString()); - return scope.Close(obj); + args.GetReturnValue().Set(obj); } void Init(Handle exports, Handle module) { - module->Set(String::NewSymbol("exports"), - FunctionTemplate::New(CreateObject)->GetFunction()); + NODE_SET_METHOD(module, "exports", CreateObject); } NODE_MODULE(addon, Init) To test it in JavaScript: + // test.js var addon = require('./build/Release/addon'); var obj1 = addon('hello'); @@ -259,17 +263,18 @@ This pattern illustrates how to create and return a JavaScript function that wraps a C++ function: + // addon.cc #include using namespace v8; - Handle MyFunction(const Arguments& args) { + void MyFunction(const FunctionCallbackInfo& args) { Isolate* isolate = Isolate::GetCurrent(); HandleScope scope(isolate); - return scope.Close(String::New("hello world")); + args.GetReturnValue().Set(String::NewFromUtf8(isolate, "hello world")); } - Handle CreateFunction(const Arguments& args) { + void CreateFunction(const FunctionCallbackInfo& args) { Isolate* isolate = Isolate::GetCurrent(); HandleScope scope(isolate); @@ -277,20 +282,20 @@ Local fn = tpl->GetFunction(); // omit this to make it anonymous - fn->SetName(String::NewSymbol("theFunction")); + fn->SetName(String::NewFromUtf8(isolate, "theFunction")); - return scope.Close(fn); + args.GetReturnValue().Set(fn); } void Init(Handle exports, Handle module) { - module->Set(String::NewSymbol("exports"), - FunctionTemplate::New(CreateFunction)->GetFunction()); + NODE_SET_METHOD(module, "exports", CreateFunction); } NODE_MODULE(addon, Init) To test: + // test.js var addon = require('./build/Release/addon'); var fn = addon(); @@ -303,6 +308,7 @@ instantiated in JavaScript through the `new` operator. First prepare the main module `addon.cc`: + // addon.cc #include #include "myobject.h" @@ -316,10 +322,12 @@ Then in `myobject.h` make your wrapper inherit from `node::ObjectWrap`: + // myobject.h #ifndef MYOBJECT_H #define MYOBJECT_H #include + #include class MyObject : public node::ObjectWrap { public: @@ -329,8 +337,8 @@ explicit MyObject(double value = 0); ~MyObject(); - static v8::Handle New(const v8::Arguments& args); - static v8::Handle PlusOne(const v8::Arguments& args); + static void New(const v8::FunctionCallbackInfo& args); + static void PlusOne(const v8::FunctionCallbackInfo& args); static v8::Persistent constructor; double value_; }; @@ -341,8 +349,7 @@ Here we expose the method `plusOne` by adding it to the constructor's prototype: - #include - #include + // myobject.cc #include "myobject.h" using namespace v8; @@ -360,20 +367,18 @@ // Prepare constructor template Local tpl = FunctionTemplate::New(New); - tpl->SetClassName(String::NewSymbol("MyObject")); + tpl->SetClassName(String::NewFromUtf8(isolate, "MyObject")); tpl->InstanceTemplate()->SetInternalFieldCount(1); // Prototype - tpl->PrototypeTemplate()->Set(String::NewSymbol("plusOne"), - FunctionTemplate::New(PlusOne)->GetFunction()); - - Persistent constructor - = Persistent::New(isolate, tpl->GetFunction()); + NODE_SET_PROTOTYPE_METHOD(tpl, "plusOne", PlusOne); - exports->Set(String::NewSymbol("MyObject"), constructor); + constructor.Reset(isolate, tpl->GetFunction()); + exports->Set(String::NewFromUtf8(isolate, "MyObject"), + tpl->GetFunction()); } - Handle MyObject::New(const Arguments& args) { + void MyObject::New(const FunctionCallbackInfo& args) { Isolate* isolate = Isolate::GetCurrent(); HandleScope scope(isolate); @@ -382,27 +387,29 @@ double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue(); MyObject* obj = new MyObject(value); obj->Wrap(args.This()); - return args.This(); + args.GetReturnValue().Set(args.This()); } else { // Invoked as plain function `MyObject(...)`, turn into construct call. const int argc = 1; Local argv[argc] = { args[0] }; - return scope.Close(constructor->NewInstance(argc, argv)); + Local cons = Local::New(isolate, constructor); + args.GetReturnValue().Set(cons->NewInstance(argc, argv)); } } - Handle MyObject::PlusOne(const Arguments& args) { + void MyObject::PlusOne(const FunctionCallbackInfo& args) { Isolate* isolate = Isolate::GetCurrent(); HandleScope scope(isolate); MyObject* obj = ObjectWrap::Unwrap(args.This()); obj->value_ += 1; - return scope.Close(Number::New(obj->value_)); + args.GetReturnValue().Set(Number::New(obj->value_)); } Test it with: + // test.js var addon = require('./build/Release/addon'); var obj = new addon.MyObject(10); @@ -421,22 +428,22 @@ Let's register our `createObject` method in `addon.cc`: + // addon.cc #include #include "myobject.h" using namespace v8; - Handle CreateObject(const Arguments& args) { + void CreateObject(const FunctionCallbackInfo& args) { Isolate* isolate = Isolate::GetCurrent(); HandleScope scope(isolate); - return scope.Close(MyObject::NewInstance(args)); + MyObject::NewInstance(args); } void InitAll(Handle exports, Handle module) { MyObject::Init(); - module->Set(String::NewSymbol("exports"), - FunctionTemplate::New(CreateObject)->GetFunction()); + NODE_SET_METHOD(module, "exports", CreateObject); } NODE_MODULE(addon, InitAll) @@ -444,22 +451,24 @@ 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): + // myobject.h #ifndef MYOBJECT_H #define MYOBJECT_H #include + #include class MyObject : public node::ObjectWrap { public: static void Init(); - static v8::Handle NewInstance(const v8::Arguments& args); + static void NewInstance(const v8::FunctionCallbackInfo& args); private: explicit MyObject(double value = 0); ~MyObject(); - static v8::Handle New(const v8::Arguments& args); - static v8::Handle PlusOne(const v8::Arguments& args); + static void New(const v8::FunctionCallbackInfo& args); + static void PlusOne(const v8::FunctionCallbackInfo& args); static v8::Persistent constructor; double value_; }; @@ -468,6 +477,7 @@ The implementation is similar to the above in `myobject.cc`: + // myobject.cc #include #include "myobject.h" @@ -485,17 +495,16 @@ Isolate* isolate = Isolate::GetCurrent(); // Prepare constructor template Local tpl = FunctionTemplate::New(New); - tpl->SetClassName(String::NewSymbol("MyObject")); + tpl->SetClassName(String::NewFromUtf8(isolate, "MyObject")); tpl->InstanceTemplate()->SetInternalFieldCount(1); // Prototype - tpl->PrototypeTemplate()->Set(String::NewSymbol("plusOne"), - FunctionTemplate::New(PlusOne)->GetFunction()); + NODE_SET_PROTOTYPE_METHOD(tpl, "plusOne", PlusOne); - constructor = Persistent::New(isolate, tpl->GetFunction()); + constructor.Reset(isolate, tpl->GetFunction()); } - Handle MyObject::New(const Arguments& args) { + void MyObject::New(const FunctionCallbackInfo& args) { Isolate* isolate = Isolate::GetCurrent(); HandleScope scope(isolate); @@ -504,38 +513,41 @@ double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue(); MyObject* obj = new MyObject(value); obj->Wrap(args.This()); - return args.This(); + args.GetReturnValue().Set(args.This()); } else { // Invoked as plain function `MyObject(...)`, turn into construct call. const int argc = 1; Local argv[argc] = { args[0] }; - return scope.Close(constructor->NewInstance(argc, argv)); + Local cons = Local::New(isolate, constructor); + args.GetReturnValue().Set(cons->NewInstance(argc, argv)); } } - Handle MyObject::NewInstance(const Arguments& args) { + void MyObject::NewInstance(const FunctionCallbackInfo& args) { Isolate* isolate = Isolate::GetCurrent(); HandleScope scope(isolate); const unsigned argc = 1; Handle argv[argc] = { args[0] }; - Local instance = constructor->NewInstance(argc, argv); + Local cons = Local::New(isolate, constructor); + Local instance = cons->NewInstance(argc, argv); - return scope.Close(instance); + args.GetReturnValue().Set(instance); } - Handle MyObject::PlusOne(const Arguments& args) { + void MyObject::PlusOne(const FunctionCallbackInfo& args) { Isolate* isolate = Isolate::GetCurrent(); HandleScope scope(isolate); MyObject* obj = ObjectWrap::Unwrap(args.This()); obj->value_ += 1; - return scope.Close(Number::New(obj->value_)); + args.GetReturnValue().Set(Number::New(obj->value_)); } Test it with: + // test.js var createObject = require('./build/Release/addon'); var obj = createObject(10); @@ -556,19 +568,20 @@ In the following `addon.cc` we introduce a function `add()` that can take on two `MyObject` objects: + // addon.cc #include #include #include "myobject.h" using namespace v8; - Handle CreateObject(const Arguments& args) { + void CreateObject(const FunctionCallbackInfo& args) { Isolate* isolate = Isolate::GetCurrent(); HandleScope scope(isolate); - return scope.Close(MyObject::NewInstance(args)); + MyObject::NewInstance(args); } - Handle Add(const Arguments& args) { + void Add(const FunctionCallbackInfo& args) { Isolate* isolate = Isolate::GetCurrent(); HandleScope scope(isolate); @@ -577,18 +590,15 @@ MyObject* obj2 = node::ObjectWrap::Unwrap( args[1]->ToObject()); - double sum = obj1->Value() + obj2->Value(); - return scope.Close(Number::New(sum)); + double sum = obj1->value() + obj2->value(); + args.GetReturnValue().Set(Number::New(sum)); } void InitAll(Handle exports) { MyObject::Init(); - exports->Set(String::NewSymbol("createObject"), - FunctionTemplate::New(CreateObject)->GetFunction()); - - exports->Set(String::NewSymbol("add"), - FunctionTemplate::New(Add)->GetFunction()); + NODE_SET_METHOD(exports, "createObject", CreateObject); + NODE_SET_METHOD(exports, "add", Add); } NODE_MODULE(addon, InitAll) @@ -596,6 +606,7 @@ To make things interesting we introduce a public method in `myobject.h` so we can probe private values after unwrapping the object: + // myobject.h #ifndef MYOBJECT_H #define MYOBJECT_H @@ -605,14 +616,14 @@ class MyObject : public node::ObjectWrap { public: static void Init(); - static v8::Handle NewInstance(const v8::Arguments& args); - double Value() const { return value_; } + static void NewInstance(const v8::FunctionCallbackInfo& args); + inline double value() const { return value_; } private: explicit MyObject(double value = 0); ~MyObject(); - static v8::Handle New(const v8::Arguments& args); + static void New(const v8::FunctionCallbackInfo& args); static v8::Persistent constructor; double value_; }; @@ -621,6 +632,7 @@ The implementation of `myobject.cc` is similar as before: + // myobject.cc #include #include "myobject.h" @@ -639,13 +651,13 @@ // Prepare constructor template Local tpl = FunctionTemplate::New(New); - tpl->SetClassName(String::NewSymbol("MyObject")); + tpl->SetClassName(String::NewFromUtf8(isolate, "MyObject")); tpl->InstanceTemplate()->SetInternalFieldCount(1); - constructor = Persistent::New(isolate, tpl->GetFunction()); + constructor.Reset(isolate, tpl->GetFunction()); } - Handle MyObject::New(const Arguments& args) { + void MyObject::New(const FunctionCallbackInfo& args) { Isolate* isolate = Isolate::GetCurrent(); HandleScope scope(isolate); @@ -654,28 +666,31 @@ double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue(); MyObject* obj = new MyObject(value); obj->Wrap(args.This()); - return args.This(); + args.GetReturnValue().Set(args.This()); } else { // Invoked as plain function `MyObject(...)`, turn into construct call. const int argc = 1; Local argv[argc] = { args[0] }; - return scope.Close(constructor->NewInstance(argc, argv)); + Local cons = Local::New(isolate, constructor); + args.GetReturnValue().Set(cons->NewInstance(argc, argv)); } } - Handle MyObject::NewInstance(const Arguments& args) { + void MyObject::NewInstance(const FunctionCallbackInfo& args) { Isolate* isolate = Isolate::GetCurrent(); HandleScope scope(isolate); const unsigned argc = 1; Handle argv[argc] = { args[0] }; - Local instance = constructor->NewInstance(argc, argv); + Local cons = Local::New(isolate, constructor); + Local instance = cons->NewInstance(argc, argv); - return scope.Close(instance); + args.GetReturnValue().Set(instance); } Test it with: + // test.js var addon = require('./build/Release/addon'); var obj1 = addon.createObject(10); diff -Nru nodejs-0.11.10/doc/api/all.html nodejs-0.11.11/doc/api/all.html --- nodejs-0.11.10/doc/api/all.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/all.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - About this Documentation Node.js v0.11.10 Manual & Documentation + About this Documentation Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -176,8 +176,8 @@

  • process.uptime()
  • process.hrtime()
  • Async Listeners
  • -
  • process.createAsyncListener(asyncListener[, callbacksObj[, storageValue]])
  • -
  • process.addAsyncListener(asyncListener[, callbacksObj[, storageValue]])
  • +
  • process.createAsyncListener(callbacksObj[, userData])
  • +
  • process.addAsyncListener(callbacksObj[, userData])
  • process.addAsyncListener(asyncListener)
  • process.removeAsyncListener(asyncListener)
  • @@ -374,6 +374,7 @@
  • Crypto
  • crypto.getDiffieHellman(group_name)
  • -
  • crypto.pbkdf2(password, salt, iterations, keylen, callback)
  • -
  • crypto.pbkdf2Sync(password, salt, iterations, keylen)
  • +
  • crypto.pbkdf2(password, salt, iterations, keylen, [digest], callback)
  • +
  • crypto.pbkdf2Sync(password, salt, iterations, keylen, [digest])
  • crypto.randomBytes(size, [callback])
  • crypto.pseudoRandomBytes(size, [callback])
  • Class: Certificate
  • REPL
  • @@ -2096,22 +2103,22 @@

    First we create a file hello.cc:

    -
    #include <node.h>
    +
    // hello.cc
    +#include <node.h>
     
     using namespace v8;
     
    -Handle<Value> Method(const Arguments& args) {
    +void Method(const FunctionCallbackInfo<Value>& args) {
       Isolate* isolate = Isolate::GetCurrent();
       HandleScope scope(isolate);
    -  return scope.Close(String::New("world"));
    +  args.GetReturnValue().Set(String::NewFromUtf8(isolate, "world"));
     }
     
     void init(Handle<Object> exports) {
    -  exports->Set(String::NewSymbol("hello"),
    -      FunctionTemplate::New(Method)->GetFunction());
    +  NODE_SET_METHOD(exports, "hello", Method);
     }
     
    -NODE_MODULE(hello, init)
    +NODE_MODULE(addon, init)

    Note that all Node addons must export an initialization function:

    @@ -2125,7 +2132,7 @@ .node suffix).

    -

    The source code needs to be built into hello.node, the binary Addon. To +

    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 to build your module in a JSON-like format. This file gets compiled by node-gyp. @@ -2134,7 +2141,7 @@

    {
       "targets": [
         {
    -      "target_name": "hello",
    +      "target_name": "addon",
           "sources": [ "hello.cc" ]
         }
       ]
    @@ -2156,7 +2163,8 @@
     require to the recently built hello.node module:
     
     

    -
    var addon = require('./build/Release/hello');
    +
    // hello.js
    +var addon = require('./build/Release/addon');
     
     console.log(addon.hello()); // 'world'

    Please see patterns below for further information or @@ -2201,40 +2209,43 @@ addon.cc:

    -
    #include <node.h>
    +
    // addon.cc
    +#include <node.h>
     
     using namespace v8;
     
    -Handle<Value> Add(const Arguments& args) {
    +void Add(const FunctionCallbackInfo<Value>& args) {
       Isolate* isolate = Isolate::GetCurrent();
       HandleScope scope(isolate);
     
       if (args.Length() < 2) {
    -    ThrowException(Exception::TypeError(
    -        String::New("Wrong number of arguments")));
    -    return scope.Close(Undefined(isolate));
    +    isolate->ThrowException(Exception::TypeError(
    +        String::NewFromUtf8(isolate, "Wrong number of arguments")));
    +    return;
       }
     
       if (!args[0]->IsNumber() || !args[1]->IsNumber()) {
    -    ThrowException(Exception::TypeError(String::New("Wrong arguments")));
    -    return scope.Close(Undefined(isolate));
    +    isolate->ThrowException(Exception::TypeError(
    +        String::NewFromUtf8(isolate, "Wrong arguments")));
    +    return;
       }
     
       Local<Number> num = Number::New(args[0]->NumberValue() +
           args[1]->NumberValue());
    -  return scope.Close(num);
    +
    +  args.GetReturnValue().Set(num);
     }
     
     void Init(Handle<Object> exports) {
    -  exports->Set(String::NewSymbol("add"),
    -      FunctionTemplate::New(Add)->GetFunction());
    +  NODE_SET_METHOD(exports, "add", Add);
     }
     
     NODE_MODULE(addon, Init)

    You can test it with the following JavaScript snippet:

    -
    var addon = require('./build/Release/addon');
    +
    // test.js
    +var addon = require('./build/Release/addon');
     
     console.log( 'This should be eight:', addon.add(3,5) );

    Callbacks#

    @@ -2242,25 +2253,23 @@ there. Here's addon.cc:

    -
    #include <node.h>
    +
    // addon.cc
    +#include <node.h>
     
     using namespace v8;
     
    -Handle<Value> RunCallback(const Arguments& args) {
    +void RunCallback(const FunctionCallbackInfo<Value>& args) {
       Isolate* isolate = Isolate::GetCurrent();
       HandleScope scope(isolate);
     
       Local<Function> cb = Local<Function>::Cast(args[0]);
       const unsigned argc = 1;
    -  Local<Value> argv[argc] = { String::New("hello world") };
    +  Local<Value> argv[argc] = { String::NewFromUtf8(isolate, "hello world") };
       cb->Call(Context::GetCurrent()->Global(), argc, argv);
    -
    -  return scope.Close(Undefined(isolate));
     }
     
     void Init(Handle<Object> exports, Handle<Object> module) {
    -  module->Set(String::NewSymbol("exports"),
    -      FunctionTemplate::New(RunCallback)->GetFunction());
    +  NODE_SET_METHOD(module, "exports", RunCallback);
     }
     
     NODE_MODULE(addon, Init)
    @@ -2273,7 +2282,8 @@

    To test it run the following JavaScript snippet:

    -
    var addon = require('./build/Release/addon');
    +
    // test.js
    +var addon = require('./build/Release/addon');
     
     addon(function(msg){
       console.log(msg); // 'hello world'
    @@ -2284,30 +2294,31 @@
     the string passed to createObject():
     
     

    -
    #include <node.h>
    +
    // addon.cc
    +#include <node.h>
     
     using namespace v8;
     
    -Handle<Value> CreateObject(const Arguments& args) {
    +void CreateObject(const FunctionCallbackInfo<Value>& args) {
       Isolate* isolate = Isolate::GetCurrent();
       HandleScope scope(isolate);
     
       Local<Object> obj = Object::New();
    -  obj->Set(String::NewSymbol("msg"), args[0]->ToString());
    +  obj->Set(String::NewFromUtf8(isolate, "msg"), args[0]->ToString());
     
    -  return scope.Close(obj);
    +  args.GetReturnValue().Set(obj);
     }
     
     void Init(Handle<Object> exports, Handle<Object> module) {
    -  module->Set(String::NewSymbol("exports"),
    -      FunctionTemplate::New(CreateObject)->GetFunction());
    +  NODE_SET_METHOD(module, "exports", CreateObject);
     }
     
     NODE_MODULE(addon, Init)

    To test it in JavaScript:

    -
    var addon = require('./build/Release/addon');
    +
    // test.js
    +var addon = require('./build/Release/addon');
     
     var obj1 = addon('hello');
     var obj2 = addon('world');
    @@ -2317,17 +2328,18 @@
     wraps a C++ function:
     
     

    -
    #include <node.h>
    +
    // addon.cc
    +#include <node.h>
     
     using namespace v8;
     
    -Handle<Value> MyFunction(const Arguments& args) {
    +void MyFunction(const FunctionCallbackInfo<Value>& args) {
       Isolate* isolate = Isolate::GetCurrent();
       HandleScope scope(isolate);
    -  return scope.Close(String::New("hello world"));
    +  args.GetReturnValue().Set(String::NewFromUtf8(isolate, "hello world"));
     }
     
    -Handle<Value> CreateFunction(const Arguments& args) {
    +void CreateFunction(const FunctionCallbackInfo<Value>& args) {
       Isolate* isolate = Isolate::GetCurrent();
       HandleScope scope(isolate);
     
    @@ -2335,21 +2347,21 @@
       Local<Function> fn = tpl->GetFunction();
     
       // omit this to make it anonymous
    -  fn->SetName(String::NewSymbol("theFunction"));
    +  fn->SetName(String::NewFromUtf8(isolate, "theFunction"));
     
    -  return scope.Close(fn);
    +  args.GetReturnValue().Set(fn);
     }
     
     void Init(Handle<Object> exports, Handle<Object> module) {
    -  module->Set(String::NewSymbol("exports"),
    -      FunctionTemplate::New(CreateFunction)->GetFunction());
    +  NODE_SET_METHOD(module, "exports", CreateFunction);
     }
     
     NODE_MODULE(addon, Init)

    To test:

    -
    var addon = require('./build/Release/addon');
    +
    // test.js
    +var addon = require('./build/Release/addon');
     
     var fn = addon();
     console.log(fn()); // 'hello world'
    @@ -2359,7 +2371,8 @@ module addon.cc:

    -
    #include <node.h>
    +
    // addon.cc
    +#include <node.h>
     #include "myobject.h"
     
     using namespace v8;
    @@ -2372,10 +2385,12 @@
     

    Then in myobject.h make your wrapper inherit from node::ObjectWrap:

    -
    #ifndef MYOBJECT_H
    +
    // myobject.h
    +#ifndef MYOBJECT_H
     #define MYOBJECT_H
     
     #include <node.h>
    +#include <node_object_wrap.h>
     
     class MyObject : public node::ObjectWrap {
      public:
    @@ -2385,8 +2400,8 @@
       explicit MyObject(double value = 0);
       ~MyObject();
     
    -  static v8::Handle<v8::Value> New(const v8::Arguments& args);
    -  static v8::Handle<v8::Value> PlusOne(const v8::Arguments& args);
    +  static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
    +  static void PlusOne(const v8::FunctionCallbackInfo<v8::Value>& args);
       static v8::Persistent<v8::Function> constructor;
       double value_;
     };
    @@ -2397,8 +2412,7 @@
     prototype:
     
     

    -
    #include <node.h>
    -#include <node_object_wrap.h>
    +
    // myobject.cc
     #include "myobject.h"
     
     using namespace v8;
    @@ -2416,20 +2430,18 @@
     
       // Prepare constructor template
       Local<FunctionTemplate> tpl = FunctionTemplate::New(New);
    -  tpl->SetClassName(String::NewSymbol("MyObject"));
    +  tpl->SetClassName(String::NewFromUtf8(isolate, "MyObject"));
       tpl->InstanceTemplate()->SetInternalFieldCount(1);
     
       // Prototype
    -  tpl->PrototypeTemplate()->Set(String::NewSymbol("plusOne"),
    -      FunctionTemplate::New(PlusOne)->GetFunction());
    -
    -  Persistent<Function> constructor
    -      = Persistent<Function>::New(isolate, tpl->GetFunction());
    +  NODE_SET_PROTOTYPE_METHOD(tpl, "plusOne", PlusOne);
     
    -  exports->Set(String::NewSymbol("MyObject"), constructor);
    +  constructor.Reset(isolate, tpl->GetFunction());
    +  exports->Set(String::NewFromUtf8(isolate, "MyObject"),
    +               tpl->GetFunction());
     }
     
    -Handle<Value> MyObject::New(const Arguments& args) {
    +void MyObject::New(const FunctionCallbackInfo<Value>& args) {
       Isolate* isolate = Isolate::GetCurrent();
       HandleScope scope(isolate);
     
    @@ -2438,28 +2450,30 @@
         double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
         MyObject* obj = new MyObject(value);
         obj->Wrap(args.This());
    -    return args.This();
    +    args.GetReturnValue().Set(args.This());
       } else {
         // Invoked as plain function `MyObject(...)`, turn into construct call.
         const int argc = 1;
         Local<Value> argv[argc] = { args[0] };
    -    return scope.Close(constructor->NewInstance(argc, argv));
    +    Local<Function> cons = Local<Function>::New(isolate, constructor);
    +    args.GetReturnValue().Set(cons->NewInstance(argc, argv));
       }
     }
     
    -Handle<Value> MyObject::PlusOne(const Arguments& args) {
    +void MyObject::PlusOne(const FunctionCallbackInfo<Value>& args) {
       Isolate* isolate = Isolate::GetCurrent();
       HandleScope scope(isolate);
     
       MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.This());
       obj->value_ += 1;
     
    -  return scope.Close(Number::New(obj->value_));
    +  args.GetReturnValue().Set(Number::New(obj->value_));
     }

    Test it with:

    -
    var addon = require('./build/Release/addon');
    +
    // test.js
    +var addon = require('./build/Release/addon');
     
     var obj = new addon.MyObject(10);
     console.log( obj.plusOne() ); // 11
    @@ -2476,22 +2490,22 @@
     

    Let's register our createObject method in addon.cc:

    -
    #include <node.h>
    +
    // addon.cc
    +#include <node.h>
     #include "myobject.h"
     
     using namespace v8;
     
    -Handle<Value> CreateObject(const Arguments& args) {
    +void CreateObject(const FunctionCallbackInfo<Value>& args) {
       Isolate* isolate = Isolate::GetCurrent();
       HandleScope scope(isolate);
    -  return scope.Close(MyObject::NewInstance(args));
    +  MyObject::NewInstance(args);
     }
     
     void InitAll(Handle<Object> exports, Handle<Object> module) {
       MyObject::Init();
     
    -  module->Set(String::NewSymbol("exports"),
    -      FunctionTemplate::New(CreateObject)->GetFunction());
    +  NODE_SET_METHOD(module, "exports", CreateObject);
     }
     
     NODE_MODULE(addon, InitAll)
    @@ -2499,22 +2513,24 @@ care of instantiating the object (i.e. it does the job of new in JavaScript):

    -
    #ifndef MYOBJECT_H
    +
    // myobject.h
    +#ifndef MYOBJECT_H
     #define MYOBJECT_H
     
     #include <node.h>
    +#include <node_object_wrap.h>
     
     class MyObject : public node::ObjectWrap {
      public:
       static void Init();
    -  static v8::Handle<v8::Value> NewInstance(const v8::Arguments& args);
    +  static void NewInstance(const v8::FunctionCallbackInfo<v8::Value>& args);
     
      private:
       explicit MyObject(double value = 0);
       ~MyObject();
     
    -  static v8::Handle<v8::Value> New(const v8::Arguments& args);
    -  static v8::Handle<v8::Value> PlusOne(const v8::Arguments& args);
    +  static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
    +  static void PlusOne(const v8::FunctionCallbackInfo<v8::Value>& args);
       static v8::Persistent<v8::Function> constructor;
       double value_;
     };
    @@ -2523,7 +2539,8 @@
     

    The implementation is similar to the above in myobject.cc:

    -
    #include <node.h>
    +
    // myobject.cc
    +#include <node.h>
     #include "myobject.h"
     
     using namespace v8;
    @@ -2540,17 +2557,16 @@
       Isolate* isolate = Isolate::GetCurrent();
       // Prepare constructor template
       Local<FunctionTemplate> tpl = FunctionTemplate::New(New);
    -  tpl->SetClassName(String::NewSymbol("MyObject"));
    +  tpl->SetClassName(String::NewFromUtf8(isolate, "MyObject"));
       tpl->InstanceTemplate()->SetInternalFieldCount(1);
     
       // Prototype
    -  tpl->PrototypeTemplate()->Set(String::NewSymbol("plusOne"),
    -      FunctionTemplate::New(PlusOne)->GetFunction());
    +  NODE_SET_PROTOTYPE_METHOD(tpl, "plusOne", PlusOne);
     
    -  constructor = Persistent<Function>::New(isolate, tpl->GetFunction());
    +  constructor.Reset(isolate, tpl->GetFunction());
     }
     
    -Handle<Value> MyObject::New(const Arguments& args) {
    +void MyObject::New(const FunctionCallbackInfo<Value>& args) {
       Isolate* isolate = Isolate::GetCurrent();
       HandleScope scope(isolate);
     
    @@ -2559,39 +2575,42 @@
         double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
         MyObject* obj = new MyObject(value);
         obj->Wrap(args.This());
    -    return args.This();
    +    args.GetReturnValue().Set(args.This());
       } else {
         // Invoked as plain function `MyObject(...)`, turn into construct call.
         const int argc = 1;
         Local<Value> argv[argc] = { args[0] };
    -    return scope.Close(constructor->NewInstance(argc, argv));
    +    Local<Function> cons = Local<Function>::New(isolate, constructor);
    +    args.GetReturnValue().Set(cons->NewInstance(argc, argv));
       }
     }
     
    -Handle<Value> MyObject::NewInstance(const Arguments& args) {
    +void MyObject::NewInstance(const FunctionCallbackInfo<Value>& args) {
       Isolate* isolate = Isolate::GetCurrent();
       HandleScope scope(isolate);
     
       const unsigned argc = 1;
       Handle<Value> argv[argc] = { args[0] };
    -  Local<Object> instance = constructor->NewInstance(argc, argv);
    +  Local<Function> cons = Local<Function>::New(isolate, constructor);
    +  Local<Object> instance = cons->NewInstance(argc, argv);
     
    -  return scope.Close(instance);
    +  args.GetReturnValue().Set(instance);
     }
     
    -Handle<Value> MyObject::PlusOne(const Arguments& args) {
    +void MyObject::PlusOne(const FunctionCallbackInfo<Value>& args) {
       Isolate* isolate = Isolate::GetCurrent();
       HandleScope scope(isolate);
     
       MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.This());
       obj->value_ += 1;
     
    -  return scope.Close(Number::New(obj->value_));
    +  args.GetReturnValue().Set(Number::New(obj->value_));
     }

    Test it with:

    -
    var createObject = require('./build/Release/addon');
    +
    // test.js
    +var createObject = require('./build/Release/addon');
     
     var obj = createObject(10);
     console.log( obj.plusOne() ); // 11
    @@ -2609,19 +2628,20 @@
     MyObject objects:
     
     

    -
    #include <node.h>
    +
    // addon.cc
    +#include <node.h>
     #include <node_object_wrap.h>
     #include "myobject.h"
     
     using namespace v8;
     
    -Handle<Value> CreateObject(const Arguments& args) {
    +void CreateObject(const FunctionCallbackInfo<Value>& args) {
       Isolate* isolate = Isolate::GetCurrent();
       HandleScope scope(isolate);
    -  return scope.Close(MyObject::NewInstance(args));
    +  MyObject::NewInstance(args);
     }
     
    -Handle<Value> Add(const Arguments& args) {
    +void Add(const FunctionCallbackInfo<Value>& args) {
       Isolate* isolate = Isolate::GetCurrent();
       HandleScope scope(isolate);
     
    @@ -2630,18 +2650,15 @@
       MyObject* obj2 = node::ObjectWrap::Unwrap<MyObject>(
           args[1]->ToObject());
     
    -  double sum = obj1->Value() + obj2->Value();
    -  return scope.Close(Number::New(sum));
    +  double sum = obj1->value() + obj2->value();
    +  args.GetReturnValue().Set(Number::New(sum));
     }
     
     void InitAll(Handle<Object> exports) {
       MyObject::Init();
     
    -  exports->Set(String::NewSymbol("createObject"),
    -      FunctionTemplate::New(CreateObject)->GetFunction());
    -
    -  exports->Set(String::NewSymbol("add"),
    -      FunctionTemplate::New(Add)->GetFunction());
    +  NODE_SET_METHOD(exports, "createObject", CreateObject);
    +  NODE_SET_METHOD(exports, "add", Add);
     }
     
     NODE_MODULE(addon, InitAll)
    @@ -2649,7 +2666,8 @@ can probe private values after unwrapping the object:

    -
    #ifndef MYOBJECT_H
    +
    // myobject.h
    +#ifndef MYOBJECT_H
     #define MYOBJECT_H
     
     #include <node.h>
    @@ -2658,14 +2676,14 @@
     class MyObject : public node::ObjectWrap {
      public:
       static void Init();
    -  static v8::Handle<v8::Value> NewInstance(const v8::Arguments& args);
    -  double Value() const { return value_; }
    +  static void NewInstance(const v8::FunctionCallbackInfo<v8::Value>& args);
    +  inline double value() const { return value_; }
     
      private:
       explicit MyObject(double value = 0);
       ~MyObject();
     
    -  static v8::Handle<v8::Value> New(const v8::Arguments& args);
    +  static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
       static v8::Persistent<v8::Function> constructor;
       double value_;
     };
    @@ -2674,7 +2692,8 @@
     

    The implementation of myobject.cc is similar as before:

    -
    #include <node.h>
    +
    // myobject.cc
    +#include <node.h>
     #include "myobject.h"
     
     using namespace v8;
    @@ -2692,13 +2711,13 @@
     
       // Prepare constructor template
       Local<FunctionTemplate> tpl = FunctionTemplate::New(New);
    -  tpl->SetClassName(String::NewSymbol("MyObject"));
    +  tpl->SetClassName(String::NewFromUtf8(isolate, "MyObject"));
       tpl->InstanceTemplate()->SetInternalFieldCount(1);
     
    -  constructor = Persistent<Function>::New(isolate, tpl->GetFunction());
    +  constructor.Reset(isolate, tpl->GetFunction());
     }
     
    -Handle<Value> MyObject::New(const Arguments& args) {
    +void MyObject::New(const FunctionCallbackInfo<Value>& args) {
       Isolate* isolate = Isolate::GetCurrent();
       HandleScope scope(isolate);
     
    @@ -2707,29 +2726,32 @@
         double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
         MyObject* obj = new MyObject(value);
         obj->Wrap(args.This());
    -    return args.This();
    +    args.GetReturnValue().Set(args.This());
       } else {
         // Invoked as plain function `MyObject(...)`, turn into construct call.
         const int argc = 1;
         Local<Value> argv[argc] = { args[0] };
    -    return scope.Close(constructor->NewInstance(argc, argv));
    +    Local<Function> cons = Local<Function>::New(isolate, constructor);
    +    args.GetReturnValue().Set(cons->NewInstance(argc, argv));
       }
     }
     
    -Handle<Value> MyObject::NewInstance(const Arguments& args) {
    +void MyObject::NewInstance(const FunctionCallbackInfo<Value>& args) {
       Isolate* isolate = Isolate::GetCurrent();
       HandleScope scope(isolate);
     
       const unsigned argc = 1;
       Handle<Value> argv[argc] = { args[0] };
    -  Local<Object> instance = constructor->NewInstance(argc, argv);
    +  Local<Function> cons = Local<Function>::New(isolate, constructor);
    +  Local<Object> instance = cons->NewInstance(argc, argv);
     
    -  return scope.Close(instance);
    +  args.GetReturnValue().Set(instance);
     }

    Test it with:

    -
    var addon = require('./build/Release/addon');
    +
    // test.js
    +var addon = require('./build/Release/addon');
     
     var obj1 = addon.createObject(10);
     var obj2 = addon.createObject(20);
    @@ -2887,9 +2909,9 @@
     SIGHUP is to terminate node, but once a listener has been installed its
     default behaviour will be removed.
     
  • SIGTERM is not supported on Windows, it can be listened on.
  • -
  • SIGINT is supported on all platforms, and can usually be generated with -CTRL+C (though this may be configurable). It is not generated when terminal -raw mode is enabled.
  • +
  • SIGINT from the terminal is supported on all platforms, and can usually be +generated with CTRL+C (though this may be configurable). It is not generated +when terminal raw mode is enabled.
  • SIGBREAK is delivered on Windows when CTRL+BREAK is pressed, on non-Windows platforms it can be listened on, but there is no way to send or generate it.
  • SIGWINCH is delivered when the console has been resized. On Windows, this will @@ -2899,6 +2921,13 @@ node on all platforms.
  • SIGSTOP cannot have a listener installed.
  • +

    Note that Windows does not support sending Signals, but node offers some +emulation with process.kill(), and child_process.kill(): +- Sending signal 0 can be used to search for the existence of a process +- Sending SIGINT, SIGTERM, and SIGKILL cause the unconditional exit of the + target process. + +

    process.stdout#

    A Writable Stream to stdout. @@ -3222,7 +3251,7 @@

    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'. -See kill(2) for more information. +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 @@ -3425,92 +3454,91 @@

    Stability: 1 - Experimental

    The AsyncListener API is the JavaScript interface for the AsyncWrap class which allows developers to be notified about key events in the lifetime of an asynchronous event. Node performs a lot of asynchronous -events internally, and significant use of this API will have a dramatic -performance impact on your application. +events internally, and significant use of this API may have a +significant performance impact on your application.

    -

    process.createAsyncListener(asyncListener[, callbacksObj[, storageValue]])#

    +

    process.createAsyncListener(callbacksObj[, userData])#

      -
    • asyncListener Function callback fired when an asynchronous event is -instantiated.
    • -
    • callbacksObj Object optional callbacks that will fire at specific -times in the lifetime of the asynchronous event.
    • -
    • storageValue Value a value that will be passed as the first argument -when the asyncListener callback is run, and to all subsequent callback.
    • +
    • callbacksObj Object Contains optional callbacks that will fire at +specific times in the life cycle of the asynchronous event.
    • +
    • userData Value a value that will be passed to all callbacks.

    Returns a constructed AsyncListener object.

    -

    To begin capturing asynchronous events pass the object to -process.addAsyncListener(). The same AsyncListener instance can -only be added once to the active queue, and subsequent attempts to add the -instance will be ignored. +

    To begin capturing asynchronous events pass either the callbacksObj or +and existing AsyncListener instance to process.addAsyncListener(). +The same AsyncListener instance can only be added once to the active +queue, and subsequent attempts to add the instance will be ignored.

    -

    To stop capturing pass the object to process.removeAsyncListener(). -This does not mean the AsyncListener previously added will stop -triggering callbacks. Once attached to an asynchronous event it will -persist with the lifetime of the asynchronous call stack. +

    To stop capturing pass the AsyncListener instance to +process.removeAsyncListener(). This does not mean the +AsyncListener previously added will stop triggering callbacks. Once +attached to an asynchronous event it will persist with the lifetime of the +asynchronous call stack.

    Explanation of function parameters: -

    -

    asyncListener(storageValue): A Function called when an asynchronous -event is instantiated. If a Value is returned then it will be attached -to the event and overwrite any value that had been passed to -process.createAsyncListener()'s storageValue argument. If an initial -storageValue was passed when created, then asyncListener() will -receive that as a function argument.

    callbacksObj: An Object which may contain three optional fields:

      -
    • before(context, storageValue): A Function that is called immediately +

    • create(userData): A Function called when an asynchronous +event is instantiated. If a Value is returned then it will be attached +to the event and overwrite any value that had been passed to +process.createAsyncListener()'s userData argument. If an initial +userData was passed when created, then create() will +receive that as a function argument.

      +
    • +
    • before(context, userData): A Function that is called immediately before the asynchronous callback is about to run. It will be passed both -the context (i.e. this) of the calling function and the storageValue -either returned from asyncListener or passed during construction (if +the context (i.e. this) of the calling function and the userData +either returned from create() or passed during construction (if either occurred).

    • -
    • after(context, storageValue): A Function called immediately after +

    • after(context, userData): A Function called immediately after the asynchronous event's callback has run. Note this will not be called if the callback throws and the error is not handled.

    • -
    • error(storageValue, error): A Function called if the event's -callback threw. If error returns true then Node will assume the error -has been properly handled and resume execution normally. When multiple -error() callbacks have been registered, only one of those callbacks -needs to return true for AsyncListener to accept that the error has -been handled.

      +
    • error(userData, error): A Function called if the event's +callback threw. If this registered callback returns true then Node will +assume the error has been properly handled and resume execution normally. +When multiple error() callbacks have been registered only one of +those callbacks needs to return true for AsyncListener to accept that +the error has been handled, but all error() callbacks will always be run.

    -

    storageValue: A Value (i.e. anything) that will be, by default, +

    userData: A Value (i.e. anything) that will be, by default, attached to all new event instances. This will be overwritten if a Value -is returned by asyncListener(). +is returned by create().

    -

    Here is an example of overwriting the storageValue: +

    Here is an example of overwriting the userData:

    -
    process.createAsyncListener(function listener(value) {
    -  // value === true
    -  return false;
    +
    process.createAsyncListener({
    +  create: function listener(value) {
    +    // value === true
    +    return false;
     }, {
       before: function before(context, value) {
         // value === false
       }
     }, true);

    Note: The EventEmitter, while used to emit status of an asynchronous -event, is not itself asynchronous. So asyncListener() will not fire when +event, is not itself asynchronous. So create() will not fire when an event is added, and before/after will not fire when emitted callbacks are called.

    -

    process.addAsyncListener(asyncListener[, callbacksObj[, storageValue]])#

    +

    process.addAsyncListener(callbacksObj[, userData])#

    process.addAsyncListener(asyncListener)#

    Returns a constructed AsyncListener object and immediately adds it to the listening queue to begin capturing asynchronous events. @@ -3524,36 +3552,32 @@

    Example usage for capturing errors:

    -
    var cntr = 0;
    -var key = process.addAsyncListener(function() {
    -  return { uid: cntr++ };
    -}, {
    +
    var fs = require('fs');
    +
    +var cntr = 0;
    +var key = process.addAsyncListener({
    +  create: function onCreate() {
    +    return { uid: cntr++ };
    +  },
       before: function onBefore(context, storage) {
    -    // Need to remove the listener while logging or will end up
    -    // with an infinite call loop.
    -    process.removeAsyncListener(key);
    -    console.log('uid: %s is about to run', storage.uid);
    -    process.addAsyncListener(key);
    +    // Write directly to stdout or we'll enter a recursive loop
    +    fs.writeSync(1, 'uid: ' + storage.uid + ' is about to run\n');
       },
       after: function onAfter(context, storage) {
    -    process.removeAsyncListener(key);
    -    console.log('uid: %s is about to run', storage.uid);
    -    process.addAsyncListener(key);
    +    fs.writeSync(1, 'uid: ' + storage.uid + ' is about to run\n');
       },
       error: function onError(storage, err) {
         // Handle known errors
    -    if (err.message === 'really, it\'s ok') {
    -      process.removeAsyncListener(key);
    -      console.log('handled error just threw:');
    -      console.log(err.stack);
    -      process.addAsyncListener(key);
    +    if (err.message === 'everything is fine') {
    +      fs.writeSync(1, 'handled error just threw:\n');
    +      fs.writeSync(1, err.stack + '\n');
           return true;
         }
       }
     });
     
     process.nextTick(function() {
    -  throw new Error('really, it\'s ok');
    +  throw new Error('everything is fine');
     });
     
     // Output:
    @@ -3569,17 +3593,20 @@
     

    Removes the AsyncListener from the listening queue.

    -

    Removing the AsyncListener from the queue does not mean asynchronous -events called during its execution scope will stop firing callbacks. Once -attached to an event it will persist for the entire asynchronous call -stack. For example: +

    Removing the AsyncListener from the active queue does not mean the +asyncListener callbacks will cease to fire on the events they've been +registered. Subsequently, any asynchronous events fired during the +execution of a callback will also have the same asyncListener callbacks +attached for future execution. For example:

    -
    var key = process.createAsyncListener(function asyncListener() {
    -  // To log we must stop listening or we'll enter infinite recursion.
    -  process.removeAsyncListener(key);
    -  console.log('You summoned me?');
    -  process.addAsyncListener(key);
    +
    var fs = require('fs');
    +
    +var key = process.createAsyncListener({
    +  create: function asyncListener() {
    +    // Write directly to stdout or we'll enter a recursive loop
    +    fs.writeSync(1, 'You summoned me?\n');
    +  }
     });
     
     // We want to begin capturing async events some time in the future.
    @@ -3612,11 +3639,13 @@
     stack itself. For example:
     
     

    -
    var key = process.createAsyncListener(function asyncListener() {
    -  // To log we must stop listening or we'll enter infinite recursion.
    -  process.removeAsyncListener(key);
    -  console.log('You summoned me?');
    -  process.addAsyncListener(key);
    +
    var fs = require('fs');
    +
    +var key = process.createAsyncListener({
    +  create: function asyncListener() {
    +    // Write directly to stdout or we'll enter a recursive loop
    +    fs.writeSync(1, 'You summoned me?\n');
    +  }
     });
     
     // We want to begin capturing async events some time in the future.
    @@ -6060,7 +6089,7 @@
     
     function SimpleProtocol(source, options) {
       if (!(this instanceof SimpleProtocol))
    -    return new SimpleProtocol(options);
    +    return new SimpleProtocol(source, options);
     
       Readable.call(this, options);
       this._inBody = false;
    @@ -6328,7 +6357,7 @@
     

    writable._writev(chunks, callback)#

    • chunks Array The chunks to be written. Each chunk has following -format: <span class="type"> chunk: ..., encoding: ... </span>.
    • +format: { chunk: ..., encoding: ... }.
    • callback Function Call this function (optionally with an error argument) when you are done processing the supplied chunks.
    @@ -6822,6 +6851,32 @@

    +

    crypto.setEngine(engine, [flags])#

    +

    Load and set engine for some/all OpenSSL functions (selected by flags). + +

    +

    engine could be either an id or a path to the to the engine's shared library. + +

    +

    flags is optional and has ENGINE_METHOD_ALL value by default. It could take +one of or mix of following flags (defined in constants module): + +

    +
      +
    • ENGINE_METHOD_RSA
    • +
    • ENGINE_METHOD_DSA
    • +
    • ENGINE_METHOD_DH
    • +
    • ENGINE_METHOD_RAND
    • +
    • ENGINE_METHOD_ECDH
    • +
    • ENGINE_METHOD_ECDSA
    • +
    • ENGINE_METHOD_CIPHERS
    • +
    • ENGINE_METHOD_DIGESTS
    • +
    • ENGINE_METHOD_STORE
    • +
    • ENGINE_METHOD_PKEY_METH
    • +
    • ENGINE_METHOD_PKEY_ASN1_METH
    • +
    • ENGINE_METHOD_ALL
    • +
    • ENGINE_METHOD_NONE
    • +

    crypto.getCiphers()#

    Returns an array with the names of the supported ciphers. @@ -7309,13 +7364,26 @@ /* alice_secret and bob_secret should be the same */ console.log(alice_secret == bob_secret);

    -

    crypto.pbkdf2(password, salt, iterations, keylen, callback)#

    -

    Asynchronous PBKDF2 applies pseudorandom function HMAC-SHA1 to derive -a key of given length from the given password, salt and iterations. -The callback gets two arguments (err, derivedKey). +

    crypto.pbkdf2(password, salt, iterations, keylen, [digest], callback)#

    +

    Asynchronous PBKDF2 function. Applies the selected HMAC digest function +(default: SHA1) to derive a key of the requested length from the password, +salt and number of iterations. The callback gets two arguments: +(err, derivedKey). + +

    +

    Example: + +

    +
    crypto.pbkdf2('secret', 'salt', 4096, 512, 'sha256', function(err, key) {
    +  if (err)
    +    throw err;
    +  console.log(key.toString('hex'));  // 'c5e478d...1469e50'
    +});
    +

    You can get a list of supported digest functions with +crypto.getHashes().

    -

    crypto.pbkdf2Sync(password, salt, iterations, keylen)#

    +

    crypto.pbkdf2Sync(password, salt, iterations, keylen, [digest])#

    Synchronous PBKDF2 function. Returns derivedKey or throws error.

    @@ -7506,6 +7574,35 @@
  • SNI - to use one TLS server for multiple hostnames with different SSL certificates.
  • +

    Perfect Forward Secrecy#

    + + +

    The term "Forward Secrecy" or "Perfect Forward Secrecy" describes a feature of +key-agreement (i.e. key-exchange) methods. Practically it means that even if the +private key of a (your) server is compromised, communication can only be +decrypted by eavesdroppers if they manage to obtain the key-pair specifically +generated for each session. + +

    +

    This is achieved by randomly generating a key pair for key-agreement on every +handshake (in contrary to the same key for all sessions). Methods implementing +this technique, thus offering Perfect Forward Secrecy, are called "ephemeral". + +

    +

    Currently two methods are commonly used to achieve Perfect Forward Secrecy (note +the character "E" appended to the traditional abbreviations): + +

    +
      +
    • DHE - An ephemeral version of the Diffie Hellman key-agreement protocol.
    • +
    • ECDHE - An ephemeral version of the Elliptic Curve Diffie Hellman +key-agreement protocol.
    • +
    +

    Ephemeral methods may have some performance drawbacks, because key generation +is expensive. + + +

    tls.getCiphers()#

    Returns an array with the names of the supported SSL ciphers. @@ -7548,22 +7645,20 @@

    Defaults to ECDHE-RSA-AES128-SHA256:AES128-GCM-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH. Consult the OpenSSL cipher list format documentation for details on the format.

    +

    ECDHE-RSA-AES128-SHA256 and AES128-GCM-SHA256 are TLS v1.2 ciphers and +used when node.js is linked against OpenSSL 1.0.1 or newer, such as the +bundled version of OpenSSL. Note that it is still possible for a TLS v1.2 +client to negotiate a weaker cipher unless honorCipherOrder is enabled.

    +

    RC4 is used as a fallback for clients that speak on older version of +the TLS protocol. RC4 has in recent years come under suspicion and +should be considered compromised for anything that is truly sensitive. +It is speculated that state-level actors posess the ability to break it.

    +

    NOTE: Previous revisions of this section suggested AES256-SHA as an +acceptable cipher. Unfortunately, AES256-SHA is a CBC cipher and therefore +susceptible to BEAST attacks. Do not use it.

    - -
    `AES128-GCM-SHA256` is used when node.js is linked against OpenSSL 1.0.1
    -or newer and the client speaks TLS 1.2, RC4 is used as a secure fallback.
    -
    -**NOTE**: Previous revisions of this section suggested `AES256-SHA` as an
    -acceptable cipher. Unfortunately, `AES256-SHA` is a CBC cipher and therefore
    -susceptible to BEAST attacks. Do *not* use it.
    -
      -
    • ecdhCurve: A string describing a named curve to use for ECDH ciphers or -false to disable all ECDH ciphers.

      -

      This is required to support ECDH (Elliptic Curve Diffie-Hellman) ciphers. -ECDH ciphers are a newer alternative to RSA. The advantages of ECDH over -RSA is that it offers Forward secrecy. Forward secrecy means that for an -attacker it won't be possible to decrypt your previous data exchanges if -they get access to your private key.

      +
    • ecdhCurve: A string describing a named curve to use for ECDH key agreement +or false to disable ECDH.

      Defaults to prime256v1. Consult RFC 4492 for more details.

    • handshakeTimeout: Abort the connection if the SSL/TLS handshake does not @@ -7573,11 +7668,12 @@

    • honorCipherOrder : When choosing a cipher, use the server's preferences instead of the client preferences.

      -

      Note that if SSLv2 is used, the server will send its list of preferences -to the client, and the client chooses the cipher.

      Although, this option is disabled by default, it is recommended that you use this option in conjunction with the ciphers option to mitigate BEAST attacks.

      +

      Note: If SSLv2 is used, the server will send its list of preferences to the +client, and the client chooses the cipher. Support for SSLv2 is disabled +unless node.js was configured with ./configure --with-sslv2.

    • requestCert: If true the server will request a certificate from clients that connect and attempt to verify that certificate. Default: @@ -7700,7 +7796,7 @@

    • rejectUnauthorized: If true, the server certificate is verified against the list of supplied CAs. An 'error' event is emitted if verification -fails. Default: true.

      +fails; err.code contains the OpenSSL error code. Default: true.

    • NPNProtocols: An array of strings or Buffers containing supported NPN protocols. Buffers should have following format: 0x05hello0x05world, @@ -8058,6 +8154,19 @@ with an error after handshakeTimeout timeout.

      +

      tlsSocket.setMaxSendFragment(size)#

      +

      Set maximum TLS fragment size (default and maximum value is: 16384, minimum +is: 512). Returns true on success, false otherwise. + +

      +

      Smaller fragment size decreases buffering latency on the client: large +fragments are buffered by the TLS layer until the entire fragment is received +and its integrity is verified; large fragments can span multiple roundtrips, +and their processing can be delayed due to packet loss or reordering. However, +smaller fragments add extra TLS framing bytes and CPU overhead, which may +decrease overall server throughput. + +

      tlsSocket.address()#

      Returns the bound address, the address family name and port of the underlying socket as reported by the operating system. Returns an @@ -11849,7 +11958,7 @@ Defaults to checking isTTY on the output stream upon instantiation.

    -

    The completer function is given a the current line entered by the user, and +

    The completer function is given the current line entered by the user, and is supposed to return an Array with 2 entries:

    @@ -12111,6 +12220,28 @@ console.log('Have a great day!'); process.exit(0); });
    +

    readline.cursorTo(stream, x, y)#

    +

    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. + +

    +

    readline.clearLine(stream, dir)#

    +

    Clears current line of given TTY stream in a specified direction. +dir should have one of following values: + +

    +
      +
    • -1 - to the left from cursor
    • +
    • 1 - to the right from cursor
    • +
    • 0 - the entire line
    • +
    +

    readline.clearScreenDown(stream)#

    +

    Clears the screen from the current position of the cursor down. + +

    REPL#

    Stability: 3 - Stable

    A Read-Eval-Print-Loop (REPL) is available both as a standalone program and easily includable in other programs. The REPL provides a way to interactively @@ -13051,7 +13182,9 @@

  • Stream object - Share a readable or writable stream that refers to a tty, file, socket, or a pipe with the child process. The stream's underlying file descriptor is duplicated in the child process to the fd that -corresponds to the index in the stdio array.
  • +corresponds to the index in the stdio array. Note that the stream must +have an underlying descriptor (file streams do not until the 'open' +event has occurred).
  • Positive integer - The integer value is interpreted as a file descriptor that is is currently open in the parent process. It is shared with the child process, similar to how Stream objects can be shared.
  • @@ -13186,7 +13319,7 @@

    -

    child_process.execFile(file, args, options, callback)#

    +

    child_process.execFile(file, [args], [options], [callback])#

    • file String The filename of the program to run
    • args Array List of string arguments
    • @@ -13224,8 +13357,10 @@
    • execPath String Executable used to create the child process
    • execArgv Array List of string arguments passed to the executable (Default: process.execArgv)
    • -
    • silent Boolean If true, prevent stdout and stderr in the spawned node -process from being associated with the parent's (default is false)
    • +
    • 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 +(default is false)
  • Return: ChildProcess object
  • @@ -14292,7 +14427,7 @@
  • worker Worker object
  • When a new worker is forked the cluster module will emit a 'fork' event. -This can be used to log worker activity, and create you own timeout. +This can be used to log worker activity, and create your own timeout.

    var timeouts = [];
    @@ -14934,7 +15069,7 @@
                 
  • -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/api/all.json nodejs-0.11.11/doc/api/all.json --- nodejs-0.11.10/doc/api/all.json 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/all.json 2014-01-29 03:26:35.000000000 +0000 @@ -268,7 +268,7 @@ "textRaw": "Signal Events", "name": "SIGINT, SIGHUP, etc.", "type": "event", - "desc": "

    Emitted when the processes receives a signal. See sigaction(2) for a list of\nstandard POSIX signal names such as SIGINT, SIGHUP, etc.\n\n

    \n

    Example of listening for SIGINT:\n\n

    \n
    // Start reading from stdin so we don't exit.\nprocess.stdin.resume();\n\nprocess.on('SIGINT', function() {\n  console.log('Got SIGINT.  Press Control-D to exit.');\n});
    \n

    An easy way to send the SIGINT signal is with Control-C in most terminal\nprograms.\n\n

    \n

    Note:\n\n

    \n
      \n
    • SIGUSR1 is reserved by node.js to start the debugger. It's possible to\ninstall a listener but that won't stop the debugger from starting.
    • \n
    • SIGTERM and SIGINT have default handlers on non-Windows platforms that resets\nthe terminal mode before exiting with code 128 + signal number. If one of\nthese signals has a listener installed, its default behaviour will be removed\n(node will no longer exit).
    • \n
    • SIGPIPE is ignored by default, it can have a listener installed.
    • \n
    • SIGHUP is generated on Windows when the console window is closed, and on other\nplatforms under various similar conditions, see signal(7). It can have a\nlistener installed, however node will be unconditionally terminated by Windows\nabout 10 seconds later. On non-Windows platforms, the default behaviour of\nSIGHUP is to terminate node, but once a listener has been installed its\ndefault behaviour will be removed.
    • \n
    • SIGTERM is not supported on Windows, it can be listened on.
    • \n
    • SIGINT is supported on all platforms, and can usually be generated with\nCTRL+C (though this may be configurable). It is not generated when terminal\nraw mode is enabled.
    • \n
    • SIGBREAK is delivered on Windows when CTRL+BREAK is pressed, on non-Windows\nplatforms it can be listened on, but there is no way to send or generate it.
    • \n
    • SIGWINCH is delivered when the console has been resized. On Windows, this will\nonly happen on write to the console when the cursor is being moved, or when a\nreadable tty is used in raw mode.
    • \n
    • SIGKILL cannot have a listener installed, it will unconditionally terminate\nnode on all platforms.
    • \n
    • SIGSTOP cannot have a listener installed.
    • \n
    \n", + "desc": "

    Emitted when the processes receives a signal. See sigaction(2) for a list of\nstandard POSIX signal names such as SIGINT, SIGHUP, etc.\n\n

    \n

    Example of listening for SIGINT:\n\n

    \n
    // Start reading from stdin so we don't exit.\nprocess.stdin.resume();\n\nprocess.on('SIGINT', function() {\n  console.log('Got SIGINT.  Press Control-D to exit.');\n});
    \n

    An easy way to send the SIGINT signal is with Control-C in most terminal\nprograms.\n\n

    \n

    Note:\n\n

    \n
      \n
    • SIGUSR1 is reserved by node.js to start the debugger. It's possible to\ninstall a listener but that won't stop the debugger from starting.
    • \n
    • SIGTERM and SIGINT have default handlers on non-Windows platforms that resets\nthe terminal mode before exiting with code 128 + signal number. If one of\nthese signals has a listener installed, its default behaviour will be removed\n(node will no longer exit).
    • \n
    • SIGPIPE is ignored by default, it can have a listener installed.
    • \n
    • SIGHUP is generated on Windows when the console window is closed, and on other\nplatforms under various similar conditions, see signal(7). It can have a\nlistener installed, however node will be unconditionally terminated by Windows\nabout 10 seconds later. On non-Windows platforms, the default behaviour of\nSIGHUP is to terminate node, but once a listener has been installed its\ndefault behaviour will be removed.
    • \n
    • SIGTERM is not supported on Windows, it can be listened on.
    • \n
    • SIGINT from the terminal is supported on all platforms, and can usually be\ngenerated with CTRL+C (though this may be configurable). It is not generated\nwhen terminal raw mode is enabled.
    • \n
    • SIGBREAK is delivered on Windows when CTRL+BREAK is pressed, on non-Windows\nplatforms it can be listened on, but there is no way to send or generate it.
    • \n
    • SIGWINCH is delivered when the console has been resized. On Windows, this will\nonly happen on write to the console when the cursor is being moved, or when a\nreadable tty is used in raw mode.
    • \n
    • SIGKILL cannot have a listener installed, it will unconditionally terminate\nnode on all platforms.
    • \n
    • SIGSTOP cannot have a listener installed.
    • \n
    \n

    Note that Windows does not support sending Signals, but node offers some\nemulation with process.kill(), and child_process.kill():\n- Sending signal 0 can be used to search for the existence of a process\n- Sending SIGINT, SIGTERM, and SIGKILL cause the unconditional exit of the\n target process.\n\n

    \n", "params": [] } ], @@ -503,7 +503,7 @@ "textRaw": "process.kill(pid, [signal])", "type": "method", "name": "kill", - "desc": "

    Send a signal to a process. pid is the process id and signal is the\nstring describing the signal to send. Signal names are strings like\n'SIGINT' or 'SIGHUP'. If omitted, the signal will be 'SIGTERM'.\nSee kill(2) for more information.\n\n

    \n

    Will throw an error if target does not exist, and as a special case, a signal of\n0 can be used to test for the existence of a process.\n\n

    \n

    Note that just because the name of this function is process.kill, it is\nreally just a signal sender, like the kill system call. The signal sent\nmay do something other than kill the target process.\n\n

    \n

    Example of sending a signal to yourself:\n\n

    \n
    process.on('SIGHUP', function() {\n  console.log('Got SIGHUP signal.');\n});\n\nsetTimeout(function() {\n  console.log('Exiting.');\n  process.exit(0);\n}, 100);\n\nprocess.kill(process.pid, 'SIGHUP');
    \n

    Note: When SIGUSR1 is received by Node.js it starts the debugger, see\nSignal Events.\n\n

    \n", + "desc": "

    Send a signal to a process. pid is the process id and signal is the\nstring describing the signal to send. Signal names are strings like\n'SIGINT' or 'SIGHUP'. If omitted, the signal will be 'SIGTERM'.\nSee Signal Events and kill(2) for more information.\n\n

    \n

    Will throw an error if target does not exist, and as a special case, a signal of\n0 can be used to test for the existence of a process.\n\n

    \n

    Note that just because the name of this function is process.kill, it is\nreally just a signal sender, like the kill system call. The signal sent\nmay do something other than kill the target process.\n\n

    \n

    Example of sending a signal to yourself:\n\n

    \n
    process.on('SIGHUP', function() {\n  console.log('Got SIGHUP signal.');\n});\n\nsetTimeout(function() {\n  console.log('Exiting.');\n  process.exit(0);\n}, 100);\n\nprocess.kill(process.pid, 'SIGHUP');
    \n

    Note: When SIGUSR1 is received by Node.js it starts the debugger, see\nSignal Events.\n\n

    \n", "signatures": [ { "params": [ @@ -592,53 +592,44 @@ ] }, { - "textRaw": "process.createAsyncListener(asyncListener[, callbacksObj[, storageValue]])", + "textRaw": "process.createAsyncListener(callbacksObj[, userData])", "type": "method", "name": "createAsyncListener", "signatures": [ { "params": [ { - "textRaw": "`asyncListener` {Function} callback fired when an asynchronous event is instantiated. ", - "name": "asyncListener", - "type": "Function", - "desc": "callback fired when an asynchronous event is instantiated." - }, - { - "textRaw": "`callbacksObj` {Object} optional callbacks that will fire at specific times in the lifetime of the asynchronous event. ", + "textRaw": "`callbacksObj` {Object} Contains optional callbacks that will fire at specific times in the life cycle of the asynchronous event. ", "name": "callbacksObj", "type": "Object", - "desc": "optional callbacks that will fire at specific times in the lifetime of the asynchronous event." + "desc": "Contains optional callbacks that will fire at specific times in the life cycle of the asynchronous event." }, { - "textRaw": "`storageValue` {Value} a value that will be passed as the first argument when the `asyncListener` callback is run, and to all subsequent callback. ", - "name": "storageValue", + "textRaw": "`userData` {Value} a value that will be passed to all callbacks. ", + "name": "userData", "type": "Value", - "desc": "a value that will be passed as the first argument when the `asyncListener` callback is run, and to all subsequent callback." + "desc": "a value that will be passed to all callbacks." } ] }, { "params": [ { - "name": "asyncListener[" - }, - { "name": "callbacksObj[" }, { - "name": "storageValue" + "name": "userData" } ] } ], - "desc": "

    Returns a constructed AsyncListener object.\n\n

    \n

    To begin capturing asynchronous events pass the object to\n[process.addAsyncListener()][]. The same AsyncListener instance can\nonly be added once to the active queue, and subsequent attempts to add the\ninstance will be ignored.\n\n

    \n

    To stop capturing pass the object to [process.removeAsyncListener()][].\nThis does not mean the AsyncListener previously added will stop\ntriggering callbacks. Once attached to an asynchronous event it will\npersist with the lifetime of the asynchronous call stack.\n\n

    \n

    Explanation of function parameters:\n\n

    \n

    asyncListener(storageValue): A Function called when an asynchronous\nevent is instantiated. If a Value is returned then it will be attached\nto the event and overwrite any value that had been passed to\nprocess.createAsyncListener()'s storageValue argument. If an initial\nstorageValue was passed when created, then asyncListener() will\nreceive that as a function argument.\n\n

    \n

    callbacksObj: An Object which may contain three optional fields:\n\n

    \n
      \n
    • before(context, storageValue): A Function that is called immediately\nbefore the asynchronous callback is about to run. It will be passed both\nthe context (i.e. this) of the calling function and the storageValue\neither returned from asyncListener or passed during construction (if\neither occurred).

      \n
    • \n
    • after(context, storageValue): A Function called immediately after\nthe asynchronous event's callback has run. Note this will not be called\nif the callback throws and the error is not handled.

      \n
    • \n
    • error(storageValue, error): A Function called if the event's\ncallback threw. If error returns true then Node will assume the error\nhas been properly handled and resume execution normally. When multiple\nerror() callbacks have been registered, only one of those callbacks\nneeds to return true for AsyncListener to accept that the error has\nbeen handled.

      \n
    • \n
    \n

    storageValue: A Value (i.e. anything) that will be, by default,\nattached to all new event instances. This will be overwritten if a Value\nis returned by asyncListener().\n\n

    \n

    Here is an example of overwriting the storageValue:\n\n

    \n
    process.createAsyncListener(function listener(value) {\n  // value === true\n  return false;\n}, {\n  before: function before(context, value) {\n    // value === false\n  }\n}, true);
    \n

    Note: The [EventEmitter][], while used to emit status of an asynchronous\nevent, is not itself asynchronous. So asyncListener() will not fire when\nan event is added, and before/after will not fire when emitted\ncallbacks are called.\n\n\n

    \n" + "desc": "

    Returns a constructed AsyncListener object.\n\n

    \n

    To begin capturing asynchronous events pass either the callbacksObj or\nand existing AsyncListener instance to [process.addAsyncListener()][].\nThe same AsyncListener instance can only be added once to the active\nqueue, and subsequent attempts to add the instance will be ignored.\n\n

    \n

    To stop capturing pass the AsyncListener instance to\n[process.removeAsyncListener()][]. This does not mean the\nAsyncListener previously added will stop triggering callbacks. Once\nattached to an asynchronous event it will persist with the lifetime of the\nasynchronous call stack.\n\n

    \n

    Explanation of function parameters:\n\n\n

    \n

    callbacksObj: An Object which may contain three optional fields:\n\n

    \n
      \n
    • create(userData): A Function called when an asynchronous\nevent is instantiated. If a Value is returned then it will be attached\nto the event and overwrite any value that had been passed to\nprocess.createAsyncListener()'s userData argument. If an initial\nuserData was passed when created, then create() will\nreceive that as a function argument.

      \n
    • \n
    • before(context, userData): A Function that is called immediately\nbefore the asynchronous callback is about to run. It will be passed both\nthe context (i.e. this) of the calling function and the userData\neither returned from create() or passed during construction (if\neither occurred).

      \n
    • \n
    • after(context, userData): A Function called immediately after\nthe asynchronous event's callback has run. Note this will not be called\nif the callback throws and the error is not handled.

      \n
    • \n
    • error(userData, error): A Function called if the event's\ncallback threw. If this registered callback returns true then Node will\nassume the error has been properly handled and resume execution normally.\nWhen multiple error() callbacks have been registered only one of\nthose callbacks needs to return true for AsyncListener to accept that\nthe error has been handled, but all error() callbacks will always be run.

      \n
    • \n
    \n

    userData: A Value (i.e. anything) that will be, by default,\nattached to all new event instances. This will be overwritten if a Value\nis returned by create().\n\n

    \n

    Here is an example of overwriting the userData:\n\n

    \n
    process.createAsyncListener({\n  create: function listener(value) {\n    // value === true\n    return false;\n}, {\n  before: function before(context, value) {\n    // value === false\n  }\n}, true);
    \n

    Note: The [EventEmitter][], while used to emit status of an asynchronous\nevent, is not itself asynchronous. So create() will not fire when\nan event is added, and before/after will not fire when emitted\ncallbacks are called.\n\n\n

    \n" }, { - "textRaw": "process.addAsyncListener(asyncListener[, callbacksObj[, storageValue]])", + "textRaw": "process.addAsyncListener(callbacksObj[, userData])", "type": "method", "name": "addAsyncListener", - "desc": "

    Returns a constructed AsyncListener object and immediately adds it to\nthe listening queue to begin capturing asynchronous events.\n\n

    \n

    Function parameters can either be the same as\n[process.createAsyncListener()][], or a constructed AsyncListener\nobject.\n\n

    \n

    Example usage for capturing errors:\n\n

    \n
    var cntr = 0;\nvar key = process.addAsyncListener(function() {\n  return { uid: cntr++ };\n}, {\n  before: function onBefore(context, storage) {\n    // Need to remove the listener while logging or will end up\n    // with an infinite call loop.\n    process.removeAsyncListener(key);\n    console.log('uid: %s is about to run', storage.uid);\n    process.addAsyncListener(key);\n  },\n  after: function onAfter(context, storage) {\n    process.removeAsyncListener(key);\n    console.log('uid: %s is about to run', storage.uid);\n    process.addAsyncListener(key);\n  },\n  error: function onError(storage, err) {\n    // Handle known errors\n    if (err.message === 'really, it\\'s ok') {\n      process.removeAsyncListener(key);\n      console.log('handled error just threw:');\n      console.log(err.stack);\n      process.addAsyncListener(key);\n      return true;\n    }\n  }\n});\n\nprocess.nextTick(function() {\n  throw new Error('really, it\\'s ok');\n});\n\n// Output:\n// uid: 0 is about to run\n// handled error just threw:\n// Error: really, it's ok\n//     at /tmp/test2.js:27:9\n//     at process._tickCallback (node.js:583:11)\n//     at Function.Module.runMain (module.js:492:11)\n//     at startup (node.js:123:16)\n//     at node.js:1012:3
    \n", + "desc": "

    Returns a constructed AsyncListener object and immediately adds it to\nthe listening queue to begin capturing asynchronous events.\n\n

    \n

    Function parameters can either be the same as\n[process.createAsyncListener()][], or a constructed AsyncListener\nobject.\n\n

    \n

    Example usage for capturing errors:\n\n

    \n
    var fs = require('fs');\n\nvar cntr = 0;\nvar key = process.addAsyncListener({\n  create: function onCreate() {\n    return { uid: cntr++ };\n  },\n  before: function onBefore(context, storage) {\n    // Write directly to stdout or we'll enter a recursive loop\n    fs.writeSync(1, 'uid: ' + storage.uid + ' is about to run\\n');\n  },\n  after: function onAfter(context, storage) {\n    fs.writeSync(1, 'uid: ' + storage.uid + ' is about to run\\n');\n  },\n  error: function onError(storage, err) {\n    // Handle known errors\n    if (err.message === 'everything is fine') {\n      fs.writeSync(1, 'handled error just threw:\\n');\n      fs.writeSync(1, err.stack + '\\n');\n      return true;\n    }\n  }\n});\n\nprocess.nextTick(function() {\n  throw new Error('everything is fine');\n});\n\n// Output:\n// uid: 0 is about to run\n// handled error just threw:\n// Error: really, it's ok\n//     at /tmp/test2.js:27:9\n//     at process._tickCallback (node.js:583:11)\n//     at Function.Module.runMain (module.js:492:11)\n//     at startup (node.js:123:16)\n//     at node.js:1012:3
    \n", "signatures": [ { "params": [ @@ -650,13 +641,10 @@ { "params": [ { - "name": "asyncListener[" - }, - { "name": "callbacksObj[" }, { - "name": "storageValue" + "name": "userData" } ] } @@ -666,7 +654,7 @@ "textRaw": "process.addAsyncListener(asyncListener)", "type": "method", "name": "addAsyncListener", - "desc": "

    Returns a constructed AsyncListener object and immediately adds it to\nthe listening queue to begin capturing asynchronous events.\n\n

    \n

    Function parameters can either be the same as\n[process.createAsyncListener()][], or a constructed AsyncListener\nobject.\n\n

    \n

    Example usage for capturing errors:\n\n

    \n
    var cntr = 0;\nvar key = process.addAsyncListener(function() {\n  return { uid: cntr++ };\n}, {\n  before: function onBefore(context, storage) {\n    // Need to remove the listener while logging or will end up\n    // with an infinite call loop.\n    process.removeAsyncListener(key);\n    console.log('uid: %s is about to run', storage.uid);\n    process.addAsyncListener(key);\n  },\n  after: function onAfter(context, storage) {\n    process.removeAsyncListener(key);\n    console.log('uid: %s is about to run', storage.uid);\n    process.addAsyncListener(key);\n  },\n  error: function onError(storage, err) {\n    // Handle known errors\n    if (err.message === 'really, it\\'s ok') {\n      process.removeAsyncListener(key);\n      console.log('handled error just threw:');\n      console.log(err.stack);\n      process.addAsyncListener(key);\n      return true;\n    }\n  }\n});\n\nprocess.nextTick(function() {\n  throw new Error('really, it\\'s ok');\n});\n\n// Output:\n// uid: 0 is about to run\n// handled error just threw:\n// Error: really, it's ok\n//     at /tmp/test2.js:27:9\n//     at process._tickCallback (node.js:583:11)\n//     at Function.Module.runMain (module.js:492:11)\n//     at startup (node.js:123:16)\n//     at node.js:1012:3
    \n", + "desc": "

    Returns a constructed AsyncListener object and immediately adds it to\nthe listening queue to begin capturing asynchronous events.\n\n

    \n

    Function parameters can either be the same as\n[process.createAsyncListener()][], or a constructed AsyncListener\nobject.\n\n

    \n

    Example usage for capturing errors:\n\n

    \n
    var fs = require('fs');\n\nvar cntr = 0;\nvar key = process.addAsyncListener({\n  create: function onCreate() {\n    return { uid: cntr++ };\n  },\n  before: function onBefore(context, storage) {\n    // Write directly to stdout or we'll enter a recursive loop\n    fs.writeSync(1, 'uid: ' + storage.uid + ' is about to run\\n');\n  },\n  after: function onAfter(context, storage) {\n    fs.writeSync(1, 'uid: ' + storage.uid + ' is about to run\\n');\n  },\n  error: function onError(storage, err) {\n    // Handle known errors\n    if (err.message === 'everything is fine') {\n      fs.writeSync(1, 'handled error just threw:\\n');\n      fs.writeSync(1, err.stack + '\\n');\n      return true;\n    }\n  }\n});\n\nprocess.nextTick(function() {\n  throw new Error('everything is fine');\n});\n\n// Output:\n// uid: 0 is about to run\n// handled error just threw:\n// Error: really, it's ok\n//     at /tmp/test2.js:27:9\n//     at process._tickCallback (node.js:583:11)\n//     at Function.Module.runMain (module.js:492:11)\n//     at startup (node.js:123:16)\n//     at node.js:1012:3
    \n", "signatures": [ { "params": [ @@ -681,7 +669,7 @@ "textRaw": "process.removeAsyncListener(asyncListener)", "type": "method", "name": "removeAsyncListener", - "desc": "

    Removes the AsyncListener from the listening queue.\n\n

    \n

    Removing the AsyncListener from the queue does not mean asynchronous\nevents called during its execution scope will stop firing callbacks. Once\nattached to an event it will persist for the entire asynchronous call\nstack. For example:\n\n

    \n
    var key = process.createAsyncListener(function asyncListener() {\n  // To log we must stop listening or we'll enter infinite recursion.\n  process.removeAsyncListener(key);\n  console.log('You summoned me?');\n  process.addAsyncListener(key);\n});\n\n// We want to begin capturing async events some time in the future.\nsetTimeout(function() {\n  process.addAsyncListener(key);\n\n  // Perform a few additional async events.\n  setTimeout(function() {\n    setImmediate(function() {\n      process.nextTick(function() { });\n    });\n  });\n\n  // Removing the listener doesn't mean to stop capturing events that\n  // have already been added.\n  process.removeAsyncListener(key);\n}, 100);\n\n// Output:\n// You summoned me?\n// You summoned me?\n// You summoned me?\n// You summoned me?
    \n

    The fact that we logged 4 asynchronous events is an implementation detail\nof Node's [Timers][].\n\n

    \n

    To stop capturing from a specific asynchronous event stack\nprocess.removeAsyncListener() must be called from within the call\nstack itself. For example:\n\n

    \n
    var key = process.createAsyncListener(function asyncListener() {\n  // To log we must stop listening or we'll enter infinite recursion.\n  process.removeAsyncListener(key);\n  console.log('You summoned me?');\n  process.addAsyncListener(key);\n});\n\n// We want to begin capturing async events some time in the future.\nsetTimeout(function() {\n  process.addAsyncListener(key);\n\n  // Perform a few additional async events.\n  setImmediate(function() {\n    // Stop capturing from this call stack.\n    process.removeAsyncListener(key);\n\n    process.nextTick(function() { });\n  });\n}, 100);\n\n// Output:\n// You summoned me?
    \n

    The user must be explicit and always pass the AsyncListener they wish\nto remove. It is not possible to simply remove all listeners at once.\n\n\n

    \n", + "desc": "

    Removes the AsyncListener from the listening queue.\n\n

    \n

    Removing the AsyncListener from the active queue does not mean the\nasyncListener callbacks will cease to fire on the events they've been\nregistered. Subsequently, any asynchronous events fired during the\nexecution of a callback will also have the same asyncListener callbacks\nattached for future execution. For example:\n\n

    \n
    var fs = require('fs');\n\nvar key = process.createAsyncListener({\n  create: function asyncListener() {\n    // Write directly to stdout or we'll enter a recursive loop\n    fs.writeSync(1, 'You summoned me?\\n');\n  }\n});\n\n// We want to begin capturing async events some time in the future.\nsetTimeout(function() {\n  process.addAsyncListener(key);\n\n  // Perform a few additional async events.\n  setTimeout(function() {\n    setImmediate(function() {\n      process.nextTick(function() { });\n    });\n  });\n\n  // Removing the listener doesn't mean to stop capturing events that\n  // have already been added.\n  process.removeAsyncListener(key);\n}, 100);\n\n// Output:\n// You summoned me?\n// You summoned me?\n// You summoned me?\n// You summoned me?
    \n

    The fact that we logged 4 asynchronous events is an implementation detail\nof Node's [Timers][].\n\n

    \n

    To stop capturing from a specific asynchronous event stack\nprocess.removeAsyncListener() must be called from within the call\nstack itself. For example:\n\n

    \n
    var fs = require('fs');\n\nvar key = process.createAsyncListener({\n  create: function asyncListener() {\n    // Write directly to stdout or we'll enter a recursive loop\n    fs.writeSync(1, 'You summoned me?\\n');\n  }\n});\n\n// We want to begin capturing async events some time in the future.\nsetTimeout(function() {\n  process.addAsyncListener(key);\n\n  // Perform a few additional async events.\n  setImmediate(function() {\n    // Stop capturing from this call stack.\n    process.removeAsyncListener(key);\n\n    process.nextTick(function() { });\n  });\n}, 100);\n\n// Output:\n// You summoned me?
    \n

    The user must be explicit and always pass the AsyncListener they wish\nto remove. It is not possible to simply remove all listeners at once.\n\n\n

    \n", "signatures": [ { "params": [ @@ -702,7 +690,7 @@ "type": "misc", "stability": 1, "stabilityText": "Experimental", - "desc": "

    The AsyncListener API is the JavaScript interface for the AsyncWrap\nclass which allows developers to be notified about key events in the\nlifetime of an asynchronous event. Node performs a lot of asynchronous\nevents internally, and significant use of this API will have a dramatic\nperformance impact on your application.\n\n\n

    \n" + "desc": "

    The AsyncListener API is the JavaScript interface for the AsyncWrap\nclass which allows developers to be notified about key events in the\nlifetime of an asynchronous event. Node performs a lot of asynchronous\nevents internally, and significant use of this API may have a\nsignificant performance impact on your application.\n\n\n

    \n" } ] } @@ -1112,7 +1100,7 @@ "textRaw": "Signal Events", "name": "SIGINT, SIGHUP, etc.", "type": "event", - "desc": "

    Emitted when the processes receives a signal. See sigaction(2) for a list of\nstandard POSIX signal names such as SIGINT, SIGHUP, etc.\n\n

    \n

    Example of listening for SIGINT:\n\n

    \n
    // Start reading from stdin so we don't exit.\nprocess.stdin.resume();\n\nprocess.on('SIGINT', function() {\n  console.log('Got SIGINT.  Press Control-D to exit.');\n});
    \n

    An easy way to send the SIGINT signal is with Control-C in most terminal\nprograms.\n\n

    \n

    Note:\n\n

    \n
      \n
    • SIGUSR1 is reserved by node.js to start the debugger. It's possible to\ninstall a listener but that won't stop the debugger from starting.
    • \n
    • SIGTERM and SIGINT have default handlers on non-Windows platforms that resets\nthe terminal mode before exiting with code 128 + signal number. If one of\nthese signals has a listener installed, its default behaviour will be removed\n(node will no longer exit).
    • \n
    • SIGPIPE is ignored by default, it can have a listener installed.
    • \n
    • SIGHUP is generated on Windows when the console window is closed, and on other\nplatforms under various similar conditions, see signal(7). It can have a\nlistener installed, however node will be unconditionally terminated by Windows\nabout 10 seconds later. On non-Windows platforms, the default behaviour of\nSIGHUP is to terminate node, but once a listener has been installed its\ndefault behaviour will be removed.
    • \n
    • SIGTERM is not supported on Windows, it can be listened on.
    • \n
    • SIGINT is supported on all platforms, and can usually be generated with\nCTRL+C (though this may be configurable). It is not generated when terminal\nraw mode is enabled.
    • \n
    • SIGBREAK is delivered on Windows when CTRL+BREAK is pressed, on non-Windows\nplatforms it can be listened on, but there is no way to send or generate it.
    • \n
    • SIGWINCH is delivered when the console has been resized. On Windows, this will\nonly happen on write to the console when the cursor is being moved, or when a\nreadable tty is used in raw mode.
    • \n
    • SIGKILL cannot have a listener installed, it will unconditionally terminate\nnode on all platforms.
    • \n
    • SIGSTOP cannot have a listener installed.
    • \n
    \n", + "desc": "

    Emitted when the processes receives a signal. See sigaction(2) for a list of\nstandard POSIX signal names such as SIGINT, SIGHUP, etc.\n\n

    \n

    Example of listening for SIGINT:\n\n

    \n
    // Start reading from stdin so we don't exit.\nprocess.stdin.resume();\n\nprocess.on('SIGINT', function() {\n  console.log('Got SIGINT.  Press Control-D to exit.');\n});
    \n

    An easy way to send the SIGINT signal is with Control-C in most terminal\nprograms.\n\n

    \n

    Note:\n\n

    \n
      \n
    • SIGUSR1 is reserved by node.js to start the debugger. It's possible to\ninstall a listener but that won't stop the debugger from starting.
    • \n
    • SIGTERM and SIGINT have default handlers on non-Windows platforms that resets\nthe terminal mode before exiting with code 128 + signal number. If one of\nthese signals has a listener installed, its default behaviour will be removed\n(node will no longer exit).
    • \n
    • SIGPIPE is ignored by default, it can have a listener installed.
    • \n
    • SIGHUP is generated on Windows when the console window is closed, and on other\nplatforms under various similar conditions, see signal(7). It can have a\nlistener installed, however node will be unconditionally terminated by Windows\nabout 10 seconds later. On non-Windows platforms, the default behaviour of\nSIGHUP is to terminate node, but once a listener has been installed its\ndefault behaviour will be removed.
    • \n
    • SIGTERM is not supported on Windows, it can be listened on.
    • \n
    • SIGINT from the terminal is supported on all platforms, and can usually be\ngenerated with CTRL+C (though this may be configurable). It is not generated\nwhen terminal raw mode is enabled.
    • \n
    • SIGBREAK is delivered on Windows when CTRL+BREAK is pressed, on non-Windows\nplatforms it can be listened on, but there is no way to send or generate it.
    • \n
    • SIGWINCH is delivered when the console has been resized. On Windows, this will\nonly happen on write to the console when the cursor is being moved, or when a\nreadable tty is used in raw mode.
    • \n
    • SIGKILL cannot have a listener installed, it will unconditionally terminate\nnode on all platforms.
    • \n
    • SIGSTOP cannot have a listener installed.
    • \n
    \n

    Note that Windows does not support sending Signals, but node offers some\nemulation with process.kill(), and child_process.kill():\n- Sending signal 0 can be used to search for the existence of a process\n- Sending SIGINT, SIGTERM, and SIGKILL cause the unconditional exit of the\n target process.\n\n

    \n", "params": [] } ], @@ -1347,7 +1335,7 @@ "textRaw": "process.kill(pid, [signal])", "type": "method", "name": "kill", - "desc": "

    Send a signal to a process. pid is the process id and signal is the\nstring describing the signal to send. Signal names are strings like\n'SIGINT' or 'SIGHUP'. If omitted, the signal will be 'SIGTERM'.\nSee kill(2) for more information.\n\n

    \n

    Will throw an error if target does not exist, and as a special case, a signal of\n0 can be used to test for the existence of a process.\n\n

    \n

    Note that just because the name of this function is process.kill, it is\nreally just a signal sender, like the kill system call. The signal sent\nmay do something other than kill the target process.\n\n

    \n

    Example of sending a signal to yourself:\n\n

    \n
    process.on('SIGHUP', function() {\n  console.log('Got SIGHUP signal.');\n});\n\nsetTimeout(function() {\n  console.log('Exiting.');\n  process.exit(0);\n}, 100);\n\nprocess.kill(process.pid, 'SIGHUP');
    \n

    Note: When SIGUSR1 is received by Node.js it starts the debugger, see\nSignal Events.\n\n

    \n", + "desc": "

    Send a signal to a process. pid is the process id and signal is the\nstring describing the signal to send. Signal names are strings like\n'SIGINT' or 'SIGHUP'. If omitted, the signal will be 'SIGTERM'.\nSee Signal Events and kill(2) for more information.\n\n

    \n

    Will throw an error if target does not exist, and as a special case, a signal of\n0 can be used to test for the existence of a process.\n\n

    \n

    Note that just because the name of this function is process.kill, it is\nreally just a signal sender, like the kill system call. The signal sent\nmay do something other than kill the target process.\n\n

    \n

    Example of sending a signal to yourself:\n\n

    \n
    process.on('SIGHUP', function() {\n  console.log('Got SIGHUP signal.');\n});\n\nsetTimeout(function() {\n  console.log('Exiting.');\n  process.exit(0);\n}, 100);\n\nprocess.kill(process.pid, 'SIGHUP');
    \n

    Note: When SIGUSR1 is received by Node.js it starts the debugger, see\nSignal Events.\n\n

    \n", "signatures": [ { "params": [ @@ -1436,53 +1424,44 @@ ] }, { - "textRaw": "process.createAsyncListener(asyncListener[, callbacksObj[, storageValue]])", + "textRaw": "process.createAsyncListener(callbacksObj[, userData])", "type": "method", "name": "createAsyncListener", "signatures": [ { "params": [ { - "textRaw": "`asyncListener` {Function} callback fired when an asynchronous event is instantiated. ", - "name": "asyncListener", - "type": "Function", - "desc": "callback fired when an asynchronous event is instantiated." - }, - { - "textRaw": "`callbacksObj` {Object} optional callbacks that will fire at specific times in the lifetime of the asynchronous event. ", + "textRaw": "`callbacksObj` {Object} Contains optional callbacks that will fire at specific times in the life cycle of the asynchronous event. ", "name": "callbacksObj", "type": "Object", - "desc": "optional callbacks that will fire at specific times in the lifetime of the asynchronous event." + "desc": "Contains optional callbacks that will fire at specific times in the life cycle of the asynchronous event." }, { - "textRaw": "`storageValue` {Value} a value that will be passed as the first argument when the `asyncListener` callback is run, and to all subsequent callback. ", - "name": "storageValue", + "textRaw": "`userData` {Value} a value that will be passed to all callbacks. ", + "name": "userData", "type": "Value", - "desc": "a value that will be passed as the first argument when the `asyncListener` callback is run, and to all subsequent callback." + "desc": "a value that will be passed to all callbacks." } ] }, { "params": [ { - "name": "asyncListener[" - }, - { "name": "callbacksObj[" }, { - "name": "storageValue" + "name": "userData" } ] } ], - "desc": "

    Returns a constructed AsyncListener object.\n\n

    \n

    To begin capturing asynchronous events pass the object to\n[process.addAsyncListener()][]. The same AsyncListener instance can\nonly be added once to the active queue, and subsequent attempts to add the\ninstance will be ignored.\n\n

    \n

    To stop capturing pass the object to [process.removeAsyncListener()][].\nThis does not mean the AsyncListener previously added will stop\ntriggering callbacks. Once attached to an asynchronous event it will\npersist with the lifetime of the asynchronous call stack.\n\n

    \n

    Explanation of function parameters:\n\n

    \n

    asyncListener(storageValue): A Function called when an asynchronous\nevent is instantiated. If a Value is returned then it will be attached\nto the event and overwrite any value that had been passed to\nprocess.createAsyncListener()'s storageValue argument. If an initial\nstorageValue was passed when created, then asyncListener() will\nreceive that as a function argument.\n\n

    \n

    callbacksObj: An Object which may contain three optional fields:\n\n

    \n
      \n
    • before(context, storageValue): A Function that is called immediately\nbefore the asynchronous callback is about to run. It will be passed both\nthe context (i.e. this) of the calling function and the storageValue\neither returned from asyncListener or passed during construction (if\neither occurred).

      \n
    • \n
    • after(context, storageValue): A Function called immediately after\nthe asynchronous event's callback has run. Note this will not be called\nif the callback throws and the error is not handled.

      \n
    • \n
    • error(storageValue, error): A Function called if the event's\ncallback threw. If error returns true then Node will assume the error\nhas been properly handled and resume execution normally. When multiple\nerror() callbacks have been registered, only one of those callbacks\nneeds to return true for AsyncListener to accept that the error has\nbeen handled.

      \n
    • \n
    \n

    storageValue: A Value (i.e. anything) that will be, by default,\nattached to all new event instances. This will be overwritten if a Value\nis returned by asyncListener().\n\n

    \n

    Here is an example of overwriting the storageValue:\n\n

    \n
    process.createAsyncListener(function listener(value) {\n  // value === true\n  return false;\n}, {\n  before: function before(context, value) {\n    // value === false\n  }\n}, true);
    \n

    Note: The [EventEmitter][], while used to emit status of an asynchronous\nevent, is not itself asynchronous. So asyncListener() will not fire when\nan event is added, and before/after will not fire when emitted\ncallbacks are called.\n\n\n

    \n" + "desc": "

    Returns a constructed AsyncListener object.\n\n

    \n

    To begin capturing asynchronous events pass either the callbacksObj or\nand existing AsyncListener instance to [process.addAsyncListener()][].\nThe same AsyncListener instance can only be added once to the active\nqueue, and subsequent attempts to add the instance will be ignored.\n\n

    \n

    To stop capturing pass the AsyncListener instance to\n[process.removeAsyncListener()][]. This does not mean the\nAsyncListener previously added will stop triggering callbacks. Once\nattached to an asynchronous event it will persist with the lifetime of the\nasynchronous call stack.\n\n

    \n

    Explanation of function parameters:\n\n\n

    \n

    callbacksObj: An Object which may contain three optional fields:\n\n

    \n
      \n
    • create(userData): A Function called when an asynchronous\nevent is instantiated. If a Value is returned then it will be attached\nto the event and overwrite any value that had been passed to\nprocess.createAsyncListener()'s userData argument. If an initial\nuserData was passed when created, then create() will\nreceive that as a function argument.

      \n
    • \n
    • before(context, userData): A Function that is called immediately\nbefore the asynchronous callback is about to run. It will be passed both\nthe context (i.e. this) of the calling function and the userData\neither returned from create() or passed during construction (if\neither occurred).

      \n
    • \n
    • after(context, userData): A Function called immediately after\nthe asynchronous event's callback has run. Note this will not be called\nif the callback throws and the error is not handled.

      \n
    • \n
    • error(userData, error): A Function called if the event's\ncallback threw. If this registered callback returns true then Node will\nassume the error has been properly handled and resume execution normally.\nWhen multiple error() callbacks have been registered only one of\nthose callbacks needs to return true for AsyncListener to accept that\nthe error has been handled, but all error() callbacks will always be run.

      \n
    • \n
    \n

    userData: A Value (i.e. anything) that will be, by default,\nattached to all new event instances. This will be overwritten if a Value\nis returned by create().\n\n

    \n

    Here is an example of overwriting the userData:\n\n

    \n
    process.createAsyncListener({\n  create: function listener(value) {\n    // value === true\n    return false;\n}, {\n  before: function before(context, value) {\n    // value === false\n  }\n}, true);
    \n

    Note: The [EventEmitter][], while used to emit status of an asynchronous\nevent, is not itself asynchronous. So create() will not fire when\nan event is added, and before/after will not fire when emitted\ncallbacks are called.\n\n\n

    \n" }, { - "textRaw": "process.addAsyncListener(asyncListener[, callbacksObj[, storageValue]])", + "textRaw": "process.addAsyncListener(callbacksObj[, userData])", "type": "method", "name": "addAsyncListener", - "desc": "

    Returns a constructed AsyncListener object and immediately adds it to\nthe listening queue to begin capturing asynchronous events.\n\n

    \n

    Function parameters can either be the same as\n[process.createAsyncListener()][], or a constructed AsyncListener\nobject.\n\n

    \n

    Example usage for capturing errors:\n\n

    \n
    var cntr = 0;\nvar key = process.addAsyncListener(function() {\n  return { uid: cntr++ };\n}, {\n  before: function onBefore(context, storage) {\n    // Need to remove the listener while logging or will end up\n    // with an infinite call loop.\n    process.removeAsyncListener(key);\n    console.log('uid: %s is about to run', storage.uid);\n    process.addAsyncListener(key);\n  },\n  after: function onAfter(context, storage) {\n    process.removeAsyncListener(key);\n    console.log('uid: %s is about to run', storage.uid);\n    process.addAsyncListener(key);\n  },\n  error: function onError(storage, err) {\n    // Handle known errors\n    if (err.message === 'really, it\\'s ok') {\n      process.removeAsyncListener(key);\n      console.log('handled error just threw:');\n      console.log(err.stack);\n      process.addAsyncListener(key);\n      return true;\n    }\n  }\n});\n\nprocess.nextTick(function() {\n  throw new Error('really, it\\'s ok');\n});\n\n// Output:\n// uid: 0 is about to run\n// handled error just threw:\n// Error: really, it's ok\n//     at /tmp/test2.js:27:9\n//     at process._tickCallback (node.js:583:11)\n//     at Function.Module.runMain (module.js:492:11)\n//     at startup (node.js:123:16)\n//     at node.js:1012:3
    \n", + "desc": "

    Returns a constructed AsyncListener object and immediately adds it to\nthe listening queue to begin capturing asynchronous events.\n\n

    \n

    Function parameters can either be the same as\n[process.createAsyncListener()][], or a constructed AsyncListener\nobject.\n\n

    \n

    Example usage for capturing errors:\n\n

    \n
    var fs = require('fs');\n\nvar cntr = 0;\nvar key = process.addAsyncListener({\n  create: function onCreate() {\n    return { uid: cntr++ };\n  },\n  before: function onBefore(context, storage) {\n    // Write directly to stdout or we'll enter a recursive loop\n    fs.writeSync(1, 'uid: ' + storage.uid + ' is about to run\\n');\n  },\n  after: function onAfter(context, storage) {\n    fs.writeSync(1, 'uid: ' + storage.uid + ' is about to run\\n');\n  },\n  error: function onError(storage, err) {\n    // Handle known errors\n    if (err.message === 'everything is fine') {\n      fs.writeSync(1, 'handled error just threw:\\n');\n      fs.writeSync(1, err.stack + '\\n');\n      return true;\n    }\n  }\n});\n\nprocess.nextTick(function() {\n  throw new Error('everything is fine');\n});\n\n// Output:\n// uid: 0 is about to run\n// handled error just threw:\n// Error: really, it's ok\n//     at /tmp/test2.js:27:9\n//     at process._tickCallback (node.js:583:11)\n//     at Function.Module.runMain (module.js:492:11)\n//     at startup (node.js:123:16)\n//     at node.js:1012:3
    \n", "signatures": [ { "params": [ @@ -1494,13 +1473,10 @@ { "params": [ { - "name": "asyncListener[" - }, - { "name": "callbacksObj[" }, { - "name": "storageValue" + "name": "userData" } ] } @@ -1510,7 +1486,7 @@ "textRaw": "process.addAsyncListener(asyncListener)", "type": "method", "name": "addAsyncListener", - "desc": "

    Returns a constructed AsyncListener object and immediately adds it to\nthe listening queue to begin capturing asynchronous events.\n\n

    \n

    Function parameters can either be the same as\n[process.createAsyncListener()][], or a constructed AsyncListener\nobject.\n\n

    \n

    Example usage for capturing errors:\n\n

    \n
    var cntr = 0;\nvar key = process.addAsyncListener(function() {\n  return { uid: cntr++ };\n}, {\n  before: function onBefore(context, storage) {\n    // Need to remove the listener while logging or will end up\n    // with an infinite call loop.\n    process.removeAsyncListener(key);\n    console.log('uid: %s is about to run', storage.uid);\n    process.addAsyncListener(key);\n  },\n  after: function onAfter(context, storage) {\n    process.removeAsyncListener(key);\n    console.log('uid: %s is about to run', storage.uid);\n    process.addAsyncListener(key);\n  },\n  error: function onError(storage, err) {\n    // Handle known errors\n    if (err.message === 'really, it\\'s ok') {\n      process.removeAsyncListener(key);\n      console.log('handled error just threw:');\n      console.log(err.stack);\n      process.addAsyncListener(key);\n      return true;\n    }\n  }\n});\n\nprocess.nextTick(function() {\n  throw new Error('really, it\\'s ok');\n});\n\n// Output:\n// uid: 0 is about to run\n// handled error just threw:\n// Error: really, it's ok\n//     at /tmp/test2.js:27:9\n//     at process._tickCallback (node.js:583:11)\n//     at Function.Module.runMain (module.js:492:11)\n//     at startup (node.js:123:16)\n//     at node.js:1012:3
    \n", + "desc": "

    Returns a constructed AsyncListener object and immediately adds it to\nthe listening queue to begin capturing asynchronous events.\n\n

    \n

    Function parameters can either be the same as\n[process.createAsyncListener()][], or a constructed AsyncListener\nobject.\n\n

    \n

    Example usage for capturing errors:\n\n

    \n
    var fs = require('fs');\n\nvar cntr = 0;\nvar key = process.addAsyncListener({\n  create: function onCreate() {\n    return { uid: cntr++ };\n  },\n  before: function onBefore(context, storage) {\n    // Write directly to stdout or we'll enter a recursive loop\n    fs.writeSync(1, 'uid: ' + storage.uid + ' is about to run\\n');\n  },\n  after: function onAfter(context, storage) {\n    fs.writeSync(1, 'uid: ' + storage.uid + ' is about to run\\n');\n  },\n  error: function onError(storage, err) {\n    // Handle known errors\n    if (err.message === 'everything is fine') {\n      fs.writeSync(1, 'handled error just threw:\\n');\n      fs.writeSync(1, err.stack + '\\n');\n      return true;\n    }\n  }\n});\n\nprocess.nextTick(function() {\n  throw new Error('everything is fine');\n});\n\n// Output:\n// uid: 0 is about to run\n// handled error just threw:\n// Error: really, it's ok\n//     at /tmp/test2.js:27:9\n//     at process._tickCallback (node.js:583:11)\n//     at Function.Module.runMain (module.js:492:11)\n//     at startup (node.js:123:16)\n//     at node.js:1012:3
    \n", "signatures": [ { "params": [ @@ -1525,7 +1501,7 @@ "textRaw": "process.removeAsyncListener(asyncListener)", "type": "method", "name": "removeAsyncListener", - "desc": "

    Removes the AsyncListener from the listening queue.\n\n

    \n

    Removing the AsyncListener from the queue does not mean asynchronous\nevents called during its execution scope will stop firing callbacks. Once\nattached to an event it will persist for the entire asynchronous call\nstack. For example:\n\n

    \n
    var key = process.createAsyncListener(function asyncListener() {\n  // To log we must stop listening or we'll enter infinite recursion.\n  process.removeAsyncListener(key);\n  console.log('You summoned me?');\n  process.addAsyncListener(key);\n});\n\n// We want to begin capturing async events some time in the future.\nsetTimeout(function() {\n  process.addAsyncListener(key);\n\n  // Perform a few additional async events.\n  setTimeout(function() {\n    setImmediate(function() {\n      process.nextTick(function() { });\n    });\n  });\n\n  // Removing the listener doesn't mean to stop capturing events that\n  // have already been added.\n  process.removeAsyncListener(key);\n}, 100);\n\n// Output:\n// You summoned me?\n// You summoned me?\n// You summoned me?\n// You summoned me?
    \n

    The fact that we logged 4 asynchronous events is an implementation detail\nof Node's [Timers][].\n\n

    \n

    To stop capturing from a specific asynchronous event stack\nprocess.removeAsyncListener() must be called from within the call\nstack itself. For example:\n\n

    \n
    var key = process.createAsyncListener(function asyncListener() {\n  // To log we must stop listening or we'll enter infinite recursion.\n  process.removeAsyncListener(key);\n  console.log('You summoned me?');\n  process.addAsyncListener(key);\n});\n\n// We want to begin capturing async events some time in the future.\nsetTimeout(function() {\n  process.addAsyncListener(key);\n\n  // Perform a few additional async events.\n  setImmediate(function() {\n    // Stop capturing from this call stack.\n    process.removeAsyncListener(key);\n\n    process.nextTick(function() { });\n  });\n}, 100);\n\n// Output:\n// You summoned me?
    \n

    The user must be explicit and always pass the AsyncListener they wish\nto remove. It is not possible to simply remove all listeners at once.\n\n\n

    \n", + "desc": "

    Removes the AsyncListener from the listening queue.\n\n

    \n

    Removing the AsyncListener from the active queue does not mean the\nasyncListener callbacks will cease to fire on the events they've been\nregistered. Subsequently, any asynchronous events fired during the\nexecution of a callback will also have the same asyncListener callbacks\nattached for future execution. For example:\n\n

    \n
    var fs = require('fs');\n\nvar key = process.createAsyncListener({\n  create: function asyncListener() {\n    // Write directly to stdout or we'll enter a recursive loop\n    fs.writeSync(1, 'You summoned me?\\n');\n  }\n});\n\n// We want to begin capturing async events some time in the future.\nsetTimeout(function() {\n  process.addAsyncListener(key);\n\n  // Perform a few additional async events.\n  setTimeout(function() {\n    setImmediate(function() {\n      process.nextTick(function() { });\n    });\n  });\n\n  // Removing the listener doesn't mean to stop capturing events that\n  // have already been added.\n  process.removeAsyncListener(key);\n}, 100);\n\n// Output:\n// You summoned me?\n// You summoned me?\n// You summoned me?\n// You summoned me?
    \n

    The fact that we logged 4 asynchronous events is an implementation detail\nof Node's [Timers][].\n\n

    \n

    To stop capturing from a specific asynchronous event stack\nprocess.removeAsyncListener() must be called from within the call\nstack itself. For example:\n\n

    \n
    var fs = require('fs');\n\nvar key = process.createAsyncListener({\n  create: function asyncListener() {\n    // Write directly to stdout or we'll enter a recursive loop\n    fs.writeSync(1, 'You summoned me?\\n');\n  }\n});\n\n// We want to begin capturing async events some time in the future.\nsetTimeout(function() {\n  process.addAsyncListener(key);\n\n  // Perform a few additional async events.\n  setImmediate(function() {\n    // Stop capturing from this call stack.\n    process.removeAsyncListener(key);\n\n    process.nextTick(function() { });\n  });\n}, 100);\n\n// Output:\n// You summoned me?
    \n

    The user must be explicit and always pass the AsyncListener they wish\nto remove. It is not possible to simply remove all listeners at once.\n\n\n

    \n", "signatures": [ { "params": [ @@ -1546,7 +1522,7 @@ "type": "misc", "stability": 1, "stabilityText": "Experimental", - "desc": "

    The AsyncListener API is the JavaScript interface for the AsyncWrap\nclass which allows developers to be notified about key events in the\nlifetime of an asynchronous event. Node performs a lot of asynchronous\nevents internally, and significant use of this API will have a dramatic\nperformance impact on your application.\n\n\n

    \n" + "desc": "

    The AsyncListener API is the JavaScript interface for the AsyncWrap\nclass which allows developers to be notified about key events in the\nlifetime of an asynchronous event. Node performs a lot of asynchronous\nevents internally, and significant use of this API may have a\nsignificant performance impact on your application.\n\n\n

    \n" } ] } @@ -1985,7 +1961,7 @@ { "textRaw": "Hello world", "name": "hello_world", - "desc": "

    To get started let's make a small Addon which is the C++ equivalent of\nthe following JavaScript code:\n\n

    \n
    module.exports.hello = function() { return 'world'; };
    \n

    First we create a file hello.cc:\n\n

    \n
    #include <node.h>\n\nusing namespace v8;\n\nHandle<Value> Method(const Arguments& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n  return scope.Close(String::New("world"));\n}\n\nvoid init(Handle<Object> exports) {\n  exports->Set(String::NewSymbol("hello"),\n      FunctionTemplate::New(Method)->GetFunction());\n}\n\nNODE_MODULE(hello, init)
    \n

    Note that all Node addons must export an initialization function:\n\n

    \n
    void Initialize (Handle<Object> exports);\nNODE_MODULE(module_name, Initialize)
    \n

    There is no semi-colon after NODE_MODULE as it's not a function (see\nnode.h).\n\n

    \n

    The module_name needs to match the filename of the final binary (minus the\n.node suffix).\n\n

    \n

    The source code needs to be built into hello.node, the binary Addon. To\ndo this we create a file called binding.gyp which describes the configuration\nto build your module in a JSON-like format. This file gets compiled by\nnode-gyp.\n\n

    \n
    {\n  "targets": [\n    {\n      "target_name": "hello",\n      "sources": [ "hello.cc" ]\n    }\n  ]\n}
    \n

    The next step is to generate the appropriate project build files for the\ncurrent platform. Use node-gyp configure for that.\n\n

    \n

    Now you will have either a Makefile (on Unix platforms) or a vcxproj file\n(on Windows) in the build/ directory. Next invoke the node-gyp build\ncommand.\n\n

    \n

    Now you have your compiled .node bindings file! The compiled bindings end up\nin build/Release/.\n\n

    \n

    You can now use the binary addon in a Node project hello.js by pointing\nrequire to the recently built hello.node module:\n\n

    \n
    var addon = require('./build/Release/hello');\n\nconsole.log(addon.hello()); // 'world'
    \n

    Please see patterns below for further information or\n

    \n

    https://github.com/arturadib/node-qt for an example in production.\n\n\n

    \n", + "desc": "

    To get started let's make a small Addon which is the C++ equivalent of\nthe following JavaScript code:\n\n

    \n
    module.exports.hello = function() { return 'world'; };
    \n

    First we create a file hello.cc:\n\n

    \n
    // hello.cc\n#include <node.h>\n\nusing namespace v8;\n\nvoid Method(const FunctionCallbackInfo<Value>& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n  args.GetReturnValue().Set(String::NewFromUtf8(isolate, "world"));\n}\n\nvoid init(Handle<Object> exports) {\n  NODE_SET_METHOD(exports, "hello", Method);\n}\n\nNODE_MODULE(addon, init)
    \n

    Note that all Node addons must export an initialization function:\n\n

    \n
    void Initialize (Handle<Object> exports);\nNODE_MODULE(module_name, Initialize)
    \n

    There is no semi-colon after NODE_MODULE as it's not a function (see\nnode.h).\n\n

    \n

    The module_name needs to match the filename of the final binary (minus the\n.node suffix).\n\n

    \n

    The source code needs to be built into addon.node, the binary Addon. To\ndo this we create a file called binding.gyp which describes the configuration\nto build your module in a JSON-like format. This file gets compiled by\nnode-gyp.\n\n

    \n
    {\n  "targets": [\n    {\n      "target_name": "addon",\n      "sources": [ "hello.cc" ]\n    }\n  ]\n}
    \n

    The next step is to generate the appropriate project build files for the\ncurrent platform. Use node-gyp configure for that.\n\n

    \n

    Now you will have either a Makefile (on Unix platforms) or a vcxproj file\n(on Windows) in the build/ directory. Next invoke the node-gyp build\ncommand.\n\n

    \n

    Now you have your compiled .node bindings file! The compiled bindings end up\nin build/Release/.\n\n

    \n

    You can now use the binary addon in a Node project hello.js by pointing\nrequire to the recently built hello.node module:\n\n

    \n
    // hello.js\nvar addon = require('./build/Release/addon');\n\nconsole.log(addon.hello()); // 'world'
    \n

    Please see patterns below for further information or\n

    \n

    https://github.com/arturadib/node-qt for an example in production.\n\n\n

    \n", "type": "module", "displayName": "Hello world" }, @@ -1997,49 +1973,49 @@ { "textRaw": "Function arguments", "name": "function_arguments", - "desc": "

    The following pattern illustrates how to read arguments from JavaScript\nfunction calls and return a result. This is the main and only needed source\naddon.cc:\n\n

    \n
    #include <node.h>\n\nusing namespace v8;\n\nHandle<Value> Add(const Arguments& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  if (args.Length() < 2) {\n    ThrowException(Exception::TypeError(\n        String::New("Wrong number of arguments")));\n    return scope.Close(Undefined(isolate));\n  }\n\n  if (!args[0]->IsNumber() || !args[1]->IsNumber()) {\n    ThrowException(Exception::TypeError(String::New("Wrong arguments")));\n    return scope.Close(Undefined(isolate));\n  }\n\n  Local<Number> num = Number::New(args[0]->NumberValue() +\n      args[1]->NumberValue());\n  return scope.Close(num);\n}\n\nvoid Init(Handle<Object> exports) {\n  exports->Set(String::NewSymbol("add"),\n      FunctionTemplate::New(Add)->GetFunction());\n}\n\nNODE_MODULE(addon, Init)
    \n

    You can test it with the following JavaScript snippet:\n\n

    \n
    var addon = require('./build/Release/addon');\n\nconsole.log( 'This should be eight:', addon.add(3,5) );
    \n", + "desc": "

    The following pattern illustrates how to read arguments from JavaScript\nfunction calls and return a result. This is the main and only needed source\naddon.cc:\n\n

    \n
    // addon.cc\n#include <node.h>\n\nusing namespace v8;\n\nvoid Add(const FunctionCallbackInfo<Value>& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  if (args.Length() < 2) {\n    isolate->ThrowException(Exception::TypeError(\n        String::NewFromUtf8(isolate, "Wrong number of arguments")));\n    return;\n  }\n\n  if (!args[0]->IsNumber() || !args[1]->IsNumber()) {\n    isolate->ThrowException(Exception::TypeError(\n        String::NewFromUtf8(isolate, "Wrong arguments")));\n    return;\n  }\n\n  Local<Number> num = Number::New(args[0]->NumberValue() +\n      args[1]->NumberValue());\n\n  args.GetReturnValue().Set(num);\n}\n\nvoid Init(Handle<Object> exports) {\n  NODE_SET_METHOD(exports, "add", Add);\n}\n\nNODE_MODULE(addon, Init)
    \n

    You can test it with the following JavaScript snippet:\n\n

    \n
    // test.js\nvar addon = require('./build/Release/addon');\n\nconsole.log( 'This should be eight:', addon.add(3,5) );
    \n", "type": "module", "displayName": "Function arguments" }, { "textRaw": "Callbacks", "name": "callbacks", - "desc": "

    You can pass JavaScript functions to a C++ function and execute them from\nthere. Here's addon.cc:\n\n

    \n
    #include <node.h>\n\nusing namespace v8;\n\nHandle<Value> RunCallback(const Arguments& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  Local<Function> cb = Local<Function>::Cast(args[0]);\n  const unsigned argc = 1;\n  Local<Value> argv[argc] = { String::New("hello world") };\n  cb->Call(Context::GetCurrent()->Global(), argc, argv);\n\n  return scope.Close(Undefined(isolate));\n}\n\nvoid Init(Handle<Object> exports, Handle<Object> module) {\n  module->Set(String::NewSymbol("exports"),\n      FunctionTemplate::New(RunCallback)->GetFunction());\n}\n\nNODE_MODULE(addon, Init)
    \n

    Note that this example uses a two-argument form of Init() that receives\nthe full module object as the second argument. This allows the addon\nto completely overwrite exports with a single function instead of\nadding the function as a property of exports.\n\n

    \n

    To test it run the following JavaScript snippet:\n\n

    \n
    var addon = require('./build/Release/addon');\n\naddon(function(msg){\n  console.log(msg); // 'hello world'\n});
    \n", + "desc": "

    You can pass JavaScript functions to a C++ function and execute them from\nthere. Here's addon.cc:\n\n

    \n
    // addon.cc\n#include <node.h>\n\nusing namespace v8;\n\nvoid RunCallback(const FunctionCallbackInfo<Value>& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  Local<Function> cb = Local<Function>::Cast(args[0]);\n  const unsigned argc = 1;\n  Local<Value> argv[argc] = { String::NewFromUtf8(isolate, "hello world") };\n  cb->Call(Context::GetCurrent()->Global(), argc, argv);\n}\n\nvoid Init(Handle<Object> exports, Handle<Object> module) {\n  NODE_SET_METHOD(module, "exports", RunCallback);\n}\n\nNODE_MODULE(addon, Init)
    \n

    Note that this example uses a two-argument form of Init() that receives\nthe full module object as the second argument. This allows the addon\nto completely overwrite exports with a single function instead of\nadding the function as a property of exports.\n\n

    \n

    To test it run the following JavaScript snippet:\n\n

    \n
    // test.js\nvar addon = require('./build/Release/addon');\n\naddon(function(msg){\n  console.log(msg); // 'hello world'\n});
    \n", "type": "module", "displayName": "Callbacks" }, { "textRaw": "Object factory", "name": "object_factory", - "desc": "

    You can create and return new objects from within a C++ function with this\naddon.cc pattern, which returns an object with property msg that echoes\nthe string passed to createObject():\n\n

    \n
    #include <node.h>\n\nusing namespace v8;\n\nHandle<Value> CreateObject(const Arguments& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  Local<Object> obj = Object::New();\n  obj->Set(String::NewSymbol("msg"), args[0]->ToString());\n\n  return scope.Close(obj);\n}\n\nvoid Init(Handle<Object> exports, Handle<Object> module) {\n  module->Set(String::NewSymbol("exports"),\n      FunctionTemplate::New(CreateObject)->GetFunction());\n}\n\nNODE_MODULE(addon, Init)
    \n

    To test it in JavaScript:\n\n

    \n
    var addon = require('./build/Release/addon');\n\nvar obj1 = addon('hello');\nvar obj2 = addon('world');\nconsole.log(obj1.msg+' '+obj2.msg); // 'hello world'
    \n", + "desc": "

    You can create and return new objects from within a C++ function with this\naddon.cc pattern, which returns an object with property msg that echoes\nthe string passed to createObject():\n\n

    \n
    // addon.cc\n#include <node.h>\n\nusing namespace v8;\n\nvoid CreateObject(const FunctionCallbackInfo<Value>& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  Local<Object> obj = Object::New();\n  obj->Set(String::NewFromUtf8(isolate, "msg"), args[0]->ToString());\n\n  args.GetReturnValue().Set(obj);\n}\n\nvoid Init(Handle<Object> exports, Handle<Object> module) {\n  NODE_SET_METHOD(module, "exports", CreateObject);\n}\n\nNODE_MODULE(addon, Init)
    \n

    To test it in JavaScript:\n\n

    \n
    // test.js\nvar addon = require('./build/Release/addon');\n\nvar obj1 = addon('hello');\nvar obj2 = addon('world');\nconsole.log(obj1.msg+' '+obj2.msg); // 'hello world'
    \n", "type": "module", "displayName": "Object factory" }, { "textRaw": "Function factory", "name": "function_factory", - "desc": "

    This pattern illustrates how to create and return a JavaScript function that\nwraps a C++ function:\n\n

    \n
    #include <node.h>\n\nusing namespace v8;\n\nHandle<Value> MyFunction(const Arguments& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n  return scope.Close(String::New("hello world"));\n}\n\nHandle<Value> CreateFunction(const Arguments& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  Local<FunctionTemplate> tpl = FunctionTemplate::New(MyFunction);\n  Local<Function> fn = tpl->GetFunction();\n\n  // omit this to make it anonymous\n  fn->SetName(String::NewSymbol("theFunction"));\n\n  return scope.Close(fn);\n}\n\nvoid Init(Handle<Object> exports, Handle<Object> module) {\n  module->Set(String::NewSymbol("exports"),\n      FunctionTemplate::New(CreateFunction)->GetFunction());\n}\n\nNODE_MODULE(addon, Init)
    \n

    To test:\n\n

    \n
    var addon = require('./build/Release/addon');\n\nvar fn = addon();\nconsole.log(fn()); // 'hello world'
    \n", + "desc": "

    This pattern illustrates how to create and return a JavaScript function that\nwraps a C++ function:\n\n

    \n
    // addon.cc\n#include <node.h>\n\nusing namespace v8;\n\nvoid MyFunction(const FunctionCallbackInfo<Value>& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n  args.GetReturnValue().Set(String::NewFromUtf8(isolate, "hello world"));\n}\n\nvoid CreateFunction(const FunctionCallbackInfo<Value>& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  Local<FunctionTemplate> tpl = FunctionTemplate::New(MyFunction);\n  Local<Function> fn = tpl->GetFunction();\n\n  // omit this to make it anonymous\n  fn->SetName(String::NewFromUtf8(isolate, "theFunction"));\n\n  args.GetReturnValue().Set(fn);\n}\n\nvoid Init(Handle<Object> exports, Handle<Object> module) {\n  NODE_SET_METHOD(module, "exports", CreateFunction);\n}\n\nNODE_MODULE(addon, Init)
    \n

    To test:\n\n

    \n
    // test.js\nvar addon = require('./build/Release/addon');\n\nvar fn = addon();\nconsole.log(fn()); // 'hello world'
    \n", "type": "module", "displayName": "Function factory" }, { "textRaw": "Wrapping C++ objects", "name": "wrapping_c++_objects", - "desc": "

    Here we will create a wrapper for a C++ object/class MyObject that can be\ninstantiated in JavaScript through the new operator. First prepare the main\nmodule addon.cc:\n\n

    \n
    #include <node.h>\n#include "myobject.h"\n\nusing namespace v8;\n\nvoid InitAll(Handle<Object> exports) {\n  MyObject::Init(exports);\n}\n\nNODE_MODULE(addon, InitAll)
    \n

    Then in myobject.h make your wrapper inherit from node::ObjectWrap:\n\n

    \n
    #ifndef MYOBJECT_H\n#define MYOBJECT_H\n\n#include <node.h>\n\nclass MyObject : public node::ObjectWrap {\n public:\n  static void Init(v8::Handle<v8::Object> exports);\n\n private:\n  explicit MyObject(double value = 0);\n  ~MyObject();\n\n  static v8::Handle<v8::Value> New(const v8::Arguments& args);\n  static v8::Handle<v8::Value> PlusOne(const v8::Arguments& args);\n  static v8::Persistent<v8::Function> constructor;\n  double value_;\n};\n\n#endif
    \n

    And in myobject.cc implement the various methods that you want to expose.\nHere we expose the method plusOne by adding it to the constructor's\nprototype:\n\n

    \n
    #include <node.h>\n#include <node_object_wrap.h>\n#include "myobject.h"\n\nusing namespace v8;\n\nPersistent<Function> MyObject::constructor;\n\nMyObject::MyObject(double value) : value_(value) {\n}\n\nMyObject::~MyObject() {\n}\n\nvoid MyObject::Init(Handle<Object> exports) {\n  Isolate* isolate = Isolate::GetCurrent();\n\n  // Prepare constructor template\n  Local<FunctionTemplate> tpl = FunctionTemplate::New(New);\n  tpl->SetClassName(String::NewSymbol("MyObject"));\n  tpl->InstanceTemplate()->SetInternalFieldCount(1);\n\n  // Prototype\n  tpl->PrototypeTemplate()->Set(String::NewSymbol("plusOne"),\n      FunctionTemplate::New(PlusOne)->GetFunction());\n\n  Persistent<Function> constructor\n      = Persistent<Function>::New(isolate, tpl->GetFunction());\n\n  exports->Set(String::NewSymbol("MyObject"), constructor);\n}\n\nHandle<Value> MyObject::New(const Arguments& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  if (args.IsConstructCall()) {\n    // Invoked as constructor: `new MyObject(...)`\n    double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();\n    MyObject* obj = new MyObject(value);\n    obj->Wrap(args.This());\n    return args.This();\n  } else {\n    // Invoked as plain function `MyObject(...)`, turn into construct call.\n    const int argc = 1;\n    Local<Value> argv[argc] = { args[0] };\n    return scope.Close(constructor->NewInstance(argc, argv));\n  }\n}\n\nHandle<Value> MyObject::PlusOne(const Arguments& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.This());\n  obj->value_ += 1;\n\n  return scope.Close(Number::New(obj->value_));\n}
    \n

    Test it with:\n\n

    \n
    var addon = require('./build/Release/addon');\n\nvar obj = new addon.MyObject(10);\nconsole.log( obj.plusOne() ); // 11\nconsole.log( obj.plusOne() ); // 12\nconsole.log( obj.plusOne() ); // 13
    \n", + "desc": "

    Here we will create a wrapper for a C++ object/class MyObject that can be\ninstantiated in JavaScript through the new operator. First prepare the main\nmodule addon.cc:\n\n

    \n
    // addon.cc\n#include <node.h>\n#include "myobject.h"\n\nusing namespace v8;\n\nvoid InitAll(Handle<Object> exports) {\n  MyObject::Init(exports);\n}\n\nNODE_MODULE(addon, InitAll)
    \n

    Then in myobject.h make your wrapper inherit from node::ObjectWrap:\n\n

    \n
    // myobject.h\n#ifndef MYOBJECT_H\n#define MYOBJECT_H\n\n#include <node.h>\n#include <node_object_wrap.h>\n\nclass MyObject : public node::ObjectWrap {\n public:\n  static void Init(v8::Handle<v8::Object> exports);\n\n private:\n  explicit MyObject(double value = 0);\n  ~MyObject();\n\n  static void New(const v8::FunctionCallbackInfo<v8::Value>& args);\n  static void PlusOne(const v8::FunctionCallbackInfo<v8::Value>& args);\n  static v8::Persistent<v8::Function> constructor;\n  double value_;\n};\n\n#endif
    \n

    And in myobject.cc implement the various methods that you want to expose.\nHere we expose the method plusOne by adding it to the constructor's\nprototype:\n\n

    \n
    // myobject.cc\n#include "myobject.h"\n\nusing namespace v8;\n\nPersistent<Function> MyObject::constructor;\n\nMyObject::MyObject(double value) : value_(value) {\n}\n\nMyObject::~MyObject() {\n}\n\nvoid MyObject::Init(Handle<Object> exports) {\n  Isolate* isolate = Isolate::GetCurrent();\n\n  // Prepare constructor template\n  Local<FunctionTemplate> tpl = FunctionTemplate::New(New);\n  tpl->SetClassName(String::NewFromUtf8(isolate, "MyObject"));\n  tpl->InstanceTemplate()->SetInternalFieldCount(1);\n\n  // Prototype\n  NODE_SET_PROTOTYPE_METHOD(tpl, "plusOne", PlusOne);\n\n  constructor.Reset(isolate, tpl->GetFunction());\n  exports->Set(String::NewFromUtf8(isolate, "MyObject"),\n               tpl->GetFunction());\n}\n\nvoid MyObject::New(const FunctionCallbackInfo<Value>& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  if (args.IsConstructCall()) {\n    // Invoked as constructor: `new MyObject(...)`\n    double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();\n    MyObject* obj = new MyObject(value);\n    obj->Wrap(args.This());\n    args.GetReturnValue().Set(args.This());\n  } else {\n    // Invoked as plain function `MyObject(...)`, turn into construct call.\n    const int argc = 1;\n    Local<Value> argv[argc] = { args[0] };\n    Local<Function> cons = Local<Function>::New(isolate, constructor);\n    args.GetReturnValue().Set(cons->NewInstance(argc, argv));\n  }\n}\n\nvoid MyObject::PlusOne(const FunctionCallbackInfo<Value>& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.This());\n  obj->value_ += 1;\n\n  args.GetReturnValue().Set(Number::New(obj->value_));\n}
    \n

    Test it with:\n\n

    \n
    // test.js\nvar addon = require('./build/Release/addon');\n\nvar obj = new addon.MyObject(10);\nconsole.log( obj.plusOne() ); // 11\nconsole.log( obj.plusOne() ); // 12\nconsole.log( obj.plusOne() ); // 13
    \n", "type": "module", "displayName": "Wrapping C++ objects" }, { "textRaw": "Factory of wrapped objects", "name": "factory_of_wrapped_objects", - "desc": "

    This is useful when you want to be able to create native objects without\nexplicitly instantiating them with the new operator in JavaScript, e.g.\n\n

    \n
    var obj = addon.createObject();\n// instead of:\n// var obj = new addon.Object();
    \n

    Let's register our createObject method in addon.cc:\n\n

    \n
    #include <node.h>\n#include "myobject.h"\n\nusing namespace v8;\n\nHandle<Value> CreateObject(const Arguments& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n  return scope.Close(MyObject::NewInstance(args));\n}\n\nvoid InitAll(Handle<Object> exports, Handle<Object> module) {\n  MyObject::Init();\n\n  module->Set(String::NewSymbol("exports"),\n      FunctionTemplate::New(CreateObject)->GetFunction());\n}\n\nNODE_MODULE(addon, InitAll)
    \n

    In myobject.h we now introduce the static method NewInstance that takes\ncare of instantiating the object (i.e. it does the job of new in JavaScript):\n\n

    \n
    #ifndef MYOBJECT_H\n#define MYOBJECT_H\n\n#include <node.h>\n\nclass MyObject : public node::ObjectWrap {\n public:\n  static void Init();\n  static v8::Handle<v8::Value> NewInstance(const v8::Arguments& args);\n\n private:\n  explicit MyObject(double value = 0);\n  ~MyObject();\n\n  static v8::Handle<v8::Value> New(const v8::Arguments& args);\n  static v8::Handle<v8::Value> PlusOne(const v8::Arguments& args);\n  static v8::Persistent<v8::Function> constructor;\n  double value_;\n};\n\n#endif
    \n

    The implementation is similar to the above in myobject.cc:\n\n

    \n
    #include <node.h>\n#include "myobject.h"\n\nusing namespace v8;\n\nPersistent<Function> MyObject::constructor;\n\nMyObject::MyObject(double value) : value_(value) {\n}\n\nMyObject::~MyObject() {\n}\n\nvoid MyObject::Init() {\n  Isolate* isolate = Isolate::GetCurrent();\n  // Prepare constructor template\n  Local<FunctionTemplate> tpl = FunctionTemplate::New(New);\n  tpl->SetClassName(String::NewSymbol("MyObject"));\n  tpl->InstanceTemplate()->SetInternalFieldCount(1);\n\n  // Prototype\n  tpl->PrototypeTemplate()->Set(String::NewSymbol("plusOne"),\n      FunctionTemplate::New(PlusOne)->GetFunction());\n\n  constructor = Persistent<Function>::New(isolate, tpl->GetFunction());\n}\n\nHandle<Value> MyObject::New(const Arguments& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  if (args.IsConstructCall()) {\n    // Invoked as constructor: `new MyObject(...)`\n    double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();\n    MyObject* obj = new MyObject(value);\n    obj->Wrap(args.This());\n    return args.This();\n  } else {\n    // Invoked as plain function `MyObject(...)`, turn into construct call.\n    const int argc = 1;\n    Local<Value> argv[argc] = { args[0] };\n    return scope.Close(constructor->NewInstance(argc, argv));\n  }\n}\n\nHandle<Value> MyObject::NewInstance(const Arguments& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  const unsigned argc = 1;\n  Handle<Value> argv[argc] = { args[0] };\n  Local<Object> instance = constructor->NewInstance(argc, argv);\n\n  return scope.Close(instance);\n}\n\nHandle<Value> MyObject::PlusOne(const Arguments& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.This());\n  obj->value_ += 1;\n\n  return scope.Close(Number::New(obj->value_));\n}
    \n

    Test it with:\n\n

    \n
    var createObject = require('./build/Release/addon');\n\nvar obj = createObject(10);\nconsole.log( obj.plusOne() ); // 11\nconsole.log( obj.plusOne() ); // 12\nconsole.log( obj.plusOne() ); // 13\n\nvar obj2 = createObject(20);\nconsole.log( obj2.plusOne() ); // 21\nconsole.log( obj2.plusOne() ); // 22\nconsole.log( obj2.plusOne() ); // 23
    \n", + "desc": "

    This is useful when you want to be able to create native objects without\nexplicitly instantiating them with the new operator in JavaScript, e.g.\n\n

    \n
    var obj = addon.createObject();\n// instead of:\n// var obj = new addon.Object();
    \n

    Let's register our createObject method in addon.cc:\n\n

    \n
    // addon.cc\n#include <node.h>\n#include "myobject.h"\n\nusing namespace v8;\n\nvoid CreateObject(const FunctionCallbackInfo<Value>& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n  MyObject::NewInstance(args);\n}\n\nvoid InitAll(Handle<Object> exports, Handle<Object> module) {\n  MyObject::Init();\n\n  NODE_SET_METHOD(module, "exports", CreateObject);\n}\n\nNODE_MODULE(addon, InitAll)
    \n

    In myobject.h we now introduce the static method NewInstance that takes\ncare of instantiating the object (i.e. it does the job of new in JavaScript):\n\n

    \n
    // myobject.h\n#ifndef MYOBJECT_H\n#define MYOBJECT_H\n\n#include <node.h>\n#include <node_object_wrap.h>\n\nclass MyObject : public node::ObjectWrap {\n public:\n  static void Init();\n  static void NewInstance(const v8::FunctionCallbackInfo<v8::Value>& args);\n\n private:\n  explicit MyObject(double value = 0);\n  ~MyObject();\n\n  static void New(const v8::FunctionCallbackInfo<v8::Value>& args);\n  static void PlusOne(const v8::FunctionCallbackInfo<v8::Value>& args);\n  static v8::Persistent<v8::Function> constructor;\n  double value_;\n};\n\n#endif
    \n

    The implementation is similar to the above in myobject.cc:\n\n

    \n
    // myobject.cc\n#include <node.h>\n#include "myobject.h"\n\nusing namespace v8;\n\nPersistent<Function> MyObject::constructor;\n\nMyObject::MyObject(double value) : value_(value) {\n}\n\nMyObject::~MyObject() {\n}\n\nvoid MyObject::Init() {\n  Isolate* isolate = Isolate::GetCurrent();\n  // Prepare constructor template\n  Local<FunctionTemplate> tpl = FunctionTemplate::New(New);\n  tpl->SetClassName(String::NewFromUtf8(isolate, "MyObject"));\n  tpl->InstanceTemplate()->SetInternalFieldCount(1);\n\n  // Prototype\n  NODE_SET_PROTOTYPE_METHOD(tpl, "plusOne", PlusOne);\n\n  constructor.Reset(isolate, tpl->GetFunction());\n}\n\nvoid MyObject::New(const FunctionCallbackInfo<Value>& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  if (args.IsConstructCall()) {\n    // Invoked as constructor: `new MyObject(...)`\n    double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();\n    MyObject* obj = new MyObject(value);\n    obj->Wrap(args.This());\n    args.GetReturnValue().Set(args.This());\n  } else {\n    // Invoked as plain function `MyObject(...)`, turn into construct call.\n    const int argc = 1;\n    Local<Value> argv[argc] = { args[0] };\n    Local<Function> cons = Local<Function>::New(isolate, constructor);\n    args.GetReturnValue().Set(cons->NewInstance(argc, argv));\n  }\n}\n\nvoid MyObject::NewInstance(const FunctionCallbackInfo<Value>& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  const unsigned argc = 1;\n  Handle<Value> argv[argc] = { args[0] };\n  Local<Function> cons = Local<Function>::New(isolate, constructor);\n  Local<Object> instance = cons->NewInstance(argc, argv);\n\n  args.GetReturnValue().Set(instance);\n}\n\nvoid MyObject::PlusOne(const FunctionCallbackInfo<Value>& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.This());\n  obj->value_ += 1;\n\n  args.GetReturnValue().Set(Number::New(obj->value_));\n}
    \n

    Test it with:\n\n

    \n
    // test.js\nvar createObject = require('./build/Release/addon');\n\nvar obj = createObject(10);\nconsole.log( obj.plusOne() ); // 11\nconsole.log( obj.plusOne() ); // 12\nconsole.log( obj.plusOne() ); // 13\n\nvar obj2 = createObject(20);\nconsole.log( obj2.plusOne() ); // 21\nconsole.log( obj2.plusOne() ); // 22\nconsole.log( obj2.plusOne() ); // 23
    \n", "type": "module", "displayName": "Factory of wrapped objects" }, { "textRaw": "Passing wrapped objects around", "name": "passing_wrapped_objects_around", - "desc": "

    In addition to wrapping and returning C++ objects, you can pass them around\nby unwrapping them with Node's node::ObjectWrap::Unwrap helper function.\nIn the following addon.cc we introduce a function add() that can take on two\nMyObject objects:\n\n

    \n
    #include <node.h>\n#include <node_object_wrap.h>\n#include "myobject.h"\n\nusing namespace v8;\n\nHandle<Value> CreateObject(const Arguments& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n  return scope.Close(MyObject::NewInstance(args));\n}\n\nHandle<Value> Add(const Arguments& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  MyObject* obj1 = node::ObjectWrap::Unwrap<MyObject>(\n      args[0]->ToObject());\n  MyObject* obj2 = node::ObjectWrap::Unwrap<MyObject>(\n      args[1]->ToObject());\n\n  double sum = obj1->Value() + obj2->Value();\n  return scope.Close(Number::New(sum));\n}\n\nvoid InitAll(Handle<Object> exports) {\n  MyObject::Init();\n\n  exports->Set(String::NewSymbol("createObject"),\n      FunctionTemplate::New(CreateObject)->GetFunction());\n\n  exports->Set(String::NewSymbol("add"),\n      FunctionTemplate::New(Add)->GetFunction());\n}\n\nNODE_MODULE(addon, InitAll)
    \n

    To make things interesting we introduce a public method in myobject.h so we\ncan probe private values after unwrapping the object:\n\n

    \n
    #ifndef MYOBJECT_H\n#define MYOBJECT_H\n\n#include <node.h>\n#include <node_object_wrap.h>\n\nclass MyObject : public node::ObjectWrap {\n public:\n  static void Init();\n  static v8::Handle<v8::Value> NewInstance(const v8::Arguments& args);\n  double Value() const { return value_; }\n\n private:\n  explicit MyObject(double value = 0);\n  ~MyObject();\n\n  static v8::Handle<v8::Value> New(const v8::Arguments& args);\n  static v8::Persistent<v8::Function> constructor;\n  double value_;\n};\n\n#endif
    \n

    The implementation of myobject.cc is similar as before:\n\n

    \n
    #include <node.h>\n#include "myobject.h"\n\nusing namespace v8;\n\nPersistent<Function> MyObject::constructor;\n\nMyObject::MyObject(double value) : value_(value) {\n}\n\nMyObject::~MyObject() {\n}\n\nvoid MyObject::Init() {\n  Isolate* isolate = Isolate::GetCurrent();\n\n  // Prepare constructor template\n  Local<FunctionTemplate> tpl = FunctionTemplate::New(New);\n  tpl->SetClassName(String::NewSymbol("MyObject"));\n  tpl->InstanceTemplate()->SetInternalFieldCount(1);\n\n  constructor = Persistent<Function>::New(isolate, tpl->GetFunction());\n}\n\nHandle<Value> MyObject::New(const Arguments& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  if (args.IsConstructCall()) {\n    // Invoked as constructor: `new MyObject(...)`\n    double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();\n    MyObject* obj = new MyObject(value);\n    obj->Wrap(args.This());\n    return args.This();\n  } else {\n    // Invoked as plain function `MyObject(...)`, turn into construct call.\n    const int argc = 1;\n    Local<Value> argv[argc] = { args[0] };\n    return scope.Close(constructor->NewInstance(argc, argv));\n  }\n}\n\nHandle<Value> MyObject::NewInstance(const Arguments& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  const unsigned argc = 1;\n  Handle<Value> argv[argc] = { args[0] };\n  Local<Object> instance = constructor->NewInstance(argc, argv);\n\n  return scope.Close(instance);\n}
    \n

    Test it with:\n\n

    \n
    var addon = require('./build/Release/addon');\n\nvar obj1 = addon.createObject(10);\nvar obj2 = addon.createObject(20);\nvar result = addon.add(obj1, obj2);\n\nconsole.log(result); // 30
    \n", + "desc": "

    In addition to wrapping and returning C++ objects, you can pass them around\nby unwrapping them with Node's node::ObjectWrap::Unwrap helper function.\nIn the following addon.cc we introduce a function add() that can take on two\nMyObject objects:\n\n

    \n
    // addon.cc\n#include <node.h>\n#include <node_object_wrap.h>\n#include "myobject.h"\n\nusing namespace v8;\n\nvoid CreateObject(const FunctionCallbackInfo<Value>& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n  MyObject::NewInstance(args);\n}\n\nvoid Add(const FunctionCallbackInfo<Value>& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  MyObject* obj1 = node::ObjectWrap::Unwrap<MyObject>(\n      args[0]->ToObject());\n  MyObject* obj2 = node::ObjectWrap::Unwrap<MyObject>(\n      args[1]->ToObject());\n\n  double sum = obj1->value() + obj2->value();\n  args.GetReturnValue().Set(Number::New(sum));\n}\n\nvoid InitAll(Handle<Object> exports) {\n  MyObject::Init();\n\n  NODE_SET_METHOD(exports, "createObject", CreateObject);\n  NODE_SET_METHOD(exports, "add", Add);\n}\n\nNODE_MODULE(addon, InitAll)
    \n

    To make things interesting we introduce a public method in myobject.h so we\ncan probe private values after unwrapping the object:\n\n

    \n
    // myobject.h\n#ifndef MYOBJECT_H\n#define MYOBJECT_H\n\n#include <node.h>\n#include <node_object_wrap.h>\n\nclass MyObject : public node::ObjectWrap {\n public:\n  static void Init();\n  static void NewInstance(const v8::FunctionCallbackInfo<v8::Value>& args);\n  inline double value() const { return value_; }\n\n private:\n  explicit MyObject(double value = 0);\n  ~MyObject();\n\n  static void New(const v8::FunctionCallbackInfo<v8::Value>& args);\n  static v8::Persistent<v8::Function> constructor;\n  double value_;\n};\n\n#endif
    \n

    The implementation of myobject.cc is similar as before:\n\n

    \n
    // myobject.cc\n#include <node.h>\n#include "myobject.h"\n\nusing namespace v8;\n\nPersistent<Function> MyObject::constructor;\n\nMyObject::MyObject(double value) : value_(value) {\n}\n\nMyObject::~MyObject() {\n}\n\nvoid MyObject::Init() {\n  Isolate* isolate = Isolate::GetCurrent();\n\n  // Prepare constructor template\n  Local<FunctionTemplate> tpl = FunctionTemplate::New(New);\n  tpl->SetClassName(String::NewFromUtf8(isolate, "MyObject"));\n  tpl->InstanceTemplate()->SetInternalFieldCount(1);\n\n  constructor.Reset(isolate, tpl->GetFunction());\n}\n\nvoid MyObject::New(const FunctionCallbackInfo<Value>& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  if (args.IsConstructCall()) {\n    // Invoked as constructor: `new MyObject(...)`\n    double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();\n    MyObject* obj = new MyObject(value);\n    obj->Wrap(args.This());\n    args.GetReturnValue().Set(args.This());\n  } else {\n    // Invoked as plain function `MyObject(...)`, turn into construct call.\n    const int argc = 1;\n    Local<Value> argv[argc] = { args[0] };\n    Local<Function> cons = Local<Function>::New(isolate, constructor);\n    args.GetReturnValue().Set(cons->NewInstance(argc, argv));\n  }\n}\n\nvoid MyObject::NewInstance(const FunctionCallbackInfo<Value>& args) {\n  Isolate* isolate = Isolate::GetCurrent();\n  HandleScope scope(isolate);\n\n  const unsigned argc = 1;\n  Handle<Value> argv[argc] = { args[0] };\n  Local<Function> cons = Local<Function>::New(isolate, constructor);\n  Local<Object> instance = cons->NewInstance(argc, argv);\n\n  args.GetReturnValue().Set(instance);\n}
    \n

    Test it with:\n\n

    \n
    // test.js\nvar addon = require('./build/Release/addon');\n\nvar obj1 = addon.createObject(10);\nvar obj2 = addon.createObject(20);\nvar result = addon.add(obj1, obj2);\n\nconsole.log(result); // 30
    \n", "type": "module", "displayName": "Passing wrapped objects around" } @@ -5494,7 +5470,7 @@ "textRaw": "Class: stream.Readable", "type": "example", "name": "stream.Readable", - "desc": "

    stream.Readable is an abstract class designed to be extended with an\nunderlying implementation of the [_read(size)][] method.\n\n

    \n

    Please see above under [API for Stream Consumers][] for how to consume\nstreams in your programs. What follows is an explanation of how to\nimplement Readable streams in your programs.\n\n

    \n

    Example: A Counting Stream

    \n

    This is a basic example of a Readable stream. It emits the numerals\nfrom 1 to 1,000,000 in ascending order, and then ends.\n\n

    \n
    var Readable = require('stream').Readable;\nvar util = require('util');\nutil.inherits(Counter, Readable);\n\nfunction Counter(opt) {\n  Readable.call(this, opt);\n  this._max = 1000000;\n  this._index = 1;\n}\n\nCounter.prototype._read = function() {\n  var i = this._index++;\n  if (i > this._max)\n    this.push(null);\n  else {\n    var str = '' + i;\n    var buf = new Buffer(str, 'ascii');\n    this.push(buf);\n  }\n};
    \n

    Example: SimpleProtocol v1 (Sub-optimal)

    \n

    This is similar to the parseHeader function described above, but\nimplemented as a custom stream. Also, note that this implementation\ndoes not convert the incoming data to a string.\n\n

    \n

    However, this would be better implemented as a [Transform][] stream. See\nbelow for a better implementation.\n\n

    \n
    // A parser for a simple data protocol.\n// The "header" is a JSON object, followed by 2 \\n characters, and\n// then a message body.\n//\n// NOTE: This can be done more simply as a Transform stream!\n// Using Readable directly for this is sub-optimal.  See the\n// alternative example below under the Transform section.\n\nvar Readable = require('stream').Readable;\nvar util = require('util');\n\nutil.inherits(SimpleProtocol, Readable);\n\nfunction SimpleProtocol(source, options) {\n  if (!(this instanceof SimpleProtocol))\n    return new SimpleProtocol(options);\n\n  Readable.call(this, options);\n  this._inBody = false;\n  this._sawFirstCr = false;\n\n  // source is a readable stream, such as a socket or file\n  this._source = source;\n\n  var self = this;\n  source.on('end', function() {\n    self.push(null);\n  });\n\n  // give it a kick whenever the source is readable\n  // read(0) will not consume any bytes\n  source.on('readable', function() {\n    self.read(0);\n  });\n\n  this._rawHeader = [];\n  this.header = null;\n}\n\nSimpleProtocol.prototype._read = function(n) {\n  if (!this._inBody) {\n    var chunk = this._source.read();\n\n    // if the source doesn't have data, we don't have data yet.\n    if (chunk === null)\n      return this.push('');\n\n    // check if the chunk has a \\n\\n\n    var split = -1;\n    for (var i = 0; i < chunk.length; i++) {\n      if (chunk[i] === 10) { // '\\n'\n        if (this._sawFirstCr) {\n          split = i;\n          break;\n        } else {\n          this._sawFirstCr = true;\n        }\n      } else {\n        this._sawFirstCr = false;\n      }\n    }\n\n    if (split === -1) {\n      // still waiting for the \\n\\n\n      // stash the chunk, and try again.\n      this._rawHeader.push(chunk);\n      this.push('');\n    } else {\n      this._inBody = true;\n      var h = chunk.slice(0, split);\n      this._rawHeader.push(h);\n      var header = Buffer.concat(this._rawHeader).toString();\n      try {\n        this.header = JSON.parse(header);\n      } catch (er) {\n        this.emit('error', new Error('invalid simple protocol data'));\n        return;\n      }\n      // now, because we got some extra data, unshift the rest\n      // back into the read queue so that our consumer will see it.\n      var b = chunk.slice(split);\n      this.unshift(b);\n\n      // and let them know that we are done parsing the header.\n      this.emit('header', this.header);\n    }\n  } else {\n    // from there on, just provide the data to our consumer.\n    // careful not to push(null), since that would indicate EOF.\n    var chunk = this._source.read();\n    if (chunk) this.push(chunk);\n  }\n};\n\n// Usage:\n// var parser = new SimpleProtocol(source);\n// Now parser is a readable stream that will emit 'header'\n// with the parsed header data.
    \n", + "desc": "

    stream.Readable is an abstract class designed to be extended with an\nunderlying implementation of the [_read(size)][] method.\n\n

    \n

    Please see above under [API for Stream Consumers][] for how to consume\nstreams in your programs. What follows is an explanation of how to\nimplement Readable streams in your programs.\n\n

    \n

    Example: A Counting Stream

    \n

    This is a basic example of a Readable stream. It emits the numerals\nfrom 1 to 1,000,000 in ascending order, and then ends.\n\n

    \n
    var Readable = require('stream').Readable;\nvar util = require('util');\nutil.inherits(Counter, Readable);\n\nfunction Counter(opt) {\n  Readable.call(this, opt);\n  this._max = 1000000;\n  this._index = 1;\n}\n\nCounter.prototype._read = function() {\n  var i = this._index++;\n  if (i > this._max)\n    this.push(null);\n  else {\n    var str = '' + i;\n    var buf = new Buffer(str, 'ascii');\n    this.push(buf);\n  }\n};
    \n

    Example: SimpleProtocol v1 (Sub-optimal)

    \n

    This is similar to the parseHeader function described above, but\nimplemented as a custom stream. Also, note that this implementation\ndoes not convert the incoming data to a string.\n\n

    \n

    However, this would be better implemented as a [Transform][] stream. See\nbelow for a better implementation.\n\n

    \n
    // A parser for a simple data protocol.\n// The "header" is a JSON object, followed by 2 \\n characters, and\n// then a message body.\n//\n// NOTE: This can be done more simply as a Transform stream!\n// Using Readable directly for this is sub-optimal.  See the\n// alternative example below under the Transform section.\n\nvar Readable = require('stream').Readable;\nvar util = require('util');\n\nutil.inherits(SimpleProtocol, Readable);\n\nfunction SimpleProtocol(source, options) {\n  if (!(this instanceof SimpleProtocol))\n    return new SimpleProtocol(source, options);\n\n  Readable.call(this, options);\n  this._inBody = false;\n  this._sawFirstCr = false;\n\n  // source is a readable stream, such as a socket or file\n  this._source = source;\n\n  var self = this;\n  source.on('end', function() {\n    self.push(null);\n  });\n\n  // give it a kick whenever the source is readable\n  // read(0) will not consume any bytes\n  source.on('readable', function() {\n    self.read(0);\n  });\n\n  this._rawHeader = [];\n  this.header = null;\n}\n\nSimpleProtocol.prototype._read = function(n) {\n  if (!this._inBody) {\n    var chunk = this._source.read();\n\n    // if the source doesn't have data, we don't have data yet.\n    if (chunk === null)\n      return this.push('');\n\n    // check if the chunk has a \\n\\n\n    var split = -1;\n    for (var i = 0; i < chunk.length; i++) {\n      if (chunk[i] === 10) { // '\\n'\n        if (this._sawFirstCr) {\n          split = i;\n          break;\n        } else {\n          this._sawFirstCr = true;\n        }\n      } else {\n        this._sawFirstCr = false;\n      }\n    }\n\n    if (split === -1) {\n      // still waiting for the \\n\\n\n      // stash the chunk, and try again.\n      this._rawHeader.push(chunk);\n      this.push('');\n    } else {\n      this._inBody = true;\n      var h = chunk.slice(0, split);\n      this._rawHeader.push(h);\n      var header = Buffer.concat(this._rawHeader).toString();\n      try {\n        this.header = JSON.parse(header);\n      } catch (er) {\n        this.emit('error', new Error('invalid simple protocol data'));\n        return;\n      }\n      // now, because we got some extra data, unshift the rest\n      // back into the read queue so that our consumer will see it.\n      var b = chunk.slice(split);\n      this.unshift(b);\n\n      // and let them know that we are done parsing the header.\n      this.emit('header', this.header);\n    }\n  } else {\n    // from there on, just provide the data to our consumer.\n    // careful not to push(null), since that would indicate EOF.\n    var chunk = this._source.read();\n    if (chunk) this.push(chunk);\n  }\n};\n\n// Usage:\n// var parser = new SimpleProtocol(source);\n// Now parser is a readable stream that will emit 'header'\n// with the parsed header data.
    \n", "methods": [ { "textRaw": "new stream.Readable([options])", @@ -5944,7 +5920,7 @@ "textRaw": "Class: stream.Readable", "type": "example", "name": "stream.Readable", - "desc": "

    stream.Readable is an abstract class designed to be extended with an\nunderlying implementation of the [_read(size)][] method.\n\n

    \n

    Please see above under [API for Stream Consumers][] for how to consume\nstreams in your programs. What follows is an explanation of how to\nimplement Readable streams in your programs.\n\n

    \n

    Example: A Counting Stream

    \n

    This is a basic example of a Readable stream. It emits the numerals\nfrom 1 to 1,000,000 in ascending order, and then ends.\n\n

    \n
    var Readable = require('stream').Readable;\nvar util = require('util');\nutil.inherits(Counter, Readable);\n\nfunction Counter(opt) {\n  Readable.call(this, opt);\n  this._max = 1000000;\n  this._index = 1;\n}\n\nCounter.prototype._read = function() {\n  var i = this._index++;\n  if (i > this._max)\n    this.push(null);\n  else {\n    var str = '' + i;\n    var buf = new Buffer(str, 'ascii');\n    this.push(buf);\n  }\n};
    \n

    Example: SimpleProtocol v1 (Sub-optimal)

    \n

    This is similar to the parseHeader function described above, but\nimplemented as a custom stream. Also, note that this implementation\ndoes not convert the incoming data to a string.\n\n

    \n

    However, this would be better implemented as a [Transform][] stream. See\nbelow for a better implementation.\n\n

    \n
    // A parser for a simple data protocol.\n// The "header" is a JSON object, followed by 2 \\n characters, and\n// then a message body.\n//\n// NOTE: This can be done more simply as a Transform stream!\n// Using Readable directly for this is sub-optimal.  See the\n// alternative example below under the Transform section.\n\nvar Readable = require('stream').Readable;\nvar util = require('util');\n\nutil.inherits(SimpleProtocol, Readable);\n\nfunction SimpleProtocol(source, options) {\n  if (!(this instanceof SimpleProtocol))\n    return new SimpleProtocol(options);\n\n  Readable.call(this, options);\n  this._inBody = false;\n  this._sawFirstCr = false;\n\n  // source is a readable stream, such as a socket or file\n  this._source = source;\n\n  var self = this;\n  source.on('end', function() {\n    self.push(null);\n  });\n\n  // give it a kick whenever the source is readable\n  // read(0) will not consume any bytes\n  source.on('readable', function() {\n    self.read(0);\n  });\n\n  this._rawHeader = [];\n  this.header = null;\n}\n\nSimpleProtocol.prototype._read = function(n) {\n  if (!this._inBody) {\n    var chunk = this._source.read();\n\n    // if the source doesn't have data, we don't have data yet.\n    if (chunk === null)\n      return this.push('');\n\n    // check if the chunk has a \\n\\n\n    var split = -1;\n    for (var i = 0; i < chunk.length; i++) {\n      if (chunk[i] === 10) { // '\\n'\n        if (this._sawFirstCr) {\n          split = i;\n          break;\n        } else {\n          this._sawFirstCr = true;\n        }\n      } else {\n        this._sawFirstCr = false;\n      }\n    }\n\n    if (split === -1) {\n      // still waiting for the \\n\\n\n      // stash the chunk, and try again.\n      this._rawHeader.push(chunk);\n      this.push('');\n    } else {\n      this._inBody = true;\n      var h = chunk.slice(0, split);\n      this._rawHeader.push(h);\n      var header = Buffer.concat(this._rawHeader).toString();\n      try {\n        this.header = JSON.parse(header);\n      } catch (er) {\n        this.emit('error', new Error('invalid simple protocol data'));\n        return;\n      }\n      // now, because we got some extra data, unshift the rest\n      // back into the read queue so that our consumer will see it.\n      var b = chunk.slice(split);\n      this.unshift(b);\n\n      // and let them know that we are done parsing the header.\n      this.emit('header', this.header);\n    }\n  } else {\n    // from there on, just provide the data to our consumer.\n    // careful not to push(null), since that would indicate EOF.\n    var chunk = this._source.read();\n    if (chunk) this.push(chunk);\n  }\n};\n\n// Usage:\n// var parser = new SimpleProtocol(source);\n// Now parser is a readable stream that will emit 'header'\n// with the parsed header data.
    \n", + "desc": "

    stream.Readable is an abstract class designed to be extended with an\nunderlying implementation of the [_read(size)][] method.\n\n

    \n

    Please see above under [API for Stream Consumers][] for how to consume\nstreams in your programs. What follows is an explanation of how to\nimplement Readable streams in your programs.\n\n

    \n

    Example: A Counting Stream

    \n

    This is a basic example of a Readable stream. It emits the numerals\nfrom 1 to 1,000,000 in ascending order, and then ends.\n\n

    \n
    var Readable = require('stream').Readable;\nvar util = require('util');\nutil.inherits(Counter, Readable);\n\nfunction Counter(opt) {\n  Readable.call(this, opt);\n  this._max = 1000000;\n  this._index = 1;\n}\n\nCounter.prototype._read = function() {\n  var i = this._index++;\n  if (i > this._max)\n    this.push(null);\n  else {\n    var str = '' + i;\n    var buf = new Buffer(str, 'ascii');\n    this.push(buf);\n  }\n};
    \n

    Example: SimpleProtocol v1 (Sub-optimal)

    \n

    This is similar to the parseHeader function described above, but\nimplemented as a custom stream. Also, note that this implementation\ndoes not convert the incoming data to a string.\n\n

    \n

    However, this would be better implemented as a [Transform][] stream. See\nbelow for a better implementation.\n\n

    \n
    // A parser for a simple data protocol.\n// The "header" is a JSON object, followed by 2 \\n characters, and\n// then a message body.\n//\n// NOTE: This can be done more simply as a Transform stream!\n// Using Readable directly for this is sub-optimal.  See the\n// alternative example below under the Transform section.\n\nvar Readable = require('stream').Readable;\nvar util = require('util');\n\nutil.inherits(SimpleProtocol, Readable);\n\nfunction SimpleProtocol(source, options) {\n  if (!(this instanceof SimpleProtocol))\n    return new SimpleProtocol(source, options);\n\n  Readable.call(this, options);\n  this._inBody = false;\n  this._sawFirstCr = false;\n\n  // source is a readable stream, such as a socket or file\n  this._source = source;\n\n  var self = this;\n  source.on('end', function() {\n    self.push(null);\n  });\n\n  // give it a kick whenever the source is readable\n  // read(0) will not consume any bytes\n  source.on('readable', function() {\n    self.read(0);\n  });\n\n  this._rawHeader = [];\n  this.header = null;\n}\n\nSimpleProtocol.prototype._read = function(n) {\n  if (!this._inBody) {\n    var chunk = this._source.read();\n\n    // if the source doesn't have data, we don't have data yet.\n    if (chunk === null)\n      return this.push('');\n\n    // check if the chunk has a \\n\\n\n    var split = -1;\n    for (var i = 0; i < chunk.length; i++) {\n      if (chunk[i] === 10) { // '\\n'\n        if (this._sawFirstCr) {\n          split = i;\n          break;\n        } else {\n          this._sawFirstCr = true;\n        }\n      } else {\n        this._sawFirstCr = false;\n      }\n    }\n\n    if (split === -1) {\n      // still waiting for the \\n\\n\n      // stash the chunk, and try again.\n      this._rawHeader.push(chunk);\n      this.push('');\n    } else {\n      this._inBody = true;\n      var h = chunk.slice(0, split);\n      this._rawHeader.push(h);\n      var header = Buffer.concat(this._rawHeader).toString();\n      try {\n        this.header = JSON.parse(header);\n      } catch (er) {\n        this.emit('error', new Error('invalid simple protocol data'));\n        return;\n      }\n      // now, because we got some extra data, unshift the rest\n      // back into the read queue so that our consumer will see it.\n      var b = chunk.slice(split);\n      this.unshift(b);\n\n      // and let them know that we are done parsing the header.\n      this.emit('header', this.header);\n    }\n  } else {\n    // from there on, just provide the data to our consumer.\n    // careful not to push(null), since that would indicate EOF.\n    var chunk = this._source.read();\n    if (chunk) this.push(chunk);\n  }\n};\n\n// Usage:\n// var parser = new SimpleProtocol(source);\n// Now parser is a readable stream that will emit 'header'\n// with the parsed header data.
    \n", "methods": [ { "textRaw": "new stream.Readable([options])", @@ -6107,6 +6083,25 @@ "desc": "
    Stability: 2 - Unstable; API changes are being discussed for\nfuture versions.  Breaking changes will be minimized.  See below.
    \n

    Use require('crypto') to access this module.\n\n

    \n

    The crypto module offers a way of encapsulating secure credentials to be\nused as part of a secure HTTPS net or http connection.\n\n

    \n

    It also offers a set of wrappers for OpenSSL's hash, hmac, cipher,\ndecipher, sign and verify methods.\n\n\n

    \n", "methods": [ { + "textRaw": "crypto.setEngine(engine, [flags])", + "type": "method", + "name": "setEngine", + "desc": "

    Load and set engine for some/all OpenSSL functions (selected by flags).\n\n

    \n

    engine could be either an id or a path to the to the engine's shared library.\n\n

    \n

    flags is optional and has ENGINE_METHOD_ALL value by default. It could take\none of or mix of following flags (defined in constants module):\n\n

    \n
      \n
    • ENGINE_METHOD_RSA
    • \n
    • ENGINE_METHOD_DSA
    • \n
    • ENGINE_METHOD_DH
    • \n
    • ENGINE_METHOD_RAND
    • \n
    • ENGINE_METHOD_ECDH
    • \n
    • ENGINE_METHOD_ECDSA
    • \n
    • ENGINE_METHOD_CIPHERS
    • \n
    • ENGINE_METHOD_DIGESTS
    • \n
    • ENGINE_METHOD_STORE
    • \n
    • ENGINE_METHOD_PKEY_METH
    • \n
    • ENGINE_METHOD_PKEY_ASN1_METH
    • \n
    • ENGINE_METHOD_ALL
    • \n
    • ENGINE_METHOD_NONE
    • \n
    \n", + "signatures": [ + { + "params": [ + { + "name": "engine" + }, + { + "name": "flags", + "optional": true + } + ] + } + ] + }, + { "textRaw": "crypto.getCiphers()", "type": "method", "name": "getCiphers", @@ -6334,10 +6329,10 @@ ] }, { - "textRaw": "crypto.pbkdf2(password, salt, iterations, keylen, callback)", + "textRaw": "crypto.pbkdf2(password, salt, iterations, keylen, [digest], callback)", "type": "method", "name": "pbkdf2", - "desc": "

    Asynchronous PBKDF2 applies pseudorandom function HMAC-SHA1 to derive\na key of given length from the given password, salt and iterations.\nThe callback gets two arguments (err, derivedKey).\n\n

    \n", + "desc": "

    Asynchronous PBKDF2 function. Applies the selected HMAC digest function\n(default: SHA1) to derive a key of the requested length from the password,\nsalt and number of iterations. The callback gets two arguments:\n(err, derivedKey).\n\n

    \n

    Example:\n\n

    \n
    crypto.pbkdf2('secret', 'salt', 4096, 512, 'sha256', function(err, key) {\n  if (err)\n    throw err;\n  console.log(key.toString('hex'));  // 'c5e478d...1469e50'\n});
    \n

    You can get a list of supported digest functions with\ncrypto.getHashes().\n\n

    \n", "signatures": [ { "params": [ @@ -6354,6 +6349,10 @@ "name": "keylen" }, { + "name": "digest", + "optional": true + }, + { "name": "callback" } ] @@ -6361,7 +6360,7 @@ ] }, { - "textRaw": "crypto.pbkdf2Sync(password, salt, iterations, keylen)", + "textRaw": "crypto.pbkdf2Sync(password, salt, iterations, keylen, [digest])", "type": "method", "name": "pbkdf2Sync", "desc": "

    Synchronous PBKDF2 function. Returns derivedKey or throws error.\n\n

    \n", @@ -6379,6 +6378,10 @@ }, { "name": "keylen" + }, + { + "name": "digest", + "optional": true } ] } @@ -6985,6 +6988,12 @@ "name": "NPN and SNI", "type": "misc", "desc": "

    NPN (Next Protocol Negotiation) and SNI (Server Name Indication) are TLS\nhandshake extensions allowing you:\n\n

    \n
      \n
    • NPN - to use one TLS server for multiple protocols (HTTP, SPDY)
    • \n
    • SNI - to use one TLS server for multiple hostnames with different SSL\ncertificates.
    • \n
    \n" + }, + { + "textRaw": "Perfect Forward Secrecy", + "name": "Perfect Forward Secrecy", + "type": "misc", + "desc": "

    The term "[Forward Secrecy]" or "Perfect Forward Secrecy" describes a feature of\nkey-agreement (i.e. key-exchange) methods. Practically it means that even if the\nprivate key of a (your) server is compromised, communication can only be\ndecrypted by eavesdroppers if they manage to obtain the key-pair specifically\ngenerated for each session.\n\n

    \n

    This is achieved by randomly generating a key pair for key-agreement on every\nhandshake (in contrary to the same key for all sessions). Methods implementing\nthis technique, thus offering Perfect Forward Secrecy, are called "ephemeral".\n\n

    \n

    Currently two methods are commonly used to achieve Perfect Forward Secrecy (note \nthe character "E" appended to the traditional abbreviations):\n\n

    \n
      \n
    • [DHE] - An ephemeral version of the Diffie Hellman key-agreement protocol.
    • \n
    • [ECDHE] - An ephemeral version of the Elliptic Curve Diffie Hellman\nkey-agreement protocol.
    • \n
    \n

    Ephemeral methods may have some performance drawbacks, because key generation\nis expensive.\n\n\n

    \n" } ], "methods": [ @@ -7003,7 +7012,7 @@ "textRaw": "tls.createServer(options, [secureConnectionListener])", "type": "method", "name": "createServer", - "desc": "

    Creates a new [tls.Server][]. The connectionListener argument is\nautomatically set as a listener for the [secureConnection][] event. The\noptions object has these possibilities:\n\n

    \n
      \n
    • pfx: A string or Buffer containing the private key, certificate and\nCA certs of the server in PFX or PKCS12 format. (Mutually exclusive with\nthe key, cert and ca options.)

      \n
    • \n
    • key: A string or Buffer containing the private key of the server in\nPEM format. (Required)

      \n
    • \n
    • passphrase: A string of passphrase for the private key or pfx.

      \n
    • \n
    • cert: A string or Buffer containing the certificate key of the server in\nPEM format. (Required)

      \n
    • \n
    • ca: An array of strings or Buffers of trusted certificates in PEM\nformat. If this is omitted several well known "root" CAs will be used,\nlike VeriSign. These are used to authorize connections.

      \n
    • \n
    • crl : Either a string or list of strings of PEM encoded CRLs (Certificate\nRevocation List)

      \n
    • \n
    • ciphers: A string describing the ciphers to use or exclude.

      \n

      To mitigate [BEAST attacks] it is recommended that you use this option in\nconjunction with the honorCipherOrder option described below to\nprioritize the non-CBC cipher.

      \n

      Defaults to ECDHE-RSA-AES128-SHA256:AES128-GCM-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH.\nConsult the [OpenSSL cipher list format documentation] for details on the\nformat.

      \n
    • \n
    \n
    `AES128-GCM-SHA256` is used when node.js is linked against OpenSSL 1.0.1\nor newer and the client speaks TLS 1.2, RC4 is used as a secure fallback.\n\n**NOTE**: Previous revisions of this section suggested `AES256-SHA` as an\nacceptable cipher. Unfortunately, `AES256-SHA` is a CBC cipher and therefore\nsusceptible to BEAST attacks. Do *not* use it.
    \n
      \n
    • ecdhCurve: A string describing a named curve to use for ECDH ciphers or\nfalse to disable all ECDH ciphers.

      \n

      This is required to support ECDH (Elliptic Curve Diffie-Hellman) ciphers.\nECDH ciphers are a newer alternative to RSA. The advantages of ECDH over\nRSA is that it offers [Forward secrecy]. Forward secrecy means that for an\nattacker it won't be possible to decrypt your previous data exchanges if\nthey get access to your private key.

      \n

      Defaults to prime256v1. Consult [RFC 4492] for more details.

      \n
    • \n
    • handshakeTimeout: Abort the connection if the SSL/TLS handshake does not\nfinish in this many milliseconds. The default is 120 seconds.

      \n

      A 'clientError' is emitted on the tls.Server object whenever a handshake\ntimes out.

      \n
    • \n
    • honorCipherOrder : When choosing a cipher, use the server's preferences\ninstead of the client preferences.

      \n

      Note that if SSLv2 is used, the server will send its list of preferences\nto the client, and the client chooses the cipher.

      \n

      Although, this option is disabled by default, it is recommended that you\nuse this option in conjunction with the ciphers option to mitigate\nBEAST attacks.

      \n
    • \n
    • requestCert: If true the server will request a certificate from\nclients that connect and attempt to verify that certificate. Default:\nfalse.

      \n
    • \n
    • rejectUnauthorized: If true the server will reject any connection\nwhich is not authorized with the list of supplied CAs. This option only\nhas an effect if requestCert is true. Default: false.

      \n
    • \n
    • NPNProtocols: An array or Buffer of possible NPN protocols. (Protocols\nshould be ordered by their priority).

      \n
    • \n
    • SNICallback(servername, cb): A function that will be called if client\nsupports SNI TLS extension. Two argument will be passed to it: servername,\nand cb. SNICallback should invoke cb(null, ctx), where ctx is a\nSecureContext instance.\n(You can use crypto.createCredentials(...).context to get proper\nSecureContext). If SNICallback wasn't provided - default callback with\nhigh-level API will be used (see below).

      \n
    • \n
    • sessionTimeout: An integer specifying the seconds after which TLS\nsession identifiers and TLS session tickets created by the server are\ntimed out. See [SSL_CTX_set_timeout] for more details.

      \n
    • \n
    • sessionIdContext: A string containing a opaque identifier for session\nresumption. If requestCert is true, the default is MD5 hash value\ngenerated from command-line. Otherwise, the default is not provided.

      \n
    • \n
    • secureProtocol: The SSL method to use, e.g. SSLv3_method to force\nSSL version 3. The possible values depend on your installation of\nOpenSSL and are defined in the constant [SSL_METHODS][].

      \n
    • \n
    \n

    Here is a simple example echo server:\n\n

    \n
    var tls = require('tls');\nvar fs = require('fs');\n\nvar options = {\n  key: fs.readFileSync('server-key.pem'),\n  cert: fs.readFileSync('server-cert.pem'),\n\n  // This is necessary only if using the client certificate authentication.\n  requestCert: true,\n\n  // This is necessary only if the client uses the self-signed certificate.\n  ca: [ fs.readFileSync('client-cert.pem') ]\n};\n\nvar server = tls.createServer(options, function(socket) {\n  console.log('server connected',\n              socket.authorized ? 'authorized' : 'unauthorized');\n  socket.write("welcome!\\n");\n  socket.setEncoding('utf8');\n  socket.pipe(socket);\n});\nserver.listen(8000, function() {\n  console.log('server bound');\n});
    \n

    Or\n\n

    \n
    var tls = require('tls');\nvar fs = require('fs');\n\nvar options = {\n  pfx: fs.readFileSync('server.pfx'),\n\n  // This is necessary only if using the client certificate authentication.\n  requestCert: true,\n\n};\n\nvar server = tls.createServer(options, function(socket) {\n  console.log('server connected',\n              socket.authorized ? 'authorized' : 'unauthorized');\n  socket.write("welcome!\\n");\n  socket.setEncoding('utf8');\n  socket.pipe(socket);\n});\nserver.listen(8000, function() {\n  console.log('server bound');\n});
    \n

    You can test this server by connecting to it with openssl s_client:\n\n\n

    \n
    openssl s_client -connect 127.0.0.1:8000
    \n", + "desc": "

    Creates a new [tls.Server][]. The connectionListener argument is\nautomatically set as a listener for the [secureConnection][] event. The\noptions object has these possibilities:\n\n

    \n
      \n
    • pfx: A string or Buffer containing the private key, certificate and\nCA certs of the server in PFX or PKCS12 format. (Mutually exclusive with\nthe key, cert and ca options.)

      \n
    • \n
    • key: A string or Buffer containing the private key of the server in\nPEM format. (Required)

      \n
    • \n
    • passphrase: A string of passphrase for the private key or pfx.

      \n
    • \n
    • cert: A string or Buffer containing the certificate key of the server in\nPEM format. (Required)

      \n
    • \n
    • ca: An array of strings or Buffers of trusted certificates in PEM\nformat. If this is omitted several well known "root" CAs will be used,\nlike VeriSign. These are used to authorize connections.

      \n
    • \n
    • crl : Either a string or list of strings of PEM encoded CRLs (Certificate\nRevocation List)

      \n
    • \n
    • ciphers: A string describing the ciphers to use or exclude.

      \n

      To mitigate [BEAST attacks] it is recommended that you use this option in\nconjunction with the honorCipherOrder option described below to\nprioritize the non-CBC cipher.

      \n

      Defaults to ECDHE-RSA-AES128-SHA256:AES128-GCM-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH.\nConsult the [OpenSSL cipher list format documentation] for details on the\nformat.

      \n

      ECDHE-RSA-AES128-SHA256 and AES128-GCM-SHA256 are TLS v1.2 ciphers and\nused when node.js is linked against OpenSSL 1.0.1 or newer, such as the\nbundled version of OpenSSL. Note that it is still possible for a TLS v1.2\nclient to negotiate a weaker cipher unless honorCipherOrder is enabled.

      \n

      RC4 is used as a fallback for clients that speak on older version of\nthe TLS protocol. RC4 has in recent years come under suspicion and\nshould be considered compromised for anything that is truly sensitive.\nIt is speculated that state-level actors posess the ability to break it.

      \n

      NOTE: Previous revisions of this section suggested AES256-SHA as an\nacceptable cipher. Unfortunately, AES256-SHA is a CBC cipher and therefore\nsusceptible to [BEAST attacks]. Do not use it.

      \n
    • \n
    • ecdhCurve: A string describing a named curve to use for ECDH key agreement\nor false to disable ECDH.

      \n

      Defaults to prime256v1. Consult [RFC 4492] for more details.

      \n
    • \n
    • handshakeTimeout: Abort the connection if the SSL/TLS handshake does not\nfinish in this many milliseconds. The default is 120 seconds.

      \n

      A 'clientError' is emitted on the tls.Server object whenever a handshake\ntimes out.

      \n
    • \n
    • honorCipherOrder : When choosing a cipher, use the server's preferences\ninstead of the client preferences.

      \n

      Although, this option is disabled by default, it is recommended that you\nuse this option in conjunction with the ciphers option to mitigate\nBEAST attacks.

      \n

      Note: If SSLv2 is used, the server will send its list of preferences to the\nclient, and the client chooses the cipher. Support for SSLv2 is disabled\nunless node.js was configured with ./configure --with-sslv2.

      \n
    • \n
    • requestCert: If true the server will request a certificate from\nclients that connect and attempt to verify that certificate. Default:\nfalse.

      \n
    • \n
    • rejectUnauthorized: If true the server will reject any connection\nwhich is not authorized with the list of supplied CAs. This option only\nhas an effect if requestCert is true. Default: false.

      \n
    • \n
    • NPNProtocols: An array or Buffer of possible NPN protocols. (Protocols\nshould be ordered by their priority).

      \n
    • \n
    • SNICallback(servername, cb): A function that will be called if client\nsupports SNI TLS extension. Two argument will be passed to it: servername,\nand cb. SNICallback should invoke cb(null, ctx), where ctx is a\nSecureContext instance.\n(You can use crypto.createCredentials(...).context to get proper\nSecureContext). If SNICallback wasn't provided - default callback with\nhigh-level API will be used (see below).

      \n
    • \n
    • sessionTimeout: An integer specifying the seconds after which TLS\nsession identifiers and TLS session tickets created by the server are\ntimed out. See [SSL_CTX_set_timeout] for more details.

      \n
    • \n
    • sessionIdContext: A string containing a opaque identifier for session\nresumption. If requestCert is true, the default is MD5 hash value\ngenerated from command-line. Otherwise, the default is not provided.

      \n
    • \n
    • secureProtocol: The SSL method to use, e.g. SSLv3_method to force\nSSL version 3. The possible values depend on your installation of\nOpenSSL and are defined in the constant [SSL_METHODS][].

      \n
    • \n
    \n

    Here is a simple example echo server:\n\n

    \n
    var tls = require('tls');\nvar fs = require('fs');\n\nvar options = {\n  key: fs.readFileSync('server-key.pem'),\n  cert: fs.readFileSync('server-cert.pem'),\n\n  // This is necessary only if using the client certificate authentication.\n  requestCert: true,\n\n  // This is necessary only if the client uses the self-signed certificate.\n  ca: [ fs.readFileSync('client-cert.pem') ]\n};\n\nvar server = tls.createServer(options, function(socket) {\n  console.log('server connected',\n              socket.authorized ? 'authorized' : 'unauthorized');\n  socket.write("welcome!\\n");\n  socket.setEncoding('utf8');\n  socket.pipe(socket);\n});\nserver.listen(8000, function() {\n  console.log('server bound');\n});
    \n

    Or\n\n

    \n
    var tls = require('tls');\nvar fs = require('fs');\n\nvar options = {\n  pfx: fs.readFileSync('server.pfx'),\n\n  // This is necessary only if using the client certificate authentication.\n  requestCert: true,\n\n};\n\nvar server = tls.createServer(options, function(socket) {\n  console.log('server connected',\n              socket.authorized ? 'authorized' : 'unauthorized');\n  socket.write("welcome!\\n");\n  socket.setEncoding('utf8');\n  socket.pipe(socket);\n});\nserver.listen(8000, function() {\n  console.log('server bound');\n});
    \n

    You can test this server by connecting to it with openssl s_client:\n\n\n

    \n
    openssl s_client -connect 127.0.0.1:8000
    \n", "signatures": [ { "params": [ @@ -7022,7 +7031,7 @@ "textRaw": "tls.connect(options, [callback])", "type": "method", "name": "connect", - "desc": "

    Creates a new client connection to the given port and host (old API) or\noptions.port and options.host. (If host is omitted, it defaults to\nlocalhost.) options should be an object which specifies:\n\n

    \n
      \n
    • host: Host the client should connect to

      \n
    • \n
    • port: Port the client should connect to

      \n
    • \n
    • socket: Establish secure connection on a given socket rather than\ncreating a new socket. If this option is specified, host and port\nare ignored.

      \n
    • \n
    • pfx: A string or Buffer containing the private key, certificate and\nCA certs of the server in PFX or PKCS12 format.

      \n
    • \n
    • key: A string or Buffer containing the private key of the client in\nPEM format.

      \n
    • \n
    • passphrase: A string of passphrase for the private key or pfx.

      \n
    • \n
    • cert: A string or Buffer containing the certificate key of the client in\nPEM format.

      \n
    • \n
    • ca: An array of strings or Buffers of trusted certificates in PEM\nformat. If this is omitted several well known "root" CAs will be used,\nlike VeriSign. These are used to authorize connections.

      \n
    • \n
    • rejectUnauthorized: If true, the server certificate is verified against\nthe list of supplied CAs. An 'error' event is emitted if verification\nfails. Default: true.

      \n
    • \n
    • NPNProtocols: An array of strings or Buffers containing supported NPN\nprotocols. Buffers should have following format: 0x05hello0x05world,\nwhere first byte is next protocol name's length. (Passing array should\nusually be much simpler: ['hello', 'world'].)

      \n
    • \n
    • servername: Servername for SNI (Server Name Indication) TLS extension.

      \n
    • \n
    • secureProtocol: The SSL method to use, e.g. SSLv3_method to force\nSSL version 3. The possible values depend on your installation of\nOpenSSL and are defined in the constant [SSL_METHODS][].

      \n
    • \n
    \n

    The callback parameter will be added as a listener for the\n['secureConnect'][] event.\n\n

    \n

    tls.connect() returns a [tls.TLSSocket][] object.\n\n

    \n

    Here is an example of a client of echo server as described previously:\n\n

    \n
    var tls = require('tls');\nvar fs = require('fs');\n\nvar options = {\n  // These are necessary only if using the client certificate authentication\n  key: fs.readFileSync('client-key.pem'),\n  cert: fs.readFileSync('client-cert.pem'),\n\n  // This is necessary only if the server uses the self-signed certificate\n  ca: [ fs.readFileSync('server-cert.pem') ]\n};\n\nvar socket = tls.connect(8000, options, function() {\n  console.log('client connected',\n              socket.authorized ? 'authorized' : 'unauthorized');\n  process.stdin.pipe(socket);\n  process.stdin.resume();\n});\nsocket.setEncoding('utf8');\nsocket.on('data', function(data) {\n  console.log(data);\n});\nsocket.on('end', function() {\n  server.close();\n});
    \n

    Or\n\n

    \n
    var tls = require('tls');\nvar fs = require('fs');\n\nvar options = {\n  pfx: fs.readFileSync('client.pfx')\n};\n\nvar socket = tls.connect(8000, options, function() {\n  console.log('client connected',\n              socket.authorized ? 'authorized' : 'unauthorized');\n  process.stdin.pipe(socket);\n  process.stdin.resume();\n});\nsocket.setEncoding('utf8');\nsocket.on('data', function(data) {\n  console.log(data);\n});\nsocket.on('end', function() {\n  server.close();\n});
    \n", + "desc": "

    Creates a new client connection to the given port and host (old API) or\noptions.port and options.host. (If host is omitted, it defaults to\nlocalhost.) options should be an object which specifies:\n\n

    \n
      \n
    • host: Host the client should connect to

      \n
    • \n
    • port: Port the client should connect to

      \n
    • \n
    • socket: Establish secure connection on a given socket rather than\ncreating a new socket. If this option is specified, host and port\nare ignored.

      \n
    • \n
    • pfx: A string or Buffer containing the private key, certificate and\nCA certs of the server in PFX or PKCS12 format.

      \n
    • \n
    • key: A string or Buffer containing the private key of the client in\nPEM format.

      \n
    • \n
    • passphrase: A string of passphrase for the private key or pfx.

      \n
    • \n
    • cert: A string or Buffer containing the certificate key of the client in\nPEM format.

      \n
    • \n
    • ca: An array of strings or Buffers of trusted certificates in PEM\nformat. If this is omitted several well known "root" CAs will be used,\nlike VeriSign. These are used to authorize connections.

      \n
    • \n
    • rejectUnauthorized: If true, the server certificate is verified against\nthe list of supplied CAs. An 'error' event is emitted if verification\nfails; err.code contains the OpenSSL error code. Default: true.

      \n
    • \n
    • NPNProtocols: An array of strings or Buffers containing supported NPN\nprotocols. Buffers should have following format: 0x05hello0x05world,\nwhere first byte is next protocol name's length. (Passing array should\nusually be much simpler: ['hello', 'world'].)

      \n
    • \n
    • servername: Servername for SNI (Server Name Indication) TLS extension.

      \n
    • \n
    • secureProtocol: The SSL method to use, e.g. SSLv3_method to force\nSSL version 3. The possible values depend on your installation of\nOpenSSL and are defined in the constant [SSL_METHODS][].

      \n
    • \n
    \n

    The callback parameter will be added as a listener for the\n['secureConnect'][] event.\n\n

    \n

    tls.connect() returns a [tls.TLSSocket][] object.\n\n

    \n

    Here is an example of a client of echo server as described previously:\n\n

    \n
    var tls = require('tls');\nvar fs = require('fs');\n\nvar options = {\n  // These are necessary only if using the client certificate authentication\n  key: fs.readFileSync('client-key.pem'),\n  cert: fs.readFileSync('client-cert.pem'),\n\n  // This is necessary only if the server uses the self-signed certificate\n  ca: [ fs.readFileSync('server-cert.pem') ]\n};\n\nvar socket = tls.connect(8000, options, function() {\n  console.log('client connected',\n              socket.authorized ? 'authorized' : 'unauthorized');\n  process.stdin.pipe(socket);\n  process.stdin.resume();\n});\nsocket.setEncoding('utf8');\nsocket.on('data', function(data) {\n  console.log(data);\n});\nsocket.on('end', function() {\n  server.close();\n});
    \n

    Or\n\n

    \n
    var tls = require('tls');\nvar fs = require('fs');\n\nvar options = {\n  pfx: fs.readFileSync('client.pfx')\n};\n\nvar socket = tls.connect(8000, options, function() {\n  console.log('client connected',\n              socket.authorized ? 'authorized' : 'unauthorized');\n  process.stdin.pipe(socket);\n  process.stdin.resume();\n});\nsocket.setEncoding('utf8');\nsocket.on('data', function(data) {\n  console.log(data);\n});\nsocket.on('end', function() {\n  server.close();\n});
    \n", "signatures": [ { "params": [ @@ -7060,7 +7069,7 @@ "textRaw": "tls.connect(port, [host], [options], [callback])", "type": "method", "name": "connect", - "desc": "

    Creates a new client connection to the given port and host (old API) or\noptions.port and options.host. (If host is omitted, it defaults to\nlocalhost.) options should be an object which specifies:\n\n

    \n
      \n
    • host: Host the client should connect to

      \n
    • \n
    • port: Port the client should connect to

      \n
    • \n
    • socket: Establish secure connection on a given socket rather than\ncreating a new socket. If this option is specified, host and port\nare ignored.

      \n
    • \n
    • pfx: A string or Buffer containing the private key, certificate and\nCA certs of the server in PFX or PKCS12 format.

      \n
    • \n
    • key: A string or Buffer containing the private key of the client in\nPEM format.

      \n
    • \n
    • passphrase: A string of passphrase for the private key or pfx.

      \n
    • \n
    • cert: A string or Buffer containing the certificate key of the client in\nPEM format.

      \n
    • \n
    • ca: An array of strings or Buffers of trusted certificates in PEM\nformat. If this is omitted several well known "root" CAs will be used,\nlike VeriSign. These are used to authorize connections.

      \n
    • \n
    • rejectUnauthorized: If true, the server certificate is verified against\nthe list of supplied CAs. An 'error' event is emitted if verification\nfails. Default: true.

      \n
    • \n
    • NPNProtocols: An array of strings or Buffers containing supported NPN\nprotocols. Buffers should have following format: 0x05hello0x05world,\nwhere first byte is next protocol name's length. (Passing array should\nusually be much simpler: ['hello', 'world'].)

      \n
    • \n
    • servername: Servername for SNI (Server Name Indication) TLS extension.

      \n
    • \n
    • secureProtocol: The SSL method to use, e.g. SSLv3_method to force\nSSL version 3. The possible values depend on your installation of\nOpenSSL and are defined in the constant [SSL_METHODS][].

      \n
    • \n
    \n

    The callback parameter will be added as a listener for the\n['secureConnect'][] event.\n\n

    \n

    tls.connect() returns a [tls.TLSSocket][] object.\n\n

    \n

    Here is an example of a client of echo server as described previously:\n\n

    \n
    var tls = require('tls');\nvar fs = require('fs');\n\nvar options = {\n  // These are necessary only if using the client certificate authentication\n  key: fs.readFileSync('client-key.pem'),\n  cert: fs.readFileSync('client-cert.pem'),\n\n  // This is necessary only if the server uses the self-signed certificate\n  ca: [ fs.readFileSync('server-cert.pem') ]\n};\n\nvar socket = tls.connect(8000, options, function() {\n  console.log('client connected',\n              socket.authorized ? 'authorized' : 'unauthorized');\n  process.stdin.pipe(socket);\n  process.stdin.resume();\n});\nsocket.setEncoding('utf8');\nsocket.on('data', function(data) {\n  console.log(data);\n});\nsocket.on('end', function() {\n  server.close();\n});
    \n

    Or\n\n

    \n
    var tls = require('tls');\nvar fs = require('fs');\n\nvar options = {\n  pfx: fs.readFileSync('client.pfx')\n};\n\nvar socket = tls.connect(8000, options, function() {\n  console.log('client connected',\n              socket.authorized ? 'authorized' : 'unauthorized');\n  process.stdin.pipe(socket);\n  process.stdin.resume();\n});\nsocket.setEncoding('utf8');\nsocket.on('data', function(data) {\n  console.log(data);\n});\nsocket.on('end', function() {\n  server.close();\n});
    \n", + "desc": "

    Creates a new client connection to the given port and host (old API) or\noptions.port and options.host. (If host is omitted, it defaults to\nlocalhost.) options should be an object which specifies:\n\n

    \n
      \n
    • host: Host the client should connect to

      \n
    • \n
    • port: Port the client should connect to

      \n
    • \n
    • socket: Establish secure connection on a given socket rather than\ncreating a new socket. If this option is specified, host and port\nare ignored.

      \n
    • \n
    • pfx: A string or Buffer containing the private key, certificate and\nCA certs of the server in PFX or PKCS12 format.

      \n
    • \n
    • key: A string or Buffer containing the private key of the client in\nPEM format.

      \n
    • \n
    • passphrase: A string of passphrase for the private key or pfx.

      \n
    • \n
    • cert: A string or Buffer containing the certificate key of the client in\nPEM format.

      \n
    • \n
    • ca: An array of strings or Buffers of trusted certificates in PEM\nformat. If this is omitted several well known "root" CAs will be used,\nlike VeriSign. These are used to authorize connections.

      \n
    • \n
    • rejectUnauthorized: If true, the server certificate is verified against\nthe list of supplied CAs. An 'error' event is emitted if verification\nfails; err.code contains the OpenSSL error code. Default: true.

      \n
    • \n
    • NPNProtocols: An array of strings or Buffers containing supported NPN\nprotocols. Buffers should have following format: 0x05hello0x05world,\nwhere first byte is next protocol name's length. (Passing array should\nusually be much simpler: ['hello', 'world'].)

      \n
    • \n
    • servername: Servername for SNI (Server Name Indication) TLS extension.

      \n
    • \n
    • secureProtocol: The SSL method to use, e.g. SSLv3_method to force\nSSL version 3. The possible values depend on your installation of\nOpenSSL and are defined in the constant [SSL_METHODS][].

      \n
    • \n
    \n

    The callback parameter will be added as a listener for the\n['secureConnect'][] event.\n\n

    \n

    tls.connect() returns a [tls.TLSSocket][] object.\n\n

    \n

    Here is an example of a client of echo server as described previously:\n\n

    \n
    var tls = require('tls');\nvar fs = require('fs');\n\nvar options = {\n  // These are necessary only if using the client certificate authentication\n  key: fs.readFileSync('client-key.pem'),\n  cert: fs.readFileSync('client-cert.pem'),\n\n  // This is necessary only if the server uses the self-signed certificate\n  ca: [ fs.readFileSync('server-cert.pem') ]\n};\n\nvar socket = tls.connect(8000, options, function() {\n  console.log('client connected',\n              socket.authorized ? 'authorized' : 'unauthorized');\n  process.stdin.pipe(socket);\n  process.stdin.resume();\n});\nsocket.setEncoding('utf8');\nsocket.on('data', function(data) {\n  console.log(data);\n});\nsocket.on('end', function() {\n  server.close();\n});
    \n

    Or\n\n

    \n
    var tls = require('tls');\nvar fs = require('fs');\n\nvar options = {\n  pfx: fs.readFileSync('client.pfx')\n};\n\nvar socket = tls.connect(8000, options, function() {\n  console.log('client connected',\n              socket.authorized ? 'authorized' : 'unauthorized');\n  process.stdin.pipe(socket);\n  process.stdin.resume();\n});\nsocket.setEncoding('utf8');\nsocket.on('data', function(data) {\n  console.log(data);\n});\nsocket.on('end', function() {\n  server.close();\n});
    \n", "signatures": [ { "params": [ @@ -7375,6 +7384,21 @@ ] }, { + "textRaw": "tlsSocket.setMaxSendFragment(size)", + "type": "method", + "name": "setMaxSendFragment", + "desc": "

    Set maximum TLS fragment size (default and maximum value is: 16384, minimum\nis: 512). Returns true on success, false otherwise.\n\n

    \n

    Smaller fragment size decreases buffering latency on the client: large\nfragments are buffered by the TLS layer until the entire fragment is received\nand its integrity is verified; large fragments can span multiple roundtrips,\nand their processing can be delayed due to packet loss or reordering. However,\nsmaller fragments add extra TLS framing bytes and CPU overhead, which may\ndecrease overall server throughput.\n\n

    \n", + "signatures": [ + { + "params": [ + { + "name": "size" + } + ] + } + ] + }, + { "textRaw": "tlsSocket.address()", "type": "method", "name": "address", @@ -12065,7 +12089,7 @@ "textRaw": "readline.createInterface(options)", "type": "method", "name": "createInterface", - "desc": "

    Creates a readline Interface instance. Accepts an "options" Object that takes\nthe following values:\n\n

    \n
      \n
    • input - the readable stream to listen to (Required).

      \n
    • \n
    • output - the writable stream to write readline data to (Required).

      \n
    • \n
    • completer - an optional function that is used for Tab autocompletion. See\nbelow for an example of using this.

      \n
    • \n
    • terminal - pass true if the input and output streams should be\ntreated like a TTY, and have ANSI/VT100 escape codes written to it.\nDefaults to checking isTTY on the output stream upon instantiation.

      \n
    • \n
    \n

    The completer function is given a the current line entered by the user, and\nis supposed to return an Array with 2 entries:\n\n

    \n
      \n
    1. An Array with matching entries for the completion.

      \n
    2. \n
    3. The substring that was used for the matching.

      \n
    4. \n
    \n

    Which ends up looking something like:\n[[substr1, substr2, ...], originalsubstring].\n\n

    \n

    Example:\n\n

    \n
    function completer(line) {\n  var completions = '.help .error .exit .quit .q'.split(' ')\n  var hits = completions.filter(function(c) { return c.indexOf(line) == 0 })\n  // show all completions if none found\n  return [hits.length ? hits : completions, line]\n}
    \n

    Also completer can be run in async mode if it accepts two arguments:\n\n

    \n
    function completer(linePartial, callback) {\n  callback(null, [['123'], linePartial]);\n}
    \n

    createInterface is commonly used with process.stdin and\nprocess.stdout in order to accept user input:\n\n

    \n
    var readline = require('readline');\nvar rl = readline.createInterface({\n  input: process.stdin,\n  output: process.stdout\n});
    \n

    Once you have a readline instance, you most commonly listen for the\n"line" event.\n\n

    \n

    If terminal is true for this instance then the output stream will get\nthe best compatibility if it defines an output.columns property, and fires\na "resize" event on the output if/when the columns ever change\n(process.stdout does this automatically when it is a TTY).\n\n

    \n", + "desc": "

    Creates a readline Interface instance. Accepts an "options" Object that takes\nthe following values:\n\n

    \n
      \n
    • input - the readable stream to listen to (Required).

      \n
    • \n
    • output - the writable stream to write readline data to (Required).

      \n
    • \n
    • completer - an optional function that is used for Tab autocompletion. See\nbelow for an example of using this.

      \n
    • \n
    • terminal - pass true if the input and output streams should be\ntreated like a TTY, and have ANSI/VT100 escape codes written to it.\nDefaults to checking isTTY on the output stream upon instantiation.

      \n
    • \n
    \n

    The completer function is given the current line entered by the user, and\nis supposed to return an Array with 2 entries:\n\n

    \n
      \n
    1. An Array with matching entries for the completion.

      \n
    2. \n
    3. The substring that was used for the matching.

      \n
    4. \n
    \n

    Which ends up looking something like:\n[[substr1, substr2, ...], originalsubstring].\n\n

    \n

    Example:\n\n

    \n
    function completer(line) {\n  var completions = '.help .error .exit .quit .q'.split(' ')\n  var hits = completions.filter(function(c) { return c.indexOf(line) == 0 })\n  // show all completions if none found\n  return [hits.length ? hits : completions, line]\n}
    \n

    Also completer can be run in async mode if it accepts two arguments:\n\n

    \n
    function completer(linePartial, callback) {\n  callback(null, [['123'], linePartial]);\n}
    \n

    createInterface is commonly used with process.stdin and\nprocess.stdout in order to accept user input:\n\n

    \n
    var readline = require('readline');\nvar rl = readline.createInterface({\n  input: process.stdin,\n  output: process.stdout\n});
    \n

    Once you have a readline instance, you most commonly listen for the\n"line" event.\n\n

    \n

    If terminal is true for this instance then the output stream will get\nthe best compatibility if it defines an output.columns property, and fires\na "resize" event on the output if/when the columns ever change\n(process.stdout does this automatically when it is a TTY).\n\n

    \n", "signatures": [ { "params": [ @@ -12075,6 +12099,81 @@ ] } ] + }, + { + "textRaw": "readline.cursorTo(stream, x, y)", + "type": "method", + "name": "cursorTo", + "desc": "

    Move cursor to the specified position in a given TTY stream.\n\n

    \n", + "signatures": [ + { + "params": [ + { + "name": "stream" + }, + { + "name": "x" + }, + { + "name": "y" + } + ] + } + ] + }, + { + "textRaw": "readline.moveCursor(stream, dx, dy)", + "type": "method", + "name": "moveCursor", + "desc": "

    Move cursor relative to it's current position in a given TTY stream.\n\n

    \n", + "signatures": [ + { + "params": [ + { + "name": "stream" + }, + { + "name": "dx" + }, + { + "name": "dy" + } + ] + } + ] + }, + { + "textRaw": "readline.clearLine(stream, dir)", + "type": "method", + "name": "clearLine", + "desc": "

    Clears current line of given TTY stream in a specified direction.\ndir should have one of following values:\n\n

    \n
      \n
    • -1 - to the left from cursor
    • \n
    • 1 - to the right from cursor
    • \n
    • 0 - the entire line
    • \n
    \n", + "signatures": [ + { + "params": [ + { + "name": "stream" + }, + { + "name": "dir" + } + ] + } + ] + }, + { + "textRaw": "readline.clearScreenDown(stream)", + "type": "method", + "name": "clearScreenDown", + "desc": "

    Clears the screen from the current position of the cursor down.\n\n

    \n", + "signatures": [ + { + "params": [ + { + "name": "stream" + } + ] + } + ] } ], "classes": [ @@ -12735,7 +12834,7 @@ ] } ], - "desc": "

    Launches a new process with the given command, with command line arguments in args.\nIf omitted, args defaults to an empty Array.\n\n

    \n

    The third argument is used to specify additional options, which defaults to:\n\n

    \n
    { cwd: undefined,\n  env: process.env\n}
    \n

    cwd allows you to specify the working directory from which the process is spawned.\nUse env to specify environment variables that will be visible to the new process.\n\n

    \n

    Example of running ls -lh /usr, capturing stdout, stderr, and the exit code:\n\n

    \n
    var spawn = require('child_process').spawn,\n    ls    = spawn('ls', ['-lh', '/usr']);\n\nls.stdout.on('data', function (data) {\n  console.log('stdout: ' + data);\n});\n\nls.stderr.on('data', function (data) {\n  console.log('stderr: ' + data);\n});\n\nls.on('close', function (code) {\n  console.log('child process exited with code ' + code);\n});
    \n

    Example: A very elaborate way to run 'ps ax | grep ssh'\n\n

    \n
    var spawn = require('child_process').spawn,\n    ps    = spawn('ps', ['ax']),\n    grep  = spawn('grep', ['ssh']);\n\nps.stdout.on('data', function (data) {\n  grep.stdin.write(data);\n});\n\nps.stderr.on('data', function (data) {\n  console.log('ps stderr: ' + data);\n});\n\nps.on('close', function (code) {\n  if (code !== 0) {\n    console.log('ps process exited with code ' + code);\n  }\n  grep.stdin.end();\n});\n\ngrep.stdout.on('data', function (data) {\n  console.log('' + data);\n});\n\ngrep.stderr.on('data', function (data) {\n  console.log('grep stderr: ' + data);\n});\n\ngrep.on('close', function (code) {\n  if (code !== 0) {\n    console.log('grep process exited with code ' + code);\n  }\n});
    \n

    Example of checking for failed exec:\n\n

    \n
    var spawn = require('child_process').spawn,\n    child = spawn('bad_command');\n\nchild.stderr.setEncoding('utf8');\nchild.stderr.on('data', function (data) {\n  if (/^execvp\\(\\)/.test(data)) {\n    console.log('Failed to start child process.');\n  }\n});
    \n

    Note that if spawn receives an empty options object, it will result in\nspawning the process with an empty environment rather than using\nprocess.env. This due to backwards compatibility issues with a deprecated\nAPI.\n\n

    \n

    The 'stdio' option to child_process.spawn() is an array where each\nindex corresponds to a fd in the child. The value is one of the following:\n\n

    \n
      \n
    1. 'pipe' - Create a pipe between the child process and the parent process.\nThe parent end of the pipe is exposed to the parent as a property on the\nchild_process object as ChildProcess.stdio[fd]. Pipes created for\nfds 0 - 2 are also available as ChildProcess.stdin, ChildProcess.stdout\nand ChildProcess.stderr, respectively.
    2. \n
    3. 'ipc' - Create an IPC channel for passing messages/file descriptors\nbetween parent and child. A ChildProcess may have at most one IPC stdio\nfile descriptor. Setting this option enables the ChildProcess.send() method.\nIf the child writes JSON messages to this file descriptor, then this will\ntrigger ChildProcess.on('message'). If the child is a Node.js program, then\nthe presence of an IPC channel will enable process.send() and\nprocess.on('message').
    4. \n
    5. 'ignore' - Do not set this file descriptor in the child. Note that Node\nwill always open fd 0 - 2 for the processes it spawns. When any of these is\nignored node will open /dev/null and attach it to the child's fd.
    6. \n
    7. Stream object - Share a readable or writable stream that refers to a tty,\nfile, socket, or a pipe with the child process. The stream's underlying\nfile descriptor is duplicated in the child process to the fd that \ncorresponds to the index in the stdio array.
    8. \n
    9. Positive integer - The integer value is interpreted as a file descriptor \nthat is is currently open in the parent process. It is shared with the child\nprocess, similar to how Stream objects can be shared.
    10. \n
    11. null, undefined - Use default value. For stdio fds 0, 1 and 2 (in other\nwords, stdin, stdout, and stderr) a pipe is created. For fd 3 and up, the\ndefault is 'ignore'.
    12. \n
    \n

    As a shorthand, the stdio argument may also be one of the following\nstrings, rather than an array:\n\n

    \n
      \n
    • ignore - ['ignore', 'ignore', 'ignore']
    • \n
    • pipe - ['pipe', 'pipe', 'pipe']
    • \n
    • inherit - [process.stdin, process.stdout, process.stderr] or [0,1,2]
    • \n
    \n

    Example:\n\n

    \n
    var spawn = require('child_process').spawn;\n\n// Child will use parent's stdios\nspawn('prg', [], { stdio: 'inherit' });\n\n// Spawn child sharing only stderr\nspawn('prg', [], { stdio: ['pipe', 'pipe', process.stderr] });\n\n// Open an extra fd=4, to interact with programs present a\n// startd-style interface.\nspawn('prg', [], { stdio: ['pipe', null, null, null, 'pipe'] });
    \n

    If the detached option is set, the child process will be made the leader of a\nnew process group. This makes it possible for the child to continue running \nafter the parent exits.\n\n

    \n

    By default, the parent will wait for the detached child to exit. To prevent\nthe parent from waiting for a given child, use the child.unref() method,\nand the parent's event loop will not include the child in its reference count.\n\n

    \n

    Example of detaching a long-running process and redirecting its output to a\nfile:\n\n

    \n
     var fs = require('fs'),\n     spawn = require('child_process').spawn,\n     out = fs.openSync('./out.log', 'a'),\n     err = fs.openSync('./out.log', 'a');\n\n var child = spawn('prg', [], {\n   detached: true,\n   stdio: [ 'ignore', out, err ]\n });\n\n child.unref();
    \n

    When using the detached option to start a long-running process, the process\nwill not stay running in the background unless it is provided with a stdio\nconfiguration that is not connected to the parent. If the parent's stdio is\ninherited, the child will remain attached to the controlling terminal.\n\n

    \n

    There is a deprecated option called customFds which allows one to specify\nspecific file descriptors for the stdio of the child process. This API was\nnot portable to all platforms and therefore removed.\nWith customFds it was possible to hook up the new process' [stdin, stdout,\nstderr] to existing streams; -1 meant that a new stream should be created.\nUse at your own risk.\n\n

    \n

    See also: child_process.exec() and child_process.fork()\n\n

    \n" + "desc": "

    Launches a new process with the given command, with command line arguments in args.\nIf omitted, args defaults to an empty Array.\n\n

    \n

    The third argument is used to specify additional options, which defaults to:\n\n

    \n
    { cwd: undefined,\n  env: process.env\n}
    \n

    cwd allows you to specify the working directory from which the process is spawned.\nUse env to specify environment variables that will be visible to the new process.\n\n

    \n

    Example of running ls -lh /usr, capturing stdout, stderr, and the exit code:\n\n

    \n
    var spawn = require('child_process').spawn,\n    ls    = spawn('ls', ['-lh', '/usr']);\n\nls.stdout.on('data', function (data) {\n  console.log('stdout: ' + data);\n});\n\nls.stderr.on('data', function (data) {\n  console.log('stderr: ' + data);\n});\n\nls.on('close', function (code) {\n  console.log('child process exited with code ' + code);\n});
    \n

    Example: A very elaborate way to run 'ps ax | grep ssh'\n\n

    \n
    var spawn = require('child_process').spawn,\n    ps    = spawn('ps', ['ax']),\n    grep  = spawn('grep', ['ssh']);\n\nps.stdout.on('data', function (data) {\n  grep.stdin.write(data);\n});\n\nps.stderr.on('data', function (data) {\n  console.log('ps stderr: ' + data);\n});\n\nps.on('close', function (code) {\n  if (code !== 0) {\n    console.log('ps process exited with code ' + code);\n  }\n  grep.stdin.end();\n});\n\ngrep.stdout.on('data', function (data) {\n  console.log('' + data);\n});\n\ngrep.stderr.on('data', function (data) {\n  console.log('grep stderr: ' + data);\n});\n\ngrep.on('close', function (code) {\n  if (code !== 0) {\n    console.log('grep process exited with code ' + code);\n  }\n});
    \n

    Example of checking for failed exec:\n\n

    \n
    var spawn = require('child_process').spawn,\n    child = spawn('bad_command');\n\nchild.stderr.setEncoding('utf8');\nchild.stderr.on('data', function (data) {\n  if (/^execvp\\(\\)/.test(data)) {\n    console.log('Failed to start child process.');\n  }\n});
    \n

    Note that if spawn receives an empty options object, it will result in\nspawning the process with an empty environment rather than using\nprocess.env. This due to backwards compatibility issues with a deprecated\nAPI.\n\n

    \n

    The 'stdio' option to child_process.spawn() is an array where each\nindex corresponds to a fd in the child. The value is one of the following:\n\n

    \n
      \n
    1. 'pipe' - Create a pipe between the child process and the parent process.\nThe parent end of the pipe is exposed to the parent as a property on the\nchild_process object as ChildProcess.stdio[fd]. Pipes created for\nfds 0 - 2 are also available as ChildProcess.stdin, ChildProcess.stdout\nand ChildProcess.stderr, respectively.
    2. \n
    3. 'ipc' - Create an IPC channel for passing messages/file descriptors\nbetween parent and child. A ChildProcess may have at most one IPC stdio\nfile descriptor. Setting this option enables the ChildProcess.send() method.\nIf the child writes JSON messages to this file descriptor, then this will\ntrigger ChildProcess.on('message'). If the child is a Node.js program, then\nthe presence of an IPC channel will enable process.send() and\nprocess.on('message').
    4. \n
    5. 'ignore' - Do not set this file descriptor in the child. Note that Node\nwill always open fd 0 - 2 for the processes it spawns. When any of these is\nignored node will open /dev/null and attach it to the child's fd.
    6. \n
    7. Stream object - Share a readable or writable stream that refers to a tty,\nfile, socket, or a pipe with the child process. The stream's underlying\nfile descriptor is duplicated in the child process to the fd that \ncorresponds to the index in the stdio array. Note that the stream must\nhave an underlying descriptor (file streams do not until the 'open'\nevent has occurred).
    8. \n
    9. Positive integer - The integer value is interpreted as a file descriptor \nthat is is currently open in the parent process. It is shared with the child\nprocess, similar to how Stream objects can be shared.
    10. \n
    11. null, undefined - Use default value. For stdio fds 0, 1 and 2 (in other\nwords, stdin, stdout, and stderr) a pipe is created. For fd 3 and up, the\ndefault is 'ignore'.
    12. \n
    \n

    As a shorthand, the stdio argument may also be one of the following\nstrings, rather than an array:\n\n

    \n
      \n
    • ignore - ['ignore', 'ignore', 'ignore']
    • \n
    • pipe - ['pipe', 'pipe', 'pipe']
    • \n
    • inherit - [process.stdin, process.stdout, process.stderr] or [0,1,2]
    • \n
    \n

    Example:\n\n

    \n
    var spawn = require('child_process').spawn;\n\n// Child will use parent's stdios\nspawn('prg', [], { stdio: 'inherit' });\n\n// Spawn child sharing only stderr\nspawn('prg', [], { stdio: ['pipe', 'pipe', process.stderr] });\n\n// Open an extra fd=4, to interact with programs present a\n// startd-style interface.\nspawn('prg', [], { stdio: ['pipe', null, null, null, 'pipe'] });
    \n

    If the detached option is set, the child process will be made the leader of a\nnew process group. This makes it possible for the child to continue running \nafter the parent exits.\n\n

    \n

    By default, the parent will wait for the detached child to exit. To prevent\nthe parent from waiting for a given child, use the child.unref() method,\nand the parent's event loop will not include the child in its reference count.\n\n

    \n

    Example of detaching a long-running process and redirecting its output to a\nfile:\n\n

    \n
     var fs = require('fs'),\n     spawn = require('child_process').spawn,\n     out = fs.openSync('./out.log', 'a'),\n     err = fs.openSync('./out.log', 'a');\n\n var child = spawn('prg', [], {\n   detached: true,\n   stdio: [ 'ignore', out, err ]\n });\n\n child.unref();
    \n

    When using the detached option to start a long-running process, the process\nwill not stay running in the background unless it is provided with a stdio\nconfiguration that is not connected to the parent. If the parent's stdio is\ninherited, the child will remain attached to the controlling terminal.\n\n

    \n

    There is a deprecated option called customFds which allows one to specify\nspecific file descriptors for the stdio of the child process. This API was\nnot portable to all platforms and therefore removed.\nWith customFds it was possible to hook up the new process' [stdin, stdout,\nstderr] to existing streams; -1 meant that a new stream should be created.\nUse at your own risk.\n\n

    \n

    See also: child_process.exec() and child_process.fork()\n\n

    \n" }, { "textRaw": "child_process.exec(command, [options], callback)", @@ -12848,7 +12947,7 @@ "desc": "

    Runs a command in a shell and buffers the output.\n\n

    \n
    var exec = require('child_process').exec,\n    child;\n\nchild = exec('cat *.js bad_file | wc -l',\n  function (error, stdout, stderr) {\n    console.log('stdout: ' + stdout);\n    console.log('stderr: ' + stderr);\n    if (error !== null) {\n      console.log('exec error: ' + error);\n    }\n});
    \n

    The callback gets the arguments (error, stdout, stderr). On success, error\nwill be null. On error, error will be an instance of Error and err.code\nwill be the exit code of the child process, and err.signal will be set to the\nsignal that terminated the process.\n\n

    \n

    There is a second optional argument to specify several options. The\ndefault options are\n\n

    \n
    { encoding: 'utf8',\n  timeout: 0,\n  maxBuffer: 200*1024,\n  killSignal: 'SIGTERM',\n  cwd: null,\n  env: null }
    \n

    If timeout is greater than 0, then it will kill the child process\nif it runs longer than timeout milliseconds. The child process is killed with\nkillSignal (default: 'SIGTERM'). maxBuffer specifies the largest\namount of data allowed on stdout or stderr - if this value is exceeded then\nthe child process is killed.\n\n\n

    \n" }, { - "textRaw": "child_process.execFile(file, args, options, callback)", + "textRaw": "child_process.execFile(file, [args], [options], [callback])", "type": "method", "name": "execFile", "signatures": [ @@ -12869,7 +12968,8 @@ "textRaw": "`args` {Array} List of string arguments ", "name": "args", "type": "Array", - "desc": "List of string arguments" + "desc": "List of string arguments", + "optional": true }, { "textRaw": "`options` {Object} ", @@ -12912,7 +13012,8 @@ } ], "name": "options", - "type": "Object" + "type": "Object", + "optional": true }, { "textRaw": "`callback` {Function} called with the output when process terminates ", @@ -12935,7 +13036,8 @@ ], "name": "callback", "type": "Function", - "desc": "called with the output when process terminates" + "desc": "called with the output when process terminates", + "optional": true } ] }, @@ -12945,13 +13047,16 @@ "name": "file" }, { - "name": "args" + "name": "args", + "optional": true }, { - "name": "options" + "name": "options", + "optional": true }, { - "name": "callback" + "name": "callback", + "optional": true } ] } @@ -13018,10 +13123,10 @@ "desc": "List of string arguments passed to the executable" }, { - "textRaw": "`silent` {Boolean} If true, prevent stdout and stderr in the spawned node process from being associated with the parent's (default is false) ", + "textRaw": "`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 (default is false) ", "name": "silent", "type": "Boolean", - "desc": "If true, prevent stdout and stderr in the spawned node process from being associated with the parent's (default is false)" + "desc": "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 (default is false)" } ], "name": "options", @@ -14050,7 +14155,7 @@ "type": "event", "name": "fork", "params": [], - "desc": "

    When a new worker is forked the cluster module will emit a 'fork' event.\nThis can be used to log worker activity, and create you own timeout.\n\n

    \n
    var timeouts = [];\nfunction errorMsg() {\n  console.error("Something must be wrong with the connection ...");\n}\n\ncluster.on('fork', function(worker) {\n  timeouts[worker.id] = setTimeout(errorMsg, 2000);\n});\ncluster.on('listening', function(worker, address) {\n  clearTimeout(timeouts[worker.id]);\n});\ncluster.on('exit', function(worker, code, signal) {\n  clearTimeout(timeouts[worker.id]);\n  errorMsg();\n});
    \n" + "desc": "

    When a new worker is forked the cluster module will emit a 'fork' event.\nThis can be used to log worker activity, and create your own timeout.\n\n

    \n
    var timeouts = [];\nfunction errorMsg() {\n  console.error("Something must be wrong with the connection ...");\n}\n\ncluster.on('fork', function(worker) {\n  timeouts[worker.id] = setTimeout(errorMsg, 2000);\n});\ncluster.on('listening', function(worker, address) {\n  clearTimeout(timeouts[worker.id]);\n});\ncluster.on('exit', function(worker, code, signal) {\n  clearTimeout(timeouts[worker.id]);\n  errorMsg();\n});
    \n" }, { "textRaw": "Event: 'online'", diff -Nru nodejs-0.11.10/doc/api/assert.html nodejs-0.11.11/doc/api/assert.html --- nodejs-0.11.10/doc/api/assert.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/assert.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - Assert Node.js v0.11.10 Manual & Documentation + Assert Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -165,7 +165,7 @@

  • -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/api/buffer.html nodejs-0.11.11/doc/api/buffer.html --- nodejs-0.11.10/doc/api/buffer.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/buffer.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - Buffer Node.js v0.11.10 Manual & Documentation + Buffer Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -895,7 +895,7 @@

  • -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/api/child_process.html nodejs-0.11.11/doc/api/child_process.html --- nodejs-0.11.10/doc/api/child_process.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/child_process.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - Child Process Node.js v0.11.10 Manual & Documentation + Child Process Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -68,7 +68,7 @@

  • child_process.spawn(command, [args], [options])
  • child_process.exec(command, [options], callback)
  • -
  • child_process.execFile(file, args, options, callback)
  • +
  • child_process.execFile(file, [args], [options], [callback])
  • child_process.fork(modulePath, [args], [options])
  • @@ -527,7 +527,9 @@
  • Stream object - Share a readable or writable stream that refers to a tty, file, socket, or a pipe with the child process. The stream's underlying file descriptor is duplicated in the child process to the fd that -corresponds to the index in the stdio array.
  • +corresponds to the index in the stdio array. Note that the stream must +have an underlying descriptor (file streams do not until the 'open' +event has occurred).
  • Positive integer - The integer value is interpreted as a file descriptor that is is currently open in the parent process. It is shared with the child process, similar to how Stream objects can be shared.
  • @@ -662,7 +664,7 @@

    -

    child_process.execFile(file, args, options, callback)#

    +

    child_process.execFile(file, [args], [options], [callback])#

    • file String The filename of the program to run
    • args Array List of string arguments
    • @@ -700,8 +702,10 @@
    • execPath String Executable used to create the child process
    • execArgv Array List of string arguments passed to the executable (Default: process.execArgv)
    • -
    • silent Boolean If true, prevent stdout and stderr in the spawned node -process from being associated with the parent's (default is false)
    • +
    • 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 +(default is false)
  • Return: ChildProcess object
  • @@ -743,7 +747,7 @@
  • -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/api/child_process.json nodejs-0.11.11/doc/api/child_process.json --- nodejs-0.11.10/doc/api/child_process.json 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/child_process.json 2014-01-29 03:26:35.000000000 +0000 @@ -247,7 +247,7 @@ ] } ], - "desc": "

    Launches a new process with the given command, with command line arguments in args.\nIf omitted, args defaults to an empty Array.\n\n

    \n

    The third argument is used to specify additional options, which defaults to:\n\n

    \n
    { cwd: undefined,\n  env: process.env\n}
    \n

    cwd allows you to specify the working directory from which the process is spawned.\nUse env to specify environment variables that will be visible to the new process.\n\n

    \n

    Example of running ls -lh /usr, capturing stdout, stderr, and the exit code:\n\n

    \n
    var spawn = require('child_process').spawn,\n    ls    = spawn('ls', ['-lh', '/usr']);\n\nls.stdout.on('data', function (data) {\n  console.log('stdout: ' + data);\n});\n\nls.stderr.on('data', function (data) {\n  console.log('stderr: ' + data);\n});\n\nls.on('close', function (code) {\n  console.log('child process exited with code ' + code);\n});
    \n

    Example: A very elaborate way to run 'ps ax | grep ssh'\n\n

    \n
    var spawn = require('child_process').spawn,\n    ps    = spawn('ps', ['ax']),\n    grep  = spawn('grep', ['ssh']);\n\nps.stdout.on('data', function (data) {\n  grep.stdin.write(data);\n});\n\nps.stderr.on('data', function (data) {\n  console.log('ps stderr: ' + data);\n});\n\nps.on('close', function (code) {\n  if (code !== 0) {\n    console.log('ps process exited with code ' + code);\n  }\n  grep.stdin.end();\n});\n\ngrep.stdout.on('data', function (data) {\n  console.log('' + data);\n});\n\ngrep.stderr.on('data', function (data) {\n  console.log('grep stderr: ' + data);\n});\n\ngrep.on('close', function (code) {\n  if (code !== 0) {\n    console.log('grep process exited with code ' + code);\n  }\n});
    \n

    Example of checking for failed exec:\n\n

    \n
    var spawn = require('child_process').spawn,\n    child = spawn('bad_command');\n\nchild.stderr.setEncoding('utf8');\nchild.stderr.on('data', function (data) {\n  if (/^execvp\\(\\)/.test(data)) {\n    console.log('Failed to start child process.');\n  }\n});
    \n

    Note that if spawn receives an empty options object, it will result in\nspawning the process with an empty environment rather than using\nprocess.env. This due to backwards compatibility issues with a deprecated\nAPI.\n\n

    \n

    The 'stdio' option to child_process.spawn() is an array where each\nindex corresponds to a fd in the child. The value is one of the following:\n\n

    \n
      \n
    1. 'pipe' - Create a pipe between the child process and the parent process.\nThe parent end of the pipe is exposed to the parent as a property on the\nchild_process object as ChildProcess.stdio[fd]. Pipes created for\nfds 0 - 2 are also available as ChildProcess.stdin, ChildProcess.stdout\nand ChildProcess.stderr, respectively.
    2. \n
    3. 'ipc' - Create an IPC channel for passing messages/file descriptors\nbetween parent and child. A ChildProcess may have at most one IPC stdio\nfile descriptor. Setting this option enables the ChildProcess.send() method.\nIf the child writes JSON messages to this file descriptor, then this will\ntrigger ChildProcess.on('message'). If the child is a Node.js program, then\nthe presence of an IPC channel will enable process.send() and\nprocess.on('message').
    4. \n
    5. 'ignore' - Do not set this file descriptor in the child. Note that Node\nwill always open fd 0 - 2 for the processes it spawns. When any of these is\nignored node will open /dev/null and attach it to the child's fd.
    6. \n
    7. Stream object - Share a readable or writable stream that refers to a tty,\nfile, socket, or a pipe with the child process. The stream's underlying\nfile descriptor is duplicated in the child process to the fd that \ncorresponds to the index in the stdio array.
    8. \n
    9. Positive integer - The integer value is interpreted as a file descriptor \nthat is is currently open in the parent process. It is shared with the child\nprocess, similar to how Stream objects can be shared.
    10. \n
    11. null, undefined - Use default value. For stdio fds 0, 1 and 2 (in other\nwords, stdin, stdout, and stderr) a pipe is created. For fd 3 and up, the\ndefault is 'ignore'.
    12. \n
    \n

    As a shorthand, the stdio argument may also be one of the following\nstrings, rather than an array:\n\n

    \n
      \n
    • ignore - ['ignore', 'ignore', 'ignore']
    • \n
    • pipe - ['pipe', 'pipe', 'pipe']
    • \n
    • inherit - [process.stdin, process.stdout, process.stderr] or [0,1,2]
    • \n
    \n

    Example:\n\n

    \n
    var spawn = require('child_process').spawn;\n\n// Child will use parent's stdios\nspawn('prg', [], { stdio: 'inherit' });\n\n// Spawn child sharing only stderr\nspawn('prg', [], { stdio: ['pipe', 'pipe', process.stderr] });\n\n// Open an extra fd=4, to interact with programs present a\n// startd-style interface.\nspawn('prg', [], { stdio: ['pipe', null, null, null, 'pipe'] });
    \n

    If the detached option is set, the child process will be made the leader of a\nnew process group. This makes it possible for the child to continue running \nafter the parent exits.\n\n

    \n

    By default, the parent will wait for the detached child to exit. To prevent\nthe parent from waiting for a given child, use the child.unref() method,\nand the parent's event loop will not include the child in its reference count.\n\n

    \n

    Example of detaching a long-running process and redirecting its output to a\nfile:\n\n

    \n
     var fs = require('fs'),\n     spawn = require('child_process').spawn,\n     out = fs.openSync('./out.log', 'a'),\n     err = fs.openSync('./out.log', 'a');\n\n var child = spawn('prg', [], {\n   detached: true,\n   stdio: [ 'ignore', out, err ]\n });\n\n child.unref();
    \n

    When using the detached option to start a long-running process, the process\nwill not stay running in the background unless it is provided with a stdio\nconfiguration that is not connected to the parent. If the parent's stdio is\ninherited, the child will remain attached to the controlling terminal.\n\n

    \n

    There is a deprecated option called customFds which allows one to specify\nspecific file descriptors for the stdio of the child process. This API was\nnot portable to all platforms and therefore removed.\nWith customFds it was possible to hook up the new process' [stdin, stdout,\nstderr] to existing streams; -1 meant that a new stream should be created.\nUse at your own risk.\n\n

    \n

    See also: child_process.exec() and child_process.fork()\n\n

    \n" + "desc": "

    Launches a new process with the given command, with command line arguments in args.\nIf omitted, args defaults to an empty Array.\n\n

    \n

    The third argument is used to specify additional options, which defaults to:\n\n

    \n
    { cwd: undefined,\n  env: process.env\n}
    \n

    cwd allows you to specify the working directory from which the process is spawned.\nUse env to specify environment variables that will be visible to the new process.\n\n

    \n

    Example of running ls -lh /usr, capturing stdout, stderr, and the exit code:\n\n

    \n
    var spawn = require('child_process').spawn,\n    ls    = spawn('ls', ['-lh', '/usr']);\n\nls.stdout.on('data', function (data) {\n  console.log('stdout: ' + data);\n});\n\nls.stderr.on('data', function (data) {\n  console.log('stderr: ' + data);\n});\n\nls.on('close', function (code) {\n  console.log('child process exited with code ' + code);\n});
    \n

    Example: A very elaborate way to run 'ps ax | grep ssh'\n\n

    \n
    var spawn = require('child_process').spawn,\n    ps    = spawn('ps', ['ax']),\n    grep  = spawn('grep', ['ssh']);\n\nps.stdout.on('data', function (data) {\n  grep.stdin.write(data);\n});\n\nps.stderr.on('data', function (data) {\n  console.log('ps stderr: ' + data);\n});\n\nps.on('close', function (code) {\n  if (code !== 0) {\n    console.log('ps process exited with code ' + code);\n  }\n  grep.stdin.end();\n});\n\ngrep.stdout.on('data', function (data) {\n  console.log('' + data);\n});\n\ngrep.stderr.on('data', function (data) {\n  console.log('grep stderr: ' + data);\n});\n\ngrep.on('close', function (code) {\n  if (code !== 0) {\n    console.log('grep process exited with code ' + code);\n  }\n});
    \n

    Example of checking for failed exec:\n\n

    \n
    var spawn = require('child_process').spawn,\n    child = spawn('bad_command');\n\nchild.stderr.setEncoding('utf8');\nchild.stderr.on('data', function (data) {\n  if (/^execvp\\(\\)/.test(data)) {\n    console.log('Failed to start child process.');\n  }\n});
    \n

    Note that if spawn receives an empty options object, it will result in\nspawning the process with an empty environment rather than using\nprocess.env. This due to backwards compatibility issues with a deprecated\nAPI.\n\n

    \n

    The 'stdio' option to child_process.spawn() is an array where each\nindex corresponds to a fd in the child. The value is one of the following:\n\n

    \n
      \n
    1. 'pipe' - Create a pipe between the child process and the parent process.\nThe parent end of the pipe is exposed to the parent as a property on the\nchild_process object as ChildProcess.stdio[fd]. Pipes created for\nfds 0 - 2 are also available as ChildProcess.stdin, ChildProcess.stdout\nand ChildProcess.stderr, respectively.
    2. \n
    3. 'ipc' - Create an IPC channel for passing messages/file descriptors\nbetween parent and child. A ChildProcess may have at most one IPC stdio\nfile descriptor. Setting this option enables the ChildProcess.send() method.\nIf the child writes JSON messages to this file descriptor, then this will\ntrigger ChildProcess.on('message'). If the child is a Node.js program, then\nthe presence of an IPC channel will enable process.send() and\nprocess.on('message').
    4. \n
    5. 'ignore' - Do not set this file descriptor in the child. Note that Node\nwill always open fd 0 - 2 for the processes it spawns. When any of these is\nignored node will open /dev/null and attach it to the child's fd.
    6. \n
    7. Stream object - Share a readable or writable stream that refers to a tty,\nfile, socket, or a pipe with the child process. The stream's underlying\nfile descriptor is duplicated in the child process to the fd that \ncorresponds to the index in the stdio array. Note that the stream must\nhave an underlying descriptor (file streams do not until the 'open'\nevent has occurred).
    8. \n
    9. Positive integer - The integer value is interpreted as a file descriptor \nthat is is currently open in the parent process. It is shared with the child\nprocess, similar to how Stream objects can be shared.
    10. \n
    11. null, undefined - Use default value. For stdio fds 0, 1 and 2 (in other\nwords, stdin, stdout, and stderr) a pipe is created. For fd 3 and up, the\ndefault is 'ignore'.
    12. \n
    \n

    As a shorthand, the stdio argument may also be one of the following\nstrings, rather than an array:\n\n

    \n
      \n
    • ignore - ['ignore', 'ignore', 'ignore']
    • \n
    • pipe - ['pipe', 'pipe', 'pipe']
    • \n
    • inherit - [process.stdin, process.stdout, process.stderr] or [0,1,2]
    • \n
    \n

    Example:\n\n

    \n
    var spawn = require('child_process').spawn;\n\n// Child will use parent's stdios\nspawn('prg', [], { stdio: 'inherit' });\n\n// Spawn child sharing only stderr\nspawn('prg', [], { stdio: ['pipe', 'pipe', process.stderr] });\n\n// Open an extra fd=4, to interact with programs present a\n// startd-style interface.\nspawn('prg', [], { stdio: ['pipe', null, null, null, 'pipe'] });
    \n

    If the detached option is set, the child process will be made the leader of a\nnew process group. This makes it possible for the child to continue running \nafter the parent exits.\n\n

    \n

    By default, the parent will wait for the detached child to exit. To prevent\nthe parent from waiting for a given child, use the child.unref() method,\nand the parent's event loop will not include the child in its reference count.\n\n

    \n

    Example of detaching a long-running process and redirecting its output to a\nfile:\n\n

    \n
     var fs = require('fs'),\n     spawn = require('child_process').spawn,\n     out = fs.openSync('./out.log', 'a'),\n     err = fs.openSync('./out.log', 'a');\n\n var child = spawn('prg', [], {\n   detached: true,\n   stdio: [ 'ignore', out, err ]\n });\n\n child.unref();
    \n

    When using the detached option to start a long-running process, the process\nwill not stay running in the background unless it is provided with a stdio\nconfiguration that is not connected to the parent. If the parent's stdio is\ninherited, the child will remain attached to the controlling terminal.\n\n

    \n

    There is a deprecated option called customFds which allows one to specify\nspecific file descriptors for the stdio of the child process. This API was\nnot portable to all platforms and therefore removed.\nWith customFds it was possible to hook up the new process' [stdin, stdout,\nstderr] to existing streams; -1 meant that a new stream should be created.\nUse at your own risk.\n\n

    \n

    See also: child_process.exec() and child_process.fork()\n\n

    \n" }, { "textRaw": "child_process.exec(command, [options], callback)", @@ -360,7 +360,7 @@ "desc": "

    Runs a command in a shell and buffers the output.\n\n

    \n
    var exec = require('child_process').exec,\n    child;\n\nchild = exec('cat *.js bad_file | wc -l',\n  function (error, stdout, stderr) {\n    console.log('stdout: ' + stdout);\n    console.log('stderr: ' + stderr);\n    if (error !== null) {\n      console.log('exec error: ' + error);\n    }\n});
    \n

    The callback gets the arguments (error, stdout, stderr). On success, error\nwill be null. On error, error will be an instance of Error and err.code\nwill be the exit code of the child process, and err.signal will be set to the\nsignal that terminated the process.\n\n

    \n

    There is a second optional argument to specify several options. The\ndefault options are\n\n

    \n
    { encoding: 'utf8',\n  timeout: 0,\n  maxBuffer: 200*1024,\n  killSignal: 'SIGTERM',\n  cwd: null,\n  env: null }
    \n

    If timeout is greater than 0, then it will kill the child process\nif it runs longer than timeout milliseconds. The child process is killed with\nkillSignal (default: 'SIGTERM'). maxBuffer specifies the largest\namount of data allowed on stdout or stderr - if this value is exceeded then\nthe child process is killed.\n\n\n

    \n" }, { - "textRaw": "child_process.execFile(file, args, options, callback)", + "textRaw": "child_process.execFile(file, [args], [options], [callback])", "type": "method", "name": "execFile", "signatures": [ @@ -381,7 +381,8 @@ "textRaw": "`args` {Array} List of string arguments ", "name": "args", "type": "Array", - "desc": "List of string arguments" + "desc": "List of string arguments", + "optional": true }, { "textRaw": "`options` {Object} ", @@ -424,7 +425,8 @@ } ], "name": "options", - "type": "Object" + "type": "Object", + "optional": true }, { "textRaw": "`callback` {Function} called with the output when process terminates ", @@ -447,7 +449,8 @@ ], "name": "callback", "type": "Function", - "desc": "called with the output when process terminates" + "desc": "called with the output when process terminates", + "optional": true } ] }, @@ -457,13 +460,16 @@ "name": "file" }, { - "name": "args" + "name": "args", + "optional": true }, { - "name": "options" + "name": "options", + "optional": true }, { - "name": "callback" + "name": "callback", + "optional": true } ] } @@ -530,10 +536,10 @@ "desc": "List of string arguments passed to the executable" }, { - "textRaw": "`silent` {Boolean} If true, prevent stdout and stderr in the spawned node process from being associated with the parent's (default is false) ", + "textRaw": "`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 (default is false) ", "name": "silent", "type": "Boolean", - "desc": "If true, prevent stdout and stderr in the spawned node process from being associated with the parent's (default is false)" + "desc": "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 (default is false)" } ], "name": "options", diff -Nru nodejs-0.11.10/doc/api/child_process.markdown nodejs-0.11.11/doc/api/child_process.markdown --- nodejs-0.11.10/doc/api/child_process.markdown 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/doc/api/child_process.markdown 2014-01-29 01:29:56.000000000 +0000 @@ -411,7 +411,9 @@ 4. `Stream` object - Share a readable or writable stream that refers to a tty, file, socket, or a pipe with the child process. The stream's underlying file descriptor is duplicated in the child process to the fd that - corresponds to the index in the `stdio` array. + corresponds to the index in the `stdio` array. Note that the stream must + have an underlying descriptor (file streams do not until the `'open'` + event has occurred). 5. Positive integer - The integer value is interpreted as a file descriptor that is is currently open in the parent process. It is shared with the child process, similar to how `Stream` objects can be shared. @@ -533,7 +535,7 @@ the child process is killed. -## child_process.execFile(file, args, options, callback) +## child_process.execFile(file, [args], [options], [callback]) * `file` {String} The filename of the program to run * `args` {Array} List of string arguments @@ -566,8 +568,10 @@ * `execPath` {String} Executable used to create the child process * `execArgv` {Array} List of string arguments passed to the executable (Default: `process.execArgv`) - * `silent` {Boolean} If true, prevent stdout and stderr in the spawned node - process from being associated with the parent's (default is false) + * `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 + (default is false) * Return: ChildProcess object This is a special case of the `spawn()` functionality for spawning Node diff -Nru nodejs-0.11.10/doc/api/cluster.html nodejs-0.11.11/doc/api/cluster.html --- nodejs-0.11.10/doc/api/cluster.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/cluster.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - Cluster Node.js v0.11.10 Manual & Documentation + Cluster Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -259,7 +259,7 @@

  • worker Worker object
  • When a new worker is forked the cluster module will emit a 'fork' event. -This can be used to log worker activity, and create you own timeout. +This can be used to log worker activity, and create your own timeout.

    var timeouts = [];
    @@ -763,7 +763,7 @@
                 
  • -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/api/cluster.json nodejs-0.11.11/doc/api/cluster.json --- nodejs-0.11.10/doc/api/cluster.json 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/cluster.json 2014-01-29 03:26:35.000000000 +0000 @@ -83,7 +83,7 @@ "type": "event", "name": "fork", "params": [], - "desc": "

    When a new worker is forked the cluster module will emit a 'fork' event.\nThis can be used to log worker activity, and create you own timeout.\n\n

    \n
    var timeouts = [];\nfunction errorMsg() {\n  console.error("Something must be wrong with the connection ...");\n}\n\ncluster.on('fork', function(worker) {\n  timeouts[worker.id] = setTimeout(errorMsg, 2000);\n});\ncluster.on('listening', function(worker, address) {\n  clearTimeout(timeouts[worker.id]);\n});\ncluster.on('exit', function(worker, code, signal) {\n  clearTimeout(timeouts[worker.id]);\n  errorMsg();\n});
    \n" + "desc": "

    When a new worker is forked the cluster module will emit a 'fork' event.\nThis can be used to log worker activity, and create your own timeout.\n\n

    \n
    var timeouts = [];\nfunction errorMsg() {\n  console.error("Something must be wrong with the connection ...");\n}\n\ncluster.on('fork', function(worker) {\n  timeouts[worker.id] = setTimeout(errorMsg, 2000);\n});\ncluster.on('listening', function(worker, address) {\n  clearTimeout(timeouts[worker.id]);\n});\ncluster.on('exit', function(worker, code, signal) {\n  clearTimeout(timeouts[worker.id]);\n  errorMsg();\n});
    \n" }, { "textRaw": "Event: 'online'", diff -Nru nodejs-0.11.10/doc/api/cluster.markdown nodejs-0.11.11/doc/api/cluster.markdown --- nodejs-0.11.10/doc/api/cluster.markdown 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/doc/api/cluster.markdown 2014-01-29 01:29:56.000000000 +0000 @@ -156,7 +156,7 @@ * `worker` {Worker object} When a new worker is forked the cluster module will emit a 'fork' event. -This can be used to log worker activity, and create you own timeout. +This can be used to log worker activity, and create your own timeout. var timeouts = []; function errorMsg() { diff -Nru nodejs-0.11.10/doc/api/console.html nodejs-0.11.11/doc/api/console.html --- nodejs-0.11.10/doc/api/console.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/console.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - console Node.js v0.11.10 Manual & Documentation + console Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -155,7 +155,7 @@

  • -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/api/crypto.html nodejs-0.11.11/doc/api/crypto.html --- nodejs-0.11.10/doc/api/crypto.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/crypto.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - Crypto Node.js v0.11.10 Manual & Documentation + Crypto Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -46,6 +46,7 @@

    Table of Contents

    diff -Nru nodejs-0.11.10/doc/api/crypto.json nodejs-0.11.11/doc/api/crypto.json --- nodejs-0.11.10/doc/api/crypto.json 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/crypto.json 2014-01-29 03:26:35.000000000 +0000 @@ -7,6 +7,25 @@ "desc": "
    Stability: 2 - Unstable; API changes are being discussed for\nfuture versions.  Breaking changes will be minimized.  See below.
    \n

    Use require('crypto') to access this module.\n\n

    \n

    The crypto module offers a way of encapsulating secure credentials to be\nused as part of a secure HTTPS net or http connection.\n\n

    \n

    It also offers a set of wrappers for OpenSSL's hash, hmac, cipher,\ndecipher, sign and verify methods.\n\n\n

    \n", "methods": [ { + "textRaw": "crypto.setEngine(engine, [flags])", + "type": "method", + "name": "setEngine", + "desc": "

    Load and set engine for some/all OpenSSL functions (selected by flags).\n\n

    \n

    engine could be either an id or a path to the to the engine's shared library.\n\n

    \n

    flags is optional and has ENGINE_METHOD_ALL value by default. It could take\none of or mix of following flags (defined in constants module):\n\n

    \n
      \n
    • ENGINE_METHOD_RSA
    • \n
    • ENGINE_METHOD_DSA
    • \n
    • ENGINE_METHOD_DH
    • \n
    • ENGINE_METHOD_RAND
    • \n
    • ENGINE_METHOD_ECDH
    • \n
    • ENGINE_METHOD_ECDSA
    • \n
    • ENGINE_METHOD_CIPHERS
    • \n
    • ENGINE_METHOD_DIGESTS
    • \n
    • ENGINE_METHOD_STORE
    • \n
    • ENGINE_METHOD_PKEY_METH
    • \n
    • ENGINE_METHOD_PKEY_ASN1_METH
    • \n
    • ENGINE_METHOD_ALL
    • \n
    • ENGINE_METHOD_NONE
    • \n
    \n", + "signatures": [ + { + "params": [ + { + "name": "engine" + }, + { + "name": "flags", + "optional": true + } + ] + } + ] + }, + { "textRaw": "crypto.getCiphers()", "type": "method", "name": "getCiphers", @@ -234,10 +253,10 @@ ] }, { - "textRaw": "crypto.pbkdf2(password, salt, iterations, keylen, callback)", + "textRaw": "crypto.pbkdf2(password, salt, iterations, keylen, [digest], callback)", "type": "method", "name": "pbkdf2", - "desc": "

    Asynchronous PBKDF2 applies pseudorandom function HMAC-SHA1 to derive\na key of given length from the given password, salt and iterations.\nThe callback gets two arguments (err, derivedKey).\n\n

    \n", + "desc": "

    Asynchronous PBKDF2 function. Applies the selected HMAC digest function\n(default: SHA1) to derive a key of the requested length from the password,\nsalt and number of iterations. The callback gets two arguments:\n(err, derivedKey).\n\n

    \n

    Example:\n\n

    \n
    crypto.pbkdf2('secret', 'salt', 4096, 512, 'sha256', function(err, key) {\n  if (err)\n    throw err;\n  console.log(key.toString('hex'));  // 'c5e478d...1469e50'\n});
    \n

    You can get a list of supported digest functions with\ncrypto.getHashes().\n\n

    \n", "signatures": [ { "params": [ @@ -254,6 +273,10 @@ "name": "keylen" }, { + "name": "digest", + "optional": true + }, + { "name": "callback" } ] @@ -261,7 +284,7 @@ ] }, { - "textRaw": "crypto.pbkdf2Sync(password, salt, iterations, keylen)", + "textRaw": "crypto.pbkdf2Sync(password, salt, iterations, keylen, [digest])", "type": "method", "name": "pbkdf2Sync", "desc": "

    Synchronous PBKDF2 function. Returns derivedKey or throws error.\n\n

    \n", @@ -279,6 +302,10 @@ }, { "name": "keylen" + }, + { + "name": "digest", + "optional": true } ] } diff -Nru nodejs-0.11.10/doc/api/crypto.markdown nodejs-0.11.11/doc/api/crypto.markdown --- nodejs-0.11.10/doc/api/crypto.markdown 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/doc/api/crypto.markdown 2014-01-29 01:29:56.000000000 +0000 @@ -12,6 +12,30 @@ decipher, sign and verify methods. +## crypto.setEngine(engine, [flags]) + +Load and set engine for some/all OpenSSL functions (selected by flags). + +`engine` could be either an id or a path to the to the engine's shared library. + +`flags` is optional and has `ENGINE_METHOD_ALL` value by default. It could take +one of or mix of following flags (defined in `constants` module): + +* `ENGINE_METHOD_RSA` +* `ENGINE_METHOD_DSA` +* `ENGINE_METHOD_DH` +* `ENGINE_METHOD_RAND` +* `ENGINE_METHOD_ECDH` +* `ENGINE_METHOD_ECDSA` +* `ENGINE_METHOD_CIPHERS` +* `ENGINE_METHOD_DIGESTS` +* `ENGINE_METHOD_STORE` +* `ENGINE_METHOD_PKEY_METH` +* `ENGINE_METHOD_PKEY_ASN1_METH` +* `ENGINE_METHOD_ALL` +* `ENGINE_METHOD_NONE` + + ## crypto.getCiphers() Returns an array with the names of the supported ciphers. @@ -463,13 +487,25 @@ /* alice_secret and bob_secret should be the same */ console.log(alice_secret == bob_secret); -## crypto.pbkdf2(password, salt, iterations, keylen, callback) +## crypto.pbkdf2(password, salt, iterations, keylen, [digest], callback) + +Asynchronous PBKDF2 function. Applies the selected HMAC digest function +(default: SHA1) to derive a key of the requested length from the password, +salt and number of iterations. The callback gets two arguments: +`(err, derivedKey)`. + +Example: + + crypto.pbkdf2('secret', 'salt', 4096, 512, 'sha256', function(err, key) { + if (err) + throw err; + console.log(key.toString('hex')); // 'c5e478d...1469e50' + }); -Asynchronous PBKDF2 applies pseudorandom function HMAC-SHA1 to derive -a key of given length from the given password, salt and iterations. -The callback gets two arguments `(err, derivedKey)`. +You can get a list of supported digest functions with +[crypto.getHashes()](#crypto_crypto_gethashes). -## crypto.pbkdf2Sync(password, salt, iterations, keylen) +## crypto.pbkdf2Sync(password, salt, iterations, keylen, [digest]) Synchronous PBKDF2 function. Returns derivedKey or throws error. diff -Nru nodejs-0.11.10/doc/api/debugger.html nodejs-0.11.11/doc/api/debugger.html --- nodejs-0.11.10/doc/api/debugger.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/debugger.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - Debugger Node.js v0.11.10 Manual & Documentation + Debugger Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -252,7 +252,7 @@

  • -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/api/dgram.html nodejs-0.11.11/doc/api/dgram.html --- nodejs-0.11.10/doc/api/dgram.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/dgram.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - UDP / Datagram Sockets Node.js v0.11.10 Manual & Documentation + UDP / Datagram Sockets Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -381,7 +381,7 @@

  • -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/api/dns.html nodejs-0.11.11/doc/api/dns.html --- nodejs-0.11.10/doc/api/dns.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/dns.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - DNS Node.js v0.11.10 Manual & Documentation + DNS Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -285,7 +285,7 @@

  • -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/api/documentation.html nodejs-0.11.11/doc/api/documentation.html --- nodejs-0.11.10/doc/api/documentation.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/documentation.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - About this Documentation Node.js v0.11.10 Manual & Documentation + About this Documentation Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -135,7 +135,7 @@

  • -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/api/domain.html nodejs-0.11.11/doc/api/domain.html --- nodejs-0.11.10/doc/api/domain.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/domain.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - Domain Node.js v0.11.10 Manual & Documentation + Domain Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -537,7 +537,7 @@

  • -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/api/events.html nodejs-0.11.11/doc/api/events.html --- nodejs-0.11.10/doc/api/events.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/events.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - Events Node.js v0.11.10 Manual & Documentation + Events Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -225,7 +225,7 @@

  • -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/api/fs.html nodejs-0.11.11/doc/api/fs.html --- nodejs-0.11.10/doc/api/fs.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/fs.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - File System Node.js v0.11.10 Manual & Documentation + File System Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -1032,7 +1032,7 @@

  • -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/api/globals.html nodejs-0.11.11/doc/api/globals.html --- nodejs-0.11.10/doc/api/globals.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/globals.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - Global Objects Node.js v0.11.10 Manual & Documentation + Global Objects Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -296,7 +296,7 @@

  • -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/api/http.html nodejs-0.11.11/doc/api/http.html --- nodejs-0.11.10/doc/api/http.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/http.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - HTTP Node.js v0.11.10 Manual & Documentation + HTTP Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -1271,7 +1271,7 @@

  • -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/api/https.html nodejs-0.11.11/doc/api/https.html --- nodejs-0.11.10/doc/api/https.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/https.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - HTTPS Node.js v0.11.10 Manual & Documentation + HTTPS Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -305,7 +305,7 @@

  • -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/api/index.html nodejs-0.11.11/doc/api/index.html --- nodejs-0.11.10/doc/api/index.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/index.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - Node.js v0.11.10 Manual & Documentation + Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -106,7 +106,7 @@

  • -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/api/modules.html nodejs-0.11.11/doc/api/modules.html --- nodejs-0.11.10/doc/api/modules.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/modules.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - Modules Node.js v0.11.10 Manual & Documentation + Modules Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -651,7 +651,7 @@

  • -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/api/net.html nodejs-0.11.11/doc/api/net.html --- nodejs-0.11.10/doc/api/net.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/net.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - net Node.js v0.11.10 Manual & Documentation + net Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -732,7 +732,7 @@

  • -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/api/os.html nodejs-0.11.11/doc/api/os.html --- nodejs-0.11.10/doc/api/os.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/os.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - os Node.js v0.11.10 Manual & Documentation + os Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -250,7 +250,7 @@

  • -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/api/path.html nodejs-0.11.11/doc/api/path.html --- nodejs-0.11.10/doc/api/path.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/path.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - Path Node.js v0.11.10 Manual & Documentation + Path Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -284,7 +284,7 @@

  • -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/api/process.html nodejs-0.11.11/doc/api/process.html --- nodejs-0.11.10/doc/api/process.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/process.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - process Node.js v0.11.10 Manual & Documentation + process Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -83,8 +83,8 @@

  • process.uptime()
  • process.hrtime()
  • Async Listeners
  • -
  • process.createAsyncListener(asyncListener[, callbacksObj[, storageValue]])
  • -
  • process.addAsyncListener(asyncListener[, callbacksObj[, storageValue]])
  • +
  • process.createAsyncListener(callbacksObj[, userData])
  • +
  • process.addAsyncListener(callbacksObj[, userData])
  • process.addAsyncListener(asyncListener)
  • process.removeAsyncListener(asyncListener)
  • @@ -245,9 +245,9 @@ SIGHUP is to terminate node, but once a listener has been installed its default behaviour will be removed.
  • SIGTERM is not supported on Windows, it can be listened on.
  • -
  • SIGINT is supported on all platforms, and can usually be generated with -CTRL+C (though this may be configurable). It is not generated when terminal -raw mode is enabled.
  • +
  • SIGINT from the terminal is supported on all platforms, and can usually be +generated with CTRL+C (though this may be configurable). It is not generated +when terminal raw mode is enabled.
  • SIGBREAK is delivered on Windows when CTRL+BREAK is pressed, on non-Windows platforms it can be listened on, but there is no way to send or generate it.
  • SIGWINCH is delivered when the console has been resized. On Windows, this will @@ -257,6 +257,13 @@ node on all platforms.
  • SIGSTOP cannot have a listener installed.
  • +

    Note that Windows does not support sending Signals, but node offers some +emulation with process.kill(), and child_process.kill(): +- Sending signal 0 can be used to search for the existence of a process +- Sending SIGINT, SIGTERM, and SIGKILL cause the unconditional exit of the + target process. + +

    process.stdout#

    A Writable Stream to stdout. @@ -580,7 +587,7 @@

    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'. -See kill(2) for more information. +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 @@ -783,92 +790,91 @@

    Stability: 1 - Experimental

    The AsyncListener API is the JavaScript interface for the AsyncWrap class which allows developers to be notified about key events in the lifetime of an asynchronous event. Node performs a lot of asynchronous -events internally, and significant use of this API will have a dramatic -performance impact on your application. +events internally, and significant use of this API may have a +significant performance impact on your application.

    -

    process.createAsyncListener(asyncListener[, callbacksObj[, storageValue]])#

    +

    process.createAsyncListener(callbacksObj[, userData])#

      -
    • asyncListener Function callback fired when an asynchronous event is -instantiated.
    • -
    • callbacksObj Object optional callbacks that will fire at specific -times in the lifetime of the asynchronous event.
    • -
    • storageValue Value a value that will be passed as the first argument -when the asyncListener callback is run, and to all subsequent callback.
    • +
    • callbacksObj Object Contains optional callbacks that will fire at +specific times in the life cycle of the asynchronous event.
    • +
    • userData Value a value that will be passed to all callbacks.

    Returns a constructed AsyncListener object.

    -

    To begin capturing asynchronous events pass the object to -process.addAsyncListener(). The same AsyncListener instance can -only be added once to the active queue, and subsequent attempts to add the -instance will be ignored. +

    To begin capturing asynchronous events pass either the callbacksObj or +and existing AsyncListener instance to process.addAsyncListener(). +The same AsyncListener instance can only be added once to the active +queue, and subsequent attempts to add the instance will be ignored.

    -

    To stop capturing pass the object to process.removeAsyncListener(). -This does not mean the AsyncListener previously added will stop -triggering callbacks. Once attached to an asynchronous event it will -persist with the lifetime of the asynchronous call stack. +

    To stop capturing pass the AsyncListener instance to +process.removeAsyncListener(). This does not mean the +AsyncListener previously added will stop triggering callbacks. Once +attached to an asynchronous event it will persist with the lifetime of the +asynchronous call stack.

    Explanation of function parameters: -

    -

    asyncListener(storageValue): A Function called when an asynchronous -event is instantiated. If a Value is returned then it will be attached -to the event and overwrite any value that had been passed to -process.createAsyncListener()'s storageValue argument. If an initial -storageValue was passed when created, then asyncListener() will -receive that as a function argument.

    callbacksObj: An Object which may contain three optional fields:

      -
    • before(context, storageValue): A Function that is called immediately +

    • create(userData): A Function called when an asynchronous +event is instantiated. If a Value is returned then it will be attached +to the event and overwrite any value that had been passed to +process.createAsyncListener()'s userData argument. If an initial +userData was passed when created, then create() will +receive that as a function argument.

      +
    • +
    • before(context, userData): A Function that is called immediately before the asynchronous callback is about to run. It will be passed both -the context (i.e. this) of the calling function and the storageValue -either returned from asyncListener or passed during construction (if +the context (i.e. this) of the calling function and the userData +either returned from create() or passed during construction (if either occurred).

    • -
    • after(context, storageValue): A Function called immediately after +

    • after(context, userData): A Function called immediately after the asynchronous event's callback has run. Note this will not be called if the callback throws and the error is not handled.

    • -
    • error(storageValue, error): A Function called if the event's -callback threw. If error returns true then Node will assume the error -has been properly handled and resume execution normally. When multiple -error() callbacks have been registered, only one of those callbacks -needs to return true for AsyncListener to accept that the error has -been handled.

      +
    • error(userData, error): A Function called if the event's +callback threw. If this registered callback returns true then Node will +assume the error has been properly handled and resume execution normally. +When multiple error() callbacks have been registered only one of +those callbacks needs to return true for AsyncListener to accept that +the error has been handled, but all error() callbacks will always be run.

    -

    storageValue: A Value (i.e. anything) that will be, by default, +

    userData: A Value (i.e. anything) that will be, by default, attached to all new event instances. This will be overwritten if a Value -is returned by asyncListener(). +is returned by create().

    -

    Here is an example of overwriting the storageValue: +

    Here is an example of overwriting the userData:

    -
    process.createAsyncListener(function listener(value) {
    -  // value === true
    -  return false;
    +
    process.createAsyncListener({
    +  create: function listener(value) {
    +    // value === true
    +    return false;
     }, {
       before: function before(context, value) {
         // value === false
       }
     }, true);

    Note: The EventEmitter, while used to emit status of an asynchronous -event, is not itself asynchronous. So asyncListener() will not fire when +event, is not itself asynchronous. So create() will not fire when an event is added, and before/after will not fire when emitted callbacks are called.

    -

    process.addAsyncListener(asyncListener[, callbacksObj[, storageValue]])#

    +

    process.addAsyncListener(callbacksObj[, userData])#

    process.addAsyncListener(asyncListener)#

    Returns a constructed AsyncListener object and immediately adds it to the listening queue to begin capturing asynchronous events. @@ -882,36 +888,32 @@

    Example usage for capturing errors:

    -
    var cntr = 0;
    -var key = process.addAsyncListener(function() {
    -  return { uid: cntr++ };
    -}, {
    +
    var fs = require('fs');
    +
    +var cntr = 0;
    +var key = process.addAsyncListener({
    +  create: function onCreate() {
    +    return { uid: cntr++ };
    +  },
       before: function onBefore(context, storage) {
    -    // Need to remove the listener while logging or will end up
    -    // with an infinite call loop.
    -    process.removeAsyncListener(key);
    -    console.log('uid: %s is about to run', storage.uid);
    -    process.addAsyncListener(key);
    +    // Write directly to stdout or we'll enter a recursive loop
    +    fs.writeSync(1, 'uid: ' + storage.uid + ' is about to run\n');
       },
       after: function onAfter(context, storage) {
    -    process.removeAsyncListener(key);
    -    console.log('uid: %s is about to run', storage.uid);
    -    process.addAsyncListener(key);
    +    fs.writeSync(1, 'uid: ' + storage.uid + ' is about to run\n');
       },
       error: function onError(storage, err) {
         // Handle known errors
    -    if (err.message === 'really, it\'s ok') {
    -      process.removeAsyncListener(key);
    -      console.log('handled error just threw:');
    -      console.log(err.stack);
    -      process.addAsyncListener(key);
    +    if (err.message === 'everything is fine') {
    +      fs.writeSync(1, 'handled error just threw:\n');
    +      fs.writeSync(1, err.stack + '\n');
           return true;
         }
       }
     });
     
     process.nextTick(function() {
    -  throw new Error('really, it\'s ok');
    +  throw new Error('everything is fine');
     });
     
     // Output:
    @@ -927,17 +929,20 @@
     

    Removes the AsyncListener from the listening queue.

    -

    Removing the AsyncListener from the queue does not mean asynchronous -events called during its execution scope will stop firing callbacks. Once -attached to an event it will persist for the entire asynchronous call -stack. For example: +

    Removing the AsyncListener from the active queue does not mean the +asyncListener callbacks will cease to fire on the events they've been +registered. Subsequently, any asynchronous events fired during the +execution of a callback will also have the same asyncListener callbacks +attached for future execution. For example:

    -
    var key = process.createAsyncListener(function asyncListener() {
    -  // To log we must stop listening or we'll enter infinite recursion.
    -  process.removeAsyncListener(key);
    -  console.log('You summoned me?');
    -  process.addAsyncListener(key);
    +
    var fs = require('fs');
    +
    +var key = process.createAsyncListener({
    +  create: function asyncListener() {
    +    // Write directly to stdout or we'll enter a recursive loop
    +    fs.writeSync(1, 'You summoned me?\n');
    +  }
     });
     
     // We want to begin capturing async events some time in the future.
    @@ -970,11 +975,13 @@
     stack itself. For example:
     
     

    -
    var key = process.createAsyncListener(function asyncListener() {
    -  // To log we must stop listening or we'll enter infinite recursion.
    -  process.removeAsyncListener(key);
    -  console.log('You summoned me?');
    -  process.addAsyncListener(key);
    +
    var fs = require('fs');
    +
    +var key = process.createAsyncListener({
    +  create: function asyncListener() {
    +    // Write directly to stdout or we'll enter a recursive loop
    +    fs.writeSync(1, 'You summoned me?\n');
    +  }
     });
     
     // We want to begin capturing async events some time in the future.
    @@ -1016,7 +1023,7 @@
                 
  • -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/api/process.json nodejs-0.11.11/doc/api/process.json --- nodejs-0.11.10/doc/api/process.json 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/process.json 2014-01-29 03:26:35.000000000 +0000 @@ -34,7 +34,7 @@ "textRaw": "Signal Events", "name": "SIGINT, SIGHUP, etc.", "type": "event", - "desc": "

    Emitted when the processes receives a signal. See sigaction(2) for a list of\nstandard POSIX signal names such as SIGINT, SIGHUP, etc.\n\n

    \n

    Example of listening for SIGINT:\n\n

    \n
    // Start reading from stdin so we don't exit.\nprocess.stdin.resume();\n\nprocess.on('SIGINT', function() {\n  console.log('Got SIGINT.  Press Control-D to exit.');\n});
    \n

    An easy way to send the SIGINT signal is with Control-C in most terminal\nprograms.\n\n

    \n

    Note:\n\n

    \n
      \n
    • SIGUSR1 is reserved by node.js to start the debugger. It's possible to\ninstall a listener but that won't stop the debugger from starting.
    • \n
    • SIGTERM and SIGINT have default handlers on non-Windows platforms that resets\nthe terminal mode before exiting with code 128 + signal number. If one of\nthese signals has a listener installed, its default behaviour will be removed\n(node will no longer exit).
    • \n
    • SIGPIPE is ignored by default, it can have a listener installed.
    • \n
    • SIGHUP is generated on Windows when the console window is closed, and on other\nplatforms under various similar conditions, see signal(7). It can have a\nlistener installed, however node will be unconditionally terminated by Windows\nabout 10 seconds later. On non-Windows platforms, the default behaviour of\nSIGHUP is to terminate node, but once a listener has been installed its\ndefault behaviour will be removed.
    • \n
    • SIGTERM is not supported on Windows, it can be listened on.
    • \n
    • SIGINT is supported on all platforms, and can usually be generated with\nCTRL+C (though this may be configurable). It is not generated when terminal\nraw mode is enabled.
    • \n
    • SIGBREAK is delivered on Windows when CTRL+BREAK is pressed, on non-Windows\nplatforms it can be listened on, but there is no way to send or generate it.
    • \n
    • SIGWINCH is delivered when the console has been resized. On Windows, this will\nonly happen on write to the console when the cursor is being moved, or when a\nreadable tty is used in raw mode.
    • \n
    • SIGKILL cannot have a listener installed, it will unconditionally terminate\nnode on all platforms.
    • \n
    • SIGSTOP cannot have a listener installed.
    • \n
    \n", + "desc": "

    Emitted when the processes receives a signal. See sigaction(2) for a list of\nstandard POSIX signal names such as SIGINT, SIGHUP, etc.\n\n

    \n

    Example of listening for SIGINT:\n\n

    \n
    // Start reading from stdin so we don't exit.\nprocess.stdin.resume();\n\nprocess.on('SIGINT', function() {\n  console.log('Got SIGINT.  Press Control-D to exit.');\n});
    \n

    An easy way to send the SIGINT signal is with Control-C in most terminal\nprograms.\n\n

    \n

    Note:\n\n

    \n
      \n
    • SIGUSR1 is reserved by node.js to start the debugger. It's possible to\ninstall a listener but that won't stop the debugger from starting.
    • \n
    • SIGTERM and SIGINT have default handlers on non-Windows platforms that resets\nthe terminal mode before exiting with code 128 + signal number. If one of\nthese signals has a listener installed, its default behaviour will be removed\n(node will no longer exit).
    • \n
    • SIGPIPE is ignored by default, it can have a listener installed.
    • \n
    • SIGHUP is generated on Windows when the console window is closed, and on other\nplatforms under various similar conditions, see signal(7). It can have a\nlistener installed, however node will be unconditionally terminated by Windows\nabout 10 seconds later. On non-Windows platforms, the default behaviour of\nSIGHUP is to terminate node, but once a listener has been installed its\ndefault behaviour will be removed.
    • \n
    • SIGTERM is not supported on Windows, it can be listened on.
    • \n
    • SIGINT from the terminal is supported on all platforms, and can usually be\ngenerated with CTRL+C (though this may be configurable). It is not generated\nwhen terminal raw mode is enabled.
    • \n
    • SIGBREAK is delivered on Windows when CTRL+BREAK is pressed, on non-Windows\nplatforms it can be listened on, but there is no way to send or generate it.
    • \n
    • SIGWINCH is delivered when the console has been resized. On Windows, this will\nonly happen on write to the console when the cursor is being moved, or when a\nreadable tty is used in raw mode.
    • \n
    • SIGKILL cannot have a listener installed, it will unconditionally terminate\nnode on all platforms.
    • \n
    • SIGSTOP cannot have a listener installed.
    • \n
    \n

    Note that Windows does not support sending Signals, but node offers some\nemulation with process.kill(), and child_process.kill():\n- Sending signal 0 can be used to search for the existence of a process\n- Sending SIGINT, SIGTERM, and SIGKILL cause the unconditional exit of the\n target process.\n\n

    \n", "params": [] } ], @@ -269,7 +269,7 @@ "textRaw": "process.kill(pid, [signal])", "type": "method", "name": "kill", - "desc": "

    Send a signal to a process. pid is the process id and signal is the\nstring describing the signal to send. Signal names are strings like\n'SIGINT' or 'SIGHUP'. If omitted, the signal will be 'SIGTERM'.\nSee kill(2) for more information.\n\n

    \n

    Will throw an error if target does not exist, and as a special case, a signal of\n0 can be used to test for the existence of a process.\n\n

    \n

    Note that just because the name of this function is process.kill, it is\nreally just a signal sender, like the kill system call. The signal sent\nmay do something other than kill the target process.\n\n

    \n

    Example of sending a signal to yourself:\n\n

    \n
    process.on('SIGHUP', function() {\n  console.log('Got SIGHUP signal.');\n});\n\nsetTimeout(function() {\n  console.log('Exiting.');\n  process.exit(0);\n}, 100);\n\nprocess.kill(process.pid, 'SIGHUP');
    \n

    Note: When SIGUSR1 is received by Node.js it starts the debugger, see\nSignal Events.\n\n

    \n", + "desc": "

    Send a signal to a process. pid is the process id and signal is the\nstring describing the signal to send. Signal names are strings like\n'SIGINT' or 'SIGHUP'. If omitted, the signal will be 'SIGTERM'.\nSee Signal Events and kill(2) for more information.\n\n

    \n

    Will throw an error if target does not exist, and as a special case, a signal of\n0 can be used to test for the existence of a process.\n\n

    \n

    Note that just because the name of this function is process.kill, it is\nreally just a signal sender, like the kill system call. The signal sent\nmay do something other than kill the target process.\n\n

    \n

    Example of sending a signal to yourself:\n\n

    \n
    process.on('SIGHUP', function() {\n  console.log('Got SIGHUP signal.');\n});\n\nsetTimeout(function() {\n  console.log('Exiting.');\n  process.exit(0);\n}, 100);\n\nprocess.kill(process.pid, 'SIGHUP');
    \n

    Note: When SIGUSR1 is received by Node.js it starts the debugger, see\nSignal Events.\n\n

    \n", "signatures": [ { "params": [ @@ -358,53 +358,44 @@ ] }, { - "textRaw": "process.createAsyncListener(asyncListener[, callbacksObj[, storageValue]])", + "textRaw": "process.createAsyncListener(callbacksObj[, userData])", "type": "method", "name": "createAsyncListener", "signatures": [ { "params": [ { - "textRaw": "`asyncListener` {Function} callback fired when an asynchronous event is instantiated. ", - "name": "asyncListener", - "type": "Function", - "desc": "callback fired when an asynchronous event is instantiated." - }, - { - "textRaw": "`callbacksObj` {Object} optional callbacks that will fire at specific times in the lifetime of the asynchronous event. ", + "textRaw": "`callbacksObj` {Object} Contains optional callbacks that will fire at specific times in the life cycle of the asynchronous event. ", "name": "callbacksObj", "type": "Object", - "desc": "optional callbacks that will fire at specific times in the lifetime of the asynchronous event." + "desc": "Contains optional callbacks that will fire at specific times in the life cycle of the asynchronous event." }, { - "textRaw": "`storageValue` {Value} a value that will be passed as the first argument when the `asyncListener` callback is run, and to all subsequent callback. ", - "name": "storageValue", + "textRaw": "`userData` {Value} a value that will be passed to all callbacks. ", + "name": "userData", "type": "Value", - "desc": "a value that will be passed as the first argument when the `asyncListener` callback is run, and to all subsequent callback." + "desc": "a value that will be passed to all callbacks." } ] }, { "params": [ { - "name": "asyncListener[" - }, - { "name": "callbacksObj[" }, { - "name": "storageValue" + "name": "userData" } ] } ], - "desc": "

    Returns a constructed AsyncListener object.\n\n

    \n

    To begin capturing asynchronous events pass the object to\n[process.addAsyncListener()][]. The same AsyncListener instance can\nonly be added once to the active queue, and subsequent attempts to add the\ninstance will be ignored.\n\n

    \n

    To stop capturing pass the object to [process.removeAsyncListener()][].\nThis does not mean the AsyncListener previously added will stop\ntriggering callbacks. Once attached to an asynchronous event it will\npersist with the lifetime of the asynchronous call stack.\n\n

    \n

    Explanation of function parameters:\n\n

    \n

    asyncListener(storageValue): A Function called when an asynchronous\nevent is instantiated. If a Value is returned then it will be attached\nto the event and overwrite any value that had been passed to\nprocess.createAsyncListener()'s storageValue argument. If an initial\nstorageValue was passed when created, then asyncListener() will\nreceive that as a function argument.\n\n

    \n

    callbacksObj: An Object which may contain three optional fields:\n\n

    \n
      \n
    • before(context, storageValue): A Function that is called immediately\nbefore the asynchronous callback is about to run. It will be passed both\nthe context (i.e. this) of the calling function and the storageValue\neither returned from asyncListener or passed during construction (if\neither occurred).

      \n
    • \n
    • after(context, storageValue): A Function called immediately after\nthe asynchronous event's callback has run. Note this will not be called\nif the callback throws and the error is not handled.

      \n
    • \n
    • error(storageValue, error): A Function called if the event's\ncallback threw. If error returns true then Node will assume the error\nhas been properly handled and resume execution normally. When multiple\nerror() callbacks have been registered, only one of those callbacks\nneeds to return true for AsyncListener to accept that the error has\nbeen handled.

      \n
    • \n
    \n

    storageValue: A Value (i.e. anything) that will be, by default,\nattached to all new event instances. This will be overwritten if a Value\nis returned by asyncListener().\n\n

    \n

    Here is an example of overwriting the storageValue:\n\n

    \n
    process.createAsyncListener(function listener(value) {\n  // value === true\n  return false;\n}, {\n  before: function before(context, value) {\n    // value === false\n  }\n}, true);
    \n

    Note: The [EventEmitter][], while used to emit status of an asynchronous\nevent, is not itself asynchronous. So asyncListener() will not fire when\nan event is added, and before/after will not fire when emitted\ncallbacks are called.\n\n\n

    \n" + "desc": "

    Returns a constructed AsyncListener object.\n\n

    \n

    To begin capturing asynchronous events pass either the callbacksObj or\nand existing AsyncListener instance to [process.addAsyncListener()][].\nThe same AsyncListener instance can only be added once to the active\nqueue, and subsequent attempts to add the instance will be ignored.\n\n

    \n

    To stop capturing pass the AsyncListener instance to\n[process.removeAsyncListener()][]. This does not mean the\nAsyncListener previously added will stop triggering callbacks. Once\nattached to an asynchronous event it will persist with the lifetime of the\nasynchronous call stack.\n\n

    \n

    Explanation of function parameters:\n\n\n

    \n

    callbacksObj: An Object which may contain three optional fields:\n\n

    \n
      \n
    • create(userData): A Function called when an asynchronous\nevent is instantiated. If a Value is returned then it will be attached\nto the event and overwrite any value that had been passed to\nprocess.createAsyncListener()'s userData argument. If an initial\nuserData was passed when created, then create() will\nreceive that as a function argument.

      \n
    • \n
    • before(context, userData): A Function that is called immediately\nbefore the asynchronous callback is about to run. It will be passed both\nthe context (i.e. this) of the calling function and the userData\neither returned from create() or passed during construction (if\neither occurred).

      \n
    • \n
    • after(context, userData): A Function called immediately after\nthe asynchronous event's callback has run. Note this will not be called\nif the callback throws and the error is not handled.

      \n
    • \n
    • error(userData, error): A Function called if the event's\ncallback threw. If this registered callback returns true then Node will\nassume the error has been properly handled and resume execution normally.\nWhen multiple error() callbacks have been registered only one of\nthose callbacks needs to return true for AsyncListener to accept that\nthe error has been handled, but all error() callbacks will always be run.

      \n
    • \n
    \n

    userData: A Value (i.e. anything) that will be, by default,\nattached to all new event instances. This will be overwritten if a Value\nis returned by create().\n\n

    \n

    Here is an example of overwriting the userData:\n\n

    \n
    process.createAsyncListener({\n  create: function listener(value) {\n    // value === true\n    return false;\n}, {\n  before: function before(context, value) {\n    // value === false\n  }\n}, true);
    \n

    Note: The [EventEmitter][], while used to emit status of an asynchronous\nevent, is not itself asynchronous. So create() will not fire when\nan event is added, and before/after will not fire when emitted\ncallbacks are called.\n\n\n

    \n" }, { - "textRaw": "process.addAsyncListener(asyncListener[, callbacksObj[, storageValue]])", + "textRaw": "process.addAsyncListener(callbacksObj[, userData])", "type": "method", "name": "addAsyncListener", - "desc": "

    Returns a constructed AsyncListener object and immediately adds it to\nthe listening queue to begin capturing asynchronous events.\n\n

    \n

    Function parameters can either be the same as\n[process.createAsyncListener()][], or a constructed AsyncListener\nobject.\n\n

    \n

    Example usage for capturing errors:\n\n

    \n
    var cntr = 0;\nvar key = process.addAsyncListener(function() {\n  return { uid: cntr++ };\n}, {\n  before: function onBefore(context, storage) {\n    // Need to remove the listener while logging or will end up\n    // with an infinite call loop.\n    process.removeAsyncListener(key);\n    console.log('uid: %s is about to run', storage.uid);\n    process.addAsyncListener(key);\n  },\n  after: function onAfter(context, storage) {\n    process.removeAsyncListener(key);\n    console.log('uid: %s is about to run', storage.uid);\n    process.addAsyncListener(key);\n  },\n  error: function onError(storage, err) {\n    // Handle known errors\n    if (err.message === 'really, it\\'s ok') {\n      process.removeAsyncListener(key);\n      console.log('handled error just threw:');\n      console.log(err.stack);\n      process.addAsyncListener(key);\n      return true;\n    }\n  }\n});\n\nprocess.nextTick(function() {\n  throw new Error('really, it\\'s ok');\n});\n\n// Output:\n// uid: 0 is about to run\n// handled error just threw:\n// Error: really, it's ok\n//     at /tmp/test2.js:27:9\n//     at process._tickCallback (node.js:583:11)\n//     at Function.Module.runMain (module.js:492:11)\n//     at startup (node.js:123:16)\n//     at node.js:1012:3
    \n", + "desc": "

    Returns a constructed AsyncListener object and immediately adds it to\nthe listening queue to begin capturing asynchronous events.\n\n

    \n

    Function parameters can either be the same as\n[process.createAsyncListener()][], or a constructed AsyncListener\nobject.\n\n

    \n

    Example usage for capturing errors:\n\n

    \n
    var fs = require('fs');\n\nvar cntr = 0;\nvar key = process.addAsyncListener({\n  create: function onCreate() {\n    return { uid: cntr++ };\n  },\n  before: function onBefore(context, storage) {\n    // Write directly to stdout or we'll enter a recursive loop\n    fs.writeSync(1, 'uid: ' + storage.uid + ' is about to run\\n');\n  },\n  after: function onAfter(context, storage) {\n    fs.writeSync(1, 'uid: ' + storage.uid + ' is about to run\\n');\n  },\n  error: function onError(storage, err) {\n    // Handle known errors\n    if (err.message === 'everything is fine') {\n      fs.writeSync(1, 'handled error just threw:\\n');\n      fs.writeSync(1, err.stack + '\\n');\n      return true;\n    }\n  }\n});\n\nprocess.nextTick(function() {\n  throw new Error('everything is fine');\n});\n\n// Output:\n// uid: 0 is about to run\n// handled error just threw:\n// Error: really, it's ok\n//     at /tmp/test2.js:27:9\n//     at process._tickCallback (node.js:583:11)\n//     at Function.Module.runMain (module.js:492:11)\n//     at startup (node.js:123:16)\n//     at node.js:1012:3
    \n", "signatures": [ { "params": [ @@ -416,13 +407,10 @@ { "params": [ { - "name": "asyncListener[" - }, - { "name": "callbacksObj[" }, { - "name": "storageValue" + "name": "userData" } ] } @@ -432,7 +420,7 @@ "textRaw": "process.addAsyncListener(asyncListener)", "type": "method", "name": "addAsyncListener", - "desc": "

    Returns a constructed AsyncListener object and immediately adds it to\nthe listening queue to begin capturing asynchronous events.\n\n

    \n

    Function parameters can either be the same as\n[process.createAsyncListener()][], or a constructed AsyncListener\nobject.\n\n

    \n

    Example usage for capturing errors:\n\n

    \n
    var cntr = 0;\nvar key = process.addAsyncListener(function() {\n  return { uid: cntr++ };\n}, {\n  before: function onBefore(context, storage) {\n    // Need to remove the listener while logging or will end up\n    // with an infinite call loop.\n    process.removeAsyncListener(key);\n    console.log('uid: %s is about to run', storage.uid);\n    process.addAsyncListener(key);\n  },\n  after: function onAfter(context, storage) {\n    process.removeAsyncListener(key);\n    console.log('uid: %s is about to run', storage.uid);\n    process.addAsyncListener(key);\n  },\n  error: function onError(storage, err) {\n    // Handle known errors\n    if (err.message === 'really, it\\'s ok') {\n      process.removeAsyncListener(key);\n      console.log('handled error just threw:');\n      console.log(err.stack);\n      process.addAsyncListener(key);\n      return true;\n    }\n  }\n});\n\nprocess.nextTick(function() {\n  throw new Error('really, it\\'s ok');\n});\n\n// Output:\n// uid: 0 is about to run\n// handled error just threw:\n// Error: really, it's ok\n//     at /tmp/test2.js:27:9\n//     at process._tickCallback (node.js:583:11)\n//     at Function.Module.runMain (module.js:492:11)\n//     at startup (node.js:123:16)\n//     at node.js:1012:3
    \n", + "desc": "

    Returns a constructed AsyncListener object and immediately adds it to\nthe listening queue to begin capturing asynchronous events.\n\n

    \n

    Function parameters can either be the same as\n[process.createAsyncListener()][], or a constructed AsyncListener\nobject.\n\n

    \n

    Example usage for capturing errors:\n\n

    \n
    var fs = require('fs');\n\nvar cntr = 0;\nvar key = process.addAsyncListener({\n  create: function onCreate() {\n    return { uid: cntr++ };\n  },\n  before: function onBefore(context, storage) {\n    // Write directly to stdout or we'll enter a recursive loop\n    fs.writeSync(1, 'uid: ' + storage.uid + ' is about to run\\n');\n  },\n  after: function onAfter(context, storage) {\n    fs.writeSync(1, 'uid: ' + storage.uid + ' is about to run\\n');\n  },\n  error: function onError(storage, err) {\n    // Handle known errors\n    if (err.message === 'everything is fine') {\n      fs.writeSync(1, 'handled error just threw:\\n');\n      fs.writeSync(1, err.stack + '\\n');\n      return true;\n    }\n  }\n});\n\nprocess.nextTick(function() {\n  throw new Error('everything is fine');\n});\n\n// Output:\n// uid: 0 is about to run\n// handled error just threw:\n// Error: really, it's ok\n//     at /tmp/test2.js:27:9\n//     at process._tickCallback (node.js:583:11)\n//     at Function.Module.runMain (module.js:492:11)\n//     at startup (node.js:123:16)\n//     at node.js:1012:3
    \n", "signatures": [ { "params": [ @@ -447,7 +435,7 @@ "textRaw": "process.removeAsyncListener(asyncListener)", "type": "method", "name": "removeAsyncListener", - "desc": "

    Removes the AsyncListener from the listening queue.\n\n

    \n

    Removing the AsyncListener from the queue does not mean asynchronous\nevents called during its execution scope will stop firing callbacks. Once\nattached to an event it will persist for the entire asynchronous call\nstack. For example:\n\n

    \n
    var key = process.createAsyncListener(function asyncListener() {\n  // To log we must stop listening or we'll enter infinite recursion.\n  process.removeAsyncListener(key);\n  console.log('You summoned me?');\n  process.addAsyncListener(key);\n});\n\n// We want to begin capturing async events some time in the future.\nsetTimeout(function() {\n  process.addAsyncListener(key);\n\n  // Perform a few additional async events.\n  setTimeout(function() {\n    setImmediate(function() {\n      process.nextTick(function() { });\n    });\n  });\n\n  // Removing the listener doesn't mean to stop capturing events that\n  // have already been added.\n  process.removeAsyncListener(key);\n}, 100);\n\n// Output:\n// You summoned me?\n// You summoned me?\n// You summoned me?\n// You summoned me?
    \n

    The fact that we logged 4 asynchronous events is an implementation detail\nof Node's [Timers][].\n\n

    \n

    To stop capturing from a specific asynchronous event stack\nprocess.removeAsyncListener() must be called from within the call\nstack itself. For example:\n\n

    \n
    var key = process.createAsyncListener(function asyncListener() {\n  // To log we must stop listening or we'll enter infinite recursion.\n  process.removeAsyncListener(key);\n  console.log('You summoned me?');\n  process.addAsyncListener(key);\n});\n\n// We want to begin capturing async events some time in the future.\nsetTimeout(function() {\n  process.addAsyncListener(key);\n\n  // Perform a few additional async events.\n  setImmediate(function() {\n    // Stop capturing from this call stack.\n    process.removeAsyncListener(key);\n\n    process.nextTick(function() { });\n  });\n}, 100);\n\n// Output:\n// You summoned me?
    \n

    The user must be explicit and always pass the AsyncListener they wish\nto remove. It is not possible to simply remove all listeners at once.\n\n\n

    \n", + "desc": "

    Removes the AsyncListener from the listening queue.\n\n

    \n

    Removing the AsyncListener from the active queue does not mean the\nasyncListener callbacks will cease to fire on the events they've been\nregistered. Subsequently, any asynchronous events fired during the\nexecution of a callback will also have the same asyncListener callbacks\nattached for future execution. For example:\n\n

    \n
    var fs = require('fs');\n\nvar key = process.createAsyncListener({\n  create: function asyncListener() {\n    // Write directly to stdout or we'll enter a recursive loop\n    fs.writeSync(1, 'You summoned me?\\n');\n  }\n});\n\n// We want to begin capturing async events some time in the future.\nsetTimeout(function() {\n  process.addAsyncListener(key);\n\n  // Perform a few additional async events.\n  setTimeout(function() {\n    setImmediate(function() {\n      process.nextTick(function() { });\n    });\n  });\n\n  // Removing the listener doesn't mean to stop capturing events that\n  // have already been added.\n  process.removeAsyncListener(key);\n}, 100);\n\n// Output:\n// You summoned me?\n// You summoned me?\n// You summoned me?\n// You summoned me?
    \n

    The fact that we logged 4 asynchronous events is an implementation detail\nof Node's [Timers][].\n\n

    \n

    To stop capturing from a specific asynchronous event stack\nprocess.removeAsyncListener() must be called from within the call\nstack itself. For example:\n\n

    \n
    var fs = require('fs');\n\nvar key = process.createAsyncListener({\n  create: function asyncListener() {\n    // Write directly to stdout or we'll enter a recursive loop\n    fs.writeSync(1, 'You summoned me?\\n');\n  }\n});\n\n// We want to begin capturing async events some time in the future.\nsetTimeout(function() {\n  process.addAsyncListener(key);\n\n  // Perform a few additional async events.\n  setImmediate(function() {\n    // Stop capturing from this call stack.\n    process.removeAsyncListener(key);\n\n    process.nextTick(function() { });\n  });\n}, 100);\n\n// Output:\n// You summoned me?
    \n

    The user must be explicit and always pass the AsyncListener they wish\nto remove. It is not possible to simply remove all listeners at once.\n\n\n

    \n", "signatures": [ { "params": [ @@ -468,7 +456,7 @@ "type": "misc", "stability": 1, "stabilityText": "Experimental", - "desc": "

    The AsyncListener API is the JavaScript interface for the AsyncWrap\nclass which allows developers to be notified about key events in the\nlifetime of an asynchronous event. Node performs a lot of asynchronous\nevents internally, and significant use of this API will have a dramatic\nperformance impact on your application.\n\n\n

    \n" + "desc": "

    The AsyncListener API is the JavaScript interface for the AsyncWrap\nclass which allows developers to be notified about key events in the\nlifetime of an asynchronous event. Node performs a lot of asynchronous\nevents internally, and significant use of this API may have a\nsignificant performance impact on your application.\n\n\n

    \n" } ] } diff -Nru nodejs-0.11.10/doc/api/process.markdown nodejs-0.11.11/doc/api/process.markdown --- nodejs-0.11.10/doc/api/process.markdown 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/doc/api/process.markdown 2014-01-29 01:29:56.000000000 +0000 @@ -140,9 +140,9 @@ `SIGHUP` is to terminate node, but once a listener has been installed its default behaviour will be removed. - `SIGTERM` is not supported on Windows, it can be listened on. -- `SIGINT` is supported on all platforms, and can usually be generated with - `CTRL+C` (though this may be configurable). It is not generated when terminal - raw mode is enabled. +- `SIGINT` from the terminal is supported on all platforms, and can usually be + generated with `CTRL+C` (though this may be configurable). It is not generated + when terminal raw mode is enabled. - `SIGBREAK` is delivered on Windows when `CTRL+BREAK` is pressed, on non-Windows platforms it can be listened on, but there is no way to send or generate it. - `SIGWINCH` is delivered when the console has been resized. On Windows, this will @@ -152,6 +152,12 @@ node on all platforms. - `SIGSTOP` cannot have a listener installed. +Note that Windows does not support sending Signals, but node offers some +emulation with `process.kill()`, and `child_process.kill()`: +- Sending signal `0` can be used to search for the existence of a process +- Sending `SIGINT`, `SIGTERM`, and `SIGKILL` cause the unconditional exit of the + target process. + ## process.stdout A `Writable Stream` to `stdout`. @@ -483,7 +489,7 @@ 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'. -See kill(2) for more information. +See [Signal Events](#process_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. @@ -688,68 +694,68 @@ The `AsyncListener` API is the JavaScript interface for the `AsyncWrap` class which allows developers to be notified about key events in the lifetime of an asynchronous event. Node performs a lot of asynchronous -events internally, and significant use of this API will have a **dramatic -performance impact** on your application. +events internally, and significant use of this API may have a +**significant performance impact** on your application. -## process.createAsyncListener(asyncListener[, callbacksObj[, storageValue]]) +## process.createAsyncListener(callbacksObj[, userData]) -* `asyncListener` {Function} callback fired when an asynchronous event is -instantiated. -* `callbacksObj` {Object} optional callbacks that will fire at specific -times in the lifetime of the asynchronous event. -* `storageValue` {Value} a value that will be passed as the first argument -when the `asyncListener` callback is run, and to all subsequent callback. +* `callbacksObj` {Object} Contains optional callbacks that will fire at +specific times in the life cycle of the asynchronous event. +* `userData` {Value} a value that will be passed to all callbacks. Returns a constructed `AsyncListener` object. -To begin capturing asynchronous events pass the object to -[`process.addAsyncListener()`][]. The same `AsyncListener` instance can -only be added once to the active queue, and subsequent attempts to add the -instance will be ignored. - -To stop capturing pass the object to [`process.removeAsyncListener()`][]. -This does _not_ mean the `AsyncListener` previously added will stop -triggering callbacks. Once attached to an asynchronous event it will -persist with the lifetime of the asynchronous call stack. +To begin capturing asynchronous events pass either the `callbacksObj` or +and existing `AsyncListener` instance to [`process.addAsyncListener()`][]. +The same `AsyncListener` instance can only be added once to the active +queue, and subsequent attempts to add the instance will be ignored. + +To stop capturing pass the `AsyncListener` instance to +[`process.removeAsyncListener()`][]. This does _not_ mean the +`AsyncListener` previously added will stop triggering callbacks. Once +attached to an asynchronous event it will persist with the lifetime of the +asynchronous call stack. Explanation of function parameters: -`asyncListener(storageValue)`: A `Function` called when an asynchronous + +`callbacksObj`: An `Object` which may contain three optional fields: + +* `create(userData)`: A `Function` called when an asynchronous event is instantiated. If a `Value` is returned then it will be attached to the event and overwrite any value that had been passed to -`process.createAsyncListener()`'s `storageValue` argument. If an initial -`storageValue` was passed when created, then `asyncListener()` will +`process.createAsyncListener()`'s `userData` argument. If an initial +`userData` was passed when created, then `create()` will receive that as a function argument. -`callbacksObj`: An `Object` which may contain three optional fields: - -* `before(context, storageValue)`: A `Function` that is called immediately +* `before(context, userData)`: A `Function` that is called immediately before the asynchronous callback is about to run. It will be passed both -the `context` (i.e. `this`) of the calling function and the `storageValue` -either returned from `asyncListener` or passed during construction (if +the `context` (i.e. `this`) of the calling function and the `userData` +either returned from `create()` or passed during construction (if either occurred). -* `after(context, storageValue)`: A `Function` called immediately after +* `after(context, userData)`: A `Function` called immediately after the asynchronous event's callback has run. Note this will not be called if the callback throws and the error is not handled. -* `error(storageValue, error)`: A `Function` called if the event's -callback threw. If `error` returns `true` then Node will assume the error -has been properly handled and resume execution normally. When multiple -`error()` callbacks have been registered, only **one** of those callbacks -needs to return `true` for `AsyncListener` to accept that the error has -been handled. +* `error(userData, error)`: A `Function` called if the event's +callback threw. If this registered callback returns `true` then Node will +assume the error has been properly handled and resume execution normally. +When multiple `error()` callbacks have been registered only **one** of +those callbacks needs to return `true` for `AsyncListener` to accept that +the error has been handled, but all `error()` callbacks will always be run. -`storageValue`: A `Value` (i.e. anything) that will be, by default, +`userData`: A `Value` (i.e. anything) that will be, by default, attached to all new event instances. This will be overwritten if a `Value` -is returned by `asyncListener()`. +is returned by `create()`. -Here is an example of overwriting the `storageValue`: +Here is an example of overwriting the `userData`: - process.createAsyncListener(function listener(value) { - // value === true - return false; + process.createAsyncListener({ + create: function listener(value) { + // value === true + return false; }, { before: function before(context, value) { // value === false @@ -757,12 +763,12 @@ }, true); **Note:** The [EventEmitter][], while used to emit status of an asynchronous -event, is not itself asynchronous. So `asyncListener()` will not fire when +event, is not itself asynchronous. So `create()` will not fire when an event is added, and `before`/`after` will not fire when emitted callbacks are called. -## process.addAsyncListener(asyncListener[, callbacksObj[, storageValue]]) +## process.addAsyncListener(callbacksObj[, userData]) ## process.addAsyncListener(asyncListener) Returns a constructed `AsyncListener` object and immediately adds it to @@ -774,36 +780,32 @@ Example usage for capturing errors: + var fs = require('fs'); + var cntr = 0; - var key = process.addAsyncListener(function() { - return { uid: cntr++ }; - }, { + var key = process.addAsyncListener({ + create: function onCreate() { + return { uid: cntr++ }; + }, before: function onBefore(context, storage) { - // Need to remove the listener while logging or will end up - // with an infinite call loop. - process.removeAsyncListener(key); - console.log('uid: %s is about to run', storage.uid); - process.addAsyncListener(key); + // Write directly to stdout or we'll enter a recursive loop + fs.writeSync(1, 'uid: ' + storage.uid + ' is about to run\n'); }, after: function onAfter(context, storage) { - process.removeAsyncListener(key); - console.log('uid: %s is about to run', storage.uid); - process.addAsyncListener(key); + fs.writeSync(1, 'uid: ' + storage.uid + ' is about to run\n'); }, error: function onError(storage, err) { // Handle known errors - if (err.message === 'really, it\'s ok') { - process.removeAsyncListener(key); - console.log('handled error just threw:'); - console.log(err.stack); - process.addAsyncListener(key); + if (err.message === 'everything is fine') { + fs.writeSync(1, 'handled error just threw:\n'); + fs.writeSync(1, err.stack + '\n'); return true; } } }); process.nextTick(function() { - throw new Error('really, it\'s ok'); + throw new Error('everything is fine'); }); // Output: @@ -820,16 +822,19 @@ Removes the `AsyncListener` from the listening queue. -Removing the `AsyncListener` from the queue does _not_ mean asynchronous -events called during its execution scope will stop firing callbacks. Once -attached to an event it will persist for the entire asynchronous call -stack. For example: - - var key = process.createAsyncListener(function asyncListener() { - // To log we must stop listening or we'll enter infinite recursion. - process.removeAsyncListener(key); - console.log('You summoned me?'); - process.addAsyncListener(key); +Removing the `AsyncListener` from the active queue does _not_ mean the +`asyncListener` callbacks will cease to fire on the events they've been +registered. Subsequently, any asynchronous events fired during the +execution of a callback will also have the same `asyncListener` callbacks +attached for future execution. For example: + + var fs = require('fs'); + + var key = process.createAsyncListener({ + create: function asyncListener() { + // Write directly to stdout or we'll enter a recursive loop + fs.writeSync(1, 'You summoned me?\n'); + } }); // We want to begin capturing async events some time in the future. @@ -861,11 +866,13 @@ `process.removeAsyncListener()` must be called from within the call stack itself. For example: - var key = process.createAsyncListener(function asyncListener() { - // To log we must stop listening or we'll enter infinite recursion. - process.removeAsyncListener(key); - console.log('You summoned me?'); - process.addAsyncListener(key); + var fs = require('fs'); + + var key = process.createAsyncListener({ + create: function asyncListener() { + // Write directly to stdout or we'll enter a recursive loop + fs.writeSync(1, 'You summoned me?\n'); + } }); // We want to begin capturing async events some time in the future. diff -Nru nodejs-0.11.10/doc/api/punycode.html nodejs-0.11.11/doc/api/punycode.html --- nodejs-0.11.10/doc/api/punycode.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/punycode.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - punycode Node.js v0.11.10 Manual & Documentation + punycode Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -141,7 +141,7 @@

  • -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/api/querystring.html nodejs-0.11.11/doc/api/querystring.html --- nodejs-0.11.10/doc/api/querystring.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/querystring.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - Query String Node.js v0.11.10 Manual & Documentation + Query String Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -124,7 +124,7 @@

  • -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/api/readline.html nodejs-0.11.11/doc/api/readline.html --- nodejs-0.11.10/doc/api/readline.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/readline.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - Readline Node.js v0.11.10 Manual & Documentation + Readline Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -68,6 +68,10 @@

  • Example: Tiny CLI
  • +
  • readline.cursorTo(stream, x, y)
  • +
  • readline.moveCursor(stream, dx, dy)
  • +
  • readline.clearLine(stream, dir)
  • +
  • readline.clearScreenDown(stream)
  • @@ -116,7 +120,7 @@ Defaults to checking isTTY on the output stream upon instantiation.

    -

    The completer function is given a the current line entered by the user, and +

    The completer function is given the current line entered by the user, and is supposed to return an Array with 2 entries:

    @@ -378,6 +382,27 @@ console.log('Have a great day!'); process.exit(0); });
    +

    readline.cursorTo(stream, x, y)#

    +

    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. + +

    +

    readline.clearLine(stream, dir)#

    +

    Clears current line of given TTY stream in a specified direction. +dir should have one of following values: + +

    +
      +
    • -1 - to the left from cursor
    • +
    • 1 - to the right from cursor
    • +
    • 0 - the entire line
    • +
    +

    readline.clearScreenDown(stream)#

    +

    Clears the screen from the current position of the cursor down. +

    @@ -397,7 +422,7 @@
  • -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/api/readline.json nodejs-0.11.11/doc/api/readline.json --- nodejs-0.11.10/doc/api/readline.json 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/readline.json 2014-01-29 03:26:35.000000000 +0000 @@ -12,7 +12,7 @@ "textRaw": "readline.createInterface(options)", "type": "method", "name": "createInterface", - "desc": "

    Creates a readline Interface instance. Accepts an "options" Object that takes\nthe following values:\n\n

    \n
      \n
    • input - the readable stream to listen to (Required).

      \n
    • \n
    • output - the writable stream to write readline data to (Required).

      \n
    • \n
    • completer - an optional function that is used for Tab autocompletion. See\nbelow for an example of using this.

      \n
    • \n
    • terminal - pass true if the input and output streams should be\ntreated like a TTY, and have ANSI/VT100 escape codes written to it.\nDefaults to checking isTTY on the output stream upon instantiation.

      \n
    • \n
    \n

    The completer function is given a the current line entered by the user, and\nis supposed to return an Array with 2 entries:\n\n

    \n
      \n
    1. An Array with matching entries for the completion.

      \n
    2. \n
    3. The substring that was used for the matching.

      \n
    4. \n
    \n

    Which ends up looking something like:\n[[substr1, substr2, ...], originalsubstring].\n\n

    \n

    Example:\n\n

    \n
    function completer(line) {\n  var completions = '.help .error .exit .quit .q'.split(' ')\n  var hits = completions.filter(function(c) { return c.indexOf(line) == 0 })\n  // show all completions if none found\n  return [hits.length ? hits : completions, line]\n}
    \n

    Also completer can be run in async mode if it accepts two arguments:\n\n

    \n
    function completer(linePartial, callback) {\n  callback(null, [['123'], linePartial]);\n}
    \n

    createInterface is commonly used with process.stdin and\nprocess.stdout in order to accept user input:\n\n

    \n
    var readline = require('readline');\nvar rl = readline.createInterface({\n  input: process.stdin,\n  output: process.stdout\n});
    \n

    Once you have a readline instance, you most commonly listen for the\n"line" event.\n\n

    \n

    If terminal is true for this instance then the output stream will get\nthe best compatibility if it defines an output.columns property, and fires\na "resize" event on the output if/when the columns ever change\n(process.stdout does this automatically when it is a TTY).\n\n

    \n", + "desc": "

    Creates a readline Interface instance. Accepts an "options" Object that takes\nthe following values:\n\n

    \n
      \n
    • input - the readable stream to listen to (Required).

      \n
    • \n
    • output - the writable stream to write readline data to (Required).

      \n
    • \n
    • completer - an optional function that is used for Tab autocompletion. See\nbelow for an example of using this.

      \n
    • \n
    • terminal - pass true if the input and output streams should be\ntreated like a TTY, and have ANSI/VT100 escape codes written to it.\nDefaults to checking isTTY on the output stream upon instantiation.

      \n
    • \n
    \n

    The completer function is given the current line entered by the user, and\nis supposed to return an Array with 2 entries:\n\n

    \n
      \n
    1. An Array with matching entries for the completion.

      \n
    2. \n
    3. The substring that was used for the matching.

      \n
    4. \n
    \n

    Which ends up looking something like:\n[[substr1, substr2, ...], originalsubstring].\n\n

    \n

    Example:\n\n

    \n
    function completer(line) {\n  var completions = '.help .error .exit .quit .q'.split(' ')\n  var hits = completions.filter(function(c) { return c.indexOf(line) == 0 })\n  // show all completions if none found\n  return [hits.length ? hits : completions, line]\n}
    \n

    Also completer can be run in async mode if it accepts two arguments:\n\n

    \n
    function completer(linePartial, callback) {\n  callback(null, [['123'], linePartial]);\n}
    \n

    createInterface is commonly used with process.stdin and\nprocess.stdout in order to accept user input:\n\n

    \n
    var readline = require('readline');\nvar rl = readline.createInterface({\n  input: process.stdin,\n  output: process.stdout\n});
    \n

    Once you have a readline instance, you most commonly listen for the\n"line" event.\n\n

    \n

    If terminal is true for this instance then the output stream will get\nthe best compatibility if it defines an output.columns property, and fires\na "resize" event on the output if/when the columns ever change\n(process.stdout does this automatically when it is a TTY).\n\n

    \n", "signatures": [ { "params": [ @@ -22,6 +22,81 @@ ] } ] + }, + { + "textRaw": "readline.cursorTo(stream, x, y)", + "type": "method", + "name": "cursorTo", + "desc": "

    Move cursor to the specified position in a given TTY stream.\n\n

    \n", + "signatures": [ + { + "params": [ + { + "name": "stream" + }, + { + "name": "x" + }, + { + "name": "y" + } + ] + } + ] + }, + { + "textRaw": "readline.moveCursor(stream, dx, dy)", + "type": "method", + "name": "moveCursor", + "desc": "

    Move cursor relative to it's current position in a given TTY stream.\n\n

    \n", + "signatures": [ + { + "params": [ + { + "name": "stream" + }, + { + "name": "dx" + }, + { + "name": "dy" + } + ] + } + ] + }, + { + "textRaw": "readline.clearLine(stream, dir)", + "type": "method", + "name": "clearLine", + "desc": "

    Clears current line of given TTY stream in a specified direction.\ndir should have one of following values:\n\n

    \n
      \n
    • -1 - to the left from cursor
    • \n
    • 1 - to the right from cursor
    • \n
    • 0 - the entire line
    • \n
    \n", + "signatures": [ + { + "params": [ + { + "name": "stream" + }, + { + "name": "dir" + } + ] + } + ] + }, + { + "textRaw": "readline.clearScreenDown(stream)", + "type": "method", + "name": "clearScreenDown", + "desc": "

    Clears the screen from the current position of the cursor down.\n

    \n", + "signatures": [ + { + "params": [ + { + "name": "stream" + } + ] + } + ] } ], "classes": [ diff -Nru nodejs-0.11.10/doc/api/readline.markdown nodejs-0.11.11/doc/api/readline.markdown --- nodejs-0.11.10/doc/api/readline.markdown 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/doc/api/readline.markdown 2014-01-29 01:29:56.000000000 +0000 @@ -39,7 +39,7 @@ treated like a TTY, and have ANSI/VT100 escape codes written to it. Defaults to checking `isTTY` on the `output` stream upon instantiation. -The `completer` function is given a the current line entered by the user, and +The `completer` function is given the current line entered by the user, and is supposed to return an Array with 2 entries: 1. An Array with matching entries for the completion. @@ -281,3 +281,23 @@ process.exit(0); }); +## readline.cursorTo(stream, x, y) + +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. + +## readline.clearLine(stream, dir) + +Clears current line of given TTY stream in a specified direction. +`dir` should have one of following values: + +* `-1` - to the left from cursor +* `1` - to the right from cursor +* `0` - the entire line + +## readline.clearScreenDown(stream) + +Clears the screen from the current position of the cursor down. diff -Nru nodejs-0.11.10/doc/api/repl.html nodejs-0.11.11/doc/api/repl.html --- nodejs-0.11.10/doc/api/repl.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/repl.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - REPL Node.js v0.11.10 Manual & Documentation + REPL Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -302,7 +302,7 @@

  • -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/api/smalloc.html nodejs-0.11.11/doc/api/smalloc.html --- nodejs-0.11.10/doc/api/smalloc.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/smalloc.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - Smalloc Node.js v0.11.10 Manual & Documentation + Smalloc Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -215,7 +215,7 @@

  • -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/api/stream.html nodejs-0.11.11/doc/api/stream.html --- nodejs-0.11.10/doc/api/stream.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/stream.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - Stream Node.js v0.11.10 Manual & Documentation + Stream Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -916,7 +916,7 @@ function SimpleProtocol(source, options) { if (!(this instanceof SimpleProtocol)) - return new SimpleProtocol(options); + return new SimpleProtocol(source, options); Readable.call(this, options); this._inBody = false; @@ -1184,7 +1184,7 @@

    writable._writev(chunks, callback)#

    • chunks Array The chunks to be written. Each chunk has following -format: <span class="type"> chunk: ..., encoding: ... </span>.
    • +format: { chunk: ..., encoding: ... }.
    • callback Function Call this function (optionally with an error argument) when you are done processing the supplied chunks.
    @@ -1683,7 +1683,7 @@
  • -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/api/stream.json nodejs-0.11.11/doc/api/stream.json --- nodejs-0.11.10/doc/api/stream.json 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/stream.json 2014-01-29 03:26:35.000000000 +0000 @@ -922,7 +922,7 @@ "textRaw": "Class: stream.Readable", "type": "example", "name": "stream.Readable", - "desc": "

    stream.Readable is an abstract class designed to be extended with an\nunderlying implementation of the [_read(size)][] method.\n\n

    \n

    Please see above under [API for Stream Consumers][] for how to consume\nstreams in your programs. What follows is an explanation of how to\nimplement Readable streams in your programs.\n\n

    \n

    Example: A Counting Stream

    \n

    This is a basic example of a Readable stream. It emits the numerals\nfrom 1 to 1,000,000 in ascending order, and then ends.\n\n

    \n
    var Readable = require('stream').Readable;\nvar util = require('util');\nutil.inherits(Counter, Readable);\n\nfunction Counter(opt) {\n  Readable.call(this, opt);\n  this._max = 1000000;\n  this._index = 1;\n}\n\nCounter.prototype._read = function() {\n  var i = this._index++;\n  if (i > this._max)\n    this.push(null);\n  else {\n    var str = '' + i;\n    var buf = new Buffer(str, 'ascii');\n    this.push(buf);\n  }\n};
    \n

    Example: SimpleProtocol v1 (Sub-optimal)

    \n

    This is similar to the parseHeader function described above, but\nimplemented as a custom stream. Also, note that this implementation\ndoes not convert the incoming data to a string.\n\n

    \n

    However, this would be better implemented as a [Transform][] stream. See\nbelow for a better implementation.\n\n

    \n
    // A parser for a simple data protocol.\n// The "header" is a JSON object, followed by 2 \\n characters, and\n// then a message body.\n//\n// NOTE: This can be done more simply as a Transform stream!\n// Using Readable directly for this is sub-optimal.  See the\n// alternative example below under the Transform section.\n\nvar Readable = require('stream').Readable;\nvar util = require('util');\n\nutil.inherits(SimpleProtocol, Readable);\n\nfunction SimpleProtocol(source, options) {\n  if (!(this instanceof SimpleProtocol))\n    return new SimpleProtocol(options);\n\n  Readable.call(this, options);\n  this._inBody = false;\n  this._sawFirstCr = false;\n\n  // source is a readable stream, such as a socket or file\n  this._source = source;\n\n  var self = this;\n  source.on('end', function() {\n    self.push(null);\n  });\n\n  // give it a kick whenever the source is readable\n  // read(0) will not consume any bytes\n  source.on('readable', function() {\n    self.read(0);\n  });\n\n  this._rawHeader = [];\n  this.header = null;\n}\n\nSimpleProtocol.prototype._read = function(n) {\n  if (!this._inBody) {\n    var chunk = this._source.read();\n\n    // if the source doesn't have data, we don't have data yet.\n    if (chunk === null)\n      return this.push('');\n\n    // check if the chunk has a \\n\\n\n    var split = -1;\n    for (var i = 0; i < chunk.length; i++) {\n      if (chunk[i] === 10) { // '\\n'\n        if (this._sawFirstCr) {\n          split = i;\n          break;\n        } else {\n          this._sawFirstCr = true;\n        }\n      } else {\n        this._sawFirstCr = false;\n      }\n    }\n\n    if (split === -1) {\n      // still waiting for the \\n\\n\n      // stash the chunk, and try again.\n      this._rawHeader.push(chunk);\n      this.push('');\n    } else {\n      this._inBody = true;\n      var h = chunk.slice(0, split);\n      this._rawHeader.push(h);\n      var header = Buffer.concat(this._rawHeader).toString();\n      try {\n        this.header = JSON.parse(header);\n      } catch (er) {\n        this.emit('error', new Error('invalid simple protocol data'));\n        return;\n      }\n      // now, because we got some extra data, unshift the rest\n      // back into the read queue so that our consumer will see it.\n      var b = chunk.slice(split);\n      this.unshift(b);\n\n      // and let them know that we are done parsing the header.\n      this.emit('header', this.header);\n    }\n  } else {\n    // from there on, just provide the data to our consumer.\n    // careful not to push(null), since that would indicate EOF.\n    var chunk = this._source.read();\n    if (chunk) this.push(chunk);\n  }\n};\n\n// Usage:\n// var parser = new SimpleProtocol(source);\n// Now parser is a readable stream that will emit 'header'\n// with the parsed header data.
    \n", + "desc": "

    stream.Readable is an abstract class designed to be extended with an\nunderlying implementation of the [_read(size)][] method.\n\n

    \n

    Please see above under [API for Stream Consumers][] for how to consume\nstreams in your programs. What follows is an explanation of how to\nimplement Readable streams in your programs.\n\n

    \n

    Example: A Counting Stream

    \n

    This is a basic example of a Readable stream. It emits the numerals\nfrom 1 to 1,000,000 in ascending order, and then ends.\n\n

    \n
    var Readable = require('stream').Readable;\nvar util = require('util');\nutil.inherits(Counter, Readable);\n\nfunction Counter(opt) {\n  Readable.call(this, opt);\n  this._max = 1000000;\n  this._index = 1;\n}\n\nCounter.prototype._read = function() {\n  var i = this._index++;\n  if (i > this._max)\n    this.push(null);\n  else {\n    var str = '' + i;\n    var buf = new Buffer(str, 'ascii');\n    this.push(buf);\n  }\n};
    \n

    Example: SimpleProtocol v1 (Sub-optimal)

    \n

    This is similar to the parseHeader function described above, but\nimplemented as a custom stream. Also, note that this implementation\ndoes not convert the incoming data to a string.\n\n

    \n

    However, this would be better implemented as a [Transform][] stream. See\nbelow for a better implementation.\n\n

    \n
    // A parser for a simple data protocol.\n// The "header" is a JSON object, followed by 2 \\n characters, and\n// then a message body.\n//\n// NOTE: This can be done more simply as a Transform stream!\n// Using Readable directly for this is sub-optimal.  See the\n// alternative example below under the Transform section.\n\nvar Readable = require('stream').Readable;\nvar util = require('util');\n\nutil.inherits(SimpleProtocol, Readable);\n\nfunction SimpleProtocol(source, options) {\n  if (!(this instanceof SimpleProtocol))\n    return new SimpleProtocol(source, options);\n\n  Readable.call(this, options);\n  this._inBody = false;\n  this._sawFirstCr = false;\n\n  // source is a readable stream, such as a socket or file\n  this._source = source;\n\n  var self = this;\n  source.on('end', function() {\n    self.push(null);\n  });\n\n  // give it a kick whenever the source is readable\n  // read(0) will not consume any bytes\n  source.on('readable', function() {\n    self.read(0);\n  });\n\n  this._rawHeader = [];\n  this.header = null;\n}\n\nSimpleProtocol.prototype._read = function(n) {\n  if (!this._inBody) {\n    var chunk = this._source.read();\n\n    // if the source doesn't have data, we don't have data yet.\n    if (chunk === null)\n      return this.push('');\n\n    // check if the chunk has a \\n\\n\n    var split = -1;\n    for (var i = 0; i < chunk.length; i++) {\n      if (chunk[i] === 10) { // '\\n'\n        if (this._sawFirstCr) {\n          split = i;\n          break;\n        } else {\n          this._sawFirstCr = true;\n        }\n      } else {\n        this._sawFirstCr = false;\n      }\n    }\n\n    if (split === -1) {\n      // still waiting for the \\n\\n\n      // stash the chunk, and try again.\n      this._rawHeader.push(chunk);\n      this.push('');\n    } else {\n      this._inBody = true;\n      var h = chunk.slice(0, split);\n      this._rawHeader.push(h);\n      var header = Buffer.concat(this._rawHeader).toString();\n      try {\n        this.header = JSON.parse(header);\n      } catch (er) {\n        this.emit('error', new Error('invalid simple protocol data'));\n        return;\n      }\n      // now, because we got some extra data, unshift the rest\n      // back into the read queue so that our consumer will see it.\n      var b = chunk.slice(split);\n      this.unshift(b);\n\n      // and let them know that we are done parsing the header.\n      this.emit('header', this.header);\n    }\n  } else {\n    // from there on, just provide the data to our consumer.\n    // careful not to push(null), since that would indicate EOF.\n    var chunk = this._source.read();\n    if (chunk) this.push(chunk);\n  }\n};\n\n// Usage:\n// var parser = new SimpleProtocol(source);\n// Now parser is a readable stream that will emit 'header'\n// with the parsed header data.
    \n", "methods": [ { "textRaw": "new stream.Readable([options])", @@ -1372,7 +1372,7 @@ "textRaw": "Class: stream.Readable", "type": "example", "name": "stream.Readable", - "desc": "

    stream.Readable is an abstract class designed to be extended with an\nunderlying implementation of the [_read(size)][] method.\n\n

    \n

    Please see above under [API for Stream Consumers][] for how to consume\nstreams in your programs. What follows is an explanation of how to\nimplement Readable streams in your programs.\n\n

    \n

    Example: A Counting Stream

    \n

    This is a basic example of a Readable stream. It emits the numerals\nfrom 1 to 1,000,000 in ascending order, and then ends.\n\n

    \n
    var Readable = require('stream').Readable;\nvar util = require('util');\nutil.inherits(Counter, Readable);\n\nfunction Counter(opt) {\n  Readable.call(this, opt);\n  this._max = 1000000;\n  this._index = 1;\n}\n\nCounter.prototype._read = function() {\n  var i = this._index++;\n  if (i > this._max)\n    this.push(null);\n  else {\n    var str = '' + i;\n    var buf = new Buffer(str, 'ascii');\n    this.push(buf);\n  }\n};
    \n

    Example: SimpleProtocol v1 (Sub-optimal)

    \n

    This is similar to the parseHeader function described above, but\nimplemented as a custom stream. Also, note that this implementation\ndoes not convert the incoming data to a string.\n\n

    \n

    However, this would be better implemented as a [Transform][] stream. See\nbelow for a better implementation.\n\n

    \n
    // A parser for a simple data protocol.\n// The "header" is a JSON object, followed by 2 \\n characters, and\n// then a message body.\n//\n// NOTE: This can be done more simply as a Transform stream!\n// Using Readable directly for this is sub-optimal.  See the\n// alternative example below under the Transform section.\n\nvar Readable = require('stream').Readable;\nvar util = require('util');\n\nutil.inherits(SimpleProtocol, Readable);\n\nfunction SimpleProtocol(source, options) {\n  if (!(this instanceof SimpleProtocol))\n    return new SimpleProtocol(options);\n\n  Readable.call(this, options);\n  this._inBody = false;\n  this._sawFirstCr = false;\n\n  // source is a readable stream, such as a socket or file\n  this._source = source;\n\n  var self = this;\n  source.on('end', function() {\n    self.push(null);\n  });\n\n  // give it a kick whenever the source is readable\n  // read(0) will not consume any bytes\n  source.on('readable', function() {\n    self.read(0);\n  });\n\n  this._rawHeader = [];\n  this.header = null;\n}\n\nSimpleProtocol.prototype._read = function(n) {\n  if (!this._inBody) {\n    var chunk = this._source.read();\n\n    // if the source doesn't have data, we don't have data yet.\n    if (chunk === null)\n      return this.push('');\n\n    // check if the chunk has a \\n\\n\n    var split = -1;\n    for (var i = 0; i < chunk.length; i++) {\n      if (chunk[i] === 10) { // '\\n'\n        if (this._sawFirstCr) {\n          split = i;\n          break;\n        } else {\n          this._sawFirstCr = true;\n        }\n      } else {\n        this._sawFirstCr = false;\n      }\n    }\n\n    if (split === -1) {\n      // still waiting for the \\n\\n\n      // stash the chunk, and try again.\n      this._rawHeader.push(chunk);\n      this.push('');\n    } else {\n      this._inBody = true;\n      var h = chunk.slice(0, split);\n      this._rawHeader.push(h);\n      var header = Buffer.concat(this._rawHeader).toString();\n      try {\n        this.header = JSON.parse(header);\n      } catch (er) {\n        this.emit('error', new Error('invalid simple protocol data'));\n        return;\n      }\n      // now, because we got some extra data, unshift the rest\n      // back into the read queue so that our consumer will see it.\n      var b = chunk.slice(split);\n      this.unshift(b);\n\n      // and let them know that we are done parsing the header.\n      this.emit('header', this.header);\n    }\n  } else {\n    // from there on, just provide the data to our consumer.\n    // careful not to push(null), since that would indicate EOF.\n    var chunk = this._source.read();\n    if (chunk) this.push(chunk);\n  }\n};\n\n// Usage:\n// var parser = new SimpleProtocol(source);\n// Now parser is a readable stream that will emit 'header'\n// with the parsed header data.
    \n", + "desc": "

    stream.Readable is an abstract class designed to be extended with an\nunderlying implementation of the [_read(size)][] method.\n\n

    \n

    Please see above under [API for Stream Consumers][] for how to consume\nstreams in your programs. What follows is an explanation of how to\nimplement Readable streams in your programs.\n\n

    \n

    Example: A Counting Stream

    \n

    This is a basic example of a Readable stream. It emits the numerals\nfrom 1 to 1,000,000 in ascending order, and then ends.\n\n

    \n
    var Readable = require('stream').Readable;\nvar util = require('util');\nutil.inherits(Counter, Readable);\n\nfunction Counter(opt) {\n  Readable.call(this, opt);\n  this._max = 1000000;\n  this._index = 1;\n}\n\nCounter.prototype._read = function() {\n  var i = this._index++;\n  if (i > this._max)\n    this.push(null);\n  else {\n    var str = '' + i;\n    var buf = new Buffer(str, 'ascii');\n    this.push(buf);\n  }\n};
    \n

    Example: SimpleProtocol v1 (Sub-optimal)

    \n

    This is similar to the parseHeader function described above, but\nimplemented as a custom stream. Also, note that this implementation\ndoes not convert the incoming data to a string.\n\n

    \n

    However, this would be better implemented as a [Transform][] stream. See\nbelow for a better implementation.\n\n

    \n
    // A parser for a simple data protocol.\n// The "header" is a JSON object, followed by 2 \\n characters, and\n// then a message body.\n//\n// NOTE: This can be done more simply as a Transform stream!\n// Using Readable directly for this is sub-optimal.  See the\n// alternative example below under the Transform section.\n\nvar Readable = require('stream').Readable;\nvar util = require('util');\n\nutil.inherits(SimpleProtocol, Readable);\n\nfunction SimpleProtocol(source, options) {\n  if (!(this instanceof SimpleProtocol))\n    return new SimpleProtocol(source, options);\n\n  Readable.call(this, options);\n  this._inBody = false;\n  this._sawFirstCr = false;\n\n  // source is a readable stream, such as a socket or file\n  this._source = source;\n\n  var self = this;\n  source.on('end', function() {\n    self.push(null);\n  });\n\n  // give it a kick whenever the source is readable\n  // read(0) will not consume any bytes\n  source.on('readable', function() {\n    self.read(0);\n  });\n\n  this._rawHeader = [];\n  this.header = null;\n}\n\nSimpleProtocol.prototype._read = function(n) {\n  if (!this._inBody) {\n    var chunk = this._source.read();\n\n    // if the source doesn't have data, we don't have data yet.\n    if (chunk === null)\n      return this.push('');\n\n    // check if the chunk has a \\n\\n\n    var split = -1;\n    for (var i = 0; i < chunk.length; i++) {\n      if (chunk[i] === 10) { // '\\n'\n        if (this._sawFirstCr) {\n          split = i;\n          break;\n        } else {\n          this._sawFirstCr = true;\n        }\n      } else {\n        this._sawFirstCr = false;\n      }\n    }\n\n    if (split === -1) {\n      // still waiting for the \\n\\n\n      // stash the chunk, and try again.\n      this._rawHeader.push(chunk);\n      this.push('');\n    } else {\n      this._inBody = true;\n      var h = chunk.slice(0, split);\n      this._rawHeader.push(h);\n      var header = Buffer.concat(this._rawHeader).toString();\n      try {\n        this.header = JSON.parse(header);\n      } catch (er) {\n        this.emit('error', new Error('invalid simple protocol data'));\n        return;\n      }\n      // now, because we got some extra data, unshift the rest\n      // back into the read queue so that our consumer will see it.\n      var b = chunk.slice(split);\n      this.unshift(b);\n\n      // and let them know that we are done parsing the header.\n      this.emit('header', this.header);\n    }\n  } else {\n    // from there on, just provide the data to our consumer.\n    // careful not to push(null), since that would indicate EOF.\n    var chunk = this._source.read();\n    if (chunk) this.push(chunk);\n  }\n};\n\n// Usage:\n// var parser = new SimpleProtocol(source);\n// Now parser is a readable stream that will emit 'header'\n// with the parsed header data.
    \n", "methods": [ { "textRaw": "new stream.Readable([options])", diff -Nru nodejs-0.11.10/doc/api/stream.markdown nodejs-0.11.11/doc/api/stream.markdown --- nodejs-0.11.10/doc/api/stream.markdown 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/doc/api/stream.markdown 2014-01-29 01:29:56.000000000 +0000 @@ -789,7 +789,7 @@ function SimpleProtocol(source, options) { if (!(this instanceof SimpleProtocol)) - return new SimpleProtocol(options); + return new SimpleProtocol(source, options); Readable.call(this, options); this._inBody = false; diff -Nru nodejs-0.11.10/doc/api/string_decoder.html nodejs-0.11.11/doc/api/string_decoder.html --- nodejs-0.11.10/doc/api/string_decoder.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/string_decoder.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - StringDecoder Node.js v0.11.10 Manual & Documentation + StringDecoder Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -102,7 +102,7 @@

  • -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/api/synopsis.html nodejs-0.11.11/doc/api/synopsis.html --- nodejs-0.11.10/doc/api/synopsis.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/synopsis.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - Synopsis Node.js v0.11.10 Manual & Documentation + Synopsis Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -93,7 +93,7 @@

  • -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/api/timers.html nodejs-0.11.11/doc/api/timers.html --- nodejs-0.11.10/doc/api/timers.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/timers.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - Timers Node.js v0.11.10 Manual & Documentation + Timers Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -145,7 +145,7 @@

  • -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/api/tls.html nodejs-0.11.11/doc/api/tls.html --- nodejs-0.11.10/doc/api/tls.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/tls.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - TLS (SSL) Node.js v0.11.10 Manual & Documentation + TLS (SSL) Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -48,6 +48,7 @@

  • TLS (SSL) +

    Perfect Forward Secrecy#

    + + +

    The term "Forward Secrecy" or "Perfect Forward Secrecy" describes a feature of +key-agreement (i.e. key-exchange) methods. Practically it means that even if the +private key of a (your) server is compromised, communication can only be +decrypted by eavesdroppers if they manage to obtain the key-pair specifically +generated for each session. + +

    +

    This is achieved by randomly generating a key pair for key-agreement on every +handshake (in contrary to the same key for all sessions). Methods implementing +this technique, thus offering Perfect Forward Secrecy, are called "ephemeral". + +

    +

    Currently two methods are commonly used to achieve Perfect Forward Secrecy (note +the character "E" appended to the traditional abbreviations): + +

    +
      +
    • DHE - An ephemeral version of the Diffie Hellman key-agreement protocol.
    • +
    • ECDHE - An ephemeral version of the Elliptic Curve Diffie Hellman +key-agreement protocol.
    • +
    +

    Ephemeral methods may have some performance drawbacks, because key generation +is expensive. + + +

    tls.getCiphers()#

    Returns an array with the names of the supported SSL ciphers. @@ -224,22 +255,20 @@

    Defaults to ECDHE-RSA-AES128-SHA256:AES128-GCM-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH. Consult the OpenSSL cipher list format documentation for details on the format.

    +

    ECDHE-RSA-AES128-SHA256 and AES128-GCM-SHA256 are TLS v1.2 ciphers and +used when node.js is linked against OpenSSL 1.0.1 or newer, such as the +bundled version of OpenSSL. Note that it is still possible for a TLS v1.2 +client to negotiate a weaker cipher unless honorCipherOrder is enabled.

    +

    RC4 is used as a fallback for clients that speak on older version of +the TLS protocol. RC4 has in recent years come under suspicion and +should be considered compromised for anything that is truly sensitive. +It is speculated that state-level actors posess the ability to break it.

    +

    NOTE: Previous revisions of this section suggested AES256-SHA as an +acceptable cipher. Unfortunately, AES256-SHA is a CBC cipher and therefore +susceptible to BEAST attacks. Do not use it.

  • - -
    `AES128-GCM-SHA256` is used when node.js is linked against OpenSSL 1.0.1
    -or newer and the client speaks TLS 1.2, RC4 is used as a secure fallback.
    -
    -**NOTE**: Previous revisions of this section suggested `AES256-SHA` as an
    -acceptable cipher. Unfortunately, `AES256-SHA` is a CBC cipher and therefore
    -susceptible to BEAST attacks. Do *not* use it.
    -
      -
    • ecdhCurve: A string describing a named curve to use for ECDH ciphers or -false to disable all ECDH ciphers.

      -

      This is required to support ECDH (Elliptic Curve Diffie-Hellman) ciphers. -ECDH ciphers are a newer alternative to RSA. The advantages of ECDH over -RSA is that it offers Forward secrecy. Forward secrecy means that for an -attacker it won't be possible to decrypt your previous data exchanges if -they get access to your private key.

      +
    • ecdhCurve: A string describing a named curve to use for ECDH key agreement +or false to disable ECDH.

      Defaults to prime256v1. Consult RFC 4492 for more details.

    • handshakeTimeout: Abort the connection if the SSL/TLS handshake does not @@ -249,11 +278,12 @@

    • honorCipherOrder : When choosing a cipher, use the server's preferences instead of the client preferences.

      -

      Note that if SSLv2 is used, the server will send its list of preferences -to the client, and the client chooses the cipher.

      Although, this option is disabled by default, it is recommended that you use this option in conjunction with the ciphers option to mitigate BEAST attacks.

      +

      Note: If SSLv2 is used, the server will send its list of preferences to the +client, and the client chooses the cipher. Support for SSLv2 is disabled +unless node.js was configured with ./configure --with-sslv2.

    • requestCert: If true the server will request a certificate from clients that connect and attempt to verify that certificate. Default: @@ -376,7 +406,7 @@

    • rejectUnauthorized: If true, the server certificate is verified against the list of supplied CAs. An 'error' event is emitted if verification -fails. Default: true.

      +fails; err.code contains the OpenSSL error code. Default: true.

    • NPNProtocols: An array of strings or Buffers containing supported NPN protocols. Buffers should have following format: 0x05hello0x05world, @@ -734,6 +764,19 @@ with an error after handshakeTimeout timeout.

      +

      tlsSocket.setMaxSendFragment(size)#

      +

      Set maximum TLS fragment size (default and maximum value is: 16384, minimum +is: 512). Returns true on success, false otherwise. + +

      +

      Smaller fragment size decreases buffering latency on the client: large +fragments are buffered by the TLS layer until the entire fragment is received +and its integrity is verified; large fragments can span multiple roundtrips, +and their processing can be delayed due to packet loss or reordering. However, +smaller fragments add extra TLS framing bytes and CPU overhead, which may +decrease overall server throughput. + +

      tlsSocket.address()#

      Returns the bound address, the address family name and port of the underlying socket as reported by the operating system. Returns an @@ -777,7 +820,7 @@

    -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/api/tls.json nodejs-0.11.11/doc/api/tls.json --- nodejs-0.11.10/doc/api/tls.json 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/tls.json 2014-01-29 03:26:35.000000000 +0000 @@ -19,6 +19,12 @@ "name": "NPN and SNI", "type": "misc", "desc": "

    NPN (Next Protocol Negotiation) and SNI (Server Name Indication) are TLS\nhandshake extensions allowing you:\n\n

    \n
      \n
    • NPN - to use one TLS server for multiple protocols (HTTP, SPDY)
    • \n
    • SNI - to use one TLS server for multiple hostnames with different SSL\ncertificates.
    • \n
    \n" + }, + { + "textRaw": "Perfect Forward Secrecy", + "name": "Perfect Forward Secrecy", + "type": "misc", + "desc": "

    The term "[Forward Secrecy]" or "Perfect Forward Secrecy" describes a feature of\nkey-agreement (i.e. key-exchange) methods. Practically it means that even if the\nprivate key of a (your) server is compromised, communication can only be\ndecrypted by eavesdroppers if they manage to obtain the key-pair specifically\ngenerated for each session.\n\n

    \n

    This is achieved by randomly generating a key pair for key-agreement on every\nhandshake (in contrary to the same key for all sessions). Methods implementing\nthis technique, thus offering Perfect Forward Secrecy, are called "ephemeral".\n\n

    \n

    Currently two methods are commonly used to achieve Perfect Forward Secrecy (note \nthe character "E" appended to the traditional abbreviations):\n\n

    \n
      \n
    • [DHE] - An ephemeral version of the Diffie Hellman key-agreement protocol.
    • \n
    • [ECDHE] - An ephemeral version of the Elliptic Curve Diffie Hellman\nkey-agreement protocol.
    • \n
    \n

    Ephemeral methods may have some performance drawbacks, because key generation\nis expensive.\n\n\n

    \n" } ], "methods": [ @@ -37,7 +43,7 @@ "textRaw": "tls.createServer(options, [secureConnectionListener])", "type": "method", "name": "createServer", - "desc": "

    Creates a new [tls.Server][]. The connectionListener argument is\nautomatically set as a listener for the [secureConnection][] event. The\noptions object has these possibilities:\n\n

    \n
      \n
    • pfx: A string or Buffer containing the private key, certificate and\nCA certs of the server in PFX or PKCS12 format. (Mutually exclusive with\nthe key, cert and ca options.)

      \n
    • \n
    • key: A string or Buffer containing the private key of the server in\nPEM format. (Required)

      \n
    • \n
    • passphrase: A string of passphrase for the private key or pfx.

      \n
    • \n
    • cert: A string or Buffer containing the certificate key of the server in\nPEM format. (Required)

      \n
    • \n
    • ca: An array of strings or Buffers of trusted certificates in PEM\nformat. If this is omitted several well known "root" CAs will be used,\nlike VeriSign. These are used to authorize connections.

      \n
    • \n
    • crl : Either a string or list of strings of PEM encoded CRLs (Certificate\nRevocation List)

      \n
    • \n
    • ciphers: A string describing the ciphers to use or exclude.

      \n

      To mitigate [BEAST attacks] it is recommended that you use this option in\nconjunction with the honorCipherOrder option described below to\nprioritize the non-CBC cipher.

      \n

      Defaults to ECDHE-RSA-AES128-SHA256:AES128-GCM-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH.\nConsult the [OpenSSL cipher list format documentation] for details on the\nformat.

      \n
    • \n
    \n
    `AES128-GCM-SHA256` is used when node.js is linked against OpenSSL 1.0.1\nor newer and the client speaks TLS 1.2, RC4 is used as a secure fallback.\n\n**NOTE**: Previous revisions of this section suggested `AES256-SHA` as an\nacceptable cipher. Unfortunately, `AES256-SHA` is a CBC cipher and therefore\nsusceptible to BEAST attacks. Do *not* use it.
    \n
      \n
    • ecdhCurve: A string describing a named curve to use for ECDH ciphers or\nfalse to disable all ECDH ciphers.

      \n

      This is required to support ECDH (Elliptic Curve Diffie-Hellman) ciphers.\nECDH ciphers are a newer alternative to RSA. The advantages of ECDH over\nRSA is that it offers [Forward secrecy]. Forward secrecy means that for an\nattacker it won't be possible to decrypt your previous data exchanges if\nthey get access to your private key.

      \n

      Defaults to prime256v1. Consult [RFC 4492] for more details.

      \n
    • \n
    • handshakeTimeout: Abort the connection if the SSL/TLS handshake does not\nfinish in this many milliseconds. The default is 120 seconds.

      \n

      A 'clientError' is emitted on the tls.Server object whenever a handshake\ntimes out.

      \n
    • \n
    • honorCipherOrder : When choosing a cipher, use the server's preferences\ninstead of the client preferences.

      \n

      Note that if SSLv2 is used, the server will send its list of preferences\nto the client, and the client chooses the cipher.

      \n

      Although, this option is disabled by default, it is recommended that you\nuse this option in conjunction with the ciphers option to mitigate\nBEAST attacks.

      \n
    • \n
    • requestCert: If true the server will request a certificate from\nclients that connect and attempt to verify that certificate. Default:\nfalse.

      \n
    • \n
    • rejectUnauthorized: If true the server will reject any connection\nwhich is not authorized with the list of supplied CAs. This option only\nhas an effect if requestCert is true. Default: false.

      \n
    • \n
    • NPNProtocols: An array or Buffer of possible NPN protocols. (Protocols\nshould be ordered by their priority).

      \n
    • \n
    • SNICallback(servername, cb): A function that will be called if client\nsupports SNI TLS extension. Two argument will be passed to it: servername,\nand cb. SNICallback should invoke cb(null, ctx), where ctx is a\nSecureContext instance.\n(You can use crypto.createCredentials(...).context to get proper\nSecureContext). If SNICallback wasn't provided - default callback with\nhigh-level API will be used (see below).

      \n
    • \n
    • sessionTimeout: An integer specifying the seconds after which TLS\nsession identifiers and TLS session tickets created by the server are\ntimed out. See [SSL_CTX_set_timeout] for more details.

      \n
    • \n
    • sessionIdContext: A string containing a opaque identifier for session\nresumption. If requestCert is true, the default is MD5 hash value\ngenerated from command-line. Otherwise, the default is not provided.

      \n
    • \n
    • secureProtocol: The SSL method to use, e.g. SSLv3_method to force\nSSL version 3. The possible values depend on your installation of\nOpenSSL and are defined in the constant [SSL_METHODS][].

      \n
    • \n
    \n

    Here is a simple example echo server:\n\n

    \n
    var tls = require('tls');\nvar fs = require('fs');\n\nvar options = {\n  key: fs.readFileSync('server-key.pem'),\n  cert: fs.readFileSync('server-cert.pem'),\n\n  // This is necessary only if using the client certificate authentication.\n  requestCert: true,\n\n  // This is necessary only if the client uses the self-signed certificate.\n  ca: [ fs.readFileSync('client-cert.pem') ]\n};\n\nvar server = tls.createServer(options, function(socket) {\n  console.log('server connected',\n              socket.authorized ? 'authorized' : 'unauthorized');\n  socket.write("welcome!\\n");\n  socket.setEncoding('utf8');\n  socket.pipe(socket);\n});\nserver.listen(8000, function() {\n  console.log('server bound');\n});
    \n

    Or\n\n

    \n
    var tls = require('tls');\nvar fs = require('fs');\n\nvar options = {\n  pfx: fs.readFileSync('server.pfx'),\n\n  // This is necessary only if using the client certificate authentication.\n  requestCert: true,\n\n};\n\nvar server = tls.createServer(options, function(socket) {\n  console.log('server connected',\n              socket.authorized ? 'authorized' : 'unauthorized');\n  socket.write("welcome!\\n");\n  socket.setEncoding('utf8');\n  socket.pipe(socket);\n});\nserver.listen(8000, function() {\n  console.log('server bound');\n});
    \n

    You can test this server by connecting to it with openssl s_client:\n\n\n

    \n
    openssl s_client -connect 127.0.0.1:8000
    \n", + "desc": "

    Creates a new [tls.Server][]. The connectionListener argument is\nautomatically set as a listener for the [secureConnection][] event. The\noptions object has these possibilities:\n\n

    \n
      \n
    • pfx: A string or Buffer containing the private key, certificate and\nCA certs of the server in PFX or PKCS12 format. (Mutually exclusive with\nthe key, cert and ca options.)

      \n
    • \n
    • key: A string or Buffer containing the private key of the server in\nPEM format. (Required)

      \n
    • \n
    • passphrase: A string of passphrase for the private key or pfx.

      \n
    • \n
    • cert: A string or Buffer containing the certificate key of the server in\nPEM format. (Required)

      \n
    • \n
    • ca: An array of strings or Buffers of trusted certificates in PEM\nformat. If this is omitted several well known "root" CAs will be used,\nlike VeriSign. These are used to authorize connections.

      \n
    • \n
    • crl : Either a string or list of strings of PEM encoded CRLs (Certificate\nRevocation List)

      \n
    • \n
    • ciphers: A string describing the ciphers to use or exclude.

      \n

      To mitigate [BEAST attacks] it is recommended that you use this option in\nconjunction with the honorCipherOrder option described below to\nprioritize the non-CBC cipher.

      \n

      Defaults to ECDHE-RSA-AES128-SHA256:AES128-GCM-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH.\nConsult the [OpenSSL cipher list format documentation] for details on the\nformat.

      \n

      ECDHE-RSA-AES128-SHA256 and AES128-GCM-SHA256 are TLS v1.2 ciphers and\nused when node.js is linked against OpenSSL 1.0.1 or newer, such as the\nbundled version of OpenSSL. Note that it is still possible for a TLS v1.2\nclient to negotiate a weaker cipher unless honorCipherOrder is enabled.

      \n

      RC4 is used as a fallback for clients that speak on older version of\nthe TLS protocol. RC4 has in recent years come under suspicion and\nshould be considered compromised for anything that is truly sensitive.\nIt is speculated that state-level actors posess the ability to break it.

      \n

      NOTE: Previous revisions of this section suggested AES256-SHA as an\nacceptable cipher. Unfortunately, AES256-SHA is a CBC cipher and therefore\nsusceptible to [BEAST attacks]. Do not use it.

      \n
    • \n
    • ecdhCurve: A string describing a named curve to use for ECDH key agreement\nor false to disable ECDH.

      \n

      Defaults to prime256v1. Consult [RFC 4492] for more details.

      \n
    • \n
    • handshakeTimeout: Abort the connection if the SSL/TLS handshake does not\nfinish in this many milliseconds. The default is 120 seconds.

      \n

      A 'clientError' is emitted on the tls.Server object whenever a handshake\ntimes out.

      \n
    • \n
    • honorCipherOrder : When choosing a cipher, use the server's preferences\ninstead of the client preferences.

      \n

      Although, this option is disabled by default, it is recommended that you\nuse this option in conjunction with the ciphers option to mitigate\nBEAST attacks.

      \n

      Note: If SSLv2 is used, the server will send its list of preferences to the\nclient, and the client chooses the cipher. Support for SSLv2 is disabled\nunless node.js was configured with ./configure --with-sslv2.

      \n
    • \n
    • requestCert: If true the server will request a certificate from\nclients that connect and attempt to verify that certificate. Default:\nfalse.

      \n
    • \n
    • rejectUnauthorized: If true the server will reject any connection\nwhich is not authorized with the list of supplied CAs. This option only\nhas an effect if requestCert is true. Default: false.

      \n
    • \n
    • NPNProtocols: An array or Buffer of possible NPN protocols. (Protocols\nshould be ordered by their priority).

      \n
    • \n
    • SNICallback(servername, cb): A function that will be called if client\nsupports SNI TLS extension. Two argument will be passed to it: servername,\nand cb. SNICallback should invoke cb(null, ctx), where ctx is a\nSecureContext instance.\n(You can use crypto.createCredentials(...).context to get proper\nSecureContext). If SNICallback wasn't provided - default callback with\nhigh-level API will be used (see below).

      \n
    • \n
    • sessionTimeout: An integer specifying the seconds after which TLS\nsession identifiers and TLS session tickets created by the server are\ntimed out. See [SSL_CTX_set_timeout] for more details.

      \n
    • \n
    • sessionIdContext: A string containing a opaque identifier for session\nresumption. If requestCert is true, the default is MD5 hash value\ngenerated from command-line. Otherwise, the default is not provided.

      \n
    • \n
    • secureProtocol: The SSL method to use, e.g. SSLv3_method to force\nSSL version 3. The possible values depend on your installation of\nOpenSSL and are defined in the constant [SSL_METHODS][].

      \n
    • \n
    \n

    Here is a simple example echo server:\n\n

    \n
    var tls = require('tls');\nvar fs = require('fs');\n\nvar options = {\n  key: fs.readFileSync('server-key.pem'),\n  cert: fs.readFileSync('server-cert.pem'),\n\n  // This is necessary only if using the client certificate authentication.\n  requestCert: true,\n\n  // This is necessary only if the client uses the self-signed certificate.\n  ca: [ fs.readFileSync('client-cert.pem') ]\n};\n\nvar server = tls.createServer(options, function(socket) {\n  console.log('server connected',\n              socket.authorized ? 'authorized' : 'unauthorized');\n  socket.write("welcome!\\n");\n  socket.setEncoding('utf8');\n  socket.pipe(socket);\n});\nserver.listen(8000, function() {\n  console.log('server bound');\n});
    \n

    Or\n\n

    \n
    var tls = require('tls');\nvar fs = require('fs');\n\nvar options = {\n  pfx: fs.readFileSync('server.pfx'),\n\n  // This is necessary only if using the client certificate authentication.\n  requestCert: true,\n\n};\n\nvar server = tls.createServer(options, function(socket) {\n  console.log('server connected',\n              socket.authorized ? 'authorized' : 'unauthorized');\n  socket.write("welcome!\\n");\n  socket.setEncoding('utf8');\n  socket.pipe(socket);\n});\nserver.listen(8000, function() {\n  console.log('server bound');\n});
    \n

    You can test this server by connecting to it with openssl s_client:\n\n\n

    \n
    openssl s_client -connect 127.0.0.1:8000
    \n", "signatures": [ { "params": [ @@ -56,7 +62,7 @@ "textRaw": "tls.connect(options, [callback])", "type": "method", "name": "connect", - "desc": "

    Creates a new client connection to the given port and host (old API) or\noptions.port and options.host. (If host is omitted, it defaults to\nlocalhost.) options should be an object which specifies:\n\n

    \n
      \n
    • host: Host the client should connect to

      \n
    • \n
    • port: Port the client should connect to

      \n
    • \n
    • socket: Establish secure connection on a given socket rather than\ncreating a new socket. If this option is specified, host and port\nare ignored.

      \n
    • \n
    • pfx: A string or Buffer containing the private key, certificate and\nCA certs of the server in PFX or PKCS12 format.

      \n
    • \n
    • key: A string or Buffer containing the private key of the client in\nPEM format.

      \n
    • \n
    • passphrase: A string of passphrase for the private key or pfx.

      \n
    • \n
    • cert: A string or Buffer containing the certificate key of the client in\nPEM format.

      \n
    • \n
    • ca: An array of strings or Buffers of trusted certificates in PEM\nformat. If this is omitted several well known "root" CAs will be used,\nlike VeriSign. These are used to authorize connections.

      \n
    • \n
    • rejectUnauthorized: If true, the server certificate is verified against\nthe list of supplied CAs. An 'error' event is emitted if verification\nfails. Default: true.

      \n
    • \n
    • NPNProtocols: An array of strings or Buffers containing supported NPN\nprotocols. Buffers should have following format: 0x05hello0x05world,\nwhere first byte is next protocol name's length. (Passing array should\nusually be much simpler: ['hello', 'world'].)

      \n
    • \n
    • servername: Servername for SNI (Server Name Indication) TLS extension.

      \n
    • \n
    • secureProtocol: The SSL method to use, e.g. SSLv3_method to force\nSSL version 3. The possible values depend on your installation of\nOpenSSL and are defined in the constant [SSL_METHODS][].

      \n
    • \n
    \n

    The callback parameter will be added as a listener for the\n['secureConnect'][] event.\n\n

    \n

    tls.connect() returns a [tls.TLSSocket][] object.\n\n

    \n

    Here is an example of a client of echo server as described previously:\n\n

    \n
    var tls = require('tls');\nvar fs = require('fs');\n\nvar options = {\n  // These are necessary only if using the client certificate authentication\n  key: fs.readFileSync('client-key.pem'),\n  cert: fs.readFileSync('client-cert.pem'),\n\n  // This is necessary only if the server uses the self-signed certificate\n  ca: [ fs.readFileSync('server-cert.pem') ]\n};\n\nvar socket = tls.connect(8000, options, function() {\n  console.log('client connected',\n              socket.authorized ? 'authorized' : 'unauthorized');\n  process.stdin.pipe(socket);\n  process.stdin.resume();\n});\nsocket.setEncoding('utf8');\nsocket.on('data', function(data) {\n  console.log(data);\n});\nsocket.on('end', function() {\n  server.close();\n});
    \n

    Or\n\n

    \n
    var tls = require('tls');\nvar fs = require('fs');\n\nvar options = {\n  pfx: fs.readFileSync('client.pfx')\n};\n\nvar socket = tls.connect(8000, options, function() {\n  console.log('client connected',\n              socket.authorized ? 'authorized' : 'unauthorized');\n  process.stdin.pipe(socket);\n  process.stdin.resume();\n});\nsocket.setEncoding('utf8');\nsocket.on('data', function(data) {\n  console.log(data);\n});\nsocket.on('end', function() {\n  server.close();\n});
    \n", + "desc": "

    Creates a new client connection to the given port and host (old API) or\noptions.port and options.host. (If host is omitted, it defaults to\nlocalhost.) options should be an object which specifies:\n\n

    \n
      \n
    • host: Host the client should connect to

      \n
    • \n
    • port: Port the client should connect to

      \n
    • \n
    • socket: Establish secure connection on a given socket rather than\ncreating a new socket. If this option is specified, host and port\nare ignored.

      \n
    • \n
    • pfx: A string or Buffer containing the private key, certificate and\nCA certs of the server in PFX or PKCS12 format.

      \n
    • \n
    • key: A string or Buffer containing the private key of the client in\nPEM format.

      \n
    • \n
    • passphrase: A string of passphrase for the private key or pfx.

      \n
    • \n
    • cert: A string or Buffer containing the certificate key of the client in\nPEM format.

      \n
    • \n
    • ca: An array of strings or Buffers of trusted certificates in PEM\nformat. If this is omitted several well known "root" CAs will be used,\nlike VeriSign. These are used to authorize connections.

      \n
    • \n
    • rejectUnauthorized: If true, the server certificate is verified against\nthe list of supplied CAs. An 'error' event is emitted if verification\nfails; err.code contains the OpenSSL error code. Default: true.

      \n
    • \n
    • NPNProtocols: An array of strings or Buffers containing supported NPN\nprotocols. Buffers should have following format: 0x05hello0x05world,\nwhere first byte is next protocol name's length. (Passing array should\nusually be much simpler: ['hello', 'world'].)

      \n
    • \n
    • servername: Servername for SNI (Server Name Indication) TLS extension.

      \n
    • \n
    • secureProtocol: The SSL method to use, e.g. SSLv3_method to force\nSSL version 3. The possible values depend on your installation of\nOpenSSL and are defined in the constant [SSL_METHODS][].

      \n
    • \n
    \n

    The callback parameter will be added as a listener for the\n['secureConnect'][] event.\n\n

    \n

    tls.connect() returns a [tls.TLSSocket][] object.\n\n

    \n

    Here is an example of a client of echo server as described previously:\n\n

    \n
    var tls = require('tls');\nvar fs = require('fs');\n\nvar options = {\n  // These are necessary only if using the client certificate authentication\n  key: fs.readFileSync('client-key.pem'),\n  cert: fs.readFileSync('client-cert.pem'),\n\n  // This is necessary only if the server uses the self-signed certificate\n  ca: [ fs.readFileSync('server-cert.pem') ]\n};\n\nvar socket = tls.connect(8000, options, function() {\n  console.log('client connected',\n              socket.authorized ? 'authorized' : 'unauthorized');\n  process.stdin.pipe(socket);\n  process.stdin.resume();\n});\nsocket.setEncoding('utf8');\nsocket.on('data', function(data) {\n  console.log(data);\n});\nsocket.on('end', function() {\n  server.close();\n});
    \n

    Or\n\n

    \n
    var tls = require('tls');\nvar fs = require('fs');\n\nvar options = {\n  pfx: fs.readFileSync('client.pfx')\n};\n\nvar socket = tls.connect(8000, options, function() {\n  console.log('client connected',\n              socket.authorized ? 'authorized' : 'unauthorized');\n  process.stdin.pipe(socket);\n  process.stdin.resume();\n});\nsocket.setEncoding('utf8');\nsocket.on('data', function(data) {\n  console.log(data);\n});\nsocket.on('end', function() {\n  server.close();\n});
    \n", "signatures": [ { "params": [ @@ -94,7 +100,7 @@ "textRaw": "tls.connect(port, [host], [options], [callback])", "type": "method", "name": "connect", - "desc": "

    Creates a new client connection to the given port and host (old API) or\noptions.port and options.host. (If host is omitted, it defaults to\nlocalhost.) options should be an object which specifies:\n\n

    \n
      \n
    • host: Host the client should connect to

      \n
    • \n
    • port: Port the client should connect to

      \n
    • \n
    • socket: Establish secure connection on a given socket rather than\ncreating a new socket. If this option is specified, host and port\nare ignored.

      \n
    • \n
    • pfx: A string or Buffer containing the private key, certificate and\nCA certs of the server in PFX or PKCS12 format.

      \n
    • \n
    • key: A string or Buffer containing the private key of the client in\nPEM format.

      \n
    • \n
    • passphrase: A string of passphrase for the private key or pfx.

      \n
    • \n
    • cert: A string or Buffer containing the certificate key of the client in\nPEM format.

      \n
    • \n
    • ca: An array of strings or Buffers of trusted certificates in PEM\nformat. If this is omitted several well known "root" CAs will be used,\nlike VeriSign. These are used to authorize connections.

      \n
    • \n
    • rejectUnauthorized: If true, the server certificate is verified against\nthe list of supplied CAs. An 'error' event is emitted if verification\nfails. Default: true.

      \n
    • \n
    • NPNProtocols: An array of strings or Buffers containing supported NPN\nprotocols. Buffers should have following format: 0x05hello0x05world,\nwhere first byte is next protocol name's length. (Passing array should\nusually be much simpler: ['hello', 'world'].)

      \n
    • \n
    • servername: Servername for SNI (Server Name Indication) TLS extension.

      \n
    • \n
    • secureProtocol: The SSL method to use, e.g. SSLv3_method to force\nSSL version 3. The possible values depend on your installation of\nOpenSSL and are defined in the constant [SSL_METHODS][].

      \n
    • \n
    \n

    The callback parameter will be added as a listener for the\n['secureConnect'][] event.\n\n

    \n

    tls.connect() returns a [tls.TLSSocket][] object.\n\n

    \n

    Here is an example of a client of echo server as described previously:\n\n

    \n
    var tls = require('tls');\nvar fs = require('fs');\n\nvar options = {\n  // These are necessary only if using the client certificate authentication\n  key: fs.readFileSync('client-key.pem'),\n  cert: fs.readFileSync('client-cert.pem'),\n\n  // This is necessary only if the server uses the self-signed certificate\n  ca: [ fs.readFileSync('server-cert.pem') ]\n};\n\nvar socket = tls.connect(8000, options, function() {\n  console.log('client connected',\n              socket.authorized ? 'authorized' : 'unauthorized');\n  process.stdin.pipe(socket);\n  process.stdin.resume();\n});\nsocket.setEncoding('utf8');\nsocket.on('data', function(data) {\n  console.log(data);\n});\nsocket.on('end', function() {\n  server.close();\n});
    \n

    Or\n\n

    \n
    var tls = require('tls');\nvar fs = require('fs');\n\nvar options = {\n  pfx: fs.readFileSync('client.pfx')\n};\n\nvar socket = tls.connect(8000, options, function() {\n  console.log('client connected',\n              socket.authorized ? 'authorized' : 'unauthorized');\n  process.stdin.pipe(socket);\n  process.stdin.resume();\n});\nsocket.setEncoding('utf8');\nsocket.on('data', function(data) {\n  console.log(data);\n});\nsocket.on('end', function() {\n  server.close();\n});
    \n", + "desc": "

    Creates a new client connection to the given port and host (old API) or\noptions.port and options.host. (If host is omitted, it defaults to\nlocalhost.) options should be an object which specifies:\n\n

    \n
      \n
    • host: Host the client should connect to

      \n
    • \n
    • port: Port the client should connect to

      \n
    • \n
    • socket: Establish secure connection on a given socket rather than\ncreating a new socket. If this option is specified, host and port\nare ignored.

      \n
    • \n
    • pfx: A string or Buffer containing the private key, certificate and\nCA certs of the server in PFX or PKCS12 format.

      \n
    • \n
    • key: A string or Buffer containing the private key of the client in\nPEM format.

      \n
    • \n
    • passphrase: A string of passphrase for the private key or pfx.

      \n
    • \n
    • cert: A string or Buffer containing the certificate key of the client in\nPEM format.

      \n
    • \n
    • ca: An array of strings or Buffers of trusted certificates in PEM\nformat. If this is omitted several well known "root" CAs will be used,\nlike VeriSign. These are used to authorize connections.

      \n
    • \n
    • rejectUnauthorized: If true, the server certificate is verified against\nthe list of supplied CAs. An 'error' event is emitted if verification\nfails; err.code contains the OpenSSL error code. Default: true.

      \n
    • \n
    • NPNProtocols: An array of strings or Buffers containing supported NPN\nprotocols. Buffers should have following format: 0x05hello0x05world,\nwhere first byte is next protocol name's length. (Passing array should\nusually be much simpler: ['hello', 'world'].)

      \n
    • \n
    • servername: Servername for SNI (Server Name Indication) TLS extension.

      \n
    • \n
    • secureProtocol: The SSL method to use, e.g. SSLv3_method to force\nSSL version 3. The possible values depend on your installation of\nOpenSSL and are defined in the constant [SSL_METHODS][].

      \n
    • \n
    \n

    The callback parameter will be added as a listener for the\n['secureConnect'][] event.\n\n

    \n

    tls.connect() returns a [tls.TLSSocket][] object.\n\n

    \n

    Here is an example of a client of echo server as described previously:\n\n

    \n
    var tls = require('tls');\nvar fs = require('fs');\n\nvar options = {\n  // These are necessary only if using the client certificate authentication\n  key: fs.readFileSync('client-key.pem'),\n  cert: fs.readFileSync('client-cert.pem'),\n\n  // This is necessary only if the server uses the self-signed certificate\n  ca: [ fs.readFileSync('server-cert.pem') ]\n};\n\nvar socket = tls.connect(8000, options, function() {\n  console.log('client connected',\n              socket.authorized ? 'authorized' : 'unauthorized');\n  process.stdin.pipe(socket);\n  process.stdin.resume();\n});\nsocket.setEncoding('utf8');\nsocket.on('data', function(data) {\n  console.log(data);\n});\nsocket.on('end', function() {\n  server.close();\n});
    \n

    Or\n\n

    \n
    var tls = require('tls');\nvar fs = require('fs');\n\nvar options = {\n  pfx: fs.readFileSync('client.pfx')\n};\n\nvar socket = tls.connect(8000, options, function() {\n  console.log('client connected',\n              socket.authorized ? 'authorized' : 'unauthorized');\n  process.stdin.pipe(socket);\n  process.stdin.resume();\n});\nsocket.setEncoding('utf8');\nsocket.on('data', function(data) {\n  console.log(data);\n});\nsocket.on('end', function() {\n  server.close();\n});
    \n", "signatures": [ { "params": [ @@ -409,6 +415,21 @@ ] }, { + "textRaw": "tlsSocket.setMaxSendFragment(size)", + "type": "method", + "name": "setMaxSendFragment", + "desc": "

    Set maximum TLS fragment size (default and maximum value is: 16384, minimum\nis: 512). Returns true on success, false otherwise.\n\n

    \n

    Smaller fragment size decreases buffering latency on the client: large\nfragments are buffered by the TLS layer until the entire fragment is received\nand its integrity is verified; large fragments can span multiple roundtrips,\nand their processing can be delayed due to packet loss or reordering. However,\nsmaller fragments add extra TLS framing bytes and CPU overhead, which may\ndecrease overall server throughput.\n\n

    \n", + "signatures": [ + { + "params": [ + { + "name": "size" + } + ] + } + ] + }, + { "textRaw": "tlsSocket.address()", "type": "method", "name": "address", diff -Nru nodejs-0.11.10/doc/api/tls.markdown nodejs-0.11.11/doc/api/tls.markdown --- nodejs-0.11.10/doc/api/tls.markdown 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/doc/api/tls.markdown 2014-01-29 01:29:56.000000000 +0000 @@ -76,6 +76,31 @@ certificates. +## Perfect Forward Secrecy + + + +The term "[Forward Secrecy]" or "Perfect Forward Secrecy" describes a feature of +key-agreement (i.e. key-exchange) methods. Practically it means that even if the +private key of a (your) server is compromised, communication can only be +decrypted by eavesdroppers if they manage to obtain the key-pair specifically +generated for each session. + +This is achieved by randomly generating a key pair for key-agreement on every +handshake (in contrary to the same key for all sessions). Methods implementing +this technique, thus offering Perfect Forward Secrecy, are called "ephemeral". + +Currently two methods are commonly used to achieve Perfect Forward Secrecy (note +the character "E" appended to the traditional abbreviations): + + * [DHE] - An ephemeral version of the Diffie Hellman key-agreement protocol. + * [ECDHE] - An ephemeral version of the Elliptic Curve Diffie Hellman + key-agreement protocol. + +Ephemeral methods may have some performance drawbacks, because key generation +is expensive. + + ## tls.getCiphers() Returns an array with the names of the supported SSL ciphers. @@ -121,22 +146,22 @@ Consult the [OpenSSL cipher list format documentation] for details on the format. - - `AES128-GCM-SHA256` is used when node.js is linked against OpenSSL 1.0.1 - or newer and the client speaks TLS 1.2, RC4 is used as a secure fallback. + `ECDHE-RSA-AES128-SHA256` and `AES128-GCM-SHA256` are TLS v1.2 ciphers and + used when node.js is linked against OpenSSL 1.0.1 or newer, such as the + bundled version of OpenSSL. Note that it is still possible for a TLS v1.2 + client to negotiate a weaker cipher unless `honorCipherOrder` is enabled. + + `RC4` is used as a fallback for clients that speak on older version of + the TLS protocol. `RC4` has in recent years come under suspicion and + should be considered compromised for anything that is truly sensitive. + It is speculated that state-level actors posess the ability to break it. **NOTE**: Previous revisions of this section suggested `AES256-SHA` as an acceptable cipher. Unfortunately, `AES256-SHA` is a CBC cipher and therefore - susceptible to BEAST attacks. Do *not* use it. - - - `ecdhCurve`: A string describing a named curve to use for ECDH ciphers or - false to disable all ECDH ciphers. + susceptible to [BEAST attacks]. Do *not* use it. - This is required to support ECDH (Elliptic Curve Diffie-Hellman) ciphers. - ECDH ciphers are a newer alternative to RSA. The advantages of ECDH over - RSA is that it offers [Forward secrecy]. Forward secrecy means that for an - attacker it won't be possible to decrypt your previous data exchanges if - they get access to your private key. + - `ecdhCurve`: A string describing a named curve to use for ECDH key agreement + or false to disable ECDH. Defaults to `prime256v1`. Consult [RFC 4492] for more details. @@ -149,13 +174,14 @@ - `honorCipherOrder` : When choosing a cipher, use the server's preferences instead of the client preferences. - Note that if SSLv2 is used, the server will send its list of preferences - to the client, and the client chooses the cipher. - Although, this option is disabled by default, it is *recommended* that you use this option in conjunction with the `ciphers` option to mitigate BEAST attacks. + Note: If SSLv2 is used, the server will send its list of preferences to the + client, and the client chooses the cipher. Support for SSLv2 is disabled + unless node.js was configured with `./configure --with-sslv2`. + - `requestCert`: If `true` the server will request a certificate from clients that connect and attempt to verify that certificate. Default: `false`. @@ -275,7 +301,7 @@ - `rejectUnauthorized`: If `true`, the server certificate is verified against the list of supplied CAs. An `'error'` event is emitted if verification - fails. Default: `true`. + fails; `err.code` contains the OpenSSL error code. Default: `true`. - `NPNProtocols`: An array of strings or `Buffer`s containing supported NPN protocols. `Buffer`s should have following format: `0x05hello0x05world`, @@ -608,6 +634,18 @@ ANOTHER NOTE: When running as the server, socket will be destroyed with an error after `handshakeTimeout` timeout. +### tlsSocket.setMaxSendFragment(size) + +Set maximum TLS fragment size (default and maximum value is: `16384`, minimum +is: `512`). Returns `true` on success, `false` otherwise. + +Smaller fragment size decreases buffering latency on the client: large +fragments are buffered by the TLS layer until the entire fragment is received +and its integrity is verified; large fragments can span multiple roundtrips, +and their processing can be delayed due to packet loss or reordering. However, +smaller fragments add extra TLS framing bytes and CPU overhead, which may +decrease overall server throughput. + ### tlsSocket.address() Returns the bound address, the address family name and port of the @@ -648,3 +686,5 @@ [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 +[DHE]: https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange +[ECDHE]: https://en.wikipedia.org/wiki/Elliptic_curve_Diffie%E2%80%93Hellman diff -Nru nodejs-0.11.10/doc/api/tty.html nodejs-0.11.11/doc/api/tty.html --- nodejs-0.11.10/doc/api/tty.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/tty.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - TTY Node.js v0.11.10 Manual & Documentation + TTY Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -158,7 +158,7 @@

  • -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/api/url.html nodejs-0.11.11/doc/api/url.html --- nodejs-0.11.10/doc/api/url.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/url.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - URL Node.js v0.11.10 Manual & Documentation + URL Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -175,7 +175,7 @@

  • -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/api/util.html nodejs-0.11.11/doc/api/util.html --- nodejs-0.11.10/doc/api/util.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/util.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - util Node.js v0.11.10 Manual & Documentation + util Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -362,7 +362,7 @@

  • -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/api/vm.html nodejs-0.11.11/doc/api/vm.html --- nodejs-0.11.10/doc/api/vm.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/vm.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - Executing JavaScript Node.js v0.11.10 Manual & Documentation + Executing JavaScript Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -349,7 +349,7 @@

  • -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/api/zlib.html nodejs-0.11.11/doc/api/zlib.html --- nodejs-0.11.10/doc/api/zlib.html 2014-01-01 00:12:16.000000000 +0000 +++ nodejs-0.11.11/doc/api/zlib.html 2014-01-29 03:26:35.000000000 +0000 @@ -2,7 +2,7 @@ - Zlib Node.js v0.11.10 Manual & Documentation + Zlib Node.js v0.11.11 Manual & Documentation @@ -31,7 +31,7 @@
    -

    Node.js v0.11.10 Manual & Documentation

    +

    Node.js v0.11.11 Manual & Documentation

    Index | @@ -482,7 +482,7 @@

  • -

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    +

    Copyright Joyent, Inc, Node.js is a trademark of Joyent, Inc. View license.

    diff -Nru nodejs-0.11.10/doc/blog/Uncategorized/tj-fontaine-new-node-lead.md nodejs-0.11.11/doc/blog/Uncategorized/tj-fontaine-new-node-lead.md --- nodejs-0.11.10/doc/blog/Uncategorized/tj-fontaine-new-node-lead.md 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/doc/blog/Uncategorized/tj-fontaine-new-node-lead.md 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,54 @@ +title: The Next Phase of Node.js +date: Wed Jan 15 09:00:00 PST 2014 +author: Isaac Z. Schlueter +slug: the-next-phase-of-node-js + +Node's growth has continued and accelerated immensely over the last +few years. More people are developing and sharing more code with Node +and npm than I would have ever imagined. Countless companies are +using Node, and npm along with it. + +Over the last year, [TJ Fontaine](https://twitter.com/tjfontaine) has become absolutely essential to the +Node.js project. He's been building releases, managing the test bots, +[fixing nasty +bugs](http://www.joyent.com/blog/walmart-node-js-memory-leak) and +making decisions for the project with constant focus on the needs of +our users. He was responsible for an update to MDB to [support +running ::findjsobjects on Linux core +dumps](http://www.slideshare.net/bcantrill/node-summit2013), and is +working on a shim layer that will provide a stable C interface for +Node binary addons. In partnership with Joyent and The Node Firm, +he's helped to create a path forward for scalable issue triaging. +He's become the primary point of contact keeping us all driving the +project forward together. + +Anyone who's been close to the core project knows that he's been +effectively leading the project for a while now, so we're making it +official. Effective immediately, TJ Fontaine is the Node.js project +lead. I will remain a Node core committer, and expect to continue to +contribute to the project in that role. My primary focus, however, +will be npm. + +At this point, npm needs work, and I am eager to deliver what the Node +community needs from its package manager. I am starting a company, +npm, Inc., to deliver new products and services related to npm. I'll +be sharing many more details soon about exactly how this is going to +work, and what we'll be offering. For now, suffice it to say that +everything currently free will remain free, and everything currently +flaky will get less flaky. Pursuing new revenue is how we can keep +providing the npm registry service in a long-term sustainable way, and +it has to be done very carefully so that we don't damage what we've +all built together. + +npm is what I'm most passionate about, and I am now in a position to +give it my full attention. I've done more than I could have hoped to +accomplish in running Node core, and it's well past time to hand the +control of the project off to its next gatekeeper. + +TJ is exactly the leader who can help us take Node.js to 1.0 and +beyond. He brings professionalism, rigor, and a continued focus on +inclusive community values and culture. In the coming days, TJ will +spell out his plans in greater detail. I look forward to the places +that Node will go with his guidance. + +Please join me in welcoming him to this new role :) diff -Nru nodejs-0.11.10/doc/blog/nodejs-road-ahead.md nodejs-0.11.11/doc/blog/nodejs-road-ahead.md --- nodejs-0.11.10/doc/blog/nodejs-road-ahead.md 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/doc/blog/nodejs-road-ahead.md 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,52 @@ +title: Node.js and the Road Ahead +date: Thu Jan 16 15:00:00 PST 2014 +author: Timothy J Fontaine +slug: nodejs-road-ahead + +As the new project lead for Node.js I am excited for our future, and want to +give you an update on where we are. + +One of Node's major goals is to provide a small core, one that provides the +right amount of surface area for consumers to achieve and innovate, without +Node itself getting in the way. That ethos is alive and well, we're going to +continue to provide a small, simple, and stable set of APIs that facilitate the +amazing uses the community finds for Node. We're going to keep providing +backward compatible APIs, so code you write today will continue to work on +future versions of Node. And of course, performance tuning and bug fixing will +always be an important part of every release cycle. + +The release of Node v0.12 is imminent, and a lot of significant work has gone +into this release. There's streams3, a better keep alive agent for http, the vm +module is now based on contextify, and significant performance work done in +core features (Buffers, TLS, streams). We have a few APIs that are still being +ironed out before we can feature freeze and branch (execSync, AsyncListeners, +user definable instrumentation). We are definitely in the home stretch. + +But Node is far from done. In the short term there will be new releases of v8 +that we'll need to track, as well as integrating the new ABI stable C module +interface. There are interesting language features that we can use to extend +Node APIs (extend not replace). We need to write more tooling, we need to +expose more interfaces to further enable innovation. We can explore +functionality to embed Node in your existing project. + +The list can go on and on. Yet, Node is larger than the software itself. Node +is also the community, the businesses, the ecosystems, and their related +events. With that in mind there are things we can work to improve. + +The core team will be improving its procedures such that we can quickly and +efficiently communicate with you. We want to provide high quality and timely +responses to issues, describe our development roadmap, as well as provide our +progress during each release cycle. We know you're interested in our plans for +Node, and it's important we're able to provide that information. Communication +should be bidirectional: we want to continue to receive feedback about how +you're using Node, and what your pain points are. + +After the release of v0.12 we will facilitate the community to contribute and +curate content for nodejs.org. Allowing the community to continue to invest in +Node will ensure nodejs.org is an excellent starting point and the primary +resource for tutorials, documentation, and materials regarding Node. We have an +awesome and engaged community, and they're paramount to our success. + +I'm excited for Node's future, to see new and interesting use cases, and to +continue to help businesses scale and innovate with Node. We have a lot we can +accomplish together, and I look forward to seeing those results. diff -Nru nodejs-0.11.10/doc/blog/release/v0.10.25.md nodejs-0.11.11/doc/blog/release/v0.10.25.md --- nodejs-0.11.10/doc/blog/release/v0.10.25.md 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/doc/blog/release/v0.10.25.md 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,72 @@ +date: Thu Jan 23 11:43:30 PST 2014 +version: 0.10.25 +category: release +title: Node v0.10.25 (Stable) +slug: node-v0-10-25-stable + +2014.01.23, Version 0.10.25 (Stable) + +* uv: Upgrade to v0.10.23 + +* npm: Upgrade to v1.3.24 + +* v8: Fix enumeration for objects with lots of properties + +* child_process: fix spawn() optional arguments (Sam Roberts) + +* cluster: report more errors to workers (Fedor Indutny) + +* domains: exit() only affects active domains (Ryan Graham) + +* src: OnFatalError handler must abort() (Timothy J Fontaine) + +* stream: writes may return false but forget to emit drain (Yang Tianyang) + + +Source Code: http://nodejs.org/dist/v0.10.25/node-v0.10.25.tar.gz + +Macintosh Installer (Universal): http://nodejs.org/dist/v0.10.25/node-v0.10.25.pkg + +Windows Installer: http://nodejs.org/dist/v0.10.25/node-v0.10.25-x86.msi + +Windows x64 Installer: http://nodejs.org/dist/v0.10.25/x64/node-v0.10.25-x64.msi + +Windows x64 Files: http://nodejs.org/dist/v0.10.25/x64/ + +Linux 32-bit Binary: http://nodejs.org/dist/v0.10.25/node-v0.10.25-linux-x86.tar.gz + +Linux 64-bit Binary: http://nodejs.org/dist/v0.10.25/node-v0.10.25-linux-x64.tar.gz + +Solaris 32-bit Binary: http://nodejs.org/dist/v0.10.25/node-v0.10.25-sunos-x86.tar.gz + +Solaris 64-bit Binary: http://nodejs.org/dist/v0.10.25/node-v0.10.25-sunos-x64.tar.gz + +Other release files: http://nodejs.org/dist/v0.10.25/ + +Website: http://nodejs.org/docs/v0.10.25/ + +Documentation: http://nodejs.org/docs/v0.10.25/api/ + +Shasums: +``` +b347508376ceef724b464e6009ec2daead7ea572 node-v0.10.25-darwin-x64.tar.gz +f7b3c7a36b45a83360bcd9e541e64bf18ef29272 node-v0.10.25-darwin-x86.tar.gz +7c75e7e13561be1222bddd438a84a8f228fe1bc3 node-v0.10.25-linux-x64.tar.gz +16a2c861de5b27ef907dc18253fcd4f33d506662 node-v0.10.25-linux-x86.tar.gz +05bdc1cd7933ccfa95c2f1f058ff0125eacbdc2d node-v0.10.25-sunos-x64.tar.gz +250a48c9a2b6c6a8a6feebb0d7d33f96bf8d82f4 node-v0.10.25-sunos-x86.tar.gz +ce78cc8b49e339f71888f627c4e985dda0a83e27 node-v0.10.25-x86.msi +abab975e86250b51a7434d229d13b30acdf4e82e node-v0.10.25.pkg +1e330b4fbb6f7bb858a0b37d8573dd4956f40885 node-v0.10.25.tar.gz +e3779ed14a68dc6f711ead628fe11a127d09547c node.exe +35521b6142d39fa371aba7d1fda87a1836db78e4 node.exp +35eb46e5d04fdb1c1417876d1712b85eea6be03c node.lib +cc749498572b4cf4b277225404beefdd75a4e903 node.pdb +9bf1bf3a59a3f0dc0fd32f9504e8011e5b4ebc42 pkgsrc/nodejs-ia32-0.10.25.tgz +f4a6e7d561c321b917c1b6a021fe38cd330a374e pkgsrc/nodejs-x64-0.10.25.tgz +aab984860cc02e1d27a0932c4c8d34e5e3551ebf x64/node-v0.10.25-x64.msi +d2f884d75d5f30693f62625787f27fb2a8824178 x64/node.exe +75cdbe43984c9a9f6c5f1e5875fa7422c97b2d62 x64/node.exp +108c2d9dd6ecf7cad83c4cb5cd62303f51c5570a x64/node.lib +a7c37dadc994c281d08f6a55bfbd01ecf738fe66 x64/node.pdb +``` diff -Nru nodejs-0.11.10/doc/blog/release/v0.11.10.md nodejs-0.11.11/doc/blog/release/v0.11.10.md --- nodejs-0.11.10/doc/blog/release/v0.11.10.md 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/doc/blog/release/v0.11.10.md 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,106 @@ +date: Tue Dec 31 16:20:57 PST 2013 +version: 0.11.10 +category: release +title: Node v0.11.10 (Unstable) +slug: node-v0-11-10-unstable + +2013.12.31, Version 0.11.10 (Unstable) + +* http_parser: update to 2.2 + +* uv: Upgrade to v0.11.17 + +* v8: Upgrade to 3.22.24.10 + +* buffer: optimize writeInt* methods (Paul Loyd) + +* child_process: better error handling (Alexis Campailla) + +* cluster: do not synchronously emit 'setup' event (Sam Roberts) + +* cluster: restore backwards compatibility and various fixes (Sam Roberts) + +* crypto: remove unnecessary OpenSSL_add_all_digests (Yorkie) + +* crypto: support GCM authenticated encryption mode. (Ingmar Runge) + +* dns: add resolveSoa and 'SOA' rrtype (TuÄŸrul Topuz) + +* events: move EE c'tor guts to EventEmitter.init (Bert Belder) + +* http: DELETE shouldn't default to chunked encoding (Lalit Kapoor) + +* http: parse the status message in a http response. (Cam Swords) + +* node: fix removing AsyncListener in callback (Vladimir Kurchatkin) + +* node: follow specification, zero-fill ArrayBuffers (Trevor Norris) + +* openssl: use ASM optimized routines (Fedor Indutny) + +* process: allow nextTick infinite recursion (Trevor Norris) + +* querystring: remove `name` from `stringify()` (Yorkie) + +* timers: setImmediate v8 optimization fix (pflannery) + +* tls: add serialNumber to getPeerCertificate() (Ben Noordhuis) + +* tls: reintroduce socket.encrypted (Fedor Indutny) + +* tls: fix handling of asterisk in SNI context (Fedor Indutny) + +* util: Format negative zero as '-0' (David Chan) + +* vm: fix race condition in timeout (Alexis Campailla) + +* windows: fix dns lookup of localhost with ipv6 (Alexis Campailla) + + +Source Code: http://nodejs.org/dist/v0.11.10/node-v0.11.10.tar.gz + +Macintosh Installer (Universal): http://nodejs.org/dist/v0.11.10/node-v0.11.10.pkg + +Windows Installer: http://nodejs.org/dist/v0.11.10/node-v0.11.10-x86.msi + +Windows x64 Installer: http://nodejs.org/dist/v0.11.10/x64/node-v0.11.10-x64.msi + +Windows x64 Files: http://nodejs.org/dist/v0.11.10/x64/ + +Linux 32-bit Binary: http://nodejs.org/dist/v0.11.10/node-v0.11.10-linux-x86.tar.gz + +Linux 64-bit Binary: http://nodejs.org/dist/v0.11.10/node-v0.11.10-linux-x64.tar.gz + +Solaris 32-bit Binary: http://nodejs.org/dist/v0.11.10/node-v0.11.10-sunos-x86.tar.gz + +Solaris 64-bit Binary: http://nodejs.org/dist/v0.11.10/node-v0.11.10-sunos-x64.tar.gz + +Other release files: http://nodejs.org/dist/v0.11.10/ + +Website: http://nodejs.org/docs/v0.11.10/ + +Documentation: http://nodejs.org/docs/v0.11.10/api/ + +Shasums: +``` +4f7d0d43c1ee7593035ddb3cf09020a18a03c794 node-v0.11.10-darwin-x64.tar.gz +3b7100bcff39e39b6db5118805fcfc76d8524da2 node-v0.11.10-darwin-x86.tar.gz +3df4cb183a78bb975c831155d3c0aa29a274dec4 node-v0.11.10-linux-x64.tar.gz +12fc680b0a26cc73b4df0a0e9544b0db2bc06e96 node-v0.11.10-linux-x86.tar.gz +145417c8d801174a42255dc273da962cde94ffc9 node-v0.11.10-sunos-x64.tar.gz +981baba494e9be8978fa1bb336b3048367e809ce node-v0.11.10-sunos-x86.tar.gz +5f4d96c37cfb1423cc844f52e0547cb5bca99dd8 node-v0.11.10-x86.msi +8bd455fb7539609a7ee6bed87875a908fd6221ea node-v0.11.10.pkg +b860f511e4fc657a64594fc9f3f1225c1a140e5e node-v0.11.10.tar.gz +80976bffed871310a86d31694e2767ccbe9f6c35 node.exe +f11675958a492a83f057f356dd224ad507e82c61 node.exp +5a80c4ab5b1d0984b3a118536ca6421b4b9bc14f node.lib +207daafc40fba36200504fa52869b9c41cdbf5c9 node.pdb +3aa165e2d235888037f8099abd5bc9dca4b12100 pkgsrc/nodejs-ia32-0.11.10.tgz +1d5ef599b93c7d8c0d34ff2ab3dd4255babfaf72 pkgsrc/nodejs-x64-0.11.10.tgz +a6b16441721c34bae732b2b14134d0e1fd9706de x64/node-v0.11.10-x64.msi +933ff8a0a42c6e69fcbd51b9eaae4e4d14f043ae x64/node.exe +31c9abd54e5ba431f0645fa04d315f15dc010107 x64/node.exp +66bec5eae9033972463a6bd89183aa97bb84bfd1 x64/node.lib +43fbac8665dfcd121e547f56b1434a1c6039091d x64/node.pdb +``` diff -Nru nodejs-0.11.10/lib/_debugger.js nodejs-0.11.11/lib/_debugger.js --- nodejs-0.11.10/lib/_debugger.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/lib/_debugger.js 2014-01-29 01:29:56.000000000 +0000 @@ -25,6 +25,7 @@ vm = require('vm'), repl = require('repl'), inherits = util.inherits, + assert = require('assert'), spawn = require('child_process').spawn; exports.start = function(argv, stdin, stdout) { @@ -1612,6 +1613,7 @@ childArgs = this.args; this.killChild(); + assert(!this.child); if (this.args.length === 2) { var match = this.args[1].match(/^([^:]+):(\d+)$/); @@ -1647,12 +1649,10 @@ } } - if (!this.child) { - this.child = spawn(process.execPath, childArgs); + this.child = spawn(process.execPath, childArgs); - this.child.stdout.on('data', this.childPrint.bind(this)); - this.child.stderr.on('data', this.childPrint.bind(this)); - } + this.child.stdout.on('data', this.childPrint.bind(this)); + this.child.stderr.on('data', this.childPrint.bind(this)); this.pause(); @@ -1709,8 +1709,10 @@ client.connect(port, host); } - setTimeout(function() { - self.print('connecting to port ' + port + '..', true); - attemptConnect(); - }, 50); + this.child.stderr.once('data', function() { + setImmediate(function() { + self.print('connecting to port ' + port + '..', true); + attemptConnect(); + }); + }); }; diff -Nru nodejs-0.11.10/lib/_http_client.js nodejs-0.11.11/lib/_http_client.js --- nodejs-0.11.10/lib/_http_client.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/lib/_http_client.js 2014-01-29 01:29:56.000000000 +0000 @@ -457,12 +457,8 @@ var req = this; process.nextTick(function() { - // If a domain was added to the request, attach it to the socket. - if (req.domain) - socket._handle.addAsyncListener(req.domain._listener); tickOnSocket(req, socket); }); - }; ClientRequest.prototype._deferToConnect = function(method, arguments_, cb) { diff -Nru nodejs-0.11.10/lib/_http_incoming.js nodejs-0.11.11/lib/_http_incoming.js --- nodejs-0.11.10/lib/_http_incoming.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/lib/_http_incoming.js 2014-01-29 01:29:56.000000000 +0000 @@ -98,9 +98,7 @@ // We actually do almost nothing here, because the parserOnBody // function fills up our internal buffer directly. However, we // do need to unpause the underlying socket so that it flows. - if (!this.socket.readable) - this.push(null); - else + if (this.socket.readable) readStart(this.socket); }; @@ -154,40 +152,32 @@ } break; - // Comma separate. Maybe make these arrays? - case 'accept': - case 'accept-charset': - case 'accept-encoding': - case 'accept-language': - case 'connection': - case 'cookie': - case 'pragma': - case 'link': - case 'www-authenticate': - case 'proxy-authenticate': - case 'sec-websocket-extensions': - case 'sec-websocket-protocol': - if (!util.isUndefined(dest[field])) { - dest[field] += ', ' + value; - } else { + // list is taken from: + // https://mxr.mozilla.org/mozilla/source/netwerk/protocol/http/src/nsHttpHeaderArray.cpp + case 'content-type': + case 'content-length': + case 'user-agent': + case 'referer': + case 'host': + case 'authorization': + case 'proxy-authorization': + case 'if-modified-since': + case 'if-unmodified-since': + case 'from': + case 'location': + case 'max-forwards': + // drop duplicates + if (util.isUndefined(dest[field])) dest[field] = value; - } break; - default: - if (field.slice(0, 2) == 'x-') { - // except for x- - if (!util.isUndefined(dest[field])) { - dest[field] += ', ' + value; - } else { - dest[field] = value; - } - } else { - // drop duplicates - if (util.isUndefined(dest[field])) dest[field] = value; + // make comma-separated list + if (!util.isUndefined(dest[field])) + dest[field] += ', ' + value; + else { + dest[field] = value; } - break; } }; diff -Nru nodejs-0.11.10/lib/_http_outgoing.js nodejs-0.11.11/lib/_http_outgoing.js --- nodejs-0.11.10/lib/_http_outgoing.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/lib/_http_outgoing.js 2014-01-29 01:29:56.000000000 +0000 @@ -438,14 +438,18 @@ else len = chunk.length; - if (this.connection) + if (this.connection && !this.connection.corked) { this.connection.cork(); + var conn = this.connection; + process.nextTick(function connectionCork() { + if (conn) + conn.uncork(); + }); + } this._send(len.toString(16), 'binary', null); this._send(crlf_buf, null, null); this._send(chunk, encoding, null); ret = this._send(crlf_buf, null, callback); - if (this.connection) - this.connection.uncork(); } } else { ret = this._send(chunk, encoding, callback); diff -Nru nodejs-0.11.10/lib/_stream_writable.js nodejs-0.11.11/lib/_stream_writable.js --- nodejs-0.11.10/lib/_stream_writable.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/lib/_stream_writable.js 2014-01-29 01:29:56.000000000 +0000 @@ -115,6 +115,9 @@ // emit prefinish if the only thing we're waiting for is _write cbs // This is relevant for synchronous Transform streams this.prefinished = false; + + // Internal, used in net.js and _tls_wrap.js + this._errorEmitted = false; } function Writable(options) { @@ -236,7 +239,9 @@ state.length += len; var ret = state.length < state.highWaterMark; - state.needDrain = !ret; + // we must ensure that previous needDrain will not be reset to false. + if (!ret) + state.needDrain = true; if (state.writing || state.corked) state.buffer.push(new WriteReq(chunk, encoding, cb)); @@ -270,6 +275,7 @@ } stream.emit('error', er); + stream._errorEmitted = true; } function onwriteStateUpdate(state) { diff -Nru nodejs-0.11.10/lib/_tls_wrap.js nodejs-0.11.11/lib/_tls_wrap.js --- nodejs-0.11.10/lib/_tls_wrap.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/lib/_tls_wrap.js 2014-01-29 01:29:56.000000000 +0000 @@ -178,15 +178,18 @@ this.on('error', this._tlsError); - if (!this._handle) - this.once('connect', this._init.bind(this)); - else - this._init(); + if (!this._handle) { + this.once('connect', function() { + this._init(null); + }); + } else { + this._init(socket); + } } util.inherits(TLSSocket, net.Socket); exports.TLSSocket = TLSSocket; -TLSSocket.prototype._init = function() { +TLSSocket.prototype._init = function(socket) { assert(this._handle); // lib/net.js expect this value to be non-zero if write hasn't been flushed @@ -232,6 +235,10 @@ } this.ssl.onerror = function(err) { + if (self._errorEmitted) + return; + self._errorEmitted = true; + // Destroy socket if error happened before handshake's finish if (!this._secureEstablished) { self._tlsError(err); @@ -265,6 +272,13 @@ if (options.handshakeTimeout > 0) this.setTimeout(options.handshakeTimeout, this._handleTimeout); + + // Socket already has some buffered data - emulate receiving it + if (socket && socket._readableState.length) { + var buf; + while ((buf = socket.read()) !== null) + this.ssl.receive(buf); + } }; TLSSocket.prototype.renegotiate = function(options, callback) { @@ -303,6 +317,10 @@ return true; }; +TLSSocket.prototype.setMaxSendFragment = function setMaxSendFragment(size) { + return this.ssl.setMaxSendFragment(size) == 1; +}; + TLSSocket.prototype._handleTimeout = function() { this._tlsError(new Error('TLS handshake timeout')); }; @@ -475,10 +493,6 @@ // Handle option defaults: this.setOptions(options); - if (!self.pfx && (!self.cert || !self.key)) { - throw new Error('Missing PFX or certificate + private key.'); - } - var sharedCreds = crypto.createCredentials({ pfx: self.pfx, key: self.key, @@ -526,7 +540,7 @@ if (socket._requestCert) { var verifyError = socket.ssl.verifyError(); if (verifyError) { - socket.authorizationError = verifyError.message; + socket.authorizationError = verifyError.code; if (socket._rejectUnauthorized) socket.destroy(); @@ -539,9 +553,22 @@ self.emit('secureConnection', socket); }); + var errorEmitted = false; + socket.on('close', function() { + // Emit ECONNRESET + if (!socket._controlReleased && !errorEmitted) { + errorEmitted = true; + var connReset = new Error('socket hang up'); + connReset.code = 'ECONNRESET'; + self.emit('clientError', connReset, socket); + } + }); + socket.on('_tlsError', function(err) { - if (!socket._controlReleased) + if (!socket._controlReleased && !errorEmitted) { + errorEmitted = true; self.emit('clientError', err, socket); + } }); }); @@ -691,7 +718,8 @@ var cb = args[1]; var defaults = { - rejectUnauthorized: '0' !== process.env.NODE_TLS_REJECT_UNAUTHORIZED + rejectUnauthorized: '0' !== process.env.NODE_TLS_REJECT_UNAUTHORIZED, + ciphers: tls.DEFAULT_CIPHERS }; options = util._extend(defaults, options || {}); @@ -788,7 +816,7 @@ if (verifyError) { result.authorized = false; - result.authorizationError = verifyError.message; + result.authorizationError = verifyError.code || verifyError.message; if (options.rejectUnauthorized) { result.emit('error', verifyError); diff -Nru nodejs-0.11.10/lib/child_process.js nodejs-0.11.11/lib/child_process.js --- nodejs-0.11.10/lib/child_process.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/lib/child_process.js 2014-01-29 01:29:56.000000000 +0000 @@ -664,7 +664,7 @@ var exited = false; var timeoutId; - var ex; + var ex = null; function exithandler(code, signal) { if (exited) return; @@ -689,16 +689,25 @@ } if (ex) { - callback(ex, stdout, stderr); + // Will be handled later } else if (code === 0 && signal === null) { callback(null, stdout, stderr); - } else { - ex = new Error('Command failed: ' + stderr); + return; + } + + var cmd = file; + if (args.length !== 0) + cmd += ' ' + args.join(' '); + + if (!ex) { + ex = new Error('Command failed: ' + cmd + '\n' + stderr); ex.killed = child.killed || killed; ex.code = code < 0 ? uv.errname(code) : code; ex.signal = signal; - callback(ex, stdout, stderr); } + + ex.cmd = cmd; + callback(ex, stdout, stderr); } function errorhandler(e) { @@ -768,8 +777,16 @@ }; -var spawn = exports.spawn = function(file, args, options) { - args = args ? args.slice(0) : []; +var spawn = exports.spawn = function(file /*, args, options*/) { + var args, options; + if (Array.isArray(arguments[1])) { + args = arguments[1].slice(0); + options = arguments[2]; + } else { + args = []; + options = arguments[1]; + } + args.unshift(file); var env = (options ? options.env : null) || process.env; diff -Nru nodejs-0.11.10/lib/crypto.js nodejs-0.11.11/lib/crypto.js --- nodejs-0.11.10/lib/crypto.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/lib/crypto.js 2014-01-29 01:29:56.000000000 +0000 @@ -35,6 +35,7 @@ throw new Error('node.js not compiled with openssl crypto support.'); } +var constants = require('constants'); var stream = require('stream'); var util = require('util'); @@ -77,6 +78,18 @@ exports.Credentials = Credentials; +function addNewline(buf) { + var last = buf[buf.length - 1]; + var isBuf = Buffer.isBuffer(buf); + + if (!isBuf && !util.isString(buf)) + throw new Error('Certificate should be of type Buffer or string'); + + if (isBuf ? last !== 10 : last !== '\n') + return buf.toString().trim() + '\n'; + else + return buf; +} exports.createCredentials = function(options, context) { if (!options) options = {}; @@ -88,14 +101,15 @@ if (context) return c; if (options.key) { + var key = addNewline(options.key); if (options.passphrase) { - c.context.setKey(options.key, options.passphrase); + c.context.setKey(key, options.passphrase); } else { - c.context.setKey(options.key); + c.context.setKey(key); } } - if (options.cert) c.context.setCert(options.cert); + if (options.cert) c.context.setCert(addNewline(options.cert)); if (options.ciphers) c.context.setCiphers(options.ciphers); @@ -561,36 +575,47 @@ -exports.pbkdf2 = function(password, salt, iterations, keylen, callback) { +exports.pbkdf2 = function(password, + salt, + iterations, + keylen, + digest, + callback) { + if (util.isFunction(digest)) { + callback = digest; + digest = undefined; + } + if (!util.isFunction(callback)) throw new Error('No callback provided to pbkdf2'); - return pbkdf2(password, salt, iterations, keylen, callback); + return pbkdf2(password, salt, iterations, keylen, digest, callback); }; -exports.pbkdf2Sync = function(password, salt, iterations, keylen) { - return pbkdf2(password, salt, iterations, keylen); +exports.pbkdf2Sync = function(password, salt, iterations, keylen, digest) { + return pbkdf2(password, salt, iterations, keylen, digest); }; -function pbkdf2(password, salt, iterations, keylen, callback) { +function pbkdf2(password, salt, iterations, keylen, digest, callback) { password = toBuf(password); salt = toBuf(salt); if (exports.DEFAULT_ENCODING === 'buffer') - return binding.PBKDF2(password, salt, iterations, keylen, callback); + return binding.PBKDF2(password, salt, iterations, keylen, digest, callback); // at this point, we need to handle encodings. var encoding = exports.DEFAULT_ENCODING; if (callback) { - binding.PBKDF2(password, salt, iterations, keylen, function(er, ret) { + function next(er, ret) { if (ret) ret = ret.toString(encoding); callback(er, ret); - }); + } + binding.PBKDF2(password, salt, iterations, keylen, digest, next); } else { - var ret = binding.PBKDF2(password, salt, iterations, keylen); + var ret = binding.PBKDF2(password, salt, iterations, keylen, digest); return ret.toString(encoding); } } @@ -621,6 +646,21 @@ }; +exports.setEngine = function setEngine(id, flags) { + if (!util.isString(id)) + throw new TypeError('id should be a string'); + + if (flags && !util.isNumber(flags)) + throw new TypeError('flags should be a number, if present'); + flags = flags >>> 0; + + // Use provided engine for everything by default + if (flags === 0) + flags = constants.ENGINE_METHOD_ALL; + + return binding.setEngine(id, flags); +}; + exports.randomBytes = randomBytes; exports.pseudoRandomBytes = pseudoRandomBytes; diff -Nru nodejs-0.11.10/lib/domain.js nodejs-0.11.11/lib/domain.js --- nodejs-0.11.10/lib/domain.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/lib/domain.js 2014-01-29 01:29:56.000000000 +0000 @@ -28,6 +28,26 @@ // a few side effects. EventEmitter.usingDomains = true; +// overwrite process.domain with a getter/setter that will allow for more +// effective optimizations +var _domain = [null]; +Object.defineProperty(process, 'domain', { + enumerable: true, + get: function() { + return _domain[0]; + }, + set: function(arg) { + return _domain[0] = arg; + } +}); + +// objects with external array data are excellent ways to communicate state +// between js and c++ w/o much overhead +var _domain_flag = {}; + +// let the process know we're using domains +process._setupDomainUse(_domain, _domain_flag); + exports.Domain = Domain; exports.create = exports.createDomain = function() { @@ -42,74 +62,66 @@ exports.active = null; -function noop() { } - - -var listenerObj = { - error: function errorHandler(domain, er) { - var caught = false; - // ignore errors on disposed domains. - // - // XXX This is a bit stupid. We should probably get rid of - // domain.dispose() altogether. It's almost always a terrible - // idea. --isaacs - if (domain._disposed) - return true; - - er.domain = domain; - er.domainThrown = true; - // wrap this in a try/catch so we don't get infinite throwing - try { - // One of three things will happen here. - // - // 1. There is a handler, caught = true - // 2. There is no handler, caught = false - // 3. It throws, caught = false - // - // If caught is false after this, then there's no need to exit() - // the domain, because we're going to crash the process anyway. - caught = domain.emit('error', er); - - if (stack.length === 0) - process.removeAsyncListener(domain._listener); - - // Exit all domains on the stack. Uncaught exceptions end the - // current tick and no domains should be left on the stack - // between ticks. - stack.length = 0; - exports.active = process.domain = null; - } catch (er2) { - // The domain error handler threw! oh no! - // See if another domain can catch THIS error, - // or else crash on the original one. - // If the user already exited it, then don't double-exit. - if (domain === exports.active) { - stack.pop(); - } - if (stack.length) { - exports.active = process.domain = stack[stack.length - 1]; - caught = process._fatalException(er2); - } else { - caught = false; - } - return caught; - } - return caught; - } -}; - - inherits(Domain, EventEmitter); function Domain() { EventEmitter.call(this); + this.members = []; - this._listener = process.createAsyncListener(noop, listenerObj, this); } Domain.prototype.members = undefined; Domain.prototype._disposed = undefined; -Domain.prototype._listener = undefined; + + +// Called by process._fatalException in case an error was thrown. +Domain.prototype._errorHandler = function errorHandler(er) { + var caught = false; + // ignore errors on disposed domains. + // + // XXX This is a bit stupid. We should probably get rid of + // domain.dispose() altogether. It's almost always a terrible + // idea. --isaacs + if (this._disposed) + return true; + + er.domain = this; + er.domainThrown = true; + // wrap this in a try/catch so we don't get infinite throwing + try { + // One of three things will happen here. + // + // 1. There is a handler, caught = true + // 2. There is no handler, caught = false + // 3. It throws, caught = false + // + // If caught is false after this, then there's no need to exit() + // the domain, because we're going to crash the process anyway. + caught = this.emit('error', er); + + // Exit all domains on the stack. Uncaught exceptions end the + // current tick and no domains should be left on the stack + // between ticks. + stack.length = 0; + exports.active = process.domain = null; + } catch (er2) { + // The domain error handler threw! oh no! + // See if another domain can catch THIS error, + // or else crash on the original one. + // If the user already exited it, then don't double-exit. + if (this === exports.active) { + stack.pop(); + } + if (stack.length) { + exports.active = process.domain = stack[stack.length - 1]; + caught = process._fatalException(er2); + } else { + caught = false; + } + return caught; + } + return caught; +}; Domain.prototype.enter = function() { @@ -119,22 +131,19 @@ // to push it onto the stack so that we can pop it later. exports.active = process.domain = this; stack.push(this); - - process.addAsyncListener(this._listener); + _domain_flag[0] = stack.length; }; Domain.prototype.exit = function() { - if (this._disposed) return; - - process.removeAsyncListener(this._listener); + // skip disposed domains, as usual, but also don't do anything if this + // domain is not on the stack. + var index = stack.lastIndexOf(this); + if (this._disposed || index === -1) return; // exit all domains until this one. - var index = stack.lastIndexOf(this); - if (index !== -1) - stack.splice(index + 1); - else - stack.length = 0; + stack.splice(index); + _domain_flag[0] = stack.length; exports.active = stack[stack.length - 1]; process.domain = exports.active; @@ -168,13 +177,6 @@ ee.domain = this; this.members.push(ee); - - // Adding the domain._listener to the Wrap associated with the event - // emitter instance will be done automatically either on class - // instantiation or manually, like in cases of net listen(). - // The reason it cannot be done here is because in specific cases the - // _handle is not created on EE instantiation, so there's no place to - // add the listener. }; @@ -183,24 +185,6 @@ var index = this.members.indexOf(ee); if (index !== -1) this.members.splice(index, 1); - - // First check if the ee is a handle itself. - if (ee.removeAsyncListener) - ee.removeAsyncListener(this._listener); - - // Manually remove the asyncListener from the handle, if possible. - if (ee._handle && ee._handle.removeAsyncListener) - ee._handle.removeAsyncListener(this._listener); - - // TODO(trevnorris): Are there cases where the handle doesn't live on - // the ee or the _handle. - - // TODO(trevnorris): For debugging that we've missed adding AsyncWrap's - // methods to a handle somewhere on the native side. - if (ee._handle && !ee._handle.removeAsyncListener) { - process._rawDebug('Wrap handle is missing AsyncWrap methods'); - process.abort(); - } }; diff -Nru nodejs-0.11.10/lib/events.js nodejs-0.11.11/lib/events.js --- nodejs-0.11.10/lib/events.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/lib/events.js 2014-01-29 01:29:56.000000000 +0000 @@ -91,6 +91,9 @@ if (util.isUndefined(handler)) return false; + if (this.domain && this !== process) + this.domain.enter(); + if (util.isFunction(handler)) { switch (arguments.length) { // fast cases @@ -123,6 +126,9 @@ listeners[i].apply(this, args); } + if (this.domain && this !== process) + this.domain.exit(); + return true; }; diff -Nru nodejs-0.11.10/lib/fs.js nodejs-0.11.11/lib/fs.js --- nodejs-0.11.10/lib/fs.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/lib/fs.js 2014-01-29 01:29:56.000000000 +0000 @@ -1668,12 +1668,16 @@ // SyncWriteStream is internal. DO NOT USE. // Temporary hack for process.stdout and process.stderr when piped to files. -function SyncWriteStream(fd) { +function SyncWriteStream(fd, options) { Stream.call(this); + options = options || {}; + this.fd = fd; this.writable = true; this.readable = false; + this.autoClose = options.hasOwnProperty('autoClose') ? + options.autoClose : true; } util.inherits(SyncWriteStream, Stream); @@ -1723,7 +1727,8 @@ SyncWriteStream.prototype.destroy = function() { - fs.closeSync(this.fd); + if (this.autoClose) + fs.closeSync(this.fd); this.fd = null; this.emit('close'); return true; diff -Nru nodejs-0.11.10/lib/net.js nodejs-0.11.11/lib/net.js --- nodejs-0.11.10/lib/net.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/lib/net.js 2014-01-29 01:29:56.000000000 +0000 @@ -113,7 +113,6 @@ // called when creating new Socket, or when re-using a closed Socket function initSocketHandle(self) { self.destroyed = false; - self.errorEmitted = false; self.bytesRead = 0; self._bytesDispatched = 0; @@ -429,11 +428,11 @@ function fireErrorCallbacks() { if (cb) cb(exception); - if (exception && !self.errorEmitted) { + if (exception && !self._errorEmitted) { process.nextTick(function() { self.emit('error', exception); }); - self.errorEmitted = true; + self._errorEmitted = true; } }; @@ -462,8 +461,11 @@ this._handle = null; } - fireErrorCallbacks(); + // we set destroyed to true before firing error callbacks in order + // to make it re-entrance safe in case Socket.prototype.destroy() + // is called within callbacks this.destroyed = true; + fireErrorCallbacks(); if (this.server) { COUNTER_NET_SERVER_CONNECTION_CLOSE(this); @@ -624,7 +626,7 @@ return false; } - var req = { oncomplete: afterWrite }; + var req = { oncomplete: afterWrite, async: false }; var err; if (writev) { @@ -652,16 +654,16 @@ } if (err) - return this._destroy(errnoException(err, 'write'), cb); + return this._destroy(errnoException(err, 'write', req.error), cb); this._bytesDispatched += req.bytes; // If it was entirely flushed, we can write some more right now. // However, if more is left in the queue, then wait until that clears. - if (this._handle.writeQueueSize === 0) - cb(); - else + if (req.async && this._handle.writeQueueSize != 0) req.cb = cb; + else + cb(); }; @@ -746,7 +748,7 @@ }); -function afterWrite(status, handle, req) { +function afterWrite(status, handle, req, err) { var self = handle.owner; if (self !== process.stderr && self !== process.stdout) debug('afterWrite', status); @@ -758,7 +760,7 @@ } if (status < 0) { - var ex = errnoException(status, 'write'); + var ex = errnoException(status, 'write', err); debug('write failure', ex); self._destroy(ex, req.cb); return; @@ -782,7 +784,7 @@ var err; if (localAddress) { - if (addressType == 6) { + if (addressType === 6) { err = self._handle.bind6(localAddress); } else { err = self._handle.bind(localAddress); @@ -830,6 +832,7 @@ if (this.destroyed) { this._readableState.reading = false; this._readableState.ended = false; + this._readableState.endEmitted = false; this._writableState.ended = false; this._writableState.ending = false; this._writableState.finished = false; @@ -1017,7 +1020,7 @@ handle.writable = true; return handle; - } else if (port == -1 && addressType == -1) { + } else if (port === -1 && addressType === -1) { handle = createPipe(); if (process.platform === 'win32') { var instances = parseInt(process.env.NODE_PENDING_PIPE_INSTANCES); @@ -1031,7 +1034,7 @@ if (address || port) { debug('bind to ' + address); - if (addressType == 6) { + if (addressType === 6) { err = handle.bind6(address, port); } else { err = handle.bind(address, port); @@ -1089,20 +1092,9 @@ // generate connection key, this should be unique to the connection this._connectionKey = addressType + ':' + address + ':' + port; - // If a domain is attached to the event emitter then we need to add - // the listener to the handle. - if (this.domain) { - this._handle.addAsyncListener(this.domain._listener); - process.addAsyncListener(this.domain._listener); - } - process.nextTick(function() { self.emit('listening'); }); - - if (this.domain) { - process.removeAsyncListener(this.domain._listener); - } }; diff -Nru nodejs-0.11.10/lib/path.js nodejs-0.11.11/lib/path.js --- nodejs-0.11.10/lib/path.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/lib/path.js 2014-01-29 01:29:56.000000000 +0000 @@ -348,12 +348,17 @@ // posix version exports.normalize = function(path) { var isAbsolute = exports.isAbsolute(path), - trailingSlash = path.substr(-1) === '/'; + trailingSlash = path[path.length - 1] === '/', + segments = path.split('/'), + nonEmptySegments = []; // Normalize the path - path = normalizeArray(path.split('/').filter(function(p) { - return !!p; - }), !isAbsolute).join('/'); + for (var i = 0; i < segments.length; i++) { + if (segments[i]) { + nonEmptySegments.push(segments[i]); + } + } + path = normalizeArray(nonEmptySegments, !isAbsolute).join('/'); if (!path && !isAbsolute) { path = '.'; @@ -372,13 +377,21 @@ // posix version exports.join = function() { - var paths = Array.prototype.slice.call(arguments, 0); - return exports.normalize(paths.filter(function(p, index) { - if (!util.isString(p)) { + var path = ''; + for (var i = 0; i < arguments.length; i++) { + var segment = arguments[i]; + if (!util.isString(segment)) { throw new TypeError('Arguments to path.join must be strings'); } - return p; - }).join('/')); + if (segment) { + if (!path) { + path += segment; + } else { + path += '/' + segment; + } + } + } + return exports.normalize(path); }; diff -Nru nodejs-0.11.10/lib/timers.js nodejs-0.11.11/lib/timers.js --- nodejs-0.11.10/lib/timers.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/lib/timers.js 2014-01-29 01:29:56.000000000 +0000 @@ -35,6 +35,9 @@ var loadAsyncQueue = process._loadAsyncQueue; var unloadAsyncQueue = process._unloadAsyncQueue; +// Same as in AsyncListener in env.h +var kHasListener = 0; + // Do a little housekeeping. delete process._asyncFlags; delete process._runAsyncQueue; @@ -57,6 +60,8 @@ // Make Timer as monomorphic as possible. Timer.prototype._asyncQueue = undefined; +Timer.prototype._asyncData = undefined; +Timer.prototype._asyncFlags = 0; // the main function - creates lists on demand and the watchers associated // with them. @@ -112,7 +117,8 @@ // other timers that expire on this tick should still run. // // https://github.com/joyent/node/issues/2631 - if (first.domain && first.domain._disposed) + var domain = first.domain; + if (domain && domain._disposed) continue; hasQueue = !!first._asyncQueue; @@ -120,8 +126,12 @@ try { if (hasQueue) loadAsyncQueue(first); + if (domain) + domain.enter(); threw = true; first._onTimeout(); + if (domain) + domain.exit(); if (hasQueue) unloadAsyncQueue(first); threw = false; @@ -190,38 +200,11 @@ // Whether or not a new TimerWrap needed to be created, this should run // for each item. This way each "item" (i.e. timer) can properly have // their own domain assigned. - if (asyncFlags[0] > 0) + if (asyncFlags[kHasListener] > 0) runAsyncQueue(item); }; -function timerAddAsyncListener(obj) { - if (!this._asyncQueue) - this._asyncQueue = []; - var queue = this._asyncQueue; - // This queue will be small. Probably always <= 3 items. - for (var i = 0; i < queue.length; i++) { - if (queue[i].uid === obj.uid) - return; - } - this._asyncQueue.push(obj); -} - - -function timerRemoveAsyncListener(obj) { - if (!this._asyncQueue) - return; - var queue = this._asyncQueue; - // This queue will be small. Probably always <= 3 items. - for (var i = 0; i < queue.length; i++) { - if (queue[i].uid === obj.uid) { - queue.splice(i, 1); - return; - } - } -} - - /* * DOM-style timers */ @@ -357,10 +340,6 @@ } }; -// For domain compatibility need to attach this API. -Timeout.prototype.addAsyncListener = timerAddAsyncListener; -Timeout.prototype.removeAsyncListener = timerRemoveAsyncListener; - var immediateQueue = {}; L.init(immediateQueue); @@ -368,7 +347,7 @@ function processImmediate() { var queue = immediateQueue; - var hasQueue, immediate; + var domain, hasQueue, immediate; immediateQueue = {}; L.init(immediateQueue); @@ -376,9 +355,12 @@ while (L.isEmpty(queue) === false) { immediate = L.shift(queue); hasQueue = !!immediate._asyncQueue; + domain = immediate.domain; if (hasQueue) loadAsyncQueue(immediate); + if (domain) + domain.enter(); var threw = true; try { @@ -398,6 +380,8 @@ } } + if (domain) + domain.exit(); if (hasQueue) unloadAsyncQueue(immediate); } @@ -413,13 +397,13 @@ function Immediate() { } -Immediate.prototype.addAsyncListener = timerAddAsyncListener; -Immediate.prototype.removeAsyncListener = timerRemoveAsyncListener; Immediate.prototype.domain = undefined; Immediate.prototype._onImmediate = undefined; Immediate.prototype._asyncQueue = undefined; +Immediate.prototype._asyncData = undefined; Immediate.prototype._idleNext = undefined; Immediate.prototype._idlePrev = undefined; +Immediate.prototype._asyncFlags = 0; exports.setImmediate = function(callback) { @@ -446,7 +430,7 @@ } // setImmediates are handled more like nextTicks. - if (asyncFlags[0] > 0) + if (asyncFlags[kHasListener] > 0) runAsyncQueue(immediate); if (process.domain) immediate.domain = process.domain; @@ -481,10 +465,9 @@ debug('unrefTimer fired'); - var diff, first, hasQueue, threw; + var diff, domain, first, hasQueue, threw; while (first = L.peek(unrefList)) { diff = now - first._idleStart; - hasQueue = !!first._asyncQueue; if (diff < first._idleTimeout) { diff = first._idleTimeout - diff; @@ -496,16 +479,22 @@ L.remove(first); + domain = first.domain; + if (!first._onTimeout) continue; - if (first.domain && first.domain._disposed) continue; + if (domain && domain._disposed) continue; + hasQueue = !!first._asyncQueue; try { if (hasQueue) loadAsyncQueue(first); + if (domain) domain.enter(); threw = true; debug('unreftimer firing timeout'); first._onTimeout(); threw = false; + if (domain) + domain.exit(); if (hasQueue) unloadAsyncQueue(first); } finally { diff -Nru nodejs-0.11.10/lib/util.js nodejs-0.11.11/lib/util.js --- nodejs-0.11.10/lib/util.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/lib/util.js 2014-01-29 01:29:56.000000000 +0000 @@ -413,7 +413,8 @@ } else { name = name.replace(/'/g, "\\'") .replace(/\\"/g, '"') - .replace(/(^"|"$)/g, "'"); + .replace(/(^"|"$)/g, "'") + .replace(/\\\\/g, '\\'); name = ctx.stylize(name, 'string'); } } @@ -423,10 +424,7 @@ function reduceToSingleString(output, base, braces) { - var numLinesEst = 0; var length = output.reduce(function(prev, cur) { - numLinesEst++; - if (cur.indexOf('\n') >= 0) numLinesEst++; return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; }, 0); @@ -676,10 +674,13 @@ var uv; -exports._errnoException = function(err, syscall) { +exports._errnoException = function(err, syscall, original) { if (isUndefined(uv)) uv = process.binding('uv'); var errname = uv.errname(err); - var e = new Error(syscall + ' ' + errname); + var message = syscall + ' ' + errname; + if (original) + message += ' ' + original; + var e = new Error(message); e.code = errname; e.errno = errname; e.syscall = syscall; diff -Nru nodejs-0.11.10/node.gyp nodejs-0.11.11/node.gyp --- nodejs-0.11.10/node.gyp 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/node.gyp 2014-01-29 01:29:56.000000000 +0000 @@ -1,9 +1,6 @@ { 'variables': { 'v8_use_snapshot%': 'true', - # Turn off -Werror in V8 - # See http://codereview.chromium.org/8159015 - 'werror': '', 'node_use_dtrace%': 'false', 'node_use_etw%': 'false', 'node_use_perfctr%': 'false', @@ -94,7 +91,6 @@ 'src/node_buffer.cc', 'src/node_constants.cc', 'src/node_contextify.cc', - 'src/node_extensions.cc', 'src/node_file.cc', 'src/node_http_parser.cc', 'src/node_javascript.cc', @@ -126,7 +122,6 @@ 'src/node_buffer.h', 'src/node_constants.h', 'src/node_contextify.h', - 'src/node_extensions.h', 'src/node_file.h', 'src/node_http_parser.h', 'src/node_internals.h', @@ -327,7 +322,7 @@ [ 'OS=="linux" and node_shared_v8=="false"', { 'ldflags': [ - '-Wl,--whole-archive <(PRODUCT_DIR)/obj.target/deps/v8/tools/gyp/libv8_base.<(target_arch).a -Wl,--no-whole-archive', + '-Wl,--whole-archive <(V8_BASE) -Wl,--no-whole-archive', ], }], ], @@ -465,11 +460,11 @@ { 'action_name': 'node_dtrace_provider_o', 'inputs': [ - '<(PRODUCT_DIR)/obj.target/libuv/deps/uv/src/unix/core.o', - '<(PRODUCT_DIR)/obj.target/node/src/node_dtrace.o', + '<(OBJ_DIR)/libuv/deps/uv/src/unix/core.o', + '<(OBJ_DIR)/node/src/node_dtrace.o', ], 'outputs': [ - '<(PRODUCT_DIR)/obj.target/node/src/node_dtrace_provider.o' + '<(OBJ_DIR)/node/src/node_dtrace_provider.o' ], 'action': [ 'dtrace', '-G', '-xnolibs', '-s', 'src/node_provider.d', '-s', 'deps/uv/src/unix/uv-dtrace.d', '<@(_inputs)', @@ -512,7 +507,7 @@ { 'action_name': 'node_dtrace_ustack_constants', 'inputs': [ - '<(PRODUCT_DIR)/obj.target/deps/v8/tools/gyp/libv8_base.<(target_arch).a' + '<(V8_BASE)' ], 'outputs': [ '<(SHARED_INTERMEDIATE_DIR)/v8constants.h' @@ -530,7 +525,7 @@ '<(SHARED_INTERMEDIATE_DIR)/v8constants.h' ], 'outputs': [ - '<(PRODUCT_DIR)/obj.target/node/src/node_dtrace_ustack.o' + '<(OBJ_DIR)/node/src/node_dtrace_ustack.o' ], 'conditions': [ [ 'target_arch=="ia32"', { diff -Nru nodejs-0.11.10/src/async-wrap-inl.h nodejs-0.11.11/src/async-wrap-inl.h --- nodejs-0.11.10/src/async-wrap-inl.h 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/src/async-wrap-inl.h 2014-01-29 01:29:56.000000000 +0000 @@ -38,7 +38,7 @@ inline AsyncWrap::AsyncWrap(Environment* env, v8::Handle object) : BaseObject(env, object), async_flags_(NO_OPTIONS) { - if (!env->has_async_listeners()) + if (!env->has_async_listener()) return; // TODO(trevnorris): Do we really need to TryCatch this call? @@ -49,7 +49,7 @@ env->async_listener_run_function()->Call(env->process_object(), 1, &val); if (!try_catch.HasCaught()) - async_flags_ |= ASYNC_LISTENERS; + async_flags_ |= HAS_ASYNC_LISTENER; } @@ -57,34 +57,102 @@ } -template -inline void AsyncWrap::AddMethods(v8::Handle t) { - NODE_SET_PROTOTYPE_METHOD(t, - "addAsyncListener", - AddAsyncListener); - NODE_SET_PROTOTYPE_METHOD(t, - "removeAsyncListener", - RemoveAsyncListener); -} - - inline uint32_t AsyncWrap::async_flags() const { return async_flags_; } -inline void AsyncWrap::set_flag(unsigned int flag) { - async_flags_ |= flag; +inline bool AsyncWrap::has_async_listener() { + return async_flags() & HAS_ASYNC_LISTENER; } -inline void AsyncWrap::remove_flag(unsigned int flag) { - async_flags_ &= ~flag; -} +// I hate you domains. +inline v8::Handle AsyncWrap::MakeDomainCallback( + const v8::Handle cb, + int argc, + v8::Handle* argv) { + assert(env()->context() == env()->isolate()->GetCurrentContext()); + + v8::Local context = object(); + v8::Local process = env()->process_object(); + v8::Local domain_v = context->Get(env()->domain_string()); + v8::Local domain; + + v8::TryCatch try_catch; + try_catch.SetVerbose(true); + + if (has_async_listener()) { + v8::Local val = context.As(); + env()->async_listener_load_function()->Call(process, 1, &val); + + if (try_catch.HasCaught()) + return v8::Undefined(env()->isolate()); + } + + bool has_domain = domain_v->IsObject(); + if (has_domain) { + domain = domain_v.As(); + + if (domain->Get(env()->disposed_string())->IsTrue()) + return Undefined(env()->isolate()); + + v8::Local enter = + domain->Get(env()->enter_string()).As(); + assert(enter->IsFunction()); + enter->Call(domain, 0, NULL); + + if (try_catch.HasCaught()) + return Undefined(env()->isolate()); + } + + v8::Local ret = cb->Call(context, argc, argv); + if (try_catch.HasCaught()) { + return Undefined(env()->isolate()); + } -inline bool AsyncWrap::has_async_queue() { - return async_flags() & ASYNC_LISTENERS; + if (has_domain) { + v8::Local exit = + domain->Get(env()->exit_string()).As(); + assert(exit->IsFunction()); + exit->Call(domain, 0, NULL); + + if (try_catch.HasCaught()) + return Undefined(env()->isolate()); + } + + if (has_async_listener()) { + v8::Local val = context.As(); + env()->async_listener_unload_function()->Call(process, 1, &val); + + if (try_catch.HasCaught()) + return Undefined(env()->isolate()); + } + + Environment::TickInfo* tick_info = env()->tick_info(); + + if (tick_info->in_tick()) { + return ret; + } + + if (tick_info->length() == 0) { + tick_info->set_index(0); + return ret; + } + + tick_info->set_in_tick(true); + + env()->tick_callback_function()->Call(process, 0, NULL); + + tick_info->set_in_tick(false); + + if (try_catch.HasCaught()) { + tick_info->set_last_threw(true); + return Undefined(env()->isolate()); + } + + return ret; } @@ -92,6 +160,9 @@ const v8::Handle cb, int argc, v8::Handle* argv) { + if (env()->using_domains()) + return MakeDomainCallback(cb, argc, argv); + assert(env()->context() == env()->isolate()->GetCurrentContext()); v8::Local context = object(); @@ -100,7 +171,7 @@ v8::TryCatch try_catch; try_catch.SetVerbose(true); - if (has_async_queue()) { + if (has_async_listener()) { v8::Local val = context.As(); env()->async_listener_load_function()->Call(process, 1, &val); @@ -114,7 +185,7 @@ return Undefined(env()->isolate()); } - if (has_async_queue()) { + if (has_async_listener()) { v8::Local val = context.As(); env()->async_listener_unload_function()->Call(process, 1, &val); @@ -135,9 +206,6 @@ tick_info->set_in_tick(true); - // TODO(trevnorris): Consider passing "context" to _tickCallback so it - // can then be passed as the first argument to the nextTick callback. - // That should greatly help needing to create closures. env()->tick_callback_function()->Call(process, 0, NULL); tick_info->set_in_tick(false); @@ -174,49 +242,6 @@ return MakeCallback(cb, argc, argv); } - -template -inline void AsyncWrap::AddAsyncListener( - const v8::FunctionCallbackInfo& args) { - v8::HandleScope handle_scope(args.GetIsolate()); - Environment* env = Environment::GetCurrent(args.GetIsolate()); - - v8::Local handle = args.This(); - v8::Local listener = args[0]; - assert(listener->IsObject()); - assert(handle->InternalFieldCount() > 0); - - env->async_listener_push_function()->Call(handle, 1, &listener); - - Type* wrap = static_cast( - handle->GetAlignedPointerFromInternalField(0)); - assert(wrap != NULL); - wrap->set_flag(ASYNC_LISTENERS); -} - - -template -inline void AsyncWrap::RemoveAsyncListener( - const v8::FunctionCallbackInfo& args) { - v8::HandleScope handle_scope(args.GetIsolate()); - Environment* env = Environment::GetCurrent(args.GetIsolate()); - - v8::Local handle = args.This(); - v8::Local listener = args[0]; - assert(listener->IsObject()); - assert(handle->InternalFieldCount() > 0); - - v8::Local ret = - env->async_listener_strip_function()->Call(handle, 1, &listener); - - if (ret->IsFalse()) { - Type* wrap = static_cast( - handle->GetAlignedPointerFromInternalField(0)); - assert(wrap != NULL); - wrap->remove_flag(ASYNC_LISTENERS); - } -} - } // namespace node #endif // SRC_ASYNC_WRAP_INL_H_ diff -Nru nodejs-0.11.10/src/async-wrap.h nodejs-0.11.11/src/async-wrap.h --- nodejs-0.11.10/src/async-wrap.h 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/src/async-wrap.h 2014-01-29 01:29:56.000000000 +0000 @@ -32,23 +32,16 @@ public: enum AsyncFlags { NO_OPTIONS = 0, - ASYNC_LISTENERS = 1 + HAS_ASYNC_LISTENER = 1 }; inline AsyncWrap(Environment* env, v8::Handle object); inline ~AsyncWrap(); - template - static inline void AddMethods(v8::Handle t); - inline uint32_t async_flags() const; - inline void set_flag(unsigned int flag); - - inline void remove_flag(unsigned int flag); - - inline bool has_async_queue(); + inline bool has_async_listener(); // Only call these within a valid HandleScope. inline v8::Handle MakeCallback(const v8::Handle cb, @@ -62,15 +55,14 @@ v8::Handle* argv); private: - // Add an async listener to an existing handle. - template - static inline void AddAsyncListener( - const v8::FunctionCallbackInfo& args); - - // Remove an async listener to an existing handle. - template - static inline void RemoveAsyncListener( - const v8::FunctionCallbackInfo& args); + inline AsyncWrap(); + + // TODO(trevnorris): BURN IN FIRE! Remove this as soon as a suitable + // replacement is committed. + inline v8::Handle MakeDomainCallback( + const v8::Handle cb, + int argc, + v8::Handle* argv); uint32_t async_flags_; }; diff -Nru nodejs-0.11.10/src/cares_wrap.cc nodejs-0.11.11/src/cares_wrap.cc --- nodejs-0.11.10/src/cares_wrap.cc 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/src/cares_wrap.cc 2014-01-29 01:29:56.000000000 +0000 @@ -1177,4 +1177,4 @@ } // namespace cares_wrap } // namespace node -NODE_MODULE_CONTEXT_AWARE(node_cares_wrap, node::cares_wrap::Initialize) +NODE_MODULE_CONTEXT_AWARE_BUILTIN(cares_wrap, node::cares_wrap::Initialize) diff -Nru nodejs-0.11.10/src/env-inl.h nodejs-0.11.11/src/env-inl.h --- nodejs-0.11.10/src/env-inl.h 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/src/env-inl.h 2014-01-29 01:29:56.000000000 +0000 @@ -82,7 +82,23 @@ return kFieldsCount; } -inline uint32_t Environment::AsyncListener::count() const { +inline bool Environment::AsyncListener::has_listener() const { + return fields_[kHasListener] > 0; +} + +inline Environment::DomainFlag::DomainFlag() { + for (int i = 0; i < kFieldsCount; ++i) fields_[i] = 0; +} + +inline uint32_t* Environment::DomainFlag::fields() { + return fields_; +} + +inline int Environment::DomainFlag::fields_count() const { + return kFieldsCount; +} + +inline uint32_t Environment::DomainFlag::count() const { return fields_[kCount]; } @@ -163,6 +179,7 @@ : isolate_(context->GetIsolate()), isolate_data_(IsolateData::GetOrCreate(context->GetIsolate())), using_smalloc_alloc_cb_(false), + using_domains_(false), context_(context->GetIsolate(), context) { // We'll be creating new objects so make sure we've entered the context. v8::HandleScope handle_scope(isolate()); @@ -173,6 +190,8 @@ } inline Environment::~Environment() { + v8::HandleScope handle_scope(isolate()); + context()->SetAlignedPointerInEmbedderData(kContextEmbedderDataIndex, NULL); #define V(PropertyName, TypeName) PropertyName ## _.Dispose(); ENVIRONMENT_STRONG_PERSISTENT_PROPERTIES(V) @@ -188,9 +207,15 @@ return isolate_; } -inline bool Environment::has_async_listeners() const { +inline bool Environment::has_async_listener() const { // The const_cast is okay, it doesn't violate conceptual const-ness. - return const_cast(this)->async_listener()->count() > 0; + return const_cast(this)->async_listener()->has_listener(); +} + +inline bool Environment::in_domain() const { + // The const_cast is okay, it doesn't violate conceptual const-ness. + return using_domains() && + const_cast(this)->domain_flag()->count() > 0; } inline Environment* Environment::from_immediate_check_handle( @@ -231,6 +256,10 @@ return &async_listener_count_; } +inline Environment::DomainFlag* Environment::domain_flag() { + return &domain_flag_; +} + inline Environment::TickInfo* Environment::tick_info() { return &tick_info_; } @@ -243,6 +272,14 @@ using_smalloc_alloc_cb_ = value; } +inline bool Environment::using_domains() const { + return using_domains_; +} + +inline void Environment::set_using_domains(bool value) { + using_domains_ = value; +} + inline Environment* Environment::from_cares_timer_handle(uv_timer_t* handle) { return CONTAINER_OF(handle, Environment, cares_timer_handle_); } diff -Nru nodejs-0.11.10/src/env.h nodejs-0.11.11/src/env.h --- nodejs-0.11.10/src/env.h 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/src/env.h 2014-01-29 01:29:56.000000000 +0000 @@ -53,6 +53,7 @@ #define PER_ISOLATE_STRING_PROPERTIES(V) \ V(address_string, "address") \ V(atime_string, "atime") \ + V(async, "async") \ V(async_queue_string, "_asyncQueue") \ V(birthtime_string, "birthtime") \ V(blksize_string, "blksize") \ @@ -66,8 +67,10 @@ V(ctime_string, "ctime") \ V(dev_string, "dev") \ V(disposed_string, "_disposed") \ + V(domain_string, "domain") \ V(enter_string, "enter") \ V(errno_string, "errno") \ + V(error_string, "error") \ V(exit_string, "exit") \ V(exponent_string, "exponent") \ V(exports_string, "exports") \ @@ -135,14 +138,13 @@ V(write_queue_size_string, "writeQueueSize") \ #define ENVIRONMENT_STRONG_PERSISTENT_PROPERTIES(V) \ - V(async_listener_load_function, v8::Function) \ - V(async_listener_push_function, v8::Function) \ V(async_listener_run_function, v8::Function) \ - V(async_listener_strip_function, v8::Function) \ + V(async_listener_load_function, v8::Function) \ V(async_listener_unload_function, v8::Function) \ V(binding_cache_object, v8::Object) \ V(buffer_constructor_function, v8::Function) \ V(context, v8::Context) \ + V(domain_array, v8::Array) \ V(module_load_list_array, v8::Array) \ V(pipe_constructor_template, v8::FunctionTemplate) \ V(process_object, v8::Object) \ @@ -175,14 +177,14 @@ public: inline uint32_t* fields(); inline int fields_count() const; - inline uint32_t count() const; + inline bool has_listener() const; private: friend class Environment; // So we can call the constructor. inline AsyncListener(); enum Fields { - kCount, + kHasListener, kFieldsCount }; @@ -191,6 +193,26 @@ DISALLOW_COPY_AND_ASSIGN(AsyncListener); }; + class DomainFlag { + public: + inline uint32_t* fields(); + inline int fields_count() const; + inline uint32_t count() const; + + private: + friend class Environment; // So we can call the constructor. + inline DomainFlag(); + + enum Fields { + kCount, + kFieldsCount + }; + + uint32_t fields_[kFieldsCount]; + + DISALLOW_COPY_AND_ASSIGN(DomainFlag); + }; + class TickInfo { public: inline uint32_t* fields(); @@ -231,7 +253,8 @@ inline v8::Isolate* isolate() const; inline uv_loop_t* event_loop() const; - inline bool has_async_listeners() const; + inline bool has_async_listener() const; + inline bool in_domain() const; static inline Environment* from_immediate_check_handle(uv_check_t* handle); inline uv_check_t* immediate_check_handle(); @@ -244,6 +267,7 @@ inline uv_check_t* idle_check_handle(); inline AsyncListener* async_listener(); + inline DomainFlag* domain_flag(); inline TickInfo* tick_info(); static inline Environment* from_cares_timer_handle(uv_timer_t* handle); @@ -255,6 +279,9 @@ inline bool using_smalloc_alloc_cb() const; inline void set_using_smalloc_alloc_cb(bool value); + inline bool using_domains() const; + inline void set_using_domains(bool value); + // Strings are shared across shared contexts. The getters simply proxy to // the per-isolate primitive. #define V(PropertyName, StringValue) \ @@ -285,11 +312,13 @@ uv_prepare_t idle_prepare_handle_; uv_check_t idle_check_handle_; AsyncListener async_listener_count_; + DomainFlag domain_flag_; TickInfo tick_info_; uv_timer_t cares_timer_handle_; ares_channel cares_channel_; ares_task_list cares_task_list_; bool using_smalloc_alloc_cb_; + bool using_domains_; #define V(PropertyName, TypeName) \ v8::Persistent PropertyName ## _; diff -Nru nodejs-0.11.10/src/fs_event_wrap.cc nodejs-0.11.11/src/fs_event_wrap.cc --- nodejs-0.11.10/src/fs_event_wrap.cc 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/src/fs_event_wrap.cc 2014-01-29 01:29:56.000000000 +0000 @@ -193,4 +193,4 @@ } // namespace node -NODE_MODULE_CONTEXT_AWARE(node_fs_event_wrap, node::FSEventWrap::Initialize) +NODE_MODULE_CONTEXT_AWARE_BUILTIN(fs_event_wrap, node::FSEventWrap::Initialize) diff -Nru nodejs-0.11.10/src/node.cc nodejs-0.11.11/src/node.cc --- nodejs-0.11.10/src/node.cc 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/src/node.cc 2014-01-29 01:29:56.000000000 +0000 @@ -130,6 +130,9 @@ static bool debug_wait_connect = false; static int debug_port = 5858; static bool v8_is_profiling = false; +static node_module* modpending; +static node_module* modlist_builtin; +static node_module* modlist_addon; // used by C++ modules as well bool no_deprecation = false; @@ -854,14 +857,10 @@ assert(args[1]->IsFunction()); assert(args[2]->IsFunction()); assert(args[3]->IsFunction()); - assert(args[4]->IsFunction()); - assert(args[5]->IsFunction()); env->set_async_listener_run_function(args[1].As()); env->set_async_listener_load_function(args[2].As()); env->set_async_listener_unload_function(args[3].As()); - env->set_async_listener_push_function(args[4].As()); - env->set_async_listener_strip_function(args[5].As()); Local async_listener_flag_obj = args[0].As(); Environment::AsyncListener* async_listener = env->async_listener(); @@ -876,11 +875,54 @@ } +void SetupDomainUse(const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args.GetIsolate()); + + if (env->using_domains()) + return; + env->set_using_domains(true); + + HandleScope scope(node_isolate); + Local process_object = env->process_object(); + + Local tick_callback_function_key = + FIXED_ONE_BYTE_STRING(node_isolate, "_tickDomainCallback"); + Local tick_callback_function = + process_object->Get(tick_callback_function_key).As(); + + if (!tick_callback_function->IsFunction()) { + fprintf(stderr, "process._tickDomainCallback assigned to non-function\n"); + abort(); + } + + process_object->Set(FIXED_ONE_BYTE_STRING(node_isolate, "_tickCallback"), + tick_callback_function); + env->set_tick_callback_function(tick_callback_function); + + assert(args[0]->IsArray()); + assert(args[1]->IsObject()); + + env->set_domain_array(args[0].As()); + + Local domain_flag_obj = args[1].As(); + Environment::DomainFlag* domain_flag = env->domain_flag(); + domain_flag_obj->SetIndexedPropertiesToExternalArrayData( + domain_flag->fields(), + kExternalUnsignedIntArray, + domain_flag->fields_count()); + + // Do a little housekeeping. + env->process_object()->Delete( + FIXED_ONE_BYTE_STRING(args.GetIsolate(), "_setupDomainUse")); +} + + void SetupNextTick(const FunctionCallbackInfo& args) { HandleScope handle_scope(args.GetIsolate()); Environment* env = Environment::GetCurrent(args.GetIsolate()); - assert(args[0]->IsObject() && args[1]->IsFunction()); + assert(args[0]->IsObject()); + assert(args[1]->IsFunction()); // Values use to cross communicate with processNextTick. Local tick_info_obj = args[0].As(); @@ -897,11 +939,114 @@ } +Handle MakeDomainCallback(Environment* env, + Handle object, + const Handle callback, + int argc, + Handle argv[]) { + // If you hit this assertion, you forgot to enter the v8::Context first. + assert(env->context() == env->isolate()->GetCurrentContext()); + + Local process = env->process_object(); + Local domain_v = object->Get(env->domain_string()); + Local domain; + + TryCatch try_catch; + try_catch.SetVerbose(true); + + // TODO(trevnorris): This is sucky for performance. Fix it. + bool has_async_queue = object->Has(env->async_queue_string()); + if (has_async_queue) { + Local argv[] = { object }; + env->async_listener_load_function()->Call(process, ARRAY_SIZE(argv), argv); + + if (try_catch.HasCaught()) + return Undefined(node_isolate); + } + + bool has_domain = domain_v->IsObject(); + if (has_domain) { + domain = domain_v.As(); + + if (domain->Get(env->disposed_string())->IsTrue()) { + // domain has been disposed of. + return Undefined(node_isolate); + } + + Local enter = + domain->Get(env->enter_string()).As(); + assert(enter->IsFunction()); + enter->Call(domain, 0, NULL); + + if (try_catch.HasCaught()) { + return Undefined(node_isolate); + } + } + + Local ret = callback->Call(object, argc, argv); + + if (try_catch.HasCaught()) { + return Undefined(node_isolate); + } + + if (has_domain) { + Local exit = + domain->Get(env->exit_string()).As(); + assert(exit->IsFunction()); + exit->Call(domain, 0, NULL); + + if (try_catch.HasCaught()) { + return Undefined(node_isolate); + } + } + + if (has_async_queue) { + Local val = object.As(); + env->async_listener_unload_function()->Call(process, 1, &val); + + if (try_catch.HasCaught()) + return Undefined(node_isolate); + } + + Environment::TickInfo* tick_info = env->tick_info(); + + if (tick_info->last_threw() == 1) { + tick_info->set_last_threw(0); + return ret; + } + + if (tick_info->in_tick()) { + return ret; + } + + if (tick_info->length() == 0) { + tick_info->set_index(0); + return ret; + } + + tick_info->set_in_tick(true); + + env->tick_callback_function()->Call(process, 0, NULL); + + tick_info->set_in_tick(false); + + if (try_catch.HasCaught()) { + tick_info->set_last_threw(true); + return Undefined(node_isolate); + } + + return ret; +} + + Handle MakeCallback(Environment* env, Handle object, const Handle callback, int argc, Handle argv[]) { + if (env->using_domains()) + return MakeDomainCallback(env, object, callback, argc, argv); + // If you hit this assertion, you forgot to enter the v8::Context first. assert(env->context() == env->isolate()->GetCurrentContext()); @@ -1031,6 +1176,19 @@ } +Handle MakeDomainCallback(const Handle object, + const Handle callback, + int argc, + Handle argv[]) { + Local context = object->CreationContext(); + Environment* env = Environment::GetCurrent(context); + Context::Scope context_scope(context); + HandleScope handle_scope(env->isolate()); + return handle_scope.Close( + MakeDomainCallback(env, object, callback, argc, argv)); +} + + enum encoding ParseEncoding(Handle encoding_v, enum encoding _default) { HandleScope scope(node_isolate); @@ -1727,6 +1885,29 @@ args.GetReturnValue().Set(tuple); } +extern "C" void node_module_register(void* m) { + struct node_module* mp = reinterpret_cast(m); + + if (mp->nm_flags & NM_F_BUILTIN) { + mp->nm_link = modlist_builtin; + modlist_builtin = mp; + } else { + assert(modpending == NULL); + modpending = mp; + } +} + +struct node_module* get_builtin_module(const char* name) { + struct node_module* mp; + + for (mp = modlist_builtin; mp != NULL; mp = mp->nm_link) { + if (strcmp(mp->nm_modname, name) == 0) + break; + } + + assert(mp == NULL || (mp->nm_flags & NM_F_BUILTIN) != 0); + return (mp); +} typedef void (UV_DYNAMIC* extInit)(Handle exports); @@ -1739,12 +1920,12 @@ void DLOpen(const FunctionCallbackInfo& args) { HandleScope handle_scope(args.GetIsolate()); Environment* env = Environment::GetCurrent(args.GetIsolate()); - char symbol[1024], *base, *pos; + struct node_module* mp; uv_lib_t lib; - int r; if (args.Length() < 2) { - return ThrowError("process.dlopen takes exactly 2 arguments."); + ThrowError("process.dlopen takes exactly 2 arguments."); + return; } Local module = args[0]->ToObject(); // Cast @@ -1763,68 +1944,43 @@ return; } - String::Utf8Value path(args[1]); - base = *path; - - /* Find the shared library filename within the full path. */ -#ifdef __POSIX__ - pos = strrchr(base, '/'); - if (pos != NULL) { - base = pos + 1; - } -#else // Windows - for (;;) { - pos = strpbrk(base, "\\/:"); - if (pos == NULL) { - break; - } - base = pos + 1; - } -#endif // __POSIX__ - - /* Strip the .node extension. */ - pos = strrchr(base, '.'); - if (pos != NULL) { - *pos = '\0'; - } - - /* Add the `_module` suffix to the extension name. */ - r = snprintf(symbol, sizeof symbol, "%s_module", base); - if (r <= 0 || static_cast(r) >= sizeof symbol) { - return ThrowError("Out of memory."); - } - - /* Replace dashes with underscores. When loading foo-bar.node, - * look for foo_bar_module, not foo-bar_module. + /* + * Objects containing v14 or later modules will have registered themselves + * on the pending list. Activate all of them now. At present, only one + * module per object is supported. */ - for (pos = symbol; *pos != '\0'; ++pos) { - if (*pos == '-') - *pos = '_'; - } + mp = modpending; + modpending = NULL; - node_module_struct *mod; - if (uv_dlsym(&lib, symbol, reinterpret_cast(&mod))) { - char errmsg[1024]; - snprintf(errmsg, sizeof(errmsg), "Symbol %s not found.", symbol); - return ThrowError(errmsg); + if (mp == NULL) { + ThrowError("Module did not self-register."); + return; } - - if (mod->version != NODE_MODULE_VERSION) { + if (mp->nm_version != NODE_MODULE_VERSION) { char errmsg[1024]; snprintf(errmsg, sizeof(errmsg), "Module version mismatch. Expected %d, got %d.", - NODE_MODULE_VERSION, mod->version); - return ThrowError(errmsg); + NODE_MODULE_VERSION, mp->nm_version); + ThrowError(errmsg); + return; + } + if (mp->nm_flags & NM_F_BUILTIN) { + ThrowError("Built-in module self-registered."); + return; } - // Execute the C++ module - if (mod->register_context_func != NULL) { - mod->register_context_func(exports, module, env->context()); - } else if (mod->register_func != NULL) { - mod->register_func(exports, module); + mp->nm_dso_handle = lib.handle; + mp->nm_link = modlist_addon; + modlist_addon = mp; + + if (mp->nm_context_register_func != NULL) { + mp->nm_context_register_func(exports, module, env->context(), mp->nm_priv); + } else if (mp->nm_register_func != NULL) { + mp->nm_register_func(exports, module, mp->nm_priv); } else { - return ThrowError("Module has no declared entry point."); + ThrowError("Module has no declared entry point."); + return; } // Tell coverity that 'handle' should not be freed when we return. @@ -1839,10 +1995,7 @@ fprintf(stderr, "FATAL ERROR: %s\n", message); } fflush(stderr); -#if defined(DEBUG) abort(); -#endif - exit(5); } @@ -1930,14 +2083,15 @@ uint32_t l = modules->Length(); modules->Set(l, OneByteString(node_isolate, buf)); - node_module_struct* mod = get_builtin_module(*module_v); + node_module* mod = get_builtin_module(*module_v); if (mod != NULL) { exports = Object::New(); // Internal bindings don't have a "module" object, only exports. - assert(mod->register_func == NULL); - assert(mod->register_context_func != NULL); + assert(mod->nm_register_func == NULL); + assert(mod->nm_context_register_func != NULL); Local unused = Undefined(env->isolate()); - mod->register_context_func(exports, unused, env->context()); + mod->nm_context_register_func(exports, unused, + env->context(), mod->nm_priv); cache->Set(module, exports); } else if (!strcmp(*module_v, "constants")) { exports = Object::New(); @@ -2482,6 +2636,7 @@ NODE_SET_METHOD(process, "_setupAsyncListener", SetupAsyncListener); NODE_SET_METHOD(process, "_setupNextTick", SetupNextTick); + NODE_SET_METHOD(process, "_setupDomainUse", SetupDomainUse); // values use to cross communicate with processNextTick Local tick_info_obj = Object::New(); @@ -2714,7 +2869,9 @@ fprintf(stderr, "%s: %s requires an argument\n", argv[0], arg); exit(9); } - } else if (argv[index + 1] != NULL && argv[index + 1][0] != '-') { + } else if ((index + 1 < nargs) && + argv[index + 1] != NULL && + argv[index + 1][0] != '-') { args_consumed += 1; eval_string = argv[index + 1]; if (strncmp(eval_string, "\\-", 2) == 0) { @@ -3162,7 +3319,7 @@ } -void EmitExit(Environment* env) { +int EmitExit(Environment* env) { // process.emit('exit') HandleScope handle_scope(env->isolate()); Context::Scope context_scope(env->context()); @@ -3179,7 +3336,7 @@ }; MakeCallback(env, process_object, "emit", ARRAY_SIZE(args), args); - exit(code); + return code; } @@ -3253,6 +3410,7 @@ V8::SetEntropySource(crypto::EntropySource); #endif + int code; V8::Initialize(); { Locker locker(node_isolate); @@ -3264,7 +3422,7 @@ // be removed. Context::Scope context_scope(env->context()); uv_run(env->event_loop(), UV_RUN_DEFAULT); - EmitExit(env); + code = EmitExit(env); RunAtExit(env); env->Dispose(); env = NULL; @@ -3278,7 +3436,7 @@ delete[] exec_argv; exec_argv = NULL; - return 0; + return code; } diff -Nru nodejs-0.11.10/src/node.h nodejs-0.11.11/src/node.h --- nodejs-0.11.10/src/node.h 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/src/node.h 2014-01-29 01:29:56.000000000 +0000 @@ -184,6 +184,17 @@ NODE_EXTERN v8::Local Encode(const void *buf, size_t len, enum encoding encoding = BINARY); +#ifdef _WIN32 +// TODO(tjfontaine) consider changing the usage of ssize_t to ptrdiff_t +#if !defined(_SSIZE_T_) && !defined(_SSIZE_T_DEFINED) +typedef intptr_t ssize_t; +# define _SSIZE_T_ +# define _SSIZE_T_DEFINED +#endif +#else // !_WIN32 +# include // size_t, ssize_t +#endif // _WIN32 + // Returns -1 if the handle was not valid for decoding NODE_EXTERN ssize_t DecodeBytes(v8::Handle, enum encoding encoding = BINARY); @@ -203,30 +214,34 @@ const char *signo_string(int errorno); -NODE_EXTERN typedef void (*addon_register_func)( +typedef void (*addon_register_func)( v8::Handle exports, - v8::Handle module); + v8::Handle module, + void* priv); -NODE_EXTERN typedef void (*addon_context_register_func)( +typedef void (*addon_context_register_func)( v8::Handle exports, v8::Handle module, - v8::Handle context); + v8::Handle context, + void* priv); + +#define NM_F_BUILTIN 0x01 -struct node_module_struct { - int version; - void *dso_handle; - const char *filename; - node::addon_register_func register_func; - node::addon_context_register_func register_context_func; - const char *modname; +struct node_module { + int nm_version; + unsigned int nm_flags; + void* nm_dso_handle; + const char* nm_filename; + node::addon_register_func nm_register_func; + node::addon_context_register_func nm_context_register_func; + const char* nm_modname; + void* nm_priv; + struct node_module* nm_link; }; -node_module_struct* get_builtin_module(const char *name); +node_module* get_builtin_module(const char *name); -#define NODE_STANDARD_MODULE_STUFF \ - NODE_MODULE_VERSION, \ - NULL, \ - __FILE__ +extern "C" NODE_EXTERN void node_module_register(void* mod); #ifdef _WIN32 # define NODE_MODULE_EXPORT __declspec(dllexport) @@ -234,30 +249,70 @@ # define NODE_MODULE_EXPORT /* empty */ #endif -#define NODE_MODULE(modname, regfunc) \ +#if defined(_MSC_VER) +#pragma section(".CRT$XCU", read) +#define NODE_C_CTOR(fn) \ + static void __cdecl fn(void); \ + __declspec(allocate(".CRT$XCU")) static void (__cdecl*fn ## _)(void) = fn; \ + static void __cdecl fn(void) +#else +#define NODE_C_CTOR(fn) \ + static void fn(void) __attribute__((constructor)); \ + static void fn(void) +#endif + +#define NODE_MODULE_X(modstr, regfunc, priv, flags) \ extern "C" { \ - NODE_MODULE_EXPORT node::node_module_struct modname ## _module = \ + static node::node_module _module = \ { \ - NODE_STANDARD_MODULE_STUFF, \ + NODE_MODULE_VERSION, \ + flags, \ + NULL, \ + __FILE__, \ (node::addon_register_func) (regfunc), \ NULL, \ - NODE_STRINGIFY(modname) \ + modstr, \ + priv, \ + NULL \ }; \ + NODE_C_CTOR(_register) { \ + node_module_register(&_module); \ + } \ } -#define NODE_MODULE_CONTEXT_AWARE(modname, regfunc) \ +#define NODE_MODULE_CONTEXT_AWARE_X(modstr, regfunc, priv, flags) \ extern "C" { \ - NODE_MODULE_EXPORT node::node_module_struct modname ## _module = \ + static node::node_module _module = \ { \ - NODE_STANDARD_MODULE_STUFF, \ + NODE_MODULE_VERSION, \ + flags, \ + NULL, \ + __FILE__, \ NULL, \ - (regfunc), \ - NODE_STRINGIFY(modname) \ + (node::addon_context_register_func) (regfunc), \ + modstr, \ + priv, \ + NULL \ }; \ + NODE_C_CTOR(_register) { \ + node_module_register(&_module); \ + } \ } -#define NODE_MODULE_DECL(modname) \ - extern "C" node::node_module_struct modname ## _module; +#define NODE_MODULE(modname, regfunc) \ + NODE_MODULE_X(NODE_STRINGIFY(modname), regfunc, NULL, 0) + +#define NODE_MODULE_CONTEXT_AWARE(modname, regfunc) \ + NODE_MODULE_CONTEXT_AWARE_X(NODE_STRINGIFY(modname), regfunc, NULL, 0) + +#define NODE_MODULE_CONTEXT_AWARE_BUILTIN(modname, regfunc) \ + NODE_MODULE_CONTEXT_AWARE_X(NODE_STRINGIFY(modname), \ + regfunc, NULL, NM_F_BUILTIN) + +/* + * For backward compatibility in add-on modules. + */ +#define NODE_MODULE_DECL /* nothing */ /* Called after the event loop exits but before the VM is disposed. * Callbacks are run in reverse order of registration, i.e. newest first. diff -Nru nodejs-0.11.10/src/node.js nodejs-0.11.11/src/node.js --- nodejs-0.11.10/src/node.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/src/node.js 2014-01-29 01:29:56.000000000 +0000 @@ -224,11 +224,14 @@ // First run through error handlers from asyncListener. var caught = _errorHandler(er); + if (process.domain && process.domain._errorHandler) + caught = process.domain._errorHandler(er) || caught; + if (!caught) caught = process.emit('uncaughtException', er); - // If someone handled it, then great. Otherwise die in C++ since - // that means we'll exit the process, emit the 'exit' event. + // If someone handled it, then great. otherwise, die in C++ land + // since that means that we'll exit the process, emit the 'exit' event if (!caught) { try { if (!process._exiting) { @@ -253,9 +256,19 @@ }; startup.processAsyncListener = function() { - var asyncStack = []; - var asyncQueue = []; - var uid = 0; + // new Array() is used here because it is more efficient for sparse + // arrays. Please *do not* change these to simple bracket notation. + + // Track the active queue of AsyncListeners that have been added. + var asyncQueue = new Array(); + + // Keep the stack of all contexts that have been loaded in the + // execution chain of asynchronous events. + var contextStack = new Array(); + var currentContext = undefined; + + // Incremental uid for new AsyncListener instances. + var alUid = 0; // Stateful flags shared with Environment for quick JS/C++ // communication. @@ -269,7 +282,13 @@ var inErrorTick = false; // Needs to be the same as src/env.h - var kCount = 0; + var kHasListener = 0; + + // Flags to determine what async listeners are available. + var HAS_CREATE_AL = 1 << 0; + var HAS_BEFORE_AL = 1 << 1; + var HAS_AFTER_AL = 1 << 2; + var HAS_ERROR_AL = 1 << 3; // _errorHandler is scoped so it's also accessible by _fatalException. _errorHandler = errorHandler; @@ -291,184 +310,175 @@ process._setupAsyncListener(asyncFlags, runAsyncQueue, loadAsyncQueue, - unloadAsyncQueue, - pushListener, - stripListener); - - function popQueue() { - if (asyncStack.length > 0) - asyncQueue = asyncStack.pop(); - else - asyncQueue = []; + unloadAsyncQueue); + + // Load the currently executing context as the current context, and + // create a new asyncQueue that can receive any added queue items + // during the executing of the callback. + function loadContext(ctx) { + contextStack.push(currentContext); + currentContext = ctx; + + asyncFlags[kHasListener] = 1; + } + + function unloadContext() { + currentContext = contextStack.pop(); + + if (currentContext === undefined && asyncQueue.length === 0) + asyncFlags[kHasListener] = 0; } // Run all the async listeners attached when an asynchronous event is // instantiated. function runAsyncQueue(context) { - var queue = []; - var queueItem, item, i, value; + var queue = new Array(); + var data = new Array(); + var ccQueue, i, item, queueItem, value; + + context._asyncQueue = queue; + context._asyncData = data; + context._asyncFlags = 0; inAsyncTick = true; - for (i = 0; i < asyncQueue.length; i++) { - queueItem = asyncQueue[i]; - // Not passing "this" context because it hasn't actually been - // instantiated yet, so accessing some of the object properties - // can cause a segfault. - // Passing the original value will allow users to manipulate the - // original value object, while also allowing them to return a - // new value for current async call tracking. - value = queueItem.listener(queueItem.value); - if (typeof value !== 'undefined') { - item = { - callbacks: queueItem.callbacks, - value: value, - listener: queueItem.listener, - uid: queueItem.uid - }; - } else { - item = queueItem; + + // First run through all callbacks in the currentContext. These may + // add new AsyncListeners to the asyncQueue during execution. Hence + // why they need to be evaluated first. + if (currentContext) { + ccQueue = currentContext._asyncQueue; + context._asyncFlags |= currentContext._asyncFlags; + for (i = 0; i < ccQueue.length; i++) { + queueItem = ccQueue[i]; + queue[queue.length] = queueItem; + if ((queueItem.flags & HAS_CREATE_AL) === 0) { + data[queueItem.uid] = queueItem.data; + continue; + } + value = queueItem.create(queueItem.data); + data[queueItem.uid] = (value === undefined) ? queueItem.data : value; } - queue[i] = item; } - inAsyncTick = false; - context._asyncQueue = queue; + // Then run through all items in the asyncQueue + if (asyncQueue) { + for (i = 0; i < asyncQueue.length; i++) { + queueItem = asyncQueue[i]; + // Quick way to check if an AL instance with the same uid was + // already run from currentContext. + if (data[queueItem.uid] !== undefined) + continue; + queue[queue.length] = queueItem; + context._asyncFlags |= queueItem.flags; + if ((queueItem.flags & HAS_CREATE_AL) === 0) { + data[queueItem.uid] = queueItem.data; + continue; + } + value = queueItem.create(queueItem.data); + data[queueItem.uid] = (value === undefined) ? queueItem.data : value; + } + } + + inAsyncTick = false; } - // Uses the _asyncQueue object attached by runAsyncQueue. + // Load the AsyncListener queue attached to context and run all + // "before" callbacks, if they exist. function loadAsyncQueue(context) { - var queue = context._asyncQueue; - var item, before, i; + loadContext(context); - asyncStack.push(asyncQueue); - asyncQueue = queue.slice(); - // Since the async listener callback is required, the number of - // objects in the asyncQueue implies the number of async listeners - // there are to be processed. - asyncFlags[kCount] = queue.length; + if ((context._asyncFlags & HAS_BEFORE_AL) === 0) + return; + + var queue = context._asyncQueue; + var data = context._asyncData; + var i, queueItem; - // Run "before" callbacks. inAsyncTick = true; for (i = 0; i < queue.length; i++) { - item = queue[i]; - if (!item.callbacks) - continue; - before = item.callbacks.before; - if (typeof before === 'function') - before(context, item.value); + queueItem = queue[i]; + if ((queueItem.flags & HAS_BEFORE_AL) > 0) + queueItem.before(context, data[queueItem.uid]); } inAsyncTick = false; } - // Unload one level of the async stack. Returns true if there are - // still listeners somewhere in the stack. + // Unload the AsyncListener queue attached to context and run all + // "after" callbacks, if they exist. function unloadAsyncQueue(context) { + if ((context._asyncFlags & HAS_AFTER_AL) === 0) { + unloadContext(); + return; + } + var queue = context._asyncQueue; - var item, after, i; + var data = context._asyncData; + var i, queueItem; - // Run "after" callbacks. inAsyncTick = true; for (i = 0; i < queue.length; i++) { - item = queue[i]; - if (!item.callbacks) - continue; - after = item.callbacks.after; - if (typeof after === 'function') - after(context, item.value); + queueItem = queue[i]; + if ((queueItem.flags & HAS_AFTER_AL) > 0) + queueItem.after(context, data[queueItem.uid]); } inAsyncTick = false; - // Unload the current queue from the stack. - popQueue(); - - asyncFlags[kCount] = asyncQueue.length; - - return asyncQueue.length > 0 || asyncStack.length > 0; + unloadContext(); } - // Create new async listener object. Useful when instantiating a new - // object and want the listener instance, but not add it to the stack. - function createAsyncListener(listener, callbacks, value) { - return { - callbacks: callbacks, - value: value, - listener: listener, - uid: uid++ - }; - } - - // Add a listener to the current queue. - function addAsyncListener(listener, callbacks, value) { - // Accept new listeners or previous created listeners. - if (typeof listener === 'function') - callbacks = createAsyncListener(listener, callbacks, value); - else - callbacks = listener; - - var inQueue = false; - // The asyncQueue will be small. Probably always <= 3 items. - for (var i = 0; i < asyncQueue.length; i++) { - if (callbacks.uid === asyncQueue[i].uid) { - inQueue = true; - break; - } - } - - // Make sure the callback doesn't already exist in the queue. - if (!inQueue) - asyncQueue.push(callbacks); - - asyncFlags[kCount] = asyncQueue.length; - return callbacks; - } + // Handle errors that are thrown while in the context of an + // AsyncListener. If an error is thrown from an AsyncListener + // callback error handlers will be called once more to report + // the error, then the application will die forcefully. + function errorHandler(er) { + if (inErrorTick) + return false; - // Remove listener from the current queue and the entire stack. - function removeAsyncListener(obj) { - var i, j; + var handled = false; + var i, queueItem, threw; - for (i = 0; i < asyncQueue.length; i++) { - if (obj.uid === asyncQueue[i].uid) { - asyncQueue.splice(i, 1); - break; - } - } + inErrorTick = true; - for (i = 0; i < asyncStack.length; i++) { - for (j = 0; j < asyncStack[i].length; j++) { - if (obj.uid === asyncStack[i][j].uid) { - asyncStack[i].splice(j, 1); - break; + // First process error callbacks from the current context. + if (currentContext && (currentContext._asyncFlags & HAS_ERROR_AL) > 0) { + var queue = currentContext._asyncQueue; + var data = currentContext._asyncData; + for (i = 0; i < queue.length; i++) { + queueItem = queue[i]; + if ((queueItem.flags & HAS_ERROR_AL) === 0) + continue; + try { + threw = true; + // While it would be possible to pass in currentContext, if + // the error is thrown from the "create" callback then there's + // a chance the object hasn't been fully constructed. + handled = queueItem.error(data[queueItem.uid], er) || handled; + threw = false; + } finally { + // If the error callback thew then die quickly. Only allow the + // exit events to be processed. + if (threw) { + process._exiting = true; + process.emit('exit', 1); + } } } } - asyncFlags[kCount] = asyncQueue.length; - } - - // Error handler used by _fatalException to run through all error - // callbacks in the current asyncQueue. - function errorHandler(er) { - var handled = false; - var error, item, i; - - if (inErrorTick) - return false; - - inErrorTick = true; - for (i = 0; i < asyncQueue.length; i++) { - item = asyncQueue[i]; - if (!item.callbacks) - continue; - error = item.callbacks.error; - if (typeof error === 'function') { + // Now process callbacks from any existing queue. + if (asyncQueue) { + for (i = 0; i < asyncQueue.length; i++) { + queueItem = asyncQueue[i]; + if ((queueItem.flags & HAS_ERROR_AL) === 0 || + (data && data[queueItem.uid] !== undefined)) + continue; try { - var threw = true; - handled = error(item.value, er) || handled; + threw = true; + handled = queueItem.error(queueItem.data, er) || handled; threw = false; } finally { - // If the error callback throws then we're going to die - // quickly with no chance of recovery. Only thing we're going - // to allow is execution of process exit event callbacks. + // If the error callback thew then die quickly. Only allow the + // exit events to be processed. if (threw) { process._exiting = true; process.emit('exit', 1); @@ -476,51 +486,104 @@ } } } + inErrorTick = false; - // Unload the current queue from the stack. - popQueue(); + unloadContext(); + + // TODO(trevnorris): If the error was handled, should the after callbacks + // be fired anyways? return handled && !inAsyncTick; } - // Used by AsyncWrap::AddAsyncListener() to add an individual listener - // to the async queue. It will check the uid of the listener and only - // allow it to be added once. - function pushListener(obj) { - if (!this._asyncQueue) - this._asyncQueue = []; + // Instance function of an AsyncListener object. + function AsyncListenerInst(callbacks, data) { + if (typeof callbacks.create === 'function') { + this.create = callbacks.create; + this.flags |= HAS_CREATE_AL; + } + if (typeof callbacks.before === 'function') { + this.before = callbacks.before; + this.flags |= HAS_BEFORE_AL; + } + if (typeof callbacks.after === 'function') { + this.after = callbacks.after; + this.flags |= HAS_AFTER_AL; + } + if (typeof callbacks.error === 'function') { + this.error = callbacks.error; + this.flags |= HAS_ERROR_AL; + } + + this.uid = ++alUid; + this.data = data === undefined ? null : data; + } + AsyncListenerInst.prototype.create = undefined; + AsyncListenerInst.prototype.before = undefined; + AsyncListenerInst.prototype.after = undefined; + AsyncListenerInst.prototype.error = undefined; + AsyncListenerInst.prototype.data = undefined; + AsyncListenerInst.prototype.uid = 0; + AsyncListenerInst.prototype.flags = 0; + + // Create new async listener object. Useful when instantiating a new + // object and want the listener instance, but not add it to the stack. + // If an existing AsyncListenerInst is passed then any new "data" is + // ignored. + function createAsyncListener(callbacks, data) { + if (typeof callbacks !== 'object' || callbacks == null) + throw new TypeError('callbacks argument must be an object'); + + if (callbacks instanceof AsyncListenerInst) + return callbacks; + else + return new AsyncListenerInst(callbacks, data); + } + + // Add a listener to the current queue. + function addAsyncListener(callbacks, data) { + // Fast track if a new AsyncListenerInst has to be created. + if (!(callbacks instanceof AsyncListenerInst)) { + callbacks = createAsyncListener(callbacks, data); + asyncQueue.push(callbacks); + asyncFlags[kHasListener] = 1; + return callbacks; + } - var queue = this._asyncQueue; var inQueue = false; // The asyncQueue will be small. Probably always <= 3 items. - for (var i = 0; i < queue.length; i++) { - if (obj.uid === queue.uid) { + for (var i = 0; i < asyncQueue.length; i++) { + if (callbacks === asyncQueue[i]) { inQueue = true; break; } } - if (!inQueue) - queue.push(obj); - } + // Make sure the callback doesn't already exist in the queue. + if (!inQueue) { + asyncQueue.push(callbacks); + asyncFlags[kHasListener] = 1; + } - // Used by AsyncWrap::RemoveAsyncListener() to remove an individual - // listener from the async queue, and return whether there are still - // listeners in the queue. - function stripListener(obj) { - if (!this._asyncQueue || this._asyncQueue.length === 0) - return false; + return callbacks; + } - // The asyncQueue will be small. Probably always <= 3 items. - for (var i = 0; i < this._asyncQueue.length; i++) { - if (obj.uid === this._asyncQueue[i].uid) { - this._asyncQueue.splice(i, 1); + // Remove listener from the current queue. Though this will not remove + // the listener from the current context. So callback propagation will + // continue. + function removeAsyncListener(obj) { + for (var i = 0; i < asyncQueue.length; i++) { + if (obj === asyncQueue[i]) { + asyncQueue.splice(i, 1); break; } } - return this._asyncQueue.length > 0; + if (asyncQueue.length > 0 || currentContext !== undefined) + asyncFlags[kHasListener] = 1; + else + asyncFlags[kHasListener] = 0; } }; @@ -568,6 +631,7 @@ process.nextTick = nextTick; // Needs to be accessible from beyond this scope. process._tickCallback = _tickCallback; + process._tickDomainCallback = _tickDomainCallback; process._setupNextTick(tickInfo, _tickCallback); @@ -585,6 +649,7 @@ } // Run callbacks that have no domain. + // Using domains will cause this to be overridden. function _tickCallback() { var callback, hasQueue, threw, tock; @@ -611,6 +676,37 @@ tickDone(); } + function _tickDomainCallback() { + var callback, domain, hasQueue, threw, tock; + + while (tickInfo[kIndex] < tickInfo[kLength]) { + tock = nextTickQueue[tickInfo[kIndex]++]; + callback = tock.callback; + domain = tock.domain; + hasQueue = !!tock._asyncQueue; + if (hasQueue) + _loadAsyncQueue(tock); + if (domain) + domain.enter(); + threw = true; + try { + callback(); + threw = false; + } finally { + if (threw) + tickDone(); + } + if (hasQueue) + _unloadAsyncQueue(tock); + if (1e4 < tickInfo[kIndex]) + tickDone(); + if (domain) + domain.exit(); + } + + tickDone(); + } + function nextTick(callback) { // on the way out, don't bother. it won't get fired anyway. if (process._exiting) @@ -618,6 +714,7 @@ var obj = { callback: callback, + domain: process.domain || null, _asyncQueue: undefined }; @@ -674,7 +771,7 @@ case 'FILE': var fs = NativeModule.require('fs'); - stream = new fs.SyncWriteStream(fd); + stream = new fs.SyncWriteStream(fd, { autoClose: false }); stream._type = 'fs'; break; @@ -761,7 +858,7 @@ case 'FILE': var fs = NativeModule.require('fs'); - stdin = new fs.ReadStream(null, { fd: fd }); + stdin = new fs.ReadStream(null, { fd: fd, autoClose: false }); break; case 'PIPE': diff -Nru nodejs-0.11.10/src/node_buffer.cc nodejs-0.11.11/src/node_buffer.cc --- nodejs-0.11.10/src/node_buffer.cc 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/src/node_buffer.cc 2014-01-29 01:29:56.000000000 +0000 @@ -665,4 +665,4 @@ } // namespace Buffer } // namespace node -NODE_MODULE_CONTEXT_AWARE(node_buffer, node::Buffer::Initialize) +NODE_MODULE_CONTEXT_AWARE_BUILTIN(buffer, node::Buffer::Initialize) diff -Nru nodejs-0.11.10/src/node_constants.cc nodejs-0.11.11/src/node_constants.cc --- nodejs-0.11.10/src/node_constants.cc 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/src/node_constants.cc 2014-01-29 01:29:56.000000000 +0000 @@ -34,6 +34,9 @@ #if HAVE_OPENSSL # include +# ifndef OPENSSL_NO_ENGINE +# include +# endif // !OPENSSL_NO_ENGINE #endif namespace node { @@ -875,6 +878,58 @@ NODE_DEFINE_CONSTANT(target, SSL_OP_TLS_ROLLBACK_BUG); #endif +# ifndef OPENSSL_NO_ENGINE + +# ifdef ENGINE_METHOD_DSA + NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_DSA); +# endif + +# ifdef ENGINE_METHOD_DH + NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_DH); +# endif + +# ifdef ENGINE_METHOD_RAND + NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_RAND); +# endif + +# ifdef ENGINE_METHOD_ECDH + NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_ECDH); +# endif + +# ifdef ENGINE_METHOD_ECDSA + NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_ECDSA); +# endif + +# ifdef ENGINE_METHOD_CIPHERS + NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_CIPHERS); +# endif + +# ifdef ENGINE_METHOD_DIGESTS + NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_DIGESTS); +# endif + +# ifdef ENGINE_METHOD_STORE + NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_STORE); +# endif + +# ifdef ENGINE_METHOD_PKEY_METHS + NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_PKEY_METHS); +# endif + +# ifdef ENGINE_METHOD_PKEY_ASN1_METHS + NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_PKEY_ASN1_METHS); +# endif + +# ifdef ENGINE_METHOD_ALL + NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_ALL); +# endif + +# ifdef ENGINE_METHOD_NONE + NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_NONE); +# endif + +# endif // !OPENSSL_NO_ENGINE + #ifdef OPENSSL_NPN_NEGOTIATED #define NPN_ENABLED 1 NODE_DEFINE_CONSTANT(target, NPN_ENABLED); diff -Nru nodejs-0.11.10/src/node_contextify.cc nodejs-0.11.11/src/node_contextify.cc --- nodejs-0.11.10/src/node_contextify.cc 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/src/node_contextify.cc 2014-01-29 01:29:56.000000000 +0000 @@ -628,4 +628,4 @@ } // namespace node -NODE_MODULE_CONTEXT_AWARE(node_contextify, node::InitContextify); +NODE_MODULE_CONTEXT_AWARE_BUILTIN(contextify, node::InitContextify); diff -Nru nodejs-0.11.10/src/node_crypto.cc nodejs-0.11.11/src/node_crypto.cc --- nodejs-0.11.10/src/node_crypto.cc 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/src/node_crypto.cc 2014-01-29 01:29:56.000000000 +0000 @@ -83,6 +83,7 @@ using v8::Handle; using v8::HandleScope; using v8::Integer; +using v8::Isolate; using v8::Local; using v8::Null; using v8::Object; @@ -222,7 +223,7 @@ void SecureContext::Initialize(Environment* env, Handle target) { Local t = FunctionTemplate::New(SecureContext::New); t->InstanceTemplate()->SetInternalFieldCount(1); - t->SetClassName(FIXED_ONE_BYTE_STRING(node_isolate, "SecureContext")); + t->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "SecureContext")); NODE_SET_PROTOTYPE_METHOD(t, "init", SecureContext::Init); NODE_SET_PROTOTYPE_METHOD(t, "setKey", SecureContext::SetKey); @@ -242,7 +243,7 @@ NODE_SET_PROTOTYPE_METHOD(t, "getTicketKeys", SecureContext::GetTicketKeys); NODE_SET_PROTOTYPE_METHOD(t, "setTicketKeys", SecureContext::SetTicketKeys); - target->Set(FIXED_ONE_BYTE_STRING(node_isolate, "SecureContext"), + target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "SecureContext"), t->GetFunction()); env->set_secure_context_constructor_template(t); } @@ -256,7 +257,7 @@ void SecureContext::Init(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); SecureContext* sc = Unwrap(args.This()); @@ -382,7 +383,7 @@ void SecureContext::SetKey(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); SecureContext* sc = Unwrap(args.This()); @@ -488,7 +489,7 @@ void SecureContext::SetCert(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); SecureContext* sc = Unwrap(args.This()); @@ -516,7 +517,7 @@ void SecureContext::AddCACert(const FunctionCallbackInfo& args) { bool newCAStore = false; - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); SecureContext* sc = Unwrap(args.This()); @@ -545,7 +546,7 @@ void SecureContext::AddCRL(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); SecureContext* sc = Unwrap(args.This()); @@ -577,7 +578,7 @@ void SecureContext::AddRootCerts(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); SecureContext* sc = Unwrap(args.This()); @@ -614,7 +615,7 @@ void SecureContext::SetCiphers(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); SecureContext* sc = Unwrap(args.This()); @@ -628,7 +629,7 @@ void SecureContext::SetECDHCurve(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); SecureContext* sc = Unwrap(args.This()); @@ -655,7 +656,7 @@ void SecureContext::SetOptions(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); SecureContext* sc = Unwrap(args.This()); @@ -669,7 +670,7 @@ void SecureContext::SetSessionIdContext( const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); SecureContext* sc = Unwrap(args.This()); @@ -692,12 +693,12 @@ bio = BIO_new(BIO_s_mem()); if (bio == NULL) { - message = FIXED_ONE_BYTE_STRING(node_isolate, + message = FIXED_ONE_BYTE_STRING(args.GetIsolate(), "SSL_CTX_set_session_id_context error"); } else { ERR_print_errors(bio); BIO_get_mem_ptr(bio, &mem); - message = OneByteString(node_isolate, mem->data, mem->length); + message = OneByteString(args.GetIsolate(), mem->data, mem->length); BIO_free_all(bio); } @@ -706,7 +707,7 @@ void SecureContext::SetSessionTimeout(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); SecureContext* sc = Unwrap(args.This()); @@ -720,7 +721,7 @@ void SecureContext::Close(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); SecureContext* sc = Unwrap(args.This()); sc->FreeCTXMem(); } @@ -728,7 +729,7 @@ // Takes .pfx or .p12 and password in string or buffer format void SecureContext::LoadPKCS12(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); BIO* in = NULL; PKCS12* p12 = NULL; @@ -819,7 +820,7 @@ void SecureContext::SetTicketKeys(const FunctionCallbackInfo& args) { #if !defined(OPENSSL_NO_TLSEXT) && defined(SSL_CTX_get_tlsext_ticket_keys) - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); if (args.Length() < 1 || !Buffer::HasInstance(args[0]) || @@ -856,6 +857,10 @@ NODE_SET_PROTOTYPE_METHOD(t, "renegotiate", Renegotiate); NODE_SET_PROTOTYPE_METHOD(t, "shutdown", Shutdown); +#ifdef SSL_set_max_send_fragment + NODE_SET_PROTOTYPE_METHOD(t, "setMaxSendFragment", SetMaxSendFragment); +#endif // SSL_set_max_send_fragment + #ifdef OPENSSL_NPN_NEGOTIATED NODE_SET_PROTOTYPE_METHOD(t, "getNegotiatedProtocol", GetNegotiatedProto); NODE_SET_PROTOTYPE_METHOD(t, "setNPNProtocols", SetNPNProtocols); @@ -962,11 +967,14 @@ template void SSLWrap::GetPeerCertificate( const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Base* w = Unwrap(args.This()); Environment* env = w->ssl_env(); + ClearErrorOnReturn clear_error_on_return; + (void) &clear_error_on_return; // Silence unused variable warning. + Local info = Object::New(); X509* peer_cert = SSL_get_peer_certificate(w->ssl_); if (peer_cert != NULL) { @@ -978,7 +986,7 @@ X509_NAME_FLAGS) > 0) { BIO_get_mem_ptr(bio, &mem); info->Set(env->subject_string(), - OneByteString(node_isolate, mem->data, mem->length)); + OneByteString(args.GetIsolate(), mem->data, mem->length)); } (void) BIO_reset(bio); @@ -986,7 +994,7 @@ if (X509_NAME_print_ex(bio, issuer_name, 0, X509_NAME_FLAGS) > 0) { BIO_get_mem_ptr(bio, &mem); info->Set(env->issuer_string(), - OneByteString(node_isolate, mem->data, mem->length)); + OneByteString(args.GetIsolate(), mem->data, mem->length)); } (void) BIO_reset(bio); @@ -1003,7 +1011,7 @@ BIO_get_mem_ptr(bio, &mem); info->Set(env->subjectaltname_string(), - OneByteString(node_isolate, mem->data, mem->length)); + OneByteString(args.GetIsolate(), mem->data, mem->length)); (void) BIO_reset(bio); } @@ -1017,13 +1025,13 @@ BN_print(bio, rsa->n); BIO_get_mem_ptr(bio, &mem); info->Set(env->modulus_string(), - OneByteString(node_isolate, mem->data, mem->length)); + OneByteString(args.GetIsolate(), mem->data, mem->length)); (void) BIO_reset(bio); BN_print(bio, rsa->e); BIO_get_mem_ptr(bio, &mem); info->Set(env->exponent_string(), - OneByteString(node_isolate, mem->data, mem->length)); + OneByteString(args.GetIsolate(), mem->data, mem->length)); (void) BIO_reset(bio); } @@ -1039,13 +1047,13 @@ ASN1_TIME_print(bio, X509_get_notBefore(peer_cert)); BIO_get_mem_ptr(bio, &mem); info->Set(env->valid_from_string(), - OneByteString(node_isolate, mem->data, mem->length)); + OneByteString(args.GetIsolate(), mem->data, mem->length)); (void) BIO_reset(bio); ASN1_TIME_print(bio, X509_get_notAfter(peer_cert)); BIO_get_mem_ptr(bio, &mem); info->Set(env->valid_to_string(), - OneByteString(node_isolate, mem->data, mem->length)); + OneByteString(args.GetIsolate(), mem->data, mem->length)); BIO_free_all(bio); unsigned int md_size, i; @@ -1068,7 +1076,7 @@ } info->Set(env->fingerprint_string(), - OneByteString(node_isolate, fingerprint)); + OneByteString(args.GetIsolate(), fingerprint)); } STACK_OF(ASN1_OBJECT)* eku = static_cast( @@ -1080,7 +1088,7 @@ int j = 0; for (int i = 0; i < sk_ASN1_OBJECT_num(eku); i++) { if (OBJ_obj2txt(buf, sizeof(buf), sk_ASN1_OBJECT_value(eku, i), 1) >= 0) - ext_key_usage->Set(j++, OneByteString(node_isolate, buf)); + ext_key_usage->Set(j++, OneByteString(args.GetIsolate(), buf)); } sk_ASN1_OBJECT_pop_free(eku, ASN1_OBJECT_free); @@ -1091,7 +1099,7 @@ if (BIGNUM* bn = ASN1_INTEGER_to_BN(serial_number, NULL)) { if (char* buf = BN_bn2hex(bn)) { info->Set(env->serial_number_string(), - OneByteString(node_isolate, buf)); + OneByteString(args.GetIsolate(), buf)); OPENSSL_free(buf); } BN_free(bn); @@ -1107,7 +1115,7 @@ template void SSLWrap::GetSession(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Base* w = Unwrap(args.This()); @@ -1128,7 +1136,7 @@ template void SSLWrap::SetSession(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Base* w = Unwrap(args.This()); @@ -1166,7 +1174,7 @@ template void SSLWrap::LoadSession(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Base* w = Unwrap(args.This()); Environment* env = w->ssl_env(); @@ -1186,10 +1194,10 @@ Local info = Object::New(); #ifndef OPENSSL_NO_TLSEXT if (sess->tlsext_hostname == NULL) { - info->Set(env->servername_string(), False(node_isolate)); + info->Set(env->servername_string(), False(args.GetIsolate())); } else { info->Set(env->servername_string(), - OneByteString(node_isolate, sess->tlsext_hostname)); + OneByteString(args.GetIsolate(), sess->tlsext_hostname)); } #endif args.GetReturnValue().Set(info); @@ -1199,7 +1207,7 @@ template void SSLWrap::IsSessionReused(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Base* w = Unwrap(args.This()); bool yes = SSL_session_reused(w->ssl_); args.GetReturnValue().Set(yes); @@ -1208,7 +1216,7 @@ template void SSLWrap::EndParser(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Base* w = Unwrap(args.This()); w->hello_parser_.End(); } @@ -1216,7 +1224,7 @@ template void SSLWrap::Renegotiate(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Base* w = Unwrap(args.This()); @@ -1230,7 +1238,7 @@ template void SSLWrap::Shutdown(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Base* w = Unwrap(args.This()); @@ -1239,41 +1247,55 @@ } +#ifdef SSL_set_max_send_fragment template -void SSLWrap::IsInitFinished(const FunctionCallbackInfo& args) { +void SSLWrap::SetMaxSendFragment( + const v8::FunctionCallbackInfo& args) { HandleScope scope(node_isolate); + CHECK(args.Length() >= 1 && args[0]->IsNumber()); + + Base* w = Unwrap(args.This()); + + int rv = SSL_set_max_send_fragment(w->ssl_, args[0]->Int32Value()); + args.GetReturnValue().Set(rv); +} +#endif // SSL_set_max_send_fragment + + +template +void SSLWrap::IsInitFinished(const FunctionCallbackInfo& args) { + HandleScope scope(args.GetIsolate()); Base* w = Unwrap(args.This()); bool yes = SSL_is_init_finished(w->ssl_); args.GetReturnValue().Set(yes); } -#define CASE_X509_ERR(CODE) case X509_V_ERR_##CODE: reason = #CODE; break; template void SSLWrap::VerifyError(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Base* w = Unwrap(args.This()); - // XXX(indutny) Do this check in JS land? - X509* peer_cert = SSL_get_peer_certificate(w->ssl_); - if (peer_cert == NULL) { - // We requested a certificate and they did not send us one. - // Definitely an error. - // XXX(indutny) is this the right error message? - Local s = - FIXED_ONE_BYTE_STRING(node_isolate, "UNABLE_TO_GET_ISSUER_CERT"); - return args.GetReturnValue().Set(Exception::Error(s)); + // XXX(bnoordhuis) The UNABLE_TO_GET_ISSUER_CERT error when there is no + // peer certificate is questionable but it's compatible with what was + // here before. + long x509_verify_error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT; + if (X509* peer_cert = SSL_get_peer_certificate(w->ssl_)) { + X509_free(peer_cert); + x509_verify_error = SSL_get_verify_result(w->ssl_); } - X509_free(peer_cert); - long x509_verify_error = SSL_get_verify_result(w->ssl_); + if (x509_verify_error == X509_V_OK) + return args.GetReturnValue().SetNull(); - const char* reason = NULL; - Local s; + // XXX(bnoordhuis) X509_verify_cert_error_string() is not actually thread-safe + // in the presence of invalid error codes. Probably academical but something + // to keep in mind if/when node ever grows multi-isolate capabilities. + const char* reason = X509_verify_cert_error_string(x509_verify_error); + const char* code = reason; +#define CASE_X509_ERR(CODE) case X509_V_ERR_##CODE: code = #CODE; break; switch (x509_verify_error) { - case X509_V_OK: - return args.GetReturnValue().SetNull(); CASE_X509_ERR(UNABLE_TO_GET_ISSUER_CERT) CASE_X509_ERR(UNABLE_TO_GET_CRL) CASE_X509_ERR(UNABLE_TO_DECRYPT_CERT_SIGNATURE) @@ -1301,23 +1323,22 @@ CASE_X509_ERR(INVALID_PURPOSE) CASE_X509_ERR(CERT_UNTRUSTED) CASE_X509_ERR(CERT_REJECTED) - default: - s = OneByteString(node_isolate, - X509_verify_cert_error_string(x509_verify_error)); - break; } +#undef CASE_X509_ERR - if (s.IsEmpty()) - s = OneByteString(node_isolate, reason); - - args.GetReturnValue().Set(Exception::Error(s)); + Isolate* isolate = args.GetIsolate(); + Local reason_string = OneByteString(isolate, reason); + Local exception_value = Exception::Error(reason_string); + Local exception_object = exception_value->ToObject(); + exception_object->Set(FIXED_ONE_BYTE_STRING(isolate, "code"), + OneByteString(isolate, code)); + args.GetReturnValue().Set(exception_object); } -#undef CASE_X509_ERR template void SSLWrap::GetCurrentCipher(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Base* w = Unwrap(args.This()); Environment* env = w->ssl_env(); @@ -1328,9 +1349,10 @@ Local info = Object::New(); const char* cipher_name = SSL_CIPHER_get_name(c); - info->Set(env->name_string(), OneByteString(node_isolate, cipher_name)); + info->Set(env->name_string(), OneByteString(args.GetIsolate(), cipher_name)); const char* cipher_version = SSL_CIPHER_get_version(c); - info->Set(env->version_string(), OneByteString(node_isolate, cipher_version)); + info->Set(env->version_string(), + OneByteString(args.GetIsolate(), cipher_version)); args.GetReturnValue().Set(info); } @@ -1351,7 +1373,7 @@ *data = reinterpret_cast(""); *len = 0; } else { - Local obj = PersistentToLocal(node_isolate, w->npn_protos_); + Local obj = PersistentToLocal(env->isolate(), w->npn_protos_); *data = reinterpret_cast(Buffer::Data(obj)); *len = Buffer::Length(obj); } @@ -1382,12 +1404,12 @@ *outlen = 8; // set status: unsupported - w->selected_npn_proto_.Reset(node_isolate, False(node_isolate)); + w->selected_npn_proto_.Reset(env->isolate(), False(env->isolate())); return SSL_TLSEXT_ERR_OK; } - Local obj = PersistentToLocal(node_isolate, w->npn_protos_); + Local obj = PersistentToLocal(env->isolate(), w->npn_protos_); const unsigned char* npn_protos = reinterpret_cast(Buffer::Data(obj)); size_t len = Buffer::Length(obj); @@ -1396,20 +1418,20 @@ Handle result; switch (status) { case OPENSSL_NPN_UNSUPPORTED: - result = Null(node_isolate); + result = Null(env->isolate()); break; case OPENSSL_NPN_NEGOTIATED: - result = OneByteString(node_isolate, *out, *outlen); + result = OneByteString(env->isolate(), *out, *outlen); break; case OPENSSL_NPN_NO_OVERLAP: - result = False(node_isolate); + result = False(env->isolate()); break; default: break; } if (!result.IsEmpty()) - w->selected_npn_proto_.Reset(node_isolate, result); + w->selected_npn_proto_.Reset(env->isolate(), result); return SSL_TLSEXT_ERR_OK; } @@ -1418,7 +1440,7 @@ template void SSLWrap::GetNegotiatedProto( const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Base* w = Unwrap(args.This()); @@ -1438,20 +1460,20 @@ return args.GetReturnValue().Set(false); args.GetReturnValue().Set( - OneByteString(node_isolate, npn_proto, npn_proto_len)); + OneByteString(args.GetIsolate(), npn_proto, npn_proto_len)); } template void SSLWrap::SetNPNProtocols(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Base* w = Unwrap(args.This()); if (args.Length() < 1 || !Buffer::HasInstance(args[0])) return ThrowTypeError("Must give a Buffer as first argument"); - w->npn_protos_.Reset(node_isolate, args[0].As()); + w->npn_protos_.Reset(args.GetIsolate(), args[0].As()); } #endif // OPENSSL_NPN_NEGOTIATED @@ -1612,7 +1634,7 @@ void Connection::Initialize(Environment* env, Handle target) { Local t = FunctionTemplate::New(Connection::New); t->InstanceTemplate()->SetInternalFieldCount(1); - t->SetClassName(FIXED_ONE_BYTE_STRING(node_isolate, "Connection")); + t->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "Connection")); NODE_SET_PROTOTYPE_METHOD(t, "encIn", Connection::EncIn); NODE_SET_PROTOTYPE_METHOD(t, "clearOut", Connection::ClearOut); @@ -1640,7 +1662,7 @@ NODE_SET_PROTOTYPE_METHOD(t, "setSNICallback", Connection::SetSNICallback); #endif - target->Set(FIXED_ONE_BYTE_STRING(node_isolate, "Connection"), + target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "Connection"), t->GetFunction()); } @@ -1693,29 +1715,28 @@ #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB int Connection::SelectSNIContextCallback_(SSL *s, int *ad, void* arg) { - HandleScope scope(node_isolate); - Connection* conn = static_cast(SSL_get_app_data(s)); Environment* env = conn->env(); + HandleScope scope(env->isolate()); const char* servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name); if (servername) { - conn->servername_.Reset(node_isolate, - OneByteString(node_isolate, servername)); + conn->servername_.Reset(env->isolate(), + OneByteString(env->isolate(), servername)); // Call the SNI callback and use its return value as context if (!conn->sniObject_.IsEmpty()) { conn->sniContext_.Dispose(); - Local arg = PersistentToLocal(node_isolate, conn->servername_); + Local arg = PersistentToLocal(env->isolate(), conn->servername_); Local ret = conn->MakeCallback(env->onselect_string(), 1, &arg); // If ret is SecureContext Local secure_context_constructor_template = env->secure_context_constructor_template(); if (secure_context_constructor_template->HasInstance(ret)) { - conn->sniContext_.Reset(node_isolate, ret); + conn->sniContext_.Reset(env->isolate(), ret); SecureContext* sc = Unwrap(ret.As()); InitNPN(sc, conn); SSL_set_SSL_CTX(s, sc->ctx_); @@ -1730,7 +1751,7 @@ #endif void Connection::New(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); if (args.Length() < 1 || !args[0]->IsObject()) { return ThrowError("First argument must be a crypto module Credentials"); @@ -1824,7 +1845,7 @@ void Connection::EncIn(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Connection* conn = Unwrap(args.This()); @@ -1874,7 +1895,7 @@ void Connection::ClearOut(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Connection* conn = Unwrap(args.This()); @@ -1929,7 +1950,7 @@ void Connection::ClearPending(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Connection* conn = Unwrap(args.This()); int bytes_pending = BIO_pending(conn->bio_read_); args.GetReturnValue().Set(bytes_pending); @@ -1937,7 +1958,7 @@ void Connection::EncPending(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Connection* conn = Unwrap(args.This()); int bytes_pending = BIO_pending(conn->bio_write_); args.GetReturnValue().Set(bytes_pending); @@ -1945,7 +1966,7 @@ void Connection::EncOut(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Connection* conn = Unwrap(args.This()); @@ -1976,7 +1997,7 @@ void Connection::ClearIn(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Connection* conn = Unwrap(args.This()); @@ -2031,7 +2052,7 @@ void Connection::Start(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Connection* conn = Unwrap(args.This()); @@ -2056,7 +2077,7 @@ void Connection::Close(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Connection* conn = Unwrap(args.This()); @@ -2069,7 +2090,7 @@ #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB void Connection::GetServername(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Connection* conn = Unwrap(args.This()); @@ -2082,7 +2103,7 @@ void Connection::SetSNICallback(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Connection* conn = Unwrap(args.This()); @@ -2091,8 +2112,8 @@ } Local obj = Object::New(); - obj->Set(FIXED_ONE_BYTE_STRING(node_isolate, "onselect"), args[0]); - conn->sniObject_.Reset(node_isolate, obj); + obj->Set(FIXED_ONE_BYTE_STRING(args.GetIsolate(), "onselect"), args[0]); + conn->sniObject_.Reset(args.GetIsolate(), obj); } #endif @@ -2110,7 +2131,7 @@ NODE_SET_PROTOTYPE_METHOD(t, "getAuthTag", GetAuthTag); NODE_SET_PROTOTYPE_METHOD(t, "setAuthTag", SetAuthTag); - target->Set(FIXED_ONE_BYTE_STRING(node_isolate, "CipherBase"), + target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "CipherBase"), t->GetFunction()); } @@ -2165,7 +2186,7 @@ void CipherBase::Init(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); CipherBase* cipher = Unwrap(args.This()); @@ -2217,7 +2238,7 @@ void CipherBase::InitIv(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); CipherBase* cipher = Unwrap(args.This()); @@ -2376,7 +2397,7 @@ void CipherBase::SetAutoPadding(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); CipherBase* cipher = Unwrap(args.This()); cipher->SetAutoPadding(args.Length() < 1 || args[0]->BooleanValue()); } @@ -2444,7 +2465,7 @@ NODE_SET_PROTOTYPE_METHOD(t, "update", HmacUpdate); NODE_SET_PROTOTYPE_METHOD(t, "digest", HmacDigest); - target->Set(FIXED_ONE_BYTE_STRING(node_isolate, "Hmac"), t->GetFunction()); + target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "Hmac"), t->GetFunction()); } @@ -2474,7 +2495,7 @@ void Hmac::HmacInit(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Hmac* hmac = Unwrap(args.This()); @@ -2500,7 +2521,7 @@ void Hmac::HmacUpdate(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Hmac* hmac = Unwrap(args.This()); @@ -2542,7 +2563,7 @@ void Hmac::HmacDigest(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Hmac* hmac = Unwrap(args.This()); @@ -2575,12 +2596,12 @@ NODE_SET_PROTOTYPE_METHOD(t, "update", HashUpdate); NODE_SET_PROTOTYPE_METHOD(t, "digest", HashDigest); - target->Set(FIXED_ONE_BYTE_STRING(node_isolate, "Hash"), t->GetFunction()); + target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "Hash"), t->GetFunction()); } void Hash::New(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); if (args.Length() == 0 || !args[0]->IsString()) { return ThrowError("Must give hashtype string as argument"); @@ -2617,7 +2638,7 @@ void Hash::HashUpdate(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Hash* hash = Unwrap(args.This()); @@ -2648,7 +2669,7 @@ void Hash::HashDigest(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Hash* hash = Unwrap(args.This()); @@ -2674,6 +2695,46 @@ } +void SignBase::CheckThrow(SignBase::Error error) { + HandleScope scope(node_isolate); + + switch (error) { + case kSignUnknownDigest: + return ThrowError("Unknown message digest"); + + case kSignNotInitialised: + return ThrowError("Not initialised"); + + case kSignInit: + case kSignUpdate: + case kSignPrivateKey: + case kSignPublicKey: + { + unsigned long err = ERR_get_error(); + if (err) + return ThrowCryptoError(err); + switch (error) { + case kSignInit: + return ThrowError("EVP_SignInit_ex failed"); + case kSignUpdate: + return ThrowError("EVP_SignUpdate failed"); + case kSignPrivateKey: + return ThrowError("PEM_read_bio_PrivateKey failed"); + case kSignPublicKey: + return ThrowError("PEM_read_bio_PUBKEY failed"); + default: + abort(); + } + } + + case kSignOk: + return; + } +} + + + + void Sign::Initialize(Environment* env, v8::Handle target) { Local t = FunctionTemplate::New(New); @@ -2683,7 +2744,7 @@ NODE_SET_PROTOTYPE_METHOD(t, "update", SignUpdate); NODE_SET_PROTOTYPE_METHOD(t, "sign", SignFinal); - target->Set(FIXED_ONE_BYTE_STRING(node_isolate, "Sign"), t->GetFunction()); + target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "Sign"), t->GetFunction()); } @@ -2694,22 +2755,23 @@ } -void Sign::SignInit(const char* sign_type) { - HandleScope scope(node_isolate); - +SignBase::Error Sign::SignInit(const char* sign_type) { assert(md_ == NULL); md_ = EVP_get_digestbyname(sign_type); - if (!md_) { - return ThrowError("Uknown message digest"); - } + if (!md_) + return kSignUnknownDigest; + EVP_MD_CTX_init(&mdctx_); - EVP_SignInit_ex(&mdctx_, md_, NULL); + if (!EVP_SignInit_ex(&mdctx_, md_, NULL)) + return kSignInit; initialised_ = true; + + return kSignOk; } void Sign::SignInit(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Sign* sign = Unwrap(args.This()); @@ -2718,27 +2780,28 @@ } const String::Utf8Value sign_type(args[0]); - sign->SignInit(*sign_type); + CheckThrow(sign->SignInit(*sign_type)); } -bool Sign::SignUpdate(const char* data, int len) { +SignBase::Error Sign::SignUpdate(const char* data, int len) { if (!initialised_) - return false; - EVP_SignUpdate(&mdctx_, data, len); - return true; + return kSignNotInitialised; + if (!EVP_SignUpdate(&mdctx_, data, len)) + return kSignUpdate; + return kSignOk; } void Sign::SignUpdate(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Sign* sign = Unwrap(args.This()); ASSERT_IS_STRING_OR_BUFFER(args[0]); // Only copy the data if we have to, because it's a string - int r; + Error err; if (args[0]->IsString()) { Local string = args[0].As(); enum encoding encoding = ParseEncoding(args[1], BINARY); @@ -2747,29 +2810,25 @@ size_t buflen = StringBytes::StorageSize(string, encoding); char* buf = new char[buflen]; size_t written = StringBytes::Write(buf, buflen, string, encoding); - r = sign->SignUpdate(buf, written); + err = sign->SignUpdate(buf, written); delete[] buf; } else { char* buf = Buffer::Data(args[0]); size_t buflen = Buffer::Length(args[0]); - r = sign->SignUpdate(buf, buflen); + err = sign->SignUpdate(buf, buflen); } - if (!r) { - return ThrowTypeError("SignUpdate fail"); - } + CheckThrow(err); } -bool Sign::SignFinal(const char* key_pem, - int key_pem_len, - const char* passphrase, - unsigned char** sig, - unsigned int *sig_len) { - if (!initialised_) { - ThrowError("Sign not initalised"); - return false; - } +SignBase::Error Sign::SignFinal(const char* key_pem, + int key_pem_len, + const char* passphrase, + unsigned char** sig, + unsigned int *sig_len) { + if (!initialised_) + return kSignNotInitialised; BIO* bp = NULL; EVP_PKEY* pkey = NULL; @@ -2802,22 +2861,15 @@ EVP_MD_CTX_cleanup(&mdctx_); - if (fatal) { - unsigned long err = ERR_get_error(); - if (err) { - ThrowCryptoError(err); - } else { - ThrowError("PEM_read_bio_PrivateKey"); - } - return false; - } + if (fatal) + return kSignPrivateKey; - return true; + return kSignOk; } void Sign::SignFinal(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Sign* sign = Unwrap(args.This()); @@ -2839,15 +2891,17 @@ md_len = 8192; // Maximum key size is 8192 bits md_value = new unsigned char[md_len]; - bool r = sign->SignFinal(buf, - buf_len, - len >= 3 && !args[2]->IsNull() ? *passphrase : NULL, - &md_value, - &md_len); - if (!r) { + Error err = sign->SignFinal( + buf, + buf_len, + len >= 3 && !args[2]->IsNull() ? *passphrase : NULL, + &md_value, + &md_len); + if (err != kSignOk) { delete[] md_value; md_value = NULL; md_len = 0; + return CheckThrow(err); } Local rc = StringBytes::Encode( @@ -2866,7 +2920,8 @@ NODE_SET_PROTOTYPE_METHOD(t, "update", VerifyUpdate); NODE_SET_PROTOTYPE_METHOD(t, "verify", VerifyFinal); - target->Set(FIXED_ONE_BYTE_STRING(node_isolate, "Verify"), t->GetFunction()); + target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "Verify"), + t->GetFunction()); } @@ -2877,23 +2932,23 @@ } -void Verify::VerifyInit(const char* verify_type) { - HandleScope scope(node_isolate); - +SignBase::Error Verify::VerifyInit(const char* verify_type) { assert(md_ == NULL); md_ = EVP_get_digestbyname(verify_type); - if (md_ == NULL) { - return ThrowError("Unknown message digest"); - } + if (md_ == NULL) + return kSignUnknownDigest; EVP_MD_CTX_init(&mdctx_); - EVP_VerifyInit_ex(&mdctx_, md_, NULL); + if (!EVP_VerifyInit_ex(&mdctx_, md_, NULL)) + return kSignInit; initialised_ = true; + + return kSignOk; } void Verify::VerifyInit(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Verify* verify = Unwrap(args.This()); @@ -2902,27 +2957,30 @@ } const String::Utf8Value verify_type(args[0]); - verify->VerifyInit(*verify_type); + CheckThrow(verify->VerifyInit(*verify_type)); } -bool Verify::VerifyUpdate(const char* data, int len) { +SignBase::Error Verify::VerifyUpdate(const char* data, int len) { if (!initialised_) - return false; - EVP_VerifyUpdate(&mdctx_, data, len); - return true; + return kSignNotInitialised; + + if (!EVP_VerifyUpdate(&mdctx_, data, len)) + return kSignUpdate; + + return kSignOk; } void Verify::VerifyUpdate(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Verify* verify = Unwrap(args.This()); ASSERT_IS_STRING_OR_BUFFER(args[0]); // Only copy the data if we have to, because it's a string - bool r; + Error err; if (args[0]->IsString()) { Local string = args[0].As(); enum encoding encoding = ParseEncoding(args[1], BINARY); @@ -2931,30 +2989,25 @@ size_t buflen = StringBytes::StorageSize(string, encoding); char* buf = new char[buflen]; size_t written = StringBytes::Write(buf, buflen, string, encoding); - r = verify->VerifyUpdate(buf, written); + err = verify->VerifyUpdate(buf, written); delete[] buf; } else { char* buf = Buffer::Data(args[0]); size_t buflen = Buffer::Length(args[0]); - r = verify->VerifyUpdate(buf, buflen); + err = verify->VerifyUpdate(buf, buflen); } - if (!r) { - return ThrowTypeError("VerifyUpdate fail"); - } + CheckThrow(err); } -bool Verify::VerifyFinal(const char* key_pem, - int key_pem_len, - const char* sig, - int siglen) { - HandleScope scope(node_isolate); - - if (!initialised_) { - ThrowError("Verify not initalised"); - return false; - } +SignBase::Error Verify::VerifyFinal(const char* key_pem, + int key_pem_len, + const char* sig, + int siglen, + bool* verify_result) { + if (!initialised_) + return kSignNotInitialised; ClearErrorOnReturn clear_error_on_return; (void) &clear_error_on_return; // Silence compiler warning. @@ -3017,18 +3070,16 @@ EVP_MD_CTX_cleanup(&mdctx_); initialised_ = false; - if (fatal) { - unsigned long err = ERR_get_error(); - ThrowCryptoError(err); - return false; - } + if (fatal) + return kSignPublicKey; - return r == 1; + *verify_result = r == 1; + return kSignOk; } void Verify::VerifyFinal(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Verify* verify = Unwrap(args.This()); @@ -3055,11 +3106,13 @@ hbuf = Buffer::Data(args[1]); } - bool rc = verify->VerifyFinal(kbuf, klen, hbuf, hlen); - if (args[1]->IsString()) { + bool verify_result; + Error err = verify->VerifyFinal(kbuf, klen, hbuf, hlen, &verify_result); + if (args[1]->IsString()) delete[] hbuf; - } - args.GetReturnValue().Set(rc); + if (err != kSignOk) + return CheckThrow(err); + args.GetReturnValue().Set(verify_result); } @@ -3077,7 +3130,7 @@ NODE_SET_PROTOTYPE_METHOD(t, "setPublicKey", SetPublicKey); NODE_SET_PROTOTYPE_METHOD(t, "setPrivateKey", SetPrivateKey); - target->Set(FIXED_ONE_BYTE_STRING(node_isolate, "DiffieHellman"), + target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "DiffieHellman"), t->GetFunction()); Local t2 = FunctionTemplate::New(DiffieHellmanGroup); @@ -3090,7 +3143,7 @@ NODE_SET_PROTOTYPE_METHOD(t2, "getPublicKey", GetPublicKey); NODE_SET_PROTOTYPE_METHOD(t2, "getPrivateKey", GetPrivateKey); - target->Set(FIXED_ONE_BYTE_STRING(node_isolate, "DiffieHellmanGroup"), + target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "DiffieHellmanGroup"), t2->GetFunction()); } @@ -3131,7 +3184,7 @@ void DiffieHellman::DiffieHellmanGroup( const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Environment* env = Environment::GetCurrent(args.GetIsolate()); DiffieHellman* diffieHellman = new DiffieHellman(env, args.This()); @@ -3159,7 +3212,7 @@ void DiffieHellman::New(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Environment* env = Environment::GetCurrent(args.GetIsolate()); DiffieHellman* diffieHellman = @@ -3182,7 +3235,7 @@ void DiffieHellman::GenerateKeys(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); DiffieHellman* diffieHellman = Unwrap(args.This()); @@ -3205,7 +3258,7 @@ void DiffieHellman::GetPrime(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); DiffieHellman* diffieHellman = Unwrap(args.This()); @@ -3223,7 +3276,7 @@ void DiffieHellman::GetGenerator(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); DiffieHellman* diffieHellman = Unwrap(args.This()); @@ -3241,7 +3294,7 @@ void DiffieHellman::GetPublicKey(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); DiffieHellman* diffieHellman = Unwrap(args.This()); @@ -3264,7 +3317,7 @@ void DiffieHellman::GetPrivateKey(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); DiffieHellman* diffieHellman = Unwrap(args.This()); @@ -3287,7 +3340,7 @@ void DiffieHellman::ComputeSecret(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); DiffieHellman* diffieHellman = Unwrap(args.This()); @@ -3358,7 +3411,7 @@ void DiffieHellman::SetPublicKey(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); DiffieHellman* diffieHellman = Unwrap(args.This()); @@ -3378,7 +3431,7 @@ void DiffieHellman::SetPrivateKey(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); DiffieHellman* diffieHellman = Unwrap(args.This()); @@ -3418,6 +3471,7 @@ public: PBKDF2Request(Environment* env, Local object, + const EVP_MD* digest, ssize_t passlen, char* pass, ssize_t saltlen, @@ -3425,6 +3479,7 @@ ssize_t iter, ssize_t keylen) : AsyncWrap(env, object), + digest_(digest), error_(0), passlen_(passlen), pass_(pass), @@ -3445,6 +3500,10 @@ return &work_req_; } + inline const EVP_MD* digest() const { + return digest_; + } + inline ssize_t passlen() const { return passlen_; } @@ -3494,6 +3553,7 @@ uv_work_t work_req_; private: + const EVP_MD* digest_; int error_; ssize_t passlen_; char* pass_; @@ -3506,12 +3566,13 @@ void EIO_PBKDF2(PBKDF2Request* req) { - req->set_error(PKCS5_PBKDF2_HMAC_SHA1( + req->set_error(PKCS5_PBKDF2_HMAC( req->pass(), req->passlen(), reinterpret_cast(req->salt()), req->saltlen(), req->iter(), + req->digest(), req->keylen(), reinterpret_cast(req->key()))); memset(req->pass(), 0, req->passlen()); @@ -3556,6 +3617,7 @@ HandleScope handle_scope(args.GetIsolate()); Environment* env = Environment::GetCurrent(args.GetIsolate()); + const EVP_MD* digest = NULL; const char* type_error = NULL; char* pass = NULL; char* salt = NULL; @@ -3568,7 +3630,7 @@ PBKDF2Request* req = NULL; Local obj; - if (args.Length() != 4 && args.Length() != 5) { + if (args.Length() != 5 && args.Length() != 6) { type_error = "Bad parameter"; goto err; } @@ -3623,11 +3685,35 @@ goto err; } - obj = Object::New(); - req = new PBKDF2Request(env, obj, passlen, pass, saltlen, salt, iter, keylen); + if (args[4]->IsString()) { + String::Utf8Value digest_name(args[4]); + digest = EVP_get_digestbyname(*digest_name); + if (digest == NULL) { + type_error = "Bad digest name"; + goto err; + } + } - if (args[4]->IsFunction()) { - obj->Set(env->ondone_string(), args[4]); + if (digest == NULL) { + digest = EVP_sha1(); + } + + obj = Object::New(); + req = new PBKDF2Request(env, + obj, + digest, + passlen, + pass, + saltlen, + salt, + iter, + keylen); + + if (args[5]->IsFunction()) { + obj->Set(env->ondone_string(), args[5]); + // XXX(trevnorris): This will need to go with the rest of domains. + if (env->in_domain()) + obj->Set(env->domain_string(), env->domain_array()->Get(0)); uv_queue_work(env->event_loop(), req->work_req(), EIO_PBKDF2, @@ -3788,7 +3874,10 @@ RandomBytesRequest* req = new RandomBytesRequest(env, obj, size); if (args[1]->IsFunction()) { - obj->Set(FIXED_ONE_BYTE_STRING(node_isolate, "ondone"), args[1]); + obj->Set(FIXED_ONE_BYTE_STRING(args.GetIsolate(), "ondone"), args[1]); + // XXX(trevnorris): This will need to go with the rest of domains. + if (env->in_domain()) + obj->Set(env->domain_string(), env->domain_array()->Get(0)); uv_queue_work(env->event_loop(), req->work_req(), RandomBytesWork, @@ -3809,7 +3898,7 @@ void GetSSLCiphers(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); SSL_CTX* ctx = SSL_CTX_new(TLSv1_server_method()); if (ctx == NULL) { @@ -3827,7 +3916,7 @@ for (int i = 0; i < sk_SSL_CIPHER_num(ciphers); ++i) { SSL_CIPHER* cipher = sk_SSL_CIPHER_value(ciphers, i); - arr->Set(i, OneByteString(node_isolate, SSL_CIPHER_get_name(cipher))); + arr->Set(i, OneByteString(args.GetIsolate(), SSL_CIPHER_get_name(cipher))); } SSL_free(ssl); @@ -3848,7 +3937,7 @@ void GetCiphers(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Local arr = Array::New(); EVP_CIPHER_do_all_sorted(array_push_back, &arr); args.GetReturnValue().Set(arr); @@ -3856,7 +3945,7 @@ void GetHashes(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Local arr = Array::New(); EVP_MD_do_all_sorted(array_push_back, &arr); args.GetReturnValue().Set(arr); @@ -3913,7 +4002,7 @@ void Certificate::VerifySpkac(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Certificate* certificate = Unwrap(args.This()); bool i = false; @@ -3978,7 +4067,7 @@ void Certificate::ExportPublicKey(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Certificate* certificate = Unwrap(args.This()); @@ -4021,7 +4110,7 @@ void Certificate::ExportChallenge(const FunctionCallbackInfo& args) { - HandleScope scope(node_isolate); + HandleScope scope(args.GetIsolate()); Certificate* crt = Unwrap(args.This()); @@ -4053,7 +4142,6 @@ SSL_library_init(); OpenSSL_add_all_algorithms(); SSL_load_error_strings(); - ERR_load_crypto_strings(); crypto_lock_init(); CRYPTO_set_locking_callback(crypto_lock_cb); @@ -4069,13 +4157,61 @@ sk_SSL_COMP_zero(comp_methods); assert(sk_SSL_COMP_num(comp_methods) == 0); #endif + +#ifndef OPENSSL_NO_ENGINE + ERR_load_ENGINE_strings(); + ENGINE_load_builtin_engines(); +#endif // !OPENSSL_NO_ENGINE +} + + +#ifndef OPENSSL_NO_ENGINE +void SetEngine(const FunctionCallbackInfo& args) { + CHECK(args.Length() >= 2 && args[0]->IsString()); + unsigned int flags = args[1]->Uint32Value(); + + ClearErrorOnReturn clear_error_on_return; + (void) &clear_error_on_return; // Silence compiler warning. + + const String::Utf8Value engine_id(args[0]); + ENGINE* engine = ENGINE_by_id(*engine_id); + + // Engine not found, try loading dynamically + if (engine == NULL) { + engine = ENGINE_by_id("dynamic"); + if (engine != NULL) { + if (!ENGINE_ctrl_cmd_string(engine, "SO_PATH", *engine_id, 0) || + !ENGINE_ctrl_cmd_string(engine, "LOAD", NULL, 0)) { + ENGINE_free(engine); + engine = NULL; + } + } + } + + if (engine == NULL) { + int err = ERR_get_error(); + if (err == 0) { + char tmp[1024]; + snprintf(tmp, sizeof(tmp), "Engine \"%s\" was not found", *engine_id); + return ThrowError(tmp); + } else { + return ThrowCryptoError(err); + } + } + + int r = ENGINE_set_default(engine, flags); + ENGINE_free(engine); + if (r == 0) + return ThrowCryptoError(ERR_get_error()); } +#endif // !OPENSSL_NO_ENGINE // FIXME(bnoordhuis) Handle global init correctly. void InitCrypto(Handle target, Handle unused, - Handle context) { + Handle context, + void* priv) { static uv_once_t init_once = UV_ONCE_INIT; uv_once(&init_once, InitCryptoOnce); @@ -4090,6 +4226,9 @@ Verify::Initialize(env, target); Certificate::Initialize(target); +#ifndef OPENSSL_NO_ENGINE + NODE_SET_METHOD(target, "setEngine", SetEngine); +#endif // !OPENSSL_NO_ENGINE NODE_SET_METHOD(target, "PBKDF2", PBKDF2); NODE_SET_METHOD(target, "randomBytes", RandomBytes); NODE_SET_METHOD(target, "pseudoRandomBytes", RandomBytes); @@ -4101,4 +4240,4 @@ } // namespace crypto } // namespace node -NODE_MODULE_CONTEXT_AWARE(node_crypto, node::crypto::InitCrypto) +NODE_MODULE_CONTEXT_AWARE_BUILTIN(crypto, node::crypto::InitCrypto) diff -Nru nodejs-0.11.10/src/node_crypto.h nodejs-0.11.11/src/node_crypto.h --- nodejs-0.11.10/src/node_crypto.h 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/src/node_crypto.h 2014-01-29 01:29:56.000000000 +0000 @@ -39,6 +39,9 @@ #include "v8.h" #include +#ifndef OPENSSL_NO_ENGINE +# include +#endif // !OPENSSL_NO_ENGINE #include #include #include @@ -185,6 +188,11 @@ static void Renegotiate(const v8::FunctionCallbackInfo& args); static void Shutdown(const v8::FunctionCallbackInfo& args); +#ifdef SSL_set_max_send_fragment + static void SetMaxSendFragment( + const v8::FunctionCallbackInfo& args); +#endif // SSL_set_max_send_fragment + #ifdef OPENSSL_NPN_NEGOTIATED static void GetNegotiatedProto( const v8::FunctionCallbackInfo& args); @@ -438,23 +446,50 @@ bool initialised_; }; -class Sign : public BaseObject { +class SignBase : public BaseObject { public: - ~Sign() { + typedef enum { + kSignOk, + kSignUnknownDigest, + kSignInit, + kSignNotInitialised, + kSignUpdate, + kSignPrivateKey, + kSignPublicKey + } Error; + + SignBase(Environment* env, v8::Local wrap) + : BaseObject(env, wrap), + md_(NULL), + initialised_(false) { + } + + ~SignBase() { if (!initialised_) return; EVP_MD_CTX_cleanup(&mdctx_); } + protected: + static void CheckThrow(Error error); + + EVP_MD_CTX mdctx_; /* coverity[member_decl] */ + const EVP_MD* md_; /* coverity[member_decl] */ + bool initialised_; +}; + +class Sign : public SignBase { + public: + static void Initialize(Environment* env, v8::Handle target); - void SignInit(const char* sign_type); - bool SignUpdate(const char* data, int len); - bool SignFinal(const char* key_pem, - int key_pem_len, - const char* passphrase, - unsigned char** sig, - unsigned int *sig_len); + Error SignInit(const char* sign_type); + Error SignUpdate(const char* data, int len); + Error SignFinal(const char* key_pem, + int key_pem_len, + const char* passphrase, + unsigned char** sig, + unsigned int *sig_len); protected: static void New(const v8::FunctionCallbackInfo& args); @@ -462,35 +497,22 @@ static void SignUpdate(const v8::FunctionCallbackInfo& args); static void SignFinal(const v8::FunctionCallbackInfo& args); - Sign(Environment* env, v8::Local wrap) - : BaseObject(env, wrap), - md_(NULL), - initialised_(false) { + Sign(Environment* env, v8::Local wrap) : SignBase(env, wrap) { MakeWeak(this); } - - private: - EVP_MD_CTX mdctx_; /* coverity[member_decl] */ - const EVP_MD* md_; /* coverity[member_decl] */ - bool initialised_; }; -class Verify : public BaseObject { +class Verify : public SignBase { public: - ~Verify() { - if (!initialised_) - return; - EVP_MD_CTX_cleanup(&mdctx_); - } - static void Initialize(Environment* env, v8::Handle target); - void VerifyInit(const char* verify_type); - bool VerifyUpdate(const char* data, int len); - bool VerifyFinal(const char* key_pem, - int key_pem_len, - const char* sig, - int siglen); + Error VerifyInit(const char* verify_type); + Error VerifyUpdate(const char* data, int len); + Error VerifyFinal(const char* key_pem, + int key_pem_len, + const char* sig, + int siglen, + bool* verify_result); protected: static void New(const v8::FunctionCallbackInfo& args); @@ -498,17 +520,9 @@ static void VerifyUpdate(const v8::FunctionCallbackInfo& args); static void VerifyFinal(const v8::FunctionCallbackInfo& args); - Verify(Environment* env, v8::Local wrap) - : BaseObject(env, wrap), - md_(NULL), - initialised_(false) { + Verify(Environment* env, v8::Local wrap) : SignBase(env, wrap) { MakeWeak(this); } - - private: - EVP_MD_CTX mdctx_; /* coverity[member_decl] */ - const EVP_MD* md_; /* coverity[member_decl] */ - bool initialised_; }; class DiffieHellman : public BaseObject { @@ -574,6 +588,9 @@ }; bool EntropySource(unsigned char* buffer, size_t length); +#ifndef OPENSSL_NO_ENGINE +void SetEngine(const v8::FunctionCallbackInfo& args); +#endif // !OPENSSL_NO_ENGINE void InitCrypto(v8::Handle target); } // namespace crypto diff -Nru nodejs-0.11.10/src/node_extensions.cc nodejs-0.11.11/src/node_extensions.cc --- nodejs-0.11.10/src/node_extensions.cc 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/src/node_extensions.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,68 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - - -#include "node.h" -#include "node_version.h" -#include "node_extensions.h" -#include -#include - -#undef NODE_EXT_LIST_START -#undef NODE_EXT_LIST_ITEM -#undef NODE_EXT_LIST_END - -#define NODE_EXT_LIST_START -#define NODE_EXT_LIST_ITEM NODE_MODULE_DECL -#define NODE_EXT_LIST_END - -NODE_EXT_LIST(NODE_EXT_LIST_START, NODE_EXT_LIST_ITEM, NODE_EXT_LIST_END) - -#undef NODE_EXT_LIST_START -#undef NODE_EXT_LIST_ITEM -#undef NODE_EXT_LIST_END - -#define NODE_EXT_STRING(x) &x ## _module, -#define NODE_EXT_LIST_START node::node_module_struct *node_module_list[] = { -#define NODE_EXT_LIST_ITEM NODE_EXT_STRING -#define NODE_EXT_LIST_END NULL}; - -NODE_EXT_LIST(NODE_EXT_LIST_START, NODE_EXT_LIST_ITEM, NODE_EXT_LIST_END) - -namespace node { - -node_module_struct* get_builtin_module(const char *name) { - char buf[128]; - node_module_struct *cur = NULL; - snprintf(buf, sizeof(buf), "node_%s", name); - /* TODO: you could look these up in a hash, but there are only - * a few, and once loaded they are cached. */ - for (int i = 0; node_module_list[i] != NULL; i++) { - cur = node_module_list[i]; - if (strcmp(cur->modname, buf) == 0) { - return cur; - } - } - - return NULL; -} - -} // namespace node diff -Nru nodejs-0.11.10/src/node_extensions.h nodejs-0.11.11/src/node_extensions.h --- nodejs-0.11.10/src/node_extensions.h 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/src/node_extensions.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,57 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SRC_NODE_EXTENSIONS_H_ -#define SRC_NODE_EXTENSIONS_H_ - -#if HAVE_OPENSSL -# define NODE_EXT_LIST_SSL(ITEM) \ - ITEM(node_crypto) \ - ITEM(node_tls_wrap) -#else -# define NODE_EXT_LIST_SSL(ITEM) -#endif // HAVE_OPENSSL - -#define NODE_EXT_LIST(START, ITEM, END) \ - START \ - ITEM(node_buffer) \ - NODE_EXT_LIST_SSL(ITEM) \ - ITEM(node_contextify) \ - ITEM(node_fs) \ - ITEM(node_http_parser) \ - ITEM(node_os) \ - ITEM(node_smalloc) \ - ITEM(node_zlib) \ - \ - ITEM(node_uv) \ - ITEM(node_timer_wrap) \ - ITEM(node_tcp_wrap) \ - ITEM(node_udp_wrap) \ - ITEM(node_pipe_wrap) \ - ITEM(node_cares_wrap) \ - ITEM(node_tty_wrap) \ - ITEM(node_process_wrap) \ - ITEM(node_fs_event_wrap) \ - ITEM(node_signal_wrap) \ - \ - END \ - -#endif // SRC_NODE_EXTENSIONS_H_ diff -Nru nodejs-0.11.10/src/node_file.cc nodejs-0.11.11/src/node_file.cc --- nodejs-0.11.10/src/node_file.cc 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/src/node_file.cc 2014-01-29 01:29:56.000000000 +0000 @@ -1053,7 +1053,8 @@ void InitFs(Handle target, Handle unused, - Handle context) { + Handle context, + void* priv) { Environment* env = Environment::GetCurrent(context); // Initialize the stats object @@ -1097,4 +1098,4 @@ } // end namespace node -NODE_MODULE_CONTEXT_AWARE(node_fs, node::InitFs) +NODE_MODULE_CONTEXT_AWARE_BUILTIN(fs, node::InitFs) diff -Nru nodejs-0.11.10/src/node_http_parser.cc nodejs-0.11.11/src/node_http_parser.cc --- nodejs-0.11.10/src/node_http_parser.cc 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/src/node_http_parser.cc 2014-01-29 01:29:56.000000000 +0000 @@ -563,7 +563,8 @@ void InitHttpParser(Handle target, Handle unused, - Handle context) { + Handle context, + void* priv) { Local t = FunctionTemplate::New(Parser::New); t->InstanceTemplate()->SetInternalFieldCount(1); t->SetClassName(FIXED_ONE_BYTE_STRING(node_isolate, "HTTPParser")); @@ -600,4 +601,4 @@ } // namespace node -NODE_MODULE_CONTEXT_AWARE(node_http_parser, node::InitHttpParser) +NODE_MODULE_CONTEXT_AWARE_BUILTIN(http_parser, node::InitHttpParser) diff -Nru nodejs-0.11.10/src/node_os.cc nodejs-0.11.11/src/node_os.cc --- nodejs-0.11.10/src/node_os.cc 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/src/node_os.cc 2014-01-29 01:29:56.000000000 +0000 @@ -222,12 +222,15 @@ Local ifarr; int err = uv_interface_addresses(&interfaces, &count); - if (err) { - return ThrowUVException(err, "uv_interface_addresses"); - } ret = Object::New(); + if (err == UV_ENOSYS) { + args.GetReturnValue().Set(ret); + } else if (err) { + return ThrowUVException(err, "uv_interface_addresses"); + } + for (i = 0; i < count; i++) { name = OneByteString(node_isolate, interfaces[i].name); if (ret->Has(name)) { @@ -299,4 +302,4 @@ } // namespace os } // namespace node -NODE_MODULE_CONTEXT_AWARE(node_os, node::os::Initialize) +NODE_MODULE_CONTEXT_AWARE_BUILTIN(os, node::os::Initialize) diff -Nru nodejs-0.11.10/src/node_version.h nodejs-0.11.11/src/node_version.h --- nodejs-0.11.10/src/node_version.h 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/src/node_version.h 2014-01-29 01:29:56.000000000 +0000 @@ -24,7 +24,7 @@ #define NODE_MAJOR_VERSION 0 #define NODE_MINOR_VERSION 11 -#define NODE_PATCH_VERSION 10 +#define NODE_PATCH_VERSION 11 #define NODE_VERSION_IS_RELEASE 1 @@ -64,6 +64,6 @@ * an API is broken in the C++ side, including in v8 or * other dependencies. */ -#define NODE_MODULE_VERSION 13 /* v0.12 */ +#define NODE_MODULE_VERSION 14 /* v0.12 */ #endif /* SRC_NODE_VERSION_H_ */ diff -Nru nodejs-0.11.10/src/node_zlib.cc nodejs-0.11.11/src/node_zlib.cc --- nodejs-0.11.10/src/node_zlib.cc 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/src/node_zlib.cc 2014-01-29 01:29:56.000000000 +0000 @@ -550,7 +550,8 @@ void InitZlib(Handle target, Handle unused, - Handle context) { + Handle context, + void* priv) { Local z = FunctionTemplate::New(ZCtx::New); z->InstanceTemplate()->SetInternalFieldCount(1); @@ -608,4 +609,4 @@ } // namespace node -NODE_MODULE_CONTEXT_AWARE(node_zlib, node::InitZlib) +NODE_MODULE_CONTEXT_AWARE_BUILTIN(zlib, node::InitZlib) diff -Nru nodejs-0.11.10/src/pipe_wrap.cc nodejs-0.11.11/src/pipe_wrap.cc --- nodejs-0.11.10/src/pipe_wrap.cc 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/src/pipe_wrap.cc 2014-01-29 01:29:56.000000000 +0000 @@ -111,8 +111,6 @@ NODE_SET_PROTOTYPE_METHOD(t, "setPendingInstances", SetPendingInstances); #endif - AsyncWrap::AddMethods(t); - target->Set(FIXED_ONE_BYTE_STRING(node_isolate, "Pipe"), t->GetFunction()); env->set_pipe_constructor_template(t); } @@ -290,4 +288,4 @@ } // namespace node -NODE_MODULE_CONTEXT_AWARE(node_pipe_wrap, node::PipeWrap::Initialize) +NODE_MODULE_CONTEXT_AWARE_BUILTIN(pipe_wrap, node::PipeWrap::Initialize) diff -Nru nodejs-0.11.10/src/process_wrap.cc nodejs-0.11.11/src/process_wrap.cc --- nodejs-0.11.10/src/process_wrap.cc 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/src/process_wrap.cc 2014-01-29 01:29:56.000000000 +0000 @@ -293,4 +293,4 @@ } // namespace node -NODE_MODULE_CONTEXT_AWARE(node_process_wrap, node::ProcessWrap::Initialize) +NODE_MODULE_CONTEXT_AWARE_BUILTIN(process_wrap, node::ProcessWrap::Initialize) diff -Nru nodejs-0.11.10/src/req_wrap.h nodejs-0.11.11/src/req_wrap.h --- nodejs-0.11.10/src/req_wrap.h 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/src/req_wrap.h 2014-01-29 01:29:56.000000000 +0000 @@ -39,6 +39,9 @@ public: ReqWrap(Environment* env, v8::Handle object) : AsyncWrap(env, object) { + if (env->in_domain()) + object->Set(env->domain_string(), env->domain_array()->Get(0)); + QUEUE_INSERT_TAIL(&req_wrap_queue, &req_wrap_queue_); } diff -Nru nodejs-0.11.10/src/signal_wrap.cc nodejs-0.11.11/src/signal_wrap.cc --- nodejs-0.11.10/src/signal_wrap.cc 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/src/signal_wrap.cc 2014-01-29 01:29:56.000000000 +0000 @@ -114,4 +114,4 @@ } // namespace node -NODE_MODULE_CONTEXT_AWARE(node_signal_wrap, node::SignalWrap::Initialize) +NODE_MODULE_CONTEXT_AWARE_BUILTIN(signal_wrap, node::SignalWrap::Initialize) diff -Nru nodejs-0.11.10/src/smalloc.cc nodejs-0.11.11/src/smalloc.cc --- nodejs-0.11.10/src/smalloc.cc 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/src/smalloc.cc 2014-01-29 01:29:56.000000000 +0000 @@ -496,4 +496,4 @@ } // namespace smalloc } // namespace node -NODE_MODULE_CONTEXT_AWARE(node_smalloc, node::smalloc::Initialize) +NODE_MODULE_CONTEXT_AWARE_BUILTIN(smalloc, node::smalloc::Initialize) diff -Nru nodejs-0.11.10/src/stream_wrap.cc nodejs-0.11.11/src/stream_wrap.cc --- nodejs-0.11.10/src/stream_wrap.cc 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/src/stream_wrap.cc 2014-01-29 01:29:56.000000000 +0000 @@ -33,6 +33,7 @@ #include "util-inl.h" #include // abort() +#include // memcpy() #include // INT_MAX @@ -49,6 +50,7 @@ using v8::Object; using v8::PropertyCallbackInfo; using v8::String; +using v8::True; using v8::Undefined; using v8::Value; @@ -200,27 +202,43 @@ Local buf_obj = args[1].As(); size_t length = Buffer::Length(buf_obj); - char* storage = new char[sizeof(WriteWrap)]; - WriteWrap* req_wrap = - new(storage) WriteWrap(env, req_wrap_obj, wrap); + char* storage; + WriteWrap* req_wrap; uv_buf_t buf; WriteBuffer(buf_obj, &buf); - int err = wrap->callbacks()->DoWrite(req_wrap, - &buf, - 1, - NULL, - StreamWrap::AfterWrite); + // Try writing immediately without allocation + uv_buf_t* bufs = &buf; + size_t count = 1; + int err = wrap->callbacks()->TryWrite(&bufs, &count); + if (err == 0) + goto done; + assert(count == 1); + + // Allocate, or write rest + storage = new char[sizeof(WriteWrap)]; + req_wrap = new(storage) WriteWrap(env, req_wrap_obj, wrap); + + err = wrap->callbacks()->DoWrite(req_wrap, + bufs, + count, + NULL, + StreamWrap::AfterWrite); req_wrap->Dispatched(); - req_wrap_obj->Set(env->bytes_string(), - Integer::NewFromUnsigned(length, node_isolate)); + req_wrap_obj->Set(env->async(), True(node_isolate)); if (err) { req_wrap->~WriteWrap(); delete[] storage; } + done: + const char* msg = wrap->callbacks()->Error(); + if (msg != NULL) + req_wrap_obj->Set(env->error_string(), OneByteString(env->isolate(), msg)); + req_wrap_obj->Set(env->bytes_string(), + Integer::NewFromUnsigned(length, node_isolate)); args.GetReturnValue().Set(err); } @@ -253,22 +271,53 @@ return; } - char* storage = new char[sizeof(WriteWrap) + storage_size + 15]; - WriteWrap* req_wrap = - new(storage) WriteWrap(env, req_wrap_obj, wrap); + // Try writing immediately if write size isn't too big + char* storage; + WriteWrap* req_wrap; + char* data; + char stack_storage[16384]; // 16kb + size_t data_size; + uv_buf_t buf; + + bool try_write = storage_size + 15 <= sizeof(stack_storage) && + (!wrap->is_named_pipe_ipc() || !args[2]->IsObject()); + if (try_write) { + data_size = StringBytes::Write(stack_storage, + storage_size, + string, + encoding); + buf = uv_buf_init(stack_storage, data_size); + + uv_buf_t* bufs = &buf; + size_t count = 1; + err = wrap->callbacks()->TryWrite(&bufs, &count); + + // Success + if (err == 0) + goto done; + + // Failure, or partial write + assert(count == 1); + } + + storage = new char[sizeof(WriteWrap) + storage_size + 15]; + req_wrap = new(storage) WriteWrap(env, req_wrap_obj, wrap); - char* data = reinterpret_cast(ROUND_UP( + data = reinterpret_cast(ROUND_UP( reinterpret_cast(storage) + sizeof(WriteWrap), 16)); - size_t data_size; - data_size = StringBytes::Write(data, storage_size, string, encoding); + if (try_write) { + // Copy partial data + memcpy(data, buf.base, buf.len); + data_size = buf.len; + } else { + // Write it + data_size = StringBytes::Write(data, storage_size, string, encoding); + } assert(data_size <= storage_size); - uv_buf_t buf; - - buf.base = data; - buf.len = data_size; + buf = uv_buf_init(data, data_size); if (!wrap->is_named_pipe_ipc()) { err = wrap->callbacks()->DoWrite(req_wrap, @@ -298,14 +347,19 @@ } req_wrap->Dispatched(); - req_wrap->object()->Set(env->bytes_string(), - Integer::NewFromUnsigned(data_size, node_isolate)); + req_wrap->object()->Set(env->async(), True(node_isolate)); if (err) { req_wrap->~WriteWrap(); delete[] storage; } + done: + const char* msg = wrap->callbacks()->Error(); + if (msg != NULL) + req_wrap_obj->Set(env->error_string(), OneByteString(env->isolate(), msg)); + req_wrap_obj->Set(env->bytes_string(), + Integer::NewFromUnsigned(data_size, node_isolate)); args.GetReturnValue().Set(err); } @@ -399,8 +453,12 @@ delete[] bufs; req_wrap->Dispatched(); + req_wrap->object()->Set(env->async(), True(node_isolate)); req_wrap->object()->Set(env->bytes_string(), Number::New(node_isolate, bytes)); + const char* msg = wrap->callbacks()->Error(); + if (msg != NULL) + req_wrap_obj->Set(env->error_string(), OneByteString(env->isolate(), msg)); if (err) { req_wrap->~WriteWrap(); @@ -441,14 +499,19 @@ // Unref handle property Local req_wrap_obj = req_wrap->object(); req_wrap_obj->Delete(env->handle_string()); - wrap->callbacks_->AfterWrite(req_wrap); + wrap->callbacks()->AfterWrite(req_wrap); Local argv[] = { Integer::New(status, node_isolate), wrap->object(), - req_wrap_obj + req_wrap_obj, + Undefined() }; + const char* msg = wrap->callbacks()->Error(); + if (msg != NULL) + argv[3] = OneByteString(env->isolate(), msg); + req_wrap->MakeCallback(env->oncomplete_string(), ARRAY_SIZE(argv), argv); req_wrap->~WriteWrap(); @@ -499,6 +562,52 @@ } +const char* StreamWrapCallbacks::Error() { + return NULL; +} + + +// NOTE: Call to this function could change both `buf`'s and `count`'s +// values, shifting their base and decrementing their length. This is +// required in order to skip the data that was successfully written via +// uv_try_write(). +int StreamWrapCallbacks::TryWrite(uv_buf_t** bufs, size_t* count) { + int err; + size_t written; + uv_buf_t* vbufs = *bufs; + size_t vcount = *count; + + err = uv_try_write(wrap()->stream(), vbufs, vcount); + if (err < 0) + return err; + + // Slice off the buffers: skip all written buffers and slice the one that + // was partially written. + written = err; + for (; written != 0 && vcount > 0; vbufs++, vcount--) { + // Slice + if (vbufs[0].len > written) { + vbufs[0].base += written; + vbufs[0].len -= written; + written = 0; + break; + + // Discard + } else { + written -= vbufs[0].len; + } + } + + *bufs = vbufs; + *count = vcount; + + if (vcount == 0) + return 0; + else + return -1; +} + + int StreamWrapCallbacks::DoWrite(WriteWrap* w, uv_buf_t* bufs, size_t count, diff -Nru nodejs-0.11.10/src/stream_wrap.h nodejs-0.11.11/src/stream_wrap.h --- nodejs-0.11.10/src/stream_wrap.h 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/src/stream_wrap.h 2014-01-29 01:29:56.000000000 +0000 @@ -73,6 +73,10 @@ virtual ~StreamWrapCallbacks() { } + virtual const char* Error(); + + virtual int TryWrite(uv_buf_t** bufs, size_t* count); + virtual int DoWrite(WriteWrap* w, uv_buf_t* bufs, size_t count, diff -Nru nodejs-0.11.10/src/tcp_wrap.cc nodejs-0.11.11/src/tcp_wrap.cc --- nodejs-0.11.10/src/tcp_wrap.cc 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/src/tcp_wrap.cc 2014-01-29 01:29:56.000000000 +0000 @@ -116,8 +116,6 @@ SetSimultaneousAccepts); #endif - AsyncWrap::AddMethods(t); - target->Set(FIXED_ONE_BYTE_STRING(node_isolate, "TCP"), t->GetFunction()); env->set_tcp_constructor_template(t); } @@ -255,8 +253,11 @@ sockaddr_in addr; int err = uv_ip4_addr(*ip_address, port, &addr); - if (err == 0) - err = uv_tcp_bind(&wrap->handle_, reinterpret_cast(&addr)); + if (err == 0) { + err = uv_tcp_bind(&wrap->handle_, + reinterpret_cast(&addr), + 0); + } args.GetReturnValue().Set(err); } @@ -272,8 +273,11 @@ sockaddr_in6 addr; int err = uv_ip6_addr(*ip6_address, port, &addr); - if (err == 0) - err = uv_tcp_bind(&wrap->handle_, reinterpret_cast(&addr)); + if (err == 0) { + err = uv_tcp_bind(&wrap->handle_, + reinterpret_cast(&addr), + 0); + } args.GetReturnValue().Set(err); } @@ -461,4 +465,4 @@ } // namespace node -NODE_MODULE_CONTEXT_AWARE(node_tcp_wrap, node::TCPWrap::Initialize) +NODE_MODULE_CONTEXT_AWARE_BUILTIN(tcp_wrap, node::TCPWrap::Initialize) diff -Nru nodejs-0.11.10/src/timer_wrap.cc nodejs-0.11.11/src/timer_wrap.cc --- nodejs-0.11.10/src/timer_wrap.cc 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/src/timer_wrap.cc 2014-01-29 01:29:56.000000000 +0000 @@ -157,4 +157,4 @@ } // namespace node -NODE_MODULE_CONTEXT_AWARE(node_timer_wrap, node::TimerWrap::Initialize) +NODE_MODULE_CONTEXT_AWARE_BUILTIN(timer_wrap, node::TimerWrap::Initialize) diff -Nru nodejs-0.11.10/src/tls_wrap.cc nodejs-0.11.11/src/tls_wrap.cc --- nodejs-0.11.10/src/tls_wrap.cc 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/src/tls_wrap.cc 2014-01-29 01:29:56.000000000 +0000 @@ -58,6 +58,10 @@ | XN_FLAG_FN_SN; +size_t TLSCallbacks::error_off_; +char TLSCallbacks::error_buf_[1024]; + + TLSCallbacks::TLSCallbacks(Environment* env, Kind kind, Handle sc, @@ -71,15 +75,16 @@ enc_out_(NULL), clear_in_(NULL), write_size_(0), - pending_write_item_(NULL), started_(false), established_(false), shutdown_(false), + error_(NULL), eof_(false) { node::Wrap(object(), this); // Initialize queue for clearIn writes QUEUE_INIT(&write_item_queue_); + QUEUE_INIT(&pending_write_items_); // We've our own session callbacks SSL_CTX_sess_set_get_cb(sc_->ctx_, SSLWrap::GetSessionCallback); @@ -102,25 +107,52 @@ #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB sni_context_.Dispose(); #endif // SSL_CTRL_SET_TLSEXT_SERVERNAME_CB + + // Move all writes to pending + MakePending(); + + // And destroy + while (!QUEUE_EMPTY(&pending_write_items_)) { + QUEUE* q = QUEUE_HEAD(&pending_write_items_); + QUEUE_REMOVE(q); + + WriteItem* wi = QUEUE_DATA(q, WriteItem, member_); + delete wi; + } } -void TLSCallbacks::InvokeQueued(int status) { - // Empty queue - ignore call - if (pending_write_item_ == NULL) +void TLSCallbacks::MakePending() { + // Aliases + QUEUE* from = &write_item_queue_; + QUEUE* to = &pending_write_items_; + + if (QUEUE_EMPTY(from)) return; - QUEUE* q = &pending_write_item_->member_; - pending_write_item_ = NULL; + // Add items to pending + QUEUE_ADD(to, from); + + // Empty original queue + QUEUE_INIT(from); +} + + +bool TLSCallbacks::InvokeQueued(int status) { + if (QUEUE_EMPTY(&pending_write_items_)) + return false; // Process old queue - while (q != &write_item_queue_) { - QUEUE* next = static_cast(QUEUE_NEXT(q)); - WriteItem* wi = CONTAINER_OF(q, WriteItem, member_); + while (!QUEUE_EMPTY(&pending_write_items_)) { + QUEUE* q = QUEUE_HEAD(&pending_write_items_); + QUEUE_REMOVE(q); + + WriteItem* wi = QUEUE_DATA(q, WriteItem, member_); wi->cb_(&wi->w_->req_, status); delete wi; - q = next; } + + return true; } @@ -195,6 +227,31 @@ } +void TLSCallbacks::Receive(const FunctionCallbackInfo& args) { + HandleScope handle_scope(args.GetIsolate()); + + TLSCallbacks* wrap = Unwrap(args.This()); + + CHECK(Buffer::HasInstance(args[0])); + char* data = Buffer::Data(args[0]); + size_t len = Buffer::Length(args[0]); + + uv_buf_t buf; + uv_stream_t* stream = wrap->wrap()->stream(); + + // Copy given buffer entirely or partiall if handle becomes closed + while (len > 0 && !uv_is_closing(reinterpret_cast(stream))) { + wrap->DoAlloc(reinterpret_cast(stream), len, &buf); + size_t copy = buf.len > len ? len : buf.len; + memcpy(buf.base, data, copy); + wrap->DoRead(stream, buf.len, &buf, UV_UNKNOWN_HANDLE); + + data += copy; + len -= copy; + } +} + + void TLSCallbacks::Start(const FunctionCallbackInfo& args) { HandleScope scope(node_isolate); @@ -251,16 +308,13 @@ return; // Split-off queue - if (established_ && !QUEUE_EMPTY(&write_item_queue_)) { - pending_write_item_ = CONTAINER_OF(QUEUE_NEXT(&write_item_queue_), - WriteItem, - member_); - QUEUE_INIT(&write_item_queue_); - } + if (established_ && !QUEUE_EMPTY(&write_item_queue_)) + MakePending(); // No data to write if (BIO_pending(enc_out_) == 0) { - InvokeQueued(0); + if (clear_in_->Length() == 0) + InvokeQueued(0); return; } @@ -289,7 +343,6 @@ void TLSCallbacks::EncOutCb(uv_write_t* req, int status) { TLSCallbacks* callbacks = static_cast(req->data); - Environment* env = callbacks->env(); // Handle error if (status) { @@ -298,12 +351,6 @@ return; // Notify about error - HandleScope handle_scope(env->isolate()); - Context::Scope context_scope(env->context()); - Local arg = String::Concat( - FIXED_ONE_BYTE_STRING(node_isolate, "write cb error, status: "), - Integer::New(status, node_isolate)->ToString()); - callbacks->MakeCallback(env->onerror_string(), 1, &arg); callbacks->InvokeQueued(status); return; } @@ -317,7 +364,33 @@ } -Local TLSCallbacks::GetSSLError(int status, int* err) { +int TLSCallbacks::PrintErrorsCb(const char* str, size_t len, void* arg) { + size_t to_copy = error_off_; + size_t avail = sizeof(error_buf_) - error_off_ - 1; + + if (avail > to_copy) + to_copy = avail; + + memcpy(error_buf_, str, avail); + error_off_ += avail; + assert(error_off_ < sizeof(error_buf_)); + + // Zero-terminate + error_buf_[error_off_] = '\0'; + + return 0; +} + + +const char* TLSCallbacks::PrintErrors() { + error_off_ = 0; + ERR_print_errors_cb(PrintErrorsCb, this); + + return error_buf_; +} + + +Local TLSCallbacks::GetSSLError(int status, int* err, const char** msg) { HandleScope scope(node_isolate); *err = SSL_get_error(ssl_, status); @@ -331,19 +404,18 @@ break; default: { - BUF_MEM* mem; - BIO* bio; - assert(*err == SSL_ERROR_SSL || *err == SSL_ERROR_SYSCALL); - bio = BIO_new(BIO_s_mem()); - assert(bio != NULL); - ERR_print_errors(bio); - BIO_get_mem_ptr(bio, &mem); + const char* buf = PrintErrors(); + Local message = - OneByteString(node_isolate, mem->data, mem->length); + OneByteString(node_isolate, buf, strlen(buf)); Local exception = Exception::Error(message); - BIO_free_all(bio); + + if (msg != NULL) { + assert(*msg == NULL); + *msg = buf; + } return scope.Close(exception); } @@ -384,7 +456,7 @@ if (read == -1) { int err; - Handle arg = GetSSLError(read, &err); + Local arg = GetSSLError(read, &err, NULL); if (!arg.IsEmpty()) { MakeCallback(env()->onerror_string(), 1, &arg); @@ -420,15 +492,31 @@ // Error or partial write int err; - Handle arg = GetSSLError(written, &err); + Local arg = GetSSLError(written, &err, &error_); if (!arg.IsEmpty()) { - MakeCallback(env()->onerror_string(), 1, &arg); + MakePending(); + if (!InvokeQueued(UV_EPROTO)) + error_ = NULL; + clear_in_->Reset(); } return false; } +const char* TLSCallbacks::Error() { + const char* ret = error_; + error_ = NULL; + return ret; +} + + +int TLSCallbacks::TryWrite(uv_buf_t** bufs, size_t* count) { + // TODO(indutny): Support it + return -1; +} + + int TLSCallbacks::DoWrite(WriteWrap* w, uv_buf_t* bufs, size_t count, @@ -483,11 +571,9 @@ int err; HandleScope handle_scope(env()->isolate()); Context::Scope context_scope(env()->context()); - Handle arg = GetSSLError(written, &err); - if (!arg.IsEmpty()) { - MakeCallback(env()->onerror_string(), 1, &arg); - return -1; - } + Local arg = GetSSLError(written, &err, &error_); + if (!arg.IsEmpty()) + return UV_EPROTO; // No errors, queue rest for (; i < count; i++) @@ -700,6 +786,7 @@ t->InstanceTemplate()->SetInternalFieldCount(1); t->SetClassName(FIXED_ONE_BYTE_STRING(node_isolate, "TLSWrap")); + NODE_SET_PROTOTYPE_METHOD(t, "receive", Receive); NODE_SET_PROTOTYPE_METHOD(t, "start", Start); NODE_SET_PROTOTYPE_METHOD(t, "setVerifyMode", SetVerifyMode); NODE_SET_PROTOTYPE_METHOD(t, @@ -721,4 +808,4 @@ } // namespace node -NODE_MODULE_CONTEXT_AWARE(node_tls_wrap, node::TLSCallbacks::Initialize) +NODE_MODULE_CONTEXT_AWARE_BUILTIN(tls_wrap, node::TLSCallbacks::Initialize) diff -Nru nodejs-0.11.10/src/tls_wrap.h nodejs-0.11.11/src/tls_wrap.h --- nodejs-0.11.10/src/tls_wrap.h 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/src/tls_wrap.h 2014-01-29 01:29:56.000000000 +0000 @@ -50,6 +50,8 @@ v8::Handle unused, v8::Handle context); + const char* Error(); + int TryWrite(uv_buf_t** bufs, size_t* count); int DoWrite(WriteWrap* w, uv_buf_t* bufs, size_t count, @@ -98,7 +100,8 @@ static void EncOutCb(uv_write_t* req, int status); bool ClearIn(); void ClearOut(); - void InvokeQueued(int status); + void MakePending(); + bool InvokeQueued(int status); inline void Cycle() { ClearIn(); @@ -106,10 +109,14 @@ EncOut(); } - v8::Local GetSSLError(int status, int* err); + v8::Local GetSSLError(int status, int* err, const char** msg); + const char* PrintErrors(); + + static int PrintErrorsCb(const char* str, size_t len, void* arg); static void OnClientHelloParseEnd(void* arg); static void Wrap(const v8::FunctionCallbackInfo& args); + static void Receive(const v8::FunctionCallbackInfo& args); static void Start(const v8::FunctionCallbackInfo& args); static void SetVerifyMode(const v8::FunctionCallbackInfo& args); static void EnableSessionCallbacks( @@ -132,10 +139,11 @@ size_t write_size_; size_t write_queue_size_; QUEUE write_item_queue_; - WriteItem* pending_write_item_; + QUEUE pending_write_items_; bool started_; bool established_; bool shutdown_; + const char* error_; // If true - delivered EOF to the js-land, either after `close_notify`, or // after the `UV_EOF` on socket. @@ -144,6 +152,9 @@ #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB v8::Persistent sni_context_; #endif // SSL_CTRL_SET_TLSEXT_SERVERNAME_CB + + static size_t error_off_; + static char error_buf_[1024]; }; } // namespace node diff -Nru nodejs-0.11.10/src/tty_wrap.cc nodejs-0.11.11/src/tty_wrap.cc --- nodejs-0.11.10/src/tty_wrap.cc 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/src/tty_wrap.cc 2014-01-29 01:29:56.000000000 +0000 @@ -180,4 +180,4 @@ } // namespace node -NODE_MODULE_CONTEXT_AWARE(node_tty_wrap, node::TTYWrap::Initialize) +NODE_MODULE_CONTEXT_AWARE_BUILTIN(tty_wrap, node::TTYWrap::Initialize) diff -Nru nodejs-0.11.10/src/udp_wrap.cc nodejs-0.11.11/src/udp_wrap.cc --- nodejs-0.11.10/src/udp_wrap.cc 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/src/udp_wrap.cc 2014-01-29 01:29:56.000000000 +0000 @@ -119,9 +119,6 @@ NODE_SET_PROTOTYPE_METHOD(t, "ref", HandleWrap::Ref); NODE_SET_PROTOTYPE_METHOD(t, "unref", HandleWrap::Unref); - - AsyncWrap::AddMethods(t); - target->Set(FIXED_ONE_BYTE_STRING(node_isolate, "UDP"), t->GetFunction()); env->set_udp_constructor_function(t->GetFunction()); } @@ -439,4 +436,4 @@ } // namespace node -NODE_MODULE_CONTEXT_AWARE(node_udp_wrap, node::UDPWrap::Initialize) +NODE_MODULE_CONTEXT_AWARE_BUILTIN(udp_wrap, node::UDPWrap::Initialize) diff -Nru nodejs-0.11.10/src/uv.cc nodejs-0.11.11/src/uv.cc --- nodejs-0.11.10/src/uv.cc 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/src/uv.cc 2014-01-29 01:29:56.000000000 +0000 @@ -62,4 +62,4 @@ } // namespace uv } // namespace node -NODE_MODULE_CONTEXT_AWARE(node_uv, node::uv::Initialize) +NODE_MODULE_CONTEXT_AWARE_BUILTIN(uv, node::uv::Initialize) diff -Nru nodejs-0.11.10/test/addons/async-hello-world/binding.cc nodejs-0.11.11/test/addons/async-hello-world/binding.cc --- nodejs-0.11.10/test/addons/async-hello-world/binding.cc 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/addons/async-hello-world/binding.cc 2014-01-29 01:29:56.000000000 +0000 @@ -13,21 +13,23 @@ Persistent callback; }; -void DoAsync (uv_work_t *r) { - async_req *req = reinterpret_cast(r->data); +void DoAsync(uv_work_t* r) { + async_req* req = reinterpret_cast(r->data); sleep(1); // simulate CPU intensive process... req->output = req->input * 2; } -void AfterAsync (uv_work_t *r) { - HandleScope scope; - async_req *req = reinterpret_cast(r->data); +void AfterAsync(uv_work_t* r) { + Isolate* isolate = Isolate::GetCurrent(); + HandleScope scope(isolate); + async_req* req = reinterpret_cast(r->data); Handle argv[2] = { Null(), Integer::New(req->output) }; TryCatch try_catch; - req->callback->Call(Context::GetCurrent()->Global(), 2, argv); + Local callback = Local::New(isolate, req->callback); + callback->Call(Context::GetCurrent()->Global(), 2, argv); // cleanup req->callback.Dispose(); @@ -38,24 +40,23 @@ } } -Handle Method(const Arguments& args) { - HandleScope scope; +void Method(const FunctionCallbackInfo& args) { + Isolate* isolate = Isolate::GetCurrent(); + HandleScope scope(isolate); - async_req *req = new async_req; + async_req* req = new async_req; req->req.data = req; req->input = args[0]->IntegerValue(); req->output = 0; Local callback = Local::Cast(args[1]); - req->callback = Persistent::New(callback); + req->callback.Reset(isolate, callback); uv_queue_work(uv_default_loop(), &req->req, DoAsync, (uv_after_work_cb)AfterAsync); - - return Undefined(); } void init(Handle exports, Handle module) { diff -Nru nodejs-0.11.10/test/addons/at-exit/binding.cc nodejs-0.11.11/test/addons/at-exit/binding.cc --- nodejs-0.11.10/test/addons/at-exit/binding.cc 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/addons/at-exit/binding.cc 2014-01-29 01:29:56.000000000 +0000 @@ -7,6 +7,7 @@ using node::AtExit; using v8::Handle; using v8::HandleScope; +using v8::Isolate; using v8::Local; using v8::Object; @@ -15,7 +16,7 @@ static int at_exit_cb2_called = 0; static void at_exit_cb1(void* arg) { - HandleScope scope; + HandleScope scope(Isolate::GetCurrent()); assert(arg == 0); Local obj = Object::New(); assert(!obj.IsEmpty()); // assert VM is still alive diff -Nru nodejs-0.11.10/test/addons/hello-world/binding.cc nodejs-0.11.11/test/addons/hello-world/binding.cc --- nodejs-0.11.10/test/addons/hello-world/binding.cc 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/addons/hello-world/binding.cc 2014-01-29 01:29:56.000000000 +0000 @@ -3,9 +3,10 @@ using namespace v8; -Handle Method(const Arguments& args) { - HandleScope scope; - return scope.Close(String::New("world")); +void Method(const FunctionCallbackInfo& args) { + Isolate* isolate = Isolate::GetCurrent(); + HandleScope scope(isolate); + args.GetReturnValue().Set(String::NewFromUtf8(isolate, "world")); } void init(Handle target) { diff -Nru nodejs-0.11.10/test/addons/hello-world-function-export/binding.cc nodejs-0.11.11/test/addons/hello-world-function-export/binding.cc --- nodejs-0.11.10/test/addons/hello-world-function-export/binding.cc 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/addons/hello-world-function-export/binding.cc 2014-01-29 01:29:56.000000000 +0000 @@ -3,9 +3,10 @@ using namespace v8; -Handle Method(const Arguments& args) { - HandleScope scope; - return scope.Close(String::New("world")); +void Method(const FunctionCallbackInfo& args) { + Isolate* isolate = Isolate::GetCurrent(); + HandleScope scope(isolate); + args.GetReturnValue().Set(String::NewFromUtf8(isolate, "world")); } void init(Handle exports, Handle module) { diff -Nru nodejs-0.11.10/test/addons/testcfg.py nodejs-0.11.11/test/addons/testcfg.py --- nodejs-0.11.10/test/addons/testcfg.py 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/test/addons/testcfg.py 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,6 @@ +import sys, os +sys.path.append(os.path.join(os.path.dirname(__file__), '..')) +import testpy + +def GetConfiguration(context, root): + return testpy.AddonTestConfiguration(context, root, 'addon') diff -Nru nodejs-0.11.10/test/common.js nodejs-0.11.11/test/common.js --- nodejs-0.11.10/test/common.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/common.js 2014-01-29 01:29:56.000000000 +0000 @@ -20,6 +20,7 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. var path = require('path'); +var fs = require('fs'); var assert = require('assert'); exports.testDir = path.dirname(__filename); @@ -35,6 +36,8 @@ exports.PIPE = exports.tmpDir + '/test.sock'; exports.opensslCli = path.join(process.execPath, '..', 'openssl-cli'); } +if (!fs.existsSync(exports.opensslCli)) + exports.opensslCli = false; var util = require('util'); for (var i in util) exports[i] = util[i]; diff -Nru nodejs-0.11.10/test/debugger/helper-debugger-repl.js nodejs-0.11.11/test/debugger/helper-debugger-repl.js --- nodejs-0.11.10/test/debugger/helper-debugger-repl.js 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/test/debugger/helper-debugger-repl.js 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,149 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +process.env.NODE_DEBUGGER_TIMEOUT = 2000; +var common = require('../common'); +var assert = require('assert'); +var spawn = require('child_process').spawn; + +var port = common.PORT + 1337; + +var child; +var buffer = ''; +var expected = []; +var quit; + +function startDebugger(scriptToDebug) { + scriptToDebug = process.env.NODE_DEBUGGER_TEST_SCRIPT || + common.fixturesDir + '/' + scriptToDebug; + + child = spawn(process.execPath, ['debug', '--port=' + port, scriptToDebug]); + + console.error('./node', 'debug', '--port=' + port, scriptToDebug); + + child.stdout.setEncoding('utf-8'); + child.stdout.on('data', function(data) { + data = (buffer + data).split('\n'); + buffer = data.pop(); + data.forEach(function(line) { + child.emit('line', line); + }); + }); + child.stderr.pipe(process.stderr); + + child.on('line', function(line) { + line = line.replace(/^(debug> *)+/, ''); + console.log(line); + assert.ok(expected.length > 0, 'Got unexpected line: ' + line); + + var expectedLine = expected[0].lines.shift(); + assert.ok(line.match(expectedLine) !== null, line + ' != ' + expectedLine); + + if (expected[0].lines.length === 0) { + var callback = expected[0].callback; + expected.shift(); + callback && callback(); + } + }); + + var childClosed = false; + child.on('close', function(code) { + assert(!code); + childClosed = true; + }); + + var quitCalled = false; + quit = function() { + if (quitCalled || childClosed) return; + quitCalled = true; + child.stdin.write('quit'); + child.kill('SIGTERM'); + } + + setTimeout(function() { + console.error('dying badly buffer=%j', buffer); + var err = 'Timeout'; + if (expected.length > 0 && expected[0].lines) { + err = err + '. Expected: ' + expected[0].lines.shift(); + } + + child.on('close', function() { + console.error('child is closed'); + throw new Error(err); + }); + + quit(); + }, 10000).unref(); + + process.once('uncaughtException', function(e) { + console.error('UncaughtException', e, e.stack); + quit(); + console.error(e.toString()); + process.exit(1); + }); + + process.on('exit', function(code) { + console.error('process exit', code); + quit(); + if (code === 0) + assert(childClosed); + }); +} + +function addTest(input, output) { + function next() { + if (expected.length > 0) { + console.log('debug> ' + expected[0].input); + child.stdin.write(expected[0].input + '\n'); + + if (!expected[0].lines) { + var callback = expected[0].callback; + expected.shift(); + + callback && callback(); + } + } else { + quit(); + } + }; + expected.push({input: input, lines: output, callback: next}); +} + +var handshakeLines = [ + /listening on port \d+/, + /connecting.* ok/ +]; + +var initialBreakLines = [ + /break in .*:1/, + /1/, /2/, /3/ +]; + +var initialLines = handshakeLines.concat(initialBreakLines); + +// Process initial lines +addTest(null, initialLines); + +exports.startDebugger = startDebugger; +exports.addTest = addTest; +exports.initialLines = initialLines; +exports.handshakeLines = handshakeLines; +exports.initialBreakLines = initialBreakLines; diff -Nru nodejs-0.11.10/test/debugger/test-debug-break-on-uncaught.js nodejs-0.11.11/test/debugger/test-debug-break-on-uncaught.js --- nodejs-0.11.10/test/debugger/test-debug-break-on-uncaught.js 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/test/debugger/test-debug-break-on-uncaught.js 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,124 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var path = require('path'); +var assert = require('assert'); +var spawn = require('child_process').spawn; +var common = require('../common'); +var debug = require('_debugger'); + +addScenario('global.js', null, 2); +addScenario('timeout.js', null, 2); +addScenario('domain.js', null, 10); + +// Exception is thrown from vm.js via module.js (internal file) +// var compiledWrapper = runInThisContext(wrapper, filename, 0, true); +addScenario('parse-error.js', 'vm.js', null); + +run(); + +/***************** IMPLEMENTATION *****************/ + +var scenarios; +function addScenario(scriptName, throwsInFile, throwsOnLine) { + if (!scenarios) scenarios = []; + scenarios.push( + runScenario.bind(null, scriptName, throwsInFile, throwsOnLine, run) + ); +} + +function run() { + var next = scenarios.shift(); + if (next) next(); +} + +function runScenario(scriptName, throwsInFile, throwsOnLine, next) { + console.log('**[ %s ]**', scriptName); + var asserted = false; + var port = common.PORT + 1337; + + var testScript = path.join( + common.fixturesDir, + 'uncaught-exceptions', + scriptName + ); + + var child = spawn(process.execPath, [ '--debug-brk=' + port, testScript ]); + child.on('close', function() { + assert(asserted, 'debugger did not pause on exception'); + if (next) next(); + }) + + var exceptions = []; + + setTimeout(setupClient.bind(null, runTest), 200); + + function setupClient(callback) { + var client = new debug.Client(); + + client.once('ready', callback.bind(null, client)); + + client.on('unhandledResponse', function(body) { + console.error('unhandled response: %j', body); + }); + + client.on('error', function(err) { + if (asserted) return; + assert.ifError(err); + }); + + client.connect(port); + } + + function runTest(client) { + client.req( + { + command: 'setexceptionbreak', + arguments: { + type: 'uncaught', + enabled: true + } + }, + function(error, result) { + assert.ifError(error); + + client.on('exception', function(event) { + exceptions.push(event.body); + }); + + client.reqContinue(function(error, result) { + assert.ifError(error); + setTimeout(assertHasPaused.bind(null, client), 100); + }); + } + ); + } + + function assertHasPaused(client) { + assert.equal(exceptions.length, 1, 'debugger did not pause on exception'); + assert.equal(exceptions[0].uncaught, true); + assert.equal(exceptions[0].script.name, throwsInFile || testScript); + if (throwsOnLine != null) + assert.equal(exceptions[0].sourceLine + 1, throwsOnLine); + asserted = true; + client.reqContinue(assert.ifError); + } +} diff -Nru nodejs-0.11.10/test/debugger/test-debugger-client.js nodejs-0.11.11/test/debugger/test-debugger-client.js --- nodejs-0.11.10/test/debugger/test-debugger-client.js 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/test/debugger/test-debugger-client.js 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,239 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + + + + +process.env.NODE_DEBUGGER_TIMEOUT = 2000; +var common = require('../common'); +var assert = require('assert'); +var debug = require('_debugger'); + +var debugPort = common.PORT + 1337; +debug.port = debugPort; +var spawn = require('child_process').spawn; + +setTimeout(function() { + if (nodeProcess) nodeProcess.kill('SIGTERM'); + throw new Error('timeout'); +}, 10000).unref(); + + +var resCount = 0; +var p = new debug.Protocol(); +p.onResponse = function(res) { + resCount++; +}; + +p.execute('Type: connect\r\n' + + 'V8-Version: 3.0.4.1\r\n' + + 'Protocol-Version: 1\r\n' + + 'Embedding-Host: node v0.3.3-pre\r\n' + + 'Content-Length: 0\r\n\r\n'); +assert.equal(1, resCount); + +// Make sure split messages go in. + +var parts = []; +parts.push('Content-Length: 336\r\n'); +assert.equal(21, parts[0].length); +parts.push('\r\n'); +assert.equal(2, parts[1].length); +var bodyLength = 0; + +parts.push('{"seq":12,"type":"event","event":"break","body":' + + '{"invocationText":"#'); +assert.equal(78, parts[2].length); +bodyLength += parts[2].length; + +parts.push('.[anonymous](req=#, ' + + 'res=#)","sourceLine"'); +assert.equal(78, parts[3].length); +bodyLength += parts[3].length; + +parts.push(':45,"sourceColumn":4,"sourceLineText":" debugger;",' + + '"script":{"id":24,"name":"/home/ryan/projects/node/' + + 'benchmark/http_simple.js","lineOffset":0,"columnOffset":0,' + + '"lineCount":98}}}'); +assert.equal(180, parts[4].length); +bodyLength += parts[4].length; + +assert.equal(336, bodyLength); + +for (var i = 0; i < parts.length; i++) { + p.execute(parts[i]); +} +assert.equal(2, resCount); + + +// Make sure that if we get backed up, we still manage to get all the +// messages +var d = 'Content-Length: 466\r\n\r\n' + + '{"seq":10,"type":"event","event":"afterCompile","success":true,' + + '"body":{"script":{"handle":1,"type":"script","name":"dns.js",' + + '"id":34,"lineOffset":0,"columnOffset":0,"lineCount":241,' + + '"sourceStart":"(function (module, exports, require) {' + + 'var dns = process.binding(\'cares\')' + + ';\\nvar ne","sourceLength":6137,"scriptType":2,"compilationType":0,' + + '"context":{"ref":0},"text":"dns.js (lines: 241)"}},"refs":' + + '[{"handle":0' + + ',"type":"context","text":"#"}],"running":true}' + + 'Content-Length: 119\r\n\r\n' + + '{"seq":11,"type":"event","event":"scriptCollected","success":true,' + + '"body":{"script":{"id":26}},"refs":[],"running":true}'; +p.execute(d); +assert.equal(4, resCount); + +var expectedConnections = 0; +var tests = []; +function addTest(cb) { + expectedConnections++; + tests.push(cb); +} + +addTest(function(client, done) { + console.error('requesting version'); + client.reqVersion(function(err, v) { + assert.ok(!err); + console.log('version: %s', v); + assert.equal(process.versions.v8, v); + done(); + }); +}); + +addTest(function(client, done) { + console.error('requesting scripts'); + client.reqScripts(function(err) { + assert.ok(!err); + console.error('got %d scripts', Object.keys(client.scripts).length); + + var foundMainScript = false; + for (var k in client.scripts) { + var script = client.scripts[k]; + if (script && script.name === 'node.js') { + foundMainScript = true; + break; + } + } + assert.ok(foundMainScript); + done(); + }); +}); + +addTest(function(client, done) { + console.error('eval 2+2'); + client.reqEval('2+2', function(err, res) { + console.error(res); + assert.ok(!err); + assert.equal('4', res.text); + assert.equal(4, res.value); + done(); + }); +}); + + +var connectCount = 0; +var script = 'setTimeout(function () { console.log("blah"); });' + + 'setInterval(function () {}, 1000000);'; + +var nodeProcess; + +function doTest(cb, done) { + var args = ['--debug=' + debugPort, '-e', script]; + nodeProcess = spawn(process.execPath, args); + + nodeProcess.stdout.once('data', function(c) { + console.log('>>> new node process: %d', nodeProcess.pid); + var failed = true; + try { + process._debugProcess(nodeProcess.pid); + failed = false; + } finally { + // At least TRY not to leave zombie procs if this fails. + if (failed) + nodeProcess.kill('SIGTERM'); + } + console.log('>>> starting debugger session'); + }); + + var didTryConnect = false; + nodeProcess.stderr.setEncoding('utf8'); + var b = ''; + nodeProcess.stderr.on('data', function(data) { + console.error('got stderr data %j', data); + nodeProcess.stderr.resume(); + b += data; + if (didTryConnect === false && b.match(/Debugger listening on port/)) { + didTryConnect = true; + + // The timeout is here to expose a race in the bootstrap process. + // Without the early SIGUSR1 debug handler, it effectively results + // in an infinite ECONNREFUSED loop. + setTimeout(tryConnect, 100); + + function tryConnect() { + // Wait for some data before trying to connect + var c = new debug.Client(); + console.error('>>> connecting...'); + c.connect(debug.port); + c.on('break', function(brk) { + c.reqContinue(function() {}); + }); + c.on('ready', function() { + connectCount++; + console.log('ready!'); + cb(c, function() { + c.end(); + c.on('end', function() { + console.error( + '>>> killing node process %d\n\n', + nodeProcess.pid); + nodeProcess.kill(); + done(); + }); + }); + }); + c.on('error', function(err) { + if (err.code !== 'ECONNREFUSED') throw err; + setTimeout(tryConnect, 10); + }); + } + } + }); +} + + +function run() { + var t = tests[0]; + if (!t) return; + + doTest(t, function() { + tests.shift(); + run(); + }); +} + +run(); + +process.on('exit', function(code) { + if (!code) + assert.equal(expectedConnections, connectCount); +}); diff -Nru nodejs-0.11.10/test/debugger/test-debugger-debug-brk.js nodejs-0.11.11/test/debugger/test-debugger-debug-brk.js --- nodejs-0.11.10/test/debugger/test-debugger-debug-brk.js 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/test/debugger/test-debugger-debug-brk.js 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,49 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + + +var common = require('../common'); +var assert = require('assert'); +var spawn = require('child_process').spawn; + +var script = common.fixturesDir + '/empty.js'; + +function fail() { + assert(0); // `node --debug-brk script.js` should not quit +} + +function test(arg) { + var child = spawn(process.execPath, [arg, script]); + child.on('exit', fail); + + // give node time to start up the debugger + setTimeout(function() { + child.removeListener('exit', fail); + child.kill(); + }, 2000); + + process.on('exit', function() { + assert(child.killed); + }); +} + +test('--debug-brk'); +test('--debug-brk=5959'); diff -Nru nodejs-0.11.10/test/debugger/test-debugger-repl-break-in-module.js nodejs-0.11.11/test/debugger/test-debugger-repl-break-in-module.js --- nodejs-0.11.10/test/debugger/test-debugger-repl-break-in-module.js 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/test/debugger/test-debugger-repl-break-in-module.js 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,80 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var repl = require('./helper-debugger-repl.js'); + +repl.startDebugger('break-in-module/main.js'); + +// -- SET BREAKPOINT -- + +// Set breakpoint by file name + line number where the file is not loaded yet +repl.addTest('sb("mod.js", 23)', [ + /Warning: script 'mod\.js' was not loaded yet\./, + /1/, /2/, /3/, /4/, /5/, /6/ +]); + +// Check escaping of regex characters +repl.addTest('sb(")^$*+?}{|][(.js\\\\", 1)', [ + /Warning: script '[^']+' was not loaded yet\./, + /1/, /2/, /3/, /4/, /5/, /6/ +]); + +// continue - the breakpoint should be triggered +repl.addTest('c', [ + /break in .*[\\\/]mod\.js:23/, + /21/, /22/, /23/, /24/, /25/ +]); + +// -- RESTORE BREAKPOINT ON RESTART -- + +// Restart the application - breakpoint should be restored +repl.addTest('restart', [].concat( + [ + /terminated/ + ], + repl.handshakeLines, + [ + /Restoring breakpoint mod.js:23/, + /Warning: script 'mod\.js' was not loaded yet\./, + /Restoring breakpoint \).*:\d+/, + /Warning: script '\)[^']*' was not loaded yet\./ + ], + repl.initialBreakLines)); + +// continue - the breakpoint should be triggered +repl.addTest('c', [ + /break in .*[\\\/]mod\.js:23/, + /21/, /22/, /23/, /24/, /25/ +]); + +// -- CLEAR BREAKPOINT SET IN MODULE TO BE LOADED -- + +repl.addTest('cb("mod.js", 23)', [ + /18/, /./, /./, /./, /./, /./, /./, /./, /26/ +]); + +repl.addTest('c', [ + /break in .*[\\\/]main\.js:4/, + /2/, /3/, /4/, /5/, /6/ +]); + +// -- (END) -- +repl.addTest('quit', []); diff -Nru nodejs-0.11.10/test/debugger/test-debugger-repl-restart.js nodejs-0.11.11/test/debugger/test-debugger-repl-restart.js --- nodejs-0.11.10/test/debugger/test-debugger-repl-restart.js 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/test/debugger/test-debugger-repl-restart.js 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,31 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var repl = require('./helper-debugger-repl.js'); + +repl.startDebugger('breakpoints.js'); + +// Restart the debugged script +repl.addTest('restart', [ + /terminated/, +].concat(repl.initialLines)); + +repl.addTest('quit', []); diff -Nru nodejs-0.11.10/test/debugger/test-debugger-repl-term.js nodejs-0.11.11/test/debugger/test-debugger-repl-term.js --- nodejs-0.11.10/test/debugger/test-debugger-repl-term.js 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/test/debugger/test-debugger-repl-term.js 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,63 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +process.env.NODE_FORCE_READLINE = 1; + +var repl = require('./helper-debugger-repl.js'); + +repl.startDebugger('breakpoints.js'); + +var addTest = repl.addTest; + +// next +addTest('n', [ + /debug>.*n/, + /break in .*:11/, + /9/, /10/, /11/, /12/, /13/ +]); + +// should repeat next +addTest('', [ + /debug>/, + /break in .*:5/, + /3/, /4/, /5/, /6/, /7/, +]); + +// continue +addTest('c', [ + /debug>.*c/, + /break in .*:12/, + /10/, /11/, /12/, /13/, /14/ +]); + +// should repeat continue +addTest('', [ + /debug>/, + /break in .*:5/, + /3/, /4/, /5/, /6/, /7/, +]); + +// should repeat continue +addTest('', [ + /debug>/, + /break in .*:23/, + /21/, /22/, /23/, /24/, /25/, +]); diff -Nru nodejs-0.11.10/test/debugger/test-debugger-repl-utf8.js nodejs-0.11.11/test/debugger/test-debugger-repl-utf8.js --- nodejs-0.11.10/test/debugger/test-debugger-repl-utf8.js 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/test/debugger/test-debugger-repl-utf8.js 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,27 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var common = require('../common'); +var script = common.fixturesDir + '/breakpoints_utf8.js'; +process.env.NODE_DEBUGGER_TEST_SCRIPT = script; + +require('./test-debugger-repl.js'); + diff -Nru nodejs-0.11.10/test/debugger/test-debugger-repl.js nodejs-0.11.11/test/debugger/test-debugger-repl.js --- nodejs-0.11.10/test/debugger/test-debugger-repl.js 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/test/debugger/test-debugger-repl.js 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,77 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var repl = require('./helper-debugger-repl.js'); + +repl.startDebugger('breakpoints.js'); + +var addTest = repl.addTest; + +// Next +addTest('n', [ + /break in .*:11/, + /9/, /10/, /11/, /12/, /13/ +]); + +// Watch +addTest('watch("\'x\'")'); + +// Continue +addTest('c', [ + /break in .*:5/, + /Watchers/, + /0:\s+'x' = "x"/, + /()/, + /3/, /4/, /5/, /6/, /7/ +]); + +// Show watchers +addTest('watchers', [ + /0:\s+'x' = "x"/ +]); + +// Unwatch +addTest('unwatch("\'x\'")'); + +// Step out +addTest('o', [ + /break in .*:12/, + /10/, /11/, /12/, /13/, /14/ +]); + +// Continue +addTest('c', [ + /break in .*:5/, + /3/, /4/, /5/, /6/, /7/ +]); + +// Set breakpoint by function name +addTest('sb("setInterval()", "!(setInterval.flag++)")', [ + /1/, /2/, /3/, /4/, /5/, /6/, /7/, /8/, /9/, /10/ +]); + +// Continue +addTest('c', [ + /break in node.js:\d+/, + /\d/, /\d/, /\d/, /\d/, /\d/ +]); + +addTest('quit', []); diff -Nru nodejs-0.11.10/test/debugger/testcfg.py nodejs-0.11.11/test/debugger/testcfg.py --- nodejs-0.11.10/test/debugger/testcfg.py 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/test/debugger/testcfg.py 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,6 @@ +import sys, os +sys.path.append(os.path.join(os.path.dirname(__file__), '..')) +import testpy + +def GetConfiguration(context, root): + return testpy.SimpleTestConfiguration(context, root, 'debugger') diff -Nru nodejs-0.11.10/test/fixtures/echo-close-check.js nodejs-0.11.11/test/fixtures/echo-close-check.js --- nodejs-0.11.10/test/fixtures/echo-close-check.js 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/test/fixtures/echo-close-check.js 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,41 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var common = require('../common'); +var assert = require('assert'); +var net = require('net'); + +process.stdout.write('hello world\r\n'); + +var stdin = process.openStdin(); + +stdin.on('data', function(data) { + process.stdout.write(data.toString()); +}); + +stdin.on('end', function() { + // If stdin's fd will be closed - createServer may get it + var server = net.createServer(function() { + }).listen(common.PORT, function() { + assert(typeof server._handle.fd !== 'number' || server._handle.fd > 2); + server.close(); + }); +}); diff -Nru nodejs-0.11.10/test/fixtures/keys/Makefile nodejs-0.11.11/test/fixtures/keys/Makefile --- nodejs-0.11.10/test/fixtures/keys/Makefile 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/fixtures/keys/Makefile 2014-01-29 01:29:56.000000000 +0000 @@ -1,4 +1,4 @@ -all: agent1-cert.pem agent2-cert.pem agent3-cert.pem agent4-cert.pem ca2-crl.pem +all: agent1-cert.pem agent2-cert.pem agent3-cert.pem agent4-cert.pem ca2-crl.pem ec-cert.pem # @@ -130,6 +130,19 @@ -out ca2-crl.pem \ -passin 'pass:password' +ec-key.pem: + openssl ecparam -genkey -out ec-key.pem -name prime256v1 + +ec-csr.pem: ec-key.pem + openssl req -new -config ec.cnf -key ec-key.pem -out ec-csr.pem + +ec-cert.pem: ec-csr.pem ec-key.pem + openssl x509 -req \ + -days 9999 \ + -in ec-csr.pem \ + -signkey ec-key.pem \ + -out ec-cert.pem + clean: rm -f *.pem *.srl ca2-database.txt ca2-serial diff -Nru nodejs-0.11.10/test/fixtures/keys/ec-cert.pem nodejs-0.11.11/test/fixtures/keys/ec-cert.pem --- nodejs-0.11.10/test/fixtures/keys/ec-cert.pem 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/test/fixtures/keys/ec-cert.pem 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIIB6DCCAY8CCQDxe0NTwQvhajAJBgcqhkjOPQQBMH0xCzAJBgNVBAYTAlVTMQsw +CQYDVQQIEwJDQTELMAkGA1UEBxMCU0YxDzANBgNVBAoTBkpveWVudDEQMA4GA1UE +CxMHTm9kZS5qczEPMA0GA1UEAxMGYWdlbnQyMSAwHgYJKoZIhvcNAQkBFhFyeUB0 +aW55Y2xvdWRzLm9yZzAeFw0xNDAxMjUyMzQ1NTRaFw00MTA2MTEyMzQ1NTRaMH0x +CzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTELMAkGA1UEBxMCU0YxDzANBgNVBAoT +BkpveWVudDEQMA4GA1UECxMHTm9kZS5qczEPMA0GA1UEAxMGYWdlbnQyMSAwHgYJ +KoZIhvcNAQkBFhFyeUB0aW55Y2xvdWRzLm9yZzBZMBMGByqGSM49AgEGCCqGSM49 +AwEHA0IABMF+Qkla0cb0tH6NcJDnd2drh0xr74hkJY8SWtsZ/7WyL8VHN8SfoDOo +2BZDByoBmHkFy1BEC0b7JFYOCAs/ShwwCQYHKoZIzj0EAQNIADBFAiEAwcJ6lRH6 +EhV5Iywr9VlmDsPDypEGIXMWLvw4Sbe+2+cCIC/TOweK9vmYiY2Y1ewAqhO7TGeX +9nTgmSQD2OBZrrOf +-----END CERTIFICATE----- diff -Nru nodejs-0.11.10/test/fixtures/keys/ec-csr.pem nodejs-0.11.11/test/fixtures/keys/ec-csr.pem --- nodejs-0.11.10/test/fixtures/keys/ec-csr.pem 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/test/fixtures/keys/ec-csr.pem 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,9 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBNjCB3wIBADB9MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExCzAJBgNVBAcT +AlNGMQ8wDQYDVQQKEwZKb3llbnQxEDAOBgNVBAsTB05vZGUuanMxDzANBgNVBAMT +BmFnZW50MjEgMB4GCSqGSIb3DQEJARYRcnlAdGlueWNsb3Vkcy5vcmcwWTATBgcq +hkjOPQIBBggqhkjOPQMBBwNCAATBfkJJWtHG9LR+jXCQ53dna4dMa++IZCWPElrb +Gf+1si/FRzfEn6AzqNgWQwcqAZh5BctQRAtG+yRWDggLP0ocoAAwCQYHKoZIzj0E +AQNHADBEAiBqnVIhsMk35UAXt3/dgIAKUpnE652YTQ4rgidrxgbvqQIgDXs1gfj0 +3HACt3JASAlNgFGGUYmmDvKTj/7H1gQRB7Q= +-----END CERTIFICATE REQUEST----- diff -Nru nodejs-0.11.10/test/fixtures/keys/ec-key.pem nodejs-0.11.11/test/fixtures/keys/ec-key.pem --- nodejs-0.11.10/test/fixtures/keys/ec-key.pem 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/test/fixtures/keys/ec-key.pem 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,8 @@ +-----BEGIN EC PARAMETERS----- +BggqhkjOPQMBBw== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEINozA3blScV9x7C5R9RCaSqV4KOkrm0Gh0Qx7vr6VcnOoAoGCCqGSM49 +AwEHoUQDQgAEwX5CSVrRxvS0fo1wkOd3Z2uHTGvviGQljxJa2xn/tbIvxUc3xJ+g +M6jYFkMHKgGYeQXLUEQLRvskVg4ICz9KHA== +-----END EC PRIVATE KEY----- diff -Nru nodejs-0.11.10/test/fixtures/keys/ec.cnf nodejs-0.11.11/test/fixtures/keys/ec.cnf --- nodejs-0.11.10/test/fixtures/keys/ec.cnf 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/test/fixtures/keys/ec.cnf 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,17 @@ +[ req ] +default_bits = 1024 +days = 999 +distinguished_name = req_distinguished_name +attributes = req_attributes +prompt = no + +[ req_distinguished_name ] +C = US +ST = CA +L = SF +O = Joyent +OU = Node.js +CN = agent2 +emailAddress = ry@tinyclouds.org + +[ req_attributes ] diff -Nru nodejs-0.11.10/test/gc/testcfg.py nodejs-0.11.11/test/gc/testcfg.py --- nodejs-0.11.10/test/gc/testcfg.py 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/gc/testcfg.py 2014-01-29 01:29:56.000000000 +0000 @@ -1,133 +1,6 @@ -# Copyright 2008 the V8 project authors. All rights reserved. -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials provided -# with the distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import test -import os -import shutil -from shutil import rmtree -from os import mkdir -from glob import glob -from os.path import join, dirname, exists -import re - - -FLAGS_PATTERN = re.compile(r"//\s+Flags:(.*)") -FILES_PATTERN = re.compile(r"//\s+Files:(.*)") - - -class GCTestCase(test.TestCase): - - def __init__(self, path, file, mode, context, config): - super(GCTestCase, self).__init__(context, path, mode) - self.file = file - self.config = config - self.mode = mode - self.tmpdir = join(dirname(self.config.root), 'tmp') - - def AfterRun(self, result): - # delete the whole tmp dir - try: - rmtree(self.tmpdir) - except: - pass - # make it again. - try: - mkdir(self.tmpdir) - except: - pass - - def BeforeRun(self): - # delete the whole tmp dir - try: - rmtree(self.tmpdir) - except: - pass - # make it again. - # intermittently fails on win32, so keep trying - while not os.path.exists(self.tmpdir): - try: - mkdir(self.tmpdir) - except: - pass - - def GetLabel(self): - return "%s %s" % (self.mode, self.GetName()) - - def GetName(self): - return self.path[-1] - - def GetCommand(self): - result = [self.config.context.GetVm(self.mode)] - source = open(self.file).read() - flags_match = FLAGS_PATTERN.search(source) - if flags_match: - result += flags_match.group(1).strip().split() - files_match = FILES_PATTERN.search(source); - additional_files = [] - if files_match: - additional_files += files_match.group(1).strip().split() - for a_file in additional_files: - result.append(join(dirname(self.config.root), '..', a_file)) - result += ["--expose-gc"] - result += [self.file] - return result - - def GetSource(self): - return open(self.file).read() - - -class GCTestConfiguration(test.TestConfiguration): - - def __init__(self, context, root): - super(GCTestConfiguration, self).__init__(context, root) - - def Ls(self, path): - def SelectTest(name): - return name.startswith('test-') and name.endswith('.js') - return [f[:-3] for f in os.listdir(path) if SelectTest(f)] - - def ListTests(self, current_path, path, mode): - all_tests = [current_path + [t] for t in self.Ls(join(self.root))] - result = [] - for test in all_tests: - if self.Contains(path, test): - file_path = join(self.root, reduce(join, test[1:], "") + ".js") - result.append(GCTestCase(test, file_path, mode, self.context, self)) - return result - - def GetBuildRequirements(self): - return ['sample', 'sample=shell'] - - def GetTestStatus(self, sections, defs): - status_file = join(self.root, 'gc.status') - if exists(status_file): - test.ReadConfigurationInto(status_file, sections, defs) - - +import sys, os +sys.path.append(os.path.join(os.path.dirname(__file__), '..')) +import testpy def GetConfiguration(context, root): - return GCTestConfiguration(context, root) + return testpy.SimpleTestConfiguration(context, root, 'gc', ['--expose-gc']) diff -Nru nodejs-0.11.10/test/internet/testcfg.py nodejs-0.11.11/test/internet/testcfg.py --- nodejs-0.11.10/test/internet/testcfg.py 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/internet/testcfg.py 2014-01-29 01:29:56.000000000 +0000 @@ -1,132 +1,6 @@ -# Copyright 2008 the V8 project authors. All rights reserved. -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials provided -# with the distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import test -import os -import shutil -from shutil import rmtree -from os import mkdir -from glob import glob -from os.path import join, dirname, exists -import re - - -FLAGS_PATTERN = re.compile(r"//\s+Flags:(.*)") -FILES_PATTERN = re.compile(r"//\s+Files:(.*)") - - -class InternetTestCase(test.TestCase): - - def __init__(self, path, file, mode, context, config): - super(InternetTestCase, self).__init__(context, path, mode) - self.file = file - self.config = config - self.mode = mode - self.tmpdir = join(dirname(self.config.root), 'tmp') - - def AfterRun(self, result): - # delete the whole tmp dir - try: - rmtree(self.tmpdir) - except: - pass - # make it again. - try: - mkdir(self.tmpdir) - except: - pass - - def BeforeRun(self): - # delete the whole tmp dir - try: - rmtree(self.tmpdir) - except: - pass - # make it again. - # intermittently fails on win32, so keep trying - while not os.path.exists(self.tmpdir): - try: - mkdir(self.tmpdir) - except: - pass - - def GetLabel(self): - return "%s %s" % (self.mode, self.GetName()) - - def GetName(self): - return self.path[-1] - - def GetCommand(self): - result = [self.config.context.GetVm(self.mode)] - source = open(self.file).read() - flags_match = FLAGS_PATTERN.search(source) - if flags_match: - result += flags_match.group(1).strip().split() - files_match = FILES_PATTERN.search(source); - additional_files = [] - if files_match: - additional_files += files_match.group(1).strip().split() - for a_file in additional_files: - result.append(join(dirname(self.config.root), '..', a_file)) - result += [self.file] - return result - - def GetSource(self): - return open(self.file).read() - - -class InternetTestConfiguration(test.TestConfiguration): - - def __init__(self, context, root): - super(InternetTestConfiguration, self).__init__(context, root) - - def Ls(self, path): - def SelectTest(name): - return name.startswith('test-') and name.endswith('.js') - return [f[:-3] for f in os.listdir(path) if SelectTest(f)] - - def ListTests(self, current_path, path, mode): - all_tests = [current_path + [t] for t in self.Ls(join(self.root))] - result = [] - for test in all_tests: - if self.Contains(path, test): - file_path = join(self.root, reduce(join, test[1:], "") + ".js") - result.append(InternetTestCase(test, file_path, mode, self.context, self)) - return result - - def GetBuildRequirements(self): - return ['sample', 'sample=shell'] - - def GetTestStatus(self, sections, defs): - status_file = join(self.root, 'simple.status') - if exists(status_file): - test.ReadConfigurationInto(status_file, sections, defs) - - +import sys, os +sys.path.append(os.path.join(os.path.dirname(__file__), '..')) +import testpy def GetConfiguration(context, root): - return InternetTestConfiguration(context, root) + return testpy.SimpleTestConfiguration(context, root, 'internet') diff -Nru nodejs-0.11.10/test/pummel/test-debug-break-on-uncaught.js nodejs-0.11.11/test/pummel/test-debug-break-on-uncaught.js --- nodejs-0.11.10/test/pummel/test-debug-break-on-uncaught.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/pummel/test-debug-break-on-uncaught.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,124 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -var path = require('path'); -var assert = require('assert'); -var spawn = require('child_process').spawn; -var common = require('../common'); -var debug = require('_debugger'); - -addScenario('global.js', null, 2); -addScenario('timeout.js', null, 2); -addScenario('domain.js', null, 10); - -// Exception is thrown from vm.js via module.js (internal file) -// var compiledWrapper = runInThisContext(wrapper, filename, 0, true); -addScenario('parse-error.js', 'vm.js', null); - -run(); - -/***************** IMPLEMENTATION *****************/ - -var scenarios; -function addScenario(scriptName, throwsInFile, throwsOnLine) { - if (!scenarios) scenarios = []; - scenarios.push( - runScenario.bind(null, scriptName, throwsInFile, throwsOnLine, run) - ); -} - -function run() { - var next = scenarios.shift(); - if (next) next(); -} - -function runScenario(scriptName, throwsInFile, throwsOnLine, next) { - console.log('**[ %s ]**', scriptName); - var asserted = false; - var port = common.PORT + 1337; - - var testScript = path.join( - common.fixturesDir, - 'uncaught-exceptions', - scriptName - ); - - var child = spawn(process.execPath, [ '--debug-brk=' + port, testScript ]); - child.on('close', function() { - assert(asserted, 'debugger did not pause on exception'); - if (next) next(); - }) - - var exceptions = []; - - setTimeout(setupClient.bind(null, runTest), 200); - - function setupClient(callback) { - var client = new debug.Client(); - - client.once('ready', callback.bind(null, client)); - - client.on('unhandledResponse', function(body) { - console.error('unhandled response: %j', body); - }); - - client.on('error', function(err) { - if (asserted) return; - assert.ifError(err); - }); - - client.connect(port); - } - - function runTest(client) { - client.req( - { - command: 'setexceptionbreak', - arguments: { - type: 'uncaught', - enabled: true - } - }, - function(error, result) { - assert.ifError(error); - - client.on('exception', function(event) { - exceptions.push(event.body); - }); - - client.reqContinue(function(error, result) { - assert.ifError(error); - setTimeout(assertHasPaused.bind(null, client), 100); - }); - } - ); - } - - function assertHasPaused(client) { - assert.equal(exceptions.length, 1, 'debugger did not pause on exception'); - assert.equal(exceptions[0].uncaught, true); - assert.equal(exceptions[0].script.name, throwsInFile || testScript); - if (throwsOnLine != null) - assert.equal(exceptions[0].sourceLine + 1, throwsOnLine); - asserted = true; - client.reqContinue(assert.ifError); - } -} diff -Nru nodejs-0.11.10/test/pummel/test-debugger-debug-brk.js nodejs-0.11.11/test/pummel/test-debugger-debug-brk.js --- nodejs-0.11.10/test/pummel/test-debugger-debug-brk.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/pummel/test-debugger-debug-brk.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - - -var common = require('../common'); -var assert = require('assert'); -var spawn = require('child_process').spawn; - -var script = common.fixturesDir + '/empty.js'; - -function fail() { - assert(0); // `node --debug-brk script.js` should not quit -} - -function test(arg) { - var child = spawn(process.execPath, [arg, script]); - child.on('exit', fail); - - // give node time to start up the debugger - setTimeout(function() { - child.removeListener('exit', fail); - child.kill(); - }, 2000); - - process.on('exit', function() { - assert(child.killed); - }); -} - -test('--debug-brk'); -test('--debug-brk=5959'); diff -Nru nodejs-0.11.10/test/pummel/test-debugger-repl-break-in-module.js nodejs-0.11.11/test/pummel/test-debugger-repl-break-in-module.js --- nodejs-0.11.10/test/pummel/test-debugger-repl-break-in-module.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/pummel/test-debugger-repl-break-in-module.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,80 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -var repl = require('../simple/helper-debugger-repl.js'); - -repl.startDebugger('break-in-module/main.js'); - -// -- SET BREAKPOINT -- - -// Set breakpoint by file name + line number where the file is not loaded yet -repl.addTest('sb("mod.js", 23)', [ - /Warning: script 'mod\.js' was not loaded yet\./, - /1/, /2/, /3/, /4/, /5/, /6/ -]); - -// Check escaping of regex characters -repl.addTest('sb(")^$*+?}{|][(.js\\\\", 1)', [ - /Warning: script '[^']+' was not loaded yet\./, - /1/, /2/, /3/, /4/, /5/, /6/ -]); - -// continue - the breakpoint should be triggered -repl.addTest('c', [ - /break in .*[\\\/]mod\.js:23/, - /21/, /22/, /23/, /24/, /25/ -]); - -// -- RESTORE BREAKPOINT ON RESTART -- - -// Restart the application - breakpoint should be restored -repl.addTest('restart', [].concat( - [ - /terminated/ - ], - repl.handshakeLines, - [ - /Restoring breakpoint mod.js:23/, - /Warning: script 'mod\.js' was not loaded yet\./, - /Restoring breakpoint \).*:\d+/, - /Warning: script '\)[^']*' was not loaded yet\./ - ], - repl.initialBreakLines)); - -// continue - the breakpoint should be triggered -repl.addTest('c', [ - /break in .*[\\\/]mod\.js:23/, - /21/, /22/, /23/, /24/, /25/ -]); - -// -- CLEAR BREAKPOINT SET IN MODULE TO BE LOADED -- - -repl.addTest('cb("mod.js", 23)', [ - /18/, /./, /./, /./, /./, /./, /./, /./, /26/ -]); - -repl.addTest('c', [ - /break in .*[\\\/]main\.js:4/, - /2/, /3/, /4/, /5/, /6/ -]); - -// -- (END) -- -repl.addTest('quit', []); diff -Nru nodejs-0.11.10/test/pummel/test-https-ci-reneg-attack.js nodejs-0.11.11/test/pummel/test-https-ci-reneg-attack.js --- nodejs-0.11.10/test/pummel/test-https-ci-reneg-attack.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/pummel/test-https-ci-reneg-attack.js 2014-01-29 01:29:56.000000000 +0000 @@ -26,6 +26,11 @@ var https = require('https'); var fs = require('fs'); +if (!common.opensslCli) { + console.error('Skipping because node compiled without OpenSSL CLI.'); + process.exit(0); +} + // renegotiation limits to test var LIMITS = [0, 1, 2, 3, 5, 10, 16]; diff -Nru nodejs-0.11.10/test/pummel/test-tls-ci-reneg-attack.js nodejs-0.11.11/test/pummel/test-tls-ci-reneg-attack.js --- nodejs-0.11.10/test/pummel/test-tls-ci-reneg-attack.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/pummel/test-tls-ci-reneg-attack.js 2014-01-29 01:29:56.000000000 +0000 @@ -25,6 +25,11 @@ var tls = require('tls'); var fs = require('fs'); +if (!common.opensslCli) { + console.error('Skipping because node compiled without OpenSSL CLI.'); + process.exit(0); +} + // renegotiation limits to test var LIMITS = [0, 1, 2, 3, 5, 10, 16]; diff -Nru nodejs-0.11.10/test/pummel/test-tls-securepair-client.js nodejs-0.11.11/test/pummel/test-tls-securepair-client.js --- nodejs-0.11.10/test/pummel/test-tls-securepair-client.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/pummel/test-tls-securepair-client.js 2014-01-29 01:29:56.000000000 +0000 @@ -18,13 +18,15 @@ // 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 (!process.versions.openssl) { - console.error('Skipping because node compiled without OpenSSL.'); +var common = require('../common'); + +if (!common.opensslCli) { + console.error('Skipping because node compiled without OpenSSL CLI.'); process.exit(0); } -var common = require('../common'); var join = require('path').join; var net = require('net'); var assert = require('assert'); diff -Nru nodejs-0.11.10/test/pummel/test-tls-session-timeout.js nodejs-0.11.11/test/pummel/test-tls-session-timeout.js --- nodejs-0.11.10/test/pummel/test-tls-session-timeout.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/pummel/test-tls-session-timeout.js 2014-01-29 01:29:56.000000000 +0000 @@ -19,10 +19,13 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. -if (!process.versions.openssl) { - console.error('Skipping because node compiled without OpenSSL.'); +var common = require('../common'); + +if (!common.opensslCli) { + console.error('Skipping because node compiled without OpenSSL CLI.'); process.exit(0); } + doTest(); // This test consists of three TLS requests -- @@ -34,7 +37,6 @@ // that we used has expired by now. function doTest() { - var common = require('../common'); var assert = require('assert'); var tls = require('tls'); var fs = require('fs'); diff -Nru nodejs-0.11.10/test/pummel/testcfg.py nodejs-0.11.11/test/pummel/testcfg.py --- nodejs-0.11.10/test/pummel/testcfg.py 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/pummel/testcfg.py 2014-01-29 01:29:56.000000000 +0000 @@ -1,130 +1,6 @@ -# Copyright 2008 the V8 project authors. All rights reserved. -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials provided -# with the distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import test -import os -import shutil -from shutil import rmtree -from os import mkdir -from glob import glob -from os.path import join, dirname, exists -import re - - -FLAGS_PATTERN = re.compile(r"//\s+Flags:(.*)") -FILES_PATTERN = re.compile(r"//\s+Files:(.*)") - - -class PummelTestCase(test.TestCase): - - def __init__(self, path, file, mode, context, config): - super(PummelTestCase, self).__init__(context, path, mode) - self.file = file - self.config = config - self.mode = mode - self.tmpdir = join(dirname(self.config.root), 'tmp') - - def AfterRun(self, result): - # delete the whole tmp dir - try: - rmtree(self.tmpdir) - except: - pass - # make it again. - try: - mkdir(self.tmpdir) - except: - pass - - def BeforeRun(self): - # delete the whole tmp dir - try: - rmtree(self.tmpdir) - except: - pass - # make it again. - try: - mkdir(self.tmpdir) - except: - pass - - def GetLabel(self): - return "%s %s" % (self.mode, self.GetName()) - - def GetName(self): - return self.path[-1] - - def GetCommand(self): - result = [self.config.context.GetVm(self.mode)] - source = open(self.file).read() - flags_match = FLAGS_PATTERN.search(source) - if flags_match: - result += flags_match.group(1).strip().split() - files_match = FILES_PATTERN.search(source); - additional_files = [] - if files_match: - additional_files += files_match.group(1).strip().split() - for a_file in additional_files: - result.append(join(dirname(self.config.root), '..', a_file)) - result += [self.file] - return result - - def GetSource(self): - return open(self.file).read() - - -class PummelTestConfiguration(test.TestConfiguration): - - def __init__(self, context, root): - super(PummelTestConfiguration, self).__init__(context, root) - - def Ls(self, path): - def SelectTest(name): - return name.startswith('test-') and name.endswith('.js') - return [f[:-3] for f in os.listdir(path) if SelectTest(f)] - - def ListTests(self, current_path, path, mode): - all_tests = [current_path + [t] for t in self.Ls(join(self.root))] - result = [] - for test in all_tests: - if self.Contains(path, test): - file_path = join(self.root, reduce(join, test[1:], "") + ".js") - result.append(PummelTestCase(test, file_path, mode, self.context, self)) - return result - - def GetBuildRequirements(self): - return ['sample', 'sample=shell'] - - def GetTestStatus(self, sections, defs): - status_file = join(self.root, 'simple.status') - if exists(status_file): - test.ReadConfigurationInto(status_file, sections, defs) - - +import sys, os +sys.path.append(os.path.join(os.path.dirname(__file__), '..')) +import testpy def GetConfiguration(context, root): - return PummelTestConfiguration(context, root) + return testpy.SimpleTestConfiguration(context, root, 'pummel') diff -Nru nodejs-0.11.10/test/simple/helper-debugger-repl.js nodejs-0.11.11/test/simple/helper-debugger-repl.js --- nodejs-0.11.10/test/simple/helper-debugger-repl.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/helper-debugger-repl.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,149 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -process.env.NODE_DEBUGGER_TIMEOUT = 2000; -var common = require('../common'); -var assert = require('assert'); -var spawn = require('child_process').spawn; - -var port = common.PORT + 1337; - -var child; -var buffer = ''; -var expected = []; -var quit; - -function startDebugger(scriptToDebug) { - scriptToDebug = process.env.NODE_DEBUGGER_TEST_SCRIPT || - common.fixturesDir + '/' + scriptToDebug; - - child = spawn(process.execPath, ['debug', '--port=' + port, scriptToDebug]); - - console.error('./node', 'debug', '--port=' + port, scriptToDebug); - - child.stdout.setEncoding('utf-8'); - child.stdout.on('data', function(data) { - data = (buffer + data).split('\n'); - buffer = data.pop(); - data.forEach(function(line) { - child.emit('line', line); - }); - }); - child.stderr.pipe(process.stderr); - - child.on('line', function(line) { - line = line.replace(/^(debug> *)+/, ''); - console.log(line); - assert.ok(expected.length > 0, 'Got unexpected line: ' + line); - - var expectedLine = expected[0].lines.shift(); - assert.ok(line.match(expectedLine) !== null, line + ' != ' + expectedLine); - - if (expected[0].lines.length === 0) { - var callback = expected[0].callback; - expected.shift(); - callback && callback(); - } - }); - - var childClosed = false; - child.on('close', function(code) { - assert(!code); - childClosed = true; - }); - - var quitCalled = false; - quit = function() { - if (quitCalled || childClosed) return; - quitCalled = true; - child.stdin.write('quit'); - child.kill('SIGTERM'); - } - - setTimeout(function() { - console.error('dying badly buffer=%j', buffer); - var err = 'Timeout'; - if (expected.length > 0 && expected[0].lines) { - err = err + '. Expected: ' + expected[0].lines.shift(); - } - - child.on('close', function() { - console.error('child is closed'); - throw new Error(err); - }); - - quit(); - }, 5000).unref(); - - process.once('uncaughtException', function(e) { - console.error('UncaughtException', e, e.stack); - quit(); - console.error(e.toString()); - process.exit(1); - }); - - process.on('exit', function(code) { - console.error('process exit', code); - quit(); - if (code === 0) - assert(childClosed); - }); -} - -function addTest(input, output) { - function next() { - if (expected.length > 0) { - console.log('debug> ' + expected[0].input); - child.stdin.write(expected[0].input + '\n'); - - if (!expected[0].lines) { - var callback = expected[0].callback; - expected.shift(); - - callback && callback(); - } - } else { - quit(); - } - }; - expected.push({input: input, lines: output, callback: next}); -} - -var handshakeLines = [ - /listening on port \d+/, - /connecting.* ok/ -]; - -var initialBreakLines = [ - /break in .*:1/, - /1/, /2/, /3/ -]; - -var initialLines = handshakeLines.concat(initialBreakLines); - -// Process initial lines -addTest(null, initialLines); - -exports.startDebugger = startDebugger; -exports.addTest = addTest; -exports.initialLines = initialLines; -exports.handshakeLines = handshakeLines; -exports.initialBreakLines = initialBreakLines; diff -Nru nodejs-0.11.10/test/simple/test-abort-fatal-error.js nodejs-0.11.11/test/simple/test-abort-fatal-error.js --- nodejs-0.11.10/test/simple/test-abort-fatal-error.js 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-abort-fatal-error.js 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,50 @@ +// Copyright Joyent, Inc. and other Node contributors. + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var assert = require('assert'); +var common = require('../common'); + +if (process.platform === 'win32') { + console.log('skipping test on windows'); + process.exit(0); +} + +var exec = require('child_process').exec; + +var cmdline = 'ulimit -c 0; ' + process.execPath; +cmdline += ' --max-old-space-size=4 --max-new-space-size=1'; +cmdline += ' -e "a = []; for (i = 0; i < 1e9; i++) { a.push({}) }"'; + +exec(cmdline, function(err, stdout, stderr) { + if (!err) { + console.log(stdout); + console.log(stderr); + assert(false, 'this test should fail'); + return; + } + + if (err.code !== 134 && err.signal !== 'SIGABRT') { + console.log(stdout); + console.log(stderr); + console.log(err); + assert(false, err); + } +}); diff -Nru nodejs-0.11.10/test/simple/test-asynclistener-error-add-after.js nodejs-0.11.11/test/simple/test-asynclistener-error-add-after.js --- nodejs-0.11.10/test/simple/test-asynclistener-error-add-after.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-asynclistener-error-add-after.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,161 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -var common = require('../common'); -var assert = require('assert'); -var dns = require('dns'); -var fs = require('fs'); -var net = require('net'); - -var errorMsgs = []; -var caught = 0; -var expectCaught = 0; -var exitCbRan = false; - -function asyncL() { } - -var callbacksObj = { - error: function(value, er) { - var idx = errorMsgs.indexOf(er.message); - caught++; - - process._rawDebug('Handling error: ' + er.message); - - if (-1 < idx) - errorMsgs.splice(idx, 1); - else - throw new Error('Message not found: ' + er.message); - - return true; - } -}; - -var listener = process.createAsyncListener(asyncL, callbacksObj); - -process.on('exit', function(code) { - // Just in case. - process.removeAsyncListener(listener); - - if (code > 0) - return; - - assert.ok(!exitCbRan); - exitCbRan = true; - - if (errorMsgs.length > 0) - throw new Error('Errors not fired: ' + errorMsgs); - - assert.equal(caught, expectCaught); - process._rawDebug('ok'); -}); - - -// Simple cases -errorMsgs.push('setTimeout - simple'); -errorMsgs.push('setImmediate - simple'); -errorMsgs.push('setInterval - simple'); -setTimeout(function() { - throw new Error('setTimeout - simple'); -}).addAsyncListener(listener); -expectCaught++; - -setImmediate(function() { - throw new Error('setImmediate - simple'); -}).addAsyncListener(listener); -expectCaught++; - -var b = setInterval(function() { - clearInterval(b); - throw new Error('setInterval - simple'); -}).addAsyncListener(listener); -expectCaught++; - - -// Deeply nested -errorMsgs.push('setInterval - nested'); -errorMsgs.push('setImmediate - nested'); -errorMsgs.push('setTimeout - nested'); -setTimeout(function() { - setImmediate(function() { - var b = setInterval(function() { - clearInterval(b); - throw new Error('setInterval - nested'); - }).addAsyncListener(listener); - expectCaught++; - throw new Error('setImmediate - nested'); - }).addAsyncListener(listener); - expectCaught++; - throw new Error('setTimeout - nested'); -}).addAsyncListener(listener); -expectCaught++; - - -// Net -var iter = 3; -for (var i = 0; i < iter; i++) { - errorMsgs.push('net - error: server connection'); - errorMsgs.push('net - error: client data'); - errorMsgs.push('net - error: server data'); -} -errorMsgs.push('net - error: server closed'); - -var server = net.createServer(function(c) { - c._handle.addAsyncListener(listener); - - c.on('data', function() { - if (0 === --iter) { - server.close(function() { - process._rawDebug('net - server closing'); - throw new Error('net - error: server closed'); - }); - expectCaught++; - } - process._rawDebug('net - connection received data'); - throw new Error('net - error: server data'); - }); - expectCaught++; - - c.end('bye'); - process._rawDebug('net - connection received'); - throw new Error('net - error: server connection'); -}); -expectCaught += iter; - -server.listen(common.PORT, function() { - // Test adding the async listener after server creation. Though it - // won't catch errors that originate synchronously from this point. - server._handle.addAsyncListener(listener); - for (var i = 0; i < iter; i++) - clientConnect(); -}); - -function clientConnect() { - var client = net.connect(common.PORT, function() { - client._handle.addAsyncListener(listener); - }); - - client.on('data', function() { - client.end('see ya'); - process._rawDebug('net - client received data'); - throw new Error('net - error: client data'); - }); - expectCaught++; -} diff -Nru nodejs-0.11.10/test/simple/test-asynclistener-error-multiple-handled.js nodejs-0.11.11/test/simple/test-asynclistener-error-multiple-handled.js --- nodejs-0.11.10/test/simple/test-asynclistener-error-multiple-handled.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-asynclistener-error-multiple-handled.js 2014-01-29 01:29:56.000000000 +0000 @@ -33,17 +33,24 @@ return 1; } +function onError(stor) { + results.push(stor); + return true; +} + var results = []; -var asyncNoHandleError = { - error: function(stor) { - results.push(stor); - return true; - } +var asyncNoHandleError0 = { + create: onAsync0, + error: onError +}; +var asyncNoHandleError1 = { + create: onAsync1, + error: onError }; var listeners = [ - process.addAsyncListener(onAsync0, asyncNoHandleError), - process.addAsyncListener(onAsync1, asyncNoHandleError) + process.addAsyncListener(asyncNoHandleError0), + process.addAsyncListener(asyncNoHandleError1) ]; process.nextTick(function() { diff -Nru nodejs-0.11.10/test/simple/test-asynclistener-error-multiple-mix.js nodejs-0.11.11/test/simple/test-asynclistener-error-multiple-mix.js --- nodejs-0.11.10/test/simple/test-asynclistener-error-multiple-mix.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-asynclistener-error-multiple-mix.js 2014-01-29 01:29:56.000000000 +0000 @@ -22,8 +22,6 @@ var common = require('../common'); var assert = require('assert'); -function onAsync() {} - var results = []; var asyncNoHandleError = { error: function(stor) { @@ -39,8 +37,8 @@ }; var listeners = [ - process.addAsyncListener(onAsync, asyncHandleError), - process.addAsyncListener(onAsync, asyncNoHandleError) + process.addAsyncListener(asyncHandleError), + process.addAsyncListener(asyncNoHandleError) ]; // Even if an error handler returns true, both should fire. diff -Nru nodejs-0.11.10/test/simple/test-asynclistener-error-multiple-unhandled.js nodejs-0.11.11/test/simple/test-asynclistener-error-multiple-unhandled.js --- nodejs-0.11.10/test/simple/test-asynclistener-error-multiple-unhandled.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-asynclistener-error-multiple-unhandled.js 2014-01-29 01:29:56.000000000 +0000 @@ -30,16 +30,23 @@ return 1; } +function onError(stor) { + results.push(stor); +} + var results = []; -var asyncNoHandleError = { - error: function(stor) { - results.push(stor); - } +var asyncNoHandleError0 = { + create: onAsync0, + error: onError +}; +var asyncNoHandleError1 = { + create: onAsync1, + error: onError }; var listeners = [ - process.addAsyncListener(onAsync0, asyncNoHandleError), - process.addAsyncListener(onAsync1, asyncNoHandleError) + process.addAsyncListener(asyncNoHandleError0), + process.addAsyncListener(asyncNoHandleError1) ]; var uncaughtFired = false; diff -Nru nodejs-0.11.10/test/simple/test-asynclistener-error-net.js nodejs-0.11.11/test/simple/test-asynclistener-error-net.js --- nodejs-0.11.10/test/simple/test-asynclistener-error-net.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-asynclistener-error-net.js 2014-01-29 01:29:56.000000000 +0000 @@ -29,8 +29,6 @@ var caught = 0; var expectCaught = 0; -function asyncL() { } - var callbacksObj = { error: function(value, er) { var idx = errorMsgs.indexOf(er.message); @@ -47,7 +45,7 @@ } }; -var listener = process.addAsyncListener(asyncL, callbacksObj); +var listener = process.addAsyncListener(callbacksObj); process.on('exit', function(code) { process.removeAsyncListener(listener); diff -Nru nodejs-0.11.10/test/simple/test-asynclistener-error-throw-in-after.js nodejs-0.11.11/test/simple/test-asynclistener-error-throw-in-after.js --- nodejs-0.11.10/test/simple/test-asynclistener-error-throw-in-after.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-asynclistener-error-throw-in-after.js 2014-01-29 01:29:56.000000000 +0000 @@ -23,7 +23,6 @@ var assert = require('assert'); var once = 0; -function onAsync0() { } var results = []; var handlers = { @@ -38,7 +37,7 @@ } } -var key = process.addAsyncListener(onAsync0, handlers); +var key = process.addAsyncListener(handlers); var uncaughtFired = false; process.on('uncaughtException', function(err) { diff -Nru nodejs-0.11.10/test/simple/test-asynclistener-error-throw-in-before-multiple.js nodejs-0.11.11/test/simple/test-asynclistener-error-throw-in-before-multiple.js --- nodejs-0.11.10/test/simple/test-asynclistener-error-throw-in-before-multiple.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-asynclistener-error-throw-in-before-multiple.js 2014-01-29 01:29:56.000000000 +0000 @@ -23,8 +23,6 @@ var assert = require('assert'); var once = 0; -function onAsync0() { } -function onAsync1() { } var results = []; var handlers = { @@ -52,8 +50,8 @@ } var listeners = [ - process.addAsyncListener(onAsync0, handlers), - process.addAsyncListener(onAsync1, handlers1) + process.addAsyncListener(handlers), + process.addAsyncListener(handlers1) ]; var uncaughtFired = false; diff -Nru nodejs-0.11.10/test/simple/test-asynclistener-error-throw-in-before.js nodejs-0.11.11/test/simple/test-asynclistener-error-throw-in-before.js --- nodejs-0.11.10/test/simple/test-asynclistener-error-throw-in-before.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-asynclistener-error-throw-in-before.js 2014-01-29 01:29:56.000000000 +0000 @@ -23,7 +23,6 @@ var assert = require('assert'); var once = 0; -function onAsync0() {} var results = []; var handlers = { @@ -38,7 +37,7 @@ } } -var key = process.addAsyncListener(onAsync0, handlers); +var key = process.addAsyncListener(handlers); var uncaughtFired = false; process.on('uncaughtException', function(err) { diff -Nru nodejs-0.11.10/test/simple/test-asynclistener-error-throw-in-error.js nodejs-0.11.11/test/simple/test-asynclistener-error-throw-in-error.js --- nodejs-0.11.10/test/simple/test-asynclistener-error-throw-in-error.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-asynclistener-error-throw-in-error.js 2014-01-29 01:29:56.000000000 +0000 @@ -34,7 +34,7 @@ function runChild() { var cntr = 0; - var key = process.addAsyncListener(function() { }, { + var key = process.addAsyncListener({ error: function onError() { cntr++; throw new Error('onError'); diff -Nru nodejs-0.11.10/test/simple/test-asynclistener-error.js nodejs-0.11.11/test/simple/test-asynclistener-error.js --- nodejs-0.11.10/test/simple/test-asynclistener-error.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-asynclistener-error.js 2014-01-29 01:29:56.000000000 +0000 @@ -33,8 +33,6 @@ var expectCaught = 0; var exitCbRan = false; -function asyncL() { } - var callbacksObj = { error: function(value, er) { var idx = errorMsgs.indexOf(er.message); @@ -48,7 +46,7 @@ } }; -var listener = process.createAsyncListener(asyncL, callbacksObj); +var listener = process.createAsyncListener(callbacksObj); process.on('exit', function(code) { removeListener(listener); diff -Nru nodejs-0.11.10/test/simple/test-asynclistener-multi-timeout.js nodejs-0.11.11/test/simple/test-asynclistener-multi-timeout.js --- nodejs-0.11.10/test/simple/test-asynclistener-multi-timeout.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-asynclistener-multi-timeout.js 2014-01-29 01:29:56.000000000 +0000 @@ -27,8 +27,6 @@ var caught = []; var expect = []; -function asyncL(a) {} - var callbacksObj = { error: function(value, er) { process._rawDebug('caught', er.message); @@ -37,7 +35,7 @@ } }; -var listener = process.createAsyncListener(asyncL, callbacksObj); +var listener = process.createAsyncListener(callbacksObj); process.on('exit', function(code) { removeListener(listener); diff -Nru nodejs-0.11.10/test/simple/test-asynclistener-remove-add-in-before.js nodejs-0.11.11/test/simple/test-asynclistener-remove-add-in-before.js --- nodejs-0.11.10/test/simple/test-asynclistener-remove-add-in-before.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-asynclistener-remove-add-in-before.js 2014-01-29 01:29:56.000000000 +0000 @@ -23,6 +23,9 @@ var assert = require('assert'); var val; var callbacks = { + create: function() { + return 42; + }, before: function() { process.removeAsyncListener(listener); process.addAsyncListener(listener); @@ -32,14 +35,12 @@ } }; -var listener = process.addAsyncListener(function() { - return 66; -}, callbacks); +var listener = process.addAsyncListener(callbacks); process.nextTick(function() {}); process.on('exit', function(status) { process.removeAsyncListener(listener); assert.equal(status, 0); - assert.equal(val, 66); + assert.equal(val, 42); }); diff -Nru nodejs-0.11.10/test/simple/test-asynclistener-remove-after.js nodejs-0.11.11/test/simple/test-asynclistener-remove-after.js --- nodejs-0.11.10/test/simple/test-asynclistener-remove-after.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-asynclistener-remove-after.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,66 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -var common = require('../common'); -var assert = require('assert'); -var net = require('net'); - - -// TODO(trevnorris): Test has the flaw that it's not checking if the async -// flag has been removed on the class instance. Though currently there's -// no way to do that. -var listener = process.addAsyncListener(function() { }); - - -// Test timers - -setImmediate(function() { - assert.equal(this._asyncQueue.length, 0); -}).removeAsyncListener(listener); - -setTimeout(function() { - assert.equal(this._asyncQueue.length, 0); -}).removeAsyncListener(listener); - -setInterval(function() { - clearInterval(this); - assert.equal(this._asyncQueue.length, 0); -}).removeAsyncListener(listener); - - -// Test net - -var server = net.createServer(function(c) { - c._handle.removeAsyncListener(listener); - assert.equal(c._handle._asyncQueue.length, 0); -}); - -server.listen(common.PORT, function() { - server._handle.removeAsyncListener(listener); - assert.equal(server._handle._asyncQueue.length, 0); - - var client = net.connect(common.PORT, function() { - client._handle.removeAsyncListener(listener); - assert.equal(client._handle._asyncQueue.length, 0); - client.end(); - server.close(); - }); -}); diff -Nru nodejs-0.11.10/test/simple/test-asynclistener-remove-before.js nodejs-0.11.11/test/simple/test-asynclistener-remove-before.js --- nodejs-0.11.10/test/simple/test-asynclistener-remove-before.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-asynclistener-remove-before.js 2014-01-29 01:29:56.000000000 +0000 @@ -23,8 +23,6 @@ var assert = require('assert'); var set = 0; -function onAsync0() { } - var asyncNoHandleError = { before: function() { set++; @@ -34,7 +32,7 @@ } } -var key = process.addAsyncListener(onAsync0, asyncNoHandleError); +var key = process.addAsyncListener(asyncNoHandleError); process.removeAsyncListener(key); diff -Nru nodejs-0.11.10/test/simple/test-asynclistener-remove-in-before.js nodejs-0.11.11/test/simple/test-asynclistener-remove-in-before.js --- nodejs-0.11.10/test/simple/test-asynclistener-remove-in-before.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-asynclistener-remove-in-before.js 2014-01-29 01:29:56.000000000 +0000 @@ -31,7 +31,7 @@ } }; -var listener = process.addAsyncListener(function() {}, callbacks); +var listener = process.addAsyncListener(callbacks); process.nextTick(function() {}); diff -Nru nodejs-0.11.10/test/simple/test-asynclistener-remove-inflight-error.js nodejs-0.11.11/test/simple/test-asynclistener-remove-inflight-error.js --- nodejs-0.11.10/test/simple/test-asynclistener-remove-inflight-error.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-asynclistener-remove-inflight-error.js 2014-01-29 01:29:56.000000000 +0000 @@ -22,8 +22,6 @@ var common = require('../common'); var assert = require('assert'); -function onAsync0() { } - var set = 0; var asyncNoHandleError = { error: function() { @@ -31,7 +29,7 @@ } } -var key = process.addAsyncListener(onAsync0, asyncNoHandleError); +var key = process.addAsyncListener(asyncNoHandleError); process.nextTick(function() { throw 1; diff -Nru nodejs-0.11.10/test/simple/test-asynclistener-remove-inflight.js nodejs-0.11.11/test/simple/test-asynclistener-remove-inflight.js --- nodejs-0.11.10/test/simple/test-asynclistener-remove-inflight.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-asynclistener-remove-inflight.js 2014-01-29 01:29:56.000000000 +0000 @@ -22,8 +22,6 @@ var common = require('../common'); var assert = require('assert'); -function onAsync0() { } - var set = 0; var asyncNoHandleError = { before: function() { @@ -34,7 +32,7 @@ } } -var key = process.addAsyncListener(onAsync0, asyncNoHandleError); +var key = process.addAsyncListener(asyncNoHandleError); process.nextTick(function() { }); diff -Nru nodejs-0.11.10/test/simple/test-asynclistener-run-error-once.js nodejs-0.11.11/test/simple/test-asynclistener-run-error-once.js --- nodejs-0.11.10/test/simple/test-asynclistener-run-error-once.js 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-asynclistener-run-error-once.js 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,55 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var common = require('../common'); +var assert = require('assert'); +var net = require('net'); + +var cntr = 0; +var al = process.addAsyncListener({ + error: function(stor, er) { + cntr++; + process._rawDebug('Handling error: ' + er.message); + return true; + } +}); + +process.on('exit', function(status) { + process.removeAsyncListener(al); + + assert.equal(status, 0); + assert.equal(cntr, 1); + console.log('ok'); +}); + + +var server = net.createServer(function(c) { + throw new Error('net - error: server connection'); +}); + + +server.listen(common.PORT, function() { + net.connect(common.PORT, function() { + setImmediate(function() { + process.exit(); + }); + }); +}); diff -Nru nodejs-0.11.10/test/simple/test-asynclistener-run-inst-once.js nodejs-0.11.11/test/simple/test-asynclistener-run-inst-once.js --- nodejs-0.11.10/test/simple/test-asynclistener-run-inst-once.js 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-asynclistener-run-inst-once.js 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,45 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var common = require('../common'); +var assert = require('assert'); + +var cntr = 0; +var al = process.createAsyncListener({ + create: function() { cntr++; }, +}); + +process.on('exit', function() { + assert.equal(cntr, 4); + console.log('ok'); +}); + +process.addAsyncListener(al); + +process.nextTick(function() { + process.addAsyncListener(al); + process.nextTick(function() { + process.addAsyncListener(al); + process.nextTick(function() { + process.nextTick(function() { }); + }); + }); +}); diff -Nru nodejs-0.11.10/test/simple/test-asynclistener-throw-before-infinite-recursion.js nodejs-0.11.11/test/simple/test-asynclistener-throw-before-infinite-recursion.js --- nodejs-0.11.10/test/simple/test-asynclistener-throw-before-infinite-recursion.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-asynclistener-throw-before-infinite-recursion.js 2014-01-29 01:29:56.000000000 +0000 @@ -31,7 +31,7 @@ var cntr = 0; -process.addAsyncListener(function() { }, { +process.addAsyncListener({ before: function() { if (++cntr > 1) { // Can't throw since uncaughtException will also catch that. diff -Nru nodejs-0.11.10/test/simple/test-asynclistener.js nodejs-0.11.11/test/simple/test-asynclistener.js --- nodejs-0.11.10/test/simple/test-asynclistener.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-asynclistener.js 2014-01-29 01:29:56.000000000 +0000 @@ -30,11 +30,13 @@ var actualAsync = 0; var expectAsync = 0; -function onAsync() { - actualAsync++; -} +var callbacks = { + create: function onAsync() { + actualAsync++; + } +}; -var listener = process.createAsyncListener(onAsync); +var listener = process.createAsyncListener(callbacks); process.on('exit', function() { process._rawDebug('expected', expectAsync); diff -Nru nodejs-0.11.10/test/simple/test-child-process-exec-error.js nodejs-0.11.11/test/simple/test-child-process-exec-error.js --- nodejs-0.11.10/test/simple/test-child-process-exec-error.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-child-process-exec-error.js 2014-01-29 01:29:56.000000000 +0000 @@ -28,6 +28,7 @@ fun('does-not-exist', function(err) { assert.equal(err.code, code); + assert(/does\-not\-exist/.test(err.cmd)); errors++; }); diff -Nru nodejs-0.11.10/test/simple/test-cluster-disconnect.js nodejs-0.11.11/test/simple/test-cluster-disconnect.js --- nodejs-0.11.10/test/simple/test-cluster-disconnect.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-cluster-disconnect.js 2014-01-29 01:29:56.000000000 +0000 @@ -35,6 +35,7 @@ }).listen(common.PORT + 1, '127.0.0.1'); } else if (cluster.isMaster) { + var servers = 2; // test a single TCP server var testConnection = function(port, cb) { @@ -52,7 +53,6 @@ // test both servers created in the cluster var testCluster = function(cb) { - var servers = 2; var done = 0; for (var i = 0, l = servers; i < l; i++) { @@ -76,7 +76,7 @@ var worker = cluster.fork(); worker.on('listening', function() { online += 1; - if (online === workers) { + if (online === workers * servers) { cb(); } }); diff -Nru nodejs-0.11.10/test/simple/test-cluster-net-send.js nodejs-0.11.11/test/simple/test-cluster-net-send.js --- nodejs-0.11.10/test/simple/test-cluster-net-send.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-cluster-net-send.js 2014-01-29 01:29:56.000000000 +0000 @@ -38,6 +38,9 @@ handle.on('data', function(data) { called = true; assert.equal(data.toString(), 'hello'); + }); + + handle.on('end', function() { worker.kill(); }); }); diff -Nru nodejs-0.11.10/test/simple/test-cluster-rr-domain-listen.js nodejs-0.11.11/test/simple/test-cluster-rr-domain-listen.js --- nodejs-0.11.10/test/simple/test-cluster-rr-domain-listen.js 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-cluster-rr-domain-listen.js 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,51 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var common = require('../common'); +var cluster = require('cluster'); +var domain = require('domain'); + +// RR is the default for v0.11.9+ so the following line is redundant: +// cluster.schedulingPolicy = cluster.SCHED_RR; + +if (cluster.isWorker) { + var d = domain.create(); + d.run(function () { }); + + var http = require('http'); + http.Server(function() { }).listen(common.PORT, '127.0.0.1'); + +} else if (cluster.isMaster) { + var worker; + + //Kill worker when listening + cluster.on('listening', function() { + worker.kill(); + }); + + //Kill process when worker is killed + cluster.on('exit', function() { + process.exit(0); + }); + + //Create worker + worker = cluster.fork(); +} diff -Nru nodejs-0.11.10/test/simple/test-crypto.js nodejs-0.11.11/test/simple/test-crypto.js --- nodejs-0.11.10/test/simple/test-crypto.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-crypto.js 2014-01-29 01:29:56.000000000 +0000 @@ -24,6 +24,7 @@ var common = require('../common'); var assert = require('assert'); +var util = require('util'); try { var crypto = require('crypto'); @@ -912,8 +913,23 @@ '\x56\xfa\x6a\xa7\x55\x48\x09\x9d\xcc\x37\xd7\xf0\x34' + '\x25\xe0\xc3'); +(function() { + var expected = + '64c486c55d30d4c5a079b8823b7d7cb37ff0556f537da8410233bcec330ed956'; + var key = crypto.pbkdf2Sync('password', 'salt', 32, 32, 'sha256'); + assert.equal(key.toString('hex'), expected); + + crypto.pbkdf2('password', 'salt', 32, 32, 'sha256', common.mustCall(ondone)); + function ondone(err, key) { + if (err) throw err; + assert.equal(key.toString('hex'), expected); + } +})(); + function assertSorted(list) { - assert.deepEqual(list, list.sort()); + // Array#sort() modifies the list in place so make a copy. + var sorted = util._extend([], list).sort(); + assert.deepEqual(list, sorted); } // Assume that we have at least AES-128-CBC. @@ -1006,5 +1022,18 @@ crypto.createVerify('RSA-SHA1').update('0', 'hex'); }, /Bad input string/); +assert.throws(function() { + var private = [ + '-----BEGIN RSA PRIVATE KEY-----', + 'MIGrAgEAAiEA+3z+1QNF2/unumadiwEr+C5vfhezsb3hp4jAnCNRpPcCAwEAAQIgQNriSQK4', + 'EFwczDhMZp2dvbcz7OUUyt36z3S4usFPHSECEQD/41K7SujrstBfoCPzwC1xAhEA+5kt4BJy', + 'eKN7LggbF3Dk5wIQN6SL+fQ5H/+7NgARsVBp0QIRANxYRukavs4QvuyNhMx+vrkCEQCbf6j/', + 'Ig6/HueCK/0Jkmp+', + '-----END RSA PRIVATE KEY-----', + '' + ].join('\n'); + crypto.createSign('RSA-SHA256').update('test').sign(private); +}, /RSA_sign:digest too big for rsa key/); + // Make sure memory isn't released before being returned console.log(crypto.randomBytes(16)); diff -Nru nodejs-0.11.10/test/simple/test-debug-signal-cluster.js nodejs-0.11.11/test/simple/test-debug-signal-cluster.js --- nodejs-0.11.10/test/simple/test-debug-signal-cluster.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-debug-signal-cluster.js 2014-01-29 01:29:56.000000000 +0000 @@ -40,7 +40,7 @@ if (waitingForDebuggers) { outputLines = outputLines.concat(lines); - outputTimerId = setTimeout(onNoMoreLines, 200); + outputTimerId = setTimeout(onNoMoreLines, 800); } else if (line === 'all workers are running') { waitingForDebuggers = true; process._debugProcess(child.pid); @@ -54,7 +54,7 @@ setTimeout(function testTimedOut() { assert(false, 'test timed out.'); -}, 3000); +}, 6000); process.on('exit', function onExit() { child.kill(); diff -Nru nodejs-0.11.10/test/simple/test-debugger-client.js nodejs-0.11.11/test/simple/test-debugger-client.js --- nodejs-0.11.10/test/simple/test-debugger-client.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-debugger-client.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,234 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - - - - -process.env.NODE_DEBUGGER_TIMEOUT = 2000; -var common = require('../common'); -var assert = require('assert'); -var debug = require('_debugger'); - -var debugPort = common.PORT + 1337; -debug.port = debugPort; -var spawn = require('child_process').spawn; - -setTimeout(function() { - if (nodeProcess) nodeProcess.kill('SIGTERM'); - throw new Error('timeout'); -}, 10000).unref(); - - -var resCount = 0; -var p = new debug.Protocol(); -p.onResponse = function(res) { - resCount++; -}; - -p.execute('Type: connect\r\n' + - 'V8-Version: 3.0.4.1\r\n' + - 'Protocol-Version: 1\r\n' + - 'Embedding-Host: node v0.3.3-pre\r\n' + - 'Content-Length: 0\r\n\r\n'); -assert.equal(1, resCount); - -// Make sure split messages go in. - -var parts = []; -parts.push('Content-Length: 336\r\n'); -assert.equal(21, parts[0].length); -parts.push('\r\n'); -assert.equal(2, parts[1].length); -var bodyLength = 0; - -parts.push('{"seq":12,"type":"event","event":"break","body":' + - '{"invocationText":"#'); -assert.equal(78, parts[2].length); -bodyLength += parts[2].length; - -parts.push('.[anonymous](req=#, ' + - 'res=#)","sourceLine"'); -assert.equal(78, parts[3].length); -bodyLength += parts[3].length; - -parts.push(':45,"sourceColumn":4,"sourceLineText":" debugger;",' + - '"script":{"id":24,"name":"/home/ryan/projects/node/' + - 'benchmark/http_simple.js","lineOffset":0,"columnOffset":0,' + - '"lineCount":98}}}'); -assert.equal(180, parts[4].length); -bodyLength += parts[4].length; - -assert.equal(336, bodyLength); - -for (var i = 0; i < parts.length; i++) { - p.execute(parts[i]); -} -assert.equal(2, resCount); - - -// Make sure that if we get backed up, we still manage to get all the -// messages -var d = 'Content-Length: 466\r\n\r\n' + - '{"seq":10,"type":"event","event":"afterCompile","success":true,' + - '"body":{"script":{"handle":1,"type":"script","name":"dns.js",' + - '"id":34,"lineOffset":0,"columnOffset":0,"lineCount":241,' + - '"sourceStart":"(function (module, exports, require) {' + - 'var dns = process.binding(\'cares\')' + - ';\\nvar ne","sourceLength":6137,"scriptType":2,"compilationType":0,' + - '"context":{"ref":0},"text":"dns.js (lines: 241)"}},"refs":' + - '[{"handle":0' + - ',"type":"context","text":"#"}],"running":true}' + - 'Content-Length: 119\r\n\r\n' + - '{"seq":11,"type":"event","event":"scriptCollected","success":true,' + - '"body":{"script":{"id":26}},"refs":[],"running":true}'; -p.execute(d); -assert.equal(4, resCount); - -var expectedConnections = 0; -var tests = []; -function addTest(cb) { - expectedConnections++; - tests.push(cb); -} - -addTest(function(client, done) { - console.error('requesting version'); - client.reqVersion(function(err, v) { - assert.ok(!err); - console.log('version: %s', v); - assert.equal(process.versions.v8, v); - done(); - }); -}); - -addTest(function(client, done) { - console.error('requesting scripts'); - client.reqScripts(function(err) { - assert.ok(!err); - console.error('got %d scripts', Object.keys(client.scripts).length); - - var foundMainScript = false; - for (var k in client.scripts) { - var script = client.scripts[k]; - if (script && script.name === 'node.js') { - foundMainScript = true; - break; - } - } - assert.ok(foundMainScript); - done(); - }); -}); - -addTest(function(client, done) { - console.error('eval 2+2'); - client.reqEval('2+2', function(err, res) { - console.error(res); - assert.ok(!err); - assert.equal('4', res.text); - assert.equal(4, res.value); - done(); - }); -}); - - -var connectCount = 0; -var script = 'setTimeout(function () { console.log("blah"); });' + - 'setInterval(function () {}, 1000000);'; - -var nodeProcess; - -function doTest(cb, done) { - var args = ['--debug=' + debugPort, '-e', script]; - nodeProcess = spawn(process.execPath, args); - - nodeProcess.stdout.once('data', function(c) { - console.log('>>> new node process: %d', nodeProcess.pid); - var failed = true; - try { - process._debugProcess(nodeProcess.pid); - failed = false; - } finally { - // At least TRY not to leave zombie procs if this fails. - if (failed) - nodeProcess.kill('SIGTERM'); - } - console.log('>>> starting debugger session'); - }); - - var didTryConnect = false; - nodeProcess.stderr.setEncoding('utf8'); - var b = ''; - nodeProcess.stderr.on('data', function(data) { - console.error('got stderr data %j', data); - nodeProcess.stderr.resume(); - b += data; - if (didTryConnect === false && b.match(/Debugger listening on port/)) { - didTryConnect = true; - - // The timeout is here to expose a race in the bootstrap process. - // Without the early SIGUSR1 debug handler, it effectively results - // in an infinite ECONNREFUSED loop. - setTimeout(tryConnect, 100); - - function tryConnect() { - // Wait for some data before trying to connect - var c = new debug.Client(); - console.error('>>> connecting...'); - c.connect(debug.port); - c.on('break', function(brk) { - c.reqContinue(function() {}); - }); - c.on('ready', function() { - connectCount++; - console.log('ready!'); - cb(c, function() { - console.error('>>> killing node process %d\n\n', nodeProcess.pid); - nodeProcess.kill(); - done(); - }); - }); - c.on('error', function(err) { - if (err.code !== 'ECONNREFUSED') throw err; - setTimeout(tryConnect, 10); - }); - } - } - }); -} - - -function run() { - var t = tests[0]; - if (!t) return; - - doTest(t, function() { - tests.shift(); - run(); - }); -} - -run(); - -process.on('exit', function(code) { - if (!code) - assert.equal(expectedConnections, connectCount); -}); diff -Nru nodejs-0.11.10/test/simple/test-debugger-repl-restart.js nodejs-0.11.11/test/simple/test-debugger-repl-restart.js --- nodejs-0.11.10/test/simple/test-debugger-repl-restart.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-debugger-repl-restart.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -var repl = require('./helper-debugger-repl.js'); - -repl.startDebugger('breakpoints.js'); - -// Restart the debugged script -repl.addTest('restart', [ - /terminated/, -].concat(repl.initialLines)); - -repl.addTest('quit', []); diff -Nru nodejs-0.11.10/test/simple/test-debugger-repl-term.js nodejs-0.11.11/test/simple/test-debugger-repl-term.js --- nodejs-0.11.10/test/simple/test-debugger-repl-term.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-debugger-repl-term.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,63 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -process.env.NODE_FORCE_READLINE = 1; - -var repl = require('./helper-debugger-repl.js'); - -repl.startDebugger('breakpoints.js'); - -var addTest = repl.addTest; - -// next -addTest('n', [ - /debug>.*n/, - /break in .*:11/, - /9/, /10/, /11/, /12/, /13/ -]); - -// should repeat next -addTest('', [ - /debug>/, - /break in .*:5/, - /3/, /4/, /5/, /6/, /7/, -]); - -// continue -addTest('c', [ - /debug>.*c/, - /break in .*:12/, - /10/, /11/, /12/, /13/, /14/ -]); - -// should repeat continue -addTest('', [ - /debug>/, - /break in .*:5/, - /3/, /4/, /5/, /6/, /7/, -]); - -// should repeat continue -addTest('', [ - /debug>/, - /break in .*:23/, - /21/, /22/, /23/, /24/, /25/, -]); diff -Nru nodejs-0.11.10/test/simple/test-debugger-repl-utf8.js nodejs-0.11.11/test/simple/test-debugger-repl-utf8.js --- nodejs-0.11.10/test/simple/test-debugger-repl-utf8.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-debugger-repl-utf8.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -var common = require('../common'); -var script = common.fixturesDir + '/breakpoints_utf8.js'; -process.env.NODE_DEBUGGER_TEST_SCRIPT = script; - -require('./test-debugger-repl.js'); - diff -Nru nodejs-0.11.10/test/simple/test-debugger-repl.js nodejs-0.11.11/test/simple/test-debugger-repl.js --- nodejs-0.11.10/test/simple/test-debugger-repl.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-debugger-repl.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,77 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -var repl = require('./helper-debugger-repl.js'); - -repl.startDebugger('breakpoints.js'); - -var addTest = repl.addTest; - -// Next -addTest('n', [ - /break in .*:11/, - /9/, /10/, /11/, /12/, /13/ -]); - -// Watch -addTest('watch("\'x\'")'); - -// Continue -addTest('c', [ - /break in .*:5/, - /Watchers/, - /0:\s+'x' = "x"/, - /()/, - /3/, /4/, /5/, /6/, /7/ -]); - -// Show watchers -addTest('watchers', [ - /0:\s+'x' = "x"/ -]); - -// Unwatch -addTest('unwatch("\'x\'")'); - -// Step out -addTest('o', [ - /break in .*:12/, - /10/, /11/, /12/, /13/, /14/ -]); - -// Continue -addTest('c', [ - /break in .*:5/, - /3/, /4/, /5/, /6/, /7/ -]); - -// Set breakpoint by function name -addTest('sb("setInterval()", "!(setInterval.flag++)")', [ - /1/, /2/, /3/, /4/, /5/, /6/, /7/, /8/, /9/, /10/ -]); - -// Continue -addTest('c', [ - /break in node.js:\d+/, - /\d/, /\d/, /\d/, /\d/, /\d/ -]); - -addTest('quit', []); diff -Nru nodejs-0.11.10/test/simple/test-domain-enter-exit.js nodejs-0.11.11/test/simple/test-domain-enter-exit.js --- nodejs-0.11.10/test/simple/test-domain-enter-exit.js 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-domain-enter-exit.js 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,59 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + + +// Make sure the domain stack is a stack + +var assert = require('assert'); +var domain = require('domain'); + +function names(array) { + return array.map(function(d) { + return d.name + }).join(', '); +} + +var a = domain.create(); +a.name = 'a'; +var b = domain.create(); +b.name = 'b'; +var c = domain.create(); +c.name = 'c'; + +a.enter(); // push +assert.deepEqual(domain._stack, [a], + 'a not pushed: ' + names(domain._stack)); + +b.enter(); // push +assert.deepEqual(domain._stack, [a, b], + 'b not pushed: ' + names(domain._stack)); + +c.enter(); // push +assert.deepEqual(domain._stack, [a, b, c], + 'c not pushed: ' + names(domain._stack)); + +b.exit(); // pop +assert.deepEqual(domain._stack, [a], + 'b and c not popped: ' + names(domain._stack)); + +b.enter(); // push +assert.deepEqual(domain._stack, [a, b], + 'b not pushed: ' + names(domain._stack)); diff -Nru nodejs-0.11.10/test/simple/test-domain-safe-exit.js nodejs-0.11.11/test/simple/test-domain-safe-exit.js --- nodejs-0.11.10/test/simple/test-domain-safe-exit.js 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-domain-safe-exit.js 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,36 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + + +// Make sure the domain stack doesn't get clobbered by un-matched .exit() + +var assert = require('assert'); +var domain = require('domain'); + +var a = domain.create(); +var b = domain.create(); + +a.enter(); // push +b.enter(); // push +assert.deepEqual(domain._stack, [a, b], 'b not pushed'); + +domain.create().exit(); // no-op +assert.deepEqual(domain._stack, [a, b], 'stack mangled!'); diff -Nru nodejs-0.11.10/test/simple/test-http-client-readable.js nodejs-0.11.11/test/simple/test-http-client-readable.js --- nodejs-0.11.10/test/simple/test-http-client-readable.js 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-http-client-readable.js 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,80 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var common = require('../common'); +var assert = require('assert'); +var http = require('http'); +var util = require('util'); + +var Duplex = require('stream').Duplex; + +function FakeAgent() { + http.Agent.call(this); +} +util.inherits(FakeAgent, http.Agent); + +FakeAgent.prototype.createConnection = function createConnection() { + var s = new Duplex(); + var once = false; + + s._read = function read() { + if (once) + return this.push(null); + once = true; + + this.push('HTTP/1.1 200 Ok\r\nTransfer-Encoding: chunked\r\n\r\n'); + this.push('b\r\nhello world\r\n'); + this.readable = false; + this.push('0\r\n\r\n'); + }; + + // Blackhole + s._write = function write(data, enc, cb) { + cb(); + }; + + s.destroy = s.destroySoon = function destroy() { + this.writable = false; + }; + + return s; +}; + +var received = ''; +var ended = 0; + +var req = http.request({ + agent: new FakeAgent() +}, function(res) { + res.on('data', function(chunk) { + received += chunk; + }); + + res.on('end', function() { + ended++; + }); +}); +req.end(); + +process.on('exit', function() { + assert.equal(received, 'hello world'); + assert.equal(ended, 1); +}); diff -Nru nodejs-0.11.10/test/simple/test-http-exit-delay.js nodejs-0.11.11/test/simple/test-http-exit-delay.js --- nodejs-0.11.10/test/simple/test-http-exit-delay.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-http-exit-delay.js 2014-01-29 01:29:56.000000000 +0000 @@ -30,16 +30,16 @@ res.end('Success'); }); - server.close(function() { - start = process.hrtime(); - }); + server.close(); }); server.listen(common.PORT, 'localhost', function() { var interval_id = setInterval(function() { - if (new Date().getMilliseconds() > 100) + start = new Date(); + if (start.getMilliseconds() > 100) return; + console.log(start.toISOString()); var req = http.request({ 'host': 'localhost', 'port': common.PORT, @@ -53,8 +53,9 @@ }); process.on('exit', function() { - var d = process.hrtime(start); - assert.equal(d[0], 0); - assert(d[1] / 1e9 < 0.03); + var end = new Date(); + console.log(end.toISOString()); + assert.equal(start.getSeconds(), end.getSeconds()); + assert(end.getMilliseconds() < 900); console.log('ok'); }); diff -Nru nodejs-0.11.10/test/simple/test-http-incoming-pipelined-socket-destroy.js nodejs-0.11.11/test/simple/test-http-incoming-pipelined-socket-destroy.js --- nodejs-0.11.10/test/simple/test-http-incoming-pipelined-socket-destroy.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-http-incoming-pipelined-socket-destroy.js 2014-01-29 01:29:56.000000000 +0000 @@ -33,11 +33,13 @@ case '/1': return setTimeout(function() { req.socket.destroy(); + server.emit('requestDone'); }); case '/2': return process.nextTick(function() { res.destroy(); + server.emit('requestDone'); }); // in one case, actually send a response in 2 chunks @@ -45,18 +47,19 @@ res.write('hello '); return setTimeout(function() { res.end('world!'); + server.emit('requestDone'); }); default: - return res.destroy(); + res.destroy(); + server.emit('requestDone'); } }); // Make a bunch of requests pipelined on the same socket -function generator() { - var reqs = [ 3, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4 ]; - return reqs.map(function(r) { +function generator(seeds) { + return seeds.map(function(r) { return 'GET /' + r + ' HTTP/1.1\r\n' + 'Host: localhost:' + common.PORT + '\r\n' + '\r\n' + @@ -66,13 +69,18 @@ server.listen(common.PORT, function() { + var seeds = [ 3, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4 ]; var client = net.connect({ port: common.PORT }); + var done = 0; + server.on('requestDone', function() { + if (++done == seeds.length) { + server.close(); + } + }); // immediately write the pipelined requests. // Some of these will not have a socket to destroy! - client.write(generator(), function() { - server.close(); - }); + client.write(generator(seeds)); }); process.on('exit', function(c) { diff -Nru nodejs-0.11.10/test/simple/test-http-many-ended-pipelines.js nodejs-0.11.11/test/simple/test-http-many-ended-pipelines.js --- nodejs-0.11.10/test/simple/test-http-many-ended-pipelines.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-http-many-ended-pipelines.js 2014-01-29 01:29:56.000000000 +0000 @@ -32,23 +32,25 @@ var http = require('http'); var net = require('net'); +var numRequests = 20; +var done = 0; + var server = http.createServer(function(req, res) { res.end('ok'); // Oh no! The connection died! req.socket.destroy(); + if (++done == numRequests) + server.close(); }); server.listen(common.PORT); var client = net.connect({ port: common.PORT, allowHalfOpen: true }); -for (var i = 0; i < 20; i++) { +for (var i = 0; i < numRequests; i++) { client.write('GET / HTTP/1.1\r\n' + 'Host: some.host.name\r\n'+ '\r\n\r\n'); } client.end(); -client.on('connect', function() { - server.close(); -}); client.pipe(process.stdout); diff -Nru nodejs-0.11.10/test/simple/test-http-server-multiheaders2.js nodejs-0.11.11/test/simple/test-http-server-multiheaders2.js --- nodejs-0.11.10/test/simple/test-http-server-multiheaders2.js 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-http-server-multiheaders2.js 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,108 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// Verify that the HTTP server implementation handles multiple instances +// of the same header as per RFC2616: joining the handful of fields by ', ' +// that support it, and dropping duplicates for other fields. + +var common = require('../common'); +var assert = require('assert'); +var http = require('http'); + +var multipleAllowed = [ + 'Accept', + 'Accept-Charset', + 'Accept-Encoding', + 'Accept-Language', + 'Connection', + 'Cookie', + 'DAV', // GH-2750 + 'Pragma', // GH-715 + 'Link', // GH-1187 + 'WWW-Authenticate', // GH-1083 + 'Proxy-Authenticate', // GH-4052 + 'Sec-Websocket-Extensions', // GH-2764 + 'Sec-Websocket-Protocol', // GH-2764 + 'Via', // GH-6660 + + // not a special case, just making sure it's parsed correctly + 'X-Forwarded-For', + + // make sure that unspecified headers is treated as multiple + 'Some-Random-Header', + 'X-Some-Random-Header', +]; + +var multipleForbidden = [ + 'Content-Type', + 'User-Agent', + 'Referer', + 'Host', + 'Authorization', + 'Proxy-Authorization', + 'If-Modified-Since', + 'If-Unmodified-Since', + 'From', + 'Location', + 'Max-Forwards', + + // special case, tested differently + //'Content-Length', +]; + +var srv = http.createServer(function(req, res) { + multipleForbidden.forEach(function(header) { + assert.equal(req.headers[header.toLowerCase()], 'foo', 'header parsed incorrectly: ' + header); + }); + multipleAllowed.forEach(function(header) { + assert.equal(req.headers[header.toLowerCase()], 'foo, bar', 'header parsed incorrectly: ' + header); + }); + assert.equal(req.headers['content-length'], 0); + + res.writeHead(200, {'Content-Type' : 'text/plain'}); + res.end('EOF'); + + srv.close(); +}); + +function makeHeader(value) { + return function(header) { + return [header, value]; + } +} + +var headers = [] + .concat(multipleAllowed.map(makeHeader('foo'))) + .concat(multipleForbidden.map(makeHeader('foo'))) + .concat(multipleAllowed.map(makeHeader('bar'))) + .concat(multipleForbidden.map(makeHeader('bar'))) + // content-length is a special case since node.js + // is dropping connetions with non-numeric headers + .concat([['content-length', 0], ['content-length', 123]]); + +srv.listen(common.PORT, function() { + http.get({ + host: 'localhost', + port: common.PORT, + path: '/', + headers: headers, + }); +}); diff -Nru nodejs-0.11.10/test/simple/test-https-foafssl.js nodejs-0.11.11/test/simple/test-https-foafssl.js --- nodejs-0.11.10/test/simple/test-https-foafssl.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-https-foafssl.js 2014-01-29 01:29:56.000000000 +0000 @@ -19,12 +19,13 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. -if (!process.versions.openssl) { - console.error('Skipping because node compiled without OpenSSL.'); +var common = require('../common'); + +if (!common.opensslCli) { + console.error('Skipping because node compiled without OpenSSL CLI.'); process.exit(0); } -var common = require('../common'); var assert = require('assert'); var join = require('path').join; diff -Nru nodejs-0.11.10/test/simple/test-net-GH-5504.js nodejs-0.11.11/test/simple/test-net-GH-5504.js --- nodejs-0.11.10/test/simple/test-net-GH-5504.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-net-GH-5504.js 2014-01-29 01:29:56.000000000 +0000 @@ -93,7 +93,7 @@ setTimeout(function() { throw new Error('hang'); }); - }, 1000).unref(); + }, 4000).unref(); var s = spawn(node, [__filename, 'server'], opt); var c; diff -Nru nodejs-0.11.10/test/simple/test-net-listen-fd0.js nodejs-0.11.11/test/simple/test-net-listen-fd0.js --- nodejs-0.11.10/test/simple/test-net-listen-fd0.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-net-listen-fd0.js 2014-01-29 01:29:56.000000000 +0000 @@ -26,11 +26,15 @@ var gotError = false; process.on('exit', function() { - assert.equal(gotError, true); + assert(gotError instanceof Error); }); // this should fail with an async EINVAL error, not throw an exception net.createServer(assert.fail).listen({fd:0}).on('error', function(e) { - assert.equal(e.code, 'EINVAL'); - gotError = true; + switch(e.code) { + case 'EINVAL': + case 'ENOTSOCK': + gotError = e; + break + } }); diff -Nru nodejs-0.11.10/test/simple/test-net-reconnect.js nodejs-0.11.11/test/simple/test-net-reconnect.js --- nodejs-0.11.10/test/simple/test-net-reconnect.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-net-reconnect.js 2014-01-29 01:29:56.000000000 +0000 @@ -27,6 +27,7 @@ var N = 50; var c = 0; var client_recv_count = 0; +var client_end_count = 0; var disconnect_count = 0; var server = net.createServer(function(socket) { @@ -67,6 +68,7 @@ client.on('end', function() { console.error('CLIENT end'); + client_end_count++; }); client.on('close', function(had_error) { @@ -82,5 +84,6 @@ process.on('exit', function() { assert.equal(N + 1, disconnect_count); assert.equal(N + 1, client_recv_count); + assert.equal(N + 1, client_end_count); }); diff -Nru nodejs-0.11.10/test/simple/test-net-stream.js nodejs-0.11.11/test/simple/test-net-stream.js --- nodejs-0.11.10/test/simple/test-net-stream.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-net-stream.js 2014-01-29 01:29:56.000000000 +0000 @@ -37,3 +37,36 @@ assert.equal(9, s.server.connections); s.destroy(); assert.equal(9, s.server.connections); + +var SIZE = 2E6; +var N = 10; +var buf = new Buffer(SIZE); +buf.fill(0x61); // 'a' + +var server = net.createServer(function(socket) { + socket.setNoDelay(); + + socket.on('error', function(err) { + socket.destroy(); + }).on('close', function() { + server.close(); + }) + + for (var i = 0; i < N; ++i) { + socket.write(buf, function() { }); + } + socket.end(); + +}).listen(common.PORT, function() { + var conn = net.connect(common.PORT); + conn.on('data', function(buf) { + conn.pause(); + setTimeout(function() { + conn.destroy(); + }, 20); + }); + }); + +process.on('exit', function() { + assert.equal(server.connections, 0); +}); diff -Nru nodejs-0.11.10/test/simple/test-next-tick-error-spin.js nodejs-0.11.11/test/simple/test-next-tick-error-spin.js --- nodejs-0.11.10/test/simple/test-next-tick-error-spin.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-next-tick-error-spin.js 2014-01-29 01:29:56.000000000 +0000 @@ -29,7 +29,7 @@ }); var timer = setTimeout(function() { throw new Error('child is hung'); - }, 500); + }, 3000); child.on('exit', function(code) { console.error('ok'); assert(!code); diff -Nru nodejs-0.11.10/test/simple/test-stdin-from-file.js nodejs-0.11.11/test/simple/test-stdin-from-file.js --- nodejs-0.11.10/test/simple/test-stdin-from-file.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-stdin-from-file.js 2014-01-29 01:29:56.000000000 +0000 @@ -28,7 +28,7 @@ var childProccess = require('child_process'); var fs = require('fs'); -var stdoutScript = join(common.fixturesDir, 'echo.js'); +var stdoutScript = join(common.fixturesDir, 'echo-close-check.js'); var tmpFile = join(common.fixturesDir, 'stdin.txt'); var cmd = '"' + process.argv[0] + '" "' + stdoutScript + '" < "' + diff -Nru nodejs-0.11.10/test/simple/test-stream-big-packet.js nodejs-0.11.11/test/simple/test-stream-big-packet.js --- nodejs-0.11.10/test/simple/test-stream-big-packet.js 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-stream-big-packet.js 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,73 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var common = require('../common'); +var assert = require('assert'); +var util = require('util'); +var stream = require('stream'); + +var passed = false; + +function PassThrough () { + stream.Transform.call(this); +}; +util.inherits(PassThrough, stream.Transform); +PassThrough.prototype._transform = function (chunk, encoding, done) { + this.push(chunk); + done(); +}; + +function TestStream () { + stream.Transform.call(this); +}; +util.inherits(TestStream, stream.Transform); +TestStream.prototype._transform = function (chunk, encoding, done) { + if (!passed) { + // Char 'a' only exists in the last write + passed = chunk.toString().indexOf('a') >= 0; + } + done(); +}; + +var s1 = new PassThrough(); +var s2 = new PassThrough(); +var s3 = new TestStream(); +s1.pipe(s3); +// Don't let s2 auto close which may close s3 +s2.pipe(s3, {end: false}); + +// We must write a buffer larger than highWaterMark +var big = new Buffer(s1._writableState.highWaterMark + 1); +big.fill('x'); + +// Since big is larger than highWaterMark, it will be buffered internally. +assert(!s1.write(big)); +// 'tiny' is small enough to pass through internal buffer. +assert(s2.write('tiny')); + +// Write some small data in next IO loop, which will never be written to s3 +// Because 'drain' event is not emitted from s1 and s1 is still paused +setImmediate(s1.write.bind(s1), 'later'); + +// Assert after two IO loops when all operations have been done. +process.on('exit', function () { + assert(passed, 'Large buffer is not handled properly by Writable Stream'); +}); diff -Nru nodejs-0.11.10/test/simple/test-tcp-wrap-listen.js nodejs-0.11.11/test/simple/test-tcp-wrap-listen.js --- nodejs-0.11.10/test/simple/test-tcp-wrap-listen.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-tcp-wrap-listen.js 2014-01-29 01:29:56.000000000 +0000 @@ -55,7 +55,7 @@ assert.equal(0, client.writeQueueSize); - var req = {}; + var req = { async: false }; var err = client.writeBuffer(req, buffer); assert.equal(err, 0); client.pendingWrites.push(req); @@ -64,7 +64,12 @@ // 11 bytes should flush assert.equal(0, client.writeQueueSize); - req.oncomplete = function(status, client_, req_) { + if (req.async && client.writeQueueSize != 0) + req.oncomplete = done; + else + process.nextTick(done.bind(null, 0, client, req)); + + function done(status, client_, req_) { assert.equal(req, client.pendingWrites.shift()); // Check parameters. diff -Nru nodejs-0.11.10/test/simple/test-tls-cert-regression.js nodejs-0.11.11/test/simple/test-tls-cert-regression.js --- nodejs-0.11.10/test/simple/test-tls-cert-regression.js 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-tls-cert-regression.js 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,71 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +if (!process.versions.openssl) { + console.error('Skipping because node compiled without OpenSSL.'); + process.exit(0); +} + +var tls = require('tls'); + +var assert = require('assert'); +var common = require('../common'); + +var cert = '-----BEGIN CERTIFICATE-----\n' + + 'MIIBfjCCASgCCQDmmNjAojbDQjANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJB\n' + + 'VTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0\n' + + 'cyBQdHkgTHRkMCAXDTE0MDExNjE3NTMxM1oYDzIyODcxMDMxMTc1MzEzWjBFMQsw\n' + + 'CQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJu\n' + + 'ZXQgV2lkZ2l0cyBQdHkgTHRkMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAPKwlfMX\n' + + '6HGZIt1xm7fna72eWcOYfUfSxSugghvqYgJt2Oi3lH+wsU1O9FzRIVmpeIjDXhbp\n' + + 'Mjsa1HtzSiccPXsCAwEAATANBgkqhkiG9w0BAQUFAANBAHOoKy0NkyfiYH7Ne5ka\n' + + 'uvCyndyeB4d24FlfqEUlkfaWCZlNKRaV9YhLDiEg3BcIreFo4brtKQfZzTRs0GVm\n' + + 'KHg=\n' + + '-----END CERTIFICATE-----'; +var key = '-----BEGIN RSA PRIVATE KEY-----\n' + + 'MIIBPQIBAAJBAPKwlfMX6HGZIt1xm7fna72eWcOYfUfSxSugghvqYgJt2Oi3lH+w\n' + + 'sU1O9FzRIVmpeIjDXhbpMjsa1HtzSiccPXsCAwEAAQJBAM4uU9aJE0OfdE1p/X+K\n' + + 'LrCT3XMdFCJ24GgmHyOURtwDy18upQJecDVdcZp16fjtOPmaW95GoYRyifB3R4I5\n' + + 'RxECIQD7jRM9slCSVV8xp9kOJQNpHjhRQYVGBn+pyllS2sb+RQIhAPb7Y+BIccri\n' + + 'NWnuhwCW8hA7Fkj/kaBdAwyW7L3Tvui/AiEAiqLCovMecre4Yi6GcsQ1b/6mvSmm\n' + + 'IOS+AT6zIfXPTB0CIQCJKGR3ymN/Qw5crL1GQ41cHCQtF9ickOq/lBUW+j976wIh\n' + + 'AOaJnkQrmurlRdePX6LvN/LgGAQoxwovfjcOYNnZsIVY\n' + + '-----END RSA PRIVATE KEY-----'; + +function test(cert, key, cb) { + var server = tls.createServer({ + cert: cert, + key: key + }).listen(common.PORT, function() { + server.close(cb); + }); +} + +var completed = false; +test(cert, key, function() { + test(new Buffer(cert), new Buffer(key), function() { + completed = true; + }); +}); + +process.on('exit', function() { + assert(completed); +}); diff -Nru nodejs-0.11.10/test/simple/test-tls-client-default-ciphers.js nodejs-0.11.11/test/simple/test-tls-client-default-ciphers.js --- nodejs-0.11.10/test/simple/test-tls-client-default-ciphers.js 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-tls-client-default-ciphers.js 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,34 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var crypto = require('crypto'); +var assert = require('assert'); +var tls = require('tls'); + +function test1() { + var ciphers = ''; + crypto.createCredentials = function(options) { + ciphers = options.ciphers + } + tls.connect(443); + assert.equal(ciphers, tls.DEFAULT_CIPHERS); +} +test1(); diff -Nru nodejs-0.11.10/test/simple/test-tls-delayed-attach.js nodejs-0.11.11/test/simple/test-tls-delayed-attach.js --- nodejs-0.11.10/test/simple/test-tls-delayed-attach.js 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-tls-delayed-attach.js 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,72 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +if (!process.versions.openssl) { + console.error('Skipping because node compiled without OpenSSL.'); + process.exit(0); +} + +var assert = require('assert'); +var fs = require('fs'); +var net = require('net'); +var tls = require('tls'); +var crypto = require('crypto'); + +var common = require('../common'); + +var sent = 'hello world'; +var received = ''; +var ended = 0; + +var options = { + key: fs.readFileSync(common.fixturesDir + '/keys/agent1-key.pem'), + cert: fs.readFileSync(common.fixturesDir + '/keys/agent1-cert.pem') +}; + +var server = net.createServer(function(c) { + setTimeout(function() { + var s = new tls.TLSSocket(c, { + isServer: true, + credentials: crypto.createCredentials(options) + }); + + s.on('data', function(chunk) { + received += chunk; + }); + + s.on('end', function() { + ended++; + server.close(); + s.destroy(); + }); + }, 200); +}).listen(common.PORT, function() { + var c = tls.connect(common.PORT, { + rejectUnauthorized: false + }, function() { + c.end(sent); + }); +}); + +process.on('exit', function() { + assert.equal(received, sent); + assert.equal(ended, 1); +}); diff -Nru nodejs-0.11.10/test/simple/test-tls-ecdh-disable.js nodejs-0.11.11/test/simple/test-tls-ecdh-disable.js --- nodejs-0.11.10/test/simple/test-tls-ecdh-disable.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-tls-ecdh-disable.js 2014-01-29 01:29:56.000000000 +0000 @@ -20,6 +20,12 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. var common = require('../common'); + +if (!common.opensslCli) { + console.error('Skipping because node compiled without OpenSSL CLI.'); + process.exit(0); +} + var assert = require('assert'); var exec = require('child_process').exec; var tls = require('tls'); diff -Nru nodejs-0.11.10/test/simple/test-tls-ecdh.js nodejs-0.11.11/test/simple/test-tls-ecdh.js --- nodejs-0.11.10/test/simple/test-tls-ecdh.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-tls-ecdh.js 2014-01-29 01:29:56.000000000 +0000 @@ -20,6 +20,12 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. var common = require('../common'); + +if (!common.opensslCli) { + console.error('Skipping because node compiled without OpenSSL CLI.'); + process.exit(0); +} + var assert = require('assert'); var exec = require('child_process').exec; var tls = require('tls'); diff -Nru nodejs-0.11.10/test/simple/test-tls-econnreset.js nodejs-0.11.11/test/simple/test-tls-econnreset.js --- nodejs-0.11.10/test/simple/test-tls-econnreset.js 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-tls-econnreset.js 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,94 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +if (!process.versions.openssl) { + console.error('Skipping because node compiled without OpenSSL.'); + process.exit(0); +} + +var common = require('../common'); +var assert = require('assert'); +var tls = require('tls'); + +var cacert = '-----BEGIN CERTIFICATE-----\n' + + 'MIIBxTCCAX8CAnXnMA0GCSqGSIb3DQEBBQUAMH0xCzAJBgNVBAYTAlVTMQswCQYD\n' + + 'VQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEZMBcGA1UEChMQU3Ryb25n\n' + + 'TG9vcCwgSW5jLjESMBAGA1UECxMJU3Ryb25nT3BzMRowGAYDVQQDExFjYS5zdHJv\n' + + 'bmdsb29wLmNvbTAeFw0xNDAxMTcyMjE1MDdaFw00MTA2MDMyMjE1MDdaMH0xCzAJ\n' + + 'BgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEZ\n' + + 'MBcGA1UEChMQU3Ryb25nTG9vcCwgSW5jLjESMBAGA1UECxMJU3Ryb25nT3BzMRow\n' + + 'GAYDVQQDExFjYS5zdHJvbmdsb29wLmNvbTBMMA0GCSqGSIb3DQEBAQUAAzsAMDgC\n' + + 'MQDKbQ6rIR5t1q1v4Ha36jrq0IkyUohy9EYNvLnXUly1PGqxby0ILlAVJ8JawpY9\n' + + 'AVkCAwEAATANBgkqhkiG9w0BAQUFAAMxALA1uS4CqQXRSAyYTfio5oyLGz71a+NM\n' + + '+0AFLBwh5AQjhGd0FcenU4OfHxyDEOJT/Q==\n' + + '-----END CERTIFICATE-----\n'; + +var cert = '-----BEGIN CERTIFICATE-----\n' + + 'MIIBfDCCATYCAgQaMA0GCSqGSIb3DQEBBQUAMH0xCzAJBgNVBAYTAlVTMQswCQYD\n' + + 'VQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEZMBcGA1UEChMQU3Ryb25n\n' + + 'TG9vcCwgSW5jLjESMBAGA1UECxMJU3Ryb25nT3BzMRowGAYDVQQDExFjYS5zdHJv\n' + + 'bmdsb29wLmNvbTAeFw0xNDAxMTcyMjE1MDdaFw00MTA2MDMyMjE1MDdaMBkxFzAV\n' + + 'BgNVBAMTDnN0cm9uZ2xvb3AuY29tMEwwDQYJKoZIhvcNAQEBBQADOwAwOAIxAMfk\n' + + 'I0LWU15pPUwIQNMnRVhhOibi0TQmAau8FBtgwEfGK01WpfGUaJr1a41K8Uq7xwID\n' + + 'AQABoxkwFzAVBgNVHREEDjAMhwQAAAAAhwR/AAABMA0GCSqGSIb3DQEBBQUAAzEA\n' + + 'cGpYrhkrb7mIh9DNhV0qp7pGjqBzlHqB7KQXw2luLDp//6dyHBMexDCQznkhZKRU\n' + + '-----END CERTIFICATE-----\n'; + +var key = '-----BEGIN RSA PRIVATE KEY-----\n' + + 'MIH0AgEAAjEAx+QjQtZTXmk9TAhA0ydFWGE6JuLRNCYBq7wUG2DAR8YrTVal8ZRo\n' + + 'mvVrjUrxSrvHAgMBAAECMBCGccvSwC2r8Z9Zh1JtirQVxaL1WWpAQfmVwLe0bAgg\n' + + '/JWMU/6hS36TsYyZMxwswQIZAPTAfht/zDLb7Hwgu2twsS1Ra9w/yyvtlwIZANET\n' + + '26votwJAHK1yUrZGA5nnp5qcmQ/JUQIZAII5YV/UUZvF9D/fUplJ7puENPWNY9bN\n' + + 'pQIZAMMwxuS3XiO7two2sQF6W+JTYyX1DPCwAQIZAOYg1TvEGT38k8e8jygv8E8w\n' + + 'YqrWTeQFNQ==\n' + + '-----END RSA PRIVATE KEY-----\n'; + +var ca = [ cert, cacert ]; + +var clientError = null; +var connectError = null; + +var server = tls.createServer({ ca: ca, cert: cert, key: key }, function(conn) { + throw 'unreachable'; +}).on('clientError', function(err, conn) { + assert(!clientError && conn); + clientError = err; +}).listen(common.PORT, function() { + var options = { + ciphers: 'AES128-GCM-SHA256', + port: common.PORT, + ca: ca + }; + tls.connect(options).on('error', function(err) { + assert(!connectError); + + connectError = err; + this.destroy(); + server.close(); + }).write('123'); +}); + +process.on('exit', function() { + assert(clientError); + assert(connectError); + assert(/socket hang up/.test(clientError.message)); + assert(/ECONNRESET/.test(clientError.code)); +}); diff -Nru nodejs-0.11.10/test/simple/test-tls-friendly-error-message.js nodejs-0.11.11/test/simple/test-tls-friendly-error-message.js --- nodejs-0.11.10/test/simple/test-tls-friendly-error-message.js 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-tls-friendly-error-message.js 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,45 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +if (!process.versions.openssl) { + console.error('Skipping because node compiled without OpenSSL.'); + process.exit(0); +} + +var common = require('../common'); +var assert = require('assert'); +var fs = require('fs'); +var tls = require('tls'); + +var key = fs.readFileSync(common.fixturesDir + '/keys/agent1-key.pem'); +var cert = fs.readFileSync(common.fixturesDir + '/keys/agent1-cert.pem'); + +tls.createServer({ key: key, cert: cert }, function(conn) { + conn.end(); + this.close(); +}).listen(0, function() { + var options = { port: this.address().port, rejectUnauthorized: true }; + tls.connect(options).on('error', common.mustCall(function(err) { + assert.equal(err.code, 'UNABLE_TO_VERIFY_LEAF_SIGNATURE'); + assert.equal(err.message, 'unable to verify the first certificate'); + this.destroy(); + })); +}); diff -Nru nodejs-0.11.10/test/simple/test-tls-honorcipherorder.js nodejs-0.11.11/test/simple/test-tls-honorcipherorder.js --- nodejs-0.11.10/test/simple/test-tls-honorcipherorder.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-tls-honorcipherorder.js 2014-01-29 01:29:56.000000000 +0000 @@ -30,7 +30,7 @@ var localhost = '127.0.0.1'; process.on('exit', function() { - assert.equal(nconns, 4); + assert.equal(nconns, 5); }); function test(honorCipherOrder, clientCipher, expectedCipher, cb) { @@ -38,7 +38,7 @@ secureProtocol: SSL_Method, key: fs.readFileSync(common.fixturesDir + '/keys/agent2-key.pem'), cert: fs.readFileSync(common.fixturesDir + '/keys/agent2-cert.pem'), - ciphers: 'AES256-SHA:RC4-SHA:DES-CBC-SHA', + ciphers: 'DES-CBC-SHA:AES256-SHA:RC4-SHA', honorCipherOrder: !!honorCipherOrder }; @@ -67,23 +67,30 @@ function test1() { // Client has the preference of cipher suites by default - test(false, 'DES-CBC-SHA:RC4-SHA:AES256-SHA','DES-CBC-SHA', test2); + test(false, 'AES256-SHA:DES-CBC-SHA:RC4-SHA','AES256-SHA', test2); } function test2() { - // Server has the preference of cipher suites where AES256-SHA is in + // Server has the preference of cipher suites where DES-CBC-SHA is in // the first. - test(true, 'DES-CBC-SHA:RC4-SHA:AES256-SHA', 'AES256-SHA', test3); + test(true, 'AES256-SHA:DES-CBC-SHA:RC4-SHA', 'DES-CBC-SHA', test3); } function test3() { // Server has the preference of cipher suites. RC4-SHA is given // higher priority over DES-CBC-SHA among client cipher suites. - test(true, 'DES-CBC-SHA:RC4-SHA', 'RC4-SHA', test4); + test(true, 'RC4-SHA:AES256-SHA', 'AES256-SHA', test4); } function test4() { // As client has only one cipher, server has no choice in regardless // of honorCipherOrder. - test(true, 'DES-CBC-SHA', 'DES-CBC-SHA'); + test(true, 'RC4-SHA', 'RC4-SHA', test5); +} + +function test5() { + // Client did not explicitly set ciphers. Ensure that client defaults to + // sane ciphers. Even though server gives top priority to DES-CBC-SHA + // it should not be negotiated because it's not in default client ciphers. + test(true, null, 'AES256-SHA'); } diff -Nru nodejs-0.11.10/test/simple/test-tls-max-send-fragment.js nodejs-0.11.11/test/simple/test-tls-max-send-fragment.js --- nodejs-0.11.10/test/simple/test-tls-max-send-fragment.js 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-tls-max-send-fragment.js 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,72 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +if (!process.versions.openssl) { + console.error('Skipping because node compiled without OpenSSL.'); + process.exit(0); +} + +var assert = require('assert'); +var fs = require('fs'); +var net = require('net'); +var tls = require('tls'); + +var common = require('../common'); + +var buf = new Buffer(10000); +var received = 0; +var ended = 0; +var maxChunk = 768; + +var server = tls.createServer({ + key: fs.readFileSync(common.fixturesDir + '/keys/agent1-key.pem'), + cert: fs.readFileSync(common.fixturesDir + '/keys/agent1-cert.pem') +}, function(c) { + // Lower and upper limits + assert(!c.setMaxSendFragment(511)); + assert(!c.setMaxSendFragment(16385)); + + // Correct fragment size + assert(c.setMaxSendFragment(maxChunk)); + + c.end(buf); +}).listen(common.PORT, function() { + var c = tls.connect(common.PORT, { + rejectUnauthorized: false + }, function() { + c.on('data', function(chunk) { + assert(chunk.length <= maxChunk); + received += chunk.length; + }); + + // Ensure that we receive 'end' event anyway + c.on('end', function() { + ended++; + c.destroy(); + server.close(); + }); + }); +}); + +process.on('exit', function() { + assert.equal(ended, 1); + assert.equal(received, buf.length); +}); diff -Nru nodejs-0.11.10/test/simple/test-tls-no-cert-required.js nodejs-0.11.11/test/simple/test-tls-no-cert-required.js --- nodejs-0.11.10/test/simple/test-tls-no-cert-required.js 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-tls-no-cert-required.js 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,35 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +if (!process.versions.openssl) { + console.error('Skipping because node compiled without OpenSSL.'); + process.exit(0); +} + +var common = require('../common'); +var tls = require('tls'); + +// Omitting the cert or pfx option to tls.createServer() should not throw. +// AECDH-NULL-SHA is a no-authentication/no-encryption cipher and hence +// doesn't need a certificate. +tls.createServer({ ciphers: 'AECDH-NULL-SHA' }).listen(0, function() { + this.close(); +}); diff -Nru nodejs-0.11.10/test/simple/test-tls-no-rsa-key.js nodejs-0.11.11/test/simple/test-tls-no-rsa-key.js --- nodejs-0.11.10/test/simple/test-tls-no-rsa-key.js 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-tls-no-rsa-key.js 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,55 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +if (!process.versions.openssl) { + console.error('Skipping because node compiled without OpenSSL.'); + process.exit(0); +} + +var common = require('../common'); +var assert = require('assert'); +var tls = require('tls'); +var fs = require('fs'); +var fs = require('fs'); + +var options = { + key: fs.readFileSync(common.fixturesDir + '/keys/ec-key.pem'), + cert: fs.readFileSync(common.fixturesDir + '/keys/ec-cert.pem') +}; + +var cert = null; + +var server = tls.createServer(options, function(conn) { + conn.end('ok'); +}).listen(common.PORT, function() { + var c = tls.connect(common.PORT, { + rejectUnauthorized: false + }, function() { + cert = c.getPeerCertificate(); + c.destroy(); + server.close(); + }); +}); + +process.on('exit', function() { + assert(cert); + assert.equal(cert.subject.C, 'US'); +}); diff -Nru nodejs-0.11.10/test/simple/test-tls-securepair-server.js nodejs-0.11.11/test/simple/test-tls-securepair-server.js --- nodejs-0.11.10/test/simple/test-tls-securepair-server.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-tls-securepair-server.js 2014-01-29 01:29:56.000000000 +0000 @@ -19,13 +19,13 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. -if (!process.versions.openssl) { - console.error('Skipping because node compiled without OpenSSL.'); +var common = require('../common'); + +if (!common.opensslCli) { + console.error('Skipping because node compiled without OpenSSL CLI.'); process.exit(0); } - -var common = require('../common'); var assert = require('assert'); var join = require('path').join; diff -Nru nodejs-0.11.10/test/simple/test-tls-server-missing-options.js nodejs-0.11.11/test/simple/test-tls-server-missing-options.js --- nodejs-0.11.10/test/simple/test-tls-server-missing-options.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-tls-server-missing-options.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -if (!process.versions.openssl) { - console.error('Skipping because node compiled without OpenSSL.'); - process.exit(0); -} - -var common = require('../common'); -var assert = require('assert'); -var https = require('https'); -var tls = require('tls'); - -assert.throws(function() { - tls.createServer({ /* empty */}).listen(0); -}, /missing.+certificate/i); - -assert.throws(function() { - https.createServer({ /* empty */}).listen(0); -}, /missing.+certificate/i); diff -Nru nodejs-0.11.10/test/simple/test-tls-server-verify.js nodejs-0.11.11/test/simple/test-tls-server-verify.js --- nodejs-0.11.10/test/simple/test-tls-server-verify.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-tls-server-verify.js 2014-01-29 01:29:56.000000000 +0000 @@ -19,11 +19,10 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. +var common = require('../common'); - - -if (!process.versions.openssl) { - console.error('Skipping because node compiled without OpenSSL.'); +if (!common.opensslCli) { + console.error('Skipping because node compiled without OpenSSL CLI.'); process.exit(0); } @@ -121,7 +120,6 @@ ]; -var common = require('../common'); var constants = require('constants'); var assert = require('assert'); var fs = require('fs'); diff -Nru nodejs-0.11.10/test/simple/test-tls-session-cache.js nodejs-0.11.11/test/simple/test-tls-session-cache.js --- nodejs-0.11.10/test/simple/test-tls-session-cache.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-tls-session-cache.js 2014-01-29 01:29:56.000000000 +0000 @@ -19,8 +19,10 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. -if (!process.versions.openssl) { - console.error('Skipping because node compiled without OpenSSL.'); +var common = require('../common'); + +if (!common.opensslCli) { + console.error('Skipping because node compiled without OpenSSL CLI.'); process.exit(0); } @@ -31,7 +33,6 @@ }); function doTest(testOptions, callback) { - var common = require('../common'); var assert = require('assert'); var tls = require('tls'); var fs = require('fs'); diff -Nru nodejs-0.11.10/test/simple/test-tls-set-ciphers.js nodejs-0.11.11/test/simple/test-tls-set-ciphers.js --- nodejs-0.11.10/test/simple/test-tls-set-ciphers.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-tls-set-ciphers.js 2014-01-29 01:29:56.000000000 +0000 @@ -20,6 +20,12 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. var common = require('../common'); + +if (!common.opensslCli) { + console.error('Skipping because node compiled without OpenSSL CLI.'); + process.exit(0); +} + var assert = require('assert'); var exec = require('child_process').exec; var tls = require('tls'); diff -Nru nodejs-0.11.10/test/simple/test-util-inspect.js nodejs-0.11.11/test/simple/test-util-inspect.js --- nodejs-0.11.10/test/simple/test-util-inspect.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/test-util-inspect.js 2014-01-29 01:29:56.000000000 +0000 @@ -110,6 +110,21 @@ var x = { inspect: util.inspect }; assert.ok(util.inspect(x).indexOf('inspect') != -1); +// util.inspect should not display the escaped value of a key. +var w = { + '\\': 1, + '\\\\': 2, + '\\\\\\': 3, + '\\\\\\\\': 4, +} + +var y = ['a', 'b', 'c']; +y['\\\\\\'] = 'd'; + +assert.ok(util.inspect(w), + '{ \'\\\': 1, \'\\\\\': 2, \'\\\\\\\': 3, \'\\\\\\\\\': 4 }'); +assert.ok(util.inspect(y), '[ \'a\', \'b\', \'c\', \'\\\\\\\': \'d\' ]'); + // util.inspect.styles and util.inspect.colors function test_color_style(style, input, implicit) { var color_name = util.inspect.styles[style]; diff -Nru nodejs-0.11.10/test/simple/testcfg.py nodejs-0.11.11/test/simple/testcfg.py --- nodejs-0.11.10/test/simple/testcfg.py 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/test/simple/testcfg.py 2014-01-29 01:29:56.000000000 +0000 @@ -1,132 +1,6 @@ -# Copyright 2008 the V8 project authors. All rights reserved. -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials provided -# with the distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import test -import os -import shutil -from shutil import rmtree -from os import mkdir -from glob import glob -from os.path import join, dirname, exists -import re - - -FLAGS_PATTERN = re.compile(r"//\s+Flags:(.*)") -FILES_PATTERN = re.compile(r"//\s+Files:(.*)") - - -class SimpleTestCase(test.TestCase): - - def __init__(self, path, file, mode, context, config): - super(SimpleTestCase, self).__init__(context, path, mode) - self.file = file - self.config = config - self.mode = mode - self.tmpdir = join(dirname(self.config.root), 'tmp') - - def AfterRun(self, result): - # delete the whole tmp dir - try: - rmtree(self.tmpdir) - except: - pass - # make it again. - try: - mkdir(self.tmpdir) - except: - pass - - def BeforeRun(self): - # delete the whole tmp dir - try: - rmtree(self.tmpdir) - except: - pass - # make it again. - # intermittently fails on win32, so keep trying - while not os.path.exists(self.tmpdir): - try: - mkdir(self.tmpdir) - except: - pass - - def GetLabel(self): - return "%s %s" % (self.mode, self.GetName()) - - def GetName(self): - return self.path[-1] - - def GetCommand(self): - result = [self.config.context.GetVm(self.mode)] - source = open(self.file).read() - flags_match = FLAGS_PATTERN.search(source) - if flags_match: - result += flags_match.group(1).strip().split() - files_match = FILES_PATTERN.search(source); - additional_files = [] - if files_match: - additional_files += files_match.group(1).strip().split() - for a_file in additional_files: - result.append(join(dirname(self.config.root), '..', a_file)) - result += [self.file] - return result - - def GetSource(self): - return open(self.file).read() - - -class SimpleTestConfiguration(test.TestConfiguration): - - def __init__(self, context, root): - super(SimpleTestConfiguration, self).__init__(context, root) - - def Ls(self, path): - def SelectTest(name): - return name.startswith('test-') and name.endswith('.js') - return [f[:-3] for f in os.listdir(path) if SelectTest(f)] - - def ListTests(self, current_path, path, mode): - all_tests = [current_path + [t] for t in self.Ls(join(self.root))] - result = [] - for test in all_tests: - if self.Contains(path, test): - file_path = join(self.root, reduce(join, test[1:], "") + ".js") - result.append(SimpleTestCase(test, file_path, mode, self.context, self)) - return result - - def GetBuildRequirements(self): - return ['sample', 'sample=shell'] - - def GetTestStatus(self, sections, defs): - status_file = join(self.root, 'simple.status') - if exists(status_file): - test.ReadConfigurationInto(status_file, sections, defs) - - +import sys, os +sys.path.append(os.path.join(os.path.dirname(__file__), '..')) +import testpy def GetConfiguration(context, root): - return SimpleTestConfiguration(context, root) + return testpy.SimpleTestConfiguration(context, root, 'simple') diff -Nru nodejs-0.11.10/test/testpy/__init__.py nodejs-0.11.11/test/testpy/__init__.py --- nodejs-0.11.10/test/testpy/__init__.py 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/test/testpy/__init__.py 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,161 @@ +# Copyright 2008 the V8 project authors. All rights reserved. +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import test +import os +import shutil +from shutil import rmtree +from os import mkdir +from glob import glob +from os.path import join, dirname, exists +import re + + +FLAGS_PATTERN = re.compile(r"//\s+Flags:(.*)") +FILES_PATTERN = re.compile(r"//\s+Files:(.*)") + + +class SimpleTestCase(test.TestCase): + + def __init__(self, path, file, mode, context, config, additional=[]): + super(SimpleTestCase, self).__init__(context, path, mode) + self.file = file + self.config = config + self.mode = mode + self.tmpdir = join(dirname(self.config.root), 'tmp') + self.additional_flags = additional + + def AfterRun(self, result): + # delete the whole tmp dir + try: + rmtree(self.tmpdir) + except: + pass + # make it again. + try: + mkdir(self.tmpdir) + except: + pass + + def BeforeRun(self): + # delete the whole tmp dir + try: + rmtree(self.tmpdir) + except: + pass + # make it again. + # intermittently fails on win32, so keep trying + while not os.path.exists(self.tmpdir): + try: + mkdir(self.tmpdir) + except: + pass + + def GetLabel(self): + return "%s %s" % (self.mode, self.GetName()) + + def GetName(self): + return self.path[-1] + + def GetCommand(self): + result = [self.config.context.GetVm(self.mode)] + source = open(self.file).read() + flags_match = FLAGS_PATTERN.search(source) + if flags_match: + result += flags_match.group(1).strip().split() + files_match = FILES_PATTERN.search(source); + additional_files = [] + if files_match: + additional_files += files_match.group(1).strip().split() + for a_file in additional_files: + result.append(join(dirname(self.config.root), '..', a_file)) + + if self.additional_flags: + result += self.additional_flags + + result += [self.file] + + return result + + def GetSource(self): + return open(self.file).read() + + +class SimpleTestConfiguration(test.TestConfiguration): + + def __init__(self, context, root, section, additional=[]): + super(SimpleTestConfiguration, self).__init__(context, root) + self.section = section + self.additional_flags = additional + + def Ls(self, path): + def SelectTest(name): + return name.startswith('test-') and name.endswith('.js') + return [f[:-3] for f in os.listdir(path) if SelectTest(f)] + + def ListTests(self, current_path, path, mode): + all_tests = [current_path + [t] for t in self.Ls(join(self.root))] + result = [] + for test in all_tests: + if self.Contains(path, test): + file_path = join(self.root, reduce(join, test[1:], "") + ".js") + result.append(SimpleTestCase(test, file_path, mode, self.context, self, + self.additional_flags)) + return result + + def GetBuildRequirements(self): + return ['sample', 'sample=shell'] + + def GetTestStatus(self, sections, defs): + status_file = join(self.root, '%s.status' % (self.section)) + if exists(status_file): + test.ReadConfigurationInto(status_file, sections, defs) + +class AddonTestConfiguration(SimpleTestConfiguration): + def __init__(self, context, root, section, additional=[]): + super(AddonTestConfiguration, self).__init__(context, root, section) + + def Ls(self, path): + def SelectTest(name): + return name.endswith('.js') + + result = [] + for subpath in os.listdir(path): + if os.path.isdir(join(path, subpath)): + for f in os.listdir(join(path, subpath)): + if SelectTest(f): + result.append([subpath, f[:-3]]) + return result + + def ListTests(self, current_path, path, mode): + all_tests = [current_path + t for t in self.Ls(join(self.root))] + result = [] + for test in all_tests: + if self.Contains(path, test): + file_path = join(self.root, reduce(join, test[1:], "") + ".js") + result.append(SimpleTestCase(test, file_path, mode, self.context, self)) + return result diff -Nru nodejs-0.11.10/tools/doc/addon-verify.js nodejs-0.11.11/tools/doc/addon-verify.js --- nodejs-0.11.10/tools/doc/addon-verify.js 1970-01-01 00:00:00.000000000 +0000 +++ nodejs-0.11.11/tools/doc/addon-verify.js 2014-01-29 01:29:56.000000000 +0000 @@ -0,0 +1,94 @@ +var fs = require('fs'); +var path = require('path'); +var marked = require('marked'); + +var doc = path.resolve(__dirname, '..', '..', 'doc', 'api', 'addons.markdown'); +var verifyDir = path.resolve(__dirname, '..', '..', 'test', 'addons'); + +var contents = fs.readFileSync(doc).toString(); + +var tokens = marked.lexer(contents, {}); +var files = null; +var id = 0; + +// Just to make sure that all examples will be processed +tokens.push({ type: 'heading' }); + +var oldDirs = fs.readdirSync(verifyDir); +oldDirs = oldDirs.filter(function(dir) { + return /^doc-/.test(dir); +}).map(function(dir) { + return path.resolve(verifyDir, dir); +}); + +for (var i = 0; i < tokens.length; i++) { + var token = tokens[i]; + if (token.type === 'heading') { + if (files && Object.keys(files).length !== 0) { + verifyFiles(files, function(err) { + if (err) + console.log(err); + else + console.log('done'); + }); + } + files = {}; + } else if (token.type === 'code') { + var match = token.text.match(/^\/\/\s+(.*\.(?:cc|h|js))[\r\n]/); + if (match === null) + continue; + files[match[1]] = token.text; + } +} + +function once(fn) { + var once = false; + return function() { + if (once) + return; + once = true; + fn.apply(this, arguments); + }; +} + +function verifyFiles(files, callback) { + var dir = path.resolve(verifyDir, 'doc-' + id++); + + files = Object.keys(files).map(function(name) { + return { + path: path.resolve(dir, name), + name: name, + content: files[name] + }; + }); + files.push({ + path: path.resolve(dir, 'binding.gyp'), + content: JSON.stringify({ + targets: [ + { + target_name: 'addon', + sources: files.map(function(file) { + return file.name; + }) + } + ] + }) + }); + + fs.mkdir(dir, function() { + // Ignore errors + + var waiting = files.length; + for (var i = 0; i < files.length; i++) + fs.writeFile(files[i].path, files[i].content, next); + + var done = once(callback); + function next(err) { + if (err) + return done(err); + + if (--waiting === 0) + done(); + } + }); +} diff -Nru nodejs-0.11.10/tools/doc/html.js nodejs-0.11.11/tools/doc/html.js --- nodejs-0.11.10/tools/doc/html.js 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/tools/doc/html.js 2014-01-29 01:29:56.000000000 +0000 @@ -122,9 +122,15 @@ function parseListItem(text) { - text = text.replace(/\{([^\}]+)\}/, '$1'); + var parts = text.split('`'); + var i; + + for (i = 0; i < parts.length; i += 2) { + parts[i] = parts[i].replace(/\{([^\}]+)\}/, '$1'); + } + //XXX maybe put more stuff here? - return text; + return parts.join('`'); } function parseAPIHeader(text) { diff -Nru nodejs-0.11.10/tools/gyp/AUTHORS nodejs-0.11.11/tools/gyp/AUTHORS --- nodejs-0.11.10/tools/gyp/AUTHORS 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/tools/gyp/AUTHORS 2014-01-29 01:29:56.000000000 +0000 @@ -7,4 +7,5 @@ Steven Knight Ryan Norton +David J. Sankel Eric N. Vander Weele diff -Nru nodejs-0.11.10/tools/gyp/pylib/gyp/MSVSVersion.py nodejs-0.11.11/tools/gyp/pylib/gyp/MSVSVersion.py --- nodejs-0.11.10/tools/gyp/pylib/gyp/MSVSVersion.py 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/tools/gyp/pylib/gyp/MSVSVersion.py 2014-01-29 01:29:56.000000000 +0000 @@ -96,9 +96,11 @@ else: assert target_arch == 'x64' arg = 'x86_amd64' - if (os.environ.get('PROCESSOR_ARCHITECTURE') == 'AMD64' or + # Use the 64-on-64 compiler if we're not using an express + # edition and we're running on a 64bit OS. + if self.short_name[-1] != 'e' and ( + os.environ.get('PROCESSOR_ARCHITECTURE') == 'AMD64' or os.environ.get('PROCESSOR_ARCHITEW6432') == 'AMD64'): - # Use the 64-on-64 compiler if we can. arg = 'amd64' return [os.path.normpath( os.path.join(self.path, 'VC/vcvarsall.bat')), arg] diff -Nru nodejs-0.11.10/tools/gyp/pylib/gyp/generator/make.py nodejs-0.11.11/tools/gyp/pylib/gyp/generator/make.py --- nodejs-0.11.10/tools/gyp/pylib/gyp/generator/make.py 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/tools/gyp/pylib/gyp/generator/make.py 2014-01-29 01:29:56.000000000 +0000 @@ -1951,7 +1951,8 @@ # We write the file in the base_path directory. output_file = os.path.join(options.depth, base_path, base_name) if options.generator_output: - output_file = os.path.join(options.generator_output, output_file) + output_file = os.path.join( + options.depth, options.generator_output, base_path, base_name) base_path = gyp.common.RelativePath(os.path.dirname(build_file), options.toplevel_dir) return base_path, output_file @@ -1974,7 +1975,8 @@ makefile_path = os.path.join(options.toplevel_dir, makefile_name) if options.generator_output: global srcdir_prefix - makefile_path = os.path.join(options.generator_output, makefile_path) + makefile_path = os.path.join( + options.toplevel_dir, options.generator_output, makefile_name) srcdir = gyp.common.RelativePath(srcdir, options.generator_output) srcdir_prefix = '$(srcdir)/' @@ -2094,7 +2096,8 @@ this_make_global_settings = data[build_file].get('make_global_settings', []) assert make_global_settings_array == this_make_global_settings, ( - "make_global_settings needs to be the same for all targets.") + "make_global_settings needs to be the same for all targets. %s vs. %s" % + (this_make_global_settings, make_global_settings)) build_files.add(gyp.common.RelativePath(build_file, options.toplevel_dir)) included_files = data[build_file]['included_files'] diff -Nru nodejs-0.11.10/tools/gyp/pylib/gyp/generator/msvs.py nodejs-0.11.11/tools/gyp/pylib/gyp/generator/msvs.py --- nodejs-0.11.10/tools/gyp/pylib/gyp/generator/msvs.py 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/tools/gyp/pylib/gyp/generator/msvs.py 2014-01-29 01:29:56.000000000 +0000 @@ -209,13 +209,14 @@ def _ConvertSourcesToFilterHierarchy(sources, prefix=None, excluded=None, - list_excluded=True): + list_excluded=True, msvs_version=None): """Converts a list split source file paths into a vcproj folder hierarchy. Arguments: sources: A list of source file paths split. prefix: A list of source file path layers meant to apply to each of sources. excluded: A set of excluded files. + msvs_version: A MSVSVersion object. Returns: A hierarchy of filenames and MSVSProject.Filter objects that matches the @@ -230,6 +231,7 @@ if not prefix: prefix = [] result = [] excluded_result = [] + folders = OrderedDict() # Gather files into the final result, excluded, or folders. for s in sources: if len(s) == 1: @@ -238,10 +240,17 @@ excluded_result.append(filename) else: result.append(filename) + elif msvs_version and not msvs_version.UsesVcxproj(): + # For MSVS 2008 and earlier, we need to process all files before walking + # the sub folders. + if not folders.get(s[0]): + folders[s[0]] = [] + folders[s[0]].append(s[1:]) else: contents = _ConvertSourcesToFilterHierarchy([s[1:]], prefix + [s[0]], excluded=excluded, - list_excluded=list_excluded) + list_excluded=list_excluded, + msvs_version=msvs_version) contents = MSVSProject.Filter(s[0], contents=contents) result.append(contents) # Add a folder for excluded files. @@ -249,6 +258,17 @@ excluded_folder = MSVSProject.Filter('_excluded_files', contents=excluded_result) result.append(excluded_folder) + + if msvs_version and msvs_version.UsesVcxproj(): + return result + + # Populate all the folders. + for f in folders: + contents = _ConvertSourcesToFilterHierarchy(folders[f], prefix=prefix + [f], + excluded=excluded, + list_excluded=list_excluded) + contents = MSVSProject.Filter(f, contents=contents) + result.append(contents) return result @@ -971,8 +991,9 @@ actions_to_add) list_excluded = generator_flags.get('msvs_list_excluded_files', True) sources, excluded_sources, excluded_idl = ( - _AdjustSourcesAndConvertToFilterHierarchy( - spec, options, project_dir, sources, excluded_sources, list_excluded)) + _AdjustSourcesAndConvertToFilterHierarchy(spec, options, project_dir, + sources, excluded_sources, + list_excluded, version)) # Add in files. missing_sources = _VerifySourcesExist(sources, project_dir) @@ -1416,7 +1437,7 @@ def _AdjustSourcesAndConvertToFilterHierarchy( - spec, options, gyp_dir, sources, excluded_sources, list_excluded): + spec, options, gyp_dir, sources, excluded_sources, list_excluded, version): """Adjusts the list of sources and excluded sources. Also converts the sets to lists. @@ -1427,6 +1448,7 @@ gyp_dir: The path to the gyp file being processed. sources: A set of sources to be included for this project. excluded_sources: A set of sources to be excluded for this project. + version: A MSVSVersion object. Returns: A trio of (list of sources, list of excluded sources, path of excluded IDL file) @@ -1451,7 +1473,8 @@ # Convert to folders and the right slashes. sources = [i.split('\\') for i in sources] sources = _ConvertSourcesToFilterHierarchy(sources, excluded=fully_excluded, - list_excluded=list_excluded) + list_excluded=list_excluded, + msvs_version=version) # Prune filters with a single child to flatten ugly directory structures # such as ../../src/modules/module1 etc. @@ -3126,7 +3149,7 @@ _AdjustSourcesAndConvertToFilterHierarchy(spec, options, project_dir, sources, excluded_sources, - list_excluded)) + list_excluded, version)) # Don't add actions if we are using an external builder like ninja. if not spec.get('msvs_external_builder'): diff -Nru nodejs-0.11.10/tools/gyp/pylib/gyp/generator/ninja.py nodejs-0.11.11/tools/gyp/pylib/gyp/generator/ninja.py --- nodejs-0.11.10/tools/gyp/pylib/gyp/generator/ninja.py 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/tools/gyp/pylib/gyp/generator/ninja.py 2014-01-29 01:29:56.000000000 +0000 @@ -1037,12 +1037,13 @@ self.GypPathToNinja, arch) ldflags = env_ldflags + ldflags elif self.flavor == 'win': - manifest_name = self.GypPathToUniqueOutput( + manifest_base_name = self.GypPathToUniqueOutput( self.ComputeOutputFileName(spec)) ldflags, intermediate_manifest, manifest_files = \ self.msvs_settings.GetLdflags(config_name, self.GypPathToNinja, - self.ExpandSpecial, manifest_name, - is_executable, self.toplevel_build) + self.ExpandSpecial, manifest_base_name, + output, is_executable, + self.toplevel_build) ldflags = env_ldflags + ldflags self.WriteVariableList(ninja_file, 'manifests', manifest_files) implicit_deps = implicit_deps.union(manifest_files) @@ -1095,16 +1096,27 @@ extra_bindings.append(('lib', gyp.common.EncodePOSIXShellArgument(output))) if self.flavor == 'win': - extra_bindings.append(('dll', output)) + extra_bindings.append(('binary', output)) if '/NOENTRY' not in ldflags: self.target.import_lib = output + '.lib' extra_bindings.append(('implibflag', '/IMPLIB:%s' % self.target.import_lib)) + pdbname = self.msvs_settings.GetPDBName( + config_name, self.ExpandSpecial, output + '.pdb') output = [output, self.target.import_lib] + if pdbname: + output.append(pdbname) elif not self.is_mac_bundle: output = [output, output + '.TOC'] else: command = command + '_notoc' + elif self.flavor == 'win': + extra_bindings.append(('binary', output)) + pdbname = self.msvs_settings.GetPDBName( + config_name, self.ExpandSpecial, output + '.pdb') + if pdbname: + output = [output, pdbname] + if len(solibs): extra_bindings.append(('solibs', gyp.common.EncodePOSIXShellList(solibs))) @@ -1545,7 +1557,10 @@ mem_limit = max(1, stat.ullTotalPhys / (4 * (2 ** 30))) # total / 4GB hard_cap = max(1, int(os.getenv('GYP_LINK_CONCURRENCY_MAX', 2**32))) - return min(mem_limit, hard_cap) + # return min(mem_limit, hard_cap) + # TODO(scottmg): Temporary speculative fix for OOM on builders + # See http://crbug.com/333000. + return 2 elif sys.platform.startswith('linux'): with open("/proc/meminfo") as meminfo: memtotal_re = re.compile(r'^MemTotal:\s*(\d*)\s*kB') @@ -1591,33 +1606,35 @@ 'resname': resource_name, 'embed': embed_manifest } rule_name_suffix = _GetWinLinkRuleNameSuffix(embed_manifest) - dlldesc = 'LINK%s(DLL) $dll' % rule_name_suffix.upper() - dllcmd = ('%s gyp-win-tool link-wrapper $arch ' - '$ld /nologo $implibflag /DLL /OUT:$dll ' - '/PDB:$dll.pdb @$dll.rsp' % sys.executable) - dllcmd = FullLinkCommand(dllcmd, '$dll', 'dll') + use_separate_mspdbsrv = ( + int(os.environ.get('GYP_USE_SEPARATE_MSPDBSRV', '0')) != 0) + dlldesc = 'LINK%s(DLL) $binary' % rule_name_suffix.upper() + dllcmd = ('%s gyp-win-tool link-wrapper $arch %s ' + '$ld /nologo $implibflag /DLL /OUT:$binary ' + '@$binary.rsp' % (sys.executable, use_separate_mspdbsrv)) + dllcmd = FullLinkCommand(dllcmd, '$binary', 'dll') master_ninja.rule('solink' + rule_name_suffix, description=dlldesc, command=dllcmd, - rspfile='$dll.rsp', + rspfile='$binary.rsp', rspfile_content='$libs $in_newline $ldflags', restat=True, pool='link_pool') master_ninja.rule('solink_module' + rule_name_suffix, description=dlldesc, command=dllcmd, - rspfile='$dll.rsp', + rspfile='$binary.rsp', rspfile_content='$libs $in_newline $ldflags', restat=True, pool='link_pool') # Note that ldflags goes at the end so that it has the option of # overriding default settings earlier in the command line. - exe_cmd = ('%s gyp-win-tool link-wrapper $arch ' - '$ld /nologo /OUT:$out /PDB:$out.pdb @$out.rsp' % - sys.executable) - exe_cmd = FullLinkCommand(exe_cmd, '$out', 'exe') + exe_cmd = ('%s gyp-win-tool link-wrapper $arch %s ' + '$ld /nologo /OUT:$binary @$binary.rsp' % + (sys.executable, use_separate_mspdbsrv)) + exe_cmd = FullLinkCommand(exe_cmd, '$binary', 'exe') master_ninja.rule('link' + rule_name_suffix, - description='LINK%s $out' % rule_name_suffix.upper(), + description='LINK%s $binary' % rule_name_suffix.upper(), command=exe_cmd, - rspfile='$out.rsp', + rspfile='$binary.rsp', rspfile_content='$in_newline $libs $ldflags', pool='link_pool') @@ -1877,7 +1894,7 @@ master_ninja.rule( 'alink', description='LIB $out', - command=('%s gyp-win-tool link-wrapper $arch ' + command=('%s gyp-win-tool link-wrapper $arch False ' '$ar /nologo /ignore:4221 /OUT:$out @$out.rsp' % sys.executable), rspfile='$out.rsp', @@ -2027,7 +2044,8 @@ this_make_global_settings = data[build_file].get('make_global_settings', []) assert make_global_settings == this_make_global_settings, ( - "make_global_settings needs to be the same for all targets.") + "make_global_settings needs to be the same for all targets. %s vs. %s" % + (this_make_global_settings, make_global_settings)) spec = target_dicts[qualified_target] if flavor == 'mac': diff -Nru nodejs-0.11.10/tools/gyp/pylib/gyp/mac_tool.py nodejs-0.11.11/tools/gyp/pylib/gyp/mac_tool.py --- nodejs-0.11.10/tools/gyp/pylib/gyp/mac_tool.py 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/tools/gyp/pylib/gyp/mac_tool.py 2014-01-29 01:29:56.000000000 +0000 @@ -503,7 +503,8 @@ if isinstance(data, list): return [self._ExpandVariables(v, substitutions) for v in data] if isinstance(data, dict): - return {k: self._ExpandVariables(data[k], substitutions) for k in data} + return dict((k, self._ExpandVariables(data[k], + substitutions)) for k in data) return data if __name__ == '__main__': diff -Nru nodejs-0.11.10/tools/gyp/pylib/gyp/msvs_emulation.py nodejs-0.11.11/tools/gyp/pylib/gyp/msvs_emulation.py --- nodejs-0.11.10/tools/gyp/pylib/gyp/msvs_emulation.py 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/tools/gyp/pylib/gyp/msvs_emulation.py 2014-01-29 01:29:56.000000000 +0000 @@ -317,15 +317,20 @@ output_file, config=config)) return output_file - def GetPDBName(self, config, expand_special): - """Gets the explicitly overridden pdb name for a target or returns None - if it's not overridden.""" + def GetPDBName(self, config, expand_special, default): + """Gets the explicitly overridden pdb name for a target or returns + default if it's not overridden, or if no pdb will be generated.""" config = self._TargetConfig(config) output_file = self._Setting(('VCLinkerTool', 'ProgramDatabaseFile'), config) - if output_file: - output_file = expand_special(self.ConvertVSMacros( - output_file, config=config)) - return output_file + generate_debug_info = self._Setting( + ('VCLinkerTool', 'GenerateDebugInformation'), config) + if generate_debug_info: + if output_file: + return expand_special(self.ConvertVSMacros(output_file, config=config)) + else: + return default + else: + return None def GetCflags(self, config): """Returns the flags that need to be added to .c and .cc compilations.""" @@ -454,7 +459,7 @@ return output_file def GetLdflags(self, config, gyp_to_build_path, expand_special, - manifest_base_name, is_executable, build_dir): + manifest_base_name, output_name, is_executable, build_dir): """Returns the flags that need to be added to link commands, and the manifest files.""" config = self._TargetConfig(config) @@ -472,7 +477,7 @@ out = self.GetOutputName(config, expand_special) if out: ldflags.append('/OUT:' + out) - pdb = self.GetPDBName(config, expand_special) + pdb = self.GetPDBName(config, expand_special, output_name + '.pdb') if pdb: ldflags.append('/PDB:' + pdb) pgd = self.GetPGDName(config, expand_special) diff -Nru nodejs-0.11.10/tools/gyp/pylib/gyp/ordered_dict.py nodejs-0.11.11/tools/gyp/pylib/gyp/ordered_dict.py --- nodejs-0.11.10/tools/gyp/pylib/gyp/ordered_dict.py 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/tools/gyp/pylib/gyp/ordered_dict.py 2014-01-29 01:29:56.000000000 +0000 @@ -166,6 +166,8 @@ for k in self: yield (k, self[k]) + # Suppress 'OrderedDict.update: Method has no argument': + # pylint: disable=E0211 def update(*args, **kwds): '''od.update(E, **F) -> None. Update od from dict/iterable E and F. diff -Nru nodejs-0.11.10/tools/gyp/pylib/gyp/win_tool.py nodejs-0.11.11/tools/gyp/pylib/gyp/win_tool.py --- nodejs-0.11.10/tools/gyp/pylib/gyp/win_tool.py 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/tools/gyp/pylib/gyp/win_tool.py 2014-01-29 01:29:56.000000000 +0000 @@ -18,9 +18,9 @@ BASE_DIR = os.path.dirname(os.path.abspath(__file__)) -# A regex matching an argument corresponding to a PDB filename passed as an -# argument to link.exe. -_LINK_EXE_PDB_ARG = re.compile('/PDB:(?P.+\.exe\.pdb)$', re.IGNORECASE) +# A regex matching an argument corresponding to the output filename passed to +# link.exe. +_LINK_EXE_OUT_ARG = re.compile('/OUT:(?P.+)$', re.IGNORECASE) def main(args): executor = WinTool() @@ -33,25 +33,22 @@ """This class performs all the Windows tooling steps. The methods can either be executed directly, or dispatched from an argument list.""" - def _MaybeUseSeparateMspdbsrv(self, env, args): - """Allows to use a unique instance of mspdbsrv.exe for the linkers linking - an .exe target if GYP_USE_SEPARATE_MSPDBSRV has been set.""" - if not os.environ.get('GYP_USE_SEPARATE_MSPDBSRV'): - return - + def _UseSeparateMspdbsrv(self, env, args): + """Allows to use a unique instance of mspdbsrv.exe per linker instead of a + shared one.""" if len(args) < 1: raise Exception("Not enough arguments") if args[0] != 'link.exe': return - # Checks if this linker produces a PDB for an .exe target. If so use the - # name of this PDB to generate an endpoint name for mspdbsrv.exe. + # Use the output filename passed to the linker to generate an endpoint name + # for mspdbsrv.exe. endpoint_name = None for arg in args: - m = _LINK_EXE_PDB_ARG.match(arg) + m = _LINK_EXE_OUT_ARG.match(arg) if m: - endpoint_name = '%s_%d' % (m.group('pdb'), os.getpid()) + endpoint_name = '%s_%d' % (m.group('out'), os.getpid()) break if endpoint_name is None: @@ -99,13 +96,14 @@ else: shutil.copy2(source, dest) - def ExecLinkWrapper(self, arch, *args): + def ExecLinkWrapper(self, arch, use_separate_mspdbsrv, *args): """Filter diagnostic output from link that looks like: ' Creating library ui.dll.lib and object ui.dll.exp' This happens when there are exports from the dll or exe. """ env = self._GetEnv(arch) - self._MaybeUseSeparateMspdbsrv(env, args) + if use_separate_mspdbsrv == 'True': + self._UseSeparateMspdbsrv(env, args) link = subprocess.Popen(args, shell=True, env=env, @@ -280,6 +278,11 @@ """Runs an action command line from a response file using the environment for |arch|. If |dir| is supplied, use that as the working directory.""" env = self._GetEnv(arch) + # TODO(scottmg): This is a temporary hack to get some specific variables + # through to actions that are set after gyp-time. http://crbug.com/333738. + for k, v in os.environ.iteritems(): + if k not in env: + env[k] = v args = open(rspfile).read() dir = dir[0] if dir else None return subprocess.call(args, shell=True, env=env, cwd=dir) diff -Nru nodejs-0.11.10/tools/test.py nodejs-0.11.11/tools/test.py --- nodejs-0.11.10/tools/test.py 2013-12-31 23:37:12.000000000 +0000 +++ nodejs-0.11.11/tools/test.py 2014-01-29 01:29:56.000000000 +0000 @@ -1322,7 +1322,14 @@ return ExpandCommand -BUILT_IN_TESTS = ['simple', 'pummel', 'message', 'internet', 'gc'] +BUILT_IN_TESTS = [ + 'simple', + 'pummel', + 'message', + 'internet', + 'gc', + 'debugger', +] def GetSuites(test_root):