diff --git a/.travis.yml b/.travis.yml index 80c729a772fed5..e496919579b2f8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,14 @@ cache: ccache os: linux matrix: include: + - name: "First commit message adheres to guidelines at https://goo.gl/p2fr5Q" + if: type = pull_request + language: node_js + node_js: "node" + script: + - if [ "${TRAVIS_PULL_REQUEST}" != "false" ]; then + bash -x tools/lint-pr-commit-message.sh ${TRAVIS_PULL_REQUEST}; + fi - name: "Linter" language: node_js node_js: "node" @@ -11,10 +19,6 @@ matrix: - NODE=$(which node) script: - make lint - # Lint the first commit in the PR. - - if [ "${TRAVIS_PULL_REQUEST}" != "false" ]; then - bash tools/lint-pr-commit-message.sh ${TRAVIS_PULL_REQUEST} || true; - fi - name: "Test Suite" addons: apt: diff --git a/BUILDING.md b/BUILDING.md index efe39e656b383a..36d87c0f141b79 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -69,8 +69,7 @@ There are three support tiers: ### Supported platforms The community does not build or test against end-of-life distributions (EoL). -Thus, we do not recommend that you use Node.js on end-of-life or unsupported -platforms in production. +For production applications, run Node.js on supported platforms only. | System | Support type | Version | Architectures | Notes | |--------------|--------------|----------------------------------|----------------------|------------------| @@ -134,21 +133,20 @@ OpenSSL-1.1.0 requires the following assembler version for use of asm support on x86_64 and ia32. * gas (GNU assembler) version 2.23 or higher -* xcode version 5.0 or higher +* Xcode version 5.0 or higher * llvm version 3.3 or higher * nasm version 2.10 or higher in Windows -Otherwise `configure` will fail with an error. This can be avoided by -either providing a newer assembler as per the list above or by -using the `--openssl-no-asm` flag. +If compiling without one of the above, use `configure` with the +`--openssl-no-asm` flag. Otherwise, `configure` will fail. The forthcoming OpenSSL-1.1.1 will have different requirements. Please refer to https://www.openssl.org/docs/man1.1.1/man3/OPENSSL_ia32cap.html for details. ## Building Node.js on supported platforms -*Note:* All prerequisites can be easily installed by following -[this bootstrapping guide](https://github.com/nodejs/node/blob/master/tools/bootstrap/README.md). +The [bootstrapping guide](https://github.com/nodejs/node/blob/master/tools/bootstrap/README.md) +explains how to install all prerequisites. ### Unix/macOS @@ -159,7 +157,7 @@ The forthcoming OpenSSL-1.1.1 will have different requirements. Please refer to * Python 2.6 or 2.7 * GNU Make 3.81 or newer -On macOS, you will need to install the `Xcode Command Line Tools` by running +On macOS, install the `Xcode Command Line Tools` by running `xcode-select --install`. Alternatively, if you already have the full Xcode installed, you can find them under the menu `Xcode -> Open Developer Tool -> More Developer Tools...`. This step will install `clang`, `clang++`, and @@ -180,13 +178,9 @@ $ ./configure $ make -j4 ``` -Running `make` with the `-j4` flag will cause it to run 4 compilation jobs -concurrently which may significantly reduce build time. The number after `-j` -can be changed to best suit the number of processor cores on your machine. If -you run into problems running `make` with concurrency, try running it without -the `-j4` flag. See the -[GNU Make Documentation](https://www.gnu.org/software/make/manual/html_node/Parallel.html) -for more information. +The `-j4` option will cause `make` to run 4 simultaneous compilation jobs which +may reduce build time. For more information, see the +[GNU Make Documentation](https://www.gnu.org/software/make/manual/html_node/Parallel.html). Note that the above requires that `python` resolve to Python 2.6 or 2.7 and not a newer version. diff --git a/Makefile b/Makefile index ae3830ddd40e00..d24451f4289414 100644 --- a/Makefile +++ b/Makefile @@ -270,7 +270,7 @@ v8: tools/make-v8.sh $(V8_ARCH).$(BUILDTYPE_LOWER) $(V8_BUILD_OPTIONS) .PHONY: jstest -jstest: build-addons build-addons-napi bench-addons-build ## Runs addon tests and JS tests +jstest: build-addons build-addons-napi ## Runs addon tests and JS tests $(PYTHON) tools/test.py $(PARALLEL_ARGS) --mode=$(BUILDTYPE_LOWER) \ --skip-tests=$(CI_SKIP_TESTS) \ $(CI_JS_SUITES) \ @@ -332,16 +332,16 @@ ifeq ($(OSTYPE),aix) DOCBUILDSTAMP_PREREQS := $(DOCBUILDSTAMP_PREREQS) out/$(BUILDTYPE)/node.exp endif -node_use_openssl = $(shell $(call available-node,"-p" \ - "process.versions.openssl != undefined")) +node_use_openssl = $(call available-node,"-p" \ + "process.versions.openssl != undefined") test/addons/.docbuildstamp: $(DOCBUILDSTAMP_PREREQS) tools/doc/node_modules -ifeq ($(node_use_openssl),true) - $(RM) -r test/addons/??_*/ - [ -x $(NODE) ] && $(NODE) $< || node $< - touch $@ -else - @echo "Skipping .docbuildstamp (no crypto)" -endif + @if [ "$(shell $(node_use_openssl))" != "true" ]; then \ + echo "Skipping .docbuildstamp (no crypto)"; \ + else \ + $(RM) -r test/addons/??_*/; \ + [ -x $(NODE) ] && $(NODE) $< || node $< ; \ + touch $@; \ + fi ADDONS_BINDING_GYPS := \ $(filter-out test/addons/??_*/binding.gyp, \ @@ -414,7 +414,7 @@ clear-stalled: echo $${PS_OUT} | xargs kill -9; \ fi -test-build: | all build-addons build-addons-napi bench-addons-build +test-build: | all build-addons build-addons-napi test-build-addons-napi: all build-addons-napi @@ -455,7 +455,7 @@ test-ci-js: | clear-stalled .PHONY: test-ci # Related CI jobs: most CI tests, excluding node-test-commit-arm-fanned test-ci: LOGLEVEL := info -test-ci: | clear-stalled build-addons build-addons-napi doc-only bench-addons-build +test-ci: | clear-stalled build-addons build-addons-napi doc-only out/Release/cctest --gtest_output=tap:cctest.tap $(PYTHON) tools/test.py $(PARALLEL_ARGS) -p tap --logfile test.tap \ --mode=$(BUILDTYPE_LOWER) --flaky-tests=$(FLAKY_TESTS) \ @@ -496,7 +496,7 @@ test-debug: test-build test-message: test-build $(PYTHON) tools/test.py $(PARALLEL_ARGS) message -test-simple: | cctest bench-addons-build # Depends on 'all'. +test-simple: | cctest # Depends on 'all'. $(PYTHON) tools/test.py $(PARALLEL_ARGS) parallel sequential test-pummel: all @@ -509,6 +509,9 @@ test-node-inspect: $(NODE_EXE) USE_EMBEDDED_NODE_INSPECT=1 $(NODE) tools/test-npm-package \ --install deps/node-inspect test +test-benchmark: | bench-addons-build + $(PYTHON) tools/test.py $(PARALLEL_ARGS) benchmark + test-tick-processor: all $(PYTHON) tools/test.py $(PARALLEL_ARGS) tick-processor @@ -609,11 +612,11 @@ apidocs_json = $(addprefix out/,$(apidoc_sources:.md=.json)) apiassets = $(subst api_assets,api/assets,$(addprefix out/,$(wildcard doc/api_assets/*))) tools/doc/node_modules: tools/doc/package.json -ifeq ($(node_use_openssl),true) - cd tools/doc && $(call available-node,$(run-npm-ci)) -else - @echo "Skipping tools/doc/node_modules (no crypto)" -endif + @if [ "$(shell $(node_use_openssl))" != "true" ]; then \ + echo "Skipping tools/doc/node_modules (no crypto)"; \ + else \ + cd tools/doc && $(call available-node,$(run-npm-ci)) \ + fi .PHONY: doc-only doc-only: tools/doc/node_modules \ diff --git a/README.md b/README.md index 79b12e289a58f4..533b36bf8dbd58 100644 --- a/README.md +++ b/README.md @@ -401,6 +401,8 @@ For information about the governance of the Node.js project, see **Alexis Campailla** <orangemocha@nodejs.org> * [othiym23](https://github.com/othiym23) - **Forrest L Norvell** <ogd@aoaioxxysz.net> (he/him) +* [oyyd](https://github.com/oyyd) - +**Ouyang Yadong** <oyydoibh@gmail.com> (he/him) * [pmq20](https://github.com/pmq20) - **Minqi Pan** <pmq2001@gmail.com> * [princejwesley](https://github.com/princejwesley) - diff --git a/benchmark/fixtures/require-cachable.js b/benchmark/fixtures/require-cachable.js new file mode 100644 index 00000000000000..f651728dc78f35 --- /dev/null +++ b/benchmark/fixtures/require-cachable.js @@ -0,0 +1,13 @@ +'use strict'; + +const list = require('internal/bootstrap/cache'); +const { + isMainThread +} = require('worker_threads'); + +for (const key of list.cachableBuiltins) { + if (!isMainThread && key === 'trace_events') { + continue; + } + require(key); +} diff --git a/benchmark/misc/startup.js b/benchmark/misc/startup.js index 703146f081b3c6..1350cd291e2b18 100644 --- a/benchmark/misc/startup.js +++ b/benchmark/misc/startup.js @@ -1,36 +1,76 @@ 'use strict'; const common = require('../common.js'); -const spawn = require('child_process').spawn; +const { spawn } = require('child_process'); const path = require('path'); -const emptyJsFile = path.resolve(__dirname, '../../test/fixtures/semicolon.js'); -const bench = common.createBenchmark(startNode, { - dur: [1] +let Worker; // Lazy loaded in main + +const bench = common.createBenchmark(main, { + dur: [1], + script: ['benchmark/fixtures/require-cachable', 'test/fixtures/semicolon'], + mode: ['process', 'worker'] +}, { + flags: ['--expose-internals', '--experimental-worker'] // for workers }); -function startNode({ dur }) { - var go = true; - var starts = 0; +function spawnProcess(script) { + const cmd = process.execPath || process.argv[0]; + const argv = ['--expose-internals', script]; + return spawn(cmd, argv); +} + +function spawnWorker(script) { + return new Worker(script, { stderr: true, stdout: true }); +} + +function start(state, script, bench, getNode) { + const node = getNode(script); + let stdout = ''; + let stderr = ''; + + node.stdout.on('data', (data) => { + stdout += data; + }); + + node.stderr.on('data', (data) => { + stderr += data; + }); + + node.on('exit', (code) => { + if (code !== 0) { + console.error('------ stdout ------'); + console.error(stdout); + console.error('------ stderr ------'); + console.error(stderr); + throw new Error(`Error during node startup, exit code ${code}`); + } + state.throughput++; + + if (state.go) { + start(state, script, bench, getNode); + } else { + bench.end(state.throughput); + } + }); +} + +function main({ dur, script, mode }) { + const state = { + go: true, + throughput: 0 + }; setTimeout(function() { - go = false; + state.go = false; }, dur * 1000); - bench.start(); - start(); - - function start() { - const node = spawn(process.execPath || process.argv[0], [emptyJsFile]); - node.on('exit', function(exitCode) { - if (exitCode !== 0) { - throw new Error('Error during node startup'); - } - starts++; - - if (go) - start(); - else - bench.end(starts); - }); + script = path.resolve(__dirname, '../../', `${script}.js`); + if (mode === 'worker') { + Worker = require('worker_threads').Worker; + bench.start(); + start(state, script, bench, spawnWorker); + } else { + bench.start(); + start(state, script, bench, spawnProcess); } } diff --git a/common.gypi b/common.gypi index e2295ee35de832..ba444e1429f856 100644 --- a/common.gypi +++ b/common.gypi @@ -33,7 +33,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.45', + 'v8_embedder_string': '-node.46', # Enable disassembler for `--print-code` v8 options 'v8_enable_disassembler': 1, diff --git a/deps/http_parser/http_parser.c b/deps/http_parser/http_parser.c index 6522618671d09c..46764bced09478 100644 --- a/deps/http_parser/http_parser.c +++ b/deps/http_parser/http_parser.c @@ -25,6 +25,8 @@ #include #include +static uint32_t max_header_size = HTTP_MAX_HEADER_SIZE; + #ifndef ULLONG_MAX # define ULLONG_MAX ((uint64_t) -1) /* 2^64-1 */ #endif @@ -137,20 +139,20 @@ do { \ } while (0) /* Don't allow the total size of the HTTP headers (including the status - * line) to exceed HTTP_MAX_HEADER_SIZE. This check is here to protect + * line) to exceed max_header_size. This check is here to protect * embedders against denial-of-service attacks where the attacker feeds * us a never-ending header that the embedder keeps buffering. * * This check is arguably the responsibility of embedders but we're doing * it on the embedder's behalf because most won't bother and this way we - * make the web a little safer. HTTP_MAX_HEADER_SIZE is still far bigger + * make the web a little safer. max_header_size is still far bigger * than any reasonable request or response so this should never affect * day-to-day operation. */ #define COUNT_HEADER_SIZE(V) \ do { \ parser->nread += (V); \ - if (UNLIKELY(parser->nread > (HTTP_MAX_HEADER_SIZE))) { \ + if (UNLIKELY(parser->nread > max_header_size)) { \ SET_ERRNO(HPE_HEADER_OVERFLOW); \ goto error; \ } \ @@ -1471,7 +1473,7 @@ size_t http_parser_execute (http_parser *parser, const char* p_lf; size_t limit = data + len - p; - limit = MIN(limit, HTTP_MAX_HEADER_SIZE); + limit = MIN(limit, max_header_size); p_cr = (const char*) memchr(p, CR, limit); p_lf = (const char*) memchr(p, LF, limit); @@ -2437,3 +2439,8 @@ http_parser_version(void) { HTTP_PARSER_VERSION_MINOR * 0x00100 | HTTP_PARSER_VERSION_PATCH * 0x00001; } + +void +http_parser_set_max_header_size(uint32_t size) { + max_header_size = size; +} diff --git a/deps/http_parser/http_parser.h b/deps/http_parser/http_parser.h index 1fbf30e2b4740b..ea7bafef2c3178 100644 --- a/deps/http_parser/http_parser.h +++ b/deps/http_parser/http_parser.h @@ -427,6 +427,9 @@ void http_parser_pause(http_parser *parser, int paused); /* Checks if this is the final chunk of the body. */ int http_body_is_final(const http_parser *parser); +/* Change the maximum header size provided at compile time. */ +void http_parser_set_max_header_size(uint32_t size); + #ifdef __cplusplus } #endif diff --git a/deps/v8/src/compiler/js-operator.cc b/deps/v8/src/compiler/js-operator.cc index 04feec6827aad0..8dedd68d946032 100644 --- a/deps/v8/src/compiler/js-operator.cc +++ b/deps/v8/src/compiler/js-operator.cc @@ -598,7 +598,7 @@ CompareOperationHint CompareOperationHintOf(const Operator* op) { V(CreateKeyValueArray, Operator::kEliminatable, 2, 1) \ V(CreatePromise, Operator::kEliminatable, 0, 1) \ V(CreateTypedArray, Operator::kNoProperties, 5, 1) \ - V(CreateObject, Operator::kNoWrite, 1, 1) \ + V(CreateObject, Operator::kNoProperties, 1, 1) \ V(ObjectIsArray, Operator::kNoProperties, 1, 1) \ V(HasProperty, Operator::kNoProperties, 2, 1) \ V(HasInPrototypeChain, Operator::kNoProperties, 2, 1) \ diff --git a/deps/v8/test/mjsunit/compiler/regress-888923.js b/deps/v8/test/mjsunit/compiler/regress-888923.js new file mode 100644 index 00000000000000..e352673b7d933d --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/regress-888923.js @@ -0,0 +1,31 @@ +// Copyright 2018 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax + +(function() { + function f(o) { + o.x; + Object.create(o); + return o.y.a; + } + + f({ x : 0, y : { a : 1 } }); + f({ x : 0, y : { a : 2 } }); + %OptimizeFunctionOnNextCall(f); + assertEquals(3, f({ x : 0, y : { a : 3 } })); +})(); + +(function() { + function f(o) { + let a = o.y; + Object.create(o); + return o.x + a; + } + + f({ x : 42, y : 21 }); + f({ x : 42, y : 21 }); + %OptimizeFunctionOnNextCall(f); + assertEquals(63, f({ x : 42, y : 21 })); +})(); diff --git a/doc/api/addons.md b/doc/api/addons.md index 757f24c5194271..e2530acb77d5e0 100644 --- a/doc/api/addons.md +++ b/doc/api/addons.md @@ -63,13 +63,15 @@ namespace demo { using v8::FunctionCallbackInfo; using v8::Isolate; using v8::Local; +using v8::NewStringType; using v8::Object; using v8::String; using v8::Value; void Method(const FunctionCallbackInfo& args) { Isolate* isolate = args.GetIsolate(); - args.GetReturnValue().Set(String::NewFromUtf8(isolate, "world")); + args.GetReturnValue().Set(String::NewFromUtf8( + isolate, "world", NewStringType::kNormal).ToLocalChecked()); } void Initialize(Local exports) { @@ -464,6 +466,7 @@ using v8::Exception; using v8::FunctionCallbackInfo; using v8::Isolate; using v8::Local; +using v8::NewStringType; using v8::Number; using v8::Object; using v8::String; @@ -479,14 +482,18 @@ void Add(const FunctionCallbackInfo& args) { if (args.Length() < 2) { // Throw an Error that is passed back to JavaScript isolate->ThrowException(Exception::TypeError( - String::NewFromUtf8(isolate, "Wrong number of arguments"))); + String::NewFromUtf8(isolate, + "Wrong number of arguments", + NewStringType::kNormal).ToLocalChecked())); return; } // Check the argument types if (!args[0]->IsNumber() || !args[1]->IsNumber()) { isolate->ThrowException(Exception::TypeError( - String::NewFromUtf8(isolate, "Wrong arguments"))); + String::NewFromUtf8(isolate, + "Wrong arguments", + NewStringType::kNormal).ToLocalChecked())); return; } @@ -534,6 +541,7 @@ using v8::Function; using v8::FunctionCallbackInfo; using v8::Isolate; using v8::Local; +using v8::NewStringType; using v8::Null; using v8::Object; using v8::String; @@ -543,7 +551,10 @@ void RunCallback(const FunctionCallbackInfo& args) { Isolate* isolate = args.GetIsolate(); Local cb = Local::Cast(args[0]); const unsigned argc = 1; - Local argv[argc] = { String::NewFromUtf8(isolate, "hello world") }; + Local argv[argc] = { + String::NewFromUtf8(isolate, + "hello world", + NewStringType::kNormal).ToLocalChecked() }; cb->Call(Null(isolate), argc, argv); } @@ -591,6 +602,7 @@ using v8::Context; using v8::FunctionCallbackInfo; using v8::Isolate; using v8::Local; +using v8::NewStringType; using v8::Object; using v8::String; using v8::Value; @@ -600,7 +612,9 @@ void CreateObject(const FunctionCallbackInfo& args) { Local context = isolate->GetCurrentContext(); Local obj = Object::New(isolate); - obj->Set(String::NewFromUtf8(isolate, "msg"), + obj->Set(String::NewFromUtf8(isolate, + "msg", + NewStringType::kNormal).ToLocalChecked(), args[0]->ToString(context).ToLocalChecked()); args.GetReturnValue().Set(obj); @@ -644,13 +658,15 @@ using v8::FunctionCallbackInfo; using v8::FunctionTemplate; using v8::Isolate; using v8::Local; +using v8::NewStringType; using v8::Object; using v8::String; using v8::Value; void MyFunction(const FunctionCallbackInfo& args) { Isolate* isolate = args.GetIsolate(); - args.GetReturnValue().Set(String::NewFromUtf8(isolate, "hello world")); + args.GetReturnValue().Set(String::NewFromUtf8( + isolate, "hello world", NewStringType::kNormal).ToLocalChecked()); } void CreateFunction(const FunctionCallbackInfo& args) { @@ -661,7 +677,8 @@ void CreateFunction(const FunctionCallbackInfo& args) { Local fn = tpl->GetFunction(context).ToLocalChecked(); // omit this to make it anonymous - fn->SetName(String::NewFromUtf8(isolate, "theFunction")); + fn->SetName(String::NewFromUtf8( + isolate, "theFunction", NewStringType::kNormal).ToLocalChecked()); args.GetReturnValue().Set(fn); } @@ -757,6 +774,7 @@ using v8::FunctionCallbackInfo; using v8::FunctionTemplate; using v8::Isolate; using v8::Local; +using v8::NewStringType; using v8::Number; using v8::Object; using v8::Persistent; @@ -776,7 +794,8 @@ void MyObject::Init(Local exports) { // Prepare constructor template Local tpl = FunctionTemplate::New(isolate, New); - tpl->SetClassName(String::NewFromUtf8(isolate, "MyObject")); + tpl->SetClassName(String::NewFromUtf8( + isolate, "MyObject", NewStringType::kNormal).ToLocalChecked()); tpl->InstanceTemplate()->SetInternalFieldCount(1); // Prototype @@ -784,7 +803,8 @@ void MyObject::Init(Local exports) { Local context = isolate->GetCurrentContext(); constructor.Reset(isolate, tpl->GetFunction(context).ToLocalChecked()); - exports->Set(String::NewFromUtf8(isolate, "MyObject"), + exports->Set(String::NewFromUtf8( + isolate, "MyObject", NewStringType::kNormal).ToLocalChecked(), tpl->GetFunction(context).ToLocalChecked()); } @@ -952,6 +972,7 @@ using v8::FunctionCallbackInfo; using v8::FunctionTemplate; using v8::Isolate; using v8::Local; +using v8::NewStringType; using v8::Number; using v8::Object; using v8::Persistent; @@ -969,7 +990,8 @@ MyObject::~MyObject() { void MyObject::Init(Isolate* isolate) { // Prepare constructor template Local tpl = FunctionTemplate::New(isolate, New); - tpl->SetClassName(String::NewFromUtf8(isolate, "MyObject")); + tpl->SetClassName(String::NewFromUtf8( + isolate, "MyObject", NewStringType::kNormal).ToLocalChecked()); tpl->InstanceTemplate()->SetInternalFieldCount(1); // Prototype @@ -1167,6 +1189,7 @@ using v8::FunctionCallbackInfo; using v8::FunctionTemplate; using v8::Isolate; using v8::Local; +using v8::NewStringType; using v8::Object; using v8::Persistent; using v8::String; @@ -1183,7 +1206,8 @@ MyObject::~MyObject() { void MyObject::Init(Isolate* isolate) { // Prepare constructor template Local tpl = FunctionTemplate::New(isolate, New); - tpl->SetClassName(String::NewFromUtf8(isolate, "MyObject")); + tpl->SetClassName(String::NewFromUtf8( + isolate, "MyObject", NewStringType::kNormal).ToLocalChecked()); tpl->InstanceTemplate()->SetInternalFieldCount(1); Local context = isolate->GetCurrentContext(); diff --git a/doc/api/assert.md b/doc/api/assert.md index 50519b831c9a2c..ab664d94d88a65 100644 --- a/doc/api/assert.md +++ b/doc/api/assert.md @@ -1233,8 +1233,8 @@ assert.throws(throwingFirst, /Second$/); 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. -[`ERR_INVALID_RETURN_VALUE`]: errors.html#errors_err_invalid_return_value [`Class`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes +[`ERR_INVALID_RETURN_VALUE`]: errors.html#errors_err_invalid_return_value [`Error.captureStackTrace`]: errors.html#errors_error_capturestacktrace_targetobject_constructoropt [`Error`]: errors.html#errors_class_error [`Map`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map @@ -1255,10 +1255,10 @@ second argument. This might lead to difficult-to-spot errors. [`assert.throws()`]: #assert_assert_throws_fn_error_message [`strict mode`]: #assert_strict_mode [Abstract Equality Comparison]: https://tc39.github.io/ecma262/#sec-abstract-equality-comparison +[Object wrappers]: https://developer.mozilla.org/en-US/docs/Glossary/Primitive#Primitive_wrapper_objects_in_JavaScript [Object.prototype.toString()]: https://tc39.github.io/ecma262/#sec-object.prototype.tostring [SameValue Comparison]: https://tc39.github.io/ecma262/#sec-samevalue [Strict Equality Comparison]: https://tc39.github.io/ecma262/#sec-strict-equality-comparison [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 -[Object wrappers]: https://developer.mozilla.org/en-US/docs/Glossary/Primitive#Primitive_wrapper_objects_in_JavaScript diff --git a/doc/api/async_hooks.md b/doc/api/async_hooks.md index f0752a5892c362..6a6cc781a79f1f 100644 --- a/doc/api/async_hooks.md +++ b/doc/api/async_hooks.md @@ -238,8 +238,8 @@ resource's constructor. ```text FSEVENTWRAP, FSREQWRAP, GETADDRINFOREQWRAP, GETNAMEINFOREQWRAP, HTTPPARSER, JSSTREAM, PIPECONNECTWRAP, PIPEWRAP, PROCESSWRAP, QUERYWRAP, SHUTDOWNWRAP, -SIGNALWRAP, STATWATCHER, TCPCONNECTWRAP, TCPSERVER, TCPWRAP, TIMERWRAP, TTYWRAP, -UDPSENDWRAP, UDPWRAP, WRITEWRAP, ZLIB, SSLCONNECTION, PBKDF2REQUEST, +SIGNALWRAP, STATWATCHER, TCPCONNECTWRAP, TCPSERVERWRAP, TCPWRAP, TIMERWRAP, +TTYWRAP, UDPSENDWRAP, UDPWRAP, WRITEWRAP, ZLIB, SSLCONNECTION, PBKDF2REQUEST, RANDOMBYTESREQUEST, TLSWRAP, Timeout, Immediate, TickObject ``` @@ -276,8 +276,8 @@ require('net').createServer((conn) => {}).listen(8080); Output when hitting the server with `nc localhost 8080`: ```console -TCPSERVERWRAP(2): trigger: 1 execution: 1 -TCPWRAP(4): trigger: 2 execution: 0 +TCPSERVERWRAP(5): trigger: 1 execution: 1 +TCPWRAP(7): trigger: 5 execution: 0 ``` The `TCPSERVERWRAP` is the server which receives the connections. @@ -296,7 +296,7 @@ of propagating what resource is responsible for the new resource's existence. been initialized. This can contain useful information that can vary based on the value of `type`. For instance, for the `GETADDRINFOREQWRAP` resource type, `resource` provides the hostname used when looking up the IP address for the -hostname in `net.Server.listen()`. The API for accessing this information is +host in `net.Server.listen()`. The API for accessing this information is currently not considered public, but using the Embedder API, users can provide and document their own resource objects. For example, such a resource object could contain the SQL query being executed. @@ -355,27 +355,18 @@ require('net').createServer(() => {}).listen(8080, () => { Output from only starting the server: ```console -TCPSERVERWRAP(2): trigger: 1 execution: 1 -TickObject(3): trigger: 2 execution: 1 -before: 3 - Timeout(4): trigger: 3 execution: 3 - TIMERWRAP(5): trigger: 3 execution: 3 -after: 3 -destroy: 3 -before: 5 - before: 4 - TTYWRAP(6): trigger: 4 execution: 4 - SIGNALWRAP(7): trigger: 4 execution: 4 - TTYWRAP(8): trigger: 4 execution: 4 ->>> 4 - TickObject(9): trigger: 4 execution: 4 - after: 4 -after: 5 -before: 9 -after: 9 -destroy: 4 -destroy: 9 -destroy: 5 +TCPSERVERWRAP(5): trigger: 1 execution: 1 +TickObject(6): trigger: 5 execution: 1 +before: 6 + Timeout(7): trigger: 6 execution: 6 +after: 6 +destroy: 6 +before: 7 +>>> 7 + TickObject(8): trigger: 7 execution: 7 +after: 7 +before: 8 +after: 8 ``` As illustrated in the example, `executionAsyncId()` and `execution` each specify @@ -385,7 +376,7 @@ the value of the current execution context; which is delineated by calls to Only using `execution` to graph resource allocation results in the following: ```console -TTYWRAP(6) -> Timeout(4) -> TIMERWRAP(5) -> TickObject(3) -> root(1) +Timeout(7) -> TickObject(6) -> root(1) ``` The `TCPSERVERWRAP` is not part of this graph, even though it was the reason for @@ -720,6 +711,7 @@ never be called. * Returns: {number} The same `triggerAsyncId` that is passed to the `AsyncResource` constructor. +[`Worker`]: worker_threads.html#worker_threads_class_worker [`after` callback]: #async_hooks_after_asyncid [`asyncResource.runInAsyncScope()`]: #async_hooks_asyncresource_runinasyncscope_fn_thisarg_args [`before` callback]: #async_hooks_before_asyncid @@ -728,4 +720,3 @@ never be called. [Hook Callbacks]: #async_hooks_hook_callbacks [PromiseHooks]: https://docs.google.com/document/d/1rda3yKGHimKIhg5YeoAmCOtyURgsbTH_qaYR79FELlk/edit [promise execution tracking]: #async_hooks_promise_execution_tracking -[`Worker`]: worker_threads.html#worker_threads_class_worker diff --git a/doc/api/buffer.md b/doc/api/buffer.md index 897512ae000805..97fc170c02c9c6 100644 --- a/doc/api/buffer.md +++ b/doc/api/buffer.md @@ -2669,9 +2669,9 @@ This value may depend on the JS engine that is being used. [`buf.length`]: #buffer_buf_length [`buf.slice()`]: #buffer_buf_slice_start_end [`buf.values()`]: #buffer_buf_values -[`buffer.kMaxLength`]: #buffer_buffer_kmaxlength [`buffer.constants.MAX_LENGTH`]: #buffer_buffer_constants_max_length [`buffer.constants.MAX_STRING_LENGTH`]: #buffer_buffer_constants_max_string_length +[`buffer.kMaxLength`]: #buffer_buffer_kmaxlength [`util.inspect()`]: util.html#util_util_inspect_object_options [RFC1345]: https://tools.ietf.org/html/rfc1345 [RFC4648, Section 5]: https://tools.ietf.org/html/rfc4648#section-5 diff --git a/doc/api/child_process.md b/doc/api/child_process.md index 23715b2dd1080f..04f8fa8a3d9bb6 100644 --- a/doc/api/child_process.md +++ b/doc/api/child_process.md @@ -1432,13 +1432,6 @@ unavailable. [`ChildProcess`]: #child_process_child_process [`Error`]: errors.html#errors_class_error [`EventEmitter`]: events.html#events_class_eventemitter -[`subprocess.connected`]: #child_process_subprocess_connected -[`subprocess.disconnect()`]: #child_process_subprocess_disconnect -[`subprocess.kill()`]: #child_process_subprocess_kill_signal -[`subprocess.send()`]: #child_process_subprocess_send_message_sendhandle_options_callback -[`subprocess.stderr`]: #child_process_subprocess_stderr -[`subprocess.stdin`]: #child_process_subprocess_stdin -[`subprocess.stdout`]: #child_process_subprocess_stdout [`child_process.exec()`]: #child_process_child_process_exec_command_options_callback [`child_process.execFile()`]: #child_process_child_process_execfile_file_args_options_callback [`child_process.execFileSync()`]: #child_process_child_process_execfilesync_file_args_options @@ -1455,6 +1448,13 @@ unavailable. [`process.execPath`]: process.html#process_process_execpath [`process.send()`]: process.html#process_process_send_message_sendhandle_options_callback [`stdio`]: #child_process_options_stdio +[`subprocess.connected`]: #child_process_subprocess_connected +[`subprocess.disconnect()`]: #child_process_subprocess_disconnect +[`subprocess.kill()`]: #child_process_subprocess_kill_signal +[`subprocess.send()`]: #child_process_subprocess_send_message_sendhandle_options_callback +[`subprocess.stderr`]: #child_process_subprocess_stderr +[`subprocess.stdin`]: #child_process_subprocess_stdin +[`subprocess.stdout`]: #child_process_subprocess_stdout [`util.promisify()`]: util.html#util_util_promisify_original [Default Windows Shell]: #child_process_default_windows_shell [Shell Requirements]: #child_process_shell_requirements diff --git a/doc/api/cli.md b/doc/api/cli.md index 29f3360dda1d78..d1fbf9432eb376 100644 --- a/doc/api/cli.md +++ b/doc/api/cli.md @@ -181,6 +181,13 @@ added: v9.0.0 Specify the `file` of the custom [experimental ECMAScript Module][] loader. +### `--max-http-header-size=size` + + +Specify the maximum size, in bytes, of HTTP headers. Defaults to 8KB. + ### `--napi-modules` Too much HTTP header data was received. In order to protect against malicious or -malconfigured clients, if more than 80KB of HTTP header data is received then +malconfigured clients, if more than 8KB of HTTP header data is received then HTTP parsing will abort without a request or response object being created, and an `Error` with this code will be emitted. @@ -2097,24 +2103,25 @@ instance.setEncoding('utf8'); An attempt has been made to create a string larger than the maximum allowed size. -[`--force-fips`]: cli.html#cli_force_fips [`'uncaughtException'`]: process.html#process_event_uncaughtexception +[`--force-fips`]: cli.html#cli_force_fips +[`Class: assert.AssertionError`]: assert.html#assert_class_assert_assertionerror +[`ERR_INVALID_ARG_TYPE`]: #ERR_INVALID_ARG_TYPE +[`EventEmitter`]: events.html#events_class_eventemitter +[`Writable`]: stream.html#stream_class_stream_writable [`child_process`]: child_process.html [`cipher.getAuthTag()`]: crypto.html#crypto_cipher_getauthtag -[`Class: assert.AssertionError`]: assert.html#assert_class_assert_assertionerror [`crypto.scrypt()`]: crypto.html#crypto_crypto_scrypt_password_salt_keylen_options_callback [`crypto.scryptSync()`]: crypto.html#crypto_crypto_scryptsync_password_salt_keylen_options [`crypto.timingSafeEqual()`]: crypto.html#crypto_crypto_timingsafeequal_a_b [`dgram.createSocket()`]: dgram.html#dgram_dgram_createsocket_options_callback -[`ERR_INVALID_ARG_TYPE`]: #ERR_INVALID_ARG_TYPE -[`EventEmitter`]: events.html#events_class_eventemitter -[`fs`]: fs.html [`errno`(3) man page]: http://man7.org/linux/man-pages/man3/errno.3.html [`fs.readFileSync`]: fs.html#fs_fs_readfilesync_path_options [`fs.readdir`]: fs.html#fs_fs_readdir_path_options_callback [`fs.symlink()`]: fs.html#fs_fs_symlink_target_path_type_callback [`fs.symlinkSync()`]: fs.html#fs_fs_symlinksync_target_path_type [`fs.unlink`]: fs.html#fs_fs_unlink_path_callback +[`fs`]: fs.html [`hash.digest()`]: crypto.html#crypto_hash_digest_encoding [`hash.update()`]: crypto.html#crypto_hash_update_data_inputencoding [`http`]: http.html @@ -2126,10 +2133,10 @@ size. [`process.send()`]: process.html#process_process_send_message_sendhandle_options_callback [`process.setUncaughtExceptionCaptureCallback()`]: process.html#process_process_setuncaughtexceptioncapturecallback_fn [`readable._read()`]: stream.html#stream_readable_read_size_1 -[`require()`]: modules.html#modules_require [`require('crypto').setEngine()`]: crypto.html#crypto_crypto_setengine_engine_flags -[`server.listen()`]: net.html#net_server_listen +[`require()`]: modules.html#modules_require [`server.close()`]: net.html#net_server_close_callback +[`server.listen()`]: net.html#net_server_listen [`sign.sign()`]: crypto.html#crypto_sign_sign_privatekey_outputformat [`stream.pipe()`]: stream.html#stream_readable_pipe_destination_options [`stream.push()`]: stream.html#stream_readable_push_chunk_encoding @@ -2137,11 +2144,12 @@ size. [`stream.write()`]: stream.html#stream_writable_write_chunk_encoding_callback [`subprocess.kill()`]: child_process.html#child_process_subprocess_kill_signal [`subprocess.send()`]: child_process.html#child_process_subprocess_send_message_sendhandle_options_callback -[`Writable`]: stream.html#stream_class_stream_writable [`zlib`]: zlib.html [ES6 module]: esm.html +[ICU]: intl.html#intl_internationalization_support [Node.js Error Codes]: #nodejs-error-codes [V8's stack trace API]: https://github.com/v8/v8/wiki/Stack-Trace-API +[WHATWG Supported Encodings]: util.html#util_whatwg_supported_encodings [WHATWG URL API]: url.html#url_the_whatwg_url_api [crypto digest algorithm]: crypto.html#crypto_crypto_gethashes [domains]: domain.html @@ -2151,4 +2159,3 @@ size. [syscall]: http://man7.org/linux/man-pages/man2/syscalls.2.html [try-catch]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch [vm]: vm.html -[WHATWG Supported Encodings]: util.html#util_whatwg_supported_encodings diff --git a/doc/api/fs.md b/doc/api/fs.md index 21f1b91db6e15e..16cede54dba598 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -2308,6 +2308,9 @@ object with an `encoding` property specifying the character encoding to use. * `path` {string|Buffer|URL} * `flags` {string|number} See [support of file system `flags`][]. + **Default:** `'r'`. * `mode` {integer} **Default:** `0o666` (readable and writable) * Returns: {Promise} @@ -4798,13 +4812,13 @@ the file contents. [`AHAFS`]: https://www.ibm.com/developerworks/aix/library/au-aix_event_infrastructure/ [`Buffer.byteLength`]: buffer.html#buffer_class_method_buffer_bytelength_string_encoding [`Buffer`]: buffer.html#buffer_buffer +[`EventEmitter`]: events.html [`FSEvents`]: https://developer.apple.com/documentation/coreservices/file_system_events [`ReadDirectoryChangesW`]: https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-readdirectorychangesw [`ReadStream`]: #fs_class_fs_readstream [`URL`]: url.html#url_the_whatwg_url_api [`UV_THREADPOOL_SIZE`]: cli.html#cli_uv_threadpool_size_size [`WriteStream`]: #fs_class_fs_writestream -[`EventEmitter`]: events.html [`event ports`]: http://illumos.org/man/port_create [`fs.Dirent`]: #fs_class_fs_dirent [`fs.FSWatcher`]: #fs_class_fs_fswatcher @@ -4823,10 +4837,10 @@ the file contents. [`fs.mkdtemp()`]: #fs_fs_mkdtemp_prefix_options_callback [`fs.open()`]: #fs_fs_open_path_flags_mode_callback [`fs.read()`]: #fs_fs_read_fd_buffer_offset_length_position_callback -[`fs.readdir()`]: #fs_fs_readdir_path_options_callback -[`fs.readdirSync()`]: #fs_fs_readdirsync_path_options [`fs.readFile()`]: #fs_fs_readfile_path_options_callback [`fs.readFileSync()`]: #fs_fs_readfilesync_path_options +[`fs.readdir()`]: #fs_fs_readdir_path_options_callback +[`fs.readdirSync()`]: #fs_fs_readdirsync_path_options [`fs.realpath()`]: #fs_fs_realpath_path_options_callback [`fs.rmdir()`]: #fs_fs_rmdir_path_callback [`fs.stat()`]: #fs_fs_stat_path_options_callback @@ -4844,13 +4858,13 @@ the file contents. [Caveats]: #fs_caveats [Common System Errors]: errors.html#errors_common_system_errors [FS Constants]: #fs_fs_constants_1 +[File Access Constants]: #fs_file_access_constants [MDN-Date]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date [MDN-Number]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Number_type [MSDN-Rel-Path]: https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file#fully-qualified-vs-relative-paths +[MSDN-Using-Streams]: https://docs.microsoft.com/en-us/windows/desktop/FileIO/using-streams +[Naming Files, Paths, and Namespaces]: https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file [Readable Streams]: stream.html#stream_class_stream_readable [Writable Stream]: stream.html#stream_class_stream_writable [inode]: https://en.wikipedia.org/wiki/Inode -[Naming Files, Paths, and Namespaces]: https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file -[MSDN-Using-Streams]: https://docs.microsoft.com/en-us/windows/desktop/FileIO/using-streams [support of file system `flags`]: #fs_file_system_flags -[File Access Constants]: #fs_file_access_constants diff --git a/doc/api/globals.md b/doc/api/globals.md index 0277f7db603ef8..a3f76db9d6d692 100644 --- a/doc/api/globals.md +++ b/doc/api/globals.md @@ -169,6 +169,8 @@ The object that acts as the namespace for all W3C [WebAssembly][webassembly-org] related functionality. See the [Mozilla Developer Network][webassembly-mdn] for usage and compatibility. +[`URLSearchParams`]: url.html#url_class_urlsearchparams +[`URL`]: url.html#url_class_url [`__dirname`]: modules.html#modules_dirname [`__filename`]: modules.html#modules_filename [`clearImmediate`]: timers.html#timers_clearimmediate_immediate @@ -182,8 +184,6 @@ The object that acts as the namespace for all W3C [`setImmediate`]: timers.html#timers_setimmediate_callback_args [`setInterval`]: timers.html#timers_setinterval_callback_delay_args [`setTimeout`]: timers.html#timers_settimeout_callback_delay_args -[`URL`]: url.html#url_class_url -[`URLSearchParams`]: url.html#url_class_urlsearchparams [buffer section]: buffer.html [built-in objects]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects [module system documentation]: modules.html diff --git a/doc/api/http.md b/doc/api/http.md index 9a9e5c939ddff2..c75cbc403f7595 100644 --- a/doc/api/http.md +++ b/doc/api/http.md @@ -368,7 +368,7 @@ proxy.listen(1337, '127.0.0.1', () => { // make a request to a tunneling proxy const options = { port: 1337, - hostname: '127.0.0.1', + host: '127.0.0.1', method: 'CONNECT', path: 'www.google.com:80' }; @@ -415,7 +415,7 @@ event is emitted with a callback containing an object with a status code. const http = require('http'); const options = { - hostname: '127.0.0.1', + host: '127.0.0.1', port: 8080, path: '/length_request' }; @@ -502,7 +502,7 @@ srv.listen(1337, '127.0.0.1', () => { // make a request const options = { port: 1337, - hostname: '127.0.0.1', + host: '127.0.0.1', headers: { 'Connection': 'Upgrade', 'Upgrade': 'websocket' @@ -1894,6 +1894,16 @@ added: v0.5.9 Global instance of `Agent` which is used as the default for all HTTP client requests. +## http.maxHeaderSize + + +* {number} + +Read-only property specifying the maximum allowed size of HTTP headers in bytes. +Defaults to 8KB. Configurable using the [`--max-http-header-size`][] CLI option. + ## http.request(options[, callback]) ## http.request(url[, options][, callback]) -* `hostname` {string} The hostname to verify the certificate against +* `hostname` {string} The host name or IP address to verify the certificate + against. * `cert` {Object} An object representing the peer's certificate. The returned object has some properties corresponding to the fields of the certificate. * Returns: {Error|undefined} Verifies the certificate `cert` is issued to `hostname`. -Returns {Error} object, populating it with the reason, host, and cert on +Returns {Error} object, populating it with `reason`, `host`, and `cert` on failure. On success, returns {undefined}. This function can be overwritten by providing alternative function as part of @@ -891,7 +892,10 @@ changes: first byte is the length of the next protocol name. Passing an array is usually much simpler, e.g. `['hello', 'world']`. * `servername`: {string} Server name for the SNI (Server Name Indication) TLS - extension. It must be a host name, and not an IP address. + extension. It is the name of the host being connected to, and must be a host + name, and not an IP address. It can be used by a multi-homed server to + choose the correct certificate to present to the client, see the + `SNICallback` option to [`tls.createServer()`][]. * `checkServerIdentity(servername, cert)` {Function} A callback function to be used (instead of the builtin `tls.checkServerIdentity()` function) when checking the server's hostname (or the provided `servername` when diff --git a/doc/api/tty.md b/doc/api/tty.md index 2b205481560392..26761442a50865 100644 --- a/doc/api/tty.md +++ b/doc/api/tty.md @@ -214,6 +214,6 @@ a TTY and `false` if it is not, including whenever `fd` is not a non-negative integer. [`net.Socket`]: net.html#net_class_net_socket +[`process.stderr`]: process.html#process_process_stderr [`process.stdin`]: process.html#process_process_stdin [`process.stdout`]: process.html#process_process_stdout -[`process.stderr`]: process.html#process_process_stderr diff --git a/doc/api/util.md b/doc/api/util.md index 250f6ceebf0e13..8be463bdf86cbe 100644 --- a/doc/api/util.md +++ b/doc/api/util.md @@ -2141,20 +2141,17 @@ Deprecated predecessor of `console.log`. [`'uncaughtException'`]: process.html#process_event_uncaughtexception [`'warning'`]: process.html#process_event_warning [`Array.isArray()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray -[`ArrayBuffer`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer [`ArrayBuffer.isView()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer/isView -[`assert.deepStrictEqual()`]: assert.html#assert_assert_deepstrictequal_actual_expected_message +[`ArrayBuffer`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer [`Buffer.isBuffer()`]: buffer.html#buffer_class_method_buffer_isbuffer_obj -[`console.error()`]: console.html#console_console_error_data_args -[`console.log()`]: console.html#console_console_log_data_args [`DataView`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView [`Date`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date [`Error`]: errors.html#errors_class_error [`Float32Array`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float32Array [`Float64Array`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float64Array -[`Int8Array`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int8Array [`Int16Array`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int16Array [`Int32Array`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int32Array +[`Int8Array`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int8Array [`Map`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map [`Object.assign()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign [`Promise`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise @@ -2162,6 +2159,16 @@ Deprecated predecessor of `console.log`. [`Set`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set [`SharedArrayBuffer`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer [`TypedArray`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray +[`Uint16Array`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint16Array +[`Uint32Array`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint32Array +[`Uint8Array`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array +[`Uint8ClampedArray`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8ClampedArray +[`WeakMap`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap +[`WeakSet`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet +[`WebAssembly.Module`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module +[`assert.deepStrictEqual()`]: assert.html#assert_assert_deepstrictequal_actual_expected_message +[`console.error()`]: console.html#console_console_error_data_args +[`console.log()`]: console.html#console_console_log_data_args [`util.format()`]: #util_util_format_format_args [`util.inspect()`]: #util_util_inspect_object_options [`util.promisify()`]: #util_util_promisify_original @@ -2170,20 +2177,13 @@ Deprecated predecessor of `console.log`. [`util.types.isDate()`]: #util_util_types_isdate_value [`util.types.isNativeError()`]: #util_util_types_isnativeerror_value [`util.types.isSharedArrayBuffer()`]: #util_util_types_issharedarraybuffer_value -[`Uint8Array`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array -[`Uint8ClampedArray`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8ClampedArray -[`Uint16Array`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint16Array -[`Uint32Array`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint32Array -[`WeakMap`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap -[`WeakSet`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet -[`WebAssembly.Module`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module +[Common System Errors]: errors.html#errors_common_system_errors [Custom inspection functions on Objects]: #util_custom_inspection_functions_on_objects [Custom promisified functions]: #util_custom_promisified_functions [Customizing `util.inspect` colors]: #util_customizing_util_inspect_colors [Internationalization]: intl.html [Module Namespace Object]: https://tc39.github.io/ecma262/#sec-module-namespace-exotic-objects [WHATWG Encoding Standard]: https://encoding.spec.whatwg.org/ -[Common System Errors]: errors.html#errors_common_system_errors [async function]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function [compare function]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#Parameters [constructor]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor diff --git a/doc/api/v8.md b/doc/api/v8.md index 4a04e89319927d..e16e8645090713 100644 --- a/doc/api/v8.md +++ b/doc/api/v8.md @@ -404,6 +404,7 @@ A subclass of [`Deserializer`][] corresponding to the format written by [`DefaultSerializer`]: #v8_class_v8_defaultserializer [`Deserializer`]: #v8_class_v8_deserializer [`Error`]: errors.html#errors_class_error +[`GetHeapSpaceStatistics`]: https://v8docs.nodesource.com/node-10.6/d5/dda/classv8_1_1_isolate.html#ac673576f24fdc7a33378f8f57e1d13a4 [`Serializer`]: #v8_class_v8_serializer [`deserializer._readHostObject()`]: #v8_deserializer_readhostobject [`deserializer.transferArrayBuffer()`]: #v8_deserializer_transferarraybuffer_id_arraybuffer @@ -413,8 +414,7 @@ A subclass of [`Deserializer`][] corresponding to the format written by [`serializer.releaseBuffer()`]: #v8_serializer_releasebuffer [`serializer.transferArrayBuffer()`]: #v8_serializer_transferarraybuffer_id_arraybuffer [`serializer.writeRawBytes()`]: #v8_serializer_writerawbytes_buffer +[`vm.Script`]: vm.html#vm_new_vm_script_code_options [HTML structured clone algorithm]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm [V8]: https://developers.google.com/v8/ -[`vm.Script`]: vm.html#vm_new_vm_script_code_options [here]: https://github.com/thlorenz/v8-flags/blob/master/flags-0.11.md -[`GetHeapSpaceStatistics`]: https://v8docs.nodesource.com/node-10.6/d5/dda/classv8_1_1_isolate.html#ac673576f24fdc7a33378f8f57e1d13a4 diff --git a/doc/api/vm.md b/doc/api/vm.md index 892f7b97c39a30..d023d9c216903a 100644 --- a/doc/api/vm.md +++ b/doc/api/vm.md @@ -944,6 +944,38 @@ within which it can operate. The process of creating the V8 Context and associating it with the `sandbox` object is what this document refers to as "contextifying" the `sandbox`. +## Timeout limitations when using process.nextTick(), and Promises + +Because of the internal mechanics of how the `process.nextTick()` queue and +the microtask queue that underlies Promises are implemented within V8 and +Node.js, it is possible for code running within a context to "escape" the +`timeout` set using `vm.runInContext()`, `vm.runInNewContext()`, and +`vm.runInThisContext()`. + +For example, the following code executed by `vm.runInNewContext()` with a +timeout of 5 milliseconds schedules an infinite loop to run after a promise +resolves. The scheduled loop is never interrupted by the timeout: + +```js +const vm = require('vm'); + +function loop() { + while (1) console.log(Date.now()); +} + +vm.runInNewContext( + 'Promise.resolve().then(loop);', + { loop, console }, + { timeout: 5 } +); +``` + +This issue also occurs when the `loop()` call is scheduled using +the `process.nextTick()` function. + +This issue occurs because all contexts share the same microtask and nextTick +queues. + [`Error`]: errors.html#errors_class_error [`URL`]: url.html#url_class_url [`eval()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval @@ -953,9 +985,9 @@ associating it with the `sandbox` object is what this document refers to as [`vm.createContext()`]: #vm_vm_createcontext_sandbox_options [`vm.runInContext()`]: #vm_vm_runincontext_code_contextifiedsandbox_options [`vm.runInThisContext()`]: #vm_vm_runinthiscontext_code_options -[GetModuleNamespace]: https://tc39.github.io/ecma262/#sec-getmodulenamespace [ECMAScript Module Loader]: esm.html#esm_ecmascript_modules [Evaluate() concrete method]: https://tc39.github.io/ecma262/#sec-moduleevaluation +[GetModuleNamespace]: https://tc39.github.io/ecma262/#sec-getmodulenamespace [HostResolveImportedModule]: https://tc39.github.io/ecma262/#sec-hostresolveimportedmodule [Instantiate() concrete method]: https://tc39.github.io/ecma262/#sec-moduledeclarationinstantiation [Source Text Module Record]: https://tc39.github.io/ecma262/#sec-source-text-module-records diff --git a/doc/api/worker_threads.md b/doc/api/worker_threads.md index b73787174cdc96..86b66fec90f9b4 100644 --- a/doc/api/worker_threads.md +++ b/doc/api/worker_threads.md @@ -462,34 +462,34 @@ active handle in the event system. If the worker is already `unref()`ed calling [`Buffer`]: buffer.html [`EventEmitter`]: events.html [`MessagePort`]: #worker_threads_class_messageport -[`port.postMessage()`]: #worker_threads_port_postmessage_value_transferlist +[`SharedArrayBuffer`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer +[`Uint8Array`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array [`Worker`]: #worker_threads_class_worker -[`worker.terminate()`]: #worker_threads_worker_terminate_callback -[`worker.postMessage()`]: #worker_threads_worker_postmessage_value_transferlist -[`worker.on('message')`]: #worker_threads_event_message_1 -[`worker.threadId`]: #worker_threads_worker_threadid_1 +[`cluster` module]: cluster.html +[`inspector`]: inspector.html [`port.on('message')`]: #worker_threads_event_message -[`process.exit()`]: process.html#process_process_exit_code +[`port.postMessage()`]: #worker_threads_port_postmessage_value_transferlist [`process.abort()`]: process.html#process_process_abort [`process.chdir()`]: process.html#process_process_chdir_directory [`process.env`]: process.html#process_process_env -[`process.stdin`]: process.html#process_process_stdin +[`process.exit()`]: process.html#process_process_exit_code [`process.stderr`]: process.html#process_process_stderr +[`process.stdin`]: process.html#process_process_stdin [`process.stdout`]: process.html#process_process_stdout [`process.title`]: process.html#process_process_title -[`require('worker_threads').workerData`]: #worker_threads_worker_workerdata -[`require('worker_threads').parentPort.on('message')`]: #worker_threads_event_message -[`require('worker_threads').postMessage()`]: #worker_threads_worker_postmessage_value_transferlist [`require('worker_threads').isMainThread`]: #worker_threads_worker_ismainthread +[`require('worker_threads').parentPort.on('message')`]: #worker_threads_event_message [`require('worker_threads').parentPort`]: #worker_threads_worker_parentport +[`require('worker_threads').postMessage()`]: #worker_threads_worker_postmessage_value_transferlist [`require('worker_threads').threadId`]: #worker_threads_worker_threadid -[`cluster` module]: cluster.html -[`inspector`]: inspector.html -[v8.serdes]: v8.html#v8_serialization_api -[`SharedArrayBuffer`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer +[`require('worker_threads').workerData`]: #worker_threads_worker_workerdata +[`worker.on('message')`]: #worker_threads_event_message_1 +[`worker.postMessage()`]: #worker_threads_worker_postmessage_value_transferlist +[`worker.terminate()`]: #worker_threads_worker_terminate_callback +[`worker.threadId`]: #worker_threads_worker_threadid_1 +[HTML structured clone algorithm]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm [Signals events]: process.html#process_signal_events -[`Uint8Array`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array +[Web Workers]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API [browser `MessagePort`]: https://developer.mozilla.org/en-US/docs/Web/API/MessagePort [child processes]: child_process.html -[HTML structured clone algorithm]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm -[Web Workers]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API +[v8.serdes]: v8.html#v8_serialization_api diff --git a/doc/api/zlib.md b/doc/api/zlib.md index 8725c40354d3a7..7e5e7b65ff031c 100644 --- a/doc/api/zlib.md +++ b/doc/api/zlib.md @@ -835,12 +835,12 @@ Decompress a chunk of data with [`Unzip`][]. [`Buffer`]: buffer.html#buffer_class_buffer [`Content-Encoding`]: https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.11 [`DataView`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView -[`Deflate`]: #zlib_class_zlib_deflate [`DeflateRaw`]: #zlib_class_zlib_deflateraw +[`Deflate`]: #zlib_class_zlib_deflate [`Gunzip`]: #zlib_class_zlib_gunzip [`Gzip`]: #zlib_class_zlib_gzip -[`Inflate`]: #zlib_class_zlib_inflate [`InflateRaw`]: #zlib_class_zlib_inflateraw +[`Inflate`]: #zlib_class_zlib_inflate [`TypedArray`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray [`Unzip`]: #zlib_class_zlib_unzip [`stream.Transform`]: stream.html#stream_class_stream_transform diff --git a/doc/node.1 b/doc/node.1 index b8144f4ebb5f6c..3d2344822df261 100644 --- a/doc/node.1 +++ b/doc/node.1 @@ -133,6 +133,9 @@ Specify the as a custom loader, to load .Fl -experimental-modules . . +.It Fl -max-http-header-size Ns = Ns Ar size +Specify the maximum size of HTTP headers in bytes. Defaults to 8KB. +. .It Fl -napi-modules This option is a no-op. It is kept for compatibility. diff --git a/lib/_stream_writable.js b/lib/_stream_writable.js index 3bad957912b323..ed354126f7d812 100644 --- a/lib/_stream_writable.js +++ b/lib/_stream_writable.js @@ -456,7 +456,7 @@ function onwrite(stream, er) { onwriteError(stream, state, sync, er, cb); else { // Check if we're actually ready to finish, but don't emit yet - var finished = needFinish(state); + var finished = needFinish(state) || stream.destroyed; if (!finished && !state.corked && diff --git a/lib/crypto.js b/lib/crypto.js index f23f1f9ae749e6..9ab08ab4b2a568 100644 --- a/lib/crypto.js +++ b/lib/crypto.js @@ -34,7 +34,7 @@ const { ERR_CRYPTO_FIPS_FORCED, ERR_CRYPTO_FIPS_UNAVAILABLE } = require('internal/errors').codes; -const constants = process.binding('constants').crypto; +const constants = internalBinding('constants').crypto; const { fipsMode, fipsForced diff --git a/lib/http.js b/lib/http.js index 660de78650f45c..e3707ffa62b25d 100644 --- a/lib/http.js +++ b/lib/http.js @@ -32,6 +32,7 @@ const { Server, ServerResponse } = require('_http_server'); +let maxHeaderSize; function createServer(opts, requestListener) { return new Server(opts, requestListener); @@ -62,3 +63,16 @@ module.exports = { get, request }; + +Object.defineProperty(module.exports, 'maxHeaderSize', { + configurable: true, + enumerable: true, + get() { + if (maxHeaderSize === undefined) { + const { getOptionValue } = require('internal/options'); + maxHeaderSize = getOptionValue('--max-http-header-size'); + } + + return maxHeaderSize; + } +}); diff --git a/lib/internal/bash_completion.js b/lib/internal/bash_completion.js index cb8eab9ceec855..13363e8c4b8c32 100644 --- a/lib/internal/bash_completion.js +++ b/lib/internal/bash_completion.js @@ -1,8 +1,7 @@ 'use strict'; -const { getOptions } = internalBinding('options'); +const { options, aliases } = require('internal/options'); function print(stream) { - const { options, aliases } = getOptions(); const all_opts = [...options.keys(), ...aliases.keys()]; stream.write(`_node_complete() { diff --git a/lib/internal/bootstrap/loaders.js b/lib/internal/bootstrap/loaders.js index a90da4861b7b79..e2cfdbf83d38ef 100644 --- a/lib/internal/bootstrap/loaders.js +++ b/lib/internal/bootstrap/loaders.js @@ -217,8 +217,7 @@ NativeModule.isInternal = function(id) { return id.startsWith('internal/') || - (id === 'worker_threads' && - !internalBinding('options').getOptions('--experimental-worker')); + (id === 'worker_threads' && !config.experimentalWorker); }; } diff --git a/lib/internal/bootstrap/node.js b/lib/internal/bootstrap/node.js index 067998f115ccc9..0ac0559000732b 100644 --- a/lib/internal/bootstrap/node.js +++ b/lib/internal/bootstrap/node.js @@ -113,12 +113,13 @@ NativeModule.require('internal/inspector_async_hook').setup(); } - const { getOptions } = internalBinding('options'); - const helpOption = getOptions('--help'); - const completionBashOption = getOptions('--completion-bash'); - const experimentalModulesOption = getOptions('--experimental-modules'); - const experimentalVMModulesOption = getOptions('--experimental-vm-modules'); - const experimentalWorkerOption = getOptions('--experimental-worker'); + const { getOptionValue } = NativeModule.require('internal/options'); + const helpOption = getOptionValue('--help'); + const completionBashOption = getOptionValue('--completion-bash'); + const experimentalModulesOption = getOptionValue('--experimental-modules'); + const experimentalVMModulesOption = + getOptionValue('--experimental-vm-modules'); + const experimentalWorkerOption = getOptionValue('--experimental-worker'); if (helpOption) { NativeModule.require('internal/print_help').print(process.stdout); return; @@ -631,10 +632,9 @@ const get = () => { const { - getOptions, envSettings: { kAllowedInEnvironment } } = internalBinding('options'); - const { options, aliases } = getOptions(); + const { options, aliases } = NativeModule.require('internal/options'); const allowedNodeEnvironmentFlags = []; for (const [name, info] of options) { diff --git a/lib/internal/buffer.js b/lib/internal/buffer.js index 3a944a13de3031..42f4dc3fdc07a4 100644 --- a/lib/internal/buffer.js +++ b/lib/internal/buffer.js @@ -658,7 +658,7 @@ function writeU_Int16BE(buf, value, offset, min, max) { } function writeUInt16BE(value, offset = 0) { - return writeU_Int16BE(this, value, offset, 0, 0xffffffff); + return writeU_Int16BE(this, value, offset, 0, 0xffff); } function writeIntLE(value, offset = 0, byteLength) { diff --git a/lib/internal/child_process.js b/lib/internal/child_process.js index 0a1dc40f8aaf77..63038bcc54750f 100644 --- a/lib/internal/child_process.js +++ b/lib/internal/child_process.js @@ -31,9 +31,7 @@ const SocketList = require('internal/socket_list'); const { owner_symbol } = require('internal/async_hooks').symbols; const { convertToValidSignal } = require('internal/util'); const { isArrayBufferView } = require('internal/util/types'); -const spawn_sync = process.binding('spawn_sync'); -const { HTTPParser } = process.binding('http_parser'); -const { freeParser } = require('_http_common'); +const spawn_sync = internalBinding('spawn_sync'); const { kStateSymbol } = require('internal/dgram'); const { @@ -51,6 +49,10 @@ const { SocketListSend, SocketListReceive } = SocketList; // Lazy loaded for startup performance. let StringDecoder; +// Lazy loaded for startup performance and to allow monkey patching of +// internalBinding('http_parser').HTTPParser. +let freeParser; +let HTTPParser; const MAX_HANDLE_RETRANSMISSIONS = 3; @@ -115,6 +117,12 @@ const handleConversion = { handle.onread = nop; socket._handle = null; socket.setTimeout(0); + + if (freeParser === undefined) + freeParser = require('_http_common').freeParser; + if (HTTPParser === undefined) + HTTPParser = internalBinding('http_parser').HTTPParser; + // In case of an HTTP connection socket, release the associated // resources if (socket.parser && socket.parser instanceof HTTPParser) { diff --git a/lib/internal/encoding.js b/lib/internal/encoding.js index 161ae72a19eaef..c0083948e0d72d 100644 --- a/lib/internal/encoding.js +++ b/lib/internal/encoding.js @@ -341,22 +341,16 @@ Object.defineProperties( value: 'TextEncoder' } }); -const { hasConverter, TextDecoder } = +const TextDecoder = process.binding('config').hasIntl ? makeTextDecoderICU() : makeTextDecoderJS(); -function hasTextDecoder(encoding = 'utf-8') { - validateArgument(encoding, 'string', 'encoding', 'string'); - return hasConverter(getEncodingFromLabel(encoding)); -} - function makeTextDecoderICU() { const { decode: _decode, getConverter, - hasConverter - } = process.binding('icu'); + } = internalBinding('icu'); class TextDecoder { constructor(encoding = 'utf-8', options = {}) { @@ -409,7 +403,7 @@ function makeTextDecoderICU() { } } - return { hasConverter, TextDecoder }; + return TextDecoder; } function makeTextDecoderJS() { @@ -497,7 +491,7 @@ function makeTextDecoderJS() { } } - return { hasConverter, TextDecoder }; + return TextDecoder; } // Mix in some shared properties. @@ -552,7 +546,6 @@ function makeTextDecoderJS() { module.exports = { getEncodingFromLabel, - hasTextDecoder, TextDecoder, TextEncoder }; diff --git a/lib/internal/errors.js b/lib/internal/errors.js index 9f5e6d696c3043..9ec369ce0a12b8 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -834,10 +834,11 @@ 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', - (name, range, value) => { - let msg = `The value of "${name}" is out of range.`; + (str, range, input, replaceDefaultBoolean = false) => { + let msg = replaceDefaultBoolean ? str : + `The value of "${str}" is out of range.`; if (range !== undefined) msg += ` It must be ${range}.`; - msg += ` Received ${value}`; + msg += ` Received ${input}`; return msg; }, RangeError); E('ERR_REQUIRE_ESM', 'Must use import to load ES Module: %s', Error); diff --git a/lib/internal/modules/cjs/helpers.js b/lib/internal/modules/cjs/helpers.js index cda94987fad210..b08e97b29c5c8d 100644 --- a/lib/internal/modules/cjs/helpers.js +++ b/lib/internal/modules/cjs/helpers.js @@ -9,7 +9,7 @@ const { CHAR_HASH, } = require('internal/constants'); -const { getOptions } = internalBinding('options'); +const { getOptionValue } = require('internal/options'); // Invoke with makeRequireFunction(module) where |module| is the Module object // to use as the context for the require() function. @@ -107,7 +107,7 @@ const builtinLibs = [ 'v8', 'vm', 'zlib' ]; -if (getOptions('--experimental-worker')) { +if (getOptionValue('--experimental-worker')) { builtinLibs.push('worker_threads'); builtinLibs.sort(); } diff --git a/lib/internal/modules/cjs/loader.js b/lib/internal/modules/cjs/loader.js index 4e48d549377081..fb3770b7299d4e 100644 --- a/lib/internal/modules/cjs/loader.js +++ b/lib/internal/modules/cjs/loader.js @@ -40,10 +40,10 @@ const { stripBOM, stripShebang } = require('internal/modules/cjs/helpers'); -const options = internalBinding('options'); -const preserveSymlinks = options.getOptions('--preserve-symlinks'); -const preserveSymlinksMain = options.getOptions('--preserve-symlinks-main'); -const experimentalModules = options.getOptions('--experimental-modules'); +const { getOptionValue } = require('internal/options'); +const preserveSymlinks = getOptionValue('--preserve-symlinks'); +const preserveSymlinksMain = getOptionValue('--preserve-symlinks-main'); +const experimentalModules = getOptionValue('--experimental-modules'); const { ERR_INVALID_ARG_TYPE, diff --git a/lib/internal/modules/esm/default_resolve.js b/lib/internal/modules/esm/default_resolve.js index 7654ca91129325..9aa54d09a1b07c 100644 --- a/lib/internal/modules/esm/default_resolve.js +++ b/lib/internal/modules/esm/default_resolve.js @@ -6,9 +6,9 @@ const internalFS = require('internal/fs/utils'); const { NativeModule } = require('internal/bootstrap/loaders'); const { extname } = require('path'); const { realpathSync } = require('fs'); -const { getOptions } = internalBinding('options'); -const preserveSymlinks = getOptions('--preserve-symlinks'); -const preserveSymlinksMain = getOptions('--preserve-symlinks-main'); +const { getOptionValue } = require('internal/options'); +const preserveSymlinks = getOptionValue('--preserve-symlinks'); +const preserveSymlinksMain = getOptionValue('--preserve-symlinks-main'); const { ERR_MISSING_MODULE, ERR_MODULE_RESOLUTION_LEGACY, diff --git a/lib/internal/options.js b/lib/internal/options.js new file mode 100644 index 00000000000000..e494787b96c088 --- /dev/null +++ b/lib/internal/options.js @@ -0,0 +1,18 @@ +'use strict'; + +const { getOptions } = internalBinding('options'); +const { options, aliases } = getOptions(); + +function getOptionValue(option) { + const result = options.get(option); + if (!result) { + return undefined; + } + return result.value; +} + +module.exports = { + options, + aliases, + getOptionValue +}; diff --git a/lib/internal/print_help.js b/lib/internal/print_help.js index 8acc9271b19188..c453562c5c40bf 100644 --- a/lib/internal/print_help.js +++ b/lib/internal/print_help.js @@ -1,5 +1,6 @@ 'use strict'; -const { getOptions, types } = internalBinding('options'); + +const { types } = internalBinding('options'); const typeLookup = []; for (const key of Object.keys(types)) @@ -58,6 +59,7 @@ function getArgDescription(type) { case 'kHostPort': return '[host:]port'; case 'kInteger': + case 'kUInteger': case 'kString': case 'kStringList': return '...'; @@ -132,7 +134,7 @@ function format({ options, aliases = new Map(), firstColumn, secondColumn }) { } function print(stream) { - const { options, aliases } = getOptions(); + const { options, aliases } = require('internal/options'); // Use 75 % of the available width, and at least 70 characters. const width = Math.max(70, (stream.columns || 0) * 0.75); diff --git a/lib/internal/process/esm_loader.js b/lib/internal/process/esm_loader.js index d775e685d13ea7..be08a6364781ed 100644 --- a/lib/internal/process/esm_loader.js +++ b/lib/internal/process/esm_loader.js @@ -48,7 +48,7 @@ exports.setup = function() { let ESMLoader = new Loader(); const loaderPromise = (async () => { - const userLoader = internalBinding('options').getOptions('--loader'); + const userLoader = require('internal/options').getOptionValue('--loader'); if (userLoader) { const hooks = await ESMLoader.import( userLoader, pathToFileURL(`${process.cwd()}/`).href); diff --git a/lib/internal/url.js b/lib/internal/url.js index 2bad698883631e..a3b1bedaca51ef 100644 --- a/lib/internal/url.js +++ b/lib/internal/url.js @@ -245,7 +245,14 @@ function onParseError(flags, input) { // Reused by URL constructor and URL#href setter. function parse(url, input, base) { const base_context = base ? base[context] : undefined; - url[context] = new URLContext(); + // In the URL#href setter + if (!url[context]) { + Object.defineProperty(url, context, { + enumerable: false, + configurable: false, + value: new URLContext() + }); + } _parse(input.trim(), -1, base_context, undefined, onParseComplete.bind(url), onParseError); } @@ -1437,7 +1444,11 @@ function toPathIfFileURL(fileURLOrPath) { } function NativeURL(ctx) { - this[context] = ctx; + Object.defineProperty(this, context, { + enumerable: false, + configurable: false, + value: ctx + }); } NativeURL.prototype = URL.prototype; diff --git a/lib/internal/util/inspect.js b/lib/internal/util/inspect.js index 6cec84355211d4..094240c694ea53 100644 --- a/lib/internal/util/inspect.js +++ b/lib/internal/util/inspect.js @@ -362,6 +362,10 @@ function getKeys(value, showHidden) { return keys; } +function getCtxStyle(constructor, tag) { + return constructor || tag || 'Object'; +} + function formatProxy(ctx, proxy, recurseTimes) { if (recurseTimes != null) { if (recurseTimes < 0) @@ -708,7 +712,7 @@ function formatRaw(ctx, value, recurseTimes) { if (recurseTimes != null) { if (recurseTimes < 0) - return ctx.stylize(`[${constructor || tag || 'Object'}]`, 'special'); + return ctx.stylize(`[${getCtxStyle(constructor, tag)}]`, 'special'); recurseTimes -= 1; } @@ -746,7 +750,7 @@ function handleMaxCallStackSize(ctx, err, constructor, tag, indentationLvl) { ctx.seen.pop(); ctx.indentationLvl = indentationLvl; return ctx.stylize( - `[${constructor || tag || 'Object'}: Inspection interrupted ` + + `[${getCtxStyle(constructor, tag)}: Inspection interrupted ` + 'prematurely. Maximum call stack size exceeded.]', 'special' ); diff --git a/lib/net.js b/lib/net.js index 48a8bc069901e2..35bfd33eaaf473 100644 --- a/lib/net.js +++ b/lib/net.js @@ -335,14 +335,6 @@ Socket.prototype._unrefTimer = function _unrefTimer() { }; -function shutdownSocket(self, callback) { - var req = new ShutdownWrap(); - req.oncomplete = afterShutdown; - req.handle = self._handle; - req.callback = callback; - return self._handle.shutdown(req); -} - // the user has called .end(), and all the bytes have been // sent out to the other side. Socket.prototype._final = function(cb) { @@ -352,23 +344,22 @@ Socket.prototype._final = function(cb) { return this.once('connect', () => this._final(cb)); } + // TODO(addaleax): This should not be necessary. if (!this.readable || this._readableState.ended) { - debug('_final: ended, destroy', this._readableState); cb(); return this.destroy(); } - debug('_final: not ended, call shutdown()'); + if (!this._handle) + return cb(); - // otherwise, just shutdown, or destroy() if not possible - if (!this._handle || !this._handle.shutdown) { - cb(); - return this.destroy(); - } + debug('_final: not ended, call shutdown()'); - var err = defaultTriggerAsyncIdScope( - this[async_id_symbol], shutdownSocket, this, cb - ); + var req = new ShutdownWrap(); + req.oncomplete = afterShutdown; + req.handle = this._handle; + req.callback = cb; + var err = this._handle.shutdown(req); if (err) return this.destroy(errnoException(err, 'shutdown')); @@ -387,7 +378,7 @@ function afterShutdown(status, handle) { if (self.destroyed) return; - if (self._readableState.ended) { + if (!self.readable || self._readableState.ended) { debug('readableState ended, destroying'); self.destroy(); } diff --git a/lib/repl.js b/lib/repl.js index b00bca41cbda8c..448308a44c007a 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -71,7 +71,7 @@ const { ERR_SCRIPT_EXECUTION_INTERRUPTED } = require('internal/errors').codes; const { sendInspectorCommand } = require('internal/util/inspector'); -const experimentalREPLAwait = internalBinding('options').getOptions( +const experimentalREPLAwait = require('internal/options').getOptionValue( '--experimental-repl-await' ); const { isRecoverableError } = require('internal/repl/recoverable'); diff --git a/lib/tls.js b/lib/tls.js index 0324f6db877d48..b8de6efc8e402d 100644 --- a/lib/tls.js +++ b/lib/tls.js @@ -21,7 +21,10 @@ 'use strict'; -const { ERR_TLS_CERT_ALTNAME_INVALID } = require('internal/errors').codes; +const { + ERR_TLS_CERT_ALTNAME_INVALID, + ERR_OUT_OF_RANGE +} = require('internal/errors').codes; const internalUtil = require('internal/util'); const internalTLS = require('internal/tls'); internalUtil.assertCrypto(); @@ -59,6 +62,10 @@ function convertProtocols(protocols) { const lens = new Array(protocols.length); const buff = Buffer.allocUnsafe(protocols.reduce((p, c, i) => { var len = Buffer.byteLength(c); + if (len > 255) { + throw new ERR_OUT_OF_RANGE('The byte length of the protocol at index ' + + `${i} exceeds the maximum length.`, '<= 255', len, true); + } lens[i] = len; return p + 1 + len; }, 0)); diff --git a/lib/vm.js b/lib/vm.js index 720d46ea1abdcd..dbe48b7b15c194 100644 --- a/lib/vm.js +++ b/lib/vm.js @@ -402,7 +402,7 @@ module.exports = { compileFunction, }; -if (internalBinding('options').getOptions('--experimental-vm-modules')) { +if (require('internal/options').getOptionValue('--experimental-vm-modules')) { const { SourceTextModule } = require('internal/vm/source_text_module'); module.exports.SourceTextModule = SourceTextModule; } diff --git a/lib/zlib.js b/lib/zlib.js index 97b12410f121ef..9336b52f85313b 100644 --- a/lib/zlib.js +++ b/lib/zlib.js @@ -427,6 +427,11 @@ Zlib.prototype.close = function close(callback) { this.destroy(); }; +Zlib.prototype._destroy = function _destroy(err, callback) { + _close(this); + callback(err); +}; + Zlib.prototype._transform = function _transform(chunk, encoding, cb) { var flushFlag = this._defaultFlushFlag; // We use a 'fake' zero-length chunk to carry information about flushes from @@ -589,6 +594,10 @@ function processCallback() { assert(false, 'have should not go down'); } + if (self.destroyed) { + return; + } + // exhausted the output buffer, or used all the input create a new one. if (availOutAfter === 0 || self._outOffset >= self._chunkSize) { handle.availOutBefore = self._chunkSize; diff --git a/node.gyp b/node.gyp index f59b071b1ebba6..a8de196916c085 100644 --- a/node.gyp +++ b/node.gyp @@ -134,6 +134,7 @@ 'lib/internal/modules/esm/translators.js', 'lib/internal/safe_globals.js', 'lib/internal/net.js', + 'lib/internal/options.js', 'lib/internal/print_help.js', 'lib/internal/process/esm_loader.js', 'lib/internal/process/main_thread_only.js', @@ -621,7 +622,8 @@ # Categories to export. '-CAES,BF,BIO,DES,DH,DSA,EC,ECDH,ECDSA,ENGINE,EVP,HMAC,MD4,MD5,' 'PSK,RC2,RC4,RSA,SHA,SHA0,SHA1,SHA256,SHA512,SOCK,STDIO,TLSEXT,' - 'FP_API,TLS1_METHOD,TLS1_1_METHOD,TLS1_2_METHOD,SCRYPT', + 'FP_API,TLS1_METHOD,TLS1_1_METHOD,TLS1_2_METHOD,SCRYPT,OCSP,' + 'NEXTPROTONEG,RMD160,CAST', # Defines. '-DWIN32', # Symbols to filter from the export list. diff --git a/src/cares_wrap.cc b/src/cares_wrap.cc index 8799f4a3cd0c37..ad5284c2ba4171 100644 --- a/src/cares_wrap.cc +++ b/src/cares_wrap.cc @@ -1061,118 +1061,117 @@ int ParseSoaReply(Environment* env, EscapableHandleScope handle_scope(env->isolate()); auto context = env->context(); - /* Can't use ares_parse_soa_reply() here which can only parse single record */ - unsigned int ancount = cares_get_16bit(buf + 6); + // Manage memory using standardard smart pointer std::unique_tr + struct AresDeleter { + void operator()(char* ptr) const noexcept { ares_free_string(ptr); } + }; + using ares_unique_ptr = std::unique_ptr; + + // Can't use ares_parse_soa_reply() here which can only parse single record + const unsigned int ancount = cares_get_16bit(buf + 6); unsigned char* ptr = buf + NS_HFIXEDSZ; - char* name; - char* rr_name; + char* name_temp; long temp_len; // NOLINT(runtime/int) - int status = ares_expand_name(ptr, buf, len, &name, &temp_len); + int status = ares_expand_name(ptr, buf, len, &name_temp, &temp_len); + const ares_unique_ptr name(name_temp); if (status != ARES_SUCCESS) { - /* returns EBADRESP in case of invalid input */ + // returns EBADRESP in case of invalid input return status == ARES_EBADNAME ? ARES_EBADRESP : status; } if (ptr + temp_len + NS_QFIXEDSZ > buf + len) { - free(name); return ARES_EBADRESP; } ptr += temp_len + NS_QFIXEDSZ; for (unsigned int i = 0; i < ancount; i++) { - status = ares_expand_name(ptr, buf, len, &rr_name, &temp_len); + char* rr_name_temp; + long rr_temp_len; // NOLINT(runtime/int) + int status2 = ares_expand_name(ptr, buf, len, &rr_name_temp, &rr_temp_len); + const ares_unique_ptr rr_name(rr_name_temp); - if (status != ARES_SUCCESS) - break; + if (status2 != ARES_SUCCESS) + return status2 == ARES_EBADNAME ? ARES_EBADRESP : status2; - ptr += temp_len; + ptr += rr_temp_len; if (ptr + NS_RRFIXEDSZ > buf + len) { - free(rr_name); - status = ARES_EBADRESP; - break; + return ARES_EBADRESP; } const int rr_type = cares_get_16bit(ptr); const int rr_len = cares_get_16bit(ptr + 8); ptr += NS_RRFIXEDSZ; - /* only need SOA */ + // only need SOA if (rr_type == ns_t_soa) { - ares_soa_reply soa; - - status = ares_expand_name(ptr, buf, len, &soa.nsname, &temp_len); - if (status != ARES_SUCCESS) { - free(rr_name); - break; + char* nsname_temp; + long nsname_temp_len; // NOLINT(runtime/int) + + int status3 = ares_expand_name(ptr, buf, len, + &nsname_temp, + &nsname_temp_len); + const ares_unique_ptr nsname(nsname_temp); + if (status3 != ARES_SUCCESS) { + return status3 == ARES_EBADNAME ? ARES_EBADRESP : status3; } - ptr += temp_len; - - status = ares_expand_name(ptr, buf, len, &soa.hostmaster, &temp_len); - if (status != ARES_SUCCESS) { - free(rr_name); - free(soa.nsname); - break; + ptr += nsname_temp_len; + + char* hostmaster_temp; + long hostmaster_temp_len; // NOLINT(runtime/int) + int status4 = ares_expand_name(ptr, buf, len, + &hostmaster_temp, + &hostmaster_temp_len); + const ares_unique_ptr hostmaster(hostmaster_temp); + if (status4 != ARES_SUCCESS) { + return status4 == ARES_EBADNAME ? ARES_EBADRESP : status4; } - ptr += temp_len; + ptr += hostmaster_temp_len; if (ptr + 5 * 4 > buf + len) { - free(rr_name); - free(soa.nsname); - free(soa.hostmaster); - status = ARES_EBADRESP; - break; + return ARES_EBADRESP; } - soa.serial = cares_get_32bit(ptr + 0 * 4); - soa.refresh = cares_get_32bit(ptr + 1 * 4); - soa.retry = cares_get_32bit(ptr + 2 * 4); - soa.expire = cares_get_32bit(ptr + 3 * 4); - soa.minttl = cares_get_32bit(ptr + 4 * 4); + const unsigned int serial = cares_get_32bit(ptr + 0 * 4); + const unsigned int refresh = cares_get_32bit(ptr + 1 * 4); + const unsigned int retry = cares_get_32bit(ptr + 2 * 4); + const unsigned int expire = cares_get_32bit(ptr + 3 * 4); + const unsigned int minttl = cares_get_32bit(ptr + 4 * 4); Local soa_record = Object::New(env->isolate()); soa_record->Set(context, env->nsname_string(), - OneByteString(env->isolate(), soa.nsname)).FromJust(); + OneByteString(env->isolate(), nsname.get())).FromJust(); soa_record->Set(context, env->hostmaster_string(), OneByteString(env->isolate(), - soa.hostmaster)).FromJust(); + hostmaster.get())).FromJust(); soa_record->Set(context, env->serial_string(), - Integer::New(env->isolate(), soa.serial)).FromJust(); + Integer::New(env->isolate(), serial)).FromJust(); soa_record->Set(context, env->refresh_string(), - Integer::New(env->isolate(), soa.refresh)).FromJust(); + Integer::New(env->isolate(), refresh)).FromJust(); soa_record->Set(context, env->retry_string(), - Integer::New(env->isolate(), soa.retry)).FromJust(); + Integer::New(env->isolate(), retry)).FromJust(); soa_record->Set(context, env->expire_string(), - Integer::New(env->isolate(), soa.expire)).FromJust(); + Integer::New(env->isolate(), expire)).FromJust(); soa_record->Set(context, env->minttl_string(), - Integer::New(env->isolate(), soa.minttl)).FromJust(); + Integer::New(env->isolate(), minttl)).FromJust(); soa_record->Set(context, env->type_string(), env->dns_soa_string()).FromJust(); - free(soa.nsname); - free(soa.hostmaster); *ret = handle_scope.Escape(soa_record); break; } - free(rr_name); ptr += rr_len; } - free(name); - - if (status != ARES_SUCCESS) { - return status == ARES_EBADNAME ? ARES_EBADRESP : status; - } - return ARES_SUCCESS; } diff --git a/src/env-inl.h b/src/env-inl.h index 208cc5381c9008..b512412c0ff4f0 100644 --- a/src/env-inl.h +++ b/src/env-inl.h @@ -186,20 +186,20 @@ inline void Environment::AsyncHooks::clear_async_id_stack() { inline Environment::AsyncHooks::DefaultTriggerAsyncIdScope ::DefaultTriggerAsyncIdScope(Environment* env, double default_trigger_async_id) - : async_id_fields_ref_(env->async_hooks()->async_id_fields()) { + : async_hooks_(env->async_hooks()) { if (env->async_hooks()->fields()[AsyncHooks::kCheck] > 0) { CHECK_GE(default_trigger_async_id, 0); } old_default_trigger_async_id_ = - async_id_fields_ref_[AsyncHooks::kDefaultTriggerAsyncId]; - async_id_fields_ref_[AsyncHooks::kDefaultTriggerAsyncId] = + async_hooks_->async_id_fields()[AsyncHooks::kDefaultTriggerAsyncId]; + async_hooks_->async_id_fields()[AsyncHooks::kDefaultTriggerAsyncId] = default_trigger_async_id; } inline Environment::AsyncHooks::DefaultTriggerAsyncIdScope ::~DefaultTriggerAsyncIdScope() { - async_id_fields_ref_[AsyncHooks::kDefaultTriggerAsyncId] = + async_hooks_->async_id_fields()[AsyncHooks::kDefaultTriggerAsyncId] = old_default_trigger_async_id_; } diff --git a/src/env.h b/src/env.h index 80fc750f0b555a..1d2baf58b007ea 100644 --- a/src/env.h +++ b/src/env.h @@ -482,7 +482,7 @@ class Environment { ~DefaultTriggerAsyncIdScope(); private: - AliasedBuffer async_id_fields_ref_; + AsyncHooks* async_hooks_; double old_default_trigger_async_id_; DISALLOW_COPY_AND_ASSIGN(DefaultTriggerAsyncIdScope); diff --git a/src/inspector_agent.cc b/src/inspector_agent.cc index ebb7b7d5bc3e72..48a3e2e2be6e51 100644 --- a/src/inspector_agent.cc +++ b/src/inspector_agent.cc @@ -474,11 +474,9 @@ class NodeInspectorClient : public V8InspectorClient { bool prevent_shutdown) { events_dispatched_ = true; int session_id = next_session_id_++; - // TODO(addaleax): Revert back to using make_unique once we get issues - // with CI resolved (i.e. revert the patch that added this comment). - channels_[session_id].reset( - new ChannelImpl(env_, client_, getWorkerManager(), - std::move(delegate), prevent_shutdown)); + channels_[session_id] = + std::make_unique(env_, client_, getWorkerManager(), + std::move(delegate), prevent_shutdown); return session_id; } diff --git a/src/node_crypto.cc b/src/node_crypto.cc index 8e65bd3c44b071..1027f5f760a56a 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -43,6 +43,7 @@ #include #include +#include #include static const int X509_NAME_FLAGS = ASN1_STRFLGS_ESC_CTRL @@ -3530,46 +3531,51 @@ void Sign::SignUpdate(const FunctionCallbackInfo& args) { sign->CheckThrow(err); } -static int Node_SignFinal(EVPMDPointer&& mdctx, unsigned char* md, - unsigned int* sig_len, - const EVPKeyPointer& pkey, int padding, - int pss_salt_len) { +static MallocedBuffer Node_SignFinal(EVPMDPointer&& mdctx, + const EVPKeyPointer& pkey, + int padding, + int pss_salt_len) { unsigned char m[EVP_MAX_MD_SIZE]; unsigned int m_len; - *sig_len = 0; if (!EVP_DigestFinal_ex(mdctx.get(), m, &m_len)) - return 0; + return MallocedBuffer(); + + int signed_sig_len = EVP_PKEY_size(pkey.get()); + CHECK_GE(signed_sig_len, 0); + size_t sig_len = static_cast(signed_sig_len); + MallocedBuffer sig(sig_len); - size_t sltmp = static_cast(EVP_PKEY_size(pkey.get())); EVPKeyCtxPointer pkctx(EVP_PKEY_CTX_new(pkey.get(), nullptr)); if (pkctx && EVP_PKEY_sign_init(pkctx.get()) > 0 && ApplyRSAOptions(pkey, pkctx.get(), padding, pss_salt_len) && EVP_PKEY_CTX_set_signature_md(pkctx.get(), EVP_MD_CTX_md(mdctx.get())) > 0 && - EVP_PKEY_sign(pkctx.get(), md, &sltmp, m, m_len) > 0) { - *sig_len = sltmp; - return 1; + EVP_PKEY_sign(pkctx.get(), sig.data, &sig_len, m, m_len) > 0) { + sig.Truncate(sig_len); + return sig; } - return 0; + + return MallocedBuffer(); } -SignBase::Error Sign::SignFinal(const char* key_pem, - int key_pem_len, - const char* passphrase, - unsigned char* sig, - unsigned int* sig_len, - int padding, - int salt_len) { +std::pair> Sign::SignFinal( + const char* key_pem, + int key_pem_len, + const char* passphrase, + int padding, + int salt_len) { + MallocedBuffer buffer; + if (!mdctx_) - return kSignNotInitialised; + return std::make_pair(kSignNotInitialised, std::move(buffer)); EVPMDPointer mdctx = std::move(mdctx_); BIOPointer bp(BIO_new_mem_buf(const_cast(key_pem), key_pem_len)); if (!bp) - return kSignPrivateKey; + return std::make_pair(kSignPrivateKey, std::move(buffer)); EVPKeyPointer pkey(PEM_read_bio_PrivateKey(bp.get(), nullptr, @@ -3580,7 +3586,7 @@ SignBase::Error Sign::SignFinal(const char* key_pem, // without `pkey` being set to nullptr; // cf. the test of `test_bad_rsa_privkey.pem` for an example. if (!pkey || 0 != ERR_peek_error()) - return kSignPrivateKey; + return std::make_pair(kSignPrivateKey, std::move(buffer)); #ifdef NODE_FIPS_MODE /* Validate DSA2 parameters from FIPS 186-4 */ @@ -3604,10 +3610,9 @@ SignBase::Error Sign::SignFinal(const char* key_pem, } #endif // NODE_FIPS_MODE - if (Node_SignFinal(std::move(mdctx), sig, sig_len, pkey, padding, salt_len)) - return kSignOk; - else - return kSignPrivateKey; + buffer = Node_SignFinal(std::move(mdctx), pkey, padding, salt_len); + Error error = buffer.is_empty() ? kSignPrivateKey : kSignOk; + return std::make_pair(error, std::move(buffer)); } @@ -3631,22 +3636,22 @@ void Sign::SignFinal(const FunctionCallbackInfo& args) { int salt_len = args[3].As()->Value(); ClearErrorOnReturn clear_error_on_return; - unsigned char md_value[8192]; - unsigned int md_len = sizeof(md_value); - Error err = sign->SignFinal( + std::pair> ret = sign->SignFinal( buf, buf_len, len >= 2 && !args[1]->IsNull() ? *passphrase : nullptr, - md_value, - &md_len, padding, salt_len); - if (err != kSignOk) - return sign->CheckThrow(err); + + if (std::get(ret) != kSignOk) + return sign->CheckThrow(std::get(ret)); + + MallocedBuffer sig = + std::move(std::get>(ret)); Local rc = - Buffer::Copy(env, reinterpret_cast(md_value), md_len) + Buffer::New(env, reinterpret_cast(sig.release()), sig.size) .ToLocalChecked(); args.GetReturnValue().Set(rc); } diff --git a/src/node_crypto.h b/src/node_crypto.h index fd865e909d773f..6fcf737f6c43c3 100644 --- a/src/node_crypto.h +++ b/src/node_crypto.h @@ -518,13 +518,12 @@ class Sign : public SignBase { public: static void Initialize(Environment* env, v8::Local target); - Error SignFinal(const char* key_pem, - int key_pem_len, - const char* passphrase, - unsigned char* sig, - unsigned int* sig_len, - int padding, - int saltlen); + std::pair> SignFinal( + const char* key_pem, + int key_pem_len, + const char* passphrase, + int padding, + int saltlen); protected: static void New(const v8::FunctionCallbackInfo& args); diff --git a/src/node_http_parser.cc b/src/node_http_parser.cc index 5ad8afbdbf76b2..4411b6b32f8e2b 100644 --- a/src/node_http_parser.cc +++ b/src/node_http_parser.cc @@ -605,8 +605,6 @@ class Parser : public AsyncWrap, public StreamListener { size_t nparsed = http_parser_execute(&parser_, &settings, data, len); - enum http_errno err = HTTP_PARSER_ERRNO(&parser_); - Save(); // Unassign the 'buffer_' variable @@ -621,7 +619,9 @@ class Parser : public AsyncWrap, public StreamListener { Local nparsed_obj = Integer::New(env()->isolate(), nparsed); // If there was a parse error in one of the callbacks // TODO(bnoordhuis) What if there is an error on EOF? - if ((!parser_.upgrade && nparsed != len) || err != HPE_OK) { + if (!parser_.upgrade && nparsed != len) { + enum http_errno err = HTTP_PARSER_ERRNO(&parser_); + Local e = Exception::Error(env()->parse_error_string()); Local obj = e->ToObject(env()->isolate()->GetCurrentContext()) .ToLocalChecked(); @@ -738,6 +738,10 @@ const struct http_parser_settings Parser::settings = { nullptr // on_chunk_complete }; +void InitMaxHttpHeaderSizeOnce() { + const uint32_t max_http_header_size = per_process_opts->max_http_header_size; + http_parser_set_max_header_size(max_http_header_size); +} void Initialize(Local target, Local unused, @@ -784,6 +788,9 @@ void Initialize(Local target, target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "HTTPParser"), t->GetFunction(env->context()).ToLocalChecked()); + + static uv_once_t init_once = UV_ONCE_INIT; + uv_once(&init_once, InitMaxHttpHeaderSizeOnce); } } // anonymous namespace diff --git a/src/node_options-inl.h b/src/node_options-inl.h index 277121036e519d..69b8ee0e787747 100644 --- a/src/node_options-inl.h +++ b/src/node_options-inl.h @@ -35,6 +35,19 @@ void OptionsParser::AddOption(const std::string& name, help_text}); } +template +void OptionsParser::AddOption(const std::string& name, + const std::string& help_text, + uint64_t Options::* field, + OptionEnvvarSettings env_setting) { + options_.emplace( + name, + OptionInfo{kUInteger, + std::make_shared>(field), + env_setting, + help_text}); +} + template void OptionsParser::AddOption(const std::string& name, const std::string& help_text, @@ -397,6 +410,9 @@ void OptionsParser::Parse( case kInteger: *Lookup(info.field, options) = std::atoll(value.c_str()); break; + case kUInteger: + *Lookup(info.field, options) = std::stoull(value.c_str()); + break; case kString: *Lookup(info.field, options) = value; break; diff --git a/src/node_options.cc b/src/node_options.cc index 2b95b3f811b4e7..79dff7adbf9d63 100644 --- a/src/node_options.cc +++ b/src/node_options.cc @@ -236,6 +236,10 @@ PerProcessOptionsParser::PerProcessOptionsParser() { kAllowedInEnvironment); AddAlias("--trace-events-enabled", { "--trace-event-categories", "v8,node,node.async_hooks" }); + AddOption("--max-http-header-size", + "set the maximum size of HTTP headers (default: 8KB)", + &PerProcessOptions::max_http_header_size, + kAllowedInEnvironment); AddOption("--v8-pool-size", "set V8's thread pool size", &PerProcessOptions::v8_thread_pool_size, @@ -367,9 +371,8 @@ HostPort SplitHostPort(const std::string& arg, ParseAndValidatePort(arg.substr(colon + 1), errors) }; } -// Usage: Either: -// - getOptions() to get all options + metadata or -// - getOptions(string) to get the value of a particular option +// Return a map containing all the options and their metadata as well +// as the aliases void GetOptions(const FunctionCallbackInfo& args) { Mutex::ScopedLock lock(per_process_opts_mutex); Environment* env = Environment::GetCurrent(args); @@ -390,13 +393,8 @@ void GetOptions(const FunctionCallbackInfo& args) { const auto& parser = PerProcessOptionsParser::instance; - std::string filter; - if (args[0]->IsString()) filter = *node::Utf8Value(isolate, args[0]); - Local options = Map::New(isolate); for (const auto& item : parser.options_) { - if (!filter.empty() && item.first != filter) continue; - Local value; const auto& option_info = item.second; auto field = option_info.field; @@ -412,6 +410,9 @@ void GetOptions(const FunctionCallbackInfo& args) { case kInteger: value = Number::New(isolate, *parser.Lookup(field, opts)); break; + case kUInteger: + value = Number::New(isolate, *parser.Lookup(field, opts)); + break; case kString: if (!ToV8Value(context, *parser.Lookup(field, opts)) .ToLocal(&value)) { @@ -445,11 +446,6 @@ void GetOptions(const FunctionCallbackInfo& args) { } CHECK(!value.IsEmpty()); - if (!filter.empty()) { - args.GetReturnValue().Set(value); - return; - } - Local name = ToV8Value(context, item.first).ToLocalChecked(); Local info = Object::New(isolate); Local help_text; @@ -471,8 +467,6 @@ void GetOptions(const FunctionCallbackInfo& args) { } } - if (!filter.empty()) return; - Local aliases; if (!ToV8Value(context, parser.aliases_).ToLocal(&aliases)) return; @@ -505,6 +499,7 @@ void Initialize(Local target, NODE_DEFINE_CONSTANT(types, kV8Option); NODE_DEFINE_CONSTANT(types, kBoolean); NODE_DEFINE_CONSTANT(types, kInteger); + NODE_DEFINE_CONSTANT(types, kUInteger); NODE_DEFINE_CONSTANT(types, kString); NODE_DEFINE_CONSTANT(types, kHostPort); NODE_DEFINE_CONSTANT(types, kStringList); diff --git a/src/node_options.h b/src/node_options.h index 8c71881e64311d..4edec114d6da1f 100644 --- a/src/node_options.h +++ b/src/node_options.h @@ -116,6 +116,7 @@ class PerProcessOptions : public Options { std::string title; std::string trace_event_categories; std::string trace_event_file_pattern = "node_trace.${rotation}.log"; + uint64_t max_http_header_size = 8 * 1024; int64_t v8_thread_pool_size = 4; bool zero_fill_all_buffers = false; @@ -168,6 +169,7 @@ enum OptionType { kV8Option, kBoolean, kInteger, + kUInteger, kString, kHostPort, kStringList, @@ -194,6 +196,10 @@ class OptionsParser { const std::string& help_text, bool Options::* field, OptionEnvvarSettings env_setting = kDisallowedInEnvironment); + void AddOption(const std::string& name, + const std::string& help_text, + uint64_t Options::* field, + OptionEnvvarSettings env_setting = kDisallowedInEnvironment); void AddOption(const std::string& name, const std::string& help_text, int64_t Options::* field, diff --git a/src/node_perf.cc b/src/node_perf.cc index aed97d2b3b263a..4aa5da03d7a7e4 100644 --- a/src/node_perf.cc +++ b/src/node_perf.cc @@ -317,49 +317,30 @@ void TimerFunctionCall(const FunctionCallbackInfo& args) { size_t idx; SlicedArguments call_args(args); Utf8Value name(isolate, GetName(fn)); + bool is_construct_call = args.IsConstructCall(); - uint64_t start; - uint64_t end; - v8::TryCatch try_catch(isolate); - if (args.IsConstructCall()) { - start = PERFORMANCE_NOW(); - TRACE_EVENT_COPY_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0( - TRACING_CATEGORY_NODE2(perf, timerify), - *name, *name, start / 1000); - v8::MaybeLocal ret = fn->NewInstance(context, - call_args.size(), - call_args.data()); - end = PERFORMANCE_NOW(); - TRACE_EVENT_COPY_NESTABLE_ASYNC_END_WITH_TIMESTAMP0( - TRACING_CATEGORY_NODE2(perf, timerify), - *name, *name, end / 1000); - - if (ret.IsEmpty()) { - try_catch.ReThrow(); - return; - } - args.GetReturnValue().Set(ret.ToLocalChecked()); + uint64_t start = PERFORMANCE_NOW(); + TRACE_EVENT_COPY_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0( + TRACING_CATEGORY_NODE2(perf, timerify), + *name, *name, start / 1000); + v8::MaybeLocal ret; + + if (is_construct_call) { + ret = fn->NewInstance(context, call_args.size(), call_args.data()) + .FromMaybe(Local()); } else { - start = PERFORMANCE_NOW(); - TRACE_EVENT_COPY_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0( - TRACING_CATEGORY_NODE2(perf, timerify), - *name, *name, start / 1000); - v8::MaybeLocal ret = fn->Call(context, - args.This(), - call_args.size(), - call_args.data()); - end = PERFORMANCE_NOW(); - TRACE_EVENT_COPY_NESTABLE_ASYNC_END_WITH_TIMESTAMP0( - TRACING_CATEGORY_NODE2(perf, timerify), - *name, *name, end / 1000); - - if (ret.IsEmpty()) { - try_catch.ReThrow(); - return; - } - args.GetReturnValue().Set(ret.ToLocalChecked()); + ret = fn->Call(context, args.This(), call_args.size(), call_args.data()); } + uint64_t end = PERFORMANCE_NOW(); + TRACE_EVENT_COPY_NESTABLE_ASYNC_END_WITH_TIMESTAMP0( + TRACING_CATEGORY_NODE2(perf, timerify), + *name, *name, end / 1000); + + if (ret.IsEmpty()) + return; + args.GetReturnValue().Set(ret.ToLocalChecked()); + AliasedBuffer& observers = env->performance_state()->observers; if (!observers[NODE_PERFORMANCE_ENTRY_TYPE_FUNCTION]) diff --git a/src/tracing/node_trace_writer.h b/src/tracing/node_trace_writer.h index 5e5781479c689f..a91176ad4905a9 100644 --- a/src/tracing/node_trace_writer.h +++ b/src/tracing/node_trace_writer.h @@ -61,7 +61,7 @@ class NodeTraceWriter : public AsyncTraceWriter { int highest_request_id_completed_ = 0; int total_traces_ = 0; int file_num_ = 0; - const std::string& log_file_pattern_; + std::string log_file_pattern_; std::ostringstream stream_; std::unique_ptr json_trace_writer_; bool exited_ = false; diff --git a/src/util.h b/src/util.h index d41255bd32cc81..880408df4d57fd 100644 --- a/src/util.h +++ b/src/util.h @@ -439,9 +439,14 @@ struct MallocedBuffer { return ret; } + void Truncate(size_t new_size) { + CHECK(new_size <= size); + size = new_size; + } + inline bool is_empty() const { return data == nullptr; } - MallocedBuffer() : data(nullptr) {} + MallocedBuffer() : data(nullptr), size(0) {} explicit MallocedBuffer(size_t size) : data(Malloc(size)), size(size) {} MallocedBuffer(T* data, size_t size) : data(data), size(size) {} MallocedBuffer(MallocedBuffer&& other) : data(other.data), size(other.size) { diff --git a/test/README.md b/test/README.md index 7ef705230983f3..25243d7687d133 100644 --- a/test/README.md +++ b/test/README.md @@ -19,6 +19,7 @@ GitHub with the `autocrlf` git config flag set to true. | `addons` | Yes | Tests for [addon](https://nodejs.org/api/addons.html) functionality along with some tests that require an addon to function properly. | | `addons-napi` | Yes | Tests for [n-api](https://nodejs.org/api/n-api.html) functionality. | | `async-hooks` | Yes | Tests for [async_hooks](https://nodejs.org/api/async_hooks.html) functionality. | +| `benchmark` | No | Test minimal functionality of benchmarks. | | `cctest` | Yes | C++ tests that are run as part of the build process. | | `code-cache` | No | Tests for a Node.js binary compiled with V8 code cache. | | `common` | | Common modules shared among many tests. [Documentation](./common/README.md) | diff --git a/test/abort/test-http-parser-consume.js b/test/abort/test-http-parser-consume.js index 673e04cfa3a573..13dc93874a226f 100644 --- a/test/abort/test-http-parser-consume.js +++ b/test/abort/test-http-parser-consume.js @@ -7,7 +7,7 @@ const { spawn } = require('child_process'); if (process.argv[2] === 'child') { // sub-process const server = createServer(common.mustCall((_, res) => res.end('h'))); - server.listen(0, common.mustCall((s) => { + server.listen(0, common.mustCall(() => { const rr = get({ port: server.address().port }, common.mustCall(() => { // This bad input (0) should abort the parser and the process rr.parser.consume(0); diff --git a/test/addons-napi/common.h b/test/addons-napi/common.h index 422418ced49a39..b16f944771c1df 100644 --- a/test/addons-napi/common.h +++ b/test/addons-napi/common.h @@ -54,7 +54,7 @@ NAPI_CALL_BASE(env, the_call, NAPI_RETVAL_NOTHING) #define DECLARE_NAPI_PROPERTY(name, func) \ - { (name), 0, (func), 0, 0, 0, napi_default, 0 } + { (name), NULL, (func), NULL, NULL, NULL, napi_default, NULL } #define DECLARE_NAPI_GETTER(name, func) \ - { (name), 0, 0, (func), 0, 0, napi_default, 0 } + { (name), NULL, NULL, (func), NULL, NULL, napi_default, NULL } diff --git a/test/addons-napi/test_make_callback/test.js b/test/addons-napi/test_make_callback/test.js index 3f51acb6c07ac6..f409bbc9d127d6 100644 --- a/test/addons-napi/test_make_callback/test.js +++ b/test/addons-napi/test_make_callback/test.js @@ -14,7 +14,7 @@ function myMultiArgFunc(arg1, arg2, arg3) { } assert.strictEqual(makeCallback(process, common.mustCall(function() { - assert.strictEqual(0, arguments.length); + assert.strictEqual(arguments.length, 0); assert.strictEqual(this, process); return 42; })), 42); diff --git a/test/addons/dlopen-ping-pong/binding.cc b/test/addons/dlopen-ping-pong/binding.cc index a3b9af1b8099a3..6a6c297b52fff9 100644 --- a/test/addons/dlopen-ping-pong/binding.cc +++ b/test/addons/dlopen-ping-pong/binding.cc @@ -15,6 +15,7 @@ using v8::FunctionCallbackInfo; using v8::Isolate; using v8::Local; using v8::Object; +using v8::NewStringType; using v8::String; using v8::Value; @@ -33,7 +34,8 @@ void LoadLibrary(const FunctionCallbackInfo& args) { void Ping(const FunctionCallbackInfo& args) { Isolate* isolate = args.GetIsolate(); assert(ping_func != nullptr); - args.GetReturnValue().Set(String::NewFromUtf8(isolate, ping_func())); + args.GetReturnValue().Set(String::NewFromUtf8( + isolate, ping_func(), NewStringType::kNormal).ToLocalChecked()); } void init(Local exports) { diff --git a/test/addons/heap-profiler/binding.cc b/test/addons/heap-profiler/binding.cc index 861fb5a80c4651..29f58a5920825a 100644 --- a/test/addons/heap-profiler/binding.cc +++ b/test/addons/heap-profiler/binding.cc @@ -19,7 +19,8 @@ inline void Test(const v8::FunctionCallbackInfo& args) { inline void Initialize(v8::Local binding) { v8::Isolate* const isolate = binding->GetIsolate(); v8::Local context = isolate->GetCurrentContext(); - binding->Set(v8::String::NewFromUtf8(isolate, "test"), + binding->Set(v8::String::NewFromUtf8( + isolate, "test", v8::NewStringType::kNormal).ToLocalChecked(), v8::FunctionTemplate::New(isolate, Test) ->GetFunction(context) .ToLocalChecked()); diff --git a/test/addons/hello-world-esm/binding.cc b/test/addons/hello-world-esm/binding.cc index 944f5631956d15..02eecec099807a 100644 --- a/test/addons/hello-world-esm/binding.cc +++ b/test/addons/hello-world-esm/binding.cc @@ -3,7 +3,8 @@ void Method(const v8::FunctionCallbackInfo& args) { v8::Isolate* isolate = args.GetIsolate(); - args.GetReturnValue().Set(v8::String::NewFromUtf8(isolate, "world")); + args.GetReturnValue().Set(v8::String::NewFromUtf8( + isolate, "world", v8::NewStringType::kNormal).ToLocalChecked()); } void init(v8::Local exports) { diff --git a/test/addons/hello-world-function-export/binding.cc b/test/addons/hello-world-function-export/binding.cc index 55d64b3d6c3513..e5476c4ee1e364 100644 --- a/test/addons/hello-world-function-export/binding.cc +++ b/test/addons/hello-world-function-export/binding.cc @@ -3,7 +3,8 @@ void Method(const v8::FunctionCallbackInfo& args) { v8::Isolate* isolate = args.GetIsolate(); - args.GetReturnValue().Set(v8::String::NewFromUtf8(isolate, "world")); + args.GetReturnValue().Set(v8::String::NewFromUtf8( + isolate, "world", v8::NewStringType::kNormal).ToLocalChecked()); } void init(v8::Local exports, v8::Local module) { diff --git a/test/addons/hello-world/binding.cc b/test/addons/hello-world/binding.cc index 341b58f9a640d8..81bcbc29c78645 100644 --- a/test/addons/hello-world/binding.cc +++ b/test/addons/hello-world/binding.cc @@ -3,7 +3,8 @@ void Method(const v8::FunctionCallbackInfo& args) { v8::Isolate* isolate = args.GetIsolate(); - args.GetReturnValue().Set(v8::String::NewFromUtf8(isolate, "world")); + args.GetReturnValue().Set(v8::String::NewFromUtf8( + isolate, "world", v8::NewStringType::kNormal).ToLocalChecked()); } // Not using the full NODE_MODULE_INIT() macro here because we want to test the diff --git a/test/addons/load-long-path/binding.cc b/test/addons/load-long-path/binding.cc index 944f5631956d15..02eecec099807a 100644 --- a/test/addons/load-long-path/binding.cc +++ b/test/addons/load-long-path/binding.cc @@ -3,7 +3,8 @@ void Method(const v8::FunctionCallbackInfo& args) { v8::Isolate* isolate = args.GetIsolate(); - args.GetReturnValue().Set(v8::String::NewFromUtf8(isolate, "world")); + args.GetReturnValue().Set(v8::String::NewFromUtf8( + isolate, "world", v8::NewStringType::kNormal).ToLocalChecked()); } void init(v8::Local exports) { diff --git a/test/addons/new-target/binding.cc b/test/addons/new-target/binding.cc index 21b932ae018dfd..c2777c831e484a 100644 --- a/test/addons/new-target/binding.cc +++ b/test/addons/new-target/binding.cc @@ -12,7 +12,8 @@ inline void NewClass(const v8::FunctionCallbackInfo& args) { inline void Initialize(v8::Local binding) { auto isolate = binding->GetIsolate(); auto context = isolate->GetCurrentContext(); - binding->Set(v8::String::NewFromUtf8(isolate, "Class"), + binding->Set(v8::String::NewFromUtf8( + isolate, "Class", v8::NewStringType::kNormal).ToLocalChecked(), v8::FunctionTemplate::New(isolate, NewClass) ->GetFunction(context) .ToLocalChecked()); diff --git a/test/addons/openssl-binding/binding.cc b/test/addons/openssl-binding/binding.cc index bb00f1e176d7ce..122d420bc14e0b 100644 --- a/test/addons/openssl-binding/binding.cc +++ b/test/addons/openssl-binding/binding.cc @@ -22,7 +22,8 @@ inline void Initialize(v8::Local exports, v8::Local module, v8::Local context) { auto isolate = context->GetIsolate(); - auto key = v8::String::NewFromUtf8(isolate, "randomBytes"); + auto key = v8::String::NewFromUtf8( + isolate, "randomBytes", v8::NewStringType::kNormal).ToLocalChecked(); auto value = v8::FunctionTemplate::New(isolate, RandomBytes) ->GetFunction(context) .ToLocalChecked(); diff --git a/test/addons/symlinked-module/binding.cc b/test/addons/symlinked-module/binding.cc index 944f5631956d15..02eecec099807a 100644 --- a/test/addons/symlinked-module/binding.cc +++ b/test/addons/symlinked-module/binding.cc @@ -3,7 +3,8 @@ void Method(const v8::FunctionCallbackInfo& args) { v8::Isolate* isolate = args.GetIsolate(); - args.GetReturnValue().Set(v8::String::NewFromUtf8(isolate, "world")); + args.GetReturnValue().Set(v8::String::NewFromUtf8( + isolate, "world", v8::NewStringType::kNormal).ToLocalChecked()); } void init(v8::Local exports) { diff --git a/test/addons/zlib-binding/binding.cc b/test/addons/zlib-binding/binding.cc index 1d0af911115359..0b82de211a8430 100644 --- a/test/addons/zlib-binding/binding.cc +++ b/test/addons/zlib-binding/binding.cc @@ -45,7 +45,8 @@ inline void Initialize(v8::Local exports, v8::Local module, v8::Local context) { auto isolate = context->GetIsolate(); - auto key = v8::String::NewFromUtf8(isolate, "compressBytes"); + auto key = v8::String::NewFromUtf8( + isolate, "compressBytes", v8::NewStringType::kNormal).ToLocalChecked(); auto value = v8::FunctionTemplate::New(isolate, CompressBytes) ->GetFunction(context) .ToLocalChecked(); diff --git a/test/async-hooks/init-hooks.js b/test/async-hooks/init-hooks.js index 14969d8e753b68..817b2db0c781b4 100644 --- a/test/async-hooks/init-hooks.js +++ b/test/async-hooks/init-hooks.js @@ -120,8 +120,7 @@ class ActivityCollector { } if (violations.length) { console.error(violations.join('\n\n') + '\n'); - assert.fail(violations.length, 0, - `${violations.length} failed sanity checks`); + assert.fail(`${violations.length} failed sanity checks`); } } diff --git a/test/benchmark/benchmark.status b/test/benchmark/benchmark.status new file mode 100644 index 00000000000000..6a966743aab26b --- /dev/null +++ b/test/benchmark/benchmark.status @@ -0,0 +1,21 @@ +prefix benchmark + +# To mark a test as flaky, list the test name in the appropriate section +# below, without ".js", followed by ": PASS,FLAKY". Example: +# sample-test : PASS,FLAKY + +[true] # This section applies to all platforms + +[$system==win32] + +[$system==linux] + +[$system==macos] + +[$system==solaris] # Also applies to SmartOS + +[$system==freebsd] + +[$system==aix] + +[$arch==arm] diff --git a/test/parallel/test-benchmark-assert.js b/test/benchmark/test-benchmark-assert.js similarity index 100% rename from test/parallel/test-benchmark-assert.js rename to test/benchmark/test-benchmark-assert.js diff --git a/test/sequential/test-benchmark-async-hooks.js b/test/benchmark/test-benchmark-async-hooks.js similarity index 100% rename from test/sequential/test-benchmark-async-hooks.js rename to test/benchmark/test-benchmark-async-hooks.js diff --git a/test/sequential/test-benchmark-buffer.js b/test/benchmark/test-benchmark-buffer.js similarity index 100% rename from test/sequential/test-benchmark-buffer.js rename to test/benchmark/test-benchmark-buffer.js diff --git a/test/sequential/test-benchmark-child-process.js b/test/benchmark/test-benchmark-child-process.js similarity index 100% rename from test/sequential/test-benchmark-child-process.js rename to test/benchmark/test-benchmark-child-process.js diff --git a/test/parallel/test-benchmark-cluster.js b/test/benchmark/test-benchmark-cluster.js similarity index 100% rename from test/parallel/test-benchmark-cluster.js rename to test/benchmark/test-benchmark-cluster.js diff --git a/test/parallel/test-benchmark-crypto.js b/test/benchmark/test-benchmark-crypto.js similarity index 100% rename from test/parallel/test-benchmark-crypto.js rename to test/benchmark/test-benchmark-crypto.js diff --git a/test/sequential/test-benchmark-dgram.js b/test/benchmark/test-benchmark-dgram.js similarity index 100% rename from test/sequential/test-benchmark-dgram.js rename to test/benchmark/test-benchmark-dgram.js diff --git a/test/parallel/test-benchmark-dns.js b/test/benchmark/test-benchmark-dns.js similarity index 100% rename from test/parallel/test-benchmark-dns.js rename to test/benchmark/test-benchmark-dns.js diff --git a/test/parallel/test-benchmark-domain.js b/test/benchmark/test-benchmark-domain.js similarity index 100% rename from test/parallel/test-benchmark-domain.js rename to test/benchmark/test-benchmark-domain.js diff --git a/test/parallel/test-benchmark-es.js b/test/benchmark/test-benchmark-es.js similarity index 100% rename from test/parallel/test-benchmark-es.js rename to test/benchmark/test-benchmark-es.js diff --git a/test/parallel/test-benchmark-events.js b/test/benchmark/test-benchmark-events.js similarity index 100% rename from test/parallel/test-benchmark-events.js rename to test/benchmark/test-benchmark-events.js diff --git a/test/parallel/test-benchmark-fs.js b/test/benchmark/test-benchmark-fs.js similarity index 100% rename from test/parallel/test-benchmark-fs.js rename to test/benchmark/test-benchmark-fs.js diff --git a/test/sequential/test-benchmark-http.js b/test/benchmark/test-benchmark-http.js similarity index 100% rename from test/sequential/test-benchmark-http.js rename to test/benchmark/test-benchmark-http.js diff --git a/test/parallel/test-benchmark-misc.js b/test/benchmark/test-benchmark-misc.js similarity index 82% rename from test/parallel/test-benchmark-misc.js rename to test/benchmark/test-benchmark-misc.js index fc7e340a80d0bb..b88415280833bc 100644 --- a/test/parallel/test-benchmark-misc.js +++ b/test/benchmark/test-benchmark-misc.js @@ -11,4 +11,6 @@ runBenchmark('misc', [ 'n=1', 'type=', 'val=magyarország.icom.museum', + 'script=test/fixtures/semicolon', + 'mode=worker' ], { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); diff --git a/test/parallel/test-benchmark-module.js b/test/benchmark/test-benchmark-module.js similarity index 100% rename from test/parallel/test-benchmark-module.js rename to test/benchmark/test-benchmark-module.js diff --git a/test/sequential/test-benchmark-napi.js b/test/benchmark/test-benchmark-napi.js similarity index 100% rename from test/sequential/test-benchmark-napi.js rename to test/benchmark/test-benchmark-napi.js diff --git a/test/sequential/test-benchmark-net.js b/test/benchmark/test-benchmark-net.js similarity index 100% rename from test/sequential/test-benchmark-net.js rename to test/benchmark/test-benchmark-net.js diff --git a/test/parallel/test-benchmark-os.js b/test/benchmark/test-benchmark-os.js similarity index 100% rename from test/parallel/test-benchmark-os.js rename to test/benchmark/test-benchmark-os.js diff --git a/test/sequential/test-benchmark-path.js b/test/benchmark/test-benchmark-path.js similarity index 100% rename from test/sequential/test-benchmark-path.js rename to test/benchmark/test-benchmark-path.js diff --git a/test/parallel/test-benchmark-process.js b/test/benchmark/test-benchmark-process.js similarity index 100% rename from test/parallel/test-benchmark-process.js rename to test/benchmark/test-benchmark-process.js diff --git a/test/parallel/test-benchmark-querystring.js b/test/benchmark/test-benchmark-querystring.js similarity index 100% rename from test/parallel/test-benchmark-querystring.js rename to test/benchmark/test-benchmark-querystring.js diff --git a/test/parallel/test-benchmark-streams.js b/test/benchmark/test-benchmark-streams.js similarity index 100% rename from test/parallel/test-benchmark-streams.js rename to test/benchmark/test-benchmark-streams.js diff --git a/test/parallel/test-benchmark-string_decoder.js b/test/benchmark/test-benchmark-string_decoder.js similarity index 100% rename from test/parallel/test-benchmark-string_decoder.js rename to test/benchmark/test-benchmark-string_decoder.js diff --git a/test/parallel/test-benchmark-timers.js b/test/benchmark/test-benchmark-timers.js similarity index 100% rename from test/parallel/test-benchmark-timers.js rename to test/benchmark/test-benchmark-timers.js diff --git a/test/sequential/test-benchmark-tls.js b/test/benchmark/test-benchmark-tls.js similarity index 100% rename from test/sequential/test-benchmark-tls.js rename to test/benchmark/test-benchmark-tls.js diff --git a/test/parallel/test-benchmark-url.js b/test/benchmark/test-benchmark-url.js similarity index 100% rename from test/parallel/test-benchmark-url.js rename to test/benchmark/test-benchmark-url.js diff --git a/test/parallel/test-benchmark-util.js b/test/benchmark/test-benchmark-util.js similarity index 100% rename from test/parallel/test-benchmark-util.js rename to test/benchmark/test-benchmark-util.js diff --git a/test/parallel/test-benchmark-v8.js b/test/benchmark/test-benchmark-v8.js similarity index 100% rename from test/parallel/test-benchmark-v8.js rename to test/benchmark/test-benchmark-v8.js diff --git a/test/parallel/test-benchmark-vm.js b/test/benchmark/test-benchmark-vm.js similarity index 100% rename from test/parallel/test-benchmark-vm.js rename to test/benchmark/test-benchmark-vm.js diff --git a/test/sequential/test-benchmark-worker.js b/test/benchmark/test-benchmark-worker.js similarity index 100% rename from test/sequential/test-benchmark-worker.js rename to test/benchmark/test-benchmark-worker.js diff --git a/test/parallel/test-benchmark-zlib.js b/test/benchmark/test-benchmark-zlib.js similarity index 100% rename from test/parallel/test-benchmark-zlib.js rename to test/benchmark/test-benchmark-zlib.js diff --git a/test/benchmark/testcfg.py b/test/benchmark/testcfg.py new file mode 100644 index 00000000000000..2c2929f610b851 --- /dev/null +++ b/test/benchmark/testcfg.py @@ -0,0 +1,6 @@ +import sys, os +sys.path.append(os.path.join(os.path.dirname(__file__), '..')) +import testpy + +def GetConfiguration(context, root): + return testpy.SimpleTestConfiguration(context, root, 'benchmark') diff --git a/test/known_issues/known_issues.status b/test/known_issues/known_issues.status index e21913e232c03f..447f648e5a8c9e 100644 --- a/test/known_issues/known_issues.status +++ b/test/known_issues/known_issues.status @@ -9,6 +9,8 @@ prefix known_issues [$system==win32] [$system==linux] +test-vm-timeout-escape-nexttick: PASS,FLAKY +test-vm-timeout-escape-promise: PASS,FLAKY [$system==macos] diff --git a/test/known_issues/test-vm-timeout-escape-nexttick.js b/test/known_issues/test-vm-timeout-escape-nexttick.js new file mode 100644 index 00000000000000..8afe2fb8cebb15 --- /dev/null +++ b/test/known_issues/test-vm-timeout-escape-nexttick.js @@ -0,0 +1,41 @@ +'use strict'; + +// https://github.com/nodejs/node/issues/3020 +// Promises, nextTick, and queueMicrotask allow code to escape the timeout +// set for runInContext, runInNewContext, and runInThisContext + +require('../common'); +const assert = require('assert'); +const vm = require('vm'); + +const NS_PER_MS = 1000000n; + +const hrtime = process.hrtime.bigint; +const nextTick = process.nextTick; + +function loop() { + const start = hrtime(); + while (1) { + const current = hrtime(); + const span = (current - start) / NS_PER_MS; + if (span >= 100n) { + throw new Error( + `escaped timeout at ${span} milliseconds!`); + } + } +} + +assert.throws(() => { + vm.runInNewContext( + 'nextTick(loop); loop();', + { + hrtime, + nextTick, + loop + }, + { timeout: 5 } + ); +}, { + code: 'ERR_SCRIPT_EXECUTION_TIMEOUT', + message: 'Script execution timed out after 5ms' +}); diff --git a/test/known_issues/test-vm-timeout-escape-promise.js b/test/known_issues/test-vm-timeout-escape-promise.js new file mode 100644 index 00000000000000..4452c83cd182e3 --- /dev/null +++ b/test/known_issues/test-vm-timeout-escape-promise.js @@ -0,0 +1,39 @@ +'use strict'; + +// https://github.com/nodejs/node/issues/3020 +// Promises, nextTick, and queueMicrotask allow code to escape the timeout +// set for runInContext, runInNewContext, and runInThisContext + +require('../common'); +const assert = require('assert'); +const vm = require('vm'); + +const NS_PER_MS = 1000000n; + +const hrtime = process.hrtime.bigint; + +function loop() { + const start = hrtime(); + while (1) { + const current = hrtime(); + const span = (current - start) / NS_PER_MS; + if (span >= 100n) { + throw new Error( + `escaped timeout at ${span} milliseconds!`); + } + } +} + +assert.throws(() => { + vm.runInNewContext( + 'Promise.resolve().then(loop); loop();', + { + hrtime, + loop + }, + { timeout: 5 } + ); +}, { + code: 'ERR_SCRIPT_EXECUTION_TIMEOUT', + message: 'Script execution timed out after 5ms' +}); diff --git a/test/parallel/parallel.status b/test/parallel/parallel.status index b45e4448d97c06..4bfc8fe7d0eeb1 100644 --- a/test/parallel/parallel.status +++ b/test/parallel/parallel.status @@ -24,3 +24,4 @@ test-worker-syntax-error-file: PASS,FLAKY [$system==freebsd] [$system==aix] +test-repl-envvars: PASS,FLAKY diff --git a/test/parallel/test-assert-deep.js b/test/parallel/test-assert-deep.js index af1003fd51eebe..45f4353ce6c577 100644 --- a/test/parallel/test-assert-deep.js +++ b/test/parallel/test-assert-deep.js @@ -947,6 +947,27 @@ assert.throws(() => assert.deepStrictEqual(new Boolean(true), {}), ); } +// Strict equal with identical objects that are not identical +// by reference and longer than 30 elements +// E.g., assert.deepStrictEqual({ a: Symbol() }, { a: Symbol() }) +{ + const a = {}; + const b = {}; + for (let i = 0; i < 35; i++) { + a[`symbol${i}`] = Symbol(); + b[`symbol${i}`] = Symbol(); + } + + assert.throws( + () => assert.deepStrictEqual(a, b), + { + code: 'ERR_ASSERTION', + name: 'AssertionError [ERR_ASSERTION]', + message: /\.\.\./g + } + ); +} + // Basic valueOf check. { const a = new String(1); diff --git a/test/parallel/test-assert-typedarray-deepequal.js b/test/parallel/test-assert-typedarray-deepequal.js index b648f07d3297f6..65b94f6c24b028 100644 --- a/test/parallel/test-assert-typedarray-deepequal.js +++ b/test/parallel/test-assert-typedarray-deepequal.js @@ -44,6 +44,7 @@ const notEqualArrayPairs = [ [new Int16Array([-256]), new Uint16Array([0xff00])], // same bits [new Int32Array([-256]), new Uint32Array([0xffffff00])], // ditto [new Float32Array([0.1]), new Float32Array([0.0])], + [new Float32Array([0.1]), new Float32Array([0.1, 0.2])], [new Float64Array([0.1]), new Float64Array([0.0])] ]; diff --git a/test/parallel/test-bash-completion.js b/test/parallel/test-bash-completion.js new file mode 100644 index 00000000000000..50378a7b0f8028 --- /dev/null +++ b/test/parallel/test-bash-completion.js @@ -0,0 +1,23 @@ +'use strict'; +require('../common'); +const assert = require('assert'); +const child_process = require('child_process'); + +const p = child_process.spawnSync( + process.execPath, [ '--completion-bash' ]); +assert.ifError(p.error); +assert.ok(p.stdout.toString().includes( + `_node_complete() { + local cur_word options + cur_word="\${COMP_WORDS[COMP_CWORD]}" + if [[ "\${cur_word}" == -* ]] ; then + COMPREPLY=( $(compgen -W '`)); +assert.ok(p.stdout.toString().includes( + `' -- "\${cur_word}") ) + return 0 + else + COMPREPLY=( $(compgen -f "\${cur_word}") ) + return 0 + fi +} +complete -F _node_complete node node_g`)); diff --git a/test/parallel/test-bootstrap-modules.js b/test/parallel/test-bootstrap-modules.js index 70011637e08af4..a047d50b57e2b6 100644 --- a/test/parallel/test-bootstrap-modules.js +++ b/test/parallel/test-bootstrap-modules.js @@ -11,4 +11,5 @@ const list = process.moduleLoadList.slice(); const assert = require('assert'); -assert(list.length <= 78, list); +assert(list.length <= 81, + `Expected <= 81 elements in moduleLoadLists, got ${list.length}`); diff --git a/test/parallel/test-buffer-fill.js b/test/parallel/test-buffer-fill.js index 4eef0edefcbb22..2544a73819ce17 100644 --- a/test/parallel/test-buffer-fill.js +++ b/test/parallel/test-buffer-fill.js @@ -302,19 +302,19 @@ Buffer.alloc(8, ''); buf.fill(0); for (let i = 0; i < buf.length; i++) - assert.strictEqual(0, buf[i]); + assert.strictEqual(buf[i], 0); buf.fill(null); for (let i = 0; i < buf.length; i++) - assert.strictEqual(0, buf[i]); + assert.strictEqual(buf[i], 0); buf.fill(1, 16, 32); for (let i = 0; i < 16; i++) - assert.strictEqual(0, buf[i]); + assert.strictEqual(buf[i], 0); for (let i = 16; i < 32; i++) - assert.strictEqual(1, buf[i]); + assert.strictEqual(buf[i], 1); for (let i = 32; i < buf.length; i++) - assert.strictEqual(0, buf[i]); + assert.strictEqual(buf[i], 0); } { diff --git a/test/parallel/test-buffer-indexof.js b/test/parallel/test-buffer-indexof.js index 357558c74d2edc..3647d115b0dc5b 100644 --- a/test/parallel/test-buffer-indexof.js +++ b/test/parallel/test-buffer-indexof.js @@ -183,24 +183,24 @@ assert.strictEqual(Buffer.from('aaaa00a').indexOf('3030', 'hex'), 4); // test usc2 encoding const twoByteString = Buffer.from('\u039a\u0391\u03a3\u03a3\u0395', 'ucs2'); - assert.strictEqual(8, twoByteString.indexOf('\u0395', 4, 'ucs2')); - assert.strictEqual(6, twoByteString.indexOf('\u03a3', -4, 'ucs2')); - assert.strictEqual(4, twoByteString.indexOf('\u03a3', -6, 'ucs2')); - assert.strictEqual(4, twoByteString.indexOf( - Buffer.from('\u03a3', 'ucs2'), -6, 'ucs2')); + assert.strictEqual(twoByteString.indexOf('\u0395', 4, 'ucs2'), 8); + assert.strictEqual(twoByteString.indexOf('\u03a3', -4, 'ucs2'), 6); + assert.strictEqual(twoByteString.indexOf('\u03a3', -6, 'ucs2'), 4); + assert.strictEqual(twoByteString.indexOf( + Buffer.from('\u03a3', 'ucs2'), -6, 'ucs2'), 4); assert.strictEqual(-1, twoByteString.indexOf('\u03a3', -2, 'ucs2')); } const mixedByteStringUcs2 = Buffer.from('\u039a\u0391abc\u03a3\u03a3\u0395', 'ucs2'); -assert.strictEqual(6, mixedByteStringUcs2.indexOf('bc', 0, 'ucs2')); -assert.strictEqual(10, mixedByteStringUcs2.indexOf('\u03a3', 0, 'ucs2')); +assert.strictEqual(mixedByteStringUcs2.indexOf('bc', 0, 'ucs2'), 6); +assert.strictEqual(mixedByteStringUcs2.indexOf('\u03a3', 0, 'ucs2'), 10); assert.strictEqual(-1, mixedByteStringUcs2.indexOf('\u0396', 0, 'ucs2')); assert.strictEqual( - 6, mixedByteStringUcs2.indexOf(Buffer.from('bc', 'ucs2'), 0, 'ucs2')); + mixedByteStringUcs2.indexOf(Buffer.from('bc', 'ucs2'), 0, 'ucs2'), 6); assert.strictEqual( - 10, mixedByteStringUcs2.indexOf(Buffer.from('\u03a3', 'ucs2'), 0, 'ucs2')); + mixedByteStringUcs2.indexOf(Buffer.from('\u03a3', 'ucs2'), 0, 'ucs2'), 10); assert.strictEqual( -1, mixedByteStringUcs2.indexOf(Buffer.from('\u0396', 'ucs2'), 0, 'ucs2')); @@ -208,34 +208,34 @@ assert.strictEqual( const twoByteString = Buffer.from('\u039a\u0391\u03a3\u03a3\u0395', 'ucs2'); // Test single char pattern - assert.strictEqual(0, twoByteString.indexOf('\u039a', 0, 'ucs2')); + assert.strictEqual(twoByteString.indexOf('\u039a', 0, 'ucs2'), 0); let index = twoByteString.indexOf('\u0391', 0, 'ucs2'); - assert.strictEqual(2, index, `Alpha - at index ${index}`); + assert.strictEqual(index, 2, `Alpha - at index ${index}`); index = twoByteString.indexOf('\u03a3', 0, 'ucs2'); - assert.strictEqual(4, index, `First Sigma - at index ${index}`); + assert.strictEqual(index, 4, `First Sigma - at index ${index}`); index = twoByteString.indexOf('\u03a3', 6, 'ucs2'); - assert.strictEqual(6, index, `Second Sigma - at index ${index}`); + assert.strictEqual(index, 6, `Second Sigma - at index ${index}`); index = twoByteString.indexOf('\u0395', 0, 'ucs2'); - assert.strictEqual(8, index, `Epsilon - at index ${index}`); + assert.strictEqual(index, 8, `Epsilon - at index ${index}`); index = twoByteString.indexOf('\u0392', 0, 'ucs2'); assert.strictEqual(-1, index, `Not beta - at index ${index}`); // Test multi-char pattern index = twoByteString.indexOf('\u039a\u0391', 0, 'ucs2'); - assert.strictEqual(0, index, `Lambda Alpha - at index ${index}`); + assert.strictEqual(index, 0, `Lambda Alpha - at index ${index}`); index = twoByteString.indexOf('\u0391\u03a3', 0, 'ucs2'); - assert.strictEqual(2, index, `Alpha Sigma - at index ${index}`); + assert.strictEqual(index, 2, `Alpha Sigma - at index ${index}`); index = twoByteString.indexOf('\u03a3\u03a3', 0, 'ucs2'); - assert.strictEqual(4, index, `Sigma Sigma - at index ${index}`); + assert.strictEqual(index, 4, `Sigma Sigma - at index ${index}`); index = twoByteString.indexOf('\u03a3\u0395', 0, 'ucs2'); - assert.strictEqual(6, index, `Sigma Epsilon - at index ${index}`); + assert.strictEqual(index, 6, `Sigma Epsilon - at index ${index}`); } const mixedByteStringUtf8 = Buffer.from('\u039a\u0391abc\u03a3\u03a3\u0395'); -assert.strictEqual(5, mixedByteStringUtf8.indexOf('bc')); -assert.strictEqual(5, mixedByteStringUtf8.indexOf('bc', 5)); -assert.strictEqual(5, mixedByteStringUtf8.indexOf('bc', -8)); -assert.strictEqual(7, mixedByteStringUtf8.indexOf('\u03a3')); +assert.strictEqual(mixedByteStringUtf8.indexOf('bc'), 5); +assert.strictEqual(mixedByteStringUtf8.indexOf('bc', 5), 5); +assert.strictEqual(mixedByteStringUtf8.indexOf('bc', -8), 5); +assert.strictEqual(mixedByteStringUtf8.indexOf('\u03a3'), 7); assert.strictEqual(-1, mixedByteStringUtf8.indexOf('\u0396')); @@ -257,22 +257,22 @@ for (let i = 0; i < longBufferString.length - pattern.length; i += 7) { } let index = longBufferString.indexOf('AJABACA'); -assert.strictEqual(510, index, `Long AJABACA, First J - at index ${index}`); +assert.strictEqual(index, 510, `Long AJABACA, First J - at index ${index}`); index = longBufferString.indexOf('AJABACA', 511); -assert.strictEqual(1534, index, `Long AJABACA, Second J - at index ${index}`); +assert.strictEqual(index, 1534, `Long AJABACA, Second J - at index ${index}`); pattern = 'JABACABADABACABA'; index = longBufferString.indexOf(pattern); -assert.strictEqual(511, index, `Long JABACABA..., First J - at index ${index}`); +assert.strictEqual(index, 511, `Long JABACABA..., First J - at index ${index}`); index = longBufferString.indexOf(pattern, 512); assert.strictEqual( - 1535, index, `Long JABACABA..., Second J - at index ${index}`); + index, 1535, `Long JABACABA..., Second J - at index ${index}`); // Search for a non-ASCII string in a pure ASCII string. const asciiString = Buffer.from( 'arglebargleglopglyfarglebargleglopglyfarglebargleglopglyf'); assert.strictEqual(-1, asciiString.indexOf('\x2061')); -assert.strictEqual(3, asciiString.indexOf('leb', 0)); +assert.strictEqual(asciiString.indexOf('leb', 0), 3); // Search in string containing many non-ASCII chars. const allCodePoints = []; @@ -505,20 +505,20 @@ assert.strictEqual(buf_bc.lastIndexOf(Buffer.from('你好'), 7), -1); // Test lastIndexOf on a longer buffer: const bufferString = Buffer.from('a man a plan a canal panama'); -assert.strictEqual(15, bufferString.lastIndexOf('canal')); -assert.strictEqual(21, bufferString.lastIndexOf('panama')); -assert.strictEqual(0, bufferString.lastIndexOf('a man a plan a canal panama')); +assert.strictEqual(bufferString.lastIndexOf('canal'), 15); +assert.strictEqual(bufferString.lastIndexOf('panama'), 21); +assert.strictEqual(bufferString.lastIndexOf('a man a plan a canal panama'), 0); assert.strictEqual(-1, bufferString.lastIndexOf('a man a plan a canal mexico')); assert.strictEqual(-1, bufferString .lastIndexOf('a man a plan a canal mexico city')); assert.strictEqual(-1, bufferString.lastIndexOf(Buffer.from('a'.repeat(1000)))); -assert.strictEqual(0, bufferString.lastIndexOf('a man a plan', 4)); -assert.strictEqual(13, bufferString.lastIndexOf('a ')); -assert.strictEqual(13, bufferString.lastIndexOf('a ', 13)); -assert.strictEqual(6, bufferString.lastIndexOf('a ', 12)); -assert.strictEqual(0, bufferString.lastIndexOf('a ', 5)); -assert.strictEqual(13, bufferString.lastIndexOf('a ', -1)); -assert.strictEqual(0, bufferString.lastIndexOf('a ', -27)); +assert.strictEqual(bufferString.lastIndexOf('a man a plan', 4), 0); +assert.strictEqual(bufferString.lastIndexOf('a '), 13); +assert.strictEqual(bufferString.lastIndexOf('a ', 13), 13); +assert.strictEqual(bufferString.lastIndexOf('a ', 12), 6); +assert.strictEqual(bufferString.lastIndexOf('a ', 5), 0); +assert.strictEqual(bufferString.lastIndexOf('a ', -1), 13); +assert.strictEqual(bufferString.lastIndexOf('a ', -27), 0); assert.strictEqual(-1, bufferString.lastIndexOf('a ', -28)); // Test lastIndexOf for the case that the first character can be found, @@ -534,18 +534,18 @@ assert.strictEqual(-1, Buffer.from('bc').lastIndexOf(Buffer.from('ab'))); assert.strictEqual(-1, Buffer.from('bc', 'ucs2').lastIndexOf('ab', 'ucs2')); assert.strictEqual(-1, Buffer.from('bc', 'ucs2').lastIndexOf(abInUCS2)); -assert.strictEqual(0, Buffer.from('abc').lastIndexOf('ab')); -assert.strictEqual(0, Buffer.from('abc').lastIndexOf('ab', 1)); -assert.strictEqual(0, Buffer.from('abc').lastIndexOf('ab', 2)); -assert.strictEqual(0, Buffer.from('abc').lastIndexOf('ab', 3)); +assert.strictEqual(Buffer.from('abc').lastIndexOf('ab'), 0); +assert.strictEqual(Buffer.from('abc').lastIndexOf('ab', 1), 0); +assert.strictEqual(Buffer.from('abc').lastIndexOf('ab', 2), 0); +assert.strictEqual(Buffer.from('abc').lastIndexOf('ab', 3), 0); // The above tests test the LINEAR and SINGLE-CHAR strategies. // Now, we test the BOYER-MOORE-HORSPOOL strategy. // Test lastIndexOf on a long buffer w multiple matches: pattern = 'JABACABADABACABA'; -assert.strictEqual(1535, longBufferString.lastIndexOf(pattern)); -assert.strictEqual(1535, longBufferString.lastIndexOf(pattern, 1535)); -assert.strictEqual(511, longBufferString.lastIndexOf(pattern, 1534)); +assert.strictEqual(longBufferString.lastIndexOf(pattern), 1535); +assert.strictEqual(longBufferString.lastIndexOf(pattern, 1535), 1535); +assert.strictEqual(longBufferString.lastIndexOf(pattern, 1534), 511); // Finally, give it a really long input to trigger fallback from BMH to // regular BOYER-MOORE (which has better worst-case complexity). @@ -567,19 +567,19 @@ for (let i = 0; i < 1000000; i++) { parts.push((countBits(i) % 2 === 0) ? 'yolo' : 'swag'); } const reallyLong = Buffer.from(parts.join(' ')); -assert.strictEqual('yolo swag swag yolo', reallyLong.slice(0, 19).toString()); +assert.strictEqual(reallyLong.slice(0, 19).toString(), 'yolo swag swag yolo'); // Expensive reverse searches. Stress test lastIndexOf: pattern = reallyLong.slice(0, 100000); // First 1/50th of the pattern. -assert.strictEqual(4751360, reallyLong.lastIndexOf(pattern)); -assert.strictEqual(3932160, reallyLong.lastIndexOf(pattern, 4000000)); -assert.strictEqual(2949120, reallyLong.lastIndexOf(pattern, 3000000)); +assert.strictEqual(reallyLong.lastIndexOf(pattern), 4751360); +assert.strictEqual(reallyLong.lastIndexOf(pattern, 4000000), 3932160); +assert.strictEqual(reallyLong.lastIndexOf(pattern, 3000000), 2949120); pattern = reallyLong.slice(100000, 200000); // Second 1/50th. -assert.strictEqual(4728480, reallyLong.lastIndexOf(pattern)); +assert.strictEqual(reallyLong.lastIndexOf(pattern), 4728480); pattern = reallyLong.slice(0, 1000000); // First 1/5th. -assert.strictEqual(3932160, reallyLong.lastIndexOf(pattern)); +assert.strictEqual(reallyLong.lastIndexOf(pattern), 3932160); pattern = reallyLong.slice(0, 2000000); // first 2/5ths. -assert.strictEqual(0, reallyLong.lastIndexOf(pattern)); +assert.strictEqual(reallyLong.lastIndexOf(pattern), 0); // test truncation of Number arguments to uint8 { diff --git a/test/parallel/test-buffer-slice.js b/test/parallel/test-buffer-slice.js index 6175370a9bccee..f40a495b206079 100644 --- a/test/parallel/test-buffer-slice.js +++ b/test/parallel/test-buffer-slice.js @@ -24,8 +24,8 @@ require('../common'); const assert = require('assert'); -assert.strictEqual(0, Buffer.from('hello', 'utf8').slice(0, 0).length); -assert.strictEqual(0, Buffer('hello', 'utf8').slice(0, 0).length); +assert.strictEqual(Buffer.from('hello', 'utf8').slice(0, 0).length, 0); +assert.strictEqual(Buffer('hello', 'utf8').slice(0, 0).length, 0); const buf = Buffer.from('0123456789', 'utf8'); const expectedSameBufs = [ @@ -72,7 +72,7 @@ for (let i = 0, s = buf.toString(); i < buf.length; ++i) { } expectedSameBufs.forEach(([buf1, buf2]) => { - assert.strictEqual(0, Buffer.compare(buf1, buf2)); + assert.strictEqual(Buffer.compare(buf1, buf2), 0); }); const utf16Buf = Buffer.from('0123456789', 'utf16le'); @@ -83,12 +83,12 @@ assert.strictEqual(Buffer.alloc(0).slice(0, 1).length, 0); { // Single argument slice - assert.strictEqual('bcde', - Buffer.from('abcde', 'utf8').slice(1).toString('utf8')); + assert.strictEqual(Buffer.from('abcde', 'utf8').slice(1).toString('utf8'), + 'bcde'); } // slice(0,0).length === 0 -assert.strictEqual(0, Buffer.from('hello', 'utf8').slice(0, 0).length); +assert.strictEqual(Buffer.from('hello', 'utf8').slice(0, 0).length, 0); { // Regression tests for https://github.com/nodejs/node/issues/9096 diff --git a/test/parallel/test-buffer-writeuint.js b/test/parallel/test-buffer-writeuint.js index b0d49240dc6b90..346bb589a72b50 100644 --- a/test/parallel/test-buffer-writeuint.js +++ b/test/parallel/test-buffer-writeuint.js @@ -84,6 +84,18 @@ const assert = require('assert'); data.writeUInt16BE(value, 0); assert.ok(data.equals(new Uint8Array([0xff, 0x80, 0x43, 0x23]))); + + value = 0xfffff; + ['writeUInt16BE', 'writeUInt16LE'].forEach((fn) => { + assert.throws( + () => data[fn](value, 0), + { + code: 'ERR_OUT_OF_RANGE', + message: 'The value of "value" is out of range. ' + + `It must be >= 0 and <= 65535. Received ${value}` + } + ); + }); } // Test 32 bit diff --git a/test/parallel/test-child-process-stdio.js b/test/parallel/test-child-process-stdio.js index 5ca3875f5600f6..a5e5f952259cee 100644 --- a/test/parallel/test-child-process-stdio.js +++ b/test/parallel/test-child-process-stdio.js @@ -60,8 +60,8 @@ const { spawn } = require('child_process'); })); child.on('close', common.mustCall(function() { - assert.strictEqual(true, output.length > 1); - assert.strictEqual('\n', output[output.length - 1]); + assert.strictEqual(output.length > 1, true); + assert.strictEqual(output[output.length - 1], '\n'); })); } diff --git a/test/parallel/test-console-instance.js b/test/parallel/test-console-instance.js index 0b69212948dd2c..91d130f260184b 100644 --- a/test/parallel/test-console-instance.js +++ b/test/parallel/test-console-instance.js @@ -33,7 +33,7 @@ const err = new Stream(); process.stdout.write = process.stderr.write = common.mustNotCall(); // Make sure that the "Console" function exists. -assert.strictEqual('function', typeof Console); +assert.strictEqual(typeof Console, 'function'); // Make sure that the Console constructor throws // when not given a writable stream instance. diff --git a/test/parallel/test-console.js b/test/parallel/test-console.js index a97e4cf33f8603..0898e964069204 100644 --- a/test/parallel/test-console.js +++ b/test/parallel/test-console.js @@ -168,6 +168,8 @@ assert.strictEqual(errStrings[errStrings.length - 1], console.assert(true, 'this should not throw'); +console.assert(true); + assert.strictEqual(strings.length, process.stdout.writeTimes); assert.strictEqual(errStrings.length, process.stderr.writeTimes); restoreStdout(); diff --git a/test/parallel/test-delayed-require.js b/test/parallel/test-delayed-require.js index 8aecb354698185..355d503d2650d2 100644 --- a/test/parallel/test-delayed-require.js +++ b/test/parallel/test-delayed-require.js @@ -26,7 +26,7 @@ const fixtures = require('../common/fixtures'); setTimeout(common.mustCall(function() { const a = require(fixtures.path('a')); - assert.strictEqual(true, 'A' in a); - assert.strictEqual('A', a.A()); - assert.strictEqual('D', a.D()); + assert.strictEqual('A' in a, true); + assert.strictEqual(a.A(), 'A'); + assert.strictEqual(a.D(), 'D'); }), 50); diff --git a/test/parallel/test-dgram-send-bad-arguments.js b/test/parallel/test-dgram-send-bad-arguments.js index 4eb7dca7a38e5d..20356ba50c477a 100644 --- a/test/parallel/test-dgram-send-bad-arguments.js +++ b/test/parallel/test-dgram-send-bad-arguments.js @@ -20,7 +20,7 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. 'use strict'; -require('../common'); +const common = require('../common'); const assert = require('assert'); const dgram = require('dgram'); @@ -28,9 +28,16 @@ const buf = Buffer.from('test'); const host = '127.0.0.1'; const sock = dgram.createSocket('udp4'); -assert.throws(() => { - sock.send(); -}, TypeError); // First argument should be a buffer. +// First argument should be a buffer. +common.expectsError( + () => { sock.send(); }, + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError, + message: 'The "buffer" argument must be one of type ' + + 'Buffer, Uint8Array, or string. Received type undefined' + } +); // send(buf, offset, length, port, host) assert.throws(() => { sock.send(buf, 1, 1, -1, host); }, RangeError); @@ -38,7 +45,23 @@ assert.throws(() => { sock.send(buf, 1, 1, 0, host); }, RangeError); assert.throws(() => { sock.send(buf, 1, 1, 65536, host); }, RangeError); // send(buf, port, host) -assert.throws(() => { sock.send(23, 12345, host); }, TypeError); +common.expectsError( + () => { sock.send(23, 12345, host); }, + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError, + message: 'The "buffer" argument must be one of type ' + + 'Buffer, Uint8Array, or string. Received type number' + } +); // send([buf1, ..], port, host) -assert.throws(() => { sock.send([buf, 23], 12345, host); }, TypeError); +common.expectsError( + () => { sock.send([buf, 23], 12345, host); }, + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError, + message: 'The "buffer list arguments" argument must be one of type ' + + 'Buffer or string. Received type object' + } +); diff --git a/test/parallel/test-errors-systemerror.js b/test/parallel/test-errors-systemerror.js index 957a0dd7b22196..0b5f9b9a107d59 100644 --- a/test/parallel/test-errors-systemerror.js +++ b/test/parallel/test-errors-systemerror.js @@ -111,3 +111,25 @@ const { ERR_TEST } = codes; assert.strictEqual(err.path, 'path'); assert.strictEqual(err.dest, 'path'); } + +{ + const ctx = { + code: 'ERR_TEST', + message: 'Error occurred', + syscall: 'syscall_test' + }; + assert.throws( + () => { + const err = new ERR_TEST(ctx); + err.name = 'SystemError [CUSTOM_ERR_TEST]'; + throw err; + }, + { + code: 'ERR_TEST', + name: 'SystemError [CUSTOM_ERR_TEST]', + message: 'custom message: syscall_test returned ERR_TEST ' + + '(Error occurred)', + info: ctx + } + ); +} diff --git a/test/parallel/test-event-emitter-add-listeners.js b/test/parallel/test-event-emitter-add-listeners.js index 45bfd3832caaaf..6ef39522183d4f 100644 --- a/test/parallel/test-event-emitter-add-listeners.js +++ b/test/parallel/test-event-emitter-add-listeners.js @@ -42,8 +42,8 @@ const EventEmitter = require('events'); }); const hello = common.mustCall(function(a, b) { - assert.strictEqual('a', a); - assert.strictEqual('b', b); + assert.strictEqual(a, 'a'); + assert.strictEqual(b, 'b'); }); ee.once('newListener', function(name, listener) { diff --git a/test/parallel/test-file-write-stream.js b/test/parallel/test-file-write-stream.js index 4860417dd29bc5..4d9df25d4cd2ac 100644 --- a/test/parallel/test-file-write-stream.js +++ b/test/parallel/test-file-write-stream.js @@ -44,7 +44,7 @@ file .on('open', function(fd) { console.error('open!'); callbacks.open++; - assert.strictEqual('number', typeof fd); + assert.strictEqual(typeof fd, 'number'); }) .on('error', function(err) { throw err; @@ -86,7 +86,7 @@ for (let i = 0; i < 11; i++) { process.on('exit', function() { for (const k in callbacks) { - assert.strictEqual(0, callbacks[k], `${k} count off by ${callbacks[k]}`); + assert.strictEqual(callbacks[k], 0, `${k} count off by ${callbacks[k]}`); } console.log('ok'); }); diff --git a/test/parallel/test-fs-error-messages.js b/test/parallel/test-fs-error-messages.js index e0c8e4b584f5b5..5e7c1ec1a4553a 100644 --- a/test/parallel/test-fs-error-messages.js +++ b/test/parallel/test-fs-error-messages.js @@ -25,15 +25,22 @@ const fixtures = require('../common/fixtures'); const tmpdir = require('../common/tmpdir'); const assert = require('assert'); const fs = require('fs'); +const path = require('path'); tmpdir.refresh(); -const nonexistentFile = fixtures.path('non-existent'); -const nonexistentDir = fixtures.path('non-existent', 'foo', 'bar'); -const existingFile = fixtures.path('exit.js'); -const existingFile2 = fixtures.path('a.js'); -const existingDir = tmpdir.path; + +const nonexistentFile = path.join(tmpdir.path, 'non-existent'); +const nonexistentDir = path.join(tmpdir.path, 'non-existent', 'foo', 'bar'); +const existingFile = path.join(tmpdir.path, 'existingFile.js'); +const existingFile2 = path.join(tmpdir.path, 'existingFile2.js'); +const existingDir = path.join(tmpdir.path, 'dir'); const existingDir2 = fixtures.path('keys'); +fs.mkdirSync(existingDir); +fs.writeFileSync(existingFile, 'test', 'utf-8'); +fs.writeFileSync(existingFile2, 'test', 'utf-8'); + + const { COPYFILE_EXCL } = fs.constants; const uv = process.binding('uv'); diff --git a/test/parallel/test-fs-link.js b/test/parallel/test-fs-link.js index d007f4e985b2d5..9b95fc3e026140 100644 --- a/test/parallel/test-fs-link.js +++ b/test/parallel/test-fs-link.js @@ -15,7 +15,7 @@ fs.writeFileSync(srcPath, 'hello world'); function callback(err) { assert.ifError(err); const dstContent = fs.readFileSync(dstPath, 'utf8'); - assert.strictEqual('hello world', dstContent); + assert.strictEqual(dstContent, 'hello world'); } fs.link(srcPath, dstPath, common.mustCall(callback)); diff --git a/test/parallel/test-fs-read-file-sync.js b/test/parallel/test-fs-read-file-sync.js index c8a9941b4990da..ee6f34ac4dccfd 100644 --- a/test/parallel/test-fs-read-file-sync.js +++ b/test/parallel/test-fs-read-file-sync.js @@ -29,6 +29,6 @@ const fn = fixtures.path('elipses.txt'); const s = fs.readFileSync(fn, 'utf8'); for (let i = 0; i < s.length; i++) { - assert.strictEqual('\u2026', s[i]); + assert.strictEqual(s[i], '\u2026'); } -assert.strictEqual(10000, s.length); +assert.strictEqual(s.length, 10000); diff --git a/test/parallel/test-fs-read-stream-fd-leak.js b/test/parallel/test-fs-read-stream-fd-leak.js index 5bf0157ff4e7ae..81712def761340 100644 --- a/test/parallel/test-fs-read-stream-fd-leak.js +++ b/test/parallel/test-fs-read-stream-fd-leak.js @@ -37,8 +37,8 @@ function testLeak(endFn, callback) { } assert.strictEqual( - 0, openCount, + 0, `no leaked file descriptors using ${endFn}() (got ${openCount})` ); diff --git a/test/parallel/test-fs-read-stream.js b/test/parallel/test-fs-read-stream.js index 870edf2820e87b..db9cf9a72fdadf 100644 --- a/test/parallel/test-fs-read-stream.js +++ b/test/parallel/test-fs-read-stream.js @@ -42,7 +42,7 @@ const rangeFile = fixtures.path('x.txt'); file.on('open', common.mustCall(function(fd) { file.length = 0; - assert.strictEqual('number', typeof fd); + assert.strictEqual(typeof fd, 'number'); assert.strictEqual(file.bytesRead, 0); assert.ok(file.readable); @@ -91,12 +91,12 @@ const rangeFile = fixtures.path('x.txt'); const file = fs.createReadStream(fn, { encoding: 'utf8' }); file.length = 0; file.on('data', function(data) { - assert.strictEqual('string', typeof data); + assert.strictEqual(typeof data, 'string'); file.length += data.length; for (let i = 0; i < data.length; i++) { // http://www.fileformat.info/info/unicode/char/2026/index.htm - assert.strictEqual('\u2026', data[i]); + assert.strictEqual(data[i], '\u2026'); } }); @@ -162,7 +162,7 @@ common.expectsError( }); stream.on('end', common.mustCall(function() { - assert.strictEqual('x', stream.data); + assert.strictEqual(stream.data, 'x'); })); } @@ -176,7 +176,7 @@ common.expectsError( }); stream.on('end', common.mustCall(function() { - assert.strictEqual('xy', stream.data); + assert.strictEqual(stream.data, 'xy'); })); } @@ -197,7 +197,7 @@ if (!common.isWindows) { }); stream.on('end', common.mustCall(function() { - assert.strictEqual('xy', stream.data); + assert.strictEqual(stream.data, 'xy'); fs.unlinkSync(filename); })); } else { diff --git a/test/parallel/test-fs-readfile-empty.js b/test/parallel/test-fs-readfile-empty.js index 36eccfb1162713..7bb942fc2d6fe3 100644 --- a/test/parallel/test-fs-readfile-empty.js +++ b/test/parallel/test-fs-readfile-empty.js @@ -35,12 +35,12 @@ fs.readFile(fn, function(err, data) { }); fs.readFile(fn, 'utf8', function(err, data) { - assert.strictEqual('', data); + assert.strictEqual(data, ''); }); fs.readFile(fn, { encoding: 'utf8' }, function(err, data) { - assert.strictEqual('', data); + assert.strictEqual(data, ''); }); assert.ok(fs.readFileSync(fn)); -assert.strictEqual('', fs.readFileSync(fn, 'utf8')); +assert.strictEqual(fs.readFileSync(fn, 'utf8'), ''); diff --git a/test/parallel/test-fs-readfile-fd.js b/test/parallel/test-fs-readfile-fd.js index 7458af7b2e53af..b5d2a33e285f5f 100644 --- a/test/parallel/test-fs-readfile-fd.js +++ b/test/parallel/test-fs-readfile-fd.js @@ -17,7 +17,7 @@ tempFd(function(fd, close) { tempFd(function(fd, close) { fs.readFile(fd, 'utf8', function(err, data) { - assert.strictEqual('', data); + assert.strictEqual(data, ''); close(); }); }); @@ -27,7 +27,7 @@ tempFdSync(function(fd) { }); tempFdSync(function(fd) { - assert.strictEqual('', fs.readFileSync(fd, 'utf8')); + assert.strictEqual(fs.readFileSync(fd, 'utf8'), ''); }); function tempFd(callback) { diff --git a/test/parallel/test-fs-write-buffer.js b/test/parallel/test-fs-write-buffer.js index 6e6154642a583d..0ff9fd69a82a3a 100644 --- a/test/parallel/test-fs-write-buffer.js +++ b/test/parallel/test-fs-write-buffer.js @@ -58,11 +58,11 @@ tmpdir.refresh(); const cb = common.mustCall((err, written) => { assert.ifError(err); - assert.strictEqual(2, written); + assert.strictEqual(written, 2); fs.closeSync(fd); const found = fs.readFileSync(filename, 'utf8'); - assert.strictEqual('lo', found); + assert.strictEqual(found, 'lo'); }); fs.write(fd, Buffer.from('hello'), 3, cb); diff --git a/test/parallel/test-fs-write-sync.js b/test/parallel/test-fs-write-sync.js index 4ca7a1dd570eb0..1873c44fb9ae33 100644 --- a/test/parallel/test-fs-write-sync.js +++ b/test/parallel/test-fs-write-sync.js @@ -34,7 +34,7 @@ tmpdir.refresh(); const fd = fs.openSync(filename, 'w'); let written = fs.writeSync(fd, ''); - assert.strictEqual(0, written); + assert.strictEqual(written, 0); fs.writeSync(fd, 'foo'); @@ -50,7 +50,7 @@ tmpdir.refresh(); const fd = fs.openSync(filename, 'w'); let written = fs.writeSync(fd, ''); - assert.strictEqual(0, written); + assert.strictEqual(written, 0); fs.writeSync(fd, 'foo'); @@ -66,7 +66,7 @@ tmpdir.refresh(); const fd = fs.openSync(filename, 'w'); let written = fs.writeSync(fd, ''); - assert.strictEqual(0, written); + assert.strictEqual(written, 0); fs.writeSync(fd, 'foo'); diff --git a/test/parallel/test-gc-http-client-onerror.js b/test/parallel/test-gc-http-client-onerror.js index 28a8aecd27e794..30b272ed94aae9 100644 --- a/test/parallel/test-gc-http-client-onerror.js +++ b/test/parallel/test-gc-http-client-onerror.js @@ -6,6 +6,8 @@ const common = require('../common'); const onGC = require('../common/ongc'); +const cpus = require('os').cpus().length; + function serverHandler(req, res) { req.resume(); res.writeHead(200, { 'Content-Type': 'text/plain' }); @@ -13,38 +15,35 @@ function serverHandler(req, res) { } const http = require('http'); -const todo = 500; +let createClients = true; let done = 0; let count = 0; let countGC = 0; -console.log(`We should do ${todo} requests`); - const server = http.createServer(serverHandler); server.listen(0, common.mustCall(() => { - for (let i = 0; i < 10; i++) - getall(); + for (let i = 0; i < cpus; i++) + getAll(); })); -function getall() { - if (count >= todo) - return; - - const req = http.get({ - hostname: 'localhost', - pathname: '/', - port: server.address().port - }, cb).on('error', onerror); +function getAll() { + if (createClients) { + const req = http.get({ + hostname: 'localhost', + pathname: '/', + port: server.address().port + }, cb).on('error', onerror); - count++; - onGC(req, { ongc }); + count++; + onGC(req, { ongc }); - setImmediate(getall); + setImmediate(getAll); + } } function cb(res) { res.resume(); - done += 1; + done++; } function onerror(err) { @@ -55,11 +54,19 @@ function ongc() { countGC++; } -setInterval(status, 100).unref(); +setImmediate(status); function status() { - global.gc(); - console.log('Done: %d/%d', done, todo); - console.log('Collected: %d/%d', countGC, count); - if (countGC === todo) server.close(); + if (done > 0) { + createClients = false; + global.gc(); + console.log(`done/collected/total: ${done}/${countGC}/${count}`); + if (countGC === count) { + server.close(); + } else { + setImmediate(status); + } + } else { + setImmediate(status); + } } diff --git a/test/parallel/test-http-1.0.js b/test/parallel/test-http-1.0.js index 47df50e2897b79..134a5bb9853102 100644 --- a/test/parallel/test-http-1.0.js +++ b/test/parallel/test-http-1.0.js @@ -58,9 +58,9 @@ function test(handler, request_generator, response_validator) { { function handler(req, res) { - assert.strictEqual('1.0', req.httpVersion); - assert.strictEqual(1, req.httpVersionMajor); - assert.strictEqual(0, req.httpVersionMinor); + assert.strictEqual(req.httpVersion, '1.0'); + assert.strictEqual(req.httpVersionMajor, 1); + assert.strictEqual(req.httpVersionMinor, 0); res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end(body); } @@ -72,8 +72,8 @@ function test(handler, request_generator, response_validator) { function response_validator(server_response, client_got_eof, timed_out) { const m = server_response.split('\r\n\r\n'); assert.strictEqual(m[1], body); - assert.strictEqual(true, client_got_eof); - assert.strictEqual(false, timed_out); + assert.strictEqual(client_got_eof, true); + assert.strictEqual(timed_out, false); } test(handler, request_generator, response_validator); @@ -86,9 +86,9 @@ function test(handler, request_generator, response_validator) { // { function handler(req, res) { - assert.strictEqual('1.0', req.httpVersion); - assert.strictEqual(1, req.httpVersionMajor); - assert.strictEqual(0, req.httpVersionMinor); + assert.strictEqual(req.httpVersion, '1.0'); + assert.strictEqual(req.httpVersionMajor, 1); + assert.strictEqual(req.httpVersionMinor, 0); res.sendDate = false; res.writeHead(200, { 'Content-Type': 'text/plain' }); res.write('Hello, '); res._send(''); @@ -112,9 +112,9 @@ function test(handler, request_generator, response_validator) { '\r\n' + 'Hello, world!'; - assert.strictEqual(expected_response, server_response); - assert.strictEqual(true, client_got_eof); - assert.strictEqual(false, timed_out); + assert.strictEqual(server_response, expected_response); + assert.strictEqual(client_got_eof, true); + assert.strictEqual(timed_out, false); } test(handler, request_generator, response_validator); @@ -122,9 +122,9 @@ function test(handler, request_generator, response_validator) { { function handler(req, res) { - assert.strictEqual('1.1', req.httpVersion); - assert.strictEqual(1, req.httpVersionMajor); - assert.strictEqual(1, req.httpVersionMinor); + assert.strictEqual(req.httpVersion, '1.1'); + assert.strictEqual(req.httpVersionMajor, 1); + assert.strictEqual(req.httpVersionMinor, 1); res.sendDate = false; res.writeHead(200, { 'Content-Type': 'text/plain' }); res.write('Hello, '); res._send(''); @@ -155,9 +155,9 @@ function test(handler, request_generator, response_validator) { '0\r\n' + '\r\n'; - assert.strictEqual(expected_response, server_response); - assert.strictEqual(true, client_got_eof); - assert.strictEqual(false, timed_out); + assert.strictEqual(server_response, expected_response); + assert.strictEqual(client_got_eof, true); + assert.strictEqual(timed_out, false); } test(handler, request_generator, response_validator); diff --git a/test/parallel/test-http-blank-header.js b/test/parallel/test-http-blank-header.js index 40377fb6684db4..3f2b512fc85567 100644 --- a/test/parallel/test-http-blank-header.js +++ b/test/parallel/test-http-blank-header.js @@ -26,8 +26,8 @@ const http = require('http'); const net = require('net'); const server = http.createServer(common.mustCall((req, res) => { - assert.strictEqual('GET', req.method); - assert.strictEqual('/blah', req.url); + assert.strictEqual(req.method, 'GET'); + assert.strictEqual(req.url, '/blah'); assert.deepStrictEqual({ host: 'example.org:443', origin: 'http://example.org', diff --git a/test/parallel/test-http-chunked.js b/test/parallel/test-http-chunked.js index 9ae2932a5c4149..264a87be6adc7f 100644 --- a/test/parallel/test-http-chunked.js +++ b/test/parallel/test-http-chunked.js @@ -48,7 +48,7 @@ server.listen(0, common.mustCall(() => { x.setEncoding('utf8'); x.on('data', (c) => data += c); x.on('end', common.mustCall(() => { - assert.strictEqual('string', typeof data); + assert.strictEqual(typeof data, 'string'); assert.strictEqual(UTF8_STRING, data); server.close(); })); diff --git a/test/parallel/test-http-client-timeout-on-connect.js b/test/parallel/test-http-client-timeout-on-connect.js index 928f781e261758..3a0098229d9af8 100644 --- a/test/parallel/test-http-client-timeout-on-connect.js +++ b/test/parallel/test-http-client-timeout-on-connect.js @@ -24,7 +24,7 @@ server.listen(0, common.localhostIPv4, common.mustCall(() => { })); req.on('timeout', common.mustCall(() => req.abort())); req.on('error', common.mustCall((err) => { - assert.strictEqual('socket hang up', err.message); + assert.strictEqual(err.message, 'socket hang up'); server.close(); })); })); diff --git a/test/parallel/test-http-client-upload-buf.js b/test/parallel/test-http-client-upload-buf.js index b778d07a826b1d..1c75612c807874 100644 --- a/test/parallel/test-http-client-upload-buf.js +++ b/test/parallel/test-http-client-upload-buf.js @@ -27,8 +27,7 @@ const http = require('http'); const N = 1024; const server = http.createServer(common.mustCall(function(req, res) { - assert.strictEqual('POST', req.method); - + assert.strictEqual(req.method, 'POST'); let bytesReceived = 0; req.on('data', function(chunk) { diff --git a/test/parallel/test-http-client-upload.js b/test/parallel/test-http-client-upload.js index 000bf1d58424a3..830c37da8ef567 100644 --- a/test/parallel/test-http-client-upload.js +++ b/test/parallel/test-http-client-upload.js @@ -25,7 +25,7 @@ const assert = require('assert'); const http = require('http'); const server = http.createServer(common.mustCall(function(req, res) { - assert.strictEqual('POST', req.method); + assert.strictEqual(req.method, 'POST'); req.setEncoding('utf8'); let sent_body = ''; @@ -36,7 +36,7 @@ const server = http.createServer(common.mustCall(function(req, res) { }); req.on('end', common.mustCall(function() { - assert.strictEqual('1\n2\n3\n', sent_body); + assert.strictEqual(sent_body, '1\n2\n3\n'); console.log('request complete from server'); res.writeHead(200, { 'Content-Type': 'text/plain' }); res.write('hello\n'); diff --git a/test/parallel/test-http-expect-continue.js b/test/parallel/test-http-expect-continue.js index eb4dd23d7b552f..10bcb9d568ff35 100644 --- a/test/parallel/test-http-expect-continue.js +++ b/test/parallel/test-http-expect-continue.js @@ -67,7 +67,7 @@ server.on('listening', common.mustCall(() => { })); req.on('response', common.mustCall((res) => { assert.ok(got_continue, 'Full response received before 100 Continue'); - assert.strictEqual(200, res.statusCode, + assert.strictEqual(res.statusCode, 200, `Final status code was ${res.statusCode}, not 200.`); res.setEncoding('utf8'); res.on('data', function(chunk) { body += chunk; }); diff --git a/test/parallel/test-http-max-header-size.js b/test/parallel/test-http-max-header-size.js new file mode 100644 index 00000000000000..07fbe902963525 --- /dev/null +++ b/test/parallel/test-http-max-header-size.js @@ -0,0 +1,11 @@ +'use strict'; + +require('../common'); +const assert = require('assert'); +const { spawnSync } = require('child_process'); +const http = require('http'); + +assert.strictEqual(http.maxHeaderSize, 8 * 1024); +const child = spawnSync(process.execPath, ['--max-http-header-size=10', '-p', + 'http.maxHeaderSize']); +assert.strictEqual(+child.stdout.toString().trim(), 10); diff --git a/test/parallel/test-http-outgoing-settimeout.js b/test/parallel/test-http-outgoing-settimeout.js new file mode 100644 index 00000000000000..3dd27686153672 --- /dev/null +++ b/test/parallel/test-http-outgoing-settimeout.js @@ -0,0 +1,30 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); + +const { OutgoingMessage } = require('http'); + +{ + // tests for settimeout method with socket + const expectedMsecs = 42; + const outgoingMessage = new OutgoingMessage(); + outgoingMessage.socket = { + setTimeout: common.mustCall((msecs) => { + assert.strictEqual(msecs, expectedMsecs); + }) + }; + outgoingMessage.setTimeout(expectedMsecs); +} + +{ + // tests for settimeout method without socket + const expectedMsecs = 23; + const outgoingMessage = new OutgoingMessage(); + outgoingMessage.setTimeout(expectedMsecs); + + outgoingMessage.emit('socket', { + setTimeout: common.mustCall((msecs) => { + assert.strictEqual(msecs, expectedMsecs); + }) + }); +} diff --git a/test/parallel/test-http-parser-lazy-loaded.js b/test/parallel/test-http-parser-lazy-loaded.js new file mode 100644 index 00000000000000..c1eb29fb163d00 --- /dev/null +++ b/test/parallel/test-http-parser-lazy-loaded.js @@ -0,0 +1,37 @@ +// Flags: --expose-internals + +'use strict'; + +const { internalBinding } = require('internal/test/binding'); + +// Monkey patch before requiring anything +class DummyParser { + constructor(type) { + this.test_type = type; + } +} +DummyParser.REQUEST = Symbol(); +internalBinding('http_parser').HTTPParser = DummyParser; + +const common = require('../common'); +const assert = require('assert'); +const { spawn } = require('child_process'); +const { parsers } = require('_http_common'); + +// Test _http_common was not loaded before monkey patching +const parser = parsers.alloc(); +assert.strictEqual(parser instanceof DummyParser, true); +assert.strictEqual(parser.test_type, DummyParser.REQUEST); + +if (process.argv[2] !== 'child') { + // Also test in a child process with IPC (specific case of https://github.com/nodejs/node/issues/23716) + const child = spawn(process.execPath, [ + '--expose-internals', __filename, 'child' + ], { + stdio: ['inherit', 'inherit', 'inherit', 'ipc'] + }); + child.on('exit', common.mustCall((code, signal) => { + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + })); +} diff --git a/test/parallel/test-net-connect-options-fd.js b/test/parallel/test-net-connect-options-fd.js index 76a5e30755b15c..8a53c3df928b25 100644 --- a/test/parallel/test-net-connect-options-fd.js +++ b/test/parallel/test-net-connect-options-fd.js @@ -68,7 +68,7 @@ const forAllClients = (cb) => common.mustCall(cb, CLIENT_VARIANTS); }) .on('error', function(err) { console.error(err); - assert.fail(null, null, `[Pipe server]${err}`); + assert.fail(`[Pipe server]${err}`); }) .listen({ path: serverPath }, common.mustCall(function serverOnListen() { const getSocketOpt = (index) => { @@ -92,7 +92,7 @@ const forAllClients = (cb) => common.mustCall(cb, CLIENT_VARIANTS); console.error(`[Pipe]Sending data through fd ${oldHandle.fd}`); this.on('error', function(err) { console.error(err); - assert.fail(null, null, `[Pipe Client]${err}`); + assert.fail(`[Pipe Client]${err}`); }); }); diff --git a/test/parallel/test-net-eaddrinuse.js b/test/parallel/test-net-eaddrinuse.js index 8c3bcc6cf142dc..29508e4582852e 100644 --- a/test/parallel/test-net-eaddrinuse.js +++ b/test/parallel/test-net-eaddrinuse.js @@ -30,7 +30,7 @@ const server2 = net.createServer(function(socket) { }); server1.listen(0, function() { server2.on('error', function(error) { - assert.strictEqual(true, error.message.includes('EADDRINUSE')); + assert.strictEqual(error.message.includes('EADDRINUSE'), true); server1.close(); }); server2.listen(this.address().port); diff --git a/test/parallel/test-net-stream.js b/test/parallel/test-net-stream.js index a6ec4548ada6ea..4e7e06bfcf2546 100644 --- a/test/parallel/test-net-stream.js +++ b/test/parallel/test-net-stream.js @@ -34,11 +34,11 @@ s.server = new net.Server(); s.server.connections = 10; s._server = s.server; -assert.strictEqual(10, s.server.connections); +assert.strictEqual(s.server.connections, 10); s.destroy(); -assert.strictEqual(9, s.server.connections); +assert.strictEqual(s.server.connections, 9); s.destroy(); -assert.strictEqual(9, s.server.connections); +assert.strictEqual(s.server.connections, 9); const SIZE = 2E6; const N = 10; @@ -69,5 +69,5 @@ const server = net.createServer(function(socket) { }); process.on('exit', function() { - assert.strictEqual(0, server.connections); + assert.strictEqual(server.connections, 0); }); diff --git a/test/parallel/test-readline-keys.js b/test/parallel/test-readline-keys.js index f739999110b12f..b1c88e2acee157 100644 --- a/test/parallel/test-readline-keys.js +++ b/test/parallel/test-readline-keys.js @@ -99,15 +99,21 @@ addTest('\n\r\t', [ ]); // space and backspace -addTest('\b\x7f\x1b\b\x1b\x7f \x1b ', [ +addTest('\b\x7f\x1b\b\x1b\x7f\x1b\x1b \x1b ', [ { name: 'backspace', sequence: '\b' }, { name: 'backspace', sequence: '\x7f' }, { name: 'backspace', sequence: '\x1b\b', meta: true }, { name: 'backspace', sequence: '\x1b\x7f', meta: true }, + { name: 'space', sequence: '\x1b\x1b ', meta: true }, { name: 'space', sequence: ' ' }, { name: 'space', sequence: '\x1b ', meta: true }, ]); +// escape key +addTest('\x1b\x1b\x1b', [ + { name: 'escape', sequence: '\x1b\x1b\x1b', meta: true }, +]); + // control keys addTest('\x01\x0b\x10', [ { name: 'a', sequence: '\x01', ctrl: true }, diff --git a/test/parallel/test-stream-write-destroy.js b/test/parallel/test-stream-write-destroy.js new file mode 100644 index 00000000000000..83b329a6a8a7b3 --- /dev/null +++ b/test/parallel/test-stream-write-destroy.js @@ -0,0 +1,59 @@ +'use strict'; +require('../common'); +const assert = require('assert'); +const { Writable } = require('stream'); + +// Test interaction between calling .destroy() on a writable and pending +// writes. + +for (const withPendingData of [ false, true ]) { + for (const useEnd of [ false, true ]) { + const callbacks = []; + + const w = new Writable({ + write(data, enc, cb) { + callbacks.push(cb); + }, + // Effectively disable the HWM to observe 'drain' events more easily. + highWaterMark: 1 + }); + + let chunksWritten = 0; + let drains = 0; + let finished = false; + w.on('drain', () => drains++); + w.on('finish', () => finished = true); + + w.write('abc', () => chunksWritten++); + assert.strictEqual(chunksWritten, 0); + assert.strictEqual(drains, 0); + callbacks.shift()(); + assert.strictEqual(chunksWritten, 1); + assert.strictEqual(drains, 1); + + if (withPendingData) { + // Test 2 cases: There either is or is not data still in the write queue. + // (The second write will never actually get executed either way.) + w.write('def', () => chunksWritten++); + } + if (useEnd) { + // Again, test 2 cases: Either we indicate that we want to end the + // writable or not. + w.end('ghi', () => chunksWritten++); + } else { + w.write('ghi', () => chunksWritten++); + } + + assert.strictEqual(chunksWritten, 1); + w.destroy(); + assert.strictEqual(chunksWritten, 1); + callbacks.shift()(); + assert.strictEqual(chunksWritten, 2); + assert.strictEqual(callbacks.length, 0); + assert.strictEqual(drains, 1); + + // When we used `.end()`, we see the 'finished' event if and only if + // we actually finished processing the write queue. + assert.strictEqual(finished, !withPendingData && useEnd); + } +} diff --git a/test/parallel/test-string-decoder.js b/test/parallel/test-string-decoder.js index c4607672b0420c..37902c5ccbc5fd 100644 --- a/test/parallel/test-string-decoder.js +++ b/test/parallel/test-string-decoder.js @@ -217,7 +217,7 @@ function test(encoding, input, expected, singleSequence) { `input: ${input.toString('hex').match(hexNumberRE)}\n` + `Write sequence: ${JSON.stringify(sequence)}\n` + `Full Decoder State: ${inspect(decoder)}`; - assert.fail(output, expected, message); + assert.fail(message); } }); } diff --git a/test/parallel/test-tls-basic-validations.js b/test/parallel/test-tls-basic-validations.js index 3840acc0243898..b5987251a71b13 100644 --- a/test/parallel/test-tls-basic-validations.js +++ b/test/parallel/test-tls-basic-validations.js @@ -115,3 +115,16 @@ common.expectsError( tls.convertNPNProtocols(buffer, out); assert(out.NPNProtocols.equals(Buffer.from('abcd'))); } + +{ + const protocols = [(new String('a')).repeat(500)]; + const out = {}; + common.expectsError( + () => tls.convertALPNProtocols(protocols, out), + { + code: 'ERR_OUT_OF_RANGE', + message: 'The byte length of the protocol at index 0 exceeds the ' + + 'maximum length. It must be <= 255. Received 500' + } + ); +} diff --git a/test/parallel/test-tracing-no-crash.js b/test/parallel/test-tracing-no-crash.js index 5b11522911e75d..0ae402f5288cca 100644 --- a/test/parallel/test-tracing-no-crash.js +++ b/test/parallel/test-tracing-no-crash.js @@ -8,7 +8,15 @@ function CheckNoSignalAndErrorCodeOne(code, signal) { assert.strictEqual(code, 1); } -const child = spawn(process.execPath, - ['--trace-event-categories', 'madeup', '-e', - 'throw new Error()'], { stdio: 'inherit' }); +const child = spawn(process.execPath, [ + '--trace-event-categories', 'madeup', '-e', 'throw new Error()' +], { stdio: [ 'inherit', 'inherit', 'pipe' ] }); child.on('exit', common.mustCall(CheckNoSignalAndErrorCodeOne)); + +let stderr; +child.stderr.setEncoding('utf8'); +child.stderr.on('data', (chunk) => stderr += chunk); +child.stderr.on('end', common.mustCall(() => { + assert(stderr.includes('throw new Error()'), stderr); + assert(!stderr.includes('Could not open trace file'), stderr); +})); diff --git a/test/parallel/test-util-isDeepStrictEqual.js b/test/parallel/test-util-isDeepStrictEqual.js index 938781a43084a5..fd585f7ccf0f1e 100644 --- a/test/parallel/test-util-isDeepStrictEqual.js +++ b/test/parallel/test-util-isDeepStrictEqual.js @@ -459,10 +459,13 @@ utilIsDeepStrict(-0, -0); const obj1 = { [symbol1]: 1 }; const obj2 = { [symbol1]: 1 }; const obj3 = { [Symbol()]: 1 }; + const obj4 = { }; // Add a non enumerable symbol as well. It is going to be ignored! Object.defineProperty(obj2, Symbol(), { value: 1 }); + Object.defineProperty(obj4, symbol1, { value: 1 }); notUtilIsDeepStrict(obj1, obj3); utilIsDeepStrict(obj1, obj2); + notUtilIsDeepStrict(obj1, obj4); // TypedArrays have a fast path. Test for this as well. const a = new Uint8Array(4); const b = new Uint8Array(4); diff --git a/test/parallel/test-vm-create-and-run-in-context.js b/test/parallel/test-vm-create-and-run-in-context.js index 8f4ce72c50f246..bd746cf2df7080 100644 --- a/test/parallel/test-vm-create-and-run-in-context.js +++ b/test/parallel/test-vm-create-and-run-in-context.js @@ -29,7 +29,7 @@ const vm = require('vm'); // Run in a new empty context let context = vm.createContext(); let result = vm.runInContext('"passed";', context); -assert.strictEqual('passed', result); +assert.strictEqual(result, 'passed'); // Create a new pre-populated context context = vm.createContext({ 'foo': 'bar', 'thing': 'lala' }); diff --git a/test/parallel/test-whatwg-url-custom-no-enumerable-context.js b/test/parallel/test-whatwg-url-custom-no-enumerable-context.js new file mode 100644 index 00000000000000..f24a47b6d5c8f0 --- /dev/null +++ b/test/parallel/test-whatwg-url-custom-no-enumerable-context.js @@ -0,0 +1,14 @@ +'use strict'; +// This tests that the context of URL objects are not +// enumerable and thus considered by assert libraries. +// See https://github.com/nodejs/node/issues/24211 + +// Tests below are not from WPT. + +require('../common'); +const assert = require('assert'); + +assert.deepStrictEqual( + new URL('./foo', 'https://example.com/'), + new URL('https://example.com/foo') +); diff --git a/test/parallel/test-zlib-close-in-ondata.js b/test/parallel/test-zlib-close-in-ondata.js new file mode 100644 index 00000000000000..44d996311dca13 --- /dev/null +++ b/test/parallel/test-zlib-close-in-ondata.js @@ -0,0 +1,10 @@ +'use strict'; + +const common = require('../common'); +const zlib = require('zlib'); + +const ts = zlib.createGzip(); +const buf = Buffer.alloc(1024 * 1024 * 20); + +ts.on('data', common.mustCall(() => ts.close())); +ts.end(buf); diff --git a/test/parallel/test-zlib-destroy.js b/test/parallel/test-zlib-destroy.js new file mode 100644 index 00000000000000..d8eab42186a5fa --- /dev/null +++ b/test/parallel/test-zlib-destroy.js @@ -0,0 +1,13 @@ +'use strict'; + +require('../common'); + +const assert = require('assert'); +const zlib = require('zlib'); + +// verify that the zlib transform does clean up +// the handle when calling destroy. + +const ts = zlib.createGzip(); +ts.destroy(); +assert.strictEqual(ts._handle, null); diff --git a/test/pseudo-tty/test-tty-get-color-depth.js b/test/pseudo-tty/test-tty-get-color-depth.js index d802add1189db2..d4062f5fdb6d39 100644 --- a/test/pseudo-tty/test-tty-get-color-depth.js +++ b/test/pseudo-tty/test-tty-get-color-depth.js @@ -2,7 +2,6 @@ const common = require('../common'); const assert = require('assert').strict; -/* eslint-disable no-restricted-properties */ const { WriteStream } = require('tty'); const fd = common.getTTYfd(); @@ -10,7 +9,7 @@ const writeStream = new WriteStream(fd); { const depth = writeStream.getColorDepth(); - assert.equal(typeof depth, 'number'); + assert.strictEqual(typeof depth, 'number'); assert(depth >= 1 && depth <= 24); } @@ -44,7 +43,7 @@ const writeStream = new WriteStream(fd); [{ TERM: 'dumb', COLORTERM: '1' }, 4], ].forEach(([env, depth], i) => { const actual = writeStream.getColorDepth(env); - assert.equal( + assert.strictEqual( actual, depth, `i: ${i}, expected: ${depth}, actual: ${actual}, env: ${env}` @@ -57,8 +56,8 @@ const writeStream = new WriteStream(fd); const [ value, depth1, depth2 ] = process.platform !== 'win32' ? ['win32', 1, 4] : ['linux', 4, 1]; - assert.equal(writeStream.getColorDepth({}), depth1); + assert.strictEqual(writeStream.getColorDepth({}), depth1); Object.defineProperty(process, 'platform', { value }); - assert.equal(writeStream.getColorDepth({}), depth2); + assert.strictEqual(writeStream.getColorDepth({}), depth2); Object.defineProperty(process, 'platform', platform); } diff --git a/test/sequential/test-fs-watch-system-limit.js b/test/pummel/test-fs-watch-system-limit.js similarity index 100% rename from test/sequential/test-fs-watch-system-limit.js rename to test/pummel/test-fs-watch-system-limit.js diff --git a/test/root.status b/test/root.status index 9ed9004c2169d0..9c40512cb68051 100644 --- a/test/root.status +++ b/test/root.status @@ -9,27 +9,6 @@ async-hooks/test-tlswrap: SLOW async-hooks/test-tlswrap: SLOW message/eval_messages: SLOW message/stdin_messages: SLOW -parallel/test-benchmark-assert: SLOW -parallel/test-benchmark-cluster: SLOW -parallel/test-benchmark-crypto: SLOW -parallel/test-benchmark-dns: SLOW -parallel/test-benchmark-domain: SLOW -parallel/test-benchmark-es: SLOW -parallel/test-benchmark-events: SLOW -parallel/test-benchmark-fs: SLOW -parallel/test-benchmark-misc: SLOW -parallel/test-benchmark-module: SLOW -parallel/test-benchmark-os: SLOW -parallel/test-benchmark-process: SLOW -parallel/test-benchmark-querystring: SLOW -parallel/test-benchmark-streams: SLOW -parallel/test-benchmark-string_decoder: SLOW -parallel/test-benchmark-timers: SLOW -parallel/test-benchmark-url: SLOW -parallel/test-benchmark-util: SLOW -parallel/test-benchmark-v8: SLOW -parallel/test-benchmark-vm: SLOW -parallel/test-benchmark-zlib: SLOW parallel/test-buffer-constructor-node-modules-paths: SLOW parallel/test-buffer-indexof: SLOW parallel/test-child-process-spawnsync-input: SLOW @@ -165,13 +144,6 @@ parallel/test-worker-unsupported-things: SLOW parallel/test-worker-workerdata-sharedarraybuffer: SLOW parallel/test-zlib-bytes-read: SLOW parallel/test-zlib-convenience-methods: SLOW -sequential/test-benchmark-buffer: SLOW -sequential/test-benchmark-child-process: SLOW -sequential/test-benchmark-dgram: SLOW -sequential/test-benchmark-http: SLOW -sequential/test-benchmark-net: SLOW -sequential/test-benchmark-path: SLOW -sequential/test-benchmark-tls: SLOW sequential/test-child-process-execsync: SLOW sequential/test-child-process-exit: SLOW sequential/test-child-process-pass-fd: SLOW diff --git a/test/sequential/test-http-max-http-headers.js b/test/sequential/test-http-max-http-headers.js index ae76142a4fd077..b9a37ac71ab79e 100644 --- a/test/sequential/test-http-max-http-headers.js +++ b/test/sequential/test-http-max-http-headers.js @@ -1,10 +1,16 @@ +// Flags: --expose-internals 'use strict'; const assert = require('assert'); const common = require('../common'); const http = require('http'); const net = require('net'); -const MAX = 8 * 1024; // 8KB +const MAX = +(process.argv[2] || 8 * 1024); // Command line option, or 8KB. + +const { getOptionValue } = require('internal/options'); + +console.log('pid is', process.pid); +console.log('max header size is', getOptionValue('--max-http-header-size')); // Verify that we cannot receive more than 8KB of headers. @@ -28,19 +34,15 @@ function fillHeaders(headers, currentSize, valid = false) { headers += 'a'.repeat(MAX - headers.length - 3); // Generate valid headers if (valid) { - // TODO(mcollina): understand why -9 is needed instead of -1 - headers = headers.slice(0, -9); + // TODO(mcollina): understand why -32 is needed instead of -1 + headers = headers.slice(0, -32); } return headers + '\r\n\r\n'; } -const timeout = common.platformTimeout(10); - function writeHeaders(socket, headers) { const array = []; - - // this is off from 1024 so that \r\n does not get split - const chunkSize = 1000; + const chunkSize = 100; let last = 0; for (let i = 0; i < headers.length / chunkSize; i++) { @@ -55,19 +57,25 @@ function writeHeaders(socket, headers) { next(); function next() { - if (socket.write(array.shift())) { - if (array.length === 0) { - socket.end(); - } else { - setTimeout(next, timeout); - } + if (socket.destroyed) { + console.log('socket was destroyed early, data left to write:', + array.join('').length); + return; + } + + const chunk = array.shift(); + + if (chunk) { + console.log('writing chunk of size', chunk.length); + socket.write(chunk, next); } else { - socket.once('drain', next); + socket.end(); } } } function test1() { + console.log('test1'); let headers = 'HTTP/1.1 200 OK\r\n' + 'Content-Length: 0\r\n' + @@ -82,6 +90,9 @@ function test1() { writeHeaders(sock, headers); sock.resume(); }); + + // The socket might error but that's ok + sock.on('error', () => {}); }); server.listen(0, common.mustCall(() => { @@ -90,17 +101,17 @@ function test1() { client.on('error', common.mustCall((err) => { assert.strictEqual(err.code, 'HPE_HEADER_OVERFLOW'); - server.close(); - setImmediate(test2); + server.close(test2); })); })); } const test2 = common.mustCall(() => { + console.log('test2'); let headers = 'GET / HTTP/1.1\r\n' + 'Host: localhost\r\n' + - 'Agent: node\r\n' + + 'Agent: nod2\r\n' + 'X-CRASH: '; // /, Host, localhost, Agent, node, X-CRASH, a... @@ -109,7 +120,7 @@ const test2 = common.mustCall(() => { const server = http.createServer(common.mustNotCall()); - server.on('clientError', common.mustCall((err) => { + server.once('clientError', common.mustCall((err) => { assert.strictEqual(err.code, 'HPE_HEADER_OVERFLOW'); })); @@ -121,34 +132,46 @@ const test2 = common.mustCall(() => { }); finished(client, common.mustCall((err) => { - server.close(); - setImmediate(test3); + server.close(test3); })); })); }); const test3 = common.mustCall(() => { + console.log('test3'); let headers = 'GET / HTTP/1.1\r\n' + 'Host: localhost\r\n' + - 'Agent: node\r\n' + + 'Agent: nod3\r\n' + 'X-CRASH: '; // /, Host, localhost, Agent, node, X-CRASH, a... const currentSize = 1 + 4 + 9 + 5 + 4 + 7; headers = fillHeaders(headers, currentSize, true); + console.log('writing', headers.length); + const server = http.createServer(common.mustCall((req, res) => { - res.end('hello world'); - setImmediate(server.close.bind(server)); + res.end('hello from test3 server'); + server.close(); })); + server.on('clientError', (err) => { + console.log(err.code); + if (err.code === 'HPE_HEADER_OVERFLOW') { + console.log(err.rawPacket.toString('hex')); + } + }); + server.on('clientError', common.mustNotCall()); + server.listen(0, common.mustCall(() => { const client = net.connect(server.address().port); client.on('connect', () => { writeHeaders(client, headers); client.resume(); }); + + client.pipe(process.stdout); })); }); diff --git a/test/sequential/test-inspector-module.js b/test/sequential/test-inspector-module.js index eaecd49c982311..26bb7fe9262889 100644 --- a/test/sequential/test-inspector-module.js +++ b/test/sequential/test-inspector-module.js @@ -46,6 +46,17 @@ session.post('Runtime.evaluate', { expression: '2 + 2' }); ); }); +[1, 'a', {}, [], true, Infinity].forEach((i) => { + common.expectsError( + () => session.post('test', {}, i), + { + code: 'ERR_INVALID_CALLBACK', + type: TypeError, + message: 'Callback must be a function' + } + ); +}); + common.expectsError( () => session.connect(), { diff --git a/test/sequential/test-set-http-max-http-headers.js b/test/sequential/test-set-http-max-http-headers.js new file mode 100644 index 00000000000000..7ec13f370784f8 --- /dev/null +++ b/test/sequential/test-set-http-max-http-headers.js @@ -0,0 +1,104 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const { spawn } = require('child_process'); +const path = require('path'); +const testName = path.join(__dirname, 'test-http-max-http-headers.js'); + +const timeout = common.platformTimeout(100); + +const tests = []; + +function test(fn) { + tests.push(fn); +} + +test(function(cb) { + console.log('running subtest expecting failure'); + + // Validate that the test fails if the max header size is too small. + const args = ['--expose-internals', + '--max-http-header-size=1024', + testName]; + const cp = spawn(process.execPath, args, { stdio: 'inherit' }); + + cp.on('close', common.mustCall((code, signal) => { + assert.strictEqual(code, 1); + assert.strictEqual(signal, null); + cb(); + })); +}); + +test(function(cb) { + console.log('running subtest expecting success'); + + const env = Object.assign({}, process.env, { + NODE_DEBUG: 'http' + }); + + // Validate that the test fails if the max header size is too small. + // Validate that the test now passes if the same limit becomes large enough. + const args = ['--expose-internals', + '--max-http-header-size=1024', + testName, + '1024']; + const cp = spawn(process.execPath, args, { + env, + stdio: 'inherit' + }); + + cp.on('close', common.mustCall((code, signal) => { + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + cb(); + })); +}); + +// Next, repeat the same checks using NODE_OPTIONS if it is supported. +if (process.config.variables.node_without_node_options) { + const env = Object.assign({}, process.env, { + NODE_OPTIONS: '--max-http-header-size=1024' + }); + + test(function(cb) { + console.log('running subtest expecting failure'); + + // Validate that the test fails if the max header size is too small. + const args = ['--expose-internals', testName]; + const cp = spawn(process.execPath, args, { env, stdio: 'inherit' }); + + cp.on('close', common.mustCall((code, signal) => { + assert.strictEqual(code, 1); + assert.strictEqual(signal, null); + cb(); + })); + }); + + test(function(cb) { + // Validate that the test now passes if the same limit + // becomes large enough. + const args = ['--expose-internals', testName, '1024']; + const cp = spawn(process.execPath, args, { env, stdio: 'inherit' }); + + cp.on('close', common.mustCall((code, signal) => { + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + cb(); + })); + }); +} + +function runTest() { + const fn = tests.shift(); + + if (!fn) { + return; + } + + fn(() => { + setTimeout(runTest, timeout); + }); +} + +runTest(); diff --git a/tools/make-v8.sh b/tools/make-v8.sh index 4365412856d741..1bbf472aae7df2 100755 --- a/tools/make-v8.sh +++ b/tools/make-v8.sh @@ -1,9 +1,27 @@ -#!/bin/bash +#!/bin/bash -xe BUILD_ARCH_TYPE=$1 V8_BUILD_OPTIONS=$2 cd deps/v8 tools/node/fetch_deps.py . -PATH=~/_depot_tools:$PATH tools/dev/v8gen.py $BUILD_ARCH_TYPE --no-goma $V8_BUILD_OPTIONS -PATH=~/_depot_tools:$PATH ninja -C out.gn/$BUILD_ARCH_TYPE/ d8 cctest inspector-test + +if [ "`arch`" == "s390x" ] +then + # set paths manually for now to use locally installed gn + export BUILD_TOOLS=/home/iojs/build-tools + export LD_LIBRARY_PATH=$BUILD_TOOLS:$LD_LIBRARY_PATH + export PATH=$BUILD_TOOLS:$PATH + CXX_PATH=`which $CXX |grep g++` + rm -f "$BUILD_TOOLS/g++" + rm -f "$BUILD_TOOLS/gcc" + ln -s $CXX_PATH "$BUILD_TOOLS/g++" + ln -s $CXX_PATH "$BUILD_TOOLS/gcc" + g++ --version + export PKG_CONFIG_PATH=$BUILD_TOOLS/pkg-config + gn gen -v out.gn/$BUILD_ARCH_TYPE --args='is_component_build=false is_debug=false use_goma=false goma_dir="None" use_custom_libcxx=false v8_target_cpu="s390x" target_cpu="s390x"' + ninja -v -C out.gn/$BUILD_ARCH_TYPE d8 cctest inspector-test +else + PATH=~/_depot_tools:$PATH tools/dev/v8gen.py $BUILD_ARCH_TYPE --no-goma $V8_BUILD_OPTIONS + PATH=~/_depot_tools:$PATH ninja -C out.gn/$BUILD_ARCH_TYPE/ d8 cctest inspector-test +fi diff --git a/tools/test.py b/tools/test.py index cd361196653043..3a464be61da1b3 100755 --- a/tools/test.py +++ b/tools/test.py @@ -1498,6 +1498,7 @@ def PrintCrashed(code): IGNORED_SUITES = [ 'addons', 'addons-napi', + 'benchmark', 'doctool', 'internet', 'pummel', diff --git a/vcbuild.bat b/vcbuild.bat index 8627dcb296fba7..81dd6087882d32 100644 --- a/vcbuild.bat +++ b/vcbuild.bat @@ -85,6 +85,7 @@ if /i "%1"=="build-addons" set build_addons=1&goto arg-ok if /i "%1"=="build-addons-napi" set build_addons_napi=1&goto arg-ok if /i "%1"=="test-addons" set test_args=%test_args% addons&set build_addons=1&goto arg-ok if /i "%1"=="test-addons-napi" set test_args=%test_args% addons-napi&set build_addons_napi=1&goto arg-ok +if /i "%1"=="test-benchmark" set test_args=%test_args% benchmark&goto arg-ok if /i "%1"=="test-simple" set test_args=%test_args% sequential parallel -J&goto arg-ok if /i "%1"=="test-message" set test_args=%test_args% message&goto arg-ok if /i "%1"=="test-tick-processor" set test_args=%test_args% tick-processor&goto arg-ok @@ -632,7 +633,7 @@ del .used_configure_flags goto exit :help -echo vcbuild.bat [debug/release] [msi] [doc] [test/test-ci/test-all/test-addons/test-addons-napi/test-internet/test-pummel/test-simple/test-message/test-tick-processor/test-known-issues/test-node-inspect/test-check-deopts/test-npm/test-async-hooks/test-v8/test-v8-intl/test-v8-benchmarks/test-v8-all] [ignore-flaky] [static/dll] [noprojgen] [projgen] [small-icu/full-icu/without-intl] [nobuild] [nosnapshot] [noetw] [noperfctr] [ltcg] [nopch] [licensetf] [sign] [ia32/x86/x64] [vs2017] [download-all] [enable-vtune] [lint/lint-ci/lint-js/lint-js-ci/lint-md] [lint-md-build] [package] [build-release] [upload] [no-NODE-OPTIONS] [link-module path-to-module] [debug-http2] [debug-nghttp2] [clean] [no-cctest] [openssl-no-asm] +echo vcbuild.bat [debug/release] [msi] [doc] [test/test-ci/test-all/test-addons/test-addons-napi/test-benchmark/test-internet/test-pummel/test-simple/test-message/test-tick-processor/test-known-issues/test-node-inspect/test-check-deopts/test-npm/test-async-hooks/test-v8/test-v8-intl/test-v8-benchmarks/test-v8-all] [ignore-flaky] [static/dll] [noprojgen] [projgen] [small-icu/full-icu/without-intl] [nobuild] [nosnapshot] [noetw] [noperfctr] [ltcg] [nopch] [licensetf] [sign] [ia32/x86/x64] [vs2017] [download-all] [enable-vtune] [lint/lint-ci/lint-js/lint-js-ci/lint-md] [lint-md-build] [package] [build-release] [upload] [no-NODE-OPTIONS] [link-module path-to-module] [debug-http2] [debug-nghttp2] [clean] [no-cctest] [openssl-no-asm] echo Examples: echo vcbuild.bat : builds release build echo vcbuild.bat debug : builds debug build