diff --git a/deps/chakrashim/include/v8-version.h b/deps/chakrashim/include/v8-version.h index ee6ccec7cec..133ee1f3f1b 100644 --- a/deps/chakrashim/include/v8-version.h +++ b/deps/chakrashim/include/v8-version.h @@ -11,7 +11,7 @@ #define V8_MAJOR_VERSION 6 #define V8_MINOR_VERSION 5 #define V8_BUILD_NUMBER 254 -#define V8_PATCH_LEVEL 38 +#define V8_PATCH_LEVEL 40 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.) diff --git a/deps/v8/include/v8-version.h b/deps/v8/include/v8-version.h index ee6ccec7cec..133ee1f3f1b 100644 --- a/deps/v8/include/v8-version.h +++ b/deps/v8/include/v8-version.h @@ -11,7 +11,7 @@ #define V8_MAJOR_VERSION 6 #define V8_MINOR_VERSION 5 #define V8_BUILD_NUMBER 254 -#define V8_PATCH_LEVEL 38 +#define V8_PATCH_LEVEL 40 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.) diff --git a/deps/v8/src/wasm/wasm-code-manager.cc b/deps/v8/src/wasm/wasm-code-manager.cc index 8e46f33b012..2b8f3097339 100644 --- a/deps/v8/src/wasm/wasm-code-manager.cc +++ b/deps/v8/src/wasm/wasm-code-manager.cc @@ -954,6 +954,8 @@ void WasmCodeManager::FreeNativeModuleMemories(NativeModule* native_module) { Free(&vmem); DCHECK(!vmem.IsReserved()); } + native_module->owned_memory_.clear(); + // No need to tell the GC anything if we're destroying the heap, // which we currently indicate by having the isolate_ as null if (isolate_ == nullptr) return; diff --git a/deps/v8/tools/whitespace.txt b/deps/v8/tools/whitespace.txt index ed5e51f96a6..83f006688cd 100644 --- a/deps/v8/tools/whitespace.txt +++ b/deps/v8/tools/whitespace.txt @@ -8,5 +8,3 @@ The doubles heard this and started to unbox. The Smi looked at them when a crazy v8-autoroll account showed up... The autoroller bought a round of Himbeerbrause. Suddenly... The bartender starts to shake the bottles....................... -. -. diff --git a/doc/api/errors.md b/doc/api/errors.md index f5190dc52bf..5c38dde4130 100644 --- a/doc/api/errors.md +++ b/doc/api/errors.md @@ -783,18 +783,6 @@ falsy value. An invalid symlink type was passed to the [`fs.symlink()`][] or [`fs.symlinkSync()`][] methods. - -### ERR_FS_WATCHER_ALREADY_STARTED - -An attempt was made to start a watcher returned by `fs.watch()` that has -already been started. - - -### ERR_FS_WATCHER_NOT_STARTED - -An attempt was made to initiate operations on a watcher returned by -`fs.watch()` that has not yet been started. - ### ERR_HTTP_HEADERS_SENT diff --git a/doc/api/stream.md b/doc/api/stream.md index 814acc69d6a..01405556674 100644 --- a/doc/api/stream.md +++ b/doc/api/stream.md @@ -1208,7 +1208,10 @@ print(fs.createReadStream('file')).catch(console.log); If the loop terminates with a `break` or a `throw`, the stream will be destroyed. In other terms, iterating over a stream will consume the stream -fully. +fully. The stream will be read in chunks of size equal to the `highWaterMark` +option. In the code example above, data will be in a single chunk if the file +has less then 64kb of data because no `highWaterMark` option is provided to +[`fs.createReadStream()`][]. ### Duplex and Transform Streams diff --git a/lib/fs.js b/lib/fs.js index 352d2fd1ffd..f6722921fc5 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -36,8 +36,6 @@ const fs = exports; const { Buffer } = require('buffer'); const errors = require('internal/errors'); const { - ERR_FS_WATCHER_ALREADY_STARTED, - ERR_FS_WATCHER_NOT_STARTED, ERR_INVALID_ARG_TYPE, ERR_INVALID_CALLBACK, ERR_OUT_OF_RANGE @@ -1342,25 +1340,26 @@ util.inherits(FSWatcher, EventEmitter); // FIXME(joyeecheung): this method is not documented. // At the moment if filename is undefined, we -// 1. Throw an Error from C++ land if it's the first time .start() is called -// 2. Return silently from C++ land if .start() has already been called +// 1. Throw an Error if it's the first time .start() is called +// 2. Return silently if .start() has already been called // on a valid filename and the wrap has been initialized +// This method is a noop if the watcher has already been started. FSWatcher.prototype.start = function(filename, persistent, recursive, encoding) { lazyAssert()(this._handle instanceof FSEvent, 'handle must be a FSEvent'); if (this._handle.initialized) { - throw new ERR_FS_WATCHER_ALREADY_STARTED(); + return; } filename = getPathFromURL(filename); validatePath(filename, 'filename'); - var err = this._handle.start(pathModule.toNamespacedPath(filename), - persistent, - recursive, - encoding); + const err = this._handle.start(pathModule.toNamespacedPath(filename), + persistent, + recursive, + encoding); if (err) { const error = errors.uvException({ errno: err, @@ -1372,10 +1371,11 @@ FSWatcher.prototype.start = function(filename, } }; +// This method is a noop if the watcher has not been started. FSWatcher.prototype.close = function() { lazyAssert()(this._handle instanceof FSEvent, 'handle must be a FSEvent'); if (!this._handle.initialized) { - throw new ERR_FS_WATCHER_NOT_STARTED(); + return; } this._handle.close(); }; @@ -1449,18 +1449,43 @@ util.inherits(StatWatcher, EventEmitter); // FIXME(joyeecheung): this method is not documented. // At the moment if filename is undefined, we -// 1. Throw an Error from C++ land if it's the first time .start() is called -// 2. Return silently from C++ land if .start() has already been called +// 1. Throw an Error if it's the first time .start() is called +// 2. Return silently if .start() has already been called // on a valid filename and the wrap has been initialized +// This method is a noop if the watcher has already been started. StatWatcher.prototype.start = function(filename, persistent, interval) { + lazyAssert()(this._handle instanceof binding.StatWatcher, + 'handle must be a StatWatcher'); + if (this._handle.isActive) { + return; + } + filename = getPathFromURL(filename); - nullCheck(filename, 'filename'); - this._handle.start(pathModule.toNamespacedPath(filename), - persistent, interval); + validatePath(filename, 'filename'); + validateUint32(interval, 'interval'); + const err = this._handle.start(pathModule.toNamespacedPath(filename), + persistent, interval); + if (err) { + const error = errors.uvException({ + errno: err, + syscall: 'watch', + path: filename + }); + error.filename = filename; + throw error; + } }; - +// FIXME(joyeecheung): this method is not documented while there is +// another documented fs.unwatchFile(). The counterpart in +// FSWatcher is .close() +// This method is a noop if the watcher has not been started. StatWatcher.prototype.stop = function() { + lazyAssert()(this._handle instanceof binding.StatWatcher, + 'handle must be a StatWatcher'); + if (!this._handle.isActive) { + return; + } this._handle.stop(); }; diff --git a/lib/internal/errors.js b/lib/internal/errors.js index 3d0b6cf9b39..d5260bd501f 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -654,10 +654,6 @@ E('ERR_FALSY_VALUE_REJECTION', 'Promise was rejected with falsy value', Error); E('ERR_FS_INVALID_SYMLINK_TYPE', 'Symlink type must be one of "dir", "file", or "junction". Received "%s"', Error); // Switch to TypeError. The current implementation does not seem right -E('ERR_FS_WATCHER_ALREADY_STARTED', - 'The watcher has already been started', Error); -E('ERR_FS_WATCHER_NOT_STARTED', - 'The watcher has not been started', Error); E('ERR_HTTP2_ALTSVC_INVALID_ORIGIN', 'HTTP/2 ALTSVC frames require a valid origin', TypeError); E('ERR_HTTP2_ALTSVC_LENGTH', diff --git a/src/node_file.cc b/src/node_file.cc index b6c9a277be2..11065082071 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -1538,7 +1538,6 @@ static void WriteString(const FunctionCallbackInfo& args) { const auto enc = ParseEncoding(env->isolate(), args[3], UTF8); - std::unique_ptr delete_on_return; Local value = args[1]; char* buf = nullptr; size_t len; @@ -1566,24 +1565,42 @@ static void WriteString(const FunctionCallbackInfo& args) { } } - if (buf == nullptr) { + if (is_async) { // write(fd, string, pos, enc, req) + CHECK_NE(req_wrap, nullptr); len = StringBytes::StorageSize(env->isolate(), value, enc); - buf = new char[len]; - // SYNC_CALL returns on error. Make sure to always free the memory. - if (!is_async) delete_on_return.reset(buf); + FSReqBase::FSReqBuffer& stack_buffer = + req_wrap->Init("write", len, enc); // StorageSize may return too large a char, so correct the actual length // by the write size - len = StringBytes::Write(env->isolate(), buf, len, args[1], enc); - } - - uv_buf_t uvbuf = uv_buf_init(buf, len); - - if (is_async) { // write(fd, string, pos, enc, req) - AsyncCall(env, req_wrap, args, "write", UTF8, AfterInteger, - uv_fs_write, fd, &uvbuf, 1, pos); + len = StringBytes::Write(env->isolate(), *stack_buffer, len, args[1], enc); + stack_buffer.SetLengthAndZeroTerminate(len); + uv_buf_t uvbuf = uv_buf_init(*stack_buffer, len); + int err = uv_fs_write(env->event_loop(), req_wrap->req(), + fd, &uvbuf, 1, pos, AfterInteger); + req_wrap->Dispatched(); + if (err < 0) { + uv_fs_t* uv_req = req_wrap->req(); + uv_req->result = err; + uv_req->path = nullptr; + AfterInteger(uv_req); // after may delete req_wrap if there is an error + } else { + req_wrap->SetReturnValue(args); + } } else { // write(fd, string, pos, enc, undefined, ctx) CHECK_EQ(argc, 6); fs_req_wrap req_wrap; + FSReqBase::FSReqBuffer stack_buffer; + if (buf == nullptr) { + len = StringBytes::StorageSize(env->isolate(), value, enc); + stack_buffer.AllocateSufficientStorage(len + 1); + // StorageSize may return too large a char, so correct the actual length + // by the write size + len = StringBytes::Write(env->isolate(), *stack_buffer, + len, args[1], enc); + stack_buffer.SetLengthAndZeroTerminate(len); + buf = *stack_buffer; + } + uv_buf_t uvbuf = uv_buf_init(buf, len); int bytesWritten = SyncCall(env, args[5], &req_wrap, "write", uv_fs_write, fd, &uvbuf, 1, pos); args.GetReturnValue().Set(bytesWritten); diff --git a/src/node_file.h b/src/node_file.h index fa373d46ad0..1925e400f2d 100644 --- a/src/node_file.h +++ b/src/node_file.h @@ -24,6 +24,8 @@ namespace fs { class FSReqBase : public ReqWrap { public: + typedef MaybeStackBuffer FSReqBuffer; + FSReqBase(Environment* env, Local req, AsyncWrap::ProviderType type) : ReqWrap(env, req, type) { Wrap(object(), this); @@ -34,9 +36,9 @@ class FSReqBase : public ReqWrap { } void Init(const char* syscall, - const char* data = nullptr, - size_t len = 0, - enum encoding encoding = UTF8) { + const char* data, + size_t len, + enum encoding encoding) { syscall_ = syscall; encoding_ = encoding; @@ -49,6 +51,16 @@ class FSReqBase : public ReqWrap { } } + FSReqBuffer& Init(const char* syscall, size_t len, + enum encoding encoding) { + syscall_ = syscall; + encoding_ = encoding; + + buffer_.AllocateSufficientStorage(len + 1); + has_data_ = false; // so that the data does not show up in error messages + return buffer_; + } + virtual void FillStatsArray(const uv_stat_t* stat) = 0; virtual void Reject(Local reject) = 0; virtual void Resolve(Local value) = 0; @@ -68,7 +80,7 @@ class FSReqBase : public ReqWrap { // Typically, the content of buffer_ is something like a file name, so // something around 64 bytes should be enough. - MaybeStackBuffer buffer_; + FSReqBuffer buffer_; DISALLOW_COPY_AND_ASSIGN(FSReqBase); }; diff --git a/src/node_stat_watcher.cc b/src/node_stat_watcher.cc index 00b43f6eb7c..32b416c466f 100644 --- a/src/node_stat_watcher.cc +++ b/src/node_stat_watcher.cc @@ -30,13 +30,19 @@ namespace node { using v8::Context; +using v8::DontDelete; +using v8::DontEnum; using v8::FunctionCallbackInfo; using v8::FunctionTemplate; using v8::HandleScope; using v8::Integer; using v8::Local; using v8::Object; +using v8::PropertyAttribute; +using v8::ReadOnly; +using v8::Signature; using v8::String; +using v8::Uint32; using v8::Value; @@ -53,6 +59,17 @@ void StatWatcher::Initialize(Environment* env, Local target) { env->SetProtoMethod(t, "start", StatWatcher::Start); env->SetProtoMethod(t, "stop", StatWatcher::Stop); + Local is_active_templ = + FunctionTemplate::New(env->isolate(), + IsActive, + env->as_external(), + Signature::New(env->isolate(), t)); + t->PrototypeTemplate()->SetAccessorProperty( + FIXED_ONE_BYTE_STRING(env->isolate(), "isActive"), + is_active_templ, + Local(), + static_cast(ReadOnly | DontDelete | DontEnum)); + target->Set(statWatcherString, t->GetFunction()); } @@ -73,7 +90,9 @@ StatWatcher::StatWatcher(Environment* env, Local wrap) StatWatcher::~StatWatcher() { - Stop(); + if (IsActive()) { + Stop(); + } uv_close(reinterpret_cast(watcher_), Delete); } @@ -101,32 +120,63 @@ void StatWatcher::New(const FunctionCallbackInfo& args) { new StatWatcher(env, args.This()); } +bool StatWatcher::IsActive() { + return uv_is_active(reinterpret_cast(watcher_)) != 0; +} + +void StatWatcher::IsActive(const v8::FunctionCallbackInfo& args) { + StatWatcher* wrap = Unwrap(args.This()); + CHECK(wrap != nullptr); + args.GetReturnValue().Set(wrap->IsActive()); +} +// wrap.start(filename, persistent, interval) void StatWatcher::Start(const FunctionCallbackInfo& args) { CHECK_EQ(args.Length(), 3); - StatWatcher* wrap; - ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); + StatWatcher* wrap = Unwrap(args.Holder()); + CHECK_NE(wrap, nullptr); + if (wrap->IsActive()) { + return; + } + + const int argc = args.Length(); + CHECK_GE(argc, 3); + node::Utf8Value path(args.GetIsolate(), args[0]); - const bool persistent = args[1]->BooleanValue(); - const uint32_t interval = args[2]->Uint32Value(); + CHECK_NE(*path, nullptr); + + bool persistent = true; + if (args[1]->IsFalse()) { + persistent = false; + } + + CHECK(args[2]->IsUint32()); + const uint32_t interval = args[2].As()->Value(); - if (uv_is_active(reinterpret_cast(wrap->watcher_))) - return; // Safe, uv_ref/uv_unref are idempotent. if (persistent) uv_ref(reinterpret_cast(wrap->watcher_)); else uv_unref(reinterpret_cast(wrap->watcher_)); - uv_fs_poll_start(wrap->watcher_, Callback, *path, interval); + // Note that uv_fs_poll_start does not return ENOENT, we are handling + // mostly memory errors here. + const int err = uv_fs_poll_start(wrap->watcher_, Callback, *path, interval); + if (err != 0) { + args.GetReturnValue().Set(err); + } wrap->ClearWeak(); } void StatWatcher::Stop(const FunctionCallbackInfo& args) { - StatWatcher* wrap; - ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); + StatWatcher* wrap = Unwrap(args.Holder()); + CHECK_NE(wrap, nullptr); + if (!wrap->IsActive()) { + return; + } + Environment* env = wrap->env(); Context::Scope context_scope(env->context()); wrap->MakeCallback(env->onstop_string(), 0, nullptr); @@ -135,8 +185,6 @@ void StatWatcher::Stop(const FunctionCallbackInfo& args) { void StatWatcher::Stop() { - if (!uv_is_active(reinterpret_cast(watcher_))) - return; uv_fs_poll_stop(watcher_); MakeWeak(this); } diff --git a/src/node_stat_watcher.h b/src/node_stat_watcher.h index 55f4307fdbc..587203ff1ed 100644 --- a/src/node_stat_watcher.h +++ b/src/node_stat_watcher.h @@ -44,6 +44,7 @@ class StatWatcher : public AsyncWrap { static void New(const v8::FunctionCallbackInfo& args); static void Start(const v8::FunctionCallbackInfo& args); static void Stop(const v8::FunctionCallbackInfo& args); + static void IsActive(const v8::FunctionCallbackInfo& args); size_t self_size() const override { return sizeof(*this); } @@ -53,6 +54,7 @@ class StatWatcher : public AsyncWrap { const uv_stat_t* prev, const uv_stat_t* curr); void Stop(); + bool IsActive(); uv_fs_poll_t* watcher_; }; diff --git a/src/stream_base.h b/src/stream_base.h index 3267e544a04..d5a759bd8de 100644 --- a/src/stream_base.h +++ b/src/stream_base.h @@ -225,7 +225,7 @@ class StreamResource { // Clear the current error (i.e. that would be returned by Error()). virtual void ClearError(); - // Transfer ownership of this tream to `listener`. The previous listener + // Transfer ownership of this stream to `listener`. The previous listener // will not receive any more callbacks while the new listener was active. void PushStreamListener(StreamListener* listener); // Remove a listener, and, if this was the currently active one, diff --git a/test/addons-napi/test_make_callback/test-async-hooks.js b/test/addons-napi/test_make_callback/test-async-hooks.js new file mode 100644 index 00000000000..755a2389c68 --- /dev/null +++ b/test/addons-napi/test_make_callback/test-async-hooks.js @@ -0,0 +1,44 @@ +'use strict'; + +const common = require('../../common'); +const assert = require('assert'); +const async_hooks = require('async_hooks'); +const binding = require(`./build/${common.buildType}/binding`); +const makeCallback = binding.makeCallback; + +// Check async hooks integration using async context. +const hook_result = { + id: null, + init_called: false, + before_called: false, + after_called: false, + destroy_called: false, +}; +const test_hook = async_hooks.createHook({ + init: (id, type) => { + if (type === 'test') { + hook_result.id = id; + hook_result.init_called = true; + } + }, + before: (id) => { + if (id === hook_result.id) hook_result.before_called = true; + }, + after: (id) => { + if (id === hook_result.id) hook_result.after_called = true; + }, + destroy: (id) => { + if (id === hook_result.id) hook_result.destroy_called = true; + }, +}); + +test_hook.enable(); +makeCallback(process, function() {}); + +assert.strictEqual(hook_result.init_called, true); +assert.strictEqual(hook_result.before_called, true); +assert.strictEqual(hook_result.after_called, true); +setImmediate(() => { + assert.strictEqual(hook_result.destroy_called, true); + test_hook.disable(); +}); diff --git a/test/addons-napi/test_make_callback/test.js b/test/addons-napi/test_make_callback/test.js index 0e94caf1d97..56e2b3f4e2b 100644 --- a/test/addons-napi/test_make_callback/test.js +++ b/test/addons-napi/test_make_callback/test.js @@ -2,7 +2,6 @@ const common = require('../../common'); const assert = require('assert'); -const async_hooks = require('async_hooks'); const vm = require('vm'); const binding = require(`./build/${common.buildType}/binding`); const makeCallback = binding.makeCallback; @@ -81,40 +80,3 @@ function endpoint($Object) { } assert.strictEqual(Object, makeCallback(process, forward, endpoint)); - -// Check async hooks integration using async context. -const hook_result = { - id: null, - init_called: false, - before_called: false, - after_called: false, - destroy_called: false, -}; -const test_hook = async_hooks.createHook({ - init: (id, type) => { - if (type === 'test') { - hook_result.id = id; - hook_result.init_called = true; - } - }, - before: (id) => { - if (id === hook_result.id) hook_result.before_called = true; - }, - after: (id) => { - if (id === hook_result.id) hook_result.after_called = true; - }, - destroy: (id) => { - if (id === hook_result.id) hook_result.destroy_called = true; - }, -}); - -test_hook.enable(); -makeCallback(process, function() {}); - -assert.strictEqual(hook_result.init_called, true); -assert.strictEqual(hook_result.before_called, true); -assert.strictEqual(hook_result.after_called, true); -setImmediate(() => { - assert.strictEqual(hook_result.destroy_called, true); - test_hook.disable(); -}); diff --git a/test/parallel/test-fs-watch.js b/test/parallel/test-fs-watch.js index f980363b9fd..24600b79ceb 100644 --- a/test/parallel/test-fs-watch.js +++ b/test/parallel/test-fs-watch.js @@ -65,16 +65,10 @@ for (const testCase of cases) { assert.strictEqual(eventType, 'change'); assert.strictEqual(argFilename, testCase.fileName); - common.expectsError(() => watcher.start(), { - code: 'ERR_FS_WATCHER_ALREADY_STARTED', - message: 'The watcher has already been started' - }); + watcher.start(); // starting a started watcher should be a noop // end of test case watcher.close(); - common.expectsError(() => watcher.close(), { - code: 'ERR_FS_WATCHER_NOT_STARTED', - message: 'The watcher has not been started' - }); + watcher.close(); // closing a closed watcher should be a noop })); // long content so it's actually flushed. toUpperCase so there's real change. diff --git a/test/parallel/test-fs-watchfile.js b/test/parallel/test-fs-watchfile.js index 3c24ae84ac0..ba4becb2627 100644 --- a/test/parallel/test-fs-watchfile.js +++ b/test/parallel/test-fs-watchfile.js @@ -74,10 +74,15 @@ const watcher = assert(prev.ino <= 0); // Stop watching the file fs.unwatchFile(enoentFile); + watcher.stop(); // stopping a stopped watcher should be a noop } }, 2)); -watcher.start(); // should not crash +// 'stop' should only be emitted once - stopping a stopped watcher should +// not trigger a 'stop' event. +watcher.on('stop', common.mustCall(function onStop() {})); + +watcher.start(); // starting a started watcher should be a noop // Watch events should callback with a filename on supported systems. // Omitting AIX. It works but not reliably. diff --git a/test/parallel/test-regress-GH-node-9326.js b/test/parallel/test-kill-segfault-freebsd.js similarity index 61% rename from test/parallel/test-regress-GH-node-9326.js rename to test/parallel/test-kill-segfault-freebsd.js index 78565e3f596..8532f11c86b 100644 --- a/test/parallel/test-regress-GH-node-9326.js +++ b/test/parallel/test-kill-segfault-freebsd.js @@ -1,5 +1,10 @@ 'use strict'; require('../common'); + +// This test ensures Node.js doesn't crash on hitting Ctrl+C in order to +// terminate the currently running process (especially on FreeBSD). +// https://github.com/nodejs/node-v0.x-archive/issues/9326 + const assert = require('assert'); const child_process = require('child_process'); diff --git a/test/parallel/test-regress-GH-io-1068.js b/test/parallel/test-regress-GH-io-1068.js deleted file mode 100644 index a92bb3e7525..00000000000 --- a/test/parallel/test-regress-GH-io-1068.js +++ /dev/null @@ -1,3 +0,0 @@ -'use strict'; -require('../common'); -process.stdin.emit('end'); diff --git a/test/parallel/test-timers-regress-GH-9765.js b/test/parallel/test-timers-setimmediate-infinite-loop.js similarity index 100% rename from test/parallel/test-timers-regress-GH-9765.js rename to test/parallel/test-timers-setimmediate-infinite-loop.js diff --git a/test/parallel/test-tls-pfx-authorizationerror.js b/test/parallel/test-tls-pfx-authorizationerror.js new file mode 100644 index 00000000000..64b6e1485dc --- /dev/null +++ b/test/parallel/test-tls-pfx-authorizationerror.js @@ -0,0 +1,42 @@ +'use strict'; +const common = require('../common'); +if (!common.hasCrypto) + common.skip('node compiled without crypto.'); +const fixtures = require('../common/fixtures'); + +// This test ensures that TLS does not fail to read a self-signed certificate +// and thus throw an `authorizationError`. +// https://github.com/nodejs/node/issues/5100 + +const assert = require('assert'); +const tls = require('tls'); + +const pfx = fixtures.readKey('agent1-pfx.pem'); + +const server = tls + .createServer( + { + pfx: pfx, + passphrase: 'sample', + requestCert: true, + rejectUnauthorized: false + }, + common.mustCall(function(c) { + assert.strictEqual(c.authorizationError, null); + c.end(); + }) + ) + .listen(0, function() { + const client = tls.connect( + { + port: this.address().port, + pfx: pfx, + passphrase: 'sample', + rejectUnauthorized: false + }, + function() { + client.end(); + server.close(); + } + ); + }); diff --git a/test/parallel/test-tls-pfx-gh-5100-regr.js b/test/parallel/test-tls-pfx-gh-5100-regr.js deleted file mode 100644 index 199d4bdf227..00000000000 --- a/test/parallel/test-tls-pfx-gh-5100-regr.js +++ /dev/null @@ -1,32 +0,0 @@ -'use strict'; - -const common = require('../common'); - -if (!common.hasCrypto) - common.skip('node compiled without crypto.'); - -const assert = require('assert'); -const tls = require('tls'); -const fixtures = require('../common/fixtures'); - -const pfx = fixtures.readKey('agent1-pfx.pem'); - -const server = tls.createServer({ - pfx: pfx, - passphrase: 'sample', - requestCert: true, - rejectUnauthorized: false -}, common.mustCall(function(c) { - assert.strictEqual(c.authorizationError, null); - c.end(); -})).listen(0, function() { - const client = tls.connect({ - port: this.address().port, - pfx: pfx, - passphrase: 'sample', - rejectUnauthorized: false - }, function() { - client.end(); - server.close(); - }); -}); diff --git a/test/parallel/test-tls-regr-gh-5108.js b/test/parallel/test-tls-tlswrap-segfault.js similarity index 81% rename from test/parallel/test-tls-regr-gh-5108.js rename to test/parallel/test-tls-tlswrap-segfault.js index 402a6014d13..eaa51ff51ba 100644 --- a/test/parallel/test-tls-regr-gh-5108.js +++ b/test/parallel/test-tls-tlswrap-segfault.js @@ -1,19 +1,21 @@ 'use strict'; const common = require('../common'); - if (!common.hasCrypto) common.skip('missing crypto'); +const fixtures = require('../common/fixtures'); + +// This test ensures that Node.js doesn't incur a segfault while accessing +// TLSWrap fields after the parent handle was destroyed. +// https://github.com/nodejs/node/issues/5108 const assert = require('assert'); const tls = require('tls'); -const fixtures = require('../common/fixtures'); const options = { key: fixtures.readKey('agent1-key.pem'), cert: fixtures.readKey('agent1-cert.pem') }; - const server = tls.createServer(options, function(s) { s.end('hello'); }).listen(0, function() { @@ -26,7 +28,6 @@ const server = tls.createServer(options, function(s) { }); }); - function putImmediate(client) { setImmediate(function() { if (client.ssl) { diff --git a/test/parallel/test-tty-stdin-end.js b/test/parallel/test-tty-stdin-end.js new file mode 100644 index 00000000000..c78f58446d0 --- /dev/null +++ b/test/parallel/test-tty-stdin-end.js @@ -0,0 +1,7 @@ +'use strict'; +require('../common'); + +// This test ensures that Node.js doesn't crash on `process.stdin.emit("end")`. +// https://github.com/nodejs/node/issues/1068 + +process.stdin.emit('end'); diff --git a/test/parallel/test-regress-GH-io-1811.js b/test/parallel/test-zlib-kmaxlength-rangeerror.js similarity index 76% rename from test/parallel/test-regress-GH-io-1811.js rename to test/parallel/test-zlib-kmaxlength-rangeerror.js index a8966da10ba..e8e47865f79 100644 --- a/test/parallel/test-regress-GH-io-1811.js +++ b/test/parallel/test-zlib-kmaxlength-rangeerror.js @@ -1,6 +1,10 @@ 'use strict'; - require('../common'); + +// This test ensures that zlib throws a RangeError if the final buffer needs to +// be larger than kMaxLength and concatenation fails. +// https://github.com/nodejs/node/pull/1811 + const assert = require('assert'); // Change kMaxLength for zlib to trigger the error without having to allocate diff --git a/test/sequential/sequential.status b/test/sequential/sequential.status index dae4bf37359..f9aff44c879 100644 --- a/test/sequential/sequential.status +++ b/test/sequential/sequential.status @@ -11,7 +11,6 @@ test-inspector-async-call-stack : PASS, FLAKY test-inspector-bindings : PASS, FLAKY test-inspector-debug-end : PASS, FLAKY test-inspector-async-hook-setup-at-signal: PASS, FLAKY -test-http2-ping-flood : PASS, FLAKY [$system==linux] diff --git a/test/sequential/test-fs-watch.js b/test/sequential/test-fs-watch.js index 91d750acd00..3c8ae0eba7d 100644 --- a/test/sequential/test-fs-watch.js +++ b/test/sequential/test-fs-watch.js @@ -122,13 +122,20 @@ tmpdir.refresh(); code: 'ERR_ASSERTION' }); oldhandle.close(); // clean up +} - assert.throws(function() { - const w = fs.watchFile(__filename, { persistent: false }, +{ + let oldhandle; + assert.throws(() => { + const w = fs.watchFile(__filename, + { persistent: false }, common.mustNotCall()); oldhandle = w._handle; w._handle = { stop: w._handle.stop }; w.stop(); - }, /^TypeError: Illegal invocation$/); + }, { + message: 'handle must be a StatWatcher', + code: 'ERR_ASSERTION' + }); oldhandle.stop(); // clean up } diff --git a/test/sequential/test-http2-ping-flood.js b/test/sequential/test-http2-ping-flood.js index 5b47d51be9c..b414aca8a47 100644 --- a/test/sequential/test-http2-ping-flood.js +++ b/test/sequential/test-http2-ping-flood.js @@ -4,8 +4,10 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); +const assert = require('assert'); const http2 = require('http2'); const net = require('net'); + const http2util = require('../common/http2'); // Test that ping flooding causes the session to be torn down @@ -15,13 +17,15 @@ const kPing = new http2util.PingFrame(); const server = http2.createServer(); +let interval; + server.on('stream', common.mustNotCall()); server.on('session', common.mustCall((session) => { - session.on('error', common.expectsError({ - code: 'ERR_HTTP2_ERROR', - message: - 'Flooding was detected in this HTTP/2 session, and it must be closed' - })); + session.on('error', (e) => { + assert.strictEqual(e.code, 'ERR_HTTP2_ERROR'); + assert(e.message.includes('Flooding was detected')); + clearInterval(interval); + }); session.on('close', common.mustCall(() => { server.close(); })); @@ -31,9 +35,7 @@ server.listen(0, common.mustCall(() => { const client = net.connect(server.address().port); // nghttp2 uses a limit of 10000 items in it's outbound queue. - // If this number is exceeded, a flooding error is raised. Set - // this lim higher to account for the ones that nghttp2 is - // successfully able to respond to. + // If this number is exceeded, a flooding error is raised. // TODO(jasnell): Unfortunately, this test is inherently flaky because // it is entirely dependent on how quickly the server is able to handle // the inbound frames and whether those just happen to overflow nghttp2's @@ -42,8 +44,10 @@ server.listen(0, common.mustCall(() => { client.on('connect', common.mustCall(() => { client.write(http2util.kClientMagic, () => { client.write(kSettings.data, () => { - for (let n = 0; n < 35000; n++) - client.write(kPing.data); + interval = setInterval(() => { + for (let n = 0; n < 10000; n++) + client.write(kPing.data); + }, 1); }); }); }));