diff --git a/.eslintrc.yaml b/.eslintrc.yaml index 0e7e9ccfcb73b8..99489d2e7d8589 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -137,8 +137,11 @@ rules: no-mixed-spaces-and-tabs: error no-multiple-empty-lines: [error, {max: 2, maxEOF: 0, maxBOF: 0}] no-restricted-syntax: [error, { + selector: "CallExpression[callee.object.name='assert'][callee.property.name='doesNotThrow']", + message: "Please replace `assert.doesNotThrow()` and add a comment next to the code instead." + }, { selector: "CallExpression[callee.object.name='assert'][callee.property.name='throws'][arguments.1.type='Literal']:not([arguments.1.regex])", - message: "use a regular expression for second argument of assert.throws()" + message: "Use a regular expression for second argument of assert.throws()" }, { selector: "CallExpression[callee.object.name='assert'][callee.property.name='throws'][arguments.length<2]", message: "assert.throws() must be invoked with at least two arguments." @@ -154,6 +157,7 @@ rules: }] no-tabs: error no-trailing-spaces: error + no-unsafe-finally: error object-curly-spacing: [error, always] one-var-declaration-per-line: error operator-linebreak: [error, after] diff --git a/BUILDING.md b/BUILDING.md index 74b5903ed22cd0..eda74fb70f41bc 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -39,7 +39,8 @@ in production. | System | Support type | Version | Architectures | Notes | |--------------|--------------|----------------------------------|----------------------|------------------| -| GNU/Linux | Tier 1 | kernel >= 2.6.32, glibc >= 2.12 | x64, arm, arm64 | | +| GNU/Linux | Tier 1 | kernel >= 2.6.32, glibc >= 2.12 | x64, arm | | +| GNU/Linux | Tier 1 | kernel >= 3.10, glibc >= 2.17 | arm64 | | | macOS | Tier 1 | >= 10.10 | x64 | | | Windows | Tier 1 | >= Windows 7/2008 R2 | x86, x64 | vs2017 | | SmartOS | Tier 2 | >= 15 < 16.4 | x86, x64 | see note1 | diff --git a/CHANGELOG.md b/CHANGELOG.md index ace79efd98eb37..74b83c56eb87f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,7 +29,8 @@ release. -9.8.0
+9.9.0
+9.8.0
9.7.1
9.7.0
9.6.1
diff --git a/COLLABORATOR_GUIDE.md b/COLLABORATOR_GUIDE.md index e08c84e77cbc11..973e9c3681f981 100644 --- a/COLLABORATOR_GUIDE.md +++ b/COLLABORATOR_GUIDE.md @@ -469,10 +469,11 @@ $ npm install -g node-core-utils $ git node land $PRID ``` -If it's the first time you ever use `node-core-utils`, you will be prompted -to type the password of your GitHub account in the console so the tool can -create the GitHub access token for you. If you do not want to do that, follow -[the guide of `node-core-utils`][node-core-utils-credentials] +If it's the first time you have used `node-core-utils`, you will be prompted +to type the password of your GitHub account and the two-factor authentication +code in the console so the tool can create the GitHub access token for you. +If you do not want to do that, follow +[the `node-core-utils` guide][node-core-utils-credentials] to set up your credentials manually. ### Technical HOWTO diff --git a/README.md b/README.md index 1e6be9a38cbe1b..4bab46ef3d54c9 100644 --- a/README.md +++ b/README.md @@ -291,8 +291,6 @@ For more information about the governance of the Node.js project, see ### Collaborators -* [abouthiroppy](https://github.com/abouthiroppy) - -**Yuta Hiroto** <hello@about-hiroppy.com> (he/him) * [addaleax](https://github.com/addaleax) - **Anna Henningsen** <anna@addaleax.net> (she/her) * [ak239](https://github.com/ak239) - @@ -367,6 +365,8 @@ For more information about the governance of the Node.js project, see **Guy Bedford** <guybedford@gmail.com> (he/him) * [hashseed](https://github.com/hashseed) - **Yang Guo** <yangguo@chromium.org> (he/him) +* [hiroppy](https://github.com/hiroppy) - +**Yuta Hiroto** <hello@hiroppy.me> (he/him) * [iarna](https://github.com/iarna) - **Rebecca Turner** <me@re-becca.org> * [imran-iq](https://github.com/imran-iq) - @@ -509,6 +509,8 @@ For more information about the governance of the Node.js project, see **Vse Mozhet Byt** <vsemozhetbyt@gmail.com> (he/him) * [watilde](https://github.com/watilde) - **Daijiro Wachi** <daijiro.wachi@gmail.com> (he/him) +* [watson](https://github.com/watson) - +**Thomas Watson** <w@tson.dk> * [whitlockjc](https://github.com/whitlockjc) - **Jeremy Whitlock** <jwhitlock@apache.org> * [XadillaX](https://github.com/XadillaX) - diff --git a/benchmark/assert/throws.js b/benchmark/assert/throws.js index bffde7cbc1fd94..2409d19206e353 100644 --- a/benchmark/assert/throws.js +++ b/benchmark/assert/throws.js @@ -26,6 +26,7 @@ function main({ n, method }) { case 'doesNotThrow': bench.start(); for (i = 0; i < n; ++i) { + // eslint-disable-next-line no-restricted-syntax assert.doesNotThrow(doesNotThrow); } bench.end(n); diff --git a/benchmark/http/_chunky_http_client.js b/benchmark/http/_chunky_http_client.js index a90535e489f4c9..7728a5d06c60aa 100644 --- a/benchmark/http/_chunky_http_client.js +++ b/benchmark/http/_chunky_http_client.js @@ -5,8 +5,8 @@ const common = require('../common.js'); const net = require('net'); const bench = common.createBenchmark(main, { - len: [1, 4, 8, 16, 32, 64, 128], - n: [5, 50, 500, 2000], + len: [1, 4, 8, 16, 32, 64, 128], + n: [5, 50, 500, 2000], type: ['send'], }); diff --git a/benchmark/querystring/querystring-stringify.js b/benchmark/querystring/querystring-stringify.js index cd1debd4df622d..9f025c922ad4e8 100644 --- a/benchmark/querystring/querystring-stringify.js +++ b/benchmark/querystring/querystring-stringify.js @@ -17,7 +17,7 @@ function main({ type, n }) { encodemany: { '\u0080\u0083\u0089': 'bar', '\u008C\u008E\u0099': 'quux', - xyzzy: '\u00A5q\u00A3r' + 'xyzzy': '\u00A5q\u00A3r' }, encodelast: { foo: 'bar', diff --git a/benchmark/tls/tls-connect.js b/benchmark/tls/tls-connect.js index da0f5e08d5e6db..524d7468d000a1 100644 --- a/benchmark/tls/tls-connect.js +++ b/benchmark/tls/tls-connect.js @@ -1,7 +1,7 @@ 'use strict'; -var fs = require('fs'), - path = require('path'), - tls = require('tls'); +const fs = require('fs'); +const path = require('path'); +const tls = require('tls'); const common = require('../common.js'); const bench = common.createBenchmark(main, { diff --git a/benchmark/url/legacy-vs-whatwg-url-searchparams-parse.js b/benchmark/url/legacy-vs-whatwg-url-searchparams-parse.js index e915ceb54f917f..6b054d0b2a1f1a 100644 --- a/benchmark/url/legacy-vs-whatwg-url-searchparams-parse.js +++ b/benchmark/url/legacy-vs-whatwg-url-searchparams-parse.js @@ -2,10 +2,10 @@ const common = require('../common.js'); const { URLSearchParams } = require('url'); const querystring = require('querystring'); -const inputs = require('../fixtures/url-inputs.js').searchParams; +const searchParams = require('../fixtures/url-inputs.js').searchParams; const bench = common.createBenchmark(main, { - type: Object.keys(inputs), + searchParam: Object.keys(searchParams), method: ['legacy', 'whatwg'], n: [1e6] }); @@ -19,27 +19,27 @@ function useLegacy(n, input) { bench.end(n); } -function useWHATWG(n, input) { - new URLSearchParams(input); +function useWHATWG(n, param) { + new URLSearchParams(param); bench.start(); for (var i = 0; i < n; i += 1) { - new URLSearchParams(input); + new URLSearchParams(param); } bench.end(n); } -function main({ type, n, method }) { - const input = inputs[type]; - if (!input) { - throw new Error(`Unknown input type "${type}"`); +function main({ searchParam, n, method }) { + const param = searchParams[searchParam]; + if (!param) { + throw new Error(`Unknown search parameter type "${searchParam}"`); } switch (method) { case 'legacy': - useLegacy(n, input); + useLegacy(n, param); break; case 'whatwg': - useWHATWG(n, input); + useWHATWG(n, param); break; default: throw new Error(`Unknown method ${method}`); diff --git a/benchmark/url/legacy-vs-whatwg-url-searchparams-serialize.js b/benchmark/url/legacy-vs-whatwg-url-searchparams-serialize.js index 8fe3e546f0780d..54fdd956544886 100644 --- a/benchmark/url/legacy-vs-whatwg-url-searchparams-serialize.js +++ b/benchmark/url/legacy-vs-whatwg-url-searchparams-serialize.js @@ -2,10 +2,10 @@ const common = require('../common.js'); const { URLSearchParams } = require('url'); const querystring = require('querystring'); -const inputs = require('../fixtures/url-inputs.js').searchParams; +const searchParams = require('../fixtures/url-inputs.js').searchParams; const bench = common.createBenchmark(main, { - type: Object.keys(inputs), + searchParam: Object.keys(searchParams), method: ['legacy', 'whatwg'], n: [1e6] }); @@ -20,8 +20,8 @@ function useLegacy(n, input, prop) { bench.end(n); } -function useWHATWG(n, input, prop) { - const obj = new URLSearchParams(input); +function useWHATWG(n, param, prop) { + const obj = new URLSearchParams(param); obj.toString(); bench.start(); for (var i = 0; i < n; i += 1) { @@ -30,18 +30,18 @@ function useWHATWG(n, input, prop) { bench.end(n); } -function main({ type, n, method }) { - const input = inputs[type]; - if (!input) { - throw new Error(`Unknown input type "${type}"`); +function main({ searchParam, n, method }) { + const param = searchParams[searchParam]; + if (!param) { + throw new Error(`Unknown search parameter type "${searchParam}"`); } switch (method) { case 'legacy': - useLegacy(n, input); + useLegacy(n, param); break; case 'whatwg': - useWHATWG(n, input); + useWHATWG(n, param); break; default: throw new Error(`Unknown method ${method}`); diff --git a/benchmark/url/url-searchparams-iteration.js b/benchmark/url/url-searchparams-iteration.js index cae2ef5df61956..244c95502bfffb 100644 --- a/benchmark/url/url-searchparams-iteration.js +++ b/benchmark/url/url-searchparams-iteration.js @@ -4,7 +4,7 @@ const assert = require('assert'); const { URLSearchParams } = require('url'); const bench = common.createBenchmark(main, { - method: ['forEach', 'iterator'], + loopMethod: ['forEach', 'iterator'], n: [1e6] }); @@ -44,8 +44,8 @@ function iterator(n) { assert.strictEqual(noDead[1], '3rd'); } -function main({ method, n }) { - switch (method) { +function main({ loopMethod, n }) { + switch (loopMethod) { case 'forEach': forEach(n); break; @@ -53,6 +53,6 @@ function main({ method, n }) { iterator(n); break; default: - throw new Error(`Unknown method ${method}`); + throw new Error(`Unknown method ${loopMethod}`); } } diff --git a/benchmark/url/url-searchparams-read.js b/benchmark/url/url-searchparams-read.js index 0cf66dabbc36dc..2eb0a4f21350dc 100644 --- a/benchmark/url/url-searchparams-read.js +++ b/benchmark/url/url-searchparams-read.js @@ -3,21 +3,20 @@ const common = require('../common.js'); const { URLSearchParams } = require('url'); const bench = common.createBenchmark(main, { - method: ['get', 'getAll', 'has'], + accessMethod: ['get', 'getAll', 'has'], param: ['one', 'two', 'three', 'nonexistent'], n: [2e7] }); const str = 'one=single&two=first&three=first&two=2nd&three=2nd&three=3rd'; -function main({ method, param, n }) { +function main({ accessMethod, param, n }) { const params = new URLSearchParams(str); - const fn = params[method]; - if (!fn) - throw new Error(`Unknown method ${method}`); + if (!params[accessMethod]) + throw new Error(`Unknown method ${accessMethod}`); bench.start(); for (var i = 0; i < n; i += 1) - fn(param); + params[accessMethod](param); bench.end(n); } diff --git a/benchmark/url/whatwg-url-idna.js b/benchmark/url/whatwg-url-idna.js index c1e3d4a0b85cec..b67a08da7a88e0 100644 --- a/benchmark/url/whatwg-url-idna.js +++ b/benchmark/url/whatwg-url-idna.js @@ -2,7 +2,7 @@ const common = require('../common.js'); const { domainToASCII, domainToUnicode } = require('url'); -const inputs = { +const domains = { empty: { ascii: '', unicode: '' @@ -26,13 +26,13 @@ const inputs = { }; const bench = common.createBenchmark(main, { - input: Object.keys(inputs), + domain: Object.keys(domains), to: ['ascii', 'unicode'], n: [5e6] }); -function main({ n, to, input }) { - const value = inputs[input][to]; +function main({ n, to, domain }) { + const value = domains[domain][to]; const method = to === 'ascii' ? domainToASCII : domainToUnicode; bench.start(); diff --git a/common.gypi b/common.gypi index aaae133e1ac188..5a5409cb0c610f 100644 --- a/common.gypi +++ b/common.gypi @@ -27,7 +27,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.21', + 'v8_embedder_string': '-node.22', # Enable disassembler for `--print-code` v8 options 'v8_enable_disassembler': 1, diff --git a/deps/v8/src/deoptimizer.cc b/deps/v8/src/deoptimizer.cc index 93a21a7b3adf5c..21b36ba49c9149 100644 --- a/deps/v8/src/deoptimizer.cc +++ b/deps/v8/src/deoptimizer.cc @@ -144,6 +144,50 @@ void Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm, generator.Generate(); } +namespace { +class ActivationsFinder : public ThreadVisitor { + public: + explicit ActivationsFinder(std::set* codes, + Code* topmost_optimized_code, + bool safe_to_deopt_topmost_optimized_code) + : codes_(codes) { +#ifdef DEBUG + topmost_ = topmost_optimized_code; + safe_to_deopt_ = safe_to_deopt_topmost_optimized_code; +#endif + } + + // Find the frames with activations of codes marked for deoptimization, search + // for the trampoline to the deoptimizer call respective to each code, and use + // it to replace the current pc on the stack. + void VisitThread(Isolate* isolate, ThreadLocalTop* top) { + for (StackFrameIterator it(isolate, top); !it.done(); it.Advance()) { + if (it.frame()->type() == StackFrame::OPTIMIZED) { + Code* code = it.frame()->LookupCode(); + if (code->kind() == Code::OPTIMIZED_FUNCTION && + code->marked_for_deoptimization()) { + codes_->erase(code); + // Obtain the trampoline to the deoptimizer call. + SafepointEntry safepoint = code->GetSafepointEntry(it.frame()->pc()); + int trampoline_pc = safepoint.trampoline_pc(); + DCHECK_IMPLIES(code == topmost_, safe_to_deopt_); + // Replace the current pc on the stack with the trampoline. + it.frame()->set_pc(code->instruction_start() + trampoline_pc); + } + } + } + } + + private: + std::set* codes_; + +#ifdef DEBUG + Code* topmost_; + bool safe_to_deopt_; +#endif +}; +} // namespace + void Deoptimizer::VisitAllOptimizedFunctionsForContext( Context* context, OptimizedFunctionVisitor* visitor) { DisallowHeapAllocation no_allocation; @@ -264,9 +308,9 @@ void Deoptimizer::DeoptimizeMarkedCodeForContext(Context* context) { VisitAllOptimizedFunctionsForContext(context, &unlinker); Isolate* isolate = context->GetHeap()->isolate(); -#ifdef DEBUG Code* topmost_optimized_code = NULL; bool safe_to_deopt_topmost_optimized_code = false; +#ifdef DEBUG // Make sure all activations of optimized code can deopt at their current PC. // The topmost optimized code has special handling because it cannot be // deoptimized due to weak object dependency. @@ -304,6 +348,10 @@ void Deoptimizer::DeoptimizeMarkedCodeForContext(Context* context) { } #endif + // We will use this set to mark those Code objects that are marked for + // deoptimization and have not been found in stack frames. + std::set codes; + // Move marked code from the optimized code list to the deoptimized // code list. // Walk over all optimized code objects in this native context. @@ -335,25 +383,14 @@ void Deoptimizer::DeoptimizeMarkedCodeForContext(Context* context) { element = next; } - // Finds the with activations of codes marked for deoptimization, search for - // the trampoline to the deoptimizer call respective to each code, and use it - // to replace the current pc on the stack. - for (StackFrameIterator it(isolate, isolate->thread_local_top()); !it.done(); - it.Advance()) { - if (it.frame()->type() == StackFrame::OPTIMIZED) { - Code* code = it.frame()->LookupCode(); - if (code->kind() == Code::OPTIMIZED_FUNCTION && - code->marked_for_deoptimization()) { - // Obtain the trampoline to the deoptimizer call. - SafepointEntry safepoint = code->GetSafepointEntry(it.frame()->pc()); - int trampoline_pc = safepoint.trampoline_pc(); - DCHECK_IMPLIES(code == topmost_optimized_code, - safe_to_deopt_topmost_optimized_code); - // Replace the current pc on the stack with the trampoline. - it.frame()->set_pc(code->instruction_start() + trampoline_pc); - } - } - } + ActivationsFinder visitor(&codes, topmost_optimized_code, + safe_to_deopt_topmost_optimized_code); + // Iterate over the stack of this thread. + visitor.VisitThread(isolate, isolate->thread_local_top()); + // In addition to iterate over the stack of this thread, we also + // need to consider all the other threads as they may also use + // the code currently beings deoptimized. + isolate->thread_manager()->IterateArchivedThreads(&visitor); } diff --git a/deps/v8/src/profiler/cpu-profiler.cc b/deps/v8/src/profiler/cpu-profiler.cc index 80d488f12c527f..1be42952d795a5 100644 --- a/deps/v8/src/profiler/cpu-profiler.cc +++ b/deps/v8/src/profiler/cpu-profiler.cc @@ -162,13 +162,16 @@ void ProfilerEventsProcessor::Run() { if (nextSampleTime > now) { #if V8_OS_WIN - // Do not use Sleep on Windows as it is very imprecise. - // Could be up to 16ms jitter, which is unacceptable for the purpose. - while (base::TimeTicks::HighResolutionNow() < nextSampleTime) { - } -#else - base::OS::Sleep(nextSampleTime - now); + if (nextSampleTime - now < base::TimeDelta::FromMilliseconds(100)) { + // Do not use Sleep on Windows as it is very imprecise, with up to 16ms + // jitter, which is unacceptable for short profile intervals. + while (base::TimeTicks::HighResolutionNow() < nextSampleTime) { + } + } else // NOLINT #endif + { + base::OS::Sleep(nextSampleTime - now); + } } // Schedule next sample. sampler_ is NULL in tests. diff --git a/deps/v8/test/cctest/test-lockers.cc b/deps/v8/test/cctest/test-lockers.cc index a310bfd68456c4..36a9f11ee27773 100644 --- a/deps/v8/test/cctest/test-lockers.cc +++ b/deps/v8/test/cctest/test-lockers.cc @@ -55,6 +55,244 @@ using ::v8::Value; using ::v8::V8; +namespace { + +class DeoptimizeCodeThread : public v8::base::Thread { + public: + DeoptimizeCodeThread(v8::Isolate* isolate, v8::Local context, + const char* trigger) + : Thread(Options("DeoptimizeCodeThread")), + isolate_(isolate), + context_(isolate, context), + source_(trigger) {} + + void Run() { + v8::Locker locker(isolate_); + isolate_->Enter(); + v8::HandleScope handle_scope(isolate_); + v8::Local context = + v8::Local::New(isolate_, context_); + v8::Context::Scope context_scope(context); + CHECK_EQ(isolate_, v8::Isolate::GetCurrent()); + // This code triggers deoptimization of some function that will be + // used in a different thread. + CompileRun(source_); + isolate_->Exit(); + } + + private: + v8::Isolate* isolate_; + Persistent context_; + // The code that triggers the deoptimization. + const char* source_; +}; + +void UnlockForDeoptimization(const v8::FunctionCallbackInfo& args) { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + // Gets the pointer to the thread that will trigger the deoptimization of the + // code. + DeoptimizeCodeThread* deoptimizer = + reinterpret_cast(isolate->GetData(0)); + { + // Exits and unlocks the isolate. + isolate->Exit(); + v8::Unlocker unlocker(isolate); + // Starts the deoptimizing thread. + deoptimizer->Start(); + // Waits for deoptimization to finish. + deoptimizer->Join(); + } + // The deoptimizing thread has finished its work, and the isolate + // will now be used by the current thread. + isolate->Enter(); +} + +void UnlockForDeoptimizationIfReady( + const v8::FunctionCallbackInfo& args) { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + bool* ready_to_deoptimize = reinterpret_cast(isolate->GetData(1)); + if (*ready_to_deoptimize) { + // The test should enter here only once, so put the flag back to false. + *ready_to_deoptimize = false; + // Gets the pointer to the thread that will trigger the deoptimization of + // the code. + DeoptimizeCodeThread* deoptimizer = + reinterpret_cast(isolate->GetData(0)); + { + // Exits and unlocks the thread. + isolate->Exit(); + v8::Unlocker unlocker(isolate); + // Starts the thread that deoptimizes the function. + deoptimizer->Start(); + // Waits for the deoptimizing thread to finish. + deoptimizer->Join(); + } + // The deoptimizing thread has finished its work, and the isolate + // will now be used by the current thread. + isolate->Enter(); + } +} +} // namespace + +TEST(LazyDeoptimizationMultithread) { + i::FLAG_allow_natives_syntax = true; + v8::Isolate::CreateParams create_params; + create_params.array_buffer_allocator = CcTest::array_buffer_allocator(); + v8::Isolate* isolate = v8::Isolate::New(create_params); + { + v8::Locker locker(isolate); + v8::Isolate::Scope isolate_scope(isolate); + v8::HandleScope scope(isolate); + v8::Local context = v8::Context::New(isolate); + const char* trigger_deopt = "obj = { y: 0, x: 1 };"; + + // We use the isolate to pass arguments to the UnlockForDeoptimization + // function. Namely, we pass a pointer to the deoptimizing thread. + DeoptimizeCodeThread deoptimize_thread(isolate, context, trigger_deopt); + isolate->SetData(0, &deoptimize_thread); + v8::Context::Scope context_scope(context); + + // Create the function templace for C++ code that is invoked from + // JavaScript code. + Local fun_templ = + v8::FunctionTemplate::New(isolate, UnlockForDeoptimization); + Local fun = fun_templ->GetFunction(context).ToLocalChecked(); + CHECK(context->Global() + ->Set(context, v8_str("unlock_for_deoptimization"), fun) + .FromJust()); + + // Optimizes a function f, which will be deoptimized in another + // thread. + CompileRun( + "var b = false; var obj = { x: 1 };" + "function f() { g(); return obj.x; }" + "function g() { if (b) { unlock_for_deoptimization(); } }" + "%NeverOptimizeFunction(g);" + "f(); f(); %OptimizeFunctionOnNextCall(f);" + "f();"); + + // Trigger the unlocking. + Local v = CompileRun("b = true; f();"); + + // Once the isolate has been unlocked, the thread will wait for the + // other thread to finish its task. Once this happens, this thread + // continues with its execution, that is, with the execution of the + // function g, which then returns to f. The function f should have + // also been deoptimized. If the replacement did not happen on this + // thread's stack, then the test will fail here. + CHECK(v->IsNumber()); + CHECK_EQ(1, static_cast(v->NumberValue(context).FromJust())); + } + isolate->Dispose(); +} + +TEST(LazyDeoptimizationMultithreadWithNatives) { + i::FLAG_allow_natives_syntax = true; + v8::Isolate::CreateParams create_params; + create_params.array_buffer_allocator = CcTest::array_buffer_allocator(); + v8::Isolate* isolate = v8::Isolate::New(create_params); + { + v8::Locker locker(isolate); + v8::Isolate::Scope isolate_scope(isolate); + v8::HandleScope scope(isolate); + v8::Local context = v8::Context::New(isolate); + const char* trigger_deopt = "%DeoptimizeFunction(f);"; + + // We use the isolate to pass arguments to the UnlockForDeoptimization + // function. Namely, we pass a pointer to the deoptimizing thread. + DeoptimizeCodeThread deoptimize_thread(isolate, context, trigger_deopt); + isolate->SetData(0, &deoptimize_thread); + bool ready_to_deopt = false; + isolate->SetData(1, &ready_to_deopt); + v8::Context::Scope context_scope(context); + + // Create the function templace for C++ code that is invoked from + // JavaScript code. + Local fun_templ = + v8::FunctionTemplate::New(isolate, UnlockForDeoptimizationIfReady); + Local fun = fun_templ->GetFunction(context).ToLocalChecked(); + CHECK(context->Global() + ->Set(context, v8_str("unlock_for_deoptimization"), fun) + .FromJust()); + + // Optimizes a function f, which will be deoptimized in another + // thread. + CompileRun( + "var obj = { x: 1 };" + "function f() { g(); return obj.x;}" + "function g() { " + " unlock_for_deoptimization(); }" + "%NeverOptimizeFunction(g);" + "f(); f(); %OptimizeFunctionOnNextCall(f);"); + + // Trigger the unlocking. + ready_to_deopt = true; + isolate->SetData(1, &ready_to_deopt); + Local v = CompileRun("f();"); + + // Once the isolate has been unlocked, the thread will wait for the + // other thread to finish its task. Once this happens, this thread + // continues with its execution, that is, with the execution of the + // function g, which then returns to f. The function f should have + // also been deoptimized. Otherwise, the test will fail here. + CHECK(v->IsNumber()); + CHECK_EQ(1, static_cast(v->NumberValue(context).FromJust())); + } + isolate->Dispose(); +} + +TEST(EagerDeoptimizationMultithread) { + i::FLAG_allow_natives_syntax = true; + v8::Isolate::CreateParams create_params; + create_params.array_buffer_allocator = CcTest::array_buffer_allocator(); + v8::Isolate* isolate = v8::Isolate::New(create_params); + { + v8::Locker locker(isolate); + v8::Isolate::Scope isolate_scope(isolate); + v8::HandleScope scope(isolate); + v8::Local context = v8::Context::New(isolate); + const char* trigger_deopt = "f({y: 0, x: 1});"; + + // We use the isolate to pass arguments to the UnlockForDeoptimization + // function. Namely, we pass a pointer to the deoptimizing thread. + DeoptimizeCodeThread deoptimize_thread(isolate, context, trigger_deopt); + isolate->SetData(0, &deoptimize_thread); + bool ready_to_deopt = false; + isolate->SetData(1, &ready_to_deopt); + v8::Context::Scope context_scope(context); + + // Create the function templace for C++ code that is invoked from + // JavaScript code. + Local fun_templ = + v8::FunctionTemplate::New(isolate, UnlockForDeoptimizationIfReady); + Local fun = fun_templ->GetFunction(context).ToLocalChecked(); + CHECK(context->Global() + ->Set(context, v8_str("unlock_for_deoptimization"), fun) + .FromJust()); + + // Optimizes a function f, which will be deoptimized by another thread. + CompileRun( + "function f(obj) { unlock_for_deoptimization(); return obj.x; }" + "f({x: 1}); f({x: 1});" + "%OptimizeFunctionOnNextCall(f);" + "f({x: 1});"); + + // Trigger the unlocking. + ready_to_deopt = true; + isolate->SetData(1, &ready_to_deopt); + Local v = CompileRun("f({x: 1});"); + + // Once the isolate has been unlocked, the thread will wait for the + // other thread to finish its task. Once this happens, this thread + // continues with its execution, that is, with the execution of the + // function g, which then returns to f. The function f should have + // also been deoptimized. Otherwise, the test will fail here. + CHECK(v->IsNumber()); + CHECK_EQ(1, static_cast(v->NumberValue(context).FromJust())); + } + isolate->Dispose(); +} + // Migrating an isolate class KangarooThread : public v8::base::Thread { public: diff --git a/doc/.eslintrc.yaml b/doc/.eslintrc.yaml index c8c1612e3a100b..7b38afec10276a 100644 --- a/doc/.eslintrc.yaml +++ b/doc/.eslintrc.yaml @@ -12,6 +12,7 @@ rules: no-var: error prefer-const: error prefer-rest-params: error + prefer-template: error # Stylistic Issues no-multiple-empty-lines: [error, {max: 1, maxEOF: 0, maxBOF: 0}] diff --git a/doc/STYLE_GUIDE.md b/doc/STYLE_GUIDE.md index 7fc2d6e0b1bb13..009b0ee2b5ec4b 100644 --- a/doc/STYLE_GUIDE.md +++ b/doc/STYLE_GUIDE.md @@ -13,12 +13,10 @@ * American English spelling is preferred. "Capitalize" vs. "Capitalise", "color" vs. "colour", etc. * Use [serial commas][]. -* Generally avoid personal pronouns in reference documentation ("I", "you", - "we"). - * Pronouns are acceptable in more colloquial documentation, like guides. - * Use gender-neutral pronouns and mass nouns. Non-comprehensive - examples: - * OK: "they", "their", "them", "folks", "people", "developers", "cats" +* Avoid personal pronouns in reference documentation ("I", "you", "we"). + * Personal pronouns are acceptable in colloquial documentation such as guides. + * Use gender-neutral pronouns and gender-neutral plural nouns. + * OK: "they", "their", "them", "folks", "people", "developers" * NOT OK: "his", "hers", "him", "her", "guys", "dudes" * When combining wrapping elements (parentheses and quotes), terminal punctuation should be placed: diff --git a/doc/api/assert.md b/doc/api/assert.md index 6935a9db4bda64..2ecf628e4aa80a 100644 --- a/doc/api/assert.md +++ b/doc/api/assert.md @@ -7,6 +7,93 @@ The `assert` module provides a simple set of assertion tests that can be used to test invariants. +A `strict` and a `legacy` mode exist, while it is recommended to only use +[`strict mode`][]. + +For more information about the used equality comparisons see +[MDN's guide on equality comparisons and sameness][mdn-equality-guide]. + +## Strict mode + + +When using the `strict mode`, any `assert` function will use the equality used in +the strict function mode. So [`assert.deepEqual()`][] will, for example, work the +same as [`assert.deepStrictEqual()`][]. + +On top of that, error messages which involve objects produce an error diff +instead of displaying both objects. That is not the case for the legacy mode. + +It can be accessed using: + +```js +const assert = require('assert').strict; +``` + +Example error diff (the `expected`, `actual`, and `Lines skipped` will be on a +single row): + +```js +const assert = require('assert').strict; + +assert.deepEqual([[[1, 2, 3]], 4, 5], [[[1, 2, '3']], 4, 5]); +``` + +```diff +AssertionError [ERR_ASSERTION]: Input A expected to deepStrictEqual input B: ++ expected +- actual +... Lines skipped + + [ + [ +... + 2, +- 3 ++ '3' + ], +... + 5 + ] +``` + +To deactivate the colors, use the `NODE_DISABLE_COLORS` environment variable. +Please note that this will also deactivate the colors in the REPL. + +## Legacy mode + +> Stability: 0 - Deprecated: Use strict mode instead. + +When accessing `assert` directly instead of using the `strict` property, the +[Abstract Equality Comparison][] will be used for any function without a +"strict" in its name (e.g. [`assert.deepEqual()`][]). + +It can be accessed using: + +```js +const assert = require('assert'); +``` + +It is recommended to use the [`strict mode`][] instead as the +[Abstract Equality Comparison][] can often have surprising results. Especially +in case of [`assert.deepEqual()`][] as the used comparison rules there are very +lax. + +E.g. + +```js +// WARNING: This does not throw an AssertionError! +assert.deepEqual(/a/gi, new Date()); +``` + ## assert(value[, message]) ```js assert.doesNotThrow( () => { @@ -246,6 +359,7 @@ assert.doesNotThrow( However, the following will result in an `AssertionError` with the message 'Got unwanted exception (TypeError)..': + ```js assert.doesNotThrow( () => { @@ -259,6 +373,7 @@ If an `AssertionError` is thrown and a value is provided for the `message` parameter, the value of `message` will be appended to the `AssertionError` message: + ```js assert.doesNotThrow( () => { @@ -278,6 +393,14 @@ added: v0.1.21 * `expected` {any} * `message` {any} +**Strict mode** + +An alias of [`assert.strictEqual()`][]. + +**Legacy mode** + +> Stability: 0 - Deprecated: Use [`assert.strictEqual()`][] instead. + Tests shallow, coercive equality between the `actual` and `expected` parameters using the [Abstract Equality Comparison][] ( `==` ). @@ -298,7 +421,7 @@ assert.equal({ a: { b: 1 } }, { a: { b: 1 } }); If the values are not equal, an `AssertionError` is thrown with a `message` property set equal to the value of the `message` parameter. If the `message` parameter is undefined, a default error message is assigned. If the `message` -parameter is an instance of an `Error` then it will be thrown instead of the +parameter is an instance of an [`Error`][] then it will be thrown instead of the `AssertionError`. ## assert.fail([message]) @@ -314,7 +437,7 @@ added: v0.1.21 Throws an `AssertionError`. If `message` is falsy, the error message is set as the values of `actual` and `expected` separated by the provided `operator`. If -the `message` parameter is an instance of an `Error` then it will be thrown +the `message` parameter is an instance of an [`Error`][] then it will be thrown instead of the `AssertionError`. If just the two `actual` and `expected` arguments are provided, `operator` will default to `'!='`. If `message` is provided only it will be used as the error message, the other arguments will be @@ -324,7 +447,7 @@ all stack frames above that function will be removed from stacktrace (see `Failed` will be used. ```js -const assert = require('assert'); +const assert = require('assert').strict; assert.fail(1, 2, undefined, '>'); // AssertionError [ERR_ASSERTION]: 1 > 2 @@ -375,7 +498,7 @@ Throws `value` if `value` is truthy. This is useful when testing the `error` argument in callbacks. ```js -const assert = require('assert'); +const assert = require('assert').strict; assert.ifError(null); // OK @@ -413,6 +536,14 @@ changes: * `expected` {any} * `message` {any} +**Strict mode** + +An alias of [`assert.notDeepStrictEqual()`][]. + +**Legacy mode** + +> Stability: 0 - Deprecated: Use [`assert.notDeepStrictEqual()`][] instead. + Tests for any deep inequality. Opposite of [`assert.deepEqual()`][]. ```js @@ -451,7 +582,7 @@ assert.notDeepEqual(obj1, obj4); If the values are deeply equal, an `AssertionError` is thrown with a `message` property set equal to the value of the `message` parameter. If the `message` parameter is undefined, a default error message is assigned. If the `message` -parameter is an instance of an `Error` then it will be thrown instead of the +parameter is an instance of an [`Error`][] then it will be thrown instead of the `AssertionError`. ## assert.notDeepStrictEqual(actual, expected[, message]) @@ -489,10 +620,7 @@ changes: Tests for deep strict inequality. Opposite of [`assert.deepStrictEqual()`][]. ```js -const assert = require('assert'); - -assert.notDeepEqual({ a: 1 }, { a: '1' }); -// AssertionError: { a: 1 } notDeepEqual { a: '1' } +const assert = require('assert').strict; assert.notDeepStrictEqual({ a: 1 }, { a: '1' }); // OK @@ -501,8 +629,8 @@ assert.notDeepStrictEqual({ a: 1 }, { a: '1' }); If the values are deeply and strictly equal, an `AssertionError` is thrown with a `message` property set equal to the value of the `message` parameter. If the `message` parameter is undefined, a default error message is assigned. If the -`message` parameter is an instance of an `Error` then it will be thrown instead -of the `AssertionError`. +`message` parameter is an instance of an [`Error`][] then it will be thrown +instead of the `AssertionError`. ## assert.notEqual(actual, expected[, message]) * `block` {Function} -* `error` {RegExp|Function} +* `error` {RegExp|Function|object} * `message` {any} Expects the function `block` to throw an error. -If specified, `error` can be a constructor, [`RegExp`][], or validation -function. +If specified, `error` can be a constructor, [`RegExp`][], a validation +function, or an object where each property will be tested for. If specified, `message` will be the message provided by the `AssertionError` if the block fails to throw. @@ -658,12 +797,15 @@ assert.throws( Validate error message using [`RegExp`][]: +Using a regular expression runs `.toString` on the error object, and will +therefore also include the error name. + ```js assert.throws( () => { throw new Error('Wrong value'); }, - /value/ + /^Error: Wrong value$/ ); ``` @@ -683,19 +825,61 @@ assert.throws( ); ``` +Custom error object / error instance: + +```js +assert.throws( + () => { + const err = new TypeError('Wrong value'); + err.code = 404; + throw err; + }, + { + name: 'TypeError', + message: 'Wrong value' + // Note that only properties on the error object will be tested! + } +); +``` + Note that `error` can not be a string. If a string is provided as the second argument, then `error` is assumed to be omitted and the string will be used for -`message` instead. This can lead to easy-to-miss mistakes: +`message` instead. This can lead to easy-to-miss mistakes. Please read the +example below carefully if using a string as the second argument gets +considered: ```js -// THIS IS A MISTAKE! DO NOT DO THIS! -assert.throws(myFunction, 'missing foo', 'did not throw with expected message'); - -// Do this instead. -assert.throws(myFunction, /missing foo/, 'did not throw with expected message'); +function throwingFirst() { + throw new Error('First'); +} +function throwingSecond() { + throw new Error('Second'); +} +function notThrowing() {} + +// The second argument is a string and the input function threw an Error. +// In that case both cases do not throw as neither is going to try to +// match for the error message thrown by the input function! +assert.throws(throwingFirst, 'Second'); +assert.throws(throwingSecond, 'Second'); + +// The string is only used (as message) in case the function does not throw: +assert.throws(notThrowing, 'Second'); +// AssertionError [ERR_ASSERTION]: Missing expected exception: Second + +// If it was intended to match for the error message do this instead: +assert.throws(throwingSecond, /Second$/); +// Does not throw because the error messages match. +assert.throws(throwingFirst, /Second$/); +// Throws a error: +// Error: First +// at throwingFirst (repl:2:9) ``` +Due to the confusing notation, it is recommended not to use a string as the +second argument. This might lead to difficult-to-spot errors. + ## Caveats For the following cases, consider using ES2015 [`Object.is()`][], @@ -729,15 +913,21 @@ For more information, see [`Set`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set [`Symbol`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol [`TypeError`]: errors.html#errors_class_typeerror +[`WeakMap`]: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/WeakMap +[`WeakSet`]: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/WeakSet [`assert.deepEqual()`]: #assert_assert_deepequal_actual_expected_message [`assert.deepStrictEqual()`]: #assert_assert_deepstrictequal_actual_expected_message +[`assert.notDeepStrictEqual()`]: #assert_assert_notdeepstrictequal_actual_expected_message +[`assert.notStrictEqual()`]: #assert_assert_notstrictequal_actual_expected_message [`assert.ok()`]: #assert_assert_ok_value_message +[`assert.strictEqual()`]: #assert_assert_strictequal_actual_expected_message [`assert.throws()`]: #assert_assert_throws_block_error_message +[`strict mode`]: #assert_strict_mode [Abstract Equality Comparison]: https://tc39.github.io/ecma262/#sec-abstract-equality-comparison [Object.prototype.toString()]: https://tc39.github.io/ecma262/#sec-object.prototype.tostring [SameValueZero]: https://tc39.github.io/ecma262/#sec-samevaluezero +[SameValue Comparison]: https://tc39.github.io/ecma262/#sec-samevalue [Strict Equality Comparison]: https://tc39.github.io/ecma262/#sec-strict-equality-comparison -[caveats]: #assert_caveats [enumerable "own" properties]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Enumerability_and_ownership_of_properties [mdn-equality-guide]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness [prototype-spec]: https://tc39.github.io/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots diff --git a/doc/api/async_hooks.md b/doc/api/async_hooks.md index 15bdf56e365de9..1a162a038a6831 100644 --- a/doc/api/async_hooks.md +++ b/doc/api/async_hooks.md @@ -147,10 +147,10 @@ unintentional side effects. Because printing to the console is an asynchronous operation, `console.log()` will cause the AsyncHooks callbacks to be called. Using `console.log()` or similar asynchronous operations inside an AsyncHooks callback function will thus -cause an infinite recursion. An easily solution to this when debugging is -to use a synchronous logging operation such as `fs.writeSync(1, msg)`. This -will print to stdout because `1` is the file descriptor for stdout and will -not invoke AsyncHooks recursively because it is synchronous. +cause an infinite recursion. An easy solution to this when debugging is to use a +synchronous logging operation such as `fs.writeSync(1, msg)`. This will print to +stdout because `1` is the file descriptor for stdout and will not invoke +AsyncHooks recursively because it is synchronous. ```js const fs = require('fs'); @@ -587,8 +587,8 @@ JavaScript API so that all the appropriate callbacks are called. ### `class AsyncResource()` -The class `AsyncResource` was designed to be extended by the embedder's async -resources. Using this users can easily trigger the lifetime events of their +The class `AsyncResource` is designed to be extended by the embedder's async +resources. Using this, users can easily trigger the lifetime events of their own resources. The `init` hook will trigger when an `AsyncResource` is instantiated. diff --git a/doc/api/buffer.md b/doc/api/buffer.md index 2b0ce95afa2f76..da46fa7c2e4341 100644 --- a/doc/api/buffer.md +++ b/doc/api/buffer.md @@ -22,8 +22,6 @@ resized. The `Buffer` class is a global within Node.js, making it unlikely that one would need to ever use `require('buffer').Buffer`. -Examples: - ```js // Creates a zero-filled Buffer of length 10. const buf1 = Buffer.alloc(10); @@ -163,11 +161,10 @@ Example: ```js const buf = Buffer.from('hello world', 'ascii'); -// Prints: 68656c6c6f20776f726c64 console.log(buf.toString('hex')); - -// Prints: aGVsbG8gd29ybGQ= +// Prints: 68656c6c6f20776f726c64 console.log(buf.toString('base64')); +// Prints: aGVsbG8gd29ybGQ= ``` The character encodings currently supported by Node.js include: @@ -241,23 +238,20 @@ arr[1] = 4000; // Copies the contents of `arr` const buf1 = Buffer.from(arr); - // Shares memory with `arr` const buf2 = Buffer.from(arr.buffer); -// Prints: console.log(buf1); - -// Prints: +// Prints: console.log(buf2); +// Prints: arr[1] = 6000; -// Prints: console.log(buf1); - -// Prints: +// Prints: console.log(buf2); +// Prints: ``` Note that when creating a `Buffer` using a [`TypedArray`]'s `.buffer`, it is @@ -270,8 +264,8 @@ Example: const arr = new Uint16Array(20); const buf = Buffer.from(arr.buffer, 0, 16); -// Prints: 16 console.log(buf.length); +// Prints: 16 ``` The `Buffer.from()` and [`TypedArray.from()`] have different signatures and @@ -386,14 +380,14 @@ arr[1] = 4000; // Shares memory with `arr` const buf = new Buffer(arr.buffer); -// Prints: console.log(buf); +// Prints: // Changing the original Uint16Array changes the Buffer also arr[1] = 6000; -// Prints: console.log(buf); +// Prints: ``` ### new Buffer(buffer) @@ -422,11 +416,10 @@ const buf2 = new Buffer(buf1); buf1[0] = 0x61; -// Prints: auffer console.log(buf1.toString()); - -// Prints: buffer +// Prints: auffer console.log(buf2.toString()); +// Prints: buffer ``` ### new Buffer(size) @@ -464,8 +457,8 @@ Example: ```js const buf = new Buffer(10); -// Prints: console.log(buf); +// Prints: ``` ### new Buffer(string[, encoding]) @@ -489,21 +482,16 @@ changes: Creates a new `Buffer` containing the given JavaScript string `string`. If provided, the `encoding` parameter identifies the character encoding of `string`. -Examples: - ```js const buf1 = new Buffer('this is a tést'); - -// Prints: this is a tést -console.log(buf1.toString()); - -// Prints: this is a tC)st -console.log(buf1.toString('ascii')); - const buf2 = new Buffer('7468697320697320612074c3a97374', 'hex'); +console.log(buf1.toString()); // Prints: this is a tést console.log(buf2.toString()); +// Prints: this is a tést +console.log(buf1.toString('ascii')); +// Prints: this is a tC)st ``` ### Class Method: Buffer.alloc(size[, fill[, encoding]]) @@ -530,8 +518,8 @@ Example: ```js const buf = Buffer.alloc(5); -// Prints: console.log(buf); +// Prints: ``` Allocates a new `Buffer` of `size` bytes. If the `size` is larger than @@ -546,8 +534,8 @@ Example: ```js const buf = Buffer.alloc(5, 'a'); -// Prints: console.log(buf); +// Prints: ``` If both `fill` and `encoding` are specified, the allocated `Buffer` will be @@ -558,8 +546,8 @@ Example: ```js const buf = Buffer.alloc(11, 'aGVsbG8gd29ybGQ=', 'base64'); -// Prints: console.log(buf); +// Prints: ``` Calling [`Buffer.alloc()`] can be significantly slower than the alternative @@ -593,13 +581,13 @@ Example: ```js const buf = Buffer.allocUnsafe(10); -// Prints: (contents may vary): console.log(buf); +// Prints: (contents may vary): buf.fill(0); -// Prints: console.log(buf); +// Prints: ``` A `TypeError` will be thrown if `size` is not a number. @@ -702,9 +690,9 @@ Example: ```js const str = '\u00bd + \u00bc = \u00be'; -// Prints: ½ + ¼ = ¾: 9 characters, 12 bytes console.log(`${str}: ${str.length} characters, ` + `${Buffer.byteLength(str, 'utf8')} bytes`); +// Prints: ½ + ¼ = ¾: 9 characters, 12 bytes ``` When `string` is a `Buffer`/[`DataView`]/[`TypedArray`]/[`ArrayBuffer`]/ @@ -734,9 +722,9 @@ const buf1 = Buffer.from('1234'); const buf2 = Buffer.from('0123'); const arr = [buf1, buf2]; +console.log(arr.sort(Buffer.compare)); // Prints: [ , ] // (This result is equal to: [buf2, buf1]) -console.log(arr.sort(Buffer.compare)); ``` ### Class Method: Buffer.concat(list[, totalLength]) @@ -776,16 +764,15 @@ const buf2 = Buffer.alloc(14); const buf3 = Buffer.alloc(18); const totalLength = buf1.length + buf2.length + buf3.length; -// Prints: 42 console.log(totalLength); +// Prints: 42 const bufA = Buffer.concat([buf1, buf2, buf3], totalLength); -// Prints: console.log(bufA); - -// Prints: 42 +// Prints: console.log(bufA.length); +// Prints: 42 ``` ### Class Method: Buffer.from(array) @@ -833,14 +820,14 @@ arr[1] = 4000; // Shares memory with `arr` const buf = Buffer.from(arr.buffer); -// Prints: console.log(buf); +// Prints: // Changing the original Uint16Array changes the Buffer also arr[1] = 6000; -// Prints: console.log(buf); +// Prints: ``` The optional `byteOffset` and `length` arguments specify a memory range within @@ -852,8 +839,8 @@ Example: const ab = new ArrayBuffer(10); const buf = Buffer.from(ab, 0, 2); -// Prints: 2 console.log(buf.length); +// Prints: 2 ``` A `TypeError` will be thrown if `arrayBuffer` is not an [`ArrayBuffer`] or a @@ -876,11 +863,10 @@ const buf2 = Buffer.from(buf1); buf1[0] = 0x61; -// Prints: auffer console.log(buf1.toString()); - -// Prints: buffer +// Prints: auffer console.log(buf2.toString()); +// Prints: buffer ``` A `TypeError` will be thrown if `buffer` is not a `Buffer`. @@ -896,21 +882,16 @@ added: v5.10.0 Creates a new `Buffer` containing the given JavaScript string `string`. If provided, the `encoding` parameter identifies the character encoding of `string`. -Examples: - ```js const buf1 = Buffer.from('this is a tést'); - -// Prints: this is a tést -console.log(buf1.toString()); - -// Prints: this is a tC)st -console.log(buf1.toString('ascii')); - const buf2 = Buffer.from('7468697320697320612074c3a97374', 'hex'); +console.log(buf1.toString()); // Prints: this is a tést console.log(buf2.toString()); +// Prints: this is a tést +console.log(buf1.toString('ascii')); +// Prints: this is a tC)st ``` A `TypeError` will be thrown if `string` is not a string. @@ -932,7 +913,7 @@ For objects whose `valueOf()` function returns a value not strictly equal to ```js const buf = Buffer.from(new String('this is a test')); -// +// Prints: ``` For objects that support `Symbol.toPrimitive`, returns @@ -946,7 +927,7 @@ class Foo { } const buf = Buffer.from(new Foo(), 'utf8'); -// +// Prints: ``` ### Class Method: Buffer.isBuffer(obj) @@ -1004,8 +985,8 @@ for (let i = 0; i < str.length; i++) { buf[i] = str.charCodeAt(i); } -// Prints: Node.js console.log(buf.toString('ascii')); +// Prints: Node.js ``` ### buf.buffer @@ -1052,51 +1033,40 @@ Comparison is based on the actual sequence of bytes in each `Buffer`. * `1` is returned if `target` should come *before* `buf` when sorted. * `-1` is returned if `target` should come *after* `buf` when sorted. -Examples: - ```js const buf1 = Buffer.from('ABC'); const buf2 = Buffer.from('BCD'); const buf3 = Buffer.from('ABCD'); -// Prints: 0 console.log(buf1.compare(buf1)); - -// Prints: -1 +// Prints: 0 console.log(buf1.compare(buf2)); - // Prints: -1 console.log(buf1.compare(buf3)); - -// Prints: 1 +// Prints: -1 console.log(buf2.compare(buf1)); - // Prints: 1 console.log(buf2.compare(buf3)); - +// Prints: 1 +console.log([buf1, buf2, buf3].sort(Buffer.compare)); // Prints: [ , , ] // (This result is equal to: [buf1, buf3, buf2]) -console.log([buf1, buf2, buf3].sort(Buffer.compare)); ``` The optional `targetStart`, `targetEnd`, `sourceStart`, and `sourceEnd` arguments can be used to limit the comparison to specific ranges within `target` and `buf` respectively. -Examples: - ```js const buf1 = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8, 9]); const buf2 = Buffer.from([5, 6, 7, 8, 9, 1, 2, 3, 4]); -// Prints: 0 console.log(buf1.compare(buf2, 5, 9, 0, 4)); - -// Prints: -1 +// Prints: 0 console.log(buf1.compare(buf2, 0, 6, 4)); - -// Prints: 1 +// Prints: -1 console.log(buf1.compare(buf2, 5, 6, 5)); +// Prints: 1 ``` A `RangeError` will be thrown if: `targetStart < 0`, `sourceStart < 0`, @@ -1133,8 +1103,8 @@ for (let i = 0; i < 26; i++) { buf1.copy(buf2, 8, 16, 20); -// Prints: !!!!!!!!qrst!!!!!!!!!!!!! console.log(buf2.toString('ascii', 0, 25)); +// Prints: !!!!!!!!qrst!!!!!!!!!!!!! ``` Example: Create a single `Buffer` and copy data from one region to an @@ -1150,8 +1120,8 @@ for (let i = 0; i < 26; i++) { buf.copy(buf, 0, 4, 10); -// Prints: efghijghijklmnopqrstuvwxyz console.log(buf.toString()); +// Prints: efghijghijklmnopqrstuvwxyz ``` ### buf.entries() @@ -1169,6 +1139,9 @@ Example: Log the entire contents of a `Buffer` ```js const buf = Buffer.from('buffer'); +for (const pair of buf.entries()) { + console.log(pair); +} // Prints: // [0, 98] // [1, 117] @@ -1176,9 +1149,6 @@ const buf = Buffer.from('buffer'); // [3, 102] // [4, 101] // [5, 114] -for (const pair of buf.entries()) { - console.log(pair); -} ``` ### buf.equals(otherBuffer) @@ -1196,18 +1166,15 @@ changes: Returns `true` if both `buf` and `otherBuffer` have exactly the same bytes, `false` otherwise. -Examples: - ```js const buf1 = Buffer.from('ABC'); const buf2 = Buffer.from('414243', 'hex'); const buf3 = Buffer.from('ABCD'); -// Prints: true console.log(buf1.equals(buf2)); - -// Prints: false +// Prints: true console.log(buf1.equals(buf3)); +// Prints: false ``` ### buf.fill(value[, offset[, end]][, encoding]) @@ -1235,8 +1202,8 @@ Example: Fill a `Buffer` with the ASCII character `'h'` ```js const b = Buffer.allocUnsafe(50).fill('h'); -// Prints: hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh console.log(b.toString()); +// Prints: hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh ``` `value` is coerced to a `uint32` value if it is not a String or Integer. @@ -1247,8 +1214,8 @@ then only the first bytes of that character that fit into `buf` are written. Example: Fill a `Buffer` with a two-byte character ```js -// Prints: console.log(Buffer.allocUnsafe(3).fill('\u0222')); +// Prints: ``` If `value` contains invalid characters, it is truncated; if no valid @@ -1256,12 +1223,13 @@ fill data remains, no filling is performed: ```js const buf = Buffer.allocUnsafe(5); -// Prints: + console.log(buf.fill('a')); -// Prints: +// Prints: console.log(buf.fill('aazz', 'hex')); // Prints: console.log(buf.fill('zz', 'hex')); +// Throws an exception. ``` ### buf.includes(value[, byteOffset][, encoding]) @@ -1277,32 +1245,23 @@ added: v5.3.0 Equivalent to [`buf.indexOf() !== -1`][`buf.indexOf()`]. -Examples: - ```js const buf = Buffer.from('this is a buffer'); -// Prints: true console.log(buf.includes('this')); - // Prints: true console.log(buf.includes('is')); - // Prints: true console.log(buf.includes(Buffer.from('a buffer'))); - // Prints: true -// (97 is the decimal ASCII value for 'a') console.log(buf.includes(97)); - -// Prints: false +// Prints: true (97 is the decimal ASCII value for 'a') console.log(buf.includes(Buffer.from('a buffer example'))); - -// Prints: true -console.log(buf.includes(Buffer.from('a buffer example').slice(0, 8))); - // Prints: false +console.log(buf.includes(Buffer.from('a buffer example').slice(0, 8))); +// Prints: true console.log(buf.includes('this', 4)); +// Prints: false ``` ### buf.indexOf(value[, byteOffset][, encoding]) @@ -1334,37 +1293,28 @@ If `value` is: * a number, `value` will be interpreted as an unsigned 8-bit integer value between `0` and `255`. -Examples: - ```js const buf = Buffer.from('this is a buffer'); -// Prints: 0 console.log(buf.indexOf('this')); - -// Prints: 2 +// Prints: 0 console.log(buf.indexOf('is')); - -// Prints: 8 +// Prints: 2 console.log(buf.indexOf(Buffer.from('a buffer'))); - // Prints: 8 -// (97 is the decimal ASCII value for 'a') console.log(buf.indexOf(97)); - -// Prints: -1 +// Prints: 8 (97 is the decimal ASCII value for 'a') console.log(buf.indexOf(Buffer.from('a buffer example'))); - -// Prints: 8 +// Prints: -1 console.log(buf.indexOf(Buffer.from('a buffer example').slice(0, 8))); +// Prints: 8 const utf16Buffer = Buffer.from('\u039a\u0391\u03a3\u03a3\u0395', 'ucs2'); -// Prints: 4 console.log(utf16Buffer.indexOf('\u03a3', 0, 'ucs2')); - -// Prints: 6 +// Prints: 4 console.log(utf16Buffer.indexOf('\u03a3', -4, 'ucs2')); +// Prints: 6 ``` If `value` is not a string, number, or `Buffer`, this method will throw a @@ -1409,6 +1359,9 @@ Example: ```js const buf = Buffer.from('buffer'); +for (const key of buf.keys()) { + console.log(key); +} // Prints: // 0 // 1 @@ -1416,9 +1369,6 @@ const buf = Buffer.from('buffer'); // 3 // 4 // 5 -for (const key of buf.keys()) { - console.log(key); -} ``` ### buf.lastIndexOf(value[, byteOffset][, encoding]) @@ -1441,40 +1391,30 @@ changes: Identical to [`buf.indexOf()`], except `buf` is searched from back to front instead of front to back. -Examples: - ```js const buf = Buffer.from('this buffer is a buffer'); -// Prints: 0 console.log(buf.lastIndexOf('this')); - -// Prints: 17 +// Prints: 0 console.log(buf.lastIndexOf('buffer')); - // Prints: 17 console.log(buf.lastIndexOf(Buffer.from('buffer'))); - -// Prints: 15 -// (97 is the decimal ASCII value for 'a') +// Prints: 17 console.log(buf.lastIndexOf(97)); - -// Prints: -1 +// Prints: 15 (97 is the decimal ASCII value for 'a') console.log(buf.lastIndexOf(Buffer.from('yolo'))); - -// Prints: 5 -console.log(buf.lastIndexOf('buffer', 5)); - // Prints: -1 +console.log(buf.lastIndexOf('buffer', 5)); +// Prints: 5 console.log(buf.lastIndexOf('buffer', 4)); +// Prints: -1 const utf16Buffer = Buffer.from('\u039a\u0391\u03a3\u03a3\u0395', 'ucs2'); -// Prints: 6 console.log(utf16Buffer.lastIndexOf('\u03a3', undefined, 'ucs2')); - -// Prints: 4 +// Prints: 6 console.log(utf16Buffer.lastIndexOf('\u03a3', -5, 'ucs2')); +// Prints: 4 ``` If `value` is not a string, number, or `Buffer`, this method will throw a @@ -1521,13 +1461,13 @@ Example: Create a `Buffer` and write a shorter ASCII string to it ```js const buf = Buffer.alloc(1234); -// Prints: 1234 console.log(buf.length); +// Prints: 1234 buf.write('some string', 0, 'ascii'); -// Prints: 1234 console.log(buf.length); +// Prints: 1234 ``` While the `length` property is not immutable, changing the value of `length` @@ -1535,20 +1475,18 @@ can result in undefined and inconsistent behavior. Applications that wish to modify the length of a `Buffer` should therefore treat `length` as read-only and use [`buf.slice()`] to create a new `Buffer`. -Examples: - ```js let buf = Buffer.allocUnsafe(10); buf.write('abcdefghj', 0, 'ascii'); -// Prints: 10 console.log(buf.length); +// Prints: 10 buf = buf.slice(0, 5); -// Prints: 5 console.log(buf.length); +// Prints: 5 ``` ### buf.parent @@ -1577,23 +1515,18 @@ little endian). Setting `noAssert` to `true` allows `offset` to be beyond the end of `buf`, but the resulting behavior is undefined. -Examples: - ```js const buf = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]); -// Prints: 8.20788039913184e-304 console.log(buf.readDoubleBE()); - -// Prints: 5.447603722011605e-270 +// Prints: 8.20788039913184e-304 console.log(buf.readDoubleLE()); - -// Throws an exception: RangeError: Index out of range +// Prints: 5.447603722011605e-270 console.log(buf.readDoubleLE(1)); - +// Throws an exception: RangeError: Index out of range +console.log(buf.readDoubleLE(1, true)); // Warning: reads passed end of buffer! // This will result in a segmentation fault! Don't do this! -console.log(buf.readDoubleLE(1, true)); ``` ### buf.readFloatBE(offset[, noAssert]) @@ -1613,23 +1546,18 @@ little endian). Setting `noAssert` to `true` allows `offset` to be beyond the end of `buf`, but the resulting behavior is undefined. -Examples: - ```js const buf = Buffer.from([1, 2, 3, 4]); -// Prints: 2.387939260590663e-38 console.log(buf.readFloatBE()); - -// Prints: 1.539989614439558e-36 +// Prints: 2.387939260590663e-38 console.log(buf.readFloatLE()); - -// Throws an exception: RangeError: Index out of range +// Prints: 1.539989614439558e-36 console.log(buf.readFloatLE(1)); - +// Throws an exception: RangeError: Index out of range +console.log(buf.readFloatLE(1, true)); // Warning: reads passed end of buffer! // This will result in a segmentation fault! Don't do this! -console.log(buf.readFloatLE(1, true)); ``` ### buf.readInt8(offset[, noAssert]) @@ -1648,19 +1576,15 @@ the resulting behavior is undefined. Integers read from a `Buffer` are interpreted as two's complement signed values. -Examples: - ```js const buf = Buffer.from([-1, 5]); -// Prints: -1 console.log(buf.readInt8(0)); - -// Prints: 5 +// Prints: -1 console.log(buf.readInt8(1)); - -// Throws an exception: RangeError: Index out of range +// Prints: 5 console.log(buf.readInt8(2)); +// Throws an exception: RangeError: Index out of range ``` ### buf.readInt16BE(offset[, noAssert]) @@ -1682,19 +1606,15 @@ the resulting behavior is undefined. Integers read from a `Buffer` are interpreted as two's complement signed values. -Examples: - ```js const buf = Buffer.from([0, 5]); -// Prints: 5 console.log(buf.readInt16BE()); - -// Prints: 1280 +// Prints: 5 console.log(buf.readInt16LE()); - -// Throws an exception: RangeError: Index out of range +// Prints: 1280 console.log(buf.readInt16LE(1)); +// Throws an exception: RangeError: Index out of range ``` ### buf.readInt32BE(offset[, noAssert]) @@ -1716,19 +1636,15 @@ the resulting behavior is undefined. Integers read from a `Buffer` are interpreted as two's complement signed values. -Examples: - ```js const buf = Buffer.from([0, 0, 0, 5]); -// Prints: 5 console.log(buf.readInt32BE()); - -// Prints: 83886080 +// Prints: 5 console.log(buf.readInt32LE()); - -// Throws an exception: RangeError: Index out of range +// Prints: 83886080 console.log(buf.readInt32LE(1)); +// Throws an exception: RangeError: Index out of range ``` ### buf.readIntBE(offset, byteLength[, noAssert]) @@ -1749,19 +1665,15 @@ bits of accuracy. Setting `noAssert` to `true` allows `offset` to be beyond the end of `buf`, but the resulting behavior is undefined. -Examples: - ```js const buf = Buffer.from([0x12, 0x34, 0x56, 0x78, 0x90, 0xab]); -// Prints: -546f87a9cbee console.log(buf.readIntLE(0, 6).toString(16)); - -// Prints: 1234567890ab +// Prints: -546f87a9cbee console.log(buf.readIntBE(0, 6).toString(16)); - -// Throws an exception: RangeError: Index out of range +// Prints: 1234567890ab console.log(buf.readIntBE(1, 6).toString(16)); +// Throws: RangeError [ERR_INDEX_OUT_OF_RANGE]: Index out of range ``` ### buf.readUInt8(offset[, noAssert]) @@ -1778,19 +1690,15 @@ Reads an unsigned 8-bit integer from `buf` at the specified `offset`. Setting `noAssert` to `true` allows `offset` to be beyond the end of `buf`, but the resulting behavior is undefined. -Examples: - ```js const buf = Buffer.from([1, -2]); -// Prints: 1 console.log(buf.readUInt8(0)); - -// Prints: 254 +// Prints: 1 console.log(buf.readUInt8(1)); - -// Throws an exception: RangeError: Index out of range +// Prints: 254 console.log(buf.readUInt8(2)); +// Throws an exception: RangeError: Index out of range ``` ### buf.readUInt16BE(offset[, noAssert]) @@ -1810,25 +1718,19 @@ returns little endian). Setting `noAssert` to `true` allows `offset` to be beyond the end of `buf`, but the resulting behavior is undefined. -Examples: - ```js const buf = Buffer.from([0x12, 0x34, 0x56]); -// Prints: 1234 console.log(buf.readUInt16BE(0).toString(16)); - -// Prints: 3412 +// Prints: 1234 console.log(buf.readUInt16LE(0).toString(16)); - -// Prints: 3456 +// Prints: 3412 console.log(buf.readUInt16BE(1).toString(16)); - -// Prints: 5634 +// Prints: 3456 console.log(buf.readUInt16LE(1).toString(16)); - -// Throws an exception: RangeError: Index out of range +// Prints: 5634 console.log(buf.readUInt16LE(2).toString(16)); +// Throws an exception: RangeError: Index out of range ``` ### buf.readUInt32BE(offset[, noAssert]) @@ -1848,19 +1750,15 @@ specified endian format (`readUInt32BE()` returns big endian, Setting `noAssert` to `true` allows `offset` to be beyond the end of `buf`, but the resulting behavior is undefined. -Examples: - ```js const buf = Buffer.from([0x12, 0x34, 0x56, 0x78]); -// Prints: 12345678 console.log(buf.readUInt32BE(0).toString(16)); - -// Prints: 78563412 +// Prints: 12345678 console.log(buf.readUInt32LE(0).toString(16)); - -// Throws an exception: RangeError: Index out of range +// Prints: 78563412 console.log(buf.readUInt32LE(1).toString(16)); +// Throws an exception: RangeError: Index out of range ``` ### buf.readUIntBE(offset, byteLength[, noAssert]) @@ -1881,19 +1779,15 @@ bits of accuracy. Setting `noAssert` to `true` allows `offset` to be beyond the end of `buf`, but the resulting behavior is undefined. -Examples: - ```js const buf = Buffer.from([0x12, 0x34, 0x56, 0x78, 0x90, 0xab]); -// Prints: 1234567890ab console.log(buf.readUIntBE(0, 6).toString(16)); - -// Prints: ab9078563412 +// Prints: 1234567890ab console.log(buf.readUIntLE(0, 6).toString(16)); - -// Throws an exception: RangeError: Index out of range +// Prints: ab9078563412 console.log(buf.readUIntBE(1, 6).toString(16)); +// Throws an exception: RangeError: Index out of range ``` ### buf.slice([start[, end]]) @@ -1937,34 +1831,32 @@ for (let i = 0; i < 26; i++) { const buf2 = buf1.slice(0, 3); -// Prints: abc console.log(buf2.toString('ascii', 0, buf2.length)); +// Prints: abc buf1[0] = 33; -// Prints: !bc console.log(buf2.toString('ascii', 0, buf2.length)); +// Prints: !bc ``` Specifying negative indexes causes the slice to be generated relative to the end of `buf` rather than the beginning. -Examples: - ```js const buf = Buffer.from('buffer'); +console.log(buf.slice(-6, -1).toString()); // Prints: buffe // (Equivalent to buf.slice(0, 5)) -console.log(buf.slice(-6, -1).toString()); +console.log(buf.slice(-6, -2).toString()); // Prints: buff // (Equivalent to buf.slice(0, 4)) -console.log(buf.slice(-6, -2).toString()); +console.log(buf.slice(-5, -2).toString()); // Prints: uff // (Equivalent to buf.slice(1, 4)) -console.log(buf.slice(-5, -2).toString()); ``` ### buf.swap16() @@ -1977,23 +1869,21 @@ added: v5.10.0 Interprets `buf` as an array of unsigned 16-bit integers and swaps the byte-order *in-place*. Throws a `RangeError` if [`buf.length`] is not a multiple of 2. -Examples: - ```js const buf1 = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8]); -// Prints: console.log(buf1); +// Prints: buf1.swap16(); -// Prints: console.log(buf1); +// Prints: const buf2 = Buffer.from([0x1, 0x2, 0x3]); -// Throws an exception: RangeError: Buffer size must be a multiple of 16-bits buf2.swap16(); +// Throws an exception: RangeError: Buffer size must be a multiple of 16-bits ``` ### buf.swap32() @@ -2006,23 +1896,21 @@ added: v5.10.0 Interprets `buf` as an array of unsigned 32-bit integers and swaps the byte-order *in-place*. Throws a `RangeError` if [`buf.length`] is not a multiple of 4. -Examples: - ```js const buf1 = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8]); -// Prints: console.log(buf1); +// Prints: buf1.swap32(); -// Prints: console.log(buf1); +// Prints: const buf2 = Buffer.from([0x1, 0x2, 0x3]); -// Throws an exception: RangeError: Buffer size must be a multiple of 32-bits buf2.swap32(); +// Throws an exception: RangeError: Buffer size must be a multiple of 32-bits ``` ### buf.swap64() @@ -2035,23 +1923,21 @@ added: v6.3.0 Interprets `buf` as an array of 64-bit numbers and swaps the byte-order *in-place*. Throws a `RangeError` if [`buf.length`] is not a multiple of 8. -Examples: - ```js const buf1 = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8]); -// Prints: console.log(buf1); +// Prints: buf1.swap64(); -// Prints: console.log(buf1); +// Prints: const buf2 = Buffer.from([0x1, 0x2, 0x3]); -// Throws an exception: RangeError: Buffer size must be a multiple of 64-bits buf2.swap64(); +// Throws an exception: RangeError: Buffer size must be a multiple of 64-bits ``` Note that JavaScript cannot encode 64-bit integers. This method is intended @@ -2073,8 +1959,8 @@ Example: const buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5]); const json = JSON.stringify(buf); -// Prints: {"type":"Buffer","data":[1,2,3,4,5]} console.log(json); +// Prints: {"type":"Buffer","data":[1,2,3,4,5]} const copy = JSON.parse(json, (key, value) => { return value && value.type === 'Buffer' ? @@ -2082,8 +1968,8 @@ const copy = JSON.parse(json, (key, value) => { value; }); -// Prints: console.log(copy); +// Prints: ``` ### buf.toString([encoding[, start[, end]]]) @@ -2103,8 +1989,6 @@ Decodes `buf` to a string according to the specified character encoding in The maximum length of a string instance (in UTF-16 code units) is available as [`buffer.constants.MAX_STRING_LENGTH`][]. -Examples: - ```js const buf1 = Buffer.allocUnsafe(26); @@ -2113,22 +1997,19 @@ for (let i = 0; i < 26; i++) { buf1[i] = i + 97; } -// Prints: abcdefghijklmnopqrstuvwxyz console.log(buf1.toString('ascii')); - -// Prints: abcde +// Prints: abcdefghijklmnopqrstuvwxyz console.log(buf1.toString('ascii', 0, 5)); +// Prints: abcde const buf2 = Buffer.from('tést'); -// Prints: 74c3a97374 console.log(buf2.toString('hex')); - -// Prints: té +// Prints: 74c3a97374 console.log(buf2.toString('utf8', 0, 3)); - // Prints: té console.log(buf2.toString(undefined, 0, 3)); +// Prints: té ``` ### buf.values() @@ -2141,11 +2022,12 @@ added: v1.1.0 Creates and returns an [iterator] for `buf` values (bytes). This function is called automatically when a `Buffer` is used in a `for..of` statement. -Examples: - ```js const buf = Buffer.from('buffer'); +for (const value of buf.values()) { + console.log(value); +} // Prints: // 98 // 117 @@ -2153,10 +2035,10 @@ const buf = Buffer.from('buffer'); // 102 // 101 // 114 -for (const value of buf.values()) { + +for (const value of buf) { console.log(value); } - // Prints: // 98 // 117 @@ -2164,9 +2046,6 @@ for (const value of buf.values()) { // 102 // 101 // 114 -for (const value of buf) { - console.log(value); -} ``` ### buf.write(string[, offset[, length]][, encoding]) @@ -2192,8 +2071,8 @@ const buf = Buffer.allocUnsafe(256); const len = buf.write('\u00bd + \u00bc = \u00be', 0); -// Prints: 12 bytes: ½ + ¼ = ¾ console.log(`${len} bytes: ${buf.toString('utf8', 0, len)}`); +// Prints: 12 bytes: ½ + ¼ = ¾ ``` ### buf.writeDoubleBE(value, offset[, noAssert]) @@ -2215,20 +2094,18 @@ endian). `value` *should* be a valid 64-bit double. Behavior is undefined when Setting `noAssert` to `true` allows the encoded form of `value` to extend beyond the end of `buf`, but the resulting behavior is undefined. -Examples: - ```js const buf = Buffer.allocUnsafe(8); buf.writeDoubleBE(0xdeadbeefcafebabe, 0); -// Prints: console.log(buf); +// Prints: buf.writeDoubleLE(0xdeadbeefcafebabe, 0); -// Prints: console.log(buf); +// Prints: ``` ### buf.writeFloatBE(value, offset[, noAssert]) @@ -2250,20 +2127,18 @@ endian). `value` *should* be a valid 32-bit float. Behavior is undefined when Setting `noAssert` to `true` allows the encoded form of `value` to extend beyond the end of `buf`, but the resulting behavior is undefined. -Examples: - ```js const buf = Buffer.allocUnsafe(4); buf.writeFloatBE(0xcafebabe, 0); -// Prints: console.log(buf); +// Prints: buf.writeFloatLE(0xcafebabe, 0); -// Prints: console.log(buf); +// Prints: ``` ### buf.writeInt8(value, offset[, noAssert]) @@ -2285,16 +2160,14 @@ the end of `buf`, but the resulting behavior is undefined. `value` is interpreted and written as a two's complement signed integer. -Examples: - ```js const buf = Buffer.allocUnsafe(2); buf.writeInt8(2, 0); buf.writeInt8(-2, 1); -// Prints: console.log(buf); +// Prints: ``` ### buf.writeInt16BE(value, offset[, noAssert]) @@ -2318,16 +2191,14 @@ the end of `buf`, but the resulting behavior is undefined. `value` is interpreted and written as a two's complement signed integer. -Examples: - ```js const buf = Buffer.allocUnsafe(4); buf.writeInt16BE(0x0102, 0); buf.writeInt16LE(0x0304, 2); -// Prints: console.log(buf); +// Prints: ``` ### buf.writeInt32BE(value, offset[, noAssert]) @@ -2351,16 +2222,14 @@ the end of `buf`, but the resulting behavior is undefined. `value` is interpreted and written as a two's complement signed integer. -Examples: - ```js const buf = Buffer.allocUnsafe(8); buf.writeInt32BE(0x01020304, 0); buf.writeInt32LE(0x05060708, 4); -// Prints: console.log(buf); +// Prints: ``` ### buf.writeIntBE(value, offset, byteLength[, noAssert]) @@ -2383,20 +2252,18 @@ anything other than a signed integer. Setting `noAssert` to `true` allows the encoded form of `value` to extend beyond the end of `buf`, but the resulting behavior is undefined. -Examples: - ```js const buf = Buffer.allocUnsafe(6); buf.writeIntBE(0x1234567890ab, 0, 6); -// Prints: console.log(buf); +// Prints: buf.writeIntLE(0x1234567890ab, 0, 6); -// Prints: console.log(buf); +// Prints: ``` ### buf.writeUInt8(value, offset[, noAssert]) @@ -2416,8 +2283,6 @@ other than an unsigned 8-bit integer. Setting `noAssert` to `true` allows the encoded form of `value` to extend beyond the end of `buf`, but the resulting behavior is undefined. -Examples: - ```js const buf = Buffer.allocUnsafe(4); @@ -2426,8 +2291,8 @@ buf.writeUInt8(0x4, 1); buf.writeUInt8(0x23, 2); buf.writeUInt8(0x42, 3); -// Prints: console.log(buf); +// Prints: ``` ### buf.writeUInt16BE(value, offset[, noAssert]) @@ -2449,22 +2314,20 @@ undefined when `value` is anything other than an unsigned 16-bit integer. Setting `noAssert` to `true` allows the encoded form of `value` to extend beyond the end of `buf`, but the resulting behavior is undefined. -Examples: - ```js const buf = Buffer.allocUnsafe(4); buf.writeUInt16BE(0xdead, 0); buf.writeUInt16BE(0xbeef, 2); -// Prints: console.log(buf); +// Prints: buf.writeUInt16LE(0xdead, 0); buf.writeUInt16LE(0xbeef, 2); -// Prints: console.log(buf); +// Prints: ``` ### buf.writeUInt32BE(value, offset[, noAssert]) @@ -2486,20 +2349,18 @@ undefined when `value` is anything other than an unsigned 32-bit integer. Setting `noAssert` to `true` allows the encoded form of `value` to extend beyond the end of `buf`, but the resulting behavior is undefined. -Examples: - ```js const buf = Buffer.allocUnsafe(4); buf.writeUInt32BE(0xfeedface, 0); -// Prints: console.log(buf); +// Prints: buf.writeUInt32LE(0xfeedface, 0); -// Prints: console.log(buf); +// Prints: ``` ### buf.writeUIntBE(value, offset, byteLength[, noAssert]) @@ -2522,20 +2383,18 @@ anything other than an unsigned integer. Setting `noAssert` to `true` allows the encoded form of `value` to extend beyond the end of `buf`, but the resulting behavior is undefined. -Examples: - ```js const buf = Buffer.allocUnsafe(6); buf.writeUIntBE(0x1234567890ab, 0, 6); -// Prints: console.log(buf); +// Prints: buf.writeUIntLE(0x1234567890ab, 0, 6); -// Prints: console.log(buf); +// Prints: ``` ## buffer.INSPECT_MAX_BYTES @@ -2663,13 +2522,13 @@ const { SlowBuffer } = require('buffer'); const buf = new SlowBuffer(5); -// Prints: (contents may vary): console.log(buf); +// Prints: (contents may vary): buf.fill(0); -// Prints: console.log(buf); +// Prints: ``` ## Buffer Constants diff --git a/doc/api/crypto.md b/doc/api/crypto.md index 00128cebfb8154..bf0315fc034366 100644 --- a/doc/api/crypto.md +++ b/doc/api/crypto.md @@ -1273,6 +1273,11 @@ Adversaries][] for details. ### crypto.createCipheriv(algorithm, key, iv[, options]) - `algorithm` {string} - `key` {string | Buffer | TypedArray | DataView} @@ -1288,7 +1293,8 @@ available cipher algorithms. The `key` is the raw key used by the `algorithm` and `iv` is an [initialization vector][]. Both arguments must be `'utf8'` encoded strings, -[Buffers][`Buffer`], `TypedArray`, or `DataView`s. +[Buffers][`Buffer`], `TypedArray`, or `DataView`s. If the cipher does not need +an initialization vector, `iv` may be `null`. ### crypto.createCredentials(details) - `algorithm` {string} - `key` {string | Buffer | TypedArray | DataView} @@ -1350,7 +1361,8 @@ available cipher algorithms. The `key` is the raw key used by the `algorithm` and `iv` is an [initialization vector][]. Both arguments must be `'utf8'` encoded strings, -[Buffers][`Buffer`], `TypedArray`, or `DataView`s. +[Buffers][`Buffer`], `TypedArray`, or `DataView`s. If the cipher does not need +an initialization vector, `iv` may be `null`. ### crypto.createDiffieHellman(prime[, primeEncoding][, generator][, generatorEncoding]) + +* Returns: {Buffer|undefined} The latest `Finished` message that has been +sent to the socket as part of a SSL/TLS handshake, or `undefined` if +no `Finished` message has been sent yet. + +As the `Finished` messages are message digests of the complete handshake +(with a total of 192 bits for TLS 1.0 and more for SSL 3.0), they can +be used for external authentication procedures when the authentication +provided by SSL/TLS is not desired or is not enough. + +Corresponds to the `SSL_get_finished` routine in OpenSSL and may be used +to implement the `tls-unique` channel binding from [RFC 5929][]. + ### tlsSocket.getPeerCertificate([detailed]) + +* Returns: {Buffer|undefined} The latest `Finished` message that is expected +or has actually been received from the socket as part of a SSL/TLS handshake, +or `undefined` if there is no `Finished` message so far. + +As the `Finished` messages are message digests of the complete handshake +(with a total of 192 bits for TLS 1.0 and more for SSL 3.0), they can +be used for external authentication procedures when the authentication +provided by SSL/TLS is not desired or is not enough. + +Corresponds to the `SSL_get_peer_finished` routine in OpenSSL and may be used +to implement the `tls-unique` channel binding from [RFC 5929][]. + ### tlsSocket.getProtocol() + +* `env` {object} A object containing the environment variables to check. + Defaults to `process.env`. +* Returns: {number} + +Returns: +* 1 for 2, +* 4 for 16, +* 8 for 256, +* 24 for 16,777,216 +colors supported. + +Use this to determine what colors the terminal supports. Due to the nature of +colors in terminals it is possible to either have false positives or false +negatives. It depends on process information and the environment variables that +may lie about what terminal is used. +To enforce a specific behavior without relying on `process.env` it is possible +to pass in an object with different settings. + +Use the `NODE_DISABLE_COLORS` environment variable to enforce this function to +always return 1. + ## tty.isatty(fd) diff --git a/doc/changelogs/CHANGELOG_V9.md b/doc/changelogs/CHANGELOG_V9.md index 35107dc996d63f..df896acb4d7101 100644 --- a/doc/changelogs/CHANGELOG_V9.md +++ b/doc/changelogs/CHANGELOG_V9.md @@ -8,6 +8,7 @@ +9.9.0
9.8.0
9.7.1
9.7.0
@@ -35,6 +36,164 @@ * [io.js](CHANGELOG_IOJS.md) * [Archive](CHANGELOG_ARCHIVE.md) + +## 2018-03-21, Version 9.9.0 (Current), @MylesBorins prepared by @targos + +### Notable Changes + +* **assert**: + - From now on all error messages produced by `assert` in strict mode will produce a error diff. (Ruben Bridgewater) [#17615](https://github.com/nodejs/node/pull/17615) + - From now on it is possible to use a validation object in throws instead of the other possibilities. (Ruben Bridgewater) [#17584](https://github.com/nodejs/node/pull/17584) +* **crypto**: + - allow passing null as IV unless required (Tobias Nießen) [#18644](https://github.com/nodejs/node/pull/18644) +* **fs**: + - support as and as+ flags in stringToFlags() (Sarat Addepalli) [#18801](https://github.com/nodejs/node/pull/18801) +* **tls**: + - expose Finished messages in TLSSocket (Anton Salikhmetov) [#19102](https://github.com/nodejs/node/pull/19102) +* **tty**: + - Add getColorDepth function to determine if terminal supports colors. (Ruben Bridgewater) [#17615](https://github.com/nodejs/node/pull/17615) +* **util**: + - add util.inspect compact option (Ruben Bridgewater) [#17576](https://github.com/nodejs/node/pull/17576) +* **Added new collaborators** + - [watson](https://github.com/watson) Thomas Watson + +### Commits + +* [[`acc86ed246`](https://github.com/nodejs/node/commit/acc86ed246)] - 2018-03-XX, Version 9.9.0 (Current) (Michaël Zasso) +* [[`8d33e5c214`](https://github.com/nodejs/node/commit/8d33e5c214)] - **assert**: improve error check (Ruben Bridgewater) [#17574](https://github.com/nodejs/node/pull/17574) +* [[`5e6b42ec9c`](https://github.com/nodejs/node/commit/5e6b42ec9c)] - **assert**: show proper differences (Ruben Bridgewater) [#18611](https://github.com/nodejs/node/pull/18611) +* [[`9abbb6b857`](https://github.com/nodejs/node/commit/9abbb6b857)] - **assert**: fix infinite loop (Ruben Bridgewater) [#18611](https://github.com/nodejs/node/pull/18611) +* [[`e9ac468146`](https://github.com/nodejs/node/commit/e9ac468146)] - **assert**: fix throws trace (Ruben Bridgewater) [#18595](https://github.com/nodejs/node/pull/18595) +* [[`d3c2534bbe`](https://github.com/nodejs/node/commit/d3c2534bbe)] - **assert**: use destructuring for errors (Ruben Bridgewater) [#18247](https://github.com/nodejs/node/pull/18247) +* [[`5aa3a2d172`](https://github.com/nodejs/node/commit/5aa3a2d172)] - **(SEMVER-MINOR)** **assert**: improve error messages (Ruben Bridgewater) [#17615](https://github.com/nodejs/node/pull/17615) +* [[`f96ea47cf5`](https://github.com/nodejs/node/commit/f96ea47cf5)] - **assert**: fix strict regression (Ruben Bridgewater) [#17903](https://github.com/nodejs/node/pull/17903) +* [[`ebd60fa505`](https://github.com/nodejs/node/commit/ebd60fa505)] - **(SEMVER-MINOR)** **assert**: .throws accept objects (Ruben Bridgewater) [#17584](https://github.com/nodejs/node/pull/17584) +* [[`612ba1a3f0`](https://github.com/nodejs/node/commit/612ba1a3f0)] - **(SEMVER-MINOR)** **assert**: improve assert.throws (Ruben Bridgewater) [#17585](https://github.com/nodejs/node/pull/17585) +* [[`24aeca7dd5`](https://github.com/nodejs/node/commit/24aeca7dd5)] - **assert**: fix throws and doesNotThrow stack frames (Ruben Bridgewater) [#17703](https://github.com/nodejs/node/pull/17703) +* [[`db73d1c13b`](https://github.com/nodejs/node/commit/db73d1c13b)] - **assert**: use object argument in innerFail (Ruben Bridgewater) [#17582](https://github.com/nodejs/node/pull/17582) +* [[`bae5de1949`](https://github.com/nodejs/node/commit/bae5de1949)] - **(SEMVER-MINOR)** **assert**: add strict functionality export (Ruben Bridgewater) [#17002](https://github.com/nodejs/node/pull/17002) +* [[`f0f31d080a`](https://github.com/nodejs/node/commit/f0f31d080a)] - **async_hooks**: add copyHooks function (Daniel Bevenius) [#19391](https://github.com/nodejs/node/pull/19391) +* [[`71b1c7f79f`](https://github.com/nodejs/node/commit/71b1c7f79f)] - **async_hooks**: don't set hook\_fields\[kTotals\] to 0 (Daniel Bevenius) [#19219](https://github.com/nodejs/node/pull/19219) +* [[`530b8a4077`](https://github.com/nodejs/node/commit/530b8a4077)] - **benchmark**: fix benchmark for url (Sergey Golovin) [#19084](https://github.com/nodejs/node/pull/19084) +* [[`563bed00f5`](https://github.com/nodejs/node/commit/563bed00f5)] - **benchmark,lib,test,tools**: use consistent quotes (Rich Trott) [#19156](https://github.com/nodejs/node/pull/19156) +* [[`3f7c4eea04`](https://github.com/nodejs/node/commit/3f7c4eea04)] - **build**: do not cd on vcbuild help (Vse Mozhet Byt) [#19291](https://github.com/nodejs/node/pull/19291) +* [[`5a1437cdbd`](https://github.com/nodejs/node/commit/5a1437cdbd)] - **build**: update arm64 minimum supported platform (Gibson Fahnestock) [#19164](https://github.com/nodejs/node/pull/19164) +* [[`07845fc19e`](https://github.com/nodejs/node/commit/07845fc19e)] - **console**: port errors to new system (Ruben Bridgewater) [#18857](https://github.com/nodejs/node/pull/18857) +* [[`03c321a713`](https://github.com/nodejs/node/commit/03c321a713)] - **(SEMVER-MINOR)** **crypto**: allow passing null as IV unless required (Tobias Nießen) [#18644](https://github.com/nodejs/node/pull/18644) +* [[`044995e546`](https://github.com/nodejs/node/commit/044995e546)] - **crypto**: use bool over int consistently (Tobias Nießen) [#19238](https://github.com/nodejs/node/pull/19238) +* [[`36f664ef9a`](https://github.com/nodejs/node/commit/36f664ef9a)] - **deps**: V8: backport 596d55a from upstream (Myles Borins) [#19477](https://github.com/nodejs/node/pull/19477) +* [[`5966b8cc06`](https://github.com/nodejs/node/commit/5966b8cc06)] - **deps**: v8: cherry-pick fixes for v8:7535 (Flarna) [#19333](https://github.com/nodejs/node/pull/19333) +* [[`cb732aeda4`](https://github.com/nodejs/node/commit/cb732aeda4)] - **doc**: enable eslint prefer-template rule (Ruben Bridgewater) [#18831](https://github.com/nodejs/node/pull/18831) +* [[`ff82acb95a`](https://github.com/nodejs/node/commit/ff82acb95a)] - **doc**: update buffer examples (Ruben Bridgewater) [#18758](https://github.com/nodejs/node/pull/18758) +* [[`a4c28d77f7`](https://github.com/nodejs/node/commit/a4c28d77f7)] - **doc**: fix deprecation removed by mistake (Michaël Zasso) [#19482](https://github.com/nodejs/node/pull/19482) +* [[`b229912f6f`](https://github.com/nodejs/node/commit/b229912f6f)] - **doc**: do not announce obvious examples (Rich Trott) [#19270](https://github.com/nodejs/node/pull/19270) +* [[`c1fa0926e3`](https://github.com/nodejs/node/commit/c1fa0926e3)] - **doc**: fix typos on n-api (Kyle Robinson Young) [#19385](https://github.com/nodejs/node/pull/19385) +* [[`99e6734f19`](https://github.com/nodejs/node/commit/99e6734f19)] - **doc**: improve best practices in onboarding-extras (Rich Trott) [#19315](https://github.com/nodejs/node/pull/19315) +* [[`5a56327e79`](https://github.com/nodejs/node/commit/5a56327e79)] - **doc**: fix minor issues in async\_hooks.md (Rich Trott) [#19313](https://github.com/nodejs/node/pull/19313) +* [[`5da3ee7719`](https://github.com/nodejs/node/commit/5da3ee7719)] - **doc**: clarify default TLS handshake timeout (Rich Trott) [#19290](https://github.com/nodejs/node/pull/19290) +* [[`7f652c2bcc`](https://github.com/nodejs/node/commit/7f652c2bcc)] - **doc**: update username and email (Yuta Hiroto) [#19338](https://github.com/nodejs/node/pull/19338) +* [[`e247f19ac3`](https://github.com/nodejs/node/commit/e247f19ac3)] - **doc**: improve style guide text (Rich Trott) [#19269](https://github.com/nodejs/node/pull/19269) +* [[`c9b12f302a`](https://github.com/nodejs/node/commit/c9b12f302a)] - **doc**: remove superfluous text in onboarding-extras (Rich Trott) [#19247](https://github.com/nodejs/node/pull/19247) +* [[`6c5afebf55`](https://github.com/nodejs/node/commit/6c5afebf55)] - **doc**: make caveat in stream.md more concise (Rich Trott) [#19251](https://github.com/nodejs/node/pull/19251) +* [[`8e88a180b9`](https://github.com/nodejs/node/commit/8e88a180b9)] - **doc**: add warning to assert.doesNotThrow() (Ruben Bridgewater) [#18699](https://github.com/nodejs/node/pull/18699) +* [[`a04e4ae5e4`](https://github.com/nodejs/node/commit/a04e4ae5e4)] - **doc**: remove confusing "cats" from style guide (Rich Trott) [#19246](https://github.com/nodejs/node/pull/19246) +* [[`7c3617558e`](https://github.com/nodejs/node/commit/7c3617558e)] - **doc**: remove superfluous adverb from style guide (Rich Trott) [#19246](https://github.com/nodejs/node/pull/19246) +* [[`d117f5ff22`](https://github.com/nodejs/node/commit/d117f5ff22)] - **doc**: remove warning against readable/readable.read (Rich Trott) [#19193](https://github.com/nodejs/node/pull/19193) +* [[`5c21d16c31`](https://github.com/nodejs/node/commit/5c21d16c31)] - **doc**: add watson to collaborators (Thomas Watson) [#19234](https://github.com/nodejs/node/pull/19234) +* [[`9557e66ae1`](https://github.com/nodejs/node/commit/9557e66ae1)] - **doc**: update labels info in onboarding-extras.md (Rich Trott) [#19160](https://github.com/nodejs/node/pull/19160) +* [[`84acb9fae5`](https://github.com/nodejs/node/commit/84acb9fae5)] - **doc**: add inspector usage example (Ali Ijaz Sheikh) [#19172](https://github.com/nodejs/node/pull/19172) +* [[`27088cfaa7`](https://github.com/nodejs/node/commit/27088cfaa7)] - **doc**: improve onboarding instructions (Joyee Cheung) [#19108](https://github.com/nodejs/node/pull/19108) +* [[`9ec0eab019`](https://github.com/nodejs/node/commit/9ec0eab019)] - **doc**: make suggestion more direct in stream.md (Rich Trott) [#19124](https://github.com/nodejs/node/pull/19124) +* [[`968b867bf2`](https://github.com/nodejs/node/commit/968b867bf2)] - **doc**: document asserts Weak(Map|Set) behavior (Ruben Bridgewater) [#18248](https://github.com/nodejs/node/pull/18248) +* [[`745709396c`](https://github.com/nodejs/node/commit/745709396c)] - **(SEMVER-MINOR)** **doc**: improve .throws RegExp info (Ruben Bridgewater) [#17585](https://github.com/nodejs/node/pull/17585) +* [[`5a78c6c0a6`](https://github.com/nodejs/node/commit/5a78c6c0a6)] - **(SEMVER-MINOR)** **doc**: improve assert documentation (Ruben Bridgewater) [#17002](https://github.com/nodejs/node/pull/17002) +* [[`f4f0266bfe`](https://github.com/nodejs/node/commit/f4f0266bfe)] - **errors**: add comments about falsy error types (Ruben Bridgewater) [#18857](https://github.com/nodejs/node/pull/18857) +* [[`ffa16aad60`](https://github.com/nodejs/node/commit/ffa16aad60)] - **errors**: update all internal errors (Ruben Bridgewater) [#18857](https://github.com/nodejs/node/pull/18857) +* [[`d57a2421fc`](https://github.com/nodejs/node/commit/d57a2421fc)] - **errors**: implement new error handling (Ruben Bridgewater) [#18857](https://github.com/nodejs/node/pull/18857) +* [[`607b33cfcc`](https://github.com/nodejs/node/commit/607b33cfcc)] - **(SEMVER-MINOR)** **fs**: support as and as+ flags in stringToFlags() (Sarat Addepalli) [#18801](https://github.com/nodejs/node/pull/18801) +* [[`b01bd800c6`](https://github.com/nodejs/node/commit/b01bd800c6)] - **fs**: fix `createReadStream(…, {end: n})` for non-seekable fds (Anna Henningsen) [#19329](https://github.com/nodejs/node/pull/19329) +* [[`3914e97741`](https://github.com/nodejs/node/commit/3914e97741)] - **http2**: fixes error handling (Matteo Collina) [#19232](https://github.com/nodejs/node/pull/19232) +* [[`3bf69cd3e7`](https://github.com/nodejs/node/commit/3bf69cd3e7)] - **http2**: some general code improvements (James M Snell) [#19400](https://github.com/nodejs/node/pull/19400) +* [[`4277635bed`](https://github.com/nodejs/node/commit/4277635bed)] - **http2**: clean up Http2Settings (James M Snell) [#19400](https://github.com/nodejs/node/pull/19400) +* [[`42b6d801dc`](https://github.com/nodejs/node/commit/42b6d801dc)] - **http2**: don't aggressively inline (James M Snell) [#19400](https://github.com/nodejs/node/pull/19400) +* [[`89fbbc48ff`](https://github.com/nodejs/node/commit/89fbbc48ff)] - **http2**: simplify timeout tracking (Anna Henningsen) [#19206](https://github.com/nodejs/node/pull/19206) +* [[`f06622cd56`](https://github.com/nodejs/node/commit/f06622cd56)] - **lib**: define printErr() in script string (cjihrig) [#19285](https://github.com/nodejs/node/pull/19285) +* [[`b35eabb837`](https://github.com/nodejs/node/commit/b35eabb837)] - **lib**: handle `throw undefined` in assert.throws() (Ben Noordhuis) [#18029](https://github.com/nodejs/node/pull/18029) +* [[`0e6f720991`](https://github.com/nodejs/node/commit/0e6f720991)] - **n-api**: separate out async\_hooks test (Gabriel Schulhof) [#19392](https://github.com/nodejs/node/pull/19392) +* [[`528798c3f4`](https://github.com/nodejs/node/commit/528798c3f4)] - **n-api**: add missing exception checking (Michael Dawson) [#19362](https://github.com/nodejs/node/pull/19362) +* [[`f679ac19e0`](https://github.com/nodejs/node/commit/f679ac19e0)] - **n-api**: resolve promise in test (Gabriel Schulhof) [#19245](https://github.com/nodejs/node/pull/19245) +* [[`12f19a6b86`](https://github.com/nodejs/node/commit/12f19a6b86)] - **n-api**: update documentation (Gabriel Schulhof) [#19078](https://github.com/nodejs/node/pull/19078) +* [[`0c9577edfc`](https://github.com/nodejs/node/commit/0c9577edfc)] - **n-api,test**: add int64 bounds tests (Kyle Farnung) [#19309](https://github.com/nodejs/node/pull/19309) +* [[`f36521becf`](https://github.com/nodejs/node/commit/f36521becf)] - **n-api,test**: add a new.target test to addons-napi (Taylor Woll) [#19236](https://github.com/nodejs/node/pull/19236) +* [[`5b12d3a58e`](https://github.com/nodejs/node/commit/5b12d3a58e)] - **net**: do not inherit the no-half-open enforcer (Luigi Pinca) [#18974](https://github.com/nodejs/node/pull/18974) +* [[`a9bd8bff8a`](https://github.com/nodejs/node/commit/a9bd8bff8a)] - **path**: remove redundant function (Sergey Golovin) [#19237](https://github.com/nodejs/node/pull/19237) +* [[`55f7bbb0bd`](https://github.com/nodejs/node/commit/55f7bbb0bd)] - **repl**: refactor code for readability (Ruben Bridgewater) [#17919](https://github.com/nodejs/node/pull/17919) +* [[`6997af7378`](https://github.com/nodejs/node/commit/6997af7378)] - **repl**: upper case comments first char (Ruben Bridgewater) [#17919](https://github.com/nodejs/node/pull/17919) +* [[`3e6858e4a7`](https://github.com/nodejs/node/commit/3e6858e4a7)] - **repl**: better handling of recoverable errors (Prince J Wesley) [#18915](https://github.com/nodejs/node/pull/18915) +* [[`49391a70e1`](https://github.com/nodejs/node/commit/49391a70e1)] - **src**: fix util abort (Ruben Bridgewater) [#19223](https://github.com/nodejs/node/pull/19223) +* [[`1ba1861731`](https://github.com/nodejs/node/commit/1ba1861731)] - **src**: remove unused using declarations async\_wrap (Daniel Bevenius) [#18893](https://github.com/nodejs/node/pull/18893) +* [[`8757799d69`](https://github.com/nodejs/node/commit/8757799d69)] - **src**: remove unused stdlib.h include (Daniel Bevenius) [#19427](https://github.com/nodejs/node/pull/19427) +* [[`da62c5ca68`](https://github.com/nodejs/node/commit/da62c5ca68)] - **src**: fix minor typo in comment stream\_base.h (Daniel Bevenius) [#19429](https://github.com/nodejs/node/pull/19429) +* [[`43c482b9c8`](https://github.com/nodejs/node/commit/43c482b9c8)] - **src**: fix indentation of params in env-inl.h (Daniel Bevenius) [#19390](https://github.com/nodejs/node/pull/19390) +* [[`054dd28da6`](https://github.com/nodejs/node/commit/054dd28da6)] - **src**: make AsyncWrap constructors delegate (Daniel Bevenius) [#19366](https://github.com/nodejs/node/pull/19366) +* [[`7a3d1d205e`](https://github.com/nodejs/node/commit/7a3d1d205e)] - **src**: remove unused uv.h include from async\_wrap.cc (Daniel Bevenius) [#19342](https://github.com/nodejs/node/pull/19342) +* [[`126a161928`](https://github.com/nodejs/node/commit/126a161928)] - **src**: fix indenting of wrap-\>EmitTraceEventBefore (Daniel Bevenius) [#19340](https://github.com/nodejs/node/pull/19340) +* [[`03fb817a1d`](https://github.com/nodejs/node/commit/03fb817a1d)] - **src**: add extractPromiseWrap function (Daniel Bevenius) [#19340](https://github.com/nodejs/node/pull/19340) +* [[`e208282f68`](https://github.com/nodejs/node/commit/e208282f68)] - **src**: refactor emit before/after/promiseResolve (Daniel Bevenius) [#19295](https://github.com/nodejs/node/pull/19295) +* [[`49481d0e3b`](https://github.com/nodejs/node/commit/49481d0e3b)] - **src**: add convenience ctor for async trigger id scope (Anna Henningsen) [#19204](https://github.com/nodejs/node/pull/19204) +* [[`4b9914a318`](https://github.com/nodejs/node/commit/4b9914a318)] - **src**: avoid duplicate Before/AtExitCallback structs (Daniel Bevenius) [#19226](https://github.com/nodejs/node/pull/19226) +* [[`27754c5408`](https://github.com/nodejs/node/commit/27754c5408)] - **src**: add incr/decr operators for Reference (Daniel Bevenius) [#19083](https://github.com/nodejs/node/pull/19083) +* [[`64f646269a`](https://github.com/nodejs/node/commit/64f646269a)] - **src**: use smart pointer in AsyncWrap::WeakCallback (Daniel Bevenius) [#19168](https://github.com/nodejs/node/pull/19168) +* [[`152c931f53`](https://github.com/nodejs/node/commit/152c931f53)] - **stream**: make Duplex inherits from DuplexBase (Luigi Pinca) [#18974](https://github.com/nodejs/node/pull/18974) +* [[`9c0c0e68ac`](https://github.com/nodejs/node/commit/9c0c0e68ac)] - **stream**: add no-half-open enforcer only if needed (Luigi Pinca) [#18953](https://github.com/nodejs/node/pull/18953) +* [[`1eac1d7d85`](https://github.com/nodejs/node/commit/1eac1d7d85)] - **test**: minor refactoring (Ruben Bridgewater) [#18669](https://github.com/nodejs/node/pull/18669) +* [[`574d061c3c`](https://github.com/nodejs/node/commit/574d061c3c)] - **test**: remove assert.doesNotThrow() (Ruben Bridgewater) [#18669](https://github.com/nodejs/node/pull/18669) +* [[`5478746203`](https://github.com/nodejs/node/commit/5478746203)] - **test**: refactor assert test (Ruben Bridgewater) [#18610](https://github.com/nodejs/node/pull/18610) +* [[`4e9279df5c`](https://github.com/nodejs/node/commit/4e9279df5c)] - **test**: remove NodeTestFixture from Env constructor (Daniel Bevenius) [#18558](https://github.com/nodejs/node/pull/18558) +* [[`22b8f9fba6`](https://github.com/nodejs/node/commit/22b8f9fba6)] - **test**: introduce SetUpTestCase/TearDownTestCase (Daniel Bevenius) [#18558](https://github.com/nodejs/node/pull/18558) +* [[`519850f21e`](https://github.com/nodejs/node/commit/519850f21e)] - **test**: http2 client setNextStreamID errors (Trivikram) [#18848](https://github.com/nodejs/node/pull/18848) +* [[`e3ce084f7c`](https://github.com/nodejs/node/commit/e3ce084f7c)] - **test**: fix flaky test-http2-ping-flood (Rich Trott) [#19395](https://github.com/nodejs/node/pull/19395) +* [[`7df6d9ddc8`](https://github.com/nodejs/node/commit/7df6d9ddc8)] - **test**: rename regression tests file names (Ujjwal Sharma) [#19332](https://github.com/nodejs/node/pull/19332) +* [[`f49042131a`](https://github.com/nodejs/node/commit/f49042131a)] - **test**: use descriptive names for regression tests (Ujjwal Sharma) [#19275](https://github.com/nodejs/node/pull/19275) +* [[`01749f07bd`](https://github.com/nodejs/node/commit/01749f07bd)] - **test**: fix flaky test-http2-settings-flood (Rich Trott) [#19349](https://github.com/nodejs/node/pull/19349) +* [[`9aa5090689`](https://github.com/nodejs/node/commit/9aa5090689)] - **test**: fix test-cluster-send-handle-large-payload (Rich Trott) [#19311](https://github.com/nodejs/node/pull/19311) +* [[`11a0ef566a`](https://github.com/nodejs/node/commit/11a0ef566a)] - **test**: delete test/parallel/test-regress-GH-4948 (Ujjwal Sharma) [#19279](https://github.com/nodejs/node/pull/19279) +* [[`be20914958`](https://github.com/nodejs/node/commit/be20914958)] - **test**: shared lib build doesn't handle SIGPIPE (Yihong Wang) [#19211](https://github.com/nodejs/node/pull/19211) +* [[`f84f548986`](https://github.com/nodejs/node/commit/f84f548986)] - **test**: fix assertion argument order (Rich Trott) [#19264](https://github.com/nodejs/node/pull/19264) +* [[`84ae59e5f8`](https://github.com/nodejs/node/commit/84ae59e5f8)] - **test**: fix path in doctool/test-doctool-json (Vse Mozhet Byt) [#19287](https://github.com/nodejs/node/pull/19287) +* [[`b8ca616baa`](https://github.com/nodejs/node/commit/b8ca616baa)] - **test**: fix compiler warnings in callback-scope (Daniel Bevenius) [#19252](https://github.com/nodejs/node/pull/19252) +* [[`d3bc72e9cc`](https://github.com/nodejs/node/commit/d3bc72e9cc)] - **test**: name test files appropriately (Ujjwal Sharma) [#19212](https://github.com/nodejs/node/pull/19212) +* [[`f0c8f6969f`](https://github.com/nodejs/node/commit/f0c8f6969f)] - **test**: fix test-abort-backtrace in shared lib build (Yihong Wang) [#19213](https://github.com/nodejs/node/pull/19213) +* [[`e4c320e5d7`](https://github.com/nodejs/node/commit/e4c320e5d7)] - **test**: Remove unnecessary asserion messages in test-crypto-hash.js (Piotr Grzesik) [#18984](https://github.com/nodejs/node/pull/18984) +* [[`411f3e03fe`](https://github.com/nodejs/node/commit/411f3e03fe)] - **test**: remove flaky status for test-npm-install (Rich Trott) [#19216](https://github.com/nodejs/node/pull/19216) +* [[`a4a4819954`](https://github.com/nodejs/node/commit/a4a4819954)] - **test**: do not check text for engine-generated error (Rich Trott) [#19215](https://github.com/nodejs/node/pull/19215) +* [[`38eb432260`](https://github.com/nodejs/node/commit/38eb432260)] - **test**: refactor http-https-default-ports (Ken Lin) [#19130](https://github.com/nodejs/node/pull/19130) +* [[`0ece7cc227`](https://github.com/nodejs/node/commit/0ece7cc227)] - **test**: rename test-regress-GH-877.js (Ujjwal Sharma) [#19161](https://github.com/nodejs/node/pull/19161) +* [[`636a5f627e`](https://github.com/nodejs/node/commit/636a5f627e)] - **test**: rename test-regress-GH-784.js (Ujjwal Sharma) [#19161](https://github.com/nodejs/node/pull/19161) +* [[`c0c6d5848f`](https://github.com/nodejs/node/commit/c0c6d5848f)] - **test**: address nits and rename the corresponding fixture (Ujjwal Sharma) [#19161](https://github.com/nodejs/node/pull/19161) +* [[`22484e1fb2`](https://github.com/nodejs/node/commit/22484e1fb2)] - **test**: rename tests to remove "regress" keyword (Ujjwal Sharma) [#19161](https://github.com/nodejs/node/pull/19161) +* [[`2262a34f0b`](https://github.com/nodejs/node/commit/2262a34f0b)] - **test**: rename test-regress-GH-4027 (Ujjwal Sharma) [#19161](https://github.com/nodejs/node/pull/19161) +* [[`bdbfc0e20e`](https://github.com/nodejs/node/commit/bdbfc0e20e)] - **test**: rename test-regress-GH-4015 (Ujjwal Sharma) [#19161](https://github.com/nodejs/node/pull/19161) +* [[`da44c2ccf0`](https://github.com/nodejs/node/commit/da44c2ccf0)] - **test**: rename test-regress-GH-1697 (Ujjwal Sharma) [#19161](https://github.com/nodejs/node/pull/19161) +* [[`fa43d2f69e`](https://github.com/nodejs/node/commit/fa43d2f69e)] - **test**: rename test-regress-GH-1726 (Ujjwal Sharma) [#19161](https://github.com/nodejs/node/pull/19161) +* [[`46b5915dab`](https://github.com/nodejs/node/commit/46b5915dab)] - **test**: skip postmortem metadata test when nm fails (Joyee Cheung) [#19107](https://github.com/nodejs/node/pull/19107) +* [[`16ab3b54d1`](https://github.com/nodejs/node/commit/16ab3b54d1)] - **test**: address unreliable test-performance (Rich Trott) [#19228](https://github.com/nodejs/node/pull/19228) +* [[`1e5c7e3e47`](https://github.com/nodejs/node/commit/1e5c7e3e47)] - **test**: refactor common.expectsError (Ruben Bridgewater) [#17703](https://github.com/nodejs/node/pull/17703) +* [[`060216689a`](https://github.com/nodejs/node/commit/060216689a)] - **(SEMVER-MINOR)** **tls**: expose Finished messages in TLSSocket (Anton Salikhmetov) [#19102](https://github.com/nodejs/node/pull/19102) +* [[`b04dd7b351`](https://github.com/nodejs/node/commit/b04dd7b351)] - **tools**: enable eslint one-var rule (Ruben Bridgewater) [#18831](https://github.com/nodejs/node/pull/18831) +* [[`d4d7df8371`](https://github.com/nodejs/node/commit/d4d7df8371)] - **tools**: enable eslint strict key-spacing (Ruben Bridgewater) [#18831](https://github.com/nodejs/node/pull/18831) +* [[`9e10ddc215`](https://github.com/nodejs/node/commit/9e10ddc215)] - **tools**: enable eslint no-undef-init rule (Ruben Bridgewater) [#18831](https://github.com/nodejs/node/pull/18831) +* [[`9d1e409ee3`](https://github.com/nodejs/node/commit/9d1e409ee3)] - **tools**: enable no-unsafe-finally (Ruben Bridgewater) [#18745](https://github.com/nodejs/node/pull/18745) +* [[`d7958657d7`](https://github.com/nodejs/node/commit/d7958657d7)] - **tools**: add assert.doesNotThrow eslint rule (Ruben Bridgewater) [#18669](https://github.com/nodejs/node/pull/18669) +* [[`66694e28b1`](https://github.com/nodejs/node/commit/66694e28b1)] - **tools**: fix test-npm-package (Michaël Zasso) [#19293](https://github.com/nodejs/node/pull/19293) +* [[`9613e02ff7`](https://github.com/nodejs/node/commit/9613e02ff7)] - **tools,bootstrap**: preprocess gypi files to json (Gus Caplan) [#19140](https://github.com/nodejs/node/pull/19140) +* [[`74f0d1aa60`](https://github.com/nodejs/node/commit/74f0d1aa60)] - **(SEMVER-MINOR)** **tty**: refactor to es6 (Ruben Bridgewater) [#17615](https://github.com/nodejs/node/pull/17615) +* [[`ead727c274`](https://github.com/nodejs/node/commit/ead727c274)] - **(SEMVER-MINOR)** **tty**: add getColorDepth function (Ruben Bridgewater) [#17615](https://github.com/nodejs/node/pull/17615) +* [[`072adfea8c`](https://github.com/nodejs/node/commit/072adfea8c)] - **url**: replace "magic" numbers by constants (Sergey Golovin) [#19035](https://github.com/nodejs/node/pull/19035) +* [[`c18ac52970`](https://github.com/nodejs/node/commit/c18ac52970)] - **(SEMVER-MINOR)** **util**: add util.inspect compact option (Ruben Bridgewater) [#17576](https://github.com/nodejs/node/pull/17576) +* [[`ce3a5af69f`](https://github.com/nodejs/node/commit/ce3a5af69f)] - **(SEMVER-MINOR)** **util**: rename util.inspect argument (Ruben Bridgewater) [#17576](https://github.com/nodejs/node/pull/17576) +* [[`fd4c05ab56`](https://github.com/nodejs/node/commit/fd4c05ab56)] - **(SEMVER-MINOR)** **util**: fix custom inspect description (Ruben Bridgewater) [#17576](https://github.com/nodejs/node/pull/17576) + ## 2018-03-07, Version 9.8.0 (Current), @MylesBorins diff --git a/doc/onboarding-extras.md b/doc/onboarding-extras.md index fa2d1ae02d9b60..2bbf2957835295 100644 --- a/doc/onboarding-extras.md +++ b/doc/onboarding-extras.md @@ -50,28 +50,25 @@ If you cannot find who to cc for a file, `git shortlog -n -s ` may help. ## Labels -### By Subsystem +### Subsystems -We generally sort issues by a concept of "subsystem" so that we know what -part(s) of the codebase it touches. +* `lib/*.js` (`assert`, `buffer`, etc.) +* `build` +* `doc` +* `lib / src` +* `test` +* `tools` -**Subsystems generally are**: - -* `lib/*.js` -* `doc`, `build`, `tools`, `test`, `deps`, `lib / src` (special), and there may - be others. -* `meta` for anything non-code (process) related - -There may be more than one subsystem valid for any particular issue / PR. +There may be more than one subsystem valid for any particular issue or pull +request. ### General -Please use these when possible / appropriate - * `confirmed-bug` - Bugs you have verified exist * `discuss` - Things that need larger discussion * `feature request` - Any issue that requests a new feature (usually not PRs) * `good first issue` - Issues suitable for newcomers to process +* `meta` - For issues whose topic is governance, policies, procedures, etc. -- @@ -145,10 +142,7 @@ to update from nodejs/node: * `git remote update -p` OR `git fetch --all` (I prefer the former) * `git merge --ff-only upstream/master` (or `REMOTENAME/BRANCH`) -## best practices +## Best practices -* commit often, out to your github fork (origin), open a PR -* when making PRs make sure to spend time on the description: - * every moment you spend writing a good description quarters the amount of - time it takes to understand your code. -* usually prefer to only squash at the *end* of your work, depends on the change +* When making PRs, spend time writing a thorough description. +* Usually only squash at the end of your work. diff --git a/doc/onboarding.md b/doc/onboarding.md index a85e493d3c7561..17d5e74f41ade9 100644 --- a/doc/onboarding.md +++ b/doc/onboarding.md @@ -6,16 +6,21 @@ onboarding session. ## One week before the onboarding session * If the new Collaborator is not yet a member of the nodejs GitHub organization, - confirm that they are using two-factor authentication. It will not be possible - to add them to the organization if they are not using two-factor - authentication. + confirm that they are using [two-factor authentication][]. It will not be + possible to add them to the organization if they are not using two-factor + authentication. If they cannot receive SMS messages from GitHub, try + [using a TOTP mobile app][]. * Announce the accepted nomination in a TSC meeting and in the TSC mailing list. +* Suggest the new Collaborator install [`node-core-utils`][] and + [set up the credentials][] for it. ## Fifteen minutes before the onboarding session * Prior to the onboarding session, add the new Collaborator to [the Collaborators team](https://github.com/orgs/nodejs/teams/collaborators). +* Ask them if they want to join any subsystem teams. See + [Who to CC for Issues][who-to-cc]. ## Onboarding session @@ -87,7 +92,7 @@ onboarding session. * When adding a `semver-*` label, add a comment explaining why you're adding it. Do it right away so you don't forget! -* [**See "Who to CC in issues"**](./onboarding-extras.md#who-to-cc-in-issues) +* [**See "Who to CC in issues"**][who-to-cc] * This will come more naturally over time * For many of the teams listed there, you can ask to be added if you are interested @@ -183,7 +188,13 @@ onboarding session. ## Landing PRs -* See the Collaborator Guide: [Landing Pull Requests][] +See the Collaborator Guide: [Landing Pull Requests][]. + +Note that commits in one PR that belong to one logical change should +be squashed. It is rarely the case in onboarding exercises, so this +needs to be pointed out separately during the onboarding. + + ## Exercise: Make a PR adding yourself to the README @@ -202,9 +213,11 @@ onboarding session. for 48/72 hours to land). * Be sure to add the `PR-URL: ` and appropriate `Reviewed-By:` metadata. - * [`core-validate-commit`][] automates the validation of commit messages. * [`node-core-utils`][] automates the generation of metadata and the landing process. See the documentation of [`git-node`][]. + * [`core-validate-commit`][] automates the validation of commit messages. + This will be run during `git node land --final` of the [`git-node`][] + command. ## Final notes @@ -227,9 +240,13 @@ onboarding session. [Code of Conduct]: https://github.com/nodejs/admin/blob/master/CODE_OF_CONDUCT.md [`core-validate-commit`]: https://github.com/evanlucas/core-validate-commit -[`git-node`]: https://github.com/nodejs/node-core-utils#git-node +[`git-node`]: https://github.com/nodejs/node-core-utils/blob/master/docs/git-node.md [`node-core-utils`]: https://github.com/nodejs/node-core-utils [Landing Pull Requests]: https://github.com/nodejs/node/blob/master/COLLABORATOR_GUIDE.md#landing-pull-requests [https://github.com/nodejs/node/commit/ce986de829457c39257cd205067602e765768fb0]: https://github.com/nodejs/node/commit/ce986de829457c39257cd205067602e765768fb0 [Publicizing or hiding organization membership]: https://help.github.com/articles/publicizing-or-hiding-organization-membership/ +[set up the credentials]: https://github.com/nodejs/node-core-utils#setting-up-credentials +[two-factor authentication]: https://help.github.com/articles/securing-your-account-with-two-factor-authentication-2fa/ [Updating Node.js from Upstream]: ./onboarding-extras.md#updating-nodejs-from-upstream +[using a TOTP mobile app]: https://help.github.com/articles/configuring-two-factor-authentication-via-a-totp-mobile-app/ +[who-to-cc]: ./onboarding-extras.md#who-to-cc-in-issues diff --git a/lib/_stream_duplex.js b/lib/_stream_duplex.js index 288b8b538c3219..79ff582f459109 100644 --- a/lib/_stream_duplex.js +++ b/lib/_stream_duplex.js @@ -29,39 +29,21 @@ module.exports = Duplex; const util = require('util'); -const Readable = require('_stream_readable'); -const Writable = require('_stream_writable'); - -util.inherits(Duplex, Readable); - -{ - // avoid scope creep, the keys array can then be collected - const keys = Object.keys(Writable.prototype); - for (var v = 0; v < keys.length; v++) { - const method = keys[v]; - if (!Duplex.prototype[method]) - Duplex.prototype[method] = Writable.prototype[method]; - } -} +const DuplexBase = require('internal/streams/duplex_base'); + +util.inherits(Duplex, DuplexBase); function Duplex(options) { if (!(this instanceof Duplex)) return new Duplex(options); - Readable.call(this, options); - Writable.call(this, options); - - if (options && options.readable === false) - this.readable = false; - - if (options && options.writable === false) - this.writable = false; + DuplexBase.call(this, options); this.allowHalfOpen = true; - if (options && options.allowHalfOpen === false) + if (options && options.allowHalfOpen === false) { this.allowHalfOpen = false; - - this.once('end', onend); + this.once('end', onend); + } } Object.defineProperty(Duplex.prototype, 'writableHighWaterMark', { @@ -96,9 +78,8 @@ Object.defineProperty(Duplex.prototype, 'writableLength', { // the no-half-open enforcer function onend() { - // if we allow half-open state, or if the writable side ended, - // then we're ok. - if (this.allowHalfOpen || this._writableState.ended) + // If the writable side ended, then we're ok. + if (this._writableState.ended) return; // no more data can be written. diff --git a/lib/_tls_wrap.js b/lib/_tls_wrap.js index e17ea3f5948e82..8d988cbdbc3b90 100644 --- a/lib/_tls_wrap.js +++ b/lib/_tls_wrap.js @@ -668,6 +668,16 @@ TLSSocket.prototype.getPeerCertificate = function(detailed) { return null; }; +TLSSocket.prototype.getFinished = function() { + if (this._handle) + return this._handle.getFinished(); +}; + +TLSSocket.prototype.getPeerFinished = function() { + if (this._handle) + return this._handle.getPeerFinished(); +}; + TLSSocket.prototype.getSession = function() { if (this._handle) { return this._handle.getSession(); diff --git a/lib/assert.js b/lib/assert.js index 0d061dbff617f7..6c33af3fd4b2ca 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -22,7 +22,12 @@ const { isDeepEqual, isDeepStrictEqual } = require('internal/util/comparisons'); -const errors = require('internal/errors'); +const { AssertionError, TypeError } = require('internal/errors'); +const { inspect } = require('util'); + +const ERR_DIFF_DEACTIVATED = 0; +const ERR_DIFF_NOT_EQUAL = 1; +const ERR_DIFF_EQUAL = 2; // The assert module provides functions that throw // AssertionError's when particular conditions are not met. The @@ -30,25 +35,21 @@ const errors = require('internal/errors'); const assert = module.exports = ok; +const NO_EXCEPTION_SENTINEL = {}; + // All of the following functions must throw an AssertionError // when a corresponding condition is not met, with a message that // may be undefined if not provided. All assertion methods provide // both the actual and expected values to the assertion error for // display purposes. -function innerFail(actual, expected, message, operator, stackStartFunction) { - if (message instanceof Error) throw message; +function innerFail(obj) { + if (obj.message instanceof Error) throw obj.message; - throw new errors.AssertionError({ - message, - actual, - expected, - operator, - stackStartFunction - }); + throw new AssertionError(obj); } -function fail(actual, expected, message, operator, stackStartFunction) { +function fail(actual, expected, message, operator, stackStartFn) { const argsLen = arguments.length; if (argsLen === 0) { @@ -60,7 +61,13 @@ function fail(actual, expected, message, operator, stackStartFunction) { operator = '!='; } - innerFail(actual, expected, message, operator, stackStartFunction || fail); + innerFail({ + actual, + expected, + message, + operator, + stackStartFn: stackStartFn || fail + }); } assert.fail = fail; @@ -69,13 +76,21 @@ assert.fail = fail; // new assert.AssertionError({ message: message, // actual: actual, // expected: expected }); -assert.AssertionError = errors.AssertionError; +assert.AssertionError = AssertionError; // Pure assertion tests whether a value is truthy, as determined // by !!value. function ok(value, message) { - if (!value) innerFail(value, true, message, '==', ok); + if (!value) { + innerFail({ + actual: value, + expected: true, + message, + operator: '==', + stackStartFn: ok + }); + } } assert.ok = ok; @@ -83,7 +98,15 @@ assert.ok = ok; /* eslint-disable no-restricted-properties */ assert.equal = function equal(actual, expected, message) { // eslint-disable-next-line eqeqeq - if (actual != expected) innerFail(actual, expected, message, '==', equal); + if (actual != expected) { + innerFail({ + actual, + expected, + message, + operator: '==', + stackStartFn: equal + }); + } }; // The non-equality assertion tests for whether two objects are not @@ -91,43 +114,81 @@ assert.equal = function equal(actual, expected, message) { assert.notEqual = function notEqual(actual, expected, message) { // eslint-disable-next-line eqeqeq if (actual == expected) { - innerFail(actual, expected, message, '!=', notEqual); + innerFail({ + actual, + expected, + message, + operator: '!=', + stackStartFn: notEqual + }); } }; // The equivalence assertion tests a deep equality relation. assert.deepEqual = function deepEqual(actual, expected, message) { if (!isDeepEqual(actual, expected)) { - innerFail(actual, expected, message, 'deepEqual', deepEqual); + innerFail({ + actual, + expected, + message, + operator: 'deepEqual', + stackStartFn: deepEqual + }); } }; // The non-equivalence assertion tests for any deep inequality. assert.notDeepEqual = function notDeepEqual(actual, expected, message) { if (isDeepEqual(actual, expected)) { - innerFail(actual, expected, message, 'notDeepEqual', notDeepEqual); + innerFail({ + actual, + expected, + message, + operator: 'notDeepEqual', + stackStartFn: notDeepEqual + }); } }; /* eslint-enable */ assert.deepStrictEqual = function deepStrictEqual(actual, expected, message) { if (!isDeepStrictEqual(actual, expected)) { - innerFail(actual, expected, message, 'deepStrictEqual', deepStrictEqual); + innerFail({ + actual, + expected, + message, + operator: 'deepStrictEqual', + stackStartFn: deepStrictEqual, + errorDiff: this === strict ? ERR_DIFF_EQUAL : ERR_DIFF_DEACTIVATED + }); } }; assert.notDeepStrictEqual = notDeepStrictEqual; function notDeepStrictEqual(actual, expected, message) { if (isDeepStrictEqual(actual, expected)) { - innerFail(actual, expected, message, 'notDeepStrictEqual', - notDeepStrictEqual); + innerFail({ + actual, + expected, + message, + operator: 'notDeepStrictEqual', + stackStartFn: notDeepStrictEqual, + errorDiff: this === strict ? ERR_DIFF_NOT_EQUAL : ERR_DIFF_DEACTIVATED + }); } } // The strict equality assertion tests strict equality, as determined by ===. assert.strictEqual = function strictEqual(actual, expected, message) { if (actual !== expected) { - innerFail(actual, expected, message, '===', strictEqual); + innerFail({ + actual, + expected, + message, + operator: '===', + stackStartFn: strictEqual, + errorDiff: this === strict ? ERR_DIFF_EQUAL : ERR_DIFF_DEACTIVATED + }); } }; @@ -135,14 +196,51 @@ assert.strictEqual = function strictEqual(actual, expected, message) { // determined by !==. assert.notStrictEqual = function notStrictEqual(actual, expected, message) { if (actual === expected) { - innerFail(actual, expected, message, '!==', notStrictEqual); + innerFail({ + actual, + expected, + message, + operator: '!==', + stackStartFn: notStrictEqual, + errorDiff: this === strict ? ERR_DIFF_NOT_EQUAL : ERR_DIFF_DEACTIVATED + }); } }; -function expectedException(actual, expected) { +function compareExceptionKey(actual, expected, key, msg) { + if (!isDeepStrictEqual(actual[key], expected[key])) { + innerFail({ + actual: actual[key], + expected: expected[key], + message: msg || `${key}: expected ${inspect(expected[key])}, ` + + `not ${inspect(actual[key])}`, + operator: 'throws', + stackStartFn: assert.throws + }); + } +} + +function expectedException(actual, expected, msg) { if (typeof expected !== 'function') { - // Should be a RegExp, if not fail hard - return expected.test(actual); + if (expected instanceof RegExp) + return expected.test(actual); + // assert.doesNotThrow does not accept objects. + if (arguments.length === 2) { + throw new TypeError('ERR_INVALID_ARG_TYPE', 'expected', + ['Function', 'RegExp'], expected); + } + // The name and message could be non enumerable. Therefore test them + // explicitly. + if ('name' in expected) { + compareExceptionKey(actual, expected, 'name', msg); + } + if ('message' in expected) { + compareExceptionKey(actual, expected, 'message', msg); + } + for (const key of Object.keys(expected)) { + compareExceptionKey(actual, expected, key, msg); + } + return true; } // Guard instanceof against arrow functions as they don't have a prototype. if (expected.prototype !== undefined && actual instanceof expected) { @@ -154,59 +252,94 @@ function expectedException(actual, expected) { return expected.call({}, actual) === true; } -function tryBlock(block) { +function getActual(block) { + if (typeof block !== 'function') { + throw new TypeError('ERR_INVALID_ARG_TYPE', 'block', 'Function', + block); + } try { block(); } catch (e) { return e; } + return NO_EXCEPTION_SENTINEL; } -function innerThrows(shouldThrow, block, expected, message) { - var details = ''; +// Expected to throw an error. +assert.throws = function throws(block, error, message) { + const actual = getActual(block); - if (typeof block !== 'function') { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'block', 'Function', - block); - } + if (typeof error === 'string') { + if (arguments.length === 3) + throw new TypeError('ERR_INVALID_ARG_TYPE', + 'error', + ['Function', 'RegExp'], + error); - if (typeof expected === 'string') { - message = expected; - expected = null; + message = error; + error = null; } - const actual = tryBlock(block); - - if (shouldThrow === true) { - if (actual === undefined) { - if (expected && expected.name) { - details += ` (${expected.name})`; - } - details += message ? `: ${message}` : '.'; - fail(actual, expected, `Missing expected exception${details}`, 'throws'); - } - if (expected && expectedException(actual, expected) === false) { - throw actual; - } - } else if (actual !== undefined) { - if (!expected || expectedException(actual, expected)) { - details = message ? `: ${message}` : '.'; - fail(actual, - expected, - `Got unwanted exception${details}\n${actual.message}`, - 'doesNotThrow'); + if (actual === NO_EXCEPTION_SENTINEL) { + let details = ''; + if (error && error.name) { + details += ` (${error.name})`; } + details += message ? `: ${message}` : '.'; + innerFail({ + actual, + expected: error, + operator: 'throws', + message: `Missing expected exception${details}`, + stackStartFn: throws + }); + } + if (error && expectedException(actual, error, message) === false) { throw actual; } -} - -// Expected to throw an error. -assert.throws = function throws(block, error, message) { - innerThrows(true, block, error, message); }; assert.doesNotThrow = function doesNotThrow(block, error, message) { - innerThrows(false, block, error, message); + const actual = getActual(block); + if (actual === NO_EXCEPTION_SENTINEL) + return; + + if (typeof error === 'string') { + message = error; + error = null; + } + + if (!error || expectedException(actual, error)) { + const details = message ? `: ${message}` : '.'; + innerFail({ + actual, + expected: error, + operator: 'doesNotThrow', + message: `Got unwanted exception${details}\n${actual && actual.message}`, + stackStartFn: doesNotThrow + }); + } + throw actual; }; assert.ifError = function ifError(err) { if (err) throw err; }; + +// Expose a strict only variant of assert +function strict(value, message) { + if (!value) { + innerFail({ + actual: value, + expected: true, + message, + operator: '==', + stackStartFn: strict + }); + } +} +assert.strict = Object.assign(strict, assert, { + equal: assert.strictEqual, + deepEqual: assert.deepStrictEqual, + notEqual: assert.notStrictEqual, + notDeepEqual: assert.notDeepStrictEqual +}); +assert.strict.strict = assert.strict; diff --git a/lib/async_hooks.js b/lib/async_hooks.js index 19e7886360c13f..b7ed6ab21b1365 100644 --- a/lib/async_hooks.js +++ b/lib/async_hooks.js @@ -77,12 +77,11 @@ class AsyncHook { return this; const prev_kTotals = hook_fields[kTotals]; - hook_fields[kTotals] = 0; // createHook() has already enforced that the callbacks are all functions, // so here simply increment the count of whether each callbacks exists or // not. - hook_fields[kTotals] += hook_fields[kInit] += +!!this[init_symbol]; + hook_fields[kTotals] = hook_fields[kInit] += +!!this[init_symbol]; hook_fields[kTotals] += hook_fields[kBefore] += +!!this[before_symbol]; hook_fields[kTotals] += hook_fields[kAfter] += +!!this[after_symbol]; hook_fields[kTotals] += hook_fields[kDestroy] += +!!this[destroy_symbol]; @@ -105,9 +104,8 @@ class AsyncHook { return this; const prev_kTotals = hook_fields[kTotals]; - hook_fields[kTotals] = 0; - hook_fields[kTotals] += hook_fields[kInit] -= +!!this[init_symbol]; + hook_fields[kTotals] = hook_fields[kInit] -= +!!this[init_symbol]; hook_fields[kTotals] += hook_fields[kBefore] -= +!!this[before_symbol]; hook_fields[kTotals] += hook_fields[kAfter] -= +!!this[after_symbol]; hook_fields[kTotals] += hook_fields[kDestroy] -= +!!this[destroy_symbol]; diff --git a/lib/console.js b/lib/console.js index ac75664e850e56..ad6276297f26f7 100644 --- a/lib/console.js +++ b/lib/console.js @@ -21,7 +21,7 @@ 'use strict'; -const errors = require('internal/errors'); +const { ERR_CONSOLE_WRITABLE_STREAM } = require('internal/errors').codes; const util = require('util'); const kCounts = Symbol('counts'); @@ -35,12 +35,12 @@ function Console(stdout, stderr, ignoreErrors = true) { return new Console(stdout, stderr, ignoreErrors); } if (!stdout || typeof stdout.write !== 'function') { - throw new errors.TypeError('ERR_CONSOLE_WRITABLE_STREAM', 'stdout'); + throw new ERR_CONSOLE_WRITABLE_STREAM('stdout'); } if (!stderr) { stderr = stdout; } else if (typeof stderr.write !== 'function') { - throw new errors.TypeError('ERR_CONSOLE_WRITABLE_STREAM', 'stderr'); + throw new ERR_CONSOLE_WRITABLE_STREAM('stderr'); } var prop = { diff --git a/lib/fs.js b/lib/fs.js index d0a0280f4000b9..231303ec42c620 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -2011,8 +2011,7 @@ function ReadStream(path, options) { this.flags = options.flags === undefined ? 'r' : options.flags; this.mode = options.mode === undefined ? 0o666 : options.mode; - this.start = typeof this.fd !== 'number' && options.start === undefined ? - 0 : options.start; + this.start = options.start; this.end = options.end; this.autoClose = options.autoClose === undefined ? true : options.autoClose; this.pos = undefined; @@ -2046,6 +2045,12 @@ function ReadStream(path, options) { this.pos = this.start; } + // Backwards compatibility: Make sure `end` is a number regardless of `start`. + // TODO(addaleax): Make the above typecheck not depend on `start` instead. + // (That is a semver-major change). + if (typeof this.end !== 'number') + this.end = Infinity; + if (typeof this.fd !== 'number') this.open(); @@ -2100,6 +2105,8 @@ ReadStream.prototype._read = function(n) { if (this.pos !== undefined) toRead = Math.min(this.end - this.pos + 1, toRead); + else + toRead = Math.min(this.end - this.bytesRead + 1, toRead); // already read everything we were supposed to read! // treat as EOF. diff --git a/lib/internal/async_hooks.js b/lib/internal/async_hooks.js index 6f9b5b0a93eee5..4977af637bd1da 100644 --- a/lib/internal/async_hooks.js +++ b/lib/internal/async_hooks.js @@ -207,11 +207,15 @@ function storeActiveHooks() { // Don't want to make the assumption that kInit to kDestroy are indexes 0 to // 4. So do this the long way. active_hooks.tmp_fields = []; - active_hooks.tmp_fields[kInit] = async_hook_fields[kInit]; - active_hooks.tmp_fields[kBefore] = async_hook_fields[kBefore]; - active_hooks.tmp_fields[kAfter] = async_hook_fields[kAfter]; - active_hooks.tmp_fields[kDestroy] = async_hook_fields[kDestroy]; - active_hooks.tmp_fields[kPromiseResolve] = async_hook_fields[kPromiseResolve]; + copyHooks(active_hooks.tmp_fields, async_hook_fields); +} + +function copyHooks(destination, source) { + destination[kInit] = source[kInit]; + destination[kBefore] = source[kBefore]; + destination[kAfter] = source[kAfter]; + destination[kDestroy] = source[kDestroy]; + destination[kPromiseResolve] = source[kPromiseResolve]; } @@ -219,11 +223,7 @@ function storeActiveHooks() { // during hook callback execution. function restoreActiveHooks() { active_hooks.array = active_hooks.tmp_array; - async_hook_fields[kInit] = active_hooks.tmp_fields[kInit]; - async_hook_fields[kBefore] = active_hooks.tmp_fields[kBefore]; - async_hook_fields[kAfter] = active_hooks.tmp_fields[kAfter]; - async_hook_fields[kDestroy] = active_hooks.tmp_fields[kDestroy]; - async_hook_fields[kPromiseResolve] = active_hooks.tmp_fields[kPromiseResolve]; + copyHooks(async_hook_fields, active_hooks.tmp_fields); active_hooks.tmp_array = null; active_hooks.tmp_fields = null; diff --git a/lib/internal/constants.js b/lib/internal/constants.js index f0ffec7a447529..c9a5bea833306f 100644 --- a/lib/internal/constants.js +++ b/lib/internal/constants.js @@ -8,9 +8,39 @@ module.exports = { CHAR_LOWERCASE_Z: 122, /*z*/ // Non-alphabetic chars. - CHAR_DOT: 46, /*.*/ - CHAR_FORWARD_SLASH: 47, /*/*/ - CHAR_BACKWARD_SLASH: 92, /*\*/ - CHAR_COLON: 58, /*:*/ - CHAR_QUESTION_MARK: 63, /*?*/ + CHAR_DOT: 46, /* . */ + CHAR_FORWARD_SLASH: 47, /* / */ + CHAR_BACKWARD_SLASH: 92, /* \ */ + CHAR_VERTICAL_LINE: 124, /* | */ + CHAR_COLON: 58, /* : */ + CHAR_QUESTION_MARK: 63, /* ? */ + CHAR_UNDERSCORE: 95, /* _ */ + CHAR_LINE_FEED: 10, /* \n */ + CHAR_CARRIAGE_RETURN: 13, /* \r */ + CHAR_TAB: 9, /* \t */ + CHAR_FORM_FEED: 12, /* \f */ + CHAR_EXCLAMATION_MARK: 33, /* ! */ + CHAR_HASH: 35, /* # */ + CHAR_SPACE: 32, /* */ + CHAR_NO_BREAK_SPACE: 160, /* \u00A0 */ + CHAR_ZERO_WIDTH_NOBREAK_SPACE: 65279, /* \uFEFF */ + CHAR_LEFT_SQUARE_BRACKET: 91, /* [ */ + CHAR_RIGHT_SQUARE_BRACKET: 93, /* ] */ + CHAR_LEFT_ANGLE_BRACKET: 60, /* < */ + CHAR_RIGHT_ANGLE_BRACKET: 62, /* > */ + CHAR_LEFT_CURLY_BRACKET: 123, /* { */ + CHAR_RIGHT_CURLY_BRACKET: 125, /* } */ + CHAR_HYPHEN_MINUS: 45, /* - */ + CHAR_PLUS: 43, /* + */ + CHAR_DOUBLE_QUOTE: 34, /* " */ + CHAR_SINGLE_QUOTE: 39, /* ' */ + CHAR_PERCENT: 37, /* % */ + CHAR_SEMICOLON: 59, /* ; */ + CHAR_CIRCUMFLEX_ACCENT: 94, /* ^ */ + CHAR_GRAVE_ACCENT: 96, /* ` */ + CHAR_AT: 64, /* @ */ + + // Digits + CHAR_0: 48, /* 0 */ + CHAR_9: 57, /* 9 */ }; diff --git a/lib/internal/errors.js b/lib/internal/errors.js index f4a77e037bc491..d08b1bfad156c0 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -12,6 +12,11 @@ const kCode = Symbol('code'); const messages = new Map(); +const codes = {}; + +var green = ''; +var red = ''; +var white = ''; const { UV_EAI_MEMORY, @@ -78,22 +83,227 @@ function makeNodeError(Base) { }; } +function createErrDiff(actual, expected, operator) { + var other = ''; + var res = ''; + var lastPos = 0; + var end = ''; + var skipped = false; + const util = lazyUtil(); + const actualLines = util + .inspect(actual, { compact: false, customInspect: false }).split('\n'); + const expectedLines = util + .inspect(expected, { compact: false, customInspect: false }).split('\n'); + const msg = `Input A expected to ${operator} input B:\n` + + `${green}+ expected${white} ${red}- actual${white}`; + const skippedMsg = ' ... Lines skipped'; + + // Remove all ending lines that match (this optimizes the output for + // readability by reducing the number of total changed lines). + var a = actualLines[actualLines.length - 1]; + var b = expectedLines[expectedLines.length - 1]; + var i = 0; + while (a === b) { + if (i++ < 2) { + end = `\n ${a}${end}`; + } else { + other = a; + } + actualLines.pop(); + expectedLines.pop(); + if (actualLines.length === 0 || expectedLines.length === 0) + break; + a = actualLines[actualLines.length - 1]; + b = expectedLines[expectedLines.length - 1]; + } + if (i > 3) { + end = `\n...${end}`; + skipped = true; + } + if (other !== '') { + end = `\n ${other}${end}`; + other = ''; + } + + const maxLines = Math.max(actualLines.length, expectedLines.length); + var printedLines = 0; + for (i = 0; i < maxLines; i++) { + // Only extra expected lines exist + const cur = i - lastPos; + if (actualLines.length < i + 1) { + if (cur > 1 && i > 2) { + if (cur > 4) { + res += '\n...'; + skipped = true; + } else if (cur > 3) { + res += `\n ${expectedLines[i - 2]}`; + printedLines++; + } + res += `\n ${expectedLines[i - 1]}`; + printedLines++; + } + lastPos = i; + other += `\n${green}+${white} ${expectedLines[i]}`; + printedLines++; + // Only extra actual lines exist + } else if (expectedLines.length < i + 1) { + if (cur > 1 && i > 2) { + if (cur > 4) { + res += '\n...'; + skipped = true; + } else if (cur > 3) { + res += `\n ${actualLines[i - 2]}`; + printedLines++; + } + res += `\n ${actualLines[i - 1]}`; + printedLines++; + } + lastPos = i; + res += `\n${red}-${white} ${actualLines[i]}`; + printedLines++; + // Lines diverge + } else if (actualLines[i] !== expectedLines[i]) { + if (cur > 1 && i > 2) { + if (cur > 4) { + res += '\n...'; + skipped = true; + } else if (cur > 3) { + res += `\n ${actualLines[i - 2]}`; + printedLines++; + } + res += `\n ${actualLines[i - 1]}`; + printedLines++; + } + lastPos = i; + res += `\n${red}-${white} ${actualLines[i]}`; + other += `\n${green}+${white} ${expectedLines[i]}`; + printedLines += 2; + // Lines are identical + } else { + res += other; + other = ''; + if (cur === 1 || i === 0) { + res += `\n ${actualLines[i]}`; + printedLines++; + } + } + // Inspected object to big (Show ~20 rows max) + if (printedLines > 20 && i < maxLines - 2) { + return `${msg}${skippedMsg}\n${res}\n...${other}\n...`; + } + } + return `${msg}${skipped ? skippedMsg : ''}\n${res}${other}${end}`; +} + +function makeNodeErrorWithCode(Base, key) { + return class NodeError extends Base { + constructor(...args) { + super(message(key, args)); + } + + get name() { + return `${super.name} [${key}]`; + } + + set name(value) { + defineProperty(this, 'name', { + configurable: true, + enumerable: true, + value, + writable: true + }); + } + + get code() { + return key; + } + + set code(value) { + defineProperty(this, 'code', { + configurable: true, + enumerable: true, + value, + writable: true + }); + } + }; +} + +// Utility function for registering the error codes. Only used here. Exported +// *only* to allow for testing. +function E(sym, val, def, ...otherClasses) { + messages.set(sym, val); + if (def === undefined) return; + def = makeNodeErrorWithCode(def, sym); + if (otherClasses.length !== 0) { + otherClasses.forEach((clazz) => { + def[clazz.name] = makeNodeErrorWithCode(clazz, sym); + }); + } + codes[sym] = def; +} + class AssertionError extends Error { constructor(options) { if (typeof options !== 'object' || options === null) { throw new exports.TypeError('ERR_INVALID_ARG_TYPE', 'options', 'Object'); } - var { actual, expected, message, operator, stackStartFunction } = options; - if (message) { + var { + actual, + expected, + message, + operator, + stackStartFn, + errorDiff = 0 + } = options; + + if (message != null) { super(message); } else { + if (util_ === null && + process.stdout.isTTY && + process.stdout.getColorDepth() !== 1) { + green = '\u001b[32m'; + white = '\u001b[39m'; + red = '\u001b[31m'; + } const util = lazyUtil(); - if (actual && actual.stack && actual instanceof Error) + if (typeof actual === 'object' && actual !== null && + 'stack' in actual && actual instanceof Error) { actual = `${actual.name}: ${actual.message}`; - if (expected && expected.stack && expected instanceof Error) + } + if (typeof expected === 'object' && expected !== null && + 'stack' in expected && expected instanceof Error) { expected = `${expected.name}: ${expected.message}`; - super(`${util.inspect(actual).slice(0, 128)} ` + - `${operator} ${util.inspect(expected).slice(0, 128)}`); + } + + if (errorDiff === 0) { + let res = util.inspect(actual); + let other = util.inspect(expected); + if (res.length > 128) + res = `${res.slice(0, 125)}...`; + if (other.length > 128) + other = `${other.slice(0, 125)}...`; + super(`${res} ${operator} ${other}`); + } else if (errorDiff === 1) { + // In case the objects are equal but the operator requires unequal, show + // the first object and say A equals B + const res = util.inspect( + actual, + { compact: false, customInspect: false } + ).split('\n'); + + if (res.length > 20) { + res[19] = '...'; + while (res.length > 20) { + res.pop(); + } + } + // Only print a single object. + super(`Identical input passed to ${operator}:\n${res.join('\n')}`); + } else { + super(createErrDiff(actual, expected, operator)); + } } this.generatedMessage = !message; @@ -102,7 +312,7 @@ class AssertionError extends Error { this.actual = actual; this.expected = expected; this.operator = operator; - Error.captureStackTrace(this, stackStartFunction); + Error.captureStackTrace(this, stackStartFn); } } @@ -135,12 +345,6 @@ function message(key, args) { return String(fmt.apply(null, args)); } -// Utility function for registering the error codes. Only used here. Exported -// *only* to allow for testing. -function E(sym, val) { - messages.set(sym, typeof val === 'function' ? val : String(val)); -} - /** * This used to be util._errnoException(). * @@ -251,6 +455,7 @@ module.exports = exports = { RangeError: makeNodeError(RangeError), URIError: makeNodeError(URIError), AssertionError, + codes, E // This is exported only to facilitate testing. }; @@ -267,124 +472,135 @@ module.exports = exports = { // Any error code added here should also be added to the documentation // // Note: Please try to keep these in alphabetical order -E('ERR_ARG_NOT_ITERABLE', '%s must be iterable'); -E('ERR_ASSERTION', '%s'); -E('ERR_ASYNC_CALLBACK', '%s must be a function'); -E('ERR_ASYNC_TYPE', 'Invalid name for async "type": %s'); -E('ERR_BUFFER_OUT_OF_BOUNDS', bufferOutOfBounds); +// +// Note: Node.js specific errors must begin with the prefix ERR_ + +E('ERR_ARG_NOT_ITERABLE', '%s must be iterable', TypeError); +E('ERR_ASSERTION', '%s', AssertionError); +E('ERR_ASYNC_CALLBACK', '%s must be a function', TypeError); +E('ERR_ASYNC_TYPE', 'Invalid name for async "type": %s', TypeError); +E('ERR_BUFFER_OUT_OF_BOUNDS', bufferOutOfBounds, RangeError); E('ERR_BUFFER_TOO_LARGE', - `Cannot create a Buffer larger than 0x${kMaxLength.toString(16)} bytes`); -E('ERR_CHILD_CLOSED_BEFORE_REPLY', 'Child closed before reply received'); + `Cannot create a Buffer larger than 0x${kMaxLength.toString(16)} bytes`, + RangeError); +E('ERR_CHILD_CLOSED_BEFORE_REPLY', + 'Child closed before reply received', Error); E('ERR_CONSOLE_WRITABLE_STREAM', - 'Console expects a writable stream instance for %s'); -E('ERR_CPU_USAGE', 'Unable to obtain cpu usage %s'); + 'Console expects a writable stream instance for %s', TypeError); +E('ERR_CPU_USAGE', 'Unable to obtain cpu usage %s', Error); E('ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED', - 'Custom engines not supported by this OpenSSL'); -E('ERR_CRYPTO_ECDH_INVALID_FORMAT', 'Invalid ECDH format: %s'); -E('ERR_CRYPTO_ENGINE_UNKNOWN', 'Engine "%s" was not found'); + 'Custom engines not supported by this OpenSSL', Error); +E('ERR_CRYPTO_ECDH_INVALID_FORMAT', 'Invalid ECDH format: %s', TypeError); +E('ERR_CRYPTO_ENGINE_UNKNOWN', 'Engine "%s" was not found', Error); E('ERR_CRYPTO_FIPS_FORCED', - 'Cannot set FIPS mode, it was forced with --force-fips at startup.'); -E('ERR_CRYPTO_FIPS_UNAVAILABLE', 'Cannot set FIPS mode in a non-FIPS build.'); -E('ERR_CRYPTO_HASH_DIGEST_NO_UTF16', 'hash.digest() does not support UTF-16'); -E('ERR_CRYPTO_HASH_FINALIZED', 'Digest already called'); -E('ERR_CRYPTO_HASH_UPDATE_FAILED', 'Hash update failed'); -E('ERR_CRYPTO_INVALID_DIGEST', 'Invalid digest: %s'); -E('ERR_CRYPTO_SIGN_KEY_REQUIRED', 'No key provided to sign'); + 'Cannot set FIPS mode, it was forced with --force-fips at startup.', Error); +E('ERR_CRYPTO_FIPS_UNAVAILABLE', 'Cannot set FIPS mode in a non-FIPS build.', + Error); +E('ERR_CRYPTO_HASH_DIGEST_NO_UTF16', 'hash.digest() does not support UTF-16', + Error); +E('ERR_CRYPTO_HASH_FINALIZED', 'Digest already called', Error); +E('ERR_CRYPTO_HASH_UPDATE_FAILED', 'Hash update failed', Error); +E('ERR_CRYPTO_INVALID_DIGEST', 'Invalid digest: %s', TypeError); +// Switch to TypeError. The current implementation does not seem right. +E('ERR_CRYPTO_SIGN_KEY_REQUIRED', 'No key provided to sign', Error); E('ERR_CRYPTO_TIMING_SAFE_EQUAL_LENGTH', - 'Input buffers must have the same length'); -E('ERR_DNS_SET_SERVERS_FAILED', 'c-ares failed to set servers: "%s" [%s]'); + 'Input buffers must have the same length', RangeError); +E('ERR_DNS_SET_SERVERS_FAILED', 'c-ares failed to set servers: "%s" [%s]', + Error); E('ERR_DOMAIN_CALLBACK_NOT_AVAILABLE', 'A callback was registered through ' + - 'process.setUncaughtExceptionCaptureCallback(), which is mutually ' + - 'exclusive with using the `domain` module'); + 'process.setUncaughtExceptionCaptureCallback(), which is mutually ' + + 'exclusive with using the `domain` module', + Error); E('ERR_DOMAIN_CANNOT_SET_UNCAUGHT_EXCEPTION_CAPTURE', 'The `domain` module is in use, which is mutually exclusive with calling ' + - 'process.setUncaughtExceptionCaptureCallback()'); + 'process.setUncaughtExceptionCaptureCallback()', + Error); E('ERR_ENCODING_INVALID_ENCODED_DATA', - 'The encoded data was not valid for encoding %s'); -E('ERR_ENCODING_NOT_SUPPORTED', 'The "%s" encoding is not supported'); -E('ERR_FALSY_VALUE_REJECTION', 'Promise was rejected with falsy value'); -E('ERR_HTTP2_ALREADY_SHUTDOWN', - 'Http2Session is already shutdown or destroyed'); + 'The encoded data was not valid for encoding %s', TypeError); +E('ERR_ENCODING_NOT_SUPPORTED', 'The "%s" encoding is not supported', + RangeError); // One entry is currently falsy implemented as "Error" +E('ERR_FALSY_VALUE_REJECTION', 'Promise was rejected with falsy value', Error); E('ERR_HTTP2_ALTSVC_INVALID_ORIGIN', - 'HTTP/2 ALTSVC frames require a valid origin'); + 'HTTP/2 ALTSVC frames require a valid origin', TypeError); E('ERR_HTTP2_ALTSVC_LENGTH', - 'HTTP/2 ALTSVC frames are limited to 16382 bytes'); + 'HTTP/2 ALTSVC frames are limited to 16382 bytes', TypeError); E('ERR_HTTP2_CONNECT_AUTHORITY', - ':authority header is required for CONNECT requests'); + ':authority header is required for CONNECT requests', Error); E('ERR_HTTP2_CONNECT_PATH', - 'The :path header is forbidden for CONNECT requests'); + 'The :path header is forbidden for CONNECT requests', Error); E('ERR_HTTP2_CONNECT_SCHEME', - 'The :scheme header is forbidden for CONNECT requests'); -E('ERR_HTTP2_FRAME_ERROR', - (type, code, id) => { - let msg = `Error sending frame type ${type}`; - if (id !== undefined) - msg += ` for stream ${id}`; - msg += ` with code ${code}`; - return msg; - }); + 'The :scheme header is forbidden for CONNECT requests', Error); E('ERR_HTTP2_GOAWAY_SESSION', - 'New streams cannot be created after receiving a GOAWAY'); + 'New streams cannot be created after receiving a GOAWAY', Error); E('ERR_HTTP2_HEADERS_AFTER_RESPOND', - 'Cannot specify additional headers after response initiated'); -E('ERR_HTTP2_HEADERS_OBJECT', 'Headers must be an object'); -E('ERR_HTTP2_HEADERS_SENT', 'Response has already been initiated.'); -E('ERR_HTTP2_HEADER_REQUIRED', 'The %s header is required'); + 'Cannot specify additional headers after response initiated', Error); +E('ERR_HTTP2_HEADERS_SENT', 'Response has already been initiated.', Error); + +// This should probably be a `TypeError`. E('ERR_HTTP2_HEADER_SINGLE_VALUE', - 'Header field "%s" must have only a single value'); -E('ERR_HTTP2_INFO_HEADERS_AFTER_RESPOND', - 'Cannot send informational headers after the HTTP message has been sent'); + 'Header field "%s" must have only a single value', Error); E('ERR_HTTP2_INFO_STATUS_NOT_ALLOWED', - 'Informational status codes cannot be used'); + 'Informational status codes cannot be used', RangeError); + +// This should probably be a `TypeError`. E('ERR_HTTP2_INVALID_CONNECTION_HEADERS', - 'HTTP/1 Connection specific headers are forbidden: "%s"'); -E('ERR_HTTP2_INVALID_HEADER_VALUE', 'Invalid value "%s" for header "%s"'); + 'HTTP/1 Connection specific headers are forbidden: "%s"', Error); +E('ERR_HTTP2_INVALID_HEADER_VALUE', + 'Invalid value "%s" for header "%s"', TypeError); E('ERR_HTTP2_INVALID_INFO_STATUS', - 'Invalid informational status code: %s'); + 'Invalid informational status code: %s', RangeError); E('ERR_HTTP2_INVALID_PACKED_SETTINGS_LENGTH', - 'Packed settings length must be a multiple of six'); + 'Packed settings length must be a multiple of six', RangeError); + +// This should probably be a `TypeError`. E('ERR_HTTP2_INVALID_PSEUDOHEADER', - '"%s" is an invalid pseudoheader or is used incorrectly'); -E('ERR_HTTP2_INVALID_SESSION', 'The session has been destroyed'); + '"%s" is an invalid pseudoheader or is used incorrectly', Error); +E('ERR_HTTP2_INVALID_SESSION', 'The session has been destroyed', Error); E('ERR_HTTP2_INVALID_SETTING_VALUE', - 'Invalid value for setting "%s": %s'); -E('ERR_HTTP2_INVALID_STREAM', 'The stream has been destroyed'); + 'Invalid value for setting "%s": %s', TypeError, RangeError); +E('ERR_HTTP2_INVALID_STREAM', 'The stream has been destroyed', Error); E('ERR_HTTP2_MAX_PENDING_SETTINGS_ACK', - 'Maximum number of pending settings acknowledgements (%s)'); + 'Maximum number of pending settings acknowledgements (%s)', Error); E('ERR_HTTP2_NO_SOCKET_MANIPULATION', - 'HTTP/2 sockets should not be directly manipulated (e.g. read and written)'); + 'HTTP/2 sockets should not be directly manipulated (e.g. read and written)', + Error); E('ERR_HTTP2_OUT_OF_STREAMS', - 'No stream ID is available because maximum stream ID has been reached'); + 'No stream ID is available because maximum stream ID has been reached', + Error); E('ERR_HTTP2_PAYLOAD_FORBIDDEN', - 'Responses with %s status must not have a payload'); -E('ERR_HTTP2_PING_CANCEL', 'HTTP2 ping cancelled'); -E('ERR_HTTP2_PING_LENGTH', 'HTTP2 ping payload must be 8 bytes'); -E('ERR_HTTP2_PSEUDOHEADER_NOT_ALLOWED', 'Cannot set HTTP/2 pseudo-headers'); -E('ERR_HTTP2_PUSH_DISABLED', 'HTTP/2 client has disabled push streams'); -E('ERR_HTTP2_SEND_FILE', 'Only regular files can be sent'); -E('ERR_HTTP2_SESSION_ERROR', 'Session closed with error code %s'); + 'Responses with %s status must not have a payload', Error); +E('ERR_HTTP2_PING_CANCEL', 'HTTP2 ping cancelled', Error); +E('ERR_HTTP2_PING_LENGTH', 'HTTP2 ping payload must be 8 bytes', RangeError); + +// This should probably be a `TypeError`. +E('ERR_HTTP2_PSEUDOHEADER_NOT_ALLOWED', + 'Cannot set HTTP/2 pseudo-headers', Error); +E('ERR_HTTP2_PUSH_DISABLED', 'HTTP/2 client has disabled push streams', Error); +E('ERR_HTTP2_SEND_FILE', 'Only regular files can be sent', Error); +E('ERR_HTTP2_SESSION_ERROR', 'Session closed with error code %s', Error); E('ERR_HTTP2_SOCKET_BOUND', - 'The socket is already bound to an Http2Session'); + 'The socket is already bound to an Http2Session', Error); E('ERR_HTTP2_STATUS_101', - 'HTTP status code 101 (Switching Protocols) is forbidden in HTTP/2'); -E('ERR_HTTP2_STATUS_INVALID', 'Invalid status code: %s'); -E('ERR_HTTP2_STREAM_CANCEL', 'The pending stream has been canceled'); -E('ERR_HTTP2_STREAM_ERROR', 'Stream closed with error code %s'); -E('ERR_HTTP2_STREAM_SELF_DEPENDENCY', 'A stream cannot depend on itself'); -E('ERR_HTTP2_UNSUPPORTED_PROTOCOL', 'protocol "%s" is unsupported.'); + 'HTTP status code 101 (Switching Protocols) is forbidden in HTTP/2', Error); +E('ERR_HTTP2_STATUS_INVALID', 'Invalid status code: %s', RangeError); +E('ERR_HTTP2_STREAM_CANCEL', 'The pending stream has been canceled', Error); +E('ERR_HTTP2_STREAM_ERROR', 'Stream closed with error code %s', Error); +E('ERR_HTTP2_STREAM_SELF_DEPENDENCY', + 'A stream cannot depend on itself', Error); +E('ERR_HTTP2_UNSUPPORTED_PROTOCOL', 'protocol "%s" is unsupported.', Error); E('ERR_HTTP_HEADERS_SENT', - 'Cannot %s headers after they are sent to the client'); -E('ERR_HTTP_INVALID_CHAR', 'Invalid character in statusMessage.'); -E('ERR_HTTP_INVALID_STATUS_CODE', 'Invalid status code: %s'); + 'Cannot %s headers after they are sent to the client', Error); +E('ERR_HTTP_INVALID_STATUS_CODE', 'Invalid status code: %s', RangeError); E('ERR_HTTP_TRAILER_INVALID', - 'Trailers are invalid with this transfer encoding'); -E('ERR_INDEX_OUT_OF_RANGE', 'Index out of range'); -E('ERR_INSPECTOR_ALREADY_CONNECTED', 'The inspector is already connected'); -E('ERR_INSPECTOR_CLOSED', 'Session was closed'); -E('ERR_INSPECTOR_NOT_AVAILABLE', 'Inspector is not available'); -E('ERR_INSPECTOR_NOT_CONNECTED', 'Session is not connected'); -E('ERR_INVALID_ARG_TYPE', invalidArgType); + 'Trailers are invalid with this transfer encoding', Error); +E('ERR_INDEX_OUT_OF_RANGE', 'Index out of range', RangeError); +E('ERR_INSPECTOR_ALREADY_CONNECTED', + 'The inspector is already connected', Error); +E('ERR_INSPECTOR_CLOSED', 'Session was closed', Error); +E('ERR_INSPECTOR_NOT_AVAILABLE', 'Inspector is not available', Error); +E('ERR_INSPECTOR_NOT_CONNECTED', 'Session is not connected', Error); +E('ERR_INVALID_ARG_TYPE', invalidArgType, TypeError); E('ERR_INVALID_ARG_VALUE', (name, value, reason = 'is invalid') => { const util = lazyUtil(); let inspected = util.inspect(value); @@ -392,136 +608,165 @@ E('ERR_INVALID_ARG_VALUE', (name, value, reason = 'is invalid') => { inspected = inspected.slice(0, 128) + '...'; } return `The argument '${name}' ${reason}. Received ${inspected}`; -}), +}, TypeError, RangeError); // Some are currently falsy implemented as "Error" E('ERR_INVALID_ARRAY_LENGTH', (name, len, actual) => { internalAssert(typeof actual === 'number', 'actual must be a number'); return `The array "${name}" (length ${actual}) must be of length ${len}.`; - }); -E('ERR_INVALID_ASYNC_ID', 'Invalid %s value: %s'); -E('ERR_INVALID_BUFFER_SIZE', 'Buffer size must be a multiple of %s'); -E('ERR_INVALID_CALLBACK', 'Callback must be a function'); -E('ERR_INVALID_CHAR', invalidChar); + }, TypeError); +E('ERR_INVALID_ASYNC_ID', 'Invalid %s value: %s', RangeError); +E('ERR_INVALID_BUFFER_SIZE', + 'Buffer size must be a multiple of %s', RangeError); +E('ERR_INVALID_CALLBACK', 'Callback must be a function', TypeError); +E('ERR_INVALID_CHAR', invalidChar, TypeError); //Check falsy "Error" entries. + +// This should probably be a `TypeError`. E('ERR_INVALID_CURSOR_POS', - 'Cannot set cursor row without setting its column'); -E('ERR_INVALID_DOMAIN_NAME', 'Unable to determine the domain name'); -E('ERR_INVALID_FD', '"fd" must be a positive integer: %s'); -E('ERR_INVALID_FD_TYPE', 'Unsupported fd type: %s'); + 'Cannot set cursor row without setting its column', Error); + +// This should probably be a `TypeError`. +E('ERR_INVALID_DOMAIN_NAME', 'Unable to determine the domain name', Error); +E('ERR_INVALID_FD', + '"fd" must be a positive integer: %s', RangeError); +E('ERR_INVALID_FD_TYPE', 'Unsupported fd type: %s', TypeError); E('ERR_INVALID_FILE_URL_HOST', - 'File URL host must be "localhost" or empty on %s'); -E('ERR_INVALID_FILE_URL_PATH', 'File URL path %s'); -E('ERR_INVALID_HANDLE_TYPE', 'This handle type cannot be sent'); -E('ERR_INVALID_HTTP_TOKEN', '%s must be a valid HTTP token ["%s"]'); -E('ERR_INVALID_IP_ADDRESS', 'Invalid IP address: %s'); + 'File URL host must be "localhost" or empty on %s', TypeError); +E('ERR_INVALID_FILE_URL_PATH', 'File URL path %s', TypeError); +E('ERR_INVALID_HANDLE_TYPE', 'This handle type cannot be sent', TypeError); +E('ERR_INVALID_HTTP_TOKEN', '%s must be a valid HTTP token ["%s"]', TypeError); +// The `Error` should probably be a `TypeError`. +E('ERR_INVALID_IP_ADDRESS', 'Invalid IP address: %s', TypeError, Error); E('ERR_INVALID_OPT_VALUE', (name, value) => - `The value "${String(value)}" is invalid for option "${name}"`); + `The value "${String(value)}" is invalid for option "${name}"`, + TypeError, + RangeError); E('ERR_INVALID_OPT_VALUE_ENCODING', - 'The value "%s" is invalid for option "encoding"'); -E('ERR_INVALID_PERFORMANCE_MARK', 'The "%s" performance mark has not been set'); -E('ERR_INVALID_PROTOCOL', 'Protocol "%s" not supported. Expected "%s"'); + 'The value "%s" is invalid for option "encoding"', TypeError); +E('ERR_INVALID_PERFORMANCE_MARK', + 'The "%s" performance mark has not been set', Error); + +// This should probably be a `TypeError`. +E('ERR_INVALID_PROTOCOL', 'Protocol "%s" not supported. Expected "%s"', Error); + +// This should probably be a `TypeError`. E('ERR_INVALID_REPL_EVAL_CONFIG', - 'Cannot specify both "breakEvalOnSigint" and "eval" for REPL'); + 'Cannot specify both "breakEvalOnSigint" and "eval" for REPL', Error); E('ERR_INVALID_SYNC_FORK_INPUT', - 'Asynchronous forks do not support Buffer, Uint8Array or string input: %s'); -E('ERR_INVALID_THIS', 'Value of "this" must be of type %s'); -E('ERR_INVALID_TUPLE', '%s must be an iterable %s tuple'); -E('ERR_INVALID_URI', 'URI malformed'); -E('ERR_INVALID_URL', 'Invalid URL: %s'); + 'Asynchronous forks do not support Buffer, Uint8Array or string input: %s', + TypeError); +E('ERR_INVALID_THIS', 'Value of "this" must be of type %s', TypeError); +E('ERR_INVALID_TUPLE', '%s must be an iterable %s tuple', TypeError); +E('ERR_INVALID_URI', 'URI malformed', URIError); +E('ERR_INVALID_URL', 'Invalid URL: %s', TypeError); E('ERR_INVALID_URL_SCHEME', - (expected) => `The URL must be ${oneOf(expected, 'scheme')}`); -E('ERR_IPC_CHANNEL_CLOSED', 'Channel closed'); -E('ERR_IPC_DISCONNECTED', 'IPC channel is already disconnected'); -E('ERR_IPC_ONE_PIPE', 'Child process can have only one IPC pipe'); -E('ERR_IPC_SYNC_FORK', 'IPC cannot be used with synchronous forks'); -E('ERR_METHOD_NOT_IMPLEMENTED', 'The %s method is not implemented'); -E('ERR_MISSING_ARGS', missingArgs); -E('ERR_MISSING_DYNAMIC_INSTANTIATE_HOOK', - 'The ES Module loader may not return a format of \'dynamic\' when no ' + - 'dynamicInstantiate function was provided'); -E('ERR_MISSING_MODULE', 'Cannot find module %s'); -E('ERR_MODULE_RESOLUTION_LEGACY', '%s not found by import in %s.' + - ' Legacy behavior in require() would have found it at %s'); -E('ERR_MULTIPLE_CALLBACK', 'Callback called multiple times'); -E('ERR_NAPI_CONS_FUNCTION', 'Constructor must be a function'); -E('ERR_NAPI_CONS_PROTOTYPE_OBJECT', 'Constructor.prototype must be an object'); + (expected) => `The URL must be ${oneOf(expected, 'scheme')}`, TypeError); +E('ERR_IPC_CHANNEL_CLOSED', 'Channel closed', Error); +E('ERR_IPC_DISCONNECTED', 'IPC channel is already disconnected', Error); +E('ERR_IPC_ONE_PIPE', 'Child process can have only one IPC pipe', Error); +E('ERR_IPC_SYNC_FORK', 'IPC cannot be used with synchronous forks', Error); +E('ERR_METHOD_NOT_IMPLEMENTED', 'The %s method is not implemented', Error); +E('ERR_MISSING_ARGS', missingArgs, TypeError); +E('ERR_MISSING_MODULE', 'Cannot find module %s', Error); +E('ERR_MODULE_RESOLUTION_LEGACY', + '%s not found by import in %s.' + + ' Legacy behavior in require() would have found it at %s', + Error); +E('ERR_MULTIPLE_CALLBACK', 'Callback called multiple times', Error); +E('ERR_NAPI_CONS_FUNCTION', 'Constructor must be a function', TypeError); E('ERR_NAPI_INVALID_DATAVIEW_ARGS', 'byte_offset + byte_length should be less than or eqaul to the size in ' + - 'bytes of the array passed in'); -E('ERR_NAPI_INVALID_TYPEDARRAY_ALIGNMENT', 'start offset of %s should be a ' + - 'multiple of %s'); -E('ERR_NAPI_INVALID_TYPEDARRAY_LENGTH', 'Invalid typed array length'); -E('ERR_NO_CRYPTO', 'Node.js is not compiled with OpenSSL crypto support'); -E('ERR_NO_ICU', '%s is not supported on Node.js compiled without ICU'); -E('ERR_NO_LONGER_SUPPORTED', '%s is no longer supported'); -E('ERR_OUT_OF_RANGE', 'The "%s" argument is out of range'); -E('ERR_PARSE_HISTORY_DATA', 'Could not parse history data in %s'); -E('ERR_REQUIRE_ESM', 'Must use import to load ES Module: %s'); + 'bytes of the array passed in', + RangeError); +E('ERR_NAPI_INVALID_TYPEDARRAY_ALIGNMENT', + 'start offset of %s should be a multiple of %s', RangeError); +E('ERR_NAPI_INVALID_TYPEDARRAY_LENGTH', + 'Invalid typed array length', RangeError); +E('ERR_NO_CRYPTO', + 'Node.js is not compiled with OpenSSL crypto support', Error); +E('ERR_NO_ICU', + '%s is not supported on Node.js compiled without ICU', TypeError); +E('ERR_NO_LONGER_SUPPORTED', '%s is no longer supported', Error); +E('ERR_OUT_OF_RANGE', 'The "%s" argument is out of range', RangeError); +E('ERR_REQUIRE_ESM', 'Must use import to load ES Module: %s', Error); E('ERR_SERVER_ALREADY_LISTEN', - 'Listen method has been called more than once without closing.'); -E('ERR_SOCKET_ALREADY_BOUND', 'Socket is already bound'); -E('ERR_SOCKET_BAD_BUFFER_SIZE', 'Buffer size must be a positive integer'); -E('ERR_SOCKET_BAD_PORT', 'Port should be > 0 and < 65536. Received %s.'); + 'Listen method has been called more than once without closing.', Error); +E('ERR_SOCKET_ALREADY_BOUND', 'Socket is already bound', Error); +E('ERR_SOCKET_BAD_BUFFER_SIZE', + 'Buffer size must be a positive integer', TypeError); +E('ERR_SOCKET_BAD_PORT', + 'Port should be > 0 and < 65536. Received %s.', RangeError); E('ERR_SOCKET_BAD_TYPE', - 'Bad socket type specified. Valid types are: udp4, udp6'); -E('ERR_SOCKET_BUFFER_SIZE', 'Could not get or set buffer size: %s'); -E('ERR_SOCKET_CANNOT_SEND', 'Unable to send data'); -E('ERR_SOCKET_CLOSED', 'Socket is closed'); -E('ERR_SOCKET_DGRAM_NOT_RUNNING', 'Not running'); -E('ERR_STDERR_CLOSE', 'process.stderr cannot be closed'); -E('ERR_STDOUT_CLOSE', 'process.stdout cannot be closed'); -E('ERR_STREAM_CANNOT_PIPE', 'Cannot pipe, not readable'); -E('ERR_STREAM_NULL_VALUES', 'May not write null values to stream'); -E('ERR_STREAM_PUSH_AFTER_EOF', 'stream.push() after EOF'); -E('ERR_STREAM_READ_NOT_IMPLEMENTED', '_read() is not implemented'); -E('ERR_STREAM_UNSHIFT_AFTER_END_EVENT', 'stream.unshift() after end event'); -E('ERR_STREAM_WRAP', 'Stream has StringDecoder set or is in objectMode'); -E('ERR_STREAM_WRITE_AFTER_END', 'write after end'); + 'Bad socket type specified. Valid types are: udp4, udp6', TypeError); +E('ERR_SOCKET_BUFFER_SIZE', 'Could not get or set buffer size: %s', Error); +E('ERR_SOCKET_CANNOT_SEND', 'Unable to send data', Error); +E('ERR_SOCKET_CLOSED', 'Socket is closed', Error); +E('ERR_SOCKET_DGRAM_NOT_RUNNING', 'Not running', Error); +E('ERR_STDERR_CLOSE', 'process.stderr cannot be closed', Error); +E('ERR_STDOUT_CLOSE', 'process.stdout cannot be closed', Error); +E('ERR_STREAM_CANNOT_PIPE', 'Cannot pipe, not readable', Error); +E('ERR_STREAM_NULL_VALUES', 'May not write null values to stream', TypeError); +E('ERR_STREAM_PUSH_AFTER_EOF', 'stream.push() after EOF', Error); +E('ERR_STREAM_READ_NOT_IMPLEMENTED', '_read() is not implemented', Error); +E('ERR_STREAM_UNSHIFT_AFTER_END_EVENT', + 'stream.unshift() after end event', Error); +E('ERR_STREAM_WRAP', 'Stream has StringDecoder set or is in objectMode', Error); +E('ERR_STREAM_WRITE_AFTER_END', 'write after end', Error); E('ERR_TLS_CERT_ALTNAME_INVALID', - 'Hostname/IP does not match certificate\'s altnames: %s'); -E('ERR_TLS_DH_PARAM_SIZE', 'DH parameter size %s is less than 2048'); -E('ERR_TLS_HANDSHAKE_TIMEOUT', 'TLS handshake timeout'); -E('ERR_TLS_RENEGOTIATION_FAILED', 'Failed to renegotiate'); + 'Hostname/IP does not match certificate\'s altnames: %s', Error); +E('ERR_TLS_DH_PARAM_SIZE', 'DH parameter size %s is less than 2048', Error); +E('ERR_TLS_HANDSHAKE_TIMEOUT', 'TLS handshake timeout', Error); E('ERR_TLS_REQUIRED_SERVER_NAME', - '"servername" is required parameter for Server.addContext'); -E('ERR_TLS_SESSION_ATTACK', 'TLS session renegotiation attack detected'); + '"servername" is required parameter for Server.addContext', Error); +E('ERR_TLS_SESSION_ATTACK', 'TLS session renegotiation attack detected', Error); E('ERR_TRANSFORM_ALREADY_TRANSFORMING', - 'Calling transform done when still transforming'); + 'Calling transform done when still transforming', Error); + +// This should probably be a `RangeError`. E('ERR_TRANSFORM_WITH_LENGTH_0', - 'Calling transform done when writableState.length != 0'); + 'Calling transform done when writableState.length != 0', Error); E('ERR_UNCAUGHT_EXCEPTION_CAPTURE_ALREADY_SET', '`process.setupUncaughtExceptionCapture()` was called while a capture ' + - 'callback was already active'); -E('ERR_UNESCAPED_CHARACTERS', '%s contains unescaped characters'); + 'callback was already active', + Error); +E('ERR_UNESCAPED_CHARACTERS', '%s contains unescaped characters', TypeError); E('ERR_UNHANDLED_ERROR', (err) => { const msg = 'Unhandled error.'; if (err === undefined) return msg; return `${msg} (${err})`; - }); -E('ERR_UNKNOWN_ENCODING', 'Unknown encoding: %s'); -E('ERR_UNKNOWN_FILE_EXTENSION', 'Unknown file extension: %s'); -E('ERR_UNKNOWN_MODULE_FORMAT', 'Unknown module format: %s'); -E('ERR_UNKNOWN_SIGNAL', 'Unknown signal: %s'); -E('ERR_UNKNOWN_STDIN_TYPE', 'Unknown stdin file type'); -E('ERR_UNKNOWN_STREAM_TYPE', 'Unknown stream file type'); -E('ERR_V8BREAKITERATOR', 'Full ICU data not installed. ' + - 'See https://github.com/nodejs/node/wiki/Intl'); + }, Error); +E('ERR_UNKNOWN_ENCODING', 'Unknown encoding: %s', TypeError); + +// This should probably be a `TypeError`. +E('ERR_UNKNOWN_FILE_EXTENSION', 'Unknown file extension: %s', Error); +E('ERR_UNKNOWN_MODULE_FORMAT', 'Unknown module format: %s', RangeError); +E('ERR_UNKNOWN_SIGNAL', 'Unknown signal: %s', TypeError); +E('ERR_UNKNOWN_STDIN_TYPE', 'Unknown stdin file type', Error); + +// This should probably be a `TypeError`. +E('ERR_UNKNOWN_STREAM_TYPE', 'Unknown stream file type', Error); +E('ERR_V8BREAKITERATOR', + 'Full ICU data not installed. See https://github.com/nodejs/node/wiki/Intl', + Error); + +// This should probably be a `TypeError`. E('ERR_VALID_PERFORMANCE_ENTRY_TYPE', - 'At least one valid performance entry type is required'); + 'At least one valid performance entry type is required', Error); E('ERR_VALUE_OUT_OF_RANGE', (start, end, value) => { return `The value of "${start}" must be ${end}. Received "${value}"`; -}); -E('ERR_VM_MODULE_ALREADY_LINKED', 'Module has already been linked'); +}, RangeError); +E('ERR_VM_MODULE_ALREADY_LINKED', 'Module has already been linked', Error); E('ERR_VM_MODULE_DIFFERENT_CONTEXT', - 'Linked modules must use the same context'); + 'Linked modules must use the same context', Error); E('ERR_VM_MODULE_LINKING_ERRORED', - 'Linking has already failed for the provided module'); + 'Linking has already failed for the provided module', Error); E('ERR_VM_MODULE_NOT_LINKED', - 'Module must be linked before it can be instantiated'); -E('ERR_VM_MODULE_NOT_MODULE', 'Provided module is not an instance of Module'); -E('ERR_VM_MODULE_STATUS', 'Module status %s'); -E('ERR_ZLIB_BINDING_CLOSED', 'zlib binding closed'); -E('ERR_ZLIB_INITIALIZATION_FAILED', 'Initialization failed'); + 'Module must be linked before it can be instantiated', Error); +E('ERR_VM_MODULE_NOT_MODULE', + 'Provided module is not an instance of Module', Error); +E('ERR_VM_MODULE_STATUS', 'Module status %s', Error); +E('ERR_ZLIB_BINDING_CLOSED', 'zlib binding closed', Error); +E('ERR_ZLIB_INITIALIZATION_FAILED', 'Initialization failed', Error); function invalidArgType(name, expected, actual) { internalAssert(name, 'name is required'); diff --git a/lib/internal/fs.js b/lib/internal/fs.js index 01c5ff4bfc2e4d..e58b3f5110a804 100644 --- a/lib/internal/fs.js +++ b/lib/internal/fs.js @@ -47,10 +47,14 @@ function stringToFlags(flags) { case 'a' : return O_APPEND | O_CREAT | O_WRONLY; case 'ax' : // Fall through. case 'xa' : return O_APPEND | O_CREAT | O_WRONLY | O_EXCL; + case 'as' : // Fall through. + case 'sa' : return O_APPEND | O_CREAT | O_WRONLY | O_SYNC; case 'a+' : return O_APPEND | O_CREAT | O_RDWR; case 'ax+': // Fall through. case 'xa+': return O_APPEND | O_CREAT | O_RDWR | O_EXCL; + case 'as+': // Fall through. + case 'sa+': return O_APPEND | O_CREAT | O_RDWR | O_SYNC; } throw new errors.TypeError('ERR_INVALID_OPT_VALUE', 'flags', flags); diff --git a/lib/internal/http2/core.js b/lib/internal/http2/core.js index 93b76588db03b2..86e33d9cda0da8 100644 --- a/lib/internal/http2/core.js +++ b/lib/internal/http2/core.js @@ -948,7 +948,7 @@ class Http2Session extends EventEmitter { if (typeof id !== 'number') throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'id', 'number'); if (id <= 0 || id > kMaxStreams) - throw new errors.RangeError('ERR_OUT_OF_RANGE'); + throw new errors.RangeError('ERR_OUT_OF_RANGE', 'id'); this[kHandle].setNextStreamID(id); } @@ -2041,19 +2041,12 @@ function afterOpen(session, options, headers, streamOptions, err, fd) { headers, streamOptions)); } -function streamOnError(err) { - // we swallow the error for parity with HTTP1 - // all the errors that ends here are not critical for the project -} - - class ServerHttp2Stream extends Http2Stream { constructor(session, handle, id, options, headers) { super(session, options); this[kInit](id, handle); this[kProtocol] = headers[HTTP2_HEADER_SCHEME]; this[kAuthority] = headers[HTTP2_HEADER_AUTHORITY]; - this.on('error', streamOnError); } // true if the remote peer accepts push streams diff --git a/lib/internal/loader/DefaultResolve.js b/lib/internal/loader/DefaultResolve.js index d815be87dd8954..bd99f31e54c599 100644 --- a/lib/internal/loader/DefaultResolve.js +++ b/lib/internal/loader/DefaultResolve.js @@ -40,7 +40,7 @@ function search(target, base) { } const extensionFormatMap = { - __proto__: null, + '__proto__': null, '.mjs': 'esm', '.json': 'json', '.node': 'addon', diff --git a/lib/internal/process.js b/lib/internal/process.js index 70186f0e66deaa..c94b0a9d5fc442 100644 --- a/lib/internal/process.js +++ b/lib/internal/process.js @@ -118,16 +118,9 @@ function setupMemoryUsage() { function setupConfig(_source) { // NativeModule._source // used for `process.config`, but not a real module - var config = _source.config; + const config = _source.config; delete _source.config; - // strip the gyp comment line at the beginning - config = config.split('\n') - .slice(1) - .join('\n') - .replace(/"/g, '\\"') - .replace(/'/g, '"'); - process.config = JSON.parse(config, function(key, value) { if (value === 'true') return true; if (value === 'false') return false; diff --git a/lib/internal/streams/duplex_base.js b/lib/internal/streams/duplex_base.js new file mode 100644 index 00000000000000..df3c5c37a80ea7 --- /dev/null +++ b/lib/internal/streams/duplex_base.js @@ -0,0 +1,30 @@ +'use strict'; + +const util = require('util'); +const Readable = require('_stream_readable'); +const Writable = require('_stream_writable'); + +function DuplexBase(options) { + Readable.call(this, options); + Writable.call(this, options); + + if (options && options.readable === false) + this.readable = false; + + if (options && options.writable === false) + this.writable = false; +} + +util.inherits(DuplexBase, Readable); + +{ + // Avoid scope creep, the keys array can then be collected. + const keys = Object.keys(Writable.prototype); + for (var v = 0; v < keys.length; v++) { + const method = keys[v]; + if (!DuplexBase.prototype[method]) + DuplexBase.prototype[method] = Writable.prototype[method]; + } +} + +module.exports = DuplexBase; diff --git a/lib/internal/v8_prof_processor.js b/lib/internal/v8_prof_processor.js index 7592253060294c..4799a88f69ca54 100644 --- a/lib/internal/v8_prof_processor.js +++ b/lib/internal/v8_prof_processor.js @@ -21,11 +21,6 @@ scriptFiles.forEach(function(s) { script += process.binding('natives')[s] + '\n'; }); -// eslint-disable-next-line no-unused-vars -function printErr(err) { - console.error(err); -} - const tickArguments = []; if (process.platform === 'darwin') { tickArguments.push('--mac'); @@ -36,6 +31,7 @@ tickArguments.push.apply(tickArguments, process.argv.slice(1)); script = `(function(module, require) { arguments = ${JSON.stringify(tickArguments)}; function write (s) { process.stdout.write(s) } + function printErr(err) { console.error(err); } ${script} })`; vm.runInThisContext(script)(module, require); diff --git a/lib/net.js b/lib/net.js index 90e0db558e3a9b..17a128a4f0c8db 100644 --- a/lib/net.js +++ b/lib/net.js @@ -50,6 +50,7 @@ const { async_id_symbol } = process.binding('async_wrap'); const { newUid, defaultTriggerAsyncIdScope } = require('internal/async_hooks'); const { nextTick } = require('internal/process/next_tick'); const errors = require('internal/errors'); +const DuplexBase = require('internal/streams/duplex_base'); const dns = require('dns'); const kLastWriteQueueSize = Symbol('lastWriteQueueSize'); @@ -211,7 +212,11 @@ function Socket(options) { else if (options === undefined) options = {}; - stream.Duplex.call(this, options); + // `DuplexBase` is just a slimmed down constructor for `Duplex` which allow + // us to not inherit the "no-half-open enforcer" as there is already one in + // place. Instances of `Socket` are still instances of `Duplex`, that is, + // `socket instanceof Duplex === true`. + DuplexBase.call(this, options); if (options.handle) { this._handle = options.handle; // private @@ -236,8 +241,6 @@ function Socket(options) { this._writev = null; this._write = makeSyncWrite(fd); } - this.readable = options.readable !== false; - this.writable = options.writable !== false; } else { // these will be set once there is a connection this.readable = this.writable = false; @@ -256,7 +259,7 @@ function Socket(options) { this._writableState.decodeStrings = false; // default to *not* allowing half open sockets - this.allowHalfOpen = options && options.allowHalfOpen || false; + this.allowHalfOpen = options.allowHalfOpen || false; // if we have a handle, then start the flow of data into the // buffer. if not, then this will happen when we connect diff --git a/lib/path.js b/lib/path.js index 098416adfe1a3a..3530388e945d0a 100644 --- a/lib/path.js +++ b/lib/path.js @@ -50,7 +50,7 @@ function isWindowsDeviceRoot(code) { } // Resolves . and .. elements in a path with directory names -function normalizeStringWin32(path, allowAboveRoot) { +function normalizeString(path, allowAboveRoot, separator) { var res = ''; var lastSegmentLength = 0; var lastSlash = -1; @@ -72,14 +72,14 @@ function normalizeStringWin32(path, allowAboveRoot) { res.charCodeAt(res.length - 1) !== CHAR_DOT || res.charCodeAt(res.length - 2) !== CHAR_DOT) { if (res.length > 2) { - const lastSlashIndex = res.lastIndexOf('\\'); + const lastSlashIndex = res.lastIndexOf(separator); if (lastSlashIndex !== res.length - 1) { if (lastSlashIndex === -1) { res = ''; lastSegmentLength = 0; } else { res = res.slice(0, lastSlashIndex); - lastSegmentLength = res.length - 1 - res.lastIndexOf('\\'); + lastSegmentLength = res.length - 1 - res.lastIndexOf(separator); } lastSlash = i; dots = 0; @@ -95,82 +95,14 @@ function normalizeStringWin32(path, allowAboveRoot) { } if (allowAboveRoot) { if (res.length > 0) - res += '\\..'; + res += `${separator}..`; else res = '..'; lastSegmentLength = 2; } } else { if (res.length > 0) - res += '\\' + path.slice(lastSlash + 1, i); - else - res = path.slice(lastSlash + 1, i); - lastSegmentLength = i - lastSlash - 1; - } - lastSlash = i; - dots = 0; - } else if (code === CHAR_DOT && dots !== -1) { - ++dots; - } else { - dots = -1; - } - } - return res; -} - -// Resolves . and .. elements in a path with directory names -function normalizeStringPosix(path, allowAboveRoot) { - var res = ''; - var lastSegmentLength = 0; - var lastSlash = -1; - var dots = 0; - var code; - for (var i = 0; i <= path.length; ++i) { - if (i < path.length) - code = path.charCodeAt(i); - else if (code === CHAR_FORWARD_SLASH) - break; - else - code = CHAR_FORWARD_SLASH; - if (code === CHAR_FORWARD_SLASH) { - if (lastSlash === i - 1 || dots === 1) { - // NOOP - } else if (lastSlash !== i - 1 && dots === 2) { - if (res.length < 2 || lastSegmentLength !== 2 || - res.charCodeAt(res.length - 1) !== CHAR_DOT || - res.charCodeAt(res.length - 2) !== CHAR_DOT) { - if (res.length > 2) { - const lastSlashIndex = res.lastIndexOf('/'); - if (lastSlashIndex !== res.length - 1) { - if (lastSlashIndex === -1) { - res = ''; - lastSegmentLength = 0; - } else { - res = res.slice(0, lastSlashIndex); - lastSegmentLength = res.length - 1 - res.lastIndexOf('/'); - } - lastSlash = i; - dots = 0; - continue; - } - } else if (res.length === 2 || res.length === 1) { - res = ''; - lastSegmentLength = 0; - lastSlash = i; - dots = 0; - continue; - } - } - if (allowAboveRoot) { - if (res.length > 0) - res += '/..'; - else - res = '..'; - lastSegmentLength = 2; - } - } else { - if (res.length > 0) - res += '/' + path.slice(lastSlash + 1, i); + res += separator + path.slice(lastSlash + 1, i); else res = path.slice(lastSlash + 1, i); lastSegmentLength = i - lastSlash - 1; @@ -340,7 +272,7 @@ const win32 = { // fails) // Normalize the tail path - resolvedTail = normalizeStringWin32(resolvedTail, !resolvedAbsolute); + resolvedTail = normalizeString(resolvedTail, !resolvedAbsolute, '\\'); return (resolvedDevice + (resolvedAbsolute ? '\\' : '') + resolvedTail) || '.'; @@ -432,7 +364,7 @@ const win32 = { var tail; if (rootEnd < len) - tail = normalizeStringWin32(path.slice(rootEnd), !isAbsolute); + tail = normalizeString(path.slice(rootEnd), !isAbsolute, '\\'); else tail = ''; if (tail.length === 0 && !isAbsolute) @@ -1164,7 +1096,7 @@ const posix = { // handle relative paths to be safe (might happen when process.cwd() fails) // Normalize the path - resolvedPath = normalizeStringPosix(resolvedPath, !resolvedAbsolute); + resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute, '/'); if (resolvedAbsolute) { if (resolvedPath.length > 0) @@ -1190,7 +1122,7 @@ const posix = { path.charCodeAt(path.length - 1) === CHAR_FORWARD_SLASH; // Normalize the path - path = normalizeStringPosix(path, !isAbsolute); + path = normalizeString(path, !isAbsolute, '/'); if (path.length === 0 && !isAbsolute) path = '.'; diff --git a/lib/repl.js b/lib/repl.js index 2078c5dcedaf20..5779e849f06017 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -79,7 +79,7 @@ const kBufferedCommandSymbol = Symbol('bufferedCommand'); const kContextId = Symbol('contextId'); try { - // hack for require.resolve("./relative") to work properly. + // Hack for require.resolve("./relative") to work properly. module.filename = path.resolve('repl'); } catch (e) { // path.resolve('repl') fails when the current working directory has been @@ -89,7 +89,7 @@ try { module.filename = path.resolve(dirname, 'repl'); } -// hack for repl require to work properly with node_modules folders +// Hack for repl require to work properly with node_modules folders module.paths = Module._nodeModulePaths(module.filename); // If obj.hasOwnProperty has been overridden, then calling @@ -99,14 +99,12 @@ function hasOwnProperty(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } - // Can overridden with custom print functions, such as `probe` or `eyes.js`. // This is the default "writer" value if none is passed in the REPL options. exports.writer = util.inspect; exports._builtinLibs = internalModule.builtinLibs; - function REPLServer(prompt, stream, eval_, @@ -149,7 +147,6 @@ function REPLServer(prompt, var self = this; self._domain = dom || domain.create(); - self.useGlobal = !!useGlobal; self.ignoreUndefined = !!ignoreUndefined; self.replMode = replMode || exports.REPL_MODE_SLOPPY; @@ -162,7 +159,7 @@ function REPLServer(prompt, // Context id for use with the inspector protocol. self[kContextId] = undefined; - // just for backwards compat, see github.com/joyent/node/pull/7127 + // Just for backwards compat, see github.com/joyent/node/pull/7127 self.rli = this; const savedRegExMatches = ['', '', '', '', '', '', '', '', '', '']; @@ -187,8 +184,7 @@ function REPLServer(prompt, wrappedCmd = true; } - // first, create the Script object to check the syntax - + // First, create the Script object to check the syntax if (code === '\n') return cb(null); @@ -207,13 +203,13 @@ function REPLServer(prompt, } catch (e) { debug('parse error %j', code, e); if (wrappedCmd) { + // Unwrap and try again wrappedCmd = false; - // unwrap and try again code = input; wrappedErr = e; continue; } - // preserve original error for wrapped command + // Preserve original error for wrapped command const error = wrappedErr || e; if (isRecoverableError(error, code)) err = new Recoverable(error); @@ -321,18 +317,13 @@ function REPLServer(prompt, if (!input && !output) { // legacy API, passing a 'stream'/'socket' option if (!stream) { - // use stdin and stdout as the default streams if none were given + // Use stdin and stdout as the default streams if none were given stream = process; } - if (stream.stdin && stream.stdout) { - // We're given custom object with 2 streams, or the `process` object - input = stream.stdin; - output = stream.stdout; - } else { - // We're given a duplex readable/writable Stream, like a `net.Socket` - input = stream; - output = stream; - } + // We're given a duplex readable/writable Stream, like a `net.Socket` + // or a custom object with 2 streams, or the `process` object + input = stream.stdin || stream; + output = stream.stdout || stream; } self.inputStream = input; @@ -371,7 +362,7 @@ function REPLServer(prompt, this.commands = Object.create(null); defineDefaultCommands(this); - // figure out which "writer" function to use + // Figure out which "writer" function to use self.writer = options.writer || exports.writer; if (options.useColors === undefined) { @@ -387,14 +378,14 @@ function REPLServer(prompt, } function filterInternalStackFrames(error, structuredStack) { - // search from the bottom of the call stack to + // Search from the bottom of the call stack to // find the first frame with a null function name if (typeof structuredStack !== 'object') return structuredStack; const idx = structuredStack.reverse().findIndex( (frame) => frame.getFunctionName() === null); - // if found, get rid of it and everything below it + // If found, get rid of it and everything below it structuredStack = structuredStack.splice(idx + 1); return structuredStack; } @@ -571,7 +562,7 @@ function REPLServer(prompt, return; } - // editor mode + // Editor mode if (key.ctrl && !key.shift) { switch (key.name) { case 'd': // End editor mode @@ -591,7 +582,7 @@ function REPLServer(prompt, case 'down': // Override next history item break; case 'tab': - // prevent double tab behavior + // Prevent double tab behavior self._previousKey = null; ttyWrite(d, key); break; @@ -667,7 +658,7 @@ REPLServer.prototype.createContext = function() { Object.defineProperty(context, 'console', { configurable: true, enumerable: true, - get: () => _console + value: _console }); var names = Object.getOwnPropertyNames(global); @@ -861,10 +852,8 @@ function complete(line, callback) { } var completions; - - // list of completion lists, one for each inheritance "level" + // List of completion lists, one for each inheritance "level" var completionGroups = []; - var completeOn, i, group, c; // REPL commands (e.g. ".break"). @@ -1041,19 +1030,16 @@ function complete(line, callback) { break; } } - } catch (e) { - //console.log("completion error walking prototype chain:" + e); - } + } catch (e) {} } if (memberGroups.length) { for (i = 0; i < memberGroups.length; i++) { - completionGroups.push(memberGroups[i].map(function(member) { - return expr + '.' + member; - })); + completionGroups.push( + memberGroups[i].map((member) => `${expr}.${member}`)); } if (filter) { - filter = expr + '.' + filter; + filter = `${expr}.${filter}`; } } @@ -1074,9 +1060,8 @@ function complete(line, callback) { if (completionGroups.length && filter) { var newCompletionGroups = []; for (i = 0; i < completionGroups.length; i++) { - group = completionGroups[i].filter(function(elem) { - return elem.indexOf(filter) === 0; - }); + group = completionGroups[i] + .filter((elem) => elem.indexOf(filter) === 0); if (group.length) { newCompletionGroups.push(group); } @@ -1085,7 +1070,7 @@ function complete(line, callback) { } if (completionGroups.length) { - var uniq = {}; // unique completions across all groups + var uniq = {}; // Unique completions across all groups completions = []; // Completion group 0 is the "closest" // (least far up the inheritance chain) @@ -1100,7 +1085,7 @@ function complete(line, callback) { uniq[c] = true; } } - completions.push(''); // separator btwn groups + completions.push(''); // Separator btwn groups } while (completions.length && completions[completions.length - 1] === '') { completions.pop(); @@ -1167,7 +1152,7 @@ function _memory(cmd) { self.lines = self.lines || []; self.lines.level = self.lines.level || []; - // save the line so I can do magic later + // Save the line so I can do magic later if (cmd) { // TODO should I tab the level? const len = self.lines.level.length ? self.lines.level.length - 1 : 0; @@ -1181,7 +1166,7 @@ function _memory(cmd) { // Because I can not tell the difference between a } that // closes an object literal and a } that closes a function if (cmd) { - // going down is { and ( e.g. function() { + // Going down is { and ( e.g. function() { // going up is } and ) var dw = cmd.match(/{|\(/g); var up = cmd.match(/}|\)/g); @@ -1192,8 +1177,8 @@ function _memory(cmd) { if (depth) { (function workIt() { if (depth > 0) { - // going... down. - // push the line#, depth count, and if the line is a function. + // Going... down. + // Push the line#, depth count, and if the line is a function. // Since JS only has functional scope I only need to remove // "function() {" lines, clearly this will not work for // "function() @@ -1205,16 +1190,16 @@ function _memory(cmd) { isFunction: /\bfunction\b/.test(cmd) }); } else if (depth < 0) { - // going... up. + // Going... up. var curr = self.lines.level.pop(); if (curr) { var tmp = curr.depth + depth; if (tmp < 0) { - //more to go, recurse + // More to go, recurse depth += curr.depth; workIt(); } else if (tmp > 0) { - //remove and push back + // Remove and push back curr.depth += depth; self.lines.level.push(curr); } @@ -1375,14 +1360,15 @@ function isRecoverableError(e, code) { if (e && e.name === 'SyntaxError') { var message = e.message; if (message === 'Unterminated template literal' || - message === 'Missing } in template expression') { + message === 'Unexpected end of input') { return true; } - if (message.startsWith('Unexpected end of input') || - message.startsWith('missing ) after argument list') || - message.startsWith('Unexpected token')) - return true; + if (message === 'missing ) after argument list') { + const frames = e.stack.split(/\r?\n/); + const pos = frames.findIndex((f) => f.match(/^\s*\^+$/)); + return pos > 0 && frames[pos - 1].length === frames[pos].length; + } if (message === 'Invalid or unexpected token') return isCodeRecoverable(code); @@ -1405,55 +1391,33 @@ function isCodeRecoverable(code) { if (previous === '\\' && (stringLiteral || isRegExpLiteral)) { current = null; - continue; - } - - if (stringLiteral) { + } else if (stringLiteral) { if (stringLiteral === current) { stringLiteral = null; } - continue; - } else { - if (isRegExpLiteral && current === '/') { - isRegExpLiteral = false; - continue; - } - - if (isBlockComment && previous === '*' && current === '/') { - isBlockComment = false; - continue; - } - - if (isSingleComment && current === '\n') { - isSingleComment = false; - continue; - } - - if (isBlockComment || isRegExpLiteral || isSingleComment) continue; - + } else if (isRegExpLiteral && current === '/') { + isRegExpLiteral = false; + } else if (isBlockComment && previous === '*' && current === '/') { + isBlockComment = false; + } else if (isSingleComment && current === '\n') { + isSingleComment = false; + } else if (!isBlockComment && !isRegExpLiteral && !isSingleComment) { if (current === '/' && previous === '/') { isSingleComment = true; - continue; - } - - if (previous === '/') { + } else if (previous === '/') { if (current === '*') { isBlockComment = true; - } else if ( // Distinguish between a division operator and the start of a regex // by examining the non-whitespace character that precedes the / - [null, '(', '[', '{', '}', ';'].includes(prevTokenChar) - ) { + } else if ([null, '(', '[', '{', '}', ';'].includes(prevTokenChar)) { isRegExpLiteral = true; } - continue; + } else { + if (current.trim()) prevTokenChar = current; + if (current === '\'' || current === '"') { + stringLiteral = current; + } } - - if (current.trim()) prevTokenChar = current; - } - - if (current === '\'' || current === '"') { - stringLiteral = current; } } diff --git a/lib/timers.js b/lib/timers.js index 46cd770fc643bd..c82d6cfdbb11e9 100644 --- a/lib/timers.js +++ b/lib/timers.js @@ -314,24 +314,24 @@ function tryOnTimeout(timer, list) { } } - if (!threw) return; - - // Postpone all later list events to next tick. We need to do this - // so that the events are called in the order they were created. - const lists = list._unrefed === true ? unrefedLists : refedLists; - for (var key in lists) { - if (key > list.msecs) { - lists[key].nextTick = true; + if (threw) { + // Postpone all later list events to next tick. We need to do this + // so that the events are called in the order they were created. + const lists = list._unrefed === true ? unrefedLists : refedLists; + for (var key in lists) { + if (key > list.msecs) { + lists[key].nextTick = true; + } } + // We need to continue processing after domain error handling + // is complete, but not by using whatever domain was left over + // when the timeout threw its exception. + const domain = process.domain; + process.domain = null; + // If we threw, we need to process the rest of the list in nextTick. + process.nextTick(listOnTimeoutNT, list); + process.domain = domain; } - // We need to continue processing after domain error handling - // is complete, but not by using whatever domain was left over - // when the timeout threw its exception. - const domain = process.domain; - process.domain = null; - // If we threw, we need to process the rest of the list in nextTick. - process.nextTick(listOnTimeoutNT, list); - process.domain = domain; } } diff --git a/lib/tty.js b/lib/tty.js index 29440d6d96e3d5..12d0836cde5db5 100644 --- a/lib/tty.js +++ b/lib/tty.js @@ -26,12 +26,19 @@ const net = require('net'); const { TTY, isTTY } = process.binding('tty_wrap'); const errors = require('internal/errors'); const readline = require('readline'); +const { release } = require('os'); + +const OSRelease = release().split('.'); + +const COLORS_2 = 1; +const COLORS_16 = 4; +const COLORS_256 = 8; +const COLORS_16m = 24; function isatty(fd) { return Number.isInteger(fd) && fd >= 0 && isTTY(fd); } - function ReadStream(fd, options) { if (!(this instanceof ReadStream)) return new ReadStream(fd, options); @@ -58,7 +65,6 @@ ReadStream.prototype.setRawMode = function(flag) { this.isRaw = flag; }; - function WriteStream(fd) { if (!(this instanceof WriteStream)) return new WriteStream(fd); @@ -78,8 +84,8 @@ function WriteStream(fd) { // Ref: https://github.com/nodejs/node/pull/1771#issuecomment-119351671 this._handle.setBlocking(true); - var winSize = new Array(2); - var err = this._handle.getWindowSize(winSize); + const winSize = new Array(2); + const err = this._handle.getWindowSize(winSize); if (!err) { this.columns = winSize[0]; this.rows = winSize[1]; @@ -87,21 +93,83 @@ function WriteStream(fd) { } inherits(WriteStream, net.Socket); - WriteStream.prototype.isTTY = true; +WriteStream.prototype.getColorDepth = function(env = process.env) { + if (env.NODE_DISABLE_COLORS || env.TERM === 'dumb' && !env.COLORTERM) { + return COLORS_2; + } + + if (process.platform === 'win32') { + // Windows 10 build 10586 is the first Windows release that supports 256 + // colors. Windows 10 build 14931 is the first release that supports + // 16m/TrueColor. + if (+OSRelease[0] >= 10) { + const build = +OSRelease[2]; + if (build >= 14931) + return COLORS_16m; + if (build >= 10586) + return COLORS_256; + } + + return COLORS_16; + } + + if (env.TMUX) { + return COLORS_256; + } + + if (env.CI) { + if ('TRAVIS' in env || 'CIRCLECI' in env || 'APPVEYOR' in env || + 'GITLAB_CI' in env || env.CI_NAME === 'codeship') { + return COLORS_256; + } + return COLORS_2; + } + + if ('TEAMCITY_VERSION' in env) { + return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? + COLORS_16 : COLORS_2; + } + + switch (env.TERM_PROGRAM) { + case 'iTerm.app': + if (!env.TERM_PROGRAM_VERSION || + /^[0-2]\./.test(env.TERM_PROGRAM_VERSION)) { + return COLORS_256; + } + return COLORS_16m; + case 'HyperTerm': + case 'Hyper': + case 'MacTerm': + return COLORS_16m; + case 'Apple_Terminal': + return COLORS_256; + } + + if (env.TERM) { + if (/^xterm-256/.test(env.TERM)) + return COLORS_256; + if (/^screen|^xterm|^vt100|color|ansi|cygwin|linux/i.test(env.TERM)) + return COLORS_16; + } + + if (env.COLORTERM) + return COLORS_16; + + return COLORS_2; +}; WriteStream.prototype._refreshSize = function() { - var oldCols = this.columns; - var oldRows = this.rows; - var winSize = new Array(2); - var err = this._handle.getWindowSize(winSize); + const oldCols = this.columns; + const oldRows = this.rows; + const winSize = new Array(2); + const err = this._handle.getWindowSize(winSize); if (err) { this.emit('error', errors.errnoException(err, 'getWindowSize')); return; } - var newCols = winSize[0]; - var newRows = winSize[1]; + const [newCols, newRows] = winSize; if (oldCols !== newCols || oldRows !== newRows) { this.columns = newCols; this.rows = newRows; @@ -109,8 +177,7 @@ WriteStream.prototype._refreshSize = function() { } }; - -// backwards-compat +// Backwards-compat WriteStream.prototype.cursorTo = function(x, y) { readline.cursorTo(this, x, y); }; @@ -127,5 +194,4 @@ WriteStream.prototype.getWindowSize = function() { return [this.columns, this.rows]; }; - module.exports = { isatty, ReadStream, WriteStream }; diff --git a/lib/url.js b/lib/url.js index ab4b2b4647edd2..df9d917a479aba 100644 --- a/lib/url.js +++ b/lib/url.js @@ -92,6 +92,43 @@ const slashedProtocol = { 'file:': true }; const querystring = require('querystring'); +const { + CHAR_SPACE, + CHAR_TAB, + CHAR_CARRIAGE_RETURN, + CHAR_LINE_FEED, + CHAR_FORM_FEED, + CHAR_NO_BREAK_SPACE, + CHAR_ZERO_WIDTH_NOBREAK_SPACE, + CHAR_HASH, + CHAR_FORWARD_SLASH, + CHAR_LEFT_SQUARE_BRACKET, + CHAR_RIGHT_SQUARE_BRACKET, + CHAR_LEFT_ANGLE_BRACKET, + CHAR_RIGHT_ANGLE_BRACKET, + CHAR_LEFT_CURLY_BRACKET, + CHAR_RIGHT_CURLY_BRACKET, + CHAR_QUESTION_MARK, + CHAR_LOWERCASE_A, + CHAR_LOWERCASE_Z, + CHAR_UPPERCASE_A, + CHAR_UPPERCASE_Z, + CHAR_DOT, + CHAR_0, + CHAR_9, + CHAR_HYPHEN_MINUS, + CHAR_PLUS, + CHAR_UNDERSCORE, + CHAR_DOUBLE_QUOTE, + CHAR_SINGLE_QUOTE, + CHAR_PERCENT, + CHAR_SEMICOLON, + CHAR_BACKWARD_SLASH, + CHAR_CIRCUMFLEX_ACCENT, + CHAR_GRAVE_ACCENT, + CHAR_VERTICAL_LINE, + CHAR_AT, +} = require('internal/constants'); function urlParse(url, parseQueryString, slashesDenoteHost) { if (url instanceof Url) return url; @@ -119,13 +156,13 @@ Url.prototype.parse = function parse(url, parseQueryString, slashesDenoteHost) { const code = url.charCodeAt(i); // Find first and last non-whitespace characters for trimming - const isWs = code === 32/* */ || - code === 9/*\t*/ || - code === 13/*\r*/ || - code === 10/*\n*/ || - code === 12/*\f*/ || - code === 160/*\u00A0*/ || - code === 65279/*\uFEFF*/; + const isWs = code === CHAR_SPACE || + code === CHAR_TAB || + code === CHAR_CARRIAGE_RETURN || + code === CHAR_LINE_FEED || + code === CHAR_FORM_FEED || + code === CHAR_NO_BREAK_SPACE || + code === CHAR_ZERO_WIDTH_NOBREAK_SPACE; if (start === -1) { if (isWs) continue; @@ -143,20 +180,20 @@ Url.prototype.parse = function parse(url, parseQueryString, slashesDenoteHost) { // Only convert backslashes while we haven't seen a split character if (!split) { switch (code) { - case 35: // '#' + case CHAR_HASH: hasHash = true; // Fall through - case 63: // '?' + case CHAR_QUESTION_MARK: split = true; break; - case 92: // '\\' + case CHAR_BACKWARD_SLASH: if (i - lastPos > 0) rest += url.slice(lastPos, i); rest += '/'; lastPos = i + 1; break; } - } else if (!hasHash && code === 35/*#*/) { + } else if (!hasHash && code === CHAR_HASH) { hasHash = true; } } @@ -218,8 +255,8 @@ Url.prototype.parse = function parse(url, parseQueryString, slashesDenoteHost) { // resolution will treat //foo/bar as host=foo,path=bar because that's // how the browser resolves relative URLs. if (slashesDenoteHost || proto || hostPattern.test(rest)) { - var slashes = rest.charCodeAt(0) === 47/*/*/ && - rest.charCodeAt(1) === 47/*/*/; + var slashes = rest.charCodeAt(0) === CHAR_FORWARD_SLASH && + rest.charCodeAt(1) === CHAR_FORWARD_SLASH; if (slashes && !(proto && hostlessProtocol[proto])) { rest = rest.slice(2); this.slashes = true; @@ -249,35 +286,35 @@ Url.prototype.parse = function parse(url, parseQueryString, slashesDenoteHost) { var nonHost = -1; for (i = 0; i < rest.length; ++i) { switch (rest.charCodeAt(i)) { - case 9: // '\t' - case 10: // '\n' - case 13: // '\r' - case 32: // ' ' - case 34: // '"' - case 37: // '%' - case 39: // '\'' - case 59: // ';' - case 60: // '<' - case 62: // '>' - case 92: // '\\' - case 94: // '^' - case 96: // '`' - case 123: // '{' - case 124: // '|' - case 125: // '}' + case CHAR_TAB: + case CHAR_LINE_FEED: + case CHAR_CARRIAGE_RETURN: + case CHAR_SPACE: + case CHAR_DOUBLE_QUOTE: + case CHAR_PERCENT: + case CHAR_SINGLE_QUOTE: + case CHAR_SEMICOLON: + case CHAR_LEFT_ANGLE_BRACKET: + case CHAR_RIGHT_ANGLE_BRACKET: + case CHAR_BACKWARD_SLASH: + case CHAR_CIRCUMFLEX_ACCENT: + case CHAR_GRAVE_ACCENT: + case CHAR_LEFT_CURLY_BRACKET: + case CHAR_VERTICAL_LINE: + case CHAR_RIGHT_CURLY_BRACKET: // Characters that are never ever allowed in a hostname from RFC 2396 if (nonHost === -1) nonHost = i; break; - case 35: // '#' - case 47: // '/' - case 63: // '?' + case CHAR_HASH: + case CHAR_FORWARD_SLASH: + case CHAR_QUESTION_MARK: // Find the first instance of any host-ending characters if (nonHost === -1) nonHost = i; hostEnd = i; break; - case 64: // '@' + case CHAR_AT: // At this point, either we have an explicit point where the // auth portion cannot go past, or the last @ char is the decider. atSign = i; @@ -312,8 +349,8 @@ Url.prototype.parse = function parse(url, parseQueryString, slashesDenoteHost) { // if hostname begins with [ and ends with ] // assume that it's an IPv6 address. - var ipv6Hostname = hostname.charCodeAt(0) === 91/*[*/ && - hostname.charCodeAt(hostname.length - 1) === 93/*]*/; + var ipv6Hostname = hostname.charCodeAt(0) === CHAR_LEFT_SQUARE_BRACKET && + hostname.charCodeAt(hostname.length - 1) === CHAR_RIGHT_SQUARE_BRACKET; // validate a little. if (!ipv6Hostname) { @@ -367,11 +404,11 @@ Url.prototype.parse = function parse(url, parseQueryString, slashesDenoteHost) { var hashIdx = -1; for (i = 0; i < rest.length; ++i) { const code = rest.charCodeAt(i); - if (code === 35/*#*/) { + if (code === CHAR_HASH) { this.hash = rest.slice(i); hashIdx = i; break; - } else if (code === 63/*?*/ && questionIdx === -1) { + } else if (code === CHAR_QUESTION_MARK && questionIdx === -1) { questionIdx = i; } } @@ -422,13 +459,13 @@ Url.prototype.parse = function parse(url, parseQueryString, slashesDenoteHost) { function validateHostname(self, rest, hostname) { for (var i = 0; i < hostname.length; ++i) { const code = hostname.charCodeAt(i); - const isValid = (code >= 97/*a*/ && code <= 122/*z*/) || - code === 46/*.*/ || - (code >= 65/*A*/ && code <= 90/*Z*/) || - (code >= 48/*0*/ && code <= 57/*9*/) || - code === 45/*-*/ || - code === 43/*+*/ || - code === 95/*_*/ || + const isValid = (code >= CHAR_LOWERCASE_A && code <= CHAR_LOWERCASE_Z) || + code === CHAR_DOT || + (code >= CHAR_UPPERCASE_A && code <= CHAR_UPPERCASE_Z) || + (code >= CHAR_0 && code <= CHAR_9) || + code === CHAR_HYPHEN_MINUS || + code === CHAR_PLUS || + code === CHAR_UNDERSCORE || code > 127; // Invalid host character @@ -542,13 +579,13 @@ Url.prototype.format = function format() { var lastPos = 0; for (var i = 0; i < pathname.length; ++i) { switch (pathname.charCodeAt(i)) { - case 35: // '#' + case CHAR_HASH: if (i - lastPos > 0) newPathname += pathname.slice(lastPos, i); newPathname += '%23'; lastPos = i + 1; break; - case 63: // '?' + case CHAR_QUESTION_MARK: if (i - lastPos > 0) newPathname += pathname.slice(lastPos, i); newPathname += '%3F'; @@ -567,7 +604,7 @@ Url.prototype.format = function format() { // unless they had them to begin with. if (this.slashes || slashedProtocol[protocol]) { if (this.slashes || host) { - if (pathname && pathname.charCodeAt(0) !== 47/*/*/) + if (pathname && pathname.charCodeAt(0) !== CHAR_FORWARD_SLASH) pathname = '/' + pathname; host = '//' + host; } else if (protocol.length >= 4 && @@ -581,8 +618,10 @@ Url.prototype.format = function format() { search = search.replace(/#/g, '%23'); - if (hash && hash.charCodeAt(0) !== 35/*#*/) hash = '#' + hash; - if (search && search.charCodeAt(0) !== 63/*?*/) search = '?' + search; + if (hash && hash.charCodeAt(0) !== CHAR_HASH) + hash = '#' + hash; + if (search && search.charCodeAt(0) !== CHAR_QUESTION_MARK) + search = '?' + search; return protocol + host + pathname + search + hash; }; diff --git a/lib/util.js b/lib/util.js index cd6321cfe5270e..70fd1a05564389 100644 --- a/lib/util.js +++ b/lib/util.js @@ -68,7 +68,8 @@ const inspectDefaultOptions = Object.seal({ customInspect: true, showProxy: false, maxArrayLength: 100, - breakLength: 60 + breakLength: 60, + compact: true }); const propertyIsEnumerable = Object.prototype.propertyIsEnumerable; @@ -86,6 +87,10 @@ const strEscapeSequencesReplacer = /[\x00-\x1f\x27\x5c]/g; const keyStrRegExp = /^[a-zA-Z_][a-zA-Z_0-9]*$/; const numberRegExp = /^(0|[1-9][0-9]*)$/; +const readableRegExps = {}; + +const MIN_LINE_LENGTH = 16; + // Escaped special characters. Use empty strings to fill up unused entries. const meta = [ '\\u0000', '\\u0001', '\\u0002', '\\u0003', '\\u0004', @@ -257,14 +262,14 @@ function debuglog(set) { } /** - * Echos the value of a value. Tries to print the value out + * Echos the value of any input. Tries to print the value out * in the best way possible given the different types. * - * @param {Object} obj The object to print out. + * @param {any} value The value to print out. * @param {Object} opts Optional options object that alters the output. */ -/* Legacy: obj, showHidden, depth, colors*/ -function inspect(obj, opts) { +/* Legacy: value, showHidden, depth, colors*/ +function inspect(value, opts) { // Default options const ctx = { seen: [], @@ -276,7 +281,8 @@ function inspect(obj, opts) { showProxy: inspectDefaultOptions.showProxy, maxArrayLength: inspectDefaultOptions.maxArrayLength, breakLength: inspectDefaultOptions.breakLength, - indentationLvl: 0 + indentationLvl: 0, + compact: inspectDefaultOptions.compact }; // Legacy... if (arguments.length > 2) { @@ -298,7 +304,7 @@ function inspect(obj, opts) { } if (ctx.colors) ctx.stylize = stylizeWithColor; if (ctx.maxArrayLength === null) ctx.maxArrayLength = Infinity; - return formatValue(ctx, obj, ctx.depth); + return formatValue(ctx, value, ctx.depth); } inspect.custom = customInspectSymbol; @@ -374,7 +380,7 @@ function ensureDebugIsInitialized() { function formatValue(ctx, value, recurseTimes, ln) { // Primitive types cannot have properties if (typeof value !== 'object' && typeof value !== 'function') { - return formatPrimitive(ctx.stylize, value); + return formatPrimitive(ctx.stylize, value, ctx); } if (value === null) { return ctx.stylize('null', 'null'); @@ -481,10 +487,10 @@ function formatValue(ctx, value, recurseTimes, ln) { } catch (e) { /* ignore */ } if (typeof raw === 'string') { - const formatted = formatPrimitive(stylizeNoColor, raw); + const formatted = formatPrimitive(stylizeNoColor, raw, ctx); if (keyLength === raw.length) return ctx.stylize(`[String: ${formatted}]`, 'string'); - base = ` [String: ${formatted}]`; + base = `[String: ${formatted}]`; // For boxed Strings, we have to remove the 0-n indexed entries, // since they just noisy up the output and are redundant // Make boxed primitive Strings look like such @@ -505,12 +511,12 @@ function formatValue(ctx, value, recurseTimes, ln) { const name = `${constructor.name}${value.name ? `: ${value.name}` : ''}`; if (keyLength === 0) return ctx.stylize(`[${name}]`, 'special'); - base = ` [${name}]`; + base = `[${name}]`; } else if (isRegExp(value)) { // Make RegExps say that they are RegExps if (keyLength === 0 || recurseTimes < 0) return ctx.stylize(regExpToString.call(value), 'regexp'); - base = ` ${regExpToString.call(value)}`; + base = `${regExpToString.call(value)}`; } else if (isDate(value)) { if (keyLength === 0) { if (Number.isNaN(value.getTime())) @@ -518,12 +524,12 @@ function formatValue(ctx, value, recurseTimes, ln) { return ctx.stylize(dateToISOString.call(value), 'date'); } // Make dates with properties first say the date - base = ` ${dateToISOString.call(value)}`; + base = `${dateToISOString.call(value)}`; } else if (isError(value)) { // Make error with message first say the error if (keyLength === 0) return formatError(value); - base = ` ${formatError(value)}`; + base = `${formatError(value)}`; } else if (isAnyArrayBuffer(value)) { // Fast path for ArrayBuffer and SharedArrayBuffer. // Can't do the same for DataView because it has a non-primitive @@ -553,13 +559,13 @@ function formatValue(ctx, value, recurseTimes, ln) { const formatted = formatPrimitive(stylizeNoColor, raw); if (keyLength === 0) return ctx.stylize(`[Number: ${formatted}]`, 'number'); - base = ` [Number: ${formatted}]`; + base = `[Number: ${formatted}]`; } else if (typeof raw === 'boolean') { // Make boxed primitive Booleans look like such const formatted = formatPrimitive(stylizeNoColor, raw); if (keyLength === 0) return ctx.stylize(`[Boolean: ${formatted}]`, 'boolean'); - base = ` [Boolean: ${formatted}]`; + base = `[Boolean: ${formatted}]`; } else if (typeof raw === 'symbol') { const formatted = formatPrimitive(stylizeNoColor, raw); return ctx.stylize(`[Symbol: ${formatted}]`, 'symbol'); @@ -603,9 +609,42 @@ function formatNumber(fn, value) { return fn(`${value}`, 'number'); } -function formatPrimitive(fn, value) { - if (typeof value === 'string') +function formatPrimitive(fn, value, ctx) { + if (typeof value === 'string') { + if (ctx.compact === false && + value.length > MIN_LINE_LENGTH && + ctx.indentationLvl + value.length > ctx.breakLength) { + // eslint-disable-next-line max-len + const minLineLength = Math.max(ctx.breakLength - ctx.indentationLvl, MIN_LINE_LENGTH); + // eslint-disable-next-line max-len + const averageLineLength = Math.ceil(value.length / Math.ceil(value.length / minLineLength)); + const divisor = Math.max(averageLineLength, MIN_LINE_LENGTH); + var res = ''; + if (readableRegExps[divisor] === undefined) { + // Build a new RegExp that naturally breaks text into multiple lines. + // + // Rules + // 1. Greedy match all text up the max line length that ends with a + // whitespace or the end of the string. + // 2. If none matches, non-greedy match any text up to a whitespace or + // the end of the string. + // + // eslint-disable-next-line max-len, no-unescaped-regexp-dot + readableRegExps[divisor] = new RegExp(`(.|\\n){1,${divisor}}(\\s|$)|(\\n|.)+?(\\s|$)`, 'gm'); + } + const indent = ' '.repeat(ctx.indentationLvl); + const matches = value.match(readableRegExps[divisor]); + if (matches.length > 1) { + res += `${fn(strEscape(matches[0]), 'string')} +\n`; + for (var i = 1; i < matches.length - 1; i++) { + res += `${indent} ${fn(strEscape(matches[i]), 'string')} +\n`; + } + res += `${indent} ${fn(strEscape(matches[i]), 'string')}`; + return res; + } + } return fn(strEscape(value), 'string'); + } if (typeof value === 'number') return formatNumber(fn, value); if (typeof value === 'boolean') @@ -806,7 +845,7 @@ function formatProperty(ctx, value, recurseTimes, key, array) { const desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key], enumerable: true }; if (desc.value !== undefined) { - const diff = array === 0 ? 3 : 2; + const diff = array !== 0 || ctx.compact === false ? 2 : 3; ctx.indentationLvl += diff; str = formatValue(ctx, desc.value, recurseTimes, array === 0); ctx.indentationLvl -= diff; @@ -839,9 +878,19 @@ function formatProperty(ctx, value, recurseTimes, key, array) { function reduceToSingleString(ctx, output, base, braces, addLn) { const breakLength = ctx.breakLength; + var i = 0; + if (ctx.compact === false) { + const indentation = ' '.repeat(ctx.indentationLvl); + var res = `${base ? `${base} ` : ''}${braces[0]}\n${indentation} `; + for (; i < output.length - 1; i++) { + res += `${output[i]},\n${indentation} `; + } + res += `${output[i]}\n${indentation}${braces[1]}`; + return res; + } if (output.length * 2 <= breakLength) { var length = 0; - for (var i = 0; i < output.length && length <= breakLength; i++) { + for (; i < output.length && length <= breakLength; i++) { if (ctx.colors) { length += removeColors(output[i]).length + 1; } else { @@ -849,7 +898,8 @@ function reduceToSingleString(ctx, output, base, braces, addLn) { } } if (length <= breakLength) - return `${braces[0]}${base} ${join(output, ', ')} ${braces[1]}`; + return `${braces[0]}${base ? ` ${base}` : ''} ${join(output, ', ')} ` + + braces[1]; } // If the opening "brace" is too large, like in the case of "Set {", // we need to force the first item to be on the next line or the @@ -857,7 +907,7 @@ function reduceToSingleString(ctx, output, base, braces, addLn) { const indentation = ' '.repeat(ctx.indentationLvl); const extraLn = addLn === true ? `\n${indentation}` : ''; const ln = base === '' && braces[0].length === 1 ? - ' ' : `${base}\n${indentation} `; + ' ' : `${base ? ` ${base}` : base}\n${indentation} `; const str = join(output, `,\n${indentation} `); return `${extraLn}${braces[0]}${ln}${str} ${braces[1]}`; } diff --git a/node.gyp b/node.gyp index d85f6a491a9eea..1ab7b207e21339 100644 --- a/node.gyp +++ b/node.gyp @@ -142,6 +142,7 @@ 'lib/internal/vm/Module.js', 'lib/internal/streams/lazy_transform.js', 'lib/internal/streams/BufferList.js', + 'lib/internal/streams/duplex_base.js', 'lib/internal/streams/legacy.js', 'lib/internal/streams/destroy.js', 'lib/internal/wrap_js_stream.js', @@ -193,6 +194,9 @@ 'sources': [ 'src/node_main.cc' ], + 'includes': [ + 'node.gypi' + ], 'include_dirs': [ 'src', 'deps/v8/include', @@ -210,9 +214,6 @@ }], [ 'node_intermediate_lib_type=="static_library" and ' 'node_shared=="false"', { - 'includes': [ - 'node.gypi' - ], 'xcode_settings': { 'OTHER_LDFLAGS': [ '-Wl,-force_load,<(PRODUCT_DIR)/<(STATIC_LIB_PREFIX)' @@ -454,22 +455,8 @@ ], }], ], - 'defines!': [ - 'NODE_PLATFORM="win"', - ], - 'defines': [ - 'FD_SETSIZE=1024', - # we need to use node's preferred "win32" rather than gyp's preferred "win" - 'NODE_PLATFORM="win32"', - # Stop from defining macros that conflict with - # std::min() and std::max(). We don't use (much) - # but we still inherit it from uv.h. - 'NOMINMAX', - '_UNICODE=1', - ], 'libraries': [ '-lpsapi.lib' ] }, { # POSIX - 'defines': [ '__POSIX__' ], 'sources': [ 'src/backtrace_posix.cc' ], }], [ 'node_use_etw=="true"', { diff --git a/node.gypi b/node.gypi index 852cc18eee7495..ac043dac2423ca 100644 --- a/node.gypi +++ b/node.gypi @@ -37,6 +37,24 @@ 'NODE_SHARED_MODE', ], }], + [ 'OS=="win"', { + 'defines!': [ + 'NODE_PLATFORM="win"', + ], + 'defines': [ + 'FD_SETSIZE=1024', + # we need to use node's preferred "win32" rather than gyp's preferred "win" + 'NODE_PLATFORM="win32"', + # Stop from defining macros that conflict with + # std::min() and std::max(). We don't use (much) + # but we still inherit it from uv.h. + 'NOMINMAX', + '_UNICODE=1', + ], + }, { # POSIX + 'defines': [ '__POSIX__' ], + }], + [ 'node_enable_d8=="true"', { 'dependencies': [ 'deps/v8/src/d8.gyp:d8' ], }], diff --git a/src/aliased_buffer.h b/src/aliased_buffer.h index b99b01f5d94ca2..8b103f4949030c 100644 --- a/src/aliased_buffer.h +++ b/src/aliased_buffer.h @@ -141,6 +141,22 @@ class AliasedBuffer { return aliased_buffer_->GetValue(index_); } + template + inline Reference& operator+=(const T& val) { + const T current = aliased_buffer_->GetValue(index_); + aliased_buffer_->SetValue(index_, current + val); + return *this; + } + + inline Reference& operator+=(const Reference& val) { + return this->operator+=(static_cast(val)); + } + + template + inline Reference& operator-=(const T& val) { + return this->operator+=(-val); + } + private: AliasedBuffer* aliased_buffer_; size_t index_; diff --git a/src/async_wrap-inl.h b/src/async_wrap-inl.h index cc6377d82a0fee..21b1f9cee9f0e8 100644 --- a/src/async_wrap-inl.h +++ b/src/async_wrap-inl.h @@ -64,6 +64,13 @@ inline v8::MaybeLocal AsyncWrap::MakeCallback( return MakeCallback(cb_v.As(), argc, argv); } + +// Defined here to avoid a circular dependency with env-inl.h. +inline Environment::AsyncHooks::DefaultTriggerAsyncIdScope + ::DefaultTriggerAsyncIdScope(AsyncWrap* async_wrap) + : DefaultTriggerAsyncIdScope(async_wrap->env(), + async_wrap->get_async_id()) {} + } // namespace node #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS diff --git a/src/async_wrap.cc b/src/async_wrap.cc index cd9f26d7782d46..f85c8c7be6692f 100644 --- a/src/async_wrap.cc +++ b/src/async_wrap.cc @@ -23,13 +23,10 @@ #include "env-inl.h" #include "util-inl.h" -#include "uv.h" #include "v8.h" #include "v8-profiler.h" -using v8::Array; using v8::Context; -using v8::Float64Array; using v8::Function; using v8::FunctionCallbackInfo; using v8::FunctionTemplate; @@ -48,7 +45,6 @@ using v8::PropertyCallbackInfo; using v8::RetainedObjectInfo; using v8::String; using v8::Symbol; -using v8::TryCatch; using v8::Undefined; using v8::Value; @@ -166,19 +162,25 @@ static void DestroyAsyncIdsCallback(void* arg) { } -void AsyncWrap::EmitPromiseResolve(Environment* env, double async_id) { +void Emit(Environment* env, double async_id, AsyncHooks::Fields type, + Local fn) { AsyncHooks* async_hooks = env->async_hooks(); - if (async_hooks->fields()[AsyncHooks::kPromiseResolve] == 0) + if (async_hooks->fields()[type] == 0) return; Local async_id_value = Number::New(env->isolate(), async_id); - Local fn = env->async_hooks_promise_resolve_function(); FatalTryCatch try_catch(env); USE(fn->Call(env->context(), Undefined(env->isolate()), 1, &async_id_value)); } +void AsyncWrap::EmitPromiseResolve(Environment* env, double async_id) { + Emit(env, async_id, AsyncHooks::kPromiseResolve, + env->async_hooks_promise_resolve_function()); +} + + void AsyncWrap::EmitTraceEventBefore() { switch (provider_type()) { #define V(PROVIDER) \ @@ -195,15 +197,8 @@ void AsyncWrap::EmitTraceEventBefore() { void AsyncWrap::EmitBefore(Environment* env, double async_id) { - AsyncHooks* async_hooks = env->async_hooks(); - - if (async_hooks->fields()[AsyncHooks::kBefore] == 0) - return; - - Local async_id_value = Number::New(env->isolate(), async_id); - Local fn = env->async_hooks_before_function(); - FatalTryCatch try_catch(env); - USE(fn->Call(env->context(), Undefined(env->isolate()), 1, &async_id_value)); + Emit(env, async_id, AsyncHooks::kBefore, + env->async_hooks_before_function()); } @@ -223,23 +218,16 @@ void AsyncWrap::EmitTraceEventAfter() { void AsyncWrap::EmitAfter(Environment* env, double async_id) { - AsyncHooks* async_hooks = env->async_hooks(); - - if (async_hooks->fields()[AsyncHooks::kAfter] == 0) - return; - // If the user's callback failed then the after() hooks will be called at the // end of _fatalException(). - Local async_id_value = Number::New(env->isolate(), async_id); - Local fn = env->async_hooks_after_function(); - FatalTryCatch try_catch(env); - USE(fn->Call(env->context(), Undefined(env->isolate()), 1, &async_id_value)); + Emit(env, async_id, AsyncHooks::kAfter, + env->async_hooks_after_function()); } class PromiseWrap : public AsyncWrap { public: PromiseWrap(Environment* env, Local object, bool silent) - : AsyncWrap(env, object, silent) { + : AsyncWrap(env, object, PROVIDER_PROMISE, -1, silent) { MakeWeak(this); } size_t self_size() const override { return sizeof(*this); } @@ -285,19 +273,20 @@ void PromiseWrap::getIsChainedPromise(Local property, info.Holder()->GetInternalField(kIsChainedPromiseField)); } -static void PromiseHook(PromiseHookType type, Local promise, - Local parent, void* arg) { - Environment* env = static_cast(arg); +static PromiseWrap* extractPromiseWrap(Local promise) { Local resource_object_value = promise->GetInternalField(0); - PromiseWrap* wrap = nullptr; if (resource_object_value->IsObject()) { - Local resource_object = resource_object_value.As(); - wrap = Unwrap(resource_object); + return Unwrap(resource_object_value.As()); } + return nullptr; +} +static void PromiseHook(PromiseHookType type, Local promise, + Local parent, void* arg) { + Environment* env = static_cast(arg); + PromiseWrap* wrap = extractPromiseWrap(promise); if (type == PromiseHookType::kInit || wrap == nullptr) { bool silent = type != PromiseHookType::kInit; - PromiseWrap* parent_wrap = nullptr; // set parent promise's async Id as this promise's triggerAsyncId if (parent->IsPromise()) { @@ -305,17 +294,12 @@ static void PromiseHook(PromiseHookType type, Local promise, // is a chained promise, so we set parent promise's id as // current promise's triggerAsyncId Local parent_promise = parent.As(); - Local parent_resource = parent_promise->GetInternalField(0); - if (parent_resource->IsObject()) { - parent_wrap = Unwrap(parent_resource.As()); - } - + PromiseWrap* parent_wrap = extractPromiseWrap(parent_promise); if (parent_wrap == nullptr) { parent_wrap = PromiseWrap::New(env, parent_promise, nullptr, true); } - AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope( - env, parent_wrap->get_async_id()); + AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(parent_wrap); wrap = PromiseWrap::New(env, promise, parent_wrap, silent); } else { wrap = PromiseWrap::New(env, promise, nullptr, silent); @@ -326,7 +310,7 @@ static void PromiseHook(PromiseHookType type, Local promise, if (type == PromiseHookType::kBefore) { env->async_hooks()->push_async_ids( wrap->get_async_id(), wrap->get_trigger_async_id()); - wrap->EmitTraceEventBefore(); + wrap->EmitTraceEventBefore(); AsyncWrap::EmitBefore(wrap->env(), wrap->get_async_id()); } else if (type == PromiseHookType::kAfter) { wrap->EmitTraceEventAfter(); @@ -419,14 +403,14 @@ void AsyncWrap::WeakCallback(const v8::WeakCallbackInfo& info) { HandleScope scope(info.GetIsolate()); Environment* env = Environment::GetCurrent(info.GetIsolate()); - DestroyParam* p = info.GetParameter(); + std::unique_ptr p{info.GetParameter()}; Local prop_bag = PersistentToLocal(info.GetIsolate(), p->propBag); Local val = prop_bag->Get(env->destroyed_string()); if (val->IsFalse()) { AsyncWrap::EmitDestroy(env, p->asyncId); } - delete p; + // unique_ptr goes out of scope here and pointer is deleted. } @@ -615,32 +599,23 @@ AsyncWrap::AsyncWrap(Environment* env, Local object, ProviderType provider, double execution_async_id) - : BaseObject(env, object), - provider_type_(provider) { - CHECK_NE(provider, PROVIDER_NONE); - CHECK_GE(object->InternalFieldCount(), 1); - - // Shift provider value over to prevent id collision. - persistent().SetWrapperClassId(NODE_ASYNC_ID_OFFSET + provider); - - // Use AsyncReset() call to execute the init() callbacks. - AsyncReset(execution_async_id); -} - + : AsyncWrap(env, object, provider, execution_async_id, false) {} -// This is specifically used by the PromiseWrap constructor. AsyncWrap::AsyncWrap(Environment* env, Local object, + ProviderType provider, + double execution_async_id, bool silent) : BaseObject(env, object), - provider_type_(PROVIDER_PROMISE) { + provider_type_(provider) { + CHECK_NE(provider, PROVIDER_NONE); CHECK_GE(object->InternalFieldCount(), 1); // Shift provider value over to prevent id collision. persistent().SetWrapperClassId(NODE_ASYNC_ID_OFFSET + provider_type_); // Use AsyncReset() call to execute the init() callbacks. - AsyncReset(-1, silent); + AsyncReset(execution_async_id, silent); } diff --git a/src/async_wrap.h b/src/async_wrap.h index 9b5632598bcc0b..d8b04f2538ccc4 100644 --- a/src/async_wrap.h +++ b/src/async_wrap.h @@ -172,8 +172,11 @@ class AsyncWrap : public BaseObject { private: friend class PromiseWrap; - // This is specifically used by the PromiseWrap constructor. - AsyncWrap(Environment* env, v8::Local promise, bool silent); + AsyncWrap(Environment* env, + v8::Local promise, + ProviderType provider, + double execution_async_id, + bool silent); inline AsyncWrap(); const ProviderType provider_type_; // Because the values may be Reset(), cannot be made const. diff --git a/src/cares_wrap.cc b/src/cares_wrap.cc index b8da20346692c3..da3083a9ce3673 100644 --- a/src/cares_wrap.cc +++ b/src/cares_wrap.cc @@ -29,7 +29,6 @@ #include "uv.h" #include -#include #include #include #include diff --git a/src/env-inl.h b/src/env-inl.h index f647f428c324ff..615d4b95a543bc 100644 --- a/src/env-inl.h +++ b/src/env-inl.h @@ -111,8 +111,7 @@ inline v8::Local Environment::AsyncHooks::provider_string(int idx) { } inline void Environment::AsyncHooks::no_force_checks() { - // fields_ does not have the -= operator defined - fields_[kCheck] = fields_[kCheck] - 1; + fields_[kCheck] -= 1; } inline Environment* Environment::AsyncHooks::env() { @@ -121,7 +120,7 @@ inline Environment* Environment::AsyncHooks::env() { // Remember to keep this code aligned with pushAsyncIds() in JS. inline void Environment::AsyncHooks::push_async_ids(double async_id, - double trigger_async_id) { + double trigger_async_id) { // Since async_hooks is experimental, do only perform the check // when async_hooks is enabled. if (fields_[kCheck] > 0) { @@ -134,7 +133,7 @@ inline void Environment::AsyncHooks::push_async_ids(double async_id, grow_async_ids_stack(); async_ids_stack_[2 * offset] = async_id_fields_[kExecutionAsyncId]; async_ids_stack_[2 * offset + 1] = async_id_fields_[kTriggerAsyncId]; - fields_[kStackLength] = fields_[kStackLength] + 1; + fields_[kStackLength] += 1; async_id_fields_[kExecutionAsyncId] = async_id; async_id_fields_[kTriggerAsyncId] = trigger_async_id; } @@ -178,6 +177,9 @@ inline void Environment::AsyncHooks::clear_async_id_stack() { fields_[kStackLength] = 0; } +// The DefaultTriggerAsyncIdScope(AsyncWrap*) constructor is defined in +// async_wrap-inl.h to avoid a circular dependency. + inline Environment::AsyncHooks::DefaultTriggerAsyncIdScope ::DefaultTriggerAsyncIdScope(Environment* env, double default_trigger_async_id) @@ -238,19 +240,19 @@ inline bool Environment::ImmediateInfo::has_outstanding() const { } inline void Environment::ImmediateInfo::count_inc(uint32_t increment) { - fields_[kCount] = fields_[kCount] + increment; + fields_[kCount] += increment; } inline void Environment::ImmediateInfo::count_dec(uint32_t decrement) { - fields_[kCount] = fields_[kCount] - decrement; + fields_[kCount] -= decrement; } inline void Environment::ImmediateInfo::ref_count_inc(uint32_t increment) { - fields_[kRefCount] = fields_[kRefCount] + increment; + fields_[kRefCount] += increment; } inline void Environment::ImmediateInfo::ref_count_dec(uint32_t decrement) { - fields_[kRefCount] = fields_[kRefCount] - decrement; + fields_[kRefCount] -= decrement; } inline Environment::TickInfo::TickInfo(v8::Isolate* isolate) @@ -461,8 +463,7 @@ inline std::vector* Environment::destroy_async_id_list() { } inline double Environment::new_async_id() { - async_hooks()->async_id_fields()[AsyncHooks::kAsyncIdCounter] = - async_hooks()->async_id_fields()[AsyncHooks::kAsyncIdCounter] + 1; + async_hooks()->async_id_fields()[AsyncHooks::kAsyncIdCounter] += 1; return async_hooks()->async_id_fields()[AsyncHooks::kAsyncIdCounter]; } @@ -532,9 +533,9 @@ inline void Environment::set_fs_stats_field_array(double* fields) { } void Environment::CreateImmediate(native_immediate_callback cb, - void* data, - v8::Local obj, - bool ref) { + void* data, + v8::Local obj, + bool ref) { native_immediate_callbacks_.push_back({ cb, data, diff --git a/src/env.cc b/src/env.cc index 455f5980731f3f..960cc4d5f88a69 100644 --- a/src/env.cc +++ b/src/env.cc @@ -218,25 +218,25 @@ void Environment::PrintSyncTrace() const { } void Environment::RunBeforeExitCallbacks() { - for (BeforeExitCallback before_exit : before_exit_functions_) { + for (ExitCallback before_exit : before_exit_functions_) { before_exit.cb_(before_exit.arg_); } before_exit_functions_.clear(); } void Environment::BeforeExit(void (*cb)(void* arg), void* arg) { - before_exit_functions_.push_back(BeforeExitCallback{cb, arg}); + before_exit_functions_.push_back(ExitCallback{cb, arg}); } void Environment::RunAtExitCallbacks() { - for (AtExitCallback at_exit : at_exit_functions_) { + for (ExitCallback at_exit : at_exit_functions_) { at_exit.cb_(at_exit.arg_); } at_exit_functions_.clear(); } void Environment::AtExit(void (*cb)(void* arg), void* arg) { - at_exit_functions_.push_back(AtExitCallback{cb, arg}); + at_exit_functions_.push_back(ExitCallback{cb, arg}); } void Environment::AddPromiseHook(promise_hook_func fn, void* arg) { diff --git a/src/env.h b/src/env.h index dcabf7f54fadef..b1ec2a1fe7f267 100644 --- a/src/env.h +++ b/src/env.h @@ -434,6 +434,7 @@ class Environment { DefaultTriggerAsyncIdScope() = delete; explicit DefaultTriggerAsyncIdScope(Environment* env, double init_trigger_async_id); + explicit DefaultTriggerAsyncIdScope(AsyncWrap* async_wrap); ~DefaultTriggerAsyncIdScope(); private: @@ -799,17 +800,13 @@ class Environment { double* fs_stats_field_array_; - struct BeforeExitCallback { + struct ExitCallback { void (*cb_)(void* arg); void* arg_; }; - std::list before_exit_functions_; + std::list before_exit_functions_; - struct AtExitCallback { - void (*cb_)(void* arg); - void* arg_; - }; - std::list at_exit_functions_; + std::list at_exit_functions_; struct PromiseHookCallback { promise_hook_func cb_; diff --git a/src/fs_event_wrap.cc b/src/fs_event_wrap.cc index 85a09060a11edc..e37c82516f194a 100644 --- a/src/fs_event_wrap.cc +++ b/src/fs_event_wrap.cc @@ -26,7 +26,6 @@ #include "handle_wrap.h" #include "string_bytes.h" -#include namespace node { diff --git a/src/node_api.cc b/src/node_api.cc index 63ce1d8e86955e..fa6d09dbd9cbb5 100644 --- a/src/node_api.cc +++ b/src/node_api.cc @@ -2811,11 +2811,15 @@ napi_status napi_make_callback(napi_env env, isolate, v8recv, v8func, argc, reinterpret_cast*>(const_cast(argv)), *node_async_context); - CHECK_MAYBE_EMPTY(env, callback_result, napi_generic_failure); - if (result != nullptr) { - *result = v8impl::JsValueFromV8LocalValue( - callback_result.ToLocalChecked()); + if (try_catch.HasCaught()) { + return napi_set_last_error(env, napi_pending_exception); + } else { + CHECK_MAYBE_EMPTY(env, callback_result, napi_generic_failure); + if (result != nullptr) { + *result = v8impl::JsValueFromV8LocalValue( + callback_result.ToLocalChecked()); + } } return GET_RETURN_STATUS(env); diff --git a/src/node_crypto.cc b/src/node_crypto.cc index 3e630926b5547a..1451b44a370871 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -46,7 +46,6 @@ #include #include // INT_MAX #include -#include #include #include @@ -1615,6 +1614,8 @@ void SSLWrap::AddMethods(Environment* env, Local t) { HandleScope scope(env->isolate()); env->SetProtoMethod(t, "getPeerCertificate", GetPeerCertificate); + env->SetProtoMethod(t, "getFinished", GetFinished); + env->SetProtoMethod(t, "getPeerFinished", GetPeerFinished); env->SetProtoMethod(t, "getSession", GetSession); env->SetProtoMethod(t, "setSession", SetSession); env->SetProtoMethod(t, "loadSession", LoadSession); @@ -2133,6 +2134,52 @@ void SSLWrap::GetPeerCertificate( } +template +void SSLWrap::GetFinished(const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args); + + Base* w; + ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder()); + + // We cannot just pass nullptr to SSL_get_finished() + // because it would further be propagated to memcpy(), + // where the standard requirements as described in ISO/IEC 9899:2011 + // sections 7.21.2.1, 7.21.1.2, and 7.1.4, would be violated. + // Thus, we use a dummy byte. + char dummy[1]; + size_t len = SSL_get_finished(w->ssl_, dummy, sizeof dummy); + if (len == 0) + return; + + char* buf = Malloc(len); + CHECK_EQ(len, SSL_get_finished(w->ssl_, buf, len)); + args.GetReturnValue().Set(Buffer::New(env, buf, len).ToLocalChecked()); +} + + +template +void SSLWrap::GetPeerFinished(const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args); + + Base* w; + ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder()); + + // We cannot just pass nullptr to SSL_get_peer_finished() + // because it would further be propagated to memcpy(), + // where the standard requirements as described in ISO/IEC 9899:2011 + // sections 7.21.2.1, 7.21.1.2, and 7.1.4, would be violated. + // Thus, we use a dummy byte. + char dummy[1]; + size_t len = SSL_get_peer_finished(w->ssl_, dummy, sizeof dummy); + if (len == 0) + return; + + char* buf = Malloc(len); + CHECK_EQ(len, SSL_get_peer_finished(w->ssl_, buf, len)); + args.GetReturnValue().Set(Buffer::New(env, buf, len).ToLocalChecked()); +} + + template void SSLWrap::GetSession(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); @@ -3760,8 +3807,17 @@ void CipherBase::InitIv(const char* cipher_type, const int expected_iv_len = EVP_CIPHER_iv_length(cipher); const int mode = EVP_CIPHER_mode(cipher); const bool is_gcm_mode = (EVP_CIPH_GCM_MODE == mode); + const bool has_iv = iv_len >= 0; + + // Throw if no IV was passed and the cipher requires an IV + if (!has_iv && expected_iv_len != 0) { + char msg[128]; + snprintf(msg, sizeof(msg), "Missing IV for cipher %s", cipher_type); + return env()->ThrowError(msg); + } - if (is_gcm_mode == false && iv_len != expected_iv_len) { + // Throw if an IV was passed which does not match the cipher's fixed IV length + if (is_gcm_mode == false && has_iv && iv_len != expected_iv_len) { return env()->ThrowError("Invalid IV length"); } @@ -3773,11 +3829,13 @@ void CipherBase::InitIv(const char* cipher_type, const bool encrypt = (kind_ == kCipher); EVP_CipherInit_ex(ctx_, cipher, nullptr, nullptr, nullptr, encrypt); - if (is_gcm_mode && - !EVP_CIPHER_CTX_ctrl(ctx_, EVP_CTRL_GCM_SET_IVLEN, iv_len, nullptr)) { - EVP_CIPHER_CTX_free(ctx_); - ctx_ = nullptr; - return env()->ThrowError("Invalid IV length"); + if (is_gcm_mode) { + CHECK(has_iv); + if (!EVP_CIPHER_CTX_ctrl(ctx_, EVP_CTRL_GCM_SET_IVLEN, iv_len, nullptr)) { + EVP_CIPHER_CTX_free(ctx_); + ctx_ = nullptr; + return env()->ThrowError("Invalid IV length"); + } } if (!EVP_CIPHER_CTX_set_key_length(ctx_, key_len)) { @@ -3806,13 +3864,23 @@ void CipherBase::InitIv(const FunctionCallbackInfo& args) { THROW_AND_RETURN_IF_NOT_STRING(args[0], "Cipher type"); THROW_AND_RETURN_IF_NOT_BUFFER(args[1], "Key"); - THROW_AND_RETURN_IF_NOT_BUFFER(args[2], "IV"); + + if (!args[2]->IsNull() && !Buffer::HasInstance(args[2])) { + return env->ThrowTypeError("IV must be a buffer"); + } const node::Utf8Value cipher_type(env->isolate(), args[0]); ssize_t key_len = Buffer::Length(args[1]); const char* key_buf = Buffer::Data(args[1]); - ssize_t iv_len = Buffer::Length(args[2]); - const char* iv_buf = Buffer::Data(args[2]); + ssize_t iv_len; + const char* iv_buf; + if (args[2]->IsNull()) { + iv_buf = nullptr; + iv_len = -1; + } else { + iv_buf = Buffer::Data(args[2]); + iv_len = Buffer::Length(args[2]); + } cipher->InitIv(*cipher_type, key_buf, key_len, iv_buf, iv_len); } @@ -3911,7 +3979,7 @@ bool CipherBase::Update(const char* data, unsigned char** out, int* out_len) { if (ctx_ == nullptr) - return 0; + return false; // on first update: if (kind_ == kDecipher && IsAuthenticatedMode() && auth_tag_len_ > 0) { diff --git a/src/node_crypto.h b/src/node_crypto.h index f1efa811985681..4c750b313df15a 100644 --- a/src/node_crypto.h +++ b/src/node_crypto.h @@ -269,6 +269,8 @@ class SSLWrap { static void GetPeerCertificate( const v8::FunctionCallbackInfo& args); + static void GetFinished(const v8::FunctionCallbackInfo& args); + static void GetPeerFinished(const v8::FunctionCallbackInfo& args); static void GetSession(const v8::FunctionCallbackInfo& args); static void SetSession(const v8::FunctionCallbackInfo& args); static void LoadSession(const v8::FunctionCallbackInfo& args); diff --git a/src/node_http2.cc b/src/node_http2.cc index 7650969f8639ce..a11a0bc87b82b1 100644 --- a/src/node_http2.cc +++ b/src/node_http2.cc @@ -190,60 +190,28 @@ Http2Options::Http2Options(Environment* env) { } void Http2Session::Http2Settings::Init() { - entries_.AllocateSufficientStorage(IDX_SETTINGS_COUNT); AliasedBuffer& buffer = env()->http2_state()->settings_buffer; uint32_t flags = buffer[IDX_SETTINGS_COUNT]; size_t n = 0; - if (flags & (1 << IDX_SETTINGS_HEADER_TABLE_SIZE)) { - uint32_t val = buffer[IDX_SETTINGS_HEADER_TABLE_SIZE]; - DEBUG_HTTP2SESSION2(session_, "setting header table size: %d\n", val); - entries_[n].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE; - entries_[n].value = val; - n++; +#define GRABSETTING(N, trace) \ + if (flags & (1 << IDX_SETTINGS_##N)) { \ + uint32_t val = buffer[IDX_SETTINGS_##N]; \ + DEBUG_HTTP2SESSION2(session_, "setting " trace ": %d\n", val); \ + entries_[n++] = \ + nghttp2_settings_entry {NGHTTP2_SETTINGS_##N, val}; \ } - if (flags & (1 << IDX_SETTINGS_MAX_CONCURRENT_STREAMS)) { - uint32_t val = buffer[IDX_SETTINGS_MAX_CONCURRENT_STREAMS]; - DEBUG_HTTP2SESSION2(session_, "setting max concurrent streams: %d\n", val); - entries_[n].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS; - entries_[n].value = val; - n++; - } - - if (flags & (1 << IDX_SETTINGS_MAX_FRAME_SIZE)) { - uint32_t val = buffer[IDX_SETTINGS_MAX_FRAME_SIZE]; - DEBUG_HTTP2SESSION2(session_, "setting max frame size: %d\n", val); - entries_[n].settings_id = NGHTTP2_SETTINGS_MAX_FRAME_SIZE; - entries_[n].value = val; - n++; - } + GRABSETTING(HEADER_TABLE_SIZE, "header table size"); + GRABSETTING(MAX_CONCURRENT_STREAMS, "max concurrent streams"); + GRABSETTING(MAX_FRAME_SIZE, "max frame size"); + GRABSETTING(INITIAL_WINDOW_SIZE, "initial window size"); + GRABSETTING(MAX_HEADER_LIST_SIZE, "max header list size"); + GRABSETTING(ENABLE_PUSH, "enable push"); - if (flags & (1 << IDX_SETTINGS_INITIAL_WINDOW_SIZE)) { - uint32_t val = buffer[IDX_SETTINGS_INITIAL_WINDOW_SIZE]; - DEBUG_HTTP2SESSION2(session_, "setting initial window size: %d\n", val); - entries_[n].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE; - entries_[n].value = val; - n++; - } - - if (flags & (1 << IDX_SETTINGS_MAX_HEADER_LIST_SIZE)) { - uint32_t val = buffer[IDX_SETTINGS_MAX_HEADER_LIST_SIZE]; - DEBUG_HTTP2SESSION2(session_, "setting max header list size: %d\n", val); - entries_[n].settings_id = NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE; - entries_[n].value = val; - n++; - } - - if (flags & (1 << IDX_SETTINGS_ENABLE_PUSH)) { - uint32_t val = buffer[IDX_SETTINGS_ENABLE_PUSH]; - DEBUG_HTTP2SESSION2(session_, "setting enable push: %d\n", val); - entries_[n].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH; - entries_[n].value = val; - n++; - } +#undef GRABSETTING count_ = n; } @@ -283,13 +251,13 @@ Http2Session::Http2Settings::~Http2Settings() { // Generates a Buffer that contains the serialized payload of a SETTINGS // frame. This can be used, for instance, to create the Base64-encoded // content of an Http2-Settings header field. -inline Local Http2Session::Http2Settings::Pack() { +Local Http2Session::Http2Settings::Pack() { const size_t len = count_ * 6; Local buf = Buffer::New(env(), len).ToLocalChecked(); ssize_t ret = nghttp2_pack_settings_payload( reinterpret_cast(Buffer::Data(buf)), len, - *entries_, count_); + &entries_[0], count_); if (ret >= 0) return buf; else @@ -298,9 +266,9 @@ inline Local Http2Session::Http2Settings::Pack() { // Updates the shared TypedArray with the current remote or local settings for // the session. -inline void Http2Session::Http2Settings::Update(Environment* env, - Http2Session* session, - get_setting fn) { +void Http2Session::Http2Settings::Update(Environment* env, + Http2Session* session, + get_setting fn) { AliasedBuffer& buffer = env->http2_state()->settings_buffer; buffer[IDX_SETTINGS_HEADER_TABLE_SIZE] = @@ -318,7 +286,7 @@ inline void Http2Session::Http2Settings::Update(Environment* env, } // Initializes the shared TypedArray with the default settings values. -inline void Http2Session::Http2Settings::RefreshDefaults(Environment* env) { +void Http2Session::Http2Settings::RefreshDefaults(Environment* env) { AliasedBuffer& buffer = env->http2_state()->settings_buffer; @@ -344,7 +312,7 @@ inline void Http2Session::Http2Settings::RefreshDefaults(Environment* env) { void Http2Session::Http2Settings::Send() { Http2Scope h2scope(session_); CHECK_EQ(nghttp2_submit_settings(**session_, NGHTTP2_FLAG_NONE, - *entries_, length()), 0); + &entries_[0], count_), 0); } void Http2Session::Http2Settings::Done(bool ack) { @@ -541,7 +509,7 @@ inline bool HasHttp2Observer(Environment* env) { return observers[performance::NODE_PERFORMANCE_ENTRY_TYPE_HTTP2] != 0; } -inline void Http2Stream::EmitStatistics() { +void Http2Stream::EmitStatistics() { if (!HasHttp2Observer(env())) return; Http2StreamPerformanceEntry* entry = @@ -579,7 +547,7 @@ inline void Http2Stream::EmitStatistics() { }, static_cast(entry)); } -inline void Http2Session::EmitStatistics() { +void Http2Session::EmitStatistics() { if (!HasHttp2Observer(env())) return; Http2SessionPerformanceEntry* entry = @@ -627,9 +595,8 @@ void Http2Session::Close(uint32_t code, bool socket_closed) { Http2Scope h2scope(this); DEBUG_HTTP2SESSION2(this, "terminating session with code %d", code); CHECK_EQ(nghttp2_session_terminate_session(session_, code), 0); - } else { - if (stream_ != nullptr) - stream_->RemoveStreamListener(this); + } else if (stream_ != nullptr) { + stream_->RemoveStreamListener(this); } // If there are outstanding pings, those will need to be canceled, do @@ -684,8 +651,8 @@ inline void Http2Session::RemoveStream(Http2Stream* stream) { // that the total frame size, including header bytes, are 8-byte aligned. // If maxPayloadLen is smaller than the number of bytes necessary to align, // will return maxPayloadLen instead. -inline ssize_t Http2Session::OnDWordAlignedPadding(size_t frameLen, - size_t maxPayloadLen) { +ssize_t Http2Session::OnDWordAlignedPadding(size_t frameLen, + size_t maxPayloadLen) { size_t r = (frameLen + 9) % 8; if (r == 0) return frameLen; // If already a multiple of 8, return. @@ -701,8 +668,8 @@ inline ssize_t Http2Session::OnDWordAlignedPadding(size_t frameLen, // Used as one of the Padding Strategy functions. Uses the maximum amount // of padding allowed for the current frame. -inline ssize_t Http2Session::OnMaxFrameSizePadding(size_t frameLen, - size_t maxPayloadLen) { +ssize_t Http2Session::OnMaxFrameSizePadding(size_t frameLen, + size_t maxPayloadLen) { DEBUG_HTTP2SESSION2(this, "using max frame size padding: %d", maxPayloadLen); return maxPayloadLen; } @@ -711,8 +678,8 @@ inline ssize_t Http2Session::OnMaxFrameSizePadding(size_t frameLen, // to determine the amount of padding for the current frame. This option is // rather more expensive because of the JS boundary cross. It generally should // not be the preferred option. -inline ssize_t Http2Session::OnCallbackPadding(size_t frameLen, - size_t maxPayloadLen) { +ssize_t Http2Session::OnCallbackPadding(size_t frameLen, + size_t maxPayloadLen) { if (frameLen == 0) return 0; DEBUG_HTTP2SESSION(this, "using callback to determine padding"); Isolate* isolate = env()->isolate(); @@ -720,10 +687,6 @@ inline ssize_t Http2Session::OnCallbackPadding(size_t frameLen, Local context = env()->context(); Context::Scope context_scope(context); -#if defined(DEBUG) && DEBUG - CHECK(object()->Has(context, env()->ongetpadding_string()).FromJust()); -#endif - AliasedBuffer& buffer = env()->http2_state()->padding_buffer; buffer[PADDING_BUF_FRAME_LENGTH] = frameLen; @@ -743,7 +706,7 @@ inline ssize_t Http2Session::OnCallbackPadding(size_t frameLen, // various callback functions. Each of these will typically result in a call // out to JavaScript so this particular function is rather hot and can be // quite expensive. This is a potential performance optimization target later. -inline ssize_t Http2Session::Write(const uv_buf_t* bufs, size_t nbufs) { +ssize_t Http2Session::Write(const uv_buf_t* bufs, size_t nbufs) { size_t total = 0; // Note that nghttp2_session_mem_recv is a synchronous operation that // will trigger a number of other callbacks. Those will, in turn have @@ -783,27 +746,23 @@ inline int32_t GetFrameID(const nghttp2_frame* frame) { // callback to determine if a new stream is being created or if we are simply // adding a new block of headers to an existing stream. The header pairs // themselves are set in the OnHeaderCallback -inline int Http2Session::OnBeginHeadersCallback(nghttp2_session* handle, - const nghttp2_frame* frame, - void* user_data) { +int Http2Session::OnBeginHeadersCallback(nghttp2_session* handle, + const nghttp2_frame* frame, + void* user_data) { Http2Session* session = static_cast(user_data); int32_t id = GetFrameID(frame); DEBUG_HTTP2SESSION2(session, "beginning headers for stream %d", id); Http2Stream* stream = session->FindStream(id); if (stream == nullptr) { - if (session->CanAddStream()) { - new Http2Stream(session, id, frame->headers.cat); - } else { + if (!session->CanAddStream()) { // Too many concurrent streams being opened nghttp2_submit_rst_stream(**session, NGHTTP2_FLAG_NONE, id, NGHTTP2_ENHANCE_YOUR_CALM); return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; } - } else { - // If the stream has already been destroyed, ignore. - if (stream->IsDestroyed()) - return 0; + new Http2Stream(session, id, frame->headers.cat); + } else if (!stream->IsDestroyed()) { stream->StartHeaders(frame->headers.cat); } return 0; @@ -812,20 +771,18 @@ inline int Http2Session::OnBeginHeadersCallback(nghttp2_session* handle, // Called by nghttp2 for each header name/value pair in a HEADERS block. // This had to have been preceded by a call to OnBeginHeadersCallback so // the Http2Stream is guaranteed to already exist. -inline int Http2Session::OnHeaderCallback(nghttp2_session* handle, - const nghttp2_frame* frame, - nghttp2_rcbuf* name, - nghttp2_rcbuf* value, - uint8_t flags, - void* user_data) { +int Http2Session::OnHeaderCallback(nghttp2_session* handle, + const nghttp2_frame* frame, + nghttp2_rcbuf* name, + nghttp2_rcbuf* value, + uint8_t flags, + void* user_data) { Http2Session* session = static_cast(user_data); int32_t id = GetFrameID(frame); Http2Stream* stream = session->FindStream(id); CHECK_NE(stream, nullptr); // If the stream has already been destroyed, ignore. - if (stream->IsDestroyed()) - return 0; - if (!stream->AddHeader(name, value, flags)) { + if (!stream->IsDestroyed() && !stream->AddHeader(name, value, flags)) { // This will only happen if the connected peer sends us more // than the allowed number of header items at any given time stream->SubmitRstStream(NGHTTP2_ENHANCE_YOUR_CALM); @@ -837,9 +794,9 @@ inline int Http2Session::OnHeaderCallback(nghttp2_session* handle, // Called by nghttp2 when a complete HTTP2 frame has been received. There are // only a handful of frame types tha we care about handling here. -inline int Http2Session::OnFrameReceive(nghttp2_session* handle, - const nghttp2_frame* frame, - void* user_data) { +int Http2Session::OnFrameReceive(nghttp2_session* handle, + const nghttp2_frame* frame, + void* user_data) { Http2Session* session = static_cast(user_data); session->statistics_.frame_count++; DEBUG_HTTP2SESSION2(session, "complete frame received: type: %d", @@ -874,10 +831,10 @@ inline int Http2Session::OnFrameReceive(nghttp2_session* handle, return 0; } -inline int Http2Session::OnInvalidFrame(nghttp2_session* handle, - const nghttp2_frame *frame, - int lib_error_code, - void* user_data) { +int Http2Session::OnInvalidFrame(nghttp2_session* handle, + const nghttp2_frame *frame, + int lib_error_code, + void* user_data) { Http2Session* session = static_cast(user_data); DEBUG_HTTP2SESSION2(session, "invalid frame received, code: %d", @@ -891,11 +848,8 @@ inline int Http2Session::OnInvalidFrame(nghttp2_session* handle, HandleScope scope(isolate); Local context = env->context(); Context::Scope context_scope(context); - - Local argv[1] = { - Integer::New(isolate, lib_error_code), - }; - session->MakeCallback(env->error_string(), arraysize(argv), argv); + Local arg = Integer::New(isolate, lib_error_code); + session->MakeCallback(env->error_string(), 1, &arg); } return 0; } @@ -906,10 +860,10 @@ inline int Http2Session::OnInvalidFrame(nghttp2_session* handle, // really care about those and there's nothing we can reasonably do about it // anyway. Other types of failures are reported up to JavaScript. This should // be exceedingly rare. -inline int Http2Session::OnFrameNotSent(nghttp2_session* handle, - const nghttp2_frame* frame, - int error_code, - void* user_data) { +int Http2Session::OnFrameNotSent(nghttp2_session* handle, + const nghttp2_frame* frame, + int error_code, + void* user_data) { Http2Session* session = static_cast(user_data); Environment* env = session->env(); DEBUG_HTTP2SESSION2(session, "frame type %d was not sent, code: %d", @@ -933,19 +887,19 @@ inline int Http2Session::OnFrameNotSent(nghttp2_session* handle, return 0; } -inline int Http2Session::OnFrameSent(nghttp2_session* handle, - const nghttp2_frame* frame, - void* user_data) { +int Http2Session::OnFrameSent(nghttp2_session* handle, + const nghttp2_frame* frame, + void* user_data) { Http2Session* session = static_cast(user_data); session->statistics_.frame_sent += 1; return 0; } // Called by nghttp2 when a stream closes. -inline int Http2Session::OnStreamClose(nghttp2_session* handle, - int32_t id, - uint32_t code, - void* user_data) { +int Http2Session::OnStreamClose(nghttp2_session* handle, + int32_t id, + uint32_t code, + void* user_data) { Http2Session* session = static_cast(user_data); Environment* env = session->env(); Isolate* isolate = env->isolate(); @@ -982,12 +936,12 @@ inline int Http2Session::OnStreamClose(nghttp2_session* handle, // ignore these. If this callback was not provided, nghttp2 would handle // invalid headers strictly and would shut down the stream. We are intentionally // being more lenient here although we may want to revisit this choice later. -inline int Http2Session::OnInvalidHeader(nghttp2_session* session, - const nghttp2_frame* frame, - nghttp2_rcbuf* name, - nghttp2_rcbuf* value, - uint8_t flags, - void* user_data) { +int Http2Session::OnInvalidHeader(nghttp2_session* session, + const nghttp2_frame* frame, + nghttp2_rcbuf* name, + nghttp2_rcbuf* value, + uint8_t flags, + void* user_data) { // Ignore invalid header fields by default. return 0; } @@ -996,12 +950,12 @@ inline int Http2Session::OnInvalidHeader(nghttp2_session* session, // us in discrete chunks. We push these into a linked list stored in the // Http2Sttream which is flushed out to JavaScript as quickly as possible. // This can be a particularly hot path. -inline int Http2Session::OnDataChunkReceived(nghttp2_session* handle, - uint8_t flags, - int32_t id, - const uint8_t* data, - size_t len, - void* user_data) { +int Http2Session::OnDataChunkReceived(nghttp2_session* handle, + uint8_t flags, + int32_t id, + const uint8_t* data, + size_t len, + void* user_data) { Http2Session* session = static_cast(user_data); DEBUG_HTTP2SESSION2(session, "buffering data chunk for stream %d, size: " "%d, flags: %d", id, len, flags); @@ -1059,10 +1013,10 @@ inline int Http2Session::OnDataChunkReceived(nghttp2_session* handle, // Called by nghttp2 when it needs to determine how much padding to use in // a DATA or HEADERS frame. -inline ssize_t Http2Session::OnSelectPadding(nghttp2_session* handle, - const nghttp2_frame* frame, - size_t maxPayloadLen, - void* user_data) { +ssize_t Http2Session::OnSelectPadding(nghttp2_session* handle, + const nghttp2_frame* frame, + size_t maxPayloadLen, + void* user_data) { Http2Session* session = static_cast(user_data); ssize_t padding = frame->hd.length; @@ -1089,10 +1043,10 @@ inline ssize_t Http2Session::OnSelectPadding(nghttp2_session* handle, // We use this currently to determine when an attempt is made to use the http2 // protocol with a non-http2 peer. -inline int Http2Session::OnNghttpError(nghttp2_session* handle, - const char* message, - size_t len, - void* user_data) { +int Http2Session::OnNghttpError(nghttp2_session* handle, + const char* message, + size_t len, + void* user_data) { // Unfortunately, this is currently the only way for us to know if // the session errored because the peer is not an http2 peer. Http2Session* session = static_cast(user_data); @@ -1103,11 +1057,8 @@ inline int Http2Session::OnNghttpError(nghttp2_session* handle, HandleScope scope(isolate); Local context = env->context(); Context::Scope context_scope(context); - - Local argv[1] = { - Integer::New(isolate, NGHTTP2_ERR_PROTO), - }; - session->MakeCallback(env->error_string(), arraysize(argv), argv); + Local arg = Integer::New(isolate, NGHTTP2_ERR_PROTO); + session->MakeCallback(env->error_string(), 1, &arg); } return 0; } @@ -1115,7 +1066,7 @@ inline int Http2Session::OnNghttpError(nghttp2_session* handle, // Once all of the DATA frames for a Stream have been sent, the GetTrailers // method calls out to JavaScript to fetch the trailing headers that need // to be sent. -inline void Http2Session::GetTrailers(Http2Stream* stream, uint32_t* flags) { +void Http2Session::GetTrailers(Http2Stream* stream, uint32_t* flags) { if (!stream->IsDestroyed() && stream->HasTrailers()) { Http2Stream::SubmitTrailers submit_trailers{this, stream, flags}; stream->OnTrailers(submit_trailers); @@ -1162,8 +1113,8 @@ Http2Stream::SubmitTrailers::SubmitTrailers( : session_(session), stream_(stream), flags_(flags) { } -inline void Http2Stream::SubmitTrailers::Submit(nghttp2_nv* trailers, - size_t length) const { +void Http2Stream::SubmitTrailers::Submit(nghttp2_nv* trailers, + size_t length) const { Http2Scope h2scope(session_); if (length == 0) return; @@ -1178,7 +1129,7 @@ inline void Http2Stream::SubmitTrailers::Submit(nghttp2_nv* trailers, // Called by OnFrameReceived to notify JavaScript land that a complete // HEADERS frame has been received and processed. This method converts the // received headers into a JavaScript array and pushes those out to JS. -inline void Http2Session::HandleHeadersFrame(const nghttp2_frame* frame) { +void Http2Session::HandleHeadersFrame(const nghttp2_frame* frame) { Isolate* isolate = env()->isolate(); HandleScope scope(isolate); Local context = env()->context(); @@ -1247,7 +1198,7 @@ inline void Http2Session::HandleHeadersFrame(const nghttp2_frame* frame) { // received. Notifies JS land about the priority change. Note that priorities // are considered advisory only, so this has no real effect other than to // simply let user code know that the priority has changed. -inline void Http2Session::HandlePriorityFrame(const nghttp2_frame* frame) { +void Http2Session::HandlePriorityFrame(const nghttp2_frame* frame) { Isolate* isolate = env()->isolate(); HandleScope scope(isolate); Local context = env()->context(); @@ -1272,23 +1223,18 @@ inline void Http2Session::HandlePriorityFrame(const nghttp2_frame* frame) { // Called by OnFrameReceived when a complete DATA frame has been received. // If we know that this was the last DATA frame (because the END_STREAM flag // is set), then we'll terminate the readable side of the StreamBase. -inline void Http2Session::HandleDataFrame(const nghttp2_frame* frame) { +void Http2Session::HandleDataFrame(const nghttp2_frame* frame) { int32_t id = GetFrameID(frame); DEBUG_HTTP2SESSION2(this, "handling data frame for stream %d", id); Http2Stream* stream = FindStream(id); - // If the stream has already been destroyed, do nothing - if (stream->IsDestroyed()) - return; - - if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) { + if (!stream->IsDestroyed() && frame->hd.flags & NGHTTP2_FLAG_END_STREAM) stream->EmitRead(UV_EOF); - } } // Called by OnFrameReceived when a complete GOAWAY frame has been received. -inline void Http2Session::HandleGoawayFrame(const nghttp2_frame* frame) { +void Http2Session::HandleGoawayFrame(const nghttp2_frame* frame) { Isolate* isolate = env()->isolate(); HandleScope scope(isolate); Local context = env()->context(); @@ -1314,7 +1260,7 @@ inline void Http2Session::HandleGoawayFrame(const nghttp2_frame* frame) { } // Called by OnFrameReceived when a complete ALTSVC frame has been received. -inline void Http2Session::HandleAltSvcFrame(const nghttp2_frame* frame) { +void Http2Session::HandleAltSvcFrame(const nghttp2_frame* frame) { Isolate* isolate = env()->isolate(); HandleScope scope(isolate); Local context = env()->context(); @@ -1342,7 +1288,7 @@ inline void Http2Session::HandleAltSvcFrame(const nghttp2_frame* frame) { } // Called by OnFrameReceived when a complete PING frame has been received. -inline void Http2Session::HandlePingFrame(const nghttp2_frame* frame) { +void Http2Session::HandlePingFrame(const nghttp2_frame* frame) { bool ack = frame->hd.flags & NGHTTP2_FLAG_ACK; if (ack) { Http2Ping* ping = PopPing(); @@ -1358,17 +1304,14 @@ inline void Http2Session::HandlePingFrame(const nghttp2_frame* frame) { HandleScope scope(isolate); Local context = env()->context(); Context::Scope context_scope(context); - - Local argv[1] = { - Integer::New(isolate, NGHTTP2_ERR_PROTO), - }; - MakeCallback(env()->error_string(), arraysize(argv), argv); + Local arg = Integer::New(isolate, NGHTTP2_ERR_PROTO); + MakeCallback(env()->error_string(), 1, &arg); } } } // Called by OnFrameReceived when a complete SETTINGS frame has been received. -inline void Http2Session::HandleSettingsFrame(const nghttp2_frame* frame) { +void Http2Session::HandleSettingsFrame(const nghttp2_frame* frame) { bool ack = frame->hd.flags & NGHTTP2_FLAG_ACK; if (ack) { // If this is an acknowledgement, we should have an Http2Settings @@ -1390,11 +1333,8 @@ inline void Http2Session::HandleSettingsFrame(const nghttp2_frame* frame) { HandleScope scope(isolate); Local context = env()->context(); Context::Scope context_scope(context); - - Local argv[1] = { - Integer::New(isolate, NGHTTP2_ERR_PROTO), - }; - MakeCallback(env()->error_string(), arraysize(argv), argv); + Local arg = Integer::New(isolate, NGHTTP2_ERR_PROTO); + MakeCallback(env()->error_string(), 1, &arg); } } else { // Otherwise, notify the session about a new settings @@ -1613,7 +1553,7 @@ int Http2Session::OnSendData( } // Creates a new Http2Stream and submits a new http2 request. -inline Http2Stream* Http2Session::SubmitRequest( +Http2Stream* Http2Session::SubmitRequest( nghttp2_priority_spec* prispec, nghttp2_nv* nva, size_t len, @@ -1630,10 +1570,6 @@ inline Http2Stream* Http2Session::SubmitRequest( return stream; } -inline void Http2Session::SetChunksSinceLastWrite(size_t n) { - chunks_sent_since_last_write_ = n; -} - // Callback used to receive inbound data from the i/o stream void Http2Session::OnStreamRead(ssize_t nread, const uv_buf_t& buf) { Http2Scope h2scope(this); @@ -1806,7 +1742,7 @@ void Http2Stream::OnTrailers(const SubmitTrailers& submit_trailers) { } } -inline void Http2Stream::Close(int32_t code) { +void Http2Stream::Close(int32_t code) { CHECK(!this->IsDestroyed()); flags_ |= NGHTTP2_STREAM_FLAG_CLOSED; code_ = code; @@ -1818,7 +1754,7 @@ int Http2Stream::DoShutdown(ShutdownWrap* req_wrap) { { Http2Scope h2scope(this); flags_ |= NGHTTP2_STREAM_FLAG_SHUT; - CHECK_NE(nghttp2_session_resume_data(session_->session(), id_), + CHECK_NE(nghttp2_session_resume_data(**session_, id_), NGHTTP2_ERR_NOMEM); DEBUG_HTTP2STREAM(this, "writable side shutdown"); } @@ -1829,7 +1765,7 @@ int Http2Stream::DoShutdown(ShutdownWrap* req_wrap) { // Destroy the Http2Stream and render it unusable. Actual resources for the // Stream will not be freed until the next tick of the Node.js event loop // using the SetImmediate queue. -inline void Http2Stream::Destroy() { +void Http2Stream::Destroy() { // Do nothing if this stream instance is already destroyed if (IsDestroyed()) return; @@ -1868,9 +1804,7 @@ inline void Http2Stream::Destroy() { // Initiates a response on the Http2Stream using data provided via the // StreamBase Streams API. -inline int Http2Stream::SubmitResponse(nghttp2_nv* nva, - size_t len, - int options) { +int Http2Stream::SubmitResponse(nghttp2_nv* nva, size_t len, int options) { CHECK(!this->IsDestroyed()); Http2Scope h2scope(this); DEBUG_HTTP2STREAM(this, "submitting response"); @@ -1881,7 +1815,7 @@ inline int Http2Stream::SubmitResponse(nghttp2_nv* nva, options |= STREAM_OPTION_EMPTY_PAYLOAD; Http2Stream::Provider::Stream prov(this, options); - int ret = nghttp2_submit_response(session_->session(), id_, nva, len, *prov); + int ret = nghttp2_submit_response(**session_, id_, nva, len, *prov); CHECK_NE(ret, NGHTTP2_ERR_NOMEM); return ret; } @@ -1910,11 +1844,11 @@ inline int Http2Stream::SubmitFile(int fd, // Submit informational headers for a stream. -inline int Http2Stream::SubmitInfo(nghttp2_nv* nva, size_t len) { +int Http2Stream::SubmitInfo(nghttp2_nv* nva, size_t len) { CHECK(!this->IsDestroyed()); Http2Scope h2scope(this); DEBUG_HTTP2STREAM2(this, "sending %d informational headers", len); - int ret = nghttp2_submit_headers(session_->session(), + int ret = nghttp2_submit_headers(**session_, NGHTTP2_FLAG_NONE, id_, nullptr, nva, len, nullptr); @@ -1923,15 +1857,15 @@ inline int Http2Stream::SubmitInfo(nghttp2_nv* nva, size_t len) { } // Submit a PRIORITY frame to the connected peer. -inline int Http2Stream::SubmitPriority(nghttp2_priority_spec* prispec, - bool silent) { +int Http2Stream::SubmitPriority(nghttp2_priority_spec* prispec, + bool silent) { CHECK(!this->IsDestroyed()); Http2Scope h2scope(this); DEBUG_HTTP2STREAM(this, "sending priority spec"); int ret = silent ? - nghttp2_session_change_stream_priority(session_->session(), + nghttp2_session_change_stream_priority(**session_, id_, prispec) : - nghttp2_submit_priority(session_->session(), + nghttp2_submit_priority(**session_, NGHTTP2_FLAG_NONE, id_, prispec); CHECK_NE(ret, NGHTTP2_ERR_NOMEM); @@ -1940,7 +1874,7 @@ inline int Http2Stream::SubmitPriority(nghttp2_priority_spec* prispec, // Closes the Http2Stream by submitting an RST_STREAM frame to the connected // peer. -inline void Http2Stream::SubmitRstStream(const uint32_t code) { +void Http2Stream::SubmitRstStream(const uint32_t code) { CHECK(!this->IsDestroyed()); Http2Scope h2scope(this); // Force a purge of any currently pending data here to make sure @@ -1952,10 +1886,10 @@ inline void Http2Stream::SubmitRstStream(const uint32_t code) { // Submit a push promise and create the associated Http2Stream if successful. -inline Http2Stream* Http2Stream::SubmitPushPromise(nghttp2_nv* nva, - size_t len, - int32_t* ret, - int options) { +Http2Stream* Http2Stream::SubmitPushPromise(nghttp2_nv* nva, + size_t len, + int32_t* ret, + int options) { CHECK(!this->IsDestroyed()); Http2Scope h2scope(this); DEBUG_HTTP2STREAM(this, "sending push promise"); @@ -1971,7 +1905,7 @@ inline Http2Stream* Http2Stream::SubmitPushPromise(nghttp2_nv* nva, // Switch the StreamBase into flowing mode to begin pushing chunks of data // out to JS land. -inline int Http2Stream::ReadStart() { +int Http2Stream::ReadStart() { Http2Scope h2scope(this); CHECK(!this->IsDestroyed()); flags_ |= NGHTTP2_STREAM_FLAG_READ_START; @@ -1981,7 +1915,7 @@ inline int Http2Stream::ReadStart() { // Tell nghttp2 about our consumption of the data that was handed // off to JS land. - nghttp2_session_consume_stream(session_->session(), + nghttp2_session_consume_stream(**session_, id_, inbound_consumed_data_while_paused_); inbound_consumed_data_while_paused_ = 0; @@ -1990,7 +1924,7 @@ inline int Http2Stream::ReadStart() { } // Switch the StreamBase into paused mode. -inline int Http2Stream::ReadStop() { +int Http2Stream::ReadStop() { CHECK(!this->IsDestroyed()); if (!IsReading()) return 0; @@ -2009,14 +1943,13 @@ inline int Http2Stream::ReadStop() { // chunks of data have been flushed to the underlying nghttp2_session. // Note that this does *not* mean that the data has been flushed // to the socket yet. -inline int Http2Stream::DoWrite(WriteWrap* req_wrap, - uv_buf_t* bufs, - size_t nbufs, - uv_stream_t* send_handle) { +int Http2Stream::DoWrite(WriteWrap* req_wrap, + uv_buf_t* bufs, + size_t nbufs, + uv_stream_t* send_handle) { CHECK(!this->IsDestroyed()); CHECK_EQ(send_handle, nullptr); Http2Scope h2scope(this); - session_->SetChunksSinceLastWrite(); if (!IsWritable()) { req_wrap->Done(UV_EOF); return 0; @@ -2035,22 +1968,19 @@ inline int Http2Stream::DoWrite(WriteWrap* req_wrap, return 0; } -inline size_t GetBufferLength(nghttp2_rcbuf* buf) { - return nghttp2_rcbuf_get_buf(buf).len; -} - // Ads a header to the Http2Stream. Note that the header name and value are // provided using a buffer structure provided by nghttp2 that allows us to // avoid unnecessary memcpy's. Those buffers are ref counted. The ref count // is incremented here and are decremented when the header name and values // are garbage collected later. -inline bool Http2Stream::AddHeader(nghttp2_rcbuf* name, - nghttp2_rcbuf* value, - uint8_t flags) { +bool Http2Stream::AddHeader(nghttp2_rcbuf* name, + nghttp2_rcbuf* value, + uint8_t flags) { CHECK(!this->IsDestroyed()); if (this->statistics_.first_header == 0) this->statistics_.first_header = uv_hrtime(); - size_t length = GetBufferLength(name) + GetBufferLength(value) + 32; + size_t length = nghttp2_rcbuf_get_buf(name).len + + nghttp2_rcbuf_get_buf(value).len + 32; // A header can only be added if we have not exceeded the maximum number // of headers and the session has memory available for it. if (!session_->IsAvailableSessionMemory(length) || @@ -2519,8 +2449,6 @@ void Http2Stream::RespondFD(const FunctionCallbackInfo& args) { int64_t length = args[3]->IntegerValue(context).ToChecked(); int options = args[4]->IntegerValue(context).ToChecked(); - stream->session()->SetChunksSinceLastWrite(); - Headers list(isolate, context, headers); args.GetReturnValue().Set(stream->SubmitFile(fd, *list, list.length(), offset, length, options)); diff --git a/src/node_http2.h b/src/node_http2.h index 8f6662a0160bec..780bdc8c6e1919 100644 --- a/src/node_http2.h +++ b/src/node_http2.h @@ -558,7 +558,7 @@ class Http2Stream : public AsyncWrap, Http2Session* session() { return session_; } - inline void EmitStatistics(); + void EmitStatistics(); // Process a Data Chunk void OnDataChunk(uv_buf_t* chunk); @@ -574,9 +574,7 @@ class Http2Stream : public AsyncWrap, int DoShutdown(ShutdownWrap* req_wrap) override; // Initiate a response on this stream. - inline int SubmitResponse(nghttp2_nv* nva, - size_t len, - int options); + int SubmitResponse(nghttp2_nv* nva, size_t len, int options); // Send data read from a file descriptor as the response on this stream. inline int SubmitFile(int fd, @@ -586,27 +584,26 @@ class Http2Stream : public AsyncWrap, int options); // Submit informational headers for this stream - inline int SubmitInfo(nghttp2_nv* nva, size_t len); + int SubmitInfo(nghttp2_nv* nva, size_t len); // Submit a PRIORITY frame for this stream - inline int SubmitPriority(nghttp2_priority_spec* prispec, - bool silent = false); + int SubmitPriority(nghttp2_priority_spec* prispec, bool silent = false); // Submits an RST_STREAM frame using the given code - inline void SubmitRstStream(const uint32_t code); + void SubmitRstStream(const uint32_t code); // Submits a PUSH_PROMISE frame with this stream as the parent. - inline Http2Stream* SubmitPushPromise( + Http2Stream* SubmitPushPromise( nghttp2_nv* nva, size_t len, int32_t* ret, int options = 0); - inline void Close(int32_t code); + void Close(int32_t code); // Destroy this stream instance and free all held memory. - inline void Destroy(); + void Destroy(); inline bool IsDestroyed() const { return flags_ & NGHTTP2_STREAM_FLAG_DESTROYED; @@ -645,9 +642,7 @@ class Http2Stream : public AsyncWrap, inline void IncrementAvailableOutboundLength(size_t amount); inline void DecrementAvailableOutboundLength(size_t amount); - inline bool AddHeader(nghttp2_rcbuf* name, - nghttp2_rcbuf* value, - uint8_t flags); + bool AddHeader(nghttp2_rcbuf* name, nghttp2_rcbuf* value, uint8_t flags); inline nghttp2_header* headers() { return current_headers_.data(); @@ -683,11 +678,11 @@ class Http2Stream : public AsyncWrap, // Handling Trailer Headers class SubmitTrailers { public: - inline void Submit(nghttp2_nv* trailers, size_t length) const; + void Submit(nghttp2_nv* trailers, size_t length) const; - inline SubmitTrailers(Http2Session* sesion, - Http2Stream* stream, - uint32_t* flags); + SubmitTrailers(Http2Session* sesion, + Http2Stream* stream, + uint32_t* flags); private: Http2Session* const session_; @@ -817,7 +812,7 @@ class Http2Session : public AsyncWrap, public StreamListener { class Http2Ping; class Http2Settings; - inline void EmitStatistics(); + void EmitStatistics(); inline StreamBase* underlying_stream() { return static_cast(stream_); @@ -838,25 +833,25 @@ class Http2Session : public AsyncWrap, public StreamListener { bool Ping(v8::Local function); - inline void SendPendingData(); + void SendPendingData(); // Submits a new request. If the request is a success, assigned // will be a pointer to the Http2Stream instance assigned. // This only works if the session is a client session. - inline Http2Stream* SubmitRequest( + Http2Stream* SubmitRequest( nghttp2_priority_spec* prispec, nghttp2_nv* nva, size_t len, int32_t* ret, int options = 0); - nghttp2_session_type type() const { return session_type_; } + inline nghttp2_session_type type() const { return session_type_; } inline nghttp2_session* session() const { return session_; } - nghttp2_session* operator*() { return session_; } + inline nghttp2_session* operator*() { return session_; } - uint32_t GetMaxHeaderPairs() const { return max_header_pairs_; } + inline uint32_t GetMaxHeaderPairs() const { return max_header_pairs_; } inline const char* TypeName(); @@ -882,13 +877,11 @@ class Http2Session : public AsyncWrap, public StreamListener { bool HasWritesOnSocketForStream(Http2Stream* stream); // Write data to the session - inline ssize_t Write(const uv_buf_t* bufs, size_t nbufs); - - inline void SetChunksSinceLastWrite(size_t n = 0); + ssize_t Write(const uv_buf_t* bufs, size_t nbufs); size_t self_size() const override { return sizeof(*this); } - inline void GetTrailers(Http2Stream* stream, uint32_t* flags); + void GetTrailers(Http2Stream* stream, uint32_t* flags); // Handle reads/writes from the underlying network transport. void OnStreamRead(ssize_t nread, const uv_buf_t& buf) override; @@ -966,84 +959,84 @@ class Http2Session : public AsyncWrap, public StreamListener { private: // Frame Padding Strategies - inline ssize_t OnDWordAlignedPadding(size_t frameLength, - size_t maxPayloadLen); - inline ssize_t OnMaxFrameSizePadding(size_t frameLength, - size_t maxPayloadLen); - inline ssize_t OnCallbackPadding(size_t frame, - size_t maxPayloadLen); + ssize_t OnDWordAlignedPadding(size_t frameLength, + size_t maxPayloadLen); + ssize_t OnMaxFrameSizePadding(size_t frameLength, + size_t maxPayloadLen); + ssize_t OnCallbackPadding(size_t frameLength, + size_t maxPayloadLen); // Frame Handler - inline void HandleDataFrame(const nghttp2_frame* frame); - inline void HandleGoawayFrame(const nghttp2_frame* frame); - inline void HandleHeadersFrame(const nghttp2_frame* frame); - inline void HandlePriorityFrame(const nghttp2_frame* frame); - inline void HandleSettingsFrame(const nghttp2_frame* frame); - inline void HandlePingFrame(const nghttp2_frame* frame); - inline void HandleAltSvcFrame(const nghttp2_frame* frame); + void HandleDataFrame(const nghttp2_frame* frame); + void HandleGoawayFrame(const nghttp2_frame* frame); + void HandleHeadersFrame(const nghttp2_frame* frame); + void HandlePriorityFrame(const nghttp2_frame* frame); + void HandleSettingsFrame(const nghttp2_frame* frame); + void HandlePingFrame(const nghttp2_frame* frame); + void HandleAltSvcFrame(const nghttp2_frame* frame); // nghttp2 callbacks - static inline int OnBeginHeadersCallback( + static int OnBeginHeadersCallback( nghttp2_session* session, const nghttp2_frame* frame, void* user_data); - static inline int OnHeaderCallback( + static int OnHeaderCallback( nghttp2_session* session, const nghttp2_frame* frame, nghttp2_rcbuf* name, nghttp2_rcbuf* value, uint8_t flags, void* user_data); - static inline int OnFrameReceive( + static int OnFrameReceive( nghttp2_session* session, const nghttp2_frame* frame, void* user_data); - static inline int OnFrameNotSent( + static int OnFrameNotSent( nghttp2_session* session, const nghttp2_frame* frame, int error_code, void* user_data); - static inline int OnFrameSent( + static int OnFrameSent( nghttp2_session* session, const nghttp2_frame* frame, void* user_data); - static inline int OnStreamClose( + static int OnStreamClose( nghttp2_session* session, int32_t id, uint32_t code, void* user_data); - static inline int OnInvalidHeader( + static int OnInvalidHeader( nghttp2_session* session, const nghttp2_frame* frame, nghttp2_rcbuf* name, nghttp2_rcbuf* value, uint8_t flags, void* user_data); - static inline int OnDataChunkReceived( + static int OnDataChunkReceived( nghttp2_session* session, uint8_t flags, int32_t id, const uint8_t* data, size_t len, void* user_data); - static inline ssize_t OnSelectPadding( + static ssize_t OnSelectPadding( nghttp2_session* session, const nghttp2_frame* frame, size_t maxPayloadLen, void* user_data); - static inline int OnNghttpError( + static int OnNghttpError( nghttp2_session* session, const char* message, size_t len, void* user_data); - static inline int OnSendData( + static int OnSendData( nghttp2_session* session, nghttp2_frame* frame, const uint8_t* framehd, size_t length, nghttp2_data_source* source, void* user_data); - static inline int OnInvalidFrame( + static int OnInvalidFrame( nghttp2_session* session, const nghttp2_frame *frame, int lib_error_code, @@ -1214,29 +1207,23 @@ class Http2Session::Http2Settings : public AsyncWrap { void Send(); void Done(bool ack); - size_t length() const { return count_; } - - nghttp2_settings_entry* operator*() { - return *entries_; - } - // Returns a Buffer instance with the serialized SETTINGS payload - inline Local Pack(); + Local Pack(); // Resets the default values in the settings buffer - static inline void RefreshDefaults(Environment* env); + static void RefreshDefaults(Environment* env); // Update the local or remote settings for the given session - static inline void Update(Environment* env, - Http2Session* session, - get_setting fn); + static void Update(Environment* env, + Http2Session* session, + get_setting fn); private: void Init(); Http2Session* session_; uint64_t startTime_; size_t count_ = 0; - MaybeStackBuffer entries_; + nghttp2_settings_entry entries_[IDX_SETTINGS_COUNT]; }; class ExternalHeader : diff --git a/src/node_main.cc b/src/node_main.cc index 7ab612d53e500a..8907c47ae0ea4c 100644 --- a/src/node_main.cc +++ b/src/node_main.cc @@ -82,12 +82,30 @@ int wmain(int argc, wchar_t *wargv[]) { #endif // __LP64__ extern char** environ; #endif // __linux__ +#if defined(__POSIX__) && defined(NODE_SHARED_MODE) +#include +#include +#endif namespace node { extern bool linux_at_secure; } // namespace node int main(int argc, char *argv[]) { +#if defined(__POSIX__) && defined(NODE_SHARED_MODE) + // In node::PlatformInit(), we squash all signal handlers for non-shared lib + // build. In order to run test cases against shared lib build, we also need + // to do the same thing for shared lib build here, but only for SIGPIPE for + // now. If node::PlatformInit() is moved to here, then this section could be + // removed. + { + struct sigaction act; + memset(&act, 0, sizeof(act)); + act.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &act, nullptr); + } +#endif + #if defined(__linux__) char** envp = environ; while (*envp++ != nullptr) {} diff --git a/src/node_util.cc b/src/node_util.cc index 864cb0f0e0b1b0..852902d7cc8132 100644 --- a/src/node_util.cc +++ b/src/node_util.cc @@ -37,7 +37,6 @@ using v8::Value; #define V(_, ucname) \ static void ucname(const FunctionCallbackInfo& args) { \ - CHECK_EQ(1, args.Length()); \ args.GetReturnValue().Set(args[0]->ucname()); \ } @@ -45,7 +44,6 @@ using v8::Value; #undef V static void IsAnyArrayBuffer(const FunctionCallbackInfo& args) { - CHECK_EQ(1, args.Length()); args.GetReturnValue().Set( args[0]->IsArrayBuffer() || args[0]->IsSharedArrayBuffer()); } diff --git a/src/node_version.h b/src/node_version.h index 804fb451aed60b..6a33849680b1da 100644 --- a/src/node_version.h +++ b/src/node_version.h @@ -23,13 +23,13 @@ #define SRC_NODE_VERSION_H_ #define NODE_MAJOR_VERSION 9 -#define NODE_MINOR_VERSION 8 -#define NODE_PATCH_VERSION 1 +#define NODE_MINOR_VERSION 9 +#define NODE_PATCH_VERSION 0 #define NODE_VERSION_IS_LTS 0 #define NODE_VERSION_LTS_CODENAME "" -#define NODE_VERSION_IS_RELEASE 0 +#define NODE_VERSION_IS_RELEASE 1 #ifndef NODE_STRINGIFY #define NODE_STRINGIFY(n) NODE_STRINGIFY_HELPER(n) diff --git a/src/pipe_wrap.cc b/src/pipe_wrap.cc index 016ce480b6a809..14ac671b92b5bb 100644 --- a/src/pipe_wrap.cc +++ b/src/pipe_wrap.cc @@ -54,8 +54,7 @@ Local PipeWrap::Instantiate(Environment* env, AsyncWrap* parent, PipeWrap::SocketType type) { EscapableHandleScope handle_scope(env->isolate()); - AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(env, - parent->get_async_id()); + AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(parent); CHECK_EQ(false, env->pipe_constructor_template().IsEmpty()); Local constructor = env->pipe_constructor_template()->GetFunction(); CHECK_EQ(false, constructor.IsEmpty()); diff --git a/src/spawn_sync.cc b/src/spawn_sync.cc index 2a524153a29d13..525aa4df2bcf74 100644 --- a/src/spawn_sync.cc +++ b/src/spawn_sync.cc @@ -25,7 +25,6 @@ #include "util.h" #include -#include namespace node { diff --git a/src/stream_base-inl.h b/src/stream_base-inl.h index 81adf7a866b927..1534dcd1d53359 100644 --- a/src/stream_base-inl.h +++ b/src/stream_base-inl.h @@ -164,8 +164,7 @@ inline int StreamBase::Shutdown(v8::Local req_wrap_obj) { ->NewInstance(env->context()).ToLocalChecked(); } - AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope( - env, GetAsyncWrap()->get_async_id()); + AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(GetAsyncWrap()); ShutdownWrap* req_wrap = CreateShutdownWrap(req_wrap_obj); int err = DoShutdown(req_wrap); @@ -202,8 +201,7 @@ inline StreamWriteResult StreamBase::Write( ->NewInstance(env->context()).ToLocalChecked(); } - AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope( - env, GetAsyncWrap()->get_async_id()); + AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(GetAsyncWrap()); WriteWrap* req_wrap = CreateWriteWrap(req_wrap_obj); err = DoWrite(req_wrap, bufs, count, send_handle); @@ -383,8 +381,7 @@ void StreamBase::JSMethod(const FunctionCallbackInfo& args) { if (!wrap->IsAlive()) return args.GetReturnValue().Set(UV_EINVAL); - AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope( - handle->env(), handle->get_async_id()); + AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(handle); args.GetReturnValue().Set((wrap->*Method)(args)); } diff --git a/src/stream_base.h b/src/stream_base.h index 8af05059f49e47..d8fc6f331e57c7 100644 --- a/src/stream_base.h +++ b/src/stream_base.h @@ -200,7 +200,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/src/stream_wrap.cc b/src/stream_wrap.cc index 27fe48d1165c75..2a614afffde591 100644 --- a/src/stream_wrap.cc +++ b/src/stream_wrap.cc @@ -32,7 +32,6 @@ #include "udp_wrap.h" #include "util-inl.h" -#include // abort() #include // memcpy() #include // INT_MAX diff --git a/src/tcp_wrap.cc b/src/tcp_wrap.cc index 61b08217b8f129..cd6ed3cef0a5bf 100644 --- a/src/tcp_wrap.cc +++ b/src/tcp_wrap.cc @@ -57,8 +57,7 @@ Local TCPWrap::Instantiate(Environment* env, AsyncWrap* parent, TCPWrap::SocketType type) { EscapableHandleScope handle_scope(env->isolate()); - AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope( - env, parent->get_async_id()); + AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(parent); CHECK_EQ(env->tcp_constructor_template().IsEmpty(), false); Local constructor = env->tcp_constructor_template()->GetFunction(); CHECK_EQ(constructor.IsEmpty(), false); @@ -289,8 +288,7 @@ void TCPWrap::Connect(const FunctionCallbackInfo& args) { int err = uv_ip4_addr(*ip_address, port, &addr); if (err == 0) { - AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope( - env, wrap->get_async_id()); + AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(wrap); ConnectWrap* req_wrap = new ConnectWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_TCPCONNECTWRAP); err = uv_tcp_connect(req_wrap->req(), @@ -326,8 +324,7 @@ void TCPWrap::Connect6(const FunctionCallbackInfo& args) { int err = uv_ip6_addr(*ip_address, port, &addr); if (err == 0) { - AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope( - env, wrap->get_async_id()); + AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(wrap); ConnectWrap* req_wrap = new ConnectWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_TCPCONNECTWRAP); err = uv_tcp_connect(req_wrap->req(), diff --git a/src/udp_wrap.cc b/src/udp_wrap.cc index 0d7a048a7d7eb2..a7b56c067b2c2d 100644 --- a/src/udp_wrap.cc +++ b/src/udp_wrap.cc @@ -26,7 +26,6 @@ #include "req_wrap-inl.h" #include "util-inl.h" -#include namespace node { @@ -355,8 +354,7 @@ void UDPWrap::DoSend(const FunctionCallbackInfo& args, int family) { SendWrap* req_wrap; { - AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope( - env, wrap->get_async_id()); + AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(wrap); req_wrap = new SendWrap(env, req_wrap_obj, have_callback); } size_t msg_size = 0; @@ -507,8 +505,7 @@ Local UDPWrap::Instantiate(Environment* env, AsyncWrap* parent, UDPWrap::SocketType type) { EscapableHandleScope scope(env->isolate()); - AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope( - env, parent->get_async_id()); + AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(parent); // If this assert fires then Initialize hasn't been called yet. CHECK_EQ(env->udp_constructor_function().IsEmpty(), false); diff --git a/test/abort/test-abort-backtrace.js b/test/abort/test-abort-backtrace.js index e69ac3ddfdece8..7f87ef0e7f4559 100644 --- a/test/abort/test-abort-backtrace.js +++ b/test/abort/test-abort-backtrace.js @@ -19,7 +19,8 @@ if (process.argv[2] === 'child') { } if (!common.isWindows) { - if (!frames.some((frame) => frame.includes(`[${process.execPath}]`))) { + const { getBinaryPath } = require('../common/shared-lib-util'); + if (!frames.some((frame) => frame.includes(`[${getBinaryPath()}]`))) { assert.fail(`Some frames should include the binary name:\n${stderr}`); } } diff --git a/test/addons-napi/test_general/test.js b/test/addons-napi/test_general/test.js index bcaa13d894bedc..fa6240d384a0fd 100644 --- a/test/addons-napi/test_general/test.js +++ b/test/addons-napi/test_general/test.js @@ -81,7 +81,7 @@ const y = {}; test_general.wrap(y); test_general.removeWrap(y); // Wrapping twice succeeds if a remove_wrap() separates the instances -assert.doesNotThrow(() => test_general.wrap(y)); +test_general.wrap(y); // Ensure that removing a wrap and garbage collecting does not fire the // finalize callback. 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 00000000000000..755a2389c68591 --- /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 0e94caf1d975f2..56e2b3f4e2b6c6 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/addons-napi/test_make_callback_recurse/binding.cc b/test/addons-napi/test_make_callback_recurse/binding.cc index 641f9f64237e5d..bfe9a457d237c8 100644 --- a/test/addons-napi/test_make_callback_recurse/binding.cc +++ b/test/addons-napi/test_make_callback_recurse/binding.cc @@ -13,9 +13,22 @@ napi_value MakeCallback(napi_env env, napi_callback_info info) { napi_value recv = args[0]; napi_value func = args[1]; - napi_make_callback(env, nullptr /* async_context */, + napi_status status = napi_make_callback(env, nullptr /* async_context */, recv, func, 0 /* argc */, nullptr /* argv */, nullptr /* result */); + bool isExceptionPending; + NAPI_CALL(env, napi_is_exception_pending(env, &isExceptionPending)); + if (isExceptionPending && !(status == napi_pending_exception)) { + // if there is an exception pending we don't expect any + // other error + napi_value pending_error; + status = napi_get_and_clear_last_exception(env, &pending_error); + NAPI_CALL(env, + napi_throw_error((env), + nullptr, + "error when only pending exception expected")); + } + return recv; } diff --git a/test/addons-napi/test_new_target/binding.c b/test/addons-napi/test_new_target/binding.c new file mode 100644 index 00000000000000..a74d4bb2f877be --- /dev/null +++ b/test/addons-napi/test_new_target/binding.c @@ -0,0 +1,69 @@ +#include +#include "../common.h" + +napi_value BaseClass(napi_env env, napi_callback_info info) { + napi_value newTargetArg; + NAPI_CALL(env, napi_get_new_target(env, info, &newTargetArg)); + napi_value thisArg; + NAPI_CALL(env, napi_get_cb_info(env, info, NULL, NULL, &thisArg, NULL)); + napi_value undefined; + NAPI_CALL(env, napi_get_undefined(env, &undefined)); + + // this !== new.target since we are being invoked through super() + bool result; + NAPI_CALL(env, napi_strict_equals(env, newTargetArg, thisArg, &result)); + NAPI_ASSERT(env, !result, "this !== new.target"); + + // new.target !== undefined because we should be called as a new expression + NAPI_ASSERT(env, newTargetArg != NULL, "newTargetArg != NULL"); + NAPI_CALL(env, napi_strict_equals(env, newTargetArg, undefined, &result)); + NAPI_ASSERT(env, !result, "new.target !== undefined"); + + return thisArg; +} + +napi_value Constructor(napi_env env, napi_callback_info info) { + bool result; + napi_value newTargetArg; + NAPI_CALL(env, napi_get_new_target(env, info, &newTargetArg)); + size_t argc = 1; + napi_value argv; + napi_value thisArg; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &argv, &thisArg, NULL)); + napi_value undefined; + NAPI_CALL(env, napi_get_undefined(env, &undefined)); + + // new.target !== undefined because we should be called as a new expression + NAPI_ASSERT(env, newTargetArg != NULL, "newTargetArg != NULL"); + NAPI_CALL(env, napi_strict_equals(env, newTargetArg, undefined, &result)); + NAPI_ASSERT(env, !result, "new.target !== undefined"); + + // arguments[0] should be Constructor itself (test harness passed it) + NAPI_CALL(env, napi_strict_equals(env, newTargetArg, argv, &result)); + NAPI_ASSERT(env, result, "new.target === Constructor"); + + return thisArg; +} + +napi_value OrdinaryFunction(napi_env env, napi_callback_info info) { + napi_value newTargetArg; + NAPI_CALL(env, napi_get_new_target(env, info, &newTargetArg)); + + NAPI_ASSERT(env, newTargetArg == NULL, "newTargetArg == NULL"); + + napi_value _true; + NAPI_CALL(env, napi_get_boolean(env, true, &_true)); + return _true; +} + +napi_value Init(napi_env env, napi_value exports) { + const napi_property_descriptor desc[] = { + DECLARE_NAPI_PROPERTY("BaseClass", BaseClass), + DECLARE_NAPI_PROPERTY("OrdinaryFunction", OrdinaryFunction), + DECLARE_NAPI_PROPERTY("Constructor", Constructor) + }; + NAPI_CALL(env, napi_define_properties(env, exports, 3, desc)); + return exports; +} + +NAPI_MODULE(NODE_GYP_MODULE_NAME, Init) diff --git a/test/addons-napi/test_new_target/binding.gyp b/test/addons-napi/test_new_target/binding.gyp new file mode 100644 index 00000000000000..23daf507916ff6 --- /dev/null +++ b/test/addons-napi/test_new_target/binding.gyp @@ -0,0 +1,9 @@ +{ + 'targets': [ + { + 'target_name': 'binding', + 'defines': [ 'V8_DEPRECATION_WARNINGS=1' ], + 'sources': [ 'binding.c' ] + } + ] +} diff --git a/test/addons-napi/test_new_target/test.js b/test/addons-napi/test_new_target/test.js new file mode 100644 index 00000000000000..702e8ca8b4387d --- /dev/null +++ b/test/addons-napi/test_new_target/test.js @@ -0,0 +1,21 @@ +'use strict'; + +const common = require('../../common'); +const assert = require('assert'); +const binding = require(`./build/${common.buildType}/binding`); + +class Class extends binding.BaseClass { + constructor() { + super(); + this.method(); + } + method() { + this.ok = true; + } +} + +assert.ok(new Class() instanceof binding.BaseClass); +assert.ok(new Class().ok); +assert.ok(binding.OrdinaryFunction()); +assert.ok( + new binding.Constructor(binding.Constructor) instanceof binding.Constructor); diff --git a/test/addons-napi/test_number/test.js b/test/addons-napi/test_number/test.js index e92c6d0cd29951..11cf6f6b7478a6 100644 --- a/test/addons-napi/test_number/test.js +++ b/test/addons-napi/test_number/test.js @@ -45,3 +45,10 @@ assert.strictEqual(1, test_number.TestInt32Truncation(4294967297)); assert.strictEqual(0, test_number.TestInt32Truncation(4294967296)); assert.strictEqual(-1, test_number.TestInt32Truncation(4294967295)); assert.strictEqual(3, test_number.TestInt32Truncation(4294967296 * 5 + 3)); + +// validate that the boundaries of safe integer can be passed through +// successfully +assert.strictEqual(Number.MAX_SAFE_INTEGER, + test_number.TestInt64Truncation(Number.MAX_SAFE_INTEGER)); +assert.strictEqual(Number.MIN_SAFE_INTEGER, + test_number.TestInt64Truncation(Number.MIN_SAFE_INTEGER)); diff --git a/test/addons-napi/test_number/test_number.c b/test/addons-napi/test_number/test_number.c index 3707f1ee57d713..a1a70950083324 100644 --- a/test/addons-napi/test_number/test_number.c +++ b/test/addons-napi/test_number/test_number.c @@ -45,10 +45,33 @@ napi_value TestInt32Truncation(napi_env env, napi_callback_info info) { return output; } +napi_value TestInt64Truncation(napi_env env, napi_callback_info info) { + size_t argc = 1; + napi_value args[1]; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + + NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments"); + + napi_valuetype valuetype0; + NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0)); + + NAPI_ASSERT(env, valuetype0 == napi_number, + "Wrong type of arguments. Expects a number as first argument."); + + int64_t input; + NAPI_CALL(env, napi_get_value_int64(env, args[0], &input)); + + napi_value output; + NAPI_CALL(env, napi_create_int64(env, input, &output)); + + return output; +} + napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor descriptors[] = { DECLARE_NAPI_PROPERTY("Test", Test), DECLARE_NAPI_PROPERTY("TestInt32Truncation", TestInt32Truncation), + DECLARE_NAPI_PROPERTY("TestInt64Truncation", TestInt64Truncation), }; NAPI_CALL(env, napi_define_properties( diff --git a/test/addons-napi/test_promise/test.js b/test/addons-napi/test_promise/test.js index 6dc51b3fa558a2..477ceb75969d51 100644 --- a/test/addons-napi/test_promise/test.js +++ b/test/addons-napi/test_promise/test.js @@ -45,7 +45,9 @@ common.crashOnUnhandledRejection(); test_promise.concludeCurrentPromise(Promise.resolve('chained answer'), true); } -assert.strictEqual(test_promise.isPromise(test_promise.createPromise()), true); +const promiseTypeTestPromise = test_promise.createPromise(); +assert.strictEqual(test_promise.isPromise(promiseTypeTestPromise), true); +test_promise.concludeCurrentPromise(undefined, true); const rejectPromise = Promise.reject(-1); const expected_reason = -1; diff --git a/test/addons/callback-scope/binding.cc b/test/addons/callback-scope/binding.cc index 3b69d2d5725a8f..94d5ec91d7f3a2 100644 --- a/test/addons/callback-scope/binding.cc +++ b/test/addons/callback-scope/binding.cc @@ -41,7 +41,8 @@ static void Callback(uv_work_t* req, int ignored) { v8::Local local = v8::Local::New(isolate, persistent); - local->Resolve(v8::Undefined(isolate)); + local->Resolve(isolate->GetCurrentContext(), + v8::Undefined(isolate)).ToChecked(); delete req; } @@ -49,7 +50,8 @@ static void TestResolveAsync(const v8::FunctionCallbackInfo& args) { v8::Isolate* isolate = args.GetIsolate(); if (persistent.IsEmpty()) { - persistent.Reset(isolate, v8::Promise::Resolver::New(isolate)); + persistent.Reset(isolate, v8::Promise::Resolver::New( + isolate->GetCurrentContext()).ToLocalChecked()); uv_work_t* req = new uv_work_t; diff --git a/test/addons/symlinked-module/test.js b/test/addons/symlinked-module/test.js index e8c26544f2a38c..cbd01e938fe25f 100644 --- a/test/addons/symlinked-module/test.js +++ b/test/addons/symlinked-module/test.js @@ -30,5 +30,5 @@ const sub = require('./submodule'); const mod = require(path.join(i, 'binding.node')); assert.notStrictEqual(mod, null); assert.strictEqual(mod.hello(), 'world'); - assert.doesNotThrow(() => sub.test(i)); + sub.test(i); // Should not throw. }); diff --git a/test/cctest/node_test_fixture.cc b/test/cctest/node_test_fixture.cc index e4675c5db3c9f9..3e5a112240f6d3 100644 --- a/test/cctest/node_test_fixture.cc +++ b/test/cctest/node_test_fixture.cc @@ -3,4 +3,5 @@ uv_loop_t NodeTestFixture::current_loop; std::unique_ptr NodeTestFixture::platform; std::unique_ptr NodeTestFixture::allocator; +std::unique_ptr NodeTestFixture::tracing_controller; v8::Isolate::CreateParams NodeTestFixture::params; diff --git a/test/cctest/node_test_fixture.h b/test/cctest/node_test_fixture.h index 583530c65ebe9e..660111c5a90c6f 100644 --- a/test/cctest/node_test_fixture.h +++ b/test/cctest/node_test_fixture.h @@ -55,13 +55,9 @@ struct Argv { class NodeTestFixture : public ::testing::Test { - public: - static uv_loop_t* CurrentLoop() { return ¤t_loop; } - - node::MultiIsolatePlatform* Platform() const { return platform.get(); } - protected: static std::unique_ptr allocator; + static std::unique_ptr tracing_controller; static std::unique_ptr platform; static v8::Isolate::CreateParams params; static uv_loop_t current_loop; @@ -69,18 +65,14 @@ class NodeTestFixture : public ::testing::Test { static void SetUpTestCase() { platform.reset(new node::NodePlatform(4, nullptr)); + tracing_controller.reset(new v8::TracingController()); allocator.reset(v8::ArrayBuffer::Allocator::NewDefaultAllocator()); params.array_buffer_allocator = allocator.get(); + node::tracing::TraceEventHelper::SetTracingController( + tracing_controller.get()); CHECK_EQ(0, uv_loop_init(¤t_loop)); v8::V8::InitializePlatform(platform.get()); v8::V8::Initialize(); - - // As the TracingController is stored globally, we only need to create it - // one time for all tests. - if (node::tracing::TraceEventHelper::GetTracingController() == nullptr) { - node::tracing::TraceEventHelper::SetTracingController( - new v8::TracingController()); - } } static void TearDownTestCase() { @@ -108,17 +100,15 @@ class EnvironmentTestFixture : public NodeTestFixture { public: class Env { public: - Env(const v8::HandleScope& handle_scope, - const Argv& argv, - NodeTestFixture* test_fixture) { + Env(const v8::HandleScope& handle_scope, const Argv& argv) { auto isolate = handle_scope.GetIsolate(); context_ = node::NewContext(isolate); CHECK(!context_.IsEmpty()); context_->Enter(); isolate_data_ = node::CreateIsolateData(isolate, - NodeTestFixture::CurrentLoop(), - test_fixture->Platform()); + &NodeTestFixture::current_loop, + platform.get()); CHECK_NE(nullptr, isolate_data_); environment_ = node::CreateEnvironment(isolate_data_, context_, diff --git a/test/cctest/test_aliased_buffer.cc b/test/cctest/test_aliased_buffer.cc index 0eaddf773555db..7afa466133b757 100644 --- a/test/cctest/test_aliased_buffer.cc +++ b/test/cctest/test_aliased_buffer.cc @@ -207,3 +207,33 @@ TEST_F(AliasBufferTest, SharedArrayBuffer4) { int8_t, v8::Int8Array, int32_t, v8::Int32Array>(isolate_, 1, 3, 1); } + +TEST_F(AliasBufferTest, OperatorOverloads) { + v8::Isolate::Scope isolate_scope(isolate_); + v8::HandleScope handle_scope(isolate_); + v8::Local context = v8::Context::New(isolate_); + v8::Context::Scope context_scope(context); + const size_t size = 10; + AliasedBuffer ab{isolate_, size}; + + EXPECT_EQ(static_cast(1), ab[0] = 1); + EXPECT_EQ(static_cast(4), ab[0] += 3); + EXPECT_EQ(static_cast(2), ab[0] -= 2); + EXPECT_EQ(static_cast(-2), -ab[0]); +} + +TEST_F(AliasBufferTest, OperatorOverloadsRefs) { + v8::Isolate::Scope isolate_scope(isolate_); + v8::HandleScope handle_scope(isolate_); + v8::Local context = v8::Context::New(isolate_); + v8::Context::Scope context_scope(context); + AliasedBuffer ab{isolate_, 2}; + using Reference = AliasedBuffer::Reference; + Reference ref = ab[0]; + Reference ref_value = ab[1] = 2; + + EXPECT_EQ(static_cast(2), ref = ref_value); + EXPECT_EQ(static_cast(4), ref += ref_value); + EXPECT_EQ(static_cast(2), ref -= ref_value); + EXPECT_EQ(static_cast(-2), -ref); +} diff --git a/test/cctest/test_environment.cc b/test/cctest/test_environment.cc index 352fed1fb62ed9..4575d3b65ae318 100644 --- a/test/cctest/test_environment.cc +++ b/test/cctest/test_environment.cc @@ -32,7 +32,7 @@ class EnvironmentTest : public EnvironmentTestFixture { TEST_F(EnvironmentTest, AtExitWithEnvironment) { const v8::HandleScope handle_scope(isolate_); const Argv argv; - Env env {handle_scope, argv, this}; + Env env {handle_scope, argv}; AtExit(*env, at_exit_callback1); RunAtExit(*env); @@ -42,7 +42,7 @@ TEST_F(EnvironmentTest, AtExitWithEnvironment) { TEST_F(EnvironmentTest, AtExitWithArgument) { const v8::HandleScope handle_scope(isolate_); const Argv argv; - Env env {handle_scope, argv, this}; + Env env {handle_scope, argv}; std::string arg{"some args"}; AtExit(*env, at_exit_callback1, static_cast(&arg)); @@ -53,8 +53,8 @@ TEST_F(EnvironmentTest, AtExitWithArgument) { TEST_F(EnvironmentTest, MultipleEnvironmentsPerIsolate) { const v8::HandleScope handle_scope(isolate_); const Argv argv; - Env env1 {handle_scope, argv, this}; - Env env2 {handle_scope, argv, this}; + Env env1 {handle_scope, argv}; + Env env2 {handle_scope, argv}; AtExit(*env1, at_exit_callback1); AtExit(*env2, at_exit_callback2); diff --git a/test/cctest/test_node_postmortem_metadata.cc b/test/cctest/test_node_postmortem_metadata.cc index e46cb69432d8bf..e901d97668f5ff 100644 --- a/test/cctest/test_node_postmortem_metadata.cc +++ b/test/cctest/test_node_postmortem_metadata.cc @@ -70,7 +70,7 @@ TEST_F(DebugSymbolsTest, ExternalStringDataOffset) { TEST_F(DebugSymbolsTest, BaseObjectPersistentHandle) { const v8::HandleScope handle_scope(isolate_); const Argv argv; - Env env{handle_scope, argv, this}; + Env env{handle_scope, argv}; v8::Local object = v8::Object::New(isolate_); node::BaseObject obj(*env, object); @@ -87,7 +87,7 @@ TEST_F(DebugSymbolsTest, BaseObjectPersistentHandle) { TEST_F(DebugSymbolsTest, EnvironmentHandleWrapQueue) { const v8::HandleScope handle_scope(isolate_); const Argv argv; - Env env{handle_scope, argv, this}; + Env env{handle_scope, argv}; auto expected = reinterpret_cast((*env)->handle_wrap_queue()); auto calculated = reinterpret_cast(*env) + @@ -98,7 +98,7 @@ TEST_F(DebugSymbolsTest, EnvironmentHandleWrapQueue) { TEST_F(DebugSymbolsTest, EnvironmentReqWrapQueue) { const v8::HandleScope handle_scope(isolate_); const Argv argv; - Env env{handle_scope, argv, this}; + Env env{handle_scope, argv}; auto expected = reinterpret_cast((*env)->req_wrap_queue()); auto calculated = reinterpret_cast(*env) + @@ -109,7 +109,7 @@ TEST_F(DebugSymbolsTest, EnvironmentReqWrapQueue) { TEST_F(DebugSymbolsTest, HandleWrapList) { const v8::HandleScope handle_scope(isolate_); const Argv argv; - Env env{handle_scope, argv, this}; + Env env{handle_scope, argv}; uv_tcp_t handle; @@ -138,7 +138,7 @@ TEST_F(DebugSymbolsTest, HandleWrapList) { TEST_F(DebugSymbolsTest, ReqWrapList) { const v8::HandleScope handle_scope(isolate_); const Argv argv; - Env env{handle_scope, argv, this}; + Env env{handle_scope, argv}; auto obj_template = v8::FunctionTemplate::New(isolate_); obj_template->InstanceTemplate()->SetInternalFieldCount(1); diff --git a/test/common/index.js b/test/common/index.js index eb4d5a5251cab8..165014e585c49f 100644 --- a/test/common/index.js +++ b/test/common/index.js @@ -514,21 +514,13 @@ exports.canCreateSymLink = function() { const whoamiPath = path.join(process.env.SystemRoot, 'System32', 'whoami.exe'); - let err = false; - let output = ''; - try { - output = execSync(`${whoamiPath} /priv`, { timout: 1000 }); + const output = execSync(`${whoamiPath} /priv`, { timout: 1000 }); + return output.includes('SeCreateSymbolicLinkPrivilege'); } catch (e) { - err = true; - } finally { - if (err || !output.includes('SeCreateSymbolicLinkPrivilege')) { - return false; - } + return false; } } - - return true; }; exports.getCallSite = function getCallSite(top) { diff --git a/test/common/shared-lib-util.js b/test/common/shared-lib-util.js index baa989824cdc2c..89b1231e5cc66c 100644 --- a/test/common/shared-lib-util.js +++ b/test/common/shared-lib-util.js @@ -29,7 +29,7 @@ exports.addLibraryPath = function(env) { path.dirname(process.execPath); }; -// Get the full path of shared lib +// Get the full path of shared lib. exports.getSharedLibPath = function() { if (common.isWindows) { return path.join(path.dirname(process.execPath), 'node.dll'); @@ -42,3 +42,9 @@ exports.getSharedLibPath = function() { `libnode.${process.config.variables.shlib_suffix}`); } }; + +// Get the binary path of stack frames. +exports.getBinaryPath = function() { + return process.config.variables.node_shared ? + exports.getSharedLibPath() : process.execPath; +}; diff --git a/test/doctool/test-doctool-json.js b/test/doctool/test-doctool-json.js index 1be086c3a6a7ea..e295014071a3c5 100644 --- a/test/doctool/test-doctool-json.js +++ b/test/doctool/test-doctool-json.js @@ -1,9 +1,9 @@ 'use strict'; const common = require('../common'); -// The doctool currently uses js-yaml from the tool/eslint/ tree. +// The doctool currently uses js-yaml from the tool/node_modules/eslint/ tree. try { - require('../../tools/eslint/node_modules/js-yaml'); + require('../../tools/node_modules/eslint/node_modules/js-yaml'); } catch (e) { common.skip('missing js-yaml (eslint not present)'); } @@ -102,9 +102,9 @@ const testData = [ meta: { added: ['v5.3.0', 'v4.2.0'], changes: [ - { version: 'v4.2.0', + { 'version': 'v4.2.0', 'pr-url': 'https://github.com/nodejs/node/pull/3276', - description: 'The `error` parameter can now be ' + + 'description': 'The `error` parameter can now be ' + 'an arrow function.' } ] diff --git a/test/fixtures/test-regress-GH-4015.js b/test/fixtures/test-fs-stat-sync-overflow.js similarity index 100% rename from test/fixtures/test-regress-GH-4015.js rename to test/fixtures/test-fs-stat-sync-overflow.js diff --git a/test/internet/test-dgram-membership.js b/test/internet/test-dgram-membership.js index 97bc1e648ad79e..d4bad5c2daa08c 100644 --- a/test/internet/test-dgram-membership.js +++ b/test/internet/test-dgram-membership.js @@ -10,7 +10,7 @@ const setup = dgram.createSocket.bind(dgram, { type: 'udp4', reuseAddr: true }); // addMembership() with valid socket and multicast address should not throw { const socket = setup(); - assert.doesNotThrow(() => { socket.addMembership(multicastAddress); }); + socket.addMembership(multicastAddress); socket.close(); } @@ -27,11 +27,7 @@ const setup = dgram.createSocket.bind(dgram, { type: 'udp4', reuseAddr: true }); // dropMembership() after addMembership() should not throw { const socket = setup(); - assert.doesNotThrow( - () => { - socket.addMembership(multicastAddress); - socket.dropMembership(multicastAddress); - } - ); + socket.addMembership(multicastAddress); + socket.dropMembership(multicastAddress); socket.close(); } diff --git a/test/internet/test-dns.js b/test/internet/test-dns.js index 20d44118d782a3..f1b7b4ff056833 100644 --- a/test/internet/test-dns.js +++ b/test/internet/test-dns.js @@ -579,15 +579,8 @@ process.on('exit', function() { assert.ok(getaddrinfoCallbackCalled); }); - -assert.doesNotThrow(() => - dns.lookup(addresses.INET6_HOST, 6, common.mustCall())); - -assert.doesNotThrow(() => - dns.lookup(addresses.INET_HOST, {}, common.mustCall())); - -assert.doesNotThrow(() => - dns.lookupService('0.0.0.0', '0', common.mustCall())); - -assert.doesNotThrow(() => - dns.lookupService('0.0.0.0', 0, common.mustCall())); +// Should not throw. +dns.lookup(addresses.INET6_HOST, 6, common.mustCall()); +dns.lookup(addresses.INET_HOST, {}, common.mustCall()); +dns.lookupService('0.0.0.0', '0', common.mustCall()); +dns.lookupService('0.0.0.0', 0, common.mustCall()); diff --git a/test/internet/test-http-https-default-ports.js b/test/internet/test-http-https-default-ports.js index 5f1b9eddb4f416..ddf4c5d73902bc 100644 --- a/test/internet/test-http-https-default-ports.js +++ b/test/internet/test-http-https-default-ports.js @@ -30,10 +30,10 @@ const https = require('https'); const http = require('http'); -https.get(`https://${addresses.INET_HOST}/`, common.mustCall(function(res) { +https.get(`https://${addresses.INET_HOST}/`, common.mustCall((res) => { res.resume(); })); -http.get(`http://${addresses.INET_HOST}/`, common.mustCall(function(res) { +http.get(`http://${addresses.INET_HOST}/`, common.mustCall((res) => { res.resume(); })); diff --git a/test/message/assert_throws_stack.js b/test/message/assert_throws_stack.js new file mode 100644 index 00000000000000..36bc5734cae37f --- /dev/null +++ b/test/message/assert_throws_stack.js @@ -0,0 +1,6 @@ +'use strict'; + +require('../common'); +const assert = require('assert').strict; + +assert.throws(() => { throw new Error('foo'); }, { bar: true }); diff --git a/test/message/assert_throws_stack.out b/test/message/assert_throws_stack.out new file mode 100644 index 00000000000000..d34bdd24798190 --- /dev/null +++ b/test/message/assert_throws_stack.out @@ -0,0 +1,14 @@ +assert.js:* + throw new AssertionError(obj); + ^ + +AssertionError [ERR_ASSERTION]: bar: expected true, not undefined + at Object. (*assert_throws_stack.js:*:*) + at * + at * + at * + at * + at * + at * + at * + at * diff --git a/test/message/error_exit.out b/test/message/error_exit.out index d6fbded760106b..8f03f08a7e0392 100644 --- a/test/message/error_exit.out +++ b/test/message/error_exit.out @@ -1,6 +1,6 @@ Exiting with code=1 assert.js:* - throw new errors.AssertionError({ + throw new AssertionError(obj); ^ AssertionError [ERR_ASSERTION]: 1 === 2 diff --git a/test/parallel/parallel.status b/test/parallel/parallel.status index 8163bc672f34a5..899e6adfac060d 100644 --- a/test/parallel/parallel.status +++ b/test/parallel/parallel.status @@ -15,7 +15,6 @@ test-postmortem-metadata: PASS,FLAKY [$system==macos] [$arch==arm || $arch==arm64] -test-npm-install: PASS,FLAKY [$system==solaris] # Also applies to SmartOS diff --git a/test/parallel/test-assert-checktag.js b/test/parallel/test-assert-checktag.js index c4823243e7d3e9..632bfa03c6d4bf 100644 --- a/test/parallel/test-assert-checktag.js +++ b/test/parallel/test-assert-checktag.js @@ -30,8 +30,8 @@ function re(literals, ...values) { FakeDate.prototype = Date.prototype; const fake = new FakeDate(); - assert.doesNotThrow(() => assert.deepEqual(date, fake)); - assert.doesNotThrow(() => assert.deepEqual(fake, date)); + assert.deepEqual(date, fake); + assert.deepEqual(fake, date); // For deepStrictEqual we check the runtime type, // then reveal the fakeness of the fake date @@ -47,7 +47,7 @@ function re(literals, ...values) { for (const prop of Object.keys(global)) { fakeGlobal[prop] = global[prop]; } - assert.doesNotThrow(() => assert.deepEqual(fakeGlobal, global)); + assert.deepEqual(fakeGlobal, global); // Message will be truncated anyway, don't validate assert.throws(() => assert.deepStrictEqual(fakeGlobal, global), assert.AssertionError); @@ -59,7 +59,7 @@ function re(literals, ...values) { for (const prop of Object.keys(process)) { fakeProcess[prop] = process[prop]; } - assert.doesNotThrow(() => assert.deepEqual(fakeProcess, process)); + assert.deepEqual(fakeProcess, process); // Message will be truncated anyway, don't validate assert.throws(() => assert.deepStrictEqual(fakeProcess, process), assert.AssertionError); diff --git a/test/parallel/test-assert-deep.js b/test/parallel/test-assert-deep.js index 8f08d571383a77..d0aacfdf516f4c 100644 --- a/test/parallel/test-assert-deep.js +++ b/test/parallel/test-assert-deep.js @@ -1,7 +1,9 @@ 'use strict'; + const common = require('../common'); const assert = require('assert'); const util = require('util'); +const { AssertionError } = assert; // Template tag function turning an error message into a RegExp // for assert.throws() @@ -25,14 +27,14 @@ function re(literals, ...values) { // That is why we discourage using deepEqual in our own tests. // Turn off no-restricted-properties because we are testing deepEqual! -/* eslint-disable no-restricted-properties */ +/* eslint-disable no-restricted-properties, prefer-common-expectserror */ const arr = new Uint8Array([120, 121, 122, 10]); const buf = Buffer.from(arr); // They have different [[Prototype]] assert.throws(() => assert.deepStrictEqual(arr, buf), re`${arr} deepStrictEqual ${buf}`); -assert.doesNotThrow(() => assert.deepEqual(arr, buf)); +assert.deepEqual(arr, buf); { const buf2 = Buffer.from(arr); @@ -40,7 +42,7 @@ assert.doesNotThrow(() => assert.deepEqual(arr, buf)); assert.throws(() => assert.deepStrictEqual(buf2, buf), re`${buf2} deepStrictEqual ${buf}`); - assert.doesNotThrow(() => assert.deepEqual(buf2, buf)); + assert.deepEqual(buf2, buf); } { @@ -48,7 +50,7 @@ assert.doesNotThrow(() => assert.deepEqual(arr, buf)); arr2.prop = 5; assert.throws(() => assert.deepStrictEqual(arr, arr2), re`${arr} deepStrictEqual ${arr2}`); - assert.doesNotThrow(() => assert.deepEqual(arr, arr2)); + assert.deepEqual(arr, arr2); } const date = new Date('2016'); @@ -64,8 +66,8 @@ const date2 = new MyDate('2016'); // deepEqual returns true as long as the time are the same, // but deepStrictEqual checks own properties -assert.doesNotThrow(() => assert.deepEqual(date, date2)); -assert.doesNotThrow(() => assert.deepEqual(date2, date)); +assert.deepEqual(date, date2); +assert.deepEqual(date2, date); assert.throws(() => assert.deepStrictEqual(date, date2), re`${date} deepStrictEqual ${date2}`); assert.throws(() => assert.deepStrictEqual(date2, date), @@ -83,7 +85,7 @@ const re2 = new MyRegExp('test'); // deepEqual returns true as long as the regexp-specific properties // are the same, but deepStrictEqual checks all properties -assert.doesNotThrow(() => assert.deepEqual(re1, re2)); +assert.deepEqual(re1, re2); assert.throws(() => assert.deepStrictEqual(re1, re2), re`${re1} deepStrictEqual ${re2}`); @@ -146,11 +148,11 @@ function assertNotDeepOrStrict(a, b, err) { } function assertOnlyDeepEqual(a, b, err) { - assert.doesNotThrow(() => assert.deepEqual(a, b)); + assert.deepEqual(a, b); assert.throws(() => assert.deepStrictEqual(a, b), err || re`${a} deepStrictEqual ${b}`); - assert.doesNotThrow(() => assert.deepEqual(b, a)); + assert.deepEqual(b, a); assert.throws(() => assert.deepStrictEqual(b, a), err || re`${b} deepStrictEqual ${a}`); } @@ -490,10 +492,9 @@ assertOnlyDeepEqual([1, , , 3], [1, , , 3, , , ]); // Handle NaN assert.throws(() => { assert.deepEqual(NaN, NaN); }, assert.AssertionError); -assert.doesNotThrow(() => { assert.deepStrictEqual(NaN, NaN); }); -assert.doesNotThrow(() => { assert.deepStrictEqual({ a: NaN }, { a: NaN }); }); -assert.doesNotThrow( - () => { assert.deepStrictEqual([ 1, 2, NaN, 4 ], [ 1, 2, NaN, 4 ]); }); +assert.deepStrictEqual(NaN, NaN); +assert.deepStrictEqual({ a: NaN }, { a: NaN }); +assert.deepStrictEqual([ 1, 2, NaN, 4 ], [ 1, 2, NaN, 4 ]); // Handle boxed primitives { @@ -545,4 +546,283 @@ assertDeepAndStrictEqual(-0, -0); assertDeepAndStrictEqual(a, b); } +assert.deepEqual(new Date(2000, 3, 14), new Date(2000, 3, 14)); + +assert.throws(() => assert.deepEqual(new Date(), new Date(2000, 3, 14)), + AssertionError, + 'deepEqual(new Date(), new Date(2000, 3, 14))'); + +assert.throws( + () => assert.notDeepEqual(new Date(2000, 3, 14), new Date(2000, 3, 14)), + AssertionError, + 'notDeepEqual(new Date(2000, 3, 14), new Date(2000, 3, 14))' +); + +assert.notDeepEqual(new Date(), new Date(2000, 3, 14)); + +assert.deepEqual(/a/, /a/); +assert.deepEqual(/a/g, /a/g); +assert.deepEqual(/a/i, /a/i); +assert.deepEqual(/a/m, /a/m); +assert.deepEqual(/a/igm, /a/igm); +common.expectsError(() => assert.deepEqual(/ab/, /a/), + { + code: 'ERR_ASSERTION', + name: 'AssertionError [ERR_ASSERTION]', + message: '/ab/ deepEqual /a/' + }); +common.expectsError(() => assert.deepEqual(/a/g, /a/), + { + code: 'ERR_ASSERTION', + name: 'AssertionError [ERR_ASSERTION]', + message: '/a/g deepEqual /a/' + }); +common.expectsError(() => assert.deepEqual(/a/i, /a/), + { + code: 'ERR_ASSERTION', + name: 'AssertionError [ERR_ASSERTION]', + message: '/a/i deepEqual /a/' + }); +common.expectsError(() => assert.deepEqual(/a/m, /a/), + { + code: 'ERR_ASSERTION', + name: 'AssertionError [ERR_ASSERTION]', + message: '/a/m deepEqual /a/' + }); +common.expectsError(() => assert.deepEqual(/a/igm, /a/im), + { + code: 'ERR_ASSERTION', + name: 'AssertionError [ERR_ASSERTION]', + message: '/a/gim deepEqual /a/im' + }); + +{ + const re1 = /a/g; + re1.lastIndex = 3; + assert.deepEqual(re1, /a/g); +} + +assert.deepEqual(4, '4'); +assert.deepEqual(true, 1); +assert.throws(() => assert.deepEqual(4, '5'), + AssertionError, + 'deepEqual( 4, \'5\')'); + +// Having the same number of owned properties && the same set of keys. +assert.deepEqual({ a: 4 }, { a: 4 }); +assert.deepEqual({ a: 4, b: '2' }, { a: 4, b: '2' }); +assert.deepEqual([4], ['4']); +assert.throws( + () => assert.deepEqual({ a: 4 }, { a: 4, b: true }), AssertionError); +assert.deepEqual(['a'], { 0: 'a' }); +assert.deepEqual({ a: 4, b: '1' }, { b: '1', a: 4 }); +const a1 = [1, 2, 3]; +const a2 = [1, 2, 3]; +a1.a = 'test'; +a1.b = true; +a2.b = true; +a2.a = 'test'; +assert.throws(() => assert.deepEqual(Object.keys(a1), Object.keys(a2)), + AssertionError); +assert.deepEqual(a1, a2); + +// Having an identical prototype property. +const nbRoot = { + toString() { return `${this.first} ${this.last}`; } +}; + +function nameBuilder(first, last) { + this.first = first; + this.last = last; + return this; +} +nameBuilder.prototype = nbRoot; + +function nameBuilder2(first, last) { + this.first = first; + this.last = last; + return this; +} +nameBuilder2.prototype = nbRoot; + +const nb1 = new nameBuilder('Ryan', 'Dahl'); +let nb2 = new nameBuilder2('Ryan', 'Dahl'); + +assert.deepEqual(nb1, nb2); + +nameBuilder2.prototype = Object; +nb2 = new nameBuilder2('Ryan', 'Dahl'); +assert.deepEqual(nb1, nb2); + +// Primitives and object. +assert.throws(() => assert.deepEqual(null, {}), AssertionError); +assert.throws(() => assert.deepEqual(undefined, {}), AssertionError); +assert.throws(() => assert.deepEqual('a', ['a']), AssertionError); +assert.throws(() => assert.deepEqual('a', { 0: 'a' }), AssertionError); +assert.throws(() => assert.deepEqual(1, {}), AssertionError); +assert.throws(() => assert.deepEqual(true, {}), AssertionError); +assert.throws(() => assert.deepEqual(Symbol(), {}), AssertionError); + +// Primitive wrappers and object. +assert.deepEqual(new String('a'), ['a']); +assert.deepEqual(new String('a'), { 0: 'a' }); +assert.deepEqual(new Number(1), {}); +assert.deepEqual(new Boolean(true), {}); + +// Same number of keys but different key names. +assert.throws(() => assert.deepEqual({ a: 1 }, { b: 1 }), AssertionError); + +assert.deepStrictEqual(new Date(2000, 3, 14), new Date(2000, 3, 14)); + +assert.throws( + () => assert.deepStrictEqual(new Date(), new Date(2000, 3, 14)), + AssertionError, + 'deepStrictEqual(new Date(), new Date(2000, 3, 14))' +); + +assert.throws( + () => assert.notDeepStrictEqual(new Date(2000, 3, 14), new Date(2000, 3, 14)), + AssertionError, + 'notDeepStrictEqual(new Date(2000, 3, 14), new Date(2000, 3, 14))' +); + +assert.notDeepStrictEqual(new Date(), new Date(2000, 3, 14)); + +assert.deepStrictEqual(/a/, /a/); +assert.deepStrictEqual(/a/g, /a/g); +assert.deepStrictEqual(/a/i, /a/i); +assert.deepStrictEqual(/a/m, /a/m); +assert.deepStrictEqual(/a/igm, /a/igm); +common.expectsError( + () => assert.deepStrictEqual(/ab/, /a/), + { + code: 'ERR_ASSERTION', + name: 'AssertionError [ERR_ASSERTION]', + message: '/ab/ deepStrictEqual /a/' + }); +common.expectsError( + () => assert.deepStrictEqual(/a/g, /a/), + { + code: 'ERR_ASSERTION', + name: 'AssertionError [ERR_ASSERTION]', + message: '/a/g deepStrictEqual /a/' + }); +common.expectsError( + () => assert.deepStrictEqual(/a/i, /a/), + { + code: 'ERR_ASSERTION', + name: 'AssertionError [ERR_ASSERTION]', + message: '/a/i deepStrictEqual /a/' + }); +common.expectsError( + () => assert.deepStrictEqual(/a/m, /a/), + { + code: 'ERR_ASSERTION', + name: 'AssertionError [ERR_ASSERTION]', + message: '/a/m deepStrictEqual /a/' + }); +common.expectsError( + () => assert.deepStrictEqual(/a/igm, /a/im), + { + code: 'ERR_ASSERTION', + name: 'AssertionError [ERR_ASSERTION]', + message: '/a/gim deepStrictEqual /a/im' + }); + +{ + const re1 = /a/; + re1.lastIndex = 3; + assert.deepStrictEqual(re1, /a/); +} + +assert.throws(() => assert.deepStrictEqual(4, '4'), + AssertionError, + 'deepStrictEqual(4, \'4\')'); + +assert.throws(() => assert.deepStrictEqual(true, 1), + AssertionError, + 'deepStrictEqual(true, 1)'); + +assert.throws(() => assert.deepStrictEqual(4, '5'), + AssertionError, + 'deepStrictEqual(4, \'5\')'); + +// Having the same number of owned properties && the same set of keys. +assert.deepStrictEqual({ a: 4 }, { a: 4 }); +assert.deepStrictEqual({ a: 4, b: '2' }, { a: 4, b: '2' }); +common.expectsError(() => assert.deepStrictEqual([4], ['4']), + { + code: 'ERR_ASSERTION', + name: 'AssertionError [ERR_ASSERTION]', + message: "[ 4 ] deepStrictEqual [ '4' ]" + }); +common.expectsError(() => assert.deepStrictEqual({ a: 4 }, { a: 4, b: true }), + { + code: 'ERR_ASSERTION', + name: 'AssertionError [ERR_ASSERTION]', + message: '{ a: 4 } deepStrictEqual { a: 4, b: true }' + }); +common.expectsError(() => assert.deepStrictEqual(['a'], { 0: 'a' }), + { + code: 'ERR_ASSERTION', + name: 'AssertionError [ERR_ASSERTION]', + message: "[ 'a' ] deepStrictEqual { '0': 'a' }" + }); + /* eslint-enable */ + +assert.deepStrictEqual({ a: 4, b: '1' }, { b: '1', a: 4 }); + +assert.throws( + () => assert.deepStrictEqual([0, 1, 2, 'a', 'b'], [0, 1, 2, 'b', 'a']), + AssertionError); + +assert.deepStrictEqual(a1, a2); + +// Prototype check. +function Constructor1(first, last) { + this.first = first; + this.last = last; +} + +function Constructor2(first, last) { + this.first = first; + this.last = last; +} + +const obj1 = new Constructor1('Ryan', 'Dahl'); +let obj2 = new Constructor2('Ryan', 'Dahl'); + +assert.throws(() => assert.deepStrictEqual(obj1, obj2), AssertionError); + +Constructor2.prototype = Constructor1.prototype; +obj2 = new Constructor2('Ryan', 'Dahl'); + +assert.deepStrictEqual(obj1, obj2); + +// primitives +assert.throws(() => assert.deepStrictEqual(4, '4'), AssertionError); +assert.throws(() => assert.deepStrictEqual(true, 1), AssertionError); +assert.throws(() => assert.deepStrictEqual(Symbol(), Symbol()), + AssertionError); + +const s = Symbol(); +assert.deepStrictEqual(s, s); + +// Primitives and object. +assert.throws(() => assert.deepStrictEqual(null, {}), AssertionError); +assert.throws(() => assert.deepStrictEqual(undefined, {}), AssertionError); +assert.throws(() => assert.deepStrictEqual('a', ['a']), AssertionError); +assert.throws(() => assert.deepStrictEqual('a', { 0: 'a' }), AssertionError); +assert.throws(() => assert.deepStrictEqual(1, {}), AssertionError); +assert.throws(() => assert.deepStrictEqual(true, {}), AssertionError); +assert.throws(() => assert.deepStrictEqual(Symbol(), {}), AssertionError); + +// Primitive wrappers and object. +assert.throws(() => assert.deepStrictEqual(new String('a'), ['a']), + AssertionError); +assert.throws(() => assert.deepStrictEqual(new String('a'), { 0: 'a' }), + AssertionError); +assert.throws(() => assert.deepStrictEqual(new Number(1), {}), AssertionError); +assert.throws(() => assert.deepStrictEqual(new Boolean(true), {}), + AssertionError); diff --git a/test/parallel/test-assert.js b/test/parallel/test-assert.js index 971c99be918d6a..6375311fa6e31c 100644 --- a/test/parallel/test-assert.js +++ b/test/parallel/test-assert.js @@ -25,449 +25,102 @@ const common = require('../common'); const assert = require('assert'); +const { inspect } = require('util'); const a = assert; -function makeBlock(f) { - const args = Array.prototype.slice.call(arguments, 1); - return () => { - return f.apply(null, args); - }; -} - assert.ok(a.AssertionError.prototype instanceof Error, 'a.AssertionError instanceof Error'); -assert.throws(makeBlock(a, false), a.AssertionError, 'ok(false)'); - -// Using a object as second arg results in a failure -assert.throws( - () => { assert.throws(() => { throw new Error(); }, { foo: 'bar' }); }, - common.expectsError({ - type: TypeError, - message: 'expected.test is not a function' - }) -); - - -assert.doesNotThrow(makeBlock(a, true), a.AssertionError, 'ok(true)'); - -assert.doesNotThrow(makeBlock(a, 'test', 'ok(\'test\')')); - -assert.throws(makeBlock(a.ok, false), - a.AssertionError, 'ok(false)'); +assert.throws(() => a(false), a.AssertionError, 'ok(false)'); +assert.throws(() => a.ok(false), a.AssertionError, 'ok(false)'); -assert.doesNotThrow(makeBlock(a.ok, true), - a.AssertionError, 'ok(true)'); +a(true); +a('test', 'ok(\'test\')'); +a.ok(true); +a.ok('test'); -assert.doesNotThrow(makeBlock(a.ok, 'test'), 'ok(\'test\')'); - -assert.throws(makeBlock(a.equal, true, false), +assert.throws(() => a.equal(true, false), a.AssertionError, 'equal(true, false)'); -assert.doesNotThrow(makeBlock(a.equal, null, null), - 'equal(null, null)'); - -assert.doesNotThrow(makeBlock(a.equal, undefined, undefined), - 'equal(undefined, undefined)'); - -assert.doesNotThrow(makeBlock(a.equal, null, undefined), - 'equal(null, undefined)'); - -assert.doesNotThrow(makeBlock(a.equal, true, true), 'equal(true, true)'); - -assert.doesNotThrow(makeBlock(a.equal, 2, '2'), 'equal(2, \'2\')'); +a.equal(null, null); +a.equal(undefined, undefined); +a.equal(null, undefined); +a.equal(true, true); +a.equal(2, '2'); +a.notEqual(true, false); -assert.doesNotThrow(makeBlock(a.notEqual, true, false), - 'notEqual(true, false)'); - -assert.throws(makeBlock(a.notEqual, true, true), +assert.throws(() => a.notEqual(true, true), a.AssertionError, 'notEqual(true, true)'); -assert.throws(makeBlock(a.strictEqual, 2, '2'), +assert.throws(() => a.strictEqual(2, '2'), a.AssertionError, 'strictEqual(2, \'2\')'); -assert.throws(makeBlock(a.strictEqual, null, undefined), +assert.throws(() => a.strictEqual(null, undefined), a.AssertionError, 'strictEqual(null, undefined)'); -assert.throws(makeBlock(a.notStrictEqual, 2, 2), +assert.throws(() => a.notStrictEqual(2, 2), a.AssertionError, 'notStrictEqual(2, 2)'); -assert.doesNotThrow(makeBlock(a.notStrictEqual, 2, '2'), - 'notStrictEqual(2, \'2\')'); - -// deepEqual joy! -assert.doesNotThrow(makeBlock(a.deepEqual, new Date(2000, 3, 14), - new Date(2000, 3, 14)), - 'deepEqual(new Date(2000, 3, 14), new Date(2000, 3, 14))'); - -assert.throws(makeBlock(a.deepEqual, new Date(), new Date(2000, 3, 14)), - a.AssertionError, - 'deepEqual(new Date(), new Date(2000, 3, 14))'); - -assert.throws( - makeBlock(a.notDeepEqual, new Date(2000, 3, 14), new Date(2000, 3, 14)), - a.AssertionError, - 'notDeepEqual(new Date(2000, 3, 14), new Date(2000, 3, 14))' -); - -assert.doesNotThrow(makeBlock( - a.notDeepEqual, - new Date(), - new Date(2000, 3, 14)), - 'notDeepEqual(new Date(), new Date(2000, 3, 14))' -); - -assert.doesNotThrow(makeBlock(a.deepEqual, /a/, /a/)); -assert.doesNotThrow(makeBlock(a.deepEqual, /a/g, /a/g)); -assert.doesNotThrow(makeBlock(a.deepEqual, /a/i, /a/i)); -assert.doesNotThrow(makeBlock(a.deepEqual, /a/m, /a/m)); -assert.doesNotThrow(makeBlock(a.deepEqual, /a/igm, /a/igm)); -assert.throws(makeBlock(a.deepEqual, /ab/, /a/), - common.expectsError({ - code: 'ERR_ASSERTION', - type: a.AssertionError, - message: /^\/ab\/ deepEqual \/a\/$/ - })); -assert.throws(makeBlock(a.deepEqual, /a/g, /a/), - common.expectsError({ - code: 'ERR_ASSERTION', - type: a.AssertionError, - message: /^\/a\/g deepEqual \/a\/$/ - })); -assert.throws(makeBlock(a.deepEqual, /a/i, /a/), - common.expectsError({ - code: 'ERR_ASSERTION', - type: a.AssertionError, - message: /^\/a\/i deepEqual \/a\/$/ - })); -assert.throws(makeBlock(a.deepEqual, /a/m, /a/), - common.expectsError({ - code: 'ERR_ASSERTION', - type: a.AssertionError, - message: /^\/a\/m deepEqual \/a\/$/ - })); -assert.throws(makeBlock(a.deepEqual, /a/igm, /a/im), - common.expectsError({ - code: 'ERR_ASSERTION', - type: a.AssertionError, - message: /^\/a\/gim deepEqual \/a\/im$/ - })); - -{ - const re1 = /a/g; - re1.lastIndex = 3; - assert.doesNotThrow(makeBlock(a.deepEqual, re1, /a/g)); -} - -assert.doesNotThrow(makeBlock(a.deepEqual, 4, '4'), 'deepEqual(4, \'4\')'); -assert.doesNotThrow(makeBlock(a.deepEqual, true, 1), 'deepEqual(true, 1)'); -assert.throws(makeBlock(a.deepEqual, 4, '5'), - a.AssertionError, - 'deepEqual( 4, \'5\')'); - -// having the same number of owned properties && the same set of keys -assert.doesNotThrow(makeBlock(a.deepEqual, { a: 4 }, { a: 4 })); -assert.doesNotThrow(makeBlock(a.deepEqual, { a: 4, b: '2' }, { a: 4, b: '2' })); -assert.doesNotThrow(makeBlock(a.deepEqual, [4], ['4'])); -assert.throws(makeBlock(a.deepEqual, { a: 4 }, { a: 4, b: true }), - a.AssertionError); -assert.doesNotThrow(makeBlock(a.deepEqual, ['a'], { 0: 'a' })); -//(although not necessarily the same order), -assert.doesNotThrow(makeBlock(a.deepEqual, { a: 4, b: '1' }, { b: '1', a: 4 })); -const a1 = [1, 2, 3]; -const a2 = [1, 2, 3]; -a1.a = 'test'; -a1.b = true; -a2.b = true; -a2.a = 'test'; -assert.throws(makeBlock(a.deepEqual, Object.keys(a1), Object.keys(a2)), - a.AssertionError); -assert.doesNotThrow(makeBlock(a.deepEqual, a1, a2)); - -// having an identical prototype property -const nbRoot = { - toString() { return `${this.first} ${this.last}`; } -}; - -function nameBuilder(first, last) { - this.first = first; - this.last = last; - return this; -} -nameBuilder.prototype = nbRoot; - -function nameBuilder2(first, last) { - this.first = first; - this.last = last; - return this; -} -nameBuilder2.prototype = nbRoot; - -const nb1 = new nameBuilder('Ryan', 'Dahl'); -let nb2 = new nameBuilder2('Ryan', 'Dahl'); - -assert.doesNotThrow(makeBlock(a.deepEqual, nb1, nb2)); - -nameBuilder2.prototype = Object; -nb2 = new nameBuilder2('Ryan', 'Dahl'); -assert.doesNotThrow(makeBlock(a.deepEqual, nb1, nb2)); - -// primitives and object -assert.throws(makeBlock(a.deepEqual, null, {}), a.AssertionError); -assert.throws(makeBlock(a.deepEqual, undefined, {}), a.AssertionError); -assert.throws(makeBlock(a.deepEqual, 'a', ['a']), a.AssertionError); -assert.throws(makeBlock(a.deepEqual, 'a', { 0: 'a' }), a.AssertionError); -assert.throws(makeBlock(a.deepEqual, 1, {}), a.AssertionError); -assert.throws(makeBlock(a.deepEqual, true, {}), a.AssertionError); -assert.throws(makeBlock(a.deepEqual, Symbol(), {}), a.AssertionError); - -// primitive wrappers and object -assert.doesNotThrow(makeBlock(a.deepEqual, new String('a'), ['a']), - a.AssertionError); -assert.doesNotThrow(makeBlock(a.deepEqual, new String('a'), { 0: 'a' }), - a.AssertionError); -assert.doesNotThrow(makeBlock(a.deepEqual, new Number(1), {}), - a.AssertionError); -assert.doesNotThrow(makeBlock(a.deepEqual, new Boolean(true), {}), - a.AssertionError); - -// same number of keys but different key names -assert.throws(makeBlock(a.deepEqual, { a: 1 }, { b: 1 }), a.AssertionError); - -//deepStrictEqual -assert.doesNotThrow( - makeBlock(a.deepStrictEqual, new Date(2000, 3, 14), new Date(2000, 3, 14)), - 'deepStrictEqual(new Date(2000, 3, 14), new Date(2000, 3, 14))' -); - -assert.throws( - makeBlock(a.deepStrictEqual, new Date(), new Date(2000, 3, 14)), - a.AssertionError, - 'deepStrictEqual(new Date(), new Date(2000, 3, 14))' -); - -assert.throws( - makeBlock(a.notDeepStrictEqual, new Date(2000, 3, 14), new Date(2000, 3, 14)), - a.AssertionError, - 'notDeepStrictEqual(new Date(2000, 3, 14), new Date(2000, 3, 14))' -); - -assert.doesNotThrow( - makeBlock(a.notDeepStrictEqual, new Date(), new Date(2000, 3, 14)), - 'notDeepStrictEqual(new Date(), new Date(2000, 3, 14))' -); - -assert.doesNotThrow(makeBlock(a.deepStrictEqual, /a/, /a/)); -assert.doesNotThrow(makeBlock(a.deepStrictEqual, /a/g, /a/g)); -assert.doesNotThrow(makeBlock(a.deepStrictEqual, /a/i, /a/i)); -assert.doesNotThrow(makeBlock(a.deepStrictEqual, /a/m, /a/m)); -assert.doesNotThrow(makeBlock(a.deepStrictEqual, /a/igm, /a/igm)); -assert.throws( - makeBlock(a.deepStrictEqual, /ab/, /a/), - common.expectsError({ - code: 'ERR_ASSERTION', - type: a.AssertionError, - message: /^\/ab\/ deepStrictEqual \/a\/$/ - })); -assert.throws( - makeBlock(a.deepStrictEqual, /a/g, /a/), - common.expectsError({ - code: 'ERR_ASSERTION', - type: a.AssertionError, - message: /^\/a\/g deepStrictEqual \/a\/$/ - })); -assert.throws( - makeBlock(a.deepStrictEqual, /a/i, /a/), - common.expectsError({ - code: 'ERR_ASSERTION', - type: a.AssertionError, - message: /^\/a\/i deepStrictEqual \/a\/$/ - })); -assert.throws( - makeBlock(a.deepStrictEqual, /a/m, /a/), - common.expectsError({ - code: 'ERR_ASSERTION', - type: a.AssertionError, - message: /^\/a\/m deepStrictEqual \/a\/$/ - })); -assert.throws( - makeBlock(a.deepStrictEqual, /a/igm, /a/im), - common.expectsError({ - code: 'ERR_ASSERTION', - type: a.AssertionError, - message: /^\/a\/gim deepStrictEqual \/a\/im$/ - })); - -{ - const re1 = /a/; - re1.lastIndex = 3; - assert.doesNotThrow(makeBlock(a.deepStrictEqual, re1, /a/)); -} - -assert.throws(makeBlock(a.deepStrictEqual, 4, '4'), - a.AssertionError, - 'deepStrictEqual(4, \'4\')'); - -assert.throws(makeBlock(a.deepStrictEqual, true, 1), - a.AssertionError, - 'deepStrictEqual(true, 1)'); - -assert.throws(makeBlock(a.deepStrictEqual, 4, '5'), - a.AssertionError, - 'deepStrictEqual(4, \'5\')'); - -// having the same number of owned properties && the same set of keys -assert.doesNotThrow(makeBlock(a.deepStrictEqual, { a: 4 }, { a: 4 })); -assert.doesNotThrow(makeBlock(a.deepStrictEqual, - { a: 4, b: '2' }, - { a: 4, b: '2' })); -assert.throws(makeBlock(a.deepStrictEqual, [4], ['4']), - common.expectsError({ - code: 'ERR_ASSERTION', - type: a.AssertionError, - message: /^\[ 4 ] deepStrictEqual \[ '4' ]$/ - })); -assert.throws(makeBlock(a.deepStrictEqual, { a: 4 }, { a: 4, b: true }), - common.expectsError({ - code: 'ERR_ASSERTION', - type: a.AssertionError, - message: /^{ a: 4 } deepStrictEqual { a: 4, b: true }$/ - })); -assert.throws(makeBlock(a.deepStrictEqual, ['a'], { 0: 'a' }), - common.expectsError({ - code: 'ERR_ASSERTION', - type: a.AssertionError, - message: /^\[ 'a' ] deepStrictEqual { '0': 'a' }$/ - })); -//(although not necessarily the same order), -assert.doesNotThrow(makeBlock(a.deepStrictEqual, - { a: 4, b: '1' }, - { b: '1', a: 4 })); - -assert.throws(makeBlock(a.deepStrictEqual, - [0, 1, 2, 'a', 'b'], - [0, 1, 2, 'b', 'a']), - a.AssertionError); - -assert.doesNotThrow(makeBlock(a.deepStrictEqual, a1, a2)); - -// Prototype check -function Constructor1(first, last) { - this.first = first; - this.last = last; -} - -function Constructor2(first, last) { - this.first = first; - this.last = last; -} - -const obj1 = new Constructor1('Ryan', 'Dahl'); -let obj2 = new Constructor2('Ryan', 'Dahl'); - -assert.throws(makeBlock(a.deepStrictEqual, obj1, obj2), a.AssertionError); +a.notStrictEqual(2, '2'); -Constructor2.prototype = Constructor1.prototype; -obj2 = new Constructor2('Ryan', 'Dahl'); - -assert.doesNotThrow(makeBlock(a.deepStrictEqual, obj1, obj2)); - -// primitives -assert.throws(makeBlock(assert.deepStrictEqual, 4, '4'), - a.AssertionError); -assert.throws(makeBlock(assert.deepStrictEqual, true, 1), - a.AssertionError); -assert.throws(makeBlock(assert.deepStrictEqual, Symbol(), Symbol()), - a.AssertionError); - -const s = Symbol(); -assert.doesNotThrow(makeBlock(assert.deepStrictEqual, s, s)); - - -// primitives and object -assert.throws(makeBlock(a.deepStrictEqual, null, {}), a.AssertionError); -assert.throws(makeBlock(a.deepStrictEqual, undefined, {}), a.AssertionError); -assert.throws(makeBlock(a.deepStrictEqual, 'a', ['a']), a.AssertionError); -assert.throws(makeBlock(a.deepStrictEqual, 'a', { 0: 'a' }), a.AssertionError); -assert.throws(makeBlock(a.deepStrictEqual, 1, {}), a.AssertionError); -assert.throws(makeBlock(a.deepStrictEqual, true, {}), a.AssertionError); -assert.throws(makeBlock(assert.deepStrictEqual, Symbol(), {}), - a.AssertionError); - - -// primitive wrappers and object -assert.throws(makeBlock(a.deepStrictEqual, new String('a'), ['a']), - a.AssertionError); -assert.throws(makeBlock(a.deepStrictEqual, new String('a'), { 0: 'a' }), - a.AssertionError); -assert.throws(makeBlock(a.deepStrictEqual, new Number(1), {}), - a.AssertionError); -assert.throws(makeBlock(a.deepStrictEqual, new Boolean(true), {}), - a.AssertionError); - - -// Testing the throwing +// Testing the throwing. function thrower(errorConstructor) { throw new errorConstructor({}); } -// the basic calls work -assert.throws(makeBlock(thrower, a.AssertionError), - a.AssertionError, 'message'); -assert.throws(makeBlock(thrower, a.AssertionError), a.AssertionError); +// The basic calls work. +assert.throws(() => thrower(a.AssertionError), a.AssertionError, 'message'); +assert.throws(() => thrower(a.AssertionError), a.AssertionError); // eslint-disable-next-line no-restricted-syntax -assert.throws(makeBlock(thrower, a.AssertionError)); +assert.throws(() => thrower(a.AssertionError)); -// if not passing an error, catch all. +// If not passing an error, catch all. // eslint-disable-next-line no-restricted-syntax -assert.throws(makeBlock(thrower, TypeError)); +assert.throws(() => thrower(TypeError)); -// when passing a type, only catch errors of the appropriate type +// When passing a type, only catch errors of the appropriate type. { let threw = false; try { - a.throws(makeBlock(thrower, TypeError), a.AssertionError); + a.throws(() => thrower(TypeError), a.AssertionError); } catch (e) { threw = true; assert.ok(e instanceof TypeError, 'type'); } - assert.strictEqual(true, threw, - 'a.throws with an explicit error is eating extra errors'); + assert.ok(threw, 'a.throws with an explicit error is eating extra errors'); } -// doesNotThrow should pass through all errors +// doesNotThrow should pass through all errors. { let threw = false; try { - a.doesNotThrow(makeBlock(thrower, TypeError), a.AssertionError); + a.doesNotThrow(() => thrower(TypeError), a.AssertionError); } catch (e) { threw = true; assert.ok(e instanceof TypeError); } - assert.strictEqual(true, threw, 'a.doesNotThrow with an explicit error is ' + - 'eating extra errors'); + assert(threw, 'a.doesNotThrow with an explicit error is eating extra errors'); } -// key difference is that throwing our correct error makes an assertion error +// Key difference is that throwing our correct error makes an assertion error. { let threw = false; try { - a.doesNotThrow(makeBlock(thrower, TypeError), TypeError); + a.doesNotThrow(() => thrower(TypeError), TypeError); } catch (e) { threw = true; assert.ok(e instanceof a.AssertionError); } - assert.strictEqual(true, threw, - 'a.doesNotThrow is not catching type matching errors'); + assert.ok(threw, 'a.doesNotThrow is not catching type matching errors'); } assert.throws(() => { assert.ifError(new Error('test error')); }, /^Error: test error$/); -assert.doesNotThrow(() => { assert.ifError(null); }); -assert.doesNotThrow(() => { assert.ifError(); }); +assert.ifError(null); +assert.ifError(); common.expectsError( - () => assert.doesNotThrow(makeBlock(thrower, Error), 'user message'), + () => a.doesNotThrow(() => thrower(Error), 'user message'), { type: a.AssertionError, code: 'ERR_ASSERTION', @@ -476,35 +129,23 @@ common.expectsError( } ); -{ - let threw = false; - try { - assert.doesNotThrow(makeBlock(thrower, Error), 'user message'); - } catch (e) { - threw = true; - common.expectsError({ - code: 'ERR_ASSERTION', - message: /Got unwanted exception: user message\n\[object Object\]/ - })(e); +common.expectsError( + () => a.doesNotThrow(() => thrower(Error), 'user message'), + { + code: 'ERR_ASSERTION', + message: /Got unwanted exception: user message\n\[object Object\]/ } - assert.ok(threw); -} +); -{ - let threw = false; - try { - assert.doesNotThrow(makeBlock(thrower, Error)); - } catch (e) { - threw = true; - common.expectsError({ - code: 'ERR_ASSERTION', - message: /Got unwanted exception\.\n\[object Object\]/ - })(e); +common.expectsError( + () => a.doesNotThrow(() => thrower(Error)), + { + code: 'ERR_ASSERTION', + message: /Got unwanted exception\.\n\[object Object\]/ } - assert.ok(threw); -} +); -// make sure that validating using constructor really works +// Make sure that validating using constructor really works. { let threw = false; try { @@ -520,11 +161,11 @@ common.expectsError( assert.ok(threw, 'wrong constructor validation'); } -// use a RegExp to validate error message -a.throws(makeBlock(thrower, TypeError), /\[object Object\]/); +// Use a RegExp to validate the error message. +a.throws(() => thrower(TypeError), /\[object Object\]/); -// use a fn to validate error object -a.throws(makeBlock(thrower, TypeError), (err) => { +// Use a fn to validate the error object. +a.throws(() => thrower(TypeError), (err) => { if ((err instanceof TypeError) && /\[object Object\]/.test(err)) { return true; } @@ -533,18 +174,12 @@ a.throws(makeBlock(thrower, TypeError), (err) => { // https://github.com/nodejs/node/issues/3188 { let threw = false; - let AnotherErrorType; try { const ES6Error = class extends Error {}; - AnotherErrorType = class extends Error {}; - const functionThatThrows = () => { - throw new AnotherErrorType('foo'); - }; - - assert.throws(functionThatThrows, ES6Error); + assert.throws(() => { throw new AnotherErrorType('foo'); }, ES6Error); } catch (e) { threw = true; assert(e instanceof AnotherErrorType, @@ -554,7 +189,7 @@ a.throws(makeBlock(thrower, TypeError), (err) => { assert.ok(threw); } -// check messages from assert.throws() +// Check messages from assert.throws(). { const noop = () => {}; assert.throws( @@ -634,6 +269,7 @@ testAssertionMessage({ a: NaN, b: Infinity, c: -Infinity }, } catch (e) { threw = true; assert.strictEqual(e.message, 'Missing expected exception.'); + assert.ok(!e.stack.includes('throws'), e.stack); } assert.ok(threw); } @@ -658,7 +294,7 @@ try { let threw = false; const rangeError = new RangeError('my range'); - // verify custom errors + // Verify custom errors. try { assert.strictEqual(1, 2, rangeError); } catch (e) { @@ -669,41 +305,36 @@ try { assert.ok(threw); threw = false; - // verify AssertionError is the result from doesNotThrow with custom Error + // Verify AssertionError is the result from doesNotThrow with custom Error. try { - assert.doesNotThrow(() => { + a.doesNotThrow(() => { throw new TypeError('wrong type'); }, TypeError, rangeError); } catch (e) { threw = true; assert.ok(e.message.includes(rangeError.message)); assert.ok(e instanceof assert.AssertionError); + assert.ok(!e.stack.includes('doesNotThrow'), e.stack); } assert.ok(threw); } { - // Verify that throws() and doesNotThrow() throw on non-function block + // Verify that throws() and doesNotThrow() throw on non-function block. function typeName(value) { return value === null ? 'null' : typeof value; } const testBlockTypeError = (method, block) => { - let threw = true; - - try { - method(block); - threw = false; - } catch (e) { - common.expectsError({ + common.expectsError( + () => method(block), + { code: 'ERR_INVALID_ARG_TYPE', type: TypeError, message: 'The "block" argument must be of type Function. Received ' + - `type ${typeName(block)}` - })(e); - } - - assert.ok(threw); + `type ${typeName(block)}` + } + ); }; testBlockTypeError(assert.throws, 'string'); @@ -736,10 +367,11 @@ assert.throws(() => { assert.strictEqual('A'.repeat(1000), ''); }, common.expectsError({ code: 'ERR_ASSERTION', - message: new RegExp(`^'${'A'.repeat(127)} === ''$`) })); + message: /^'A{124}\.\.\. === ''$/ +})); { - // bad args to AssertionError constructor should throw TypeError + // Bad args to AssertionError constructor should throw TypeError. const args = [1, true, false, '', null, Infinity, Symbol('test'), undefined]; const re = /^The "options" argument must be of type Object$/; args.forEach((input) => { @@ -761,3 +393,294 @@ common.expectsError( message: /^'Error: foo' === 'Error: foobar'$/ } ); + +// Test strict assert +{ + const a = require('assert'); + const assert = require('assert').strict; + /* eslint-disable no-restricted-properties */ + assert.throws(() => assert.equal(1, true), assert.AssertionError); + assert.notEqual(0, false); + assert.throws(() => assert.deepEqual(1, true), assert.AssertionError); + assert.notDeepEqual(0, false); + assert.equal(assert.strict, assert.strict.strict); + assert.equal(assert.equal, assert.strictEqual); + assert.equal(assert.deepEqual, assert.deepStrictEqual); + assert.equal(assert.notEqual, assert.notStrictEqual); + assert.equal(assert.notDeepEqual, assert.notDeepStrictEqual); + assert.equal(Object.keys(assert).length, Object.keys(a).length); + assert(7); + common.expectsError( + () => assert(), + { + code: 'ERR_ASSERTION', + type: assert.AssertionError, + message: 'undefined == true' + } + ); + + // Test error diffs + const colors = process.stdout.isTTY && process.stdout.getColorDepth() > 1; + const start = 'Input A expected to deepStrictEqual input B:'; + const actExp = colors ? + '\u001b[32m+ expected\u001b[39m \u001b[31m- actual\u001b[39m' : + '+ expected - actual'; + const plus = colors ? '\u001b[32m+\u001b[39m' : '+'; + const minus = colors ? '\u001b[31m-\u001b[39m' : '-'; + let message = [ + start, + `${actExp} ... Lines skipped`, + '', + ' [', + ' [', + '...', + ' 2,', + `${minus} 3`, + `${plus} '3'`, + ' ]', + '...', + ' 5', + ' ]'].join('\n'); + assert.throws( + () => assert.deepEqual([[[1, 2, 3]], 4, 5], [[[1, 2, '3']], 4, 5]), + { message }); + + message = [ + start, + `${actExp} ... Lines skipped`, + '', + ' [', + ' 1,', + '...', + ' 0,', + `${plus} 1,`, + ' 1,', + '...', + ' 1', + ' ]' + ].join('\n'); + assert.throws( + () => assert.deepEqual( + [1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1]), + { message }); + + message = [ + start, + `${actExp} ... Lines skipped`, + '', + ' [', + ' 1,', + '...', + ' 0,', + `${minus} 1,`, + ' 1,', + '...', + ' 1', + ' ]' + ].join('\n'); + assert.throws( + () => assert.deepEqual( + [1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1]), + { message }); + + message = [ + start, + actExp, + '', + ' [', + ' 1,', + `${minus} 2,`, + `${plus} 1,`, + ' 1,', + ' 1,', + ' 0,', + `${minus} 1,`, + ' 1', + ' ]' + ].join('\n'); + assert.throws( + () => assert.deepEqual( + [1, 2, 1, 1, 0, 1, 1], + [1, 1, 1, 1, 0, 1]), + { message }); + + message = [ + start, + actExp, + '', + `${minus} [`, + `${minus} 1,`, + `${minus} 2,`, + `${minus} 1`, + `${minus} ]`, + `${plus} undefined`, + ].join('\n'); + assert.throws( + () => assert.deepEqual([1, 2, 1]), + { message }); + + message = [ + start, + actExp, + '', + ' [', + `${minus} 1,`, + ' 2,', + ' 1', + ' ]' + ].join('\n'); + assert.throws( + () => assert.deepEqual([1, 2, 1], [2, 1]), + { message }); + + message = `${start}\n` + + `${actExp} ... Lines skipped\n` + + '\n' + + ' [\n' + + `${minus} 1,\n`.repeat(10) + + '...\n' + + `${plus} 2,\n`.repeat(10) + + '...'; + assert.throws( + () => assert.deepEqual(Array(12).fill(1), Array(12).fill(2)), + { message }); + + const obj1 = {}; + const obj2 = { loop: 'forever' }; + obj2[inspect.custom] = () => '{}'; + // No infinite loop and no custom inspect. + assert.throws(() => assert.deepEqual(obj1, obj2), { + message: `${start}\n` + + `${actExp}\n` + + '\n' + + `${minus} {}\n` + + `${plus} {\n` + + `${plus} loop: 'forever',\n` + + `${plus} [Symbol(util.inspect.custom)]: [Function]\n` + + `${plus} }` + }); + + // notDeepEqual tests + message = 'Identical input passed to notDeepStrictEqual:\n[\n 1\n]'; + assert.throws( + () => assert.notDeepEqual([1], [1]), + { message }); + + message = 'Identical input passed to notDeepStrictEqual:' + + `\n[${'\n 1,'.repeat(18)}\n...`; + const data = Array(21).fill(1); + assert.throws( + () => assert.notDeepEqual(data, data), + { message }); + /* eslint-enable no-restricted-properties */ +} + +common.expectsError( + () => assert.ok(null), + { + code: 'ERR_ASSERTION', + type: assert.AssertionError, + message: 'null == true' + } +); + +common.expectsError( + // eslint-disable-next-line no-restricted-syntax + () => assert.throws(() => {}, 'Error message', 'message'), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError, + message: 'The "error" argument must be one of type Function or RegExp. ' + + 'Received type string' + } +); + +{ + const errFn = () => { + const err = new TypeError('Wrong value'); + err.code = 404; + throw err; + }; + const errObj = { + name: 'TypeError', + message: 'Wrong value' + }; + assert.throws(errFn, errObj); + + errObj.code = 404; + assert.throws(errFn, errObj); + + errObj.code = '404'; + common.expectsError( + // eslint-disable-next-line no-restricted-syntax + () => assert.throws(errFn, errObj), + { + code: 'ERR_ASSERTION', + type: assert.AssertionError, + message: 'code: expected \'404\', not 404' + } + ); + + errObj.code = 404; + errObj.foo = 'bar'; + common.expectsError( + // eslint-disable-next-line no-restricted-syntax + () => assert.throws(errFn, errObj), + { + code: 'ERR_ASSERTION', + type: assert.AssertionError, + message: 'foo: expected \'bar\', not undefined' + } + ); + + common.expectsError( + () => assert.throws(() => { throw new Error(); }, { foo: 'bar' }, 'foobar'), + { + type: assert.AssertionError, + code: 'ERR_ASSERTION', + message: 'foobar' + } + ); + + common.expectsError( + () => a.doesNotThrow(() => { throw new Error(); }, { foo: 'bar' }), + { + type: TypeError, + code: 'ERR_INVALID_ARG_TYPE', + message: 'The "expected" argument must be one of type Function or ' + + 'RegExp. Received type object' + } + ); + + assert.throws(() => { throw new Error('e'); }, new Error('e')); + common.expectsError( + () => assert.throws(() => { throw new TypeError('e'); }, new Error('e')), + { + type: assert.AssertionError, + code: 'ERR_ASSERTION', + message: "name: expected 'Error', not 'TypeError'" + } + ); + common.expectsError( + () => assert.throws(() => { throw new Error('foo'); }, new Error('')), + { + type: assert.AssertionError, + code: 'ERR_ASSERTION', + message: "message: expected '', not 'foo'" + } + ); + + // eslint-disable-next-line no-throw-literal + assert.throws(() => { throw undefined; }, /undefined/); + common.expectsError( + // eslint-disable-next-line no-throw-literal + () => a.doesNotThrow(() => { throw undefined; }), + { + type: assert.AssertionError, + code: 'ERR_ASSERTION', + message: 'Got unwanted exception.\nundefined' + } + ); +} diff --git a/test/parallel/test-benchmark-url.js b/test/parallel/test-benchmark-url.js new file mode 100644 index 00000000000000..e4bcf5017004f4 --- /dev/null +++ b/test/parallel/test-benchmark-url.js @@ -0,0 +1,22 @@ +'use strict'; + +require('../common'); + +const runBenchmark = require('../common/benchmark'); + +runBenchmark('url', + [ + 'method=legacy', + 'loopMethod=forEach', + 'accessMethod=get', + 'type=short', + 'searchParam=noencode', + 'href=short', + 'input=short', + 'domain=empty', + 'path=up', + 'to=ascii', + 'prop=href', + 'n=1', + ], + { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); diff --git a/test/parallel/test-buffer-alloc.js b/test/parallel/test-buffer-alloc.js index 7143133cd103ff..20e91377cd7fdf 100644 --- a/test/parallel/test-buffer-alloc.js +++ b/test/parallel/test-buffer-alloc.js @@ -62,17 +62,17 @@ assert.throws(() => b.write('test', 'utf8', 0), /is no longer supported/); -// try to create 0-length buffers -assert.doesNotThrow(() => Buffer.from('')); -assert.doesNotThrow(() => Buffer.from('', 'ascii')); -assert.doesNotThrow(() => Buffer.from('', 'latin1')); -assert.doesNotThrow(() => Buffer.alloc(0)); -assert.doesNotThrow(() => Buffer.allocUnsafe(0)); -assert.doesNotThrow(() => new Buffer('')); -assert.doesNotThrow(() => new Buffer('', 'ascii')); -assert.doesNotThrow(() => new Buffer('', 'latin1')); -assert.doesNotThrow(() => new Buffer('', 'binary')); -assert.doesNotThrow(() => Buffer(0)); +// Try to create 0-length buffers. Should not throw. +Buffer.from(''); +Buffer.from('', 'ascii'); +Buffer.from('', 'latin1'); +Buffer.alloc(0); +Buffer.allocUnsafe(0); +new Buffer(''); +new Buffer('', 'ascii'); +new Buffer('', 'latin1'); +new Buffer('', 'binary'); +Buffer(0); // try to write a 0-length string beyond the end of b assert.throws(() => b.write('', 2048), RangeError); @@ -107,9 +107,9 @@ b.copy(Buffer.alloc(1), 0, 2048, 2048); assert.strictEqual(writeTest.toString(), 'nodejs'); } -// Offset points to the end of the buffer +// Offset points to the end of the buffer and does not throw. // (see https://github.com/nodejs/node/issues/8127). -assert.doesNotThrow(() => Buffer.alloc(1).write('', 1, 0)); +Buffer.alloc(1).write('', 1, 0); // ASCII slice test { @@ -963,7 +963,7 @@ assert.strictEqual(SlowBuffer.prototype.offset, undefined); Buffer.from('')); // Check pool offset after that by trying to write string into the pool. - assert.doesNotThrow(() => Buffer.from('abc')); + Buffer.from('abc'); } @@ -992,13 +992,13 @@ common.expectsError(() => { assert.strictEqual(ubuf.buffer.byteLength, 10); } -// Regression test -assert.doesNotThrow(() => Buffer.from(new ArrayBuffer())); +// Regression test to verify that an empty ArrayBuffer does not throw. +Buffer.from(new ArrayBuffer()); -// Test that ArrayBuffer from a different context is detected correctly +// Test that ArrayBuffer from a different context is detected correctly. const arrayBuf = vm.runInNewContext('new ArrayBuffer()'); -assert.doesNotThrow(() => Buffer.from(arrayBuf)); -assert.doesNotThrow(() => Buffer.from({ buffer: arrayBuf })); +Buffer.from(arrayBuf); +Buffer.from({ buffer: arrayBuf }); assert.throws(() => Buffer.alloc({ valueOf: () => 1 }), /"size" argument must be of type number/); diff --git a/test/parallel/test-buffer-bad-overload.js b/test/parallel/test-buffer-bad-overload.js index b442a3e8a29630..63acb8ebfb6d49 100644 --- a/test/parallel/test-buffer-bad-overload.js +++ b/test/parallel/test-buffer-bad-overload.js @@ -2,9 +2,7 @@ const common = require('../common'); const assert = require('assert'); -assert.doesNotThrow(function() { - Buffer.allocUnsafe(10); -}); +Buffer.allocUnsafe(10); // Should not throw. const err = common.expectsError({ code: 'ERR_INVALID_ARG_TYPE', @@ -16,6 +14,4 @@ assert.throws(function() { Buffer.from(10, 'hex'); }, err); -assert.doesNotThrow(function() { - Buffer.from('deadbeaf', 'hex'); -}); +Buffer.from('deadbeaf', 'hex'); // Should not throw. diff --git a/test/parallel/test-buffer-constants.js b/test/parallel/test-buffer-constants.js index 820c8dc993ed8e..f6f0dbddc39d3e 100644 --- a/test/parallel/test-buffer-constants.js +++ b/test/parallel/test-buffer-constants.js @@ -11,7 +11,7 @@ assert(MAX_STRING_LENGTH <= MAX_LENGTH); assert.throws(() => ' '.repeat(MAX_STRING_LENGTH + 1), /^RangeError: Invalid string length$/); -assert.doesNotThrow(() => ' '.repeat(MAX_STRING_LENGTH)); +' '.repeat(MAX_STRING_LENGTH); // Should not throw. // Legacy values match: assert.strictEqual(kMaxLength, MAX_LENGTH); diff --git a/test/parallel/test-buffer-copy.js b/test/parallel/test-buffer-copy.js index 1b10dadb5b709b..5c82f4de28dbee 100644 --- a/test/parallel/test-buffer-copy.js +++ b/test/parallel/test-buffer-copy.js @@ -92,8 +92,8 @@ const bb = Buffer.allocUnsafe(10); bb.fill('hello crazy world'); -// try to copy from before the beginning of b -assert.doesNotThrow(() => { b.copy(c, 0, 100, 10); }); +// Try to copy from before the beginning of b. Should not throw. +b.copy(c, 0, 100, 10); // copy throws at negative sourceStart assert.throws(function() { diff --git a/test/parallel/test-buffer-fill.js b/test/parallel/test-buffer-fill.js index 14f44767c4452a..4d9c018c7f7410 100644 --- a/test/parallel/test-buffer-fill.js +++ b/test/parallel/test-buffer-fill.js @@ -136,17 +136,13 @@ testBufs('61c8b462c8b563c8b6', 12, 1, 'hex'); { const buf = Buffer.allocUnsafe(SIZE); - assert.doesNotThrow(() => { - // Make sure this operation doesn't go on forever. - buf.fill('yKJh', 'hex'); - }); + // Make sure this operation doesn't go on forever. + buf.fill('yKJh', 'hex'); // Should not throw. } { const buf = Buffer.allocUnsafe(SIZE); - assert.doesNotThrow(() => { - buf.fill('\u0222', 'hex'); - }); + buf.fill('\u0222', 'hex'); // Should not throw. } // BASE64 diff --git a/test/parallel/test-buffer-inspect.js b/test/parallel/test-buffer-inspect.js index 6890e27a3fd5b9..aa703db67dfac4 100644 --- a/test/parallel/test-buffer-inspect.js +++ b/test/parallel/test-buffer-inspect.js @@ -51,10 +51,8 @@ assert.strictEqual(util.inspect(s), expected); buffer.INSPECT_MAX_BYTES = Infinity; -assert.doesNotThrow(function() { - assert.strictEqual(util.inspect(b), expected); - assert.strictEqual(util.inspect(s), expected); -}); +assert.strictEqual(util.inspect(b), expected); +assert.strictEqual(util.inspect(s), expected); b.inspect = undefined; assert.strictEqual(util.inspect(b), expected); diff --git a/test/parallel/test-buffer-read.js b/test/parallel/test-buffer-read.js index 8a8d239a6f30e1..3f9c20e194f6ca 100644 --- a/test/parallel/test-buffer-read.js +++ b/test/parallel/test-buffer-read.js @@ -15,11 +15,7 @@ function read(buff, funx, args, expected) { } ); - assert.doesNotThrow( - () => assert.strictEqual(buff[funx](...args, true), expected), - 'noAssert does not change return value for valid ranges' - ); - + assert.strictEqual(buff[funx](...args, true), expected); } // testing basic functionality of readDoubleBE() and readDoubleLE() diff --git a/test/parallel/test-buffer-sharedarraybuffer.js b/test/parallel/test-buffer-sharedarraybuffer.js index 4485aa8cfc6efe..0252847c054c1d 100644 --- a/test/parallel/test-buffer-sharedarraybuffer.js +++ b/test/parallel/test-buffer-sharedarraybuffer.js @@ -22,8 +22,7 @@ arr2[1] = 6000; assert.deepStrictEqual(arr_buf, ar_buf); -// Checks for calling Buffer.byteLength on a SharedArrayBuffer - +// Checks for calling Buffer.byteLength on a SharedArrayBuffer. assert.strictEqual(Buffer.byteLength(sab), sab.byteLength); -assert.doesNotThrow(() => Buffer.from({ buffer: sab })); +Buffer.from({ buffer: sab }); // Should not throw. diff --git a/test/parallel/test-buffer-slice.js b/test/parallel/test-buffer-slice.js index 8f764da09d00b0..6175370a9bccee 100644 --- a/test/parallel/test-buffer-slice.js +++ b/test/parallel/test-buffer-slice.js @@ -77,9 +77,8 @@ expectedSameBufs.forEach(([buf1, buf2]) => { const utf16Buf = Buffer.from('0123456789', 'utf16le'); assert.deepStrictEqual(utf16Buf.slice(0, 6), Buffer.from('012', 'utf16le')); -// try to slice a zero length Buffer -// see https://github.com/joyent/node/issues/5881 -assert.doesNotThrow(() => Buffer.alloc(0).slice(0, 1)); +// Try to slice a zero length Buffer. +// See https://github.com/joyent/node/issues/5881 assert.strictEqual(Buffer.alloc(0).slice(0, 1).length, 0); { diff --git a/test/parallel/test-child-process-detached.js b/test/parallel/test-child-process-detached.js index f53983c29e791c..8242536d1f49ad 100644 --- a/test/parallel/test-child-process-detached.js +++ b/test/parallel/test-child-process-detached.js @@ -39,7 +39,5 @@ process.on('exit', function() { assert.throws(function() { process.kill(child.pid); }, /^Error: kill ESRCH$/); - assert.doesNotThrow(function() { - process.kill(persistentPid); - }); + process.kill(persistentPid); }); diff --git a/test/parallel/test-child-process-spawn-typeerror.js b/test/parallel/test-child-process-spawn-typeerror.js index 065d1345d54ad9..9855c0cfd99fa6 100644 --- a/test/parallel/test-child-process-spawn-typeerror.js +++ b/test/parallel/test-child-process-spawn-typeerror.js @@ -38,24 +38,13 @@ assert.throws(function() { child.on('error', common.mustNotCall()); }, TypeError); -// verify that valid argument combinations do not throw -assert.doesNotThrow(function() { - spawn(cmd); -}); +// Verify that valid argument combinations do not throw. +spawn(cmd); +spawn(cmd, []); +spawn(cmd, {}); +spawn(cmd, [], {}); -assert.doesNotThrow(function() { - spawn(cmd, []); -}); - -assert.doesNotThrow(function() { - spawn(cmd, {}); -}); - -assert.doesNotThrow(function() { - spawn(cmd, [], {}); -}); - -// verify that invalid argument combinations throw +// Verify that invalid argument combinations throw. assert.throws(function() { spawn(); }, invalidFileMsg); @@ -85,7 +74,7 @@ assert.throws(function() { spawn(cmd, [], 1); }, invalidOptionsMsg); -// Argument types for combinatorics +// Argument types for combinatorics. const a = []; const o = {}; function c() {} @@ -98,14 +87,14 @@ const n = null; // (f, a) // (f, a, o) // (f, o) -assert.doesNotThrow(function() { spawn(cmd); }); -assert.doesNotThrow(function() { spawn(cmd, a); }); -assert.doesNotThrow(function() { spawn(cmd, a, o); }); -assert.doesNotThrow(function() { spawn(cmd, o); }); +spawn(cmd); +spawn(cmd, a); +spawn(cmd, a, o); +spawn(cmd, o); -// Variants of undefined as explicit 'no argument' at a position -assert.doesNotThrow(function() { spawn(cmd, u, o); }); -assert.doesNotThrow(function() { spawn(cmd, a, u); }); +// Variants of undefined as explicit 'no argument' at a position. +spawn(cmd, u, o); +spawn(cmd, a, u); assert.throws(function() { spawn(cmd, n, o); }, TypeError); assert.throws(function() { spawn(cmd, a, n); }, TypeError); @@ -114,7 +103,7 @@ assert.throws(function() { spawn(cmd, s); }, TypeError); assert.throws(function() { spawn(cmd, a, s); }, TypeError); -// verify that execFile has same argument parsing behavior as spawn +// Verify that execFile has same argument parsing behavior as spawn. // // function execFile(file=f [,args=a] [, options=o] [, callback=c]) has valid // combinations: @@ -126,38 +115,38 @@ assert.throws(function() { spawn(cmd, a, s); }, TypeError); // (f, o) // (f, o, c) // (f, c) -assert.doesNotThrow(function() { execFile(cmd); }); -assert.doesNotThrow(function() { execFile(cmd, a); }); -assert.doesNotThrow(function() { execFile(cmd, a, o); }); -assert.doesNotThrow(function() { execFile(cmd, a, o, c); }); -assert.doesNotThrow(function() { execFile(cmd, a, c); }); -assert.doesNotThrow(function() { execFile(cmd, o); }); -assert.doesNotThrow(function() { execFile(cmd, o, c); }); -assert.doesNotThrow(function() { execFile(cmd, c); }); - -// Variants of undefined as explicit 'no argument' at a position -assert.doesNotThrow(function() { execFile(cmd, u, o, c); }); -assert.doesNotThrow(function() { execFile(cmd, a, u, c); }); -assert.doesNotThrow(function() { execFile(cmd, a, o, u); }); -assert.doesNotThrow(function() { execFile(cmd, n, o, c); }); -assert.doesNotThrow(function() { execFile(cmd, a, n, c); }); -assert.doesNotThrow(function() { execFile(cmd, a, o, n); }); -assert.doesNotThrow(function() { execFile(cmd, u, u, u); }); -assert.doesNotThrow(function() { execFile(cmd, u, u, c); }); -assert.doesNotThrow(function() { execFile(cmd, u, o, u); }); -assert.doesNotThrow(function() { execFile(cmd, a, u, u); }); -assert.doesNotThrow(function() { execFile(cmd, n, n, n); }); -assert.doesNotThrow(function() { execFile(cmd, n, n, c); }); -assert.doesNotThrow(function() { execFile(cmd, n, o, n); }); -assert.doesNotThrow(function() { execFile(cmd, a, n, n); }); -assert.doesNotThrow(function() { execFile(cmd, a, u); }); -assert.doesNotThrow(function() { execFile(cmd, a, n); }); -assert.doesNotThrow(function() { execFile(cmd, o, u); }); -assert.doesNotThrow(function() { execFile(cmd, o, n); }); -assert.doesNotThrow(function() { execFile(cmd, c, u); }); -assert.doesNotThrow(function() { execFile(cmd, c, n); }); - -// string is invalid in arg position (this may seem strange, but is +execFile(cmd); +execFile(cmd, a); +execFile(cmd, a, o); +execFile(cmd, a, o, c); +execFile(cmd, a, c); +execFile(cmd, o); +execFile(cmd, o, c); +execFile(cmd, c); + +// Variants of undefined as explicit 'no argument' at a position. +execFile(cmd, u, o, c); +execFile(cmd, a, u, c); +execFile(cmd, a, o, u); +execFile(cmd, n, o, c); +execFile(cmd, a, n, c); +execFile(cmd, a, o, n); +execFile(cmd, u, u, u); +execFile(cmd, u, u, c); +execFile(cmd, u, o, u); +execFile(cmd, a, u, u); +execFile(cmd, n, n, n); +execFile(cmd, n, n, c); +execFile(cmd, n, o, n); +execFile(cmd, a, n, n); +execFile(cmd, a, u); +execFile(cmd, a, n); +execFile(cmd, o, u); +execFile(cmd, o, n); +execFile(cmd, c, u); +execFile(cmd, c, n); + +// String is invalid in arg position (this may seem strange, but is // consistent across node API, cf. `net.createServer('not options', 'not // callback')` assert.throws(function() { execFile(cmd, s, o, c); }, TypeError); @@ -171,26 +160,25 @@ assert.throws(function() { execFile(cmd, a, u, s); }, TypeError); assert.throws(function() { execFile(cmd, a, n, s); }, TypeError); assert.throws(function() { execFile(cmd, u, o, s); }, TypeError); assert.throws(function() { execFile(cmd, n, o, s); }, TypeError); -assert.doesNotThrow(function() { execFile(cmd, c, s); }); - +execFile(cmd, c, s); // Should not throw. -// verify that fork has same argument parsing behavior as spawn +// Verify that fork has same argument parsing behavior as spawn. // // function fork(file=f [,args=a] [, options=o]) has valid combinations: // (f) // (f, a) // (f, a, o) // (f, o) -assert.doesNotThrow(function() { fork(empty); }); -assert.doesNotThrow(function() { fork(empty, a); }); -assert.doesNotThrow(function() { fork(empty, a, o); }); -assert.doesNotThrow(function() { fork(empty, o); }); -assert.doesNotThrow(function() { fork(empty, u, u); }); -assert.doesNotThrow(function() { fork(empty, u, o); }); -assert.doesNotThrow(function() { fork(empty, a, u); }); -assert.doesNotThrow(function() { fork(empty, n, n); }); -assert.doesNotThrow(function() { fork(empty, n, o); }); -assert.doesNotThrow(function() { fork(empty, a, n); }); +fork(empty); +fork(empty, a); +fork(empty, a, o); +fork(empty, o); +fork(empty, u, u); +fork(empty, u, o); +fork(empty, a, u); +fork(empty, n, n); +fork(empty, n, o); +fork(empty, a, n); assert.throws(function() { fork(empty, s); }, TypeError); assert.throws(function() { fork(empty, a, s); }, TypeError); diff --git a/test/parallel/test-regress-GH-3238.js b/test/parallel/test-cluster-kill-disconnect.js similarity index 71% rename from test/parallel/test-regress-GH-3238.js rename to test/parallel/test-cluster-kill-disconnect.js index dd65d849d57503..f5407612a83b5f 100644 --- a/test/parallel/test-regress-GH-3238.js +++ b/test/parallel/test-cluster-kill-disconnect.js @@ -1,5 +1,11 @@ 'use strict'; const common = require('../common'); + +// Check that cluster works perfectly for both `kill` and `disconnect` cases. +// Also take into account that the `disconnect` event may be received after the +// `exit` event. +// https://github.com/nodejs/node/issues/3238 + const assert = require('assert'); const cluster = require('cluster'); diff --git a/test/parallel/test-cluster-worker-kill.js b/test/parallel/test-cluster-worker-kill.js index 38e2deb1555c2d..bb2d3495d95a4d 100644 --- a/test/parallel/test-cluster-worker-kill.js +++ b/test/parallel/test-cluster-worker-kill.js @@ -40,29 +40,28 @@ if (cluster.isWorker) { } else if (cluster.isMaster) { - const KILL_SIGNAL = 'SIGKILL', - expected_results = { - cluster_emitDisconnect: [1, "the cluster did not emit 'disconnect'"], - cluster_emitExit: [1, "the cluster did not emit 'exit'"], - cluster_exitCode: [null, 'the cluster exited w/ incorrect exitCode'], - cluster_signalCode: [KILL_SIGNAL, - 'the cluster exited w/ incorrect signalCode'], - worker_emitDisconnect: [1, "the worker did not emit 'disconnect'"], - worker_emitExit: [1, "the worker did not emit 'exit'"], - worker_state: ['disconnected', 'the worker state is incorrect'], - worker_exitedAfter: [false, - 'the .exitedAfterDisconnect flag is incorrect'], - worker_died: [true, 'the worker is still running'], - worker_exitCode: [null, 'the worker exited w/ incorrect exitCode'], - worker_signalCode: [KILL_SIGNAL, - 'the worker exited w/ incorrect signalCode'] - }, - results = { - cluster_emitDisconnect: 0, - cluster_emitExit: 0, - worker_emitDisconnect: 0, - worker_emitExit: 0 - }; + const KILL_SIGNAL = 'SIGKILL'; + const expected_results = { + cluster_emitDisconnect: [1, "the cluster did not emit 'disconnect'"], + cluster_emitExit: [1, "the cluster did not emit 'exit'"], + cluster_exitCode: [null, 'the cluster exited w/ incorrect exitCode'], + cluster_signalCode: [KILL_SIGNAL, + 'the cluster exited w/ incorrect signalCode'], + worker_emitDisconnect: [1, "the worker did not emit 'disconnect'"], + worker_emitExit: [1, "the worker did not emit 'exit'"], + worker_state: ['disconnected', 'the worker state is incorrect'], + worker_exitedAfter: [false, 'the .exitedAfterDisconnect flag is incorrect'], + worker_died: [true, 'the worker is still running'], + worker_exitCode: [null, 'the worker exited w/ incorrect exitCode'], + worker_signalCode: [KILL_SIGNAL, + 'the worker exited w/ incorrect signalCode'] + }; + const results = { + cluster_emitDisconnect: 0, + cluster_emitExit: 0, + worker_emitDisconnect: 0, + worker_emitExit: 0 + }; // start worker diff --git a/test/parallel/test-console-async-write-error.js b/test/parallel/test-console-async-write-error.js index 63e8bfbc881e4c..be76c89832f611 100644 --- a/test/parallel/test-console-async-write-error.js +++ b/test/parallel/test-console-async-write-error.js @@ -2,7 +2,6 @@ const common = require('../common'); const { Console } = require('console'); const { Writable } = require('stream'); -const assert = require('assert'); for (const method of ['dir', 'log', 'warn']) { const out = new Writable({ @@ -12,8 +11,5 @@ for (const method of ['dir', 'log', 'warn']) { }); const c = new Console(out, out, true); - - assert.doesNotThrow(() => { - c[method]('abc'); - }); + c[method]('abc'); // Should not throw. } diff --git a/test/parallel/test-console-instance.js b/test/parallel/test-console-instance.js index 7e931e0d3b30de..2fd07ac41219a9 100644 --- a/test/parallel/test-console-instance.js +++ b/test/parallel/test-console-instance.js @@ -28,15 +28,15 @@ const Console = require('console').Console; const out = new Stream(); const err = new Stream(); -// ensure the Console instance doesn't write to the -// process' "stdout" or "stderr" streams +// Ensure the Console instance doesn't write to the +// process' "stdout" or "stderr" streams. process.stdout.write = process.stderr.write = common.mustNotCall(); -// make sure that the "Console" function exists +// Make sure that the "Console" function exists. assert.strictEqual('function', typeof Console); -// make sure that the Console constructor throws -// when not given a writable stream instance +// Make sure that the Console constructor throws +// when not given a writable stream instance. common.expectsError( () => { new Console(); }, { @@ -46,7 +46,7 @@ common.expectsError( } ); -// Console constructor should throw if stderr exists but is not writable +// Console constructor should throw if stderr exists but is not writable. common.expectsError( () => { out.write = () => {}; @@ -77,7 +77,7 @@ out.write = common.mustCall((d) => { c.dir({ foo: 1 }); -// ensure that the console functions are bound to the console instance +// Ensure that the console functions are bound to the console instance. let called = 0; out.write = common.mustCall((d) => { called++; @@ -86,10 +86,8 @@ out.write = common.mustCall((d) => { [1, 2, 3].forEach(c.log); -// Console() detects if it is called without `new` keyword -assert.doesNotThrow(() => { - Console(out, err); -}); +// Console() detects if it is called without `new` keyword. +Console(out, err); // Instance that does not ignore the stream errors. const c2 = new Console(out, err, false); diff --git a/test/parallel/test-console-sync-write-error.js b/test/parallel/test-console-sync-write-error.js index fb350d463bb35d..bf916ff5b84e8d 100644 --- a/test/parallel/test-console-sync-write-error.js +++ b/test/parallel/test-console-sync-write-error.js @@ -2,7 +2,6 @@ const common = require('../common'); const { Console } = require('console'); const { Writable } = require('stream'); -const assert = require('assert'); for (const method of ['dir', 'log', 'warn']) { { @@ -13,10 +12,7 @@ for (const method of ['dir', 'log', 'warn']) { }); const c = new Console(out, out, true); - - assert.doesNotThrow(() => { - c[method]('abc'); - }); + c[method]('abc'); // Should not throw. } { @@ -27,10 +23,7 @@ for (const method of ['dir', 'log', 'warn']) { }); const c = new Console(out, out, true); - - assert.doesNotThrow(() => { - c[method]('abc'); - }); + c[method]('abc'); // Should not throw. } { @@ -41,9 +34,6 @@ for (const method of ['dir', 'log', 'warn']) { }); const c = new Console(out, out, true); - - assert.doesNotThrow(() => { - c[method]('abc'); - }); + c[method]('abc'); // Should not throw. } } diff --git a/test/parallel/test-console.js b/test/parallel/test-console.js index c0ca672eba7141..234723285d1556 100644 --- a/test/parallel/test-console.js +++ b/test/parallel/test-console.js @@ -29,18 +29,14 @@ assert.ok(process.stderr.writable); assert.strictEqual(typeof process.stdout.fd, 'number'); assert.strictEqual(typeof process.stderr.fd, 'number'); -assert.doesNotThrow(function() { - process.once('warning', common.mustCall((warning) => { - assert(/no such label/.test(warning.message)); - })); +process.once('warning', common.mustCall((warning) => { + assert(/no such label/.test(warning.message)); +})); - console.timeEnd('no such label'); -}); +console.timeEnd('no such label'); -assert.doesNotThrow(function() { - console.time('label'); - console.timeEnd('label'); -}); +console.time('label'); +console.timeEnd('label'); // Check that the `Error` is a `TypeError` but do not check the message as it // will be different in different JavaScript engines. @@ -207,9 +203,7 @@ common.expectsError(() => { message: /^should throw$/ }); -assert.doesNotThrow(() => { - console.assert(true, 'this should not throw'); -}); +console.assert(true, 'this should not throw'); // hijack stderr to catch `process.emitWarning` which is using // `process.nextTick` diff --git a/test/parallel/test-crypto-binary-default.js b/test/parallel/test-crypto-binary-default.js index ffc29e7ac8b640..6cdc894753c3ac 100644 --- a/test/parallel/test-crypto-binary-default.js +++ b/test/parallel/test-crypto-binary-default.js @@ -46,9 +46,7 @@ const rsaPubPem = fixtures.readSync('test_rsa_pubkey.pem', 'ascii'); const rsaKeyPem = fixtures.readSync('test_rsa_privkey.pem', 'ascii'); // PFX tests -assert.doesNotThrow(function() { - tls.createSecureContext({ pfx: certPfx, passphrase: 'sample' }); -}); +tls.createSecureContext({ pfx: certPfx, passphrase: 'sample' }); assert.throws(function() { tls.createSecureContext({ pfx: certPfx }); diff --git a/test/parallel/test-crypto-cipher-decipher.js b/test/parallel/test-crypto-cipher-decipher.js index 1752d903cfcb09..7b207eb0ba4105 100644 --- a/test/parallel/test-crypto-cipher-decipher.js +++ b/test/parallel/test-crypto-cipher-decipher.js @@ -126,18 +126,18 @@ testCipher2(Buffer.from('0123456789abcdef')); let decipher = crypto.createDecipher('aes192', key); let txt; - assert.doesNotThrow(() => txt = decipher.update(ciph, 'base64', 'ucs2')); - assert.doesNotThrow(() => txt += decipher.final('ucs2')); + txt = decipher.update(ciph, 'base64', 'ucs2'); + txt += decipher.final('ucs2'); assert.strictEqual(txt, plaintext); decipher = crypto.createDecipher('aes192', key); - assert.doesNotThrow(() => txt = decipher.update(ciph, 'base64', 'ucs-2')); - assert.doesNotThrow(() => txt += decipher.final('ucs-2')); + txt = decipher.update(ciph, 'base64', 'ucs-2'); + txt += decipher.final('ucs-2'); assert.strictEqual(txt, plaintext); decipher = crypto.createDecipher('aes192', key); - assert.doesNotThrow(() => txt = decipher.update(ciph, 'base64', 'utf-16le')); - assert.doesNotThrow(() => txt += decipher.final('utf-16le')); + txt = decipher.update(ciph, 'base64', 'utf-16le'); + txt += decipher.final('utf-16le'); assert.strictEqual(txt, plaintext); } diff --git a/test/parallel/test-crypto-cipheriv-decipheriv.js b/test/parallel/test-crypto-cipheriv-decipheriv.js index 01f6717e67a181..8f880cbfb2417a 100644 --- a/test/parallel/test-crypto-cipheriv-decipheriv.js +++ b/test/parallel/test-crypto-cipheriv-decipheriv.js @@ -89,8 +89,9 @@ if (!common.hasFipsCrypto) { Buffer.from('A6A6A6A6A6A6A6A6', 'hex')); } -// Zero-sized IV should be accepted in ECB mode. +// Zero-sized IV or null should be accepted in ECB mode. crypto.createCipheriv('aes-128-ecb', Buffer.alloc(16), Buffer.alloc(0)); +crypto.createCipheriv('aes-128-ecb', Buffer.alloc(16), null); const errMessage = /Invalid IV length/; @@ -114,6 +115,11 @@ for (let n = 0; n < 256; n += 1) { errMessage); } +// And so should null be. +assert.throws(() => { + crypto.createCipheriv('aes-128-cbc', Buffer.alloc(16), null); +}, /Missing IV for cipher aes-128-cbc/); + // Zero-sized IV should be rejected in GCM mode. assert.throws( () => crypto.createCipheriv('aes-128-gcm', Buffer.alloc(16), diff --git a/test/parallel/test-crypto-dh-odd-key.js b/test/parallel/test-crypto-dh-odd-key.js index 449c482d351c56..d5410daca6fb23 100644 --- a/test/parallel/test-crypto-dh-odd-key.js +++ b/test/parallel/test-crypto-dh-odd-key.js @@ -37,7 +37,7 @@ function test() { // FIPS requires a length of at least 1024 if (!common.hasFipsCrypto) { - assert.doesNotThrow(function() { test(); }); + test(); } else { assert.throws(function() { test(); }, /key size too small/); } diff --git a/test/parallel/test-crypto-dh.js b/test/parallel/test-crypto-dh.js index 30d54e2ae46aa2..515959b6948cb5 100644 --- a/test/parallel/test-crypto-dh.js +++ b/test/parallel/test-crypto-dh.js @@ -363,9 +363,7 @@ if (availableCurves.has('prime256v1') && availableHashes.has('sha256')) { 'AwEHoUQDQgAEurOxfSxmqIRYzJVagdZfMMSjRNNhB8i3mXyIMq704m2m52FdfKZ2\n' + 'pQhByd5eyj3lgZ7m7jbchtdgyOF8Io/1ng==\n' + '-----END EC PRIVATE KEY-----'; - assert.doesNotThrow(() => { - crypto.createSign('SHA256').sign(ecPrivateKey); - }); + crypto.createSign('SHA256').sign(ecPrivateKey); } // invalid test: curve argument is undefined diff --git a/test/parallel/test-crypto-hash.js b/test/parallel/test-crypto-hash.js index bf080b1970369e..e425e1fe4cdb60 100644 --- a/test/parallel/test-crypto-hash.js +++ b/test/parallel/test-crypto-hash.js @@ -82,15 +82,15 @@ assert.deepStrictEqual( ); // stream interface should produce the same result. -assert.deepStrictEqual(a5, a3, 'stream interface is consistent'); -assert.deepStrictEqual(a6, a3, 'stream interface is consistent'); -assert.notStrictEqual(a7, undefined, 'no data should return data'); -assert.notStrictEqual(a8, undefined, 'empty string should generate data'); +assert.deepStrictEqual(a5, a3); +assert.deepStrictEqual(a6, a3); +assert.notStrictEqual(a7, undefined); +assert.notStrictEqual(a8, undefined); // Test multiple updates to same hash const h1 = crypto.createHash('sha1').update('Test123').digest('hex'); const h2 = crypto.createHash('sha1').update('Test').update('123').digest('hex'); -assert.strictEqual(h1, h2, 'multipled updates'); +assert.strictEqual(h1, h2); // Test hashing for binary files const fn = fixtures.path('sample.png'); diff --git a/test/parallel/test-crypto-padding.js b/test/parallel/test-crypto-padding.js index 6ad504d12c2ced..00b600efb735e8 100644 --- a/test/parallel/test-crypto-padding.js +++ b/test/parallel/test-crypto-padding.js @@ -29,11 +29,7 @@ const crypto = require('crypto'); crypto.DEFAULT_ENCODING = 'buffer'; - -/* - * Input data - */ - +// Input data. const ODD_LENGTH_PLAIN = 'Hello node world!'; const EVEN_LENGTH_PLAIN = 'Hello node world!AbC09876dDeFgHi'; @@ -42,10 +38,7 @@ const IV_PLAIN = 'blahFizz2011Buzz'; const CIPHER_NAME = 'aes-128-cbc'; - -/* - * Expected result data - */ +// Expected result data. // echo -n 'Hello node world!' | \ // openssl enc -aes-128-cbc -e -K 5333632e722e652e742e4b2e652e5921 \ @@ -67,10 +60,7 @@ const EVEN_LENGTH_ENCRYPTED_NOPAD = '7f57859550d4d2fdb9806da2a750461ab46e71b3d78ebe2d9684dfc87f7575b9'; -/* - * Helper wrappers - */ - +// Helper wrappers. function enc(plain, pad) { const encrypt = crypto.createCipheriv(CIPHER_NAME, KEY_PLAIN, IV_PLAIN); encrypt.setAutoPadding(pad); @@ -87,47 +77,33 @@ function dec(encd, pad) { return plain; } - -/* - * Test encryption - */ - +// Test encryption assert.strictEqual(enc(ODD_LENGTH_PLAIN, true), ODD_LENGTH_ENCRYPTED); assert.strictEqual(enc(EVEN_LENGTH_PLAIN, true), EVEN_LENGTH_ENCRYPTED); assert.throws(function() { - // input must have block length % + // Input must have block length %. enc(ODD_LENGTH_PLAIN, false); }, /data not multiple of block length/); -assert.doesNotThrow(function() { - assert.strictEqual( - enc(EVEN_LENGTH_PLAIN, false), EVEN_LENGTH_ENCRYPTED_NOPAD - ); -}); - - -/* - * Test decryption - */ +assert.strictEqual( + enc(EVEN_LENGTH_PLAIN, false), EVEN_LENGTH_ENCRYPTED_NOPAD +); +// Test decryption. assert.strictEqual(dec(ODD_LENGTH_ENCRYPTED, true), ODD_LENGTH_PLAIN); assert.strictEqual(dec(EVEN_LENGTH_ENCRYPTED, true), EVEN_LENGTH_PLAIN); -assert.doesNotThrow(function() { - // returns including original padding - assert.strictEqual(dec(ODD_LENGTH_ENCRYPTED, false).length, 32); - assert.strictEqual(dec(EVEN_LENGTH_ENCRYPTED, false).length, 48); -}); +// Returns including original padding. +assert.strictEqual(dec(ODD_LENGTH_ENCRYPTED, false).length, 32); +assert.strictEqual(dec(EVEN_LENGTH_ENCRYPTED, false).length, 48); assert.throws(function() { - // must have at least 1 byte of padding (PKCS): + // Must have at least 1 byte of padding (PKCS): assert.strictEqual(dec(EVEN_LENGTH_ENCRYPTED_NOPAD, true), EVEN_LENGTH_PLAIN); }, /bad decrypt/); -assert.doesNotThrow(function() { - // no-pad encrypted string should return the same: - assert.strictEqual( - dec(EVEN_LENGTH_ENCRYPTED_NOPAD, false), EVEN_LENGTH_PLAIN - ); -}); +// No-pad encrypted string should return the same: +assert.strictEqual( + dec(EVEN_LENGTH_ENCRYPTED_NOPAD, false), EVEN_LENGTH_PLAIN +); diff --git a/test/parallel/test-crypto-pbkdf2.js b/test/parallel/test-crypto-pbkdf2.js index af8acd42c7c7fd..a9a23e155ffb2f 100644 --- a/test/parallel/test-crypto-pbkdf2.js +++ b/test/parallel/test-crypto-pbkdf2.js @@ -99,11 +99,7 @@ common.expectsError( // Should not get FATAL ERROR with empty password and salt // https://github.com/nodejs/node/issues/8571 -assert.doesNotThrow(() => { - crypto.pbkdf2('', '', 1, 32, 'sha256', common.mustCall((e) => { - assert.ifError(e); - })); -}); +crypto.pbkdf2('', '', 1, 32, 'sha256', common.mustCall(assert.ifError)); common.expectsError( () => crypto.pbkdf2('password', 'salt', 8, 8, common.mustNotCall()), diff --git a/test/parallel/test-crypto-rsa-dsa.js b/test/parallel/test-crypto-rsa-dsa.js index e0aa1ef872b89c..744dc5657b089d 100644 --- a/test/parallel/test-crypto-rsa-dsa.js +++ b/test/parallel/test-crypto-rsa-dsa.js @@ -153,10 +153,8 @@ assert.strictEqual(rsaVerify.verify(rsaPubPem, rsaSignature, 'hex'), true); // Test RSA key signing/verification with encrypted key rsaSign = crypto.createSign('SHA1'); rsaSign.update(rsaPubPem); -assert.doesNotThrow(() => { - const signOptions = { key: rsaKeyPemEncrypted, passphrase: 'password' }; - rsaSignature = rsaSign.sign(signOptions, 'hex'); -}); +const signOptions = { key: rsaKeyPemEncrypted, passphrase: 'password' }; +rsaSignature = rsaSign.sign(signOptions, 'hex'); assert.strictEqual(rsaSignature, expectedSignature); rsaVerify = crypto.createVerify('SHA1'); @@ -258,12 +256,8 @@ const input = 'I AM THE WALRUS'; // against const sign = crypto.createSign('SHA1'); sign.update(input); - - let signature; - assert.doesNotThrow(() => { - const signOptions = { key: dsaKeyPemEncrypted, passphrase: 'password' }; - signature = sign.sign(signOptions, 'hex'); - }); + const signOptions = { key: dsaKeyPemEncrypted, passphrase: 'password' }; + const signature = sign.sign(signOptions, 'hex'); const verify = crypto.createVerify('SHA1'); verify.update(input); diff --git a/test/parallel/test-regress-GH-9819.js b/test/parallel/test-crypto-tostring-segfault.js similarity index 74% rename from test/parallel/test-regress-GH-9819.js rename to test/parallel/test-crypto-tostring-segfault.js index 7eed1c512f7942..b2c95117d3b1f8 100644 --- a/test/parallel/test-regress-GH-9819.js +++ b/test/parallel/test-crypto-tostring-segfault.js @@ -3,6 +3,11 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); +// This test ensures that node doesn't SEGFAULT when either of +// `crypto.createHash` or `crypto.createHmac` are given an object that defines +// a throwing `toString`. +// https://github.com/nodejs/node/issues/9819 + const assert = require('assert'); const execFile = require('child_process').execFile; diff --git a/test/parallel/test-crypto.js b/test/parallel/test-crypto.js index 1156fe688cb8d2..1fc3db74828ca6 100644 --- a/test/parallel/test-crypto.js +++ b/test/parallel/test-crypto.js @@ -56,9 +56,7 @@ assert.throws(function() { }); // PFX tests -assert.doesNotThrow(function() { - tls.createSecureContext({ pfx: certPfx, passphrase: 'sample' }); -}); +tls.createSecureContext({ pfx: certPfx, passphrase: 'sample' }); assert.throws(function() { tls.createSecureContext({ pfx: certPfx }); diff --git a/test/parallel/test-dgram-createSocket-type.js b/test/parallel/test-dgram-createSocket-type.js index 19f4dad9208212..9c5a20eaab3191 100644 --- a/test/parallel/test-dgram-createSocket-type.js +++ b/test/parallel/test-dgram-createSocket-type.js @@ -34,10 +34,8 @@ invalidTypes.forEach((invalidType) => { // Error must not be thrown with valid types validTypes.forEach((validType) => { - assert.doesNotThrow(() => { - const socket = dgram.createSocket(validType); - socket.close(); - }); + const socket = dgram.createSocket(validType); + socket.close(); }); // Ensure buffer sizes can be set diff --git a/test/parallel/test-dns-lookup.js b/test/parallel/test-dns-lookup.js index 516f6ac0c145ec..d006355742e55b 100644 --- a/test/parallel/test-dns-lookup.js +++ b/test/parallel/test-dns-lookup.js @@ -53,55 +53,47 @@ common.expectsError(() => { message: 'The value "20" is invalid for option "family"' }); -assert.doesNotThrow(() => { - dns.lookup(false, { - hints: 0, - family: 0, - all: true - }, common.mustCall((error, result, addressType) => { - assert.ifError(error); - assert.deepStrictEqual(result, []); - assert.strictEqual(addressType, undefined); - })); -}); +dns.lookup(false, { + hints: 0, + family: 0, + all: true +}, common.mustCall((error, result, addressType) => { + assert.ifError(error); + assert.deepStrictEqual(result, []); + assert.strictEqual(addressType, undefined); +})); -assert.doesNotThrow(() => { - dns.lookup('127.0.0.1', { - hints: 0, - family: 4, - all: true - }, common.mustCall((error, result, addressType) => { - assert.ifError(error); - assert.deepStrictEqual(result, [{ - address: '127.0.0.1', - family: 4 - }]); - assert.strictEqual(addressType, undefined); - })); -}); +dns.lookup('127.0.0.1', { + hints: 0, + family: 4, + all: true +}, common.mustCall((error, result, addressType) => { + assert.ifError(error); + assert.deepStrictEqual(result, [{ + address: '127.0.0.1', + family: 4 + }]); + assert.strictEqual(addressType, undefined); +})); -assert.doesNotThrow(() => { - dns.lookup('127.0.0.1', { - hints: 0, - family: 4, - all: false - }, common.mustCall((error, result, addressType) => { - assert.ifError(error); - assert.deepStrictEqual(result, '127.0.0.1'); - assert.strictEqual(addressType, 4); - })); -}); +dns.lookup('127.0.0.1', { + hints: 0, + family: 4, + all: false +}, common.mustCall((error, result, addressType) => { + assert.ifError(error); + assert.deepStrictEqual(result, '127.0.0.1'); + assert.strictEqual(addressType, 4); +})); -assert.doesNotThrow(() => { - let tickValue = 0; +let tickValue = 0; - dns.lookup('example.com', common.mustCall((error, result, addressType) => { - assert(error); - assert.strictEqual(tickValue, 1); - assert.strictEqual(error.code, 'ENOENT'); - })); +dns.lookup('example.com', common.mustCall((error, result, addressType) => { + assert(error); + assert.strictEqual(tickValue, 1); + assert.strictEqual(error.code, 'ENOENT'); +})); - // Make sure that the error callback is called - // on next tick. - tickValue = 1; -}); +// Make sure that the error callback is called +// on next tick. +tickValue = 1; diff --git a/test/parallel/test-dns.js b/test/parallel/test-dns.js index dba14b397bc27c..839d434f9e1d65 100644 --- a/test/parallel/test-dns.js +++ b/test/parallel/test-dns.js @@ -29,7 +29,7 @@ const existing = dns.getServers(); assert(existing.length > 0); // Verify that setServers() handles arrays with holes and other oddities -assert.doesNotThrow(() => { +{ const servers = []; servers[0] = '127.0.0.1'; @@ -37,9 +37,9 @@ assert.doesNotThrow(() => { dns.setServers(servers); assert.deepStrictEqual(dns.getServers(), ['127.0.0.1', '0.0.0.0']); -}); +} -assert.doesNotThrow(() => { +{ const servers = ['127.0.0.1', '192.168.1.1']; servers[3] = '127.1.0.1'; @@ -60,13 +60,13 @@ assert.doesNotThrow(() => { '192.168.1.1', '0.0.0.0' ]); -}); +} const goog = [ '8.8.8.8', '8.8.4.4', ]; -assert.doesNotThrow(() => dns.setServers(goog)); +dns.setServers(goog); assert.deepStrictEqual(dns.getServers(), goog); common.expectsError(() => dns.setServers(['foobar']), { code: 'ERR_INVALID_IP_ADDRESS', @@ -84,7 +84,7 @@ const goog6 = [ '2001:4860:4860::8888', '2001:4860:4860::8844', ]; -assert.doesNotThrow(() => dns.setServers(goog6)); +dns.setServers(goog6); assert.deepStrictEqual(dns.getServers(), goog6); goog6.push('4.4.4.4'); @@ -106,7 +106,7 @@ const portsExpected = [ dns.setServers(ports); assert.deepStrictEqual(dns.getServers(), portsExpected); -assert.doesNotThrow(() => dns.setServers([])); +dns.setServers([]); assert.deepStrictEqual(dns.getServers(), []); common.expectsError(() => { @@ -146,16 +146,11 @@ common.expectsError(() => { assert.strictEqual(family, 4); }; - assert.doesNotThrow(() => dns.lookup('', common.mustCall(checkCallback))); - - assert.doesNotThrow(() => dns.lookup(null, common.mustCall(checkCallback))); - - assert.doesNotThrow(() => dns.lookup(undefined, - common.mustCall(checkCallback))); - - assert.doesNotThrow(() => dns.lookup(0, common.mustCall(checkCallback))); - - assert.doesNotThrow(() => dns.lookup(NaN, common.mustCall(checkCallback))); + dns.lookup('', common.mustCall(checkCallback)); + dns.lookup(null, common.mustCall(checkCallback)); + dns.lookup(undefined, common.mustCall(checkCallback)); + dns.lookup(0, common.mustCall(checkCallback)); + dns.lookup(NaN, common.mustCall(checkCallback)); } /* @@ -186,24 +181,18 @@ common.expectsError(() => dns.lookup('nodejs.org', 4), { type: TypeError }); -assert.doesNotThrow(() => dns.lookup('', { family: 4, hints: 0 }, - common.mustCall())); +dns.lookup('', { family: 4, hints: 0 }, common.mustCall()); -assert.doesNotThrow(() => { - dns.lookup('', { - family: 6, - hints: dns.ADDRCONFIG - }, common.mustCall()); -}); +dns.lookup('', { + family: 6, + hints: dns.ADDRCONFIG +}, common.mustCall()); -assert.doesNotThrow(() => dns.lookup('', { hints: dns.V4MAPPED }, - common.mustCall())); +dns.lookup('', { hints: dns.V4MAPPED }, common.mustCall()); -assert.doesNotThrow(() => { - dns.lookup('', { - hints: dns.ADDRCONFIG | dns.V4MAPPED - }, common.mustCall()); -}); +dns.lookup('', { + hints: dns.ADDRCONFIG | dns.V4MAPPED +}, common.mustCall()); common.expectsError(() => dns.lookupService('0.0.0.0'), { code: 'ERR_MISSING_ARGS', diff --git a/test/parallel/test-domain-load-after-set-uncaught-exception-capture.js b/test/parallel/test-domain-load-after-set-uncaught-exception-capture.js index 9e438368d63207..697d4d30806ee7 100644 --- a/test/parallel/test-domain-load-after-set-uncaught-exception-capture.js +++ b/test/parallel/test-domain-load-after-set-uncaught-exception-capture.js @@ -1,6 +1,5 @@ 'use strict'; const common = require('../common'); -const assert = require('assert'); process.setUncaughtExceptionCaptureCallback(common.mustNotCall()); @@ -14,5 +13,4 @@ common.expectsError( ); process.setUncaughtExceptionCaptureCallback(null); - -assert.doesNotThrow(() => require('domain')); +require('domain'); // Should not throw. diff --git a/test/parallel/test-eslint-require-buffer.js b/test/parallel/test-eslint-require-buffer.js index ca2c44cb322515..bdc794dd594240 100644 --- a/test/parallel/test-eslint-require-buffer.js +++ b/test/parallel/test-eslint-require-buffer.js @@ -36,14 +36,14 @@ ruleTester.run('require-buffer', rule, { output: useStrict + bufferModule + useBuffer, }, { - code: mockComment + useBuffer, + code: mockComment + useBuffer, errors: [{ message }], - output: mockComment + bufferModule + useBuffer, + output: mockComment + bufferModule + useBuffer, }, { - code: mockComment + useStrict + useBuffer, + code: mockComment + useStrict + useBuffer, errors: [{ message }], - output: mockComment + useStrict + bufferModule + useBuffer, + output: mockComment + useStrict + bufferModule + useBuffer, }, ] }); diff --git a/test/parallel/test-regress-GH-2245.js b/test/parallel/test-eval-strict-referenceerror.js similarity index 62% rename from test/parallel/test-regress-GH-2245.js rename to test/parallel/test-eval-strict-referenceerror.js index 37260b59e34721..a96478a1bedaae 100644 --- a/test/parallel/test-regress-GH-2245.js +++ b/test/parallel/test-eval-strict-referenceerror.js @@ -1,12 +1,11 @@ /* eslint-disable strict */ require('../common'); -const assert = require('assert'); -/* -In Node.js 0.10, a bug existed that caused strict functions to not capture -their environment when evaluated. When run in 0.10 `test()` fails with a -`ReferenceError`. See https://github.com/nodejs/node/issues/2245 for details. -*/ +// In Node.js 0.10, a bug existed that caused strict functions to not capture +// their environment when evaluated. When run in 0.10 `test()` fails with a +// `ReferenceError`. See https://github.com/nodejs/node/issues/2245 for details. + +const assert = require('assert'); function test() { diff --git a/test/parallel/test-event-emitter-remove-all-listeners.js b/test/parallel/test-event-emitter-remove-all-listeners.js index 6ab277ce4ed6be..3dfe65a8b4bfd0 100644 --- a/test/parallel/test-event-emitter-remove-all-listeners.js +++ b/test/parallel/test-event-emitter-remove-all-listeners.js @@ -81,7 +81,7 @@ function expect(expected) { // Check for regression where removeAllListeners() throws when // there exists a 'removeListener' listener, but there exists // no listeners for the provided event type. - assert.doesNotThrow(ee.removeAllListeners.bind(ee, 'foo')); + ee.removeAllListeners.bind(ee, 'foo'); } { diff --git a/test/parallel/test-fs-access.js b/test/parallel/test-fs-access.js index 867c19cc3cfa1e..9d5160f6170cad 100644 --- a/test/parallel/test-fs-access.js +++ b/test/parallel/test-fs-access.js @@ -105,15 +105,10 @@ common.expectsError( type: TypeError }); -assert.doesNotThrow(() => { - fs.accessSync(__filename); -}); - -assert.doesNotThrow(() => { - const mode = fs.F_OK | fs.R_OK | fs.W_OK; - - fs.accessSync(readWriteFile, mode); -}); +// Regular access should not throw. +fs.accessSync(__filename); +const mode = fs.F_OK | fs.R_OK | fs.W_OK; +fs.accessSync(readWriteFile, mode); assert.throws( () => { fs.accessSync(doesNotExist); }, diff --git a/test/parallel/test-fs-buffer.js b/test/parallel/test-fs-buffer.js index 84234e8a7a0bd7..f1c3484ce3a8d0 100644 --- a/test/parallel/test-fs-buffer.js +++ b/test/parallel/test-fs-buffer.js @@ -9,22 +9,14 @@ const path = require('path'); const tmpdir = require('../common/tmpdir'); tmpdir.refresh(); -assert.doesNotThrow(() => { - fs.access(Buffer.from(tmpdir.path), common.mustCall((err) => { - assert.ifError(err); - })); -}); +fs.access(Buffer.from(tmpdir.path), common.mustCall(assert.ifError)); -assert.doesNotThrow(() => { - const buf = Buffer.from(path.join(tmpdir.path, 'a.txt')); - fs.open(buf, 'w+', common.mustCall((err, fd) => { - assert.ifError(err); - assert(fd); - fs.close(fd, common.mustCall((err) => { - assert.ifError(err); - })); - })); -}); +const buf = Buffer.from(path.join(tmpdir.path, 'a.txt')); +fs.open(buf, 'w+', common.mustCall((err, fd) => { + assert.ifError(err); + assert(fd); + fs.close(fd, common.mustCall(assert.ifError)); +})); assert.throws(() => { fs.accessSync(true); diff --git a/test/parallel/test-fs-exists.js b/test/parallel/test-fs-exists.js index 331c8c04e38e78..b5c3dc154684e3 100644 --- a/test/parallel/test-fs-exists.js +++ b/test/parallel/test-fs-exists.js @@ -30,7 +30,8 @@ fs.exists(f, common.mustCall(function(y) { assert.strictEqual(y, true); })); -assert.doesNotThrow(() => fs.exists(f)); +// Does not throw +fs.exists(f); fs.exists(`${f}-NO`, common.mustCall(function(y) { assert.strictEqual(y, false); diff --git a/test/parallel/test-regress-GH-3739.js b/test/parallel/test-fs-existssync-false.js similarity index 80% rename from test/parallel/test-regress-GH-3739.js rename to test/parallel/test-fs-existssync-false.js index dbf77ad785cac9..de5ecfa66ad922 100644 --- a/test/parallel/test-regress-GH-3739.js +++ b/test/parallel/test-fs-existssync-false.js @@ -1,12 +1,15 @@ 'use strict'; - const common = require('../common'); +const tmpdir = require('../common/tmpdir'); + +// This test ensures that fs.existsSync doesn't incorrectly return false. +// (especially on Windows) +// https://github.com/nodejs/node-v0.x-archive/issues/3739 + const assert = require('assert'); const fs = require('fs'); const path = require('path'); -const tmpdir = require('../common/tmpdir'); - let dir = path.resolve(tmpdir.path); // Make sure that the tmp directory is clean diff --git a/test/parallel/test-fs-make-callback.js b/test/parallel/test-fs-make-callback.js index ca948ede182759..9d4a6121a36a65 100644 --- a/test/parallel/test-fs-make-callback.js +++ b/test/parallel/test-fs-make-callback.js @@ -1,6 +1,5 @@ 'use strict'; const common = require('../common'); -const assert = require('assert'); const fs = require('fs'); const callbackThrowValues = [null, true, false, 0, 1, 'foo', /foo/, [], {}]; @@ -20,7 +19,7 @@ function testMakeCallback(cb) { common.expectWarning('DeprecationWarning', warn); // Passing undefined/nothing calls rethrow() internally, which emits a warning -assert.doesNotThrow(testMakeCallback()); +testMakeCallback()(); function invalidCallbackThrowsTests() { callbackThrowValues.forEach((value) => { diff --git a/test/parallel/test-fs-makeStatsCallback.js b/test/parallel/test-fs-makeStatsCallback.js index 0982fcc3c7d38c..ec03b593fa2a2c 100644 --- a/test/parallel/test-fs-makeStatsCallback.js +++ b/test/parallel/test-fs-makeStatsCallback.js @@ -1,6 +1,5 @@ 'use strict'; const common = require('../common'); -const assert = require('assert'); const fs = require('fs'); const callbackThrowValues = [null, true, false, 0, 1, 'foo', /foo/, [], {}]; const warn = 'Calling an asynchronous function without callback is deprecated.'; @@ -15,10 +14,10 @@ function testMakeStatsCallback(cb) { common.expectWarning('DeprecationWarning', warn); // Verify the case where a callback function is provided -assert.doesNotThrow(testMakeStatsCallback(common.mustCall())); +testMakeStatsCallback(common.mustCall())(); // Passing undefined/nothing calls rethrow() internally, which emits a warning -assert.doesNotThrow(testMakeStatsCallback()); +testMakeStatsCallback()(); function invalidCallbackThrowsTests() { callbackThrowValues.forEach((value) => { diff --git a/test/parallel/test-fs-mkdtemp.js b/test/parallel/test-fs-mkdtemp.js index b27ab864173dd2..27e2f1c08c227d 100644 --- a/test/parallel/test-fs-mkdtemp.js +++ b/test/parallel/test-fs-mkdtemp.js @@ -32,5 +32,5 @@ fs.mkdtemp(path.join(tmpdir.path, 'bar.'), {}, common.mustCall(handler)); // Making sure that not passing a callback doesn't crash, as a default function // is passed internally. -assert.doesNotThrow(() => fs.mkdtemp(path.join(tmpdir.path, 'bar-'))); -assert.doesNotThrow(() => fs.mkdtemp(path.join(tmpdir.path, 'bar-'), {})); +fs.mkdtemp(path.join(tmpdir.path, 'bar-')); +fs.mkdtemp(path.join(tmpdir.path, 'bar-'), {}); diff --git a/test/parallel/test-fs-open-flags.js b/test/parallel/test-fs-open-flags.js index acf5c739a930c3..7f70885861ffd1 100644 --- a/test/parallel/test-fs-open-flags.js +++ b/test/parallel/test-fs-open-flags.js @@ -56,8 +56,12 @@ assert.strictEqual(stringToFlags('wx+'), O_TRUNC | O_CREAT | O_RDWR | O_EXCL); assert.strictEqual(stringToFlags('xw+'), O_TRUNC | O_CREAT | O_RDWR | O_EXCL); assert.strictEqual(stringToFlags('ax'), O_APPEND | O_CREAT | O_WRONLY | O_EXCL); assert.strictEqual(stringToFlags('xa'), O_APPEND | O_CREAT | O_WRONLY | O_EXCL); +assert.strictEqual(stringToFlags('as'), O_APPEND | O_CREAT | O_WRONLY | O_SYNC); +assert.strictEqual(stringToFlags('sa'), O_APPEND | O_CREAT | O_WRONLY | O_SYNC); assert.strictEqual(stringToFlags('ax+'), O_APPEND | O_CREAT | O_RDWR | O_EXCL); assert.strictEqual(stringToFlags('xa+'), O_APPEND | O_CREAT | O_RDWR | O_EXCL); +assert.strictEqual(stringToFlags('as+'), O_APPEND | O_CREAT | O_RDWR | O_SYNC); +assert.strictEqual(stringToFlags('sa+'), O_APPEND | O_CREAT | O_RDWR | O_SYNC); ('+ +a +r +w rw wa war raw r++ a++ w++ x +x x+ rx rx+ wxx wax xwx xxx') .split(' ') diff --git a/test/parallel/test-fs-options-immutable.js b/test/parallel/test-fs-options-immutable.js index ca5079b07dab3f..3555c82f1962f3 100644 --- a/test/parallel/test-fs-options-immutable.js +++ b/test/parallel/test-fs-options-immutable.js @@ -17,19 +17,11 @@ const options = Object.freeze({}); const tmpdir = require('../common/tmpdir'); tmpdir.refresh(); -{ - assert.doesNotThrow(() => - fs.readFile(__filename, options, common.mustCall(errHandler)) - ); - assert.doesNotThrow(() => fs.readFileSync(__filename, options)); -} +fs.readFile(__filename, options, common.mustCall(errHandler)); +fs.readFileSync(__filename, options); -{ - assert.doesNotThrow(() => - fs.readdir(__dirname, options, common.mustCall(errHandler)) - ); - assert.doesNotThrow(() => fs.readdirSync(__dirname, options)); -} +fs.readdir(__dirname, options, common.mustCall(errHandler)); +fs.readdirSync(__dirname, options); if (common.canCreateSymLink()) { const sourceFile = path.resolve(tmpdir.path, 'test-readlink'); @@ -38,63 +30,46 @@ if (common.canCreateSymLink()) { fs.writeFileSync(sourceFile, ''); fs.symlinkSync(sourceFile, linkFile); - assert.doesNotThrow(() => - fs.readlink(linkFile, options, common.mustCall(errHandler)) - ); - assert.doesNotThrow(() => fs.readlinkSync(linkFile, options)); + fs.readlink(linkFile, options, common.mustCall(errHandler)); + fs.readlinkSync(linkFile, options); } { const fileName = path.resolve(tmpdir.path, 'writeFile'); - assert.doesNotThrow(() => fs.writeFileSync(fileName, 'ABCD', options)); - assert.doesNotThrow(() => - fs.writeFile(fileName, 'ABCD', options, common.mustCall(errHandler)) - ); + fs.writeFileSync(fileName, 'ABCD', options); + fs.writeFile(fileName, 'ABCD', options, common.mustCall(errHandler)); } { const fileName = path.resolve(tmpdir.path, 'appendFile'); - assert.doesNotThrow(() => fs.appendFileSync(fileName, 'ABCD', options)); - assert.doesNotThrow(() => - fs.appendFile(fileName, 'ABCD', options, common.mustCall(errHandler)) - ); + fs.appendFileSync(fileName, 'ABCD', options); + fs.appendFile(fileName, 'ABCD', options, common.mustCall(errHandler)); } { - let watch; - assert.doesNotThrow(() => { - watch = fs.watch(__filename, options, common.mustNotCall()); - }); + const watch = fs.watch(__filename, options, common.mustNotCall()); watch.close(); } { - assert.doesNotThrow( - () => fs.watchFile(__filename, options, common.mustNotCall()) - ); + fs.watchFile(__filename, options, common.mustNotCall()); fs.unwatchFile(__filename); } { - assert.doesNotThrow(() => fs.realpathSync(__filename, options)); - assert.doesNotThrow(() => - fs.realpath(__filename, options, common.mustCall(errHandler)) - ); + fs.realpathSync(__filename, options); + fs.realpath(__filename, options, common.mustCall(errHandler)); } { const tempFileName = path.resolve(tmpdir.path, 'mkdtemp-'); - assert.doesNotThrow(() => fs.mkdtempSync(tempFileName, options)); - assert.doesNotThrow(() => - fs.mkdtemp(tempFileName, options, common.mustCall(errHandler)) - ); + fs.mkdtempSync(tempFileName, options); + fs.mkdtemp(tempFileName, options, common.mustCall(errHandler)); } { const fileName = path.resolve(tmpdir.path, 'streams'); - assert.doesNotThrow(() => { - fs.WriteStream(fileName, options).once('open', common.mustCall(() => { - assert.doesNotThrow(() => fs.ReadStream(fileName, options)); - })); - }); + fs.WriteStream(fileName, options).once('open', common.mustCall(() => { + fs.ReadStream(fileName, options); + })); } diff --git a/test/parallel/test-fs-read-stream-throw-type-error.js b/test/parallel/test-fs-read-stream-throw-type-error.js index 26fd47372ebf0c..c2b0d5452c55e3 100644 --- a/test/parallel/test-fs-read-stream-throw-type-error.js +++ b/test/parallel/test-fs-read-stream-throw-type-error.js @@ -1,23 +1,14 @@ 'use strict'; const common = require('../common'); const fixtures = require('../common/fixtures'); -const assert = require('assert'); const fs = require('fs'); const example = fixtures.path('x.txt'); - -assert.doesNotThrow(function() { - fs.createReadStream(example, undefined); -}); -assert.doesNotThrow(function() { - fs.createReadStream(example, null); -}); -assert.doesNotThrow(function() { - fs.createReadStream(example, 'utf8'); -}); -assert.doesNotThrow(function() { - fs.createReadStream(example, { encoding: 'utf8' }); -}); +// Should not throw. +fs.createReadStream(example, undefined); +fs.createReadStream(example, null); +fs.createReadStream(example, 'utf8'); +fs.createReadStream(example, { encoding: 'utf8' }); const createReadStreamErr = (path, opt) => { common.expectsError( diff --git a/test/parallel/test-fs-read-stream.js b/test/parallel/test-fs-read-stream.js index ef6cae87068ac9..79f7a4b84d5f3a 100644 --- a/test/parallel/test-fs-read-stream.js +++ b/test/parallel/test-fs-read-stream.js @@ -21,7 +21,9 @@ 'use strict'; const common = require('../common'); +const tmpdir = require('../common/tmpdir'); +const child_process = require('child_process'); const assert = require('assert'); const fs = require('fs'); const fixtures = require('../common/fixtures'); @@ -178,6 +180,31 @@ common.expectsError( })); } +if (!common.isWindows) { + // Verify that end works when start is not specified, and we do not try to + // use positioned reads. This makes sure that this keeps working for + // non-seekable file descriptors. + tmpdir.refresh(); + const filename = `${tmpdir.path}/foo.pipe`; + const mkfifoResult = child_process.spawnSync('mkfifo', [filename]); + if (!mkfifoResult.error) { + child_process.exec(`echo "xyz foobar" > '${filename}'`); + const stream = new fs.createReadStream(filename, { end: 1 }); + stream.data = ''; + + stream.on('data', function(chunk) { + stream.data += chunk; + }); + + stream.on('end', common.mustCall(function() { + assert.strictEqual('xy', stream.data); + fs.unlinkSync(filename); + })); + } else { + common.printSkipMessage('mkfifo not available'); + } +} + { // pause and then resume immediately. const pauseRes = fs.createReadStream(rangeFile); diff --git a/test/parallel/test-regress-GH-3542.js b/test/parallel/test-fs-readfilesync-enoent.js similarity index 79% rename from test/parallel/test-regress-GH-3542.js rename to test/parallel/test-fs-readfilesync-enoent.js index b652c95c9ac881..3d421e52b120af 100644 --- a/test/parallel/test-regress-GH-3542.js +++ b/test/parallel/test-fs-readfilesync-enoent.js @@ -1,9 +1,14 @@ 'use strict'; const common = require('../common'); + // This test is only relevant on Windows. if (!common.isWindows) common.skip('Windows specific test.'); +// This test ensures fs.realpathSync works on properly on Windows without +// throwing ENOENT when the path involves a fileserver. +// https://github.com/nodejs/node-v0.x-archive/issues/3542 + const assert = require('assert'); const fs = require('fs'); const path = require('path'); diff --git a/test/parallel/test-fs-timestamp-parsing-error.js b/test/parallel/test-fs-timestamp-parsing-error.js index 3680b5fece13c9..2dcd4f518427e3 100644 --- a/test/parallel/test-fs-timestamp-parsing-error.js +++ b/test/parallel/test-fs-timestamp-parsing-error.js @@ -1,7 +1,6 @@ 'use strict'; const common = require('../common'); const fs = require('fs'); -const assert = require('assert'); [Infinity, -Infinity, NaN].forEach((input) => { common.expectsError( @@ -25,5 +24,5 @@ common.expectsError( const okInputs = [1, -1, '1', '-1', Date.now()]; okInputs.forEach((input) => { - assert.doesNotThrow(() => fs._toUnixTimestamp(input)); + fs._toUnixTimestamp(input); }); diff --git a/test/parallel/test-fs-utimes.js b/test/parallel/test-fs-utimes.js index 3dc0bb59def6a2..738fc7576a8b5e 100644 --- a/test/parallel/test-fs-utimes.js +++ b/test/parallel/test-fs-utimes.js @@ -88,7 +88,7 @@ function testIt(atime, mtime, callback) { expect_errno('futimesSync', fd, ex, 'ENOSYS'); } - let err = undefined; + let err; try { fs.utimesSync('foobarbaz', atime, mtime); } catch (ex) { diff --git a/test/parallel/test-fs-write-stream-throw-type-error.js b/test/parallel/test-fs-write-stream-throw-type-error.js index 73312afa6b6423..c80f647b3d622e 100644 --- a/test/parallel/test-fs-write-stream-throw-type-error.js +++ b/test/parallel/test-fs-write-stream-throw-type-error.js @@ -1,6 +1,5 @@ 'use strict'; const common = require('../common'); -const assert = require('assert'); const fs = require('fs'); const path = require('path'); @@ -9,22 +8,11 @@ const tmpdir = require('../common/tmpdir'); const example = path.join(tmpdir.path, 'dummy'); tmpdir.refresh(); - -assert.doesNotThrow(() => { - fs.createWriteStream(example, undefined); -}); - -assert.doesNotThrow(() => { - fs.createWriteStream(example, null); -}); - -assert.doesNotThrow(() => { - fs.createWriteStream(example, 'utf8'); -}); - -assert.doesNotThrow(() => { - fs.createWriteStream(example, { encoding: 'utf8' }); -}); +// Should not throw. +fs.createWriteStream(example, undefined); +fs.createWriteStream(example, null); +fs.createWriteStream(example, 'utf8'); +fs.createWriteStream(example, { encoding: 'utf8' }); const createWriteStreamErr = (path, opt) => { common.expectsError( diff --git a/test/parallel/test-regress-GH-5051.js b/test/parallel/test-http-addrequest-localaddress.js similarity index 85% rename from test/parallel/test-regress-GH-5051.js rename to test/parallel/test-http-addrequest-localaddress.js index 0fef879c6f15d5..fce53c88af3690 100644 --- a/test/parallel/test-regress-GH-5051.js +++ b/test/parallel/test-http-addrequest-localaddress.js @@ -1,5 +1,10 @@ 'use strict'; require('../common'); + +// This test ensures that `addRequest`'s Legacy API accepts `localAddress` +// correctly instead of accepting `path`. +// https://github.com/nodejs/node/issues/5051 + const assert = require('assert'); const agent = require('http').globalAgent; diff --git a/test/parallel/test-http-client-headers-array.js b/test/parallel/test-http-client-headers-array.js index dffe04bb108401..c637de61c012b5 100644 --- a/test/parallel/test-http-client-headers-array.js +++ b/test/parallel/test-http-client-headers-array.js @@ -9,8 +9,8 @@ function execute(options) { http.createServer(function(req, res) { const expectHeaders = { 'x-foo': 'boom', - cookie: 'a=1; b=2; c=3', - connection: 'close' + 'cookie': 'a=1; b=2; c=3', + 'connection': 'close' }; // no Host header when you set headers an array diff --git a/test/parallel/test-http-client-reject-unexpected-agent.js b/test/parallel/test-http-client-reject-unexpected-agent.js index 407084c030e67d..50e5d2b57a7b96 100644 --- a/test/parallel/test-http-client-reject-unexpected-agent.js +++ b/test/parallel/test-http-client-reject-unexpected-agent.js @@ -59,7 +59,7 @@ server.listen(0, baseOptions.host, common.mustCall(function() { }); acceptableAgentOptions.forEach((agent) => { - assert.doesNotThrow(() => createRequest(agent)); + createRequest(agent); }); })); diff --git a/test/parallel/test-http-connect.js b/test/parallel/test-http-connect.js index 9b7432f03a7542..af0948dd067054 100644 --- a/test/parallel/test-http-connect.js +++ b/test/parallel/test-http-connect.js @@ -68,12 +68,7 @@ server.listen(0, common.mustCall(() => { assert.strictEqual(socket.listeners('connect').length, 0); assert.strictEqual(socket.listeners('data').length, 0); assert.strictEqual(socket.listeners('drain').length, 0); - - // the stream.Duplex onend listener - // allow 0 here, so that i can run the same test on streams1 impl - assert(socket.listenerCount('end') <= 2, - `Found ${socket.listenerCount('end')} end listeners`); - + assert.strictEqual(socket.listeners('end').length, 1); assert.strictEqual(socket.listeners('free').length, 0); assert.strictEqual(socket.listeners('close').length, 0); assert.strictEqual(socket.listeners('error').length, 0); diff --git a/test/parallel/test-http-header-read.js b/test/parallel/test-http-header-read.js index dcdabb12d83ab0..0cc7b5cae1c071 100644 --- a/test/parallel/test-http-header-read.js +++ b/test/parallel/test-http-header-read.js @@ -37,11 +37,7 @@ const s = http.createServer(function(req, res) { res.end('hello world\n'); // This checks that after the headers have been sent, getHeader works // and does not throw an exception (Issue 752) - assert.doesNotThrow( - function() { - assert.strictEqual(plain, res.getHeader(contentType)); - } - ); + assert.strictEqual(plain, res.getHeader(contentType)); }); s.listen(0, runTest); diff --git a/test/parallel/test-http-hostname-typechecking.js b/test/parallel/test-http-hostname-typechecking.js index 12fe72005a41a6..72440391fa2938 100644 --- a/test/parallel/test-http-hostname-typechecking.js +++ b/test/parallel/test-http-hostname-typechecking.js @@ -1,7 +1,6 @@ 'use strict'; const common = require('../common'); -const assert = require('assert'); const http = require('http'); // All of these values should cause http.request() to throw synchronously @@ -36,8 +35,6 @@ vals.forEach((v) => { // Only testing for 'hostname' validation so ignore connection errors. const dontCare = () => {}; ['', undefined, null].forEach((v) => { - assert.doesNotThrow(() => { - http.request({ hostname: v }).on('error', dontCare).end(); - http.request({ host: v }).on('error', dontCare).end(); - }); + http.request({ hostname: v }).on('error', dontCare).end(); + http.request({ host: v }).on('error', dontCare).end(); }); diff --git a/test/parallel/test-http-invalidheaderfield.js b/test/parallel/test-http-invalidheaderfield.js index 9e844e8a425af0..01315ba69044a2 100644 --- a/test/parallel/test-http-invalidheaderfield.js +++ b/test/parallel/test-http-invalidheaderfield.js @@ -9,9 +9,7 @@ const ee = new EventEmitter(); let count = 3; const server = http.createServer(function(req, res) { - assert.doesNotThrow(function() { - res.setHeader('testing_123', 123); - }); + res.setHeader('testing_123', 123); assert.throws(function() { res.setHeader('testing 123', 123); }, TypeError); @@ -37,17 +35,14 @@ server.listen(0, function() { } ); - assert.doesNotThrow( - function() { - const options = { - port: server.address().port, - headers: { 'testing_123': 123 } - }; - http.get(options, function() { - ee.emit('done'); - }); - }, TypeError - ); + // Should not throw. + const options = { + port: server.address().port, + headers: { 'testing_123': 123 } + }; + http.get(options, function() { + ee.emit('done'); + }); }); ee.on('done', function() { diff --git a/test/parallel/test-http-raw-headers.js b/test/parallel/test-http-raw-headers.js index eb3f7280f89100..8ce20db351302c 100644 --- a/test/parallel/test-http-raw-headers.js +++ b/test/parallel/test-http-raw-headers.js @@ -37,10 +37,10 @@ http.createServer(function(req, res) { 'close' ]; const expectHeaders = { - host: `localhost:${this.address().port}`, + 'host': `localhost:${this.address().port}`, 'transfer-encoding': 'CHUNKED', 'x-bar': 'yoyoyo', - connection: 'close' + 'connection': 'close' }; const expectRawTrailers = [ 'x-bAr', @@ -96,9 +96,9 @@ http.createServer(function(req, res) { 'chunked' ]; const expectHeaders = { - trailer: 'x-foo', - date: null, - connection: 'close', + 'trailer': 'x-foo', + 'date': null, + 'connection': 'close', 'transfer-encoding': 'chunked' }; res.rawHeaders[3] = null; diff --git a/test/parallel/test-regress-GH-1531.js b/test/parallel/test-http-request-agent.js similarity index 90% rename from test/parallel/test-regress-GH-1531.js rename to test/parallel/test-http-request-agent.js index a61cc64ab626af..a1f3077ed2820f 100644 --- a/test/parallel/test-regress-GH-1531.js +++ b/test/parallel/test-http-request-agent.js @@ -1,15 +1,15 @@ 'use strict'; const common = require('../common'); -// This test ensures that a http request callback is called -// when the agent option is set -// See https://github.com/nodejs/node-v0.x-archive/issues/1531 - if (!common.hasCrypto) common.skip('missing crypto'); const fixtures = require('../common/fixtures'); +// This test ensures that a http request callback is called when the agent +// option is set. +// See https://github.com/nodejs/node-v0.x-archive/issues/1531 + const https = require('https'); const options = { diff --git a/test/parallel/test-http-response-add-header-after-sent.js b/test/parallel/test-http-response-add-header-after-sent.js index 8329d3ea7ee55b..a4d3f629e24b3d 100644 --- a/test/parallel/test-http-response-add-header-after-sent.js +++ b/test/parallel/test-http-response-add-header-after-sent.js @@ -1,12 +1,9 @@ 'use strict'; const common = require('../common'); -const assert = require('assert'); const http = require('http'); const server = http.createServer((req, res) => { - assert.doesNotThrow(() => { - res.setHeader('header1', 1); - }); + res.setHeader('header1', 1); res.write('abc'); common.expectsError( () => res.setHeader('header2', 2), diff --git a/test/parallel/test-http-response-remove-header-after-sent.js b/test/parallel/test-http-response-remove-header-after-sent.js index e6adffc1445234..52acd3d1059ef3 100644 --- a/test/parallel/test-http-response-remove-header-after-sent.js +++ b/test/parallel/test-http-response-remove-header-after-sent.js @@ -1,12 +1,9 @@ 'use strict'; const common = require('../common'); -const assert = require('assert'); const http = require('http'); const server = http.createServer((req, res) => { - assert.doesNotThrow(() => { - res.removeHeader('header1', 1); - }); + res.removeHeader('header1', 1); res.write('abc'); common.expectsError( () => res.removeHeader('header2', 2), diff --git a/test/parallel/test-http2-binding.js b/test/parallel/test-http2-binding.js index 8935e569f500c6..f267e2e6c1481e 100644 --- a/test/parallel/test-http2-binding.js +++ b/test/parallel/test-http2-binding.js @@ -5,8 +5,6 @@ if (!common.hasCrypto) common.skip('missing crypto'); const assert = require('assert'); -assert.doesNotThrow(() => process.binding('http2')); - const binding = process.binding('http2'); const http2 = require('http2'); diff --git a/test/parallel/test-http2-client-rststream-before-connect.js b/test/parallel/test-http2-client-rststream-before-connect.js index b0faaa5de2a398..10d7520ac125fe 100644 --- a/test/parallel/test-http2-client-rststream-before-connect.js +++ b/test/parallel/test-http2-client-rststream-before-connect.js @@ -19,11 +19,11 @@ server.listen(0, common.mustCall(() => { req.close(1); assert.strictEqual(req.closed, true); - // make sure that destroy is called + // Make sure that destroy is called. req._destroy = common.mustCall(req._destroy.bind(req)); - // second call doesn't do anything - assert.doesNotThrow(() => req.close(8)); + // Second call doesn't do anything. + req.close(8); req.on('close', common.mustCall((code) => { assert.strictEqual(req.destroyed, true); diff --git a/test/parallel/test-http2-client-setNextStreamID-errors.js b/test/parallel/test-http2-client-setNextStreamID-errors.js new file mode 100644 index 00000000000000..f3d49b7f7f7a98 --- /dev/null +++ b/test/parallel/test-http2-client-setNextStreamID-errors.js @@ -0,0 +1,58 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const http2 = require('http2'); + +const server = http2.createServer(); +server.on('stream', (stream) => { + stream.respond(); + stream.end('ok'); +}); + +const types = { + boolean: true, + function: () => {}, + number: 1, + object: {}, + array: [], + null: null, + symbol: Symbol('test') +}; + +server.listen(0, common.mustCall(() => { + const client = http2.connect(`http://localhost:${server.address().port}`); + + client.on('connect', () => { + const outOfRangeNum = 2 ** 31; + common.expectsError( + () => client.setNextStreamID(outOfRangeNum), + { + type: RangeError, + code: 'ERR_OUT_OF_RANGE', + message: 'The "id" argument is out of range' + } + ); + + // should throw if something other than number is passed to setNextStreamID + Object.entries(types).forEach(([type, value]) => { + if (type === 'number') { + return; + } + + common.expectsError( + () => client.setNextStreamID(value), + { + type: TypeError, + code: 'ERR_INVALID_ARG_TYPE', + message: 'The "id" argument must be of type number' + } + ); + }); + + server.close(); + client.close(); + }); +})); diff --git a/test/parallel/test-http2-compat-expect-continue-check.js b/test/parallel/test-http2-compat-expect-continue-check.js index 6aded8b52935c1..4f2514a44a4f9e 100644 --- a/test/parallel/test-http2-compat-expect-continue-check.js +++ b/test/parallel/test-http2-compat-expect-continue-check.js @@ -33,7 +33,7 @@ server.listen(0, common.mustCall(() => { const client = http2.connect(`http://localhost:${server.address().port}`); const req = client.request({ ':method': 'POST', - expect: '100-continue' + 'expect': '100-continue' }); let gotContinue = false; diff --git a/test/parallel/test-http2-compat-expect-continue.js b/test/parallel/test-http2-compat-expect-continue.js index 42fa80ae4e8620..cb90e51f3bc9d7 100644 --- a/test/parallel/test-http2-compat-expect-continue.js +++ b/test/parallel/test-http2-compat-expect-continue.js @@ -29,7 +29,7 @@ server.on('listening', common.mustCall(() => { const client = http2.connect(`http://localhost:${server.address().port}`); const req = client.request({ ':method': 'POST', - expect: '100-continue' + 'expect': '100-continue' }); let gotContinue = false; diff --git a/test/parallel/test-http2-compat-expect-handling.js b/test/parallel/test-http2-compat-expect-handling.js index e987118476337d..77f22758345cff 100644 --- a/test/parallel/test-http2-compat-expect-handling.js +++ b/test/parallel/test-http2-compat-expect-handling.js @@ -30,7 +30,7 @@ function nextTest(testsToRun) { ':method': 'GET', ':scheme': 'http', ':authority': `localhost:${port}`, - expect: expectValue + 'expect': expectValue }); req.on('response', common.mustCall((headers) => { diff --git a/test/parallel/test-http2-compat-serverrequest-pause.js b/test/parallel/test-http2-compat-serverrequest-pause.js index 62a23997c75bd8..9c81e8ff6140c7 100644 --- a/test/parallel/test-http2-compat-serverrequest-pause.js +++ b/test/parallel/test-http2-compat-serverrequest-pause.js @@ -28,8 +28,8 @@ server.on('request', common.mustCall((req, res) => { // shouldn't throw if underlying Http2Stream no longer exists res.on('finish', common.mustCall(() => process.nextTick(() => { - assert.doesNotThrow(() => req.pause()); - assert.doesNotThrow(() => req.resume()); + req.pause(); + req.resume(); }))); })); diff --git a/test/parallel/test-http2-compat-serverrequest-settimeout.js b/test/parallel/test-http2-compat-serverrequest-settimeout.js index f7189161802301..81184d70752563 100644 --- a/test/parallel/test-http2-compat-serverrequest-settimeout.js +++ b/test/parallel/test-http2-compat-serverrequest-settimeout.js @@ -3,7 +3,6 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); -const assert = require('assert'); const http2 = require('http2'); const msecs = common.platformTimeout(1); @@ -16,9 +15,7 @@ server.on('request', (req, res) => { res.on('finish', common.mustCall(() => { req.setTimeout(msecs, common.mustNotCall()); process.nextTick(() => { - assert.doesNotThrow( - () => req.setTimeout(msecs, common.mustNotCall()) - ); + req.setTimeout(msecs, common.mustNotCall()); server.close(); }); })); diff --git a/test/parallel/test-http2-compat-serverresponse-destroy.js b/test/parallel/test-http2-compat-serverresponse-destroy.js index 54214737840061..f890346dbf4303 100644 --- a/test/parallel/test-http2-compat-serverresponse-destroy.js +++ b/test/parallel/test-http2-compat-serverresponse-destroy.js @@ -3,7 +3,6 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); -const assert = require('assert'); const http2 = require('http2'); const Countdown = require('../common/countdown'); @@ -22,9 +21,9 @@ const server = http2.createServer(common.mustCall((req, res) => { res.on('error', common.mustNotCall()); res.on('finish', common.mustCall(() => { - assert.doesNotThrow(() => res.destroy(nextError)); + res.destroy(nextError); process.nextTick(() => { - assert.doesNotThrow(() => res.destroy(nextError)); + res.destroy(nextError); }); })); diff --git a/test/parallel/test-http2-compat-serverresponse-headers-after-destroy.js b/test/parallel/test-http2-compat-serverresponse-headers-after-destroy.js index 99e3ccc948184e..206bd1c9d43e06 100644 --- a/test/parallel/test-http2-compat-serverresponse-headers-after-destroy.js +++ b/test/parallel/test-http2-compat-serverresponse-headers-after-destroy.js @@ -15,12 +15,12 @@ server.listen(0, common.mustCall(function() { server.once('request', common.mustCall(function(request, response) { response.on('finish', common.mustCall(() => { assert.strictEqual(response.headersSent, false); - assert.doesNotThrow(() => response.setHeader('test', 'value')); - assert.doesNotThrow(() => response.removeHeader('test', 'value')); + response.setHeader('test', 'value'); + response.removeHeader('test', 'value'); process.nextTick(() => { - assert.doesNotThrow(() => response.setHeader('test', 'value')); - assert.doesNotThrow(() => response.removeHeader('test', 'value')); + response.setHeader('test', 'value'); + response.removeHeader('test', 'value'); server.close(); }); diff --git a/test/parallel/test-http2-compat-serverresponse-settimeout.js b/test/parallel/test-http2-compat-serverresponse-settimeout.js index bb09633727ccf7..220a84a754d651 100644 --- a/test/parallel/test-http2-compat-serverresponse-settimeout.js +++ b/test/parallel/test-http2-compat-serverresponse-settimeout.js @@ -3,7 +3,6 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); -const assert = require('assert'); const http2 = require('http2'); const msecs = common.platformTimeout(1); @@ -16,9 +15,7 @@ server.on('request', (req, res) => { res.on('finish', common.mustCall(() => { res.setTimeout(msecs, common.mustNotCall()); process.nextTick(() => { - assert.doesNotThrow( - () => res.setTimeout(msecs, common.mustNotCall()) - ); + res.setTimeout(msecs, common.mustNotCall()); server.close(); }); })); diff --git a/test/parallel/test-http2-compat-serverresponse-statuscode.js b/test/parallel/test-http2-compat-serverresponse-statuscode.js index ecb6da5df68c11..dd92db8d96597a 100644 --- a/test/parallel/test-http2-compat-serverresponse-statuscode.js +++ b/test/parallel/test-http2-compat-serverresponse-statuscode.js @@ -27,12 +27,11 @@ server.listen(0, common.mustCall(function() { assert.strictEqual(response.statusCode, expectedDefaultStatusCode); - assert.doesNotThrow(function() { - response.statusCode = realStatusCodes.ok; - response.statusCode = realStatusCodes.multipleChoices; - response.statusCode = realStatusCodes.badRequest; - response.statusCode = realStatusCodes.internalServerError; - }); + // Setting the response.statusCode should not throw. + response.statusCode = realStatusCodes.ok; + response.statusCode = realStatusCodes.multipleChoices; + response.statusCode = realStatusCodes.badRequest; + response.statusCode = realStatusCodes.internalServerError; common.expectsError(function() { response.statusCode = realStatusCodes.continue; diff --git a/test/parallel/test-http2-compat-socket.js b/test/parallel/test-http2-compat-socket.js index 80c8b1d30d10b3..e46bc4ef54751a 100644 --- a/test/parallel/test-http2-compat-socket.js +++ b/test/parallel/test-http2-compat-socket.js @@ -45,7 +45,7 @@ server.on('request', common.mustCall(function(request, response) { request.on('end', common.mustCall(() => { assert.strictEqual(request.socket.readable, false); - assert.doesNotThrow(() => response.socket.destroy()); + response.socket.destroy(); })); response.on('finish', common.mustCall(() => { assert.ok(request.socket); diff --git a/test/parallel/test-http2-connect.js b/test/parallel/test-http2-connect.js index 894c51fe3d9330..9b628db5aeebaa 100644 --- a/test/parallel/test-http2-connect.js +++ b/test/parallel/test-http2-connect.js @@ -3,7 +3,6 @@ const { mustCall, hasCrypto, skip, expectsError } = require('../common'); if (!hasCrypto) skip('missing crypto'); -const { doesNotThrow, throws } = require('assert'); const { createServer, connect } = require('http2'); { const server = createServer(); @@ -13,10 +12,11 @@ const { createServer, connect } = require('http2'); const listener = () => mustCall(); const clients = new Set(); - doesNotThrow(() => clients.add(connect(authority))); - doesNotThrow(() => clients.add(connect(authority, options))); - doesNotThrow(() => clients.add(connect(authority, options, listener()))); - doesNotThrow(() => clients.add(connect(authority, listener()))); + // Should not throw. + clients.add(connect(authority)); + clients.add(connect(authority, options)); + clients.add(connect(authority, options, listener())); + clients.add(connect(authority, listener())); for (const client of clients) { client.once('connect', mustCall((headers) => { @@ -33,20 +33,18 @@ const { createServer, connect } = require('http2'); // check for https as protocol { const authority = 'https://localhost'; - doesNotThrow(() => { - // A socket error may or may not be reported, keep this as a non-op - // instead of a mustCall or mustNotCall - connect(authority).on('error', () => {}); - }); + // A socket error may or may not be reported, keep this as a non-op + // instead of a mustCall or mustNotCall + connect(authority).on('error', () => {}); } // check for error for an invalid protocol (not http or https) { const authority = 'ssh://localhost'; - throws(() => { + expectsError(() => { connect(authority); - }, expectsError({ + }, { code: 'ERR_HTTP2_UNSUPPORTED_PROTOCOL', type: Error - })); + }); } diff --git a/test/parallel/test-http2-cookies.js b/test/parallel/test-http2-cookies.js index cf763915389287..8b371d8c4263cb 100644 --- a/test/parallel/test-http2-cookies.js +++ b/test/parallel/test-http2-cookies.js @@ -41,8 +41,8 @@ server.on('listening', common.mustCall(() => { const req = client.request({ ':path': '/', - abc: [1, 2, 3], - cookie: ['a=b', 'c=d', 'e=f'], + 'abc': [1, 2, 3], + 'cookie': ['a=b', 'c=d', 'e=f'], }); req.resume(); diff --git a/test/parallel/test-http2-getpackedsettings.js b/test/parallel/test-http2-getpackedsettings.js index 9ae2512b2cea06..56b96321139630 100644 --- a/test/parallel/test-http2-getpackedsettings.js +++ b/test/parallel/test-http2-getpackedsettings.js @@ -26,11 +26,12 @@ assert.deepStrictEqual(val, check); ['maxHeaderListSize', 0], ['maxHeaderListSize', 2 ** 32 - 1] ].forEach((i) => { - assert.doesNotThrow(() => http2.getPackedSettings({ [i[0]]: i[1] })); + // Valid options should not throw. + http2.getPackedSettings({ [i[0]]: i[1] }); }); -assert.doesNotThrow(() => http2.getPackedSettings({ enablePush: true })); -assert.doesNotThrow(() => http2.getPackedSettings({ enablePush: false })); +http2.getPackedSettings({ enablePush: true }); +http2.getPackedSettings({ enablePush: false }); [ ['headerTableSize', -1], @@ -85,7 +86,7 @@ assert.doesNotThrow(() => http2.getPackedSettings({ enablePush: false })); assert.deepStrictEqual(packed, check); } -// check for not passing settings +// Check for not passing settings. { const packed = http2.getPackedSettings(); assert.strictEqual(packed.length, 0); @@ -143,7 +144,7 @@ assert.doesNotThrow(() => http2.getPackedSettings({ enablePush: false })); assert.strictEqual(settings.enablePush, true); } -//check for what happens if passing {validate: true} and no errors happen +// Verify that passing {validate: true} does not throw. { const packed = Buffer.from([ 0x00, 0x01, 0x00, 0x00, 0x00, 0x64, 0x00, 0x03, 0x00, 0x00, @@ -151,12 +152,10 @@ assert.doesNotThrow(() => http2.getPackedSettings({ enablePush: false })); 0x00, 0x00, 0x00, 0x64, 0x00, 0x06, 0x00, 0x00, 0x00, 0x64, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01]); - assert.doesNotThrow(() => { - http2.getUnpackedSettings(packed, { validate: true }); - }); + http2.getUnpackedSettings(packed, { validate: true }); } -// check for maxFrameSize failing the max number +// Check for maxFrameSize failing the max number. { const packed = Buffer.from([0x00, 0x05, 0x01, 0x00, 0x00, 0x00]); @@ -169,7 +168,7 @@ assert.doesNotThrow(() => http2.getPackedSettings({ enablePush: false })); }); } -// check for maxConcurrentStreams failing the max number +// Check for maxConcurrentStreams failing the max number. { const packed = Buffer.from([0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF]); diff --git a/test/parallel/test-http2-misbehaving-multiplex.js b/test/parallel/test-http2-misbehaving-multiplex.js index 7d5a7a2f552d49..757e66b100e435 100644 --- a/test/parallel/test-http2-misbehaving-multiplex.js +++ b/test/parallel/test-http2-misbehaving-multiplex.js @@ -14,7 +14,14 @@ const server = h2.createServer(); server.on('stream', common.mustCall((stream) => { stream.respond(); stream.end('ok'); + + // the error will be emitted asynchronously + stream.on('error', common.expectsError({ + code: 'ERR_HTTP2_ERROR', + message: 'Stream was already closed or invalid' + })); }, 2)); + server.on('session', common.mustCall((session) => { session.on('error', common.expectsError({ code: 'ERR_HTTP2_ERROR', diff --git a/test/parallel/test-http2-server-errors.js b/test/parallel/test-http2-server-errors.js index a3586bd64d46e7..bbdf312fc153d4 100644 --- a/test/parallel/test-http2-server-errors.js +++ b/test/parallel/test-http2-server-errors.js @@ -54,12 +54,16 @@ const h2 = require('http2'); const server = h2.createServer(); + process.on('uncaughtException', common.mustCall(function(err) { + assert.strictEqual(err.message, 'kaboom no handler'); + })); + server.on('stream', common.mustCall(function(stream) { - // there is no 'error' handler, and this will not crash + // there is no 'error' handler, and this will crash stream.write('hello'); stream.resume(); - expected = new Error('kaboom'); + expected = new Error('kaboom no handler'); stream.destroy(expected); server.close(); })); diff --git a/test/parallel/test-http2-server-push-stream-head.js b/test/parallel/test-http2-server-push-stream-head.js index cd2276746f4bdd..35e22c0ce3b561 100644 --- a/test/parallel/test-http2-server-push-stream-head.js +++ b/test/parallel/test-http2-server-push-stream-head.js @@ -21,6 +21,12 @@ server.on('stream', common.mustCall((stream, headers) => { }, common.mustCall((err, push, headers) => { assert.strictEqual(push._writableState.ended, true); push.respond(); + // cannot write to push() anymore + push.on('error', common.expectsError({ + type: Error, + code: 'ERR_STREAM_WRITE_AFTER_END', + message: 'write after end' + })); assert(!push.write('test')); stream.end('test'); })); diff --git a/test/parallel/test-http2-server-rst-before-respond.js b/test/parallel/test-http2-server-rst-before-respond.js index 74181f4ffa0bbe..c2831d33079616 100644 --- a/test/parallel/test-http2-server-rst-before-respond.js +++ b/test/parallel/test-http2-server-rst-before-respond.js @@ -17,7 +17,7 @@ function onStream(stream, headers, flags) { common.expectsError(() => { stream.additionalHeaders({ ':status': 123, - abc: 123 + 'abc': 123 }); }, { code: 'ERR_HTTP2_INVALID_STREAM' }); } diff --git a/test/parallel/test-http2-server-rst-stream.js b/test/parallel/test-http2-server-rst-stream.js index 4a58091aa61d7f..6e4e9ccb88e611 100644 --- a/test/parallel/test-http2-server-rst-stream.js +++ b/test/parallel/test-http2-server-rst-stream.js @@ -18,14 +18,22 @@ const { const tests = [ [NGHTTP2_NO_ERROR, false], [NGHTTP2_NO_ERROR, false], - [NGHTTP2_PROTOCOL_ERROR, true], + [NGHTTP2_PROTOCOL_ERROR, true, 1], [NGHTTP2_CANCEL, false], - [NGHTTP2_REFUSED_STREAM, true], - [NGHTTP2_INTERNAL_ERROR, true] + [NGHTTP2_REFUSED_STREAM, true, 7], + [NGHTTP2_INTERNAL_ERROR, true, 2] ]; const server = http2.createServer(); server.on('stream', (stream, headers) => { + const test = tests.find((t) => t[0] === Number(headers.rstcode)); + if (test[1]) { + stream.on('error', common.expectsError({ + type: Error, + code: 'ERR_HTTP2_STREAM_ERROR', + message: `Stream closed with error code ${test[2]}` + })); + } stream.close(headers.rstcode | 0); }); @@ -40,7 +48,7 @@ server.listen(0, common.mustCall(() => { tests.forEach((test) => { const req = client.request({ ':method': 'POST', - rstcode: test[0] + 'rstcode': test[0] }); req.on('close', common.mustCall((code) => { assert.strictEqual(code, test[0]); diff --git a/test/parallel/test-http2-server-startup.js b/test/parallel/test-http2-server-startup.js index 0731b83a20b651..4ebcc21c27aa8e 100644 --- a/test/parallel/test-http2-server-startup.js +++ b/test/parallel/test-http2-server-startup.js @@ -10,7 +10,6 @@ const commonFixtures = require('../common/fixtures'); if (!common.hasCrypto) common.skip('missing crypto'); -const assert = require('assert'); const http2 = require('http2'); const tls = require('tls'); const net = require('net'); @@ -20,28 +19,20 @@ const options = { cert: commonFixtures.readKey('agent2-cert.pem') }; -// There should not be any throws -assert.doesNotThrow(() => { +// There should not be any throws. +const serverTLS = http2.createSecureServer(options, () => {}); +serverTLS.listen(0, common.mustCall(() => serverTLS.close())); - const serverTLS = http2.createSecureServer(options, () => {}); +// There should not be an error event reported either. +serverTLS.on('error', common.mustNotCall()); - serverTLS.listen(0, common.mustCall(() => serverTLS.close())); +const server = http2.createServer(options, common.mustNotCall()); +server.listen(0, common.mustCall(() => server.close())); - // There should not be an error event reported either - serverTLS.on('error', common.mustNotCall()); -}); +// There should not be an error event reported either. +server.on('error', common.mustNotCall()); -// There should not be any throws -assert.doesNotThrow(() => { - const server = http2.createServer(options, common.mustNotCall()); - - server.listen(0, common.mustCall(() => server.close())); - - // There should not be an error event reported either - server.on('error', common.mustNotCall()); -}); - -// Test the plaintext server socket timeout +// Test the plaintext server socket timeout. { let client; const server = http2.createServer(); @@ -57,7 +48,7 @@ assert.doesNotThrow(() => { })); } -// Test the secure server socket timeout +// Test the secure server socket timeout. { let client; const server = http2.createSecureServer(options); diff --git a/test/parallel/test-http2-server-stream-session-destroy.js b/test/parallel/test-http2-server-stream-session-destroy.js index 5eb04a8d376635..989c72ec959679 100644 --- a/test/parallel/test-http2-server-stream-session-destroy.js +++ b/test/parallel/test-http2-server-stream-session-destroy.js @@ -34,6 +34,11 @@ server.on('stream', common.mustCall((stream) => { type: Error } ); + stream.on('error', common.expectsError({ + type: Error, + code: 'ERR_STREAM_WRITE_AFTER_END', + message: 'write after end' + })); assert.strictEqual(stream.write('data'), false); })); diff --git a/test/parallel/test-http2-session-settings.js b/test/parallel/test-http2-session-settings.js index 75fcc1942104ac..6061808082519d 100644 --- a/test/parallel/test-http2-session-settings.js +++ b/test/parallel/test-http2-session-settings.js @@ -76,9 +76,7 @@ server.listen( // State will only be valid after connect event is emitted req.on('ready', common.mustCall(() => { - assert.doesNotThrow(() => { - client.settings({ maxHeaderListSize: 1 }, common.mustCall()); - }); + client.settings({ maxHeaderListSize: 1 }, common.mustCall()); // Verify valid error ranges [ diff --git a/test/parallel/test-http2-socket-proxy.js b/test/parallel/test-http2-socket-proxy.js index 2d90ef7e952a55..912ec673ba79cc 100644 --- a/test/parallel/test-http2-socket-proxy.js +++ b/test/parallel/test-http2-socket-proxy.js @@ -47,8 +47,9 @@ server.on('stream', common.mustCall(function(stream, headers) { common.expectsError(() => (socket.resume = undefined), errMsg); common.expectsError(() => (socket.write = undefined), errMsg); - assert.doesNotThrow(() => (socket.on = socket.on)); - assert.doesNotThrow(() => (socket.once = socket.once)); + // Resetting the socket listeners to their own value should not throw. + socket.on = socket.on; + socket.once = socket.once; stream.respond(); diff --git a/test/parallel/test-http2-util-asserts.js b/test/parallel/test-http2-util-asserts.js index 1e7a0113f4a850..bfed09de4f72b8 100644 --- a/test/parallel/test-http2-util-asserts.js +++ b/test/parallel/test-http2-util-asserts.js @@ -2,7 +2,6 @@ 'use strict'; const common = require('../common'); -const assert = require('assert'); const { assertIsObject, assertWithinRange, @@ -15,7 +14,7 @@ const { new Date(), new (class Foo {})() ].forEach((i) => { - assert.doesNotThrow(() => assertIsObject(i, 'foo', 'Object')); + assertIsObject(i, 'foo', 'Object'); }); [ @@ -34,7 +33,7 @@ const { }); }); -assert.doesNotThrow(() => assertWithinRange('foo', 1, 0, 2)); +assertWithinRange('foo', 1, 0, 2); common.expectsError(() => assertWithinRange('foo', 1, 2, 3), { diff --git a/test/parallel/test-http2-withflag.js b/test/parallel/test-http2-withflag.js deleted file mode 100644 index 0a01efc517b916..00000000000000 --- a/test/parallel/test-http2-withflag.js +++ /dev/null @@ -1,8 +0,0 @@ -'use strict'; - -const common = require('../common'); -if (!common.hasCrypto) - common.skip('missing crypto'); -const assert = require('assert'); - -assert.doesNotThrow(() => require('http2')); diff --git a/test/parallel/test-https-agent-constructor.js b/test/parallel/test-https-agent-constructor.js index 29bb9eaa98067d..69156ba0f64de9 100644 --- a/test/parallel/test-https-agent-constructor.js +++ b/test/parallel/test-https-agent-constructor.js @@ -6,5 +6,4 @@ if (!common.hasCrypto) const assert = require('assert'); const https = require('https'); -assert.doesNotThrow(() => { https.Agent(); }); assert.ok(https.Agent() instanceof https.Agent); diff --git a/test/parallel/test-https-agent-servername.js b/test/parallel/test-https-agent-servername.js index 985fbb3ce3f76e..df14d113994f89 100644 --- a/test/parallel/test-https-agent-servername.js +++ b/test/parallel/test-https-agent-servername.js @@ -10,7 +10,7 @@ const fixtures = require('../common/fixtures'); const options = { key: fixtures.readKey('agent1-key.pem'), cert: fixtures.readKey('agent1-cert.pem'), - ca: fixtures.readKey('ca1-cert.pem') + ca: fixtures.readKey('ca1-cert.pem') }; diff --git a/test/parallel/test-https-options-boolean-check.js b/test/parallel/test-https-options-boolean-check.js index 04baf403df98cb..fa223aa8872bd6 100644 --- a/test/parallel/test-https-options-boolean-check.js +++ b/test/parallel/test-https-options-boolean-check.js @@ -6,7 +6,6 @@ const fixtures = require('../common/fixtures'); if (!common.hasCrypto) common.skip('missing crypto'); -const assert = require('assert'); const https = require('https'); function toArrayBuffer(buf) { @@ -65,11 +64,9 @@ const invalidCertRE = /^The "cert" argument must be one of type string, Buffer, [[{ pem: keyBuff }], false], [[{ pem: keyBuff }, { pem: keyBuff }], false] ].forEach((params) => { - assert.doesNotThrow(() => { - https.createServer({ - key: params[0], - cert: params[1] - }); + https.createServer({ + key: params[0], + cert: params[1] }); }); @@ -124,12 +121,10 @@ const invalidCertRE = /^The "cert" argument must be one of type string, Buffer, [keyBuff, certBuff, caArrDataView], [keyBuff, certBuff, false], ].forEach((params) => { - assert.doesNotThrow(() => { - https.createServer({ - key: params[0], - cert: params[1], - ca: params[2] - }); + https.createServer({ + key: params[0], + cert: params[1], + ca: params[2] }); }); diff --git a/test/parallel/test-icu-punycode.js b/test/parallel/test-icu-punycode.js index 7abcae461774c0..82c15287982631 100644 --- a/test/parallel/test-icu-punycode.js +++ b/test/parallel/test-icu-punycode.js @@ -34,13 +34,12 @@ const wptToASCIITests = require('../fixtures/url-toascii.js'); if (output === null) { assert.throws(() => icu.toASCII(input), errMessage, `ToASCII ${caseComment}`); - assert.doesNotThrow(() => icu.toASCII(input, true), - `ToASCII ${caseComment} in lenient mode`); + icu.toASCII(input, true); // Should not throw. } else { assert.strictEqual(icu.toASCII(input), output, `ToASCII ${caseComment}`); assert.strictEqual(icu.toASCII(input, true), output, `ToASCII ${caseComment} in lenient mode`); } - assert.doesNotThrow(() => icu.toUnicode(input), `ToUnicode ${caseComment}`); + icu.toUnicode(input); // Should not throw. } } diff --git a/test/parallel/test-internal-errors.js b/test/parallel/test-internal-errors.js index ae5e2672285688..f5876b7f568dd9 100644 --- a/test/parallel/test-internal-errors.js +++ b/test/parallel/test-internal-errors.js @@ -138,32 +138,24 @@ common.expectsError( message: invalidKey('true') }); - // Tests for common.expectsError -assert.doesNotThrow(() => { - common.expectsError(() => { - throw new errors.TypeError('TEST_ERROR_1', 'a'); - }, { code: 'TEST_ERROR_1' }); -}); - -assert.doesNotThrow(() => { - common.expectsError(() => { - throw new errors.TypeError('TEST_ERROR_1', 'a'); - }, { code: 'TEST_ERROR_1', - type: TypeError, - message: /^Error for testing/ }); -}); - -assert.doesNotThrow(() => { - common.expectsError(() => { - throw new errors.TypeError('TEST_ERROR_1', 'a'); - }, { code: 'TEST_ERROR_1', type: TypeError }); -}); - -assert.doesNotThrow(() => { - common.expectsError(() => { - throw new errors.TypeError('TEST_ERROR_1', 'a'); - }, { code: 'TEST_ERROR_1', type: Error }); +common.expectsError(() => { + throw new errors.TypeError('TEST_ERROR_1', 'a'); +}, { code: 'TEST_ERROR_1' }); +common.expectsError(() => { + throw new errors.TypeError('TEST_ERROR_1', 'a'); +}, { code: 'TEST_ERROR_1', + type: TypeError, + message: /^Error for testing/ }); +common.expectsError(() => { + throw new errors.TypeError('TEST_ERROR_1', 'a'); +}, { code: 'TEST_ERROR_1', type: TypeError }); +common.expectsError(() => { + throw new errors.TypeError('TEST_ERROR_1', 'a'); +}, { + code: 'TEST_ERROR_1', + type: TypeError, + message: 'Error for testing purposes: a' }); common.expectsError(() => { @@ -300,19 +292,6 @@ assert.strictEqual( errors.message('ERR_ENCODING_NOT_SUPPORTED', ['enc']), 'The "enc" encoding is not supported'); -// Test ERR_HTTP2_HEADER_REQUIRED -assert.strictEqual( - errors.message('ERR_HTTP2_HEADER_REQUIRED', ['test']), - 'The test header is required'); - -// Test ERR_HTTP2_FRAME_ERROR -assert.strictEqual( - errors.message('ERR_HTTP2_FRAME_ERROR', ['foo', 'bar', 'baz']), - 'Error sending frame type foo for stream baz with code bar'); -assert.strictEqual( - errors.message('ERR_HTTP2_FRAME_ERROR', ['foo', 'bar']), - 'Error sending frame type foo with code bar'); - // Test error messages for async_hooks assert.strictEqual( errors.message('ERR_ASYNC_CALLBACK', ['init']), diff --git a/test/parallel/test-internal-fs.js b/test/parallel/test-internal-fs.js index fe6c50194d1c72..9bc0a98b099f75 100644 --- a/test/parallel/test-internal-fs.js +++ b/test/parallel/test-internal-fs.js @@ -2,11 +2,12 @@ 'use strict'; const common = require('../common'); -const assert = require('assert'); const fs = require('internal/fs'); -assert.doesNotThrow(() => fs.assertEncoding()); -assert.doesNotThrow(() => fs.assertEncoding('utf8')); +// Valid encodings and no args should not throw. +fs.assertEncoding(); +fs.assertEncoding('utf8'); + common.expectsError( () => fs.assertEncoding('foo'), { code: 'ERR_INVALID_OPT_VALUE_ENCODING', type: TypeError } diff --git a/test/parallel/test-internal-util-assertCrypto.js b/test/parallel/test-internal-util-assertCrypto.js index d01eab3a237ded..035519c9c9ef7a 100644 --- a/test/parallel/test-internal-util-assertCrypto.js +++ b/test/parallel/test-internal-util-assertCrypto.js @@ -11,5 +11,5 @@ if (!process.versions.openssl) { }); assert.throws(() => util.assertCrypto(), expectedError); } else { - assert.doesNotThrow(() => util.assertCrypto()); + util.assertCrypto(); } diff --git a/test/parallel/test-internal-util-decorate-error-stack.js b/test/parallel/test-internal-util-decorate-error-stack.js index a0682161ae2c69..5694d746c667f4 100644 --- a/test/parallel/test-internal-util-decorate-error-stack.js +++ b/test/parallel/test-internal-util-decorate-error-stack.js @@ -12,14 +12,13 @@ const kDecoratedPrivateSymbolIndex = binding.decorated_private_symbol; const decorateErrorStack = internalUtil.decorateErrorStack; -assert.doesNotThrow(function() { - decorateErrorStack(); - decorateErrorStack(null); - decorateErrorStack(1); - decorateErrorStack(true); -}); +// Verify that decorateErrorStack does not throw with non-objects. +decorateErrorStack(); +decorateErrorStack(null); +decorateErrorStack(1); +decorateErrorStack(true); -// Verify that a stack property is not added to non-Errors +// Verify that a stack property is not added to non-Errors. const obj = {}; decorateErrorStack(obj); assert.strictEqual(obj.stack, undefined); @@ -48,12 +47,12 @@ try { assert(typeof err, 'object'); checkStack(err.stack); -// Verify that the stack is only decorated once +// Verify that the stack is only decorated once. decorateErrorStack(err); decorateErrorStack(err); checkStack(err.stack); -// Verify that the stack is only decorated once for uncaught exceptions +// Verify that the stack is only decorated once for uncaught exceptions. const args = [ '-e', `require('${badSyntaxPath}')` @@ -61,14 +60,14 @@ const args = [ const result = spawnSync(process.argv[0], args, { encoding: 'utf8' }); checkStack(result.stderr); -// Verify that the stack is unchanged when there is no arrow message +// Verify that the stack is unchanged when there is no arrow message. err = new Error('foo'); let originalStack = err.stack; decorateErrorStack(err); assert.strictEqual(originalStack, err.stack); // Verify that the arrow message is added to the start of the stack when it -// exists +// exists. const arrowMessage = 'arrow_message'; err = new Error('foo'); originalStack = err.stack; 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 78565e3f596594..8532f11c86b804 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-module-symlinked-peer-modules.js b/test/parallel/test-module-symlinked-peer-modules.js index 27e67b31d182e5..fb02a8a94d5d66 100644 --- a/test/parallel/test-module-symlinked-peer-modules.js +++ b/test/parallel/test-module-symlinked-peer-modules.js @@ -11,7 +11,6 @@ const common = require('../common'); const fs = require('fs'); const path = require('path'); -const assert = require('assert'); const tmpdir = require('../common/tmpdir'); tmpdir.refresh(); @@ -60,6 +59,4 @@ fs.writeFileSync(path.join(moduleB, 'package.json'), fs.writeFileSync(path.join(moduleB, 'index.js'), 'module.exports = 1;', 'utf8'); -assert.doesNotThrow(() => { - require(path.join(app, 'index')); -}); +require(path.join(app, 'index')); // Should not throw. diff --git a/test/parallel/test-net-after-close.js b/test/parallel/test-net-after-close.js index 1594d36f9075a3..0750ba0f435512 100644 --- a/test/parallel/test-net-after-close.js +++ b/test/parallel/test-net-after-close.js @@ -34,16 +34,16 @@ server.listen(0, common.mustCall(function() { c.on('close', common.mustCall(function() { console.error('connection closed'); assert.strictEqual(c._handle, null); - assert.doesNotThrow(function() { - c.setNoDelay(); - c.setKeepAlive(); - c.bufferSize; - c.pause(); - c.resume(); - c.address(); - c.remoteAddress; - c.remotePort; - }); + // Calling functions / accessing properties of a closed socket should not + // throw. + c.setNoDelay(); + c.setKeepAlive(); + c.bufferSize; + c.pause(); + c.resume(); + c.address(); + c.remoteAddress; + c.remotePort; server.close(); })); })); diff --git a/test/parallel/test-net-connect-options-port.js b/test/parallel/test-net-connect-options-port.js index 8152424c52c8fc..ea3fadf7211af6 100644 --- a/test/parallel/test-net-connect-options-port.js +++ b/test/parallel/test-net-connect-options-port.js @@ -171,27 +171,26 @@ function canConnect(port) { // connect(port, cb) and connect(port) const portArgBlocks = doConnect([port], noop); for (const block of portArgBlocks) { - assert.doesNotThrow(block, `${block.name}(${port})`); + block(); } // connect(port, host, cb) and connect(port, host) const portHostArgBlocks = doConnect([port, 'localhost'], noop); for (const block of portHostArgBlocks) { - assert.doesNotThrow(block, `${block.name}(${port})`); + block(); } // connect({port}, cb) and connect({port}) const portOptBlocks = doConnect([{ port }], noop); for (const block of portOptBlocks) { - assert.doesNotThrow(block, `${block.name}({port: ${port}})`); + block(); } // connect({port, host}, cb) and connect({port, host}) const portHostOptBlocks = doConnect([{ port: port, host: 'localhost' }], noop); for (const block of portHostOptBlocks) { - assert.doesNotThrow(block, - `${block.name}({port: ${port}, host: 'localhost'})`); + block(); } } @@ -205,25 +204,19 @@ function asyncFailToConnect(port) { // connect(port, cb) and connect(port) const portArgBlocks = doConnect([port], dont); for (const block of portArgBlocks) { - assert.doesNotThrow(function() { - block().on('error', onError()); - }, `${block.name}(${port})`); + block().on('error', onError()); } // connect({port}, cb) and connect({port}) const portOptBlocks = doConnect([{ port }], dont); for (const block of portOptBlocks) { - assert.doesNotThrow(function() { - block().on('error', onError()); - }, `${block.name}({port: ${port}})`); + block().on('error', onError()); } // connect({port, host}, cb) and connect({port, host}) const portHostOptBlocks = doConnect([{ port: port, host: 'localhost' }], dont); for (const block of portHostOptBlocks) { - assert.doesNotThrow(function() { - block().on('error', onError()); - }, `${block.name}({port: ${port}, host: 'localhost'})`); + block().on('error', onError()); } } diff --git a/test/parallel/test-net-during-close.js b/test/parallel/test-net-during-close.js index a85863955e7728..7bceb64041f2cc 100644 --- a/test/parallel/test-net-during-close.js +++ b/test/parallel/test-net-during-close.js @@ -21,7 +21,6 @@ 'use strict'; const common = require('../common'); -const assert = require('assert'); const net = require('net'); const server = net.createServer(function(socket) { @@ -31,13 +30,11 @@ const server = net.createServer(function(socket) { server.listen(0, common.mustCall(function() { const client = net.createConnection(this.address().port); server.close(); - // server connection event has not yet fired - // client is still attempting to connect - assert.doesNotThrow(function() { - client.remoteAddress; - client.remoteFamily; - client.remotePort; - }); - // exit now, do not wait for the client error event + // Server connection event has not yet fired client is still attempting to + // connect. Accessing properties should not throw in this case. + client.remoteAddress; + client.remoteFamily; + client.remotePort; + // Exit now, do not wait for the client error event. process.exit(0); })); diff --git a/test/parallel/test-regress-GH-5727.js b/test/parallel/test-net-listen-invalid-port.js similarity index 82% rename from test/parallel/test-regress-GH-5727.js rename to test/parallel/test-net-listen-invalid-port.js index fab139ca7c305c..d07bc9fafa8f56 100644 --- a/test/parallel/test-regress-GH-5727.js +++ b/test/parallel/test-net-listen-invalid-port.js @@ -1,5 +1,10 @@ 'use strict'; const common = require('../common'); + +// This test ensures that port numbers are validated in *all* kinds of `listen` +// calls. If an invalid port is supplied, ensures a `RangeError` is thrown. +// https://github.com/nodejs/node/issues/5727 + const assert = require('assert'); const net = require('net'); diff --git a/test/parallel/test-net-options-lookup.js b/test/parallel/test-net-options-lookup.js index 0551a241147e84..0b4e18f12f04f0 100644 --- a/test/parallel/test-net-options-lookup.js +++ b/test/parallel/test-net-options-lookup.js @@ -1,6 +1,5 @@ 'use strict'; const common = require('../common'); -const assert = require('assert'); const net = require('net'); ['foobar', 1, {}, []].forEach((input) => connectThrows(input)); @@ -30,7 +29,5 @@ function connectDoesNotThrow(input) { lookup: input }; - assert.doesNotThrow(() => { - net.connect(opts); - }); + net.connect(opts); } diff --git a/test/parallel/test-net-server-call-listen-multiple-times.js b/test/parallel/test-net-server-call-listen-multiple-times.js index 05099dadc86bdf..4b1a8d07334ac2 100644 --- a/test/parallel/test-net-server-call-listen-multiple-times.js +++ b/test/parallel/test-net-server-call-listen-multiple-times.js @@ -1,7 +1,6 @@ 'use strict'; const common = require('../common'); -const assert = require('assert'); const net = require('net'); // First test. Check that after error event you can listen right away. @@ -16,12 +15,10 @@ const net = require('net'); })); server.on('error', common.mustCall((e) => { - assert.doesNotThrow( - () => server.listen(common.mustCall(() => { - dummyServer.close(); - server.close(); - })) - ); + server.listen(common.mustCall(() => { + dummyServer.close(); + server.close(); + })); })); } @@ -44,8 +41,6 @@ const net = require('net'); server.listen(common.mustCall(() => { server.close(); - assert.doesNotThrow( - () => server.listen(common.mustCall(() => server.close())) - ); + server.listen(common.mustCall(() => server.close())); })); } diff --git a/test/parallel/test-net-socket-no-halfopen-enforcer.js b/test/parallel/test-net-socket-no-halfopen-enforcer.js new file mode 100644 index 00000000000000..3df5b6d7b9c8cb --- /dev/null +++ b/test/parallel/test-net-socket-no-halfopen-enforcer.js @@ -0,0 +1,11 @@ +'use strict'; +require('../common'); + +// This test ensures that `net.Socket` does not inherit the no-half-open +// enforcer from `stream.Duplex`. + +const { Socket } = require('net'); +const { strictEqual } = require('assert'); + +const socket = new Socket({ allowHalfOpen: false }); +strictEqual(socket.listenerCount('end'), 1); diff --git a/test/parallel/test-net-socket-timeout.js b/test/parallel/test-net-socket-timeout.js index de4a7ed37ccf20..51224f3b7ecdcf 100644 --- a/test/parallel/test-net-socket-timeout.js +++ b/test/parallel/test-net-socket-timeout.js @@ -46,9 +46,7 @@ for (let i = 0; i < badRangeDelays.length; i++) { } for (let i = 0; i < validDelays.length; i++) { - assert.doesNotThrow(function() { - s.setTimeout(validDelays[i], () => {}); - }); + s.setTimeout(validDelays[i], () => {}); } const server = net.Server(); diff --git a/test/parallel/test-performanceobserver.js b/test/parallel/test-performanceobserver.js index af83d199da9186..2a6299952271e1 100644 --- a/test/parallel/test-performanceobserver.js +++ b/test/parallel/test-performanceobserver.js @@ -77,7 +77,7 @@ assert.strictEqual(counts[NODE_PERFORMANCE_ENTRY_TYPE_FUNCTION], 0); countdown.dec(); } assert.strictEqual(counts[NODE_PERFORMANCE_ENTRY_TYPE_MARK], 1); - assert.doesNotThrow(() => observer.observe({ entryTypes: ['mark'] })); + observer.observe({ entryTypes: ['mark'] }); assert.strictEqual(counts[NODE_PERFORMANCE_ENTRY_TYPE_MARK], 2); performance.mark('test1'); performance.mark('test2'); @@ -125,13 +125,9 @@ assert.strictEqual(counts[NODE_PERFORMANCE_ENTRY_TYPE_FUNCTION], 0); } } - assert.doesNotThrow(() => { - observer.observe({ entryTypes: ['mark', 'measure'], buffered: true }); - }); + observer.observe({ entryTypes: ['mark', 'measure'], buffered: true }); // Do this twice to make sure it doesn't throw - assert.doesNotThrow(() => { - observer.observe({ entryTypes: ['mark', 'measure'], buffered: true }); - }); + observer.observe({ entryTypes: ['mark', 'measure'], buffered: true }); // Even tho we called twice, count should be 1 assert.strictEqual(counts[NODE_PERFORMANCE_ENTRY_TYPE_MARK], 2); performance.mark('test1'); diff --git a/test/parallel/test-postmortem-metadata.js b/test/parallel/test-postmortem-metadata.js index e657ec70e8f5b2..ab402054c7a527 100644 --- a/test/parallel/test-postmortem-metadata.js +++ b/test/parallel/test-postmortem-metadata.js @@ -26,6 +26,11 @@ const nm = spawnSync('nm', args); if (nm.error && nm.error.errno === 'ENOENT') common.skip('nm not found on system'); +const stderr = nm.stderr.toString(); +if (stderr.length > 0) { + common.skip(`Failed to execute nm: ${stderr}`); +} + const symbolRe = /\s_?(v8dbg_.+)$/; const symbols = nm.stdout.toString().split('\n').reduce((filtered, line) => { const match = line.match(symbolRe); diff --git a/test/parallel/test-process-binding.js b/test/parallel/test-process-binding.js index 475891aa5d30d8..3715826bb27615 100644 --- a/test/parallel/test-process-binding.js +++ b/test/parallel/test-process-binding.js @@ -9,10 +9,4 @@ assert.throws( /No such module: test/ ); -assert.doesNotThrow(function() { - process.binding('buffer'); -}, function(err) { - if (err instanceof Error) { - return true; - } -}, 'unexpected error'); +process.binding('buffer'); diff --git a/test/parallel/test-regress-GH-4256.js b/test/parallel/test-process-domain-segfault.js similarity index 88% rename from test/parallel/test-regress-GH-4256.js rename to test/parallel/test-process-domain-segfault.js index 6a4a4467b4fd81..78009f4687d8dc 100644 --- a/test/parallel/test-regress-GH-4256.js +++ b/test/parallel/test-process-domain-segfault.js @@ -21,6 +21,11 @@ 'use strict'; require('../common'); + +// This test ensures that setting `process.domain` to `null` does not result in +// node crashing with a segfault. +// https://github.com/nodejs/node-v0.x-archive/issues/4256 + process.domain = null; setTimeout(function() { console.log('this console.log statement should not make node crash'); diff --git a/test/parallel/test-process-emitwarning.js b/test/parallel/test-process-emitwarning.js index 06772c7be6c210..e07fcd253c4128 100644 --- a/test/parallel/test-process-emitwarning.js +++ b/test/parallel/test-process-emitwarning.js @@ -44,7 +44,7 @@ class CustomWarning extends Error { [testMsg, { type: testType, code: testCode, detail: null }], [testMsg, { type: testType, code: testCode, detail: 1 }] ].forEach((i) => { - assert.doesNotThrow(() => process.emitWarning.apply(null, i)); + process.emitWarning.apply(null, i); }); const warningNoToString = new CustomWarning(); diff --git a/test/parallel/test-process-env-symbols.js b/test/parallel/test-process-env-symbols.js index 51e8eafbeacf51..855c791c0fb033 100644 --- a/test/parallel/test-process-env-symbols.js +++ b/test/parallel/test-process-env-symbols.js @@ -28,4 +28,4 @@ assert.strictEqual(symbol in process.env, false); assert.strictEqual(delete process.env[symbol], true); // Checks that well-known symbols like `Symbol.toStringTag` won’t throw. -assert.doesNotThrow(() => Object.prototype.toString.call(process.env)); +Object.prototype.toString.call(process.env); diff --git a/test/parallel/test-process-geteuid-getegid.js b/test/parallel/test-process-geteuid-getegid.js index 8dab52389b0384..41e37874a41b59 100644 --- a/test/parallel/test-process-geteuid-getegid.js +++ b/test/parallel/test-process-geteuid-getegid.js @@ -21,10 +21,9 @@ assert.throws(() => { // If we're not running as super user... if (process.getuid() !== 0) { - assert.doesNotThrow(() => { - process.getegid(); - process.geteuid(); - }); + // Should not throw. + process.getegid(); + process.geteuid(); assert.throws(() => { process.setegid('nobody'); diff --git a/test/parallel/test-process-setuid-setgid.js b/test/parallel/test-process-setuid-setgid.js index e0db8ee00222dd..41fef8c9c819fa 100644 --- a/test/parallel/test-process-setuid-setgid.js +++ b/test/parallel/test-process-setuid-setgid.js @@ -39,10 +39,9 @@ assert.throws(() => { // If we're not running as super user... if (process.getuid() !== 0) { - assert.doesNotThrow(() => { - process.getgid(); - process.getuid(); - }); + // Should not throw. + process.getgid(); + process.getuid(); assert.throws( () => { process.setgid('nobody'); }, diff --git a/test/parallel/test-querystring.js b/test/parallel/test-querystring.js index 76049584dbe458..2090d76b75ee34 100644 --- a/test/parallel/test-querystring.js +++ b/test/parallel/test-querystring.js @@ -75,8 +75,8 @@ const qsTestCases = [ ['foo&bar=baz', 'foo=&bar=baz', { foo: '', bar: 'baz' }], ['a=b&c&d=e', 'a=b&c=&d=e', { a: 'b', c: '', d: 'e' }], ['a=b&c=&d=e', 'a=b&c=&d=e', { a: 'b', c: '', d: 'e' }], - ['a=b&=c&d=e', 'a=b&=c&d=e', { a: 'b', '': 'c', d: 'e' }], - ['a=b&=&c=d', 'a=b&=&c=d', { a: 'b', '': '', c: 'd' }], + ['a=b&=c&d=e', 'a=b&=c&d=e', { 'a': 'b', '': 'c', 'd': 'e' }], + ['a=b&=&c=d', 'a=b&=&c=d', { 'a': 'b', '': '', 'c': 'd' }], ['&&foo=bar&&', 'foo=bar', { foo: 'bar' }], ['&', '', {}], ['&&&&', '', {}], @@ -300,9 +300,7 @@ assert.strictEqual('foo=', qs.stringify({ foo: Infinity })); assert.strictEqual(f, 'a=b&q=x%3Dy%26y%3Dz'); } -assert.doesNotThrow(() => { - qs.parse(undefined); -}); +qs.parse(undefined); // Should not throw. // nested in colon { diff --git a/test/parallel/test-readline-csi.js b/test/parallel/test-readline-csi.js index a3316a8800e4e3..f5c2d3044c5cdf 100644 --- a/test/parallel/test-readline-csi.js +++ b/test/parallel/test-readline-csi.js @@ -61,15 +61,16 @@ assert.deepStrictEqual(writable.data, CSI.kClearLine); assert.deepStrictEqual(writable.data, set[2]); }); -assert.doesNotThrow(() => readline.cursorTo(null)); -assert.doesNotThrow(() => readline.cursorTo()); +// Undefined or null as stream should not throw. +readline.cursorTo(null); +readline.cursorTo(); writable.data = ''; -assert.doesNotThrow(() => readline.cursorTo(writable, 'a')); +readline.cursorTo(writable, 'a'); assert.strictEqual(writable.data, ''); writable.data = ''; -assert.doesNotThrow(() => readline.cursorTo(writable, 'a', 'b')); +readline.cursorTo(writable, 'a', 'b'); assert.strictEqual(writable.data, ''); writable.data = ''; @@ -83,9 +84,9 @@ common.expectsError( assert.strictEqual(writable.data, ''); writable.data = ''; -assert.doesNotThrow(() => readline.cursorTo(writable, 1, 'a')); +readline.cursorTo(writable, 1, 'a'); assert.strictEqual(writable.data, '\x1b[2G'); writable.data = ''; -assert.doesNotThrow(() => readline.cursorTo(writable, 1, 2)); +readline.cursorTo(writable, 1, 2); assert.strictEqual(writable.data, '\x1b[3;2H'); diff --git a/test/parallel/test-readline-interface.js b/test/parallel/test-readline-interface.js index fe33e244cebd20..30afba843a2d98 100644 --- a/test/parallel/test-readline-interface.js +++ b/test/parallel/test-readline-interface.js @@ -823,23 +823,12 @@ function isWarned(emitter) { fi.emit('data', 'asdf\n'); assert.ok(called); - assert.doesNotThrow(function() { - rli.setPrompt('ddd> '); - }); - - assert.doesNotThrow(function() { - rli.prompt(); - }); - - assert.doesNotThrow(function() { - rli.write('really shouldnt be seeing this'); - }); - - assert.doesNotThrow(function() { - rli.question('What do you think of node.js? ', function(answer) { - console.log('Thank you for your valuable feedback:', answer); - rli.close(); - }); + rli.setPrompt('ddd> '); + rli.prompt(); + rli.write('really shouldnt be seeing this'); + rli.question('What do you think of node.js? ', function(answer) { + console.log('Thank you for your valuable feedback:', answer); + rli.close(); }); } diff --git a/test/parallel/test-regress-GH-4948.js b/test/parallel/test-regress-GH-4948.js deleted file mode 100644 index d4d63600868470..00000000000000 --- a/test/parallel/test-regress-GH-4948.js +++ /dev/null @@ -1,43 +0,0 @@ -'use strict'; -// https://github.com/joyent/node/issues/4948 - -require('../common'); -const http = require('http'); - -let reqCount = 0; -const server = http.createServer(function(serverReq, serverRes) { - if (reqCount) { - serverRes.end(); - server.close(); - return; - } - reqCount = 1; - - - // normally the use case would be to call an external site - // does not require connecting locally or to itself to fail - const r = http.request({ hostname: 'localhost', - port: this.address().port }, function(res) { - // required, just needs to be in the client response somewhere - serverRes.end(); - - // required for test to fail - res.on('data', () => {}); - - }); - r.on('error', () => {}); - r.end(); - - serverRes.write('some data'); -}).listen(0, function() { - // simulate a client request that closes early - const net = require('net'); - - const sock = new net.Socket(); - sock.connect(this.address().port, 'localhost'); - - sock.on('connect', function() { - sock.write('GET / HTTP/1.1\r\n\r\n'); - sock.end(); - }); -}); 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 a92bb3e75259f0..00000000000000 --- 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-repl-null.js b/test/parallel/test-repl-null.js index 66d09b28f28b84..18009558eda4b5 100644 --- a/test/parallel/test-repl-null.js +++ b/test/parallel/test-repl-null.js @@ -1,7 +1,6 @@ 'use strict'; require('../common'); const repl = require('repl'); -const assert = require('assert'); const replserver = new repl.REPLServer(); @@ -10,8 +9,5 @@ replserver._inTemplateLiteral = true; // `null` gets treated like an empty string. (Should it? You have to do some // strange business to get it into the REPL. Maybe it should really throw?) -assert.doesNotThrow(() => { - replserver.emit('line', null); -}); - +replserver.emit('line', null); replserver.emit('line', '.exit'); diff --git a/test/parallel/test-repl-throw-null-or-undefined.js b/test/parallel/test-repl-throw-null-or-undefined.js index fd2fd202b5bcb6..3b4657ce98c0f3 100644 --- a/test/parallel/test-repl-throw-null-or-undefined.js +++ b/test/parallel/test-repl-throw-null-or-undefined.js @@ -3,16 +3,11 @@ require('../common'); // This test ensures that the repl does not // crash or emit error when throwing `null|undefined` -// ie `throw null` or `throw undefined` +// ie `throw null` or `throw undefined`. -const assert = require('assert'); -const repl = require('repl'); - -const r = repl.start(); - -assert.doesNotThrow(() => { - r.write('throw null\n'); - r.write('throw undefined\n'); -}, TypeError, 'repl crashes/throw error on `throw null|undefined`'); +const r = require('repl').start(); +// Should not throw. +r.write('throw null\n'); +r.write('throw undefined\n'); r.write('.exit\n'); diff --git a/test/parallel/test-repl.js b/test/parallel/test-repl.js index 942b1d341c4c0a..dc8400fab71497 100644 --- a/test/parallel/test-repl.js +++ b/test/parallel/test-repl.js @@ -165,13 +165,23 @@ const errorTests = [ send: '.break', expect: '' }, - // Template expressions can cross lines + // Template expressions { send: '`io.js ${"1.0"', + expect: [ + kSource, + kArrow, + '', + /^SyntaxError: /, + '' + ] + }, + { + send: '`io.js ${', expect: '... ' }, { - send: '+ ".2"}`', + send: '"1.0" + ".2"}`', expect: '\'io.js 1.0.2\'' }, // Dot prefix in multiline commands aren't treated as commands @@ -636,14 +646,68 @@ const errorTests = [ }, // Do not parse `...[]` as a REPL keyword { - send: '...[]\n', - expect: '... ... ' + send: '...[]', + expect: [ + kSource, + kArrow, + '', + /^SyntaxError: /, + '' + ] }, // bring back the repl to prompt { send: '.break', expect: '' - } + }, + { + send: 'console.log("Missing comma in arg list" process.version)', + expect: [ + kSource, + kArrow, + '', + /^SyntaxError: /, + '' + ] + }, + { + send: 'x = {\nfield\n{', + expect: [ + '... ... {', + kArrow, + '', + /^SyntaxError: /, + '' + ] + }, + { + send: '(2 + 3))', + expect: [ + kSource, + kArrow, + '', + /^SyntaxError: /, + '' + ] + }, + { + send: 'if (typeof process === "object"); {', + expect: '... ' + }, + { + send: 'console.log("process is defined");', + expect: '... ' + }, + { + send: '} else {', + expect: [ + kSource, + kArrow, + '', + /^SyntaxError: /, + '' + ] + }, ]; const tcpTests = [ diff --git a/test/parallel/test-stdio-closed.js b/test/parallel/test-stdio-closed.js index 7a6625f494d3a6..c21bbc2eac12b7 100644 --- a/test/parallel/test-stdio-closed.js +++ b/test/parallel/test-stdio-closed.js @@ -22,7 +22,7 @@ if (common.isWindows) { } if (process.argv[2] === 'child') { - [0, 1, 2].forEach((i) => assert.doesNotThrow(() => fs.fstatSync(i))); + [0, 1, 2].forEach((i) => fs.fstatSync(i)); return; } diff --git a/test/parallel/test-stream-duplex.js b/test/parallel/test-stream-duplex.js index 1cc54db05206a3..2b2f9a9a0e6265 100644 --- a/test/parallel/test-stream-duplex.js +++ b/test/parallel/test-stream-duplex.js @@ -29,6 +29,8 @@ const stream = new Duplex({ objectMode: true }); assert(Duplex() instanceof Duplex); assert(stream._readableState.objectMode); assert(stream._writableState.objectMode); +assert(stream.allowHalfOpen); +assert.strictEqual(stream.listenerCount('end'), 0); let written; let read; diff --git a/test/parallel/test-stream-writable-null.js b/test/parallel/test-stream-writable-null.js index f1b91dee211005..63e122a3b496e1 100644 --- a/test/parallel/test-stream-writable-null.js +++ b/test/parallel/test-stream-writable-null.js @@ -27,14 +27,10 @@ common.expectsError( } ); -assert.doesNotThrow(() => { - const m = new MyWritable({ objectMode: true }).on('error', (e) => { - assert.ok(e); - }); - m.write(null, (err) => { - assert.ok(err); - }); -}); +{ // Should not throw. + const m = new MyWritable({ objectMode: true }).on('error', assert); + m.write(null, assert); +} common.expectsError( () => { @@ -47,24 +43,19 @@ common.expectsError( } ); -assert.doesNotThrow(() => { - const m = new MyWritable().on('error', (e) => { - assert.ok(e); - }); - m.write(false, (err) => { - assert.ok(err); - }); -}); +{ // Should not throw. + const m = new MyWritable().on('error', assert); + m.write(false, assert); +} -assert.doesNotThrow(() => { +{ // Should not throw. const m = new MyWritable({ objectMode: true }); - m.write(false, (err) => assert.ifError(err)); -}); -assert.doesNotThrow(() => { + m.write(false, assert.ifError); +} + +{ // Should not throw. const m = new MyWritable({ objectMode: true }).on('error', (e) => { assert.ifError(e || new Error('should not get here')); }); - m.write(false, (err) => { - assert.ifError(err); - }); -}); + m.write(false, assert.ifError); +} diff --git a/test/parallel/test-timers-clear-null-does-not-throw-error.js b/test/parallel/test-timers-clear-null-does-not-throw-error.js index a15072a4c63f46..89d433c191abe1 100644 --- a/test/parallel/test-timers-clear-null-does-not-throw-error.js +++ b/test/parallel/test-timers-clear-null-does-not-throw-error.js @@ -1,18 +1,11 @@ 'use strict'; require('../common'); -const assert = require('assert'); // This test makes sure clearing timers with // 'null' or no input does not throw error - -assert.doesNotThrow(() => clearInterval(null)); - -assert.doesNotThrow(() => clearInterval()); - -assert.doesNotThrow(() => clearTimeout(null)); - -assert.doesNotThrow(() => clearTimeout()); - -assert.doesNotThrow(() => clearImmediate(null)); - -assert.doesNotThrow(() => clearImmediate()); +clearInterval(null); +clearInterval(); +clearTimeout(null); +clearTimeout(); +clearImmediate(null); +clearImmediate(); 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-timers-unref.js b/test/parallel/test-timers-unref.js index 9e5a4228ba92ed..8c4891f1ed6459 100644 --- a/test/parallel/test-timers-unref.js +++ b/test/parallel/test-timers-unref.js @@ -22,7 +22,6 @@ 'use strict'; const common = require('../common'); -const assert = require('assert'); let unref_interval = false; let unref_timer = false; @@ -31,13 +30,9 @@ let checks = 0; const LONG_TIME = 10 * 1000; const SHORT_TIME = 100; -assert.doesNotThrow(() => { - setTimeout(() => {}, 10).unref().ref().unref(); -}, 'ref and unref are chainable'); - -assert.doesNotThrow(() => { - setInterval(() => {}, 10).unref().ref().unref(); -}, 'ref and unref are chainable'); +// Should not throw. +setTimeout(() => {}, 10).unref().ref().unref(); +setInterval(() => {}, 10).unref().ref().unref(); setInterval(common.mustNotCall('Interval should not fire'), LONG_TIME).unref(); setTimeout(common.mustNotCall('Timer should not fire'), LONG_TIME).unref(); diff --git a/test/parallel/test-tls-client-abort.js b/test/parallel/test-tls-client-abort.js index be81420d154c08..09f252db308881 100644 --- a/test/parallel/test-tls-client-abort.js +++ b/test/parallel/test-tls-client-abort.js @@ -24,7 +24,6 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); -const assert = require('assert'); const tls = require('tls'); const fixtures = require('../common/fixtures'); @@ -32,8 +31,5 @@ const cert = fixtures.readSync('test_cert.pem'); const key = fixtures.readSync('test_key.pem'); const conn = tls.connect({ cert, key, port: 0 }, common.mustNotCall()); -conn.on('error', function() { -}); -assert.doesNotThrow(function() { - conn.destroy(); -}); +conn.on('error', function() {}); +conn.destroy(); diff --git a/test/parallel/test-tls-client-abort2.js b/test/parallel/test-tls-client-abort2.js index 59b592d2556699..b253e6696c6b5c 100644 --- a/test/parallel/test-tls-client-abort2.js +++ b/test/parallel/test-tls-client-abort2.js @@ -24,12 +24,9 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); -const assert = require('assert'); const tls = require('tls'); const conn = tls.connect(0, common.mustNotCall()); conn.on('error', common.mustCall(function() { - assert.doesNotThrow(function() { - conn.destroy(); - }); + conn.destroy(); })); diff --git a/test/parallel/test-tls-finished.js b/test/parallel/test-tls-finished.js new file mode 100644 index 00000000000000..8b52934b049d95 --- /dev/null +++ b/test/parallel/test-tls-finished.js @@ -0,0 +1,66 @@ +'use strict'; + +const common = require('../common'); +const fixtures = require('../common/fixtures'); + +if (!common.hasCrypto) + common.skip('missing crypto'); + +// This test ensures that tlsSocket.getFinished() and +// tlsSocket.getPeerFinished() return undefined before +// secure connection is established, and return non-empty +// Buffer objects with Finished messages afterwards, also +// verifying alice.getFinished() == bob.getPeerFinished() +// and alice.getPeerFinished() == bob.getFinished(). + +const assert = require('assert'); +const tls = require('tls'); + +const msg = {}; +const pem = (n) => fixtures.readKey(`${n}.pem`); +const server = tls.createServer({ + key: pem('agent1-key'), + cert: pem('agent1-cert') +}, common.mustCall((alice) => { + msg.server = { + alice: alice.getFinished(), + bob: alice.getPeerFinished() + }; + server.close(); +})); + +server.listen(0, common.mustCall(() => { + const bob = tls.connect({ + port: server.address().port, + rejectUnauthorized: false + }, common.mustCall(() => { + msg.client = { + alice: bob.getPeerFinished(), + bob: bob.getFinished() + }; + bob.end(); + })); + + msg.before = { + alice: bob.getPeerFinished(), + bob: bob.getFinished() + }; +})); + +process.on('exit', () => { + assert.strictEqual(undefined, msg.before.alice); + assert.strictEqual(undefined, msg.before.bob); + + assert(Buffer.isBuffer(msg.server.alice)); + assert(Buffer.isBuffer(msg.server.bob)); + assert(Buffer.isBuffer(msg.client.alice)); + assert(Buffer.isBuffer(msg.client.bob)); + + assert(msg.server.alice.length > 0); + assert(msg.server.bob.length > 0); + assert(msg.client.alice.length > 0); + assert(msg.client.bob.length > 0); + + assert(msg.server.alice.equals(msg.client.alice)); + assert(msg.server.bob.equals(msg.client.bob)); +}); diff --git a/test/parallel/test-tls-legacy-deprecated.js b/test/parallel/test-tls-legacy-deprecated.js index 3b1919010e40e6..c2560daf21407c 100644 --- a/test/parallel/test-tls-legacy-deprecated.js +++ b/test/parallel/test-tls-legacy-deprecated.js @@ -4,7 +4,6 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); -const assert = require('assert'); const tls = require('tls'); common.expectWarning( @@ -12,4 +11,4 @@ common.expectWarning( 'tls.createSecurePair() is deprecated. Please use tls.TLSSocket instead.' ); -assert.doesNotThrow(() => tls.createSecurePair()); +tls.createSecurePair(); diff --git a/test/parallel/test-tls-options-boolean-check.js b/test/parallel/test-tls-options-boolean-check.js index b84d9b8b1732c4..53f595e0de50e5 100644 --- a/test/parallel/test-tls-options-boolean-check.js +++ b/test/parallel/test-tls-options-boolean-check.js @@ -6,7 +6,6 @@ const fixtures = require('../common/fixtures'); if (!common.hasCrypto) common.skip('missing crypto'); -const assert = require('assert'); const tls = require('tls'); function toArrayBuffer(buf) { @@ -65,9 +64,7 @@ const invalidCertRE = /^The "cert" argument must be one of type string, Buffer, [[{ pem: keyBuff }], false], [[{ pem: keyBuff }, { pem: keyBuff }], false] ].forEach(([key, cert]) => { - assert.doesNotThrow(() => { - tls.createServer({ key, cert }); - }); + tls.createServer({ key, cert }); }); // Checks to ensure tls.createServer predictably throws an error @@ -118,9 +115,7 @@ const invalidCertRE = /^The "cert" argument must be one of type string, Buffer, [keyBuff, certBuff, caArrDataView], [keyBuff, certBuff, false], ].forEach(([key, cert, ca]) => { - assert.doesNotThrow(() => { - tls.createServer({ key, cert, ca }); - }); + tls.createServer({ key, cert, ca }); }); // Checks to ensure tls.createServer throws an error for CA assignment @@ -168,7 +163,5 @@ const invalidCertRE = /^The "cert" argument must be one of type string, Buffer, ['', '', ''], [0, 0, 0] ].forEach(([key, cert, ca]) => { - assert.doesNotThrow(() => { - tls.createSecureContext({ key, cert, ca }); - }); + tls.createSecureContext({ key, cert, ca }); }); diff --git a/test/parallel/test-tls-pfx-authorizationerror.js b/test/parallel/test-tls-pfx-authorizationerror.js new file mode 100644 index 00000000000000..64b6e1485dc538 --- /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 199d4bdf22778c..00000000000000 --- 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 402a6014d1396c..eaa51ff51baa71 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-tls-wrap-event-emmiter.js b/test/parallel/test-tls-wrap-event-emmiter.js index b6ae9e2d5a7e99..871e6c9ae6834c 100644 --- a/test/parallel/test-tls-wrap-event-emmiter.js +++ b/test/parallel/test-tls-wrap-event-emmiter.js @@ -15,5 +15,5 @@ const TlsSocket = require('tls').TLSSocket; const EventEmitter = require('events').EventEmitter; assert.throws( () => { new TlsSocket(new EventEmitter()); }, - /^TypeError: (.+) is not a function$/ + TypeError ); diff --git a/test/parallel/test-tty-get-color-depth.js b/test/parallel/test-tty-get-color-depth.js new file mode 100644 index 00000000000000..a5a998b6a3ab78 --- /dev/null +++ b/test/parallel/test-tty-get-color-depth.js @@ -0,0 +1,52 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert').strict; +/* eslint-disable no-restricted-properties */ +const { openSync } = require('fs'); +const tty = require('tty'); + +const { WriteStream } = require('tty'); + +// Do our best to grab a tty fd. +function getTTYfd() { + const ttyFd = [0, 1, 2, 4, 5].find(tty.isatty); + if (ttyFd === undefined) { + try { + return openSync('/dev/tty'); + } catch (e) { + // There aren't any tty fd's available to use. + return -1; + } + } + return ttyFd; +} + +const fd = getTTYfd(); + +// Give up if we did not find a tty +if (fd === -1) + common.skip(); + +const writeStream = new WriteStream(fd); + +let depth = writeStream.getColorDepth(); + +assert.equal(typeof depth, 'number'); +assert(depth >= 1 && depth <= 24); + +// If the terminal does not support colors, skip the rest +if (depth === 1) + common.skip(); + +assert.notEqual(writeStream.getColorDepth({ TERM: 'dumb' }), depth); + +// Deactivate colors +const tmp = process.env.NODE_DISABLE_COLORS; +process.env.NODE_DISABLE_COLORS = 1; + +depth = writeStream.getColorDepth(); + +assert.equal(depth, 1); + +process.env.NODE_DISABLE_COLORS = tmp; diff --git a/test/parallel/test-tty-stdin-end.js b/test/parallel/test-tty-stdin-end.js new file mode 100644 index 00000000000000..c78f58446d03e9 --- /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-5927.js b/test/parallel/test-tty-stdin-pipe.js similarity index 94% rename from test/parallel/test-regress-GH-5927.js rename to test/parallel/test-tty-stdin-pipe.js index f32dd61c978eb4..9e941532060384 100644 --- a/test/parallel/test-regress-GH-5927.js +++ b/test/parallel/test-tty-stdin-pipe.js @@ -21,6 +21,10 @@ 'use strict'; require('../common'); + +// This test ensures piping from `stdin` isn't broken. +// https://github.com/nodejs/node/issues/5927 + const assert = require('assert'); const readline = require('readline'); diff --git a/test/parallel/test-util-inspect-proxy.js b/test/parallel/test-util-inspect-proxy.js index 63527986b1cbf1..d7fb28ddc77282 100644 --- a/test/parallel/test-util-inspect-proxy.js +++ b/test/parallel/test-util-inspect-proxy.js @@ -13,7 +13,7 @@ const handler = { const proxyObj = new Proxy(target, handler); // Inspecting the proxy should not actually walk it's properties -assert.doesNotThrow(() => util.inspect(proxyObj, opts)); +util.inspect(proxyObj, opts); // getProxyDetails is an internal method, not intended for public use. // This is here to test that the internals are working correctly. diff --git a/test/parallel/test-util-inspect.js b/test/parallel/test-util-inspect.js index a99583d454b3f4..ec9afc677b67bc 100644 --- a/test/parallel/test-util-inspect.js +++ b/test/parallel/test-util-inspect.js @@ -146,7 +146,7 @@ for (const showHidden of [true, false]) { ' y: 1337 }'); } -// Now do the same checks but from a different context +// Now do the same checks but from a different context. for (const showHidden of [true, false]) { const ab = vm.runInNewContext('new ArrayBuffer(4)'); const dv = vm.runInNewContext('new DataView(ab, 1, 2)', { ab }); @@ -211,7 +211,7 @@ for (const showHidden of [true, false]) { ); }); -// Now check that declaring a TypedArray in a different context works the same +// Now check that declaring a TypedArray in a different context works the same. [ Float32Array, Float64Array, Int16Array, @@ -252,7 +252,7 @@ assert.strictEqual( }), { showHidden: true }), '{ visible: 1, [hidden]: 2 }' ); -// Objects without prototype +// Objects without prototype. assert.strictEqual( util.inspect(Object.create(null, { name: { value: 'Tim', enumerable: true }, @@ -269,7 +269,7 @@ assert.strictEqual( '{ name: \'Tim\' }' ); -// Dynamic properties +// Dynamic properties. { assert.strictEqual( util.inspect({ get readonly() {} }), @@ -288,7 +288,7 @@ assert.strictEqual( assert.strictEqual(util.inspect(value), '{ a: [Circular] }'); } -// Array with dynamic properties +// Array with dynamic properties. { const value = [1, 2, 3]; Object.defineProperty( @@ -311,7 +311,7 @@ assert.strictEqual( '[ 1, 2, 3, growingLength: [Getter], \'-1\': -1 ]'); } -// Array with inherited number properties +// Array with inherited number properties. { class CustomArray extends Array {} CustomArray.prototype[5] = 'foo'; @@ -319,7 +319,7 @@ assert.strictEqual( assert.strictEqual(util.inspect(arr), 'CustomArray [ <50 empty items> ]'); } -// Array with extra properties +// Array with extra properties. { const arr = [1, 2, 3, , ]; arr.foo = 'bar'; @@ -351,10 +351,10 @@ assert.strictEqual( assert.strictEqual(util.inspect(arr3), "[ '-1': -1 ]"); } -// Indices out of bounds +// Indices out of bounds. { const arr = []; - arr[2 ** 32] = true; // not a valid array index + arr[2 ** 32] = true; // Not a valid array index. assert.strictEqual(util.inspect(arr), "[ '4294967296': true ]"); arr[0] = true; arr[10] = true; @@ -374,28 +374,28 @@ assert.strictEqual( ].join('\n ')); } -// Function with properties +// Function with properties. { const value = () => {}; value.aprop = 42; assert.strictEqual(util.inspect(value), '{ [Function: value] aprop: 42 }'); } -// Anonymous function with properties +// Anonymous function with properties. { const value = (() => function() {})(); value.aprop = 42; assert.strictEqual(util.inspect(value), '{ [Function] aprop: 42 }'); } -// Regular expressions with properties +// Regular expressions with properties. { const value = /123/ig; value.aprop = 42; assert.strictEqual(util.inspect(value), '{ /123/gi aprop: 42 }'); } -// Dates with properties +// Dates with properties. { const value = new Date('Sun, 14 Feb 2010 11:48:40 GMT'); value.aprop = 42; @@ -403,7 +403,7 @@ assert.strictEqual( '{ 2010-02-14T11:48:40.000Z aprop: 42 }'); } -// test the internal isDate implementation +// Test the internal isDate implementation. { const Date2 = vm.runInNewContext('Date'); const d = new Date2(); @@ -413,13 +413,13 @@ assert.strictEqual( assert.strictEqual(orig, after); } -// test positive/negative zero +// Test positive/negative zero. assert.strictEqual(util.inspect(0), '0'); assert.strictEqual(util.inspect(-0), '-0'); -// edge case from check +// Edge case from check. assert.strictEqual(util.inspect(-5e-324), '-5e-324'); -// test for sparse array +// Test for sparse array. { const a = ['foo', 'bar', 'baz']; assert.strictEqual(util.inspect(a), '[ \'foo\', \'bar\', \'baz\' ]'); @@ -443,7 +443,7 @@ assert.strictEqual(util.inspect(-5e-324), '-5e-324'); ); } -// test for Array constructor in different context +// Test for Array constructor in different context. { const Debug = vm.runInDebugContext('Debug'); const map = new Map(); @@ -458,7 +458,7 @@ assert.strictEqual(util.inspect(-5e-324), '-5e-324'); assert.strictEqual(util.inspect(valsOutput), '[ [ 1, 2 ] ]'); } -// test for other constructors in different context +// Test for other constructors in different context. { let obj = vm.runInNewContext('(function(){return {}})()', {}); assert.strictEqual(util.inspect(obj), '{}'); @@ -470,7 +470,7 @@ assert.strictEqual(util.inspect(-5e-324), '-5e-324'); assert.strictEqual(util.inspect(obj), 'Promise { }'); } -// test for property descriptors +// Test for property descriptors. { const getter = Object.create(null, { a: { @@ -496,7 +496,7 @@ assert.strictEqual(util.inspect(-5e-324), '-5e-324'); ); } -// exceptions should print the error message, not '{}' +// Exceptions should print the error message, not '{}'. { const errors = []; errors.push(new Error()); @@ -517,7 +517,7 @@ assert.strictEqual(util.inspect(-5e-324), '-5e-324'); assert(ex.includes('[message]')); } -// Doesn't capture stack trace +// Doesn't capture stack trace. { function BadCustomError(msg) { Error.call(this); @@ -534,34 +534,29 @@ assert.strictEqual(util.inspect(-5e-324), '-5e-324'); } // GH-1941 -// should not throw: assert.strictEqual(util.inspect(Object.create(Date.prototype)), 'Date {}'); // GH-1944 -assert.doesNotThrow(() => { +{ const d = new Date(); d.toUTCString = null; util.inspect(d); -}); +} -assert.doesNotThrow(() => { +// Should not throw. +{ const d = new Date(); d.toISOString = null; util.inspect(d); -}); +} -assert.doesNotThrow(() => { - const r = /regexp/; - r.toString = null; - util.inspect(r); -}); +// Should not throw. +const r = /regexp/; +r.toString = null; +util.inspect(r); -// bug with user-supplied inspect function returns non-string -assert.doesNotThrow(() => { - util.inspect([{ - inspect: () => 123 - }]); -}); +// Bug with user-supplied inspect function returns non-string. +util.inspect([{ inspect: () => 123 }]); // GH-2225 { @@ -597,7 +592,7 @@ assert.doesNotThrow(() => { ); } -// util.inspect.styles and util.inspect.colors +// Test util.inspect.styles and util.inspect.colors. { function testColorStyle(style, input, implicit) { const colorName = util.inspect.styles[style]; @@ -624,14 +619,10 @@ assert.doesNotThrow(() => { testColorStyle('regexp', /regexp/); } -// an object with "hasOwnProperty" overwritten should not throw -assert.doesNotThrow(() => { - util.inspect({ - hasOwnProperty: null - }); -}); +// An object with "hasOwnProperty" overwritten should not throw. +util.inspect({ hasOwnProperty: null }); -// new API, accepts an "options" object +// New API, accepts an "options" object. { const subject = { foo: 'bar', hello: 31, a: { b: { c: { d: 0 } } } }; Object.defineProperty(subject, 'hidden', { enumerable: false, value: null }); @@ -671,7 +662,7 @@ assert.doesNotThrow(() => { } { - // "customInspect" option can enable/disable calling inspect() on objects + // "customInspect" option can enable/disable calling inspect() on objects. const subject = { inspect: () => 123 }; assert.strictEqual( @@ -691,7 +682,7 @@ assert.doesNotThrow(() => { true ); - // custom inspect() functions should be able to return other Objects + // Custom inspect() functions should be able to return other Objects. subject.inspect = () => ({ foo: 'bar' }); assert.strictEqual(util.inspect(subject), '{ foo: \'bar\' }'); @@ -704,7 +695,7 @@ assert.doesNotThrow(() => { } { - // "customInspect" option can enable/disable calling [util.inspect.custom]() + // "customInspect" option can enable/disable calling [util.inspect.custom](). const subject = { [util.inspect.custom]: () => 123 }; assert.strictEqual( @@ -716,7 +707,7 @@ assert.doesNotThrow(() => { false ); - // a custom [util.inspect.custom]() should be able to return other Objects + // A custom [util.inspect.custom]() should be able to return other Objects. subject[util.inspect.custom] = () => ({ foo: 'bar' }); assert.strictEqual(util.inspect(subject), '{ foo: \'bar\' }'); @@ -729,7 +720,7 @@ assert.doesNotThrow(() => { } { - // [util.inspect.custom] takes precedence over inspect + // [util.inspect.custom] takes precedence over inspect. const subject = { [util.inspect.custom]() { return 123; }, inspect() { return 456; } @@ -764,7 +755,7 @@ assert.doesNotThrow(() => { `{ a: 123,\n [Symbol(${UIC})]: [Function: [${UIC}]] }`); } -// util.inspect with "colors" option should produce as many lines as without it +// util.inspect with "colors" option should produce as many lines as without it. { function testLines(input) { const countLines = (str) => (str.match(/\n/g) || []).length; @@ -788,7 +779,7 @@ assert.doesNotThrow(() => { }); } -// test boxed primitives output the correct values +// Test boxed primitives output the correct values. assert.strictEqual(util.inspect(new String('test')), '[String: \'test\']'); assert.strictEqual( util.inspect(Object(Symbol('test'))), @@ -801,7 +792,7 @@ assert.strictEqual(util.inspect(new Number(-0)), '[Number: -0]'); assert.strictEqual(util.inspect(new Number(-1.1)), '[Number: -1.1]'); assert.strictEqual(util.inspect(new Number(13.37)), '[Number: 13.37]'); -// test boxed primitives with own properties +// Test boxed primitives with own properties. { const str = new String('baz'); str.foo = 'bar'; @@ -816,7 +807,7 @@ assert.strictEqual(util.inspect(new Number(13.37)), '[Number: 13.37]'); assert.strictEqual(util.inspect(num), '{ [Number: 13.37] foo: \'bar\' }'); } -// test es6 Symbol +// Test es6 Symbol. if (typeof Symbol !== 'undefined') { assert.strictEqual(util.inspect(Symbol()), 'Symbol()'); assert.strictEqual(util.inspect(Symbol(123)), 'Symbol(123)'); @@ -852,7 +843,7 @@ if (typeof Symbol !== 'undefined') { '[ 1, 2, 3, [Symbol(symbol)]: 42 ]'); } -// test Set +// Test Set. { assert.strictEqual(util.inspect(new Set()), 'Set {}'); assert.strictEqual(util.inspect(new Set([1, 2, 3])), 'Set { 1, 2, 3 }'); @@ -864,14 +855,14 @@ if (typeof Symbol !== 'undefined') { ); } -// Test circular Set +// Test circular Set. { const set = new Set(); set.add(set); assert.strictEqual(util.inspect(set), 'Set { [Circular] }'); } -// test Map +// Test Map. { assert.strictEqual(util.inspect(new Map()), 'Map {}'); assert.strictEqual(util.inspect(new Map([[1, 'a'], [2, 'b'], [3, 'c']])), @@ -882,7 +873,7 @@ if (typeof Symbol !== 'undefined') { 'Map { \'foo\' => null, [size]: 1, bar: 42 }'); } -// Test circular Map +// Test circular Map. { const map = new Map(); map.set(map, 'map'); @@ -894,14 +885,14 @@ if (typeof Symbol !== 'undefined') { assert.strictEqual(util.inspect(map), "Map { 'map' => [Circular] }"); } -// test Promise +// Test Promise. { const resolved = Promise.resolve(3); assert.strictEqual(util.inspect(resolved), 'Promise { 3 }'); const rejected = Promise.reject(3); assert.strictEqual(util.inspect(rejected), 'Promise { 3 }'); - // squelch UnhandledPromiseRejection + // Squelch UnhandledPromiseRejection. rejected.catch(() => {}); const pending = new Promise(() => {}); @@ -923,33 +914,33 @@ if (typeof Symbol !== 'undefined') { global.Promise = oldPromise; } -// Test Map iterators +// Test Map iterators. { const map = new Map([['foo', 'bar']]); assert.strictEqual(util.inspect(map.keys()), 'MapIterator { \'foo\' }'); assert.strictEqual(util.inspect(map.values()), 'MapIterator { \'bar\' }'); assert.strictEqual(util.inspect(map.entries()), 'MapIterator { [ \'foo\', \'bar\' ] }'); - // make sure the iterator doesn't get consumed + // Make sure the iterator doesn't get consumed. const keys = map.keys(); assert.strictEqual(util.inspect(keys), 'MapIterator { \'foo\' }'); assert.strictEqual(util.inspect(keys), 'MapIterator { \'foo\' }'); } -// Test Set iterators +// Test Set iterators. { const aSet = new Set([1, 3]); assert.strictEqual(util.inspect(aSet.keys()), 'SetIterator { 1, 3 }'); assert.strictEqual(util.inspect(aSet.values()), 'SetIterator { 1, 3 }'); assert.strictEqual(util.inspect(aSet.entries()), 'SetIterator { [ 1, 1 ], [ 3, 3 ] }'); - // make sure the iterator doesn't get consumed + // Make sure the iterator doesn't get consumed. const keys = aSet.keys(); assert.strictEqual(util.inspect(keys), 'SetIterator { 1, 3 }'); assert.strictEqual(util.inspect(keys), 'SetIterator { 1, 3 }'); } -// Test alignment of items in container +// Test alignment of items in container. // Assumes that the first numeric character is the start of an item. { function checkAlignment(container) { @@ -984,7 +975,7 @@ if (typeof Symbol !== 'undefined') { } -// Test display of constructors +// Test display of constructors. { class ObjectSubclass {} class ArraySubclass extends Array {} @@ -1010,7 +1001,7 @@ if (typeof Symbol !== 'undefined') { ); } -// Empty and circular before depth +// Empty and circular before depth. { const arr = [[[[]]]]; assert.strictEqual(util.inspect(arr), '[ [ [ [] ] ] ]'); @@ -1106,14 +1097,14 @@ if (typeof Symbol !== 'undefined') { assert.strictEqual(twoLines, '{ foo: \'abc\',\n bar: \'xyz\' }'); } -// util.inspect.defaultOptions tests +// util.inspect.defaultOptions tests. { const arr = new Array(101).fill(); const obj = { a: { a: { a: { a: 1 } } } }; const oldOptions = Object.assign({}, util.inspect.defaultOptions); - // Set single option through property assignment + // Set single option through property assignment. util.inspect.defaultOptions.maxArrayLength = null; assert(!/1 more item/.test(util.inspect(arr))); util.inspect.defaultOptions.maxArrayLength = oldOptions.maxArrayLength; @@ -1127,7 +1118,7 @@ if (typeof Symbol !== 'undefined') { JSON.stringify(oldOptions) ); - // Set multiple options through object assignment + // Set multiple options through object assignment. util.inspect.defaultOptions = { maxArrayLength: null, depth: null }; assert(!/1 more item/.test(util.inspect(arr))); assert(!/Object/.test(util.inspect(obj))); @@ -1158,5 +1149,148 @@ if (typeof Symbol !== 'undefined') { ); } -assert.doesNotThrow(() => util.inspect(process)); +util.inspect(process); // Should not throw. /* eslint-enable accessor-pairs */ + +// Setting custom inspect property to a non-function should do nothing. +{ + const obj = { inspect: 'fhqwhgads' }; + assert.strictEqual(util.inspect(obj), "{ inspect: 'fhqwhgads' }"); +} + +{ + const o = { + a: [1, 2, [[ + 'Lorem ipsum dolor\nsit amet,\tconsectetur adipiscing elit, sed do ' + + 'eiusmod tempor incididunt ut labore et dolore magna aliqua.', + 'test', + 'foo']], 4], + b: new Map([['za', 1], ['zb', 'test']]) + }; + + let out = util.inspect(o, { compact: true, depth: 5, breakLength: 80 }); + let expect = [ + '{ a: ', + ' [ 1,', + ' 2,', + " [ [ 'Lorem ipsum dolor\\nsit amet,\\tconsectetur adipiscing elit, " + + "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',", + " 'test',", + " 'foo' ] ],", + ' 4 ],', + " b: Map { 'za' => 1, 'zb' => 'test' } }", + ].join('\n'); + assert.strictEqual(out, expect); + + out = util.inspect(o, { compact: false, depth: 5, breakLength: 60 }); + expect = [ + '{', + ' a: [', + ' 1,', + ' 2,', + ' [', + ' [', + ' \'Lorem ipsum dolor\\nsit amet,\\tconsectetur \' +', + ' \'adipiscing elit, sed do eiusmod tempor \' +', + ' \'incididunt ut labore et dolore magna \' +', + ' \'aliqua.\',', + ' \'test\',', + ' \'foo\'', + ' ]', + ' ],', + ' 4', + ' ],', + ' b: Map {', + ' \'za\' => 1,', + ' \'zb\' => \'test\'', + ' }', + '}' + ].join('\n'); + assert.strictEqual(out, expect); + + out = util.inspect(o.a[2][0][0], { compact: false, breakLength: 30 }); + expect = [ + '\'Lorem ipsum dolor\\nsit \' +', + ' \'amet,\\tconsectetur \' +', + ' \'adipiscing elit, sed do \' +', + ' \'eiusmod tempor incididunt \' +', + ' \'ut labore et dolore magna \' +', + ' \'aliqua.\'' + ].join('\n'); + assert.strictEqual(out, expect); + + out = util.inspect( + '12345678901234567890123456789012345678901234567890', + { compact: false, breakLength: 3 }); + expect = '\'12345678901234567890123456789012345678901234567890\''; + assert.strictEqual(out, expect); + + out = util.inspect( + '12 45 78 01 34 67 90 23 56 89 123456789012345678901234567890', + { compact: false, breakLength: 3 }); + expect = [ + '\'12 45 78 01 34 \' +', + ' \'67 90 23 56 89 \' +', + ' \'123456789012345678901234567890\'' + ].join('\n'); + assert.strictEqual(out, expect); + + out = util.inspect( + '12 45 78 01 34 67 90 23 56 89 1234567890123 0', + { compact: false, breakLength: 3 }); + expect = [ + '\'12 45 78 01 34 \' +', + ' \'67 90 23 56 89 \' +', + ' \'1234567890123 0\'' + ].join('\n'); + assert.strictEqual(out, expect); + + out = util.inspect( + '12 45 78 01 34 67 90 23 56 89 12345678901234567 0', + { compact: false, breakLength: 3 }); + expect = [ + '\'12 45 78 01 34 \' +', + ' \'67 90 23 56 89 \' +', + ' \'12345678901234567 \' +', + ' \'0\'' + ].join('\n'); + assert.strictEqual(out, expect); + + o.a = () => {}; + o.b = new Number(3); + out = util.inspect(o, { compact: false, breakLength: 3 }); + expect = [ + '{', + ' a: [Function],', + ' b: [Number: 3]', + '}' + ].join('\n'); + assert.strictEqual(out, expect); + + out = util.inspect(o, { compact: false, breakLength: 3, showHidden: true }); + expect = [ + '{', + ' a: [Function] {', + ' [length]: 0,', + " [name]: ''", + ' },', + ' b: [Number: 3]', + '}' + ].join('\n'); + assert.strictEqual(out, expect); + + o[util.inspect.custom] = () => 42; + out = util.inspect(o, { compact: false, breakLength: 3 }); + expect = '42'; + assert.strictEqual(out, expect); + + o[util.inspect.custom] = () => '12 45 78 01 34 67 90 23'; + out = util.inspect(o, { compact: false, breakLength: 3 }); + expect = '12 45 78 01 34 67 90 23'; + assert.strictEqual(out, expect); + + o[util.inspect.custom] = () => ({ a: '12 45 78 01 34 67 90 23' }); + out = util.inspect(o, { compact: false, breakLength: 3 }); + expect = '{\n a: \'12 45 78 01 34 \' +\n \'67 90 23\'\n}'; + assert.strictEqual(out, expect); +} diff --git a/test/parallel/test-util.js b/test/parallel/test-util.js index 3b2729c107b4b1..a4aec080a9a0ad 100644 --- a/test/parallel/test-util.js +++ b/test/parallel/test-util.js @@ -43,9 +43,10 @@ assert.strictEqual(false, util.isArray(Object.create(Array.prototype))); // isRegExp assert.strictEqual(true, util.isRegExp(/regexp/)); -assert.strictEqual(true, util.isRegExp(RegExp())); +assert.strictEqual(true, util.isRegExp(RegExp(), 'foo')); assert.strictEqual(true, util.isRegExp(new RegExp())); assert.strictEqual(true, util.isRegExp(context('RegExp')())); +assert.strictEqual(false, util.isRegExp()); assert.strictEqual(false, util.isRegExp({})); assert.strictEqual(false, util.isRegExp([])); assert.strictEqual(false, util.isRegExp(new Date())); @@ -53,7 +54,7 @@ assert.strictEqual(false, util.isRegExp(Object.create(RegExp.prototype))); // isDate assert.strictEqual(true, util.isDate(new Date())); -assert.strictEqual(true, util.isDate(new Date(0))); +assert.strictEqual(true, util.isDate(new Date(0), 'foo')); assert.strictEqual(true, util.isDate(new (context('Date'))())); assert.strictEqual(false, util.isDate(Date())); assert.strictEqual(false, util.isDate({})); diff --git a/test/parallel/test-uv-errno.js b/test/parallel/test-uv-errno.js index 28f43db94a247d..c3ac40e3c94e0a 100644 --- a/test/parallel/test-uv-errno.js +++ b/test/parallel/test-uv-errno.js @@ -14,14 +14,12 @@ keys.forEach((key) => { if (!key.startsWith('UV_')) return; - assert.doesNotThrow(() => { - const err = _errnoException(uv[key], 'test'); - const name = uv.errname(uv[key]); - assert.strictEqual(getSystemErrorName(uv[key]), name); - assert.strictEqual(err.code, name); - assert.strictEqual(err.code, err.errno); - assert.strictEqual(err.message, `test ${name}`); - }); + const err = _errnoException(uv[key], 'test'); + const name = uv.errname(uv[key]); + assert.strictEqual(getSystemErrorName(uv[key]), name); + assert.strictEqual(err.code, name); + assert.strictEqual(err.code, err.errno); + assert.strictEqual(err.message, `test ${name}`); }); [0, 1, 'test', {}, [], Infinity, -Infinity, NaN].forEach((key) => { diff --git a/test/parallel/test-regress-GH-6235.js b/test/parallel/test-v8-global-setter.js similarity index 82% rename from test/parallel/test-regress-GH-6235.js rename to test/parallel/test-v8-global-setter.js index e8fcda43cc3f3e..5ee765d6e16bc4 100644 --- a/test/parallel/test-regress-GH-6235.js +++ b/test/parallel/test-v8-global-setter.js @@ -21,8 +21,8 @@ 'use strict'; require('../common'); -const assert = require('assert'); -assert.doesNotThrow(function() { - require('vm').runInNewContext('"use strict"; var v = 1; v = 2'); -}); +// This test ensures v8 correctly sets a property on the global object if it +// has a setter interceptor in strict mode. +// https://github.com/nodejs/node-v0.x-archive/issues/6235 +require('vm').runInNewContext('"use strict"; var v = 1; v = 2'); diff --git a/test/parallel/test-vm-access-process-env.js b/test/parallel/test-vm-access-process-env.js index a2f3cb5741de45..c6b18ec9026cd0 100644 --- a/test/parallel/test-vm-access-process-env.js +++ b/test/parallel/test-vm-access-process-env.js @@ -28,8 +28,6 @@ require('../common'); const assert = require('assert'); const vm = require('vm'); -assert.doesNotThrow(function() { - const context = vm.createContext({ process }); - const result = vm.runInContext('process.env["PATH"]', context); - assert.notStrictEqual(undefined, result); -}); +const context = vm.createContext({ process }); +const result = vm.runInContext('process.env["PATH"]', context); +assert.notStrictEqual(undefined, result); diff --git a/test/parallel/test-vm-create-context-arg.js b/test/parallel/test-vm-create-context-arg.js index 8675add90cfcc6..2bcdc8573fe311 100644 --- a/test/parallel/test-vm-create-context-arg.js +++ b/test/parallel/test-vm-create-context-arg.js @@ -28,13 +28,10 @@ assert.throws(function() { vm.createContext('string is not supported'); }, /^TypeError: sandbox must be an object$/); -assert.doesNotThrow(function() { - vm.createContext({ a: 1 }); - vm.createContext([0, 1, 2, 3]); -}); +// Should not throw. +vm.createContext({ a: 1 }); +vm.createContext([0, 1, 2, 3]); -assert.doesNotThrow(function() { - const sandbox = {}; - vm.createContext(sandbox); - vm.createContext(sandbox); -}); +const sandbox = {}; +vm.createContext(sandbox); +vm.createContext(sandbox); diff --git a/test/parallel/test-vm-cross-context.js b/test/parallel/test-vm-cross-context.js index 5d45387e5d76e5..b7cf1309d3689f 100644 --- a/test/parallel/test-vm-cross-context.js +++ b/test/parallel/test-vm-cross-context.js @@ -21,11 +21,9 @@ 'use strict'; require('../common'); -const assert = require('assert'); const vm = require('vm'); const ctx = vm.createContext(global); -assert.doesNotThrow(function() { - vm.runInContext('!function() { var x = console.log; }()', ctx); -}); +// Should not throw. +vm.runInContext('!function() { var x = console.log; }()', ctx); diff --git a/test/parallel/test-vm-module-link.js b/test/parallel/test-vm-module-link.js index 843c1fdc517787..d9ee8e7767f43a 100644 --- a/test/parallel/test-vm-module-link.js +++ b/test/parallel/test-vm-module-link.js @@ -88,7 +88,7 @@ async function circular() { async function circular2() { const sourceMap = { - root: ` + 'root': ` import * as a from './a.mjs'; import * as b from './b.mjs'; if (!('fromA' in a)) diff --git a/test/parallel/test-vm-proxy-failure-CP.js b/test/parallel/test-vm-proxy-failure-CP.js index 343948ac4c6377..93027576d85e80 100644 --- a/test/parallel/test-vm-proxy-failure-CP.js +++ b/test/parallel/test-vm-proxy-failure-CP.js @@ -1,6 +1,5 @@ 'use strict'; require('../common'); -const assert = require('assert'); const vm = require('vm'); // Check that we do not accidentally query attributes. @@ -13,4 +12,4 @@ const handler = { const sandbox = new Proxy({ foo: 'bar' }, handler); const context = vm.createContext(sandbox); -assert.doesNotThrow(() => vm.runInContext('', context)); +vm.runInContext('', context); diff --git a/test/parallel/test-whatwg-encoding-textdecoder.js b/test/parallel/test-whatwg-encoding-textdecoder.js index 5f9499930a07a0..e87364de1e91f7 100644 --- a/test/parallel/test-whatwg-encoding-textdecoder.js +++ b/test/parallel/test-whatwg-encoding-textdecoder.js @@ -63,8 +63,8 @@ if (common.hasIntl) { ['unicode-1-1-utf-8', 'utf8', 'utf-8'].forEach((i) => { const dec = new TextDecoder(i, { fatal: true }); - assert.doesNotThrow(() => dec.decode(buf.slice(0, 8), { stream: true })); - assert.doesNotThrow(() => dec.decode(buf.slice(8))); + dec.decode(buf.slice(0, 8), { stream: true }); + dec.decode(buf.slice(8)); }); } else { common.expectsError( @@ -107,11 +107,11 @@ if (common.hasIntl) { message: 'Value of "this" must be of type TextDecoder' }; - assert.doesNotThrow(() => inspectFn.call(instance, Infinity, {})); - assert.doesNotThrow(() => decodeFn.call(instance)); - assert.doesNotThrow(() => encodingGetter.call(instance)); - assert.doesNotThrow(() => fatalGetter.call(instance)); - assert.doesNotThrow(() => ignoreBOMGetter.call(instance)); + inspectFn.call(instance, Infinity, {}); + decodeFn.call(instance); + encodingGetter.call(instance); + fatalGetter.call(instance); + ignoreBOMGetter.call(instance); const invalidThisArgs = [{}, [], true, 1, '', new TextEncoder()]; invalidThisArgs.forEach((i) => { diff --git a/test/parallel/test-whatwg-encoding-textencoder.js b/test/parallel/test-whatwg-encoding-textencoder.js index 4096a02432e900..5514b714bd9b6e 100644 --- a/test/parallel/test-whatwg-encoding-textencoder.js +++ b/test/parallel/test-whatwg-encoding-textencoder.js @@ -48,9 +48,9 @@ assert(TextEncoder); message: 'Value of "this" must be of type TextEncoder' }; - assert.doesNotThrow(() => inspectFn.call(instance, Infinity, {})); - assert.doesNotThrow(() => encodeFn.call(instance)); - assert.doesNotThrow(() => encodingGetter.call(instance)); + inspectFn.call(instance, Infinity, {}); + encodeFn.call(instance); + encodingGetter.call(instance); const invalidThisArgs = [{}, [], true, 1, '', new TextDecoder()]; invalidThisArgs.forEach((i) => { diff --git a/test/parallel/test-zlib-close-after-error.js b/test/parallel/test-zlib-close-after-error.js index 8e21d159337c51..63d418be09946d 100644 --- a/test/parallel/test-zlib-close-after-error.js +++ b/test/parallel/test-zlib-close-after-error.js @@ -9,7 +9,7 @@ const decompress = zlib.createGunzip(15); decompress.on('error', common.mustCall((err) => { assert.strictEqual(decompress._closed, true); - assert.doesNotThrow(() => decompress.close()); + decompress.close(); })); assert.strictEqual(decompress._closed, false); diff --git a/test/parallel/test-zlib-deflate-constructors.js b/test/parallel/test-zlib-deflate-constructors.js index 090fbb8d07777e..97ece1e8afe387 100644 --- a/test/parallel/test-zlib-deflate-constructors.js +++ b/test/parallel/test-zlib-deflate-constructors.js @@ -93,25 +93,11 @@ common.expectsError( ); // Does not throw if opts.strategy is valid -assert.doesNotThrow( - () => { new zlib.Deflate({ strategy: zlib.constants.Z_FILTERED }); } -); - -assert.doesNotThrow( - () => { new zlib.Deflate({ strategy: zlib.constants.Z_HUFFMAN_ONLY }); } -); - -assert.doesNotThrow( - () => { new zlib.Deflate({ strategy: zlib.constants.Z_RLE }); } -); - -assert.doesNotThrow( - () => { new zlib.Deflate({ strategy: zlib.constants.Z_FIXED }); } -); - -assert.doesNotThrow( - () => { new zlib.Deflate({ strategy: zlib.constants.Z_DEFAULT_STRATEGY }); } -); +new zlib.Deflate({ strategy: zlib.constants.Z_FILTERED }); +new zlib.Deflate({ strategy: zlib.constants.Z_HUFFMAN_ONLY }); +new zlib.Deflate({ strategy: zlib.constants.Z_RLE }); +new zlib.Deflate({ strategy: zlib.constants.Z_FIXED }); +new zlib.Deflate({ strategy: zlib.constants.Z_DEFAULT_STRATEGY }); // Throws if opt.strategy is the wrong type. common.expectsError( diff --git a/test/parallel/test-zlib-flush-flags.js b/test/parallel/test-zlib-flush-flags.js index 25cfad70e3e3d5..fa9293cfc43175 100644 --- a/test/parallel/test-zlib-flush-flags.js +++ b/test/parallel/test-zlib-flush-flags.js @@ -1,11 +1,8 @@ 'use strict'; const common = require('../common'); -const assert = require('assert'); const zlib = require('zlib'); -assert.doesNotThrow(() => { - zlib.createGzip({ flush: zlib.constants.Z_SYNC_FLUSH }); -}); +zlib.createGzip({ flush: zlib.constants.Z_SYNC_FLUSH }); common.expectsError( () => zlib.createGzip({ flush: 'foobar' }), @@ -23,9 +20,7 @@ common.expectsError( } ); -assert.doesNotThrow(() => { - zlib.createGzip({ finishFlush: zlib.constants.Z_SYNC_FLUSH }); -}); +zlib.createGzip({ finishFlush: zlib.constants.Z_SYNC_FLUSH }); common.expectsError( () => zlib.createGzip({ finishFlush: 'foobar' }), diff --git a/test/parallel/test-zlib-invalid-input.js b/test/parallel/test-zlib-invalid-input.js index 758e489ca078a9..1b081d919e9068 100644 --- a/test/parallel/test-zlib-invalid-input.js +++ b/test/parallel/test-zlib-invalid-input.js @@ -43,11 +43,9 @@ const unzips = [ nonStringInputs.forEach(common.mustCall((input) => { // zlib.gunzip should not throw an error when called with bad input. - assert.doesNotThrow(function() { - zlib.gunzip(input, function(err, buffer) { - // zlib.gunzip should pass the error to the callback. - assert.ok(err); - }); + zlib.gunzip(input, function(err, buffer) { + // zlib.gunzip should pass the error to the callback. + assert.ok(err); }); }, nonStringInputs.length)); 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 a8966da10ba1f7..e8e47865f79604 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/parallel/test-zlib-truncated.js b/test/parallel/test-zlib-truncated.js index 678bfedd41c154..e04ef7e3d8367a 100644 --- a/test/parallel/test-zlib-truncated.js +++ b/test/parallel/test-zlib-truncated.js @@ -29,10 +29,8 @@ const errMessage = /unexpected end of file/; const toUTF8 = (buffer) => buffer.toString('utf-8'); // sync sanity - assert.doesNotThrow(function() { - const decompressed = zlib[methods.decompSync](compressed); - assert.strictEqual(toUTF8(decompressed), inputString); - }); + const decompressed = zlib[methods.decompSync](compressed); + assert.strictEqual(toUTF8(decompressed), inputString); // async sanity zlib[methods.decomp](compressed, function(err, result) { @@ -53,10 +51,8 @@ const errMessage = /unexpected end of file/; const syncFlushOpt = { finishFlush: zlib.constants.Z_SYNC_FLUSH }; // sync truncated input test, finishFlush = Z_SYNC_FLUSH - assert.doesNotThrow(function() { - const result = toUTF8(zlib[methods.decompSync](truncated, syncFlushOpt)); - assert.strictEqual(result, inputString.substr(0, result.length)); - }); + const result = toUTF8(zlib[methods.decompSync](truncated, syncFlushOpt)); + assert.strictEqual(result, inputString.substr(0, result.length)); // async truncated input test, finishFlush = Z_SYNC_FLUSH zlib[methods.decomp](truncated, syncFlushOpt, function(err, decompressed) { diff --git a/test/parallel/test-zlib.js b/test/parallel/test-zlib.js index a36e8166ab726a..1b6855a0b92062 100644 --- a/test/parallel/test-zlib.js +++ b/test/parallel/test-zlib.js @@ -152,9 +152,7 @@ class SlowStream extends stream.Stream { } // windowBits: 8 shouldn't throw -assert.doesNotThrow(() => { - zlib.createDeflateRaw({ windowBits: 8 }); -}, 'windowsBits set to 8 should follow legacy zlib behavior'); +zlib.createDeflateRaw({ windowBits: 8 }); { const node = fs.createReadStream(fixtures.path('person.jpg')); diff --git a/test/pummel/test-fs-largefile.js b/test/pummel/test-fs-largefile.js index 786e325ce3333d..2e9dda0495bd6e 100644 --- a/test/pummel/test-fs-largefile.js +++ b/test/pummel/test-fs-largefile.js @@ -44,9 +44,8 @@ assert.strictEqual(readBuf.toString(), message); fs.readSync(fd, readBuf, 0, 1, 0); assert.strictEqual(readBuf[0], 0); -assert.doesNotThrow( - () => { fs.writeSync(fd, writeBuf, 0, writeBuf.length, 42.000001); } -); +// Verify that floating point positions do not throw. +fs.writeSync(fd, writeBuf, 0, writeBuf.length, 42.000001); fs.close(fd); // Normally, we don't clean up tmp files at the end of a test, but we'll make an diff --git a/test/pummel/test-fs-watch-file.js b/test/pummel/test-fs-watch-file.js index c893c9dfa6e268..e9d208778faf3f 100644 --- a/test/pummel/test-fs-watch-file.js +++ b/test/pummel/test-fs-watch-file.js @@ -68,14 +68,11 @@ assert.throws( } ); -assert.doesNotThrow( - function() { - fs.watchFile(filepathOne, function() { - fs.unwatchFile(filepathOne); - ++watchSeenOne; - }); - } -); +// Does not throw. +fs.watchFile(filepathOne, function() { + fs.unwatchFile(filepathOne); + ++watchSeenOne; +}); setTimeout(function() { fs.writeFileSync(filepathOne, 'world'); @@ -95,36 +92,32 @@ assert.throws( } ); -assert.doesNotThrow( - function() { - function a() { - fs.unwatchFile(filepathTwo, a); - ++watchSeenTwo; - } - function b() { - fs.unwatchFile(filepathTwo, b); - ++watchSeenTwo; - } - fs.watchFile(filepathTwo, a); - fs.watchFile(filepathTwo, b); +{ // Does not throw. + function a() { + fs.unwatchFile(filepathTwo, a); + ++watchSeenTwo; } -); + function b() { + fs.unwatchFile(filepathTwo, b); + ++watchSeenTwo; + } + fs.watchFile(filepathTwo, a); + fs.watchFile(filepathTwo, b); +} setTimeout(function() { fs.writeFileSync(filepathTwoAbs, 'pardner'); }, 1000); -assert.doesNotThrow( - function() { - function b() { - fs.unwatchFile(filenameThree, b); - ++watchSeenThree; - } - fs.watchFile(filenameThree, common.mustNotCall()); - fs.watchFile(filenameThree, b); - fs.unwatchFile(filenameThree, common.mustNotCall()); +{ // Does not throw. + function b() { + fs.unwatchFile(filenameThree, b); + ++watchSeenThree; } -); + fs.watchFile(filenameThree, common.mustNotCall()); + fs.watchFile(filenameThree, b); + fs.unwatchFile(filenameThree, common.mustNotCall()); +} setTimeout(function() { fs.writeFileSync(filenameThree, 'pardner'); @@ -138,13 +131,11 @@ setTimeout(function() { fs.writeFileSync(filenameFour, 'hey'); }, 500); -assert.doesNotThrow( - function() { - function a() { - ++watchSeenFour; - assert.strictEqual(1, watchSeenFour); - fs.unwatchFile(`.${path.sep}${filenameFour}`, a); - } - fs.watchFile(filenameFour, a); +{ // Does not throw. + function a() { + ++watchSeenFour; + assert.strictEqual(1, watchSeenFour); + fs.unwatchFile(`.${path.sep}${filenameFour}`, a); } -); + fs.watchFile(filenameFour, a); +} diff --git a/test/sequential/sequential.status b/test/sequential/sequential.status index b95db2a111ea67..cf4763b00129cc 100644 --- a/test/sequential/sequential.status +++ b/test/sequential/sequential.status @@ -11,8 +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 -test-http2-settings-flood : PASS, FLAKY [$system==linux] diff --git a/test/sequential/test-child-process-execsync.js b/test/sequential/test-child-process-execsync.js index 133217dcdf7c3f..fff5b8e9f0a98b 100644 --- a/test/sequential/test-child-process-execsync.js +++ b/test/sequential/test-child-process-execsync.js @@ -144,6 +144,4 @@ assert.strictEqual(ret, `${msg}\n`); } // Verify the shell option works properly -assert.doesNotThrow(() => { - execFileSync(process.execPath, [], execOpts); -}); +execFileSync(process.execPath, [], execOpts); diff --git a/test/sequential/test-regress-GH-1726.js b/test/sequential/test-child-process-exit.js similarity index 98% rename from test/sequential/test-regress-GH-1726.js rename to test/sequential/test-child-process-exit.js index 1291dec261ccf6..303f015cf0aebd 100644 --- a/test/sequential/test-regress-GH-1726.js +++ b/test/sequential/test-child-process-exit.js @@ -20,12 +20,13 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. 'use strict'; +require('../common'); + // Open a chain of five Node processes each a child of the next. The final -// process exits immediately. Each process in the chain is instructed to -// exit when its child exits. +// process exits immediately. Each process in the chain is instructed to exit +// when its child exits. // https://github.com/joyent/node/issues/1726 -require('../common'); const assert = require('assert'); const ch = require('child_process'); diff --git a/test/parallel/test-cluster-send-handle-large-payload.js b/test/sequential/test-cluster-send-handle-large-payload.js similarity index 100% rename from test/parallel/test-cluster-send-handle-large-payload.js rename to test/sequential/test-cluster-send-handle-large-payload.js diff --git a/test/sequential/test-regress-GH-4015.js b/test/sequential/test-fs-stat-sync-overflow.js similarity index 76% rename from test/sequential/test-regress-GH-4015.js rename to test/sequential/test-fs-stat-sync-overflow.js index cac20c7948ae2f..9c9109989a19c3 100644 --- a/test/sequential/test-regress-GH-4015.js +++ b/test/sequential/test-fs-stat-sync-overflow.js @@ -22,11 +22,19 @@ 'use strict'; require('../common'); const { fixturesDir } = require('../common/fixtures'); + +// Check that the calls to Integer::New() and Date::New() succeed and bail out +// if they don't. +// V8 returns an empty handle on stack overflow. Trying to set the empty handle +// as a property on an object results in a NULL pointer dereference in release +// builds and an assert in debug builds. +// https://github.com/nodejs/node-v0.x-archive/issues/4015 + const assert = require('assert'); const { exec } = require('child_process'); const cmd = - `"${process.execPath}" "${fixturesDir}/test-regress-GH-4015.js"`; + `"${process.execPath}" "${fixturesDir}/test-fs-stat-sync-overflow.js"`; exec(cmd, function(err, stdout, stderr) { assert(/RangeError: Maximum call stack size exceeded/.test(stderr)); diff --git a/test/sequential/test-regress-GH-4027.js b/test/sequential/test-fs-watch-file-enoent-after-deletion.js similarity index 81% rename from test/sequential/test-regress-GH-4027.js rename to test/sequential/test-fs-watch-file-enoent-after-deletion.js index 8936537323581e..f5b9012acabe58 100644 --- a/test/sequential/test-regress-GH-4027.js +++ b/test/sequential/test-fs-watch-file-enoent-after-deletion.js @@ -21,6 +21,17 @@ 'use strict'; const common = require('../common'); + +// Make sure the deletion event gets reported in the following scenario: +// 1. Watch a file. +// 2. The initial stat() goes okay. +// 3. Something deletes the watched file. +// 4. The second stat() fails with ENOENT. + +// The second stat() translates into the first 'change' event but a logic error +// stopped it from getting emitted. +// https://github.com/nodejs/node-v0.x-archive/issues/4027 + const assert = require('assert'); const path = require('path'); const fs = require('fs'); diff --git a/test/sequential/test-fs-watch.js b/test/sequential/test-fs-watch.js index 31708ee6144c7d..b672e9c75395dd 100644 --- a/test/sequential/test-fs-watch.js +++ b/test/sequential/test-fs-watch.js @@ -42,19 +42,15 @@ tmpdir.refresh(); fs.writeFileSync(filepath, 'hello'); - assert.doesNotThrow( - function() { - const watcher = fs.watch(filepath); - watcher.on('change', common.mustCall(function(event, filename) { - assert.strictEqual(event, 'change'); - - if (expectFilePath) { - assert.strictEqual(filename, 'watch.txt'); - } - watcher.close(); - })); + const watcher = fs.watch(filepath); + watcher.on('change', common.mustCall(function(event, filename) { + assert.strictEqual(event, 'change'); + + if (expectFilePath) { + assert.strictEqual(filename, 'watch.txt'); } - ); + watcher.close(); + })); setImmediate(function() { fs.writeFileSync(filepath, 'world'); @@ -68,19 +64,15 @@ tmpdir.refresh(); fs.writeFileSync(filepathAbs, 'howdy'); - assert.doesNotThrow( - function() { - const watcher = - fs.watch('hasOwnProperty', common.mustCall(function(event, filename) { - assert.strictEqual(event, 'change'); - - if (expectFilePath) { - assert.strictEqual(filename, 'hasOwnProperty'); - } - watcher.close(); - })); - } - ); + const watcher = + fs.watch('hasOwnProperty', common.mustCall(function(event, filename) { + assert.strictEqual(event, 'change'); + + if (expectFilePath) { + assert.strictEqual(filename, 'hasOwnProperty'); + } + watcher.close(); + })); setImmediate(function() { fs.writeFileSync(filepathAbs, 'pardner'); @@ -91,21 +83,17 @@ tmpdir.refresh(); const testsubdir = fs.mkdtempSync(testDir + path.sep); const filepath = path.join(testsubdir, 'newfile.txt'); - assert.doesNotThrow( - function() { - const watcher = - fs.watch(testsubdir, common.mustCall(function(event, filename) { - const renameEv = common.isSunOS || common.isAIX ? 'change' : 'rename'; - assert.strictEqual(event, renameEv); - if (expectFilePath) { - assert.strictEqual(filename, 'newfile.txt'); - } else { - assert.strictEqual(filename, null); - } - watcher.close(); - })); - } - ); + const watcher = + fs.watch(testsubdir, common.mustCall(function(event, filename) { + const renameEv = common.isSunOS || common.isAIX ? 'change' : 'rename'; + assert.strictEqual(event, renameEv); + if (expectFilePath) { + assert.strictEqual(filename, 'newfile.txt'); + } else { + assert.strictEqual(filename, null); + } + watcher.close(); + })); setImmediate(function() { const fd = fs.openSync(filepath, 'w'); diff --git a/test/sequential/test-regress-GH-784.js b/test/sequential/test-http-econnrefused.js similarity index 96% rename from test/sequential/test-regress-GH-784.js rename to test/sequential/test-http-econnrefused.js index 4b285020d45a35..ff4508963b9877 100644 --- a/test/sequential/test-regress-GH-784.js +++ b/test/sequential/test-http-econnrefused.js @@ -20,15 +20,15 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. 'use strict'; -// Regression test for GH-784 -// https://github.com/joyent/node/issues/784 -// +const common = require('../common'); + // The test works by making a total of 8 requests to the server. The first // two are made with the server off - they should come back as ECONNREFUSED. // The next two are made with server on - they should come back successful. // The next two are made with the server off - and so on. Without the fix -// we were experiencing parse errors and instead of ECONNREFUSED. -const common = require('../common'); +// we were experiencing parse errors instead of ECONNREFUSED. +// https://github.com/nodejs/node-v0.x-archive/issues/784 + const http = require('http'); const assert = require('assert'); diff --git a/test/sequential/test-regress-GH-877.js b/test/sequential/test-http-max-sockets.js similarity index 94% rename from test/sequential/test-regress-GH-877.js rename to test/sequential/test-http-max-sockets.js index c717c2dd74f444..24629448f7ac77 100644 --- a/test/sequential/test-regress-GH-877.js +++ b/test/sequential/test-http-max-sockets.js @@ -21,6 +21,10 @@ 'use strict'; const common = require('../common'); + +// Make sure http server doesn't wait for socket pool to establish connections +// https://github.com/nodejs/node-v0.x-archive/issues/877 + const http = require('http'); const assert = require('assert'); diff --git a/test/sequential/test-http2-ping-flood.js b/test/sequential/test-http2-ping-flood.js index 5b47d51be9c5a8..b414aca8a4703a 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); }); }); })); diff --git a/test/sequential/test-http2-settings-flood.js b/test/sequential/test-http2-settings-flood.js index bad4cec9a8d509..15b3696b9c298e 100644 --- a/test/sequential/test-http2-settings-flood.js +++ b/test/sequential/test-http2-settings-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 settings flooding causes the session to be torn down @@ -14,13 +16,16 @@ const kSettings = new http2util.SettingsFrame(); 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(); })); @@ -30,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 @@ -40,8 +43,10 @@ server.listen(0, common.mustCall(() => { // from one system to another, and from one test run to another. client.on('connect', common.mustCall(() => { client.write(http2util.kClientMagic, () => { - for (let n = 0; n < 35000; n++) - client.write(kSettings.data); + interval = setInterval(() => { + for (let n = 0; n < 10000; n++) + client.write(kSettings.data); + }, 1); }); })); diff --git a/test/sequential/test-inspector-module.js b/test/sequential/test-inspector-module.js index af0154f7cec8de..f97d71297971f7 100644 --- a/test/sequential/test-inspector-module.js +++ b/test/sequential/test-inspector-module.js @@ -4,7 +4,6 @@ const common = require('../common'); common.skipIfInspectorDisabled(); -const assert = require('assert'); const { Session } = require('inspector'); const session = new Session(); @@ -18,10 +17,8 @@ common.expectsError( } ); -assert.doesNotThrow(() => session.connect()); - -assert.doesNotThrow( - () => session.post('Runtime.evaluate', { expression: '2 + 2' })); +session.connect(); +session.post('Runtime.evaluate', { expression: '2 + 2' }); [1, {}, [], true, Infinity, undefined].forEach((i) => { common.expectsError( @@ -58,5 +55,6 @@ common.expectsError( } ); -assert.doesNotThrow(() => session.disconnect()); -assert.doesNotThrow(() => session.disconnect()); +session.disconnect(); +// Calling disconnect twice should not throw. +session.disconnect(); diff --git a/test/sequential/test-inspector-stop-profile-after-done.js b/test/sequential/test-inspector-stop-profile-after-done.js index 15764d84860e8c..678f98a556c099 100644 --- a/test/sequential/test-inspector-stop-profile-after-done.js +++ b/test/sequential/test-inspector-stop-profile-after-done.js @@ -25,7 +25,7 @@ async function runTests() { 'Waiting for the debugger to disconnect...'); await session.send({ method: 'Profiler.stop' }); session.disconnect(); - assert.strictEqual(0, (await child.expectShutdown()).exitCode); + assert.strictEqual((await child.expectShutdown()).exitCode, 0); } common.crashOnUnhandledRejection(); diff --git a/test/sequential/test-regress-GH-1697.js b/test/sequential/test-net-response-size.js similarity index 91% rename from test/sequential/test-regress-GH-1697.js rename to test/sequential/test-net-response-size.js index 9d2555705ab023..c5d7e9b600e05d 100644 --- a/test/sequential/test-regress-GH-1697.js +++ b/test/sequential/test-net-response-size.js @@ -21,6 +21,11 @@ 'use strict'; const common = require('../common'); + +// Make sure the net module's server doesn't throw an error when handling +// responses that are either too long or too small (especially on Windows) +// https://github.com/nodejs/node-v0.x-archive/issues/1697 + const net = require('net'); const cp = require('child_process'); diff --git a/test/parallel/test-performance.js b/test/sequential/test-performance.js similarity index 98% rename from test/parallel/test-performance.js rename to test/sequential/test-performance.js index d262e1f1f149d1..770ca7bf6407be 100644 --- a/test/parallel/test-performance.js +++ b/test/sequential/test-performance.js @@ -70,7 +70,7 @@ assert(inited < 20000); { performance.mark('A'); [undefined, null, 'foo', 'initialize', 1].forEach((i) => { - assert.doesNotThrow(() => performance.measure('test', i, 'A')); + performance.measure('test', i, 'A'); // Should not throw. }); [undefined, null, 'foo', 1].forEach((i) => { diff --git a/test/sequential/test-tls-lookup.js b/test/sequential/test-tls-lookup.js index ff759cf2fe6bea..568ba1350675e1 100644 --- a/test/sequential/test-tls-lookup.js +++ b/test/sequential/test-tls-lookup.js @@ -3,7 +3,6 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); -const assert = require('assert'); const tls = require('tls'); ['foobar', 1, {}, []].forEach(function connectThrows(input) { @@ -30,7 +29,5 @@ function connectDoesNotThrow(input) { lookup: input }; - assert.doesNotThrow(function() { - tls.connect(opts); - }); + tls.connect(opts); } diff --git a/tools/eslint-rules/no-unescaped-regexp-dot.js b/tools/eslint-rules/no-unescaped-regexp-dot.js index d0c575071297fb..3af514d4bb91a9 100644 --- a/tools/eslint-rules/no-unescaped-regexp-dot.js +++ b/tools/eslint-rules/no-unescaped-regexp-dot.js @@ -120,10 +120,10 @@ module.exports = function(context) { } return { - TemplateLiteral: checkLiteral, - Literal: checkLiteral, - CallExpression: checkRegExpStart, - NewExpression: checkRegExpStart, + 'TemplateLiteral': checkLiteral, + 'Literal': checkLiteral, + 'CallExpression': checkRegExpStart, + 'NewExpression': checkRegExpStart, 'CallExpression:exit': checkRegExpEnd, 'NewExpression:exit': checkRegExpEnd }; diff --git a/tools/js2c.py b/tools/js2c.py index f7951617d34064..d2d63ad571205d 100755 --- a/tools/js2c.py +++ b/tools/js2c.py @@ -261,6 +261,11 @@ def JS2C(source, target): if '/' in name or '\\' in name: name = '/'.join(re.split('/|\\\\', name)[1:]) + # if its a gypi file we're going to want it as json + # later on anyway, so get it out of the way now + if name.endswith(".gypi"): + lines = re.sub(r'#.*?\n', '', lines) + lines = re.sub(r'\'', '"', lines) name = name.split('.', 1)[0] var = name.replace('-', '_').replace('/', '_') key = '%s_key' % var diff --git a/tools/test-npm-package.js b/tools/test-npm-package.js index 00e9a81928a819..0cf9700ef96e80 100755 --- a/tools/test-npm-package.js +++ b/tools/test-npm-package.js @@ -22,6 +22,7 @@ const { createWriteStream, mkdirSync, rmdirSync } = require('fs'); const path = require('path'); const common = require('../test/common'); +const tmpDir = require('../test/common/tmpdir'); const projectDir = path.resolve(__dirname, '..'); const npmBin = path.join(projectDir, 'deps', 'npm', 'bin', 'npm-cli.js'); @@ -39,15 +40,14 @@ function spawnCopyDeepSync(source, destination) { function runNPMPackageTests({ srcDir, install, rebuild, testArgs, logfile }) { // Make sure we don't conflict with concurrent test runs const srcHash = createHash('md5').update(srcDir).digest('hex'); - common.tmpDir = `${common.tmpDir}.npm.${srcHash}`; - common.refreshTmpDir(); + tmpDir.path = `${tmpDir.path}.npm.${srcHash}`; + tmpDir.refresh(); - const tmpDir = common.tmpDir; - const npmCache = path.join(tmpDir, 'npm-cache'); - const npmPrefix = path.join(tmpDir, 'npm-prefix'); - const npmTmp = path.join(tmpDir, 'npm-tmp'); - const npmUserconfig = path.join(tmpDir, 'npm-userconfig'); - const pkgDir = path.join(tmpDir, 'pkg'); + const npmCache = path.join(tmpDir.path, 'npm-cache'); + const npmPrefix = path.join(tmpDir.path, 'npm-prefix'); + const npmTmp = path.join(tmpDir.path, 'npm-tmp'); + const npmUserconfig = path.join(tmpDir.path, 'npm-userconfig'); + const pkgDir = path.join(tmpDir.path, 'pkg'); spawnCopyDeepSync(srcDir, pkgDir); @@ -63,10 +63,10 @@ function runNPMPackageTests({ srcDir, install, rebuild, testArgs, logfile }) { }; if (common.isWindows) { - npmOptions.env.home = tmpDir; + npmOptions.env.home = tmpDir.path; npmOptions.env.Path = `${nodePath};${process.env.Path}`; } else { - npmOptions.env.HOME = tmpDir; + npmOptions.env.HOME = tmpDir.path; npmOptions.env.PATH = `${nodePath}:${process.env.PATH}`; } @@ -102,8 +102,8 @@ function runNPMPackageTests({ srcDir, install, rebuild, testArgs, logfile }) { } testChild.on('exit', () => { - common.refreshTmpDir(); - rmdirSync(tmpDir); + tmpDir.refresh(); + rmdirSync(tmpDir.path); }); } diff --git a/vcbuild.bat b/vcbuild.bat index 9d5bff7df720ab..56d80861c4b2ee 100644 --- a/vcbuild.bat +++ b/vcbuild.bat @@ -1,7 +1,5 @@ @if not defined DEBUG_HELPER @ECHO OFF -cd %~dp0 - if /i "%1"=="help" goto help if /i "%1"=="--help" goto help if /i "%1"=="-help" goto help @@ -11,6 +9,8 @@ if /i "%1"=="-?" goto help if /i "%1"=="--?" goto help if /i "%1"=="/?" goto help +cd %~dp0 + @rem Process arguments. set config=Release set target=Build